"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.getData = void 0; const dataType_1 = require("./validate/dataType"); const util_1 = require("./util"); const errors_1 = require("./errors"); const codegen_1 = require("./codegen"); const names_1 = require("./names"); const subschema_1 = require("./subschema"); class KeywordCxt { constructor(it, def, keyword) { validateKeywordUsage(it, def, keyword); this.gen = it.gen; this.allErrors = it.allErrors; this.keyword = keyword; this.data = it.data; this.schema = it.schema[keyword]; this.$data = def.$data && it.opts.$data && this.schema && this.schema.$data; this.schemaValue = util_1.schemaRefOrVal(it, this.schema, keyword, this.$data); this.schemaType = def.schemaType; this.parentSchema = it.schema; this.params = {}; this.it = it; this.def = def; if (this.$data) { this.schemaCode = it.gen.const("vSchema", getData(this.$data, it)); } else { this.schemaCode = this.schemaValue; if (!validSchemaType(this.schema, def.schemaType, def.allowUndefined)) { throw new Error(`${keyword} value must be ${JSON.stringify(def.schemaType)}`); } } if ("code" in def ? def.trackErrors : def.errors !== false) { this.errsCount = it.gen.const("_errs", names_1.default.errors); } } result(condition, successAction, failAction) { this.gen.if(codegen_1.not(condition)); if (failAction) failAction(); else this.error(); if (successAction) { this.gen.else(); successAction(); if (this.allErrors) this.gen.endIf(); } else { if (this.allErrors) this.gen.endIf(); else this.gen.else(); } } pass(condition, failAction) { this.result(condition, undefined, failAction); } fail(condition) { if (condition === undefined) { this.error(); if (!this.allErrors) this.gen.if(false); // this branch will be removed by gen.optimize return; } this.gen.if(condition); this.error(); if (this.allErrors) this.gen.endIf(); else this.gen.else(); } fail$data(condition) { if (!this.$data) return this.fail(condition); const { schemaCode } = this; this.fail(codegen_1._ `${schemaCode} !== undefined && (${codegen_1.or(this.invalid$data(), condition)})`); } error(append) { ; (append ? errors_1.reportExtraError : errors_1.reportError)(this, this.def.error); } $dataError() { errors_1.reportError(this, this.def.$dataError || errors_1.keyword$DataError); } reset() { if (this.errsCount === undefined) throw new Error('add "trackErrors" to keyword definition'); errors_1.resetErrorsCount(this.gen, this.errsCount); } ok(cond) { if (!this.allErrors) this.gen.if(cond); } setParams(obj, assign) { if (assign) Object.assign(this.params, obj); else this.params = obj; } block$data(valid, codeBlock, $dataValid = codegen_1.nil) { this.gen.block(() => { this.check$data(valid, $dataValid); codeBlock(); }); } check$data(valid = codegen_1.nil, $dataValid = codegen_1.nil) { if (!this.$data) return; const { gen, schemaCode, schemaType, def } = this; gen.if(codegen_1.or(codegen_1._ `${schemaCode} === undefined`, $dataValid)); if (valid !== codegen_1.nil) gen.assign(valid, true); if (schemaType.length || def.validateSchema) { gen.elseIf(this.invalid$data()); this.$dataError(); if (valid !== codegen_1.nil) gen.assign(valid, false); } gen.else(); } invalid$data() { const { gen, schemaCode, schemaType, def, it } = this; return codegen_1.or(wrong$DataType(), invalid$DataSchema()); function wrong$DataType() { if (schemaType.length) { /* istanbul ignore if */ if (!(schemaCode instanceof codegen_1.Name)) throw new Error("ajv implementation error"); const st = Array.isArray(schemaType) ? schemaType : [schemaType]; return codegen_1._ `${dataType_1.checkDataTypes(st, schemaCode, it.opts.strict, dataType_1.DataType.Wrong)}`; } return codegen_1.nil; } function invalid$DataSchema() { if (def.validateSchema) { const validateSchemaRef = gen.scopeValue("validate$data", { ref: def.validateSchema }); // TODO value.code for standalone return codegen_1._ `!${validateSchemaRef}(${schemaCode})`; } return codegen_1.nil; } } subschema(appl, valid) { return subschema_1.applySubschema(this.it, appl, valid); } mergeEvaluated(schemaCxt, toName) { const { it, gen } = this; if (!it.opts.unevaluated) return; if (it.props !== true && schemaCxt.props !== undefined) { it.props = util_1.mergeEvaluated.props(gen, schemaCxt.props, it.props, toName); } if (it.items !== true && schemaCxt.items !== undefined) { it.items = util_1.mergeEvaluated.items(gen, schemaCxt.items, it.items, toName); } } mergeValidEvaluated(schemaCxt, valid) { const { it, gen } = this; if (it.opts.unevaluated && (it.props !== true || it.items !== true)) { gen.if(valid, () => this.mergeEvaluated(schemaCxt, codegen_1.Name)); return true; } } } exports.default = KeywordCxt; function validSchemaType(schema, schemaType, allowUndefined = false) { // TODO add tests return (!schemaType.length || schemaType.some((st) => st === "array" ? Array.isArray(schema) : st === "object" ? schema && typeof schema == "object" && !Array.isArray(schema) : typeof schema == st || (allowUndefined && typeof schema == "undefined"))); } function validateKeywordUsage({ schema, opts, self }, def, keyword) { /* istanbul ignore if */ if (Array.isArray(def.keyword) ? !def.keyword.includes(keyword) : def.keyword !== keyword) { throw new Error("ajv implementation error"); } const deps = def.dependencies; if (deps === null || deps === void 0 ? void 0 : deps.some((kwd) => !Object.prototype.hasOwnProperty.call(schema, kwd))) { throw new Error(`parent schema must have dependencies of ${keyword}: ${deps.join(",")}`); } if (def.validateSchema) { const valid = def.validateSchema(schema[keyword]); if (!valid) { const msg = "keyword value is invalid: " + self.errorsText(def.validateSchema.errors); if (opts.validateSchema === "log") self.logger.error(msg); else throw new Error(msg); } } } const JSON_POINTER = /^\/(?:[^~]|~0|~1)*$/; const RELATIVE_JSON_POINTER = /^([0-9]+)(#|\/(?:[^~]|~0|~1)*)?$/; function getData($data, { dataLevel, dataNames, dataPathArr }) { let jsonPointer; let data; if ($data === "") return names_1.default.rootData; if ($data[0] === "/") { if (!JSON_POINTER.test($data)) throw new Error(`Invalid JSON-pointer: ${$data}`); jsonPointer = $data; data = names_1.default.rootData; } else { const matches = RELATIVE_JSON_POINTER.exec($data); if (!matches) throw new Error(`Invalid JSON-pointer: ${$data}`); const up = +matches[1]; jsonPointer = matches[2]; if (jsonPointer === "#") { if (up >= dataLevel) throw new Error(errorMsg("property/index", up)); return dataPathArr[dataLevel - up]; } if (up > dataLevel) throw new Error(errorMsg("data", up)); data = dataNames[dataLevel - up]; if (!jsonPointer) return data; } let expr = data; const segments = jsonPointer.split("/"); for (const segment of segments) { if (segment) { data = codegen_1._ `${data}${codegen_1.getProperty(util_1.unescapeJsonPointer(segment))}`; expr = codegen_1._ `${expr} && ${data}`; } } return expr; function errorMsg(pointerType, up) { return `Cannot access ${pointerType} ${up} levels up, current level is ${dataLevel}`; } } exports.getData = getData; //# sourceMappingURL=context.js.map