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.
		
		
		
		
		
			
		
			
				
					
					
						
							136 lines
						
					
					
						
							4.3 KiB
						
					
					
				
			
		
		
	
	
							136 lines
						
					
					
						
							4.3 KiB
						
					
					
				| import type {AnySchema} from "../../types"
 | |
| import type {SchemaObjCxt} from ".."
 | |
| import {_, str, getProperty, Code, Name} from "../codegen"
 | |
| import {escapeFragment, getErrorPath, Type} from "../util"
 | |
| import type {JSONType} from "../rules"
 | |
| 
 | |
| export interface SubschemaContext {
 | |
|   // TODO use Optional? align with SchemCxt property types
 | |
|   schema: AnySchema
 | |
|   schemaPath: Code
 | |
|   errSchemaPath: string
 | |
|   topSchemaRef?: Code
 | |
|   errorPath?: Code
 | |
|   dataLevel?: number
 | |
|   dataTypes?: JSONType[]
 | |
|   data?: Name
 | |
|   parentData?: Name
 | |
|   parentDataProperty?: Code | number
 | |
|   dataNames?: Name[]
 | |
|   dataPathArr?: (Code | number)[]
 | |
|   propertyName?: Name
 | |
|   jtdDiscriminator?: string
 | |
|   jtdMetadata?: boolean
 | |
|   compositeRule?: true
 | |
|   createErrors?: boolean
 | |
|   allErrors?: boolean
 | |
| }
 | |
| 
 | |
| export type SubschemaArgs = Partial<{
 | |
|   keyword: string
 | |
|   schemaProp: string | number
 | |
|   schema: AnySchema
 | |
|   schemaPath: Code
 | |
|   errSchemaPath: string
 | |
|   topSchemaRef: Code
 | |
|   data: Name | Code
 | |
|   dataProp: Code | string | number
 | |
|   dataTypes: JSONType[]
 | |
|   definedProperties: Set<string>
 | |
|   propertyName: Name
 | |
|   dataPropType: Type
 | |
|   jtdDiscriminator: string
 | |
|   jtdMetadata: boolean
 | |
|   compositeRule: true
 | |
|   createErrors: boolean
 | |
|   allErrors: boolean
 | |
| }>
 | |
| 
 | |
| export function getSubschema(
 | |
|   it: SchemaObjCxt,
 | |
|   {keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef}: SubschemaArgs
 | |
| ): SubschemaContext {
 | |
|   if (keyword !== undefined && schema !== undefined) {
 | |
|     throw new Error('both "keyword" and "schema" passed, only one allowed')
 | |
|   }
 | |
| 
 | |
|   if (keyword !== undefined) {
 | |
|     const sch = it.schema[keyword]
 | |
|     return schemaProp === undefined
 | |
|       ? {
 | |
|           schema: sch,
 | |
|           schemaPath: _`${it.schemaPath}${getProperty(keyword)}`,
 | |
|           errSchemaPath: `${it.errSchemaPath}/${keyword}`,
 | |
|         }
 | |
|       : {
 | |
|           schema: sch[schemaProp],
 | |
|           schemaPath: _`${it.schemaPath}${getProperty(keyword)}${getProperty(schemaProp)}`,
 | |
|           errSchemaPath: `${it.errSchemaPath}/${keyword}/${escapeFragment(schemaProp)}`,
 | |
|         }
 | |
|   }
 | |
| 
 | |
|   if (schema !== undefined) {
 | |
|     if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
 | |
|       throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"')
 | |
|     }
 | |
|     return {
 | |
|       schema,
 | |
|       schemaPath,
 | |
|       topSchemaRef,
 | |
|       errSchemaPath,
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   throw new Error('either "keyword" or "schema" must be passed')
 | |
| }
 | |
| 
 | |
| export function extendSubschemaData(
 | |
|   subschema: SubschemaContext,
 | |
|   it: SchemaObjCxt,
 | |
|   {dataProp, dataPropType: dpType, data, dataTypes, propertyName}: SubschemaArgs
 | |
| ): void {
 | |
|   if (data !== undefined && dataProp !== undefined) {
 | |
|     throw new Error('both "data" and "dataProp" passed, only one allowed')
 | |
|   }
 | |
| 
 | |
|   const {gen} = it
 | |
| 
 | |
|   if (dataProp !== undefined) {
 | |
|     const {errorPath, dataPathArr, opts} = it
 | |
|     const nextData = gen.let("data", _`${it.data}${getProperty(dataProp)}`, true)
 | |
|     dataContextProps(nextData)
 | |
|     subschema.errorPath = str`${errorPath}${getErrorPath(dataProp, dpType, opts.jsPropertySyntax)}`
 | |
|     subschema.parentDataProperty = _`${dataProp}`
 | |
|     subschema.dataPathArr = [...dataPathArr, subschema.parentDataProperty]
 | |
|   }
 | |
| 
 | |
|   if (data !== undefined) {
 | |
|     const nextData = data instanceof Name ? data : gen.let("data", data, true) // replaceable if used once?
 | |
|     dataContextProps(nextData)
 | |
|     if (propertyName !== undefined) subschema.propertyName = propertyName
 | |
|     // TODO something is possibly wrong here with not changing parentDataProperty and not appending dataPathArr
 | |
|   }
 | |
| 
 | |
|   if (dataTypes) subschema.dataTypes = dataTypes
 | |
| 
 | |
|   function dataContextProps(_nextData: Name): void {
 | |
|     subschema.data = _nextData
 | |
|     subschema.dataLevel = it.dataLevel + 1
 | |
|     subschema.dataTypes = []
 | |
|     it.definedProperties = new Set<string>()
 | |
|     subschema.parentData = it.data
 | |
|     subschema.dataNames = [...it.dataNames, _nextData]
 | |
|   }
 | |
| }
 | |
| 
 | |
| export function extendSubschemaMode(
 | |
|   subschema: SubschemaContext,
 | |
|   {jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors}: SubschemaArgs
 | |
| ): void {
 | |
|   if (compositeRule !== undefined) subschema.compositeRule = compositeRule
 | |
|   if (createErrors !== undefined) subschema.createErrors = createErrors
 | |
|   if (allErrors !== undefined) subschema.allErrors = allErrors
 | |
|   subschema.jtdDiscriminator = jtdDiscriminator // not inherited
 | |
|   subschema.jtdMetadata = jtdMetadata // not inherited
 | |
| }
 |