1 import type {AnySchema} from "../../types"
2 import type {SchemaObjCxt} from ".."
3 import {_, str, getProperty, Code, Name} from "../codegen"
4 import {escapeFragment, getErrorPath, Type} from "../util"
5 import type {JSONType} from "../rules"
7 export interface SubschemaContext {
8 // TODO use Optional? align with SchemCxt property types
15 dataTypes?: JSONType[]
18 parentDataProperty?: Code | number
20 dataPathArr?: (Code | number)[]
22 jtdDiscriminator?: string
25 createErrors?: boolean
29 export type SubschemaArgs = Partial<{
31 schemaProp: string | number
37 dataProp: Code | string | number
39 definedProperties: Set<string>
42 jtdDiscriminator: string
49 export function getSubschema(
51 {keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef}: SubschemaArgs
53 if (keyword !== undefined && schema !== undefined) {
54 throw new Error('both "keyword" and "schema" passed, only one allowed')
57 if (keyword !== undefined) {
58 const sch = it.schema[keyword]
59 return schemaProp === undefined
62 schemaPath: _`${it.schemaPath}${getProperty(keyword)}`,
63 errSchemaPath: `${it.errSchemaPath}/${keyword}`,
66 schema: sch[schemaProp],
67 schemaPath: _`${it.schemaPath}${getProperty(keyword)}${getProperty(schemaProp)}`,
68 errSchemaPath: `${it.errSchemaPath}/${keyword}/${escapeFragment(schemaProp)}`,
72 if (schema !== undefined) {
73 if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
74 throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"')
84 throw new Error('either "keyword" or "schema" must be passed')
87 export function extendSubschemaData(
88 subschema: SubschemaContext,
90 {dataProp, dataPropType: dpType, data, dataTypes, propertyName}: SubschemaArgs
92 if (data !== undefined && dataProp !== undefined) {
93 throw new Error('both "data" and "dataProp" passed, only one allowed')
98 if (dataProp !== undefined) {
99 const {errorPath, dataPathArr, opts} = it
100 const nextData = gen.let("data", _`${it.data}${getProperty(dataProp)}`, true)
101 dataContextProps(nextData)
102 subschema.errorPath = str`${errorPath}${getErrorPath(dataProp, dpType, opts.jsPropertySyntax)}`
103 subschema.parentDataProperty = _`${dataProp}`
104 subschema.dataPathArr = [...dataPathArr, subschema.parentDataProperty]
107 if (data !== undefined) {
108 const nextData = data instanceof Name ? data : gen.let("data", data, true) // replaceable if used once?
109 dataContextProps(nextData)
110 if (propertyName !== undefined) subschema.propertyName = propertyName
111 // TODO something is possibly wrong here with not changing parentDataProperty and not appending dataPathArr
114 if (dataTypes) subschema.dataTypes = dataTypes
116 function dataContextProps(_nextData: Name): void {
117 subschema.data = _nextData
118 subschema.dataLevel = it.dataLevel + 1
119 subschema.dataTypes = []
120 it.definedProperties = new Set<string>()
121 subschema.parentData = it.data
122 subschema.dataNames = [...it.dataNames, _nextData]
126 export function extendSubschemaMode(
127 subschema: SubschemaContext,
128 {jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors}: SubschemaArgs
130 if (compositeRule !== undefined) subschema.compositeRule = compositeRule
131 if (createErrors !== undefined) subschema.createErrors = createErrors
132 if (allErrors !== undefined) subschema.allErrors = allErrors
133 subschema.jtdDiscriminator = jtdDiscriminator // not inherited
134 subschema.jtdMetadata = jtdMetadata // not inherited