@jarenjs/validate 0.8.4 → 0.9.2
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 +1067 -0
- package/LICENSE +21 -0
- package/README.md +339 -2
- package/dist/types/array.d.ts +2 -0
- package/dist/types/bigint.d.ts +1 -0
- package/dist/types/combine.d.ts +1 -0
- package/dist/types/condition.d.ts +1 -0
- package/dist/types/content.d.ts +3 -0
- package/dist/types/data.d.ts +7 -0
- package/dist/types/dollar-data.d.ts +20 -0
- package/dist/types/dynamic-ref.d.ts +44 -0
- package/dist/types/enum.d.ts +1 -0
- package/dist/types/format.d.ts +21 -0
- package/dist/types/index.d.ts +874 -0
- package/dist/types/number.d.ts +1 -0
- package/dist/types/object.d.ts +3 -0
- package/dist/types/query-keyword.d.ts +19 -0
- package/dist/types/query.d.ts +29 -0
- package/dist/types/schema.d.ts +1 -0
- package/dist/types/string.d.ts +1 -0
- package/dist/types/tools.d.ts +51 -0
- package/dist/types/traverse.d.ts +32 -0
- package/dist/types/unevaluated.d.ts +12 -0
- package/package.json +32 -7
- package/src/array.js +565 -0
- package/src/bigint.js +97 -0
- package/src/combine.js +226 -0
- package/src/condition.js +109 -0
- package/src/content.js +83 -0
- package/src/data.js +477 -0
- package/src/dollar-data.js +629 -0
- package/src/dynamic-ref.js +121 -0
- package/src/enum.js +148 -0
- package/src/format.js +66 -0
- package/src/index.js +1854 -0
- package/src/number.js +159 -0
- package/src/object.js +755 -0
- package/src/query-keyword.js +99 -0
- package/src/query.js +59 -0
- package/src/schema.js +645 -0
- package/src/string.js +152 -0
- package/src/tools.js +205 -0
- package/src/traverse.js +433 -0
- package/src/unevaluated.js +151 -0
- package/dist/index.js +0 -1998
- package/dist/index.js.map +0 -7
- package/dist/index.min.js +0 -2
- package/dist/index.min.js.map +0 -7
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2019 Joham
|
|
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
CHANGED
|
@@ -1,3 +1,340 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @jarenjs/validate
|
|
2
2
|
|
|
3
|
-
|
|
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 100% of the official [JSON-Schema-Test-Suite](https://github.com/json-schema-org/JSON-Schema-Test-Suite) for draft-07, 2019-09 and 2020-12.
|
|
4
|
+
|
|
5
|
+
## Usage
|
|
6
|
+
|
|
7
|
+
```javascript
|
|
8
|
+
import { JarenValidator } from '@jarenjs/validate';
|
|
9
|
+
|
|
10
|
+
const jaren = new JarenValidator();
|
|
11
|
+
|
|
12
|
+
const validate = jaren.compile({
|
|
13
|
+
type: 'object',
|
|
14
|
+
properties: {
|
|
15
|
+
name: { type: 'string' },
|
|
16
|
+
age: { type: 'integer', minimum: 0 }
|
|
17
|
+
},
|
|
18
|
+
required: ['name']
|
|
19
|
+
});
|
|
20
|
+
|
|
21
|
+
validate({ name: 'John', age: 30 }); // true
|
|
22
|
+
```
|
|
23
|
+
|
|
24
|
+
Key entry points:
|
|
25
|
+
|
|
26
|
+
- `new JarenValidator(options)` — create a validator instance
|
|
27
|
+
- `.addSchema(schema, key)` — register schemas for `$ref` resolution
|
|
28
|
+
- `.addMetaSchema(schemas, key)` — register (custom) meta-schemas, honoring `$vocabulary`
|
|
29
|
+
- `.addFormats(formats)` — register format validators (see [`@jarenjs/formats`](../formats))
|
|
30
|
+
- `.compile(schema)` — compile a schema into a validation function
|
|
31
|
+
|
|
32
|
+
Highlights:
|
|
33
|
+
|
|
34
|
+
- Annotation-based `unevaluatedProperties`/`unevaluatedItems`
|
|
35
|
+
- Spec-compliant dynamic scope for `$dynamicRef`/`$dynamicAnchor` and `$recursiveRef`/`$recursiveAnchor`
|
|
36
|
+
- Per-document draft handling for cross-draft references
|
|
37
|
+
- `$vocabulary`-aware keyword selection and per-draft `format`/content assertion defaults
|
|
38
|
+
- Instance-data references via the `data` keyword (json-everything data-ref) and Ajv-style `$data`
|
|
39
|
+
- Cross-field assertions via the `$query` extension keyword (a [Jaren JSON Query](../json/docs/QUERY-FORMAT.md) inside the schema)
|
|
40
|
+
|
|
41
|
+
## 🔑 JSON Schema validation keywords
|
|
42
|
+
|
|
43
|
+
Jaren supports the full set of JSON Schema validation keywords. Here's a quick overview:
|
|
44
|
+
|
|
45
|
+
- JSON data type: `type`, `nullable`, `required`
|
|
46
|
+
- Numbers: `maximum`, `minimum`, `multipleOf`
|
|
47
|
+
- Strings: `maxLength`, `minLength`, `pattern`
|
|
48
|
+
- Content: `contentEncoding`, `contentMediaType`
|
|
49
|
+
- Arrays: `maxItems`, `minItems`, `uniqueItems`, `items`, `prefixItems`, `contains`, `unevaluatedItems`
|
|
50
|
+
- Objects: `maxProperties`, `minProperties`, `required`, `properties`, `patternProperties`, `unevaluatedProperties`
|
|
51
|
+
- All types: `enum`, `const`
|
|
52
|
+
- Compound: `not`, `oneOf`, `anyOf`, `allOf`, `if/then/else`
|
|
53
|
+
- Meta: `$schema`, `$id`, `$ref`, `$anchor`, `$dynamicRef`/`$dynamicAnchor`, `$recursiveRef`/`$recursiveAnchor`, `$vocabulary`
|
|
54
|
+
- **Non-standard**: `data` (json-everything's [data-ref](https://docs.json-everything.net/schema/examples/data-ref/) proposal), Ajv-style `$data` references, and the [`$query` keyword](#query--cross-field-assertions) below
|
|
55
|
+
|
|
56
|
+
<details>
|
|
57
|
+
<summary>🔥 For a complete list of supported keywords and their implementation status, click here</summary>
|
|
58
|
+
|
|
59
|
+
### 🔑 JSON data type
|
|
60
|
+
|
|
61
|
+
- type
|
|
62
|
+
- nullable | _(OpenAPI)_
|
|
63
|
+
- required | _as boolean (OpenAPI)_
|
|
64
|
+
|
|
65
|
+
### 🔑 Keywords for numbers
|
|
66
|
+
|
|
67
|
+
- maximum / minimum<br />or exclusiveMaximum / exclusiveMinimum
|
|
68
|
+
- multipleOf
|
|
69
|
+
|
|
70
|
+
BigInt instance values are supported too: `maximum`/`minimum`/`exclusiveMaximum`/`exclusiveMinimum` and `multipleOf` compile dedicated BigInt comparators when the data is a `bigint`.
|
|
71
|
+
|
|
72
|
+
### 🔑 Keywords for strings
|
|
73
|
+
|
|
74
|
+
- maxLength / minLength
|
|
75
|
+
- pattern
|
|
76
|
+
|
|
77
|
+
### 🔑 Keywords for content
|
|
78
|
+
|
|
79
|
+
- contentEncoding | asserts in `draft7`, annotation-only from `draft2019` on (spec default), controlled by the `contentValidation` option
|
|
80
|
+
- contentMediaType | same assertion defaults; `application/json` content is parse-checked
|
|
81
|
+
- ❌ contentSchema | annotation only (never asserted)
|
|
82
|
+
|
|
83
|
+
### 🔑 Keywords for format
|
|
84
|
+
|
|
85
|
+
- format
|
|
86
|
+
- formatMinimum / formatMaximum<br />or formatExclusiveMinimum / formatExclusiveMaximum
|
|
87
|
+
|
|
88
|
+
### 🔑 Keywords for array
|
|
89
|
+
|
|
90
|
+
- maxItems / minItems
|
|
91
|
+
- uniqueItems
|
|
92
|
+
- items
|
|
93
|
+
- items | as schema or tuple _deprecated in `draft2020`_
|
|
94
|
+
- items | as schema only _new `draft2020`_
|
|
95
|
+
- prefixItems | as tuple _new `draft2020`_
|
|
96
|
+
- additionalItems | as schema _deprecated in `draft2020`_
|
|
97
|
+
- contains
|
|
98
|
+
- maxContains / minContains | _new `draft2019`_
|
|
99
|
+
- unevaluatedItems | _new `draft2019`_
|
|
100
|
+
|
|
101
|
+
### 🔑 Keywords for object
|
|
102
|
+
|
|
103
|
+
- maxProperties / minProperties
|
|
104
|
+
- required | _as array!_
|
|
105
|
+
- properties
|
|
106
|
+
- patternProperties
|
|
107
|
+
- additionalProperties
|
|
108
|
+
- dependencies | _deprecated in `draft2019`_
|
|
109
|
+
- dependentRequired | _new `draft2019`_
|
|
110
|
+
- dependentSchemas | _new `draft2019`_
|
|
111
|
+
- propertyNames
|
|
112
|
+
- unevaluatedProperties | _new `draft2019`_
|
|
113
|
+
- ❌ [propertyDependencies](https://github.com/json-schema-org/json-schema-spec/blob/main/proposals/propertyDependencies.md)
|
|
114
|
+
|
|
115
|
+
### 🔑 Keywords for all types
|
|
116
|
+
|
|
117
|
+
- enum
|
|
118
|
+
- const
|
|
119
|
+
|
|
120
|
+
### 🔑 Compound keywords
|
|
121
|
+
|
|
122
|
+
- not
|
|
123
|
+
- oneOf
|
|
124
|
+
- anyOf
|
|
125
|
+
- allOf
|
|
126
|
+
- if / then / else
|
|
127
|
+
|
|
128
|
+
See also:
|
|
129
|
+
- [Schema Composition](https://json-schema.org/understanding-json-schema/reference/combining)
|
|
130
|
+
- [Applying Subschemas Conditionally](https://json-schema.org/understanding-json-schema/reference/conditionals)
|
|
131
|
+
|
|
132
|
+
### 🔑 Meta keywords
|
|
133
|
+
|
|
134
|
+
- $schema | used for draft detection, vocabulary selection and cross-draft references
|
|
135
|
+
- $id
|
|
136
|
+
- $ref
|
|
137
|
+
- $anchor
|
|
138
|
+
- $recursiveRef | _new `draft2019` & deprecated in `draft2020`_
|
|
139
|
+
- $recursiveAnchor | _new `draft2019` & deprecated in `draft2020`_
|
|
140
|
+
- $dynamicRef | _new `draft2020`_
|
|
141
|
+
- $dynamicAnchor | _new `draft2020`_
|
|
142
|
+
- $data | _(Ajv specific)_
|
|
143
|
+
- [$vocabulary](https://github.com/json-schema-org/json-schema-spec/blob/main/proposals/vocabularies.md) | _new `draft2019`_ - a custom metaschema that omits the validation vocabulary turns keywords like `type` and `minimum` into annotations; a metaschema that declares the `format-assertion` vocabulary turns format assertion on
|
|
144
|
+
|
|
145
|
+
### 🔑 Non-standard keywords
|
|
146
|
+
|
|
147
|
+
- `data` | json-everything's [data-ref](https://docs.json-everything.net/schema/examples/data-ref/) proposal
|
|
148
|
+
|
|
149
|
+
The `data` keyword allows you to reference values from the instance being validated, enabling dynamic constraints based on other parts of the data.
|
|
150
|
+
|
|
151
|
+
**Example - Requiring B >= A:**
|
|
152
|
+
```json
|
|
153
|
+
{
|
|
154
|
+
"type": "object",
|
|
155
|
+
"properties": {
|
|
156
|
+
"A": { "type": "number" },
|
|
157
|
+
"B": {
|
|
158
|
+
"type": "number",
|
|
159
|
+
"data": {
|
|
160
|
+
"minimum": "/A"
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
}
|
|
165
|
+
```
|
|
166
|
+
- Passes: `{ "A": 5, "B": 10 }` (10 >= 5)
|
|
167
|
+
- Fails: `{ "A": 15, "B": 10 }` (10 < 15)
|
|
168
|
+
|
|
169
|
+
**Example - Enum from instance array:**
|
|
170
|
+
```json
|
|
171
|
+
{
|
|
172
|
+
"type": "object",
|
|
173
|
+
"properties": {
|
|
174
|
+
"color": {
|
|
175
|
+
"data": {
|
|
176
|
+
"enum": "/validColors"
|
|
177
|
+
}
|
|
178
|
+
},
|
|
179
|
+
"validColors": {
|
|
180
|
+
"type": "array",
|
|
181
|
+
"items": { "type": "string" }
|
|
182
|
+
}
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
```
|
|
186
|
+
|
|
187
|
+
**Supported keywords within `data`:**
|
|
188
|
+
- Number constraints: `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`
|
|
189
|
+
- String constraints: `minLength`, `maxLength`, `pattern`, `format`
|
|
190
|
+
- Array constraints: `minItems`, `maxItems`
|
|
191
|
+
- Object constraints: `minProperties`, `maxProperties`
|
|
192
|
+
- Value constraints: `enum`, `const`
|
|
193
|
+
|
|
194
|
+
Both absolute JSON Pointers (e.g., `/A`, `/limits/min`) and relative JSON Pointers (e.g., `0/parent`, `1/sibling`) are supported.
|
|
195
|
+
|
|
196
|
+
- `$data` | Ajv-style instance references (`{ "minimum": { "$data": "1/limit" } }`) — supports every keyword the `data` list above supports, plus `uniqueItems` and `required`. Refs compile once at schema compile time through the compiled pointer engine of `@jarenjs/json`.
|
|
197
|
+
|
|
198
|
+
- `$query` | Jaren's cross-field assertion keyword — see [below](#query--cross-field-assertions)
|
|
199
|
+
|
|
200
|
+
### 🔑 Miscellaneous keywords
|
|
201
|
+
|
|
202
|
+
- ❌ strict
|
|
203
|
+
- ❌ strictFormat
|
|
204
|
+
- ❌ strictTuple
|
|
205
|
+
- ❌ errorMessage
|
|
206
|
+
- definitions | used by initial schema traversal _deprecated in `draft2019`_
|
|
207
|
+
- $defs | used by initial schema traversal _new `draft2019`_
|
|
208
|
+
- components | _(OpenAPI)_
|
|
209
|
+
|
|
210
|
+
</details>
|
|
211
|
+
|
|
212
|
+
## 🛠️ Notable capabilities
|
|
213
|
+
|
|
214
|
+
### 👉 Modelling Inheritance with JSON Schema
|
|
215
|
+
|
|
216
|
+
Jaren fully supports `unevaluatedProperties`, so the inheritance patterns from the [Modelling Inheritance](https://json-schema.org/blog/posts/modelling-inheritance) blog post work out of the box. Annotations flow from `properties`, `patternProperties`, `additionalProperties` and every in-place applicator (`allOf`/`anyOf`/`oneOf`/`if-then-else`/`$ref`/`dependentSchemas`), with annotations from failed branches correctly discarded.
|
|
217
|
+
|
|
218
|
+
See also:
|
|
219
|
+
- [json-schema-core](https://json-schema.org/draft/2020-12/json-schema-core#name-unevaluatedproperties)
|
|
220
|
+
- [Combining unevaluatedProperties and ref: # #375](https://github.com/orgs/json-schema-org/discussions/375)
|
|
221
|
+
|
|
222
|
+
### 👉 Express array constraints more cleanly
|
|
223
|
+
|
|
224
|
+
Jaren fully supports `unevaluatedItems`, covering the array patterns from the 2020-12 [release notes](https://json-schema.org/draft/2020-12/release-notes#contains-and-unevaluateditems): items evaluated by `items`, `prefixItems`, `additionalItems` and (in 2020-12) `contains` are tracked, and everything left over is validated by the `unevaluatedItems` schema.
|
|
225
|
+
|
|
226
|
+
### 👉 Using Dynamic References to Support Generic Types
|
|
227
|
+
|
|
228
|
+
Jaren fully supports `$dynamicRef`/`$dynamicAnchor` (2020-12) and `$recursiveRef`/`$recursiveAnchor` (2019-09), including the generic-type patterns from the [dynamicRef and generics](https://json-schema.org/blog/posts/dynamicref-and-generics) blog post. Resolution follows the specification's dynamic-scope rules: entering a schema resource brings all of its dynamic anchors into scope, and a `$dynamicRef` resolves to the anchor in the outermost resource of the dynamic scope.
|
|
229
|
+
|
|
230
|
+
See also:
|
|
231
|
+
- [Understanding lexical dynamic scopes](https://json-schema.org/blog/posts/understanding-lexical-dynamic-scopes)
|
|
232
|
+
- [$dynamicRef and $dynamicAnchor](https://json-schema.org/draft/2020-12/release-notes#dollardynamicref-and-dollardynamicanchor)
|
|
233
|
+
|
|
234
|
+
### 👉 Runtime schema manipulation of constraints
|
|
235
|
+
|
|
236
|
+
Jaren supports the `data-ref` proposal from json-everything through the `data` keyword, plus Ajv-style `$data` references. Both allow a schema constraint to take its value from the instance being validated:
|
|
237
|
+
|
|
238
|
+
- Absolute JSON Pointers (e.g., `/A`, `/limits/min`)
|
|
239
|
+
- Relative JSON Pointers (e.g., `0/parent`, `1/sibling`)
|
|
240
|
+
- All common constraint keywords: `minimum`, `maximum`, `exclusiveMinimum`, `exclusiveMaximum`, `multipleOf`, `minLength`, `maxLength`, `pattern`, `format`, `enum`, `const`, `minItems`, `maxItems`, `minProperties`, `maxProperties`
|
|
241
|
+
|
|
242
|
+
The refs compile once at schema compile time through the compiled pointer engine of [`@jarenjs/json`](../json) and resolve allocation-free per validation.
|
|
243
|
+
|
|
244
|
+
See also:
|
|
245
|
+
- [$data](https://github.com/json-schema-org/json-schema-spec/issues/51)
|
|
246
|
+
- [Ajv $data spec](https://github.com/ajv-validator/ajv/tree/master/spec/extras/%24data)
|
|
247
|
+
- [data-ref](https://docs.json-everything.net/schema/examples/data-ref/)
|
|
248
|
+
|
|
249
|
+
### 👉 Vocabularies and cross-draft references
|
|
250
|
+
|
|
251
|
+
A schema's `$schema` declaration is honored per document: referenced documents that declare a different draft are processed with that draft's keyword set (a draft-07 document ignores `dependentRequired`; a 2019-09 document ignores `prefixItems`). Custom metaschemas with `$vocabulary` are respected — omitting the validation vocabulary turns validation keywords into annotations, and declaring `format-assertion` turns format assertion on.
|
|
252
|
+
|
|
253
|
+
## `$query` — cross-field assertions
|
|
254
|
+
|
|
255
|
+
`$query` is a **Jaren extension keyword**: its value is a
|
|
256
|
+
[Jaren JSON Query](../json/docs/QUERY-FORMAT.md) document, compiled once at
|
|
257
|
+
schema compile time and evaluated per validation against the current instance
|
|
258
|
+
location. The instance is valid when the query result's
|
|
259
|
+
[effective boolean value](../json/docs/QUERY-FORMAT.md#22-effective-boolean-value-ebv)
|
|
260
|
+
is true. This gives JSON Schema the class of constraint it is notoriously bad
|
|
261
|
+
at — cross-field arithmetic, ordering, aggregate consistency, quantification —
|
|
262
|
+
through the query engine that already sits underneath the stack. Other
|
|
263
|
+
validators treat `$query` as an unknown-keyword annotation, so schemas using
|
|
264
|
+
it stay portable; the constraint simply only asserts here.
|
|
265
|
+
|
|
266
|
+
An invoice whose `total` must equal the sum of its line amounts:
|
|
267
|
+
|
|
268
|
+
```javascript
|
|
269
|
+
const validate = jaren.compile({
|
|
270
|
+
type: 'object',
|
|
271
|
+
properties: {
|
|
272
|
+
lines: { type: 'array', items: { type: 'object' } },
|
|
273
|
+
total: { type: 'number' }
|
|
274
|
+
},
|
|
275
|
+
$query: { $eq: ['$.total', { $sum: '$.lines[*].amount' }] }
|
|
276
|
+
});
|
|
277
|
+
|
|
278
|
+
validate({ lines: [{ amount: 12.5 }, { amount: 7.5 }], total: 20 }); // true
|
|
279
|
+
validate({ lines: [{ amount: 12.5 }, { amount: 7.5 }], total: 21 }); // false
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Date ordering (`$le` compares strings by code points, QUERY-FORMAT §8.4 —
|
|
283
|
+
exactly right for ISO dates):
|
|
284
|
+
|
|
285
|
+
```javascript
|
|
286
|
+
jaren.compile({ $query: { $le: ['$.start', '$.end'] } });
|
|
287
|
+
```
|
|
288
|
+
|
|
289
|
+
Quantification over items:
|
|
290
|
+
|
|
291
|
+
```javascript
|
|
292
|
+
jaren.compile({
|
|
293
|
+
$query: { $every: { l: '$.lines[*]' }, $satisfies: { $gt: ['$l.qty', 0] } }
|
|
294
|
+
});
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
Two external parameters are bound on every evaluation: `root` — the instance
|
|
298
|
+
root — and `path` — the current instance location as a JSON pointer string.
|
|
299
|
+
(The JSLT template layer reserves the same two names with one twist: its
|
|
300
|
+
matching language is JSONPath, so its `path` is an RFC 9535 *normalized
|
|
301
|
+
path*, not a pointer — see [JSLT-FORMAT §8.2](../json/docs/JSLT-FORMAT.md).)
|
|
302
|
+
So a subschema can reach across the document:
|
|
303
|
+
|
|
304
|
+
```javascript
|
|
305
|
+
jaren.compile({
|
|
306
|
+
type: 'object',
|
|
307
|
+
properties: {
|
|
308
|
+
lines: {
|
|
309
|
+
type: 'array',
|
|
310
|
+
items: {
|
|
311
|
+
type: 'object',
|
|
312
|
+
// every line's currency must match the document-level currency
|
|
313
|
+
$query: { $eq: ['$.currency', '$root.currency'] }
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
});
|
|
318
|
+
```
|
|
319
|
+
|
|
320
|
+
Semantics and composition:
|
|
321
|
+
|
|
322
|
+
- `$query` works at **any subschema level** and composes like every other
|
|
323
|
+
keyword: under `properties`/`items` the query's `$` is that location's
|
|
324
|
+
value, `$path` its pointer (`/lines/0`, ...), `$root` the whole document.
|
|
325
|
+
- A bare JSONPath string is the degenerate query: `{ "$query": "$.approved" }`
|
|
326
|
+
asserts the EBV of that member (missing → empty sequence → false).
|
|
327
|
+
- Query **runtime** errors (`JQ2xxx` — e.g. arithmetic on a non-number, the
|
|
328
|
+
EBV of a multi-item result) are validation **failures**, never throws; in
|
|
329
|
+
`collectErrors` mode the error params carry the `code` and the query
|
|
330
|
+
`docPath`. Malformed query documents and free externals other than
|
|
331
|
+
`root`/`path` fail fast at `compile()`.
|
|
332
|
+
- Schema literals inside the query (`$valid`/`$assert`/`$as`,
|
|
333
|
+
QUERY-FORMAT §8.11) compile against the **same validator instance**, so
|
|
334
|
+
their `$ref`s resolve to your `addSchema` registrations.
|
|
335
|
+
|
|
336
|
+
## Development
|
|
337
|
+
|
|
338
|
+
Unit tests live in `test/validate/` at the repository root (`npm run test:validate`). Performance against Ajv is measured over the official test suite with the [benchmark workspace](../../benchmark/README.md) (`node benchmark/profiler.js --profile-all`), which also houses the test-failure debugger, coverage and call-graph tools.
|
|
339
|
+
|
|
340
|
+
This package's internals — the four-phase compile pipeline, ref flattening, annotation tracking, dynamic scope — are described in its own [ARCHITECTURE](./ARCHITECTURE.md) document. For practical usage recipes (options, lightweight setups, custom formats, pitfalls) see the repository [HOWTO](../../HOWTO.md); for the monorepo picture see the repository [README](../../README.md) and [ARCHITECTURE](../../ARCHITECTURE.md); for what is planned next see the [ROADMAP](../../ROADMAP.md).
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function compileBigIntBasic(schemaObj: any, jsonSchema: any): ((data: any, dataPath: any) => any) | undefined;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function compileCombineSchema(schemaObj: any, jsonSchema: any): any;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function compileConditionSchema(schemaObj: any, jsonSchema: any): ((data: any, dataPath: any, dataRoot: any, dataKey: any) => any) | undefined;
|
|
@@ -0,0 +1,3 @@
|
|
|
1
|
+
export declare function compileContentEncoding(schemaObj: any, jsonSchema: any): ((data: any, dataPath: any) => any) | undefined;
|
|
2
|
+
export declare function compileContentMediaType(schemaObj: any, jsonSchema: any): ((data: any, dataPath: any) => any) | undefined;
|
|
3
|
+
export declare function compileContentSchema(schemaObj: any, jsonSchema: any): ((data: any, dataPath: any) => any) | undefined;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile the data keyword schema
|
|
3
|
+
* @param {object} schemaObj - The validation object
|
|
4
|
+
* @param {object} jsonSchema - The JSON schema containing the data keyword
|
|
5
|
+
* @returns {function|undefined} The compiled validator function or undefined
|
|
6
|
+
*/
|
|
7
|
+
export declare function compileDataSchema(schemaObj: object, jsonSchema: object): Function | undefined;
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Compile $data keyword validators for a schema object
|
|
3
|
+
* This detects when keyword values are { $data: "..." } objects and creates
|
|
4
|
+
* dynamic validators that resolve the reference at validation time.
|
|
5
|
+
*
|
|
6
|
+
* @param {object} schemaObj - The validation object
|
|
7
|
+
* @param {object} jsonSchema - The JSON schema to compile
|
|
8
|
+
* @returns {function|undefined} The compiled validator function or undefined
|
|
9
|
+
*/
|
|
10
|
+
export declare function compileDollarDataSchema(schemaObj: object, jsonSchema: object): Function | undefined;
|
|
11
|
+
/**
|
|
12
|
+
* Check if the schema has any $data references
|
|
13
|
+
* This is used to determine if we should use the $data-aware compilation path
|
|
14
|
+
* or the standard static compilation path.
|
|
15
|
+
*
|
|
16
|
+
* @param {object} jsonSchema - The JSON schema to check
|
|
17
|
+
* @returns {boolean} True if the schema has any $data references
|
|
18
|
+
*/
|
|
19
|
+
export declare function hasDollarDataReferences(jsonSchema: object): boolean;
|
|
20
|
+
export declare function isDollarDataReference(jsonSchema: any): any;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Check if a schema has $recursiveAnchor: true.
|
|
3
|
+
* @param {object} schema - The schema object
|
|
4
|
+
* @returns {boolean}
|
|
5
|
+
*/
|
|
6
|
+
export declare function hasRecursiveAnchor(schema: object): boolean;
|
|
7
|
+
/**
|
|
8
|
+
* Get the $dynamicAnchor name from a schema.
|
|
9
|
+
* @param {object} schema - The schema object
|
|
10
|
+
* @returns {string|null}
|
|
11
|
+
*/
|
|
12
|
+
export declare function getDynamicAnchorName(schema: object): string | null;
|
|
13
|
+
/**
|
|
14
|
+
* Collect ALL dynamic anchors of a schema RESOURCE: every $dynamicAnchor
|
|
15
|
+
* reachable from the given schema without crossing into an embedded
|
|
16
|
+
* resource (a subschema that declares its own $id).
|
|
17
|
+
*
|
|
18
|
+
* Per draft 2020-12, entering a schema resource during evaluation brings
|
|
19
|
+
* every $dynamicAnchor of that resource into the dynamic scope - wherever
|
|
20
|
+
* it sits ($defs, allOf branches, properties, ...), not just at the root.
|
|
21
|
+
*
|
|
22
|
+
* @param {object} schema - The resource root schema object
|
|
23
|
+
* @returns {Array<{name: string, schema: object, validator: (function|null)}>}
|
|
24
|
+
*/
|
|
25
|
+
export declare function collectDynamicAnchorsDeep(schema: object): Array<{
|
|
26
|
+
name: string;
|
|
27
|
+
schema: object;
|
|
28
|
+
validator: (Function | null);
|
|
29
|
+
}>;
|
|
30
|
+
/**
|
|
31
|
+
* Collect all dynamic anchors from a schema's immediate definitions ($defs/definitions).
|
|
32
|
+
* This is used to find all $dynamicAnchor definitions that should be in scope
|
|
33
|
+
* when following a $ref from this schema.
|
|
34
|
+
*
|
|
35
|
+
* IMPORTANT: This only collects from the IMMEDIATE $defs of the given schema,
|
|
36
|
+
* not recursively.
|
|
37
|
+
*
|
|
38
|
+
* @param {object} schema - The schema object
|
|
39
|
+
* @returns {Array<{name: string, schema: object}>} Array of {name, schema} objects
|
|
40
|
+
*/
|
|
41
|
+
export declare function collectDynamicAnchors(schema: object): Array<{
|
|
42
|
+
name: string;
|
|
43
|
+
schema: object;
|
|
44
|
+
}>;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare function compileEnumBasic(schemaObj: any, jsonSchema: any): (((data: any, dataPath: any) => any) | undefined)[];
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
export type FormatCompiler = import('./index.js').FormatCompiler;
|
|
2
|
+
/** @typedef {import('./index.js').FormatCompiler} FormatCompiler */
|
|
3
|
+
/**
|
|
4
|
+
* Registers a single format compiler under a name.
|
|
5
|
+
* Existing registrations are never overwritten.
|
|
6
|
+
* @param {Record<string, FormatCompiler>} registered - The formats registry object
|
|
7
|
+
* @param {string} name - The format name (e.g. 'email', 'uri', 'date-time')
|
|
8
|
+
* @param {FormatCompiler} formatCompiler - The compiler to register
|
|
9
|
+
* @returns {boolean} True when the compiler was registered
|
|
10
|
+
*/
|
|
11
|
+
export declare function registerFormatCompiler(registered: Record<string, FormatCompiler>, name: string, formatCompiler: FormatCompiler): boolean;
|
|
12
|
+
/**
|
|
13
|
+
* Registers multiple format compilers at once.
|
|
14
|
+
* Existing registrations are never overwritten.
|
|
15
|
+
* @param {Record<string, FormatCompiler>} registered - The formats registry object
|
|
16
|
+
* @param {Record<string, FormatCompiler>} formatCompilers - Object mapping format names to compiler functions
|
|
17
|
+
* @returns {Record<string, FormatCompiler>} The registry object passed in
|
|
18
|
+
*/
|
|
19
|
+
export declare function registerFormatCompilers(registered: Record<string, FormatCompiler>, formatCompilers: Record<string, FormatCompiler>): Record<string, FormatCompiler>;
|
|
20
|
+
export declare function getSchemaFormatCompiler(registered: any, name: any): any;
|
|
21
|
+
export declare function compileFormatBasic(schemaObj: any, jsonSchema: any): any;
|