json-schema-migrate-x
Version:
Migrate JSON-Schema `draft-04` to `draft-07`, `draft-2019-09` or `draft-2020-12`
158 lines • 6.45 kB
JavaScript
import { Ajv2019 } from 'ajv/dist/2019.js';
import { Ajv2020 } from 'ajv/dist/2020.js';
import { constantResultSchema, metaSchema } from './common.js';
const ajvCache = {};
export function getAjv(version = 'draft2019') {
const isDraft2020 = version === 'draft2020';
const cacheKey = isDraft2020 ? 'draft2020' : 'default';
let ajv = ajvCache[cacheKey];
if (ajv) {
return ajv;
}
ajv = new (isDraft2020 ? Ajv2020 : Ajv2019)({ allErrors: true });
ajv.addKeyword({
keyword: 'migrateSchema',
schemaType: 'string',
modifying: true,
metaSchema: { enum: ['draft7', 'draft2019', 'draft2020'] },
validate(version, schema, _parentSchema, dataCxt) {
if (typeof schema != 'object') {
return true;
}
if (dataCxt) {
const { parentData, parentDataProperty } = dataCxt;
const valid = constantResultSchema(schema);
if (typeof valid == 'boolean') {
parentData[parentDataProperty] = valid;
return true;
}
}
const dsCopy = { ...schema };
for (const key in dsCopy) {
delete schema[key];
switch (key) {
case 'id': {
const { id } = dsCopy;
if (typeof id !== 'string') {
throw new TypeError(`json-schema-migrate: schema id must be string`);
}
if ((version === 'draft2019' || isDraft2020) && id.includes('#')) {
const [$id, $anchor, ...rest] = id.split('#');
if (rest.length > 0) {
throw new Error(`json-schema-migrate: invalid schema id ${id}`);
}
if ($id) {
schema.$id = $id;
}
if ($anchor && $anchor !== '/') {
schema.$anchor = $anchor;
}
}
else {
schema.$id = id;
}
break;
}
case '$schema': {
schema.$schema = metaSchema(version);
break;
}
case 'constant': {
schema.const = dsCopy.constant;
break;
}
case 'enum': {
if (Array.isArray(dsCopy.enum) &&
dsCopy.enum.length === 1 &&
dsCopy.constant === undefined &&
dsCopy.const === undefined) {
schema.const = dsCopy.enum[0];
}
else {
schema.enum = dsCopy.enum;
}
break;
}
case 'exclusiveMaximum': {
migrateExclusive(schema, key, 'maximum');
break;
}
case 'exclusiveMinimum': {
migrateExclusive(schema, key, 'minimum');
break;
}
case 'maximum': {
if (dsCopy.exclusiveMaximum !== true) {
schema.maximum = dsCopy.maximum;
}
break;
}
case 'minimum': {
if (dsCopy.exclusiveMinimum !== true) {
schema.minimum = dsCopy.minimum;
}
break;
}
case 'dependencies': {
const deps = dsCopy.dependencies;
if (version === 'draft7') {
schema.dependencies = deps;
}
else {
for (const prop in deps) {
const kwd = Array.isArray(deps[prop])
? 'dependentRequired'
: 'dependentSchemas';
schema[kwd] ||= {};
schema[kwd][prop] = deps[prop];
}
}
break;
}
case 'items': {
if (isDraft2020 && Array.isArray(dsCopy.items)) {
schema.prefixItems = dsCopy.items;
if (dsCopy.additionalItems !== undefined) {
schema.items = dsCopy.additionalItems;
}
}
else {
schema.items = dsCopy.items;
}
break;
}
case 'additionalItems': {
if (!isDraft2020) {
schema.additionalItems = dsCopy.additionalItems;
}
break;
}
case '$recursiveAnchor': {
if (isDraft2020) {
schema.$dynamicAnchor = 'meta';
}
else {
schema.$recursiveAnchor = dsCopy.$recursiveAnchor;
}
break;
}
default: {
schema[key] = dsCopy[key];
}
}
}
return true;
function migrateExclusive(schema, key, limit) {
if (dsCopy[key] === true) {
schema[key] = dsCopy[limit];
}
else if (dsCopy[key] !== false && dsCopy[key] !== undefined) {
ajv.logger.warn(`${key} is not boolean`);
}
}
},
});
ajvCache[cacheKey] = ajv;
return ajv;
}
//# sourceMappingURL=ajv.js.map