UNPKG

2.44 kBPlain TextView Raw
1import type {
2 CodeKeywordDefinition,
3 KeywordErrorDefinition,
4 ErrorObject,
5 AnySchema,
6} from "../../types"
7import {_, not, and, Name, Code} from "../../compile/codegen"
8import {alwaysValidSchema, Type} from "../../compile/util"
9import N from "../../compile/names"
10
11export type UnevaluatedPropertiesError = ErrorObject<
12 "unevaluatedProperties",
13 {unevaluatedProperty: string},
14 AnySchema
15>
16
17const error: KeywordErrorDefinition = {
18 message: "must NOT have unevaluated properties",
19 params: ({params}) => _`{unevaluatedProperty: ${params.unevaluatedProperty}}`,
20}
21
22const def: CodeKeywordDefinition = {
23 keyword: "unevaluatedProperties",
24 type: "object",
25 schemaType: ["boolean", "object"],
26 trackErrors: true,
27 error,
28 code(cxt) {
29 const {gen, schema, data, errsCount, it} = cxt
30 /* istanbul ignore if */
31 if (!errsCount) throw new Error("ajv implementation error")
32 const {allErrors, props} = it
33 if (props instanceof Name) {
34 gen.if(_`${props} !== true`, () =>
35 gen.forIn("key", data, (key: Name) =>
36 gen.if(unevaluatedDynamic(props, key), () => unevaluatedPropCode(key))
37 )
38 )
39 } else if (props !== true) {
40 gen.forIn("key", data, (key: Name) =>
41 props === undefined
42 ? unevaluatedPropCode(key)
43 : gen.if(unevaluatedStatic(props, key), () => unevaluatedPropCode(key))
44 )
45 }
46 it.props = true
47 cxt.ok(_`${errsCount} === ${N.errors}`)
48
49 function unevaluatedPropCode(key: Name): void {
50 if (schema === false) {
51 cxt.setParams({unevaluatedProperty: key})
52 cxt.error()
53 if (!allErrors) gen.break()
54 return
55 }
56
57 if (!alwaysValidSchema(it, schema)) {
58 const valid = gen.name("valid")
59 cxt.subschema(
60 {
61 keyword: "unevaluatedProperties",
62 dataProp: key,
63 dataPropType: Type.Str,
64 },
65 valid
66 )
67 if (!allErrors) gen.if(not(valid), () => gen.break())
68 }
69 }
70
71 function unevaluatedDynamic(evaluatedProps: Name, key: Name): Code {
72 return _`!${evaluatedProps} || !${evaluatedProps}[${key}]`
73 }
74
75 function unevaluatedStatic(evaluatedProps: {[K in string]?: true}, key: Name): Code {
76 const ps: Code[] = []
77 for (const p in evaluatedProps) {
78 if (evaluatedProps[p] === true) ps.push(_`${key} !== ${p}`)
79 }
80 return and(...ps)
81 }
82 },
83}
84
85export default def