@canard/schema-form-ajv8-plugin
Version:
AJV 8.x validator plugin for @canard/schema-form providing JSON Schema validation with latest Draft 2020-12 and Draft 2019-09 support
73 lines (67 loc) • 2.02 kB
JavaScript
import Ajv from 'ajv';
const JSON_POINTER_SEPARATOR = '/';
const transformErrors = (errors) => {
if (!Array.isArray(errors))
return [];
const result = new Array(errors.length);
for (let i = 0, l = errors.length; i < l; i++) {
const ajvError = errors[i];
result[i] = {
dataPath: transformDataPath(ajvError),
schemaPath: ajvError.schemaPath,
keyword: ajvError.keyword,
message: ajvError.message,
details: ajvError.params,
source: ajvError,
};
}
return result;
};
const transformDataPath = (error) => {
const instancePath = error.instancePath;
const missingProperty = error.params?.missingProperty;
const hasMissingProperty = error.keyword === 'required' && missingProperty;
if (instancePath)
return hasMissingProperty
? instancePath + JSON_POINTER_SEPARATOR + missingProperty
: instancePath;
else
return hasMissingProperty
? JSON_POINTER_SEPARATOR + missingProperty
: JSON_POINTER_SEPARATOR;
};
const createValidatorFactory = (ajv) => (jsonSchema) => {
const validate = ajv.compile({
...jsonSchema,
$async: true,
});
return async (data) => {
try {
await validate(data);
return null;
}
catch (thrown) {
if (Array.isArray(thrown?.errors))
return transformErrors(thrown.errors);
throw thrown;
}
};
};
const defaultSettings = {
allErrors: true,
strictSchema: false,
validateFormats: false,
};
let ajvInstance = null;
const ajvValidatorPlugin = {
bind: (instance) => (ajvInstance = instance),
compile: (jsonSchema) => {
if (!ajvInstance)
ajvInstance = new Ajv(defaultSettings);
return createValidatorFactory(ajvInstance)(jsonSchema);
},
};
const plugin = {
validator: ajvValidatorPlugin,
};
export { createValidatorFactory, plugin };