@vltpkg/semver 1.0.0-rc.23 → 1.0.0-rc.25

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.
@@ -0,0 +1,203 @@
1
+ import { Range } from './range.ts';
2
+ import { Version } from './version.ts';
3
+ import type { IncrementType } from './version.ts';
4
+ export * from './comparator.ts';
5
+ export * from './range.ts';
6
+ export * from './version.ts';
7
+ /** Return the parsed version string, or `undefined` if invalid */
8
+ export declare const parse: (version: Version | string) => Version | undefined;
9
+ /** Return the parsed version range, or `undefined` if invalid */
10
+ export declare const parseRange: (range: Range | string, includePrerelease?: boolean) => Range | undefined;
11
+ /**
12
+ * return true if the version is valid
13
+ *
14
+ * Note: do not use this if you intend to immediately parse the version if it's
15
+ * valid. Just use {@link parse}, and guard the possible undefined value, or
16
+ * use `Version.parse(..)` to throw on invalid values.
17
+ */
18
+ export declare const valid: (version: Version | string) => boolean;
19
+ /**
20
+ * return true if the range is valid
21
+ *
22
+ * Note: do not use this if you intend to immediately parse the range if it's
23
+ * valid. Just use {@link parseRange}, and guard the possible undefined value,
24
+ * or use `new Range(..)` to throw on invalid values.
25
+ */
26
+ export declare const validRange: (range: Range | string) => boolean;
27
+ /**
28
+ * Return true if the version satisfies the range.
29
+ */
30
+ export declare const satisfies: (version: Version | string, range: Range | string, includePrerelease?: boolean) => boolean;
31
+ /**
32
+ * Increment the specified part of the version, and return the resulting
33
+ * object. If a Version object is provided, it will be modified in-place.
34
+ *
35
+ * See {@link Version.inc} for full description.
36
+ */
37
+ export declare const inc: (version: Version | string, part: IncrementType, prereleaseIdentifier?: string) => Version;
38
+ /**
39
+ * The method used by {@link sort}, exported for passing directly to
40
+ * `Array.sort`.
41
+ *
42
+ * Usage:
43
+ *
44
+ * ```ts
45
+ * import { sortMethod } from '@vltpkg/semver'
46
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
47
+ * console.log(versions.sort(sortMethod))
48
+ * // ['1.2.3', '2.3.4', '5.2.3']
49
+ * ```
50
+ */
51
+ export declare const sortMethod: (a: Version | string, b: Version | string) => number;
52
+ /**
53
+ * Sort an array of version strings or objects in ascending SemVer precedence
54
+ * order (ie, lowest versions first).
55
+ *
56
+ * Invalid version strings are sorted to the end of the array in ascending
57
+ * alphabetical order.
58
+ *
59
+ * Note: when using this method, the list is cloned prior to sorting, to
60
+ * prevent surprising mutation. To sort the list in place, see
61
+ * {@link sortMethod}.
62
+ */
63
+ export declare const sort: <T extends Version | string = string | Version>(list: T[]) => T[];
64
+ /**
65
+ * Sort an array of version strings or objects in descending SemVer
66
+ * precedence order (ie, highest versions first).
67
+ *
68
+ * Invalid version strings are sorted to the end of the array in ascending
69
+ * alphabetical order.
70
+ *
71
+ * Note: when using this method, the list is cloned prior to sorting, to
72
+ * prevent surprising mutation. To sort the list in place, see
73
+ * {@link rsortMethod}.
74
+ */
75
+ export declare const rsort: <T extends Version | string = string | Version>(list: T[]) => T[];
76
+ /**
77
+ * The method used by {@link rsort}, exported for passing directly to
78
+ * `Array.sort`.
79
+ *
80
+ * Usage:
81
+ *
82
+ * ```ts
83
+ * import { rsortMethod } from '@vltpkg/semver'
84
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
85
+ * console.log(versions.sort(rsortMethod))
86
+ * // ['5.2.3', '2.3.4', '1.2.3']
87
+ * ```
88
+ */
89
+ export declare const rsortMethod: (a: Version | string, b: Version | string) => number;
90
+ /**
91
+ * Method used by {@link filter}, for use in `Array.filter` directly.
92
+ *
93
+ * Usage:
94
+ *
95
+ * ```ts
96
+ * import { filterMethod } from '@vltpkg/semver'
97
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
98
+ * console.log(versions.filter(filterMethod('>=2.x')))
99
+ * // ['5.2.3', '2.3.4']
100
+ * ```
101
+ */
102
+ export declare const filterMethod: (range: Range | string, includePrerelease?: boolean) => ((version: Version | string) => boolean);
103
+ /**
104
+ * Filter a list of versions to find all that match a given range.
105
+ */
106
+ export declare const filter: <T extends Version | string = string | Version>(list: T[], range: Range | string, includePrerelease?: boolean) => T[];
107
+ /**
108
+ * Find the highest-precedence match for a range within a list of versions
109
+ *
110
+ * Returns `undefined` if no match was found.
111
+ */
112
+ export declare const highest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
113
+ /**
114
+ * Faster form of {@link highest}, for use when the list is sorted
115
+ * in precedence order (lower-precedence versions first).
116
+ *
117
+ * Note: This stops at the first match, and will produce incorrect results
118
+ * when the list is not properly sorted!
119
+ */
120
+ export declare const sortedHighest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
121
+ /**
122
+ * Faster form of {@link highest}, for use when the list is sorted
123
+ * in reverse precedence order (higher-precedence versions first).
124
+ *
125
+ * Note: This stops at the first match, and will produce incorrect results
126
+ * when the list is not properly sorted!
127
+ */
128
+ export declare const rsortedHighest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
129
+ /**
130
+ * Find the lowest-precedence match for a range within a list of versions
131
+ *
132
+ * Returns `undefined` if no match was found.
133
+ */
134
+ export declare const lowest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
135
+ /**
136
+ * Faster form of {@link lowest}, for use when the list is sorted
137
+ * in precedence order (lower-precedence versions first).
138
+ *
139
+ * Note: This stops at the first match, and will produce incorrect results
140
+ * when the list is not properly sorted!
141
+ */
142
+ export declare const sortedLowest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
143
+ /**
144
+ * Faster form of {@link lowest}, for use when the list is sorted
145
+ * in reverse precedence order (higher-precedence versions first).
146
+ *
147
+ * Note: This stops at the first match, and will produce incorrect results
148
+ * when the list is not properly sorted!
149
+ */
150
+ export declare const rsortedLowest: (list: (Version | string)[], range: Range | string, includePrerelease?: boolean) => Version | undefined;
151
+ /**
152
+ * Same as {@link sortMethod}, but throws if either version is not valid.
153
+ * 1 if versionA is higher precedence than versionB
154
+ * -1 if versionA is lower precedence than versionB
155
+ * 0 if they have equal precedence
156
+ */
157
+ export declare const compare: (versionA: Version | string, versionB: Version | string) => 0 | 1 | -1;
158
+ /**
159
+ * Inverse of {@link compare}
160
+ *
161
+ * Same as {@link rsortMethod}, but throws if either version is not valid.
162
+ *
163
+ * -1 if versionA is higher precedence than versionB
164
+ * 1 if versionA is lower precedence than versionB
165
+ * 0 if they have equal precedence
166
+ */
167
+ export declare const rcompare: (versionA: Version | string, versionB: Version | string) => 0 | 1 | -1;
168
+ /** true if versionA is > versionB. throws on invalid values */
169
+ export declare const gt: (versionA: Version | string, versionB: Version | string) => boolean;
170
+ /** true if versionA is >= versionB. throws on invalid values */
171
+ export declare const gte: (versionA: Version | string, versionB: Version | string) => boolean;
172
+ /** true if versionA is < versionB. throws on invalid values */
173
+ export declare const lt: (versionA: Version | string, versionB: Version | string) => boolean;
174
+ /** true if versionA is &lt;= versionB. throws on invalid values */
175
+ export declare const lte: (versionA: Version | string, versionB: Version | string) => boolean;
176
+ /** true if versionA is not equal to versionB. throws on invalid values */
177
+ export declare const neq: (versionA: Version | string, versionB: Version | string) => boolean;
178
+ /** true if versionA is equal to versionB. throws on invalid values */
179
+ export declare const eq: (versionA: Version | string, versionB: Version | string) => boolean;
180
+ /** extract the major version number, or undefined if invalid */
181
+ export declare const major: (version: Version | string) => number | undefined;
182
+ /** extract the minor version number, or undefined if invalid */
183
+ export declare const minor: (version: Version | string) => number | undefined;
184
+ /** extract the patch version number, or undefined if invalid */
185
+ export declare const patch: (version: Version | string) => number | undefined;
186
+ /**
187
+ * extract the list of prerelease identifiers, or undefined if the version
188
+ * is invalid. If no prerelease identifiers are present, returns `[]`.
189
+ */
190
+ export declare const prerelease: (version: Version | string) => (string | number)[] | undefined;
191
+ /**
192
+ * extract the list of build identifiers, or undefined if the version
193
+ * is invalid. If no build identifiers are present, returns `[]`.
194
+ */
195
+ export declare const build: (version: Version | string) => string[] | undefined;
196
+ /** return all versions that do not have any prerelease identifiers */
197
+ export declare const stable: <T extends Version | string = string | Version>(versions: T[]) => T[];
198
+ /**
199
+ * Return true if the range r1 intersects any of the ranges r2
200
+ * r1 and r2 are either Range objects or range strings.
201
+ * Returns true if any version would satisfy both ranges.
202
+ */
203
+ export declare const intersects: (r1: Range | string, r2: Range | string, includePrerelease?: boolean) => boolean;
package/dist/index.js ADDED
@@ -0,0 +1,457 @@
1
+ import { Range } from "./range.js";
2
+ import { Version } from "./version.js";
3
+ import { syntaxError } from '@vltpkg/error-cause';
4
+ export * from "./comparator.js";
5
+ export * from "./range.js";
6
+ export * from "./version.js";
7
+ /** Return the parsed version string, or `undefined` if invalid */
8
+ export const parse = (version) => {
9
+ if (!(typeof version === 'string'))
10
+ return version;
11
+ try {
12
+ return Version.parse(version);
13
+ }
14
+ catch {
15
+ return undefined;
16
+ }
17
+ };
18
+ /** Return the parsed version range, or `undefined` if invalid */
19
+ export const parseRange = (range, includePrerelease = false) => {
20
+ if (typeof range === 'object') {
21
+ if (range.includePrerelease === includePrerelease)
22
+ return range;
23
+ range = range.raw;
24
+ }
25
+ try {
26
+ return new Range(range, includePrerelease);
27
+ }
28
+ catch {
29
+ return undefined;
30
+ }
31
+ };
32
+ /**
33
+ * return true if the version is valid
34
+ *
35
+ * Note: do not use this if you intend to immediately parse the version if it's
36
+ * valid. Just use {@link parse}, and guard the possible undefined value, or
37
+ * use `Version.parse(..)` to throw on invalid values.
38
+ */
39
+ export const valid = (version) => !!parse(version);
40
+ /**
41
+ * return true if the range is valid
42
+ *
43
+ * Note: do not use this if you intend to immediately parse the range if it's
44
+ * valid. Just use {@link parseRange}, and guard the possible undefined value,
45
+ * or use `new Range(..)` to throw on invalid values.
46
+ */
47
+ export const validRange = (range) => !!parseRange(range);
48
+ /**
49
+ * Return true if the version satisfies the range.
50
+ */
51
+ export const satisfies = (version, range, includePrerelease = false) => {
52
+ if (typeof version === 'string') {
53
+ const parsed = parse(version);
54
+ if (!parsed)
55
+ return false;
56
+ version = parsed;
57
+ }
58
+ if (typeof range === 'string') {
59
+ const parsed = parseRange(range, includePrerelease);
60
+ if (!parsed)
61
+ return false;
62
+ range = parsed;
63
+ }
64
+ return version.satisfies(range);
65
+ };
66
+ /**
67
+ * Increment the specified part of the version, and return the resulting
68
+ * object. If a Version object is provided, it will be modified in-place.
69
+ *
70
+ * See {@link Version.inc} for full description.
71
+ */
72
+ export const inc = (version, part, prereleaseIdentifier) => (typeof version === 'string' ?
73
+ Version.parse(version)
74
+ : version).inc(part, prereleaseIdentifier);
75
+ /**
76
+ * The method used by {@link sort}, exported for passing directly to
77
+ * `Array.sort`.
78
+ *
79
+ * Usage:
80
+ *
81
+ * ```ts
82
+ * import { sortMethod } from '@vltpkg/semver'
83
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
84
+ * console.log(versions.sort(sortMethod))
85
+ * // ['1.2.3', '2.3.4', '5.2.3']
86
+ * ```
87
+ */
88
+ export const sortMethod = (a, b) => {
89
+ const pa = parse(a);
90
+ const pb = parse(b);
91
+ /* c8 ignore start - nondeterministic */
92
+ if (!pa && !pb)
93
+ return String(a).localeCompare(String(b), 'en');
94
+ if (!pa)
95
+ return 1;
96
+ if (!pb)
97
+ return -1;
98
+ /* c8 ignore stop */
99
+ return pa.compare(pb);
100
+ };
101
+ /**
102
+ * Sort an array of version strings or objects in ascending SemVer precedence
103
+ * order (ie, lowest versions first).
104
+ *
105
+ * Invalid version strings are sorted to the end of the array in ascending
106
+ * alphabetical order.
107
+ *
108
+ * Note: when using this method, the list is cloned prior to sorting, to
109
+ * prevent surprising mutation. To sort the list in place, see
110
+ * {@link sortMethod}.
111
+ */
112
+ export const sort = (list) => list.slice().sort(sortMethod);
113
+ /**
114
+ * Sort an array of version strings or objects in descending SemVer
115
+ * precedence order (ie, highest versions first).
116
+ *
117
+ * Invalid version strings are sorted to the end of the array in ascending
118
+ * alphabetical order.
119
+ *
120
+ * Note: when using this method, the list is cloned prior to sorting, to
121
+ * prevent surprising mutation. To sort the list in place, see
122
+ * {@link rsortMethod}.
123
+ */
124
+ export const rsort = (list) => list.slice().sort(rsortMethod);
125
+ /**
126
+ * The method used by {@link rsort}, exported for passing directly to
127
+ * `Array.sort`.
128
+ *
129
+ * Usage:
130
+ *
131
+ * ```ts
132
+ * import { rsortMethod } from '@vltpkg/semver'
133
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
134
+ * console.log(versions.sort(rsortMethod))
135
+ * // ['5.2.3', '2.3.4', '1.2.3']
136
+ * ```
137
+ */
138
+ export const rsortMethod = (a, b) => {
139
+ const pa = parse(a);
140
+ const pb = parse(b);
141
+ /* c8 ignore start - nondeterministic */
142
+ if (!pa && !pb)
143
+ return String(a).localeCompare(String(b), 'en');
144
+ if (!pa)
145
+ return 1;
146
+ if (!pb)
147
+ return -1;
148
+ /* c8 ignore stop */
149
+ return pa.rcompare(pb);
150
+ };
151
+ /**
152
+ * Method used by {@link filter}, for use in `Array.filter` directly.
153
+ *
154
+ * Usage:
155
+ *
156
+ * ```ts
157
+ * import { filterMethod } from '@vltpkg/semver'
158
+ * const versions = ['1.2.3', '5.2.3', '2.3.4']
159
+ * console.log(versions.filter(filterMethod('>=2.x')))
160
+ * // ['5.2.3', '2.3.4']
161
+ * ```
162
+ */
163
+ export const filterMethod = (range, includePrerelease = false) => {
164
+ const r = parseRange(range, includePrerelease);
165
+ return !r ?
166
+ () => false
167
+ : version => satisfies(version, r, r.includePrerelease);
168
+ };
169
+ /**
170
+ * Filter a list of versions to find all that match a given range.
171
+ */
172
+ export const filter = (list, range, includePrerelease = false) => list.filter(filterMethod(range, includePrerelease));
173
+ /**
174
+ * Find the highest-precedence match for a range within a list of versions
175
+ *
176
+ * Returns `undefined` if no match was found.
177
+ */
178
+ export const highest = (list, range, includePrerelease = false) => {
179
+ const r = parseRange(range, includePrerelease);
180
+ if (!r)
181
+ return undefined;
182
+ let max = undefined;
183
+ for (const v of list) {
184
+ const version = parse(v);
185
+ if (!version)
186
+ continue;
187
+ if (!version.satisfies(r))
188
+ continue;
189
+ if (!max)
190
+ max = version;
191
+ else if (version.greaterThan(max))
192
+ max = version;
193
+ }
194
+ return max;
195
+ };
196
+ /**
197
+ * Faster form of {@link highest}, for use when the list is sorted
198
+ * in precedence order (lower-precedence versions first).
199
+ *
200
+ * Note: This stops at the first match, and will produce incorrect results
201
+ * when the list is not properly sorted!
202
+ */
203
+ export const sortedHighest = (list, range, includePrerelease = false) => {
204
+ const r = parseRange(range, includePrerelease);
205
+ if (!r)
206
+ return undefined;
207
+ for (let i = list.length - 1; i >= 0; i--) {
208
+ const v = list[i];
209
+ /* c8 ignore next */
210
+ if (!v)
211
+ continue;
212
+ const version = parse(v);
213
+ if (!version)
214
+ continue;
215
+ if (!version.satisfies(r))
216
+ continue;
217
+ return version;
218
+ }
219
+ };
220
+ /**
221
+ * Faster form of {@link highest}, for use when the list is sorted
222
+ * in reverse precedence order (higher-precedence versions first).
223
+ *
224
+ * Note: This stops at the first match, and will produce incorrect results
225
+ * when the list is not properly sorted!
226
+ */
227
+ export const rsortedHighest = (list, range, includePrerelease = false) => {
228
+ const r = parseRange(range, includePrerelease);
229
+ if (!r)
230
+ return undefined;
231
+ for (const v of list) {
232
+ const version = parse(v);
233
+ if (!version)
234
+ continue;
235
+ if (!version.satisfies(r))
236
+ continue;
237
+ return version;
238
+ }
239
+ };
240
+ /**
241
+ * Find the lowest-precedence match for a range within a list of versions
242
+ *
243
+ * Returns `undefined` if no match was found.
244
+ */
245
+ export const lowest = (list, range, includePrerelease = false) => {
246
+ const r = parseRange(range, includePrerelease);
247
+ if (!r)
248
+ return undefined;
249
+ let min = undefined;
250
+ for (const v of list) {
251
+ const version = parse(v);
252
+ if (!version)
253
+ continue;
254
+ if (!version.satisfies(r))
255
+ continue;
256
+ if (!min)
257
+ min = version;
258
+ else if (version.lessThan(min))
259
+ min = version;
260
+ }
261
+ return min;
262
+ };
263
+ /**
264
+ * Faster form of {@link lowest}, for use when the list is sorted
265
+ * in precedence order (lower-precedence versions first).
266
+ *
267
+ * Note: This stops at the first match, and will produce incorrect results
268
+ * when the list is not properly sorted!
269
+ */
270
+ export const sortedLowest = (list, range, includePrerelease = false) => rsortedHighest(list, range, includePrerelease);
271
+ /**
272
+ * Faster form of {@link lowest}, for use when the list is sorted
273
+ * in reverse precedence order (higher-precedence versions first).
274
+ *
275
+ * Note: This stops at the first match, and will produce incorrect results
276
+ * when the list is not properly sorted!
277
+ */
278
+ export const rsortedLowest = (list, range, includePrerelease = false) => sortedHighest(list, range, includePrerelease);
279
+ /**
280
+ * Same as {@link sortMethod}, but throws if either version is not valid.
281
+ * 1 if versionA is higher precedence than versionB
282
+ * -1 if versionA is lower precedence than versionB
283
+ * 0 if they have equal precedence
284
+ */
285
+ export const compare = (versionA, versionB) => {
286
+ const a = parse(versionA);
287
+ if (!a) {
288
+ throw syntaxError('invalid version', { found: versionA });
289
+ }
290
+ const b = parse(versionB);
291
+ if (!b) {
292
+ throw syntaxError('invalid version', { found: versionB });
293
+ }
294
+ return a.compare(b);
295
+ };
296
+ /**
297
+ * Inverse of {@link compare}
298
+ *
299
+ * Same as {@link rsortMethod}, but throws if either version is not valid.
300
+ *
301
+ * -1 if versionA is higher precedence than versionB
302
+ * 1 if versionA is lower precedence than versionB
303
+ * 0 if they have equal precedence
304
+ */
305
+ export const rcompare = (versionA, versionB) => compare(versionB, versionA);
306
+ /** true if versionA is > versionB. throws on invalid values */
307
+ export const gt = (versionA, versionB) => compare(versionA, versionB) > 0;
308
+ /** true if versionA is >= versionB. throws on invalid values */
309
+ export const gte = (versionA, versionB) => compare(versionA, versionB) >= 0;
310
+ /** true if versionA is < versionB. throws on invalid values */
311
+ export const lt = (versionA, versionB) => compare(versionA, versionB) < 0;
312
+ /** true if versionA is &lt;= versionB. throws on invalid values */
313
+ export const lte = (versionA, versionB) => compare(versionA, versionB) <= 0;
314
+ /** true if versionA is not equal to versionB. throws on invalid values */
315
+ export const neq = (versionA, versionB) => compare(versionA, versionB) !== 0;
316
+ /** true if versionA is equal to versionB. throws on invalid values */
317
+ export const eq = (versionA, versionB) => compare(versionA, versionB) === 0;
318
+ /** extract the major version number, or undefined if invalid */
319
+ export const major = (version) => parse(version)?.major;
320
+ /** extract the minor version number, or undefined if invalid */
321
+ export const minor = (version) => parse(version)?.minor;
322
+ /** extract the patch version number, or undefined if invalid */
323
+ export const patch = (version) => parse(version)?.patch;
324
+ /**
325
+ * extract the list of prerelease identifiers, or undefined if the version
326
+ * is invalid. If no prerelease identifiers are present, returns `[]`.
327
+ */
328
+ export const prerelease = (version) => {
329
+ const p = parse(version);
330
+ if (!p)
331
+ return undefined;
332
+ return p.prerelease ?? [];
333
+ };
334
+ /**
335
+ * extract the list of build identifiers, or undefined if the version
336
+ * is invalid. If no build identifiers are present, returns `[]`.
337
+ */
338
+ export const build = (version) => {
339
+ const p = parse(version);
340
+ if (!p)
341
+ return undefined;
342
+ return p.build ?? [];
343
+ };
344
+ /** return all versions that do not have any prerelease identifiers */
345
+ export const stable = (versions) => versions.filter(v => {
346
+ const p = parse(v);
347
+ if (!p)
348
+ return false;
349
+ return !p.prerelease?.length;
350
+ });
351
+ /**
352
+ * Return true if the range r1 intersects any of the ranges r2
353
+ * r1 and r2 are either Range objects or range strings.
354
+ * Returns true if any version would satisfy both ranges.
355
+ */
356
+ export const intersects = (r1, r2, includePrerelease) => {
357
+ const range1 = typeof r1 === 'string' ? parseRange(r1, includePrerelease) : r1;
358
+ const range2 = typeof r2 === 'string' ? parseRange(r2, includePrerelease) : r2;
359
+ if (!range1 || !range2)
360
+ return false;
361
+ // If either range is 'any', they intersect
362
+ if (range1.isAny || range2.isAny)
363
+ return true;
364
+ // Check if any set from range1 intersects with any set from range2
365
+ return range1.set.some(set1 => range2.set.some(set2 => intersectComparators(set1, set2)));
366
+ };
367
+ /**
368
+ * Check if two comparators can be satisfied simultaneously
369
+ */
370
+ const intersectComparators = (comp1, comp2) => {
371
+ // Collect all tuples from both comparators
372
+ const tuples1 = comp1.tuples.filter((t) => Array.isArray(t));
373
+ const tuples2 = comp2.tuples.filter((t) => Array.isArray(t));
374
+ // Check if there's a satisfiable combination
375
+ return satisfiableRange(tuples1.concat(tuples2));
376
+ };
377
+ /**
378
+ * Check if a set of operator-version tuples represents a satisfiable range
379
+ * This is a simplified implementation that handles the most common cases
380
+ */
381
+ const satisfiableRange = (tuples) => {
382
+ // Find bounds
383
+ let lowerBound = null;
384
+ let lowerInclusive = false;
385
+ let upperBound = null;
386
+ let upperInclusive = false;
387
+ let hasExact = null;
388
+ for (const [op, ver] of tuples) {
389
+ switch (op) {
390
+ case '':
391
+ // Exact match - if we already have a different exact match, no intersection
392
+ if (hasExact && !eq(hasExact, ver))
393
+ return false;
394
+ hasExact = ver;
395
+ break;
396
+ case '>=':
397
+ /* c8 ignore start */
398
+ if (!lowerBound ||
399
+ gt(ver, lowerBound) ||
400
+ (eq(ver, lowerBound) && !lowerInclusive)) {
401
+ lowerBound = ver;
402
+ lowerInclusive = true;
403
+ }
404
+ /* c8 ignore stop */
405
+ break;
406
+ case '>':
407
+ if (!lowerBound || gt(ver, lowerBound)) {
408
+ lowerBound = ver;
409
+ lowerInclusive = false;
410
+ }
411
+ break;
412
+ case '<=':
413
+ if (!upperBound || lt(ver, upperBound)) {
414
+ upperBound = ver;
415
+ upperInclusive = true;
416
+ }
417
+ break;
418
+ case '<':
419
+ /* c8 ignore start */
420
+ if (!upperBound ||
421
+ lt(ver, upperBound) ||
422
+ eq(ver, upperBound)) {
423
+ upperBound = ver;
424
+ upperInclusive = false;
425
+ }
426
+ /* c8 ignore stop */
427
+ break;
428
+ }
429
+ }
430
+ // If we have an exact match, check if it's within bounds
431
+ if (hasExact) {
432
+ if (lowerBound) {
433
+ if (lowerInclusive ?
434
+ lt(hasExact, lowerBound)
435
+ : lte(hasExact, lowerBound)) {
436
+ return false;
437
+ }
438
+ }
439
+ if (upperBound) {
440
+ if (upperInclusive ?
441
+ gt(hasExact, upperBound)
442
+ : gte(hasExact, upperBound)) {
443
+ return false;
444
+ }
445
+ }
446
+ return true;
447
+ }
448
+ // Check if lower bound is less than or equal to upper bound
449
+ if (lowerBound && upperBound) {
450
+ if (gt(lowerBound, upperBound))
451
+ return false;
452
+ if (eq(lowerBound, upperBound) &&
453
+ !(lowerInclusive && upperInclusive))
454
+ return false;
455
+ }
456
+ return true;
457
+ };
@@ -0,0 +1,34 @@
1
+ import { Comparator } from './comparator.ts';
2
+ import type { Version } from './version.ts';
3
+ export declare const isRange: (range: unknown) => range is Range;
4
+ /**
5
+ * A representation of a semver range, used to test versions.
6
+ *
7
+ * Includes a set of comparators representing the `||`-separated
8
+ * sections of the range string
9
+ */
10
+ export declare class Range {
11
+ #private;
12
+ /** raw string used to create this Range */
13
+ raw: string;
14
+ /** true if the range is `*` */
15
+ isAny: boolean;
16
+ /** true if the range is a single semver version */
17
+ isSingle: boolean;
18
+ /** true if the range cannot match anything */
19
+ /**
20
+ * set of {@link Comparator} objects representing the `||`-separated sections
21
+ * of the range. If at least one of these matches, then the version is a
22
+ * match.
23
+ */
24
+ set: Comparator[];
25
+ /** true if all prerelease versions should be included */
26
+ includePrerelease: boolean;
27
+ constructor(range: string, includePrerelease?: boolean);
28
+ /**
29
+ * test a {@link Version} against the range
30
+ */
31
+ test(v: Version): boolean;
32
+ /** return the simplified canonical form of this range */
33
+ toString(): string;
34
+ }