json-schema-library
Version:
Customizable and hackable json-validator and json-schema utilities for traversal, data generation and validation
61 lines (60 loc) • 2.49 kB
JavaScript
import { resolveRef } from "../../keywords/$ref";
import { joinId } from "../../utils/joinId";
import { validateNode } from "../../validateNode";
export const $refKeyword = {
id: "$ref",
keyword: "$ref",
parse: parseRef,
addValidate: ({ schema }) => schema.$ref != null,
validate: validateRef
};
function parseRef(node) {
var _a, _b, _c, _d, _e, _f, _g;
// get and store current $id of node - this may be the same as parent $id
let currentId = (_a = node.parent) === null || _a === void 0 ? void 0 : _a.$id;
if (((_b = node.schema) === null || _b === void 0 ? void 0 : _b.$ref) == null) {
currentId = joinId((_c = node.parent) === null || _c === void 0 ? void 0 : _c.$id, (_d = node.schema) === null || _d === void 0 ? void 0 : _d.$id);
}
node.$id = currentId;
node.lastIdPointer = (_f = (_e = node.parent) === null || _e === void 0 ? void 0 : _e.lastIdPointer) !== null && _f !== void 0 ? _f : "#";
// add ref resolution method to node
node.resolveRef = resolveRef;
// store this node for retrieval by $id
if (node.context.refs[currentId] == null) {
node.context.refs[currentId] = node;
}
const idChanged = currentId !== ((_g = node.parent) === null || _g === void 0 ? void 0 : _g.$id);
if (idChanged) {
node.lastIdPointer = node.evaluationPath;
}
// store this node for retrieval by $id + json-pointer from $id
if (node.lastIdPointer !== "#" && node.evaluationPath.startsWith(node.lastIdPointer)) {
const localPointer = `#${node.evaluationPath.replace(node.lastIdPointer, "")}`;
node.context.refs[joinId(currentId, localPointer)] = node;
}
else {
node.context.refs[joinId(currentId, node.evaluationPath)] = node;
}
node.context.refs[joinId(node.context.rootNode.$id, node.evaluationPath)] = node;
// precompile reference
if (node.schema.$ref) {
node.$ref = joinId(currentId, node.schema.$ref);
}
}
function validateRef({ node, data, pointer = "#", path }) {
const nextNode = resolveAllRefs(node, pointer, path);
if (nextNode == null) {
return undefined;
}
return validateNode(nextNode, data, pointer, path);
}
function resolveAllRefs(node, pointer, path) {
const nextNode = node.resolveRef({ pointer, path });
if (nextNode == null) {
return undefined;
}
if (nextNode !== node && nextNode) {
return resolveAllRefs(nextNode, pointer, path);
}
return node;
}