@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,793 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Safe copies of Error built-ins via factory functions.
|
|
3
|
+
*
|
|
4
|
+
* Since constructors cannot be safely captured via Object.assign, this module
|
|
5
|
+
* provides factory functions that use Reflect.construct internally.
|
|
6
|
+
*
|
|
7
|
+
* These references are captured at module initialization time to protect against
|
|
8
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
9
|
+
*
|
|
10
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/error
|
|
11
|
+
*/
|
|
12
|
+
// Capture references at module initialization time
|
|
13
|
+
const _Error = globalThis.Error;
|
|
14
|
+
const _Reflect = globalThis.Reflect;
|
|
15
|
+
/**
|
|
16
|
+
* (Safe copy) Creates a new Error using the captured Error constructor.
|
|
17
|
+
* Use this instead of `new Error()`.
|
|
18
|
+
*
|
|
19
|
+
* @param message - Optional error message.
|
|
20
|
+
* @param options - Optional error options.
|
|
21
|
+
* @returns A new Error instance.
|
|
22
|
+
*/
|
|
23
|
+
const createError = (message, options) => _Reflect.construct(_Error, [message, options]);
|
|
24
|
+
|
|
25
|
+
/**
|
|
26
|
+
* Creates a new SemVer object.
|
|
27
|
+
*
|
|
28
|
+
* @param options - Version components
|
|
29
|
+
* @returns A new SemVer object
|
|
30
|
+
*/
|
|
31
|
+
function createSemVer(options) {
|
|
32
|
+
return {
|
|
33
|
+
major: options.major,
|
|
34
|
+
minor: options.minor,
|
|
35
|
+
patch: options.patch,
|
|
36
|
+
prerelease: options.prerelease ?? [],
|
|
37
|
+
build: options.build ?? [],
|
|
38
|
+
raw: options.raw,
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* Maximum version string length to prevent memory exhaustion.
|
|
44
|
+
*/
|
|
45
|
+
const MAX_VERSION_LENGTH = 256;
|
|
46
|
+
/**
|
|
47
|
+
* Parses a semantic version string.
|
|
48
|
+
*
|
|
49
|
+
* Accepts versions in the format: MAJOR.MINOR.PATCH[-prerelease][+build]
|
|
50
|
+
* Optional leading 'v' or '=' prefixes are stripped.
|
|
51
|
+
*
|
|
52
|
+
* @param input - The version string to parse
|
|
53
|
+
* @returns A ParseVersionResult with the parsed version or error
|
|
54
|
+
*
|
|
55
|
+
* @example
|
|
56
|
+
* parseVersion('1.2.3') // { success: true, version: { major: 1, minor: 2, patch: 3, ... } }
|
|
57
|
+
* parseVersion('v1.0.0-alpha.1+build.123') // { success: true, ... }
|
|
58
|
+
* parseVersion('invalid') // { success: false, error: '...' }
|
|
59
|
+
*/
|
|
60
|
+
function parseVersion(input) {
|
|
61
|
+
// Input validation
|
|
62
|
+
if (!input || typeof input !== 'string') {
|
|
63
|
+
return { success: false, error: 'Version string is required' };
|
|
64
|
+
}
|
|
65
|
+
if (input.length > MAX_VERSION_LENGTH) {
|
|
66
|
+
return { success: false, error: `Version string exceeds maximum length of ${MAX_VERSION_LENGTH}` };
|
|
67
|
+
}
|
|
68
|
+
// Strip leading whitespace
|
|
69
|
+
let pos = 0;
|
|
70
|
+
while (pos < input.length && isWhitespace(input.charCodeAt(pos))) {
|
|
71
|
+
pos++;
|
|
72
|
+
}
|
|
73
|
+
// Strip trailing whitespace
|
|
74
|
+
let end = input.length;
|
|
75
|
+
while (end > pos && isWhitespace(input.charCodeAt(end - 1))) {
|
|
76
|
+
end--;
|
|
77
|
+
}
|
|
78
|
+
// Strip optional leading 'v' or '='
|
|
79
|
+
if (pos < end) {
|
|
80
|
+
const code = input.charCodeAt(pos);
|
|
81
|
+
if (code === 118 || code === 86) {
|
|
82
|
+
// 'v' or 'V'
|
|
83
|
+
pos++;
|
|
84
|
+
}
|
|
85
|
+
else if (code === 61) {
|
|
86
|
+
// '='
|
|
87
|
+
pos++;
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
// Parse major version
|
|
91
|
+
const majorResult = parseNumericIdentifier(input, pos, end);
|
|
92
|
+
if (!majorResult.success) {
|
|
93
|
+
return { success: false, error: majorResult.error ?? 'Invalid major version' };
|
|
94
|
+
}
|
|
95
|
+
pos = majorResult.endPos;
|
|
96
|
+
// Expect dot
|
|
97
|
+
if (pos >= end || input.charCodeAt(pos) !== 46) {
|
|
98
|
+
// '.'
|
|
99
|
+
return { success: false, error: 'Expected "." after major version' };
|
|
100
|
+
}
|
|
101
|
+
pos++;
|
|
102
|
+
// Parse minor version
|
|
103
|
+
const minorResult = parseNumericIdentifier(input, pos, end);
|
|
104
|
+
if (!minorResult.success) {
|
|
105
|
+
return { success: false, error: minorResult.error ?? 'Invalid minor version' };
|
|
106
|
+
}
|
|
107
|
+
pos = minorResult.endPos;
|
|
108
|
+
// Expect dot
|
|
109
|
+
if (pos >= end || input.charCodeAt(pos) !== 46) {
|
|
110
|
+
// '.'
|
|
111
|
+
return { success: false, error: 'Expected "." after minor version' };
|
|
112
|
+
}
|
|
113
|
+
pos++;
|
|
114
|
+
// Parse patch version
|
|
115
|
+
const patchResult = parseNumericIdentifier(input, pos, end);
|
|
116
|
+
if (!patchResult.success) {
|
|
117
|
+
return { success: false, error: patchResult.error ?? 'Invalid patch version' };
|
|
118
|
+
}
|
|
119
|
+
pos = patchResult.endPos;
|
|
120
|
+
// Parse optional prerelease
|
|
121
|
+
const prerelease = [];
|
|
122
|
+
if (pos < end && input.charCodeAt(pos) === 45) {
|
|
123
|
+
// '-'
|
|
124
|
+
pos++;
|
|
125
|
+
const prereleaseResult = parseIdentifiers(input, pos, end, [43]); // Stop at '+'
|
|
126
|
+
if (!prereleaseResult.success) {
|
|
127
|
+
return { success: false, error: prereleaseResult.error ?? 'Invalid prerelease' };
|
|
128
|
+
}
|
|
129
|
+
prerelease.push(...prereleaseResult.identifiers);
|
|
130
|
+
pos = prereleaseResult.endPos;
|
|
131
|
+
}
|
|
132
|
+
// Parse optional build metadata
|
|
133
|
+
const build = [];
|
|
134
|
+
if (pos < end && input.charCodeAt(pos) === 43) {
|
|
135
|
+
// '+'
|
|
136
|
+
pos++;
|
|
137
|
+
const buildResult = parseIdentifiers(input, pos, end, []);
|
|
138
|
+
if (!buildResult.success) {
|
|
139
|
+
return { success: false, error: buildResult.error ?? 'Invalid build metadata' };
|
|
140
|
+
}
|
|
141
|
+
build.push(...buildResult.identifiers);
|
|
142
|
+
pos = buildResult.endPos;
|
|
143
|
+
}
|
|
144
|
+
// Check for trailing characters
|
|
145
|
+
if (pos < end) {
|
|
146
|
+
return { success: false, error: `Unexpected character at position ${pos}: "${input[pos]}"` };
|
|
147
|
+
}
|
|
148
|
+
return {
|
|
149
|
+
success: true,
|
|
150
|
+
version: createSemVer({
|
|
151
|
+
major: majorResult.value,
|
|
152
|
+
minor: minorResult.value,
|
|
153
|
+
patch: patchResult.value,
|
|
154
|
+
prerelease,
|
|
155
|
+
build,
|
|
156
|
+
raw: input,
|
|
157
|
+
}),
|
|
158
|
+
};
|
|
159
|
+
}
|
|
160
|
+
/**
|
|
161
|
+
* Parses a version string, throwing on invalid input.
|
|
162
|
+
*
|
|
163
|
+
* @param input - The version string to parse
|
|
164
|
+
* @returns The parsed SemVer
|
|
165
|
+
* @throws {Error} If the input is not a valid version
|
|
166
|
+
*/
|
|
167
|
+
function parseVersionStrict(input) {
|
|
168
|
+
const result = parseVersion(input);
|
|
169
|
+
if (!result.success || !result.version) {
|
|
170
|
+
throw createError(result.error ?? 'Invalid version');
|
|
171
|
+
}
|
|
172
|
+
return result.version;
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Attempts to coerce a string into a valid semver.
|
|
176
|
+
* More lenient than parseVersion - accepts partial versions.
|
|
177
|
+
*
|
|
178
|
+
* @param input - The string to coerce
|
|
179
|
+
* @returns The parsed SemVer or null if coercion failed
|
|
180
|
+
*
|
|
181
|
+
* @example
|
|
182
|
+
* coerceVersion('1') // { major: 1, minor: 0, patch: 0, ... }
|
|
183
|
+
* coerceVersion('1.2') // { major: 1, minor: 2, patch: 0, ... }
|
|
184
|
+
* coerceVersion('v2.0') // { major: 2, minor: 0, patch: 0, ... }
|
|
185
|
+
*/
|
|
186
|
+
function coerceVersion(input) {
|
|
187
|
+
if (!input || typeof input !== 'string') {
|
|
188
|
+
return null;
|
|
189
|
+
}
|
|
190
|
+
// Try strict parse first
|
|
191
|
+
const strict = parseVersion(input);
|
|
192
|
+
if (strict.success && strict.version) {
|
|
193
|
+
return strict.version;
|
|
194
|
+
}
|
|
195
|
+
// Strip leading/trailing whitespace
|
|
196
|
+
let pos = 0;
|
|
197
|
+
while (pos < input.length && isWhitespace(input.charCodeAt(pos))) {
|
|
198
|
+
pos++;
|
|
199
|
+
}
|
|
200
|
+
let end = input.length;
|
|
201
|
+
while (end > pos && isWhitespace(input.charCodeAt(end - 1))) {
|
|
202
|
+
end--;
|
|
203
|
+
}
|
|
204
|
+
// Strip optional 'v' prefix
|
|
205
|
+
if (pos < end) {
|
|
206
|
+
const code = input.charCodeAt(pos);
|
|
207
|
+
if (code === 118 || code === 86) {
|
|
208
|
+
// 'v' or 'V'
|
|
209
|
+
pos++;
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
// Parse major
|
|
213
|
+
const majorResult = parseNumericIdentifier(input, pos, end);
|
|
214
|
+
if (!majorResult.success) {
|
|
215
|
+
return null;
|
|
216
|
+
}
|
|
217
|
+
const major = majorResult.value;
|
|
218
|
+
pos = majorResult.endPos;
|
|
219
|
+
// Parse optional minor
|
|
220
|
+
let minor = 0;
|
|
221
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
222
|
+
pos++;
|
|
223
|
+
const minorResult = parseNumericIdentifier(input, pos, end);
|
|
224
|
+
if (minorResult.success) {
|
|
225
|
+
minor = minorResult.value;
|
|
226
|
+
pos = minorResult.endPos;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
// Parse optional patch
|
|
230
|
+
let patch = 0;
|
|
231
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
232
|
+
pos++;
|
|
233
|
+
const patchResult = parseNumericIdentifier(input, pos, end);
|
|
234
|
+
if (patchResult.success) {
|
|
235
|
+
patch = patchResult.value;
|
|
236
|
+
// pos = patchResult.endPos // We ignore anything after patch in coerce
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return createSemVer({
|
|
240
|
+
major,
|
|
241
|
+
minor,
|
|
242
|
+
patch,
|
|
243
|
+
prerelease: [],
|
|
244
|
+
build: [],
|
|
245
|
+
raw: input,
|
|
246
|
+
});
|
|
247
|
+
}
|
|
248
|
+
/**
|
|
249
|
+
* Parses a numeric identifier (non-negative integer, no leading zeros except for "0").
|
|
250
|
+
*
|
|
251
|
+
* @param input - Input string to parse
|
|
252
|
+
* @param start - Start position in the input
|
|
253
|
+
* @param end - End position in the input
|
|
254
|
+
* @returns Numeric parsing result
|
|
255
|
+
*/
|
|
256
|
+
function parseNumericIdentifier(input, start, end) {
|
|
257
|
+
if (start >= end) {
|
|
258
|
+
return { success: false, value: 0, endPos: start, error: 'Expected numeric identifier' };
|
|
259
|
+
}
|
|
260
|
+
let pos = start;
|
|
261
|
+
const firstCode = input.charCodeAt(pos);
|
|
262
|
+
// Must start with a digit
|
|
263
|
+
if (!isDigit(firstCode)) {
|
|
264
|
+
return { success: false, value: 0, endPos: pos, error: 'Expected digit' };
|
|
265
|
+
}
|
|
266
|
+
// Check for leading zero (only "0" is valid, not "01", "007", etc.)
|
|
267
|
+
if (firstCode === 48 && pos + 1 < end && isDigit(input.charCodeAt(pos + 1))) {
|
|
268
|
+
return { success: false, value: 0, endPos: pos, error: 'Numeric identifier cannot have leading zeros' };
|
|
269
|
+
}
|
|
270
|
+
// Consume digits
|
|
271
|
+
let value = 0;
|
|
272
|
+
while (pos < end && isDigit(input.charCodeAt(pos))) {
|
|
273
|
+
value = value * 10 + (input.charCodeAt(pos) - 48);
|
|
274
|
+
pos++;
|
|
275
|
+
// Prevent overflow
|
|
276
|
+
if (value > Number.MAX_SAFE_INTEGER) {
|
|
277
|
+
return { success: false, value: 0, endPos: pos, error: 'Numeric identifier is too large' };
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
return { success: true, value, endPos: pos };
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Parses dot-separated identifiers (for prerelease/build).
|
|
284
|
+
*
|
|
285
|
+
* @param input - Input string to parse
|
|
286
|
+
* @param start - Start position in the input
|
|
287
|
+
* @param end - End position in the input
|
|
288
|
+
* @param stopCodes - Character codes that signal end of identifiers
|
|
289
|
+
* @returns Identifiers parsing result
|
|
290
|
+
*/
|
|
291
|
+
function parseIdentifiers(input, start, end, stopCodes) {
|
|
292
|
+
const identifiers = [];
|
|
293
|
+
let pos = start;
|
|
294
|
+
while (pos < end) {
|
|
295
|
+
// Check for stop characters
|
|
296
|
+
if (stopCodes.includes(input.charCodeAt(pos))) {
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
// Parse one identifier
|
|
300
|
+
const identStart = pos;
|
|
301
|
+
while (pos < end) {
|
|
302
|
+
const code = input.charCodeAt(pos);
|
|
303
|
+
// Stop at dot or stop characters
|
|
304
|
+
if (code === 46 || stopCodes.includes(code)) {
|
|
305
|
+
break;
|
|
306
|
+
}
|
|
307
|
+
// Must be alphanumeric or hyphen
|
|
308
|
+
if (!isAlphanumeric(code) && code !== 45) {
|
|
309
|
+
return { success: false, identifiers: [], endPos: pos, error: `Invalid character in identifier: "${input[pos]}"` };
|
|
310
|
+
}
|
|
311
|
+
pos++;
|
|
312
|
+
}
|
|
313
|
+
// Empty identifier is not allowed
|
|
314
|
+
if (pos === identStart) {
|
|
315
|
+
return { success: false, identifiers: [], endPos: pos, error: 'Empty identifier' };
|
|
316
|
+
}
|
|
317
|
+
identifiers.push(input.slice(identStart, pos));
|
|
318
|
+
// Consume dot separator
|
|
319
|
+
if (pos < end && input.charCodeAt(pos) === 46) {
|
|
320
|
+
pos++;
|
|
321
|
+
// Dot at end is invalid
|
|
322
|
+
if (pos >= end || stopCodes.includes(input.charCodeAt(pos))) {
|
|
323
|
+
return { success: false, identifiers: [], endPos: pos, error: 'Identifier expected after dot' };
|
|
324
|
+
}
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
return { success: true, identifiers, endPos: pos };
|
|
328
|
+
}
|
|
329
|
+
/**
|
|
330
|
+
* Checks if a character code is a digit (0-9).
|
|
331
|
+
*
|
|
332
|
+
* @param code - Character code to check
|
|
333
|
+
* @returns True if the code represents a digit
|
|
334
|
+
*/
|
|
335
|
+
function isDigit(code) {
|
|
336
|
+
return code >= 48 && code <= 57;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Checks if a character code is alphanumeric or hyphen.
|
|
340
|
+
*
|
|
341
|
+
* @param code - Character code to check
|
|
342
|
+
* @returns True if the code represents an alphanumeric character
|
|
343
|
+
*/
|
|
344
|
+
function isAlphanumeric(code) {
|
|
345
|
+
return ((code >= 48 && code <= 57) || // 0-9
|
|
346
|
+
(code >= 65 && code <= 90) || // A-Z
|
|
347
|
+
(code >= 97 && code <= 122) // a-z
|
|
348
|
+
);
|
|
349
|
+
}
|
|
350
|
+
/**
|
|
351
|
+
* Checks if a character code is whitespace.
|
|
352
|
+
*
|
|
353
|
+
* @param code - Character code to check
|
|
354
|
+
* @returns True if the code represents whitespace
|
|
355
|
+
*/
|
|
356
|
+
function isWhitespace(code) {
|
|
357
|
+
return code === 32 || code === 9 || code === 10 || code === 13;
|
|
358
|
+
}
|
|
359
|
+
|
|
360
|
+
/**
|
|
361
|
+
* Safe copies of Number built-in methods and constants.
|
|
362
|
+
*
|
|
363
|
+
* These references are captured at module initialization time to protect against
|
|
364
|
+
* prototype pollution attacks. Import only what you need for tree-shaking.
|
|
365
|
+
*
|
|
366
|
+
* @module @hyperfrontend/immutable-api-utils/built-in-copy/number
|
|
367
|
+
*/
|
|
368
|
+
// Capture references at module initialization time
|
|
369
|
+
const _parseInt = globalThis.parseInt;
|
|
370
|
+
const _isNaN = globalThis.isNaN;
|
|
371
|
+
// ============================================================================
|
|
372
|
+
// Parsing
|
|
373
|
+
// ============================================================================
|
|
374
|
+
/**
|
|
375
|
+
* (Safe copy) Parses a string and returns an integer.
|
|
376
|
+
*/
|
|
377
|
+
const parseInt = _parseInt;
|
|
378
|
+
// ============================================================================
|
|
379
|
+
// Global Type Checking (legacy, less strict)
|
|
380
|
+
// ============================================================================
|
|
381
|
+
/**
|
|
382
|
+
* (Safe copy) Global isNaN function (coerces to number first, less strict than Number.isNaN).
|
|
383
|
+
*/
|
|
384
|
+
const globalIsNaN = _isNaN;
|
|
385
|
+
|
|
386
|
+
/**
|
|
387
|
+
* Creates a new Comparator.
|
|
388
|
+
*
|
|
389
|
+
* @param operator - The comparison operator
|
|
390
|
+
* @param version - The version to compare against
|
|
391
|
+
* @returns A new Comparator
|
|
392
|
+
*/
|
|
393
|
+
function createComparator(operator, version) {
|
|
394
|
+
return { operator, version };
|
|
395
|
+
}
|
|
396
|
+
/**
|
|
397
|
+
* Creates a new ComparatorSet.
|
|
398
|
+
*
|
|
399
|
+
* @param comparators - Array of comparators (AND logic)
|
|
400
|
+
* @returns A new ComparatorSet
|
|
401
|
+
*/
|
|
402
|
+
function createComparatorSet(comparators) {
|
|
403
|
+
return { comparators };
|
|
404
|
+
}
|
|
405
|
+
/**
|
|
406
|
+
* Creates a new Range.
|
|
407
|
+
*
|
|
408
|
+
* @param sets - Array of comparator sets (OR logic)
|
|
409
|
+
* @param raw - Original raw string
|
|
410
|
+
* @returns A new Range
|
|
411
|
+
*/
|
|
412
|
+
function createRange(sets, raw) {
|
|
413
|
+
return { sets, raw };
|
|
414
|
+
}
|
|
415
|
+
|
|
416
|
+
/**
|
|
417
|
+
* Maximum range string length.
|
|
418
|
+
*/
|
|
419
|
+
const MAX_RANGE_LENGTH = 1024;
|
|
420
|
+
/**
|
|
421
|
+
* Parses a semver range string.
|
|
422
|
+
*
|
|
423
|
+
* Supports:
|
|
424
|
+
* - Exact: 1.2.3, =1.2.3
|
|
425
|
+
* - Comparators: >1.0.0, >=1.0.0, <2.0.0, <=2.0.0
|
|
426
|
+
* - Caret: ^1.2.3 (compatible with version)
|
|
427
|
+
* - Tilde: ~1.2.3 (approximately equivalent)
|
|
428
|
+
* - X-ranges: 1.x, 1.2.x, *
|
|
429
|
+
* - Hyphen ranges: 1.0.0 - 2.0.0
|
|
430
|
+
* - OR: 1.0.0 || 2.0.0
|
|
431
|
+
* - AND: >=1.0.0 <2.0.0
|
|
432
|
+
*
|
|
433
|
+
* @param input - The range string to parse
|
|
434
|
+
* @returns A ParseRangeResult with the parsed range or error
|
|
435
|
+
*/
|
|
436
|
+
function parseRange(input) {
|
|
437
|
+
if (!input || typeof input !== 'string') {
|
|
438
|
+
return { success: false, error: 'Range string is required' };
|
|
439
|
+
}
|
|
440
|
+
if (input.length > MAX_RANGE_LENGTH) {
|
|
441
|
+
return { success: false, error: `Range string exceeds maximum length of ${MAX_RANGE_LENGTH}` };
|
|
442
|
+
}
|
|
443
|
+
// Trim whitespace
|
|
444
|
+
const trimmed = input.trim();
|
|
445
|
+
// Handle wildcard/any
|
|
446
|
+
if (trimmed === '' || trimmed === '*' || trimmed.toLowerCase() === 'x') {
|
|
447
|
+
return { success: true, range: createRange([], input) };
|
|
448
|
+
}
|
|
449
|
+
// Split by || for OR logic
|
|
450
|
+
const orParts = splitByOr(trimmed);
|
|
451
|
+
const sets = [];
|
|
452
|
+
for (const part of orParts) {
|
|
453
|
+
const setResult = parseComparatorSet(part.trim());
|
|
454
|
+
if (!setResult.success) {
|
|
455
|
+
return { success: false, error: setResult.error };
|
|
456
|
+
}
|
|
457
|
+
if (setResult.set) {
|
|
458
|
+
sets.push(setResult.set);
|
|
459
|
+
}
|
|
460
|
+
}
|
|
461
|
+
return { success: true, range: createRange(sets, input) };
|
|
462
|
+
}
|
|
463
|
+
/**
|
|
464
|
+
* Parses a range string, throwing on invalid input.
|
|
465
|
+
*
|
|
466
|
+
* @param input - The range string to parse
|
|
467
|
+
* @returns The parsed Range
|
|
468
|
+
* @throws {Error} If the input is not a valid range
|
|
469
|
+
*/
|
|
470
|
+
function parseRangeStrict(input) {
|
|
471
|
+
const result = parseRange(input);
|
|
472
|
+
if (!result.success || !result.range) {
|
|
473
|
+
throw createError(result.error ?? 'Invalid range');
|
|
474
|
+
}
|
|
475
|
+
return result.range;
|
|
476
|
+
}
|
|
477
|
+
/**
|
|
478
|
+
* Splits a string by || delimiter, respecting nesting.
|
|
479
|
+
*
|
|
480
|
+
* @param input - Range string containing OR groups
|
|
481
|
+
* @returns Array of OR-separated parts
|
|
482
|
+
*/
|
|
483
|
+
function splitByOr(input) {
|
|
484
|
+
const parts = [];
|
|
485
|
+
let current = '';
|
|
486
|
+
let pos = 0;
|
|
487
|
+
while (pos < input.length) {
|
|
488
|
+
if (input[pos] === '|' && pos + 1 < input.length && input[pos + 1] === '|') {
|
|
489
|
+
parts.push(current);
|
|
490
|
+
current = '';
|
|
491
|
+
pos += 2;
|
|
492
|
+
}
|
|
493
|
+
else {
|
|
494
|
+
current += input[pos];
|
|
495
|
+
pos++;
|
|
496
|
+
}
|
|
497
|
+
}
|
|
498
|
+
parts.push(current);
|
|
499
|
+
return parts;
|
|
500
|
+
}
|
|
501
|
+
/**
|
|
502
|
+
* Parses a single comparator set (space-separated comparators = AND logic).
|
|
503
|
+
*
|
|
504
|
+
* @param input - Comparator set string
|
|
505
|
+
* @returns Parsed set result
|
|
506
|
+
*/
|
|
507
|
+
function parseComparatorSet(input) {
|
|
508
|
+
if (!input || input.trim() === '') {
|
|
509
|
+
return { success: true }; // Empty set matches any
|
|
510
|
+
}
|
|
511
|
+
const trimmed = input.trim();
|
|
512
|
+
// Check for hyphen range: "1.0.0 - 2.0.0"
|
|
513
|
+
const hyphenMatch = parseHyphenRange(trimmed);
|
|
514
|
+
if (hyphenMatch.isHyphenRange) {
|
|
515
|
+
if (!hyphenMatch.success) {
|
|
516
|
+
return { success: false, error: hyphenMatch.error };
|
|
517
|
+
}
|
|
518
|
+
return { success: true, set: hyphenMatch.set };
|
|
519
|
+
}
|
|
520
|
+
// Split by whitespace for AND logic
|
|
521
|
+
const tokens = splitByWhitespace(trimmed);
|
|
522
|
+
const comparators = [];
|
|
523
|
+
for (const token of tokens) {
|
|
524
|
+
const compResult = parseSingleComparator(token);
|
|
525
|
+
if (!compResult.success) {
|
|
526
|
+
return { success: false, error: compResult.error };
|
|
527
|
+
}
|
|
528
|
+
if (compResult.comparators) {
|
|
529
|
+
comparators.push(...compResult.comparators);
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
if (comparators.length === 0) {
|
|
533
|
+
return { success: true }; // Empty matches any
|
|
534
|
+
}
|
|
535
|
+
return { success: true, set: createComparatorSet(comparators) };
|
|
536
|
+
}
|
|
537
|
+
/**
|
|
538
|
+
* Checks for and parses hyphen ranges like "1.0.0 - 2.0.0".
|
|
539
|
+
*
|
|
540
|
+
* @param input - Potential hyphen range string
|
|
541
|
+
* @returns Hyphen range parsing result
|
|
542
|
+
*/
|
|
543
|
+
function parseHyphenRange(input) {
|
|
544
|
+
// Look for " - " (space-hyphen-space)
|
|
545
|
+
let hyphenPos = -1;
|
|
546
|
+
for (let i = 0; i < input.length - 2; i++) {
|
|
547
|
+
if (input[i] === ' ' && input[i + 1] === '-' && input[i + 2] === ' ') {
|
|
548
|
+
hyphenPos = i;
|
|
549
|
+
break;
|
|
550
|
+
}
|
|
551
|
+
}
|
|
552
|
+
if (hyphenPos === -1) {
|
|
553
|
+
return { isHyphenRange: false, success: true };
|
|
554
|
+
}
|
|
555
|
+
const leftPart = input.slice(0, hyphenPos).trim();
|
|
556
|
+
const rightPart = input.slice(hyphenPos + 3).trim();
|
|
557
|
+
const leftVersion = parseSimpleVersion(leftPart);
|
|
558
|
+
if (!leftVersion) {
|
|
559
|
+
return { isHyphenRange: true, success: false, error: `Invalid left side of hyphen range: "${leftPart}"` };
|
|
560
|
+
}
|
|
561
|
+
const rightVersion = parseSimpleVersion(rightPart);
|
|
562
|
+
if (!rightVersion) {
|
|
563
|
+
return { isHyphenRange: true, success: false, error: `Invalid right side of hyphen range: "${rightPart}"` };
|
|
564
|
+
}
|
|
565
|
+
// Hyphen range: >=left <=right
|
|
566
|
+
const comparators = [createComparator('>=', leftVersion), createComparator('<=', rightVersion)];
|
|
567
|
+
return {
|
|
568
|
+
isHyphenRange: true,
|
|
569
|
+
success: true,
|
|
570
|
+
set: createComparatorSet(comparators),
|
|
571
|
+
};
|
|
572
|
+
}
|
|
573
|
+
/**
|
|
574
|
+
* Splits by whitespace.
|
|
575
|
+
*
|
|
576
|
+
* @param input - String to split
|
|
577
|
+
* @returns Array of whitespace-separated tokens
|
|
578
|
+
*/
|
|
579
|
+
function splitByWhitespace(input) {
|
|
580
|
+
const tokens = [];
|
|
581
|
+
let current = '';
|
|
582
|
+
for (const char of input) {
|
|
583
|
+
if (char === ' ' || char === '\t') {
|
|
584
|
+
if (current) {
|
|
585
|
+
tokens.push(current);
|
|
586
|
+
current = '';
|
|
587
|
+
}
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
current += char;
|
|
591
|
+
}
|
|
592
|
+
}
|
|
593
|
+
if (current) {
|
|
594
|
+
tokens.push(current);
|
|
595
|
+
}
|
|
596
|
+
return tokens;
|
|
597
|
+
}
|
|
598
|
+
/**
|
|
599
|
+
* Parses a single comparator token (e.g., ">=1.0.0", "^1.2.3", "~1.0").
|
|
600
|
+
*
|
|
601
|
+
* @param token - Comparator token to parse
|
|
602
|
+
* @returns Parsed comparator result
|
|
603
|
+
*/
|
|
604
|
+
function parseSingleComparator(token) {
|
|
605
|
+
let pos = 0;
|
|
606
|
+
let operator = '=';
|
|
607
|
+
// Parse operator
|
|
608
|
+
if (token[pos] === '^') {
|
|
609
|
+
operator = '^';
|
|
610
|
+
pos++;
|
|
611
|
+
}
|
|
612
|
+
else if (token[pos] === '~') {
|
|
613
|
+
operator = '~';
|
|
614
|
+
pos++;
|
|
615
|
+
}
|
|
616
|
+
else if (token[pos] === '>') {
|
|
617
|
+
if (token[pos + 1] === '=') {
|
|
618
|
+
operator = '>=';
|
|
619
|
+
pos += 2;
|
|
620
|
+
}
|
|
621
|
+
else {
|
|
622
|
+
operator = '>';
|
|
623
|
+
pos++;
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
else if (token[pos] === '<') {
|
|
627
|
+
if (token[pos + 1] === '=') {
|
|
628
|
+
operator = '<=';
|
|
629
|
+
pos += 2;
|
|
630
|
+
}
|
|
631
|
+
else {
|
|
632
|
+
operator = '<';
|
|
633
|
+
pos++;
|
|
634
|
+
}
|
|
635
|
+
}
|
|
636
|
+
else if (token[pos] === '=') {
|
|
637
|
+
operator = '=';
|
|
638
|
+
pos++;
|
|
639
|
+
}
|
|
640
|
+
const versionPart = token.slice(pos);
|
|
641
|
+
// Handle wildcards: *, x, X
|
|
642
|
+
if (versionPart === '*' || versionPart.toLowerCase() === 'x') {
|
|
643
|
+
// Wildcard matches any - return empty (will be handled as match-all)
|
|
644
|
+
return { success: true, comparators: [] };
|
|
645
|
+
}
|
|
646
|
+
// Handle x-ranges: 1.x, 1.2.x
|
|
647
|
+
if (versionPart.includes('x') || versionPart.includes('X') || versionPart.includes('*')) {
|
|
648
|
+
return parseXRange(versionPart);
|
|
649
|
+
}
|
|
650
|
+
// Parse version
|
|
651
|
+
const version = parseSimpleVersion(versionPart);
|
|
652
|
+
if (!version) {
|
|
653
|
+
return { success: false, error: `Invalid version in comparator: "${versionPart}"` };
|
|
654
|
+
}
|
|
655
|
+
// For caret and tilde, expand to range
|
|
656
|
+
if (operator === '^') {
|
|
657
|
+
return expandCaretRange(version);
|
|
658
|
+
}
|
|
659
|
+
if (operator === '~') {
|
|
660
|
+
return expandTildeRange(version);
|
|
661
|
+
}
|
|
662
|
+
return { success: true, comparators: [createComparator(operator, version)] };
|
|
663
|
+
}
|
|
664
|
+
/**
|
|
665
|
+
* Parses x-ranges like 1.x, 1.2.x, etc.
|
|
666
|
+
*
|
|
667
|
+
* @param input - X-range string to parse
|
|
668
|
+
* @param _operator - Range operator (unused but kept for interface consistency)
|
|
669
|
+
* @returns Comparator result
|
|
670
|
+
*/
|
|
671
|
+
function parseXRange(input, _operator) {
|
|
672
|
+
const parts = input.split('.');
|
|
673
|
+
const nums = [];
|
|
674
|
+
for (const part of parts) {
|
|
675
|
+
const lower = part.toLowerCase();
|
|
676
|
+
if (lower === 'x' || lower === '*' || lower === '') {
|
|
677
|
+
break;
|
|
678
|
+
}
|
|
679
|
+
const num = parseInt(part, 10);
|
|
680
|
+
if (globalIsNaN(num) || num < 0) {
|
|
681
|
+
return { success: false, error: `Invalid x-range: "${input}"` };
|
|
682
|
+
}
|
|
683
|
+
nums.push(num);
|
|
684
|
+
}
|
|
685
|
+
if (nums.length === 0) {
|
|
686
|
+
// * or X alone - match any
|
|
687
|
+
return { success: true, comparators: [] };
|
|
688
|
+
}
|
|
689
|
+
if (nums.length === 1) {
|
|
690
|
+
// 1.x or 1.* -> >=1.0.0 <2.0.0
|
|
691
|
+
const lower = createSemVer({ major: nums[0], minor: 0, patch: 0 });
|
|
692
|
+
const upper = createSemVer({ major: nums[0] + 1, minor: 0, patch: 0 });
|
|
693
|
+
return { success: true, comparators: [createComparator('>=', lower), createComparator('<', upper)] };
|
|
694
|
+
}
|
|
695
|
+
// 1.2.x -> >=1.2.0 <1.3.0
|
|
696
|
+
const lower = createSemVer({ major: nums[0], minor: nums[1], patch: 0 });
|
|
697
|
+
const upper = createSemVer({ major: nums[0], minor: nums[1] + 1, patch: 0 });
|
|
698
|
+
return { success: true, comparators: [createComparator('>=', lower), createComparator('<', upper)] };
|
|
699
|
+
}
|
|
700
|
+
/**
|
|
701
|
+
* Expands caret range: ^1.2.3 -> >=1.2.3 <2.0.0
|
|
702
|
+
*
|
|
703
|
+
* @param version - Base version for caret range
|
|
704
|
+
* @returns Expanded comparator result
|
|
705
|
+
*/
|
|
706
|
+
function expandCaretRange(version) {
|
|
707
|
+
let upperMajor = version.major;
|
|
708
|
+
let upperMinor = 0;
|
|
709
|
+
let upperPatch = 0;
|
|
710
|
+
if (version.major === 0) {
|
|
711
|
+
if (version.minor === 0) {
|
|
712
|
+
// ^0.0.x -> >=0.0.x <0.0.(x+1)
|
|
713
|
+
upperPatch = version.patch + 1;
|
|
714
|
+
upperMinor = version.minor;
|
|
715
|
+
}
|
|
716
|
+
else {
|
|
717
|
+
// ^0.x.y -> >=0.x.y <0.(x+1).0
|
|
718
|
+
upperMinor = version.minor + 1;
|
|
719
|
+
}
|
|
720
|
+
}
|
|
721
|
+
else {
|
|
722
|
+
// ^x.y.z -> >=x.y.z <(x+1).0.0
|
|
723
|
+
upperMajor = version.major + 1;
|
|
724
|
+
}
|
|
725
|
+
const upper = createSemVer({ major: upperMajor, minor: upperMinor, patch: upperPatch });
|
|
726
|
+
return { success: true, comparators: [createComparator('>=', version), createComparator('<', upper)] };
|
|
727
|
+
}
|
|
728
|
+
/**
|
|
729
|
+
* Expands tilde range: ~1.2.3 -> >=1.2.3 <1.3.0
|
|
730
|
+
*
|
|
731
|
+
* @param version - Base version for tilde range
|
|
732
|
+
* @returns Expanded comparator result
|
|
733
|
+
*/
|
|
734
|
+
function expandTildeRange(version) {
|
|
735
|
+
const upper = createSemVer({
|
|
736
|
+
major: version.major,
|
|
737
|
+
minor: version.minor + 1,
|
|
738
|
+
patch: 0,
|
|
739
|
+
});
|
|
740
|
+
return { success: true, comparators: [createComparator('>=', version), createComparator('<', upper)] };
|
|
741
|
+
}
|
|
742
|
+
/**
|
|
743
|
+
* Parses a simple version string (no range operators).
|
|
744
|
+
* More lenient - accepts partial versions.
|
|
745
|
+
*
|
|
746
|
+
* @param input - Version string to parse
|
|
747
|
+
* @returns Parsed SemVer or null if invalid
|
|
748
|
+
*/
|
|
749
|
+
function parseSimpleVersion(input) {
|
|
750
|
+
if (!input)
|
|
751
|
+
return null;
|
|
752
|
+
let pos = 0;
|
|
753
|
+
// Skip leading v
|
|
754
|
+
if (input[pos] === 'v' || input[pos] === 'V') {
|
|
755
|
+
pos++;
|
|
756
|
+
}
|
|
757
|
+
const parts = input.slice(pos).split('.');
|
|
758
|
+
if (parts.length === 0)
|
|
759
|
+
return null;
|
|
760
|
+
const nums = [];
|
|
761
|
+
for (const part of parts) {
|
|
762
|
+
// Stop at prerelease or build
|
|
763
|
+
const dashIdx = part.indexOf('-');
|
|
764
|
+
const plusIdx = part.indexOf('+');
|
|
765
|
+
let numPart = part;
|
|
766
|
+
if (dashIdx !== -1) {
|
|
767
|
+
numPart = part.slice(0, dashIdx);
|
|
768
|
+
}
|
|
769
|
+
else if (plusIdx !== -1) {
|
|
770
|
+
numPart = part.slice(0, plusIdx);
|
|
771
|
+
}
|
|
772
|
+
if (numPart === '' || numPart.toLowerCase() === 'x' || numPart === '*') {
|
|
773
|
+
break;
|
|
774
|
+
}
|
|
775
|
+
const num = parseInt(numPart, 10);
|
|
776
|
+
if (globalIsNaN(num) || num < 0)
|
|
777
|
+
return null;
|
|
778
|
+
nums.push(num);
|
|
779
|
+
}
|
|
780
|
+
if (nums.length === 0)
|
|
781
|
+
return null;
|
|
782
|
+
return createSemVer({
|
|
783
|
+
major: nums[0],
|
|
784
|
+
minor: nums[1] ?? 0,
|
|
785
|
+
patch: nums[2] ?? 0,
|
|
786
|
+
prerelease: [],
|
|
787
|
+
build: [],
|
|
788
|
+
raw: input,
|
|
789
|
+
});
|
|
790
|
+
}
|
|
791
|
+
|
|
792
|
+
export { coerceVersion, parseRange, parseRangeStrict, parseVersion, parseVersionStrict };
|
|
793
|
+
//# sourceMappingURL=index.esm.js.map
|