You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							99 lines
						
					
					
						
							2.9 KiB
						
					
					
				
			
		
		
	
	
							99 lines
						
					
					
						
							2.9 KiB
						
					
					
				import type {CodeKeywordDefinition, ErrorObject, KeywordErrorDefinition} from "../../types"
 | 
						|
import type {KeywordCxt} from "../../compile/validate"
 | 
						|
import {
 | 
						|
  checkReportMissingProp,
 | 
						|
  checkMissingProp,
 | 
						|
  reportMissingProp,
 | 
						|
  propertyInData,
 | 
						|
  noPropertyInData,
 | 
						|
} from "../code"
 | 
						|
import {_, str, nil, not, Name, Code} from "../../compile/codegen"
 | 
						|
import {checkStrictMode} from "../../compile/util"
 | 
						|
 | 
						|
export type RequiredError = ErrorObject<
 | 
						|
  "required",
 | 
						|
  {missingProperty: string},
 | 
						|
  string[] | {$data: string}
 | 
						|
>
 | 
						|
 | 
						|
const error: KeywordErrorDefinition = {
 | 
						|
  message: ({params: {missingProperty}}) => str`must have required property '${missingProperty}'`,
 | 
						|
  params: ({params: {missingProperty}}) => _`{missingProperty: ${missingProperty}}`,
 | 
						|
}
 | 
						|
 | 
						|
const def: CodeKeywordDefinition = {
 | 
						|
  keyword: "required",
 | 
						|
  type: "object",
 | 
						|
  schemaType: "array",
 | 
						|
  $data: true,
 | 
						|
  error,
 | 
						|
  code(cxt: KeywordCxt) {
 | 
						|
    const {gen, schema, schemaCode, data, $data, it} = cxt
 | 
						|
    const {opts} = it
 | 
						|
    if (!$data && schema.length === 0) return
 | 
						|
    const useLoop = schema.length >= opts.loopRequired
 | 
						|
    if (it.allErrors) allErrorsMode()
 | 
						|
    else exitOnErrorMode()
 | 
						|
 | 
						|
    if (opts.strictRequired) {
 | 
						|
      const props = cxt.parentSchema.properties
 | 
						|
      const {definedProperties} = cxt.it
 | 
						|
      for (const requiredKey of schema) {
 | 
						|
        if (props?.[requiredKey] === undefined && !definedProperties.has(requiredKey)) {
 | 
						|
          const schemaPath = it.schemaEnv.baseId + it.errSchemaPath
 | 
						|
          const msg = `required property "${requiredKey}" is not defined at "${schemaPath}" (strictRequired)`
 | 
						|
          checkStrictMode(it, msg, it.opts.strictRequired)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    function allErrorsMode(): void {
 | 
						|
      if (useLoop || $data) {
 | 
						|
        cxt.block$data(nil, loopAllRequired)
 | 
						|
      } else {
 | 
						|
        for (const prop of schema) {
 | 
						|
          checkReportMissingProp(cxt, prop)
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    function exitOnErrorMode(): void {
 | 
						|
      const missing = gen.let("missing")
 | 
						|
      if (useLoop || $data) {
 | 
						|
        const valid = gen.let("valid", true)
 | 
						|
        cxt.block$data(valid, () => loopUntilMissing(missing, valid))
 | 
						|
        cxt.ok(valid)
 | 
						|
      } else {
 | 
						|
        gen.if(checkMissingProp(cxt, schema, missing))
 | 
						|
        reportMissingProp(cxt, missing)
 | 
						|
        gen.else()
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    function loopAllRequired(): void {
 | 
						|
      gen.forOf("prop", schemaCode as Code, (prop) => {
 | 
						|
        cxt.setParams({missingProperty: prop})
 | 
						|
        gen.if(noPropertyInData(gen, data, prop, opts.ownProperties), () => cxt.error())
 | 
						|
      })
 | 
						|
    }
 | 
						|
 | 
						|
    function loopUntilMissing(missing: Name, valid: Name): void {
 | 
						|
      cxt.setParams({missingProperty: missing})
 | 
						|
      gen.forOf(
 | 
						|
        missing,
 | 
						|
        schemaCode as Code,
 | 
						|
        () => {
 | 
						|
          gen.assign(valid, propertyInData(gen, data, missing, opts.ownProperties))
 | 
						|
          gen.if(not(valid), () => {
 | 
						|
            cxt.error()
 | 
						|
            gen.break()
 | 
						|
          })
 | 
						|
        },
 | 
						|
        nil
 | 
						|
      )
 | 
						|
    }
 | 
						|
  },
 | 
						|
}
 | 
						|
 | 
						|
export default def
 |