anyOf.ts 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. import type {CodeKeywordDefinition, ErrorNoParams, AnySchema} from "../../types"
  2. import type KeywordCxt from "../../compile/context"
  3. import {_, not} from "../../compile/codegen"
  4. import {alwaysValidSchema} from "../../compile/util"
  5. export type AnyOfError = ErrorNoParams<"anyOf", AnySchema[]>
  6. const def: CodeKeywordDefinition = {
  7. keyword: "anyOf",
  8. schemaType: "array",
  9. trackErrors: true,
  10. code(cxt: KeywordCxt) {
  11. const {gen, schema, it} = cxt
  12. /* istanbul ignore if */
  13. if (!Array.isArray(schema)) throw new Error("ajv implementation error")
  14. const alwaysValid = schema.some((sch: AnySchema) => alwaysValidSchema(it, sch))
  15. if (alwaysValid && !it.opts.unevaluated) return
  16. const valid = gen.let("valid", false)
  17. const schValid = gen.name("_valid")
  18. gen.block(() =>
  19. schema.forEach((_sch: AnySchema, i: number) => {
  20. const schCxt = cxt.subschema(
  21. {
  22. keyword: "anyOf",
  23. schemaProp: i,
  24. compositeRule: true,
  25. },
  26. schValid
  27. )
  28. gen.assign(valid, _`${valid} || ${schValid}`)
  29. const merged = cxt.mergeValidEvaluated(schCxt, schValid)
  30. // can short-circuit if `unevaluatedProperties/Items` not supported (opts.unevaluated !== true)
  31. // or if all properties and items were evaluated (it.props === true && it.items === true)
  32. if (!merged) gen.if(not(valid))
  33. })
  34. )
  35. cxt.result(
  36. valid,
  37. () => cxt.reset(),
  38. () => cxt.error(true)
  39. )
  40. },
  41. error: {
  42. message: "should match some schema in anyOf",
  43. },
  44. }
  45. export default def