| import type { |
| CodeKeywordDefinition, |
| ErrorObject, |
| KeywordErrorDefinition, |
| AnySchema, |
| } from "../../types" |
| import type {KeywordCxt} from "../../compile/validate" |
| import {_, Name} from "../../compile/codegen" |
| import {alwaysValidSchema} from "../../compile/util" |
| import {SchemaCxt} from "../../compile" |
| |
| export type OneOfError = ErrorObject< |
| "oneOf", |
| {passingSchemas: [number, number] | null}, |
| AnySchema[] |
| > |
| |
| const error: KeywordErrorDefinition = { |
| message: "must match exactly one schema in oneOf", |
| params: ({params}) => _`{passingSchemas: ${params.passing}}`, |
| } |
| |
| const def: CodeKeywordDefinition = { |
| keyword: "oneOf", |
| schemaType: "array", |
| trackErrors: true, |
| error, |
| code(cxt: KeywordCxt) { |
| const {gen, schema, parentSchema, it} = cxt |
| /* istanbul ignore if */ |
| if (!Array.isArray(schema)) throw new Error("ajv implementation error") |
| if (it.opts.discriminator && parentSchema.discriminator) return |
| const schArr: AnySchema[] = schema |
| const valid = gen.let("valid", false) |
| const passing = gen.let("passing", null) |
| const schValid = gen.name("_valid") |
| cxt.setParams({passing}) |
| // TODO possibly fail straight away (with warning or exception) if there are two empty always valid schemas |
| |
| gen.block(validateOneOf) |
| |
| cxt.result( |
| valid, |
| () => cxt.reset(), |
| () => cxt.error(true) |
| ) |
| |
| function validateOneOf(): void { |
| schArr.forEach((sch: AnySchema, i: number) => { |
| let schCxt: SchemaCxt | undefined |
| if (alwaysValidSchema(it, sch)) { |
| gen.var(schValid, true) |
| } else { |
| schCxt = cxt.subschema( |
| { |
| keyword: "oneOf", |
| schemaProp: i, |
| compositeRule: true, |
| }, |
| schValid |
| ) |
| } |
| |
| if (i > 0) { |
| gen |
| .if(_`${schValid} && ${valid}`) |
| .assign(valid, false) |
| .assign(passing, _`[${passing}, ${i}]`) |
| .else() |
| } |
| |
| gen.if(schValid, () => { |
| gen.assign(valid, true) |
| gen.assign(passing, i) |
| if (schCxt) cxt.mergeEvaluated(schCxt, Name) |
| }) |
| }) |
| } |
| }, |
| } |
| |
| export default def |