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) // optimizer should remove it from generated code
|
---|
34 | for (const schemaProp in parentSchema.selectCases) {
|
---|
35 | cxt.setParams({schemaProp})
|
---|
36 | gen.elseIf(_`"" + ${value} == ${schemaProp}`) // intentional ==, to match numbers and booleans
|
---|
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
|
---|