@maroonedog/luq 2.1.0 → 2.3.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 +92 -430
- package/dist/builder/builder-surface.types.d.ts +1 -0
- package/dist/builder/compile-declarations.d.ts +7 -1
- package/dist/builder/compile-declarations.js +18 -8
- package/dist/builder/compile-declarations.mjs +18 -8
- package/dist/builder/create-builder.js +8 -0
- package/dist/builder/create-builder.mjs +8 -0
- package/dist/builder/create-field-builder.js +13 -1
- package/dist/builder/create-field-builder.mjs +13 -1
- package/dist/builder/declared-calls-store.d.ts +9 -0
- package/dist/builder/declared-calls-store.js +19 -0
- package/dist/builder/declared-calls-store.mjs +15 -0
- package/dist/builder/field-builder.types.d.ts +13 -0
- package/dist/builder/field-declared-calls.types.d.ts +6 -0
- package/dist/builder/field-declared-calls.types.js +2 -0
- package/dist/builder/field-declared-calls.types.mjs +1 -0
- package/dist/builder/field-entry.types.d.ts +9 -3
- package/dist/builder/field-options.types.d.ts +26 -0
- package/dist/chain/bundle-paths.types.d.ts +23 -0
- package/dist/chain/bundle-paths.types.js +2 -0
- package/dist/chain/bundle-paths.types.mjs +1 -0
- package/dist/chain/chain-method.types.d.ts +8 -3
- package/dist/chain/chain-node-store.d.ts +5 -0
- package/dist/chain/chain-node-store.js +15 -0
- package/dist/chain/chain-node-store.mjs +11 -0
- package/dist/chain/collect-field-rules.d.ts +13 -2
- package/dist/chain/collect-field-rules.js +10 -3
- package/dist/chain/collect-field-rules.mjs +10 -3
- package/dist/chain/create-chain-node.js +19 -9
- package/dist/chain/create-chain-node.mjs +19 -9
- package/dist/chain/declaration-recorder.port.d.ts +31 -0
- package/dist/chain/declaration-recorder.port.js +17 -0
- package/dist/chain/declaration-recorder.port.mjs +13 -0
- package/dist/chain/declared-call.types.d.ts +15 -0
- package/dist/chain/declared-call.types.js +2 -0
- package/dist/chain/declared-call.types.mjs +1 -0
- package/dist/chain/index.d.ts +3 -1
- package/dist/chain/resolve-args.types.d.ts +4 -2
- package/dist/compile/compile-array-node.d.ts +0 -7
- package/dist/compile/compile-array-node.js +5 -0
- package/dist/compile/compile-array-node.mjs +5 -0
- package/dist/compile/compile-field.d.ts +1 -0
- package/dist/compile/compile-field.js +13 -2
- package/dist/compile/compile-field.mjs +13 -2
- package/dist/compile/compile-schema.js +4 -0
- package/dist/compile/compile-schema.mjs +4 -0
- package/dist/compile/group-array-fields.d.ts +1 -0
- package/dist/compile/split-rules-by-kind.js +27 -7
- package/dist/compile/split-rules-by-kind.mjs +27 -7
- package/dist/compile/validation-plan.types.d.ts +36 -0
- package/dist/core/type-erasure.d.ts +36 -30
- package/dist/core/type-erasure.js +36 -30
- package/dist/core/type-erasure.mjs +36 -30
- package/dist/json-schema/build-from-schema.js +8 -1
- package/dist/json-schema/build-from-schema.mjs +8 -1
- package/dist/json-schema/declare-additional-properties.d.ts +7 -7
- package/dist/json-schema/declare-additional-properties.js +7 -7
- package/dist/json-schema/declare-additional-properties.mjs +7 -7
- package/dist/json-schema/declare-object-keywords.js +4 -4
- package/dist/json-schema/declare-object-keywords.mjs +4 -4
- package/dist/json-schema/flatten-schema.js +1 -1
- package/dist/json-schema/flatten-schema.mjs +1 -1
- package/dist/json-schema/follow-json-pointer.d.ts +7 -6
- package/dist/json-schema/follow-json-pointer.js +24 -24
- package/dist/json-schema/follow-json-pointer.mjs +24 -24
- package/dist/json-schema/ref-resolution-error.js +3 -3
- package/dist/json-schema/ref-resolution-error.mjs +3 -3
- package/dist/json-schema/schema-registry.js +12 -11
- package/dist/json-schema/schema-registry.mjs +12 -11
- package/dist/json-schema/uri-reference.js +12 -12
- package/dist/json-schema/uri-reference.mjs +12 -12
- package/dist/path/create-value-writer.js +12 -12
- package/dist/path/create-value-writer.mjs +12 -12
- package/dist/path/reserved-segment.d.ts +16 -16
- package/dist/path/reserved-segment.js +17 -21
- package/dist/path/reserved-segment.mjs +17 -21
- package/dist/plugin-kit/marker.types.d.ts +18 -0
- package/dist/plugins/index.generated.d.ts +1 -0
- package/dist/plugins/index.generated.js +6 -4
- package/dist/plugins/index.generated.mjs +3 -2
- package/dist/plugins/manifest.generated.js +3 -2
- package/dist/plugins/manifest.generated.mjs +3 -2
- package/dist/plugins/object-additional-properties/select-additional-keys.d.ts +8 -8
- package/dist/plugins/object-additional-properties/select-additional-keys.js +16 -16
- package/dist/plugins/object-additional-properties/select-additional-keys.mjs +16 -16
- package/dist/plugins/stitch/stitch.d.ts +24 -8
- package/dist/plugins/stitch-with/index.d.ts +2 -0
- package/dist/plugins/stitch-with/index.js +5 -0
- package/dist/plugins/stitch-with/index.mjs +1 -0
- package/dist/plugins/stitch-with/stitch-with.d.ts +12 -0
- package/dist/plugins/stitch-with/stitch-with.js +92 -0
- package/dist/plugins/stitch-with/stitch-with.mjs +89 -0
- package/dist/plugins/stitchWith.d.ts +1 -0
- package/dist/plugins/stitchWith.js +2 -0
- package/dist/plugins/stitchWith.mjs +1 -0
- package/dist/plugins/string-min/string-min.js +19 -3
- package/dist/plugins/string-min/string-min.mjs +20 -4
- package/dist/presets/index.d.ts +1 -0
- package/dist/presets/index.js +9 -0
- package/dist/presets/index.mjs +1 -0
- package/dist/presets/presets.d.ts +164 -0
- package/dist/presets/presets.js +79 -0
- package/dist/presets/presets.mjs +76 -0
- package/dist/runtime/create-field-validator.js +22 -8
- package/dist/runtime/create-field-validator.mjs +22 -8
- package/dist/runtime/create-validator.js +38 -8
- package/dist/runtime/create-validator.mjs +38 -8
- package/dist/runtime/field-rule-context.d.ts +32 -0
- package/dist/runtime/field-rule-context.js +48 -0
- package/dist/runtime/field-rule-context.mjs +44 -0
- package/dist/runtime/index-stack.d.ts +29 -4
- package/dist/runtime/index-stack.js +76 -15
- package/dist/runtime/index-stack.mjs +76 -15
- package/dist/runtime/output-writer.js +5 -1
- package/dist/runtime/output-writer.mjs +5 -1
- package/dist/runtime/run-array-node.js +22 -10
- package/dist/runtime/run-array-node.mjs +22 -10
- package/dist/runtime/run-field.js +47 -18
- package/dist/runtime/run-field.mjs +47 -18
- package/dist/runtime/run-plan.js +5 -1
- package/dist/runtime/run-plan.mjs +5 -1
- package/dist/standard-schema/assemble-json-schema.d.ts +4 -0
- package/dist/standard-schema/assemble-json-schema.js +95 -0
- package/dist/standard-schema/assemble-json-schema.mjs +92 -0
- package/dist/standard-schema/declaration-recorder.d.ts +6 -0
- package/dist/standard-schema/declaration-recorder.js +30 -0
- package/dist/standard-schema/declaration-recorder.mjs +27 -0
- package/dist/standard-schema/declarations-unavailable-error.d.ts +4 -0
- package/dist/standard-schema/declarations-unavailable-error.js +32 -0
- package/dist/standard-schema/declarations-unavailable-error.mjs +28 -0
- package/dist/standard-schema/emit-field-schema.d.ts +9 -0
- package/dist/standard-schema/emit-field-schema.js +68 -0
- package/dist/standard-schema/emit-field-schema.mjs +65 -0
- package/dist/standard-schema/index.d.ts +5 -0
- package/dist/standard-schema/index.js +9 -1
- package/dist/standard-schema/index.mjs +4 -0
- package/dist/standard-schema/json-schema-target.d.ts +6 -0
- package/dist/standard-schema/json-schema-target.js +44 -0
- package/dist/standard-schema/json-schema-target.mjs +39 -0
- package/dist/standard-schema/plugin-keyword-map.d.ts +3 -0
- package/dist/standard-schema/plugin-keyword-map.js +93 -0
- package/dist/standard-schema/plugin-keyword-map.mjs +90 -0
- package/dist/standard-schema/split-issue-path.d.ts +6 -4
- package/dist/standard-schema/split-issue-path.js +15 -13
- package/dist/standard-schema/split-issue-path.mjs +15 -13
- package/dist/standard-schema/standard-schema.types.d.ts +8 -7
- package/dist/standard-schema/standard-schema.types.js +6 -6
- package/dist/standard-schema/standard-schema.types.mjs +6 -6
- package/dist/standard-schema/to-standard-json-schema.d.ts +19 -0
- package/dist/standard-schema/to-standard-json-schema.js +36 -0
- package/dist/standard-schema/to-standard-json-schema.mjs +33 -0
- package/dist/standard-schema/to-standard-schema.d.ts +16 -15
- package/dist/standard-schema/to-standard-schema.js +15 -22
- package/dist/standard-schema/to-standard-schema.mjs +15 -22
- package/dist/standard-schema/unrepresentable-rule-error.d.ts +15 -0
- package/dist/standard-schema/unrepresentable-rule-error.js +43 -0
- package/dist/standard-schema/unrepresentable-rule-error.mjs +38 -0
- package/dist/types/index.d.ts +19 -7
- package/dist/types/index.js +7 -7
- package/dist/types/index.mjs +7 -7
- package/package.json +35 -19
|
@@ -6,51 +6,57 @@
|
|
|
6
6
|
// the whole escape hatch in one file.
|
|
7
7
|
// ===========================================================================
|
|
8
8
|
/**
|
|
9
|
-
*
|
|
10
|
-
*
|
|
11
|
-
*
|
|
12
|
-
*
|
|
9
|
+
* Why: a record built up key by key has all its keys at run time but stays
|
|
10
|
+
* Record<string, unknown> statically. The generic on the calling side —
|
|
11
|
+
* AsyncContextBuilder.set's `C & { [P in K]: V }` — is what holds the
|
|
12
|
+
* key-to-value correspondence as a type.
|
|
13
13
|
*/
|
|
14
14
|
export function eraseAssembledRecord(assembled) {
|
|
15
15
|
return assembled;
|
|
16
16
|
}
|
|
17
17
|
/**
|
|
18
|
-
*
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
18
|
+
* Why: a chain is a record carrying one method per plugin in the bag. The
|
|
19
|
+
* keys are all there at run time but the value stays Record<string, unknown>
|
|
20
|
+
* statically, while the matching types are mapped types — which keys appear
|
|
21
|
+
* follows from the type arguments alone and cannot be written where the value
|
|
22
|
+
* is assembled.
|
|
23
|
+
*
|
|
24
|
+
* Soundness depends on the assembly following the same rule the mapped type
|
|
25
|
+
* does: attach a method for a plugin exactly when that plugin declares the
|
|
26
|
+
* slot.
|
|
24
27
|
*/
|
|
25
28
|
export function eraseChainSurface(assembled) {
|
|
26
29
|
return assembled;
|
|
27
30
|
}
|
|
28
31
|
/**
|
|
29
|
-
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
*
|
|
36
|
-
*
|
|
37
|
-
*
|
|
38
|
-
*
|
|
32
|
+
* Why: a builder chain is one record holding the plugins added by use() and
|
|
33
|
+
* the declarations added by v(), and its shape does not change as the chain
|
|
34
|
+
* advances. Its static type does — each step is expressed with type arguments
|
|
35
|
+
* (the bag intersection, the union of declared paths, the conditional that
|
|
36
|
+
* branches on union guard exhaustiveness) that the assembling code has no way
|
|
37
|
+
* to write. For the same reason the runtime knows only the plan and can only
|
|
38
|
+
* answer ValidationResult<unknown>; this boundary is the one place the
|
|
39
|
+
* declared T can be put back.
|
|
40
|
+
*
|
|
41
|
+
* Soundness depends on the erased surface declaring the same member set as
|
|
42
|
+
* the public type, with the implementation structurally conforming to it.
|
|
43
|
+
* Exactly one call site is allowed.
|
|
39
44
|
*/
|
|
40
45
|
export function eraseBuilderSurface(assembled) {
|
|
41
46
|
return assembled;
|
|
42
47
|
}
|
|
43
48
|
/**
|
|
44
|
-
*
|
|
45
|
-
*
|
|
46
|
-
*
|
|
47
|
-
* ValidationResult<unknown
|
|
48
|
-
*
|
|
49
|
-
*
|
|
50
|
-
*
|
|
51
|
-
*
|
|
52
|
-
*
|
|
53
|
-
*
|
|
49
|
+
* Why: building a validator from a JSON Schema read at run time gives the
|
|
50
|
+
* compiler nothing to check the declared T against — the document is a value,
|
|
51
|
+
* not a type. The plan-backed validator can only answer
|
|
52
|
+
* ValidationResult<unknown>, so this boundary is the one place the caller's
|
|
53
|
+
* explicit T can be put back. Same kind of erasure as the builder surface,
|
|
54
|
+
* hence the same home.
|
|
55
|
+
*
|
|
56
|
+
* Soundness depends on the plan-backed validator declaring the same member
|
|
57
|
+
* set as Validator<T>, with the implementation structurally conforming to it.
|
|
58
|
+
* When T disagrees with the actual document the type lies, but the runtime
|
|
59
|
+
* result is still correct. Exactly one call site is allowed.
|
|
54
60
|
*/
|
|
55
61
|
export function eraseSchemaValidator(planBacked) {
|
|
56
62
|
return planBacked;
|
|
@@ -42,7 +42,14 @@ function buildFieldEntries(bag, schema) {
|
|
|
42
42
|
path: declaration.path,
|
|
43
43
|
defaultOf: null,
|
|
44
44
|
applyDefaultToNull: false,
|
|
45
|
-
|
|
45
|
+
normalize: null,
|
|
46
|
+
// No record of declared calls: what is assembled here comes from a
|
|
47
|
+
// document, and nobody called a chain method. null rather than the empty
|
|
48
|
+
// list is what lets a writer say "not known" instead of "none".
|
|
49
|
+
collectRules: (chain) => ({
|
|
50
|
+
rules: collectDeclaredRules(declaration, bag, schema, chain),
|
|
51
|
+
calls: null,
|
|
52
|
+
}),
|
|
46
53
|
}));
|
|
47
54
|
}
|
|
48
55
|
/** The erased front door: the declarations, with nothing compiled yet. */
|
|
@@ -35,7 +35,14 @@ export function buildFieldEntries(bag, schema) {
|
|
|
35
35
|
path: declaration.path,
|
|
36
36
|
defaultOf: null,
|
|
37
37
|
applyDefaultToNull: false,
|
|
38
|
-
|
|
38
|
+
normalize: null,
|
|
39
|
+
// No record of declared calls: what is assembled here comes from a
|
|
40
|
+
// document, and nobody called a chain method. null rather than the empty
|
|
41
|
+
// list is what lets a writer say "not known" instead of "none".
|
|
42
|
+
collectRules: (chain) => ({
|
|
43
|
+
rules: collectDeclaredRules(declaration, bag, schema, chain),
|
|
44
|
+
calls: null,
|
|
45
|
+
}),
|
|
39
46
|
}));
|
|
40
47
|
}
|
|
41
48
|
/** The erased front door: the declarations, with nothing compiled yet. */
|
|
@@ -3,17 +3,17 @@ import type { ConverterChain } from "./apply-keyword-binding";
|
|
|
3
3
|
import type { Draft07SchemaObject } from "./draft07.types";
|
|
4
4
|
import type { StructuralContext } from "./structural-expansion.types";
|
|
5
5
|
/**
|
|
6
|
-
* `patternProperties
|
|
7
|
-
* additionalProperties
|
|
6
|
+
* The keys of `patternProperties`, which are regular expression strings.
|
|
7
|
+
* additionalProperties needs them to pick out the keys that match none.
|
|
8
8
|
*/
|
|
9
9
|
export declare function patternPropertyKeys(schema: Draft07SchemaObject): readonly string[];
|
|
10
10
|
/**
|
|
11
|
-
* BOOLEAN
|
|
11
|
+
* The BOOLEAN form.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* A keyword binding can only carry its own value, so when patterns are present
|
|
14
|
+
* the plugin is called directly. The binding stays either way: it is what
|
|
15
|
+
* holds the keyword table and the compile-time check that the method exists.
|
|
16
16
|
*/
|
|
17
17
|
export declare function applyAdditionalPropertiesBoolean(chain: ConverterChain<"object">, schema: Draft07SchemaObject, allowed: boolean): ConverterChain<"object">;
|
|
18
|
-
/** SCHEMA
|
|
18
|
+
/** The SCHEMA form: whatever matches neither a declaration nor a pattern follows it. */
|
|
19
19
|
export declare function declareAdditionalPropertiesSchema(schema: Draft07SchemaObject, context: StructuralContext): readonly Rule[];
|
|
@@ -7,8 +7,8 @@ const apply_keyword_binding_1 = require("./apply-keyword-binding");
|
|
|
7
7
|
const keyword_map_object_1 = require("./keyword-map-object");
|
|
8
8
|
const NO_RULES = Object.freeze([]);
|
|
9
9
|
/**
|
|
10
|
-
* `patternProperties
|
|
11
|
-
* additionalProperties
|
|
10
|
+
* The keys of `patternProperties`, which are regular expression strings.
|
|
11
|
+
* additionalProperties needs them to pick out the keys that match none.
|
|
12
12
|
*/
|
|
13
13
|
function patternPropertyKeys(schema) {
|
|
14
14
|
const patterns = schema.patternProperties;
|
|
@@ -17,11 +17,11 @@ function patternPropertyKeys(schema) {
|
|
|
17
17
|
return Object.freeze(Object.keys(patterns));
|
|
18
18
|
}
|
|
19
19
|
/**
|
|
20
|
-
* BOOLEAN
|
|
20
|
+
* The BOOLEAN form.
|
|
21
21
|
*
|
|
22
|
-
*
|
|
23
|
-
*
|
|
24
|
-
*
|
|
22
|
+
* A keyword binding can only carry its own value, so when patterns are present
|
|
23
|
+
* the plugin is called directly. The binding stays either way: it is what
|
|
24
|
+
* holds the keyword table and the compile-time check that the method exists.
|
|
25
25
|
*/
|
|
26
26
|
function applyAdditionalPropertiesBoolean(chain, schema, allowed) {
|
|
27
27
|
const patterns = patternPropertyKeys(schema);
|
|
@@ -29,7 +29,7 @@ function applyAdditionalPropertiesBoolean(chain, schema, allowed) {
|
|
|
29
29
|
? (0, apply_keyword_binding_1.applyKeywordBinding)(chain, keyword_map_object_1.additionalPropertiesBinding, allowed)
|
|
30
30
|
: chain.additionalProperties(allowed, undefined, patterns);
|
|
31
31
|
}
|
|
32
|
-
/** SCHEMA
|
|
32
|
+
/** The SCHEMA form: whatever matches neither a declaration nor a pattern follows it. */
|
|
33
33
|
function declareAdditionalPropertiesSchema(schema, context) {
|
|
34
34
|
const additional = schema.additionalProperties;
|
|
35
35
|
if (additional === undefined || typeof additional === "boolean") {
|
|
@@ -2,8 +2,8 @@ import { applyKeywordBinding } from "./apply-keyword-binding.mjs";
|
|
|
2
2
|
import { additionalPropertiesBinding } from "./keyword-map-object.mjs";
|
|
3
3
|
const NO_RULES = Object.freeze([]);
|
|
4
4
|
/**
|
|
5
|
-
* `patternProperties
|
|
6
|
-
* additionalProperties
|
|
5
|
+
* The keys of `patternProperties`, which are regular expression strings.
|
|
6
|
+
* additionalProperties needs them to pick out the keys that match none.
|
|
7
7
|
*/
|
|
8
8
|
export function patternPropertyKeys(schema) {
|
|
9
9
|
const patterns = schema.patternProperties;
|
|
@@ -12,11 +12,11 @@ export function patternPropertyKeys(schema) {
|
|
|
12
12
|
return Object.freeze(Object.keys(patterns));
|
|
13
13
|
}
|
|
14
14
|
/**
|
|
15
|
-
* BOOLEAN
|
|
15
|
+
* The BOOLEAN form.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
19
|
-
*
|
|
17
|
+
* A keyword binding can only carry its own value, so when patterns are present
|
|
18
|
+
* the plugin is called directly. The binding stays either way: it is what
|
|
19
|
+
* holds the keyword table and the compile-time check that the method exists.
|
|
20
20
|
*/
|
|
21
21
|
export function applyAdditionalPropertiesBoolean(chain, schema, allowed) {
|
|
22
22
|
const patterns = patternPropertyKeys(schema);
|
|
@@ -24,7 +24,7 @@ export function applyAdditionalPropertiesBoolean(chain, schema, allowed) {
|
|
|
24
24
|
? applyKeywordBinding(chain, additionalPropertiesBinding, allowed)
|
|
25
25
|
: chain.additionalProperties(allowed, undefined, patterns);
|
|
26
26
|
}
|
|
27
|
-
/** SCHEMA
|
|
27
|
+
/** The SCHEMA form: whatever matches neither a declaration nor a pattern follows it. */
|
|
28
28
|
export function declareAdditionalPropertiesSchema(schema, context) {
|
|
29
29
|
const additional = schema.additionalProperties;
|
|
30
30
|
if (additional === undefined || typeof additional === "boolean") {
|
|
@@ -40,10 +40,10 @@ function declareObjectRules(schema, context) {
|
|
|
40
40
|
}
|
|
41
41
|
const additional = schema.additionalProperties;
|
|
42
42
|
if (typeof additional === "boolean") {
|
|
43
|
-
// §6.5.4
|
|
44
|
-
//
|
|
45
|
-
//
|
|
46
|
-
//
|
|
43
|
+
// §6.5.4 applies to the keys matched by neither properties nor
|
|
44
|
+
// patternProperties. A keyword binding can only carry its own value, so
|
|
45
|
+
// when patterns are present the plugin is called directly. The binding
|
|
46
|
+
// stays: it holds the keyword table and the check that the method exists.
|
|
47
47
|
chain = (0, declare_additional_properties_1.applyAdditionalPropertiesBoolean)(chain, schema, additional);
|
|
48
48
|
}
|
|
49
49
|
return readRules(chain);
|
|
@@ -33,10 +33,10 @@ export function declareObjectRules(schema, context) {
|
|
|
33
33
|
}
|
|
34
34
|
const additional = schema.additionalProperties;
|
|
35
35
|
if (typeof additional === "boolean") {
|
|
36
|
-
// §6.5.4
|
|
37
|
-
//
|
|
38
|
-
//
|
|
39
|
-
//
|
|
36
|
+
// §6.5.4 applies to the keys matched by neither properties nor
|
|
37
|
+
// patternProperties. A keyword binding can only carry its own value, so
|
|
38
|
+
// when patterns are present the plugin is called directly. The binding
|
|
39
|
+
// stays: it holds the keyword table and the check that the method exists.
|
|
40
40
|
chain = applyAdditionalPropertiesBoolean(chain, schema, additional);
|
|
41
41
|
}
|
|
42
42
|
return readRules(chain);
|
|
@@ -91,7 +91,7 @@ function hasRootRuleKeyword(node) {
|
|
|
91
91
|
/** The root node MINUS the three keywords the flattener applies itself. A rest
|
|
92
92
|
* destructuring, so the compiler and not a comment keeps the result a schema. */
|
|
93
93
|
function dropDistributedKeywords(node) {
|
|
94
|
-
const { type, required, allOf, ...residual } = node;
|
|
94
|
+
const { type: _type, required: _required, allOf: _allOf, ...residual } = node;
|
|
95
95
|
return residual;
|
|
96
96
|
}
|
|
97
97
|
/** Children of the root, merged across the `allOf` arms, first arm winning. */
|
|
@@ -86,7 +86,7 @@ function hasRootRuleKeyword(node) {
|
|
|
86
86
|
/** The root node MINUS the three keywords the flattener applies itself. A rest
|
|
87
87
|
* destructuring, so the compiler and not a comment keeps the result a schema. */
|
|
88
88
|
function dropDistributedKeywords(node) {
|
|
89
|
-
const { type, required, allOf, ...residual } = node;
|
|
89
|
+
const { type: _type, required: _required, allOf: _allOf, ...residual } = node;
|
|
90
90
|
return residual;
|
|
91
91
|
}
|
|
92
92
|
/** Children of the root, merged across the `allOf` arms, first arm winning. */
|
|
@@ -8,14 +8,15 @@ export declare function toPointerTokens(fragment: string): readonly string[];
|
|
|
8
8
|
*/
|
|
9
9
|
export declare function stepInto(current: unknown, token: string): unknown;
|
|
10
10
|
/**
|
|
11
|
-
*
|
|
11
|
+
* Walks the pointer while **counting every `$id` crossed on the way**.
|
|
12
12
|
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
*
|
|
13
|
+
* When an intermediate node along the path carries `$id: "folder/"`, a
|
|
14
|
+
* relative `$ref` written deeper in must resolve under folder/. Looking only
|
|
15
|
+
* at the `$id` of the node landed on loses every node passed through.
|
|
16
16
|
*
|
|
17
|
-
*
|
|
18
|
-
*
|
|
17
|
+
* How the base advances is supplied by the caller. This function only needs
|
|
18
|
+
* to know which nodes were crossed and in what order; it does no URI
|
|
19
|
+
* arithmetic of its own.
|
|
19
20
|
*/
|
|
20
21
|
export declare function walkPointer<TScope>(fragment: string, document: unknown, scope: TScope, advance: (scope: TScope, node: unknown) => TScope, onMissing: (token: string) => never): {
|
|
21
22
|
readonly node: unknown;
|
|
@@ -4,13 +4,12 @@ exports.toPointerTokens = toPointerTokens;
|
|
|
4
4
|
exports.stepInto = stepInto;
|
|
5
5
|
exports.walkPointer = walkPointer;
|
|
6
6
|
// ===========================================================================
|
|
7
|
-
// L8 src/json-schema/follow-json-pointer.ts — RFC 6901
|
|
7
|
+
// L8 src/json-schema/follow-json-pointer.ts — walks an RFC 6901 pointer.
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
//
|
|
13
|
-
// なるからである。
|
|
9
|
+
// Answers only WHERE INSIDE a document, never WHICH document. Choosing the
|
|
10
|
+
// document is a separate job, kept separate because base-URI arithmetic and
|
|
11
|
+
// pointer decoding are different problems and neither reads well once they
|
|
12
|
+
// share a file.
|
|
14
13
|
// ===========================================================================
|
|
15
14
|
const types_1 = require("../types");
|
|
16
15
|
/** RFC 6901: `~1` is "/" and `~0` is "~", decoded in that order. */
|
|
@@ -18,18 +17,18 @@ function decodePointerToken(token) {
|
|
|
18
17
|
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
19
18
|
}
|
|
20
19
|
/**
|
|
21
|
-
* `$ref`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
20
|
+
* A `$ref` is a URI and the pointer is its fragment. RFC 6901 §6 says the
|
|
21
|
+
* fragment is percent-encoded by the fragment rules, so **the whole fragment
|
|
22
|
+
* is decoded before splitting on slashes**.
|
|
24
23
|
*
|
|
25
|
-
*
|
|
26
|
-
* `/definitions/percent%field`
|
|
27
|
-
*
|
|
28
|
-
*
|
|
24
|
+
* The order matters. `#/definitions/percent%25field` decodes to
|
|
25
|
+
* `/definitions/percent%field` and is split from there. Splitting first and
|
|
26
|
+
* decoding each token does decode `%25`, but then `%2F` turns back into a
|
|
27
|
+
* separator, which is not what the spec says it means.
|
|
29
28
|
*
|
|
30
|
-
*
|
|
31
|
-
*
|
|
32
|
-
*
|
|
29
|
+
* decodeURIComponent throws on a malformed sequence like `%zz`, and a
|
|
30
|
+
* pointer that cannot be decoded is used as-is. Throwing here would make one
|
|
31
|
+
* broken pointer take the whole document down.
|
|
33
32
|
*/
|
|
34
33
|
function decodeFragment(pointer) {
|
|
35
34
|
try {
|
|
@@ -44,8 +43,8 @@ function toPointerTokens(fragment) {
|
|
|
44
43
|
const pointer = decodeFragment(fragment);
|
|
45
44
|
if (pointer === "")
|
|
46
45
|
return [];
|
|
47
|
-
// "/"
|
|
48
|
-
//
|
|
46
|
+
// "/" is the empty-string key directly under the root, not an empty token
|
|
47
|
+
// list. Returning [] here would turn a pointer at `{"": ...}` into the root.
|
|
49
48
|
return pointer.split("/").slice(1).map(decodePointerToken);
|
|
50
49
|
}
|
|
51
50
|
/**
|
|
@@ -65,14 +64,15 @@ function stepInto(current, token) {
|
|
|
65
64
|
return current[token];
|
|
66
65
|
}
|
|
67
66
|
/**
|
|
68
|
-
*
|
|
67
|
+
* Walks the pointer while **counting every `$id` crossed on the way**.
|
|
69
68
|
*
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
69
|
+
* When an intermediate node along the path carries `$id: "folder/"`, a
|
|
70
|
+
* relative `$ref` written deeper in must resolve under folder/. Looking only
|
|
71
|
+
* at the `$id` of the node landed on loses every node passed through.
|
|
73
72
|
*
|
|
74
|
-
*
|
|
75
|
-
*
|
|
73
|
+
* How the base advances is supplied by the caller. This function only needs
|
|
74
|
+
* to know which nodes were crossed and in what order; it does no URI
|
|
75
|
+
* arithmetic of its own.
|
|
76
76
|
*/
|
|
77
77
|
function walkPointer(fragment, document, scope, advance, onMissing) {
|
|
78
78
|
let current = document;
|
|
@@ -1,11 +1,10 @@
|
|
|
1
1
|
// ===========================================================================
|
|
2
|
-
// L8 src/json-schema/follow-json-pointer.ts — RFC 6901
|
|
2
|
+
// L8 src/json-schema/follow-json-pointer.ts — walks an RFC 6901 pointer.
|
|
3
3
|
//
|
|
4
|
-
//
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
8
|
-
// なるからである。
|
|
4
|
+
// Answers only WHERE INSIDE a document, never WHICH document. Choosing the
|
|
5
|
+
// document is a separate job, kept separate because base-URI arithmetic and
|
|
6
|
+
// pointer decoding are different problems and neither reads well once they
|
|
7
|
+
// share a file.
|
|
9
8
|
// ===========================================================================
|
|
10
9
|
import { isArray, isPlainObject } from "../types/index.mjs";
|
|
11
10
|
/** RFC 6901: `~1` is "/" and `~0` is "~", decoded in that order. */
|
|
@@ -13,18 +12,18 @@ function decodePointerToken(token) {
|
|
|
13
12
|
return token.replace(/~1/g, "/").replace(/~0/g, "~");
|
|
14
13
|
}
|
|
15
14
|
/**
|
|
16
|
-
* `$ref`
|
|
17
|
-
*
|
|
18
|
-
*
|
|
15
|
+
* A `$ref` is a URI and the pointer is its fragment. RFC 6901 §6 says the
|
|
16
|
+
* fragment is percent-encoded by the fragment rules, so **the whole fragment
|
|
17
|
+
* is decoded before splitting on slashes**.
|
|
19
18
|
*
|
|
20
|
-
*
|
|
21
|
-
* `/definitions/percent%field`
|
|
22
|
-
*
|
|
23
|
-
*
|
|
19
|
+
* The order matters. `#/definitions/percent%25field` decodes to
|
|
20
|
+
* `/definitions/percent%field` and is split from there. Splitting first and
|
|
21
|
+
* decoding each token does decode `%25`, but then `%2F` turns back into a
|
|
22
|
+
* separator, which is not what the spec says it means.
|
|
24
23
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
24
|
+
* decodeURIComponent throws on a malformed sequence like `%zz`, and a
|
|
25
|
+
* pointer that cannot be decoded is used as-is. Throwing here would make one
|
|
26
|
+
* broken pointer take the whole document down.
|
|
28
27
|
*/
|
|
29
28
|
function decodeFragment(pointer) {
|
|
30
29
|
try {
|
|
@@ -39,8 +38,8 @@ export function toPointerTokens(fragment) {
|
|
|
39
38
|
const pointer = decodeFragment(fragment);
|
|
40
39
|
if (pointer === "")
|
|
41
40
|
return [];
|
|
42
|
-
// "/"
|
|
43
|
-
//
|
|
41
|
+
// "/" is the empty-string key directly under the root, not an empty token
|
|
42
|
+
// list. Returning [] here would turn a pointer at `{"": ...}` into the root.
|
|
44
43
|
return pointer.split("/").slice(1).map(decodePointerToken);
|
|
45
44
|
}
|
|
46
45
|
/**
|
|
@@ -60,14 +59,15 @@ export function stepInto(current, token) {
|
|
|
60
59
|
return current[token];
|
|
61
60
|
}
|
|
62
61
|
/**
|
|
63
|
-
*
|
|
62
|
+
* Walks the pointer while **counting every `$id` crossed on the way**.
|
|
64
63
|
*
|
|
65
|
-
*
|
|
66
|
-
*
|
|
67
|
-
*
|
|
64
|
+
* When an intermediate node along the path carries `$id: "folder/"`, a
|
|
65
|
+
* relative `$ref` written deeper in must resolve under folder/. Looking only
|
|
66
|
+
* at the `$id` of the node landed on loses every node passed through.
|
|
68
67
|
*
|
|
69
|
-
*
|
|
70
|
-
*
|
|
68
|
+
* How the base advances is supplied by the caller. This function only needs
|
|
69
|
+
* to know which nodes were crossed and in what order; it does no URI
|
|
70
|
+
* arithmetic of its own.
|
|
71
71
|
*/
|
|
72
72
|
export function walkPointer(fragment, document, scope, advance, onMissing) {
|
|
73
73
|
let current = document;
|
|
@@ -2,9 +2,9 @@
|
|
|
2
2
|
// ===========================================================================
|
|
3
3
|
// L8 src/json-schema/ref-resolution-error.ts
|
|
4
4
|
//
|
|
5
|
-
// `$ref`
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// Raised when a `$ref` cannot be resolved. Callers must be able to catch it
|
|
6
|
+
// **by identity**, so it is its own class — and its own module, so catching it
|
|
7
|
+
// does not drag in the resolver's dependencies.
|
|
8
8
|
// ===========================================================================
|
|
9
9
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
10
10
|
exports.RefResolutionError = void 0;
|
|
@@ -1,9 +1,9 @@
|
|
|
1
1
|
// ===========================================================================
|
|
2
2
|
// L8 src/json-schema/ref-resolution-error.ts
|
|
3
3
|
//
|
|
4
|
-
// `$ref`
|
|
5
|
-
//
|
|
6
|
-
//
|
|
4
|
+
// Raised when a `$ref` cannot be resolved. Callers must be able to catch it
|
|
5
|
+
// **by identity**, so it is its own class — and its own module, so catching it
|
|
6
|
+
// does not drag in the resolver's dependencies.
|
|
7
7
|
// ===========================================================================
|
|
8
8
|
export class RefResolutionError extends Error {
|
|
9
9
|
constructor(ref, reason) {
|
|
@@ -2,19 +2,20 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.createSchemaRegistry = createSchemaRegistry;
|
|
4
4
|
// ===========================================================================
|
|
5
|
-
// L8 src/json-schema/schema-registry.ts —
|
|
5
|
+
// L8 src/json-schema/schema-registry.ts — which URI names which schema.
|
|
6
6
|
//
|
|
7
|
-
// Draft-07 §8.2
|
|
8
|
-
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
7
|
+
// Draft-07 §8.2 gives `$id` two jobs: a URI that names a location re-bases
|
|
8
|
+
// what follows, and the `#name` form gives a **location-independent name**.
|
|
9
|
+
// Both are the same index — this URI is that node — which is this file's whole
|
|
10
|
+
// responsibility. Walking a pointer is about location, and lives elsewhere.
|
|
11
11
|
//
|
|
12
|
-
//
|
|
13
|
-
//
|
|
14
|
-
//
|
|
15
|
-
// *
|
|
16
|
-
// *
|
|
17
|
-
//
|
|
12
|
+
// External documents are **only what the caller passed in**; nothing is
|
|
13
|
+
// fetched. Taking a map rather than a loader function is what makes all three
|
|
14
|
+
// of these true at once:
|
|
15
|
+
// * a URI written in a schema can never make this process open a socket,
|
|
16
|
+
// * conversion stays synchronous, so it works under CSP,
|
|
17
|
+
// * everything that could possibly be read is visible in the caller's code.
|
|
18
|
+
// An async loader gives up all three.
|
|
18
19
|
// ===========================================================================
|
|
19
20
|
const draft07_types_1 = require("./draft07.types");
|
|
20
21
|
const types_1 = require("../types");
|
|
@@ -1,17 +1,18 @@
|
|
|
1
1
|
// ===========================================================================
|
|
2
|
-
// L8 src/json-schema/schema-registry.ts —
|
|
2
|
+
// L8 src/json-schema/schema-registry.ts — which URI names which schema.
|
|
3
3
|
//
|
|
4
|
-
// Draft-07 §8.2
|
|
5
|
-
//
|
|
6
|
-
//
|
|
7
|
-
//
|
|
4
|
+
// Draft-07 §8.2 gives `$id` two jobs: a URI that names a location re-bases
|
|
5
|
+
// what follows, and the `#name` form gives a **location-independent name**.
|
|
6
|
+
// Both are the same index — this URI is that node — which is this file's whole
|
|
7
|
+
// responsibility. Walking a pointer is about location, and lives elsewhere.
|
|
8
8
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// *
|
|
13
|
-
// *
|
|
14
|
-
//
|
|
9
|
+
// External documents are **only what the caller passed in**; nothing is
|
|
10
|
+
// fetched. Taking a map rather than a loader function is what makes all three
|
|
11
|
+
// of these true at once:
|
|
12
|
+
// * a URI written in a schema can never make this process open a socket,
|
|
13
|
+
// * conversion stays synchronous, so it works under CSP,
|
|
14
|
+
// * everything that could possibly be read is visible in the caller's code.
|
|
15
|
+
// An async loader gives up all three.
|
|
15
16
|
// ===========================================================================
|
|
16
17
|
import { isDraft07Schema, isSchemaObject } from "./draft07.types.mjs";
|
|
17
18
|
import { isArray, isPlainObject } from "../types/index.mjs";
|
|
@@ -1,20 +1,20 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
// ===========================================================================
|
|
3
|
-
// L8 src/json-schema/uri-reference.ts —
|
|
3
|
+
// L8 src/json-schema/uri-reference.ts — the URI arithmetic of `$id`/`$ref`.
|
|
4
4
|
//
|
|
5
|
-
// Draft-07 §8.2
|
|
6
|
-
//
|
|
7
|
-
//
|
|
5
|
+
// Draft-07 §8.2 makes `$id` establish a base URI that `$ref` resolves
|
|
6
|
+
// against. A `$ref` is therefore a **URI reference** and not a pointer within
|
|
7
|
+
// a document: the same string points somewhere else depending on which `$id`
|
|
8
|
+
// it was written under.
|
|
8
9
|
//
|
|
9
|
-
//
|
|
10
|
-
//
|
|
11
|
-
//
|
|
12
|
-
// eval
|
|
10
|
+
// Resolution is delegated to the WHATWG URL. Rewriting RFC 3986 §5.3 by hand
|
|
11
|
+
// goes wrong on percent-encoding, dot segments and scheme-relative
|
|
12
|
+
// (`//host/x`) every time — and URL is a standard global in both browsers and
|
|
13
|
+
// Node, needing neither eval nor new Function.
|
|
13
14
|
//
|
|
14
|
-
//
|
|
15
|
-
//
|
|
16
|
-
//
|
|
17
|
-
// このプロセスがソケットを開くことは無い。
|
|
15
|
+
// **Nothing here touches the network.** This is string arithmetic; how a
|
|
16
|
+
// resolved URI is actually obtained is the caller's responsibility. A URI
|
|
17
|
+
// written in a schema never causes this process to open a socket.
|
|
18
18
|
// ===========================================================================
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
20
|
exports.splitUri = splitUri;
|