json-schema-library 5.3.0 → 7.0.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/.editorconfig +1 -0
- package/.prettierignore +1 -0
- package/.prettierrc +7 -0
- package/CHANGELOG.md +106 -0
- package/README.md +811 -199
- package/TASKS.md +3 -81
- package/dist/index.d.ts +29 -71
- package/dist/jsonSchemaLibrary.js +1 -1
- package/dist/lib/SchemaService.d.ts +6 -8
- package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
- package/dist/lib/addValidator.d.ts +3 -2
- package/dist/lib/compile/getRef.d.ts +2 -1
- package/dist/lib/compile/index.d.ts +15 -1
- package/dist/lib/compile/types.d.ts +5 -0
- package/dist/lib/config/strings.d.ts +1 -39
- package/dist/lib/draft/index.d.ts +132 -0
- package/dist/lib/draft04/index.d.ts +7 -0
- package/dist/lib/draft06/compile/index.d.ts +16 -0
- package/dist/lib/draft06/index.d.ts +7 -0
- package/dist/lib/draft06/validation/keyword.d.ts +3 -0
- package/dist/lib/draft06/validation/type.d.ts +10 -0
- package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
- package/dist/lib/draft07/index.d.ts +7 -0
- package/dist/lib/each.d.ts +3 -2
- package/dist/lib/eachSchema.d.ts +2 -4
- package/dist/lib/getChildSchemaSelection.d.ts +7 -5
- package/dist/lib/getSchema.d.ts +2 -2
- package/dist/lib/getTemplate.d.ts +1 -1
- package/dist/lib/getTypeOf.d.ts +2 -1
- package/dist/lib/isValid.d.ts +1 -1
- package/dist/lib/jsoneditor/index.d.ts +7 -0
- package/dist/lib/resolveAllOf.d.ts +1 -1
- package/dist/lib/resolveAnyOf.d.ts +1 -1
- package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
- package/dist/lib/resolveOneOf.strict.d.ts +2 -2
- package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
- package/dist/lib/schema/getTypeDefs.d.ts +6 -4
- package/dist/lib/schema/getTypeId.d.ts +1 -1
- package/dist/lib/schema/types.d.ts +7 -57
- package/dist/lib/step.d.ts +5 -5
- package/dist/lib/types.d.ts +11 -3
- package/dist/lib/utils/createCustomError.d.ts +8 -11
- package/dist/lib/utils/filter.d.ts +4 -4
- package/dist/lib/utils/flattenArray.d.ts +1 -1
- package/dist/lib/utils/merge.d.ts +3 -0
- package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
- package/dist/lib/validate.d.ts +2 -2
- package/dist/lib/validateAsync.d.ts +1 -1
- package/dist/lib/validation/errors.d.ts +1 -3
- package/dist/lib/validation/format.d.ts +4 -11
- package/dist/lib/validation/keyword.d.ts +2 -27
- package/dist/lib/validation/type.d.ts +3 -10
- package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
- package/dist/module/index.js +23 -32
- package/dist/module/lib/SchemaService.js +7 -4
- package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
- package/dist/module/lib/addValidator.js +3 -4
- package/dist/module/lib/compile/getRef.js +1 -1
- package/dist/module/lib/compile/index.js +43 -18
- package/dist/module/lib/compile/types.js +1 -0
- package/dist/module/lib/config/strings.js +15 -2
- package/dist/module/lib/createSchemaOf.js +1 -1
- package/dist/module/lib/draft/index.js +133 -0
- package/dist/module/lib/draft04/index.js +90 -0
- package/dist/module/lib/draft06/compile/index.js +77 -0
- package/dist/module/lib/draft06/index.js +96 -0
- package/dist/module/lib/draft06/validation/keyword.js +168 -0
- package/dist/module/lib/draft06/validation/type.js +31 -0
- package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
- package/dist/module/lib/draft07/index.js +96 -0
- package/dist/module/lib/each.js +2 -2
- package/dist/module/lib/eachSchema.js +28 -19
- package/dist/module/lib/getChildSchemaSelection.js +7 -6
- package/dist/module/lib/getSchema.js +4 -2
- package/dist/module/lib/getTemplate.js +42 -15
- package/dist/module/lib/jsoneditor/index.js +16 -0
- package/dist/module/lib/resolveAllOf.js +3 -4
- package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
- package/dist/module/lib/resolveOneOf.strict.js +49 -2
- package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
- package/dist/module/lib/resolveRef.strict.js +8 -0
- package/dist/module/lib/schema/getTypeDefs.js +14 -3
- package/dist/module/lib/schema/getTypeId.js +10 -6
- package/dist/module/lib/schema/types.js +33 -9
- package/dist/module/lib/step.js +67 -13
- package/dist/module/lib/types.js +7 -1
- package/dist/module/lib/utils/createCustomError.js +4 -4
- package/dist/module/lib/utils/filter.js +3 -5
- package/dist/module/lib/utils/flattenArray.js +4 -3
- package/dist/module/lib/utils/merge.js +4 -0
- package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
- package/dist/module/lib/validate.js +34 -8
- package/dist/module/lib/validateAsync.js +7 -7
- package/dist/module/lib/validation/errors.js +16 -3
- package/dist/module/lib/validation/format.js +115 -8
- package/dist/module/lib/validation/keyword.js +79 -32
- package/dist/module/lib/validation/type.js +2 -1
- package/index.ts +46 -32
- package/lib/SchemaService.ts +18 -11
- package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
- package/lib/addValidator.ts +15 -12
- package/lib/compile/getRef.ts +3 -4
- package/lib/compile/index.ts +65 -19
- package/lib/compile/types.ts +6 -0
- package/lib/config/strings.ts +17 -3
- package/lib/createSchemaOf.ts +1 -3
- package/lib/draft/index.ts +201 -0
- package/lib/draft04/index.ts +95 -0
- package/lib/draft06/compile/index.ts +104 -0
- package/lib/draft06/index.ts +101 -0
- package/lib/draft06/validation/keyword.ts +199 -0
- package/lib/draft06/validation/type.ts +47 -0
- package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
- package/lib/draft07/index.ts +101 -0
- package/lib/each.ts +11 -4
- package/lib/eachSchema.ts +45 -32
- package/lib/getChildSchemaSelection.ts +14 -7
- package/lib/getSchema.ts +18 -9
- package/lib/getTemplate.ts +155 -42
- package/lib/getTypeOf.ts +2 -1
- package/lib/isValid.ts +7 -3
- package/lib/jsoneditor/index.ts +20 -0
- package/lib/resolveAllOf.ts +10 -6
- package/lib/resolveAnyOf.ts +7 -3
- package/lib/resolveOneOf.fuzzy.ts +26 -9
- package/lib/resolveOneOf.strict.ts +63 -5
- package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
- package/lib/resolveRef.strict.ts +9 -0
- package/lib/schema/getTypeDefs.ts +19 -7
- package/lib/schema/getTypeId.ts +11 -8
- package/lib/schema/types.ts +41 -9
- package/lib/step.ts +109 -25
- package/lib/types.ts +23 -5
- package/lib/utils/createCustomError.ts +8 -13
- package/lib/utils/filter.ts +7 -9
- package/lib/utils/flattenArray.ts +5 -4
- package/lib/utils/merge.ts +5 -0
- package/lib/utils/punycode.ucs2decode.ts +6 -5
- package/lib/validate.ts +47 -16
- package/lib/validateAsync.ts +15 -14
- package/lib/validation/errors.ts +17 -6
- package/lib/validation/format.ts +147 -13
- package/lib/validation/keyword.ts +172 -103
- package/lib/validation/type.ts +5 -1
- package/package.json +75 -63
- package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
- package/remotes/draft07.json +172 -0
- package/remotes/draft2019-09.json +86 -0
- package/tsconfig.json +3 -10
- package/dist/lib/cores/CoreInterface.d.ts +0 -23
- package/dist/lib/cores/Draft04.d.ts +0 -13
- package/dist/lib/cores/JsonEditor.d.ts +0 -13
- package/dist/module/lib/cores/CoreInterface.js +0 -51
- package/dist/module/lib/cores/Draft04.js +0 -52
- package/dist/module/lib/cores/JsonEditor.js +0 -51
- package/dist/module/remotes/index.js +0 -10
- package/dist/remotes/index.d.ts +0 -5
- package/lib/cores/CoreInterface.ts +0 -76
- package/lib/cores/Draft04.ts +0 -66
- package/lib/cores/JsonEditor.ts +0 -64
- package/remotes/index.ts +0 -11
|
@@ -0,0 +1,201 @@
|
|
|
1
|
+
import step from "../step";
|
|
2
|
+
import validate from "../validate";
|
|
3
|
+
import resolveOneOf from "../resolveOneOf.strict";
|
|
4
|
+
import resolveRef from "../resolveRef.strict";
|
|
5
|
+
import resolveAllOf from "../resolveAllOf";
|
|
6
|
+
import resolveAnyOf from "../resolveAnyOf";
|
|
7
|
+
import getTemplate from "../getTemplate";
|
|
8
|
+
import getChildSchemaSelection from "../getChildSchemaSelection";
|
|
9
|
+
import getSchema from "../getSchema";
|
|
10
|
+
import { each, EachCallback } from "../each";
|
|
11
|
+
import isValid from "../isValid";
|
|
12
|
+
import { eachSchema, EachSchemaCallback } from "../eachSchema";
|
|
13
|
+
import createSchemaOf from "../createSchemaOf";
|
|
14
|
+
import compileSchema from "../compileSchema";
|
|
15
|
+
import { CreateError } from "../utils/createCustomError";
|
|
16
|
+
import addRemoteSchema from "../addRemoteSchema";
|
|
17
|
+
import { JSONSchema, JSONPointer, JSONValidator, JSONTypeValidator, JSONError } from "../types";
|
|
18
|
+
|
|
19
|
+
export type DraftConfig = {
|
|
20
|
+
/** error creators by id */
|
|
21
|
+
errors: Record<string, CreateError>;
|
|
22
|
+
/** map for valid keywords of a type */
|
|
23
|
+
typeKeywords: Record<string, string[]>;
|
|
24
|
+
/** keyword validators */
|
|
25
|
+
validateKeyword: Record<string, JSONValidator>;
|
|
26
|
+
/** type validators */
|
|
27
|
+
validateType: Record<string, JSONTypeValidator>;
|
|
28
|
+
/** format validators */
|
|
29
|
+
validateFormat: Record<string, JSONValidator>;
|
|
30
|
+
|
|
31
|
+
addRemoteSchema: typeof addRemoteSchema;
|
|
32
|
+
compileSchema: typeof compileSchema;
|
|
33
|
+
createSchemaOf: typeof createSchemaOf;
|
|
34
|
+
each: typeof each;
|
|
35
|
+
eachSchema: typeof eachSchema;
|
|
36
|
+
getChildSchemaSelection: typeof getChildSchemaSelection;
|
|
37
|
+
getSchema: typeof getSchema;
|
|
38
|
+
getTemplate: typeof getTemplate;
|
|
39
|
+
isValid: typeof isValid;
|
|
40
|
+
resolveAllOf: typeof resolveAllOf;
|
|
41
|
+
resolveAnyOf: typeof resolveAnyOf;
|
|
42
|
+
resolveOneOf: typeof resolveOneOf;
|
|
43
|
+
resolveRef: typeof resolveRef;
|
|
44
|
+
step: typeof step;
|
|
45
|
+
validate: typeof validate;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export class Draft {
|
|
49
|
+
readonly config: DraftConfig;
|
|
50
|
+
/** entry point of schema */
|
|
51
|
+
private __rootSchema: JSONSchema;
|
|
52
|
+
/** cache for remote schemas */
|
|
53
|
+
remotes: Record<string, JSONSchema> = {};
|
|
54
|
+
/** error creators by id */
|
|
55
|
+
readonly errors: Record<string, CreateError> = {};
|
|
56
|
+
/** map for valid keywords of a type */
|
|
57
|
+
readonly typeKeywords: Record<string, string[]> = {};
|
|
58
|
+
/** keyword validators */
|
|
59
|
+
readonly validateKeyword: Record<string, JSONValidator> = {};
|
|
60
|
+
/** type validators */
|
|
61
|
+
readonly validateType: Record<string, JSONTypeValidator> = {};
|
|
62
|
+
/** format validators */
|
|
63
|
+
readonly validateFormat: Record<string, JSONValidator> = {};
|
|
64
|
+
|
|
65
|
+
constructor(config: DraftConfig, schema?: JSONSchema) {
|
|
66
|
+
this.config = config;
|
|
67
|
+
this.typeKeywords = JSON.parse(JSON.stringify(config.typeKeywords));
|
|
68
|
+
this.validateKeyword = Object.assign({}, config.validateKeyword);
|
|
69
|
+
this.validateType = Object.assign({}, config.validateType);
|
|
70
|
+
this.validateFormat = Object.assign({}, config.validateFormat);
|
|
71
|
+
this.errors = Object.assign({}, config.errors);
|
|
72
|
+
this.setSchema(schema);
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
get rootSchema() {
|
|
76
|
+
return this.__rootSchema;
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
set rootSchema(rootSchema: JSONSchema) {
|
|
80
|
+
if (rootSchema == null) {
|
|
81
|
+
return;
|
|
82
|
+
}
|
|
83
|
+
this.__rootSchema = this.config.compileSchema(this, rootSchema);
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* register a json-schema to be referenced from another json-schema
|
|
88
|
+
* @param url - base-url of json-schema (aka id)
|
|
89
|
+
* @param schema - json-schema root
|
|
90
|
+
*/
|
|
91
|
+
addRemoteSchema(url: string, schema: JSONSchema): void {
|
|
92
|
+
this.config.addRemoteSchema(this, url, schema);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
compileSchema(schema: JSONSchema): JSONSchema {
|
|
96
|
+
return this.config.compileSchema(this, schema, this.rootSchema ?? schema);
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
createSchemaOf(data: unknown) {
|
|
100
|
+
return this.config.createSchemaOf(data);
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
/**
|
|
104
|
+
* Iterates over data, retrieving its schema
|
|
105
|
+
*
|
|
106
|
+
* @param data - the data to iterate
|
|
107
|
+
* @param callback - will be called with (schema, data, pointer) on each item
|
|
108
|
+
* @param [schema] - the schema matching the data. Defaults to rootSchema
|
|
109
|
+
* @param [pointer] - pointer to current data. Default to rootPointer
|
|
110
|
+
*/
|
|
111
|
+
each(data: any, callback: EachCallback, schema?: JSONSchema, pointer?: JSONPointer) {
|
|
112
|
+
return this.config.each(this, data, callback, schema, pointer);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
eachSchema(callback: EachSchemaCallback, schema = this.rootSchema) {
|
|
116
|
+
return this.config.eachSchema(schema, callback);
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
getChildSchemaSelection(property: string | number, schema?: JSONSchema) {
|
|
120
|
+
return this.config.getChildSchemaSelection(this, property, schema);
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/**
|
|
124
|
+
* Returns the json-schema of a data-json-pointer.
|
|
125
|
+
* Notes
|
|
126
|
+
* - Uses core.step to walk through data and schema
|
|
127
|
+
*
|
|
128
|
+
* @param pointer - json pointer in data to get the json schema for
|
|
129
|
+
* @param [data] - the data object, which includes the json pointers value. This is optional, as
|
|
130
|
+
* long as no oneOf, anyOf, etc statement is part of the pointers schema
|
|
131
|
+
* @param [schema] - the json schema to iterate. Defaults to core.rootSchema
|
|
132
|
+
* @return json schema object of the json-pointer or an error
|
|
133
|
+
*/
|
|
134
|
+
getSchema(pointer: JSONPointer = "#", data?: any, schema?: JSONSchema): JSONSchema | JSONError {
|
|
135
|
+
return this.config.getSchema(this, pointer, data, schema);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
/**
|
|
139
|
+
* Create data object matching the given schema
|
|
140
|
+
*
|
|
141
|
+
* @param [data] - optional template data
|
|
142
|
+
* @param [schema] - json schema, defaults to rootSchema
|
|
143
|
+
* @return created template data
|
|
144
|
+
*/
|
|
145
|
+
getTemplate(data?: unknown, schema?: JSONSchema) {
|
|
146
|
+
return this.config.getTemplate(this, data, schema);
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
isValid(data: any, schema?: JSONSchema, pointer?: JSONPointer): boolean {
|
|
150
|
+
return this.config.isValid(this, data, schema, pointer);
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
resolveAnyOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
|
|
154
|
+
return this.config.resolveAnyOf(this, data, schema, pointer);
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
resolveAllOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
|
|
158
|
+
return this.config.resolveAllOf(this, data, schema, pointer);
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
resolveRef(schema: JSONSchema): JSONSchema {
|
|
162
|
+
return this.config.resolveRef(schema, this.rootSchema);
|
|
163
|
+
}
|
|
164
|
+
|
|
165
|
+
resolveOneOf(data: any, schema: JSONSchema, pointer?: JSONPointer): JSONSchema {
|
|
166
|
+
return this.config.resolveOneOf(this, data, schema, pointer);
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
setSchema(schema: JSONSchema) {
|
|
170
|
+
this.rootSchema = schema;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Returns the json-schema of the given object property or array item.
|
|
175
|
+
* e.g. it steps by one key into the data
|
|
176
|
+
*
|
|
177
|
+
* This helper determines the location of the property within the schema (additional properties, oneOf, ...) and
|
|
178
|
+
* returns the correct schema.
|
|
179
|
+
*
|
|
180
|
+
* @param key - property-name or array-index
|
|
181
|
+
* @param schema - json schema of current data
|
|
182
|
+
* @param data - parent of key
|
|
183
|
+
* @param [pointer] - pointer to schema and data (parent of key)
|
|
184
|
+
* @return Schema or Error if failed resolving key
|
|
185
|
+
*/
|
|
186
|
+
step(key: string | number, schema: JSONSchema, data: any, pointer?: JSONPointer): JSONSchema {
|
|
187
|
+
return this.config.step(this, key, schema, data, pointer);
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
/**
|
|
191
|
+
* Validate data by a json schema
|
|
192
|
+
*
|
|
193
|
+
* @param value - value to validate
|
|
194
|
+
* @param [schema] - json schema, defaults to rootSchema
|
|
195
|
+
* @param [pointer] - json pointer pointing to value (used for error-messages only)
|
|
196
|
+
* @return list of errors or empty
|
|
197
|
+
*/
|
|
198
|
+
validate(data: unknown, schema?: JSONSchema, pointer?: JSONPointer): JSONError[] {
|
|
199
|
+
return this.config.validate(this, data, schema, pointer);
|
|
200
|
+
}
|
|
201
|
+
}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import addRemoteSchema from "../addRemoteSchema";
|
|
2
|
+
import compileSchema from "../compileSchema";
|
|
3
|
+
import { each } from "../each";
|
|
4
|
+
import { eachSchema } from "../eachSchema";
|
|
5
|
+
import ERRORS from "../validation/errors";
|
|
6
|
+
import FORMATS from "../validation/format";
|
|
7
|
+
import getSchema from "../getSchema";
|
|
8
|
+
import getTemplate from "../getTemplate";
|
|
9
|
+
import isValid from "../isValid";
|
|
10
|
+
import KEYWORDS from "../validation/keyword";
|
|
11
|
+
import merge from "../utils/merge";
|
|
12
|
+
import resolveAllOf from "../resolveAllOf";
|
|
13
|
+
import resolveAnyOf from "../resolveAnyOf";
|
|
14
|
+
import resolveOneOf from "../resolveOneOf.strict";
|
|
15
|
+
import resolveRef from "../resolveRef.strict";
|
|
16
|
+
import step from "../step";
|
|
17
|
+
import createSchemaOf from "../createSchemaOf";
|
|
18
|
+
import getChildSchemaSelection from "../getChildSchemaSelection";
|
|
19
|
+
import TYPES from "../validation/type";
|
|
20
|
+
import validate from "../validate";
|
|
21
|
+
import { DraftConfig, Draft } from "../draft";
|
|
22
|
+
import { JSONSchema } from "../types";
|
|
23
|
+
|
|
24
|
+
const draft04Config: DraftConfig = {
|
|
25
|
+
typeKeywords: {
|
|
26
|
+
array: ["enum", "items", "minItems", "maxItems", "uniqueItems", "not"],
|
|
27
|
+
boolean: ["enum", "not"],
|
|
28
|
+
object: [
|
|
29
|
+
"additionalProperties",
|
|
30
|
+
"dependencies",
|
|
31
|
+
"enum",
|
|
32
|
+
"format",
|
|
33
|
+
"minProperties",
|
|
34
|
+
"maxProperties",
|
|
35
|
+
"patternProperties",
|
|
36
|
+
"properties",
|
|
37
|
+
"required",
|
|
38
|
+
"not",
|
|
39
|
+
"oneOf",
|
|
40
|
+
"allOf",
|
|
41
|
+
"anyOf"
|
|
42
|
+
],
|
|
43
|
+
string: [
|
|
44
|
+
"enum",
|
|
45
|
+
"format",
|
|
46
|
+
"maxLength",
|
|
47
|
+
"minLength",
|
|
48
|
+
"pattern",
|
|
49
|
+
"not",
|
|
50
|
+
"oneOf",
|
|
51
|
+
"allOf",
|
|
52
|
+
"anyOf"
|
|
53
|
+
],
|
|
54
|
+
number: [
|
|
55
|
+
"enum",
|
|
56
|
+
"format",
|
|
57
|
+
"maximum",
|
|
58
|
+
"minimum",
|
|
59
|
+
"multipleOf",
|
|
60
|
+
"not",
|
|
61
|
+
"oneOf",
|
|
62
|
+
"allOf",
|
|
63
|
+
"anyOf"
|
|
64
|
+
],
|
|
65
|
+
null: ["enum", "format", "not", "oneOf", "allOf", "anyOf"]
|
|
66
|
+
},
|
|
67
|
+
validateKeyword: KEYWORDS,
|
|
68
|
+
validateType: TYPES,
|
|
69
|
+
validateFormat: FORMATS,
|
|
70
|
+
errors: ERRORS,
|
|
71
|
+
|
|
72
|
+
addRemoteSchema,
|
|
73
|
+
compileSchema,
|
|
74
|
+
createSchemaOf,
|
|
75
|
+
each,
|
|
76
|
+
eachSchema,
|
|
77
|
+
getChildSchemaSelection,
|
|
78
|
+
getSchema,
|
|
79
|
+
getTemplate,
|
|
80
|
+
isValid,
|
|
81
|
+
resolveAllOf,
|
|
82
|
+
resolveAnyOf,
|
|
83
|
+
resolveOneOf,
|
|
84
|
+
resolveRef,
|
|
85
|
+
step,
|
|
86
|
+
validate
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
class Draft04 extends Draft {
|
|
90
|
+
constructor(schema?: JSONSchema, config: Partial<DraftConfig> = {}) {
|
|
91
|
+
super(merge(draft04Config, config), schema);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
export { Draft04, draft04Config };
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/* eslint max-statements-per-line: ["error", { "max": 2 }] */
|
|
2
|
+
import { Draft } from "../../draft";
|
|
3
|
+
import { eachSchema } from "../../eachSchema";
|
|
4
|
+
// import remotes from "../../../remotes";
|
|
5
|
+
import joinScope from "../../compile/joinScope";
|
|
6
|
+
import getRef from "../../compile/getRef";
|
|
7
|
+
import { JSONSchema } from "../../types";
|
|
8
|
+
|
|
9
|
+
const COMPILED = "__compiled";
|
|
10
|
+
const COMPILED_REF = "__ref";
|
|
11
|
+
const GET_REF = "getRef";
|
|
12
|
+
const GET_ROOT = "getRoot";
|
|
13
|
+
const suffixes = /(#|\/)+$/g;
|
|
14
|
+
|
|
15
|
+
type Context = {
|
|
16
|
+
ids: Record<string, unknown>;
|
|
17
|
+
remotes: Record<string, JSONSchema>;
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* @draft starting with _draft 06_ keyword `id` has been renamed to `$id`
|
|
22
|
+
*
|
|
23
|
+
* compiles the input root schema for $ref resolution and returns it again
|
|
24
|
+
* @attention this modifies input schema but maintains object-structure
|
|
25
|
+
*
|
|
26
|
+
* for a compiled json-schema you can call getRef on any contained schema (location of type).
|
|
27
|
+
* this resolves a $ref target to a valid schema (for a valid $ref)
|
|
28
|
+
*
|
|
29
|
+
* @param rootSchema root json-schema ($id, defs, ... ) to compile
|
|
30
|
+
* @param [force] = false force compile json-schema
|
|
31
|
+
* @return compiled json-schema
|
|
32
|
+
*/
|
|
33
|
+
export default function compileSchema(
|
|
34
|
+
draft: Draft,
|
|
35
|
+
schemaToCompile: JSONSchema,
|
|
36
|
+
rootSchema = schemaToCompile,
|
|
37
|
+
force = false
|
|
38
|
+
): JSONSchema {
|
|
39
|
+
// @ts-ignore
|
|
40
|
+
if (schemaToCompile === true || schemaToCompile === false || schemaToCompile === undefined) {
|
|
41
|
+
return schemaToCompile;
|
|
42
|
+
}
|
|
43
|
+
if (schemaToCompile[COMPILED] !== undefined) {
|
|
44
|
+
return schemaToCompile;
|
|
45
|
+
} // eslint-disable-line
|
|
46
|
+
const context: Context = { ids: {}, remotes: draft.remotes };
|
|
47
|
+
const rootSchemaAsString = JSON.stringify(schemaToCompile);
|
|
48
|
+
const compiledSchema = JSON.parse(rootSchemaAsString);
|
|
49
|
+
Object.defineProperty(compiledSchema, COMPILED, { enumerable: false, value: true });
|
|
50
|
+
Object.defineProperty(compiledSchema, GET_REF, {
|
|
51
|
+
enumerable: false,
|
|
52
|
+
value: getRef.bind(null, context, compiledSchema)
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
// bail early, when no $refs are defined
|
|
56
|
+
if (force === false && rootSchemaAsString.includes("$ref") === false) {
|
|
57
|
+
return compiledSchema;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// compile this schema under rootSchema, making definitions available to $ref-resolution
|
|
61
|
+
if (compiledSchema !== rootSchema) {
|
|
62
|
+
Object.defineProperty(compiledSchema, "$defs", {
|
|
63
|
+
enumerable: true,
|
|
64
|
+
value: Object.assign(
|
|
65
|
+
{},
|
|
66
|
+
rootSchema.definitions,
|
|
67
|
+
rootSchema.$defs,
|
|
68
|
+
compiledSchema.definitions,
|
|
69
|
+
compiledSchema.$defs
|
|
70
|
+
)
|
|
71
|
+
});
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const scopes: Record<string, string> = {};
|
|
75
|
+
const getRoot = () => compiledSchema;
|
|
76
|
+
eachSchema(compiledSchema, (schema, pointer) => {
|
|
77
|
+
if (schema.$id) {
|
|
78
|
+
context.ids[schema.$id.replace(suffixes, "")] = pointer;
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
// build up scopes and add them to $ref-resolution map
|
|
82
|
+
pointer = `#${pointer}`.replace(/##+/, "#");
|
|
83
|
+
const previousPointer = pointer.replace(/\/[^/]+$/, "");
|
|
84
|
+
const parentPointer = pointer.replace(/\/[^/]+\/[^/]+$/, "");
|
|
85
|
+
const previousScope = scopes[previousPointer] || scopes[parentPointer];
|
|
86
|
+
const scope = joinScope(previousScope, schema.$id);
|
|
87
|
+
scopes[pointer] = scope;
|
|
88
|
+
if (context.ids[scope] == null) {
|
|
89
|
+
context.ids[scope] = pointer;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
if (schema.$ref && !schema[COMPILED_REF]) {
|
|
93
|
+
Object.defineProperty(schema, COMPILED_REF, {
|
|
94
|
+
enumerable: false,
|
|
95
|
+
value: joinScope(scope, schema.$ref)
|
|
96
|
+
});
|
|
97
|
+
// @todo currently not used:
|
|
98
|
+
Object.defineProperty(schema, GET_ROOT, { enumerable: false, value: getRoot });
|
|
99
|
+
// console.log("compiled ref", scope, schema.$ref, "=>", joinScope(scope, schema.$ref));
|
|
100
|
+
}
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
return compiledSchema;
|
|
104
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
import addRemoteSchema from "../addRemoteSchema";
|
|
2
|
+
import compileSchema from "../draft06/compile";
|
|
3
|
+
import { each } from "../each";
|
|
4
|
+
import { eachSchema } from "../eachSchema";
|
|
5
|
+
import ERRORS from "../validation/errors";
|
|
6
|
+
import FORMATS from "../validation/format";
|
|
7
|
+
import getSchema from "../getSchema";
|
|
8
|
+
import getTemplate from "../getTemplate";
|
|
9
|
+
import isValid from "../isValid";
|
|
10
|
+
import KEYWORDS from "../draft06/validation/keyword";
|
|
11
|
+
import merge from "../utils/merge";
|
|
12
|
+
import resolveAllOf from "../resolveAllOf";
|
|
13
|
+
import resolveAnyOf from "../resolveAnyOf";
|
|
14
|
+
import resolveOneOf from "../resolveOneOf.strict";
|
|
15
|
+
import resolveRef from "../resolveRef.strict";
|
|
16
|
+
import createSchemaOf from "../createSchemaOf";
|
|
17
|
+
import getChildSchemaSelection from "../getChildSchemaSelection";
|
|
18
|
+
import step from "../step";
|
|
19
|
+
import TYPES from "../draft06/validation/type";
|
|
20
|
+
import validate from "../validate";
|
|
21
|
+
import { DraftConfig, Draft } from "../draft";
|
|
22
|
+
import { JSONSchema } from "../types";
|
|
23
|
+
|
|
24
|
+
const draft06Config: DraftConfig = {
|
|
25
|
+
typeKeywords: {
|
|
26
|
+
array: ["enum", "contains", "items", "minItems", "maxItems", "uniqueItems", "not", "if"],
|
|
27
|
+
boolean: ["enum", "not"],
|
|
28
|
+
object: [
|
|
29
|
+
"additionalProperties",
|
|
30
|
+
"dependencies",
|
|
31
|
+
"enum",
|
|
32
|
+
"format",
|
|
33
|
+
"minProperties",
|
|
34
|
+
"maxProperties",
|
|
35
|
+
"patternProperties",
|
|
36
|
+
"properties",
|
|
37
|
+
"propertyNames",
|
|
38
|
+
"required",
|
|
39
|
+
"not",
|
|
40
|
+
"oneOf",
|
|
41
|
+
"allOf",
|
|
42
|
+
"anyOf",
|
|
43
|
+
"if"
|
|
44
|
+
],
|
|
45
|
+
string: [
|
|
46
|
+
"enum",
|
|
47
|
+
"format",
|
|
48
|
+
"maxLength",
|
|
49
|
+
"minLength",
|
|
50
|
+
"pattern",
|
|
51
|
+
"not",
|
|
52
|
+
"oneOf",
|
|
53
|
+
"allOf",
|
|
54
|
+
"anyOf",
|
|
55
|
+
"if"
|
|
56
|
+
],
|
|
57
|
+
number: [
|
|
58
|
+
"enum",
|
|
59
|
+
"exclusiveMaximum",
|
|
60
|
+
"exclusiveMinimum",
|
|
61
|
+
"format",
|
|
62
|
+
"maximum",
|
|
63
|
+
"minimum",
|
|
64
|
+
"multipleOf",
|
|
65
|
+
"not",
|
|
66
|
+
"oneOf",
|
|
67
|
+
"allOf",
|
|
68
|
+
"anyOf",
|
|
69
|
+
"if"
|
|
70
|
+
],
|
|
71
|
+
null: ["enum", "format", "not", "oneOf", "allOf", "anyOf"]
|
|
72
|
+
},
|
|
73
|
+
validateKeyword: KEYWORDS,
|
|
74
|
+
validateType: TYPES,
|
|
75
|
+
validateFormat: FORMATS,
|
|
76
|
+
errors: ERRORS,
|
|
77
|
+
|
|
78
|
+
addRemoteSchema,
|
|
79
|
+
compileSchema,
|
|
80
|
+
createSchemaOf,
|
|
81
|
+
each,
|
|
82
|
+
eachSchema,
|
|
83
|
+
getChildSchemaSelection,
|
|
84
|
+
getSchema,
|
|
85
|
+
getTemplate,
|
|
86
|
+
isValid,
|
|
87
|
+
resolveAllOf,
|
|
88
|
+
resolveAnyOf,
|
|
89
|
+
resolveOneOf,
|
|
90
|
+
resolveRef,
|
|
91
|
+
step,
|
|
92
|
+
validate
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
class Draft06 extends Draft {
|
|
96
|
+
constructor(schema?: JSONSchema, config: Partial<DraftConfig> = {}) {
|
|
97
|
+
super(merge(draft06Config, config), schema);
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export { Draft06, draft06Config };
|
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
import Keywords from "../../validation/keyword";
|
|
2
|
+
import getTypeOf from "../../getTypeOf";
|
|
3
|
+
import { JSONValidator, JSONError } from "../../types";
|
|
4
|
+
|
|
5
|
+
const KeywordValidation: Record<string, JSONValidator> = {
|
|
6
|
+
...Keywords,
|
|
7
|
+
// @draft >= 6
|
|
8
|
+
contains: (core, schema, value: unknown[], pointer) => {
|
|
9
|
+
if (schema.contains === false) {
|
|
10
|
+
return core.errors.containsArrayError({ pointer, value });
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
if (schema.contains === true) {
|
|
14
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
15
|
+
return core.errors.containsAnyError({ pointer });
|
|
16
|
+
}
|
|
17
|
+
return undefined;
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
if (getTypeOf(schema.contains) !== "object") {
|
|
21
|
+
// ignore invalid schema
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
for (let i = 0; i < value.length; i += 1) {
|
|
26
|
+
if (core.isValid(value[i], schema.contains)) {
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
return core.errors.containsError({ pointer, schema: JSON.stringify(schema.contains) });
|
|
31
|
+
},
|
|
32
|
+
exclusiveMaximum: (core, schema, value, pointer) => {
|
|
33
|
+
if (isNaN(schema.exclusiveMaximum)) {
|
|
34
|
+
return undefined;
|
|
35
|
+
}
|
|
36
|
+
if (schema.exclusiveMaximum <= value) {
|
|
37
|
+
return core.errors.maximumError({
|
|
38
|
+
maximum: schema.exclusiveMaximum,
|
|
39
|
+
length: value,
|
|
40
|
+
pointer
|
|
41
|
+
});
|
|
42
|
+
}
|
|
43
|
+
return undefined;
|
|
44
|
+
},
|
|
45
|
+
exclusiveMinimum: (core, schema, value, pointer) => {
|
|
46
|
+
if (isNaN(schema.exclusiveMinimum)) {
|
|
47
|
+
return undefined;
|
|
48
|
+
}
|
|
49
|
+
if (schema.exclusiveMinimum >= value) {
|
|
50
|
+
return core.errors.minimumError({
|
|
51
|
+
minimum: schema.exclusiveMinimum,
|
|
52
|
+
length: value,
|
|
53
|
+
pointer
|
|
54
|
+
});
|
|
55
|
+
}
|
|
56
|
+
return undefined;
|
|
57
|
+
},
|
|
58
|
+
if: (core, schema, value, pointer) => {
|
|
59
|
+
if (schema.if == null) {
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
const ifErrors = core.validate(value, schema.if, pointer);
|
|
64
|
+
// console.log("if Errors", value, ifErrors);
|
|
65
|
+
|
|
66
|
+
if (ifErrors.length === 0 && schema.then) {
|
|
67
|
+
return core.validate(value, schema.then, pointer);
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
if (ifErrors.length !== 0 && schema.else) {
|
|
71
|
+
return core.validate(value, schema.else, pointer);
|
|
72
|
+
}
|
|
73
|
+
},
|
|
74
|
+
maximum: (core, schema, value, pointer) => {
|
|
75
|
+
if (isNaN(schema.maximum)) {
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
if (schema.maximum && schema.maximum < value) {
|
|
79
|
+
return core.errors.maximumError({ maximum: schema.maximum, length: value, pointer });
|
|
80
|
+
}
|
|
81
|
+
return undefined;
|
|
82
|
+
},
|
|
83
|
+
minimum: (core, schema, value, pointer) => {
|
|
84
|
+
if (isNaN(schema.minimum)) {
|
|
85
|
+
return undefined;
|
|
86
|
+
}
|
|
87
|
+
if (schema.minimum > value) {
|
|
88
|
+
return core.errors.minimumError({ minimum: schema.minimum, length: value, pointer });
|
|
89
|
+
}
|
|
90
|
+
return undefined;
|
|
91
|
+
},
|
|
92
|
+
patternProperties: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
93
|
+
const properties = schema.properties || {};
|
|
94
|
+
const pp = schema.patternProperties;
|
|
95
|
+
if (getTypeOf(pp) !== "object") {
|
|
96
|
+
return undefined;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
const errors: JSONError[] = [];
|
|
100
|
+
const keys = Object.keys(value);
|
|
101
|
+
const patterns = Object.keys(pp).map((expr) => ({
|
|
102
|
+
regex: new RegExp(expr),
|
|
103
|
+
patternSchema: pp[expr]
|
|
104
|
+
}));
|
|
105
|
+
|
|
106
|
+
keys.forEach((key) => {
|
|
107
|
+
let patternFound = false;
|
|
108
|
+
|
|
109
|
+
for (let i = 0, l = patterns.length; i < l; i += 1) {
|
|
110
|
+
if (patterns[i].regex.test(key)) {
|
|
111
|
+
patternFound = true;
|
|
112
|
+
|
|
113
|
+
// for a boolean schema `false`, always invalidate
|
|
114
|
+
if (patterns[i].patternSchema === false) {
|
|
115
|
+
errors.push(
|
|
116
|
+
core.errors.patternPropertiesError({
|
|
117
|
+
key,
|
|
118
|
+
pointer,
|
|
119
|
+
patterns: Object.keys(pp).join(",")
|
|
120
|
+
})
|
|
121
|
+
);
|
|
122
|
+
return;
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
const valErrors = core.validate(
|
|
126
|
+
value[key],
|
|
127
|
+
patterns[i].patternSchema,
|
|
128
|
+
`${pointer}/${key}`
|
|
129
|
+
);
|
|
130
|
+
if (valErrors && valErrors.length > 0) {
|
|
131
|
+
errors.push(...valErrors);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
if (properties[key]) {
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
if (patternFound === false && schema.additionalProperties === false) {
|
|
141
|
+
// this is an arrangement with additionalProperties
|
|
142
|
+
errors.push(
|
|
143
|
+
core.errors.patternPropertiesError({
|
|
144
|
+
key,
|
|
145
|
+
pointer,
|
|
146
|
+
patterns: Object.keys(pp).join(",")
|
|
147
|
+
})
|
|
148
|
+
);
|
|
149
|
+
}
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
return errors;
|
|
153
|
+
},
|
|
154
|
+
// @draft >= 6
|
|
155
|
+
propertyNames: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
156
|
+
// bool schema
|
|
157
|
+
if (schema.propertyNames === false) {
|
|
158
|
+
// empty objects are valid
|
|
159
|
+
if (Object.keys(value).length === 0) {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
return core.errors.invalidPropertyNameError({
|
|
163
|
+
property: Object.keys(value),
|
|
164
|
+
pointer,
|
|
165
|
+
value
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
169
|
+
if (schema.propertyNames === true) {
|
|
170
|
+
return undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
if (getTypeOf(schema.propertyNames) !== "object") {
|
|
174
|
+
// ignore invalid schema
|
|
175
|
+
return undefined;
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
const errors: JSONError[] = [];
|
|
179
|
+
const properties = Object.keys(value);
|
|
180
|
+
const propertySchema = { ...schema.propertyNames, type: "string" };
|
|
181
|
+
properties.forEach((prop) => {
|
|
182
|
+
const validationResult = core.validate(prop, propertySchema, `${pointer}/${prop}`);
|
|
183
|
+
if (validationResult.length > 0) {
|
|
184
|
+
errors.push(
|
|
185
|
+
core.errors.invalidPropertyNameError({
|
|
186
|
+
property: prop,
|
|
187
|
+
pointer,
|
|
188
|
+
validationError: validationResult[0],
|
|
189
|
+
value: value[prop]
|
|
190
|
+
})
|
|
191
|
+
);
|
|
192
|
+
}
|
|
193
|
+
});
|
|
194
|
+
|
|
195
|
+
return errors;
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
|
|
199
|
+
export default KeywordValidation;
|