| import Ajv, { type ValidateFunction, type ErrorObject, type SchemaObject } from 'ajv' | |
| import addErrors from 'ajv-errors' | |
| import addFormats from 'ajv-formats' | |
| import semver from 'semver' | |
| const ajv = new Ajv({ allErrors: true, allowUnionTypes: true }) | |
| addFormats(ajv) | |
| addErrors(ajv) | |
| // Custom JSON keywords | |
| ajv.addKeyword({ | |
| keyword: 'translatable', | |
| }) | |
| // Schemas can contain the custom keyword `lintable` to define | |
| // a property as a Markdown string that can be linted by the | |
| // content linter. | |
| // The custom keyword does not define a custom validator function. | |
| // This allows the custom keyword to be present in a schema but | |
| // doesn't perform additional validation other than type checking. | |
| ajv.addKeyword({ | |
| keyword: 'lintable', | |
| type: 'string', | |
| }) | |
| // Custom JSON formats | |
| ajv.addFormat('semver', { | |
| validate: (x: string): boolean => semver.validRange(x) !== null, | |
| }) | |
| // The ajv.validate function is supposed to cache | |
| // the compiled schema, but the documentation says | |
| // that the best performance is achieved by calling | |
| // the compile function and then calling validate. | |
| // So when the same schema is validated multiple times, | |
| // this is the best function to use. If the schema | |
| // changes from one call to the next, then the validateJson | |
| // function makes more sense to use. | |
| export function getJsonValidator(schema: SchemaObject): ValidateFunction { | |
| return ajv.compile(schema) | |
| } | |
| // The next call to ajv.validate will overwrite | |
| // the ajv.errors property, so returning it here | |
| // ensures that it remains accessible. | |
| export function validateJson( | |
| schema: SchemaObject, | |
| data: unknown, | |
| ): { | |
| isValid: boolean | |
| errors: ErrorObject[] | null | |
| } { | |
| const isValid = ajv.validate(schema, data) | |
| return { | |
| isValid, | |
| errors: isValid ? null : structuredClone(ajv.errors || []), | |
| } | |
| } | |
| export default ajv | |