@csaf-rs/vers-like-specifier 0.1.2 → 0.1.3
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/README.md +22 -9
- package/package.json +1 -1
- package/vers_like_specifier.d.ts +55 -27
- package/vers_like_specifier.js +57 -22
- package/vers_like_specifier_bg.wasm +0 -0
package/README.md
CHANGED
|
@@ -3,13 +3,13 @@
|
|
|
3
3
|
[](https://crates.io/crates/vers-like-specifier)
|
|
4
4
|
[](https://www.npmjs.com/package/@csaf-rs/vers-like-specifier)
|
|
5
5
|
|
|
6
|
-
A Rust library for parsing and validating **
|
|
6
|
+
A Rust library for parsing and validating **VERS-like Specifiers** (vls) as defined in [CSAF 2.0](https://docs.oasis-open.org/csaf/csaf/v2.0/os/csaf-v2.0-os.html#31232-branches-type---name-under-product-version-range) and [CSAF 2.1](https://docs.oasis-open.org/csaf/csaf/v2.1/csaf-v2.1.html#branches-type---name-under-product-version-range).
|
|
7
7
|
|
|
8
|
-
|
|
8
|
+
VERS-like specifier is the `<constraints>` portion of a [VERS](https://github.com/package-url/vers-spec) URL **without** the `vers:<type>/` prefix.
|
|
9
9
|
|
|
10
10
|
It represents a `|`-separated list of constraints each consisting of an implicit or explicit comparator and a version string.
|
|
11
11
|
|
|
12
|
-
**Due to the undefined / unknown
|
|
12
|
+
**Due to the undefined / unknown VERS type, it is nearly impossible for tools to reliably determine whether a given version is in the range or not. vls is a fallback option and SHOULD NOT be used unless really necessary.**
|
|
13
13
|
|
|
14
14
|
## Minimum Supported Rust Version (MSRV)
|
|
15
15
|
|
|
@@ -27,7 +27,7 @@ vers-like-specifier = "0.1"
|
|
|
27
27
|
## Usage
|
|
28
28
|
|
|
29
29
|
```rust
|
|
30
|
-
use vers_like_specifier::{Vls, Comparator};
|
|
30
|
+
use vers_like_specifier::{Vls, Comparator, Containment};
|
|
31
31
|
|
|
32
32
|
let vls: Vls = ">=1.0.0|<2.0.0".parse().unwrap();
|
|
33
33
|
assert_eq!(vls.constraints().len(), 2);
|
|
@@ -39,28 +39,41 @@ assert_eq!(constraints[0].comparator(), &Comparator::GreaterThanOrEqual);
|
|
|
39
39
|
assert_eq!(constraints[0].version().to_string(), "1.0.0");
|
|
40
40
|
assert_eq!(constraints[1].comparator(), &Comparator::LessThan);
|
|
41
41
|
assert_eq!(constraints[1].version().to_string(), "2.0.0");
|
|
42
|
+
|
|
43
|
+
// Because the VERS type is unknown, `contains` can only resolve a definite
|
|
44
|
+
// answer when a version exactly matches a constraint; otherwise it is `Undetermined`.
|
|
45
|
+
assert_eq!(vls.contains("1.0.0"), Containment::Contained);
|
|
46
|
+
assert_eq!(vls.contains("2.0.0"), Containment::NotContained);
|
|
47
|
+
assert_eq!(vls.contains("1.5.0"), Containment::Undetermined);
|
|
48
|
+
|
|
49
|
+
// The one exception: a vls pinning a single version is always decidable, since
|
|
50
|
+
// containment then reduces to a plain string comparison.
|
|
51
|
+
let pinned: Vls = "1.0.0".parse().unwrap();
|
|
52
|
+
assert_eq!(pinned.contains("1.0.0"), Containment::Contained);
|
|
53
|
+
assert_eq!(pinned.contains("2.0.0"), Containment::NotContained);
|
|
42
54
|
```
|
|
43
55
|
|
|
44
56
|
### JavaScript / WASM Usage
|
|
45
57
|
|
|
46
58
|
```js
|
|
47
|
-
import init, { Vls, Constraint, Comparator } from "@csaf-rs/vers-like-specifier";
|
|
59
|
+
import init, { Vls, Constraint, Comparator, Containment } from "@csaf-rs/vers-like-specifier";
|
|
48
60
|
|
|
49
61
|
await init();
|
|
50
62
|
|
|
51
63
|
const vls = Vls.parse(">=1.0.0|<2.0.0");
|
|
52
64
|
console.log(vls.isSingleVersion()); // false
|
|
53
65
|
|
|
54
|
-
const single = Vls.parse("=1.0.0");
|
|
55
|
-
console.log(single.isSingleVersion()); // true
|
|
56
|
-
|
|
57
66
|
const constraint = new Constraint(Comparator.GreaterThanOrEqual, "1.0.0");
|
|
58
67
|
console.log(constraint.version); // "1.0.0"
|
|
59
68
|
|
|
69
|
+
console.log(vls.contains("1.0.0") === Containment.Contained); // true (matches the >= constraint exactly)
|
|
70
|
+
console.log(vls.contains("2.0.0") === Containment.NotContained); // true (2.0.0 < 2.0.0 is always false)
|
|
71
|
+
console.log(vls.contains("1.5.0") === Containment.Undetermined); // true (can't be resolved; VERS type is unknown)
|
|
72
|
+
|
|
60
73
|
try {
|
|
61
74
|
Vls.parse("*");
|
|
62
75
|
} catch (e) {
|
|
63
|
-
console.error(e); // Error: '*' (
|
|
76
|
+
console.error(e); // Error: '*' (VERS syntax for matching all versions) is not allowed as a vls string
|
|
64
77
|
}
|
|
65
78
|
```
|
|
66
79
|
|
package/package.json
CHANGED
package/vers_like_specifier.d.ts
CHANGED
|
@@ -16,7 +16,7 @@ export type ConstraintError = "EmptyConstraint" | "EmptyConstraintVersion" | { I
|
|
|
16
16
|
/**
|
|
17
17
|
* Errors that can occur when parsing a vls string.
|
|
18
18
|
*/
|
|
19
|
-
export type VlsError = "EmptyInput" | "ForbiddenAnyUsed" | { InvalidCharacters: string[] } |
|
|
19
|
+
export type VlsError = "EmptyInput" | "ForbiddenAnyUsed" | { InvalidCharacters: string[] } | { InvalidConstraints: ConstraintError[] } | { DuplicateConstraintVersions: string[] } | { Serialization: string };
|
|
20
20
|
|
|
21
21
|
|
|
22
22
|
/**
|
|
@@ -79,9 +79,47 @@ export class Constraint {
|
|
|
79
79
|
}
|
|
80
80
|
|
|
81
81
|
/**
|
|
82
|
-
*
|
|
82
|
+
* The result of a containment check performed by [`Vls::contains`].
|
|
83
|
+
*
|
|
84
|
+
* Because the VERS type of a [`Vls`] is unspecified, containment can usually only be
|
|
85
|
+
* resolved when the queried version exactly matches a constraint's version:
|
|
86
|
+
*
|
|
87
|
+
* * [`Comparator::Equal`], [`Comparator::GreaterThanOrEqual`], [`Comparator::LessThanOrEqual`]:
|
|
88
|
+
* an exact match means the version is contained (`x = x`, `x >= x`, `x <= x` all hold) →
|
|
89
|
+
* [`Containment::Contained`].
|
|
90
|
+
* * [`Comparator::NotEqual`], [`Comparator::LessThan`], [`Comparator::GreaterThan`]:
|
|
91
|
+
* an exact match means the version is explicitly not contained (`x != x`, `x < x`, `x > x`
|
|
92
|
+
* are always false) → [`Containment::NotContained`].
|
|
93
|
+
* * No constraint's version matches exactly: containment cannot be resolved, as the VERS
|
|
94
|
+
* type is unknown / unspecified → [`Containment::Undetermined`].
|
|
95
|
+
*
|
|
96
|
+
* The one exception is a [`Vls`] that pins a single version (see [`Vls::is_single_version`]):
|
|
97
|
+
* since it has exactly one [`Comparator::Equal`] constraint, containment reduces to a plain
|
|
98
|
+
* string comparison and is always decidable, regardless of VERS type. In that case,
|
|
99
|
+
* *any* queried version resolves to either [`Containment::Contained`] or
|
|
100
|
+
* [`Containment::NotContained`], never [`Containment::Undetermined`].
|
|
101
|
+
*/
|
|
102
|
+
export enum Containment {
|
|
103
|
+
/**
|
|
104
|
+
* The version is contained in the specifier.
|
|
105
|
+
*/
|
|
106
|
+
Contained = 0,
|
|
107
|
+
/**
|
|
108
|
+
* The version is explicitly not contained in the specifier.
|
|
109
|
+
*/
|
|
110
|
+
NotContained = 1,
|
|
111
|
+
/**
|
|
112
|
+
* Containment could not be determined: the version does not exactly match any
|
|
113
|
+
* constraint, and the (unspecified) VERS type does not allow any further
|
|
114
|
+
* comparison.
|
|
115
|
+
*/
|
|
116
|
+
Undetermined = 2,
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
/**
|
|
120
|
+
* A **VERS-like specifier** (vls).
|
|
83
121
|
*
|
|
84
|
-
*
|
|
122
|
+
* vls is the `<constraints>` part of a [VERS](https://github.com/package-url/vers-spec)
|
|
85
123
|
* URL *without* the `vers:<type>/` prefix.
|
|
86
124
|
*
|
|
87
125
|
* It is an ordered, `|`-separated list of [`Constraint`] values.
|
|
@@ -93,30 +131,14 @@ export class Constraint {
|
|
|
93
131
|
*
|
|
94
132
|
* # Syntax
|
|
95
133
|
*
|
|
96
|
-
* Derived from the [
|
|
134
|
+
* Derived from the [VERS specification](https://www.packageurl.org/docs/vers/how-to-parse),
|
|
97
135
|
* its comments in
|
|
98
136
|
* [CSAF 2.0](https://docs.oasis-open.org/csaf/csaf/v2.0/os/csaf-v2.0-os.html#31232-branches-type---name-under-product-version-range)
|
|
99
137
|
* and
|
|
100
138
|
* [CSAF 2.1](https://docs.oasis-open.org/csaf/csaf/v2.1/csaf-v2.1.html#branches-type---name-under-product-version-range).
|
|
101
139
|
*
|
|
102
|
-
* There currently is no "official" grammar for
|
|
103
|
-
*
|
|
104
|
-
*
|
|
105
|
-
* **Note:** This grammar may need to be updated once vers has been ratified through ECMA / following changes
|
|
106
|
-
* to / clarifications of CSAF 2.0 or CSAF 2.1.
|
|
107
|
-
*
|
|
108
|
-
* ```text
|
|
109
|
-
* vls = constraint *( "|" constraint )
|
|
110
|
-
* constraint = comparator version-string / version-string
|
|
111
|
-
* comparator = "!=" / "<=" / ">=" / "<" / ">"
|
|
112
|
-
* version-string = 1*( ALPHA / DIGIT / "-" / "." / "_" / "+" / "~" )
|
|
113
|
-
* ```
|
|
114
|
-
*
|
|
115
|
-
* For validation, this leads to two sets of characters allowed in the context of the grammar.
|
|
116
|
-
*
|
|
117
|
-
* For `constraints`: `ALPHA / DIGIT / "-" / "." / "_" / "+" / "~" / "=" / "!" / "<" / ">" / "|"`
|
|
118
|
-
*
|
|
119
|
-
* For `version-string`: `ALPHA / DIGIT / "-" / "." / "_" / "+" / "~"`
|
|
140
|
+
* There currently is no "official" grammar for VERS-like specifier / the `<constraints>` part of
|
|
141
|
+
* VERS. This is a best-effort attempt used for this library.
|
|
120
142
|
*
|
|
121
143
|
* # Examples
|
|
122
144
|
*
|
|
@@ -135,6 +157,11 @@ export class Vls {
|
|
|
135
157
|
private constructor();
|
|
136
158
|
free(): void;
|
|
137
159
|
[Symbol.dispose](): void;
|
|
160
|
+
/**
|
|
161
|
+
* Return the [`Containment`] of the given `version` in this specifier, exposed as the
|
|
162
|
+
* instance method `vls.contains(version)` in JS.
|
|
163
|
+
*/
|
|
164
|
+
contains(version: string): Containment;
|
|
138
165
|
/**
|
|
139
166
|
* Return `true` if this specifier pins exactly one version, exposed as the
|
|
140
167
|
* instance method `vls.isSingleVersion()` in JS.
|
|
@@ -144,7 +171,7 @@ export class Vls {
|
|
|
144
171
|
* Parse a `vls` as a [`Vls`] string, exposed as the static `Vls.parse(vls)` in JS.
|
|
145
172
|
*
|
|
146
173
|
* # Errors
|
|
147
|
-
* Throws a JS `Error` if `vls` is not a valid
|
|
174
|
+
* Throws a JS `Error` if `vls` is not a valid VERS-like specifier.
|
|
148
175
|
*/
|
|
149
176
|
static parse(vls: string): Vls;
|
|
150
177
|
}
|
|
@@ -158,14 +185,15 @@ export type InitInput = RequestInfo | URL | Response | BufferSource | WebAssembl
|
|
|
158
185
|
|
|
159
186
|
export interface InitOutput {
|
|
160
187
|
readonly memory: WebAssembly.Memory;
|
|
161
|
-
readonly
|
|
188
|
+
readonly init: () => void;
|
|
162
189
|
readonly __wbg_vls_free: (a: number, b: number) => void;
|
|
190
|
+
readonly vls_contains: (a: number, b: number, c: number) => number;
|
|
191
|
+
readonly vls_isSingleVersion: (a: number) => number;
|
|
192
|
+
readonly vls_parse: (a: number, b: number) => [number, number, number];
|
|
193
|
+
readonly __wbg_constraint_free: (a: number, b: number) => void;
|
|
163
194
|
readonly constraint_comparator: (a: number) => number;
|
|
164
195
|
readonly constraint_version: (a: number) => [number, number];
|
|
165
196
|
readonly constraint_wasm_new: (a: number, b: number, c: number) => [number, number, number];
|
|
166
|
-
readonly vls_isSingleVersion: (a: number) => number;
|
|
167
|
-
readonly vls_parse: (a: number, b: number) => [number, number, number];
|
|
168
|
-
readonly init: () => void;
|
|
169
197
|
readonly __wbindgen_free: (a: number, b: number, c: number) => void;
|
|
170
198
|
readonly __wbindgen_malloc: (a: number, b: number) => number;
|
|
171
199
|
readonly __wbindgen_realloc: (a: number, b: number, c: number, d: number) => number;
|
package/vers_like_specifier.js
CHANGED
|
@@ -98,9 +98,48 @@ export class Constraint {
|
|
|
98
98
|
if (Symbol.dispose) Constraint.prototype[Symbol.dispose] = Constraint.prototype.free;
|
|
99
99
|
|
|
100
100
|
/**
|
|
101
|
-
*
|
|
101
|
+
* The result of a containment check performed by [`Vls::contains`].
|
|
102
102
|
*
|
|
103
|
-
*
|
|
103
|
+
* Because the VERS type of a [`Vls`] is unspecified, containment can usually only be
|
|
104
|
+
* resolved when the queried version exactly matches a constraint's version:
|
|
105
|
+
*
|
|
106
|
+
* * [`Comparator::Equal`], [`Comparator::GreaterThanOrEqual`], [`Comparator::LessThanOrEqual`]:
|
|
107
|
+
* an exact match means the version is contained (`x = x`, `x >= x`, `x <= x` all hold) →
|
|
108
|
+
* [`Containment::Contained`].
|
|
109
|
+
* * [`Comparator::NotEqual`], [`Comparator::LessThan`], [`Comparator::GreaterThan`]:
|
|
110
|
+
* an exact match means the version is explicitly not contained (`x != x`, `x < x`, `x > x`
|
|
111
|
+
* are always false) → [`Containment::NotContained`].
|
|
112
|
+
* * No constraint's version matches exactly: containment cannot be resolved, as the VERS
|
|
113
|
+
* type is unknown / unspecified → [`Containment::Undetermined`].
|
|
114
|
+
*
|
|
115
|
+
* The one exception is a [`Vls`] that pins a single version (see [`Vls::is_single_version`]):
|
|
116
|
+
* since it has exactly one [`Comparator::Equal`] constraint, containment reduces to a plain
|
|
117
|
+
* string comparison and is always decidable, regardless of VERS type. In that case,
|
|
118
|
+
* *any* queried version resolves to either [`Containment::Contained`] or
|
|
119
|
+
* [`Containment::NotContained`], never [`Containment::Undetermined`].
|
|
120
|
+
* @enum {0 | 1 | 2}
|
|
121
|
+
*/
|
|
122
|
+
export const Containment = Object.freeze({
|
|
123
|
+
/**
|
|
124
|
+
* The version is contained in the specifier.
|
|
125
|
+
*/
|
|
126
|
+
Contained: 0, "0": "Contained",
|
|
127
|
+
/**
|
|
128
|
+
* The version is explicitly not contained in the specifier.
|
|
129
|
+
*/
|
|
130
|
+
NotContained: 1, "1": "NotContained",
|
|
131
|
+
/**
|
|
132
|
+
* Containment could not be determined: the version does not exactly match any
|
|
133
|
+
* constraint, and the (unspecified) VERS type does not allow any further
|
|
134
|
+
* comparison.
|
|
135
|
+
*/
|
|
136
|
+
Undetermined: 2, "2": "Undetermined",
|
|
137
|
+
});
|
|
138
|
+
|
|
139
|
+
/**
|
|
140
|
+
* A **VERS-like specifier** (vls).
|
|
141
|
+
*
|
|
142
|
+
* vls is the `<constraints>` part of a [VERS](https://github.com/package-url/vers-spec)
|
|
104
143
|
* URL *without* the `vers:<type>/` prefix.
|
|
105
144
|
*
|
|
106
145
|
* It is an ordered, `|`-separated list of [`Constraint`] values.
|
|
@@ -112,30 +151,14 @@ if (Symbol.dispose) Constraint.prototype[Symbol.dispose] = Constraint.prototype.
|
|
|
112
151
|
*
|
|
113
152
|
* # Syntax
|
|
114
153
|
*
|
|
115
|
-
* Derived from the [
|
|
154
|
+
* Derived from the [VERS specification](https://www.packageurl.org/docs/vers/how-to-parse),
|
|
116
155
|
* its comments in
|
|
117
156
|
* [CSAF 2.0](https://docs.oasis-open.org/csaf/csaf/v2.0/os/csaf-v2.0-os.html#31232-branches-type---name-under-product-version-range)
|
|
118
157
|
* and
|
|
119
158
|
* [CSAF 2.1](https://docs.oasis-open.org/csaf/csaf/v2.1/csaf-v2.1.html#branches-type---name-under-product-version-range).
|
|
120
159
|
*
|
|
121
|
-
* There currently is no "official" grammar for
|
|
122
|
-
*
|
|
123
|
-
*
|
|
124
|
-
* **Note:** This grammar may need to be updated once vers has been ratified through ECMA / following changes
|
|
125
|
-
* to / clarifications of CSAF 2.0 or CSAF 2.1.
|
|
126
|
-
*
|
|
127
|
-
* ```text
|
|
128
|
-
* vls = constraint *( "|" constraint )
|
|
129
|
-
* constraint = comparator version-string / version-string
|
|
130
|
-
* comparator = "!=" / "<=" / ">=" / "<" / ">"
|
|
131
|
-
* version-string = 1*( ALPHA / DIGIT / "-" / "." / "_" / "+" / "~" )
|
|
132
|
-
* ```
|
|
133
|
-
*
|
|
134
|
-
* For validation, this leads to two sets of characters allowed in the context of the grammar.
|
|
135
|
-
*
|
|
136
|
-
* For `constraints`: `ALPHA / DIGIT / "-" / "." / "_" / "+" / "~" / "=" / "!" / "<" / ">" / "|"`
|
|
137
|
-
*
|
|
138
|
-
* For `version-string`: `ALPHA / DIGIT / "-" / "." / "_" / "+" / "~"`
|
|
160
|
+
* There currently is no "official" grammar for VERS-like specifier / the `<constraints>` part of
|
|
161
|
+
* VERS. This is a best-effort attempt used for this library.
|
|
139
162
|
*
|
|
140
163
|
* # Examples
|
|
141
164
|
*
|
|
@@ -168,6 +191,18 @@ export class Vls {
|
|
|
168
191
|
const ptr = this.__destroy_into_raw();
|
|
169
192
|
wasm.__wbg_vls_free(ptr, 0);
|
|
170
193
|
}
|
|
194
|
+
/**
|
|
195
|
+
* Return the [`Containment`] of the given `version` in this specifier, exposed as the
|
|
196
|
+
* instance method `vls.contains(version)` in JS.
|
|
197
|
+
* @param {string} version
|
|
198
|
+
* @returns {Containment}
|
|
199
|
+
*/
|
|
200
|
+
contains(version) {
|
|
201
|
+
const ptr0 = passStringToWasm0(version, wasm.__wbindgen_malloc, wasm.__wbindgen_realloc);
|
|
202
|
+
const len0 = WASM_VECTOR_LEN;
|
|
203
|
+
const ret = wasm.vls_contains(this.__wbg_ptr, ptr0, len0);
|
|
204
|
+
return ret;
|
|
205
|
+
}
|
|
171
206
|
/**
|
|
172
207
|
* Return `true` if this specifier pins exactly one version, exposed as the
|
|
173
208
|
* instance method `vls.isSingleVersion()` in JS.
|
|
@@ -181,7 +216,7 @@ export class Vls {
|
|
|
181
216
|
* Parse a `vls` as a [`Vls`] string, exposed as the static `Vls.parse(vls)` in JS.
|
|
182
217
|
*
|
|
183
218
|
* # Errors
|
|
184
|
-
* Throws a JS `Error` if `vls` is not a valid
|
|
219
|
+
* Throws a JS `Error` if `vls` is not a valid VERS-like specifier.
|
|
185
220
|
* @param {string} vls
|
|
186
221
|
* @returns {Vls}
|
|
187
222
|
*/
|
|
Binary file
|