properties.ts 1.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657
  1. import type {CodeKeywordDefinition} from "../../types"
  2. import {KeywordCxt} from "../../compile/validate"
  3. import {propertyInData, allSchemaProperties} from "../code"
  4. import {alwaysValidSchema, toHash, mergeEvaluated} from "../../compile/util"
  5. import apDef from "./additionalProperties"
  6. const def: CodeKeywordDefinition = {
  7. keyword: "properties",
  8. type: "object",
  9. schemaType: "object",
  10. code(cxt: KeywordCxt) {
  11. const {gen, schema, parentSchema, data, it} = cxt
  12. if (it.opts.removeAdditional === "all" && parentSchema.additionalProperties === undefined) {
  13. apDef.code(new KeywordCxt(it, apDef, "additionalProperties"))
  14. }
  15. const allProps = allSchemaProperties(schema)
  16. for (const prop of allProps) {
  17. it.definedProperties.add(prop)
  18. }
  19. if (it.opts.unevaluated && allProps.length && it.props !== true) {
  20. it.props = mergeEvaluated.props(gen, toHash(allProps), it.props)
  21. }
  22. const properties = allProps.filter((p) => !alwaysValidSchema(it, schema[p]))
  23. if (properties.length === 0) return
  24. const valid = gen.name("valid")
  25. for (const prop of properties) {
  26. if (hasDefault(prop)) {
  27. applyPropertySchema(prop)
  28. } else {
  29. gen.if(propertyInData(gen, data, prop, it.opts.ownProperties))
  30. applyPropertySchema(prop)
  31. if (!it.allErrors) gen.else().var(valid, true)
  32. gen.endIf()
  33. }
  34. cxt.it.definedProperties.add(prop)
  35. cxt.ok(valid)
  36. }
  37. function hasDefault(prop: string): boolean | undefined {
  38. return it.opts.useDefaults && !it.compositeRule && schema[prop].default !== undefined
  39. }
  40. function applyPropertySchema(prop: string): void {
  41. cxt.subschema(
  42. {
  43. keyword: "properties",
  44. schemaProp: prop,
  45. dataProp: prop,
  46. },
  47. valid
  48. )
  49. }
  50. },
  51. }
  52. export default def