@jarenjs/validate 0.34.2 → 0.43.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/ARCHITECTURE.md +1 -1
- package/README.md +1 -1
- package/dist/types/tools.d.ts +16 -0
- package/package.json +3 -3
- package/src/schema.js +5 -16
- package/src/tools.js +36 -0
- package/src/traverse.js +12 -3
package/ARCHITECTURE.md
CHANGED
package/README.md
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# @jarenjs/validate
|
|
2
2
|
|
|
3
|
-
The JSON Schema validating compiler at the heart of [Jaren](https://github.com/jklarenbeek/jarenjs). It compiles JSON Schemas into optimized validation functions and fully supports `draft-06`, `draft-07`, `draft 2019-09` and `draft 2020-12` — passing
|
|
3
|
+
The JSON Schema validating compiler at the heart of [Jaren](https://github.com/jklarenbeek/jarenjs). It compiles JSON Schemas into optimized validation functions and fully supports `draft-06`, `draft-07`, `draft 2019-09` and `draft 2020-12` — passing the official [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite) for draft-07 and 2019-09 in full, and all of 2020-12 except the `$dynamicRef` cases the repository's roadmap names.
|
|
4
4
|
|
|
5
5
|
## Usage
|
|
6
6
|
|
package/dist/types/tools.d.ts
CHANGED
|
@@ -14,6 +14,22 @@ export declare function isOfSchemaType(schema: any, type: any): boolean;
|
|
|
14
14
|
export declare function hasSchemaRef(schema: any): boolean;
|
|
15
15
|
export declare function hasSchemaRecursiveRef(schema: any): boolean;
|
|
16
16
|
export declare function hasSchemaDynamicRef(schema: any): boolean;
|
|
17
|
+
/**
|
|
18
|
+
* The keywords that assert something beside a `$ref`: the siblings draft
|
|
19
|
+
* 2019-09+ applies alongside the reference and draft-07 ignores.
|
|
20
|
+
* Membership-only (order-insensitive): the shared constraint groups plus
|
|
21
|
+
* the applicators and extras. One list, read by the schema compiler (does
|
|
22
|
+
* this `$ref` carry siblings to compile?) and by the reference resolver
|
|
23
|
+
* (may this hop of a `$ref` chain be flattened away?).
|
|
24
|
+
*/
|
|
25
|
+
export declare const REF_SIBLING_KEYWORDS: readonly string[];
|
|
26
|
+
/**
|
|
27
|
+
* Whether a schema carrying a `$ref` also carries a keyword of
|
|
28
|
+
* {@link REF_SIBLING_KEYWORDS}.
|
|
29
|
+
* @param {object} schema
|
|
30
|
+
* @returns {boolean}
|
|
31
|
+
*/
|
|
32
|
+
export declare function hasRefSiblings(schema: object): boolean;
|
|
17
33
|
/**
|
|
18
34
|
* Whether a sibling keyword of unevaluatedProperties already evaluates every
|
|
19
35
|
* property of the instance. additionalProperties (boolean or schema) applies
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@jarenjs/validate",
|
|
3
3
|
"private": false,
|
|
4
|
-
"version": "0.
|
|
4
|
+
"version": "0.43.1",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./src/index.js",
|
|
7
7
|
"types": "./dist/types/index.d.ts",
|
|
@@ -55,7 +55,7 @@
|
|
|
55
55
|
"prepack": "npm run build:types"
|
|
56
56
|
},
|
|
57
57
|
"dependencies": {
|
|
58
|
-
"@jarenjs/core": "^0.
|
|
59
|
-
"@jarenjs/json": "^0.
|
|
58
|
+
"@jarenjs/core": "^0.43.1",
|
|
59
|
+
"@jarenjs/json": "^0.43.1"
|
|
60
60
|
}
|
|
61
61
|
}
|
package/src/schema.js
CHANGED
|
@@ -5,10 +5,6 @@ import {
|
|
|
5
5
|
getStringType,
|
|
6
6
|
isObjectClass,
|
|
7
7
|
} from '@jarenjs/core';
|
|
8
|
-
import {
|
|
9
|
-
NUMERIC_CONSTRAINTS, STRING_CONSTRAINTS,
|
|
10
|
-
ARRAY_CONSTRAINTS, OBJECT_CONSTRAINTS,
|
|
11
|
-
} from '@jarenjs/core/schema';
|
|
12
8
|
|
|
13
9
|
import {
|
|
14
10
|
getUniqueArray,
|
|
@@ -29,6 +25,7 @@ import {
|
|
|
29
25
|
hasSchemaRef,
|
|
30
26
|
hasSchemaRecursiveRef,
|
|
31
27
|
hasSchemaDynamicRef,
|
|
28
|
+
hasRefSiblings,
|
|
32
29
|
} from './tools.js';
|
|
33
30
|
|
|
34
31
|
import {
|
|
@@ -453,18 +450,10 @@ export function compileSchemaObject(schemaObj, jsonSchema) {
|
|
|
453
450
|
let refWithSiblings = false;
|
|
454
451
|
if (hasSchemaRef(jsonSchema) && !hasSchemaRecursiveRef(jsonSchema)) {
|
|
455
452
|
// Check if there are any validation-related sibling keywords
|
|
456
|
-
//
|
|
457
|
-
//
|
|
458
|
-
//
|
|
459
|
-
const
|
|
460
|
-
...NUMERIC_CONSTRAINTS, ...STRING_CONSTRAINTS,
|
|
461
|
-
...ARRAY_CONSTRAINTS, 'maxContains', 'minContains',
|
|
462
|
-
...OBJECT_CONSTRAINTS, 'required',
|
|
463
|
-
'dependentRequired', 'properties', 'patternProperties', 'additionalProperties', 'items',
|
|
464
|
-
'prefixItems', 'additionalItems', 'contains', 'allOf', 'anyOf', 'oneOf', 'not', 'if',
|
|
465
|
-
'then', 'else', 'propertyNames', 'contentEncoding', 'contentMediaType',
|
|
466
|
-
'unevaluatedProperties', 'unevaluatedItems', '$query'];
|
|
467
|
-
const hasValidationSiblings = keys.some(k => validationKeywords.includes(k));
|
|
453
|
+
// (REF_SIBLING_KEYWORDS — the one list the reference resolver reads
|
|
454
|
+
// too). In draft 2019-09+, if there are validation siblings, we
|
|
455
|
+
// process them together.
|
|
456
|
+
const hasValidationSiblings = hasRefSiblings(jsonSchema);
|
|
468
457
|
// In draft 7 and earlier, $ref always overrides siblings regardless
|
|
469
458
|
// In draft 2019-09+, $ref can have validation siblings
|
|
470
459
|
if (!hasValidationSiblings || draftVersion < 2019) {
|
package/src/tools.js
CHANGED
|
@@ -31,6 +31,11 @@ import {
|
|
|
31
31
|
JSONPOINTER_NOTHING,
|
|
32
32
|
} from '@jarenjs/json';
|
|
33
33
|
|
|
34
|
+
import {
|
|
35
|
+
NUMERIC_CONSTRAINTS, STRING_CONSTRAINTS,
|
|
36
|
+
ARRAY_CONSTRAINTS, OBJECT_CONSTRAINTS,
|
|
37
|
+
} from '@jarenjs/core/schema';
|
|
38
|
+
|
|
34
39
|
//#region Object
|
|
35
40
|
export function isBoolOrObjectClass(obj) {
|
|
36
41
|
return isBooleanType(obj)
|
|
@@ -85,6 +90,37 @@ export function hasSchemaDynamicRef(schema) {
|
|
|
85
90
|
&& !isStringWhiteSpace(schema.$dynamicRef);
|
|
86
91
|
}
|
|
87
92
|
|
|
93
|
+
/**
|
|
94
|
+
* The keywords that assert something beside a `$ref`: the siblings draft
|
|
95
|
+
* 2019-09+ applies alongside the reference and draft-07 ignores.
|
|
96
|
+
* Membership-only (order-insensitive): the shared constraint groups plus
|
|
97
|
+
* the applicators and extras. One list, read by the schema compiler (does
|
|
98
|
+
* this `$ref` carry siblings to compile?) and by the reference resolver
|
|
99
|
+
* (may this hop of a `$ref` chain be flattened away?).
|
|
100
|
+
*/
|
|
101
|
+
export const REF_SIBLING_KEYWORDS = Object.freeze(['type', 'const', 'enum',
|
|
102
|
+
...NUMERIC_CONSTRAINTS, ...STRING_CONSTRAINTS,
|
|
103
|
+
...ARRAY_CONSTRAINTS, 'maxContains', 'minContains',
|
|
104
|
+
...OBJECT_CONSTRAINTS, 'required',
|
|
105
|
+
'dependentRequired', 'properties', 'patternProperties', 'additionalProperties', 'items',
|
|
106
|
+
'prefixItems', 'additionalItems', 'contains', 'allOf', 'anyOf', 'oneOf', 'not', 'if',
|
|
107
|
+
'then', 'else', 'propertyNames', 'contentEncoding', 'contentMediaType',
|
|
108
|
+
'unevaluatedProperties', 'unevaluatedItems', '$query']);
|
|
109
|
+
|
|
110
|
+
/**
|
|
111
|
+
* Whether a schema carrying a `$ref` also carries a keyword of
|
|
112
|
+
* {@link REF_SIBLING_KEYWORDS}.
|
|
113
|
+
* @param {object} schema
|
|
114
|
+
* @returns {boolean}
|
|
115
|
+
*/
|
|
116
|
+
export function hasRefSiblings(schema) {
|
|
117
|
+
const keys = Object.keys(schema);
|
|
118
|
+
for (let i = 0; i < keys.length; i++) {
|
|
119
|
+
if (REF_SIBLING_KEYWORDS.includes(keys[i])) return true;
|
|
120
|
+
}
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
|
|
88
124
|
/**
|
|
89
125
|
* Whether a sibling keyword of unevaluatedProperties already evaluates every
|
|
90
126
|
* property of the instance. additionalProperties (boolean or schema) applies
|
package/src/traverse.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
isBoolOrObjectClass,
|
|
3
3
|
hasSchemaRef,
|
|
4
|
+
hasRefSiblings,
|
|
4
5
|
} from './tools.js';
|
|
5
6
|
|
|
6
7
|
import {
|
|
@@ -416,10 +417,18 @@ export function resolveRefSchemaDeep(schemas, baseUri, refschema, opts = new Tra
|
|
|
416
417
|
if (!isObjectClass(item))
|
|
417
418
|
return { id: base, schema: item };
|
|
418
419
|
|
|
419
|
-
//
|
|
420
|
-
//
|
|
421
|
-
//
|
|
420
|
+
// A pure `$ref` hop is flattened away: only the `$ref` is kept to
|
|
421
|
+
// resolve it, the other (annotation) keywords of this item are
|
|
422
|
+
// discarded. A target reached THROUGH the chain that asserts
|
|
423
|
+
// keywords beside its `$ref` is the end of what may be flattened:
|
|
424
|
+
// draft 2019-09+ applies those siblings alongside the reference, so
|
|
425
|
+
// collapsing the chain past them would drop assertions (an OpenAPI
|
|
426
|
+
// document schema is nothing but such hops). The item is kept as
|
|
427
|
+
// written and compiled as a schema object, where the resource's
|
|
428
|
+
// draft decides whether its siblings assert (draft-07 ignores them).
|
|
422
429
|
if (hasSchemaRef(item)) {
|
|
430
|
+
if (item !== refschema && hasRefSiblings(item))
|
|
431
|
+
return { id: base, schema: item };
|
|
423
432
|
const ref = item.$ref;
|
|
424
433
|
const { id, schema } = resolveRefSchemaShallow(schemas, ref, base, opts);
|
|
425
434
|
|