@hyperfrontend/versioning 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/ARCHITECTURE.md +593 -0
- package/CHANGELOG.md +35 -0
- package/FUNDING.md +141 -0
- package/LICENSE.md +21 -0
- package/README.md +195 -0
- package/SECURITY.md +82 -0
- package/changelog/compare/diff.d.ts +128 -0
- package/changelog/compare/diff.d.ts.map +1 -0
- package/changelog/compare/index.cjs.js +628 -0
- package/changelog/compare/index.cjs.js.map +1 -0
- package/changelog/compare/index.d.ts +4 -0
- package/changelog/compare/index.d.ts.map +1 -0
- package/changelog/compare/index.esm.js +612 -0
- package/changelog/compare/index.esm.js.map +1 -0
- package/changelog/compare/is-equal.d.ts +114 -0
- package/changelog/compare/is-equal.d.ts.map +1 -0
- package/changelog/index.cjs.js +6448 -0
- package/changelog/index.cjs.js.map +1 -0
- package/changelog/index.d.ts +6 -0
- package/changelog/index.d.ts.map +1 -0
- package/changelog/index.esm.js +6358 -0
- package/changelog/index.esm.js.map +1 -0
- package/changelog/models/changelog.d.ts +86 -0
- package/changelog/models/changelog.d.ts.map +1 -0
- package/changelog/models/commit-ref.d.ts +51 -0
- package/changelog/models/commit-ref.d.ts.map +1 -0
- package/changelog/models/entry.d.ts +84 -0
- package/changelog/models/entry.d.ts.map +1 -0
- package/changelog/models/index.cjs.js +2043 -0
- package/changelog/models/index.cjs.js.map +1 -0
- package/changelog/models/index.d.ts +11 -0
- package/changelog/models/index.d.ts.map +1 -0
- package/changelog/models/index.esm.js +2026 -0
- package/changelog/models/index.esm.js.map +1 -0
- package/changelog/models/schema.d.ts +68 -0
- package/changelog/models/schema.d.ts.map +1 -0
- package/changelog/models/section.d.ts +25 -0
- package/changelog/models/section.d.ts.map +1 -0
- package/changelog/operations/add-entry.d.ts +56 -0
- package/changelog/operations/add-entry.d.ts.map +1 -0
- package/changelog/operations/add-item.d.ts +18 -0
- package/changelog/operations/add-item.d.ts.map +1 -0
- package/changelog/operations/filter-by-predicate.d.ts +81 -0
- package/changelog/operations/filter-by-predicate.d.ts.map +1 -0
- package/changelog/operations/filter-by-range.d.ts +63 -0
- package/changelog/operations/filter-by-range.d.ts.map +1 -0
- package/changelog/operations/filter-entries.d.ts +9 -0
- package/changelog/operations/filter-entries.d.ts.map +1 -0
- package/changelog/operations/index.cjs.js +2455 -0
- package/changelog/operations/index.cjs.js.map +1 -0
- package/changelog/operations/index.d.ts +15 -0
- package/changelog/operations/index.d.ts.map +1 -0
- package/changelog/operations/index.esm.js +2411 -0
- package/changelog/operations/index.esm.js.map +1 -0
- package/changelog/operations/merge.d.ts +88 -0
- package/changelog/operations/merge.d.ts.map +1 -0
- package/changelog/operations/remove-entry.d.ts +45 -0
- package/changelog/operations/remove-entry.d.ts.map +1 -0
- package/changelog/operations/remove-section.d.ts +50 -0
- package/changelog/operations/remove-section.d.ts.map +1 -0
- package/changelog/operations/transform.d.ts +143 -0
- package/changelog/operations/transform.d.ts.map +1 -0
- package/changelog/parse/index.cjs.js +1282 -0
- package/changelog/parse/index.cjs.js.map +1 -0
- package/changelog/parse/index.d.ts +5 -0
- package/changelog/parse/index.d.ts.map +1 -0
- package/changelog/parse/index.esm.js +1275 -0
- package/changelog/parse/index.esm.js.map +1 -0
- package/changelog/parse/line.d.ts +48 -0
- package/changelog/parse/line.d.ts.map +1 -0
- package/changelog/parse/parser.d.ts +16 -0
- package/changelog/parse/parser.d.ts.map +1 -0
- package/changelog/parse/tokenizer.d.ts +49 -0
- package/changelog/parse/tokenizer.d.ts.map +1 -0
- package/changelog/serialize/index.cjs.js +574 -0
- package/changelog/serialize/index.cjs.js.map +1 -0
- package/changelog/serialize/index.d.ts +6 -0
- package/changelog/serialize/index.d.ts.map +1 -0
- package/changelog/serialize/index.esm.js +564 -0
- package/changelog/serialize/index.esm.js.map +1 -0
- package/changelog/serialize/templates.d.ts +81 -0
- package/changelog/serialize/templates.d.ts.map +1 -0
- package/changelog/serialize/to-json.d.ts +57 -0
- package/changelog/serialize/to-json.d.ts.map +1 -0
- package/changelog/serialize/to-string.d.ts +30 -0
- package/changelog/serialize/to-string.d.ts.map +1 -0
- package/commits/index.cjs.js +648 -0
- package/commits/index.cjs.js.map +1 -0
- package/commits/index.d.ts +3 -0
- package/commits/index.d.ts.map +1 -0
- package/commits/index.esm.js +629 -0
- package/commits/index.esm.js.map +1 -0
- package/commits/models/breaking.d.ts +39 -0
- package/commits/models/breaking.d.ts.map +1 -0
- package/commits/models/commit-type.d.ts +32 -0
- package/commits/models/commit-type.d.ts.map +1 -0
- package/commits/models/conventional.d.ts +49 -0
- package/commits/models/conventional.d.ts.map +1 -0
- package/commits/models/index.cjs.js +207 -0
- package/commits/models/index.cjs.js.map +1 -0
- package/commits/models/index.d.ts +7 -0
- package/commits/models/index.d.ts.map +1 -0
- package/commits/models/index.esm.js +193 -0
- package/commits/models/index.esm.js.map +1 -0
- package/commits/parse/body.d.ts +18 -0
- package/commits/parse/body.d.ts.map +1 -0
- package/commits/parse/footer.d.ts +16 -0
- package/commits/parse/footer.d.ts.map +1 -0
- package/commits/parse/header.d.ts +15 -0
- package/commits/parse/header.d.ts.map +1 -0
- package/commits/parse/index.cjs.js +505 -0
- package/commits/parse/index.cjs.js.map +1 -0
- package/commits/parse/index.d.ts +5 -0
- package/commits/parse/index.d.ts.map +1 -0
- package/commits/parse/index.esm.js +499 -0
- package/commits/parse/index.esm.js.map +1 -0
- package/commits/parse/message.d.ts +17 -0
- package/commits/parse/message.d.ts.map +1 -0
- package/commits/utils/replace-char.d.ts +19 -0
- package/commits/utils/replace-char.d.ts.map +1 -0
- package/flow/executor/execute.d.ts +72 -0
- package/flow/executor/execute.d.ts.map +1 -0
- package/flow/executor/index.cjs.js +4402 -0
- package/flow/executor/index.cjs.js.map +1 -0
- package/flow/executor/index.d.ts +3 -0
- package/flow/executor/index.d.ts.map +1 -0
- package/flow/executor/index.esm.js +4398 -0
- package/flow/executor/index.esm.js.map +1 -0
- package/flow/factory.d.ts +58 -0
- package/flow/factory.d.ts.map +1 -0
- package/flow/index.cjs.js +8506 -0
- package/flow/index.cjs.js.map +1 -0
- package/flow/index.d.ts +7 -0
- package/flow/index.d.ts.map +1 -0
- package/flow/index.esm.js +8451 -0
- package/flow/index.esm.js.map +1 -0
- package/flow/models/flow.d.ts +130 -0
- package/flow/models/flow.d.ts.map +1 -0
- package/flow/models/index.cjs.js +285 -0
- package/flow/models/index.cjs.js.map +1 -0
- package/flow/models/index.d.ts +7 -0
- package/flow/models/index.d.ts.map +1 -0
- package/flow/models/index.esm.js +268 -0
- package/flow/models/index.esm.js.map +1 -0
- package/flow/models/step.d.ts +108 -0
- package/flow/models/step.d.ts.map +1 -0
- package/flow/models/types.d.ts +150 -0
- package/flow/models/types.d.ts.map +1 -0
- package/flow/presets/conventional.d.ts +59 -0
- package/flow/presets/conventional.d.ts.map +1 -0
- package/flow/presets/independent.d.ts +61 -0
- package/flow/presets/independent.d.ts.map +1 -0
- package/flow/presets/index.cjs.js +3903 -0
- package/flow/presets/index.cjs.js.map +1 -0
- package/flow/presets/index.d.ts +4 -0
- package/flow/presets/index.d.ts.map +1 -0
- package/flow/presets/index.esm.js +3889 -0
- package/flow/presets/index.esm.js.map +1 -0
- package/flow/presets/synced.d.ts +65 -0
- package/flow/presets/synced.d.ts.map +1 -0
- package/flow/steps/analyze-commits.d.ts +19 -0
- package/flow/steps/analyze-commits.d.ts.map +1 -0
- package/flow/steps/calculate-bump.d.ts +27 -0
- package/flow/steps/calculate-bump.d.ts.map +1 -0
- package/flow/steps/create-commit.d.ts +16 -0
- package/flow/steps/create-commit.d.ts.map +1 -0
- package/flow/steps/create-tag.d.ts +22 -0
- package/flow/steps/create-tag.d.ts.map +1 -0
- package/flow/steps/fetch-registry.d.ts +19 -0
- package/flow/steps/fetch-registry.d.ts.map +1 -0
- package/flow/steps/generate-changelog.d.ts +25 -0
- package/flow/steps/generate-changelog.d.ts.map +1 -0
- package/flow/steps/index.cjs.js +3523 -0
- package/flow/steps/index.cjs.js.map +1 -0
- package/flow/steps/index.d.ts +8 -0
- package/flow/steps/index.d.ts.map +1 -0
- package/flow/steps/index.esm.js +3504 -0
- package/flow/steps/index.esm.js.map +1 -0
- package/flow/steps/update-packages.d.ts +25 -0
- package/flow/steps/update-packages.d.ts.map +1 -0
- package/flow/utils/interpolate.d.ts +11 -0
- package/flow/utils/interpolate.d.ts.map +1 -0
- package/git/factory.d.ts +233 -0
- package/git/factory.d.ts.map +1 -0
- package/git/index.cjs.js +2863 -0
- package/git/index.cjs.js.map +1 -0
- package/git/index.d.ts +5 -0
- package/git/index.d.ts.map +1 -0
- package/git/index.esm.js +2785 -0
- package/git/index.esm.js.map +1 -0
- package/git/models/commit.d.ts +129 -0
- package/git/models/commit.d.ts.map +1 -0
- package/git/models/index.cjs.js +755 -0
- package/git/models/index.cjs.js.map +1 -0
- package/git/models/index.d.ts +7 -0
- package/git/models/index.d.ts.map +1 -0
- package/git/models/index.esm.js +729 -0
- package/git/models/index.esm.js.map +1 -0
- package/git/models/ref.d.ts +120 -0
- package/git/models/ref.d.ts.map +1 -0
- package/git/models/tag.d.ts +141 -0
- package/git/models/tag.d.ts.map +1 -0
- package/git/operations/commit.d.ts +97 -0
- package/git/operations/commit.d.ts.map +1 -0
- package/git/operations/head-info.d.ts +29 -0
- package/git/operations/head-info.d.ts.map +1 -0
- package/git/operations/index.cjs.js +1954 -0
- package/git/operations/index.cjs.js.map +1 -0
- package/git/operations/index.d.ts +14 -0
- package/git/operations/index.d.ts.map +1 -0
- package/git/operations/index.esm.js +1903 -0
- package/git/operations/index.esm.js.map +1 -0
- package/git/operations/log.d.ts +104 -0
- package/git/operations/log.d.ts.map +1 -0
- package/git/operations/manage-tags.d.ts +60 -0
- package/git/operations/manage-tags.d.ts.map +1 -0
- package/git/operations/query-tags.d.ts +88 -0
- package/git/operations/query-tags.d.ts.map +1 -0
- package/git/operations/stage.d.ts +66 -0
- package/git/operations/stage.d.ts.map +1 -0
- package/git/operations/status.d.ts +173 -0
- package/git/operations/status.d.ts.map +1 -0
- package/index.cjs.js +16761 -0
- package/index.cjs.js.map +1 -0
- package/index.d.ts +102 -0
- package/index.d.ts.map +1 -0
- package/index.esm.js +16427 -0
- package/index.esm.js.map +1 -0
- package/package.json +200 -0
- package/registry/factory.d.ts +18 -0
- package/registry/factory.d.ts.map +1 -0
- package/registry/index.cjs.js +543 -0
- package/registry/index.cjs.js.map +1 -0
- package/registry/index.d.ts +5 -0
- package/registry/index.d.ts.map +1 -0
- package/registry/index.esm.js +535 -0
- package/registry/index.esm.js.map +1 -0
- package/registry/models/index.cjs.js +69 -0
- package/registry/models/index.cjs.js.map +1 -0
- package/registry/models/index.d.ts +6 -0
- package/registry/models/index.d.ts.map +1 -0
- package/registry/models/index.esm.js +66 -0
- package/registry/models/index.esm.js.map +1 -0
- package/registry/models/package-info.d.ts +55 -0
- package/registry/models/package-info.d.ts.map +1 -0
- package/registry/models/registry.d.ts +62 -0
- package/registry/models/registry.d.ts.map +1 -0
- package/registry/models/version-info.d.ts +67 -0
- package/registry/models/version-info.d.ts.map +1 -0
- package/registry/npm/cache.d.ts +50 -0
- package/registry/npm/cache.d.ts.map +1 -0
- package/registry/npm/client.d.ts +30 -0
- package/registry/npm/client.d.ts.map +1 -0
- package/registry/npm/index.cjs.js +456 -0
- package/registry/npm/index.cjs.js.map +1 -0
- package/registry/npm/index.d.ts +4 -0
- package/registry/npm/index.d.ts.map +1 -0
- package/registry/npm/index.esm.js +451 -0
- package/registry/npm/index.esm.js.map +1 -0
- package/semver/compare/compare.d.ts +100 -0
- package/semver/compare/compare.d.ts.map +1 -0
- package/semver/compare/index.cjs.js +386 -0
- package/semver/compare/index.cjs.js.map +1 -0
- package/semver/compare/index.d.ts +3 -0
- package/semver/compare/index.d.ts.map +1 -0
- package/semver/compare/index.esm.js +370 -0
- package/semver/compare/index.esm.js.map +1 -0
- package/semver/compare/sort.d.ts +36 -0
- package/semver/compare/sort.d.ts.map +1 -0
- package/semver/format/index.cjs.js +58 -0
- package/semver/format/index.cjs.js.map +1 -0
- package/semver/format/index.d.ts +2 -0
- package/semver/format/index.d.ts.map +1 -0
- package/semver/format/index.esm.js +53 -0
- package/semver/format/index.esm.js.map +1 -0
- package/semver/format/to-string.d.ts +31 -0
- package/semver/format/to-string.d.ts.map +1 -0
- package/semver/increment/bump.d.ts +37 -0
- package/semver/increment/bump.d.ts.map +1 -0
- package/semver/increment/index.cjs.js +223 -0
- package/semver/increment/index.cjs.js.map +1 -0
- package/semver/increment/index.d.ts +2 -0
- package/semver/increment/index.d.ts.map +1 -0
- package/semver/increment/index.esm.js +219 -0
- package/semver/increment/index.esm.js.map +1 -0
- package/semver/index.cjs.js +1499 -0
- package/semver/index.cjs.js.map +1 -0
- package/semver/index.d.ts +6 -0
- package/semver/index.d.ts.map +1 -0
- package/semver/index.esm.js +1458 -0
- package/semver/index.esm.js.map +1 -0
- package/semver/models/index.cjs.js +153 -0
- package/semver/models/index.cjs.js.map +1 -0
- package/semver/models/index.d.ts +5 -0
- package/semver/models/index.d.ts.map +1 -0
- package/semver/models/index.esm.js +139 -0
- package/semver/models/index.esm.js.map +1 -0
- package/semver/models/range.d.ts +83 -0
- package/semver/models/range.d.ts.map +1 -0
- package/semver/models/version.d.ts +78 -0
- package/semver/models/version.d.ts.map +1 -0
- package/semver/parse/index.cjs.js +799 -0
- package/semver/parse/index.cjs.js.map +1 -0
- package/semver/parse/index.d.ts +5 -0
- package/semver/parse/index.d.ts.map +1 -0
- package/semver/parse/index.esm.js +793 -0
- package/semver/parse/index.esm.js.map +1 -0
- package/semver/parse/range.d.ts +38 -0
- package/semver/parse/range.d.ts.map +1 -0
- package/semver/parse/version.d.ts +49 -0
- package/semver/parse/version.d.ts.map +1 -0
- package/workspace/discovery/changelog-path.d.ts +21 -0
- package/workspace/discovery/changelog-path.d.ts.map +1 -0
- package/workspace/discovery/dependencies.d.ts +145 -0
- package/workspace/discovery/dependencies.d.ts.map +1 -0
- package/workspace/discovery/discover-changelogs.d.ts +76 -0
- package/workspace/discovery/discover-changelogs.d.ts.map +1 -0
- package/workspace/discovery/index.cjs.js +2300 -0
- package/workspace/discovery/index.cjs.js.map +1 -0
- package/workspace/discovery/index.d.ts +13 -0
- package/workspace/discovery/index.d.ts.map +1 -0
- package/workspace/discovery/index.esm.js +2283 -0
- package/workspace/discovery/index.esm.js.map +1 -0
- package/workspace/discovery/packages.d.ts +83 -0
- package/workspace/discovery/packages.d.ts.map +1 -0
- package/workspace/index.cjs.js +4445 -0
- package/workspace/index.cjs.js.map +1 -0
- package/workspace/index.d.ts +52 -0
- package/workspace/index.d.ts.map +1 -0
- package/workspace/index.esm.js +4394 -0
- package/workspace/index.esm.js.map +1 -0
- package/workspace/models/index.cjs.js +284 -0
- package/workspace/models/index.cjs.js.map +1 -0
- package/workspace/models/index.d.ts +10 -0
- package/workspace/models/index.d.ts.map +1 -0
- package/workspace/models/index.esm.js +261 -0
- package/workspace/models/index.esm.js.map +1 -0
- package/workspace/models/project.d.ts +118 -0
- package/workspace/models/project.d.ts.map +1 -0
- package/workspace/models/workspace.d.ts +139 -0
- package/workspace/models/workspace.d.ts.map +1 -0
- package/workspace/operations/batch-update.d.ts +99 -0
- package/workspace/operations/batch-update.d.ts.map +1 -0
- package/workspace/operations/cascade-bump.d.ts +125 -0
- package/workspace/operations/cascade-bump.d.ts.map +1 -0
- package/workspace/operations/index.cjs.js +2675 -0
- package/workspace/operations/index.cjs.js.map +1 -0
- package/workspace/operations/index.d.ts +12 -0
- package/workspace/operations/index.d.ts.map +1 -0
- package/workspace/operations/index.esm.js +2663 -0
- package/workspace/operations/index.esm.js.map +1 -0
- package/workspace/operations/validate.d.ts +85 -0
- package/workspace/operations/validate.d.ts.map +1 -0
|
@@ -0,0 +1,1458 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Creates a new SemVer object.
|
|
3
|
+
*
|
|
4
|
+
* @param options - Version components
|
|
5
|
+
* @returns A new SemVer object
|
|
6
|
+
*/
|
|
7
|
+
function createSemVer(options) {
|
|
8
|
+
return {
|
|
9
|
+
major: options.major,
|
|
10
|
+
minor: options.minor,
|
|
11
|
+
patch: options.patch,
|
|
12
|
+
prerelease: options.prerelease ?? [],
|
|
13
|
+
build: options.build ?? [],
|
|
14
|
+
raw: options.raw,
|
|
15
|
+
};
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* Creates a SemVer representing version 0.0.0.
|
|
19
|
+
*
|
|
20
|
+
* @returns A SemVer at version 0.0.0
|
|
21
|
+
*/
|
|
22
|
+
function createInitialVersion() {
|
|
23
|
+
return createSemVer({ major: 0, minor: 0, patch: 0 });
|
|
24
|
+
}
|
|
25
|
+
/**
|
|
26
|
+
* Creates a SemVer representing version 1.0.0.
|
|
27
|
+
*
|
|
28
|
+
* @returns A SemVer at version 1.0.0
|
|
29
|
+
*/
|
|
30
|
+
function createFirstRelease() {
|
|
31
|
+
return createSemVer({ major: 1, minor: 0, patch: 0 });
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* Checks if the version has prerelease identifiers.
|
|
35
|
+
*
|
|
36
|
+
* @param version - The version to check
|
|
37
|
+
* @returns True if version has prerelease identifiers
|
|
38
|
+
*/
|
|
39
|
+
function isPrerelease(version) {
|
|
40
|
+
return version.prerelease.length > 0;
|
|
41
|
+
}
|
|
42
|
+
/**
|
|
43
|
+
* Checks if the version is a stable release (>= 1.0.0 with no prerelease).
|
|
44
|
+
*
|
|
45
|
+
* @param version - The version to check
|
|
46
|
+
* @returns True if version is stable
|
|
47
|
+
*/
|
|
48
|
+
function isStable(version) {
|
|
49
|
+
return version.major >= 1 && version.prerelease.length === 0;
|
|
50
|
+
}
|
|
51
|
+
/**
|
|
52
|
+
* Returns a new version with build metadata stripped.
|
|
53
|
+
*
|
|
54
|
+
* @param version - The version to strip
|
|
55
|
+
* @returns A new SemVer without build metadata
|
|
56
|
+
*/
|
|
57
|
+
function stripBuild(version) {
|
|
58
|
+
return createSemVer({
|
|
59
|
+
major: version.major,
|
|
60
|
+
minor: version.minor,
|
|
61
|
+
patch: version.patch,
|
|
62
|
+
prerelease: version.prerelease,
|
|
63
|
+
build: [],
|
|
64
|
+
});
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Returns a new version with prerelease identifiers stripped.
|
|
68
|
+
*
|
|
69
|
+
* @param version - The version to strip
|
|
70
|
+
* @returns A new SemVer without prerelease identifiers
|
|
71
|
+
*/
|
|
72
|
+
function stripPrerelease(version) {
|
|
73
|
+
return createSemVer({
|
|
74
|
+
major: version.major,
|
|
75
|
+
minor: version.minor,
|
|
76
|
+
patch: version.patch,
|
|
77
|
+
prerelease: [],
|
|
78
|
+
build: version.build,
|
|
79
|
+
});
|
|
80
|
+
}
|
|
81
|
+
|
|
82
|
+
/**
|
|
83
|
+
* Creates a new Comparator.
|
|
84
|
+
*
|
|
85
|
+
* @param operator - The comparison operator
|
|
86
|
+
* @param version - The version to compare against
|
|
87
|
+
* @returns A new Comparator
|
|
88
|
+
*/
|
|
89
|
+
function createComparator(operator, version) {
|
|
90
|
+
return { operator, version };
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Creates a new ComparatorSet.
|
|
94
|
+
*
|
|
95
|
+
* @param comparators - Array of comparators (AND logic)
|
|
96
|
+
* @returns A new ComparatorSet
|
|
97
|
+
*/
|
|
98
|
+
function createComparatorSet(comparators) {
|
|
99
|
+
return { comparators };
|
|
100
|
+
}
|
|
101
|
+
/**
|
|
102
|
+
* Creates a new Range.
|
|
103
|
+
*
|
|
104
|
+
* @param sets - Array of comparator sets (OR logic)
|
|
105
|
+
* @param raw - Original raw string
|
|
106
|
+
* @returns A new Range
|
|
107
|
+
*/
|
|
108
|
+
function createRange(sets, raw) {
|
|
109
|
+
return { sets, raw };
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Creates a range that matches any version.
|
|
113
|
+
*
|
|
114
|
+
* @returns A Range matching any version (*)
|
|
115
|
+
*/
|
|
116
|
+
function createAnyRange() {
|
|
117
|
+
return createRange([], '*');
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Creates a range that matches exactly one version.
|
|
121
|
+
*
|
|
122
|
+
* @param version - The exact version to match
|
|
123
|
+
* @returns A Range matching exactly the specified version
|
|
124
|
+
*/
|
|
125
|
+
function createExactRange(version) {
|
|
126
|
+
return createRange([createComparatorSet([createComparator('=', version)])]);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* Checks if a range represents a wildcard/any match.
|
|
130
|
+
*
|
|
131
|
+
* @param range - The range to check
|
|
132
|
+
* @returns True if the range matches any version
|
|
133
|
+
*/
|
|
134
|
+
function isWildcard(range) {
|
|
135
|
+
return range.sets.length === 0 || range.raw === '*' || range.raw === '';
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Safe copies of Error built-ins via factory functions.
|
|
140
|
+
*
|
|
141
|
+
* Since constructors cannot be safely captured via Object.assign, this module
|
|
142
|
+
* provides factory functions that use Reflect.construct internally.
|
|
143
|
+
*
|
|
144
|
+
* These references are captured at module initialization time to protect against
|
|
145
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
146
|
+
*
|
|
147
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
148
|
+
*/
|
|
149
|
+
// Capture references at module initialization time
|
|
150
|
+
const _Error = globalThis.Error;
|
|
151
|
+
const _Reflect = globalThis.Reflect;
|
|
152
|
+
/**
|
|
153
|
+
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
154
|
+
* Use this instead of `new Error()`.
|
|
155
|
+
*
|
|
156
|
+
* @param message - Optional error message.
|
|
157
|
+
* @param options - Optional error options.
|
|
158
|
+
* @returns A new Error instance.
|
|
159
|
+
*/
|
|
160
|
+
const createError = (message, options) => _Reflect.construct(_Error, [message, options]);
|
|
161
|
+
|
|
162
|
+
/**
|
|
163
|
+
* Maximum version string length to prevent memory exhaustion.
|
|
164
|
+
*/
|
|
165
|
+
const MAX_VERSION_LENGTH = 256;
|
|
166
|
+
/**
|
|
167
|
+
* Parses a semantic version string.
|
|
168
|
+
*
|
|
169
|
+
* Accepts versions in the format: MAJOR.MINOR.PATCH[-prerelease][+build]
|
|
170
|
+
* Optional leading 'v' or '=' prefixes are stripped.
|
|
171
|
+
*
|
|
172
|
+
* @param input - The version string to parse
|
|
173
|
+
* @returns A ParseVersionResult with the parsed version or error
|
|
174
|
+
*
|
|
175
|
+
* @example
|
|
176
|
+
* parseVersion('1.2.3') // { success: true, version: { major: 1, minor: 2, patch: 3, ... } }
|
|
177
|
+
* parseVersion('v1.0.0-alpha.1+build.123') // { success: true, ... }
|
|
178
|
+
* parseVersion('invalid') // { success: false, error: '...' }
|
|
179
|
+
*/
|
|
180
|
+
function parseVersion(input) {
|
|
181
|
+
// Input validation
|
|
182
|
+
if (!input || typeof input !== 'string') {
|
|
183
|
+
return { success: false, error: 'Version string is required' };
|
|
184
|
+
}
|
|
185
|
+
if (input.length > MAX_VERSION_LENGTH) {
|
|
186
|
+
return { success: false, error: `Version string exceeds maximum length of ${MAX_VERSION_LENGTH}` };
|
|
187
|
+
}
|
|
188
|
+
// Strip leading whitespace
|
|
189
|
+
let pos = 0;
|
|
190
|
+
while (pos < input.length && isWhitespace(input.charCodeAt(pos))) {
|
|
191
|
+
pos++;
|
|
192
|
+
}
|
|
193
|
+
// Strip trailing whitespace
|
|
194
|
+
let end = input.length;
|
|
195
|
+
while (end > pos && isWhitespace(input.charCodeAt(end - 1))) {
|
|
196
|
+
end--;
|
|
197
|
+
}
|
|
198
|
+
// Strip optional leading 'v' or '='
|
|
199
|
+
if (pos < end) {
|
|
200
|
+
const code = input.charCodeAt(pos);
|
|
201
|
+
if (code === 118 || code === 86) {
|
|
202
|
+
// 'v' or 'V'
|
|
203
|
+
pos++;
|
|
204
|
+
}
|
|
205
|
+
else if (code === 61) {
|
|
206
|
+
// '='
|
|
207
|
+
pos++;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
// Parse major version
|
|
211
|
+
const majorResult = parseNumericIdentifier(input, pos, end);
|
|
212
|
+
if (!majorResult.success) {
|
|
213
|
+
return { success: false, error: majorResult.error ?? 'Invalid major version' };
|
|
214
|
+
}
|
|
215
|
+
pos = majorResult.endPos;
|
|
216
|
+
// Expect dot
|
|
217
|
+
if (pos >= end || input.charCodeAt(pos) !== 46) {
|
|
218
|
+
// '.'
|
|
219
|
+
return { success: false, error: 'Expected "." after major version' };
|
|
220
|
+
}
|
|
221
|
+
pos++;
|
|
222
|
+
// Parse minor version
|
|
223
|
+
const minorResult = parseNumericIdentifier(input, pos, end);
|
|
224
|
+
if (!minorResult.success) {
|
|
225
|
+
return { success: false, error: minorResult.error ?? 'Invalid minor version' };
|
|
226
|
+
}
|
|
227
|
+
pos = minorResult.endPos;
|
|
228
|
+
// Expect dot
|
|
229
|
+
if (pos >= end || input.charCodeAt(pos) !== 46) {
|
|
230
|
+
// '.'
|
|
231
|
+
return { success: false, error: 'Expected "." after minor version' };
|
|
232
|
+
}
|
|
233
|
+
pos++;
|
|
234
|
+
// Parse patch version
|
|
235
|
+
const patchResult = parseNumericIdentifier(input, pos, end);
|
|
236
|
+
if (!patchResult.success) {
|
|
237
|
+
return { success: false, error: patchResult.error ?? 'Invalid patch version' };
|
|
238
|
+
}
|
|
239
|
+
pos = patchResult.endPos;
|
|
240
|
+
// Parse optional prerelease
|
|
241
|
+
const prerelease = [];
|
|
242
|
+
if (pos < end && input.charCodeAt(pos) === 45) {
|
|
243
|
+
// '-'
|
|
244
|
+
pos++;
|
|
245
|
+
const prereleaseResult = parseIdentifiers(input, pos, end, [43]); // Stop at '+'
|
|
246
|
+
if (!prereleaseResult.success) {
|
|
247
|
+
return { success: false, error: prereleaseResult.error ?? 'Invalid prerelease' };
|
|
248
|
+
}
|
|
249
|
+
prerelease.push(...prereleaseResult.identifiers);
|
|
250
|
+
pos = prereleaseResult.endPos;
|
|
251
|
+
}
|
|
252
|
+
// Parse optional build metadata
|
|
253
|
+
const build = [];
|
|
254
|
+
if (pos < end && input.charCodeAt(pos) === 43) {
|
|
255
|
+
// '+'
|
|
256
|
+
pos++;
|
|
257
|
+
const buildResult = parseIdentifiers(input, pos, end, []);
|
|
258
|
+
if (!buildResult.success) {
|
|
259
|
+
return { success: false, error: buildResult.error ?? 'Invalid build metadata' };
|
|
260
|
+
}
|
|
261
|
+
build.push(...buildResult.identifiers);
|
|
262
|
+
pos = buildResult.endPos;
|
|
263
|
+
}
|
|
264
|
+
// Check for trailing characters
|
|
265
|
+
if (pos < end) {
|
|
266
|
+
return { success: false, error: `Unexpected character at position ${pos}: "${input[pos]}"` };
|
|
267
|
+
}
|
|
268
|
+
return {
|
|
269
|
+
success: true,
|
|
270
|
+
version: createSemVer({
|
|
271
|
+
major: majorResult.value,
|
|
272
|
+
minor: minorResult.value,
|
|
273
|
+
patch: patchResult.value,
|
|
274
|
+
prerelease,
|
|
275
|
+
build,
|
|
276
|
+
raw: input,
|
|
277
|
+
}),
|
|
278
|
+
};
|
|
279
|
+
}
|
|
280
|
+
/**
|
|
281
|
+
* Parses a version string, throwing on invalid input.
|
|
282
|
+
*
|
|
283
|
+
* @param input - The version string to parse
|
|
284
|
+
* @returns The parsed SemVer
|
|
285
|
+
* @throws {Error} If the input is not a valid version
|
|
286
|
+
*/
|
|
287
|
+
function parseVersionStrict(input) {
|
|
288
|
+
const result = parseVersion(input);
|
|
289
|
+
if (!result.success || !result.version) {
|
|
290
|
+
throw createError(result.error ?? 'Invalid version');
|
|
291
|
+
}
|
|
292
|
+
return result.version;
|
|
293
|
+
}
|
|
294
|
+
/**
|
|
295
|
+
* Attempts to coerce a string into a valid semver.
|
|
296
|
+
* More lenient than parseVersion - accepts partial versions.
|
|
297
|
+
*
|
|
298
|
+
* @param input - The string to coerce
|
|
299
|
+
* @returns The parsed SemVer or null if coercion failed
|
|
300
|
+
*
|
|
301
|
+
* @example
|
|
302
|
+
* coerceVersion('1') // { major: 1, minor: 0, patch: 0, ... }
|
|
303
|
+
* coerceVersion('1.2') // { major: 1, minor: 2, patch: 0, ... }
|
|
304
|
+
* coerceVersion('v2.0') // { major: 2, minor: 0, patch: 0, ... }
|
|
305
|
+
*/
|
|
306
|
+
function coerceVersion(input) {
|
|
307
|
+
if (!input || typeof input !== 'string') {
|
|
308
|
+
return null;
|
|
309
|
+
}
|
|
310
|
+
// Try strict parse first
|
|
311
|
+
const strict = parseVersion(input);
|
|
312
|
+
if (strict.success && strict.version) {
|
|
313
|
+
return strict.version;
|
|
314
|
+
}
|
|
315
|
+
// Strip leading/trailing whitespace
|
|
316
|
+
let pos = 0;
|
|
317
|
+
while (pos < input.length && isWhitespace(input.charCodeAt(pos))) {
|
|
318
|
+
pos++;
|
|
319
|
+
}
|
|
320
|
+
let end = input.length;
|
|
321
|
+
while (end > pos && isWhitespace(input.charCodeAt(end - 1))) {
|
|
322
|
+
end--;
|
|
323
|
+
}
|
|
324
|
+
// Strip optional 'v' prefix
|
|
325
|
+
if (pos < end) {
|
|
326
|
+
const code = input.charCodeAt(pos);
|
|
327
|
+
if (code === 118 || code === 86) {
|
|
328
|
+
// 'v' or 'V'
|
|
329
|
+
pos++;
|
|
330
|
+
}
|
|
331
|
+
}
|
|
332
|
+
// Parse major
|
|
333
|
+
const majorResult = parseNumericIdentifier(input, pos, end);
|
|
334
|
+
if (!majorResult.success) {
|
|
335
|
+
return null;
|
|
336
|
+
}
|
|
337
|
+
const major = majorResult.value;
|
|
338
|
+
pos = majorResult.endPos;
|
|
339
|
+
// Parse optional minor
|
|
340
|
+
let minor = 0;
|
|
341
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
342
|
+
pos++;
|
|
343
|
+
const minorResult = parseNumericIdentifier(input, pos, end);
|
|
344
|
+
if (minorResult.success) {
|
|
345
|
+
minor = minorResult.value;
|
|
346
|
+
pos = minorResult.endPos;
|
|
347
|
+
}
|
|
348
|
+
}
|
|
349
|
+
// Parse optional patch
|
|
350
|
+
let patch = 0;
|
|
351
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
352
|
+
pos++;
|
|
353
|
+
const patchResult = parseNumericIdentifier(input, pos, end);
|
|
354
|
+
if (patchResult.success) {
|
|
355
|
+
patch = patchResult.value;
|
|
356
|
+
// pos = patchResult.endPos // We ignore anything after patch in coerce
|
|
357
|
+
}
|
|
358
|
+
}
|
|
359
|
+
return createSemVer({
|
|
360
|
+
major,
|
|
361
|
+
minor,
|
|
362
|
+
patch,
|
|
363
|
+
prerelease: [],
|
|
364
|
+
build: [],
|
|
365
|
+
raw: input,
|
|
366
|
+
});
|
|
367
|
+
}
|
|
368
|
+
/**
|
|
369
|
+
* Parses a numeric identifier (non-negative integer, no leading zeros except for "0").
|
|
370
|
+
*
|
|
371
|
+
* @param input - Input string to parse
|
|
372
|
+
* @param start - Start position in the input
|
|
373
|
+
* @param end - End position in the input
|
|
374
|
+
* @returns Numeric parsing result
|
|
375
|
+
*/
|
|
376
|
+
function parseNumericIdentifier(input, start, end) {
|
|
377
|
+
if (start >= end) {
|
|
378
|
+
return { success: false, value: 0, endPos: start, error: 'Expected numeric identifier' };
|
|
379
|
+
}
|
|
380
|
+
let pos = start;
|
|
381
|
+
const firstCode = input.charCodeAt(pos);
|
|
382
|
+
// Must start with a digit
|
|
383
|
+
if (!isDigit(firstCode)) {
|
|
384
|
+
return { success: false, value: 0, endPos: pos, error: 'Expected digit' };
|
|
385
|
+
}
|
|
386
|
+
// Check for leading zero (only "0" is valid, not "01", "007", etc.)
|
|
387
|
+
if (firstCode === 48 && pos + 1 < end && isDigit(input.charCodeAt(pos + 1))) {
|
|
388
|
+
return { success: false, value: 0, endPos: pos, error: 'Numeric identifier cannot have leading zeros' };
|
|
389
|
+
}
|
|
390
|
+
// Consume digits
|
|
391
|
+
let value = 0;
|
|
392
|
+
while (pos < end && isDigit(input.charCodeAt(pos))) {
|
|
393
|
+
value = value * 10 + (input.charCodeAt(pos) - 48);
|
|
394
|
+
pos++;
|
|
395
|
+
// Prevent overflow
|
|
396
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
397
|
+
return { success: false, value: 0, endPos: pos, error: 'Numeric identifier is too large' };
|
|
398
|
+
}
|
|
399
|
+
}
|
|
400
|
+
return { success: true, value, endPos: pos };
|
|
401
|
+
}
|
|
402
|
+
/**
|
|
403
|
+
* Parses dot-separated identifiers (for prerelease/build).
|
|
404
|
+
*
|
|
405
|
+
* @param input - Input string to parse
|
|
406
|
+
* @param start - Start position in the input
|
|
407
|
+
* @param end - End position in the input
|
|
408
|
+
* @param stopCodes - Character codes that signal end of identifiers
|
|
409
|
+
* @returns Identifiers parsing result
|
|
410
|
+
*/
|
|
411
|
+
function parseIdentifiers(input, start, end, stopCodes) {
|
|
412
|
+
const identifiers = [];
|
|
413
|
+
let pos = start;
|
|
414
|
+
while (pos < end) {
|
|
415
|
+
// Check for stop characters
|
|
416
|
+
if (stopCodes.includes(input.charCodeAt(pos))) {
|
|
417
|
+
break;
|
|
418
|
+
}
|
|
419
|
+
// Parse one identifier
|
|
420
|
+
const identStart = pos;
|
|
421
|
+
while (pos < end) {
|
|
422
|
+
const code = input.charCodeAt(pos);
|
|
423
|
+
// Stop at dot or stop characters
|
|
424
|
+
if (code === 46 || stopCodes.includes(code)) {
|
|
425
|
+
break;
|
|
426
|
+
}
|
|
427
|
+
// Must be alphanumeric or hyphen
|
|
428
|
+
if (!isAlphanumeric(code) && code !== 45) {
|
|
429
|
+
return { success: false, identifiers: [], endPos: pos, error: `Invalid character in identifier: "${input[pos]}"` };
|
|
430
|
+
}
|
|
431
|
+
pos++;
|
|
432
|
+
}
|
|
433
|
+
// Empty identifier is not allowed
|
|
434
|
+
if (pos === identStart) {
|
|
435
|
+
return { success: false, identifiers: [], endPos: pos, error: 'Empty identifier' };
|
|
436
|
+
}
|
|
437
|
+
identifiers.push(input.slice(identStart, pos));
|
|
438
|
+
// Consume dot separator
|
|
439
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
440
|
+
pos++;
|
|
441
|
+
// Dot at end is invalid
|
|
442
|
+
if (pos >= end || stopCodes.includes(input.charCodeAt(pos))) {
|
|
443
|
+
return { success: false, identifiers: [], endPos: pos, error: 'Identifier expected after dot' };
|
|
444
|
+
}
|
|
445
|
+
}
|
|
446
|
+
}
|
|
447
|
+
return { success: true, identifiers, endPos: pos };
|
|
448
|
+
}
|
|
449
|
+
/**
|
|
450
|
+
* Checks if a character code is a digit (0-9).
|
|
451
|
+
*
|
|
452
|
+
* @param code - Character code to check
|
|
453
|
+
* @returns True if the code represents a digit
|
|
454
|
+
*/
|
|
455
|
+
function isDigit(code) {
|
|
456
|
+
return code >= 48 && code <= 57;
|
|
457
|
+
}
|
|
458
|
+
/**
|
|
459
|
+
* Checks if a character code is alphanumeric or hyphen.
|
|
460
|
+
*
|
|
461
|
+
* @param code - Character code to check
|
|
462
|
+
* @returns True if the code represents an alphanumeric character
|
|
463
|
+
*/
|
|
464
|
+
function isAlphanumeric(code) {
|
|
465
|
+
return ((code >= 48 && code <= 57) || // 0-9
|
|
466
|
+
(code >= 65 && code <= 90) || // A-Z
|
|
467
|
+
(code >= 97 && code <= 122) // a-z
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
/**
|
|
471
|
+
* Checks if a character code is whitespace.
|
|
472
|
+
*
|
|
473
|
+
* @param code - Character code to check
|
|
474
|
+
* @returns True if the code represents whitespace
|
|
475
|
+
*/
|
|
476
|
+
function isWhitespace(code) {
|
|
477
|
+
return code === 32 || code === 9 || code === 10 || code === 13;
|
|
478
|
+
}
|
|
479
|
+
|
|
480
|
+
/**
|
|
481
|
+
* Safe copies of Number built-in methods and constants.
|
|
482
|
+
*
|
|
483
|
+
* These references are captured at module initialization time to protect against
|
|
484
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
485
|
+
*
|
|
486
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/number
|
|
487
|
+
*/
|
|
488
|
+
// Capture references at module initialization time
|
|
489
|
+
const _parseInt = globalThis.parseInt;
|
|
490
|
+
const _isNaN = globalThis.isNaN;
|
|
491
|
+
// ============================================================================
|
|
492
|
+
// Parsing
|
|
493
|
+
// ============================================================================
|
|
494
|
+
/**
|
|
495
|
+
* (Safe copy) Parses a string and returns an integer.
|
|
496
|
+
*/
|
|
497
|
+
const parseInt = _parseInt;
|
|
498
|
+
// ============================================================================
|
|
499
|
+
// Global Type Checking (legacy, less strict)
|
|
500
|
+
// ============================================================================
|
|
501
|
+
/**
|
|
502
|
+
* (Safe copy) Global isNaN function (coerces to number first, less strict than Number.isNaN).
|
|
503
|
+
*/
|
|
504
|
+
const globalIsNaN = _isNaN;
|
|
505
|
+
|
|
506
|
+
/**
|
|
507
|
+
* Maximum range string length.
|
|
508
|
+
*/
|
|
509
|
+
const MAX_RANGE_LENGTH = 1024;
|
|
510
|
+
/**
|
|
511
|
+
* Parses a semver range string.
|
|
512
|
+
*
|
|
513
|
+
* Supports:
|
|
514
|
+
* - Exact: 1.2.3, =1.2.3
|
|
515
|
+
* - Comparators: >1.0.0, >=1.0.0, <2.0.0, <=2.0.0
|
|
516
|
+
* - Caret: ^1.2.3 (compatible with version)
|
|
517
|
+
* - Tilde: ~1.2.3 (approximately equivalent)
|
|
518
|
+
* - X-ranges: 1.x, 1.2.x, *
|
|
519
|
+
* - Hyphen ranges: 1.0.0 - 2.0.0
|
|
520
|
+
* - OR: 1.0.0 || 2.0.0
|
|
521
|
+
* - AND: >=1.0.0 <2.0.0
|
|
522
|
+
*
|
|
523
|
+
* @param input - The range string to parse
|
|
524
|
+
* @returns A ParseRangeResult with the parsed range or error
|
|
525
|
+
*/
|
|
526
|
+
function parseRange(input) {
|
|
527
|
+
if (!input || typeof input !== 'string') {
|
|
528
|
+
return { success: false, error: 'Range string is required' };
|
|
529
|
+
}
|
|
530
|
+
if (input.length > MAX_RANGE_LENGTH) {
|
|
531
|
+
return { success: false, error: `Range string exceeds maximum length of ${MAX_RANGE_LENGTH}` };
|
|
532
|
+
}
|
|
533
|
+
// Trim whitespace
|
|
534
|
+
const trimmed = input.trim();
|
|
535
|
+
// Handle wildcard/any
|
|
536
|
+
if (trimmed === '' || trimmed === '*' || trimmed.toLowerCase() === 'x') {
|
|
537
|
+
return { success: true, range: createRange([], input) };
|
|
538
|
+
}
|
|
539
|
+
// Split by || for OR logic
|
|
540
|
+
const orParts = splitByOr(trimmed);
|
|
541
|
+
const sets = [];
|
|
542
|
+
for (const part of orParts) {
|
|
543
|
+
const setResult = parseComparatorSet(part.trim());
|
|
544
|
+
if (!setResult.success) {
|
|
545
|
+
return { success: false, error: setResult.error };
|
|
546
|
+
}
|
|
547
|
+
if (setResult.set) {
|
|
548
|
+
sets.push(setResult.set);
|
|
549
|
+
}
|
|
550
|
+
}
|
|
551
|
+
return { success: true, range: createRange(sets, input) };
|
|
552
|
+
}
|
|
553
|
+
/**
|
|
554
|
+
* Parses a range string, throwing on invalid input.
|
|
555
|
+
*
|
|
556
|
+
* @param input - The range string to parse
|
|
557
|
+
* @returns The parsed Range
|
|
558
|
+
* @throws {Error} If the input is not a valid range
|
|
559
|
+
*/
|
|
560
|
+
function parseRangeStrict(input) {
|
|
561
|
+
const result = parseRange(input);
|
|
562
|
+
if (!result.success || !result.range) {
|
|
563
|
+
throw createError(result.error ?? 'Invalid range');
|
|
564
|
+
}
|
|
565
|
+
return result.range;
|
|
566
|
+
}
|
|
567
|
+
/**
|
|
568
|
+
* Splits a string by || delimiter, respecting nesting.
|
|
569
|
+
*
|
|
570
|
+
* @param input - Range string containing OR groups
|
|
571
|
+
* @returns Array of OR-separated parts
|
|
572
|
+
*/
|
|
573
|
+
function splitByOr(input) {
|
|
574
|
+
const parts = [];
|
|
575
|
+
let current = '';
|
|
576
|
+
let pos = 0;
|
|
577
|
+
while (pos < input.length) {
|
|
578
|
+
if (input[pos] === '|' && pos + 1 < input.length && input[pos + 1] === '|') {
|
|
579
|
+
parts.push(current);
|
|
580
|
+
current = '';
|
|
581
|
+
pos += 2;
|
|
582
|
+
}
|
|
583
|
+
else {
|
|
584
|
+
current += input[pos];
|
|
585
|
+
pos++;
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
parts.push(current);
|
|
589
|
+
return parts;
|
|
590
|
+
}
|
|
591
|
+
/**
|
|
592
|
+
* Parses a single comparator set (space-separated comparators = AND logic).
|
|
593
|
+
*
|
|
594
|
+
* @param input - Comparator set string
|
|
595
|
+
* @returns Parsed set result
|
|
596
|
+
*/
|
|
597
|
+
function parseComparatorSet(input) {
|
|
598
|
+
if (!input || input.trim() === '') {
|
|
599
|
+
return { success: true }; // Empty set matches any
|
|
600
|
+
}
|
|
601
|
+
const trimmed = input.trim();
|
|
602
|
+
// Check for hyphen range: "1.0.0 - 2.0.0"
|
|
603
|
+
const hyphenMatch = parseHyphenRange(trimmed);
|
|
604
|
+
if (hyphenMatch.isHyphenRange) {
|
|
605
|
+
if (!hyphenMatch.success) {
|
|
606
|
+
return { success: false, error: hyphenMatch.error };
|
|
607
|
+
}
|
|
608
|
+
return { success: true, set: hyphenMatch.set };
|
|
609
|
+
}
|
|
610
|
+
// Split by whitespace for AND logic
|
|
611
|
+
const tokens = splitByWhitespace(trimmed);
|
|
612
|
+
const comparators = [];
|
|
613
|
+
for (const token of tokens) {
|
|
614
|
+
const compResult = parseSingleComparator(token);
|
|
615
|
+
if (!compResult.success) {
|
|
616
|
+
return { success: false, error: compResult.error };
|
|
617
|
+
}
|
|
618
|
+
if (compResult.comparators) {
|
|
619
|
+
comparators.push(...compResult.comparators);
|
|
620
|
+
}
|
|
621
|
+
}
|
|
622
|
+
if (comparators.length === 0) {
|
|
623
|
+
return { success: true }; // Empty matches any
|
|
624
|
+
}
|
|
625
|
+
return { success: true, set: createComparatorSet(comparators) };
|
|
626
|
+
}
|
|
627
|
+
/**
|
|
628
|
+
* Checks for and parses hyphen ranges like "1.0.0 - 2.0.0".
|
|
629
|
+
*
|
|
630
|
+
* @param input - Potential hyphen range string
|
|
631
|
+
* @returns Hyphen range parsing result
|
|
632
|
+
*/
|
|
633
|
+
function parseHyphenRange(input) {
|
|
634
|
+
// Look for " - " (space-hyphen-space)
|
|
635
|
+
let hyphenPos = -1;
|
|
636
|
+
for (let i = 0; i < input.length - 2; i++) {
|
|
637
|
+
if (input[i] === ' ' && input[i + 1] === '-' && input[i + 2] === ' ') {
|
|
638
|
+
hyphenPos = i;
|
|
639
|
+
break;
|
|
640
|
+
}
|
|
641
|
+
}
|
|
642
|
+
if (hyphenPos === -1) {
|
|
643
|
+
return { isHyphenRange: false, success: true };
|
|
644
|
+
}
|
|
645
|
+
const leftPart = input.slice(0, hyphenPos).trim();
|
|
646
|
+
const rightPart = input.slice(hyphenPos + 3).trim();
|
|
647
|
+
const leftVersion = parseSimpleVersion(leftPart);
|
|
648
|
+
if (!leftVersion) {
|
|
649
|
+
return { isHyphenRange: true, success: false, error: `Invalid left side of hyphen range: "${leftPart}"` };
|
|
650
|
+
}
|
|
651
|
+
const rightVersion = parseSimpleVersion(rightPart);
|
|
652
|
+
if (!rightVersion) {
|
|
653
|
+
return { isHyphenRange: true, success: false, error: `Invalid right side of hyphen range: "${rightPart}"` };
|
|
654
|
+
}
|
|
655
|
+
// Hyphen range: >=left <=right
|
|
656
|
+
const comparators = [createComparator('>=', leftVersion), createComparator('<=', rightVersion)];
|
|
657
|
+
return {
|
|
658
|
+
isHyphenRange: true,
|
|
659
|
+
success: true,
|
|
660
|
+
set: createComparatorSet(comparators),
|
|
661
|
+
};
|
|
662
|
+
}
|
|
663
|
+
/**
|
|
664
|
+
* Splits by whitespace.
|
|
665
|
+
*
|
|
666
|
+
* @param input - String to split
|
|
667
|
+
* @returns Array of whitespace-separated tokens
|
|
668
|
+
*/
|
|
669
|
+
function splitByWhitespace(input) {
|
|
670
|
+
const tokens = [];
|
|
671
|
+
let current = '';
|
|
672
|
+
for (const char of input) {
|
|
673
|
+
if (char === ' ' || char === '\t') {
|
|
674
|
+
if (current) {
|
|
675
|
+
tokens.push(current);
|
|
676
|
+
current = '';
|
|
677
|
+
}
|
|
678
|
+
}
|
|
679
|
+
else {
|
|
680
|
+
current += char;
|
|
681
|
+
}
|
|
682
|
+
}
|
|
683
|
+
if (current) {
|
|
684
|
+
tokens.push(current);
|
|
685
|
+
}
|
|
686
|
+
return tokens;
|
|
687
|
+
}
|
|
688
|
+
/**
|
|
689
|
+
* Parses a single comparator token (e.g., ">=1.0.0", "^1.2.3", "~1.0").
|
|
690
|
+
*
|
|
691
|
+
* @param token - Comparator token to parse
|
|
692
|
+
* @returns Parsed comparator result
|
|
693
|
+
*/
|
|
694
|
+
function parseSingleComparator(token) {
|
|
695
|
+
let pos = 0;
|
|
696
|
+
let operator = '=';
|
|
697
|
+
// Parse operator
|
|
698
|
+
if (token[pos] === '^') {
|
|
699
|
+
operator = '^';
|
|
700
|
+
pos++;
|
|
701
|
+
}
|
|
702
|
+
else if (token[pos] === '~') {
|
|
703
|
+
operator = '~';
|
|
704
|
+
pos++;
|
|
705
|
+
}
|
|
706
|
+
else if (token[pos] === '>') {
|
|
707
|
+
if (token[pos + 1] === '=') {
|
|
708
|
+
operator = '>=';
|
|
709
|
+
pos += 2;
|
|
710
|
+
}
|
|
711
|
+
else {
|
|
712
|
+
operator = '>';
|
|
713
|
+
pos++;
|
|
714
|
+
}
|
|
715
|
+
}
|
|
716
|
+
else if (token[pos] === '<') {
|
|
717
|
+
if (token[pos + 1] === '=') {
|
|
718
|
+
operator = '<=';
|
|
719
|
+
pos += 2;
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
operator = '<';
|
|
723
|
+
pos++;
|
|
724
|
+
}
|
|
725
|
+
}
|
|
726
|
+
else if (token[pos] === '=') {
|
|
727
|
+
operator = '=';
|
|
728
|
+
pos++;
|
|
729
|
+
}
|
|
730
|
+
const versionPart = token.slice(pos);
|
|
731
|
+
// Handle wildcards: *, x, X
|
|
732
|
+
if (versionPart === '*' || versionPart.toLowerCase() === 'x') {
|
|
733
|
+
// Wildcard matches any - return empty (will be handled as match-all)
|
|
734
|
+
return { success: true, comparators: [] };
|
|
735
|
+
}
|
|
736
|
+
// Handle x-ranges: 1.x, 1.2.x
|
|
737
|
+
if (versionPart.includes('x') || versionPart.includes('X') || versionPart.includes('*')) {
|
|
738
|
+
return parseXRange(versionPart);
|
|
739
|
+
}
|
|
740
|
+
// Parse version
|
|
741
|
+
const version = parseSimpleVersion(versionPart);
|
|
742
|
+
if (!version) {
|
|
743
|
+
return { success: false, error: `Invalid version in comparator: "${versionPart}"` };
|
|
744
|
+
}
|
|
745
|
+
// For caret and tilde, expand to range
|
|
746
|
+
if (operator === '^') {
|
|
747
|
+
return expandCaretRange(version);
|
|
748
|
+
}
|
|
749
|
+
if (operator === '~') {
|
|
750
|
+
return expandTildeRange(version);
|
|
751
|
+
}
|
|
752
|
+
return { success: true, comparators: [createComparator(operator, version)] };
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Parses x-ranges like 1.x, 1.2.x, etc.
|
|
756
|
+
*
|
|
757
|
+
* @param input - X-range string to parse
|
|
758
|
+
* @param _operator - Range operator (unused but kept for interface consistency)
|
|
759
|
+
* @returns Comparator result
|
|
760
|
+
*/
|
|
761
|
+
function parseXRange(input, _operator) {
|
|
762
|
+
const parts = input.split('.');
|
|
763
|
+
const nums = [];
|
|
764
|
+
for (const part of parts) {
|
|
765
|
+
const lower = part.toLowerCase();
|
|
766
|
+
if (lower === 'x' || lower === '*' || lower === '') {
|
|
767
|
+
break;
|
|
768
|
+
}
|
|
769
|
+
const num = parseInt(part, 10);
|
|
770
|
+
if (globalIsNaN(num) || num < 0) {
|
|
771
|
+
return { success: false, error: `Invalid x-range: "${input}"` };
|
|
772
|
+
}
|
|
773
|
+
nums.push(num);
|
|
774
|
+
}
|
|
775
|
+
if (nums.length === 0) {
|
|
776
|
+
// * or X alone - match any
|
|
777
|
+
return { success: true, comparators: [] };
|
|
778
|
+
}
|
|
779
|
+
if (nums.length === 1) {
|
|
780
|
+
// 1.x or 1.* -> >=1.0.0 <2.0.0
|
|
781
|
+
const lower = createSemVer({ major: nums[0], minor: 0, patch: 0 });
|
|
782
|
+
const upper = createSemVer({ major: nums[0] + 1, minor: 0, patch: 0 });
|
|
783
|
+
return { success: true, comparators: [createComparator('>=', lower), createComparator('<', upper)] };
|
|
784
|
+
}
|
|
785
|
+
// 1.2.x -> >=1.2.0 <1.3.0
|
|
786
|
+
const lower = createSemVer({ major: nums[0], minor: nums[1], patch: 0 });
|
|
787
|
+
const upper = createSemVer({ major: nums[0], minor: nums[1] + 1, patch: 0 });
|
|
788
|
+
return { success: true, comparators: [createComparator('>=', lower), createComparator('<', upper)] };
|
|
789
|
+
}
|
|
790
|
+
/**
|
|
791
|
+
* Expands caret range: ^1.2.3 -> >=1.2.3 <2.0.0
|
|
792
|
+
*
|
|
793
|
+
* @param version - Base version for caret range
|
|
794
|
+
* @returns Expanded comparator result
|
|
795
|
+
*/
|
|
796
|
+
function expandCaretRange(version) {
|
|
797
|
+
let upperMajor = version.major;
|
|
798
|
+
let upperMinor = 0;
|
|
799
|
+
let upperPatch = 0;
|
|
800
|
+
if (version.major === 0) {
|
|
801
|
+
if (version.minor === 0) {
|
|
802
|
+
// ^0.0.x -> >=0.0.x <0.0.(x+1)
|
|
803
|
+
upperPatch = version.patch + 1;
|
|
804
|
+
upperMinor = version.minor;
|
|
805
|
+
}
|
|
806
|
+
else {
|
|
807
|
+
// ^0.x.y -> >=0.x.y <0.(x+1).0
|
|
808
|
+
upperMinor = version.minor + 1;
|
|
809
|
+
}
|
|
810
|
+
}
|
|
811
|
+
else {
|
|
812
|
+
// ^x.y.z -> >=x.y.z <(x+1).0.0
|
|
813
|
+
upperMajor = version.major + 1;
|
|
814
|
+
}
|
|
815
|
+
const upper = createSemVer({ major: upperMajor, minor: upperMinor, patch: upperPatch });
|
|
816
|
+
return { success: true, comparators: [createComparator('>=', version), createComparator('<', upper)] };
|
|
817
|
+
}
|
|
818
|
+
/**
|
|
819
|
+
* Expands tilde range: ~1.2.3 -> >=1.2.3 <1.3.0
|
|
820
|
+
*
|
|
821
|
+
* @param version - Base version for tilde range
|
|
822
|
+
* @returns Expanded comparator result
|
|
823
|
+
*/
|
|
824
|
+
function expandTildeRange(version) {
|
|
825
|
+
const upper = createSemVer({
|
|
826
|
+
major: version.major,
|
|
827
|
+
minor: version.minor + 1,
|
|
828
|
+
patch: 0,
|
|
829
|
+
});
|
|
830
|
+
return { success: true, comparators: [createComparator('>=', version), createComparator('<', upper)] };
|
|
831
|
+
}
|
|
832
|
+
/**
|
|
833
|
+
* Parses a simple version string (no range operators).
|
|
834
|
+
* More lenient - accepts partial versions.
|
|
835
|
+
*
|
|
836
|
+
* @param input - Version string to parse
|
|
837
|
+
* @returns Parsed SemVer or null if invalid
|
|
838
|
+
*/
|
|
839
|
+
function parseSimpleVersion(input) {
|
|
840
|
+
if (!input)
|
|
841
|
+
return null;
|
|
842
|
+
let pos = 0;
|
|
843
|
+
// Skip leading v
|
|
844
|
+
if (input[pos] === 'v' || input[pos] === 'V') {
|
|
845
|
+
pos++;
|
|
846
|
+
}
|
|
847
|
+
const parts = input.slice(pos).split('.');
|
|
848
|
+
if (parts.length === 0)
|
|
849
|
+
return null;
|
|
850
|
+
const nums = [];
|
|
851
|
+
for (const part of parts) {
|
|
852
|
+
// Stop at prerelease or build
|
|
853
|
+
const dashIdx = part.indexOf('-');
|
|
854
|
+
const plusIdx = part.indexOf('+');
|
|
855
|
+
let numPart = part;
|
|
856
|
+
if (dashIdx !== -1) {
|
|
857
|
+
numPart = part.slice(0, dashIdx);
|
|
858
|
+
}
|
|
859
|
+
else if (plusIdx !== -1) {
|
|
860
|
+
numPart = part.slice(0, plusIdx);
|
|
861
|
+
}
|
|
862
|
+
if (numPart === '' || numPart.toLowerCase() === 'x' || numPart === '*') {
|
|
863
|
+
break;
|
|
864
|
+
}
|
|
865
|
+
const num = parseInt(numPart, 10);
|
|
866
|
+
if (globalIsNaN(num) || num < 0)
|
|
867
|
+
return null;
|
|
868
|
+
nums.push(num);
|
|
869
|
+
}
|
|
870
|
+
if (nums.length === 0)
|
|
871
|
+
return null;
|
|
872
|
+
return createSemVer({
|
|
873
|
+
major: nums[0],
|
|
874
|
+
minor: nums[1] ?? 0,
|
|
875
|
+
patch: nums[2] ?? 0,
|
|
876
|
+
prerelease: [],
|
|
877
|
+
build: [],
|
|
878
|
+
raw: input,
|
|
879
|
+
});
|
|
880
|
+
}
|
|
881
|
+
|
|
882
|
+
/**
|
|
883
|
+
* Safe copies of Math built-in methods.
|
|
884
|
+
*
|
|
885
|
+
* These references are captured at module initialization time to protect against
|
|
886
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
887
|
+
*
|
|
888
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/math
|
|
889
|
+
*/
|
|
890
|
+
// Capture references at module initialization time
|
|
891
|
+
const _Math = globalThis.Math;
|
|
892
|
+
// ============================================================================
|
|
893
|
+
// Min/Max
|
|
894
|
+
// ============================================================================
|
|
895
|
+
/**
|
|
896
|
+
* (Safe copy) Returns the larger of zero or more numbers.
|
|
897
|
+
*/
|
|
898
|
+
const max$1 = _Math.max;
|
|
899
|
+
|
|
900
|
+
/**
|
|
901
|
+
* Compares two semantic versions.
|
|
902
|
+
*
|
|
903
|
+
* @param a - First version
|
|
904
|
+
* @param b - Second version
|
|
905
|
+
* @returns -1 if a < b, 0 if a == b, 1 if a > b
|
|
906
|
+
*
|
|
907
|
+
* @example
|
|
908
|
+
* compare(parseVersion('1.0.0'), parseVersion('2.0.0')) // -1
|
|
909
|
+
* compare(parseVersion('1.0.0'), parseVersion('1.0.0')) // 0
|
|
910
|
+
* compare(parseVersion('2.0.0'), parseVersion('1.0.0')) // 1
|
|
911
|
+
*/
|
|
912
|
+
function compare(a, b) {
|
|
913
|
+
// Compare major, minor, patch
|
|
914
|
+
if (a.major !== b.major) {
|
|
915
|
+
return a.major < b.major ? -1 : 1;
|
|
916
|
+
}
|
|
917
|
+
if (a.minor !== b.minor) {
|
|
918
|
+
return a.minor < b.minor ? -1 : 1;
|
|
919
|
+
}
|
|
920
|
+
if (a.patch !== b.patch) {
|
|
921
|
+
return a.patch < b.patch ? -1 : 1;
|
|
922
|
+
}
|
|
923
|
+
// Compare prerelease
|
|
924
|
+
// Version with prerelease has lower precedence than release
|
|
925
|
+
if (a.prerelease.length === 0 && b.prerelease.length > 0) {
|
|
926
|
+
return 1; // a is release, b is prerelease -> a > b
|
|
927
|
+
}
|
|
928
|
+
if (a.prerelease.length > 0 && b.prerelease.length === 0) {
|
|
929
|
+
return -1; // a is prerelease, b is release -> a < b
|
|
930
|
+
}
|
|
931
|
+
// Both have prerelease - compare identifiers
|
|
932
|
+
const maxLen = max$1(a.prerelease.length, b.prerelease.length);
|
|
933
|
+
for (let i = 0; i < maxLen; i++) {
|
|
934
|
+
const aId = a.prerelease[i];
|
|
935
|
+
const bId = b.prerelease[i];
|
|
936
|
+
// Shorter prerelease array has lower precedence
|
|
937
|
+
if (aId === undefined && bId !== undefined) {
|
|
938
|
+
return -1;
|
|
939
|
+
}
|
|
940
|
+
if (aId !== undefined && bId === undefined) {
|
|
941
|
+
return 1;
|
|
942
|
+
}
|
|
943
|
+
if (aId === undefined || bId === undefined) {
|
|
944
|
+
continue;
|
|
945
|
+
}
|
|
946
|
+
// Compare identifiers
|
|
947
|
+
const cmp = compareIdentifiers(aId, bId);
|
|
948
|
+
if (cmp !== 0) {
|
|
949
|
+
return cmp;
|
|
950
|
+
}
|
|
951
|
+
}
|
|
952
|
+
return 0;
|
|
953
|
+
}
|
|
954
|
+
/**
|
|
955
|
+
* Checks if two versions are equal (ignoring build metadata).
|
|
956
|
+
*
|
|
957
|
+
* @param a - First version
|
|
958
|
+
* @param b - Second version
|
|
959
|
+
* @returns True if versions are equal
|
|
960
|
+
*/
|
|
961
|
+
function eq(a, b) {
|
|
962
|
+
return compare(a, b) === 0;
|
|
963
|
+
}
|
|
964
|
+
/**
|
|
965
|
+
* Checks if a < b.
|
|
966
|
+
*
|
|
967
|
+
* @param a - First version to compare
|
|
968
|
+
* @param b - Second version to compare
|
|
969
|
+
* @returns True if a is less than b
|
|
970
|
+
*/
|
|
971
|
+
function lt(a, b) {
|
|
972
|
+
return compare(a, b) === -1;
|
|
973
|
+
}
|
|
974
|
+
/**
|
|
975
|
+
* Checks if a <= b.
|
|
976
|
+
*
|
|
977
|
+
* @param a - First version to compare
|
|
978
|
+
* @param b - Second version to compare
|
|
979
|
+
* @returns True if a is less than or equal to b
|
|
980
|
+
*/
|
|
981
|
+
function lte(a, b) {
|
|
982
|
+
return compare(a, b) !== 1;
|
|
983
|
+
}
|
|
984
|
+
/**
|
|
985
|
+
* Checks if a > b.
|
|
986
|
+
*
|
|
987
|
+
* @param a - First version to compare
|
|
988
|
+
* @param b - Second version to compare
|
|
989
|
+
* @returns True if a is greater than b
|
|
990
|
+
*/
|
|
991
|
+
function gt(a, b) {
|
|
992
|
+
return compare(a, b) === 1;
|
|
993
|
+
}
|
|
994
|
+
/**
|
|
995
|
+
* Checks if a >= b.
|
|
996
|
+
*
|
|
997
|
+
* @param a - First version to compare
|
|
998
|
+
* @param b - Second version to compare
|
|
999
|
+
* @returns True if a is greater than or equal to b
|
|
1000
|
+
*/
|
|
1001
|
+
function gte(a, b) {
|
|
1002
|
+
return compare(a, b) !== -1;
|
|
1003
|
+
}
|
|
1004
|
+
/**
|
|
1005
|
+
* Checks if a != b.
|
|
1006
|
+
*
|
|
1007
|
+
* @param a - First version to compare
|
|
1008
|
+
* @param b - Second version to compare
|
|
1009
|
+
* @returns True if versions are not equal
|
|
1010
|
+
*/
|
|
1011
|
+
function neq(a, b) {
|
|
1012
|
+
return compare(a, b) !== 0;
|
|
1013
|
+
}
|
|
1014
|
+
/**
|
|
1015
|
+
* Checks if a version satisfies a comparator.
|
|
1016
|
+
*
|
|
1017
|
+
* @param version - Version to check
|
|
1018
|
+
* @param comparator - Comparator to test against
|
|
1019
|
+
* @returns True if version satisfies the comparator
|
|
1020
|
+
*/
|
|
1021
|
+
function satisfiesComparator(version, comparator) {
|
|
1022
|
+
const cmp = compare(version, comparator.version);
|
|
1023
|
+
switch (comparator.operator) {
|
|
1024
|
+
case '=':
|
|
1025
|
+
return cmp === 0;
|
|
1026
|
+
case '>':
|
|
1027
|
+
return cmp === 1;
|
|
1028
|
+
case '>=':
|
|
1029
|
+
return cmp >= 0;
|
|
1030
|
+
case '<':
|
|
1031
|
+
return cmp === -1;
|
|
1032
|
+
case '<=':
|
|
1033
|
+
return cmp <= 0;
|
|
1034
|
+
case '^':
|
|
1035
|
+
case '~':
|
|
1036
|
+
// These should have been expanded during parsing
|
|
1037
|
+
// If we encounter them here, treat as >=
|
|
1038
|
+
return cmp >= 0;
|
|
1039
|
+
default:
|
|
1040
|
+
return false;
|
|
1041
|
+
}
|
|
1042
|
+
}
|
|
1043
|
+
/**
|
|
1044
|
+
* Checks if a version satisfies a range.
|
|
1045
|
+
*
|
|
1046
|
+
* @param version - Version to check
|
|
1047
|
+
* @param range - Range to test against
|
|
1048
|
+
* @returns True if version satisfies the range
|
|
1049
|
+
*
|
|
1050
|
+
* @example
|
|
1051
|
+
* satisfies(parseVersion('1.2.3'), parseRange('^1.0.0')) // true
|
|
1052
|
+
* satisfies(parseVersion('2.0.0'), parseRange('^1.0.0')) // false
|
|
1053
|
+
*/
|
|
1054
|
+
function satisfies(version, range) {
|
|
1055
|
+
// Empty range matches any
|
|
1056
|
+
if (range.sets.length === 0) {
|
|
1057
|
+
return true;
|
|
1058
|
+
}
|
|
1059
|
+
// OR logic: at least one set must be satisfied
|
|
1060
|
+
for (const set of range.sets) {
|
|
1061
|
+
// AND logic: all comparators in set must be satisfied
|
|
1062
|
+
let allSatisfied = true;
|
|
1063
|
+
// Empty comparator set matches any
|
|
1064
|
+
if (set.comparators.length === 0) {
|
|
1065
|
+
return true;
|
|
1066
|
+
}
|
|
1067
|
+
for (const comp of set.comparators) {
|
|
1068
|
+
if (!satisfiesComparator(version, comp)) {
|
|
1069
|
+
allSatisfied = false;
|
|
1070
|
+
break;
|
|
1071
|
+
}
|
|
1072
|
+
}
|
|
1073
|
+
if (allSatisfied) {
|
|
1074
|
+
return true;
|
|
1075
|
+
}
|
|
1076
|
+
}
|
|
1077
|
+
return false;
|
|
1078
|
+
}
|
|
1079
|
+
/**
|
|
1080
|
+
* Finds the maximum version that satisfies a range.
|
|
1081
|
+
*
|
|
1082
|
+
* @param versions - Array of versions to check
|
|
1083
|
+
* @param range - Range to test against
|
|
1084
|
+
* @returns The maximum satisfying version, or null if none satisfy
|
|
1085
|
+
*/
|
|
1086
|
+
function maxSatisfying(versions, range) {
|
|
1087
|
+
let max = null;
|
|
1088
|
+
for (const version of versions) {
|
|
1089
|
+
if (satisfies(version, range)) {
|
|
1090
|
+
if (max === null || gt(version, max)) {
|
|
1091
|
+
max = version;
|
|
1092
|
+
}
|
|
1093
|
+
}
|
|
1094
|
+
}
|
|
1095
|
+
return max;
|
|
1096
|
+
}
|
|
1097
|
+
/**
|
|
1098
|
+
* Finds the minimum version that satisfies a range.
|
|
1099
|
+
*
|
|
1100
|
+
* @param versions - Array of versions to check
|
|
1101
|
+
* @param range - Range to test against
|
|
1102
|
+
* @returns The minimum satisfying version, or null if none satisfy
|
|
1103
|
+
*/
|
|
1104
|
+
function minSatisfying(versions, range) {
|
|
1105
|
+
let min = null;
|
|
1106
|
+
for (const version of versions) {
|
|
1107
|
+
if (satisfies(version, range)) {
|
|
1108
|
+
if (min === null || lt(version, min)) {
|
|
1109
|
+
min = version;
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
}
|
|
1113
|
+
return min;
|
|
1114
|
+
}
|
|
1115
|
+
// ============================================================================
|
|
1116
|
+
// Internal helpers
|
|
1117
|
+
// ============================================================================
|
|
1118
|
+
/**
|
|
1119
|
+
* Compares two prerelease identifiers.
|
|
1120
|
+
* Numeric identifiers have lower precedence than alphanumeric.
|
|
1121
|
+
* Numeric identifiers are compared numerically.
|
|
1122
|
+
* Alphanumeric identifiers are compared lexically.
|
|
1123
|
+
*
|
|
1124
|
+
* @param a - First prerelease identifier
|
|
1125
|
+
* @param b - Second prerelease identifier
|
|
1126
|
+
* @returns -1 if a < b, 0 if equal, 1 if a > b
|
|
1127
|
+
*/
|
|
1128
|
+
function compareIdentifiers(a, b) {
|
|
1129
|
+
const aIsNumeric = isNumeric(a);
|
|
1130
|
+
const bIsNumeric = isNumeric(b);
|
|
1131
|
+
// Numeric identifiers have lower precedence
|
|
1132
|
+
if (aIsNumeric && !bIsNumeric) {
|
|
1133
|
+
return -1;
|
|
1134
|
+
}
|
|
1135
|
+
if (!aIsNumeric && bIsNumeric) {
|
|
1136
|
+
return 1;
|
|
1137
|
+
}
|
|
1138
|
+
// Both numeric - compare as numbers
|
|
1139
|
+
if (aIsNumeric && bIsNumeric) {
|
|
1140
|
+
const aNum = parseInt(a, 10);
|
|
1141
|
+
const bNum = parseInt(b, 10);
|
|
1142
|
+
if (aNum < bNum)
|
|
1143
|
+
return -1;
|
|
1144
|
+
if (aNum > bNum)
|
|
1145
|
+
return 1;
|
|
1146
|
+
return 0;
|
|
1147
|
+
}
|
|
1148
|
+
// Both alphanumeric - compare lexically
|
|
1149
|
+
if (a < b)
|
|
1150
|
+
return -1;
|
|
1151
|
+
if (a > b)
|
|
1152
|
+
return 1;
|
|
1153
|
+
return 0;
|
|
1154
|
+
}
|
|
1155
|
+
/**
|
|
1156
|
+
* Checks if a string consists only of digits.
|
|
1157
|
+
*
|
|
1158
|
+
* @param str - String to check for numeric content
|
|
1159
|
+
* @returns True if string contains only digits
|
|
1160
|
+
*/
|
|
1161
|
+
function isNumeric(str) {
|
|
1162
|
+
if (str.length === 0)
|
|
1163
|
+
return false;
|
|
1164
|
+
for (let i = 0; i < str.length; i++) {
|
|
1165
|
+
const code = str.charCodeAt(i);
|
|
1166
|
+
if (code < 48 || code > 57) {
|
|
1167
|
+
return false;
|
|
1168
|
+
}
|
|
1169
|
+
}
|
|
1170
|
+
return true;
|
|
1171
|
+
}
|
|
1172
|
+
|
|
1173
|
+
/**
|
|
1174
|
+
* Sorts an array of versions in ascending order.
|
|
1175
|
+
*
|
|
1176
|
+
* @param versions - Array of versions to sort
|
|
1177
|
+
* @returns A new sorted array
|
|
1178
|
+
*
|
|
1179
|
+
* @example
|
|
1180
|
+
* sort([v2, v1, v3]) // [v1, v2, v3]
|
|
1181
|
+
*/
|
|
1182
|
+
function sort(versions) {
|
|
1183
|
+
return [...versions].sort(compare);
|
|
1184
|
+
}
|
|
1185
|
+
/**
|
|
1186
|
+
* Sorts an array of versions in descending order.
|
|
1187
|
+
*
|
|
1188
|
+
* @param versions - Array of versions to sort
|
|
1189
|
+
* @returns A new sorted array
|
|
1190
|
+
*
|
|
1191
|
+
* @example
|
|
1192
|
+
* sortDescending([v1, v3, v2]) // [v3, v2, v1]
|
|
1193
|
+
*/
|
|
1194
|
+
function sortDescending(versions) {
|
|
1195
|
+
return [...versions].sort((a, b) => compare(b, a));
|
|
1196
|
+
}
|
|
1197
|
+
/**
|
|
1198
|
+
* Returns the maximum version from an array.
|
|
1199
|
+
*
|
|
1200
|
+
* @param versions - Array of versions
|
|
1201
|
+
* @returns The maximum version, or null if array is empty
|
|
1202
|
+
*/
|
|
1203
|
+
function max(versions) {
|
|
1204
|
+
if (versions.length === 0)
|
|
1205
|
+
return null;
|
|
1206
|
+
let maxVer = versions[0];
|
|
1207
|
+
for (let i = 1; i < versions.length; i++) {
|
|
1208
|
+
if (compare(versions[i], maxVer) === 1) {
|
|
1209
|
+
maxVer = versions[i];
|
|
1210
|
+
}
|
|
1211
|
+
}
|
|
1212
|
+
return maxVer;
|
|
1213
|
+
}
|
|
1214
|
+
/**
|
|
1215
|
+
* Returns the minimum version from an array.
|
|
1216
|
+
*
|
|
1217
|
+
* @param versions - Array of versions
|
|
1218
|
+
* @returns The minimum version, or null if array is empty
|
|
1219
|
+
*/
|
|
1220
|
+
function min(versions) {
|
|
1221
|
+
if (versions.length === 0)
|
|
1222
|
+
return null;
|
|
1223
|
+
let minVer = versions[0];
|
|
1224
|
+
for (let i = 1; i < versions.length; i++) {
|
|
1225
|
+
if (compare(versions[i], minVer) === -1) {
|
|
1226
|
+
minVer = versions[i];
|
|
1227
|
+
}
|
|
1228
|
+
}
|
|
1229
|
+
return minVer;
|
|
1230
|
+
}
|
|
1231
|
+
|
|
1232
|
+
/**
|
|
1233
|
+
* Increments a version based on the bump type.
|
|
1234
|
+
*
|
|
1235
|
+
* @param version - The version to increment
|
|
1236
|
+
* @param type - The type of bump (major, minor, patch, etc.)
|
|
1237
|
+
* @param prereleaseId - Optional prerelease identifier for prerelease bumps
|
|
1238
|
+
* @returns A new incremented SemVer
|
|
1239
|
+
*
|
|
1240
|
+
* @example
|
|
1241
|
+
* increment(parseVersion('1.2.3'), 'minor') // 1.3.0
|
|
1242
|
+
* increment(parseVersion('1.2.3'), 'major') // 2.0.0
|
|
1243
|
+
* increment(parseVersion('1.2.3'), 'prerelease', 'alpha') // 1.2.4-alpha.0
|
|
1244
|
+
*/
|
|
1245
|
+
function increment(version, type, prereleaseId) {
|
|
1246
|
+
switch (type) {
|
|
1247
|
+
case 'major':
|
|
1248
|
+
return createSemVer({
|
|
1249
|
+
major: version.major + 1,
|
|
1250
|
+
minor: 0,
|
|
1251
|
+
patch: 0,
|
|
1252
|
+
prerelease: [],
|
|
1253
|
+
build: [],
|
|
1254
|
+
});
|
|
1255
|
+
case 'minor':
|
|
1256
|
+
return createSemVer({
|
|
1257
|
+
major: version.major,
|
|
1258
|
+
minor: version.minor + 1,
|
|
1259
|
+
patch: 0,
|
|
1260
|
+
prerelease: [],
|
|
1261
|
+
build: [],
|
|
1262
|
+
});
|
|
1263
|
+
case 'patch':
|
|
1264
|
+
// If version has prerelease, just remove it (1.2.3-alpha -> 1.2.3)
|
|
1265
|
+
if (version.prerelease.length > 0) {
|
|
1266
|
+
return createSemVer({
|
|
1267
|
+
major: version.major,
|
|
1268
|
+
minor: version.minor,
|
|
1269
|
+
patch: version.patch,
|
|
1270
|
+
prerelease: [],
|
|
1271
|
+
build: [],
|
|
1272
|
+
});
|
|
1273
|
+
}
|
|
1274
|
+
return createSemVer({
|
|
1275
|
+
major: version.major,
|
|
1276
|
+
minor: version.minor,
|
|
1277
|
+
patch: version.patch + 1,
|
|
1278
|
+
prerelease: [],
|
|
1279
|
+
build: [],
|
|
1280
|
+
});
|
|
1281
|
+
case 'premajor':
|
|
1282
|
+
return createSemVer({
|
|
1283
|
+
major: version.major + 1,
|
|
1284
|
+
minor: 0,
|
|
1285
|
+
patch: 0,
|
|
1286
|
+
prerelease: [prereleaseId ?? 'alpha', '0'],
|
|
1287
|
+
build: [],
|
|
1288
|
+
});
|
|
1289
|
+
case 'preminor':
|
|
1290
|
+
return createSemVer({
|
|
1291
|
+
major: version.major,
|
|
1292
|
+
minor: version.minor + 1,
|
|
1293
|
+
patch: 0,
|
|
1294
|
+
prerelease: [prereleaseId ?? 'alpha', '0'],
|
|
1295
|
+
build: [],
|
|
1296
|
+
});
|
|
1297
|
+
case 'prepatch':
|
|
1298
|
+
return createSemVer({
|
|
1299
|
+
major: version.major,
|
|
1300
|
+
minor: version.minor,
|
|
1301
|
+
patch: version.patch + 1,
|
|
1302
|
+
prerelease: [prereleaseId ?? 'alpha', '0'],
|
|
1303
|
+
build: [],
|
|
1304
|
+
});
|
|
1305
|
+
case 'prerelease':
|
|
1306
|
+
return incrementPrerelease(version, prereleaseId);
|
|
1307
|
+
case 'none':
|
|
1308
|
+
default:
|
|
1309
|
+
return version;
|
|
1310
|
+
}
|
|
1311
|
+
}
|
|
1312
|
+
/**
|
|
1313
|
+
* Increments the prerelease portion of a version.
|
|
1314
|
+
*
|
|
1315
|
+
* @param version - The version to increment
|
|
1316
|
+
* @param id - Optional prerelease identifier
|
|
1317
|
+
* @returns A new version with incremented prerelease
|
|
1318
|
+
*/
|
|
1319
|
+
function incrementPrerelease(version, id) {
|
|
1320
|
+
const prerelease = [...version.prerelease];
|
|
1321
|
+
if (prerelease.length === 0) {
|
|
1322
|
+
// No existing prerelease - start at patch+1 with id.0
|
|
1323
|
+
return createSemVer({
|
|
1324
|
+
major: version.major,
|
|
1325
|
+
minor: version.minor,
|
|
1326
|
+
patch: version.patch + 1,
|
|
1327
|
+
prerelease: [id ?? 'alpha', '0'],
|
|
1328
|
+
build: [],
|
|
1329
|
+
});
|
|
1330
|
+
}
|
|
1331
|
+
// Check if the last identifier is numeric
|
|
1332
|
+
const lastIdx = prerelease.length - 1;
|
|
1333
|
+
const last = prerelease[lastIdx];
|
|
1334
|
+
const lastNum = parseInt(last, 10);
|
|
1335
|
+
if (!globalIsNaN(lastNum)) {
|
|
1336
|
+
// Increment the numeric part
|
|
1337
|
+
prerelease[lastIdx] = String(lastNum + 1);
|
|
1338
|
+
}
|
|
1339
|
+
else {
|
|
1340
|
+
// Append .0
|
|
1341
|
+
prerelease.push('0');
|
|
1342
|
+
}
|
|
1343
|
+
// If a different id is specified, replace the base identifier
|
|
1344
|
+
if (id && prerelease.length > 0 && prerelease[0] !== id) {
|
|
1345
|
+
prerelease[0] = id;
|
|
1346
|
+
// Reset numeric part
|
|
1347
|
+
if (prerelease.length > 1) {
|
|
1348
|
+
prerelease[prerelease.length - 1] = '0';
|
|
1349
|
+
}
|
|
1350
|
+
}
|
|
1351
|
+
return createSemVer({
|
|
1352
|
+
major: version.major,
|
|
1353
|
+
minor: version.minor,
|
|
1354
|
+
patch: version.patch,
|
|
1355
|
+
prerelease,
|
|
1356
|
+
build: [],
|
|
1357
|
+
});
|
|
1358
|
+
}
|
|
1359
|
+
/**
|
|
1360
|
+
* Calculates the difference type between two versions.
|
|
1361
|
+
*
|
|
1362
|
+
* @param older - The older version
|
|
1363
|
+
* @param newer - The newer version
|
|
1364
|
+
* @returns The type of difference, or null if versions are equal
|
|
1365
|
+
*
|
|
1366
|
+
* @example
|
|
1367
|
+
* diff(parseVersion('1.0.0'), parseVersion('2.0.0')) // 'major'
|
|
1368
|
+
* diff(parseVersion('1.0.0'), parseVersion('1.1.0')) // 'minor'
|
|
1369
|
+
* diff(parseVersion('1.0.0'), parseVersion('1.0.1')) // 'patch'
|
|
1370
|
+
*/
|
|
1371
|
+
function diff(older, newer) {
|
|
1372
|
+
// Check major
|
|
1373
|
+
if (older.major !== newer.major) {
|
|
1374
|
+
if (newer.prerelease.length > 0) {
|
|
1375
|
+
return 'premajor';
|
|
1376
|
+
}
|
|
1377
|
+
return 'major';
|
|
1378
|
+
}
|
|
1379
|
+
// Check minor
|
|
1380
|
+
if (older.minor !== newer.minor) {
|
|
1381
|
+
if (newer.prerelease.length > 0) {
|
|
1382
|
+
return 'preminor';
|
|
1383
|
+
}
|
|
1384
|
+
return 'minor';
|
|
1385
|
+
}
|
|
1386
|
+
// Check patch
|
|
1387
|
+
if (older.patch !== newer.patch) {
|
|
1388
|
+
if (newer.prerelease.length > 0) {
|
|
1389
|
+
return 'prepatch';
|
|
1390
|
+
}
|
|
1391
|
+
return 'patch';
|
|
1392
|
+
}
|
|
1393
|
+
// Check prerelease
|
|
1394
|
+
if (older.prerelease.length !== newer.prerelease.length) {
|
|
1395
|
+
return 'prerelease';
|
|
1396
|
+
}
|
|
1397
|
+
for (let i = 0; i < older.prerelease.length; i++) {
|
|
1398
|
+
if (older.prerelease[i] !== newer.prerelease[i]) {
|
|
1399
|
+
return 'prerelease';
|
|
1400
|
+
}
|
|
1401
|
+
}
|
|
1402
|
+
// Versions are equal (ignoring build)
|
|
1403
|
+
return null;
|
|
1404
|
+
}
|
|
1405
|
+
|
|
1406
|
+
/**
|
|
1407
|
+
* Converts a SemVer to its canonical string representation.
|
|
1408
|
+
*
|
|
1409
|
+
* @param version - The version to format
|
|
1410
|
+
* @returns The version string (e.g., "1.2.3-alpha.1+build.123")
|
|
1411
|
+
*/
|
|
1412
|
+
function format(version) {
|
|
1413
|
+
let result = `${version.major}.${version.minor}.${version.patch}`;
|
|
1414
|
+
if (version.prerelease.length > 0) {
|
|
1415
|
+
result += '-' + version.prerelease.join('.');
|
|
1416
|
+
}
|
|
1417
|
+
if (version.build.length > 0) {
|
|
1418
|
+
result += '+' + version.build.join('.');
|
|
1419
|
+
}
|
|
1420
|
+
return result;
|
|
1421
|
+
}
|
|
1422
|
+
/**
|
|
1423
|
+
* Converts a SemVer to a string without prerelease/build.
|
|
1424
|
+
*
|
|
1425
|
+
* @param version - The version to format
|
|
1426
|
+
* @returns The version string (e.g., "1.2.3")
|
|
1427
|
+
*/
|
|
1428
|
+
function formatSimple(version) {
|
|
1429
|
+
return `${version.major}.${version.minor}.${version.patch}`;
|
|
1430
|
+
}
|
|
1431
|
+
/**
|
|
1432
|
+
* Converts a Range to its string representation.
|
|
1433
|
+
*
|
|
1434
|
+
* @param range - The range to format
|
|
1435
|
+
* @returns The range string
|
|
1436
|
+
*/
|
|
1437
|
+
function formatRange(range) {
|
|
1438
|
+
if (range.raw) {
|
|
1439
|
+
return range.raw;
|
|
1440
|
+
}
|
|
1441
|
+
if (range.sets.length === 0) {
|
|
1442
|
+
return '*';
|
|
1443
|
+
}
|
|
1444
|
+
return range.sets.map((set) => set.comparators.map((c) => formatComparator(c)).join(' ')).join(' || ');
|
|
1445
|
+
}
|
|
1446
|
+
/**
|
|
1447
|
+
* Converts a Comparator to its string representation.
|
|
1448
|
+
*
|
|
1449
|
+
* @param comparator - The comparator to format
|
|
1450
|
+
* @returns The comparator string (e.g., ">=1.0.0")
|
|
1451
|
+
*/
|
|
1452
|
+
function formatComparator(comparator) {
|
|
1453
|
+
const op = comparator.operator === '=' ? '' : comparator.operator;
|
|
1454
|
+
return op + format(comparator.version);
|
|
1455
|
+
}
|
|
1456
|
+
|
|
1457
|
+
export { coerceVersion, compare, createAnyRange, createComparator, createComparatorSet, createExactRange, createFirstRelease, createInitialVersion, createRange, createSemVer, diff, eq, format, formatComparator, formatRange, formatSimple, gt, gte, increment, incrementPrerelease, isPrerelease, isStable, isWildcard, lt, lte, max, maxSatisfying, min, minSatisfying, neq, parseRange, parseRangeStrict, parseVersion, parseVersionStrict, satisfies, satisfiesComparator, sort, sortDescending, stripBuild, stripPrerelease };
|
|
1458
|
+
//# sourceMappingURL=index.esm.js.map
|