1 | "use strict";
|
2 | Object.defineProperty(exports, "__esModule", { value: true });
|
3 | exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = void 0;
|
4 | const codegen_1 = require("./codegen");
|
5 | const validation_error_1 = require("../runtime/validation_error");
|
6 | const names_1 = require("./names");
|
7 | const resolve_1 = require("./resolve");
|
8 | const util_1 = require("./util");
|
9 | const validate_1 = require("./validate");
|
10 | class SchemaEnv {
|
11 | constructor(env) {
|
12 | var _a;
|
13 | this.refs = {};
|
14 | this.dynamicAnchors = {};
|
15 | let schema;
|
16 | if (typeof env.schema == "object")
|
17 | schema = env.schema;
|
18 | this.schema = env.schema;
|
19 | this.schemaId = env.schemaId;
|
20 | this.root = env.root || this;
|
21 | this.baseId = (_a = env.baseId) !== null && _a !== void 0 ? _a : (0, resolve_1.normalizeId)(schema === null || schema === void 0 ? void 0 : schema[env.schemaId || "$id"]);
|
22 | this.schemaPath = env.schemaPath;
|
23 | this.localRefs = env.localRefs;
|
24 | this.meta = env.meta;
|
25 | this.$async = schema === null || schema === void 0 ? void 0 : schema.$async;
|
26 | this.refs = {};
|
27 | }
|
28 | }
|
29 | exports.SchemaEnv = SchemaEnv;
|
30 |
|
31 |
|
32 |
|
33 | function compileSchema(sch) {
|
34 |
|
35 | const _sch = getCompilingSchema.call(this, sch);
|
36 | if (_sch)
|
37 | return _sch;
|
38 | const rootId = (0, resolve_1.getFullPath)(this.opts.uriResolver, sch.root.baseId);
|
39 | const { es5, lines } = this.opts.code;
|
40 | const { ownProperties } = this.opts;
|
41 | const gen = new codegen_1.CodeGen(this.scope, { es5, lines, ownProperties });
|
42 | let _ValidationError;
|
43 | if (sch.$async) {
|
44 | _ValidationError = gen.scopeValue("Error", {
|
45 | ref: validation_error_1.default,
|
46 | code: (0, codegen_1._) `require("ajv/dist/runtime/validation_error").default`,
|
47 | });
|
48 | }
|
49 | const validateName = gen.scopeName("validate");
|
50 | sch.validateName = validateName;
|
51 | const schemaCxt = {
|
52 | gen,
|
53 | allErrors: this.opts.allErrors,
|
54 | data: names_1.default.data,
|
55 | parentData: names_1.default.parentData,
|
56 | parentDataProperty: names_1.default.parentDataProperty,
|
57 | dataNames: [names_1.default.data],
|
58 | dataPathArr: [codegen_1.nil],
|
59 | dataLevel: 0,
|
60 | dataTypes: [],
|
61 | definedProperties: new Set(),
|
62 | topSchemaRef: gen.scopeValue("schema", this.opts.code.source === true
|
63 | ? { ref: sch.schema, code: (0, codegen_1.stringify)(sch.schema) }
|
64 | : { ref: sch.schema }),
|
65 | validateName,
|
66 | ValidationError: _ValidationError,
|
67 | schema: sch.schema,
|
68 | schemaEnv: sch,
|
69 | rootId,
|
70 | baseId: sch.baseId || rootId,
|
71 | schemaPath: codegen_1.nil,
|
72 | errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
|
73 | errorPath: (0, codegen_1._) `""`,
|
74 | opts: this.opts,
|
75 | self: this,
|
76 | };
|
77 | let sourceCode;
|
78 | try {
|
79 | this._compilations.add(sch);
|
80 | (0, validate_1.validateFunctionCode)(schemaCxt);
|
81 | gen.optimize(this.opts.code.optimize);
|
82 |
|
83 | const validateCode = gen.toString();
|
84 | sourceCode = `${gen.scopeRefs(names_1.default.scope)}return ${validateCode}`;
|
85 |
|
86 | if (this.opts.code.process)
|
87 | sourceCode = this.opts.code.process(sourceCode, sch);
|
88 |
|
89 | const makeValidate = new Function(`${names_1.default.self}`, `${names_1.default.scope}`, sourceCode);
|
90 | const validate = makeValidate(this, this.scope.get());
|
91 | this.scope.value(validateName, { ref: validate });
|
92 | validate.errors = null;
|
93 | validate.schema = sch.schema;
|
94 | validate.schemaEnv = sch;
|
95 | if (sch.$async)
|
96 | validate.$async = true;
|
97 | if (this.opts.code.source === true) {
|
98 | validate.source = { validateName, validateCode, scopeValues: gen._values };
|
99 | }
|
100 | if (this.opts.unevaluated) {
|
101 | const { props, items } = schemaCxt;
|
102 | validate.evaluated = {
|
103 | props: props instanceof codegen_1.Name ? undefined : props,
|
104 | items: items instanceof codegen_1.Name ? undefined : items,
|
105 | dynamicProps: props instanceof codegen_1.Name,
|
106 | dynamicItems: items instanceof codegen_1.Name,
|
107 | };
|
108 | if (validate.source)
|
109 | validate.source.evaluated = (0, codegen_1.stringify)(validate.evaluated);
|
110 | }
|
111 | sch.validate = validate;
|
112 | return sch;
|
113 | }
|
114 | catch (e) {
|
115 | delete sch.validate;
|
116 | delete sch.validateName;
|
117 | if (sourceCode)
|
118 | this.logger.error("Error compiling schema, function code:", sourceCode);
|
119 |
|
120 | throw e;
|
121 | }
|
122 | finally {
|
123 | this._compilations.delete(sch);
|
124 | }
|
125 | }
|
126 | exports.compileSchema = compileSchema;
|
127 | function resolveRef(root, baseId, ref) {
|
128 | var _a;
|
129 | ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
|
130 | const schOrFunc = root.refs[ref];
|
131 | if (schOrFunc)
|
132 | return schOrFunc;
|
133 | let _sch = resolve.call(this, root, ref);
|
134 | if (_sch === undefined) {
|
135 | const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref];
|
136 | const { schemaId } = this.opts;
|
137 | if (schema)
|
138 | _sch = new SchemaEnv({ schema, schemaId, root, baseId });
|
139 | }
|
140 | if (_sch === undefined)
|
141 | return;
|
142 | return (root.refs[ref] = inlineOrCompile.call(this, _sch));
|
143 | }
|
144 | exports.resolveRef = resolveRef;
|
145 | function inlineOrCompile(sch) {
|
146 | if ((0, resolve_1.inlineRef)(sch.schema, this.opts.inlineRefs))
|
147 | return sch.schema;
|
148 | return sch.validate ? sch : compileSchema.call(this, sch);
|
149 | }
|
150 |
|
151 | function getCompilingSchema(schEnv) {
|
152 | for (const sch of this._compilations) {
|
153 | if (sameSchemaEnv(sch, schEnv))
|
154 | return sch;
|
155 | }
|
156 | }
|
157 | exports.getCompilingSchema = getCompilingSchema;
|
158 | function sameSchemaEnv(s1, s2) {
|
159 | return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
|
160 | }
|
161 |
|
162 |
|
163 | function resolve(root, // information about the root schema for the current schema
|
164 | ref // reference to resolve
|
165 | ) {
|
166 | let sch;
|
167 | while (typeof (sch = this.refs[ref]) == "string")
|
168 | ref = sch;
|
169 | return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
|
170 | }
|
171 |
|
172 | function resolveSchema(root, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
|
173 | ref // reference to resolve
|
174 | ) {
|
175 | const p = this.opts.uriResolver.parse(ref);
|
176 | const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
|
177 | let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, undefined);
|
178 |
|
179 | if (Object.keys(root.schema).length > 0 && refPath === baseId) {
|
180 | return getJsonPointer.call(this, p, root);
|
181 | }
|
182 | const id = (0, resolve_1.normalizeId)(refPath);
|
183 | const schOrRef = this.refs[id] || this.schemas[id];
|
184 | if (typeof schOrRef == "string") {
|
185 | const sch = resolveSchema.call(this, root, schOrRef);
|
186 | if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
|
187 | return;
|
188 | return getJsonPointer.call(this, p, sch);
|
189 | }
|
190 | if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
|
191 | return;
|
192 | if (!schOrRef.validate)
|
193 | compileSchema.call(this, schOrRef);
|
194 | if (id === (0, resolve_1.normalizeId)(ref)) {
|
195 | const { schema } = schOrRef;
|
196 | const { schemaId } = this.opts;
|
197 | const schId = schema[schemaId];
|
198 | if (schId)
|
199 | baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
|
200 | return new SchemaEnv({ schema, schemaId, root, baseId });
|
201 | }
|
202 | return getJsonPointer.call(this, p, schOrRef);
|
203 | }
|
204 | exports.resolveSchema = resolveSchema;
|
205 | const PREVENT_SCOPE_CHANGE = new Set([
|
206 | "properties",
|
207 | "patternProperties",
|
208 | "enum",
|
209 | "dependencies",
|
210 | "definitions",
|
211 | ]);
|
212 | function getJsonPointer(parsedRef, { baseId, schema, root }) {
|
213 | var _a;
|
214 | if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
|
215 | return;
|
216 | for (const part of parsedRef.fragment.slice(1).split("/")) {
|
217 | if (typeof schema === "boolean")
|
218 | return;
|
219 | const partSchema = schema[(0, util_1.unescapeFragment)(part)];
|
220 | if (partSchema === undefined)
|
221 | return;
|
222 | schema = partSchema;
|
223 |
|
224 | const schId = typeof schema === "object" && schema[this.opts.schemaId];
|
225 | if (!PREVENT_SCOPE_CHANGE.has(part) && schId) {
|
226 | baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
|
227 | }
|
228 | }
|
229 | let env;
|
230 | if (typeof schema != "boolean" && schema.$ref && !(0, util_1.schemaHasRulesButRef)(schema, this.RULES)) {
|
231 | const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
|
232 | env = resolveSchema.call(this, root, $ref);
|
233 | }
|
234 |
|
235 |
|
236 | const { schemaId } = this.opts;
|
237 | env = env || new SchemaEnv({ schema, schemaId, root, baseId });
|
238 | if (env.schema !== env.root.schema)
|
239 | return env;
|
240 | return undefined;
|
241 | }
|
242 |
|
\ | No newline at end of file |