@rjsf/validator-ajv8 5.0.0-beta.8 → 5.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.
@@ -1,22 +1,53 @@
1
1
  (function (global, factory) {
2
- typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash-es/toPath'), require('@rjsf/utils'), require('ajv'), require('ajv-formats'), require('lodash-es/isObject')) :
3
- typeof define === 'function' && define.amd ? define(['exports', 'lodash-es/toPath', '@rjsf/utils', 'ajv', 'ajv-formats', 'lodash-es/isObject'], factory) :
4
- (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@rjsf/validator-ajv8"] = {}, global.toPath, global.utils, global.Ajv, global.addFormats, global.isObject));
5
- })(this, (function (exports, toPath, utils, Ajv, addFormats, isObject) { 'use strict';
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('lodash-es/toPath'), require('lodash-es/isObject'), require('lodash-es/clone'), require('@rjsf/utils'), require('lodash-es/get'), require('ajv'), require('ajv-formats')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', 'lodash-es/toPath', 'lodash-es/isObject', 'lodash-es/clone', '@rjsf/utils', 'lodash-es/get', 'ajv', 'ajv-formats'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@rjsf/validator-ajv8"] = {}, global.toPath, global.isObject, global.clone, global.utils, global.get, global.Ajv, global.addFormats));
5
+ })(this, (function (exports, toPath, isObject, clone, utils, get, Ajv, addFormats) { 'use strict';
6
6
 
7
7
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
8
8
 
9
9
  var toPath__default = /*#__PURE__*/_interopDefaultLegacy(toPath);
10
+ var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
11
+ var clone__default = /*#__PURE__*/_interopDefaultLegacy(clone);
12
+ var get__default = /*#__PURE__*/_interopDefaultLegacy(get);
10
13
  var Ajv__default = /*#__PURE__*/_interopDefaultLegacy(Ajv);
11
14
  var addFormats__default = /*#__PURE__*/_interopDefaultLegacy(addFormats);
12
- var isObject__default = /*#__PURE__*/_interopDefaultLegacy(isObject);
13
15
 
14
- const AJV_CONFIG = {
16
+ function _extends() {
17
+ _extends = Object.assign ? Object.assign.bind() : function (target) {
18
+ for (var i = 1; i < arguments.length; i++) {
19
+ var source = arguments[i];
20
+ for (var key in source) {
21
+ if (Object.prototype.hasOwnProperty.call(source, key)) {
22
+ target[key] = source[key];
23
+ }
24
+ }
25
+ }
26
+ return target;
27
+ };
28
+ return _extends.apply(this, arguments);
29
+ }
30
+ function _objectWithoutPropertiesLoose(source, excluded) {
31
+ if (source == null) return {};
32
+ var target = {};
33
+ var sourceKeys = Object.keys(source);
34
+ var key, i;
35
+ for (i = 0; i < sourceKeys.length; i++) {
36
+ key = sourceKeys[i];
37
+ if (excluded.indexOf(key) >= 0) continue;
38
+ target[key] = source[key];
39
+ }
40
+ return target;
41
+ }
42
+
43
+ var AJV_CONFIG = {
15
44
  allErrors: true,
16
- multipleOfPrecision: 8
45
+ multipleOfPrecision: 8,
46
+ strict: false,
47
+ verbose: true
17
48
  };
18
- const COLOR_FORMAT_REGEX = /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/;
19
- const DATA_URL_FORMAT_REGEX = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
49
+ var COLOR_FORMAT_REGEX = /^(#?([0-9A-Fa-f]{3}){1,2}\b|aqua|black|blue|fuchsia|gray|green|lime|maroon|navy|olive|orange|purple|red|silver|teal|white|yellow|(rgb\(\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*,\s*\b([0-9]|[1-9][0-9]|1[0-9][0-9]|2[0-4][0-9]|25[0-5])\b\s*\))|(rgb\(\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*,\s*(\d?\d%|100%)+\s*\)))$/;
50
+ var DATA_URL_FORMAT_REGEX = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
20
51
  /** Creates an Ajv version 8 implementation object with standard support for the 'color` and `data-url` custom formats.
21
52
  * If `additionalMetaSchemas` are provided then the Ajv instance is modified to add each of the meta schemas in the
22
53
  * list. If `customFormats` are provided then those additional formats are added to the list of supported formats. If
@@ -30,44 +61,45 @@
30
61
  * @param [customFormats] - The set of additional custom formats that the validator will support
31
62
  * @param [ajvOptionsOverrides={}] - The set of validator config override options
32
63
  * @param [ajvFormatOptions] - The `ajv-format` options to use when adding formats to `ajv`; pass `false` to disable it
64
+ * @param [AjvClass] - The `Ajv` class to use when creating the validator instance
33
65
  */
34
-
35
- function createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions) {
66
+ function createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions, AjvClass) {
36
67
  if (ajvOptionsOverrides === void 0) {
37
68
  ajvOptionsOverrides = {};
38
69
  }
39
-
40
- const ajv = new Ajv__default["default"]({ ...AJV_CONFIG,
41
- ...ajvOptionsOverrides
42
- });
43
-
44
- if (typeof ajvFormatOptions !== "boolean") {
70
+ if (AjvClass === void 0) {
71
+ AjvClass = Ajv__default["default"];
72
+ }
73
+ var ajv = new AjvClass(_extends({}, AJV_CONFIG, ajvOptionsOverrides));
74
+ if (ajvFormatOptions) {
45
75
  addFormats__default["default"](ajv, ajvFormatOptions);
46
- } // add custom formats
47
-
48
-
76
+ } else if (ajvFormatOptions !== false) {
77
+ addFormats__default["default"](ajv);
78
+ }
79
+ // add custom formats
49
80
  ajv.addFormat("data-url", DATA_URL_FORMAT_REGEX);
50
- ajv.addFormat("color", COLOR_FORMAT_REGEX); // add more schemas to validate against
51
-
81
+ ajv.addFormat("color", COLOR_FORMAT_REGEX);
82
+ // Add RJSF-specific additional properties keywords so Ajv doesn't report errors if strict is enabled.
83
+ ajv.addKeyword(utils.ADDITIONAL_PROPERTY_FLAG);
84
+ ajv.addKeyword(utils.RJSF_ADDITONAL_PROPERTIES_FLAG);
85
+ // add more schemas to validate against
52
86
  if (Array.isArray(additionalMetaSchemas)) {
53
87
  ajv.addMetaSchema(additionalMetaSchemas);
54
- } // add more custom formats to validate against
55
-
56
-
88
+ }
89
+ // add more custom formats to validate against
57
90
  if (isObject__default["default"](customFormats)) {
58
- Object.keys(customFormats).forEach(formatName => {
91
+ Object.keys(customFormats).forEach(function (formatName) {
59
92
  ajv.addFormat(formatName, customFormats[formatName]);
60
93
  });
61
94
  }
62
-
63
95
  return ajv;
64
96
  }
65
97
 
66
- const ROOT_SCHEMA_PREFIX = "__rjsf_rootSchema";
98
+ var _excluded = ["instancePath", "keyword", "params", "schemaPath", "parentSchema"];
99
+ var ROOT_SCHEMA_PREFIX = "__rjsf_rootSchema";
67
100
  /** `ValidatorType` implementation that uses the AJV 8 validation mechanism.
68
101
  */
69
-
70
- class AJV8Validator {
102
+ var AJV8Validator = /*#__PURE__*/function () {
71
103
  /** The AJV instance to use for all validations
72
104
  *
73
105
  * @private
@@ -83,16 +115,15 @@
83
115
  * @param options - The `CustomValidatorOptionsType` options that are used to create the AJV instance
84
116
  * @param [localizer] - If provided, is used to localize a list of Ajv `ErrorObject`s
85
117
  */
86
- constructor(options, localizer) {
118
+ function AJV8Validator(options, localizer) {
87
119
  this.ajv = void 0;
88
120
  this.localizer = void 0;
89
- const {
90
- additionalMetaSchemas,
91
- customFormats,
92
- ajvOptionsOverrides,
93
- ajvFormatOptions
94
- } = options;
95
- this.ajv = createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions);
121
+ var additionalMetaSchemas = options.additionalMetaSchemas,
122
+ customFormats = options.customFormats,
123
+ ajvOptionsOverrides = options.ajvOptionsOverrides,
124
+ ajvFormatOptions = options.ajvFormatOptions,
125
+ AjvClass = options.AjvClass;
126
+ this.ajv = createAjvInstance(additionalMetaSchemas, customFormats, ajvOptionsOverrides, ajvFormatOptions, AjvClass);
96
127
  this.localizer = localizer;
97
128
  }
98
129
  /** Transforms a ajv validation errors list:
@@ -114,82 +145,54 @@
114
145
  * @param errors - The list of RJSFValidationError objects
115
146
  * @private
116
147
  */
117
-
118
-
119
- toErrorSchema(errors) {
120
- if (!errors.length) {
121
- return {};
122
- }
123
-
124
- return errors.reduce((errorSchema, error) => {
125
- const {
126
- property,
127
- message
128
- } = error;
129
- const path = toPath__default["default"](property);
130
- let parent = errorSchema; // If the property is at the root (.level1) then toPath creates
131
- // an empty array element at the first index. Remove it.
132
-
133
- if (path.length > 0 && path[0] === "") {
134
- path.splice(0, 1);
135
- }
136
-
137
- for (const segment of path.slice(0)) {
138
- if (!(segment in parent)) {
139
- parent[segment] = {};
148
+ var _proto = AJV8Validator.prototype;
149
+ _proto.toErrorSchema = function toErrorSchema(errors) {
150
+ var builder = new utils.ErrorSchemaBuilder();
151
+ if (errors.length) {
152
+ errors.forEach(function (error) {
153
+ var property = error.property,
154
+ message = error.message;
155
+ var path = toPath__default["default"](property);
156
+ // If the property is at the root (.level1) then toPath creates
157
+ // an empty array element at the first index. Remove it.
158
+ if (path.length > 0 && path[0] === "") {
159
+ path.splice(0, 1);
140
160
  }
141
-
142
- parent = parent[segment];
143
- }
144
-
145
- if (Array.isArray(parent.__errors)) {
146
- // We store the list of errors for this node in a property named __errors
147
- // to avoid name collision with a possible sub schema field named
148
- // 'errors' (see `validate.createErrorHandler`).
149
- parent.__errors = parent.__errors.concat(message);
150
- } else {
151
161
  if (message) {
152
- parent.__errors = [message];
162
+ builder.addErrors(message, path);
153
163
  }
154
- }
155
-
156
- return errorSchema;
157
- }, {});
164
+ });
165
+ }
166
+ return builder.ErrorSchema;
158
167
  }
159
168
  /** Converts an `errorSchema` into a list of `RJSFValidationErrors`
160
169
  *
161
170
  * @param errorSchema - The `ErrorSchema` instance to convert
162
171
  * @param [fieldPath=[]] - The current field path, defaults to [] if not specified
163
- */
164
-
165
-
166
- toErrorList(errorSchema, fieldPath) {
172
+ */;
173
+ _proto.toErrorList = function toErrorList(errorSchema, fieldPath) {
174
+ var _this = this;
167
175
  if (fieldPath === void 0) {
168
176
  fieldPath = [];
169
177
  }
170
-
171
178
  if (!errorSchema) {
172
179
  return [];
173
180
  }
174
-
175
- let errorList = [];
176
-
181
+ var errorList = [];
177
182
  if (utils.ERRORS_KEY in errorSchema) {
178
- errorList = errorList.concat(errorSchema.__errors.map(message => {
179
- const property = "." + fieldPath.join(".");
183
+ errorList = errorList.concat(errorSchema[utils.ERRORS_KEY].map(function (message) {
184
+ var property = "." + fieldPath.join(".");
180
185
  return {
181
- property,
182
- message,
186
+ property: property,
187
+ message: message,
183
188
  stack: property + " " + message
184
189
  };
185
190
  }));
186
191
  }
187
-
188
- return Object.keys(errorSchema).reduce((acc, key) => {
192
+ return Object.keys(errorSchema).reduce(function (acc, key) {
189
193
  if (key !== utils.ERRORS_KEY) {
190
- acc = acc.concat(this.toErrorList(errorSchema[key], [...fieldPath, key]));
194
+ acc = acc.concat(_this.toErrorList(errorSchema[key], [].concat(fieldPath, [key])));
191
195
  }
192
-
193
196
  return acc;
194
197
  }, errorList);
195
198
  }
@@ -197,100 +200,141 @@
197
200
  *
198
201
  * @param formData - The form data around which the error handler is created
199
202
  * @private
200
- */
201
-
202
-
203
- createErrorHandler(formData) {
204
- const handler = {
203
+ */;
204
+ _proto.createErrorHandler = function createErrorHandler(formData) {
205
+ var _this2 = this;
206
+ var handler = {
205
207
  // We store the list of errors for this node in a property named __errors
206
208
  // to avoid name collision with a possible sub schema field named
207
209
  // 'errors' (see `utils.toErrorSchema`).
208
210
  __errors: [],
209
-
210
- addError(message) {
211
+ addError: function addError(message) {
211
212
  this.__errors.push(message);
212
213
  }
213
-
214
214
  };
215
-
216
- if (utils.isObject(formData)) {
217
- const formObject = formData;
218
- return Object.keys(formObject).reduce((acc, key) => {
219
- return { ...acc,
220
- [key]: this.createErrorHandler(formObject[key])
221
- };
215
+ if (Array.isArray(formData)) {
216
+ return formData.reduce(function (acc, value, key) {
217
+ var _extends2;
218
+ return _extends({}, acc, (_extends2 = {}, _extends2[key] = _this2.createErrorHandler(value), _extends2));
222
219
  }, handler);
223
220
  }
224
-
225
- if (Array.isArray(formData)) {
226
- return formData.reduce((acc, value, key) => {
227
- return { ...acc,
228
- [key]: this.createErrorHandler(value)
229
- };
221
+ if (isObject__default["default"](formData)) {
222
+ var formObject = formData;
223
+ return Object.keys(formObject).reduce(function (acc, key) {
224
+ var _extends3;
225
+ return _extends({}, acc, (_extends3 = {}, _extends3[key] = _this2.createErrorHandler(formObject[key]), _extends3));
230
226
  }, handler);
231
227
  }
232
-
233
228
  return handler;
234
229
  }
235
230
  /** Unwraps the `errorHandler` structure into the associated `ErrorSchema`, stripping the `addError` functions from it
236
231
  *
237
232
  * @param errorHandler - The `FormValidation` error handling structure
238
233
  * @private
239
- */
240
-
241
-
242
- unwrapErrorHandler(errorHandler) {
243
- return Object.keys(errorHandler).reduce((acc, key) => {
234
+ */;
235
+ _proto.unwrapErrorHandler = function unwrapErrorHandler(errorHandler) {
236
+ var _this3 = this;
237
+ return Object.keys(errorHandler).reduce(function (acc, key) {
238
+ var _extends5;
244
239
  if (key === "addError") {
245
240
  return acc;
246
241
  } else if (key === utils.ERRORS_KEY) {
247
- return { ...acc,
248
- [key]: errorHandler[key]
249
- };
242
+ var _extends4;
243
+ return _extends({}, acc, (_extends4 = {}, _extends4[key] = errorHandler[key], _extends4));
250
244
  }
251
-
252
- return { ...acc,
253
- [key]: this.unwrapErrorHandler(errorHandler[key])
254
- };
245
+ return _extends({}, acc, (_extends5 = {}, _extends5[key] = _this3.unwrapErrorHandler(errorHandler[key]), _extends5));
255
246
  }, {});
256
247
  }
257
248
  /** Transforming the error output from ajv to format used by @rjsf/utils.
258
249
  * At some point, components should be updated to support ajv.
259
250
  *
260
251
  * @param errors - The list of AJV errors to convert to `RJSFValidationErrors`
261
- * @private
262
- */
263
-
264
-
265
- transformRJSFValidationErrors(errors) {
252
+ * @protected
253
+ */;
254
+ _proto.transformRJSFValidationErrors = function transformRJSFValidationErrors(errors, uiSchema) {
266
255
  if (errors === void 0) {
267
256
  errors = [];
268
257
  }
269
-
270
- if (errors === null) {
271
- return [];
272
- }
273
-
274
- return errors.map(e => {
275
- const {
276
- instancePath,
277
- keyword,
278
- message,
279
- params,
280
- schemaPath
281
- } = e;
282
- const property = instancePath.replace(/\//g, "."); // put data in expected format
283
-
258
+ return errors.map(function (e) {
259
+ var instancePath = e.instancePath,
260
+ keyword = e.keyword,
261
+ params = e.params,
262
+ schemaPath = e.schemaPath,
263
+ parentSchema = e.parentSchema,
264
+ rest = _objectWithoutPropertiesLoose(e, _excluded);
265
+ var _rest$message = rest.message,
266
+ message = _rest$message === void 0 ? "" : _rest$message;
267
+ var property = instancePath.replace(/\//g, ".");
268
+ var stack = (property + " " + message).trim();
269
+ if ("missingProperty" in params) {
270
+ property = property ? property + "." + params.missingProperty : params.missingProperty;
271
+ var currentProperty = params.missingProperty;
272
+ var uiSchemaTitle = utils.getUiOptions(get__default["default"](uiSchema, "" + property.replace(/^\./, ""))).title;
273
+ if (uiSchemaTitle) {
274
+ message = message.replace(currentProperty, uiSchemaTitle);
275
+ } else {
276
+ var parentSchemaTitle = get__default["default"](parentSchema, [utils.PROPERTIES_KEY, currentProperty, "title"]);
277
+ if (parentSchemaTitle) {
278
+ message = message.replace(currentProperty, parentSchemaTitle);
279
+ }
280
+ }
281
+ stack = message;
282
+ } else {
283
+ var _uiSchemaTitle = utils.getUiOptions(get__default["default"](uiSchema, "" + property.replace(/^\./, ""))).title;
284
+ if (_uiSchemaTitle) {
285
+ stack = ("'" + _uiSchemaTitle + "' " + message).trim();
286
+ } else {
287
+ var _parentSchemaTitle = parentSchema === null || parentSchema === void 0 ? void 0 : parentSchema.title;
288
+ if (_parentSchemaTitle) {
289
+ stack = ("'" + _parentSchemaTitle + "' " + message).trim();
290
+ }
291
+ }
292
+ }
293
+ // put data in expected format
284
294
  return {
285
295
  name: keyword,
286
- property,
287
- message,
288
- params,
289
- stack: (property + " " + message).trim(),
290
- schemaPath
296
+ property: property,
297
+ message: message,
298
+ params: params,
299
+ stack: stack,
300
+ schemaPath: schemaPath
291
301
  };
292
302
  });
293
303
  }
304
+ /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
305
+ * by the playground. Returns the `errors` from the validation
306
+ *
307
+ * @param schema - The schema against which to validate the form data * @param schema
308
+ * @param formData - The form data to validate
309
+ */;
310
+ _proto.rawValidation = function rawValidation(schema, formData) {
311
+ var compilationError = undefined;
312
+ var compiledValidator;
313
+ if (schema["$id"]) {
314
+ compiledValidator = this.ajv.getSchema(schema["$id"]);
315
+ }
316
+ try {
317
+ if (compiledValidator === undefined) {
318
+ compiledValidator = this.ajv.compile(schema);
319
+ }
320
+ compiledValidator(formData);
321
+ } catch (err) {
322
+ compilationError = err;
323
+ }
324
+ var errors;
325
+ if (compiledValidator) {
326
+ if (typeof this.localizer === "function") {
327
+ this.localizer(compiledValidator.errors);
328
+ }
329
+ errors = compiledValidator.errors || undefined;
330
+ // Clear errors to prevent persistent errors, see #1104
331
+ compiledValidator.errors = null;
332
+ }
333
+ return {
334
+ errors: errors,
335
+ validationError: compilationError
336
+ };
337
+ }
294
338
  /** This function processes the `formData` with an optional user contributed `customValidate` function, which receives
295
339
  * the form data and a `errorHandler` function that will be used to add custom validation errors for each field. Also
296
340
  * supports a `transformErrors` function that will take the raw AJV validation errors, prior to custom validation and
@@ -300,64 +344,41 @@
300
344
  * @param schema - The schema against which to validate the form data
301
345
  * @param [customValidate] - An optional function that is used to perform custom validation
302
346
  * @param [transformErrors] - An optional function that is used to transform errors after AJV validation
303
- */
304
-
305
-
306
- validateFormData(formData, schema, customValidate, transformErrors) {
307
- // Include form data with undefined values, which is required for validation.
308
- const rootSchema = schema;
309
- const newFormData = utils.getDefaultFormState(this, schema, formData, rootSchema, true);
310
- let validationError = null;
311
-
312
- try {
313
- this.ajv.validate(schema, newFormData);
314
- } catch (err) {
315
- validationError = err;
316
- }
317
-
318
- if (typeof this.localizer === "function") {
319
- this.localizer(this.ajv.errors);
320
- }
321
-
322
- let errors = this.transformRJSFValidationErrors(this.ajv.errors); // Clear errors to prevent persistent errors, see #1104
323
-
324
- this.ajv.errors = null;
325
- const noProperMetaSchema = validationError && validationError.message && typeof validationError.message === "string" && validationError.message.includes("no schema with key or ref ");
326
-
327
- if (noProperMetaSchema) {
328
- errors = [...errors, {
329
- stack: validationError.message
330
- }];
347
+ * @param [uiSchema] - An optional uiSchema that is passed to `transformErrors` and `customValidate`
348
+ */;
349
+ _proto.validateFormData = function validateFormData(formData, schema, customValidate, transformErrors, uiSchema) {
350
+ var rawErrors = this.rawValidation(schema, formData);
351
+ var invalidSchemaError = rawErrors.validationError;
352
+ var errors = this.transformRJSFValidationErrors(rawErrors.errors, uiSchema);
353
+ if (invalidSchemaError) {
354
+ errors = [].concat(errors, [{
355
+ stack: invalidSchemaError.message
356
+ }]);
331
357
  }
332
-
333
358
  if (typeof transformErrors === "function") {
334
- errors = transformErrors(errors);
359
+ errors = transformErrors(errors, uiSchema);
335
360
  }
336
-
337
- let errorSchema = this.toErrorSchema(errors);
338
-
339
- if (noProperMetaSchema) {
340
- errorSchema = { ...errorSchema,
341
- ...{
342
- $schema: {
343
- __errors: [validationError.message]
344
- }
361
+ var errorSchema = this.toErrorSchema(errors);
362
+ if (invalidSchemaError) {
363
+ errorSchema = _extends({}, errorSchema, {
364
+ $schema: {
365
+ __errors: [invalidSchemaError.message]
345
366
  }
346
- };
367
+ });
347
368
  }
348
-
349
369
  if (typeof customValidate !== "function") {
350
370
  return {
351
- errors,
352
- errorSchema
371
+ errors: errors,
372
+ errorSchema: errorSchema
353
373
  };
354
374
  }
355
-
356
- const errorHandler = customValidate(newFormData, this.createErrorHandler(newFormData));
357
- const userErrorSchema = this.unwrapErrorHandler(errorHandler);
375
+ // Include form data with undefined values, which is required for custom validation.
376
+ var newFormData = utils.getDefaultFormState(this, schema, formData, schema, true);
377
+ var errorHandler = customValidate(newFormData, this.createErrorHandler(newFormData), uiSchema);
378
+ var userErrorSchema = this.unwrapErrorHandler(errorHandler);
358
379
  return utils.mergeValidationData(this, {
359
- errors,
360
- errorSchema
380
+ errors: errors,
381
+ errorSchema: errorSchema
361
382
  }, userErrorSchema);
362
383
  }
363
384
  /** Takes a `node` object and transforms any contained `$ref` node variables with a prefix, recursively calling
@@ -365,61 +386,67 @@
365
386
  *
366
387
  * @param node - The object node to which a ROOT_SCHEMA_PREFIX is added when a REF_KEY is part of it
367
388
  * @private
368
- */
369
-
370
-
371
- withIdRefPrefixObject(node) {
372
- for (const key in node) {
373
- const realObj = node;
374
- const value = realObj[key];
375
-
389
+ */;
390
+ _proto.withIdRefPrefixObject = function withIdRefPrefixObject(node) {
391
+ for (var key in node) {
392
+ var realObj = node;
393
+ var value = realObj[key];
376
394
  if (key === utils.REF_KEY && typeof value === "string" && value.startsWith("#")) {
377
395
  realObj[key] = ROOT_SCHEMA_PREFIX + value;
378
396
  } else {
379
397
  realObj[key] = this.withIdRefPrefix(value);
380
398
  }
381
399
  }
382
-
383
400
  return node;
384
401
  }
385
402
  /** Takes a `node` object list and transforms any contained `$ref` node variables with a prefix, recursively calling
386
403
  * `withIdRefPrefix` for any other elements.
387
404
  *
388
- * @param nodeThe - list of object nodes to which a ROOT_SCHEMA_PREFIX is added when a REF_KEY is part of it
405
+ * @param node - The list of object nodes to which a ROOT_SCHEMA_PREFIX is added when a REF_KEY is part of it
389
406
  * @private
390
- */
391
-
392
-
393
- withIdRefPrefixArray(node) {
394
- for (let i = 0; i < node.length; i++) {
407
+ */;
408
+ _proto.withIdRefPrefixArray = function withIdRefPrefixArray(node) {
409
+ for (var i = 0; i < node.length; i++) {
395
410
  node[i] = this.withIdRefPrefix(node[i]);
396
411
  }
397
-
398
412
  return node;
399
413
  }
400
414
  /** Validates data against a schema, returning true if the data is valid, or
401
415
  * false otherwise. If the schema is invalid, then this function will return
402
416
  * false.
403
417
  *
404
- * @param schema - The schema against which to validate the form data * @param schema
405
- * @param formData- - The form data to validate
418
+ * @param schema - The schema against which to validate the form data
419
+ * @param formData - The form data to validate
406
420
  * @param rootSchema - The root schema used to provide $ref resolutions
407
- */
408
-
409
-
410
- isValid(schema, formData, rootSchema) {
421
+ */;
422
+ _proto.isValid = function isValid(schema, formData, rootSchema) {
423
+ var _rootSchema$$id;
424
+ var rootSchemaId = (_rootSchema$$id = rootSchema["$id"]) != null ? _rootSchema$$id : ROOT_SCHEMA_PREFIX;
411
425
  try {
412
426
  // add the rootSchema ROOT_SCHEMA_PREFIX as id.
413
427
  // then rewrite the schema ref's to point to the rootSchema
414
428
  // this accounts for the case where schema have references to models
415
429
  // that lives in the rootSchema but not in the schema in question.
416
- const result = this.ajv.addSchema(rootSchema, ROOT_SCHEMA_PREFIX).validate(this.withIdRefPrefix(schema), formData);
430
+ if (this.ajv.getSchema(rootSchemaId) === undefined) {
431
+ this.ajv.addSchema(rootSchema, rootSchemaId);
432
+ }
433
+ var schemaWithIdRefPrefix = this.withIdRefPrefix(schema);
434
+ var compiledValidator;
435
+ if (schemaWithIdRefPrefix["$id"]) {
436
+ compiledValidator = this.ajv.getSchema(schemaWithIdRefPrefix["$id"]);
437
+ }
438
+ if (compiledValidator === undefined) {
439
+ compiledValidator = this.ajv.compile(schemaWithIdRefPrefix);
440
+ }
441
+ var result = compiledValidator(formData);
417
442
  return result;
418
443
  } catch (e) {
444
+ console.warn("Error encountered compiling schema:", e);
419
445
  return false;
420
446
  } finally {
447
+ // TODO: A function should be called if the root schema changes so we don't have to remove and recompile the schema every run.
421
448
  // make sure we remove the rootSchema from the global ajv instance
422
- this.ajv.removeSchema(ROOT_SCHEMA_PREFIX);
449
+ this.ajv.removeSchema(rootSchemaId);
423
450
  }
424
451
  }
425
452
  /** Recursively prefixes all $ref's in a schema with `ROOT_SCHEMA_PREFIX`
@@ -427,23 +454,18 @@
427
454
  *
428
455
  * @param schemaNode - The object node to which a ROOT_SCHEMA_PREFIX is added when a REF_KEY is part of it
429
456
  * @protected
430
- */
431
-
432
-
433
- withIdRefPrefix(schemaNode) {
434
- if (schemaNode.constructor === Object) {
435
- return this.withIdRefPrefixObject({ ...schemaNode
436
- });
437
- }
438
-
457
+ */;
458
+ _proto.withIdRefPrefix = function withIdRefPrefix(schemaNode) {
439
459
  if (Array.isArray(schemaNode)) {
440
- return this.withIdRefPrefixArray([...schemaNode]);
460
+ return this.withIdRefPrefixArray([].concat(schemaNode));
461
+ }
462
+ if (isObject__default["default"](schemaNode)) {
463
+ return this.withIdRefPrefixObject(clone__default["default"](schemaNode));
441
464
  }
442
-
443
465
  return schemaNode;
444
- }
445
-
446
- }
466
+ };
467
+ return AJV8Validator;
468
+ }();
447
469
 
448
470
  /** Creates and returns a customized implementation of the `ValidatorType` with the given customization `options` if
449
471
  * provided.
@@ -451,12 +473,10 @@
451
473
  * @param [options={}] - The `CustomValidatorOptionsType` options that are used to create the `ValidatorType` instance
452
474
  * @param [localizer] - If provided, is used to localize a list of Ajv `ErrorObject`s
453
475
  */
454
-
455
476
  function customizeValidator(options, localizer) {
456
477
  if (options === void 0) {
457
478
  options = {};
458
479
  }
459
-
460
480
  return new AJV8Validator(options, localizer);
461
481
  }
462
482