UNPKG

json-schema-describes-subset

Version:

Tools for static JSON schema analysis, including functions to determine if one schema describes a subset of another or if a schema describes the empty set or to convert a schema to its disjunctive normal form (DNF).

69 lines 2.75 kB
import { AllOfSchema, AtomicSchemaObject, NotSchema, } from '../atomic-schema/index.js'; import { UnsupportedKeywordError } from '../unsupported-keyword-error/unsupported-keyword-error.js'; export const internalRefKey = Symbol('internalRefKey'); export class RefAtomicSchemaBase extends AtomicSchemaObject { [internalRefKey]; constructor($ref) { super(); /* This might throw. If the `$ref` is relative, there needs to be a valid * `baseURI` */ this[internalRefKey] = new URL($ref).href; } negate() { return new NotSchema(this); } } export class RefAtomicSchema extends RefAtomicSchemaBase { get $ref() { return this[internalRefKey]; } toJSONSchema() { return { $ref: this.$ref }; } } export const refExtraction = { extract: ({ schema: { $ref, $dynamicRef, $dynamicAnchor } }) => { if ($dynamicAnchor !== undefined) { /* `$dynamicAnchor` might change how a referenced schema resource is * evaluated => throw immediately */ throw new UnsupportedKeywordError('$dynamicAnchor', $dynamicAnchor); } if ($dynamicRef !== undefined) { /* `$dynamicRef` might change how a referenced schema resource is * evaluated => throw immediately */ throw new UnsupportedKeywordError('$dynamicRef', $dynamicRef); } const schemas = []; if (typeof $ref === 'string') { /* For the moment a simple comparison of non relative `$ref`s is sufficient. * In future versions this might be optimized here with special caution on * circular references. */ schemas.push(new RefAtomicSchema($ref)); } if (schemas.length === 0) { return true; } return new AllOfSchema(schemas); }, }; export const refSimplification = { appliesToJSONSchemaType: undefined, mergeableKeywords: [], simplify({ atomicSchemasByConstructor, negatedAtomicSchemasByConstructor, }) { const refAtomicSchemas = atomicSchemasByConstructor.get(RefAtomicSchema); const negatedRefAtomicSchemas = negatedAtomicSchemasByConstructor.get(RefAtomicSchema); for (const { $ref } of refAtomicSchemas) { if (negatedRefAtomicSchemas.some((negatedSchema) => negatedSchema.$ref === $ref)) { return false; } } const allOf = [ ...refAtomicSchemas.map((schema) => schema.toJSONSchema()), ...negatedRefAtomicSchemas.map((schema) => ({ not: schema.toJSONSchema(), })), ]; return allOf.length > 0 ? { allOf } : {}; }, }; //# sourceMappingURL=ref.js.map