Skip to content

Commit cedaa77

Browse files
committed
feat: support 4-digit semver with j
1 parent 92196cc commit cedaa77

3 files changed

Lines changed: 50 additions & 0 deletions

File tree

packages/nodejs-lib/src/validation/ajv/j.validations.test.ts

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1255,6 +1255,41 @@ describe('string', () => {
12551255
})
12561256
})
12571257

1258+
describe('semVer4', () => {
1259+
test('should accept string with valid 4-part semver', () => {
1260+
const testCases = ['0.0.0.0', '1.2.3.4', '10.20.30.40']
1261+
const schema = j.string().semVer4()
1262+
1263+
testCases.forEach(semver => {
1264+
const [err] = schema.getValidationResult(semver)
1265+
expect(err, semver).toBeNull()
1266+
})
1267+
})
1268+
1269+
test('should reject string with invalid 4-part semver', () => {
1270+
const invalidCases: any[] = [
1271+
'', // empty
1272+
'1.2.3', // missing part
1273+
'1.2', // missing part
1274+
'1', // missing part
1275+
'1.2.3.4.5', // extra part
1276+
'1.2.3.', // trailing dot
1277+
'^1.2.3.4', // still not
1278+
'abcd', // text
1279+
0,
1280+
true,
1281+
[],
1282+
{},
1283+
]
1284+
const schema = j.string().semVer4()
1285+
1286+
invalidCases.forEach(semver => {
1287+
const [err] = schema.getValidationResult(semver)
1288+
expect(err, String(semver)).not.toBeNull()
1289+
})
1290+
})
1291+
})
1292+
12581293
describe('languageTag', () => {
12591294
test('should accept string with valid languageTag', () => {
12601295
const testCases = ['hu-HU', 'en-US', 'se-SE', 'se']

packages/nodejs-lib/src/validation/ajv/jSchema.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,7 @@ import {
3636
IPV4_REGEX,
3737
IPV6_REGEX,
3838
LANGUAGE_TAG_REGEX,
39+
SEMVER4_REGEX,
3940
SEMVER_REGEX,
4041
SLUG_REGEX,
4142
URL_REGEX,
@@ -831,10 +832,22 @@ export class JString<
831832
return this.regex(SLUG_REGEX, { msg: 'is not a valid slug format' })
832833
}
833834

835+
/**
836+
* Validates the 3-part semver format: `major.minor.patch`, e.g `1.2.3`.
837+
*/
834838
semVer(): this {
835839
return this.regex(SEMVER_REGEX, { msg: 'is not a valid semver format' })
836840
}
837841

842+
/**
843+
* Validates the 4-part version format: `major.minor.patch.build`, e.g `1.2.3.4`.
844+
*
845+
* Not a semver by the spec, but is used by e.g .NET and some mobile app versions.
846+
*/
847+
semVer4(): this {
848+
return this.regex(SEMVER4_REGEX, { msg: 'is not a valid 4-part semver format' })
849+
}
850+
838851
languageTag(): this {
839852
return this.regex(LANGUAGE_TAG_REGEX, { msg: 'is not a valid language format' })
840853
}

packages/nodejs-lib/src/validation/regexes.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@ export const IPV6_REGEX =
2323
export const LANGUAGE_TAG_REGEX = /^[a-z]{2}(-[A-Z]{2})?$/
2424
export const MAC_ADDRESS_REGEX = /^([0-9A-Fa-f]{2}[:-]){5}([0-9A-Fa-f]{2})$/
2525
export const SEMVER_REGEX = /^[0-9]+\.[0-9]+\.[0-9]+$/
26+
// 4-part version (major.minor.patch.build)
27+
export const SEMVER4_REGEX = /^[0-9]+\.[0-9]+\.[0-9]+\.[0-9]+$/
2628
export const SLUG_REGEX = /^[a-z0-9-]+$/
2729
// URL regex based on `ajv-formats`, but without flags for JSON Schema compatibility.
2830
// Uses [a-zA-Z] instead of [a-z] with i flag. Simplified to not require unicode flag.

0 commit comments

Comments
 (0)