UNPKG

@v4fire/core

Version:
149 lines (118 loc) 2.84 kB
/*! * V4Fire Core * https://github.com/V4Fire/Core * * Released under the MIT license * https://github.com/V4Fire/Core/blob/master/LICENSE */ /** * [[include:core/semver/README.md]] * @packageDocumentation */ import { operations, compareRgxp, operandLengthErrorText } from 'core/semver/const'; import type { Operation, Strategy, ComparisonOptions } from 'core/semver/interface'; export * from 'core/semver/const'; export * from 'core/semver/interface'; /** * Compares two strings with number versions (a <op> b) by using the semver strategy * * @param a * @param b * @param op - operation type * @param [opts] - additional options for the specified operation */ export default function compare(a: string, b: string, op: Operation, opts: ComparisonOptions = {x: '*'}): boolean { if (a.trim() === '' || b.trim() === '') { throw new Error(operandLengthErrorText); } if (!(op in operations)) { throw new TypeError(`Unknown comparator "${op}". Only "${Object.keys(operations).join(', ')}" available.`); } const left = a.split('.'), right = b.split('.'), {x} = opts; const strategyMatch = compareRgxp.exec(op); let strategy: Strategy = 'ord'; if (strategyMatch?.[0] === op) { strategy = 'range'; } else if (strategyMatch?.index === 0) { // Using for the equal == strategy = 'eq'; } const max = Math.max(left.length, right.length); let prevRes = false, res = false; for (let i = 0; i < max; i++) { const l = left[i] ?? x, r = right[i] ?? x; const rVal = parseInt(r, 10), lVal = parseInt(l, 10); if (i > 0) { prevRes = res; } res = operations[op]( lVal, rVal ); switch (strategy) { case 'range': if (!res) { if (op.startsWith('~')) { return l === x || r === x || i > 0 && rVal < lVal; } return i > 0 && right[i - 1] !== '0' && rVal < lVal || l === x || r === x; } break; case 'eq': if (!res) { return l === x || r === x; } break; case 'ord': if (!res && (r === x || l === x)) { // 1.3.0 <= >= 1.2.* if (op.length === 2 && !prevRes) { return false; } // 1.2.4 >< 1.* // 1.2.4 >< 1.2.* // 1.* >< 1.2.4 // 1.2.* >< 1.2.4 return op.length !== 1; } // 1.2.1 <= 1.1.1 // 2.1.1 <= 1.1.1 // 1.1.1 >= 1.2.1 // 1.1.1 >= 2.1.1 if (!res && op.length === 2) { return res; } // 1.1.2 > 1.2.1 // 1.2.2 > 2.1.1 if (!res && op.length === 1 && rVal !== lVal) { return res; } // 1.1.2 <= 1.2.1 // 1.2.2 <= 2.1.1 if (res && op.length === 2 && rVal !== lVal) { return res; } // 1.1.2 > 1.1.1 // 1.3.0 > 1.2.* if (res && op.length === 1) { return res; } break; default: throw new TypeError('Unsupported operation'); } } return res; }