UNPKG

4.74 kBJavaScriptView Raw
1"use strict";
2Object.defineProperty(exports, "__esModule", { value: true });
3exports.getSchemaRefs = exports.resolveUrl = exports.normalizeId = exports._getFullPath = exports.getFullPath = exports.inlineRef = void 0;
4const util_1 = require("./util");
5const equal = require("fast-deep-equal");
6const traverse = require("json-schema-traverse");
7const URI = require("uri-js");
8// TODO refactor to use keyword definitions
9const SIMPLE_INLINED = new Set([
10 "type",
11 "format",
12 "pattern",
13 "maxLength",
14 "minLength",
15 "maxProperties",
16 "minProperties",
17 "maxItems",
18 "minItems",
19 "maximum",
20 "minimum",
21 "uniqueItems",
22 "multipleOf",
23 "required",
24 "enum",
25 "const",
26]);
27function inlineRef(schema, limit = true) {
28 if (typeof schema == "boolean")
29 return true;
30 if (limit === true)
31 return !hasRef(schema);
32 if (!limit)
33 return false;
34 return countKeys(schema) <= limit;
35}
36exports.inlineRef = inlineRef;
37const REF_KEYWORDS = new Set([
38 "$ref",
39 "$recursiveRef",
40 "$recursiveAnchor",
41 "$dynamicRef",
42 "$dynamicAnchor",
43]);
44function hasRef(schema) {
45 for (const key in schema) {
46 if (REF_KEYWORDS.has(key))
47 return true;
48 const sch = schema[key];
49 if (Array.isArray(sch) && sch.some(hasRef))
50 return true;
51 if (typeof sch == "object" && hasRef(sch))
52 return true;
53 }
54 return false;
55}
56function countKeys(schema) {
57 let count = 0;
58 for (const key in schema) {
59 if (key === "$ref")
60 return Infinity;
61 count++;
62 if (SIMPLE_INLINED.has(key))
63 continue;
64 if (typeof schema[key] == "object") {
65 util_1.eachItem(schema[key], (sch) => (count += countKeys(sch)));
66 }
67 if (count === Infinity)
68 return Infinity;
69 }
70 return count;
71}
72function getFullPath(id = "", normalize) {
73 if (normalize !== false)
74 id = normalizeId(id);
75 const p = URI.parse(id);
76 return _getFullPath(p);
77}
78exports.getFullPath = getFullPath;
79function _getFullPath(p) {
80 return URI.serialize(p).split("#")[0] + "#";
81}
82exports._getFullPath = _getFullPath;
83const TRAILING_SLASH_HASH = /#\/?$/;
84function normalizeId(id) {
85 return id ? id.replace(TRAILING_SLASH_HASH, "") : "";
86}
87exports.normalizeId = normalizeId;
88function resolveUrl(baseId, id) {
89 id = normalizeId(id);
90 return URI.resolve(baseId, id);
91}
92exports.resolveUrl = resolveUrl;
93const ANCHOR = /^[a-z_][-a-z0-9._]*$/i;
94function getSchemaRefs(schema) {
95 if (typeof schema == "boolean")
96 return {};
97 const { schemaId } = this.opts;
98 const schId = normalizeId(schema[schemaId]);
99 const baseIds = { "": schId };
100 const pathPrefix = getFullPath(schId, false);
101 const localRefs = {};
102 const schemaRefs = new Set();
103 traverse(schema, { allKeys: true }, (sch, jsonPtr, _, parentJsonPtr) => {
104 if (parentJsonPtr === undefined)
105 return;
106 const fullPath = pathPrefix + jsonPtr;
107 let baseId = baseIds[parentJsonPtr];
108 if (typeof sch[schemaId] == "string")
109 baseId = addRef.call(this, sch[schemaId]);
110 addAnchor.call(this, sch.$anchor);
111 addAnchor.call(this, sch.$dynamicAnchor);
112 baseIds[jsonPtr] = baseId;
113 function addRef(ref) {
114 ref = normalizeId(baseId ? URI.resolve(baseId, ref) : ref);
115 if (schemaRefs.has(ref))
116 throw ambiguos(ref);
117 schemaRefs.add(ref);
118 let schOrRef = this.refs[ref];
119 if (typeof schOrRef == "string")
120 schOrRef = this.refs[schOrRef];
121 if (typeof schOrRef == "object") {
122 checkAmbiguosRef(sch, schOrRef.schema, ref);
123 }
124 else if (ref !== normalizeId(fullPath)) {
125 if (ref[0] === "#") {
126 checkAmbiguosRef(sch, localRefs[ref], ref);
127 localRefs[ref] = sch;
128 }
129 else {
130 this.refs[ref] = fullPath;
131 }
132 }
133 return ref;
134 }
135 function addAnchor(anchor) {
136 if (typeof anchor == "string") {
137 if (!ANCHOR.test(anchor))
138 throw new Error(`invalid anchor "${anchor}"`);
139 addRef.call(this, `#${anchor}`);
140 }
141 }
142 });
143 return localRefs;
144 function checkAmbiguosRef(sch1, sch2, ref) {
145 if (sch2 !== undefined && !equal(sch1, sch2))
146 throw ambiguos(ref);
147 }
148 function ambiguos(ref) {
149 return new Error(`reference "${ref}" resolves to more than one schema`);
150 }
151}
152exports.getSchemaRefs = getSchemaRefs;
153//# sourceMappingURL=resolve.js.map
\No newline at end of file