@rjsf/validator-ata 6.6.1

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 (53) hide show
  1. package/README.md +94 -0
  2. package/dist/compileSchemaValidators.cjs +110 -0
  3. package/dist/compileSchemaValidators.cjs.map +7 -0
  4. package/dist/compileSchemaValidators.esm.js +79 -0
  5. package/dist/compileSchemaValidators.esm.js.map +7 -0
  6. package/dist/index.cjs +461 -0
  7. package/dist/index.cjs.map +7 -0
  8. package/dist/validator-ata.esm.js +450 -0
  9. package/dist/validator-ata.esm.js.map +7 -0
  10. package/dist/validator-ata.umd.js +422 -0
  11. package/lib/compileSchemaValidators.d.ts +16 -0
  12. package/lib/compileSchemaValidators.js +21 -0
  13. package/lib/compileSchemaValidators.js.map +1 -0
  14. package/lib/compileSchemaValidatorsCode.d.ts +13 -0
  15. package/lib/compileSchemaValidatorsCode.js +80 -0
  16. package/lib/compileSchemaValidatorsCode.js.map +1 -0
  17. package/lib/createAtaInstance.d.ts +27 -0
  18. package/lib/createAtaInstance.js +68 -0
  19. package/lib/createAtaInstance.js.map +1 -0
  20. package/lib/createPrecompiledValidator.d.ts +15 -0
  21. package/lib/createPrecompiledValidator.js +17 -0
  22. package/lib/createPrecompiledValidator.js.map +1 -0
  23. package/lib/customizeValidator.d.ts +8 -0
  24. package/lib/customizeValidator.js +9 -0
  25. package/lib/customizeValidator.js.map +1 -0
  26. package/lib/index.d.ts +7 -0
  27. package/lib/index.js +7 -0
  28. package/lib/index.js.map +1 -0
  29. package/lib/precompiledValidator.d.ts +89 -0
  30. package/lib/precompiledValidator.js +107 -0
  31. package/lib/precompiledValidator.js.map +1 -0
  32. package/lib/processRawValidationErrors.d.ts +28 -0
  33. package/lib/processRawValidationErrors.js +137 -0
  34. package/lib/processRawValidationErrors.js.map +1 -0
  35. package/lib/tsconfig.tsbuildinfo +1 -0
  36. package/lib/types.d.ts +63 -0
  37. package/lib/types.js +2 -0
  38. package/lib/types.js.map +1 -0
  39. package/lib/validator.d.ts +85 -0
  40. package/lib/validator.js +154 -0
  41. package/lib/validator.js.map +1 -0
  42. package/package.json +113 -0
  43. package/src/compileSchemaValidators.ts +30 -0
  44. package/src/compileSchemaValidatorsCode.ts +92 -0
  45. package/src/createAtaInstance.ts +81 -0
  46. package/src/createPrecompiledValidator.ts +29 -0
  47. package/src/customizeValidator.ts +16 -0
  48. package/src/index.ts +8 -0
  49. package/src/precompiledValidator.ts +188 -0
  50. package/src/processRawValidationErrors.ts +197 -0
  51. package/src/tsconfig.json +15 -0
  52. package/src/types.ts +71 -0
  53. package/src/validator.ts +231 -0
