json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
54 lines (53 loc) • 1.73 kB
JavaScript
import { isSchemaNode } from "./schemaNode";
// 1. https://json-schema.org/draft/2019-09/json-schema-core#scopes
function resolveRecursiveRef(node) {
const history = node.path;
// console.log(...history);
// RESTRICT BY CHANGE IN BASE-URL
let startIndex = 0;
for (let i = history.length - 1; i >= 0; i--) {
const step = history[i][1];
if (step.$id && /^https?:\/\//.test(step.$id) && step.$recursiveAnchor !== true) {
startIndex = i;
break;
}
}
// FROM THERE FIND FIRST OCCURENCE OF ANCHOR
const firstAnchor = history.find((s, index) => index >= startIndex && s[1].$recursiveAnchor === true);
if (firstAnchor) {
return node.next(firstAnchor[1]);
}
// THEN RETURN LATEST BASE AS TARGET
for (let i = history.length - 1; i >= 0; i--) {
const step = history[i][1];
if (step.$id) {
return node.next(step);
}
}
// OR RETURN ROOT
return node.next(node.draft.rootSchema);
}
/**
* @todo update types
* Note: JsonSchema my be false
*/
export default function resolveRef(node) {
if (!isSchemaNode(node)) {
throw new Error("expected node");
}
if (node.schema == null) {
return node;
}
if (node.schema.$recursiveRef) {
return resolveRef(resolveRecursiveRef(node));
}
if (node.schema.$ref == null) {
return node;
}
const resolvedSchema = node.draft.rootSchema.getRef(node.schema);
if (resolvedSchema === false) {
return node.next(resolvedSchema);
}
// @draft >= 2019-09 we now merge schemas: in draft <= 7 $ref is treated as reference, not as schema
return node.merge(resolvedSchema, "$ref");
}