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.
Files changed (161) hide show
  1. package/.editorconfig +1 -0
  2. package/.prettierignore +1 -0
  3. package/.prettierrc +7 -0
  4. package/CHANGELOG.md +106 -0
  5. package/README.md +811 -199
  6. package/TASKS.md +3 -81
  7. package/dist/index.d.ts +29 -71
  8. package/dist/jsonSchemaLibrary.js +1 -1
  9. package/dist/lib/SchemaService.d.ts +6 -8
  10. package/dist/lib/{addSchema.d.ts → addRemoteSchema.d.ts} +2 -1
  11. package/dist/lib/addValidator.d.ts +3 -2
  12. package/dist/lib/compile/getRef.d.ts +2 -1
  13. package/dist/lib/compile/index.d.ts +15 -1
  14. package/dist/lib/compile/types.d.ts +5 -0
  15. package/dist/lib/config/strings.d.ts +1 -39
  16. package/dist/lib/draft/index.d.ts +132 -0
  17. package/dist/lib/draft04/index.d.ts +7 -0
  18. package/dist/lib/draft06/compile/index.d.ts +16 -0
  19. package/dist/lib/draft06/index.d.ts +7 -0
  20. package/dist/lib/draft06/validation/keyword.d.ts +3 -0
  21. package/dist/lib/draft06/validation/type.d.ts +10 -0
  22. package/dist/lib/draft06/validation/typeKeywordMapping.d.ts +13 -0
  23. package/dist/lib/draft07/index.d.ts +7 -0
  24. package/dist/lib/each.d.ts +3 -2
  25. package/dist/lib/eachSchema.d.ts +2 -4
  26. package/dist/lib/getChildSchemaSelection.d.ts +7 -5
  27. package/dist/lib/getSchema.d.ts +2 -2
  28. package/dist/lib/getTemplate.d.ts +1 -1
  29. package/dist/lib/getTypeOf.d.ts +2 -1
  30. package/dist/lib/isValid.d.ts +1 -1
  31. package/dist/lib/jsoneditor/index.d.ts +7 -0
  32. package/dist/lib/resolveAllOf.d.ts +1 -1
  33. package/dist/lib/resolveAnyOf.d.ts +1 -1
  34. package/dist/lib/resolveOneOf.fuzzy.d.ts +1 -1
  35. package/dist/lib/resolveOneOf.strict.d.ts +2 -2
  36. package/dist/lib/{resolveRef.withOverwrite.d.ts → resolveRef.merge.d.ts} +0 -0
  37. package/dist/lib/schema/getTypeDefs.d.ts +6 -4
  38. package/dist/lib/schema/getTypeId.d.ts +1 -1
  39. package/dist/lib/schema/types.d.ts +7 -57
  40. package/dist/lib/step.d.ts +5 -5
  41. package/dist/lib/types.d.ts +11 -3
  42. package/dist/lib/utils/createCustomError.d.ts +8 -11
  43. package/dist/lib/utils/filter.d.ts +4 -4
  44. package/dist/lib/utils/flattenArray.d.ts +1 -1
  45. package/dist/lib/utils/merge.d.ts +3 -0
  46. package/dist/lib/utils/punycode.ucs2decode.d.ts +1 -1
  47. package/dist/lib/validate.d.ts +2 -2
  48. package/dist/lib/validateAsync.d.ts +1 -1
  49. package/dist/lib/validation/errors.d.ts +1 -3
  50. package/dist/lib/validation/format.d.ts +4 -11
  51. package/dist/lib/validation/keyword.d.ts +2 -27
  52. package/dist/lib/validation/type.d.ts +3 -10
  53. package/dist/lib/validation/typeKeywordMapping.d.ts +4 -4
  54. package/dist/module/index.js +23 -32
  55. package/dist/module/lib/SchemaService.js +7 -4
  56. package/dist/module/lib/{addSchema.js → addRemoteSchema.js} +2 -4
  57. package/dist/module/lib/addValidator.js +3 -4
  58. package/dist/module/lib/compile/getRef.js +1 -1
  59. package/dist/module/lib/compile/index.js +43 -18
  60. package/dist/module/lib/compile/types.js +1 -0
  61. package/dist/module/lib/config/strings.js +15 -2
  62. package/dist/module/lib/createSchemaOf.js +1 -1
  63. package/dist/module/lib/draft/index.js +133 -0
  64. package/dist/module/lib/draft04/index.js +90 -0
  65. package/dist/module/lib/draft06/compile/index.js +77 -0
  66. package/dist/module/lib/draft06/index.js +96 -0
  67. package/dist/module/lib/draft06/validation/keyword.js +168 -0
  68. package/dist/module/lib/draft06/validation/type.js +31 -0
  69. package/dist/module/lib/draft06/validation/typeKeywordMapping.js +15 -0
  70. package/dist/module/lib/draft07/index.js +96 -0
  71. package/dist/module/lib/each.js +2 -2
  72. package/dist/module/lib/eachSchema.js +28 -19
  73. package/dist/module/lib/getChildSchemaSelection.js +7 -6
  74. package/dist/module/lib/getSchema.js +4 -2
  75. package/dist/module/lib/getTemplate.js +42 -15
  76. package/dist/module/lib/jsoneditor/index.js +16 -0
  77. package/dist/module/lib/resolveAllOf.js +3 -4
  78. package/dist/module/lib/resolveOneOf.fuzzy.js +13 -3
  79. package/dist/module/lib/resolveOneOf.strict.js +49 -2
  80. package/dist/module/lib/{resolveRef.withOverwrite.js → resolveRef.merge.js} +0 -0
  81. package/dist/module/lib/resolveRef.strict.js +8 -0
  82. package/dist/module/lib/schema/getTypeDefs.js +14 -3
  83. package/dist/module/lib/schema/getTypeId.js +10 -6
  84. package/dist/module/lib/schema/types.js +33 -9
  85. package/dist/module/lib/step.js +67 -13
  86. package/dist/module/lib/types.js +7 -1
  87. package/dist/module/lib/utils/createCustomError.js +4 -4
  88. package/dist/module/lib/utils/filter.js +3 -5
  89. package/dist/module/lib/utils/flattenArray.js +4 -3
  90. package/dist/module/lib/utils/merge.js +4 -0
  91. package/dist/module/lib/utils/punycode.ucs2decode.js +4 -3
  92. package/dist/module/lib/validate.js +34 -8
  93. package/dist/module/lib/validateAsync.js +7 -7
  94. package/dist/module/lib/validation/errors.js +16 -3
  95. package/dist/module/lib/validation/format.js +115 -8
  96. package/dist/module/lib/validation/keyword.js +79 -32
  97. package/dist/module/lib/validation/type.js +2 -1
  98. package/index.ts +46 -32
  99. package/lib/SchemaService.ts +18 -11
  100. package/lib/{addSchema.ts → addRemoteSchema.ts} +3 -5
  101. package/lib/addValidator.ts +15 -12
  102. package/lib/compile/getRef.ts +3 -4
  103. package/lib/compile/index.ts +65 -19
  104. package/lib/compile/types.ts +6 -0
  105. package/lib/config/strings.ts +17 -3
  106. package/lib/createSchemaOf.ts +1 -3
  107. package/lib/draft/index.ts +201 -0
  108. package/lib/draft04/index.ts +95 -0
  109. package/lib/draft06/compile/index.ts +104 -0
  110. package/lib/draft06/index.ts +101 -0
  111. package/lib/draft06/validation/keyword.ts +199 -0
  112. package/lib/draft06/validation/type.ts +47 -0
  113. package/lib/draft06/validation/typeKeywordMapping.ts +15 -0
  114. package/lib/draft07/index.ts +101 -0
  115. package/lib/each.ts +11 -4
  116. package/lib/eachSchema.ts +45 -32
  117. package/lib/getChildSchemaSelection.ts +14 -7
  118. package/lib/getSchema.ts +18 -9
  119. package/lib/getTemplate.ts +155 -42
  120. package/lib/getTypeOf.ts +2 -1
  121. package/lib/isValid.ts +7 -3
  122. package/lib/jsoneditor/index.ts +20 -0
  123. package/lib/resolveAllOf.ts +10 -6
  124. package/lib/resolveAnyOf.ts +7 -3
  125. package/lib/resolveOneOf.fuzzy.ts +26 -9
  126. package/lib/resolveOneOf.strict.ts +63 -5
  127. package/lib/{resolveRef.withOverwrite.ts → resolveRef.merge.ts} +0 -0
  128. package/lib/resolveRef.strict.ts +9 -0
  129. package/lib/schema/getTypeDefs.ts +19 -7
  130. package/lib/schema/getTypeId.ts +11 -8
  131. package/lib/schema/types.ts +41 -9
  132. package/lib/step.ts +109 -25
  133. package/lib/types.ts +23 -5
  134. package/lib/utils/createCustomError.ts +8 -13
  135. package/lib/utils/filter.ts +7 -9
  136. package/lib/utils/flattenArray.ts +5 -4
  137. package/lib/utils/merge.ts +5 -0
  138. package/lib/utils/punycode.ucs2decode.ts +6 -5
  139. package/lib/validate.ts +47 -16
  140. package/lib/validateAsync.ts +15 -14
  141. package/lib/validation/errors.ts +17 -6
  142. package/lib/validation/format.ts +147 -13
  143. package/lib/validation/keyword.ts +172 -103
  144. package/lib/validation/type.ts +5 -1
  145. package/package.json +75 -63
  146. package/{dist/module/remotes/draft04.json → remotes/draft06.json} +47 -42
  147. package/remotes/draft07.json +172 -0
  148. package/remotes/draft2019-09.json +86 -0
  149. package/tsconfig.json +3 -10
  150. package/dist/lib/cores/CoreInterface.d.ts +0 -23
  151. package/dist/lib/cores/Draft04.d.ts +0 -13
  152. package/dist/lib/cores/JsonEditor.d.ts +0 -13
  153. package/dist/module/lib/cores/CoreInterface.js +0 -51
  154. package/dist/module/lib/cores/Draft04.js +0 -52
  155. package/dist/module/lib/cores/JsonEditor.js +0 -51
  156. package/dist/module/remotes/index.js +0 -10
  157. package/dist/remotes/index.d.ts +0 -5
  158. package/lib/cores/CoreInterface.ts +0 -76
  159. package/lib/cores/Draft04.ts +0 -66
  160. package/lib/cores/JsonEditor.ts +0 -64
  161. 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 (getTypeOf(schema.patternProperties) === "object" && schema.additionalProperties === false) {
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(prop => settings.propertyBlacklist.includes(prop) === false);
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(pattern => new RegExp(pattern));
29
- receivedProperties = receivedProperties.filter(prop => {
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], schema.additionalProperties, `${pointer}/${property}`
58
+ value[property],
59
+ schema.additionalProperties,
60
+ `${pointer}/${property}`
49
61
  );
50
- if (result.type === "error") {
51
- errors.push(core.errors.additionalPropertiesError({
52
- schema: schema.additionalProperties,
53
- property: receivedProperties[i],
54
- properties: expectedProperties,
55
- pointer,
56
- // pass all validation errors
57
- errors: result.data.errors
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
- // additionalProperties {}
77
+ // additionalProperties {}
65
78
  } else if (isObject) {
66
- if (core.validate(value[property], schema.additionalProperties, pointer).length !== 0) {
67
- errors.push(core.errors.additionalPropertiesError({
68
- schema: schema.additionalProperties,
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
- .forEach(property => {
121
- if (schema.dependencies[property] === undefined) {
122
- return;
123
- }
139
+ const errors: JSONError[] = [];
140
+ Object.keys(value).forEach((property) => {
141
+ if (schema.dependencies[property] === undefined) {
142
+ return;
143
+ }
124
144
 
125
- let dependencyErrors;
126
- const type = getTypeOf(schema.dependencies[property]);
127
- if (type === "array") {
128
- dependencyErrors = schema.dependencies[property]
129
- .filter(dependency => value[dependency] === undefined)
130
- .map(missingProperty => core.errors.missingDependencyError({ missingProperty, pointer }));
131
- } else if (type === "object") {
132
- dependencyErrors = core.validate(value, schema.dependencies[property]);
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
- } else {
135
- throw new Error(`Invalid dependency definition for ${pointer}/${property}. Must be list or schema`);
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
- errors.push(...dependencyErrors);
139
- });
170
+ errors.push(...dependencyErrors);
171
+ });
140
172
 
141
173
  return errors.length > 0 ? errors : undefined;
142
174
  },
143
175
 
144
- "enum": (core, schema, value, pointer) => {
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
- const errors = [];
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({ maximum: schema.maxItems, length: value.length, pointer });
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({ maxLength: schema.maxLength, length: lengthOfString, pointer });
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({ minLength: schema.minLength, length: lengthOfString, pointer });
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({ minItems: schema.minItems, length: value.length, pointer });
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, pointer
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 && schema.type === "error") {
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, pointer
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(value[key], patterns[i].patternSchema, `${pointer}/${key}`);
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(core.errors.patternPropertiesError({
344
- key, pointer, patterns: Object.keys(pp).join(",")
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[key] !== undefined) {
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[property] === undefined) {
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({ property, pointer: `${pointer}/${property}` });
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(core.errors.uniqueItemsError({
415
- pointer,
416
- itemPointer: `${pointer}/${index}`,
417
- duplicatePointer: `${pointer}/${i}`,
418
- value: JSON.stringify(item)
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
-
@@ -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
- export default {
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;