123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242 |
- "use strict";
- Object.defineProperty(exports, "__esModule", { value: true });
- exports.resolveSchema = exports.getCompilingSchema = exports.resolveRef = exports.compileSchema = exports.SchemaEnv = void 0;
- const codegen_1 = require("./codegen");
- const validation_error_1 = require("../runtime/validation_error");
- const names_1 = require("./names");
- const resolve_1 = require("./resolve");
- const util_1 = require("./util");
- const validate_1 = require("./validate");
- class SchemaEnv {
- constructor(env) {
- var _a;
- this.refs = {};
- this.dynamicAnchors = {};
- let schema;
- if (typeof env.schema == "object")
- schema = env.schema;
- this.schema = env.schema;
- this.schemaId = env.schemaId;
- this.root = env.root || this;
- 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"]);
- this.schemaPath = env.schemaPath;
- this.localRefs = env.localRefs;
- this.meta = env.meta;
- this.$async = schema === null || schema === void 0 ? void 0 : schema.$async;
- this.refs = {};
- }
- }
- exports.SchemaEnv = SchemaEnv;
- // let codeSize = 0
- // let nodeCount = 0
- // Compiles schema in SchemaEnv
- function compileSchema(sch) {
- // TODO refactor - remove compilations
- const _sch = getCompilingSchema.call(this, sch);
- if (_sch)
- return _sch;
- const rootId = (0, resolve_1.getFullPath)(this.opts.uriResolver, sch.root.baseId); // TODO if getFullPath removed 1 tests fails
- const { es5, lines } = this.opts.code;
- const { ownProperties } = this.opts;
- const gen = new codegen_1.CodeGen(this.scope, { es5, lines, ownProperties });
- let _ValidationError;
- if (sch.$async) {
- _ValidationError = gen.scopeValue("Error", {
- ref: validation_error_1.default,
- code: (0, codegen_1._) `require("ajv/dist/runtime/validation_error").default`,
- });
- }
- const validateName = gen.scopeName("validate");
- sch.validateName = validateName;
- const schemaCxt = {
- gen,
- allErrors: this.opts.allErrors,
- data: names_1.default.data,
- parentData: names_1.default.parentData,
- parentDataProperty: names_1.default.parentDataProperty,
- dataNames: [names_1.default.data],
- dataPathArr: [codegen_1.nil], // TODO can its length be used as dataLevel if nil is removed?
- dataLevel: 0,
- dataTypes: [],
- definedProperties: new Set(),
- topSchemaRef: gen.scopeValue("schema", this.opts.code.source === true
- ? { ref: sch.schema, code: (0, codegen_1.stringify)(sch.schema) }
- : { ref: sch.schema }),
- validateName,
- ValidationError: _ValidationError,
- schema: sch.schema,
- schemaEnv: sch,
- rootId,
- baseId: sch.baseId || rootId,
- schemaPath: codegen_1.nil,
- errSchemaPath: sch.schemaPath || (this.opts.jtd ? "" : "#"),
- errorPath: (0, codegen_1._) `""`,
- opts: this.opts,
- self: this,
- };
- let sourceCode;
- try {
- this._compilations.add(sch);
- (0, validate_1.validateFunctionCode)(schemaCxt);
- gen.optimize(this.opts.code.optimize);
- // gen.optimize(1)
- const validateCode = gen.toString();
- sourceCode = `${gen.scopeRefs(names_1.default.scope)}return ${validateCode}`;
- // console.log((codeSize += sourceCode.length), (nodeCount += gen.nodeCount))
- if (this.opts.code.process)
- sourceCode = this.opts.code.process(sourceCode, sch);
- // console.log("\n\n\n *** \n", sourceCode)
- const makeValidate = new Function(`${names_1.default.self}`, `${names_1.default.scope}`, sourceCode);
- const validate = makeValidate(this, this.scope.get());
- this.scope.value(validateName, { ref: validate });
- validate.errors = null;
- validate.schema = sch.schema;
- validate.schemaEnv = sch;
- if (sch.$async)
- validate.$async = true;
- if (this.opts.code.source === true) {
- validate.source = { validateName, validateCode, scopeValues: gen._values };
- }
- if (this.opts.unevaluated) {
- const { props, items } = schemaCxt;
- validate.evaluated = {
- props: props instanceof codegen_1.Name ? undefined : props,
- items: items instanceof codegen_1.Name ? undefined : items,
- dynamicProps: props instanceof codegen_1.Name,
- dynamicItems: items instanceof codegen_1.Name,
- };
- if (validate.source)
- validate.source.evaluated = (0, codegen_1.stringify)(validate.evaluated);
- }
- sch.validate = validate;
- return sch;
- }
- catch (e) {
- delete sch.validate;
- delete sch.validateName;
- if (sourceCode)
- this.logger.error("Error compiling schema, function code:", sourceCode);
- // console.log("\n\n\n *** \n", sourceCode, this.opts)
- throw e;
- }
- finally {
- this._compilations.delete(sch);
- }
- }
- exports.compileSchema = compileSchema;
- function resolveRef(root, baseId, ref) {
- var _a;
- ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, ref);
- const schOrFunc = root.refs[ref];
- if (schOrFunc)
- return schOrFunc;
- let _sch = resolve.call(this, root, ref);
- if (_sch === undefined) {
- const schema = (_a = root.localRefs) === null || _a === void 0 ? void 0 : _a[ref]; // TODO maybe localRefs should hold SchemaEnv
- const { schemaId } = this.opts;
- if (schema)
- _sch = new SchemaEnv({ schema, schemaId, root, baseId });
- }
- if (_sch === undefined)
- return;
- return (root.refs[ref] = inlineOrCompile.call(this, _sch));
- }
- exports.resolveRef = resolveRef;
- function inlineOrCompile(sch) {
- if ((0, resolve_1.inlineRef)(sch.schema, this.opts.inlineRefs))
- return sch.schema;
- return sch.validate ? sch : compileSchema.call(this, sch);
- }
- // Index of schema compilation in the currently compiled list
- function getCompilingSchema(schEnv) {
- for (const sch of this._compilations) {
- if (sameSchemaEnv(sch, schEnv))
- return sch;
- }
- }
- exports.getCompilingSchema = getCompilingSchema;
- function sameSchemaEnv(s1, s2) {
- return s1.schema === s2.schema && s1.root === s2.root && s1.baseId === s2.baseId;
- }
- // resolve and compile the references ($ref)
- // TODO returns AnySchemaObject (if the schema can be inlined) or validation function
- function resolve(root, // information about the root schema for the current schema
- ref // reference to resolve
- ) {
- let sch;
- while (typeof (sch = this.refs[ref]) == "string")
- ref = sch;
- return sch || this.schemas[ref] || resolveSchema.call(this, root, ref);
- }
- // Resolve schema, its root and baseId
- function resolveSchema(root, // root object with properties schema, refs TODO below SchemaEnv is assigned to it
- ref // reference to resolve
- ) {
- const p = this.opts.uriResolver.parse(ref);
- const refPath = (0, resolve_1._getFullPath)(this.opts.uriResolver, p);
- let baseId = (0, resolve_1.getFullPath)(this.opts.uriResolver, root.baseId, undefined);
- // TODO `Object.keys(root.schema).length > 0` should not be needed - but removing breaks 2 tests
- if (Object.keys(root.schema).length > 0 && refPath === baseId) {
- return getJsonPointer.call(this, p, root);
- }
- const id = (0, resolve_1.normalizeId)(refPath);
- const schOrRef = this.refs[id] || this.schemas[id];
- if (typeof schOrRef == "string") {
- const sch = resolveSchema.call(this, root, schOrRef);
- if (typeof (sch === null || sch === void 0 ? void 0 : sch.schema) !== "object")
- return;
- return getJsonPointer.call(this, p, sch);
- }
- if (typeof (schOrRef === null || schOrRef === void 0 ? void 0 : schOrRef.schema) !== "object")
- return;
- if (!schOrRef.validate)
- compileSchema.call(this, schOrRef);
- if (id === (0, resolve_1.normalizeId)(ref)) {
- const { schema } = schOrRef;
- const { schemaId } = this.opts;
- const schId = schema[schemaId];
- if (schId)
- baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
- return new SchemaEnv({ schema, schemaId, root, baseId });
- }
- return getJsonPointer.call(this, p, schOrRef);
- }
- exports.resolveSchema = resolveSchema;
- const PREVENT_SCOPE_CHANGE = new Set([
- "properties",
- "patternProperties",
- "enum",
- "dependencies",
- "definitions",
- ]);
- function getJsonPointer(parsedRef, { baseId, schema, root }) {
- var _a;
- if (((_a = parsedRef.fragment) === null || _a === void 0 ? void 0 : _a[0]) !== "/")
- return;
- for (const part of parsedRef.fragment.slice(1).split("/")) {
- if (typeof schema === "boolean")
- return;
- const partSchema = schema[(0, util_1.unescapeFragment)(part)];
- if (partSchema === undefined)
- return;
- schema = partSchema;
- // TODO PREVENT_SCOPE_CHANGE could be defined in keyword def?
- const schId = typeof schema === "object" && schema[this.opts.schemaId];
- if (!PREVENT_SCOPE_CHANGE.has(part) && schId) {
- baseId = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schId);
- }
- }
- let env;
- if (typeof schema != "boolean" && schema.$ref && !(0, util_1.schemaHasRulesButRef)(schema, this.RULES)) {
- const $ref = (0, resolve_1.resolveUrl)(this.opts.uriResolver, baseId, schema.$ref);
- env = resolveSchema.call(this, root, $ref);
- }
- // even though resolution failed we need to return SchemaEnv to throw exception
- // so that compileAsync loads missing schema.
- const { schemaId } = this.opts;
- env = env || new SchemaEnv({ schema, schemaId, root, baseId });
- if (env.schema !== env.root.schema)
- return env;
- return undefined;
- }
- //# sourceMappingURL=index.js.map
|