z-schema 12.0.4 → 12.1.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 (176) hide show
  1. package/bin/z-schema +7 -2
  2. package/cjs/index.d.ts +541 -530
  3. package/cjs/index.js +3963 -7740
  4. package/dist/errors.d.mts +64 -0
  5. package/dist/errors.mjs +67 -0
  6. package/dist/format-validators.d.mts +14 -0
  7. package/dist/format-validators.mjs +261 -0
  8. package/dist/index.d.mts +10 -0
  9. package/dist/index.mjs +7 -0
  10. package/dist/json-schema-versions.d.mts +137 -0
  11. package/dist/json-schema-versions.mjs +11 -0
  12. package/dist/json-schema.d.mts +61 -0
  13. package/dist/json-schema.mjs +53 -0
  14. package/dist/json-validation.mjs +441 -0
  15. package/dist/report.d.mts +97 -0
  16. package/dist/report.mjs +194 -0
  17. package/dist/schema-cache.d.mts +23 -0
  18. package/dist/schema-cache.mjs +144 -0
  19. package/dist/schema-compiler.d.mts +23 -0
  20. package/dist/schema-compiler.mjs +265 -0
  21. package/dist/schema-validator.d.mts +15 -0
  22. package/dist/schema-validator.mjs +446 -0
  23. package/dist/schemas/draft-04-schema.mjs +125 -0
  24. package/dist/schemas/draft-06-schema.mjs +126 -0
  25. package/dist/schemas/draft-07-schema.mjs +141 -0
  26. package/dist/schemas/draft-2019-09-meta-applicator.mjs +46 -0
  27. package/dist/schemas/draft-2019-09-meta-content.mjs +15 -0
  28. package/dist/schemas/draft-2019-09-meta-core.mjs +52 -0
  29. package/dist/schemas/draft-2019-09-meta-format.mjs +11 -0
  30. package/dist/schemas/draft-2019-09-meta-meta-data.mjs +31 -0
  31. package/dist/schemas/draft-2019-09-meta-validation.mjs +80 -0
  32. package/dist/schemas/draft-2019-09-schema.mjs +39 -0
  33. package/dist/schemas/draft-2020-12-meta-applicator.mjs +45 -0
  34. package/dist/schemas/draft-2020-12-meta-content.mjs +15 -0
  35. package/dist/schemas/draft-2020-12-meta-core.mjs +46 -0
  36. package/dist/schemas/draft-2020-12-meta-format-annotation.mjs +11 -0
  37. package/dist/schemas/draft-2020-12-meta-format-assertion.mjs +11 -0
  38. package/dist/schemas/draft-2020-12-meta-meta-data.mjs +31 -0
  39. package/dist/schemas/draft-2020-12-meta-unevaluated.mjs +14 -0
  40. package/dist/schemas/draft-2020-12-meta-validation.mjs +80 -0
  41. package/dist/schemas/draft-2020-12-schema.mjs +55 -0
  42. package/dist/utils/array.mjs +54 -0
  43. package/dist/utils/base64.mjs +21 -0
  44. package/dist/utils/clone.mjs +42 -0
  45. package/dist/utils/constants.mjs +16 -0
  46. package/dist/utils/date.mjs +19 -0
  47. package/dist/utils/hostname.mjs +73 -0
  48. package/dist/utils/json.mjs +34 -0
  49. package/dist/utils/properties.mjs +11 -0
  50. package/dist/utils/schema-regex.mjs +49 -0
  51. package/dist/utils/symbols.mjs +5 -0
  52. package/dist/utils/time.mjs +42 -0
  53. package/dist/utils/unicode.mjs +12 -0
  54. package/dist/utils/uri.mjs +12 -0
  55. package/dist/utils/what-is.mjs +23 -0
  56. package/dist/validation/array.mjs +57 -0
  57. package/dist/validation/combinators.mjs +62 -0
  58. package/dist/validation/numeric.mjs +38 -0
  59. package/dist/validation/object.mjs +109 -0
  60. package/dist/validation/ref.mjs +49 -0
  61. package/dist/validation/shared.mjs +97 -0
  62. package/dist/validation/string.mjs +88 -0
  63. package/dist/validation/type.mjs +32 -0
  64. package/dist/z-schema-base.d.mts +85 -0
  65. package/dist/z-schema-base.mjs +230 -0
  66. package/dist/z-schema-options.d.mts +35 -0
  67. package/dist/z-schema-options.mjs +55 -0
  68. package/dist/z-schema-reader.d.mts +6 -0
  69. package/dist/z-schema-reader.mjs +10 -0
  70. package/dist/z-schema-versions.mjs +67 -0
  71. package/dist/z-schema.d.mts +193 -0
  72. package/dist/z-schema.mjs +300 -0
  73. package/package.json +49 -64
  74. package/src/index.ts +3 -3
  75. package/src/schema-compiler.ts +30 -10
  76. package/src/schema-validator.ts +1 -1
  77. package/src/utils/schema-regex.ts +13 -2
  78. package/src/z-schema-base.ts +1 -1
  79. package/src/z-schema-versions.ts +1 -2
  80. package/src/z-schema.ts +0 -1
  81. package/umd/ZSchema.js +5934 -8110
  82. package/umd/ZSchema.min.js +2 -1
  83. package/dist/errors.js +0 -72
  84. package/dist/format-validators.js +0 -392
  85. package/dist/index.js +0 -5
  86. package/dist/json-schema-versions.js +0 -8
  87. package/dist/json-schema.js +0 -84
  88. package/dist/json-validation.js +0 -728
  89. package/dist/package.json +0 -3
  90. package/dist/report.js +0 -265
  91. package/dist/schema-cache.js +0 -211
  92. package/dist/schema-compiler.js +0 -415
  93. package/dist/schema-validator.js +0 -721
  94. package/dist/schemas/draft-04-schema.json +0 -149
  95. package/dist/schemas/draft-06-schema.json +0 -155
  96. package/dist/schemas/draft-07-schema.json +0 -172
  97. package/dist/schemas/draft-2019-09-meta-applicator.json +0 -52
  98. package/dist/schemas/draft-2019-09-meta-content.json +0 -12
  99. package/dist/schemas/draft-2019-09-meta-core.json +0 -53
  100. package/dist/schemas/draft-2019-09-meta-format.json +0 -10
  101. package/dist/schemas/draft-2019-09-meta-meta-data.json +0 -32
  102. package/dist/schemas/draft-2019-09-meta-validation.json +0 -94
  103. package/dist/schemas/draft-2019-09-schema.json +0 -41
  104. package/dist/schemas/draft-2020-12-meta-applicator.json +0 -44
  105. package/dist/schemas/draft-2020-12-meta-content.json +0 -12
  106. package/dist/schemas/draft-2020-12-meta-core.json +0 -47
  107. package/dist/schemas/draft-2020-12-meta-format-annotation.json +0 -10
  108. package/dist/schemas/draft-2020-12-meta-format-assertion.json +0 -10
  109. package/dist/schemas/draft-2020-12-meta-meta-data.json +0 -32
  110. package/dist/schemas/draft-2020-12-meta-unevaluated.json +0 -11
  111. package/dist/schemas/draft-2020-12-meta-validation.json +0 -94
  112. package/dist/schemas/draft-2020-12-schema.json +0 -57
  113. package/dist/types/errors.d.ts +0 -64
  114. package/dist/types/format-validators.d.ts +0 -11
  115. package/dist/types/index.d.ts +0 -14
  116. package/dist/types/json-schema-versions.d.ts +0 -142
  117. package/dist/types/json-schema.d.ts +0 -66
  118. package/dist/types/json-validation.d.ts +0 -6
  119. package/dist/types/report.d.ts +0 -94
  120. package/dist/types/schema-cache.d.ts +0 -27
  121. package/dist/types/schema-compiler.d.ts +0 -31
  122. package/dist/types/schema-validator.d.ts +0 -10
  123. package/dist/types/utils/array.d.ts +0 -9
  124. package/dist/types/utils/base64.d.ts +0 -2
  125. package/dist/types/utils/clone.d.ts +0 -2
  126. package/dist/types/utils/constants.d.ts +0 -19
  127. package/dist/types/utils/date.d.ts +0 -1
  128. package/dist/types/utils/hostname.d.ts +0 -2
  129. package/dist/types/utils/json.d.ts +0 -9
  130. package/dist/types/utils/properties.d.ts +0 -1
  131. package/dist/types/utils/schema-regex.d.ts +0 -10
  132. package/dist/types/utils/symbols.d.ts +0 -2
  133. package/dist/types/utils/time.d.ts +0 -12
  134. package/dist/types/utils/unicode.d.ts +0 -5
  135. package/dist/types/utils/uri.d.ts +0 -4
  136. package/dist/types/utils/what-is.d.ts +0 -4
  137. package/dist/types/validation/array.d.ts +0 -12
  138. package/dist/types/validation/combinators.d.ts +0 -10
  139. package/dist/types/validation/numeric.d.ts +0 -8
  140. package/dist/types/validation/object.d.ts +0 -13
  141. package/dist/types/validation/ref.d.ts +0 -11
  142. package/dist/types/validation/shared.d.ts +0 -26
  143. package/dist/types/validation/string.d.ts +0 -9
  144. package/dist/types/validation/type.d.ts +0 -6
  145. package/dist/types/z-schema-base.d.ts +0 -87
  146. package/dist/types/z-schema-options.d.ts +0 -35
  147. package/dist/types/z-schema-reader.d.ts +0 -4
  148. package/dist/types/z-schema-versions.d.ts +0 -1
  149. package/dist/types/z-schema.d.ts +0 -191
  150. package/dist/utils/array.js +0 -69
  151. package/dist/utils/base64.js +0 -29
  152. package/dist/utils/clone.js +0 -59
  153. package/dist/utils/constants.js +0 -19
  154. package/dist/utils/date.js +0 -21
  155. package/dist/utils/hostname.js +0 -146
  156. package/dist/utils/json.js +0 -70
  157. package/dist/utils/properties.js +0 -10
  158. package/dist/utils/schema-regex.js +0 -52
  159. package/dist/utils/symbols.js +0 -2
  160. package/dist/utils/time.js +0 -50
  161. package/dist/utils/unicode.js +0 -12
  162. package/dist/utils/uri.js +0 -15
  163. package/dist/utils/what-is.js +0 -32
  164. package/dist/validation/array.js +0 -127
  165. package/dist/validation/combinators.js +0 -106
  166. package/dist/validation/numeric.js +0 -97
  167. package/dist/validation/object.js +0 -237
  168. package/dist/validation/ref.js +0 -70
  169. package/dist/validation/shared.js +0 -136
  170. package/dist/validation/string.js +0 -170
  171. package/dist/validation/type.js +0 -55
  172. package/dist/z-schema-base.js +0 -286
  173. package/dist/z-schema-options.js +0 -99
  174. package/dist/z-schema-reader.js +0 -7
  175. package/dist/z-schema-versions.js +0 -110
  176. package/dist/z-schema.js +0 -287
