UNPKG

openclaw

Version:

Multi-channel AI gateway with extensible messaging integrations

66 lines (65 loc) 2.57 kB
//#region src/infra/semver-compare.ts /** * Converts legacy OpenClaw `1.2.3.beta.N` tags into semver-compatible `1.2.3-beta.N`. */ function normalizeLegacyDotBetaVersion(version) { const trimmed = version.trim(); const dotBetaMatch = /^([vV]?[0-9]+\.[0-9]+\.[0-9]+)\.beta(?:\.([0-9A-Za-z.-]+))?$/.exec(trimmed); if (!dotBetaMatch) return trimmed; const base = dotBetaMatch[1]; const suffix = dotBetaMatch[2]; return suffix ? `${base}-beta.${suffix}` : `${base}-beta`; } /** * Parses an exact semver-like version into fields used by update and plugin version ordering. */ function parseComparableSemver(version, options) { if (!version) return null; const normalized = options?.normalizeLegacyDotBeta ? normalizeLegacyDotBetaVersion(version) : version.trim(); const match = /^v?([0-9]+)\.([0-9]+)\.([0-9]+)(?:-([0-9A-Za-z.-]+))?(?:\+[0-9A-Za-z.-]+)?$/.exec(normalized); if (!match) return null; const [, major, minor, patch, prereleaseRaw] = match; if (!major || !minor || !patch) return null; return { major: Number.parseInt(major, 10), minor: Number.parseInt(minor, 10), patch: Number.parseInt(patch, 10), prerelease: prereleaseRaw ? prereleaseRaw.split(".").filter(Boolean) : null }; } /** * Compares semver prerelease identifiers using numeric-before-string semver precedence rules. */ function comparePrereleaseIdentifiers(a, b) { if (!a?.length && !b?.length) return 0; if (!a?.length) return 1; if (!b?.length) return -1; const max = Math.max(a.length, b.length); for (let i = 0; i < max; i += 1) { const ai = a[i]; const bi = b[i]; if (ai == null && bi == null) return 0; if (ai == null) return -1; if (bi == null) return 1; if (ai === bi) continue; const aiNumeric = /^[0-9]+$/.test(ai); const biNumeric = /^[0-9]+$/.test(bi); if (aiNumeric && biNumeric) return Number.parseInt(ai, 10) < Number.parseInt(bi, 10) ? -1 : 1; if (aiNumeric && !biNumeric) return -1; if (!aiNumeric && biNumeric) return 1; return ai < bi ? -1 : 1; } return 0; } /** * Compares parsed semver values, returning null when either side could not be parsed. */ function compareComparableSemver(a, b) { if (!a || !b) return null; if (a.major !== b.major) return a.major < b.major ? -1 : 1; if (a.minor !== b.minor) return a.minor < b.minor ? -1 : 1; if (a.patch !== b.patch) return a.patch < b.patch ? -1 : 1; return comparePrereleaseIdentifiers(a.prerelease, b.prerelease); } //#endregion export { parseComparableSemver as i, comparePrereleaseIdentifiers as n, normalizeLegacyDotBetaVersion as r, compareComparableSemver as t };