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.
		
		
		
		
		
			
		
			
				
					90 lines
				
				2.6 KiB
			
		
		
			
		
	
	
					90 lines
				
				2.6 KiB
			| 
											3 years ago
										 | import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types" | ||
|  | import type {KeywordCxt} from "../../compile/validate" | ||
|  | import {_, not, getProperty, Name} from "../../compile/codegen" | ||
|  | import {checkMetadata} from "./metadata" | ||
|  | import {checkNullableObject} from "./nullable" | ||
|  | import {typeErrorMessage, typeErrorParams, _JTDTypeError} from "./error" | ||
|  | import {DiscrError, DiscrErrorObj} from "../discriminator/types" | ||
|  | 
 | ||
|  | export type JTDDiscriminatorError = | ||
|  |   | _JTDTypeError<"discriminator", "object", string> | ||
|  |   | DiscrErrorObj<DiscrError.Tag> | ||
|  |   | DiscrErrorObj<DiscrError.Mapping> | ||
|  | 
 | ||
|  | const error: KeywordErrorDefinition = { | ||
|  |   message: (cxt) => { | ||
|  |     const {schema, params} = cxt | ||
|  |     return params.discrError | ||
|  |       ? params.discrError === DiscrError.Tag | ||
|  |         ? `tag "${schema}" must be string` | ||
|  |         : `value of tag "${schema}" must be in mapping` | ||
|  |       : typeErrorMessage(cxt, "object") | ||
|  |   }, | ||
|  |   params: (cxt) => { | ||
|  |     const {schema, params} = cxt | ||
|  |     return params.discrError | ||
|  |       ? _`{error: ${params.discrError}, tag: ${schema}, tagValue: ${params.tag}}` | ||
|  |       : typeErrorParams(cxt, "object") | ||
|  |   }, | ||
|  | } | ||
|  | 
 | ||
|  | const def: CodeKeywordDefinition = { | ||
|  |   keyword: "discriminator", | ||
|  |   schemaType: "string", | ||
|  |   implements: ["mapping"], | ||
|  |   error, | ||
|  |   code(cxt: KeywordCxt) { | ||
|  |     checkMetadata(cxt) | ||
|  |     const {gen, data, schema, parentSchema} = cxt | ||
|  |     const [valid, cond] = checkNullableObject(cxt, data) | ||
|  | 
 | ||
|  |     gen.if(cond) | ||
|  |     validateDiscriminator() | ||
|  |     gen.elseIf(not(valid)) | ||
|  |     cxt.error() | ||
|  |     gen.endIf() | ||
|  |     cxt.ok(valid) | ||
|  | 
 | ||
|  |     function validateDiscriminator(): void { | ||
|  |       const tag = gen.const("tag", _`${data}${getProperty(schema)}`) | ||
|  |       gen.if(_`${tag} === undefined`) | ||
|  |       cxt.error(false, {discrError: DiscrError.Tag, tag}) | ||
|  |       gen.elseIf(_`typeof ${tag} == "string"`) | ||
|  |       validateMapping(tag) | ||
|  |       gen.else() | ||
|  |       cxt.error(false, {discrError: DiscrError.Tag, tag}, {instancePath: schema}) | ||
|  |       gen.endIf() | ||
|  |     } | ||
|  | 
 | ||
|  |     function validateMapping(tag: Name): void { | ||
|  |       gen.if(false) | ||
|  |       for (const tagValue in parentSchema.mapping) { | ||
|  |         gen.elseIf(_`${tag} === ${tagValue}`) | ||
|  |         gen.assign(valid, applyTagSchema(tagValue)) | ||
|  |       } | ||
|  |       gen.else() | ||
|  |       cxt.error( | ||
|  |         false, | ||
|  |         {discrError: DiscrError.Mapping, tag}, | ||
|  |         {instancePath: schema, schemaPath: "mapping", parentSchema: true} | ||
|  |       ) | ||
|  |       gen.endIf() | ||
|  |     } | ||
|  | 
 | ||
|  |     function applyTagSchema(schemaProp: string): Name { | ||
|  |       const _valid = gen.name("valid") | ||
|  |       cxt.subschema( | ||
|  |         { | ||
|  |           keyword: "mapping", | ||
|  |           schemaProp, | ||
|  |           jtdDiscriminator: schema, | ||
|  |         }, | ||
|  |         _valid | ||
|  |       ) | ||
|  |       return _valid | ||
|  |     } | ||
|  |   }, | ||
|  | } | ||
|  | 
 | ||
|  | export default def |