@@ -1,721 +0,0 @@
1
- import { isFormatSupported } from './format-validators.js';
2
- import { getId } from './json-schema.js';
3
- import { validate } from './json-validation.js';
4
- import { Report } from './report.js';
5
- import { isUniqueArray } from './utils/array.js';
6
- import { shallowClone } from './utils/clone.js';
7
- import { compileSchemaRegex } from './utils/schema-regex.js';
8
- import { isInteger, isObject } from './utils/what-is.js';
9
- const SchemaValidators = {
10
- $ref: function (report, schema) {
11
- // http://tools.ietf.org/html/draft-ietf-appsawg-json-pointer-07
12
- // http://tools.ietf.org/html/draft-pbryan-zyp-json-ref-03
13
- if (typeof schema.$ref !== 'string') {
14
- report.addError('KEYWORD_TYPE_EXPECTED', ['$ref', 'string'], undefined, schema, '$ref');
15
- }
16
- },
17
- $schema: function (report, schema) {
18
- // http://json-schema.org/latest/json-schema-core.html#rfc.section.6
19
- if (typeof schema.$schema !== 'string') {
20
- report.addError('KEYWORD_TYPE_EXPECTED', ['$schema', 'string'], undefined, schema, '$schema');
21
- }
22
- },
23
- multipleOf: function (report, schema) {
24
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.1.1
25
- if (typeof schema.multipleOf !== 'number') {
26
- report.addError('KEYWORD_TYPE_EXPECTED', ['multipleOf', 'number'], undefined, schema, 'multipleOf');
27
- }
28
- else if (schema.multipleOf <= 0) {
29
- report.addError('KEYWORD_MUST_BE', ['multipleOf', 'strictly greater than 0'], undefined, schema, 'multipleOf');
30
- }
31
- },
32
- maximum: function (report, schema) {
33
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
34
- if (typeof schema.maximum !== 'number') {
35
- report.addError('KEYWORD_TYPE_EXPECTED', ['maximum', 'number'], undefined, schema, 'maximum');
36
- }
37
- },
38
- exclusiveMaximum: function (report, schema) {
39
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.2.1
40
- if (report.options.version === 'draft-04') {
41
- if (typeof schema.exclusiveMaximum !== 'boolean') {
42
- report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMaximum', 'boolean'], undefined, schema, 'exclusiveMaximum');
43
- }
44
- else if (schema.maximum === undefined) {
45
- report.addError('KEYWORD_DEPENDENCY', ['exclusiveMaximum', 'maximum'], undefined, schema, 'exclusiveMaximum');
46
- }
47
- }
48
- else {
49
- if (typeof schema.exclusiveMaximum !== 'boolean' && typeof schema.exclusiveMaximum !== 'number') {
50
- report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMaximum', ['boolean', 'number']], undefined, schema, 'exclusiveMaximum');
51
- }
52
- }
53
- },
54
- minimum: function (report, schema) {
55
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
56
- if (typeof schema.minimum !== 'number') {
57
- report.addError('KEYWORD_TYPE_EXPECTED', ['minimum', 'number'], undefined, schema, 'minimum');
58
- }
59
- },
60
- exclusiveMinimum: function (report, schema) {
61
- if (report.options.version === 'draft-04') {
62
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.1.3.1
63
- if (typeof schema.exclusiveMinimum !== 'boolean') {
64
- report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMinimum', 'boolean'], undefined, schema, 'exclusiveMinimum');
65
- }
66
- else if (schema.minimum === undefined) {
67
- report.addError('KEYWORD_DEPENDENCY', ['exclusiveMinimum', 'minimum'], undefined, schema, 'exclusiveMinimum');
68
- }
69
- }
70
- else {
71
- if (typeof schema.exclusiveMinimum !== 'boolean' && typeof schema.exclusiveMinimum !== 'number') {
72
- report.addError('KEYWORD_TYPE_EXPECTED', ['exclusiveMinimum', ['boolean', 'number']], undefined, schema, 'exclusiveMinimum');
73
- }
74
- }
75
- },
76
- maxLength: function (report, schema) {
77
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.1.1
78
- if (!isInteger(schema.maxLength)) {
79
- report.addError('KEYWORD_TYPE_EXPECTED', ['maxLength', 'integer'], undefined, schema, 'maxLength');
80
- }
81
- else if (schema.maxLength < 0) {
82
- report.addError('KEYWORD_MUST_BE', ['maxLength', 'greater than, or equal to 0'], undefined, schema, 'maxLength');
83
- }
84
- },
85
- minLength: function (report, schema) {
86
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.2.1
87
- if (!isInteger(schema.minLength)) {
88
- report.addError('KEYWORD_TYPE_EXPECTED', ['minLength', 'integer'], undefined, schema, 'minLength');
89
- }
90
- else if (schema.minLength < 0) {
91
- report.addError('KEYWORD_MUST_BE', ['minLength', 'greater than, or equal to 0'], undefined, schema, 'minLength');
92
- }
93
- },
94
- pattern: function (report, schema) {
95
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.2.3.1
96
- if (typeof schema.pattern !== 'string') {
97
- report.addError('KEYWORD_TYPE_EXPECTED', ['pattern', 'string'], undefined, schema, 'pattern');
98
- }
99
- else {
100
- // Use shared regex compilation helper
101
- // Import at top of file
102
- const result = compileSchemaRegex(schema.pattern);
103
- if (!result.ok) {
104
- report.addError('KEYWORD_PATTERN', ['pattern', schema.pattern, result.error.message], undefined, schema, 'pattern');
105
- }
106
- }
107
- },
108
- additionalItems: function (report, schema) {
109
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
110
- if (typeof schema.additionalItems !== 'boolean' && !isObject(schema.additionalItems)) {
111
- report.addError('KEYWORD_TYPE_EXPECTED', ['additionalItems', ['boolean', 'object']], undefined, schema, 'additionalItems');
112
- }
113
- else if (isObject(schema.additionalItems)) {
114
- report.path.push('additionalItems');
115
- this.validateSchema(report, schema.additionalItems);
116
- report.path.pop();
117
- }
118
- },
119
- items: function (report, schema) {
120
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.1.1
121
- if (Array.isArray(schema.items)) {
122
- for (let idx = 0; idx < schema.items.length; idx++) {
123
- report.path.push('items');
124
- report.path.push(idx);
125
- this.validateSchema(report, schema.items[idx]);
126
- report.path.pop();
127
- report.path.pop();
128
- }
129
- }
130
- else if (isObject(schema.items) || (report.options.version !== 'draft-04' && typeof schema.items === 'boolean')) {
131
- report.path.push('items');
132
- this.validateSchema(report, schema.items);
133
- report.path.pop();
134
- }
135
- else {
136
- report.addError('KEYWORD_TYPE_EXPECTED', ['items', report.options.version === 'draft-04' ? ['array', 'object'] : ['array', 'object', 'boolean']], undefined, schema, 'items');
137
- }
138
- // custom - strict mode
139
- if (this.options.forceAdditional === true && schema.additionalItems === undefined && Array.isArray(schema.items)) {
140
- report.addError('KEYWORD_UNDEFINED_STRICT', ['additionalItems'], undefined, schema, 'additionalItems');
141
- }
142
- // custom - assume defined false mode
143
- if (this.options.assumeAdditional && schema.additionalItems === undefined && Array.isArray(schema.items)) {
144
- schema.additionalItems = false;
145
- }
146
- },
147
- maxItems: function (report, schema) {
148
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.2.1
149
- if (typeof schema.maxItems !== 'number') {
150
- report.addError('KEYWORD_TYPE_EXPECTED', ['maxItems', 'integer'], undefined, schema, 'maxItems');
151
- }
152
- else if (schema.maxItems < 0) {
153
- report.addError('KEYWORD_MUST_BE', ['maxItems', 'greater than, or equal to 0'], undefined, schema, 'maxItems');
154
- }
155
- },
156
- minItems: function (report, schema) {
157
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.3.1
158
- if (!isInteger(schema.minItems)) {
159
- report.addError('KEYWORD_TYPE_EXPECTED', ['minItems', 'integer'], undefined, schema, 'minItems');
160
- }
161
- else if (schema.minItems < 0) {
162
- report.addError('KEYWORD_MUST_BE', ['minItems', 'greater than, or equal to 0'], undefined, schema, 'minItems');
163
- }
164
- },
165
- uniqueItems: function (report, schema) {
166
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.3.4.1
167
- if (typeof schema.uniqueItems !== 'boolean') {
168
- report.addError('KEYWORD_TYPE_EXPECTED', ['uniqueItems', 'boolean'], undefined, schema, 'uniqueItems');
169
- }
170
- },
171
- maxProperties: function (report, schema) {
172
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.1.1
173
- if (!isInteger(schema.maxProperties)) {
174
- report.addError('KEYWORD_TYPE_EXPECTED', ['maxProperties', 'integer'], undefined, schema, 'maxProperties');
175
- }
176
- else if (schema.maxProperties < 0) {
177
- report.addError('KEYWORD_MUST_BE', ['maxProperties', 'greater than, or equal to 0'], undefined, schema, 'maxProperties');
178
- }
179
- },
180
- minProperties: function (report, schema) {
181
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.2.1
182
- if (!isInteger(schema.minProperties)) {
183
- report.addError('KEYWORD_TYPE_EXPECTED', ['minProperties', 'integer'], undefined, schema, 'minProperties');
184
- }
185
- else if (schema.minProperties < 0) {
186
- report.addError('KEYWORD_MUST_BE', ['minProperties', 'greater than, or equal to 0'], undefined, schema, 'minProperties');
187
- }
188
- },
189
- required: function (report, schema) {
190
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.3.1
191
- if (!Array.isArray(schema.required)) {
192
- report.addError('KEYWORD_TYPE_EXPECTED', ['required', 'array'], undefined, schema, 'required');
193
- }
194
- else if (report.options.version === 'draft-04' && schema.required.length === 0) {
195
- report.addError('KEYWORD_MUST_BE', ['required', 'an array with at least one element'], undefined, schema, 'required');
196
- }
197
- else {
198
- for (const item of schema.required) {
199
- if (typeof item !== 'string') {
200
- report.addError('KEYWORD_VALUE_TYPE', ['required', 'string'], undefined, schema, 'required');
201
- }
202
- }
203
- if (isUniqueArray(schema.required) === false) {
204
- report.addError('KEYWORD_MUST_BE', ['required', 'an array with unique items'], undefined, schema, 'required');
205
- }
206
- }
207
- },
208
- additionalProperties: function (report, schema) {
209
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
210
- if (typeof schema.additionalProperties !== 'boolean' && !isObject(schema.additionalProperties)) {
211
- report.addError('KEYWORD_TYPE_EXPECTED', ['additionalProperties', ['boolean', 'object']], undefined, schema, 'additionalProperties');
212
- }
213
- else if (isObject(schema.additionalProperties)) {
214
- report.path.push('additionalProperties');
215
- this.validateSchema(report, schema.additionalProperties);
216
- report.path.pop();
217
- }
218
- },
219
- properties: function (report, schema) {
220
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
221
- if (!isObject(schema.properties)) {
222
- report.addError('KEYWORD_TYPE_EXPECTED', ['properties', 'object'], undefined, schema, 'properties');
223
- return;
224
- }
225
- const keys = Object.keys(schema.properties);
226
- for (const key of keys) {
227
- const val = schema.properties[key];
228
- report.path.push('properties');
229
- report.path.push(key);
230
- this.validateSchema(report, val);
231
- report.path.pop();
232
- report.path.pop();
233
- }
234
- // custom - strict mode
235
- if (this.options.forceAdditional === true && schema.additionalProperties === undefined) {
236
- report.addError('KEYWORD_UNDEFINED_STRICT', ['additionalProperties'], undefined, schema, 'additionalProperties');
237
- }
238
- // custom - assume defined false mode
239
- if (this.options.assumeAdditional && schema.additionalProperties === undefined) {
240
- schema.additionalProperties = false;
241
- }
242
- // custom - forceProperties
243
- if (this.options.forceProperties === true && keys.length === 0) {
244
- report.addError('CUSTOM_MODE_FORCE_PROPERTIES', ['properties'], undefined, schema, 'properties');
245
- }
246
- },
247
- patternProperties: function (report, schema) {
248
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.4.1
249
- if (!isObject(schema.patternProperties)) {
250
- report.addError('KEYWORD_TYPE_EXPECTED', ['patternProperties', 'object'], undefined, schema, 'patternProperties');
251
- return;
252
- }
253
- // Use shared regex compilation helper
254
- const keys = Object.keys(schema.patternProperties);
255
- for (const key of keys) {
256
- const val = schema.patternProperties[key];
257
- const result = compileSchemaRegex(key);
258
- if (!result.ok) {
259
- report.addError('KEYWORD_PATTERN', ['patternProperties', key, result.error.message], undefined, schema, 'patternProperties');
260
- }
261
- report.path.push('patternProperties');
262
- report.path.push(key);
263
- this.validateSchema(report, val);
264
- report.path.pop();
265
- report.path.pop();
266
- }
267
- // custom - forceProperties
268
- if (this.options.forceProperties === true && keys.length === 0) {
269
- report.addError('CUSTOM_MODE_FORCE_PROPERTIES', ['patternProperties'], undefined, schema, 'patternProperties');
270
- }
271
- },
272
- dependencies: function (report, schema) {
273
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.4.5.1
274
- if (!isObject(schema.dependencies)) {
275
- report.addError('KEYWORD_TYPE_EXPECTED', ['dependencies', 'object'], undefined, schema, 'dependencies');
276
- }
277
- else {
278
- const keys = Object.keys(schema.dependencies);
279
- for (const schemaKey of keys) {
280
- const schemaDependency = schema.dependencies[schemaKey];
281
- const isSchemaDependency = isObject(schemaDependency) ||
282
- (report.options.version !== 'draft-04' && typeof schemaDependency === 'boolean');
283
- if (isSchemaDependency) {
284
- report.path.push('dependencies');
285
- report.path.push(schemaKey);
286
- this.validateSchema(report, schemaDependency);
287
- report.path.pop();
288
- report.path.pop();
289
- }
290
- else if (Array.isArray(schemaDependency)) {
291
- const depArray = schemaDependency;
292
- if (report.options.version === 'draft-04' && depArray.length === 0) {
293
- report.addError('KEYWORD_MUST_BE', ['dependencies', 'not empty array'], undefined, schema, 'dependencies');
294
- }
295
- for (const dep of depArray) {
296
- if (typeof dep !== 'string') {
297
- report.addError('KEYWORD_VALUE_TYPE', ['dependencies', 'string'], undefined, schema, 'dependencies');
298
- }
299
- }
300
- if (isUniqueArray(depArray) === false) {
301
- report.addError('KEYWORD_MUST_BE', ['dependencies', 'an array with unique items'], undefined, schema, 'dependencies');
302
- }
303
- }
304
- else {
305
- report.addError('KEYWORD_VALUE_TYPE', ['dependencies', report.options.version === 'draft-04' ? 'object or array' : 'boolean, object or array'], undefined, schema, 'dependencies');
306
- }
307
- }
308
- }
309
- },
310
- enum: function (report, schema) {
311
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.1.1
312
- if (Array.isArray(schema.enum) === false) {
313
- report.addError('KEYWORD_TYPE_EXPECTED', ['enum', 'array'], undefined, schema, 'enum');
314
- }
315
- else if (schema.enum.length === 0) {
316
- report.addError('KEYWORD_MUST_BE', ['enum', 'an array with at least one element'], undefined, schema, 'enum');
317
- }
318
- else if (isUniqueArray(schema.enum) === false) {
319
- report.addError('KEYWORD_MUST_BE', ['enum', 'an array with unique elements'], undefined, schema, 'enum');
320
- }
321
- },
322
- type: function (report, schema) {
323
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.2.1
324
- const primitiveTypes = ['array', 'boolean', 'integer', 'number', 'null', 'object', 'string'];
325
- const primitiveTypeStr = primitiveTypes.join(',');
326
- const isArray = Array.isArray(schema.type);
327
- if (Array.isArray(schema.type)) {
328
- for (const typeItem of schema.type) {
329
- if (!primitiveTypes.includes(typeItem)) {
330
- report.addError('KEYWORD_TYPE_EXPECTED', ['type', primitiveTypeStr], undefined, schema, 'type');
331
- }
332
- }
333
- if (isUniqueArray(schema.type) === false) {
334
- report.addError('KEYWORD_MUST_BE', ['type', 'an object with unique properties'], undefined, schema, 'type');
335
- }
336
- }
337
- else if (typeof schema.type === 'string') {
338
- if (!primitiveTypes.includes(schema.type)) {
339
- report.addError('KEYWORD_TYPE_EXPECTED', ['type', primitiveTypeStr], undefined, schema, 'type');
340
- }
341
- }
342
- else {
343
- report.addError('KEYWORD_TYPE_EXPECTED', ['type', ['string', 'array']], undefined, schema, 'type');
344
- }
345
- if (this.options.noEmptyStrings === true) {
346
- if (schema.type === 'string' || (isArray && schema.type.includes('string'))) {
347
- if (schema.minLength === undefined && schema.enum === undefined && schema.format === undefined) {
348
- schema.minLength = 1;
349
- }
350
- }
351
- }
352
- if (this.options.noEmptyArrays === true) {
353
- if (schema.type === 'array' || (isArray && schema.type.includes('array'))) {
354
- if (schema.minItems === undefined) {
355
- schema.minItems = 1;
356
- }
357
- }
358
- }
359
- if (this.options.forceProperties === true) {
360
- if (schema.type === 'object' || (isArray && schema.type.includes('object'))) {
361
- if (schema.properties === undefined && schema.patternProperties === undefined) {
362
- report.addError('KEYWORD_UNDEFINED_STRICT', ['properties'], undefined, schema, 'properties');
363
- }
364
- }
365
- }
366
- if (this.options.forceItems === true) {
367
- if (schema.type === 'array' || (isArray && schema.type.includes('array'))) {
368
- if (schema.items === undefined) {
369
- report.addError('KEYWORD_UNDEFINED_STRICT', ['items'], undefined, schema, 'items');
370
- }
371
- }
372
- }
373
- if (this.options.forceMinItems === true) {
374
- if (schema.type === 'array' || (isArray && schema.type.includes('array'))) {
375
- if (schema.minItems === undefined) {
376
- report.addError('KEYWORD_UNDEFINED_STRICT', ['minItems'], undefined, schema, 'minItems');
377
- }
378
- }
379
- }
380
- if (this.options.forceMaxItems === true) {
381
- if (schema.type === 'array' || (isArray && schema.type.includes('array'))) {
382
- if (schema.maxItems === undefined) {
383
- report.addError('KEYWORD_UNDEFINED_STRICT', ['maxItems'], undefined, schema, 'maxItems');
384
- }
385
- }
386
- }
387
- if (this.options.forceMinLength === true) {
388
- if (schema.type === 'string' || (isArray && schema.type.includes('string'))) {
389
- if (schema.minLength === undefined &&
390
- schema.format === undefined &&
391
- schema.enum === undefined &&
392
- schema.pattern === undefined) {
393
- report.addError('KEYWORD_UNDEFINED_STRICT', ['minLength'], undefined, schema, 'minLength');
394
- }
395
- }
396
- }
397
- if (this.options.forceMaxLength === true) {
398
- if (schema.type === 'string' || (isArray && schema.type.includes('string'))) {
399
- if (schema.maxLength === undefined &&
400
- schema.format === undefined &&
401
- schema.enum === undefined &&
402
- schema.pattern === undefined) {
403
- report.addError('KEYWORD_UNDEFINED_STRICT', ['maxLength'], undefined, schema, 'maxLength');
404
- }
405
- }
406
- }
407
- },
408
- allOf: function (report, schema) {
409
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.3.1
410
- if (Array.isArray(schema.allOf) === false) {
411
- report.addError('KEYWORD_TYPE_EXPECTED', ['allOf', 'array'], undefined, schema, 'allOf');
412
- }
413
- else if (schema.allOf.length === 0) {
414
- report.addError('KEYWORD_MUST_BE', ['allOf', 'an array with at least one element'], undefined, schema, 'allOf');
415
- }
416
- else {
417
- for (let idx = 0; idx < schema.allOf.length; idx++) {
418
- report.path.push('allOf');
419
- report.path.push(idx);
420
- this.validateSchema(report, schema.allOf[idx]);
421
- report.path.pop();
422
- report.path.pop();
423
- }
424
- }
425
- },
426
- anyOf: function (report, schema) {
427
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.4.1
428
- if (Array.isArray(schema.anyOf) === false) {
429
- report.addError('KEYWORD_TYPE_EXPECTED', ['anyOf', 'array'], undefined, schema, 'anyOf');
430
- }
431
- else if (schema.anyOf.length === 0) {
432
- report.addError('KEYWORD_MUST_BE', ['anyOf', 'an array with at least one element'], undefined, schema, 'anyOf');
433
- }
434
- else {
435
- for (let idx = 0; idx < schema.anyOf.length; idx++) {
436
- report.path.push('anyOf');
437
- report.path.push(idx);
438
- this.validateSchema(report, schema.anyOf[idx]);
439
- report.path.pop();
440
- report.path.pop();
441
- }
442
- }
443
- },
444
- oneOf: function (report, schema) {
445
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.5.1
446
- if (Array.isArray(schema.oneOf) === false) {
447
- report.addError('KEYWORD_TYPE_EXPECTED', ['oneOf', 'array'], undefined, schema, 'oneOf');
448
- }
449
- else if (schema.oneOf.length === 0) {
450
- report.addError('KEYWORD_MUST_BE', ['oneOf', 'an array with at least one element'], undefined, schema, 'oneOf');
451
- }
452
- else {
453
- for (let idx = 0; idx < schema.oneOf.length; idx++) {
454
- report.path.push('oneOf');
455
- report.path.push(idx);
456
- this.validateSchema(report, schema.oneOf[idx]);
457
- report.path.pop();
458
- report.path.pop();
459
- }
460
- }
461
- },
462
- not: function (report, schema) {
463
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.6.1
464
- const notSchema = schema.not;
465
- const isValidNotSchema = report.options.version === 'draft-04'
466
- ? isObject(notSchema)
467
- : typeof notSchema === 'boolean' || isObject(notSchema);
468
- if (!isValidNotSchema) {
469
- report.addError('KEYWORD_TYPE_EXPECTED', ['not', report.options.version === 'draft-04' ? 'object' : ['boolean', 'object']], undefined, schema, 'not');
470
- }
471
- else {
472
- report.path.push('not');
473
- this.validateSchema(report, notSchema);
474
- report.path.pop();
475
- }
476
- },
477
- if: function (report, schema) {
478
- if (report.options.version !== 'draft-07') {
479
- return;
480
- }
481
- const ifSchema = schema.if;
482
- const isValidIfSchema = typeof ifSchema === 'boolean' || isObject(ifSchema);
483
- if (!isValidIfSchema) {
484
- report.addError('KEYWORD_TYPE_EXPECTED', ['if', ['boolean', 'object']], undefined, schema, 'if');
485
- return;
486
- }
487
- report.path.push('if');
488
- this.validateSchema(report, ifSchema);
489
- report.path.pop();
490
- },
491
- then: function (report, schema) {
492
- if (report.options.version !== 'draft-07') {
493
- return;
494
- }
495
- const thenSchema = schema.then;
496
- const isValidThenSchema = typeof thenSchema === 'boolean' || isObject(thenSchema);
497
- if (!isValidThenSchema) {
498
- report.addError('KEYWORD_TYPE_EXPECTED', ['then', ['boolean', 'object']], undefined, schema, 'then');
499
- return;
500
- }
501
- report.path.push('then');
502
- this.validateSchema(report, thenSchema);
503
- report.path.pop();
504
- },
505
- else: function (report, schema) {
506
- if (report.options.version !== 'draft-07') {
507
- return;
508
- }
509
- const elseSchema = schema.else;
510
- const isValidElseSchema = typeof elseSchema === 'boolean' || isObject(elseSchema);
511
- if (!isValidElseSchema) {
512
- report.addError('KEYWORD_TYPE_EXPECTED', ['else', ['boolean', 'object']], undefined, schema, 'else');
513
- return;
514
- }
515
- report.path.push('else');
516
- this.validateSchema(report, elseSchema);
517
- report.path.pop();
518
- },
519
- definitions: function (report, schema) {
520
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.5.5.7.1
521
- if (!isObject(schema.definitions)) {
522
- report.addError('KEYWORD_TYPE_EXPECTED', ['definitions', 'object'], undefined, schema, 'definitions');
523
- }
524
- else {
525
- const keys = Object.keys(schema.definitions);
526
- for (const key of keys) {
527
- const val = schema.definitions[key];
528
- report.path.push('definitions');
529
- report.path.push(key);
530
- this.validateSchema(report, val);
531
- report.path.pop();
532
- report.path.pop();
533
- }
534
- }
535
- },
536
- $defs: function (report, schema) {
537
- if (report.options.version !== 'draft2019-09' && report.options.version !== 'draft2020-12') {
538
- return;
539
- }
540
- if (!isObject(schema.$defs)) {
541
- report.addError('KEYWORD_TYPE_EXPECTED', ['$defs', 'object'], undefined, schema, '$defs');
542
- return;
543
- }
544
- const keys = Object.keys(schema.$defs);
545
- for (const key of keys) {
546
- const val = schema.$defs[key];
547
- report.path.push('$defs');
548
- report.path.push(key);
549
- this.validateSchema(report, val);
550
- report.path.pop();
551
- report.path.pop();
552
- }
553
- },
554
- format: function (report, schema) {
555
- if (this.options.formatAssertions === false) {
556
- return;
557
- }
558
- if (typeof schema.format !== 'string') {
559
- report.addError('KEYWORD_TYPE_EXPECTED', ['format', 'string'], undefined, schema, 'format');
560
- }
561
- else {
562
- const isModernDraft = this.options.version === 'draft2019-09' || this.options.version === 'draft2020-12';
563
- if (!isFormatSupported(schema.format, this.options.customFormats) &&
564
- this.options.ignoreUnknownFormats !== true &&
565
- !isModernDraft) {
566
- report.addError('UNKNOWN_FORMAT', [schema.format], undefined, schema, 'format');
567
- }
568
- }
569
- },
570
- contentEncoding: function (report, schema) {
571
- if (report.options.version !== 'draft-07') {
572
- return;
573
- }
574
- if (typeof schema.contentEncoding !== 'string') {
575
- report.addError('KEYWORD_TYPE_EXPECTED', ['contentEncoding', 'string'], undefined, schema, 'contentEncoding');
576
- }
577
- },
578
- contentMediaType: function (report, schema) {
579
- if (report.options.version !== 'draft-07') {
580
- return;
581
- }
582
- if (typeof schema.contentMediaType !== 'string') {
583
- report.addError('KEYWORD_TYPE_EXPECTED', ['contentMediaType', 'string'], undefined, schema, 'contentMediaType');
584
- }
585
- },
586
- id: function (report, schema) {
587
- // http://json-schema.org/latest/json-schema-core.html#rfc.section.7.2
588
- if (typeof schema.id !== 'string') {
589
- report.addError('KEYWORD_TYPE_EXPECTED', ['id', 'string'], undefined, schema, 'id');
590
- }
591
- },
592
- title: function (report, schema) {
593
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
594
- if (typeof schema.title !== 'string') {
595
- report.addError('KEYWORD_TYPE_EXPECTED', ['title', 'string'], undefined, schema, 'title');
596
- }
597
- },
598
- description: function (report, schema) {
599
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.1
600
- if (typeof schema.description !== 'string') {
601
- report.addError('KEYWORD_TYPE_EXPECTED', ['description', 'string'], undefined, schema, 'description');
602
- }
603
- },
604
- default: function () {
605
- // http://json-schema.org/latest/json-schema-validation.html#rfc.section.6.2
606
- // There are no restrictions placed on the value of this keyword.
607
- },
608
- };
609
- export class SchemaValidator {
610
- validator;
611
- constructor(validator) {
612
- this.validator = validator;
613
- }
614
- get options() {
615
- return this.validator.options;
616
- }
617
- validateArrayOfSchemas(report, arr) {
618
- for (const schema of arr) {
619
- this.validateSchema(report, schema);
620
- }
621
- return report.isValid();
622
- }
623
- validateSchema(report, schema) {
624
- report.commonErrorMessage = 'SCHEMA_VALIDATION_FAILED';
625
- // if schema is an array, assume it's an array of schemas
626
- if (Array.isArray(schema)) {
627
- return this.validateArrayOfSchemas(report, schema);
628
- }
629
- if (typeof schema === 'boolean') {
630
- return true;
631
- }
632
- // do not revalidate schema that has already been validated once
633
- if (schema.__$validated) {
634
- return true;
635
- }
636
- // if $schema is present, this schema should validate against that $schema
637
- const hasParentSchema = schema.$schema && getId(schema) !== schema.$schema;
638
- if (hasParentSchema) {
639
- if (schema.__$schemaResolved && schema.__$schemaResolved !== schema) {
640
- const subReport = new Report(report);
641
- const valid = validate.call(this.validator, subReport, schema.__$schemaResolved, schema);
642
- if (valid === false) {
643
- report.addError('PARENT_SCHEMA_VALIDATION_FAILED', undefined, subReport, schema, '$schema');
644
- }
645
- }
646
- else {
647
- if (this.validator.options.ignoreUnresolvableReferences !== true) {
648
- report.addError('REF_UNRESOLVED', [schema.$schema], undefined, schema, '$schema');
649
- }
650
- }
651
- }
652
- if (this.validator.options.noTypeless === true) {
653
- // issue #36 - inherit type to anyOf, oneOf, allOf if noTypeless is defined
654
- if (schema.type !== undefined) {
655
- let schemas = [];
656
- if (Array.isArray(schema.anyOf)) {
657
- schemas = schemas.concat(schema.anyOf);
658
- }
659
- if (Array.isArray(schema.oneOf)) {
660
- schemas = schemas.concat(schema.oneOf);
661
- }
662
- if (Array.isArray(schema.allOf)) {
663
- schemas = schemas.concat(schema.allOf);
664
- }
665
- schemas.forEach(function (sch) {
666
- if (!sch.type) {
667
- sch.type = schema.type;
668
- }
669
- });
670
- }
671
- // end issue #36
672
- if (schema.enum === undefined &&
673
- schema.type === undefined &&
674
- schema.anyOf === undefined &&
675
- schema.oneOf === undefined &&
676
- schema.not === undefined &&
677
- schema.$ref === undefined) {
678
- report.addError('KEYWORD_UNDEFINED_STRICT', ['type'], undefined, schema, 'type');
679
- }
680
- }
681
- const keys = Object.keys(schema);
682
- for (const key of keys) {
683
- if (key.startsWith('__')) {
684
- continue;
685
- }
686
- if (Object.hasOwn(SchemaValidators, key)) {
687
- SchemaValidators[key].call(this, report, schema);
688
- }
689
- else if (!hasParentSchema) {
690
- if (this.validator.options.noExtraKeywords === true) {
691
- report.addError('KEYWORD_UNEXPECTED', [key], undefined, schema, undefined);
692
- }
693
- }
694
- }
695
- if (this.validator.options.pedanticCheck === true) {
696
- if (schema.enum) {
697
- // break recursion
698
- const tmpSchema = shallowClone(schema);
699
- delete tmpSchema.enum;
700
- delete tmpSchema.default;
701
- report.path.push('enum');
702
- for (let idx = 0; idx < schema.enum.length; idx++) {
703
- report.path.push(idx);
704
- validate.call(this.validator, report, tmpSchema, schema.enum[idx]);
705
- report.path.pop();
706
- }
707
- report.path.pop();
708
- }
709
- if (schema.default) {
710
- report.path.push('default');
711
- validate.call(this.validator, report, schema, schema.default);
712
- report.path.pop();
713
- }
714
- }
715
- const isValid = report.isValid();
716
- if (isValid) {
717
- schema.__$validated = true;
718
- }
719
- return isValid;
720
- }
721
- }