diff --git a/lib/utils.ts b/lib/utils.ts index 8f7d4203d..ec692da7a 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -2,7 +2,7 @@ import { execFileSync } from 'node:child_process' import { basename, extname, resolve } from 'node:path' import { fileURLToPath } from 'node:url' import { ofetch } from 'ofetch' -import semver from 'semver' +import { compare, findMinimumForRange, isGreaterThanOrEqual, normalizeRange, satisfies } from 'verkit' import type { Packument } from '@npm/types' export const rootDir = fileURLToPath(new URL('..', import.meta.url)) @@ -105,12 +105,12 @@ export async function getMajorVersions(npmPackage: string): Promise { const current = majorVersionMap.get(major) // Keep the highest version for each major - if (!current || semver.compare(version, current) > 0) { + if (!current || compare(version, current) > 0) { majorVersionMap.set(major, version) } } - return Array.from(majorVersionMap.values()).sort((a, b) => semver.compare(b, a)) + return Array.from(majorVersionMap.values()).sort((a, b) => compare(b, a)) } export function uniq(items: T[]) { @@ -132,7 +132,7 @@ function parseRangeComponent(range: string): ParsedRange | null { const trimmed = range.trim() // Check if it's a valid semver range first - if (!semver.validRange(trimmed)) { + if (!normalizeRange(trimmed)) { return null } @@ -195,7 +195,7 @@ function parseRangeComponent(range: string): ParsedRange | null { } // Complex range - we can still get minVersion from it - const minVersion = semver.minVersion(trimmed) + const minVersion = findMinimumForRange(trimmed) if (minVersion) { return { original: trimmed, @@ -203,7 +203,7 @@ function parseRangeComponent(range: string): ParsedRange | null { major: minVersion.major, minor: minVersion.minor, patch: minVersion.patch, - prerelease: minVersion.prerelease.length > 0 ? minVersion.prerelease.join('.') : null, + prerelease: minVersion.prerelease?.length ? minVersion.prerelease.join('.') : null, hasUpperBound: true, // Assume complex ranges have upper bounds } } @@ -218,9 +218,9 @@ function parseRangeComponent(range: string): ParsedRange | null { function isRangeCoveredBy(a: ParsedRange, b: ParsedRange): boolean { // An open-ended >= range covers another range if its minimum is <= the other's minimum if (b.type === 'gte' && !b.hasUpperBound) { - const aMin = semver.minVersion(a.original) - const bMin = semver.minVersion(b.original) - if (aMin && bMin && semver.gte(aMin, bMin)) { + const aMin = findMinimumForRange(a.original) + const bMin = findMinimumForRange(b.original) + if (aMin && bMin && isGreaterThanOrEqual(aMin, bMin)) { // b starts at or before a, and b has no upper bound // So if a has an upper bound, b covers all of a's range and more // If a also has no upper bound, they overlap from a's min onward @@ -315,7 +315,7 @@ export function mergeCompatibilityRanges(ranges: string[]): string { if (allRangeStrings.length === 0) return '' if (allRangeStrings.length === 1) { // Single range - validate and return - const valid = semver.validRange(allRangeStrings[0]!) + const valid = normalizeRange(allRangeStrings[0]!) return valid ? allRangeStrings[0]! : '' } @@ -416,7 +416,7 @@ export function isNuxt4Compatible(range: string): boolean { if (!range) return false try { // Test against a Nuxt 4 version - return semver.satisfies('4.0.0', range) + return satisfies('4.0.0', range) } catch { return false diff --git a/package.json b/package.json index 5e6d605c4..b01e219bf 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,6 @@ "@octokit/rest": "^22.0.1", "@types/js-yaml": "^4.0.9", "@types/node": "^24.13.6", - "@types/semver": "^7.8.0", "defu": "^6.1.7", "dotenv": "^18.0.1", "eslint": "^10.11.0", @@ -38,9 +37,9 @@ "ofetch": "^1.5.1", "p-limit": "^7.3.3", "picocolors": "^1.1.1", - "semver": "^7.8.5", "std-env": "^4.2.0", - "typescript": "^6.0.3" + "typescript": "^6.0.3", + "verkit": "^0.5.0" }, "devEngines": { "runtime": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 0219c05d4..0b924c55f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -127,9 +127,6 @@ importers: '@types/node': specifier: ^24.13.6 version: 24.13.6 - '@types/semver': - specifier: ^7.8.0 - version: 7.8.0 defu: specifier: ^6.1.7 version: 6.1.7 @@ -160,15 +157,15 @@ importers: picocolors: specifier: ^1.1.1 version: 1.1.1 - semver: - specifier: ^7.8.5 - version: 7.8.5 std-env: specifier: ^4.2.0 version: 4.2.0 typescript: specifier: ^6.0.3 version: 6.0.3 + verkit: + specifier: ^0.5.0 + version: 0.5.0 packages: @@ -441,9 +438,6 @@ packages: '@types/node@26.5.1': resolution: {integrity: sha512-CzNm2FezW4VR/LjG6yUdiEgLE/rAQ9Slj5gCu/C2VrdcW7I0ahNZ8DRbHT7zOZ6r3ONgd/bsQIeSaoDGrd1C6g==} - '@types/semver@7.8.0': - resolution: {integrity: sha512-1mAINjtQCXXeLkJ9ehXkwOcBpqtLxiVtKhpUf83DdRNdQKV0iXZpaHYqRr7nj+wvxuJzoAmAwXI+sCNMv1CzLQ==} - '@typescript-eslint/eslint-plugin@8.70.0': resolution: {integrity: sha512-/v8HZt6RlyIZxB3ntehELOcUcfxKPVGWXnQdJuHRmzrqgF8nQypcC/oxGW+Ot4VGKDq81XugPKxx0n5PBtf9PA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1541,6 +1535,10 @@ packages: util-deprecate@1.0.2: resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==} + verkit@0.5.0: + resolution: {integrity: sha512-u4J1hr6Y+C/hit34GwL3eIcUf3wngT8TlYUjK7tk0jxydKLAq3sYvifjdTDA6U3KCKRcQCQDGf/srjxfZF3l7g==} + engines: {node: '>=18.12.0'} + vue-eslint-parser@10.4.1: resolution: {integrity: sha512-Gk6gRDj0n/fkRa3C3l0bBheoBckUq/Rs0F/TvMWIS6nzzx67amAViMe9CkNgsP2tXyQONvGiHQESHwFtZ3aYDA==} engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0} @@ -1886,8 +1884,6 @@ snapshots: dependencies: undici-types: 8.9.0 - '@types/semver@7.8.0': {} - '@typescript-eslint/eslint-plugin@8.70.0(@typescript-eslint/parser@8.70.0(eslint@10.11.0)(typescript@6.0.3))(eslint@10.11.0)(typescript@6.0.3)': dependencies: '@eslint-community/regexpp': 4.12.2 @@ -2837,6 +2833,8 @@ snapshots: util-deprecate@1.0.2: {} + verkit@0.5.0: {} + vue-eslint-parser@10.4.1(eslint@10.11.0): dependencies: debug: 4.4.3