.gitignore added
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / table / node_modules / ajv / lib / vocabularies / jtd / discriminator.ts
1 import type {CodeKeywordDefinition, KeywordErrorDefinition} from "../../types"
2 import type {KeywordCxt} from "../../compile/validate"
3 import {_, not, getProperty, Name} from "../../compile/codegen"
4 import {checkMetadata} from "./metadata"
5 import {checkNullableObject} from "./nullable"
6 import {typeErrorMessage, typeErrorParams, _JTDTypeError} from "./error"
7 import {DiscrError, DiscrErrorObj} from "../discriminator/types"
8
9 export type JTDDiscriminatorError =
10   | _JTDTypeError<"discriminator", "object", string>
11   | DiscrErrorObj<DiscrError.Tag>
12   | DiscrErrorObj<DiscrError.Mapping>
13
14 const error: KeywordErrorDefinition = {
15   message: (cxt) => {
16     const {schema, params} = cxt
17     return params.discrError
18       ? params.discrError === DiscrError.Tag
19         ? `tag "${schema}" must be string`
20         : `value of tag "${schema}" must be in mapping`
21       : typeErrorMessage(cxt, "object")
22   },
23   params: (cxt) => {
24     const {schema, params} = cxt
25     return params.discrError
26       ? _`{error: ${params.discrError}, tag: ${schema}, tagValue: ${params.tag}}`
27       : typeErrorParams(cxt, "object")
28   },
29 }
30
31 const def: CodeKeywordDefinition = {
32   keyword: "discriminator",
33   schemaType: "string",
34   implements: ["mapping"],
35   error,
36   code(cxt: KeywordCxt) {
37     checkMetadata(cxt)
38     const {gen, data, schema, parentSchema} = cxt
39     const [valid, cond] = checkNullableObject(cxt, data)
40
41     gen.if(cond)
42     validateDiscriminator()
43     gen.elseIf(not(valid))
44     cxt.error()
45     gen.endIf()
46     cxt.ok(valid)
47
48     function validateDiscriminator(): void {
49       const tag = gen.const("tag", _`${data}${getProperty(schema)}`)
50       gen.if(_`${tag} === undefined`)
51       cxt.error(false, {discrError: DiscrError.Tag, tag})
52       gen.elseIf(_`typeof ${tag} == "string"`)
53       validateMapping(tag)
54       gen.else()
55       cxt.error(false, {discrError: DiscrError.Tag, tag}, {instancePath: schema})
56       gen.endIf()
57     }
58
59     function validateMapping(tag: Name): void {
60       gen.if(false)
61       for (const tagValue in parentSchema.mapping) {
62         gen.elseIf(_`${tag} === ${tagValue}`)
63         gen.assign(valid, applyTagSchema(tagValue))
64       }
65       gen.else()
66       cxt.error(
67         false,
68         {discrError: DiscrError.Mapping, tag},
69         {instancePath: schema, schemaPath: "mapping", parentSchema: true}
70       )
71       gen.endIf()
72     }
73
74     function applyTagSchema(schemaProp: string): Name {
75       const _valid = gen.name("valid")
76       cxt.subschema(
77         {
78           keyword: "mapping",
79           schemaProp,
80           jtdDiscriminator: schema,
81         },
82         _valid
83       )
84       return _valid
85     }
86   },
87 }
88
89 export default def