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
						
					
					
				| 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
 |