Skip to content

Commit 55f04a4

Browse files
committed
feat(validateStrict): validate according to semver
1 parent bccab06 commit 55f04a4

4 files changed

Lines changed: 128 additions & 2 deletions

File tree

README.md

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -102,6 +102,20 @@ validate('1.0-rc.1'); // false
102102
validate('foo'); // false
103103
```
104104

105+
### Validate version numbers (strict)
106+
107+
Validate version numbers strictly according to semver.org; 3 integers, no wildcards, no leading zero or "v" etc:
108+
109+
```js
110+
import { validateStrict } from 'compare-versions';
111+
112+
validate('1.0.0'); // true
113+
validate('1.0.0-rc.1'); // true
114+
validate('1.0'); // false
115+
validate('1.x'); // false
116+
validate('v1.02'); // false
117+
```
118+
105119
### Browser
106120

107121
If included directly in the browser, the functions above are available on the global window under the `compareVersions` object:
@@ -114,5 +128,6 @@ If included directly in the browser, the functions above are available on the gl
114128
console.log(compare('11.0.0', '10.0.0', '>'))
115129
console.log(satisfies('1.2.0', '^1.0.0'))
116130
console.log(validate('11.0.0'))
131+
console.log(validateStrict('11.0.0'))
117132
</script>
118133
```

src/index.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,4 +2,4 @@ export { compare } from './compare';
22
export { compareVersions } from './compareVersions';
33
export { satisfies } from './satisfies';
44
export { CompareOperator } from './utils';
5-
export { validate } from './validate';
5+
export { validate, validateStrict } from './validate';

src/validate.ts

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,3 +15,22 @@ import { semver } from './utils';
1515
*/
1616
export const validate = (version: string) =>
1717
typeof version === 'string' && /^[v\d]/.test(version) && semver.test(version);
18+
19+
/**
20+
* Validate [semver](https://semver.org/) version strings strictly. Will not accept wildcards and version ranges.
21+
*
22+
* @param version Version number to validate
23+
* @returns `true` if the version number is a valid semver version number `false` otherwise
24+
*
25+
* @example
26+
* ```
27+
* validate('1.0.0-rc.1'); // return true
28+
* validate('1.0-rc.1'); // return false
29+
* validate('foo'); // return false
30+
* ```
31+
*/
32+
export const validateStrict = (version: string) =>
33+
typeof version === 'string' &&
34+
/^(0|[1-9]\d*)\.(0|[1-9]\d*)\.(0|[1-9]\d*)(?:-((?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(?:0|[1-9]\d*|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?(?:\+([0-9a-zA-Z-]+(?:\.[0-9a-zA-Z-]+)*))?$/.test(
35+
version
36+
);

test/validate.ts

Lines changed: 93 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import assert from 'assert';
2-
import { validate } from '../src/index';
2+
import { validate, validateStrict } from '../src/index';
33

44
describe('validate versions', () => {
55
(
@@ -32,3 +32,95 @@ describe('validate versions', () => {
3232
});
3333
});
3434
});
35+
36+
describe('validateStrict - https://regex101.com/r/vkijKf/1/', () => {
37+
describe('valid', () => {
38+
[
39+
'0.0.4',
40+
'1.2.3',
41+
'10.20.30',
42+
'1.1.2-prerelease+meta',
43+
'1.1.2+meta',
44+
'1.1.2+meta-valid',
45+
'1.0.0-alpha',
46+
'1.0.0-beta',
47+
'1.0.0-alpha.beta',
48+
'1.0.0-alpha.beta.1',
49+
'1.0.0-alpha.1',
50+
'1.0.0-alpha0.valid',
51+
'1.0.0-alpha.0valid',
52+
'1.0.0-alpha-a.b-c-somethinglong+build.1-aef.1-its-okay',
53+
'1.0.0-rc.1+build.1',
54+
'2.0.0-rc.1+build.123',
55+
'1.2.3-beta',
56+
'10.2.3-DEV-SNAPSHOT',
57+
'1.2.3-SNAPSHOT-123',
58+
'1.0.0',
59+
'2.0.0',
60+
'1.1.7',
61+
'2.0.0+build.1848',
62+
'2.0.1-alpha.1227',
63+
'1.0.0-alpha+beta',
64+
'1.2.3----RC-SNAPSHOT.12.9.1--.12+788',
65+
'1.2.3----R-S.12.9.1--.12+meta',
66+
'1.2.3----RC-SNAPSHOT.12.9.1--.12',
67+
'1.0.0+0.build.1-rc.10000aaa-kk-0.1',
68+
'99999999999999999999999.999999999999999999.99999999999999999',
69+
'1.0.0-0A.is.legal',
70+
].forEach((v) => {
71+
it(`${v}`, () => {
72+
assert.equal(validateStrict(v), true);
73+
});
74+
});
75+
});
76+
77+
describe('invalid', () => {
78+
[
79+
'1',
80+
'1.2',
81+
'1.2.3-0123',
82+
'1.2.3-0123.0123',
83+
'1.1.2+.123',
84+
'+invalid',
85+
'-invalid',
86+
'-invalid+invalid',
87+
'-invalid.01',
88+
'alpha',
89+
'alpha.beta',
90+
'alpha.beta.1',
91+
'alpha.1',
92+
'alpha+beta',
93+
'alpha_beta',
94+
'alpha.',
95+
'alpha..',
96+
'beta',
97+
'1.0.0-alpha_beta',
98+
'-alpha.',
99+
'1.0.0-alpha..',
100+
'1.0.0-alpha..1',
101+
'1.0.0-alpha...1',
102+
'1.0.0-alpha....1',
103+
'1.0.0-alpha.....1',
104+
'1.0.0-alpha......1',
105+
'1.0.0-alpha.......1',
106+
'01.1.1',
107+
'1.01.1',
108+
'1.1.01',
109+
'1.2',
110+
'1.2.3.DEV',
111+
'1.2-SNAPSHOT',
112+
'1.2.31.2.3----RC-SNAPSHOT.12.09.1--..12+788',
113+
'1.2-RC-SNAPSHOT',
114+
'-1.0.3-gamma+b7718',
115+
'+justmeta',
116+
'9.8.7+meta+meta',
117+
'9.8.7-whatever+meta+meta',
118+
'99999999999999999999999.999999999999999999.99999999999999999----RC-SNAPSHOT.12.09.1--------------------------------..',
119+
'12',
120+
].forEach((v) => {
121+
it(`${v}`, () => {
122+
assert.equal(validateStrict(v), false);
123+
});
124+
});
125+
});
126+
});

0 commit comments

Comments
 (0)