UNPKG

1.82 kBPlain TextView Raw
1import type {
2 CodeKeywordDefinition,
3 ErrorObject,
4 KeywordErrorDefinition,
5 AnySchema,
6} from "../../types"
7import type {KeywordCxt} from "../../compile/validate"
8import {_, str, not, Name} from "../../compile/codegen"
9import {alwaysValidSchema, checkStrictMode, Type} from "../../compile/util"
10
11export type AdditionalItemsError = ErrorObject<"additionalItems", {limit: number}, AnySchema>
12
13const error: KeywordErrorDefinition = {
14 message: ({params: {len}}) => str`must NOT have more than ${len} items`,
15 params: ({params: {len}}) => _`{limit: ${len}}`,
16}
17
18const def: CodeKeywordDefinition = {
19 keyword: "additionalItems" as const,
20 type: "array",
21 schemaType: ["boolean", "object"],
22 before: "uniqueItems",
23 error,
24 code(cxt: KeywordCxt) {
25 const {parentSchema, it} = cxt
26 const {items} = parentSchema
27 if (!Array.isArray(items)) {
28 checkStrictMode(it, '"additionalItems" is ignored when "items" is not an array of schemas')
29 return
30 }
31 validateAdditionalItems(cxt, items)
32 },
33}
34
35export function validateAdditionalItems(cxt: KeywordCxt, items: AnySchema[]): void {
36 const {gen, schema, data, keyword, it} = cxt
37 it.items = true
38 const len = gen.const("len", _`${data}.length`)
39 if (schema === false) {
40 cxt.setParams({len: items.length})
41 cxt.pass(_`${len} <= ${items.length}`)
42 } else if (typeof schema == "object" && !alwaysValidSchema(it, schema)) {
43 const valid = gen.var("valid", _`${len} <= ${items.length}`) // TODO var
44 gen.if(not(valid), () => validateItems(valid))
45 cxt.ok(valid)
46 }
47
48 function validateItems(valid: Name): void {
49 gen.forRange("i", items.length, len, (i) => {
50 cxt.subschema({keyword, dataProp: i, dataPropType: Type.Num}, valid)
51 if (!it.allErrors) gen.if(not(valid), () => gen.break())
52 })
53 }
54}
55
56export default def