@maroonedog/luq 2.4.4 → 2.6.0
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 +64 -10
- package/dist/chain/slot-type-guard.js +20 -6
- package/dist/chain/slot-type-guard.mjs +20 -6
- package/dist/compile/resolve-presence.js +36 -5
- package/dist/compile/resolve-presence.mjs +36 -5
- package/dist/json-schema/array-keyword-guards.d.ts +31 -0
- package/dist/json-schema/array-keyword-guards.js +120 -0
- package/dist/json-schema/array-keyword-guards.mjs +114 -0
- package/dist/json-schema/assert-object-keyword-values.d.ts +59 -0
- package/dist/json-schema/assert-object-keyword-values.js +149 -0
- package/dist/json-schema/assert-object-keyword-values.mjs +141 -0
- package/dist/json-schema/assert-supported-dialect.d.ts +37 -0
- package/dist/json-schema/assert-supported-dialect.js +113 -0
- package/dist/json-schema/assert-supported-dialect.mjs +109 -0
- package/dist/json-schema/build-from-schema.d.ts +22 -3
- package/dist/json-schema/build-from-schema.js +27 -5
- package/dist/json-schema/build-from-schema.mjs +27 -5
- package/dist/json-schema/collect-definitions.d.ts +7 -0
- package/dist/json-schema/collect-definitions.js +9 -0
- package/dist/json-schema/collect-definitions.mjs +10 -1
- package/dist/json-schema/declare-additional-properties.d.ts +11 -1
- package/dist/json-schema/declare-additional-properties.js +13 -1
- package/dist/json-schema/declare-additional-properties.mjs +13 -1
- package/dist/json-schema/declare-object-keywords.d.ts +4 -0
- package/dist/json-schema/declare-object-keywords.js +11 -4
- package/dist/json-schema/declare-object-keywords.mjs +11 -4
- package/dist/json-schema/declare-required-properties.js +6 -0
- package/dist/json-schema/declare-required-properties.mjs +6 -0
- package/dist/json-schema/declare-value-keywords.d.ts +10 -1
- package/dist/json-schema/declare-value-keywords.js +43 -4
- package/dist/json-schema/declare-value-keywords.mjs +43 -4
- package/dist/json-schema/extensions/json-schema/index.d.ts +2 -2
- package/dist/json-schema/extensions/json-schema/index.js +4 -1
- package/dist/json-schema/extensions/json-schema/index.mjs +1 -1
- package/dist/json-schema/extensions/json-schema/json-schema.d.ts +2 -2
- package/dist/json-schema/extensions/json-schema/json-schema.js +3 -0
- package/dist/json-schema/extensions/json-schema/json-schema.mjs +4 -1
- package/dist/json-schema/extensions/json-schema-full-feature/index.d.ts +3 -1
- package/dist/json-schema/extensions/json-schema-full-feature/index.js +18 -1
- package/dist/json-schema/extensions/json-schema-full-feature/index.mjs +11 -0
- package/dist/json-schema/extensions/json-schema-full-feature/json-schema-full-feature.d.ts +9 -1
- package/dist/json-schema/extensions/json-schema-full-feature/json-schema-full-feature.js +9 -2
- package/dist/json-schema/extensions/json-schema-full-feature/json-schema-full-feature.mjs +9 -2
- package/dist/json-schema/flatten-array-schema.d.ts +11 -1
- package/dist/json-schema/flatten-array-schema.js +20 -7
- package/dist/json-schema/flatten-array-schema.mjs +20 -7
- package/dist/json-schema/index.d.ts +4 -0
- package/dist/json-schema/index.js +9 -1
- package/dist/json-schema/index.mjs +3 -0
- package/dist/json-schema/keyword-map-core.js +3 -1
- package/dist/json-schema/keyword-map-core.mjs +3 -1
- package/dist/json-schema/keyword-map-string.js +30 -1
- package/dist/json-schema/keyword-map-string.mjs +30 -1
- package/dist/json-schema/keyword-map.js +5 -0
- package/dist/json-schema/keyword-map.mjs +5 -0
- package/dist/json-schema/malformed-schema-error.d.ts +38 -0
- package/dist/json-schema/malformed-schema-error.js +103 -0
- package/dist/json-schema/malformed-schema-error.mjs +98 -0
- package/dist/json-schema/unsupported-dialect-error.d.ts +21 -0
- package/dist/json-schema/unsupported-dialect-error.js +58 -0
- package/dist/json-schema/unsupported-dialect-error.mjs +54 -0
- package/dist/plugins/one-of/one-of.js +18 -4
- package/dist/plugins/one-of/one-of.mjs +18 -4
- package/package.json +8 -5
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `required` is an array of property names (§6.5.3), and whatever the document
|
|
3
|
+
* put there is refused when it is anything else.
|
|
4
|
+
*
|
|
5
|
+
* UNIQUENESS IS NOT ENFORCED, although the meta-schema's `stringArray` asks
|
|
6
|
+
* for it. A repeated name asks for nothing the single name does not — the
|
|
7
|
+
* property is required either way, so the verdict is identical — and this
|
|
8
|
+
* check exists to stop a validator enforcing LESS than its document, not to
|
|
9
|
+
* lint a document that is enforced exactly as written. Refusing a duplicate
|
|
10
|
+
* would reject working schemas for no gain in correctness.
|
|
11
|
+
*/
|
|
12
|
+
export declare function assertRequiredIsNameList(value: unknown): void;
|
|
13
|
+
/**
|
|
14
|
+
* `properties` maps property names to schemas (§6.5.4), and a schema is an
|
|
15
|
+
* object or a boolean; the map itself and every member of it are refused when
|
|
16
|
+
* they are not. The key is named in the reason so the message points at the
|
|
17
|
+
* offending node rather than at the whole document.
|
|
18
|
+
*/
|
|
19
|
+
export declare function assertPropertiesIsSchemaMap(value: unknown): void;
|
|
20
|
+
/**
|
|
21
|
+
* `additionalProperties` is a schema, and §4.4 makes a boolean one (§6.5.6).
|
|
22
|
+
* Both of those forms pass through unchanged; only a value the meta-schema
|
|
23
|
+
* already forbids — a string, a number, an array, null — is refused.
|
|
24
|
+
*/
|
|
25
|
+
export declare function assertAdditionalPropertiesIsSchema(value: unknown): void;
|
|
26
|
+
/**
|
|
27
|
+
* `patternProperties` maps regular expressions to schemas (§6.5.5). The map
|
|
28
|
+
* itself and every member of it are refused when they are not schemas, and the
|
|
29
|
+
* pattern is named in the reason so the message points at the one offending
|
|
30
|
+
* entry rather than at a map that may hold a dozen.
|
|
31
|
+
*
|
|
32
|
+
* THE KEYS ARE DELIBERATELY NOT COMPILED HERE, although Draft-07 says each
|
|
33
|
+
* SHOULD be a valid ECMA-262 pattern. A key that will not compile is not the
|
|
34
|
+
* failure this module exists to stop: the plugin compiles every key while
|
|
35
|
+
* building its rule, so such a key already kills the build, loudly, before any
|
|
36
|
+
* validator exists — it is a SyntaxError rather than a typed refusal, but
|
|
37
|
+
* nothing is silently under-enforced. Compiling one here as well would put a
|
|
38
|
+
* SECOND `new RegExp` in the converter, which holds exactly one — the `pattern`
|
|
39
|
+
* keyword's, over the document's own source string — so that regex
|
|
40
|
+
* construction and its flag handling stay in a single place.
|
|
41
|
+
*/
|
|
42
|
+
export declare function assertPatternPropertiesIsSchemaMap(value: unknown): void;
|
|
43
|
+
/**
|
|
44
|
+
* `propertyNames` is ONE schema, applied to every property name (§6.5.8), and
|
|
45
|
+
* §4.4 makes a boolean one. An ARRAY is the shape of a schema list and is not
|
|
46
|
+
* itself a schema, so it is refused along with every primitive. An object
|
|
47
|
+
* stands whatever keywords it carries, because §4.3 has a schema ignore the
|
|
48
|
+
* keywords it does not recognise rather than be invalid for holding them.
|
|
49
|
+
*/
|
|
50
|
+
export declare function assertPropertyNamesIsSchema(value: unknown): void;
|
|
51
|
+
/**
|
|
52
|
+
* `dependencies` maps a property name to what its presence demands (§6.5.7),
|
|
53
|
+
* and the draft gives that two equally lawful forms under the same key: an
|
|
54
|
+
* ARRAY of property names, which makes those names required alongside it, or a
|
|
55
|
+
* SCHEMA the whole instance must then satisfy. Both are kept; only a value
|
|
56
|
+
* that is neither is refused, and the key is named so the message points at
|
|
57
|
+
* the one offending entry rather than at the whole map.
|
|
58
|
+
*/
|
|
59
|
+
export declare function assertDependenciesIsSchemaOrNameListMap(value: unknown): void;
|
|
@@ -0,0 +1,149 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.assertRequiredIsNameList = assertRequiredIsNameList;
|
|
4
|
+
exports.assertPropertiesIsSchemaMap = assertPropertiesIsSchemaMap;
|
|
5
|
+
exports.assertAdditionalPropertiesIsSchema = assertAdditionalPropertiesIsSchema;
|
|
6
|
+
exports.assertPatternPropertiesIsSchemaMap = assertPatternPropertiesIsSchemaMap;
|
|
7
|
+
exports.assertPropertyNamesIsSchema = assertPropertyNamesIsSchema;
|
|
8
|
+
exports.assertDependenciesIsSchemaOrNameListMap = assertDependenciesIsSchemaOrNameListMap;
|
|
9
|
+
// ===========================================================================
|
|
10
|
+
// L8 src/json-schema/assert-object-keyword-values.ts — the meta-schema check
|
|
11
|
+
// on the VALUES of the object-family keywords: `required`, `properties`,
|
|
12
|
+
// `additionalProperties`, `patternProperties`, `propertyNames` and
|
|
13
|
+
// `dependencies`.
|
|
14
|
+
//
|
|
15
|
+
// They live together because they fail together: every one is read in a place
|
|
16
|
+
// that trusts the declared type, and untyped JSON reaches all six. `required:
|
|
17
|
+
// "name"` is iterated as a string and declares one phantom child per
|
|
18
|
+
// CHARACTER; `properties: {a: null}` is read for a pointer; the remaining four
|
|
19
|
+
// take the sub-schema route with a value that is not a schema at all, and the
|
|
20
|
+
// walker finds no keys on a primitive, so it yields a branch holding no rules.
|
|
21
|
+
//
|
|
22
|
+
// That last outcome is the SILENT one, and it is the one that matters most: a
|
|
23
|
+
// document saying "no extra properties", or "every key beginning with a_ holds
|
|
24
|
+
// a string", compiles to a validator that accepts everything. It is what a
|
|
25
|
+
// config service serialising booleans as strings produces, and what a
|
|
26
|
+
// hand-edited document with a quoted sub-schema produces. The loud failures
|
|
27
|
+
// are loud in the wrong place — a raw TypeError read off null somewhere deep
|
|
28
|
+
// in the walker, naming neither the keyword nor the document.
|
|
29
|
+
//
|
|
30
|
+
// Refusal is therefore always at BUILD time, and every well-formed shape is
|
|
31
|
+
// untouched: a name list, a map of schemas (including the §4.4 boolean form),
|
|
32
|
+
// a single schema, and — under `dependencies` — either a schema or an array of
|
|
33
|
+
// property names, which §6.5.7 makes equally lawful under the same key.
|
|
34
|
+
// ===========================================================================
|
|
35
|
+
const types_1 = require("../types");
|
|
36
|
+
const draft07_types_1 = require("./draft07.types");
|
|
37
|
+
const malformed_schema_error_1 = require("./malformed-schema-error");
|
|
38
|
+
/**
|
|
39
|
+
* `required` is an array of property names (§6.5.3), and whatever the document
|
|
40
|
+
* put there is refused when it is anything else.
|
|
41
|
+
*
|
|
42
|
+
* UNIQUENESS IS NOT ENFORCED, although the meta-schema's `stringArray` asks
|
|
43
|
+
* for it. A repeated name asks for nothing the single name does not — the
|
|
44
|
+
* property is required either way, so the verdict is identical — and this
|
|
45
|
+
* check exists to stop a validator enforcing LESS than its document, not to
|
|
46
|
+
* lint a document that is enforced exactly as written. Refusing a duplicate
|
|
47
|
+
* would reject working schemas for no gain in correctness.
|
|
48
|
+
*/
|
|
49
|
+
function assertRequiredIsNameList(value) {
|
|
50
|
+
if (value === undefined || (0, types_1.isStringArray)(value))
|
|
51
|
+
return;
|
|
52
|
+
throw new malformed_schema_error_1.MalformedSchemaError("required", "the value must be an array of property names", value);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* `properties` and `patternProperties` differ only in what their KEYS mean, so
|
|
56
|
+
* they are checked the same way: the map itself, then every member of it, and
|
|
57
|
+
* the offending key named in the reason so the message points at one entry
|
|
58
|
+
* rather than at a map that may hold a dozen. `dependencies` is not routed
|
|
59
|
+
* through here — §6.5.7 gives its members a second lawful form, which is a
|
|
60
|
+
* different member check and a different sentence.
|
|
61
|
+
*
|
|
62
|
+
* `mapReason` is the keyword's own, because "an object mapping property names
|
|
63
|
+
* to schemas" and "an object mapping regular expressions to schemas" are the
|
|
64
|
+
* only part of the requirement the two keywords do not share.
|
|
65
|
+
*/
|
|
66
|
+
function assertSchemaMap(keyword, mapReason, value) {
|
|
67
|
+
if (value === undefined)
|
|
68
|
+
return;
|
|
69
|
+
if (!(0, types_1.isPlainObject)(value)) {
|
|
70
|
+
throw new malformed_schema_error_1.MalformedSchemaError(keyword, mapReason, value);
|
|
71
|
+
}
|
|
72
|
+
for (const [key, member] of Object.entries(value)) {
|
|
73
|
+
if ((0, draft07_types_1.isDraft07Schema)(member))
|
|
74
|
+
continue;
|
|
75
|
+
throw new malformed_schema_error_1.MalformedSchemaError(keyword, `the schema under "${key}" ${malformed_schema_error_1.SCHEMA_FORMS}`, member);
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* `properties` maps property names to schemas (§6.5.4), and a schema is an
|
|
80
|
+
* object or a boolean; the map itself and every member of it are refused when
|
|
81
|
+
* they are not. The key is named in the reason so the message points at the
|
|
82
|
+
* offending node rather than at the whole document.
|
|
83
|
+
*/
|
|
84
|
+
function assertPropertiesIsSchemaMap(value) {
|
|
85
|
+
assertSchemaMap("properties", "the value must be an object mapping property names to schemas", value);
|
|
86
|
+
}
|
|
87
|
+
/**
|
|
88
|
+
* `additionalProperties` is a schema, and §4.4 makes a boolean one (§6.5.6).
|
|
89
|
+
* Both of those forms pass through unchanged; only a value the meta-schema
|
|
90
|
+
* already forbids — a string, a number, an array, null — is refused.
|
|
91
|
+
*/
|
|
92
|
+
function assertAdditionalPropertiesIsSchema(value) {
|
|
93
|
+
if (value === undefined || (0, draft07_types_1.isDraft07Schema)(value))
|
|
94
|
+
return;
|
|
95
|
+
throw new malformed_schema_error_1.MalformedSchemaError("additionalProperties", `the value ${malformed_schema_error_1.SCHEMA_FORMS}`, value);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* `patternProperties` maps regular expressions to schemas (§6.5.5). The map
|
|
99
|
+
* itself and every member of it are refused when they are not schemas, and the
|
|
100
|
+
* pattern is named in the reason so the message points at the one offending
|
|
101
|
+
* entry rather than at a map that may hold a dozen.
|
|
102
|
+
*
|
|
103
|
+
* THE KEYS ARE DELIBERATELY NOT COMPILED HERE, although Draft-07 says each
|
|
104
|
+
* SHOULD be a valid ECMA-262 pattern. A key that will not compile is not the
|
|
105
|
+
* failure this module exists to stop: the plugin compiles every key while
|
|
106
|
+
* building its rule, so such a key already kills the build, loudly, before any
|
|
107
|
+
* validator exists — it is a SyntaxError rather than a typed refusal, but
|
|
108
|
+
* nothing is silently under-enforced. Compiling one here as well would put a
|
|
109
|
+
* SECOND `new RegExp` in the converter, which holds exactly one — the `pattern`
|
|
110
|
+
* keyword's, over the document's own source string — so that regex
|
|
111
|
+
* construction and its flag handling stay in a single place.
|
|
112
|
+
*/
|
|
113
|
+
function assertPatternPropertiesIsSchemaMap(value) {
|
|
114
|
+
assertSchemaMap("patternProperties", "the value must be an object mapping regular expressions to schemas", value);
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* `propertyNames` is ONE schema, applied to every property name (§6.5.8), and
|
|
118
|
+
* §4.4 makes a boolean one. An ARRAY is the shape of a schema list and is not
|
|
119
|
+
* itself a schema, so it is refused along with every primitive. An object
|
|
120
|
+
* stands whatever keywords it carries, because §4.3 has a schema ignore the
|
|
121
|
+
* keywords it does not recognise rather than be invalid for holding them.
|
|
122
|
+
*/
|
|
123
|
+
function assertPropertyNamesIsSchema(value) {
|
|
124
|
+
if (value === undefined || (0, draft07_types_1.isDraft07Schema)(value))
|
|
125
|
+
return;
|
|
126
|
+
throw new malformed_schema_error_1.MalformedSchemaError("propertyNames", `the value ${malformed_schema_error_1.SCHEMA_FORMS}`, value);
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* `dependencies` maps a property name to what its presence demands (§6.5.7),
|
|
130
|
+
* and the draft gives that two equally lawful forms under the same key: an
|
|
131
|
+
* ARRAY of property names, which makes those names required alongside it, or a
|
|
132
|
+
* SCHEMA the whole instance must then satisfy. Both are kept; only a value
|
|
133
|
+
* that is neither is refused, and the key is named so the message points at
|
|
134
|
+
* the one offending entry rather than at the whole map.
|
|
135
|
+
*/
|
|
136
|
+
function assertDependenciesIsSchemaOrNameListMap(value) {
|
|
137
|
+
if (value === undefined)
|
|
138
|
+
return;
|
|
139
|
+
if (!(0, types_1.isPlainObject)(value)) {
|
|
140
|
+
throw new malformed_schema_error_1.MalformedSchemaError("dependencies", "the value must be an object mapping property names to schemas or to " +
|
|
141
|
+
"arrays of property names", value);
|
|
142
|
+
}
|
|
143
|
+
for (const [key, dependency] of Object.entries(value)) {
|
|
144
|
+
if ((0, types_1.isStringArray)(dependency) || (0, draft07_types_1.isDraft07Schema)(dependency))
|
|
145
|
+
continue;
|
|
146
|
+
throw new malformed_schema_error_1.MalformedSchemaError("dependencies", `the dependency under "${key}" ${malformed_schema_error_1.SCHEMA_FORMS}, or an array of ` +
|
|
147
|
+
"property names", dependency);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
// ===========================================================================
|
|
2
|
+
// L8 src/json-schema/assert-object-keyword-values.ts — the meta-schema check
|
|
3
|
+
// on the VALUES of the object-family keywords: `required`, `properties`,
|
|
4
|
+
// `additionalProperties`, `patternProperties`, `propertyNames` and
|
|
5
|
+
// `dependencies`.
|
|
6
|
+
//
|
|
7
|
+
// They live together because they fail together: every one is read in a place
|
|
8
|
+
// that trusts the declared type, and untyped JSON reaches all six. `required:
|
|
9
|
+
// "name"` is iterated as a string and declares one phantom child per
|
|
10
|
+
// CHARACTER; `properties: {a: null}` is read for a pointer; the remaining four
|
|
11
|
+
// take the sub-schema route with a value that is not a schema at all, and the
|
|
12
|
+
// walker finds no keys on a primitive, so it yields a branch holding no rules.
|
|
13
|
+
//
|
|
14
|
+
// That last outcome is the SILENT one, and it is the one that matters most: a
|
|
15
|
+
// document saying "no extra properties", or "every key beginning with a_ holds
|
|
16
|
+
// a string", compiles to a validator that accepts everything. It is what a
|
|
17
|
+
// config service serialising booleans as strings produces, and what a
|
|
18
|
+
// hand-edited document with a quoted sub-schema produces. The loud failures
|
|
19
|
+
// are loud in the wrong place — a raw TypeError read off null somewhere deep
|
|
20
|
+
// in the walker, naming neither the keyword nor the document.
|
|
21
|
+
//
|
|
22
|
+
// Refusal is therefore always at BUILD time, and every well-formed shape is
|
|
23
|
+
// untouched: a name list, a map of schemas (including the §4.4 boolean form),
|
|
24
|
+
// a single schema, and — under `dependencies` — either a schema or an array of
|
|
25
|
+
// property names, which §6.5.7 makes equally lawful under the same key.
|
|
26
|
+
// ===========================================================================
|
|
27
|
+
import { isPlainObject, isStringArray } from "../types/index.mjs";
|
|
28
|
+
import { isDraft07Schema } from "./draft07.types.mjs";
|
|
29
|
+
import { MalformedSchemaError, SCHEMA_FORMS } from "./malformed-schema-error.mjs";
|
|
30
|
+
/**
|
|
31
|
+
* `required` is an array of property names (§6.5.3), and whatever the document
|
|
32
|
+
* put there is refused when it is anything else.
|
|
33
|
+
*
|
|
34
|
+
* UNIQUENESS IS NOT ENFORCED, although the meta-schema's `stringArray` asks
|
|
35
|
+
* for it. A repeated name asks for nothing the single name does not — the
|
|
36
|
+
* property is required either way, so the verdict is identical — and this
|
|
37
|
+
* check exists to stop a validator enforcing LESS than its document, not to
|
|
38
|
+
* lint a document that is enforced exactly as written. Refusing a duplicate
|
|
39
|
+
* would reject working schemas for no gain in correctness.
|
|
40
|
+
*/
|
|
41
|
+
export function assertRequiredIsNameList(value) {
|
|
42
|
+
if (value === undefined || isStringArray(value))
|
|
43
|
+
return;
|
|
44
|
+
throw new MalformedSchemaError("required", "the value must be an array of property names", value);
|
|
45
|
+
}
|
|
46
|
+
/**
|
|
47
|
+
* `properties` and `patternProperties` differ only in what their KEYS mean, so
|
|
48
|
+
* they are checked the same way: the map itself, then every member of it, and
|
|
49
|
+
* the offending key named in the reason so the message points at one entry
|
|
50
|
+
* rather than at a map that may hold a dozen. `dependencies` is not routed
|
|
51
|
+
* through here — §6.5.7 gives its members a second lawful form, which is a
|
|
52
|
+
* different member check and a different sentence.
|
|
53
|
+
*
|
|
54
|
+
* `mapReason` is the keyword's own, because "an object mapping property names
|
|
55
|
+
* to schemas" and "an object mapping regular expressions to schemas" are the
|
|
56
|
+
* only part of the requirement the two keywords do not share.
|
|
57
|
+
*/
|
|
58
|
+
function assertSchemaMap(keyword, mapReason, value) {
|
|
59
|
+
if (value === undefined)
|
|
60
|
+
return;
|
|
61
|
+
if (!isPlainObject(value)) {
|
|
62
|
+
throw new MalformedSchemaError(keyword, mapReason, value);
|
|
63
|
+
}
|
|
64
|
+
for (const [key, member] of Object.entries(value)) {
|
|
65
|
+
if (isDraft07Schema(member))
|
|
66
|
+
continue;
|
|
67
|
+
throw new MalformedSchemaError(keyword, `the schema under "${key}" ${SCHEMA_FORMS}`, member);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
/**
|
|
71
|
+
* `properties` maps property names to schemas (§6.5.4), and a schema is an
|
|
72
|
+
* object or a boolean; the map itself and every member of it are refused when
|
|
73
|
+
* they are not. The key is named in the reason so the message points at the
|
|
74
|
+
* offending node rather than at the whole document.
|
|
75
|
+
*/
|
|
76
|
+
export function assertPropertiesIsSchemaMap(value) {
|
|
77
|
+
assertSchemaMap("properties", "the value must be an object mapping property names to schemas", value);
|
|
78
|
+
}
|
|
79
|
+
/**
|
|
80
|
+
* `additionalProperties` is a schema, and §4.4 makes a boolean one (§6.5.6).
|
|
81
|
+
* Both of those forms pass through unchanged; only a value the meta-schema
|
|
82
|
+
* already forbids — a string, a number, an array, null — is refused.
|
|
83
|
+
*/
|
|
84
|
+
export function assertAdditionalPropertiesIsSchema(value) {
|
|
85
|
+
if (value === undefined || isDraft07Schema(value))
|
|
86
|
+
return;
|
|
87
|
+
throw new MalformedSchemaError("additionalProperties", `the value ${SCHEMA_FORMS}`, value);
|
|
88
|
+
}
|
|
89
|
+
/**
|
|
90
|
+
* `patternProperties` maps regular expressions to schemas (§6.5.5). The map
|
|
91
|
+
* itself and every member of it are refused when they are not schemas, and the
|
|
92
|
+
* pattern is named in the reason so the message points at the one offending
|
|
93
|
+
* entry rather than at a map that may hold a dozen.
|
|
94
|
+
*
|
|
95
|
+
* THE KEYS ARE DELIBERATELY NOT COMPILED HERE, although Draft-07 says each
|
|
96
|
+
* SHOULD be a valid ECMA-262 pattern. A key that will not compile is not the
|
|
97
|
+
* failure this module exists to stop: the plugin compiles every key while
|
|
98
|
+
* building its rule, so such a key already kills the build, loudly, before any
|
|
99
|
+
* validator exists — it is a SyntaxError rather than a typed refusal, but
|
|
100
|
+
* nothing is silently under-enforced. Compiling one here as well would put a
|
|
101
|
+
* SECOND `new RegExp` in the converter, which holds exactly one — the `pattern`
|
|
102
|
+
* keyword's, over the document's own source string — so that regex
|
|
103
|
+
* construction and its flag handling stay in a single place.
|
|
104
|
+
*/
|
|
105
|
+
export function assertPatternPropertiesIsSchemaMap(value) {
|
|
106
|
+
assertSchemaMap("patternProperties", "the value must be an object mapping regular expressions to schemas", value);
|
|
107
|
+
}
|
|
108
|
+
/**
|
|
109
|
+
* `propertyNames` is ONE schema, applied to every property name (§6.5.8), and
|
|
110
|
+
* §4.4 makes a boolean one. An ARRAY is the shape of a schema list and is not
|
|
111
|
+
* itself a schema, so it is refused along with every primitive. An object
|
|
112
|
+
* stands whatever keywords it carries, because §4.3 has a schema ignore the
|
|
113
|
+
* keywords it does not recognise rather than be invalid for holding them.
|
|
114
|
+
*/
|
|
115
|
+
export function assertPropertyNamesIsSchema(value) {
|
|
116
|
+
if (value === undefined || isDraft07Schema(value))
|
|
117
|
+
return;
|
|
118
|
+
throw new MalformedSchemaError("propertyNames", `the value ${SCHEMA_FORMS}`, value);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* `dependencies` maps a property name to what its presence demands (§6.5.7),
|
|
122
|
+
* and the draft gives that two equally lawful forms under the same key: an
|
|
123
|
+
* ARRAY of property names, which makes those names required alongside it, or a
|
|
124
|
+
* SCHEMA the whole instance must then satisfy. Both are kept; only a value
|
|
125
|
+
* that is neither is refused, and the key is named so the message points at
|
|
126
|
+
* the one offending entry rather than at the whole map.
|
|
127
|
+
*/
|
|
128
|
+
export function assertDependenciesIsSchemaOrNameListMap(value) {
|
|
129
|
+
if (value === undefined)
|
|
130
|
+
return;
|
|
131
|
+
if (!isPlainObject(value)) {
|
|
132
|
+
throw new MalformedSchemaError("dependencies", "the value must be an object mapping property names to schemas or to " +
|
|
133
|
+
"arrays of property names", value);
|
|
134
|
+
}
|
|
135
|
+
for (const [key, dependency] of Object.entries(value)) {
|
|
136
|
+
if (isStringArray(dependency) || isDraft07Schema(dependency))
|
|
137
|
+
continue;
|
|
138
|
+
throw new MalformedSchemaError("dependencies", `the dependency under "${key}" ${SCHEMA_FORMS}, or an array of ` +
|
|
139
|
+
"property names", dependency);
|
|
140
|
+
}
|
|
141
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* What the caller may say about the dialect. `JsonSchemaOptions` extends this,
|
|
3
|
+
* so the chain method and the conversion function offer the same word.
|
|
4
|
+
*/
|
|
5
|
+
export interface DialectOptions {
|
|
6
|
+
/**
|
|
7
|
+
* Read the document under Draft-07 rules whatever its `$schema` declares.
|
|
8
|
+
*
|
|
9
|
+
* The reading it buys is Draft-07's, exactly: `$ref` replaces the node it
|
|
10
|
+
* sits in, `format` asserts, and an array under `items` is the tuple form.
|
|
11
|
+
* A 2019-09 or 2020-12 document that relies on any of those meaning what the
|
|
12
|
+
* NEWER draft says will be enforced as less, or as something else, than it
|
|
13
|
+
* states.
|
|
14
|
+
*/
|
|
15
|
+
readonly assumeDraft07?: boolean | undefined;
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* The released dialects Luq recognises the NAME of and does not implement,
|
|
19
|
+
* each with what it does that Draft-07 does not. They are written out so that
|
|
20
|
+
* "this is a dialect we know and did not build" and "we have never heard of
|
|
21
|
+
* this URI" stay different answers — the same distinction NON_DRAFT07_KEYWORDS
|
|
22
|
+
* draws between an out-of-dialect keyword and an invented one.
|
|
23
|
+
*/
|
|
24
|
+
export declare const NON_DRAFT07_DIALECTS: Readonly<Record<string, string>>;
|
|
25
|
+
/**
|
|
26
|
+
* Reads the root `$schema` and refuses a dialect Luq does not implement.
|
|
27
|
+
*
|
|
28
|
+
* Called at both front doors, immediately after "is this a schema at all" and
|
|
29
|
+
* before any keyword is read, so no validator that enforces less than its
|
|
30
|
+
* document states can be reached by either route.
|
|
31
|
+
*
|
|
32
|
+
* A non-string `$schema` is a malformed VALUE rather than an unimplemented
|
|
33
|
+
* dialect — the meta-schema types it as a string — so it goes to the class that
|
|
34
|
+
* answers that question, and it is refused under the opt-out too: the opt-out
|
|
35
|
+
* says "read this dialect as Draft-07", and a number names no dialect.
|
|
36
|
+
*/
|
|
37
|
+
export declare function assertSupportedDialect(document: unknown, options: DialectOptions): void;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NON_DRAFT07_DIALECTS = void 0;
|
|
4
|
+
exports.assertSupportedDialect = assertSupportedDialect;
|
|
5
|
+
// ===========================================================================
|
|
6
|
+
// L8 src/json-schema/assert-supported-dialect.ts — the DIALECT gate, read
|
|
7
|
+
// once at the document root before any keyword is.
|
|
8
|
+
//
|
|
9
|
+
// WHY A DEFAULT REFUSAL AND NOT A DIVERGENCE DETECTOR. Refusing only documents
|
|
10
|
+
// that actually USE something 2019-09 changed sounds more precise and is the
|
|
11
|
+
// worse trade. The divergences are not all spellable as keyword names: `$ref`
|
|
12
|
+
// gains siblings, `format` and the two `content*` keywords stop asserting by
|
|
13
|
+
// default, and 2020-12 moves the tuple form of `items` to `prefixItems`. A
|
|
14
|
+
// detector would therefore have to carry a second semantic model of two
|
|
15
|
+
// dialects this library does not implement, and every case it fails to think
|
|
16
|
+
// of is a SILENT wrong answer — which is the exact failure this file exists to
|
|
17
|
+
// stop. The `$ref`-sibling case was itself invisible until it was hunted for.
|
|
18
|
+
// `$schema` is the document's own statement of what it means, so that is what
|
|
19
|
+
// is read.
|
|
20
|
+
//
|
|
21
|
+
// WHAT THE DEFAULT COSTS, and why the opt-out exists. A newer `$schema` over a
|
|
22
|
+
// body that happens to be Draft-07-compatible builds correctly today, and
|
|
23
|
+
// people copy the newest `$schema` line into documents that use nothing new.
|
|
24
|
+
// Refusing outright would break those. `assumeDraft07` gives them a one-word
|
|
25
|
+
// fix that is written at the CALL SITE, in the caller's own source, where a
|
|
26
|
+
// reviewer reads it — so the reading is a stated decision rather than a silent
|
|
27
|
+
// default. There is no way to get the wrong answer without having written the
|
|
28
|
+
// word down.
|
|
29
|
+
//
|
|
30
|
+
// A document with NO `$schema` is untouched. That is most real documents and
|
|
31
|
+
// all 929 cases of the conformance corpus, and it is not a guess about the
|
|
32
|
+
// dialect: nothing was declared, so nothing contradicts Draft-07.
|
|
33
|
+
//
|
|
34
|
+
// THE ROOT ONLY. `externalDocuments` is a map the caller loads, and the suite's
|
|
35
|
+
// own map holds 37 documents across four dialects of which a given case follows
|
|
36
|
+
// two or three; refusing at registration would refuse documents nothing reads.
|
|
37
|
+
// A `$schema` deeper in a document is likewise not the document's dialect.
|
|
38
|
+
// ===========================================================================
|
|
39
|
+
const types_1 = require("../types");
|
|
40
|
+
const malformed_schema_error_1 = require("./malformed-schema-error");
|
|
41
|
+
const unsupported_dialect_error_1 = require("./unsupported-dialect-error");
|
|
42
|
+
/**
|
|
43
|
+
* Comparable form of a meta-schema URI: case folded, scheme dropped, and a
|
|
44
|
+
* trailing "#" or "/" removed.
|
|
45
|
+
*
|
|
46
|
+
* The scheme is dropped because the two families disagree about it — Draft-07
|
|
47
|
+
* publishes `http://json-schema.org/draft-07/schema#` and 2020-12 publishes
|
|
48
|
+
* `https://json-schema.org/draft/2020-12/schema` — and a document that writes
|
|
49
|
+
* `https` for the first or `http` for the second is naming the same dialect,
|
|
50
|
+
* not a different one. Matching the published string exactly would make the
|
|
51
|
+
* gate depend on which of two equally common spellings a document picked.
|
|
52
|
+
*/
|
|
53
|
+
function normaliseDialectUri(uri) {
|
|
54
|
+
return uri
|
|
55
|
+
.trim()
|
|
56
|
+
.toLowerCase()
|
|
57
|
+
.replace(/^https?:\/\//, "")
|
|
58
|
+
.replace(/[#/]+$/, "");
|
|
59
|
+
}
|
|
60
|
+
const DRAFT07_NORMALISED = normaliseDialectUri("http://json-schema.org/draft-07/schema#");
|
|
61
|
+
/**
|
|
62
|
+
* The released dialects Luq recognises the NAME of and does not implement,
|
|
63
|
+
* each with what it does that Draft-07 does not. They are written out so that
|
|
64
|
+
* "this is a dialect we know and did not build" and "we have never heard of
|
|
65
|
+
* this URI" stay different answers — the same distinction NON_DRAFT07_KEYWORDS
|
|
66
|
+
* draws between an out-of-dialect keyword and an invented one.
|
|
67
|
+
*/
|
|
68
|
+
exports.NON_DRAFT07_DIALECTS = Object.freeze({
|
|
69
|
+
"json-schema.org/schema": "the unversioned alias, which names whichever draft the site publishes " +
|
|
70
|
+
"as current rather than a fixed one",
|
|
71
|
+
"json-schema.org/draft-03/schema": "Draft-03, which spells `required` as a boolean on each property",
|
|
72
|
+
"json-schema.org/draft-04/schema": "Draft-04, whose `exclusiveMaximum` is a boolean modifier, not a bound",
|
|
73
|
+
"json-schema.org/draft-06/schema": "Draft-06, which has no `$comment` and reads `$ref` the Draft-07 way",
|
|
74
|
+
"json-schema.org/draft/2019-09/schema": "2019-09, where `$ref` is an ordinary applicator and its siblings are " +
|
|
75
|
+
"applied, and `format` asserts nothing unless the vocabulary asks",
|
|
76
|
+
"json-schema.org/draft/2020-12/schema": "2020-12, where `$ref` siblings are applied, the tuple form of `items` " +
|
|
77
|
+
"is spelled `prefixItems`, and `format` asserts nothing by default",
|
|
78
|
+
});
|
|
79
|
+
const UNRECOGNISED_DIALECT = "a meta-schema Luq has no reading for, so what its keywords mean is unknown";
|
|
80
|
+
const DIALECT_VALUE_REASON = "the value must be a URI string";
|
|
81
|
+
/**
|
|
82
|
+
* Reads the root `$schema` and refuses a dialect Luq does not implement.
|
|
83
|
+
*
|
|
84
|
+
* Called at both front doors, immediately after "is this a schema at all" and
|
|
85
|
+
* before any keyword is read, so no validator that enforces less than its
|
|
86
|
+
* document states can be reached by either route.
|
|
87
|
+
*
|
|
88
|
+
* A non-string `$schema` is a malformed VALUE rather than an unimplemented
|
|
89
|
+
* dialect — the meta-schema types it as a string — so it goes to the class that
|
|
90
|
+
* answers that question, and it is refused under the opt-out too: the opt-out
|
|
91
|
+
* says "read this dialect as Draft-07", and a number names no dialect.
|
|
92
|
+
*/
|
|
93
|
+
function assertSupportedDialect(document, options) {
|
|
94
|
+
// Read off an untyped object rather than through `Draft07SchemaObject`,
|
|
95
|
+
// which types `$schema` as a string: the document is whatever JSON.parse
|
|
96
|
+
// produced, and a `$schema` that is not a string is exactly what this has to
|
|
97
|
+
// be able to see. The §4.4 boolean form and every non-object fall out here,
|
|
98
|
+
// declaring no dialect.
|
|
99
|
+
if (!(0, types_1.isPlainObject)(document))
|
|
100
|
+
return;
|
|
101
|
+
const declared = document["$schema"];
|
|
102
|
+
if (declared === undefined)
|
|
103
|
+
return;
|
|
104
|
+
if (typeof declared !== "string") {
|
|
105
|
+
throw new malformed_schema_error_1.MalformedSchemaError("$schema", DIALECT_VALUE_REASON, declared);
|
|
106
|
+
}
|
|
107
|
+
const normalised = normaliseDialectUri(declared);
|
|
108
|
+
if (normalised === DRAFT07_NORMALISED)
|
|
109
|
+
return;
|
|
110
|
+
if (options.assumeDraft07 === true)
|
|
111
|
+
return;
|
|
112
|
+
throw new unsupported_dialect_error_1.UnsupportedDialectError(declared, exports.NON_DRAFT07_DIALECTS[normalised] ?? UNRECOGNISED_DIALECT);
|
|
113
|
+
}
|
|
@@ -0,0 +1,109 @@
|
|
|
1
|
+
// ===========================================================================
|
|
2
|
+
// L8 src/json-schema/assert-supported-dialect.ts — the DIALECT gate, read
|
|
3
|
+
// once at the document root before any keyword is.
|
|
4
|
+
//
|
|
5
|
+
// WHY A DEFAULT REFUSAL AND NOT A DIVERGENCE DETECTOR. Refusing only documents
|
|
6
|
+
// that actually USE something 2019-09 changed sounds more precise and is the
|
|
7
|
+
// worse trade. The divergences are not all spellable as keyword names: `$ref`
|
|
8
|
+
// gains siblings, `format` and the two `content*` keywords stop asserting by
|
|
9
|
+
// default, and 2020-12 moves the tuple form of `items` to `prefixItems`. A
|
|
10
|
+
// detector would therefore have to carry a second semantic model of two
|
|
11
|
+
// dialects this library does not implement, and every case it fails to think
|
|
12
|
+
// of is a SILENT wrong answer — which is the exact failure this file exists to
|
|
13
|
+
// stop. The `$ref`-sibling case was itself invisible until it was hunted for.
|
|
14
|
+
// `$schema` is the document's own statement of what it means, so that is what
|
|
15
|
+
// is read.
|
|
16
|
+
//
|
|
17
|
+
// WHAT THE DEFAULT COSTS, and why the opt-out exists. A newer `$schema` over a
|
|
18
|
+
// body that happens to be Draft-07-compatible builds correctly today, and
|
|
19
|
+
// people copy the newest `$schema` line into documents that use nothing new.
|
|
20
|
+
// Refusing outright would break those. `assumeDraft07` gives them a one-word
|
|
21
|
+
// fix that is written at the CALL SITE, in the caller's own source, where a
|
|
22
|
+
// reviewer reads it — so the reading is a stated decision rather than a silent
|
|
23
|
+
// default. There is no way to get the wrong answer without having written the
|
|
24
|
+
// word down.
|
|
25
|
+
//
|
|
26
|
+
// A document with NO `$schema` is untouched. That is most real documents and
|
|
27
|
+
// all 929 cases of the conformance corpus, and it is not a guess about the
|
|
28
|
+
// dialect: nothing was declared, so nothing contradicts Draft-07.
|
|
29
|
+
//
|
|
30
|
+
// THE ROOT ONLY. `externalDocuments` is a map the caller loads, and the suite's
|
|
31
|
+
// own map holds 37 documents across four dialects of which a given case follows
|
|
32
|
+
// two or three; refusing at registration would refuse documents nothing reads.
|
|
33
|
+
// A `$schema` deeper in a document is likewise not the document's dialect.
|
|
34
|
+
// ===========================================================================
|
|
35
|
+
import { isPlainObject } from "../types/index.mjs";
|
|
36
|
+
import { MalformedSchemaError } from "./malformed-schema-error.mjs";
|
|
37
|
+
import { UnsupportedDialectError } from "./unsupported-dialect-error.mjs";
|
|
38
|
+
/**
|
|
39
|
+
* Comparable form of a meta-schema URI: case folded, scheme dropped, and a
|
|
40
|
+
* trailing "#" or "/" removed.
|
|
41
|
+
*
|
|
42
|
+
* The scheme is dropped because the two families disagree about it — Draft-07
|
|
43
|
+
* publishes `http://json-schema.org/draft-07/schema#` and 2020-12 publishes
|
|
44
|
+
* `https://json-schema.org/draft/2020-12/schema` — and a document that writes
|
|
45
|
+
* `https` for the first or `http` for the second is naming the same dialect,
|
|
46
|
+
* not a different one. Matching the published string exactly would make the
|
|
47
|
+
* gate depend on which of two equally common spellings a document picked.
|
|
48
|
+
*/
|
|
49
|
+
function normaliseDialectUri(uri) {
|
|
50
|
+
return uri
|
|
51
|
+
.trim()
|
|
52
|
+
.toLowerCase()
|
|
53
|
+
.replace(/^https?:\/\//, "")
|
|
54
|
+
.replace(/[#/]+$/, "");
|
|
55
|
+
}
|
|
56
|
+
const DRAFT07_NORMALISED = normaliseDialectUri("http://json-schema.org/draft-07/schema#");
|
|
57
|
+
/**
|
|
58
|
+
* The released dialects Luq recognises the NAME of and does not implement,
|
|
59
|
+
* each with what it does that Draft-07 does not. They are written out so that
|
|
60
|
+
* "this is a dialect we know and did not build" and "we have never heard of
|
|
61
|
+
* this URI" stay different answers — the same distinction NON_DRAFT07_KEYWORDS
|
|
62
|
+
* draws between an out-of-dialect keyword and an invented one.
|
|
63
|
+
*/
|
|
64
|
+
export const NON_DRAFT07_DIALECTS = Object.freeze({
|
|
65
|
+
"json-schema.org/schema": "the unversioned alias, which names whichever draft the site publishes " +
|
|
66
|
+
"as current rather than a fixed one",
|
|
67
|
+
"json-schema.org/draft-03/schema": "Draft-03, which spells `required` as a boolean on each property",
|
|
68
|
+
"json-schema.org/draft-04/schema": "Draft-04, whose `exclusiveMaximum` is a boolean modifier, not a bound",
|
|
69
|
+
"json-schema.org/draft-06/schema": "Draft-06, which has no `$comment` and reads `$ref` the Draft-07 way",
|
|
70
|
+
"json-schema.org/draft/2019-09/schema": "2019-09, where `$ref` is an ordinary applicator and its siblings are " +
|
|
71
|
+
"applied, and `format` asserts nothing unless the vocabulary asks",
|
|
72
|
+
"json-schema.org/draft/2020-12/schema": "2020-12, where `$ref` siblings are applied, the tuple form of `items` " +
|
|
73
|
+
"is spelled `prefixItems`, and `format` asserts nothing by default",
|
|
74
|
+
});
|
|
75
|
+
const UNRECOGNISED_DIALECT = "a meta-schema Luq has no reading for, so what its keywords mean is unknown";
|
|
76
|
+
const DIALECT_VALUE_REASON = "the value must be a URI string";
|
|
77
|
+
/**
|
|
78
|
+
* Reads the root `$schema` and refuses a dialect Luq does not implement.
|
|
79
|
+
*
|
|
80
|
+
* Called at both front doors, immediately after "is this a schema at all" and
|
|
81
|
+
* before any keyword is read, so no validator that enforces less than its
|
|
82
|
+
* document states can be reached by either route.
|
|
83
|
+
*
|
|
84
|
+
* A non-string `$schema` is a malformed VALUE rather than an unimplemented
|
|
85
|
+
* dialect — the meta-schema types it as a string — so it goes to the class that
|
|
86
|
+
* answers that question, and it is refused under the opt-out too: the opt-out
|
|
87
|
+
* says "read this dialect as Draft-07", and a number names no dialect.
|
|
88
|
+
*/
|
|
89
|
+
export function assertSupportedDialect(document, options) {
|
|
90
|
+
// Read off an untyped object rather than through `Draft07SchemaObject`,
|
|
91
|
+
// which types `$schema` as a string: the document is whatever JSON.parse
|
|
92
|
+
// produced, and a `$schema` that is not a string is exactly what this has to
|
|
93
|
+
// be able to see. The §4.4 boolean form and every non-object fall out here,
|
|
94
|
+
// declaring no dialect.
|
|
95
|
+
if (!isPlainObject(document))
|
|
96
|
+
return;
|
|
97
|
+
const declared = document["$schema"];
|
|
98
|
+
if (declared === undefined)
|
|
99
|
+
return;
|
|
100
|
+
if (typeof declared !== "string") {
|
|
101
|
+
throw new MalformedSchemaError("$schema", DIALECT_VALUE_REASON, declared);
|
|
102
|
+
}
|
|
103
|
+
const normalised = normaliseDialectUri(declared);
|
|
104
|
+
if (normalised === DRAFT07_NORMALISED)
|
|
105
|
+
return;
|
|
106
|
+
if (options.assumeDraft07 === true)
|
|
107
|
+
return;
|
|
108
|
+
throw new UnsupportedDialectError(declared, NON_DRAFT07_DIALECTS[normalised] ?? UNRECOGNISED_DIALECT);
|
|
109
|
+
}
|
|
@@ -2,6 +2,7 @@ import type { FieldBuilderSurface } from "../builder/builder-surface.types";
|
|
|
2
2
|
import type { FieldEntry } from "../builder/field-entry.types";
|
|
3
3
|
import type { Validator } from "../builder/validator.types";
|
|
4
4
|
import type { GlobalConfig } from "../types/global-config";
|
|
5
|
+
import type { DialectOptions } from "./assert-supported-dialect";
|
|
5
6
|
import type { JsonSchemaBag } from "./json-schema-bag.types";
|
|
6
7
|
/** A value that is not a schema at all. Named, and refused at the boundary. */
|
|
7
8
|
export declare class NotASchemaError extends Error {
|
|
@@ -9,10 +10,28 @@ export declare class NotASchemaError extends Error {
|
|
|
9
10
|
constructor(received: unknown);
|
|
10
11
|
}
|
|
11
12
|
/** One pending `.v()` per declared path, with its callback still unrun. */
|
|
12
|
-
export declare function buildFieldEntries(bag: JsonSchemaBag, schema: unknown): readonly FieldEntry[];
|
|
13
|
+
export declare function buildFieldEntries(bag: JsonSchemaBag, schema: unknown, options?: DialectOptions): readonly FieldEntry[];
|
|
13
14
|
/** The erased front door: the declarations, with nothing compiled yet. */
|
|
14
|
-
export declare function buildFromSchema(bag: JsonSchemaBag, schema: unknown, config?: GlobalConfig): FieldBuilderSurface;
|
|
15
|
+
export declare function buildFromSchema(bag: JsonSchemaBag, schema: unknown, config?: GlobalConfig, options?: DialectOptions): FieldBuilderSurface;
|
|
15
16
|
/**
|
|
17
|
+
* Converts a JSON Schema document into a validator.
|
|
18
|
+
*
|
|
19
|
+
* THE INPUT LIMIT IS DRAFT-07, and it is a limit on what may be handed in, not
|
|
20
|
+
* only a statement of how much of Draft-07 is covered. A document declaring
|
|
21
|
+
* 2019-09 or 2020-12 in its root `$schema` is REFUSED with an
|
|
22
|
+
* `UnsupportedDialectError` rather than read as Draft-07, because the two
|
|
23
|
+
* dialects disagree about what an unchanged keyword means: from 2019-09 on
|
|
24
|
+
* `$ref` is an ordinary applicator whose siblings are applied, while Draft-07
|
|
25
|
+
* §8.3 replaces the node, so `{"$ref": "#/$defs/name", "minLength": 5}` read as
|
|
26
|
+
* Draft-07 loses the `minLength` and accepts a value the document forbids. A
|
|
27
|
+
* document with NO `$schema` is read as Draft-07 and always has been. Pass
|
|
28
|
+
* `{ assumeDraft07: true }` as the fourth argument to read a newer-dialect
|
|
29
|
+
* document under Draft-07 rules deliberately, with that reading's consequences.
|
|
30
|
+
*
|
|
31
|
+
* `T` defaults to `Record<string, unknown>`, never `any`; under the default NO
|
|
32
|
+
* declared path is checked. See the header of this file, which owns that
|
|
33
|
+
* escape hatch.
|
|
34
|
+
*
|
|
16
35
|
* The declared type is put back on by `eraseSchemaValidator`, the fourth
|
|
17
36
|
* function in src/core/type-erasure.ts — the one file the code standard allows
|
|
18
37
|
* to assert. Step 25 expressed this as an OVERLOAD PAIR instead, because
|
|
@@ -20,4 +39,4 @@ export declare function buildFromSchema(bag: JsonSchemaBag, schema: unknown, con
|
|
|
20
39
|
* TypeScript on lenient compatibility rules and so was never audited anywhere.
|
|
21
40
|
* The call below is, in the file where every escape hatch is reviewed together.
|
|
22
41
|
*/
|
|
23
|
-
export declare function fromJsonSchema<T extends object = Record<string, unknown>>(bag: JsonSchemaBag, schema: unknown, config?: GlobalConfig): Validator<T>;
|
|
42
|
+
export declare function fromJsonSchema<T extends object = Record<string, unknown>>(bag: JsonSchemaBag, schema: unknown, config?: GlobalConfig, options?: DialectOptions): Validator<T>;
|