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 const URI = require("uri-js");
15 this.dynamicAnchors = {};
17 if (typeof env.schema == "object")
19 this.schema = env.schema;
20 this.root = env.root || this;
21 this.baseId = (_a = env.baseId) !== null && _a !== void 0 ? _a : resolve_1.normalizeId(schema === null || schema === void 0 ? void 0 : schema.$id);
22 this.schemaPath = env.schemaPath;
23 this.localRefs = env.localRefs;
25 this.$async = schema === null || schema === void 0 ? void 0 : schema.$async;
29 exports.SchemaEnv = SchemaEnv;
32 // Compiles schema in SchemaEnv
33 function compileSchema(sch) {
34 // TODO refactor - remove compilations
35 const _sch = getCompilingSchema.call(this, sch);
38 const rootId = resolve_1.getFullPath(sch.root.baseId); // TODO if getFullPath removed 1 tests fails
39 const { es5, lines } = this.opts.code;
40 const { ownProperties } = this.opts;
41 const gen = new codegen_1.CodeGen(this.scope, { es5, lines, ownProperties });
44 _ValidationError = gen.scopeValue("Error", {
45 ref: validation_error_1.default,
46 code: codegen_1._ `require("ajv/dist/runtime/validation_error").default`,
49 const validateName = gen.scopeName("validate");
50 sch.validateName = validateName;
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],
61 definedProperties: new Set(),
62 topSchemaRef: gen.scopeValue("schema", this.opts.code.source === true
63 ? { ref: sch.schema, code: codegen_1.stringify(sch.schema) }
64 : { ref: sch.schema }),
66 ValidationError: _ValidationError,
70 baseId: sch.baseId || rootId,
71 schemaPath: codegen_1.nil,
72 errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
73 errorPath: codegen_1._ `""`,
79 this._compilations.add(sch);
80 validate_1.validateFunctionCode(schemaCxt);
81 gen.optimize(this.opts.code.optimize);
83 const validateCode = gen.toString();
84 sourceCode = `${gen.scopeRefs(names_1.default.scope)}return ${validateCode}`;
85 // console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
86 if (this.opts.code.process)
87 sourceCode = this.opts.code.process(sourceCode, sch);
88 // console.log("\n\n\n *** \n", sourceCode)
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;
96 validate.$async = true;
97 if (this.opts.code.source === true) {
98 validate.source = { validateName, validateCode, scopeValues: gen._values };
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,
109 validate.source.evaluated = codegen_1.stringify(validate.evaluated);
111 sch.validate = validate;
116 delete sch.validateName;
118 this.logger.error("Error compiling schema, function code:", sourceCode);
119 // console.log("\n\n\n *** \n", sourceCode, this.opts)
123 this._compilations.delete(sch);
126 exports.compileSchema = compileSchema;
127 function resolveRef(root, baseId, ref) {
129 ref = resolve_1.resolveUrl(baseId, ref);
130 const schOrFunc = root.refs[ref];
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]; // TODO maybe localRefs should hold SchemaEnv
137 _sch = new SchemaEnv({ schema, root, baseId });
139 if (_sch === undefined)
141 return (root.refs[ref] = inlineOrCompile.call(this, _sch));
143 exports.resolveRef = resolveRef;
144 function inlineOrCompile(sch) {
145 if (resolve_1.inlineRef(sch.schema, this.opts.inlineRefs))
147 return sch.validate ? sch : compileSchema.call(this, sch);
149 // Index of schema compilation in the currently compiled list
150 function getCompilingSchema(schEnv) {
151 for (const sch of this._compilations) {
152 if (sameSchemaEnv(sch, schEnv))
156 exports.getCompilingSchema = getCompilingSchema;
157 function sameSchemaEnv(s1, s2) {
158 return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
160 // resolve and compile the references ($ref)
161 // TODO returns AnySchemaObject (if the schema can be inlined) or validation function
162 function resolve(root, // information about the root schema for the current schema
163 ref // reference to resolve
166 while (typeof (sch = this.refs[ref]) == "string")
168 return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
170 // Resolve schema, its root and baseId
171 function resolveSchema(root, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
172 ref // reference to resolve
174 const p = URI.parse(ref);
175 const refPath = resolve_1._getFullPath(p);
176 let baseId = resolve_1.getFullPath(root.baseId);
177 // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
178 if (Object.keys(root.schema).length > 0 && refPath === baseId) {
179 return getJsonPointer.call(this, p, root);
181 const id = resolve_1.normalizeId(refPath);
182 const schOrRef = this.refs[id] || this.schemas[id];
183 if (typeof schOrRef == "string") {
184 const sch = resolveSchema.call(this, root, schOrRef);
185 if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
187 return getJsonPointer.call(this, p, sch);
189 if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
191 if (!schOrRef.validate)
192 compileSchema.call(this, schOrRef);
193 if (id === resolve_1.normalizeId(ref)) {
194 const { schema } = schOrRef;
196 baseId = resolve_1.resolveUrl(baseId, schema.$id);
197 return new SchemaEnv({ schema, root, baseId });
199 return getJsonPointer.call(this, p, schOrRef);
201 exports.resolveSchema = resolveSchema;
202 const PREVENT_SCOPE_CHANGE = new Set([
209 function getJsonPointer(parsedRef, { baseId, schema, root }) {
211 if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
213 for (const part of parsedRef.fragment.slice(1).split("/")) {
214 if (typeof schema == "boolean")
216 schema = schema[util_1.unescapeFragment(part)];
217 if (schema === undefined)
219 // TODO PREVENT_SCOPE_CHANGE could be defined in keyword def?
220 if (!PREVENT_SCOPE_CHANGE.has(part) && typeof schema == "object" && schema.$id) {
221 baseId = resolve_1.resolveUrl(baseId, schema.$id);
225 if (typeof schema != "boolean" && schema.$ref && !util_1.schemaHasRulesButRef(schema, this.RULES)) {
226 const $ref = resolve_1.resolveUrl(baseId, schema.$ref);
227 env = resolveSchema.call(this, root, $ref);
229 // even though resolution failed we need to return SchemaEnv to throw exception
230 // so that compileAsync loads missing schema.
231 env = env || new SchemaEnv({ schema, root, baseId });
232 if (env.schema !== env.root.schema)
236 //# sourceMappingURL=index.js.map