@glion/util-semver 0.14.1
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/LICENSE +21 -0
- package/README.md +379 -0
- package/dist/collection.d.ts +67 -0
- package/dist/collection.d.ts.map +1 -0
- package/dist/compare.d.ts +124 -0
- package/dist/compare.d.ts.map +1 -0
- package/dist/errors.d.ts +19 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/index.d.ts +8 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +504 -0
- package/dist/index.js.map +1 -0
- package/dist/parse.d.ts +81 -0
- package/dist/parse.d.ts.map +1 -0
- package/dist/range.d.ts +73 -0
- package/dist/range.d.ts.map +1 -0
- package/dist/types.d.ts +30 -0
- package/dist/types.d.ts.map +1 -0
- package/package.json +50 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Rethink Health
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,379 @@
|
|
|
1
|
+
# @glion/util-semver
|
|
2
|
+
|
|
3
|
+
A tiny, fast, and secure version utility for HL7v2-like version strings. Intentionally simplified for our ecosystem while maintaining excellent performance and type safety.
|
|
4
|
+
|
|
5
|
+
## Features
|
|
6
|
+
|
|
7
|
+
✨ **Simple & Elegant** - Clean API, no unnecessary complexity
|
|
8
|
+
⚡ **High Performance** - O(n) algorithms, Range caching for hot paths
|
|
9
|
+
🔒 **Secure** - ReDoS protection, integer overflow guards
|
|
10
|
+
📘 **Type Safe** - Full TypeScript support with structured errors
|
|
11
|
+
🪶 **Tiny** - ~6KB, zero dependencies
|
|
12
|
+
|
|
13
|
+
## Installation
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
npm install @glion/util-semver
|
|
17
|
+
```
|
|
18
|
+
|
|
19
|
+
## Quick Start
|
|
20
|
+
|
|
21
|
+
```typescript
|
|
22
|
+
import {
|
|
23
|
+
parse,
|
|
24
|
+
clean,
|
|
25
|
+
compare,
|
|
26
|
+
satisfies,
|
|
27
|
+
sort,
|
|
28
|
+
maxSatisfying,
|
|
29
|
+
increment,
|
|
30
|
+
diff,
|
|
31
|
+
Range,
|
|
32
|
+
} from "@glion/util-semver";
|
|
33
|
+
|
|
34
|
+
// Parse versions
|
|
35
|
+
parse("2.3"); // { major: 2, minor: 3, patch: 0 }
|
|
36
|
+
clean("2"); // "2.0.0"
|
|
37
|
+
valid("2.5.1"); // true
|
|
38
|
+
|
|
39
|
+
// Compare versions
|
|
40
|
+
compare("2.3.1", "2.4"); // -1 (less than)
|
|
41
|
+
eq("2.5.0", "2.5"); // true
|
|
42
|
+
gt("2.5.1", "2.5.0"); // true
|
|
43
|
+
|
|
44
|
+
// Version ranges
|
|
45
|
+
satisfies("2.5.1", ">=2.0 <3.0"); // true
|
|
46
|
+
satisfies("2.5.1", "2.5.1"); // true (exact match)
|
|
47
|
+
|
|
48
|
+
// Collection operations
|
|
49
|
+
sort(["2.5", "2.3.1", "2.10"]); // ["2.3.1", "2.5", "2.10"]
|
|
50
|
+
maxSatisfying(["2.3", "2.5", "3.0"], ">=2.0 <3.0"); // "2.5"
|
|
51
|
+
minSatisfying(["2.3", "2.5", "3.0"], ">=2.0 <3.0"); // "2.3"
|
|
52
|
+
|
|
53
|
+
// Version manipulation
|
|
54
|
+
increment("2.5.1", "minor"); // "2.6.0"
|
|
55
|
+
diff("2.5.1", "2.6.0"); // "minor"
|
|
56
|
+
```
|
|
57
|
+
|
|
58
|
+
## API Reference
|
|
59
|
+
|
|
60
|
+
### Parsing & Validation
|
|
61
|
+
|
|
62
|
+
#### `parse(version: string): Hl7Version`
|
|
63
|
+
|
|
64
|
+
Parses a version string into a structured object.
|
|
65
|
+
|
|
66
|
+
```typescript
|
|
67
|
+
parse("2.5.1"); // { major: 2, minor: 5, patch: 1 }
|
|
68
|
+
parse("2.3"); // { major: 2, minor: 3, patch: 0 }
|
|
69
|
+
parse("2"); // { major: 2, minor: 0, patch: 0 }
|
|
70
|
+
```
|
|
71
|
+
|
|
72
|
+
**Throws:** `VersionParseError` if invalid format
|
|
73
|
+
|
|
74
|
+
#### `clean(version: string): string`
|
|
75
|
+
|
|
76
|
+
Converts a version to canonical format (major.minor.patch).
|
|
77
|
+
|
|
78
|
+
```typescript
|
|
79
|
+
clean("2"); // "2.0.0"
|
|
80
|
+
clean("2.5"); // "2.5.0"
|
|
81
|
+
clean(" 2.5 "); // "2.5.0"
|
|
82
|
+
```
|
|
83
|
+
|
|
84
|
+
**Throws:** `VersionParseError` if invalid format
|
|
85
|
+
|
|
86
|
+
#### `valid(version: string): boolean`
|
|
87
|
+
|
|
88
|
+
Checks if a string is a valid version. Never throws.
|
|
89
|
+
|
|
90
|
+
```typescript
|
|
91
|
+
valid("2.5.1"); // true
|
|
92
|
+
valid("2"); // true
|
|
93
|
+
valid("HELLO"); // false
|
|
94
|
+
```
|
|
95
|
+
|
|
96
|
+
### Comparison
|
|
97
|
+
|
|
98
|
+
#### `compare(a, b): -1 | 0 | 1`
|
|
99
|
+
|
|
100
|
+
Compares two versions.
|
|
101
|
+
|
|
102
|
+
```typescript
|
|
103
|
+
compare("2.3.1", "2.4"); // -1 (a < b)
|
|
104
|
+
compare("2.5.1", "2.5.1"); // 0 (a = b)
|
|
105
|
+
compare("2.6", "2.5.9"); // 1 (a > b)
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
#### Comparison Operators
|
|
109
|
+
|
|
110
|
+
- `eq(a, b)` - Equal to
|
|
111
|
+
- `lt(a, b)` - Less than
|
|
112
|
+
- `lte(a, b)` - Less than or equal
|
|
113
|
+
- `gt(a, b)` - Greater than
|
|
114
|
+
- `gte(a, b)` - Greater than or equal
|
|
115
|
+
|
|
116
|
+
```typescript
|
|
117
|
+
eq("2.5.0", "2.5"); // true
|
|
118
|
+
lt("2.3", "2.4"); // true
|
|
119
|
+
gte("2.5.1", "2.5"); // true
|
|
120
|
+
```
|
|
121
|
+
|
|
122
|
+
### Range Matching
|
|
123
|
+
|
|
124
|
+
#### `satisfies(version, range): boolean`
|
|
125
|
+
|
|
126
|
+
Checks if a version satisfies a range expression.
|
|
127
|
+
|
|
128
|
+
**Range Syntax:**
|
|
129
|
+
|
|
130
|
+
- Operators: `=`, `<`, `<=`, `>`, `>=`
|
|
131
|
+
- Multiple comparators: Space-separated (AND logic)
|
|
132
|
+
- Default operator: `=` (exact match)
|
|
133
|
+
|
|
134
|
+
```typescript
|
|
135
|
+
satisfies("2.5.1", ">=2.0 <3.0"); // true
|
|
136
|
+
satisfies("2.5.1", "2.5.1"); // true (exact match)
|
|
137
|
+
satisfies("2.5.1", ">=2.6"); // false
|
|
138
|
+
```
|
|
139
|
+
|
|
140
|
+
**Performance Tip:** Use `Range` objects for repeated checks:
|
|
141
|
+
|
|
142
|
+
```typescript
|
|
143
|
+
// Slow: Parse range every time
|
|
144
|
+
for (const version of versions) {
|
|
145
|
+
if (satisfies(version, ">=2.0 <3.0")) {
|
|
146
|
+
/* ... */
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
// Fast: Parse once, reuse many times
|
|
151
|
+
const range = new Range(">=2.0 <3.0");
|
|
152
|
+
for (const version of versions) {
|
|
153
|
+
if (satisfies(version, range)) {
|
|
154
|
+
/* ... */
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
#### `Range` Class
|
|
160
|
+
|
|
161
|
+
Pre-parsed range for efficient reuse.
|
|
162
|
+
|
|
163
|
+
```typescript
|
|
164
|
+
const range = new Range(">=2.0 <3.0");
|
|
165
|
+
range.test("2.5.1"); // true
|
|
166
|
+
range.test("3.0.0"); // false
|
|
167
|
+
|
|
168
|
+
// Works with all range functions
|
|
169
|
+
satisfies("2.5.1", range);
|
|
170
|
+
maxSatisfying(versions, range);
|
|
171
|
+
minSatisfying(versions, range);
|
|
172
|
+
```
|
|
173
|
+
|
|
174
|
+
### Collection Operations
|
|
175
|
+
|
|
176
|
+
#### `sort(versions: string[]): string[]`
|
|
177
|
+
|
|
178
|
+
Sorts versions in ascending order. Returns new array (does not mutate).
|
|
179
|
+
|
|
180
|
+
```typescript
|
|
181
|
+
sort(["2.5", "2.3.1", "2.10.0"]);
|
|
182
|
+
// => ["2.3.1", "2.5", "2.10.0"]
|
|
183
|
+
```
|
|
184
|
+
|
|
185
|
+
#### `maxSatisfying(versions, range): string | null`
|
|
186
|
+
|
|
187
|
+
Finds the highest version that satisfies a range.
|
|
188
|
+
|
|
189
|
+
```typescript
|
|
190
|
+
maxSatisfying(["2.3.0", "2.5.1", "3.0.0"], ">=2.0 <3.0");
|
|
191
|
+
// => "2.5.1"
|
|
192
|
+
|
|
193
|
+
maxSatisfying(["2.3.0", "2.5.1"], ">=3.0");
|
|
194
|
+
// => null (no matches)
|
|
195
|
+
```
|
|
196
|
+
|
|
197
|
+
#### `minSatisfying(versions, range): string | null`
|
|
198
|
+
|
|
199
|
+
Finds the lowest version that satisfies a range.
|
|
200
|
+
|
|
201
|
+
```typescript
|
|
202
|
+
minSatisfying(["2.3.0", "2.5.1", "3.0.0"], ">=2.0 <3.0");
|
|
203
|
+
// => "2.3.0"
|
|
204
|
+
```
|
|
205
|
+
|
|
206
|
+
### Version Manipulation
|
|
207
|
+
|
|
208
|
+
#### `increment(version, release): string`
|
|
209
|
+
|
|
210
|
+
Increments a version component. Lower components reset to zero.
|
|
211
|
+
|
|
212
|
+
```typescript
|
|
213
|
+
increment("2.5.1", "major"); // "3.0.0"
|
|
214
|
+
increment("2.5.1", "minor"); // "2.6.0"
|
|
215
|
+
increment("2.5.1", "patch"); // "2.5.2"
|
|
216
|
+
```
|
|
217
|
+
|
|
218
|
+
#### `diff(v1, v2): 'major' | 'minor' | 'patch' | null`
|
|
219
|
+
|
|
220
|
+
Determines which component differs between versions.
|
|
221
|
+
|
|
222
|
+
```typescript
|
|
223
|
+
diff("2.5.1", "3.0.0"); // "major"
|
|
224
|
+
diff("2.5.1", "2.6.0"); // "minor"
|
|
225
|
+
diff("2.5.1", "2.5.2"); // "patch"
|
|
226
|
+
diff("2.5.1", "2.5.1"); // null (equal)
|
|
227
|
+
```
|
|
228
|
+
|
|
229
|
+
## Error Handling
|
|
230
|
+
|
|
231
|
+
All parsing/operation functions throw structured errors for invalid input:
|
|
232
|
+
|
|
233
|
+
```typescript
|
|
234
|
+
import { VersionParseError, RangeParseError } from "@glion/util-semver";
|
|
235
|
+
|
|
236
|
+
try {
|
|
237
|
+
parse("INVALID");
|
|
238
|
+
} catch (e) {
|
|
239
|
+
if (e instanceof VersionParseError) {
|
|
240
|
+
console.log(e.input); // "INVALID"
|
|
241
|
+
console.log(e.reason); // "expected format: major.minor.patch..."
|
|
242
|
+
console.log(e.message); // Full formatted message
|
|
243
|
+
}
|
|
244
|
+
}
|
|
245
|
+
|
|
246
|
+
try {
|
|
247
|
+
satisfies("2.5.1", "INVALID_RANGE");
|
|
248
|
+
} catch (e) {
|
|
249
|
+
if (e instanceof RangeParseError) {
|
|
250
|
+
console.log(e.token); // "INVALID_RANGE"
|
|
251
|
+
console.log(e.reason); // "expected format: [operator]version..."
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
```
|
|
255
|
+
|
|
256
|
+
**Validation functions never throw:**
|
|
257
|
+
|
|
258
|
+
- `valid(version)` - Returns `false` for invalid input
|
|
259
|
+
|
|
260
|
+
**Operation functions throw on invalid input:**
|
|
261
|
+
|
|
262
|
+
- `parse()`, `clean()`, `compare()`, `satisfies()`, etc.
|
|
263
|
+
|
|
264
|
+
## Performance
|
|
265
|
+
|
|
266
|
+
### Algorithm Complexity
|
|
267
|
+
|
|
268
|
+
- `parse()`, `compare()`: O(1)
|
|
269
|
+
- `sort()`: O(n log n)
|
|
270
|
+
- `maxSatisfying()`, `minSatisfying()`: O(n) - optimized to avoid full sort
|
|
271
|
+
- Range parsing: O(k) where k = number of comparators
|
|
272
|
+
|
|
273
|
+
### Optimization Tips
|
|
274
|
+
|
|
275
|
+
**1. Reuse Range objects**
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
// ❌ Slow: Parse range on every call
|
|
279
|
+
for (const version of manyVersions) {
|
|
280
|
+
if (satisfies(version, ">=2.0 <3.0")) {
|
|
281
|
+
/* ... */
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
// ✅ Fast: Parse once, reuse unlimited times
|
|
286
|
+
const range = new Range(">=2.0 <3.0");
|
|
287
|
+
for (const version of manyVersions) {
|
|
288
|
+
if (satisfies(version, range)) {
|
|
289
|
+
/* ... */
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
**2. Use appropriate algorithms**
|
|
295
|
+
|
|
296
|
+
```typescript
|
|
297
|
+
// ❌ Unnecessary: Full sort just to find max
|
|
298
|
+
const sorted = sort(versions);
|
|
299
|
+
const max = sorted[sorted.length - 1];
|
|
300
|
+
|
|
301
|
+
// ✅ Efficient: O(n) instead of O(n log n)
|
|
302
|
+
const max = maxSatisfying(versions, ">=0.0.0");
|
|
303
|
+
```
|
|
304
|
+
|
|
305
|
+
## Security
|
|
306
|
+
|
|
307
|
+
Built-in protections against common vulnerabilities:
|
|
308
|
+
|
|
309
|
+
**ReDoS Protection:**
|
|
310
|
+
|
|
311
|
+
- Maximum input length: 100 chars (versions), 1000 chars (ranges)
|
|
312
|
+
- Throws `VersionParseError` or `RangeParseError` if exceeded
|
|
313
|
+
|
|
314
|
+
**Integer Overflow Protection:**
|
|
315
|
+
|
|
316
|
+
- Version components capped at 2³¹-1 (max safe int32)
|
|
317
|
+
- Ensures cross-platform interoperability
|
|
318
|
+
- Throws `VersionParseError` if exceeded
|
|
319
|
+
|
|
320
|
+
**Input Sanitization:**
|
|
321
|
+
|
|
322
|
+
- Comprehensive validation rejects malformed input early
|
|
323
|
+
- Structured errors for debugging
|
|
324
|
+
|
|
325
|
+
## Version Format
|
|
326
|
+
|
|
327
|
+
- **Generic numeric versions:** `major[.minor][.patch]`
|
|
328
|
+
- **Missing components default to 0:** `"2"` → `{ major: 2, minor: 0, patch: 0 }`
|
|
329
|
+
- **Whitespace is trimmed:** `" 2.5.1 "` → `"2.5.1"`
|
|
330
|
+
- **No prerelease/build metadata**
|
|
331
|
+
- **No wildcards, hyphen ranges, or `^`/`~` operators**
|
|
332
|
+
|
|
333
|
+
## Range Syntax
|
|
334
|
+
|
|
335
|
+
**Operators:**
|
|
336
|
+
|
|
337
|
+
- `=` or omitted - Exact match
|
|
338
|
+
- `<` - Less than
|
|
339
|
+
- `<=` - Less than or equal
|
|
340
|
+
- `>` - Greater than
|
|
341
|
+
- `>=` - Greater than or equal
|
|
342
|
+
|
|
343
|
+
**Multiple comparators:**
|
|
344
|
+
|
|
345
|
+
- Space-separated for AND logic: `">=2.3 <3.0"`
|
|
346
|
+
- All comparators must be satisfied
|
|
347
|
+
|
|
348
|
+
**Examples:**
|
|
349
|
+
|
|
350
|
+
```typescript
|
|
351
|
+
"2.5.1"; // Exact match
|
|
352
|
+
">=2.0"; // Greater than or equal to 2.0
|
|
353
|
+
">=2.0 <3.0"; // Between 2.0 (inclusive) and 3.0 (exclusive)
|
|
354
|
+
">=2.3 <2.6 >2.4"; // Multiple AND conditions
|
|
355
|
+
```
|
|
356
|
+
|
|
357
|
+
## Contributing
|
|
358
|
+
|
|
359
|
+
We welcome contributions! Please see our [Contributing Guide][github-contributing] for more details.
|
|
360
|
+
|
|
361
|
+
1. Fork the repository
|
|
362
|
+
2. Create your feature branch (`git checkout -b feature/amazing-feature`)
|
|
363
|
+
3. Commit your changes (`git commit -m 'Add some amazing feature'`)
|
|
364
|
+
4. Push to the branch (`git push origin feature/amazing-feature`)
|
|
365
|
+
5. Open a Pull Request
|
|
366
|
+
|
|
367
|
+
## Code of Conduct
|
|
368
|
+
|
|
369
|
+
To ensure a welcoming and positive environment, we have a [Code of Conduct][github-code-of-conduct] that all contributors and participants are expected to adhere to.
|
|
370
|
+
|
|
371
|
+
## License
|
|
372
|
+
|
|
373
|
+
Copyright 2025 Rethink Health, SUARL. All rights reserved.
|
|
374
|
+
|
|
375
|
+
This program is licensed to you under the terms of the [MIT License](https://opensource.org/licenses/MIT). This program is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the [LICENSE][github-license] file for details.
|
|
376
|
+
|
|
377
|
+
[github-code-of-conduct]: https://github.com/rethinkhealth/glion/blob/main/CODE_OF_CONDUCT.md
|
|
378
|
+
[github-license]: https://github.com/rethinkhealth/glion/blob/main/LICENSE
|
|
379
|
+
[github-contributing]: https://github.com/rethinkhealth/glion/blob/main/CONTRIBUTING.md
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import type { Range } from "./range";
|
|
2
|
+
/**
|
|
3
|
+
* Sorts an array of version strings in ascending order.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* sort(["2.5", "2.3.1", "2.10.0"]);
|
|
8
|
+
* // => ["2.3.1", "2.5", "2.10.0"]
|
|
9
|
+
*
|
|
10
|
+
* sort(["2.10", "2.9", "2.8"]);
|
|
11
|
+
* // => ["2.8", "2.9", "2.10"]
|
|
12
|
+
* ```;
|
|
13
|
+
*
|
|
14
|
+
* @param versions - Array of version strings to sort
|
|
15
|
+
* @returns New sorted array (does not mutate input)
|
|
16
|
+
* @throws {VersionParseError} If any version string is invalid
|
|
17
|
+
*/
|
|
18
|
+
export declare function sort(versions: string[]): string[];
|
|
19
|
+
/**
|
|
20
|
+
* Finds the highest version that satisfies a range.
|
|
21
|
+
*
|
|
22
|
+
* @example
|
|
23
|
+
* ```typescript
|
|
24
|
+
* maxSatisfying(["2.3.0", "2.5.1", "3.0.0"], ">=2.0 <3.0");
|
|
25
|
+
* // => "2.5.1"
|
|
26
|
+
*
|
|
27
|
+
* maxSatisfying(["2.3.0", "2.5.1"], ">=3.0");
|
|
28
|
+
* // => null (no matches)
|
|
29
|
+
*
|
|
30
|
+
* // Use Range object for better performance with many versions
|
|
31
|
+
* const range = new Range(">=2.0 <3.0");
|
|
32
|
+
* maxSatisfying(["2.3.0", "2.5.1", "3.0.0"], range);
|
|
33
|
+
* // => "2.5.1"
|
|
34
|
+
* ```;
|
|
35
|
+
*
|
|
36
|
+
* @param versions - Array of version strings to search
|
|
37
|
+
* @param range - Range expression string or pre-parsed Range object
|
|
38
|
+
* @returns Highest matching version, or null if none match
|
|
39
|
+
* @throws {VersionParseError} If any version string is invalid
|
|
40
|
+
* @throws {RangeParseError} If range expression is invalid
|
|
41
|
+
*/
|
|
42
|
+
export declare function maxSatisfying(versions: string[], range: string | Range): string | null;
|
|
43
|
+
/**
|
|
44
|
+
* Finds the lowest version that satisfies a range.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```typescript
|
|
48
|
+
* minSatisfying(["2.3.0", "2.5.1", "3.0.0"], ">=2.0 <3.0");
|
|
49
|
+
* // => "2.3.0"
|
|
50
|
+
*
|
|
51
|
+
* minSatisfying(["2.3.0", "2.5.1"], ">=3.0");
|
|
52
|
+
* // => null (no matches)
|
|
53
|
+
*
|
|
54
|
+
* // Use Range object for better performance with many versions
|
|
55
|
+
* const range = new Range(">=2.0 <3.0");
|
|
56
|
+
* minSatisfying(["2.3.0", "2.5.1", "3.0.0"], range);
|
|
57
|
+
* // => "2.3.0"
|
|
58
|
+
* ```;
|
|
59
|
+
*
|
|
60
|
+
* @param versions - Array of version strings to search
|
|
61
|
+
* @param range - Range expression string or pre-parsed Range object
|
|
62
|
+
* @returns Lowest matching version, or null if none match
|
|
63
|
+
* @throws {VersionParseError} If any version string is invalid
|
|
64
|
+
* @throws {RangeParseError} If range expression is invalid
|
|
65
|
+
*/
|
|
66
|
+
export declare function minSatisfying(versions: string[], range: string | Range): string | null;
|
|
67
|
+
//# sourceMappingURL=collection.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"collection.d.ts","sourceRoot":"","sources":["../src/collection.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAErC;;;;;;;;;;;;;;;GAeG;AACH,wBAAgB,IAAI,CAAC,QAAQ,EAAE,MAAM,EAAE,GAAG,MAAM,EAAE,CAEjD;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,EAAE,MAAM,GAAG,KAAK,GACpB,MAAM,GAAG,IAAI,CAaf;AAED;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,aAAa,CAC3B,QAAQ,EAAE,MAAM,EAAE,EAClB,KAAK,EAAE,MAAM,GAAG,KAAK,GACpB,MAAM,GAAG,IAAI,CAaf"}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import type { ComparisonResult, Hl7Version } from "./types";
|
|
2
|
+
/**
|
|
3
|
+
* Compares two versions and returns their relationship.
|
|
4
|
+
*
|
|
5
|
+
* @example
|
|
6
|
+
* ```typescript
|
|
7
|
+
* compare("2.5.1", "2.5.0"); // => 1
|
|
8
|
+
* compare("2.3", "2.5"); // => -1
|
|
9
|
+
* compare("2.5.1", "2.5.1"); // => 0
|
|
10
|
+
*
|
|
11
|
+
* // Works with parsed versions too
|
|
12
|
+
* const v1 = parse("2.5.1");
|
|
13
|
+
* const v2 = parse("2.5.0");
|
|
14
|
+
* compare(v1, v2); // => 1
|
|
15
|
+
* ```;
|
|
16
|
+
*
|
|
17
|
+
* @param a - First version (string or parsed object)
|
|
18
|
+
* @param b - Second version (string or parsed object)
|
|
19
|
+
* @returns -1 if a < b, 0 if a = b, 1 if a > b
|
|
20
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
21
|
+
*/
|
|
22
|
+
export declare function compare(a: string | Hl7Version, b: string | Hl7Version): ComparisonResult;
|
|
23
|
+
/**
|
|
24
|
+
* Checks if two versions are equal.
|
|
25
|
+
*
|
|
26
|
+
* @example
|
|
27
|
+
* ```typescript
|
|
28
|
+
* eq("2.5.1", "2.5.1"); // => true
|
|
29
|
+
* eq("2.5", "2.5.0"); // => true (normalized)
|
|
30
|
+
* eq("2.5.1", "2.5.0"); // => false
|
|
31
|
+
* ```;
|
|
32
|
+
*
|
|
33
|
+
* @param a - First version (string or parsed object)
|
|
34
|
+
* @param b - Second version (string or parsed object)
|
|
35
|
+
* @returns True if versions are equal, false otherwise
|
|
36
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
37
|
+
*/
|
|
38
|
+
export declare function eq(a: string | Hl7Version, b: string | Hl7Version): boolean;
|
|
39
|
+
/**
|
|
40
|
+
* Checks if first version is less than second version.
|
|
41
|
+
*
|
|
42
|
+
* @example
|
|
43
|
+
* ```typescript
|
|
44
|
+
* lt("2.3.0", "2.5.1"); // => true
|
|
45
|
+
* lt("2.5.1", "2.5.1"); // => false
|
|
46
|
+
* lt("2.5.1", "2.3.0"); // => false
|
|
47
|
+
* ```;
|
|
48
|
+
*
|
|
49
|
+
* @param a - First version (string or parsed object)
|
|
50
|
+
* @param b - Second version (string or parsed object)
|
|
51
|
+
* @returns True if a < b, false otherwise
|
|
52
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
53
|
+
*/
|
|
54
|
+
export declare function lt(a: string | Hl7Version, b: string | Hl7Version): boolean;
|
|
55
|
+
/**
|
|
56
|
+
* Checks if first version is less than or equal to second version.
|
|
57
|
+
*
|
|
58
|
+
* @example
|
|
59
|
+
* ```typescript
|
|
60
|
+
* lte("2.3.0", "2.5.1"); // => true
|
|
61
|
+
* lte("2.5.1", "2.5.1"); // => true
|
|
62
|
+
* lte("2.5.1", "2.3.0"); // => false
|
|
63
|
+
* ```;
|
|
64
|
+
*
|
|
65
|
+
* @param a - First version (string or parsed object)
|
|
66
|
+
* @param b - Second version (string or parsed object)
|
|
67
|
+
* @returns True if a <= b, false otherwise
|
|
68
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
69
|
+
*/
|
|
70
|
+
export declare function lte(a: string | Hl7Version, b: string | Hl7Version): boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Checks if first version is greater than second version.
|
|
73
|
+
*
|
|
74
|
+
* @example
|
|
75
|
+
* ```typescript
|
|
76
|
+
* gt("2.5.1", "2.3.0"); // => true
|
|
77
|
+
* gt("2.5.1", "2.5.1"); // => false
|
|
78
|
+
* gt("2.3.0", "2.5.1"); // => false
|
|
79
|
+
* ```;
|
|
80
|
+
*
|
|
81
|
+
* @param a - First version (string or parsed object)
|
|
82
|
+
* @param b - Second version (string or parsed object)
|
|
83
|
+
* @returns True if a > b, false otherwise
|
|
84
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
85
|
+
*/
|
|
86
|
+
export declare function gt(a: string | Hl7Version, b: string | Hl7Version): boolean;
|
|
87
|
+
/**
|
|
88
|
+
* Checks if first version is greater than or equal to second version.
|
|
89
|
+
*
|
|
90
|
+
* @example
|
|
91
|
+
* ```typescript
|
|
92
|
+
* gte("2.5.1", "2.3.0"); // => true
|
|
93
|
+
* gte("2.5.1", "2.5.1"); // => true
|
|
94
|
+
* gte("2.3.0", "2.5.1"); // => false
|
|
95
|
+
* ```;
|
|
96
|
+
*
|
|
97
|
+
* @param a - First version (string or parsed object)
|
|
98
|
+
* @param b - Second version (string or parsed object)
|
|
99
|
+
* @returns True if a >= b, false otherwise
|
|
100
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
101
|
+
*/
|
|
102
|
+
export declare function gte(a: string | Hl7Version, b: string | Hl7Version): boolean;
|
|
103
|
+
/**
|
|
104
|
+
* Determines the highest-level component that differs between two versions.
|
|
105
|
+
*
|
|
106
|
+
* @example
|
|
107
|
+
* ```typescript
|
|
108
|
+
* diff("2.5.1", "3.0.0"); // => "major"
|
|
109
|
+
* diff("2.5.1", "2.6.0"); // => "minor"
|
|
110
|
+
* diff("2.5.1", "2.5.2"); // => "patch"
|
|
111
|
+
* diff("2.5.1", "2.5.1"); // => null (equal)
|
|
112
|
+
*
|
|
113
|
+
* // Works with partial versions
|
|
114
|
+
* diff("2", "2.0.0"); // => null (normalized to same)
|
|
115
|
+
* diff("2.5", "2.6"); // => "minor"
|
|
116
|
+
* ```;
|
|
117
|
+
*
|
|
118
|
+
* @param v1 - First version (string or parsed object)
|
|
119
|
+
* @param v2 - Second version (string or parsed object)
|
|
120
|
+
* @returns 'major', 'minor', 'patch', or null if versions are equal
|
|
121
|
+
* @throws {VersionParseError} If either input is an invalid version string
|
|
122
|
+
*/
|
|
123
|
+
export declare function diff(v1: string | Hl7Version, v2: string | Hl7Version): "major" | "minor" | "patch" | null;
|
|
124
|
+
//# sourceMappingURL=compare.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"compare.d.ts","sourceRoot":"","sources":["../src/compare.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,gBAAgB,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC;AAE5D;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,OAAO,CACrB,CAAC,EAAE,MAAM,GAAG,UAAU,EACtB,CAAC,EAAE,MAAM,GAAG,UAAU,GACrB,gBAAgB,CAWlB;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAE1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAE1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAE3E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,EAAE,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAE1E;AAED;;;;;;;;;;;;;;GAcG;AACH,wBAAgB,GAAG,CAAC,CAAC,EAAE,MAAM,GAAG,UAAU,EAAE,CAAC,EAAE,MAAM,GAAG,UAAU,GAAG,OAAO,CAE3E;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,wBAAgB,IAAI,CAClB,EAAE,EAAE,MAAM,GAAG,UAAU,EACvB,EAAE,EAAE,MAAM,GAAG,UAAU,GACtB,OAAO,GAAG,OAAO,GAAG,OAAO,GAAG,IAAI,CAcpC"}
|
package/dist/errors.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Error thrown when a version string cannot be parsed.
|
|
3
|
+
*/
|
|
4
|
+
export declare class VersionParseError extends Error {
|
|
5
|
+
readonly name = "VersionParseError";
|
|
6
|
+
readonly input: string;
|
|
7
|
+
readonly reason: string;
|
|
8
|
+
constructor(input: string, reason: string);
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* Error thrown when a range token cannot be parsed.
|
|
12
|
+
*/
|
|
13
|
+
export declare class RangeParseError extends Error {
|
|
14
|
+
readonly name = "RangeParseError";
|
|
15
|
+
readonly token: string;
|
|
16
|
+
readonly reason: string;
|
|
17
|
+
constructor(token: string, reason: string);
|
|
18
|
+
}
|
|
19
|
+
//# sourceMappingURL=errors.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../src/errors.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,qBAAa,iBAAkB,SAAQ,KAAK;IAC1C,SAAkB,IAAI,uBAAuB;IAC7C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAW1C;AAED;;GAEG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,SAAkB,IAAI,qBAAqB;IAC3C,QAAQ,CAAC,KAAK,EAAE,MAAM,CAAC;IACvB,QAAQ,CAAC,MAAM,EAAE,MAAM,CAAC;gBAEZ,KAAK,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;CAW1C"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/** Biome-ignore-all lint/performance/noBarrelFile: fine */
|
|
2
|
+
export { maxSatisfying, minSatisfying, sort } from "./collection";
|
|
3
|
+
export { compare, diff, eq, gt, gte, lt, lte } from "./compare";
|
|
4
|
+
export { RangeParseError, VersionParseError } from "./errors";
|
|
5
|
+
export { clean, increment, parse, valid } from "./parse";
|
|
6
|
+
export { Range, satisfies } from "./range";
|
|
7
|
+
export type { Hl7Version } from "./types";
|
|
8
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,2DAA2D;AAG3D,OAAO,EAAE,aAAa,EAAE,aAAa,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AAElE,OAAO,EAAE,OAAO,EAAE,IAAI,EAAE,EAAE,EAAE,EAAE,EAAE,GAAG,EAAE,EAAE,EAAE,GAAG,EAAE,MAAM,WAAW,CAAC;AAEhE,OAAO,EAAE,eAAe,EAAE,iBAAiB,EAAE,MAAM,UAAU,CAAC;AAE9D,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,KAAK,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAGzD,OAAO,EAAE,KAAK,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAE3C,YAAY,EAAE,UAAU,EAAE,MAAM,SAAS,CAAC"}
|