@@ -0,0 +1,422 @@
1
+ (function (global, factory) {
2
+ typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports, require('@rjsf/utils'), require('lodash/get'), require('lodash/cloneDeep'), require('ata-validator'), require('lodash/isObject')) :
3
+ typeof define === 'function' && define.amd ? define(['exports', '@rjsf/utils', 'lodash/get', 'lodash/cloneDeep', 'ata-validator', 'lodash/isObject'], factory) :
4
+ (global = typeof globalThis !== 'undefined' ? globalThis : global || self, factory(global["@rjsf/validator-ata"] = {}, global.utils, global.get, global.cloneDeep, global.ataValidator, global.isObject));
5
+ })(this, (function (exports, utils, get, cloneDeep, ataValidator, isObject) { 'use strict';
6
+
7
+ // src/precompiledValidator.ts
8
+ function filterDuplicateErrors(errorList, suppressDuplicateFiltering = "none") {
9
+ if (suppressDuplicateFiltering === "all") {
10
+ return errorList;
11
+ }
12
+ return errorList.reduce((acc, err) => {
13
+ const { message, schemaPath } = err;
14
+ const anyOfIndex = suppressDuplicateFiltering !== "anyOf" ? schemaPath?.indexOf(`/${utils.ANY_OF_KEY}/`) : void 0;
15
+ const oneOfIndex = suppressDuplicateFiltering !== "oneOf" ? schemaPath?.indexOf(`/${utils.ONE_OF_KEY}/`) : void 0;
16
+ let schemaPrefix;
17
+ if (anyOfIndex && anyOfIndex >= 0) {
18
+ schemaPrefix = schemaPath?.substring(0, anyOfIndex);
19
+ } else if (oneOfIndex && oneOfIndex >= 0) {
20
+ schemaPrefix = schemaPath?.substring(0, oneOfIndex);
21
+ }
22
+ const dup = schemaPrefix ? acc.find((e) => e.message === message && e.schemaPath?.startsWith(schemaPrefix)) : void 0;
23
+ if (!dup) {
24
+ acc.push(err);
25
+ }
26
+ return acc;
27
+ }, []);
28
+ }
29
+ function transformRJSFValidationErrors(errors = [], uiSchema, suppressDuplicateFiltering) {
30
+ const errorList = errors.map((e) => {
31
+ const { instancePath, keyword, params, schemaPath, parentSchema } = e;
32
+ let { message = "" } = e;
33
+ let property = instancePath.replace(/\//g, ".");
34
+ let stack = `${property} ${message}`.trim();
35
+ let uiTitle = "";
36
+ const p = params;
37
+ const rawPropertyNames = [
38
+ ...p?.deps?.split(", ") || [],
39
+ p?.missingProperty,
40
+ p?.property
41
+ ].filter((item) => Boolean(item));
42
+ if (rawPropertyNames.length > 0) {
43
+ rawPropertyNames.forEach((currentProperty) => {
44
+ const path = property ? `${property}.${currentProperty}` : currentProperty;
45
+ let uiSchemaTitle = utils.getUiOptions(get(uiSchema, `${path.replace(/^\./, "")}`)).title;
46
+ if (uiSchemaTitle === void 0) {
47
+ const uiSchemaPath = schemaPath.replace(/\/properties\//g, "/").split("/").slice(1, -1).concat([currentProperty]);
48
+ uiSchemaTitle = utils.getUiOptions(get(uiSchema, uiSchemaPath)).title;
49
+ }
50
+ if (uiSchemaTitle) {
51
+ message = message.replace(`'${currentProperty}'`, `'${uiSchemaTitle}'`);
52
+ uiTitle = uiSchemaTitle;
53
+ } else {
54
+ const parentSchemaTitle = get(parentSchema, [utils.PROPERTIES_KEY, currentProperty, "title"]);
55
+ if (parentSchemaTitle) {
56
+ message = message.replace(`'${currentProperty}'`, `'${parentSchemaTitle}'`);
57
+ uiTitle = parentSchemaTitle;
58
+ }
59
+ }
60
+ });
61
+ stack = message;
62
+ } else {
63
+ const uiSchemaTitle = utils.getUiOptions(get(uiSchema, `${property.replace(/^\./, "")}`)).title;
64
+ if (uiSchemaTitle) {
65
+ stack = `'${uiSchemaTitle}' ${message}`.trim();
66
+ uiTitle = uiSchemaTitle;
67
+ } else {
68
+ const parentSchemaTitle = parentSchema?.title;
69
+ if (parentSchemaTitle) {
70
+ stack = `'${parentSchemaTitle}' ${message}`.trim();
71
+ uiTitle = parentSchemaTitle;
72
+ }
73
+ }
74
+ }
75
+ if (p && "missingProperty" in p) {
76
+ property = property ? `${property}.${p.missingProperty}` : p.missingProperty;
77
+ }
78
+ return {
79
+ name: keyword,
80
+ property,
81
+ message,
82
+ params,
83
+ stack,
84
+ schemaPath,
85
+ title: uiTitle
86
+ };
87
+ });
88
+ return filterDuplicateErrors(errorList, suppressDuplicateFiltering);
89
+ }
90
+ function processRawValidationErrors(validator, rawErrors, formData, schema, customValidate, transformErrors, uiSchema, suppressDuplicateFiltering) {
91
+ const { validationError: invalidSchemaError } = rawErrors;
92
+ let errors = transformRJSFValidationErrors(rawErrors.errors, uiSchema, suppressDuplicateFiltering);
93
+ if (invalidSchemaError) {
94
+ errors = [...errors, { stack: invalidSchemaError.message }];
95
+ }
96
+ if (typeof transformErrors === "function") {
97
+ errors = transformErrors(errors, uiSchema);
98
+ }
99
+ let errorSchema = utils.toErrorSchema(errors);
100
+ if (invalidSchemaError) {
101
+ errorSchema = {
102
+ ...errorSchema,
103
+ $schema: {
104
+ __errors: [invalidSchemaError.message]
105
+ }
106
+ };
107
+ }
108
+ if (typeof customValidate !== "function") {
109
+ return { errors, errorSchema };
110
+ }
111
+ const newFormData = utils.getDefaultFormState(validator, schema, formData, schema, true);
112
+ const errorHandler = customValidate(newFormData, utils.createErrorHandler(newFormData), uiSchema, errorSchema);
113
+ const userErrorSchema = utils.unwrapErrorHandler(errorHandler);
114
+ return utils.validationDataMerge({ errors, errorSchema }, userErrorSchema);
115
+ }
116
+
117
+ // src/precompiledValidator.ts
118
+ var ATAPrecompiledValidator = class {
119
+ /** Constructs an `ATAPrecompiledValidator` instance using the `validateFns` and `rootSchema`
120
+ *
121
+ * @param validateFns - The map of the validation functions that are generated by the `schemaCompile()` function
122
+ * @param rootSchema - The root schema that was used with the `compileSchema()` function
123
+ * @param [localizer] - If provided, is used to localize a list of ata `ValidationError`s
124
+ * @param [suppressDuplicateFiltering] - Controls which duplicate filtering is suppressed; see `filterDuplicateErrors`
125
+ * @throws - Error when the base schema of the precompiled validator does not have a matching validator function
126
+ */
127
+ constructor(validateFns, rootSchema, localizer, suppressDuplicateFiltering) {
128
+ this.rootSchema = rootSchema;
129
+ this.validateFns = validateFns;
130
+ this.localizer = localizer;
131
+ this.suppressDuplicateFiltering = suppressDuplicateFiltering;
132
+ this.mainValidator = this.getValidator(rootSchema);
133
+ }
134
+ /** Returns the precompiled validator associated with the given `schema` from the map of precompiled validator
135
+ * functions.
136
+ *
137
+ * @param schema - The schema for which a precompiled validator function is desired
138
+ * @returns - The precompiled validator function associated with this schema
139
+ */
140
+ getValidator(schema) {
141
+ const key = get(schema, utils.ID_KEY) || utils.hashForSchema(schema);
142
+ const validator = this.validateFns[key];
143
+ if (!validator) {
144
+ throw new Error(`No precompiled validator function was found for the given schema for "${key}"`);
145
+ }
146
+ return validator;
147
+ }
148
+ /** Ensures that the validator is using the same schema as the root schema used to construct the precompiled
149
+ * validator. It first compares the given `schema` against the root schema and if they aren't the same, then it
150
+ * checks against the resolved root schema, on the chance that a resolved version of the root schema was passed in
151
+ * instead of the raw root schema.
152
+ *
153
+ * @param schema - The schema against which to validate the form data
154
+ * @param [formData] - The form data to validate if any
155
+ */
156
+ ensureSameRootSchema(schema, formData) {
157
+ if (!utils.deepEquals(schema, this.rootSchema)) {
158
+ const resolvedRootSchema = utils.retrieveSchema(this, this.rootSchema, this.rootSchema, formData);
159
+ if (!utils.deepEquals(schema, resolvedRootSchema)) {
160
+ throw new Error(
161
+ "The schema associated with the precompiled validator differs from the rootSchema provided for validation"
162
+ );
163
+ }
164
+ }
165
+ return true;
166
+ }
167
+ /** Runs the pure validation of the `schema` and `formData` without any of the RJSF functionality. Provided for use
168
+ * by the playground. Returns the `errors` from the validation
169
+ *
170
+ * @param schema - The schema against which to validate the form data
171
+ * @param [formData] - The form data to validate, if any
172
+ * @throws - Error when the schema provided does not match the base schema of the precompiled validator
173
+ */
174
+ rawValidation(schema, formData) {
175
+ this.ensureSameRootSchema(schema, formData);
176
+ this.mainValidator(formData);
177
+ if (typeof this.localizer === "function") {
178
+ this.localizer(this.mainValidator.errors);
179
+ }
180
+ const errors = this.mainValidator.errors || void 0;
181
+ this.mainValidator.errors = null;
182
+ return { errors };
183
+ }
184
+ /** This function processes the `formData` with an optional user contributed `customValidate` function, which receives
185
+ * the form data and a `errorHandler` function that will be used to add custom validation errors for each field. Also
186
+ * supports a `transformErrors` function that will take the raw ata validation errors, prior to custom validation and
187
+ * transform them in what ever way it chooses.
188
+ *
189
+ * @param formData - The form data to validate
190
+ * @param schema - The schema against which to validate the form data
191
+ * @param [customValidate] - An optional function that is used to perform custom validation
192
+ * @param [transformErrors] - An optional function that is used to transform errors after ata validation
193
+ * @param [uiSchema] - An optional uiSchema that is passed to `transformErrors` and `customValidate`
194
+ */
195
+ validateFormData(formData, schema, customValidate, transformErrors, uiSchema) {
196
+ const rawErrors = this.rawValidation(schema, formData);
197
+ return processRawValidationErrors(
198
+ this,
199
+ rawErrors,
200
+ formData,
201
+ schema,
202
+ customValidate,
203
+ transformErrors,
204
+ uiSchema,
205
+ this.suppressDuplicateFiltering
206
+ );
207
+ }
208
+ /** Validates data against a schema, returning true if the data is valid, or false otherwise. If the schema is
209
+ * invalid, then this function will return false.
210
+ *
211
+ * @param schema - The schema against which to validate the form data
212
+ * @param formData - The form data to validate
213
+ * @param rootSchema - The root schema used to provide $ref resolutions
214
+ * @returns - true if the formData validates against the schema, false otherwise
215
+ * @throws - Error when the schema provided does not match the base schema of the precompiled validator OR if there
216
+ * isn't a precompiled validator function associated with the schema
217
+ */
218
+ isValid(schema, formData, rootSchema) {
219
+ this.ensureSameRootSchema(rootSchema, formData);
220
+ if (get(schema, utils.ID_KEY) === utils.JUNK_OPTION_ID) {
221
+ return false;
222
+ }
223
+ const validator = this.getValidator(schema);
224
+ return validator(formData);
225
+ }
226
+ };
227
+
228
+ // src/createPrecompiledValidator.ts
229
+ function createPrecompiledValidator(validateFns, rootSchema, localizer, suppressDuplicateFiltering) {
230
+ return new ATAPrecompiledValidator(validateFns, rootSchema, localizer, suppressDuplicateFiltering);
231
+ }
232
+ var ATA_CONFIG = {
233
+ verbose: true
234
+ };
235
+ 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*\)))$/;
236
+ var DATA_URL_FORMAT_REGEX = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
237
+ function asFormatChecker(spec) {
238
+ if (typeof spec === "function") {
239
+ return spec;
240
+ }
241
+ const re = spec instanceof RegExp ? spec : new RegExp(spec);
242
+ return (value) => re.test(value);
243
+ }
244
+ function createAtaInstance(schema, options = {}) {
245
+ const { customFormats, ataOptionsOverrides, additionalMetaSchemas, extenderFn } = options;
246
+ const formats = {
247
+ color: asFormatChecker(COLOR_FORMAT_REGEX),
248
+ "data-url": asFormatChecker(DATA_URL_FORMAT_REGEX)
249
+ };
250
+ if (isObject(customFormats)) {
251
+ for (const [name, spec] of Object.entries(customFormats)) {
252
+ formats[name] = asFormatChecker(spec);
253
+ }
254
+ }
255
+ const validatorOptions = {
256
+ ...ATA_CONFIG,
257
+ ...ataOptionsOverrides,
258
+ formats
259
+ };
260
+ let validator = new ataValidator.Validator(schema, validatorOptions);
261
+ if (Array.isArray(additionalMetaSchemas)) {
262
+ for (const meta of additionalMetaSchemas) {
263
+ validator.addSchema(meta);
264
+ }
265
+ }
266
+ if (typeof extenderFn === "function") {
267
+ validator = extenderFn(validator);
268
+ }
269
+ return validator;
270
+ }
271
+
272
+ // src/validator.ts
273
+ var ATAValidator = class {
274
+ constructor(options, localizer) {
275
+ /** Per-schema-id cache of constructed ata `Validator` instances. AJV uses a
276
+ * single instance with a schema registry; ata is schema-bound, so we
277
+ * maintain the registry ourselves.
278
+ */
279
+ this.validators = /* @__PURE__ */ new Map();
280
+ /** True once a `rootSchema` has been registered in this lifecycle. */
281
+ this.hasRegisteredRootSchema = false;
282
+ this.options = options;
283
+ this.localizer = localizer;
284
+ this.suppressDuplicateFiltering = options.suppressDuplicateFiltering;
285
+ }
286
+ /** Resets the cached validators and root-schema bookkeeping. Mirrors
287
+ * `AJV8Validator#reset` so RJSF's test harness can flush state between runs.
288
+ */
289
+ reset() {
290
+ this.validators.clear();
291
+ this.lastSeenRootSchema = void 0;
292
+ this.hasRegisteredRootSchema = false;
293
+ }
294
+ /** Returns a structural copy of `formData` so ata's default-applier
295
+ * (which writes `default` values into the input object during validation)
296
+ * doesn't leak a mutation back to the caller. RJSF probes the same data
297
+ * through `isValid` repeatedly while resolving oneOf/anyOf options, and
298
+ * a mutated probe changes subsequent answers, so the wrapper has to
299
+ * preserve referential purity that AJV provides by default.
300
+ */
301
+ cloneForValidation(data) {
302
+ if (data === null || typeof data !== "object") {
303
+ return data;
304
+ }
305
+ if (typeof globalThis.structuredClone === "function") {
306
+ return globalThis.structuredClone(data);
307
+ }
308
+ return cloneDeep(data);
309
+ }
310
+ /** Returns the cached ata `Validator` for the given id, or builds and
311
+ * caches a new one. When a rootSchema has been registered via
312
+ * `handleSchemaUpdate`, it is supplied as a sibling schema so `$ref` to
313
+ * the root resolves regardless of which sub-schema is being validated.
314
+ */
315
+ getOrBuild(id, schema) {
316
+ const existing = this.validators.get(id);
317
+ if (existing && utils.deepEquals(existing.schema, schema)) {
318
+ return existing.validator;
319
+ }
320
+ const siblingRoots = this.cachedRootSchema && this.cachedRootSchema !== schema ? [this.cachedRootSchema] : [];
321
+ const optionsWithSchemas = {
322
+ ...this.options,
323
+ ataOptionsOverrides: {
324
+ ...this.options.ataOptionsOverrides || {},
325
+ ...siblingRoots.length ? { schemas: siblingRoots } : {}
326
+ }
327
+ };
328
+ const validator = createAtaInstance(schema, optionsWithSchemas);
329
+ this.validators.set(id, { validator, schema });
330
+ return validator;
331
+ }
332
+ /** Runs raw validation against the given schema. Equivalent to
333
+ * `AJV8Validator#rawValidation`: returns ata's error array (already in
334
+ * AJV-compatible shape) plus any compilation error encountered.
335
+ */
336
+ rawValidation(schema, formData) {
337
+ let compilationError;
338
+ let errors;
339
+ try {
340
+ const id = schema[utils.ID_KEY] ?? utils.hashForSchema(schema);
341
+ const validator = this.getOrBuild(id, schema);
342
+ const result = validator.validate(this.cloneForValidation(formData));
343
+ errors = result.valid ? void 0 : result.errors;
344
+ if (errors && typeof this.localizer === "function") {
345
+ this.localizer(errors);
346
+ }
347
+ } catch (err) {
348
+ compilationError = err;
349
+ }
350
+ return {
351
+ errors,
352
+ validationError: compilationError
353
+ };
354
+ }
355
+ /** Validates `formData` and returns RJSF's `ValidationData<T>`. See
356
+ * `processRawValidationErrors` for the shape of the post-processing
357
+ * pipeline (custom validation, transform hook, ui-title resolution).
358
+ */
359
+ validateFormData(formData, schema, customValidate, transformErrors, uiSchema) {
360
+ const rawErrors = this.rawValidation(schema, formData);
361
+ return processRawValidationErrors(
362
+ this,
363
+ rawErrors,
364
+ formData,
365
+ schema,
366
+ customValidate,
367
+ transformErrors,
368
+ uiSchema,
369
+ this.suppressDuplicateFiltering
370
+ );
371
+ }
372
+ /** Registers (or refreshes) the rootSchema in the per-schema registry so
373
+ * subsequent `$ref`-resolving validators can see it. Mirrors AJV's
374
+ * `addSchema(rootSchema, rootSchemaId)` flow.
375
+ */
376
+ handleSchemaUpdate(rootSchema) {
377
+ if (this.lastSeenRootSchema === rootSchema && this.hasRegisteredRootSchema) {
378
+ return;
379
+ }
380
+ const rootSchemaId = rootSchema[utils.ID_KEY] ?? utils.ROOT_SCHEMA_PREFIX;
381
+ const rootWithId = rootSchema[utils.ID_KEY] === rootSchemaId ? rootSchema : { ...rootSchema, [utils.ID_KEY]: rootSchemaId };
382
+ this.cachedRootSchema = rootWithId;
383
+ const cached = this.validators.get(rootSchemaId);
384
+ if (!cached || !utils.deepEquals(cached.schema, rootWithId)) {
385
+ this.getOrBuild(rootSchemaId, rootWithId);
386
+ }
387
+ this.lastSeenRootSchema = rootSchema;
388
+ this.hasRegisteredRootSchema = true;
389
+ }
390
+ /** Boolean validation entrypoint. Returns false on validation failure or
391
+ * compilation error. Mirrors `AJV8Validator#isValid` semantics.
392
+ */
393
+ isValid(schema, formData, rootSchema) {
394
+ try {
395
+ this.handleSchemaUpdate(rootSchema);
396
+ const schemaWithIdRefPrefix = utils.withIdRefPrefix(schema);
397
+ const id = schemaWithIdRefPrefix[utils.ID_KEY] ?? utils.hashForSchema(schemaWithIdRefPrefix);
398
+ const validator = this.getOrBuild(id, schemaWithIdRefPrefix);
399
+ return validator.validate(this.cloneForValidation(formData)).valid;
400
+ } catch (e) {
401
+ console.warn("Error encountered compiling schema:", e);
402
+ return false;
403
+ }
404
+ }
405
+ };
406
+
407
+ // src/customizeValidator.ts
408
+ function customizeValidator(options = {}, localizer) {
409
+ return new ATAValidator(options, localizer);
410
+ }
411
+
412
+ // src/index.ts
413
+ var index_default = customizeValidator();
414
+
415
+ exports.ATAValidator = ATAValidator;
416
+ exports.createPrecompiledValidator = createPrecompiledValidator;
417
+ exports.customizeValidator = customizeValidator;
418
+ exports.default = index_default;
419
+
420
+ Object.defineProperty(exports, '__esModule', { value: true });
421
+
422
+ }));
@@ -0,0 +1,16 @@
1
+ import { RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+ import { compileSchemaValidatorsCode } from './compileSchemaValidatorsCode';
3
+ import { CustomValidatorOptionsType } from './types';
4
+ export { compileSchemaValidatorsCode };
5
+ /** The function used to compile a schema into an output file in the form that allows it to be used as a precompiled
6
+ * validator. The main reasons for using a precompiled validator is reducing code size, improving validation speed and,
7
+ * most importantly, avoiding dynamic code compilation when prohibited by a browser's Content Security Policy. For more
8
+ * information about ata standalone compilation see the ata-validator documentation.
9
+ *
10
+ * @param schema - The schema to be compiled into a set of precompiled validators functions
11
+ * @param output - The name of the file into which the precompiled validator functions will be generated
12
+ * @param [options={}] - The set of `CustomValidatorOptionsType` information used to alter the ata validator used for
13
+ * compiling the schema. They are the same options that are passed to the `customizeValidator()` function in
14
+ * order to modify the behavior of the regular ata-based validator.
15
+ */
16
+ export default function compileSchemaValidators<S extends StrictRJSFSchema = RJSFSchema>(schema: S, output: string, options?: CustomValidatorOptionsType): void;
@@ -0,0 +1,21 @@
1
+ import fs from 'fs';
2
+ import { compileSchemaValidatorsCode } from './compileSchemaValidatorsCode';
3
+ export { compileSchemaValidatorsCode };
4
+ /** The function used to compile a schema into an output file in the form that allows it to be used as a precompiled
5
+ * validator. The main reasons for using a precompiled validator is reducing code size, improving validation speed and,
6
+ * most importantly, avoiding dynamic code compilation when prohibited by a browser's Content Security Policy. For more
7
+ * information about ata standalone compilation see the ata-validator documentation.
8
+ *
9
+ * @param schema - The schema to be compiled into a set of precompiled validators functions
10
+ * @param output - The name of the file into which the precompiled validator functions will be generated
11
+ * @param [options={}] - The set of `CustomValidatorOptionsType` information used to alter the ata validator used for
12
+ * compiling the schema. They are the same options that are passed to the `customizeValidator()` function in
13
+ * order to modify the behavior of the regular ata-based validator.
14
+ */
15
+ export default function compileSchemaValidators(schema, output, options = {}) {
16
+ console.log('parsing the schema');
17
+ const moduleCode = compileSchemaValidatorsCode(schema, options);
18
+ console.log(`writing ${output}`);
19
+ fs.writeFileSync(output, moduleCode);
20
+ }
21
+ //# sourceMappingURL=compileSchemaValidators.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compileSchemaValidators.js","sourceRoot":"","sources":["../src/compileSchemaValidators.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,IAAI,CAAC;AAEpB,OAAO,EAAE,2BAA2B,EAAE,MAAM,+BAA+B,CAAC;AAG5E,OAAO,EAAE,2BAA2B,EAAE,CAAC;AAEvC;;;;;;;;;;GAUG;AACH,MAAM,CAAC,OAAO,UAAU,uBAAuB,CAC7C,MAAS,EACT,MAAc,EACd,UAAsC,EAAE;IAExC,OAAO,CAAC,GAAG,CAAC,oBAAoB,CAAC,CAAC;IAElC,MAAM,UAAU,GAAG,2BAA2B,CAAC,MAAM,EAAE,OAAO,CAAC,CAAC;IAChE,OAAO,CAAC,GAAG,CAAC,WAAW,MAAM,EAAE,CAAC,CAAC;IACjC,EAAE,CAAC,aAAa,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;AACvC,CAAC"}
@@ -0,0 +1,13 @@
1
+ import { RJSFSchema, StrictRJSFSchema } from '@rjsf/utils';
2
+ import { CustomValidatorOptionsType } from './types';
3
+ /** Compiles a schema into a precompiled validator module. ata's
4
+ * `bundleStandalone` emits `module.exports = [fn, ...]`, one validator per
5
+ * schema in order, where each `fn(data)` returns `{ valid, errors }`. This wraps
6
+ * that array into the `{ [id]: (data) => boolean }`-with-`errors` map that
7
+ * `createPrecompiledValidator` consumes, keyed the same way `schemaParser` keys
8
+ * the schemas so the precompiled validator can look each one up.
9
+ *
10
+ * @param schema - The schema to compile
11
+ * @param [options={}] - The `CustomValidatorOptionsType` used to build the validator
12
+ */
13
+ export declare function compileSchemaValidatorsCode<S extends StrictRJSFSchema = RJSFSchema>(schema: S, options?: CustomValidatorOptionsType): string;
@@ -0,0 +1,80 @@
1
+ import { schemaParser } from '@rjsf/utils';
2
+ import { Validator } from 'ata-validator';
3
+ import { COLOR_FORMAT_REGEX, DATA_URL_FORMAT_REGEX } from './createAtaInstance';
4
+ /** Compiles a schema into a precompiled validator module. ata's
5
+ * `bundleStandalone` emits `module.exports = [fn, ...]`, one validator per
6
+ * schema in order, where each `fn(data)` returns `{ valid, errors }`. This wraps
7
+ * that array into the `{ [id]: (data) => boolean }`-with-`errors` map that
8
+ * `createPrecompiledValidator` consumes, keyed the same way `schemaParser` keys
9
+ * the schemas so the precompiled validator can look each one up.
10
+ *
11
+ * @param schema - The schema to compile
12
+ * @param [options={}] - The `CustomValidatorOptionsType` used to build the validator
13
+ */
14
+ export function compileSchemaValidatorsCode(schema, options = {}) {
15
+ const schemaMaps = schemaParser(schema);
16
+ const keys = Object.keys(schemaMaps);
17
+ const schemas = Object.values(schemaMaps);
18
+ const { customFormats, ataOptionsOverrides = {} } = options;
19
+ // Format checkers are serialized into the standalone module via Function#toString,
20
+ // so they must carry no closure references or build-time instrumentation (a plain
21
+ // arrow over the source file picks up coverage counters). Building each from its
22
+ // regex via `new Function` produces a function whose source is exactly its body.
23
+ const regexFormats = {
24
+ color: COLOR_FORMAT_REGEX,
25
+ 'data-url': DATA_URL_FORMAT_REGEX,
26
+ };
27
+ if (customFormats) {
28
+ for (const [name, check] of Object.entries(customFormats)) {
29
+ if (typeof check === 'function') {
30
+ // A function checker would be serialized via toString, which is unsafe in a
31
+ // precompiled bundle: transpilers, minifiers, and coverage tools rewrite the
32
+ // body and leave references that do not exist in the generated module. Only
33
+ // RegExp/string patterns can be embedded reliably here.
34
+ throw new Error(`@rjsf/validator-ata: custom format "${name}" is a function, which is not supported by the precompiled validator; provide a RegExp or string pattern instead`);
35
+ }
36
+ regexFormats[name] = typeof check === 'string' ? new RegExp(check) : check;
37
+ }
38
+ }
39
+ const formats = {};
40
+ for (const [name, re] of Object.entries(regexFormats)) {
41
+ // `new Function` rather than a fat-arrow on purpose: ata serializes these format
42
+ // checkers into the standalone bundle via Function#toString. A fat-arrow would
43
+ // close over `re` and emit `re.test(value)`, leaving `re` undefined in the
44
+ // generated module. Building it from a string inlines the regex literal into the
45
+ // body, so the bundled output stays self-contained.
46
+ // eslint-disable-next-line no-new-func
47
+ formats[name] = new Function('value', `return ${re.toString()}.test(value)`);
48
+ }
49
+ const bundle = Validator.bundleStandalone(schemas, {
50
+ format: 'cjs',
51
+ verbose: ataOptionsOverrides.verbose !== false,
52
+ formats,
53
+ });
54
+ const entries = keys
55
+ .map((key, index) => ` ${JSON.stringify(key)}: wrap(validators[${index}], ${JSON.stringify(key)}),`)
56
+ .join('\n');
57
+ return [
58
+ 'const validators = (function () {',
59
+ ' const module = { exports: {} };',
60
+ bundle,
61
+ ' return module.exports;',
62
+ '})();',
63
+ 'function wrap(fn, key) {',
64
+ ' function validate(data) {',
65
+ " if (typeof fn !== 'function') {",
66
+ " throw new Error('@rjsf/validator-ata: schema \"' + key + '\" was not compiled to a standalone validator');",
67
+ ' }',
68
+ ' const result = fn(data);',
69
+ ' validate.errors = result.valid ? null : result.errors;',
70
+ ' return result.valid;',
71
+ ' }',
72
+ ' return validate;',
73
+ '}',
74
+ 'module.exports = {',
75
+ entries,
76
+ '};',
77
+ '',
78
+ ].join('\n');
79
+ }
80
+ //# sourceMappingURL=compileSchemaValidatorsCode.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"compileSchemaValidatorsCode.js","sourceRoot":"","sources":["../src/compileSchemaValidatorsCode.ts"],"names":[],"mappings":"AAAA,OAAO,EAAgC,YAAY,EAAE,MAAM,aAAa,CAAC;AACzE,OAAO,EAAE,SAAS,EAAE,MAAM,eAAe,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,qBAAqB,EAAE,MAAM,qBAAqB,CAAC;AAGhF;;;;;;;;;GASG;AACH,MAAM,UAAU,2BAA2B,CACzC,MAAS,EACT,UAAsC,EAAE;IAExC,MAAM,UAAU,GAAG,YAAY,CAAC,MAAM,CAAC,CAAC;IACxC,MAAM,IAAI,GAAG,MAAM,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;IACrC,MAAM,OAAO,GAAG,MAAM,CAAC,MAAM,CAAC,UAAU,CAAC,CAAC;IAE1C,MAAM,EAAE,aAAa,EAAE,mBAAmB,GAAG,EAAE,EAAE,GAAG,OAAO,CAAC;IAE5D,mFAAmF;IACnF,kFAAkF;IAClF,iFAAiF;IACjF,iFAAiF;IACjF,MAAM,YAAY,GAA2B;QAC3C,KAAK,EAAE,kBAAkB;QACzB,UAAU,EAAE,qBAAqB;KAClC,CAAC;IACF,IAAI,aAAa,EAAE,CAAC;QAClB,KAAK,MAAM,CAAC,IAAI,EAAE,KAAK,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAa,CAAC,EAAE,CAAC;YAC1D,IAAI,OAAO,KAAK,KAAK,UAAU,EAAE,CAAC;gBAChC,4EAA4E;gBAC5E,6EAA6E;gBAC7E,4EAA4E;gBAC5E,wDAAwD;gBACxD,MAAM,IAAI,KAAK,CACb,uCAAuC,IAAI,kHAAkH,CAC9J,CAAC;YACJ,CAAC;YACD,YAAY,CAAC,IAAI,CAAC,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC;QAC7E,CAAC;IACH,CAAC;IACD,MAAM,OAAO,GAA+C,EAAE,CAAC;IAC/D,KAAK,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,YAAY,CAAC,EAAE,CAAC;QACtD,iFAAiF;QACjF,+EAA+E;QAC/E,2EAA2E;QAC3E,iFAAiF;QACjF,oDAAoD;QACpD,uCAAuC;QACvC,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,QAAQ,CAAC,OAAO,EAAE,UAAU,EAAE,CAAC,QAAQ,EAAE,cAAc,CAA+B,CAAC;IAC7G,CAAC;IAED,MAAM,MAAM,GAAG,SAAS,CAAC,gBAAgB,CAAC,OAAO,EAAE;QACjD,MAAM,EAAE,KAAK;QACb,OAAO,EAAE,mBAAmB,CAAC,OAAO,KAAK,KAAK;QAC9C,OAAO;KACR,CAAC,CAAC;IAEH,MAAM,OAAO,GAAG,IAAI;SACjB,GAAG,CAAC,CAAC,GAAG,EAAE,KAAK,EAAE,EAAE,CAAC,KAAK,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,qBAAqB,KAAK,MAAM,IAAI,CAAC,SAAS,CAAC,GAAG,CAAC,IAAI,CAAC;SACpG,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO;QACL,mCAAmC;QACnC,mCAAmC;QACnC,MAAM;QACN,0BAA0B;QAC1B,OAAO;QACP,0BAA0B;QAC1B,6BAA6B;QAC7B,qCAAqC;QACrC,kHAAkH;QAClH,OAAO;QACP,8BAA8B;QAC9B,4DAA4D;QAC5D,0BAA0B;QAC1B,KAAK;QACL,oBAAoB;QACpB,GAAG;QACH,oBAAoB;QACpB,OAAO;QACP,IAAI;QACJ,EAAE;KACH,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;AACf,CAAC"}
@@ -0,0 +1,27 @@
1
+ import { Validator, type ValidatorOptions } from 'ata-validator';
2
+ import type { CustomValidatorOptionsType } from './types';
3
+ /** Default options applied to every ata `Validator` constructed for RJSF.
4
+ * `verbose: true` keeps `parentSchema` available on errors, which the RJSF
5
+ * error transformer uses to recover field titles. The remainder match
6
+ * `@rjsf/validator-ajv8`'s defaults (`allErrors`-equivalent behavior is
7
+ * ata's default).
8
+ */
9
+ export declare const ATA_CONFIG: ValidatorOptions;
10
+ /** Color names + hex + `rgb()` regex source. Mirrors the pattern shipped by
11
+ * `@rjsf/validator-ajv8` so RJSF schemas using `format: 'color'` keep
12
+ * working when swapped to validator-ata.
13
+ */
14
+ export declare const COLOR_FORMAT_REGEX: RegExp;
15
+ /** RFC 2397 data URL with required mime type and base64 marker, matching
16
+ * the shape used by `@rjsf/validator-ajv8`.
17
+ */
18
+ export declare const DATA_URL_FORMAT_REGEX: RegExp;
19
+ /** Builds a fresh `ata-validator` `Validator` for a given schema with all
20
+ * RJSF-aware defaults and user customizations applied.
21
+ *
22
+ * The factory exists so that the validator class can construct one
23
+ * `Validator` per schema-id (ata is schema-bound, unlike AJV's single
24
+ * instance with a schema registry) while keeping the option translation
25
+ * in one place.
26
+ */
27
+ export default function createAtaInstance(schema: object, options?: CustomValidatorOptionsType): Validator;
@@ -0,0 +1,68 @@
1
+ import { Validator } from 'ata-validator';
2
+ import isObject from 'lodash/isObject';
3
+ /** Default options applied to every ata `Validator` constructed for RJSF.
4
+ * `verbose: true` keeps `parentSchema` available on errors, which the RJSF
5
+ * error transformer uses to recover field titles. The remainder match
6
+ * `@rjsf/validator-ajv8`'s defaults (`allErrors`-equivalent behavior is
7
+ * ata's default).
8
+ */
9
+ export const ATA_CONFIG = {
10
+ verbose: true,
11
+ };
12
+ /** Color names + hex + `rgb()` regex source. Mirrors the pattern shipped by
13
+ * `@rjsf/validator-ajv8` so RJSF schemas using `format: 'color'` keep
14
+ * working when swapped to validator-ata.
15
+ */
16
+ export 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*\)))$/;
17
+ /** RFC 2397 data URL with required mime type and base64 marker, matching
18
+ * the shape used by `@rjsf/validator-ajv8`.
19
+ */
20
+ export const DATA_URL_FORMAT_REGEX = /^data:([a-z]+\/[a-z0-9-+.]+)?;(?:name=(.*);)?base64,(.*)$/;
21
+ /** Coerces the user-supplied custom format value into the `(value: string)
22
+ * => boolean` shape expected by ata. Strings are treated as RegExp source
23
+ * (anchored at both ends if not already), RegExps are converted to a `.test`
24
+ * call, functions pass through.
25
+ */
26
+ function asFormatChecker(spec) {
27
+ if (typeof spec === 'function') {
28
+ return spec;
29
+ }
30
+ const re = spec instanceof RegExp ? spec : new RegExp(spec);
31
+ return (value) => re.test(value);
32
+ }
33
+ /** Builds a fresh `ata-validator` `Validator` for a given schema with all
34
+ * RJSF-aware defaults and user customizations applied.
35
+ *
36
+ * The factory exists so that the validator class can construct one
37
+ * `Validator` per schema-id (ata is schema-bound, unlike AJV's single
38
+ * instance with a schema registry) while keeping the option translation
39
+ * in one place.
40
+ */
41
+ export default function createAtaInstance(schema, options = {}) {
42
+ const { customFormats, ataOptionsOverrides, additionalMetaSchemas, extenderFn } = options;
43
+ const formats = {
44
+ color: asFormatChecker(COLOR_FORMAT_REGEX),
45
+ 'data-url': asFormatChecker(DATA_URL_FORMAT_REGEX),
46
+ };
47
+ if (isObject(customFormats)) {
48
+ for (const [name, spec] of Object.entries(customFormats)) {
49
+ formats[name] = asFormatChecker(spec);
50
+ }
51
+ }
52
+ const validatorOptions = {
53
+ ...ATA_CONFIG,
54
+ ...ataOptionsOverrides,
55
+ formats,
56
+ };
57
+ let validator = new Validator(schema, validatorOptions);
58
+ if (Array.isArray(additionalMetaSchemas)) {
59
+ for (const meta of additionalMetaSchemas) {
60
+ validator.addSchema(meta);
61
+ }
62
+ }
63
+ if (typeof extenderFn === 'function') {
64
+ validator = extenderFn(validator);
65
+ }
66
+ return validator;
67
+ }
68
+ //# sourceMappingURL=createAtaInstance.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"createAtaInstance.js","sourceRoot":"","sources":["../src/createAtaInstance.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAyB,MAAM,eAAe,CAAC;AACjE,OAAO,QAAQ,MAAM,iBAAiB,CAAC;AAIvC;;;;;GAKG;AACH,MAAM,CAAC,MAAM,UAAU,GAAqB;IAC1C,OAAO,EAAE,IAAI;CACL,CAAC;AAEX;;;GAGG;AACH,MAAM,CAAC,MAAM,kBAAkB,GAC7B,4YAA4Y,CAAC;AAE/Y;;GAEG;AACH,MAAM,CAAC,MAAM,qBAAqB,GAAG,2DAA2D,CAAC;AAEjG;;;;GAIG;AACH,SAAS,eAAe,CAAC,IAAwC;IAC/D,IAAI,OAAO,IAAI,KAAK,UAAU,EAAE,CAAC;QAC/B,OAAO,IAAI,CAAC;IACd,CAAC;IACD,MAAM,EAAE,GAAG,IAAI,YAAY,MAAM,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,IAAI,MAAM,CAAC,IAAI,CAAC,CAAC;IAC5D,OAAO,CAAC,KAAa,EAAE,EAAE,CAAC,EAAE,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;AAC3C,CAAC;AAED;;;;;;;GAOG;AACH,MAAM,CAAC,OAAO,UAAU,iBAAiB,CAAC,MAAc,EAAE,UAAsC,EAAE;IAChG,MAAM,EAAE,aAAa,EAAE,mBAAmB,EAAE,qBAAqB,EAAE,UAAU,EAAE,GAAG,OAAO,CAAC;IAE1F,MAAM,OAAO,GAAqC;QAChD,KAAK,EAAE,eAAe,CAAC,kBAAkB,CAAC;QAC1C,UAAU,EAAE,eAAe,CAAC,qBAAqB,CAAC;KACnD,CAAC;IACF,IAAI,QAAQ,CAAC,aAAa,CAAC,EAAE,CAAC;QAC5B,KAAK,MAAM,CAAC,IAAI,EAAE,IAAI,CAAC,IAAI,MAAM,CAAC,OAAO,CAAC,aAAc,CAAC,EAAE,CAAC;YAC1D,OAAO,CAAC,IAAI,CAAC,GAAG,eAAe,CAAC,IAAI,CAAC,CAAC;QACxC,CAAC;IACH,CAAC;IAED,MAAM,gBAAgB,GAAqB;QACzC,GAAG,UAAU;QACb,GAAG,mBAAmB;QACtB,OAAO;KACR,CAAC;IAEF,IAAI,SAAS,GAAG,IAAI,SAAS,CAAC,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAExD,IAAI,KAAK,CAAC,OAAO,CAAC,qBAAqB,CAAC,EAAE,CAAC;QACzC,KAAK,MAAM,IAAI,IAAI,qBAAqB,EAAE,CAAC;YACzC,SAAS,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC;QAC5B,CAAC;IACH,CAAC;IAED,IAAI,OAAO,UAAU,KAAK,UAAU,EAAE,CAAC;QACrC,SAAS,GAAG,UAAU,CAAC,SAAS,CAAC,CAAC;IACpC,CAAC;IAED,OAAO,SAAS,CAAC;AACnB,CAAC"}