items.ts 1.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. import type {CodeKeywordDefinition, AnySchema, AnySchemaObject} from "../../types"
  2. import type {KeywordCxt} from "../../compile/validate"
  3. import {_} from "../../compile/codegen"
  4. import {alwaysValidSchema, mergeEvaluated, checkStrictMode} from "../../compile/util"
  5. import {validateArray} from "../code"
  6. const def: CodeKeywordDefinition = {
  7. keyword: "items",
  8. type: "array",
  9. schemaType: ["object", "array", "boolean"],
  10. before: "uniqueItems",
  11. code(cxt: KeywordCxt) {
  12. const {schema, it} = cxt
  13. if (Array.isArray(schema)) return validateTuple(cxt, "additionalItems", schema)
  14. it.items = true
  15. if (alwaysValidSchema(it, schema)) return
  16. cxt.ok(validateArray(cxt))
  17. },
  18. }
  19. export function validateTuple(
  20. cxt: KeywordCxt,
  21. extraItems: string,
  22. schArr: AnySchema[] = cxt.schema
  23. ): void {
  24. const {gen, parentSchema, data, keyword, it} = cxt
  25. checkStrictTuple(parentSchema)
  26. if (it.opts.unevaluated && schArr.length && it.items !== true) {
  27. it.items = mergeEvaluated.items(gen, schArr.length, it.items)
  28. }
  29. const valid = gen.name("valid")
  30. const len = gen.const("len", _`${data}.length`)
  31. schArr.forEach((sch: AnySchema, i: number) => {
  32. if (alwaysValidSchema(it, sch)) return
  33. gen.if(_`${len} > ${i}`, () =>
  34. cxt.subschema(
  35. {
  36. keyword,
  37. schemaProp: i,
  38. dataProp: i,
  39. },
  40. valid
  41. )
  42. )
  43. cxt.ok(valid)
  44. })
  45. function checkStrictTuple(sch: AnySchemaObject): void {
  46. const {opts, errSchemaPath} = it
  47. const l = schArr.length
  48. const fullTuple = l === sch.minItems && (l === sch.maxItems || sch[extraItems] === false)
  49. if (opts.strictTuples && !fullTuple) {
  50. const msg = `"${keyword}" is ${l}-tuple, but minItems or maxItems/${extraItems} are not specified or different at path "${errSchemaPath}"`
  51. checkStrictMode(it, msg, opts.strictTuples)
  52. }
  53. }
  54. }
  55. export default def