You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					83 lines
				
				2.1 KiB
			
		
		
			
		
	
	
					83 lines
				
				2.1 KiB
			| 
											3 years ago
										 | 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 |