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
JavaScript
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