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
|
@@ -2,31 +2,41 @@ import getTypeOf from "../getTypeOf";
|
|
|
2
2
|
import isSame from "../utils/deepCompare";
|
|
3
3
|
import settings from "../config/settings";
|
|
4
4
|
import ucs2decode from "../utils/punycode.ucs2decode";
|
|
5
|
+
import { JSONValidator, isJSONError, JSONSchema, JSONError } from "../types";
|
|
5
6
|
const FPP = settings.floatingPointPrecision;
|
|
6
7
|
|
|
8
|
+
const hasOwnProperty = Object.prototype.hasOwnProperty;
|
|
9
|
+
const hasProperty = (value: Record<string, unknown>, property: string) =>
|
|
10
|
+
!(value[property] === undefined || !hasOwnProperty.call(value, property));
|
|
7
11
|
|
|
8
12
|
// list of validation keywords: http://json-schema.org/latest/json-schema-validation.html#rfc.section.5
|
|
9
|
-
const KeywordValidation = {
|
|
10
|
-
|
|
11
|
-
additionalProperties: (core, schema, value, pointer) => {
|
|
13
|
+
const KeywordValidation: Record<string, JSONValidator> = {
|
|
14
|
+
additionalProperties: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
12
15
|
if (schema.additionalProperties === true || schema.additionalProperties == null) {
|
|
13
16
|
return undefined;
|
|
14
17
|
}
|
|
15
18
|
|
|
16
|
-
if (
|
|
19
|
+
if (
|
|
20
|
+
getTypeOf(schema.patternProperties) === "object" &&
|
|
21
|
+
schema.additionalProperties === false
|
|
22
|
+
) {
|
|
17
23
|
// this is an arrangement with patternProperties. patternProperties validate before additionalProperties:
|
|
18
24
|
// https://spacetelescope.github.io/understanding-json-schema/reference/object.html#index-5
|
|
19
25
|
return undefined;
|
|
20
26
|
}
|
|
21
27
|
|
|
22
|
-
const errors = [];
|
|
23
|
-
let receivedProperties = Object.keys(value).filter(
|
|
28
|
+
const errors: JSONError[] = [];
|
|
29
|
+
let receivedProperties = Object.keys(value).filter(
|
|
30
|
+
(prop) => settings.propertyBlacklist.includes(prop) === false
|
|
31
|
+
);
|
|
24
32
|
const expectedProperties = Object.keys(schema.properties || {});
|
|
25
33
|
|
|
26
34
|
if (getTypeOf(schema.patternProperties) === "object") {
|
|
27
35
|
// filter received properties by matching patternProperties
|
|
28
|
-
const patterns = Object.keys(schema.patternProperties).map(
|
|
29
|
-
|
|
36
|
+
const patterns = Object.keys(schema.patternProperties).map(
|
|
37
|
+
(pattern) => new RegExp(pattern)
|
|
38
|
+
);
|
|
39
|
+
receivedProperties = receivedProperties.filter((prop) => {
|
|
30
40
|
for (let i = 0; i < patterns.length; i += 1) {
|
|
31
41
|
if (patterns[i].test(prop)) {
|
|
32
42
|
return false; // remove
|
|
@@ -45,37 +55,48 @@ const KeywordValidation = {
|
|
|
45
55
|
// additionalProperties { oneOf: [] }
|
|
46
56
|
if (isObject && Array.isArray(schema.additionalProperties.oneOf)) {
|
|
47
57
|
const result = core.resolveOneOf(
|
|
48
|
-
value[property],
|
|
58
|
+
value[property],
|
|
59
|
+
schema.additionalProperties,
|
|
60
|
+
`${pointer}/${property}`
|
|
49
61
|
);
|
|
50
|
-
if (result
|
|
51
|
-
errors.push(
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
62
|
+
if (isJSONError(result)) {
|
|
63
|
+
errors.push(
|
|
64
|
+
core.errors.additionalPropertiesError({
|
|
65
|
+
schema: schema.additionalProperties,
|
|
66
|
+
property: receivedProperties[i],
|
|
67
|
+
properties: expectedProperties,
|
|
68
|
+
pointer,
|
|
69
|
+
// pass all validation errors
|
|
70
|
+
errors: result.data.errors
|
|
71
|
+
})
|
|
72
|
+
);
|
|
60
73
|
} else {
|
|
61
|
-
errors.push(core.validate(value[property], result, pointer));
|
|
74
|
+
errors.push(...core.validate(value[property], result, pointer));
|
|
62
75
|
}
|
|
63
76
|
|
|
64
|
-
|
|
77
|
+
// additionalProperties {}
|
|
65
78
|
} else if (isObject) {
|
|
66
|
-
if (
|
|
67
|
-
|
|
68
|
-
|
|
79
|
+
if (
|
|
80
|
+
core.validate(value[property], schema.additionalProperties, pointer)
|
|
81
|
+
.length !== 0
|
|
82
|
+
) {
|
|
83
|
+
errors.push(
|
|
84
|
+
core.errors.additionalPropertiesError({
|
|
85
|
+
schema: schema.additionalProperties,
|
|
86
|
+
property: receivedProperties[i],
|
|
87
|
+
properties: expectedProperties,
|
|
88
|
+
pointer
|
|
89
|
+
})
|
|
90
|
+
);
|
|
91
|
+
}
|
|
92
|
+
} else {
|
|
93
|
+
errors.push(
|
|
94
|
+
core.errors.noAdditionalPropertiesError({
|
|
69
95
|
property: receivedProperties[i],
|
|
70
96
|
properties: expectedProperties,
|
|
71
97
|
pointer
|
|
72
|
-
})
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
} else {
|
|
76
|
-
errors.push(core.errors.noAdditionalPropertiesError(
|
|
77
|
-
{ property: receivedProperties[i], properties: expectedProperties, pointer }
|
|
78
|
-
));
|
|
98
|
+
})
|
|
99
|
+
);
|
|
79
100
|
}
|
|
80
101
|
}
|
|
81
102
|
}
|
|
@@ -88,9 +109,9 @@ const KeywordValidation = {
|
|
|
88
109
|
return undefined;
|
|
89
110
|
}
|
|
90
111
|
|
|
91
|
-
const errors = [];
|
|
92
|
-
schema.allOf.forEach(subSchema => {
|
|
93
|
-
errors.push(core.validate(value, subSchema, pointer));
|
|
112
|
+
const errors: JSONError[] = [];
|
|
113
|
+
schema.allOf.forEach((subSchema: JSONSchema) => {
|
|
114
|
+
errors.push(...core.validate(value, subSchema, pointer));
|
|
94
115
|
});
|
|
95
116
|
|
|
96
117
|
return errors;
|
|
@@ -110,38 +131,49 @@ const KeywordValidation = {
|
|
|
110
131
|
return core.errors.anyOfError({ anyOf: schema.anyOf, value, pointer });
|
|
111
132
|
},
|
|
112
133
|
|
|
113
|
-
dependencies: (core, schema, value, pointer) => {
|
|
134
|
+
dependencies: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
114
135
|
if (getTypeOf(schema.dependencies) !== "object") {
|
|
115
136
|
return undefined;
|
|
116
137
|
}
|
|
117
138
|
|
|
118
|
-
const errors = [];
|
|
119
|
-
Object.keys(value)
|
|
120
|
-
.
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
}
|
|
139
|
+
const errors: JSONError[] = [];
|
|
140
|
+
Object.keys(value).forEach((property) => {
|
|
141
|
+
if (schema.dependencies[property] === undefined) {
|
|
142
|
+
return;
|
|
143
|
+
}
|
|
124
144
|
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
145
|
+
// @draft >= 6 boolean schema
|
|
146
|
+
if (schema.dependencies[property] === true) {
|
|
147
|
+
return;
|
|
148
|
+
}
|
|
149
|
+
if (schema.dependencies[property] === false) {
|
|
150
|
+
errors.push(core.errors.missingDependencyError({ pointer }));
|
|
151
|
+
return;
|
|
152
|
+
}
|
|
133
153
|
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
154
|
+
let dependencyErrors;
|
|
155
|
+
const type = getTypeOf(schema.dependencies[property]);
|
|
156
|
+
if (type === "array") {
|
|
157
|
+
dependencyErrors = schema.dependencies[property]
|
|
158
|
+
.filter((dependency: any) => value[dependency] === undefined)
|
|
159
|
+
.map((missingProperty: any) =>
|
|
160
|
+
core.errors.missingDependencyError({ missingProperty, pointer })
|
|
161
|
+
);
|
|
162
|
+
} else if (type === "object") {
|
|
163
|
+
dependencyErrors = core.validate(value, schema.dependencies[property]);
|
|
164
|
+
} else {
|
|
165
|
+
throw new Error(
|
|
166
|
+
`Invalid dependency definition for ${pointer}/${property}. Must be list or schema`
|
|
167
|
+
);
|
|
168
|
+
}
|
|
137
169
|
|
|
138
|
-
|
|
139
|
-
|
|
170
|
+
errors.push(...dependencyErrors);
|
|
171
|
+
});
|
|
140
172
|
|
|
141
173
|
return errors.length > 0 ? errors : undefined;
|
|
142
174
|
},
|
|
143
175
|
|
|
144
|
-
|
|
176
|
+
enum: (core, schema, value, pointer) => {
|
|
145
177
|
const type = getTypeOf(value);
|
|
146
178
|
if (type === "object" || type === "array") {
|
|
147
179
|
const valueStr = JSON.stringify(value);
|
|
@@ -163,14 +195,21 @@ const KeywordValidation = {
|
|
|
163
195
|
// fail silently if given format is not defined
|
|
164
196
|
return undefined;
|
|
165
197
|
},
|
|
166
|
-
items: (core, schema, value, pointer) => {
|
|
167
|
-
|
|
198
|
+
items: (core, schema, value: unknown[], pointer) => {
|
|
199
|
+
// @draft >= 7 bool schema
|
|
200
|
+
if (schema.items === false) {
|
|
201
|
+
if (Array.isArray(value) && value.length === 0) {
|
|
202
|
+
return undefined;
|
|
203
|
+
}
|
|
204
|
+
return core.errors.invalidDataError({ pointer, value });
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
const errors: JSONError[] = [];
|
|
168
208
|
for (let i = 0; i < value.length; i += 1) {
|
|
169
209
|
const itemData = value[i];
|
|
170
210
|
// @todo reevaluate: incomplete schema is created here
|
|
171
211
|
const itemSchema = core.step(i, schema, value, pointer);
|
|
172
|
-
|
|
173
|
-
if (itemSchema && itemSchema.type === "error") {
|
|
212
|
+
if (isJSONError(itemSchema)) {
|
|
174
213
|
return [itemSchema];
|
|
175
214
|
}
|
|
176
215
|
|
|
@@ -192,22 +231,30 @@ const KeywordValidation = {
|
|
|
192
231
|
}
|
|
193
232
|
return undefined;
|
|
194
233
|
},
|
|
195
|
-
maxItems: (core, schema, value, pointer) => {
|
|
234
|
+
maxItems: (core, schema, value: unknown[], pointer) => {
|
|
196
235
|
if (isNaN(schema.maxItems)) {
|
|
197
236
|
return undefined;
|
|
198
237
|
}
|
|
199
238
|
if (schema.maxItems < value.length) {
|
|
200
|
-
return core.errors.maxItemsError({
|
|
239
|
+
return core.errors.maxItemsError({
|
|
240
|
+
maximum: schema.maxItems,
|
|
241
|
+
length: value.length,
|
|
242
|
+
pointer
|
|
243
|
+
});
|
|
201
244
|
}
|
|
202
245
|
return undefined;
|
|
203
246
|
},
|
|
204
|
-
maxLength: (core, schema, value, pointer) => {
|
|
247
|
+
maxLength: (core, schema, value: string, pointer) => {
|
|
205
248
|
if (isNaN(schema.maxLength)) {
|
|
206
249
|
return undefined;
|
|
207
250
|
}
|
|
208
251
|
const lengthOfString = ucs2decode(value).length;
|
|
209
252
|
if (schema.maxLength < lengthOfString) {
|
|
210
|
-
return core.errors.maxLengthError({
|
|
253
|
+
return core.errors.maxLengthError({
|
|
254
|
+
maxLength: schema.maxLength,
|
|
255
|
+
length: lengthOfString,
|
|
256
|
+
pointer
|
|
257
|
+
});
|
|
211
258
|
}
|
|
212
259
|
return undefined;
|
|
213
260
|
},
|
|
@@ -222,13 +269,17 @@ const KeywordValidation = {
|
|
|
222
269
|
}
|
|
223
270
|
return undefined;
|
|
224
271
|
},
|
|
225
|
-
minLength: (core, schema, value, pointer) => {
|
|
272
|
+
minLength: (core, schema, value: string, pointer) => {
|
|
226
273
|
if (isNaN(schema.minLength)) {
|
|
227
274
|
return undefined;
|
|
228
275
|
}
|
|
229
276
|
const lengthOfString = ucs2decode(value).length;
|
|
230
277
|
if (schema.minLength > lengthOfString) {
|
|
231
|
-
return core.errors.minLengthError({
|
|
278
|
+
return core.errors.minLengthError({
|
|
279
|
+
minLength: schema.minLength,
|
|
280
|
+
length: lengthOfString,
|
|
281
|
+
pointer
|
|
282
|
+
});
|
|
232
283
|
}
|
|
233
284
|
return undefined;
|
|
234
285
|
},
|
|
@@ -244,12 +295,16 @@ const KeywordValidation = {
|
|
|
244
295
|
}
|
|
245
296
|
return undefined;
|
|
246
297
|
},
|
|
247
|
-
minItems: (core, schema, value, pointer) => {
|
|
298
|
+
minItems: (core, schema, value: unknown[], pointer) => {
|
|
248
299
|
if (isNaN(schema.minItems)) {
|
|
249
300
|
return undefined;
|
|
250
301
|
}
|
|
251
302
|
if (schema.minItems > value.length) {
|
|
252
|
-
return core.errors.minItemsError({
|
|
303
|
+
return core.errors.minItemsError({
|
|
304
|
+
minItems: schema.minItems,
|
|
305
|
+
length: value.length,
|
|
306
|
+
pointer
|
|
307
|
+
});
|
|
253
308
|
}
|
|
254
309
|
return undefined;
|
|
255
310
|
},
|
|
@@ -261,24 +316,26 @@ const KeywordValidation = {
|
|
|
261
316
|
if (schema.minProperties > propertyCount) {
|
|
262
317
|
return core.errors.minPropertiesError({
|
|
263
318
|
minProperties: schema.minProperties,
|
|
264
|
-
length: propertyCount,
|
|
319
|
+
length: propertyCount,
|
|
320
|
+
pointer
|
|
265
321
|
});
|
|
266
322
|
}
|
|
267
323
|
return undefined;
|
|
268
324
|
},
|
|
269
|
-
multipleOf: (core, schema, value, pointer) => {
|
|
325
|
+
multipleOf: (core, schema, value: number, pointer) => {
|
|
270
326
|
if (isNaN(schema.multipleOf)) {
|
|
271
327
|
return undefined;
|
|
272
328
|
}
|
|
273
329
|
// https://github.com/cfworker/cfworker/blob/master/packages/json-schema/src/validate.ts#L1061
|
|
274
330
|
// https://github.com/ExodusMovement/schemasafe/blob/master/src/compile.js#L441
|
|
275
|
-
if ((value * FPP) % (schema.multipleOf * FPP) / FPP !== 0) {
|
|
331
|
+
if (((value * FPP) % (schema.multipleOf * FPP)) / FPP !== 0) {
|
|
276
332
|
return core.errors.multipleOfError({ multipleOf: schema.multipleOf, value, pointer });
|
|
277
333
|
}
|
|
334
|
+
// also check https://stackoverflow.com/questions/1815367/catch-and-compute-overflow-during-multiplication-of-two-large-integers
|
|
278
335
|
return undefined;
|
|
279
336
|
},
|
|
280
337
|
not: (core, schema, value, pointer) => {
|
|
281
|
-
const errors = [];
|
|
338
|
+
const errors: JSONError[] = [];
|
|
282
339
|
if (core.validate(value, schema.not, pointer).length === 0) {
|
|
283
340
|
errors.push(core.errors.notError({ value, not: schema.not, pointer }));
|
|
284
341
|
}
|
|
@@ -290,44 +347,49 @@ const KeywordValidation = {
|
|
|
290
347
|
}
|
|
291
348
|
|
|
292
349
|
schema = core.resolveOneOf(value, schema, pointer);
|
|
293
|
-
if (schema
|
|
350
|
+
if (isJSONError(schema)) {
|
|
294
351
|
return schema;
|
|
295
352
|
}
|
|
296
353
|
|
|
297
354
|
return undefined;
|
|
298
355
|
},
|
|
299
|
-
pattern: (core, schema, value, pointer) => {
|
|
356
|
+
pattern: (core, schema, value: string, pointer) => {
|
|
300
357
|
const pattern = new RegExp(schema.pattern, "u");
|
|
301
358
|
if (pattern.test(value) === false) {
|
|
302
359
|
return core.errors.patternError({
|
|
303
360
|
pattern: schema.pattern,
|
|
304
361
|
description: schema.patternExample || schema.pattern,
|
|
305
|
-
received: value,
|
|
362
|
+
received: value,
|
|
363
|
+
pointer
|
|
306
364
|
});
|
|
307
365
|
}
|
|
308
366
|
return undefined;
|
|
309
367
|
},
|
|
310
|
-
patternProperties: (core, schema, value, pointer) => {
|
|
368
|
+
patternProperties: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
311
369
|
const properties = schema.properties || {};
|
|
312
370
|
const pp = schema.patternProperties;
|
|
313
371
|
if (getTypeOf(pp) !== "object") {
|
|
314
372
|
return undefined;
|
|
315
373
|
}
|
|
316
374
|
|
|
317
|
-
const errors = [];
|
|
375
|
+
const errors: JSONError[] = [];
|
|
318
376
|
const keys = Object.keys(value);
|
|
319
|
-
const patterns = Object.keys(pp).map(expr => ({
|
|
377
|
+
const patterns = Object.keys(pp).map((expr) => ({
|
|
320
378
|
regex: new RegExp(expr),
|
|
321
379
|
patternSchema: pp[expr]
|
|
322
380
|
}));
|
|
323
381
|
|
|
324
|
-
keys.forEach(key => {
|
|
382
|
+
keys.forEach((key) => {
|
|
325
383
|
let patternFound = false;
|
|
326
384
|
|
|
327
385
|
for (let i = 0, l = patterns.length; i < l; i += 1) {
|
|
328
386
|
if (patterns[i].regex.test(key)) {
|
|
329
387
|
patternFound = true;
|
|
330
|
-
const valErrors = core.validate(
|
|
388
|
+
const valErrors = core.validate(
|
|
389
|
+
value[key],
|
|
390
|
+
patterns[i].patternSchema,
|
|
391
|
+
`${pointer}/${key}`
|
|
392
|
+
);
|
|
331
393
|
if (valErrors && valErrors.length > 0) {
|
|
332
394
|
errors.push(...valErrors);
|
|
333
395
|
}
|
|
@@ -340,20 +402,24 @@ const KeywordValidation = {
|
|
|
340
402
|
|
|
341
403
|
if (patternFound === false && schema.additionalProperties === false) {
|
|
342
404
|
// this is an arrangement with additionalProperties
|
|
343
|
-
errors.push(
|
|
344
|
-
|
|
345
|
-
|
|
405
|
+
errors.push(
|
|
406
|
+
core.errors.patternPropertiesError({
|
|
407
|
+
key,
|
|
408
|
+
pointer,
|
|
409
|
+
patterns: Object.keys(pp).join(",")
|
|
410
|
+
})
|
|
411
|
+
);
|
|
346
412
|
}
|
|
347
413
|
});
|
|
348
414
|
|
|
349
415
|
return errors;
|
|
350
416
|
},
|
|
351
|
-
properties: (core, schema, value, pointer) => {
|
|
352
|
-
const errors = [];
|
|
417
|
+
properties: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
418
|
+
const errors: JSONError[] = [];
|
|
353
419
|
const keys = Object.keys(schema.properties || {});
|
|
354
420
|
for (let i = 0; i < keys.length; i += 1) {
|
|
355
421
|
const key = keys[i];
|
|
356
|
-
if (value
|
|
422
|
+
if (hasProperty(value, key)) {
|
|
357
423
|
const itemSchema = core.step(key, schema, value, pointer);
|
|
358
424
|
const keyErrors = core.validate(value[key], itemSchema, `${pointer}/${key}`);
|
|
359
425
|
errors.push(...keyErrors);
|
|
@@ -362,8 +428,8 @@ const KeywordValidation = {
|
|
|
362
428
|
return errors;
|
|
363
429
|
},
|
|
364
430
|
// @todo move to separate file: this is custom keyword validation for JsonEditor.properties keyword
|
|
365
|
-
propertiesRequired: (core, schema, value, pointer) => {
|
|
366
|
-
const errors = [];
|
|
431
|
+
propertiesRequired: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
432
|
+
const errors: JSONError[] = [];
|
|
367
433
|
const keys = Object.keys(schema.properties || {});
|
|
368
434
|
for (let i = 0; i < keys.length; i += 1) {
|
|
369
435
|
const key = keys[i];
|
|
@@ -377,46 +443,51 @@ const KeywordValidation = {
|
|
|
377
443
|
}
|
|
378
444
|
return errors;
|
|
379
445
|
},
|
|
380
|
-
required: (core, schema, value, pointer) => {
|
|
446
|
+
required: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
381
447
|
if (Array.isArray(schema.required) === false) {
|
|
382
448
|
return undefined;
|
|
383
449
|
}
|
|
384
450
|
|
|
385
|
-
return schema.required.map(property => {
|
|
386
|
-
if (value
|
|
451
|
+
return schema.required.map((property: string) => {
|
|
452
|
+
if (!hasProperty(value, property)) {
|
|
387
453
|
return core.errors.requiredPropertyError({ key: property, pointer });
|
|
388
454
|
}
|
|
389
455
|
return undefined;
|
|
390
456
|
});
|
|
391
457
|
},
|
|
392
458
|
// @todo move to separate file: this is custom keyword validation for JsonEditor.required keyword
|
|
393
|
-
requiredNotEmpty: (core, schema, value, pointer) => {
|
|
459
|
+
requiredNotEmpty: (core, schema, value: Record<string, unknown>, pointer) => {
|
|
394
460
|
if (Array.isArray(schema.required) === false) {
|
|
395
461
|
return undefined;
|
|
396
462
|
}
|
|
397
463
|
|
|
398
|
-
return schema.required.map(property => {
|
|
464
|
+
return schema.required.map((property: string) => {
|
|
399
465
|
if (value[property] == null || value[property] === "") {
|
|
400
|
-
return core.errors.valueNotEmptyError({
|
|
466
|
+
return core.errors.valueNotEmptyError({
|
|
467
|
+
property,
|
|
468
|
+
pointer: `${pointer}/${property}`
|
|
469
|
+
});
|
|
401
470
|
}
|
|
402
471
|
return undefined;
|
|
403
472
|
});
|
|
404
473
|
},
|
|
405
|
-
uniqueItems: (core, schema, value, pointer) => {
|
|
474
|
+
uniqueItems: (core, schema, value: unknown[], pointer) => {
|
|
406
475
|
if ((Array.isArray(value) && schema.uniqueItems) === false) {
|
|
407
476
|
return undefined;
|
|
408
477
|
}
|
|
409
478
|
|
|
410
|
-
const errors = [];
|
|
479
|
+
const errors: JSONError[] = [];
|
|
411
480
|
value.forEach((item, index) => {
|
|
412
481
|
for (let i = index + 1; i < value.length; i += 1) {
|
|
413
482
|
if (isSame(item, value[i])) {
|
|
414
|
-
errors.push(
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
483
|
+
errors.push(
|
|
484
|
+
core.errors.uniqueItemsError({
|
|
485
|
+
pointer,
|
|
486
|
+
itemPointer: `${pointer}/${index}`,
|
|
487
|
+
duplicatePointer: `${pointer}/${i}`,
|
|
488
|
+
value: JSON.stringify(item)
|
|
489
|
+
})
|
|
490
|
+
);
|
|
420
491
|
}
|
|
421
492
|
}
|
|
422
493
|
});
|
|
@@ -425,6 +496,4 @@ const KeywordValidation = {
|
|
|
425
496
|
}
|
|
426
497
|
};
|
|
427
498
|
|
|
428
|
-
|
|
429
499
|
export default KeywordValidation;
|
|
430
|
-
|
package/lib/validation/type.ts
CHANGED
|
@@ -1,3 +1,5 @@
|
|
|
1
|
+
import { JSONTypeValidator } from "../types";
|
|
2
|
+
|
|
1
3
|
/**
|
|
2
4
|
* @todo: type is also a keyword, as is properties, items, etc
|
|
3
5
|
*
|
|
@@ -5,7 +7,7 @@
|
|
|
5
7
|
* or seven in case of ajv https://github.com/epoberezkin/ajv/blob/master/KEYWORDS.md#type
|
|
6
8
|
* 1 null, 2 boolean, 3 object, 4 array, 5 number, 6 string (7 integer)
|
|
7
9
|
*/
|
|
8
|
-
|
|
10
|
+
const typeValidators: Record<string, JSONTypeValidator> = {
|
|
9
11
|
|
|
10
12
|
array: (core, schema, value, pointer) =>
|
|
11
13
|
core.typeKeywords.array
|
|
@@ -42,3 +44,5 @@ export default {
|
|
|
42
44
|
.filter(key => schema && schema[key] != null)
|
|
43
45
|
.map(key => core.validateKeyword[key](core, schema, value, pointer))
|
|
44
46
|
};
|
|
47
|
+
|
|
48
|
+
export default typeValidators;
|