UNPKG

2.4 kBPlain TextView Raw
1import type {
2 CodeKeywordDefinition,
3 ErrorObject,
4 KeywordErrorDefinition,
5 AnySchema,
6} from "../../types"
7import type {SchemaObjCxt} from "../../compile"
8import type {KeywordCxt} from "../../compile/validate"
9import {_, str, not, Name} from "../../compile/codegen"
10import {alwaysValidSchema, checkStrictMode} from "../../compile/util"
11
12export type IfKeywordError = ErrorObject<"if", {failingKeyword: string}, AnySchema>
13
14const error: KeywordErrorDefinition = {
15 message: ({params}) => str`must match "${params.ifClause}" schema`,
16 params: ({params}) => _`{failingKeyword: ${params.ifClause}}`,
17}
18
19const def: CodeKeywordDefinition = {
20 keyword: "if",
21 schemaType: ["object", "boolean"],
22 trackErrors: true,
23 error,
24 code(cxt: KeywordCxt) {
25 const {gen, parentSchema, it} = cxt
26 if (parentSchema.then === undefined && parentSchema.else === undefined) {
27 checkStrictMode(it, '"if" without "then" and "else" is ignored')
28 }
29 const hasThen = hasSchema(it, "then")
30 const hasElse = hasSchema(it, "else")
31 if (!hasThen && !hasElse) return
32
33 const valid = gen.let("valid", true)
34 const schValid = gen.name("_valid")
35 validateIf()
36 cxt.reset()
37
38 if (hasThen && hasElse) {
39 const ifClause = gen.let("ifClause")
40 cxt.setParams({ifClause})
41 gen.if(schValid, validateClause("then", ifClause), validateClause("else", ifClause))
42 } else if (hasThen) {
43 gen.if(schValid, validateClause("then"))
44 } else {
45 gen.if(not(schValid), validateClause("else"))
46 }
47
48 cxt.pass(valid, () => cxt.error(true))
49
50 function validateIf(): void {
51 const schCxt = cxt.subschema(
52 {
53 keyword: "if",
54 compositeRule: true,
55 createErrors: false,
56 allErrors: false,
57 },
58 schValid
59 )
60 cxt.mergeEvaluated(schCxt)
61 }
62
63 function validateClause(keyword: string, ifClause?: Name): () => void {
64 return () => {
65 const schCxt = cxt.subschema({keyword}, schValid)
66 gen.assign(valid, schValid)
67 cxt.mergeValidEvaluated(schCxt, valid)
68 if (ifClause) gen.assign(ifClause, _`${keyword}`)
69 else cxt.setParams({ifClause: keyword})
70 }
71 }
72 },
73}
74
75function hasSchema(it: SchemaObjCxt, keyword: string): boolean {
76 const schema = it.schema[keyword]
77 return schema !== undefined && !alwaysValidSchema(it, schema)
78}
79
80export default def