1 | import type {KeywordDefinition, KeywordErrorDefinition, KeywordCxt, ErrorObject} from "ajv"
|
2 | import {_, str, nil, Name} from "ajv/dist/compile/codegen"
|
3 | import type {DefinitionOptions} from "./_types"
|
4 | import {metaSchemaRef} from "./_util"
|
5 |
|
6 | export type SelectError = ErrorObject<"select", {failingCase?: string; failingDefault?: true}>
|
7 |
|
8 | const error: KeywordErrorDefinition = {
|
9 | message: ({params: {schemaProp}}) =>
|
10 | schemaProp
|
11 | ? str`should match case "${schemaProp}" schema`
|
12 | : str`should match default case schema`,
|
13 | params: ({params: {schemaProp}}) =>
|
14 | schemaProp ? _`{failingCase: ${schemaProp}}` : _`{failingDefault: true}`,
|
15 | }
|
16 |
|
17 | export default function getDef(opts?: DefinitionOptions): KeywordDefinition[] {
|
18 | const metaSchema = metaSchemaRef(opts)
|
19 |
|
20 | return [
|
21 | {
|
22 | keyword: "select",
|
23 | schemaType: ["string", "number", "boolean", "null"],
|
24 | $data: true,
|
25 | error,
|
26 | dependencies: ["selectCases"],
|
27 | code(cxt: KeywordCxt) {
|
28 | const {gen, schemaCode, parentSchema} = cxt
|
29 | cxt.block$data(nil, () => {
|
30 | const valid = gen.let("valid", true)
|
31 | const schValid = gen.name("_valid")
|
32 | const value = gen.const("value", _`${schemaCode} === null ? "null" : ${schemaCode}`)
|
33 | gen.if(false)
|
34 | for (const schemaProp in parentSchema.selectCases) {
|
35 | cxt.setParams({schemaProp})
|
36 | gen.elseIf(_`"" + ${value} == ${schemaProp}`)
|
37 | const schCxt = cxt.subschema({keyword: "selectCases", schemaProp}, schValid)
|
38 | cxt.mergeEvaluated(schCxt, Name)
|
39 | gen.assign(valid, schValid)
|
40 | }
|
41 | gen.else()
|
42 | if (parentSchema.selectDefault !== undefined) {
|
43 | cxt.setParams({schemaProp: undefined})
|
44 | const schCxt = cxt.subschema({keyword: "selectDefault"}, schValid)
|
45 | cxt.mergeEvaluated(schCxt, Name)
|
46 | gen.assign(valid, schValid)
|
47 | }
|
48 | gen.endIf()
|
49 | cxt.pass(valid)
|
50 | })
|
51 | },
|
52 | },
|
53 | {
|
54 | keyword: "selectCases",
|
55 | dependencies: ["select"],
|
56 | metaSchema: {
|
57 | type: "object",
|
58 | additionalProperties: metaSchema,
|
59 | },
|
60 | },
|
61 | {
|
62 | keyword: "selectDefault",
|
63 | dependencies: ["select", "selectCases"],
|
64 | metaSchema,
|
65 | },
|
66 | ]
|
67 | }
|
68 |
|
69 | module.exports = getDef
|