| "use strict"; |
| Object.defineProperty(exports, "__esModule", { value: true }); |
| const codegen_1 = require("../../compile/codegen"); |
| const types_1 = require("../discriminator/types"); |
| const compile_1 = require("../../compile"); |
| const util_1 = require("../../compile/util"); |
| const error = { |
| message: ({ params: { discrError, tagName } }) => discrError === types_1.DiscrError.Tag |
| ? `tag "${tagName}" must be string` |
| : `value of tag "${tagName}" must be in oneOf`, |
| params: ({ params: { discrError, tag, tagName } }) => (0, codegen_1._) `{error: ${discrError}, tag: ${tagName}, tagValue: ${tag}}`, |
| }; |
| const def = { |
| keyword: "discriminator", |
| type: "object", |
| schemaType: "object", |
| error, |
| code(cxt) { |
| const { gen, data, schema, parentSchema, it } = cxt; |
| const { oneOf } = parentSchema; |
| if (!it.opts.discriminator) { |
| throw new Error("discriminator: requires discriminator option"); |
| } |
| const tagName = schema.propertyName; |
| if (typeof tagName != "string") |
| throw new Error("discriminator: requires propertyName"); |
| if (schema.mapping) |
| throw new Error("discriminator: mapping is not supported"); |
| if (!oneOf) |
| throw new Error("discriminator: requires oneOf keyword"); |
| const valid = gen.let("valid", false); |
| const tag = gen.const("tag", (0, codegen_1._) `${data}${(0, codegen_1.getProperty)(tagName)}`); |
| gen.if((0, codegen_1._) `typeof ${tag} == "string"`, () => validateMapping(), () => cxt.error(false, { discrError: types_1.DiscrError.Tag, tag, tagName })); |
| cxt.ok(valid); |
| function validateMapping() { |
| const mapping = getMapping(); |
| gen.if(false); |
| for (const tagValue in mapping) { |
| gen.elseIf((0, codegen_1._) `${tag} === ${tagValue}`); |
| gen.assign(valid, applyTagSchema(mapping[tagValue])); |
| } |
| gen.else(); |
| cxt.error(false, { discrError: types_1.DiscrError.Mapping, tag, tagName }); |
| gen.endIf(); |
| } |
| function applyTagSchema(schemaProp) { |
| const _valid = gen.name("valid"); |
| const schCxt = cxt.subschema({ keyword: "oneOf", schemaProp }, _valid); |
| cxt.mergeEvaluated(schCxt, codegen_1.Name); |
| return _valid; |
| } |
| function getMapping() { |
| var _a; |
| const oneOfMapping = {}; |
| const topRequired = hasRequired(parentSchema); |
| let tagRequired = true; |
| for (let i = 0; i < oneOf.length; i++) { |
| let sch = oneOf[i]; |
| if ((sch === null || sch === void 0 ? void 0 : sch.$ref) && !(0, util_1.schemaHasRulesButRef)(sch, it.self.RULES)) { |
| sch = compile_1.resolveRef.call(it.self, it.schemaEnv, it.baseId, sch === null || sch === void 0 ? void 0 : sch.$ref); |
| if (sch instanceof compile_1.SchemaEnv) |
| sch = sch.schema; |
| } |
| const propSch = (_a = sch === null || sch === void 0 ? void 0 : sch.properties) === null || _a === void 0 ? void 0 : _a[tagName]; |
| if (typeof propSch != "object") { |
| throw new Error(`discriminator: oneOf subschemas (or referenced schemas) must have "properties/${tagName}"`); |
| } |
| tagRequired = tagRequired && (topRequired || hasRequired(sch)); |
| addMappings(propSch, i); |
| } |
| if (!tagRequired) |
| throw new Error(`discriminator: "${tagName}" must be required`); |
| return oneOfMapping; |
| function hasRequired({ required }) { |
| return Array.isArray(required) && required.includes(tagName); |
| } |
| function addMappings(sch, i) { |
| if (sch.const) { |
| addMapping(sch.const, i); |
| } |
| else if (sch.enum) { |
| for (const tagValue of sch.enum) { |
| addMapping(tagValue, i); |
| } |
| } |
| else { |
| throw new Error(`discriminator: "properties/${tagName}" must have "const" or "enum"`); |
| } |
| } |
| function addMapping(tagValue, i) { |
| if (typeof tagValue != "string" || tagValue in oneOfMapping) { |
| throw new Error(`discriminator: "${tagName}" values must be unique strings`); |
| } |
| oneOfMapping[tagValue] = i; |
| } |
| } |
| }, |
| }; |
| exports.default = def; |
| //# sourceMappingURL=index.js.map |