@maroonedog/luq 2.4.3 → 2.5.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 +199 -9
- package/dist/chain/field-chain.types.d.ts +11 -1
- package/dist/chain/index.d.ts +2 -0
- package/dist/chain/plugin-not-imported.types.d.ts +40 -0
- package/dist/chain/plugin-not-imported.types.js +2 -0
- package/dist/chain/plugin-not-imported.types.mjs +1 -0
- package/dist/chain/slot-catalog.generated.d.ts +265 -0
- package/dist/chain/slot-catalog.generated.js +4 -0
- package/dist/chain/slot-catalog.generated.mjs +3 -0
- package/dist/core/type-erasure.d.ts +20 -0
- package/dist/core/type-erasure.js +23 -0
- package/dist/core/type-erasure.mjs +22 -0
- package/dist/field-rule/use-field.d.ts +2 -1
- package/dist/field-rule/use-field.js +9 -2
- package/dist/field-rule/use-field.mjs +9 -2
- 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/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 +1 -1
- package/dist/json-schema/extensions/json-schema/index.js +2 -1
- package/dist/json-schema/extensions/json-schema/index.mjs +1 -1
- 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 +1 -0
- package/dist/json-schema/index.js +3 -1
- package/dist/json-schema/index.mjs +1 -0
- 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 +2 -0
- package/dist/json-schema/keyword-map.mjs +2 -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/plugins/manifest.generated.d.ts +18 -0
- package/dist/plugins/manifest.generated.js +77 -77
- package/dist/plugins/manifest.generated.mjs +77 -77
- package/dist/plugins/one-of/one-of.js +18 -4
- package/dist/plugins/one-of/one-of.mjs +18 -4
- package/dist/schema-tooling/index.d.ts +11 -0
- package/dist/schema-tooling/index.js +12 -1
- package/dist/schema-tooling/index.mjs +10 -0
- package/package.json +8 -6
|
@@ -8,4 +8,4 @@
|
|
|
8
8
|
// a consumer of this subpath pays only for the plugins they import themselves.
|
|
9
9
|
// ===========================================================================
|
|
10
10
|
export { SCHEMA_BRANCH_LABEL, collectDocumentRules, jsonSchemaPlugin, } from "./json-schema.mjs";
|
|
11
|
-
export { NotASchemaError, UnsupportedKeywordError, RefResolutionError, buildFieldEntries, buildFromSchema, fromJsonSchema, isDraft07Schema, listBoundPluginNames, listDraft07Keywords, listFormatNames, } from "../../index.mjs";
|
|
11
|
+
export { MalformedSchemaError, NotASchemaError, UnsupportedKeywordError, RefResolutionError, buildFieldEntries, buildFromSchema, fromJsonSchema, isDraft07Schema, listBoundPluginNames, listDraft07Keywords, listFormatNames, } from "../../index.mjs";
|
|
@@ -6,6 +6,10 @@ export declare const EACH_STEP = "[*]";
|
|
|
6
6
|
/**
|
|
7
7
|
* The single form only. The tuple form gets no child path: element 0 and
|
|
8
8
|
* element 1 obey DIFFERENT schemas, and one declared `[*]` cannot say that.
|
|
9
|
+
*
|
|
10
|
+
* Reading through readCheckedItems is what stops a non-schema value here from
|
|
11
|
+
* becoming a child declaration whose sub-schema yields no rules at all; see
|
|
12
|
+
* array-keyword-guards.ts.
|
|
9
13
|
*/
|
|
10
14
|
export declare function readItemChildren(schema: Draft07SchemaObject): readonly ChildSchema[];
|
|
11
15
|
export declare function composeTupleItems(schema: Draft07SchemaObject, context: StructuralContext): readonly Rule[];
|
|
@@ -13,6 +17,10 @@ export declare function composeTupleItems(schema: Draft07SchemaObject, context:
|
|
|
13
17
|
* `contains` is EXISTENTIAL: at least one element matches. arrayContains owns
|
|
14
18
|
* that reduction, and its default bounds (min 1, no max) are exactly the
|
|
15
19
|
* draft's, so this is one call and no arithmetic.
|
|
20
|
+
*
|
|
21
|
+
* An element branch holding no rules would satisfy the existence check on the
|
|
22
|
+
* first element and turn the keyword into "the array is non-empty", so the
|
|
23
|
+
* value is read through array-keyword-guards.ts.
|
|
16
24
|
*/
|
|
17
25
|
export declare function composeContains(schema: Draft07SchemaObject, context: StructuralContext): readonly Rule[];
|
|
18
26
|
/**
|
|
@@ -20,6 +28,8 @@ export declare function composeContains(schema: Draft07SchemaObject, context: St
|
|
|
20
28
|
* and `maxItems` to `maxLength`; writing "minItems" as the method name does not
|
|
21
29
|
* compile (keyword-map-array.ts), which is the C2 regression made impossible.
|
|
22
30
|
* `uniqueItems: false` never reaches its binding: §6.4.3 gives it no effect and
|
|
23
|
-
* the binding's value type is `true`.
|
|
31
|
+
* the binding's value type is `true`. That is why the value is read through
|
|
32
|
+
* readCheckedUniqueItems: with a bare `=== true`, a non-boolean would take the
|
|
33
|
+
* same silent route as the lawful `false` and lose the constraint entirely.
|
|
24
34
|
*/
|
|
25
35
|
export declare function declareArrayRules(schema: Draft07SchemaObject, context: StructuralContext): readonly Rule[];
|
|
@@ -33,6 +33,7 @@ const create_chain_node_1 = require("../chain/create-chain-node");
|
|
|
33
33
|
const create_field_slots_1 = require("../chain/create-field-slots");
|
|
34
34
|
const create_rule_1 = require("../plugin-kit/create-rule");
|
|
35
35
|
const apply_keyword_binding_1 = require("./apply-keyword-binding");
|
|
36
|
+
const array_keyword_guards_1 = require("./array-keyword-guards");
|
|
36
37
|
const keyword_map_array_1 = require("./keyword-map-array");
|
|
37
38
|
const types_1 = require("../types");
|
|
38
39
|
const collect_definitions_1 = require("./collect-definitions");
|
|
@@ -47,9 +48,13 @@ function isTupleItems(items) {
|
|
|
47
48
|
/**
|
|
48
49
|
* The single form only. The tuple form gets no child path: element 0 and
|
|
49
50
|
* element 1 obey DIFFERENT schemas, and one declared `[*]` cannot say that.
|
|
51
|
+
*
|
|
52
|
+
* Reading through readCheckedItems is what stops a non-schema value here from
|
|
53
|
+
* becoming a child declaration whose sub-schema yields no rules at all; see
|
|
54
|
+
* array-keyword-guards.ts.
|
|
50
55
|
*/
|
|
51
56
|
function readItemChildren(schema) {
|
|
52
|
-
const items = schema
|
|
57
|
+
const items = (0, array_keyword_guards_1.readCheckedItems)(schema);
|
|
53
58
|
if (items === undefined || isTupleItems(items))
|
|
54
59
|
return NO_CHILDREN;
|
|
55
60
|
return Object.freeze([{ step: exports.EACH_STEP, schema: items, isRequired: false }]);
|
|
@@ -58,7 +63,9 @@ function readItemChildren(schema) {
|
|
|
58
63
|
* Element i against position i, extra elements against `additionalItems`.
|
|
59
64
|
* A non-array passes, a short array passes, and `additionalItems: false`
|
|
60
65
|
* becomes the schema that matches nothing (collect-definitions), so the
|
|
61
|
-
* "no extra elements" case needs no fourth branch kind.
|
|
66
|
+
* "no extra elements" case needs no fourth branch kind. A rest branch built
|
|
67
|
+
* from a non-schema would carry no rules and check none of those elements,
|
|
68
|
+
* which is why the value is read through array-keyword-guards.ts.
|
|
62
69
|
*/
|
|
63
70
|
function applyPositionally(runners, positionCount, hasRest) {
|
|
64
71
|
return (value, ctx) => {
|
|
@@ -85,11 +92,11 @@ function describePosition(index) {
|
|
|
85
92
|
: `Element ${String(index)} does not match the schema declared for it`;
|
|
86
93
|
}
|
|
87
94
|
function composeTupleItems(schema, context) {
|
|
88
|
-
const items = schema
|
|
95
|
+
const items = (0, array_keyword_guards_1.readCheckedItems)(schema);
|
|
89
96
|
if (items === undefined || !isTupleItems(items))
|
|
90
97
|
return NO_RULES;
|
|
91
98
|
const branches = items.map((position, index) => context.toBranch(`position:${String(index)}`, position));
|
|
92
|
-
const rest = schema
|
|
99
|
+
const rest = (0, array_keyword_guards_1.readCheckedAdditionalItems)(schema);
|
|
93
100
|
const hasRest = rest !== undefined;
|
|
94
101
|
if (rest !== undefined)
|
|
95
102
|
branches.push(context.toBranch("rest", rest));
|
|
@@ -109,9 +116,13 @@ function composeTupleItems(schema, context) {
|
|
|
109
116
|
* `contains` is EXISTENTIAL: at least one element matches. arrayContains owns
|
|
110
117
|
* that reduction, and its default bounds (min 1, no max) are exactly the
|
|
111
118
|
* draft's, so this is one call and no arithmetic.
|
|
119
|
+
*
|
|
120
|
+
* An element branch holding no rules would satisfy the existence check on the
|
|
121
|
+
* first element and turn the keyword into "the array is non-empty", so the
|
|
122
|
+
* value is read through array-keyword-guards.ts.
|
|
112
123
|
*/
|
|
113
124
|
function composeContains(schema, context) {
|
|
114
|
-
const contains = schema
|
|
125
|
+
const contains = (0, array_keyword_guards_1.readCheckedContains)(schema);
|
|
115
126
|
if (contains === undefined)
|
|
116
127
|
return NO_RULES;
|
|
117
128
|
const element = context.collectSubSchemaRules((0, collect_definitions_1.toSchemaObject)(contains));
|
|
@@ -124,7 +135,9 @@ function composeContains(schema, context) {
|
|
|
124
135
|
* and `maxItems` to `maxLength`; writing "minItems" as the method name does not
|
|
125
136
|
* compile (keyword-map-array.ts), which is the C2 regression made impossible.
|
|
126
137
|
* `uniqueItems: false` never reaches its binding: §6.4.3 gives it no effect and
|
|
127
|
-
* the binding's value type is `true`.
|
|
138
|
+
* the binding's value type is `true`. That is why the value is read through
|
|
139
|
+
* readCheckedUniqueItems: with a bare `=== true`, a non-boolean would take the
|
|
140
|
+
* same silent route as the lawful `false` and lose the constraint entirely.
|
|
128
141
|
*/
|
|
129
142
|
function declareArrayRules(schema, context) {
|
|
130
143
|
let chain = (0, create_field_slots_1.createFieldSlots)(context.bag, context.build).array;
|
|
@@ -134,7 +147,7 @@ function declareArrayRules(schema, context) {
|
|
|
134
147
|
if (schema.maxItems !== undefined) {
|
|
135
148
|
chain = (0, apply_keyword_binding_1.applyKeywordBinding)(chain, keyword_map_array_1.maxItemsBinding, schema.maxItems);
|
|
136
149
|
}
|
|
137
|
-
if (schema
|
|
150
|
+
if ((0, array_keyword_guards_1.readCheckedUniqueItems)(schema) === true) {
|
|
138
151
|
chain = (0, apply_keyword_binding_1.applyKeywordBinding)(chain, keyword_map_array_1.uniqueItemsBinding, true);
|
|
139
152
|
}
|
|
140
153
|
return (0, create_chain_node_1.readChainRules)(chain) ?? NO_RULES;
|
|
@@ -26,6 +26,7 @@ import { readChainRules } from "../chain/create-chain-node.mjs";
|
|
|
26
26
|
import { createFieldSlots } from "../chain/create-field-slots.mjs";
|
|
27
27
|
import { composite } from "../plugin-kit/create-rule.mjs";
|
|
28
28
|
import { applyKeywordBinding } from "./apply-keyword-binding.mjs";
|
|
29
|
+
import { readCheckedAdditionalItems, readCheckedContains, readCheckedItems, readCheckedUniqueItems, } from "./array-keyword-guards.mjs";
|
|
29
30
|
import { maxItemsBinding, minItemsBinding, uniqueItemsBinding, } from "./keyword-map-array.mjs";
|
|
30
31
|
import { PASS, fail, isArray, isNumber } from "../types/index.mjs";
|
|
31
32
|
import { toSchemaObject } from "./collect-definitions.mjs";
|
|
@@ -40,9 +41,13 @@ function isTupleItems(items) {
|
|
|
40
41
|
/**
|
|
41
42
|
* The single form only. The tuple form gets no child path: element 0 and
|
|
42
43
|
* element 1 obey DIFFERENT schemas, and one declared `[*]` cannot say that.
|
|
44
|
+
*
|
|
45
|
+
* Reading through readCheckedItems is what stops a non-schema value here from
|
|
46
|
+
* becoming a child declaration whose sub-schema yields no rules at all; see
|
|
47
|
+
* array-keyword-guards.ts.
|
|
43
48
|
*/
|
|
44
49
|
export function readItemChildren(schema) {
|
|
45
|
-
const items = schema
|
|
50
|
+
const items = readCheckedItems(schema);
|
|
46
51
|
if (items === undefined || isTupleItems(items))
|
|
47
52
|
return NO_CHILDREN;
|
|
48
53
|
return Object.freeze([{ step: EACH_STEP, schema: items, isRequired: false }]);
|
|
@@ -51,7 +56,9 @@ export function readItemChildren(schema) {
|
|
|
51
56
|
* Element i against position i, extra elements against `additionalItems`.
|
|
52
57
|
* A non-array passes, a short array passes, and `additionalItems: false`
|
|
53
58
|
* becomes the schema that matches nothing (collect-definitions), so the
|
|
54
|
-
* "no extra elements" case needs no fourth branch kind.
|
|
59
|
+
* "no extra elements" case needs no fourth branch kind. A rest branch built
|
|
60
|
+
* from a non-schema would carry no rules and check none of those elements,
|
|
61
|
+
* which is why the value is read through array-keyword-guards.ts.
|
|
55
62
|
*/
|
|
56
63
|
function applyPositionally(runners, positionCount, hasRest) {
|
|
57
64
|
return (value, ctx) => {
|
|
@@ -78,11 +85,11 @@ function describePosition(index) {
|
|
|
78
85
|
: `Element ${String(index)} does not match the schema declared for it`;
|
|
79
86
|
}
|
|
80
87
|
export function composeTupleItems(schema, context) {
|
|
81
|
-
const items = schema
|
|
88
|
+
const items = readCheckedItems(schema);
|
|
82
89
|
if (items === undefined || !isTupleItems(items))
|
|
83
90
|
return NO_RULES;
|
|
84
91
|
const branches = items.map((position, index) => context.toBranch(`position:${String(index)}`, position));
|
|
85
|
-
const rest = schema
|
|
92
|
+
const rest = readCheckedAdditionalItems(schema);
|
|
86
93
|
const hasRest = rest !== undefined;
|
|
87
94
|
if (rest !== undefined)
|
|
88
95
|
branches.push(context.toBranch("rest", rest));
|
|
@@ -102,9 +109,13 @@ export function composeTupleItems(schema, context) {
|
|
|
102
109
|
* `contains` is EXISTENTIAL: at least one element matches. arrayContains owns
|
|
103
110
|
* that reduction, and its default bounds (min 1, no max) are exactly the
|
|
104
111
|
* draft's, so this is one call and no arithmetic.
|
|
112
|
+
*
|
|
113
|
+
* An element branch holding no rules would satisfy the existence check on the
|
|
114
|
+
* first element and turn the keyword into "the array is non-empty", so the
|
|
115
|
+
* value is read through array-keyword-guards.ts.
|
|
105
116
|
*/
|
|
106
117
|
export function composeContains(schema, context) {
|
|
107
|
-
const contains = schema
|
|
118
|
+
const contains = readCheckedContains(schema);
|
|
108
119
|
if (contains === undefined)
|
|
109
120
|
return NO_RULES;
|
|
110
121
|
const element = context.collectSubSchemaRules(toSchemaObject(contains));
|
|
@@ -117,7 +128,9 @@ export function composeContains(schema, context) {
|
|
|
117
128
|
* and `maxItems` to `maxLength`; writing "minItems" as the method name does not
|
|
118
129
|
* compile (keyword-map-array.ts), which is the C2 regression made impossible.
|
|
119
130
|
* `uniqueItems: false` never reaches its binding: §6.4.3 gives it no effect and
|
|
120
|
-
* the binding's value type is `true`.
|
|
131
|
+
* the binding's value type is `true`. That is why the value is read through
|
|
132
|
+
* readCheckedUniqueItems: with a bare `=== true`, a non-boolean would take the
|
|
133
|
+
* same silent route as the lawful `false` and lose the constraint entirely.
|
|
121
134
|
*/
|
|
122
135
|
export function declareArrayRules(schema, context) {
|
|
123
136
|
let chain = createFieldSlots(context.bag, context.build).array;
|
|
@@ -127,7 +140,7 @@ export function declareArrayRules(schema, context) {
|
|
|
127
140
|
if (schema.maxItems !== undefined) {
|
|
128
141
|
chain = applyKeywordBinding(chain, maxItemsBinding, schema.maxItems);
|
|
129
142
|
}
|
|
130
|
-
if (schema
|
|
143
|
+
if (readCheckedUniqueItems(schema) === true) {
|
|
131
144
|
chain = applyKeywordBinding(chain, uniqueItemsBinding, true);
|
|
132
145
|
}
|
|
133
146
|
return readChainRules(chain) ?? NO_RULES;
|
|
@@ -17,6 +17,7 @@ export { createDocumentScope, createLocalScope } from "./ref-scope";
|
|
|
17
17
|
export type { SchemaRegistry } from "./schema-registry";
|
|
18
18
|
export { createSchemaRegistry } from "./schema-registry";
|
|
19
19
|
export { UnsupportedKeywordError } from "./unsupported-keyword-error";
|
|
20
|
+
export { MalformedSchemaError } from "./malformed-schema-error";
|
|
20
21
|
export { isDraft07Schema, isSchemaObject } from "./draft07.types";
|
|
21
22
|
export type { Draft07Schema, Draft07SchemaObject, Draft07TypeKeyword, } from "./draft07.types";
|
|
22
23
|
export { assertKeywordSupported, countKeywordHandlings, findKeywordHandling, isDraft07Keyword, listBoundPluginNames, listDraft07Keywords, } from "./keyword-map";
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.listFormatNames = exports.findFormatHandling = exports.listDraft07Keywords = exports.listBoundPluginNames = exports.isDraft07Keyword = exports.findKeywordHandling = exports.countKeywordHandlings = exports.assertKeywordSupported = exports.isSchemaObject = exports.isDraft07Schema = exports.UnsupportedKeywordError = exports.createSchemaRegistry = exports.createLocalScope = exports.createDocumentScope = exports.resolveRefInScope = exports.resolveRef = exports.isResolvableRef = exports.RefResolutionError = exports.declarePresenceRules = exports.declareRequiredProperties = exports.createStructuralContext = exports.toSchemaBranch = exports.collectSubSchemaRules = exports.readChildSchemas = exports.isStructuralKeyword = exports.expandSchemaRules = exports.STRUCTURAL_EXPANSIONS = exports.joinDeclaredPath = exports.flattenSchema = exports.toSchemaObject = exports.resolveSchemaNodeInScope = exports.resolveSchemaNode = exports.readRefPointer = exports.isDefinitionContainer = exports.collectDefinitionNames = exports.DEFINITION_CONTAINERS = exports.fromJsonSchema = exports.buildFromSchema = exports.buildFieldEntries = exports.NotASchemaError = void 0;
|
|
3
|
+
exports.listFormatNames = exports.findFormatHandling = exports.listDraft07Keywords = exports.listBoundPluginNames = exports.isDraft07Keyword = exports.findKeywordHandling = exports.countKeywordHandlings = exports.assertKeywordSupported = exports.isSchemaObject = exports.isDraft07Schema = exports.MalformedSchemaError = exports.UnsupportedKeywordError = exports.createSchemaRegistry = exports.createLocalScope = exports.createDocumentScope = exports.resolveRefInScope = exports.resolveRef = exports.isResolvableRef = exports.RefResolutionError = exports.declarePresenceRules = exports.declareRequiredProperties = exports.createStructuralContext = exports.toSchemaBranch = exports.collectSubSchemaRules = exports.readChildSchemas = exports.isStructuralKeyword = exports.expandSchemaRules = exports.STRUCTURAL_EXPANSIONS = exports.joinDeclaredPath = exports.flattenSchema = exports.toSchemaObject = exports.resolveSchemaNodeInScope = exports.resolveSchemaNode = exports.readRefPointer = exports.isDefinitionContainer = exports.collectDefinitionNames = exports.DEFINITION_CONTAINERS = exports.fromJsonSchema = exports.buildFromSchema = exports.buildFieldEntries = exports.NotASchemaError = void 0;
|
|
4
4
|
// ===========================================================================
|
|
5
5
|
// L8 src/json-schema/index.ts — re-exports only. Nothing is defined here.
|
|
6
6
|
//
|
|
@@ -50,6 +50,8 @@ var schema_registry_1 = require("./schema-registry");
|
|
|
50
50
|
Object.defineProperty(exports, "createSchemaRegistry", { enumerable: true, get: function () { return schema_registry_1.createSchemaRegistry; } });
|
|
51
51
|
var unsupported_keyword_error_1 = require("./unsupported-keyword-error");
|
|
52
52
|
Object.defineProperty(exports, "UnsupportedKeywordError", { enumerable: true, get: function () { return unsupported_keyword_error_1.UnsupportedKeywordError; } });
|
|
53
|
+
var malformed_schema_error_1 = require("./malformed-schema-error");
|
|
54
|
+
Object.defineProperty(exports, "MalformedSchemaError", { enumerable: true, get: function () { return malformed_schema_error_1.MalformedSchemaError; } });
|
|
53
55
|
var draft07_types_1 = require("./draft07.types");
|
|
54
56
|
Object.defineProperty(exports, "isDraft07Schema", { enumerable: true, get: function () { return draft07_types_1.isDraft07Schema; } });
|
|
55
57
|
Object.defineProperty(exports, "isSchemaObject", { enumerable: true, get: function () { return draft07_types_1.isSchemaObject; } });
|
|
@@ -17,6 +17,7 @@ export { isResolvableRef, resolveRef, resolveRefInScope } from "./resolve-ref.mj
|
|
|
17
17
|
export { createDocumentScope, createLocalScope } from "./ref-scope.mjs";
|
|
18
18
|
export { createSchemaRegistry } from "./schema-registry.mjs";
|
|
19
19
|
export { UnsupportedKeywordError } from "./unsupported-keyword-error.mjs";
|
|
20
|
+
export { MalformedSchemaError } from "./malformed-schema-error.mjs";
|
|
20
21
|
export { isDraft07Schema, isSchemaObject } from "./draft07.types.mjs";
|
|
21
22
|
export { assertKeywordSupported, countKeywordHandlings, findKeywordHandling, isDraft07Keyword, listBoundPluginNames, listDraft07Keywords, } from "./keyword-map.mjs";
|
|
22
23
|
export { findFormatHandling, listFormatNames } from "./format-map.mjs";
|
|
@@ -10,7 +10,9 @@ exports.stringKeywordMap = exports.contentMediaTypeBinding = exports.contentEnco
|
|
|
10
10
|
// table in this repository — 1.x shipped three of them and they disagreed
|
|
11
11
|
// (docs/legacy-spec/json-schema-mapping.md records the disagreements).
|
|
12
12
|
// ===========================================================================
|
|
13
|
+
const types_1 = require("../types");
|
|
13
14
|
const bind_keyword_1 = require("./bind-keyword");
|
|
15
|
+
const malformed_schema_error_1 = require("./malformed-schema-error");
|
|
14
16
|
const string_min_1 = require("../plugins/string-min");
|
|
15
17
|
const string_max_1 = require("../plugins/string-max");
|
|
16
18
|
const string_pattern_1 = require("../plugins/string-pattern");
|
|
@@ -18,13 +20,40 @@ const string_content_encoding_1 = require("../plugins/string-content-encoding");
|
|
|
18
20
|
const string_content_media_type_1 = require("../plugins/string-content-media-type");
|
|
19
21
|
exports.minLengthBinding = (0, bind_keyword_1.bindKeyword)("string", "min", string_min_1.stringMinPlugin, (v) => [v]);
|
|
20
22
|
exports.maxLengthBinding = (0, bind_keyword_1.bindKeyword)("string", "max", string_max_1.stringMaxPlugin, (v) => [v]);
|
|
23
|
+
/**
|
|
24
|
+
* Compiles the document's source, refusing anything the meta-schema forbids.
|
|
25
|
+
*
|
|
26
|
+
* The parameter is `unknown` although the keyword's value type is `string`,
|
|
27
|
+
* and that is the whole point: compiling is a TOTAL operation on JSON values —
|
|
28
|
+
* every one of them has a string form — so a number becomes a literal digit
|
|
29
|
+
* pattern and an object becomes one that matches almost every string. Both
|
|
30
|
+
* then reach stringPattern as a perfectly valid RegExp, leaving its
|
|
31
|
+
* non-RegExp guard nothing to fire on. The refusal has to be here, before the
|
|
32
|
+
* value is turned into something well formed.
|
|
33
|
+
*
|
|
34
|
+
* A string that is not a valid ECMA-262 pattern is the same failure wearing a
|
|
35
|
+
* different coat: the compile step throws a SyntaxError naming neither the
|
|
36
|
+
* keyword nor the document, so it is caught and re-raised as the typed refusal
|
|
37
|
+
* every other malformed value gets.
|
|
38
|
+
*/
|
|
39
|
+
function compilePattern(source) {
|
|
40
|
+
if (!(0, types_1.isString)(source)) {
|
|
41
|
+
throw new malformed_schema_error_1.MalformedSchemaError("pattern", "the value must be a string", source);
|
|
42
|
+
}
|
|
43
|
+
try {
|
|
44
|
+
return new RegExp(source);
|
|
45
|
+
}
|
|
46
|
+
catch {
|
|
47
|
+
throw new malformed_schema_error_1.MalformedSchemaError("pattern", "the value must be a valid ECMA-262 regular expression", source);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
21
50
|
/**
|
|
22
51
|
* Draft-07 spells `pattern` as an ECMA-262 SOURCE string; the plugin accepts a
|
|
23
52
|
* RegExp and only a RegExp, because 1.x's `new RegExp(source)` at the call site
|
|
24
53
|
* dropped flags silently and gave the caller no compile-time check. Compiling
|
|
25
54
|
* the schema's string therefore happens HERE, once, and nowhere else.
|
|
26
55
|
*/
|
|
27
|
-
exports.patternBinding = (0, bind_keyword_1.bindKeyword)("string", "pattern", string_pattern_1.stringPatternPlugin, (v) => [
|
|
56
|
+
exports.patternBinding = (0, bind_keyword_1.bindKeyword)("string", "pattern", string_pattern_1.stringPatternPlugin, (v) => [compilePattern(v)]);
|
|
28
57
|
/**
|
|
29
58
|
* The value type is `ContentEncodingName`, not `string`: an encoding the
|
|
30
59
|
* plugin does not know must be refused by the converter rather than accepted
|
|
@@ -7,7 +7,9 @@
|
|
|
7
7
|
// table in this repository — 1.x shipped three of them and they disagreed
|
|
8
8
|
// (docs/legacy-spec/json-schema-mapping.md records the disagreements).
|
|
9
9
|
// ===========================================================================
|
|
10
|
+
import { isString } from "../types/index.mjs";
|
|
10
11
|
import { bindKeyword, structural } from "./bind-keyword.mjs";
|
|
12
|
+
import { MalformedSchemaError } from "./malformed-schema-error.mjs";
|
|
11
13
|
import { stringMinPlugin } from "../plugins/string-min/index.mjs";
|
|
12
14
|
import { stringMaxPlugin } from "../plugins/string-max/index.mjs";
|
|
13
15
|
import { stringPatternPlugin } from "../plugins/string-pattern/index.mjs";
|
|
@@ -15,13 +17,40 @@ import { stringContentEncodingPlugin, } from "../plugins/string-content-encoding
|
|
|
15
17
|
import { stringContentMediaTypePlugin } from "../plugins/string-content-media-type/index.mjs";
|
|
16
18
|
export const minLengthBinding = bindKeyword("string", "min", stringMinPlugin, (v) => [v]);
|
|
17
19
|
export const maxLengthBinding = bindKeyword("string", "max", stringMaxPlugin, (v) => [v]);
|
|
20
|
+
/**
|
|
21
|
+
* Compiles the document's source, refusing anything the meta-schema forbids.
|
|
22
|
+
*
|
|
23
|
+
* The parameter is `unknown` although the keyword's value type is `string`,
|
|
24
|
+
* and that is the whole point: compiling is a TOTAL operation on JSON values —
|
|
25
|
+
* every one of them has a string form — so a number becomes a literal digit
|
|
26
|
+
* pattern and an object becomes one that matches almost every string. Both
|
|
27
|
+
* then reach stringPattern as a perfectly valid RegExp, leaving its
|
|
28
|
+
* non-RegExp guard nothing to fire on. The refusal has to be here, before the
|
|
29
|
+
* value is turned into something well formed.
|
|
30
|
+
*
|
|
31
|
+
* A string that is not a valid ECMA-262 pattern is the same failure wearing a
|
|
32
|
+
* different coat: the compile step throws a SyntaxError naming neither the
|
|
33
|
+
* keyword nor the document, so it is caught and re-raised as the typed refusal
|
|
34
|
+
* every other malformed value gets.
|
|
35
|
+
*/
|
|
36
|
+
function compilePattern(source) {
|
|
37
|
+
if (!isString(source)) {
|
|
38
|
+
throw new MalformedSchemaError("pattern", "the value must be a string", source);
|
|
39
|
+
}
|
|
40
|
+
try {
|
|
41
|
+
return new RegExp(source);
|
|
42
|
+
}
|
|
43
|
+
catch {
|
|
44
|
+
throw new MalformedSchemaError("pattern", "the value must be a valid ECMA-262 regular expression", source);
|
|
45
|
+
}
|
|
46
|
+
}
|
|
18
47
|
/**
|
|
19
48
|
* Draft-07 spells `pattern` as an ECMA-262 SOURCE string; the plugin accepts a
|
|
20
49
|
* RegExp and only a RegExp, because 1.x's `new RegExp(source)` at the call site
|
|
21
50
|
* dropped flags silently and gave the caller no compile-time check. Compiling
|
|
22
51
|
* the schema's string therefore happens HERE, once, and nowhere else.
|
|
23
52
|
*/
|
|
24
|
-
export const patternBinding = bindKeyword("string", "pattern", stringPatternPlugin, (v) => [
|
|
53
|
+
export const patternBinding = bindKeyword("string", "pattern", stringPatternPlugin, (v) => [compilePattern(v)]);
|
|
25
54
|
/**
|
|
26
55
|
* The value type is `ContentEncodingName`, not `string`: an encoding the
|
|
27
56
|
* plugin does not know must be refused by the converter rather than accepted
|
|
@@ -35,6 +35,8 @@ exports.NON_DRAFT07_KEYWORDS = {
|
|
|
35
35
|
$recursiveRef: "2019-09 recursive references",
|
|
36
36
|
dependentRequired: "2019-09 split of `dependencies`; use `dependencies`",
|
|
37
37
|
dependentSchemas: "2019-09 split of `dependencies`; use `dependencies`",
|
|
38
|
+
minContains: "2019-09 bound on `contains`; Draft-07's is fixed at one",
|
|
39
|
+
maxContains: "2019-09 bound on `contains`; Draft-07 states no maximum",
|
|
38
40
|
unevaluatedItems: "2019-09; no annotation-collection model in Luq",
|
|
39
41
|
unevaluatedProperties: "2019-09; no annotation-collection model in Luq",
|
|
40
42
|
contentSchema: "2019-09 companion to contentMediaType",
|
|
@@ -26,6 +26,8 @@ export const NON_DRAFT07_KEYWORDS = {
|
|
|
26
26
|
$recursiveRef: "2019-09 recursive references",
|
|
27
27
|
dependentRequired: "2019-09 split of `dependencies`; use `dependencies`",
|
|
28
28
|
dependentSchemas: "2019-09 split of `dependencies`; use `dependencies`",
|
|
29
|
+
minContains: "2019-09 bound on `contains`; Draft-07's is fixed at one",
|
|
30
|
+
maxContains: "2019-09 bound on `contains`; Draft-07 states no maximum",
|
|
29
31
|
unevaluatedItems: "2019-09; no annotation-collection model in Luq",
|
|
30
32
|
unevaluatedProperties: "2019-09; no annotation-collection model in Luq",
|
|
31
33
|
contentSchema: "2019-09 companion to contentMediaType",
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The two shapes §4.4 lets a schema take, worded once. Several keywords take a
|
|
3
|
+
* schema as their value — `properties` members, `additionalProperties`, every
|
|
4
|
+
* position of the tuple form of `items` — and each is read by a different
|
|
5
|
+
* module; sharing the phrase is what stops the same refusal being explained
|
|
6
|
+
* three different ways to the same caller.
|
|
7
|
+
*
|
|
8
|
+
* It is a fragment, so it composes: "the value ", `the schema under "a" `.
|
|
9
|
+
*/
|
|
10
|
+
export declare const SCHEMA_FORMS = "must be an object or a boolean";
|
|
11
|
+
/**
|
|
12
|
+
* Renders an untrusted schema value for a message, in at most
|
|
13
|
+
* RECEIVED_MAX_LENGTH characters. The value comes from the same document that
|
|
14
|
+
* is already known to be malformed, so nothing about it can be assumed: it may
|
|
15
|
+
* be circular, hold a bigint, or be large enough to drown the message.
|
|
16
|
+
* Rendering must never be the thing that throws.
|
|
17
|
+
*/
|
|
18
|
+
export declare function renderReceivedValue(value: unknown): string;
|
|
19
|
+
/**
|
|
20
|
+
* Raised when a keyword's value violates the Draft-07 meta-schema. Thrown at
|
|
21
|
+
* build time, before a validator that would enforce less than the document
|
|
22
|
+
* states can exist.
|
|
23
|
+
*/
|
|
24
|
+
export declare class MalformedSchemaError extends Error {
|
|
25
|
+
/** The keyword whose value is malformed, for instance "type". */
|
|
26
|
+
readonly keyword: string;
|
|
27
|
+
/**
|
|
28
|
+
* What the meta-schema REQUIRES, written as a sentence fragment with no
|
|
29
|
+
* terminal punctuation — the message supplies it. Every keyword phrases it
|
|
30
|
+
* the same way, "<the thing> must be <the shape>", so that a caller reading
|
|
31
|
+
* two refusals from two different keywords reads one library rather than
|
|
32
|
+
* three; what was found instead is carried separately, in `received`.
|
|
33
|
+
*/
|
|
34
|
+
readonly reason: string;
|
|
35
|
+
/** The offending value, rendered short and safe by renderReceivedValue. */
|
|
36
|
+
readonly received: string;
|
|
37
|
+
constructor(keyword: string, reason: string, value: unknown);
|
|
38
|
+
}
|
|
@@ -0,0 +1,103 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ===========================================================================
|
|
3
|
+
// L8 src/json-schema/malformed-schema-error.ts
|
|
4
|
+
//
|
|
5
|
+
// UnsupportedKeywordError refuses a keyword NAME Luq cannot honour. This
|
|
6
|
+
// refuses a keyword VALUE the Draft-07 meta-schema does not allow, which until
|
|
7
|
+
// it is refused does not fail — it quietly enforces less than the document
|
|
8
|
+
// says. `{"type":"strig"}` drops the unknown name, so the type check vanishes
|
|
9
|
+
// and the field starts accepting null; `{"pattern":{"source":"^SKU-"}}` reaches
|
|
10
|
+
// the regex constructor as a stringified object and compiles to one matching
|
|
11
|
+
// almost anything; `{"additionalProperties":"false"}` loses the closed-object
|
|
12
|
+
// guarantee; `{"required":"name"}` builds and then throws a raw TypeError
|
|
13
|
+
// inside validate() on the first request. A validator that silently drops a
|
|
14
|
+
// constraint is worse than one that refuses the schema, so the refusal is a
|
|
15
|
+
// typed error carrying the keyword, what the meta-schema requires, and a
|
|
16
|
+
// rendering of what was found instead.
|
|
17
|
+
//
|
|
18
|
+
// The two refusals stay separate classes, neither extending the other, because
|
|
19
|
+
// they answer different questions: "Luq cannot honour this keyword" versus
|
|
20
|
+
// "this document is not valid Draft-07". The first is a limit of the library
|
|
21
|
+
// and the second is a bug in the document; a caller catching one must not
|
|
22
|
+
// silently catch the other.
|
|
23
|
+
// ===========================================================================
|
|
24
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
25
|
+
exports.MalformedSchemaError = exports.SCHEMA_FORMS = void 0;
|
|
26
|
+
exports.renderReceivedValue = renderReceivedValue;
|
|
27
|
+
/**
|
|
28
|
+
* The two shapes §4.4 lets a schema take, worded once. Several keywords take a
|
|
29
|
+
* schema as their value — `properties` members, `additionalProperties`, every
|
|
30
|
+
* position of the tuple form of `items` — and each is read by a different
|
|
31
|
+
* module; sharing the phrase is what stops the same refusal being explained
|
|
32
|
+
* three different ways to the same caller.
|
|
33
|
+
*
|
|
34
|
+
* It is a fragment, so it composes: "the value ", `the schema under "a" `.
|
|
35
|
+
*/
|
|
36
|
+
exports.SCHEMA_FORMS = "must be an object or a boolean";
|
|
37
|
+
/**
|
|
38
|
+
* How much of the offending value a message may carry. A schema node is
|
|
39
|
+
* arbitrarily large, and an error whose message is a megabyte long is unusable
|
|
40
|
+
* in a log line.
|
|
41
|
+
*/
|
|
42
|
+
const RECEIVED_MAX_LENGTH = 80;
|
|
43
|
+
const TRUNCATION_MARKER = "...";
|
|
44
|
+
/**
|
|
45
|
+
* Renders an untrusted schema value for a message, in at most
|
|
46
|
+
* RECEIVED_MAX_LENGTH characters. The value comes from the same document that
|
|
47
|
+
* is already known to be malformed, so nothing about it can be assumed: it may
|
|
48
|
+
* be circular, hold a bigint, or be large enough to drown the message.
|
|
49
|
+
* Rendering must never be the thing that throws.
|
|
50
|
+
*/
|
|
51
|
+
function renderReceivedValue(value) {
|
|
52
|
+
if (value === undefined)
|
|
53
|
+
return "undefined";
|
|
54
|
+
if (typeof value === "function")
|
|
55
|
+
return "[function]";
|
|
56
|
+
if (typeof value === "symbol")
|
|
57
|
+
return "[symbol]";
|
|
58
|
+
return truncate(renderJson(value));
|
|
59
|
+
}
|
|
60
|
+
/**
|
|
61
|
+
* JSON.stringify throws on a circular reference and on a bigint anywhere in
|
|
62
|
+
* the value, and returns undefined for a value it has no encoding for at all.
|
|
63
|
+
* Both outcomes become a description of the shape rather than a failure.
|
|
64
|
+
*/
|
|
65
|
+
function renderJson(value) {
|
|
66
|
+
try {
|
|
67
|
+
const rendered = JSON.stringify(value);
|
|
68
|
+
return rendered === undefined ? describeUnrenderable(value) : rendered;
|
|
69
|
+
}
|
|
70
|
+
catch {
|
|
71
|
+
return describeUnrenderable(value);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
function describeUnrenderable(value) {
|
|
75
|
+
return Array.isArray(value)
|
|
76
|
+
? "[unrenderable array]"
|
|
77
|
+
: `[unrenderable ${typeof value}]`;
|
|
78
|
+
}
|
|
79
|
+
function truncate(rendered) {
|
|
80
|
+
if (rendered.length <= RECEIVED_MAX_LENGTH)
|
|
81
|
+
return rendered;
|
|
82
|
+
const kept = RECEIVED_MAX_LENGTH - TRUNCATION_MARKER.length;
|
|
83
|
+
return `${rendered.slice(0, kept)}${TRUNCATION_MARKER}`;
|
|
84
|
+
}
|
|
85
|
+
/**
|
|
86
|
+
* Raised when a keyword's value violates the Draft-07 meta-schema. Thrown at
|
|
87
|
+
* build time, before a validator that would enforce less than the document
|
|
88
|
+
* states can exist.
|
|
89
|
+
*/
|
|
90
|
+
class MalformedSchemaError extends Error {
|
|
91
|
+
constructor(keyword, reason, value) {
|
|
92
|
+
const received = renderReceivedValue(value);
|
|
93
|
+
super(`JSON Schema keyword "${keyword}" has a value the Draft-07 meta-schema ` +
|
|
94
|
+
`does not allow: ${reason}. Received: ${received}.`);
|
|
95
|
+
this.name = "MalformedSchemaError";
|
|
96
|
+
this.keyword = keyword;
|
|
97
|
+
this.reason = reason;
|
|
98
|
+
this.received = received;
|
|
99
|
+
// Without this, `instanceof` fails when the package is compiled to ES5.
|
|
100
|
+
Object.setPrototypeOf(this, MalformedSchemaError.prototype);
|
|
101
|
+
}
|
|
102
|
+
}
|
|
103
|
+
exports.MalformedSchemaError = MalformedSchemaError;
|
|
@@ -0,0 +1,98 @@
|
|
|
1
|
+
// ===========================================================================
|
|
2
|
+
// L8 src/json-schema/malformed-schema-error.ts
|
|
3
|
+
//
|
|
4
|
+
// UnsupportedKeywordError refuses a keyword NAME Luq cannot honour. This
|
|
5
|
+
// refuses a keyword VALUE the Draft-07 meta-schema does not allow, which until
|
|
6
|
+
// it is refused does not fail — it quietly enforces less than the document
|
|
7
|
+
// says. `{"type":"strig"}` drops the unknown name, so the type check vanishes
|
|
8
|
+
// and the field starts accepting null; `{"pattern":{"source":"^SKU-"}}` reaches
|
|
9
|
+
// the regex constructor as a stringified object and compiles to one matching
|
|
10
|
+
// almost anything; `{"additionalProperties":"false"}` loses the closed-object
|
|
11
|
+
// guarantee; `{"required":"name"}` builds and then throws a raw TypeError
|
|
12
|
+
// inside validate() on the first request. A validator that silently drops a
|
|
13
|
+
// constraint is worse than one that refuses the schema, so the refusal is a
|
|
14
|
+
// typed error carrying the keyword, what the meta-schema requires, and a
|
|
15
|
+
// rendering of what was found instead.
|
|
16
|
+
//
|
|
17
|
+
// The two refusals stay separate classes, neither extending the other, because
|
|
18
|
+
// they answer different questions: "Luq cannot honour this keyword" versus
|
|
19
|
+
// "this document is not valid Draft-07". The first is a limit of the library
|
|
20
|
+
// and the second is a bug in the document; a caller catching one must not
|
|
21
|
+
// silently catch the other.
|
|
22
|
+
// ===========================================================================
|
|
23
|
+
/**
|
|
24
|
+
* The two shapes §4.4 lets a schema take, worded once. Several keywords take a
|
|
25
|
+
* schema as their value — `properties` members, `additionalProperties`, every
|
|
26
|
+
* position of the tuple form of `items` — and each is read by a different
|
|
27
|
+
* module; sharing the phrase is what stops the same refusal being explained
|
|
28
|
+
* three different ways to the same caller.
|
|
29
|
+
*
|
|
30
|
+
* It is a fragment, so it composes: "the value ", `the schema under "a" `.
|
|
31
|
+
*/
|
|
32
|
+
export const SCHEMA_FORMS = "must be an object or a boolean";
|
|
33
|
+
/**
|
|
34
|
+
* How much of the offending value a message may carry. A schema node is
|
|
35
|
+
* arbitrarily large, and an error whose message is a megabyte long is unusable
|
|
36
|
+
* in a log line.
|
|
37
|
+
*/
|
|
38
|
+
const RECEIVED_MAX_LENGTH = 80;
|
|
39
|
+
const TRUNCATION_MARKER = "...";
|
|
40
|
+
/**
|
|
41
|
+
* Renders an untrusted schema value for a message, in at most
|
|
42
|
+
* RECEIVED_MAX_LENGTH characters. The value comes from the same document that
|
|
43
|
+
* is already known to be malformed, so nothing about it can be assumed: it may
|
|
44
|
+
* be circular, hold a bigint, or be large enough to drown the message.
|
|
45
|
+
* Rendering must never be the thing that throws.
|
|
46
|
+
*/
|
|
47
|
+
export function renderReceivedValue(value) {
|
|
48
|
+
if (value === undefined)
|
|
49
|
+
return "undefined";
|
|
50
|
+
if (typeof value === "function")
|
|
51
|
+
return "[function]";
|
|
52
|
+
if (typeof value === "symbol")
|
|
53
|
+
return "[symbol]";
|
|
54
|
+
return truncate(renderJson(value));
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* JSON.stringify throws on a circular reference and on a bigint anywhere in
|
|
58
|
+
* the value, and returns undefined for a value it has no encoding for at all.
|
|
59
|
+
* Both outcomes become a description of the shape rather than a failure.
|
|
60
|
+
*/
|
|
61
|
+
function renderJson(value) {
|
|
62
|
+
try {
|
|
63
|
+
const rendered = JSON.stringify(value);
|
|
64
|
+
return rendered === undefined ? describeUnrenderable(value) : rendered;
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return describeUnrenderable(value);
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
function describeUnrenderable(value) {
|
|
71
|
+
return Array.isArray(value)
|
|
72
|
+
? "[unrenderable array]"
|
|
73
|
+
: `[unrenderable ${typeof value}]`;
|
|
74
|
+
}
|
|
75
|
+
function truncate(rendered) {
|
|
76
|
+
if (rendered.length <= RECEIVED_MAX_LENGTH)
|
|
77
|
+
return rendered;
|
|
78
|
+
const kept = RECEIVED_MAX_LENGTH - TRUNCATION_MARKER.length;
|
|
79
|
+
return `${rendered.slice(0, kept)}${TRUNCATION_MARKER}`;
|
|
80
|
+
}
|
|
81
|
+
/**
|
|
82
|
+
* Raised when a keyword's value violates the Draft-07 meta-schema. Thrown at
|
|
83
|
+
* build time, before a validator that would enforce less than the document
|
|
84
|
+
* states can exist.
|
|
85
|
+
*/
|
|
86
|
+
export class MalformedSchemaError extends Error {
|
|
87
|
+
constructor(keyword, reason, value) {
|
|
88
|
+
const received = renderReceivedValue(value);
|
|
89
|
+
super(`JSON Schema keyword "${keyword}" has a value the Draft-07 meta-schema ` +
|
|
90
|
+
`does not allow: ${reason}. Received: ${received}.`);
|
|
91
|
+
this.name = "MalformedSchemaError";
|
|
92
|
+
this.keyword = keyword;
|
|
93
|
+
this.reason = reason;
|
|
94
|
+
this.received = received;
|
|
95
|
+
// Without this, `instanceof` fails when the package is compiled to ES5.
|
|
96
|
+
Object.setPrototypeOf(this, MalformedSchemaError.prototype);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
@@ -1,8 +1,26 @@
|
|
|
1
|
+
/** One plugin symbol: the method it adds, and the slots it adds it to. */
|
|
2
|
+
export interface PluginSurface {
|
|
3
|
+
/** The symbol to pass to `.use()`, e.g. "stringMinPlugin". */
|
|
4
|
+
readonly symbol: string;
|
|
5
|
+
/** The chain method it adds, e.g. "min". */
|
|
6
|
+
readonly method: string;
|
|
7
|
+
/** The slots that method appears on, e.g. ["string"]. */
|
|
8
|
+
readonly slots: readonly string[];
|
|
9
|
+
}
|
|
1
10
|
export interface PluginManifestEntry {
|
|
2
11
|
readonly directoryName: string;
|
|
3
12
|
readonly subpathName: string;
|
|
4
13
|
readonly tier: "isolated" | "extension";
|
|
14
|
+
/**
|
|
15
|
+
* Where the plugin lives in the REPOSITORY. A source path, so it resolves
|
|
16
|
+
* only in a checkout; an installed package has no src directory. What a
|
|
17
|
+
* consumer writes instead is `entryPoint`.
|
|
18
|
+
*/
|
|
5
19
|
readonly entryFile: string;
|
|
20
|
+
/** The specifier a consumer writes, e.g. "@maroonedog/luq/plugins/stringMin". */
|
|
21
|
+
readonly entryPoint: string;
|
|
6
22
|
readonly exportedSymbols: readonly string[];
|
|
23
|
+
/** One per exported symbol, in the same order. */
|
|
24
|
+
readonly surfaces: readonly PluginSurface[];
|
|
7
25
|
}
|
|
8
26
|
export declare const PLUGIN_MANIFEST: readonly PluginManifestEntry[];
|