diff options
Diffstat (limited to 'packages/kernel/src/host/version.ts')
| -rw-r--r-- | packages/kernel/src/host/version.ts | 52 |
1 files changed, 52 insertions, 0 deletions
diff --git a/packages/kernel/src/host/version.ts b/packages/kernel/src/host/version.ts new file mode 100644 index 0000000..0d62a3b --- /dev/null +++ b/packages/kernel/src/host/version.ts @@ -0,0 +1,52 @@ +interface SemVer { + readonly major: number; + readonly minor: number; + readonly patch: number; +} + +function parseSemVer(version: string): SemVer { + const match = version.match(/^(\d+)\.(\d+)\.(\d+)$/); + if (!match) throw new Error(`Invalid semver: "${version}"`); + return { + major: Number(match[1]), + minor: Number(match[2]), + patch: Number(match[3]), + }; +} + +function gte(a: SemVer, b: SemVer): boolean { + if (a.major !== b.major) return a.major > b.major; + if (a.minor !== b.minor) return a.minor > b.minor; + return a.patch >= b.patch; +} + +export function isApiVersionCompatible(range: string, kernelVersion: string): boolean { + if (range === "*") return true; + + const kernel = parseSemVer(kernelVersion); + + if (range.startsWith("^")) { + const min = parseSemVer(range.slice(1)); + if (!gte(kernel, min)) return false; + if (min.major === 0) { + return kernel.major === 0 && kernel.minor === min.minor; + } + return kernel.major === min.major; + } + + if (range.startsWith("~")) { + const min = parseSemVer(range.slice(1)); + if (!gte(kernel, min)) return false; + return kernel.major === min.major && kernel.minor === min.minor; + } + + if (range.startsWith(">=")) { + const min = parseSemVer(range.slice(2)); + return gte(kernel, min); + } + + const exact = parseSemVer(range); + return ( + kernel.major === exact.major && kernel.minor === exact.minor && kernel.patch === exact.patch + ); +} |
