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.
		
		
		
		
		
			
		
			
				
					77 lines
				
				2.3 KiB
			
		
		
			
		
	
	
					77 lines
				
				2.3 KiB
			| 
								 
											3 years ago
										 
									 | 
							
								import type {CodeKeywordDefinition, AnySchemaObject} from "../../types"
							 | 
						||
| 
								 | 
							
								import type {KeywordCxt} from "../../compile/validate"
							 | 
						||
| 
								 | 
							
								import {compileSchema, SchemaEnv} from "../../compile"
							 | 
						||
| 
								 | 
							
								import {_, not, nil, stringify} from "../../compile/codegen"
							 | 
						||
| 
								 | 
							
								import MissingRefError from "../../compile/ref_error"
							 | 
						||
| 
								 | 
							
								import N from "../../compile/names"
							 | 
						||
| 
								 | 
							
								import {getValidate, callRef} from "../core/ref"
							 | 
						||
| 
								 | 
							
								import {checkMetadata} from "./metadata"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								const def: CodeKeywordDefinition = {
							 | 
						||
| 
								 | 
							
								  keyword: "ref",
							 | 
						||
| 
								 | 
							
								  schemaType: "string",
							 | 
						||
| 
								 | 
							
								  code(cxt: KeywordCxt) {
							 | 
						||
| 
								 | 
							
								    checkMetadata(cxt)
							 | 
						||
| 
								 | 
							
								    const {gen, data, schema: ref, parentSchema, it} = cxt
							 | 
						||
| 
								 | 
							
								    const {
							 | 
						||
| 
								 | 
							
								      schemaEnv: {root},
							 | 
						||
| 
								 | 
							
								    } = it
							 | 
						||
| 
								 | 
							
								    const valid = gen.name("valid")
							 | 
						||
| 
								 | 
							
								    if (parentSchema.nullable) {
							 | 
						||
| 
								 | 
							
								      gen.var(valid, _`${data} === null`)
							 | 
						||
| 
								 | 
							
								      gen.if(not(valid), validateJtdRef)
							 | 
						||
| 
								 | 
							
								    } else {
							 | 
						||
| 
								 | 
							
								      gen.var(valid, false)
							 | 
						||
| 
								 | 
							
								      validateJtdRef()
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								    cxt.ok(valid)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function validateJtdRef(): void {
							 | 
						||
| 
								 | 
							
								      const refSchema = (root.schema as AnySchemaObject).definitions?.[ref]
							 | 
						||
| 
								 | 
							
								      if (!refSchema) {
							 | 
						||
| 
								 | 
							
								        throw new MissingRefError(it.opts.uriResolver, "", ref, `No definition ${ref}`)
							 | 
						||
| 
								 | 
							
								      }
							 | 
						||
| 
								 | 
							
								      if (hasRef(refSchema) || !it.opts.inlineRefs) callValidate(refSchema)
							 | 
						||
| 
								 | 
							
								      else inlineRefSchema(refSchema)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function callValidate(schema: AnySchemaObject): void {
							 | 
						||
| 
								 | 
							
								      const sch = compileSchema.call(
							 | 
						||
| 
								 | 
							
								        it.self,
							 | 
						||
| 
								 | 
							
								        new SchemaEnv({schema, root, schemaPath: `/definitions/${ref}`})
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								      const v = getValidate(cxt, sch)
							 | 
						||
| 
								 | 
							
								      const errsCount = gen.const("_errs", N.errors)
							 | 
						||
| 
								 | 
							
								      callRef(cxt, v, sch, sch.$async)
							 | 
						||
| 
								 | 
							
								      gen.assign(valid, _`${errsCount} === ${N.errors}`)
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    function inlineRefSchema(schema: AnySchemaObject): void {
							 | 
						||
| 
								 | 
							
								      const schName = gen.scopeValue(
							 | 
						||
| 
								 | 
							
								        "schema",
							 | 
						||
| 
								 | 
							
								        it.opts.code.source === true ? {ref: schema, code: stringify(schema)} : {ref: schema}
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								      cxt.subschema(
							 | 
						||
| 
								 | 
							
								        {
							 | 
						||
| 
								 | 
							
								          schema,
							 | 
						||
| 
								 | 
							
								          dataTypes: [],
							 | 
						||
| 
								 | 
							
								          schemaPath: nil,
							 | 
						||
| 
								 | 
							
								          topSchemaRef: schName,
							 | 
						||
| 
								 | 
							
								          errSchemaPath: `/definitions/${ref}`,
							 | 
						||
| 
								 | 
							
								        },
							 | 
						||
| 
								 | 
							
								        valid
							 | 
						||
| 
								 | 
							
								      )
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								  },
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export function hasRef(schema: AnySchemaObject): boolean {
							 | 
						||
| 
								 | 
							
								  for (const key in schema) {
							 | 
						||
| 
								 | 
							
								    let sch: AnySchemaObject
							 | 
						||
| 
								 | 
							
								    if (key === "ref" || (typeof (sch = schema[key]) == "object" && hasRef(sch))) return true
							 | 
						||
| 
								 | 
							
								  }
							 | 
						||
| 
								 | 
							
								  return false
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								export default def
							 |