import type {CodeKeywordDefinition, AnySchema, AnySchemaObject} from "../../types" import type {KeywordCxt} from "../../compile/validate" import {_} from "../../compile/codegen" import {alwaysValidSchema, mergeEvaluated, checkStrictMode} from "../../compile/util" import {validateArray} from "../code" const def: CodeKeywordDefinition = { keyword: "items", type: "array", schemaType: ["object", "array", "boolean"], before: "uniqueItems", code(cxt: KeywordCxt) { const {schema, it} = cxt if (Array.isArray(schema)) return validateTuple(cxt, "additionalItems", schema) it.items = true if (alwaysValidSchema(it, schema)) return cxt.ok(validateArray(cxt)) }, } export function validateTuple( cxt: KeywordCxt, extraItems: string, schArr: AnySchema[] = cxt.schema ): void { const {gen, parentSchema, data, keyword, it} = cxt checkStrictTuple(parentSchema) if (it.opts.unevaluated && schArr.length && it.items !== true) { it.items = mergeEvaluated.items(gen, schArr.length, it.items) } const valid = gen.name("valid") const len = gen.const("len", _`${data}.length`) schArr.forEach((sch: AnySchema, i: number) => { if (alwaysValidSchema(it, sch)) return gen.if(_`${len} > ${i}`, () => cxt.subschema( { keyword, schemaProp: i, dataProp: i, }, valid ) ) cxt.ok(valid) }) function checkStrictTuple(sch: AnySchemaObject): void { const {opts, errSchemaPath} = it const l = schArr.length const fullTuple = l === sch.minItems && (l === sch.maxItems || sch[extraItems] === false) if (opts.strictTuples && !fullTuple) { const msg = `"${keyword}" is ${l}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"` checkStrictMode(it, msg, opts.strictTuples) } } } export default def