[79a0317] | 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"
|
---|
| 6 |
|
---|
| 7 | export interface SubschemaContext {
|
---|
| 8 | // TODO use Optional? align with SchemCxt property types
|
---|
| 9 | schema: AnySchema
|
---|
| 10 | schemaPath: Code
|
---|
| 11 | errSchemaPath: string
|
---|
| 12 | topSchemaRef?: Code
|
---|
| 13 | errorPath?: Code
|
---|
| 14 | dataLevel?: number
|
---|
| 15 | dataTypes?: JSONType[]
|
---|
| 16 | data?: Name
|
---|
| 17 | parentData?: Name
|
---|
| 18 | parentDataProperty?: Code | number
|
---|
| 19 | dataNames?: Name[]
|
---|
| 20 | dataPathArr?: (Code | number)[]
|
---|
| 21 | propertyName?: Name
|
---|
| 22 | jtdDiscriminator?: string
|
---|
| 23 | jtdMetadata?: boolean
|
---|
| 24 | compositeRule?: true
|
---|
| 25 | createErrors?: boolean
|
---|
| 26 | allErrors?: boolean
|
---|
| 27 | }
|
---|
| 28 |
|
---|
| 29 | export type SubschemaArgs = Partial<{
|
---|
| 30 | keyword: string
|
---|
| 31 | schemaProp: string | number
|
---|
| 32 | schema: AnySchema
|
---|
| 33 | schemaPath: Code
|
---|
| 34 | errSchemaPath: string
|
---|
| 35 | topSchemaRef: Code
|
---|
| 36 | data: Name | Code
|
---|
| 37 | dataProp: Code | string | number
|
---|
| 38 | dataTypes: JSONType[]
|
---|
| 39 | definedProperties: Set<string>
|
---|
| 40 | propertyName: Name
|
---|
| 41 | dataPropType: Type
|
---|
| 42 | jtdDiscriminator: string
|
---|
| 43 | jtdMetadata: boolean
|
---|
| 44 | compositeRule: true
|
---|
| 45 | createErrors: boolean
|
---|
| 46 | allErrors: boolean
|
---|
| 47 | }>
|
---|
| 48 |
|
---|
| 49 | export function getSubschema(
|
---|
| 50 | it: SchemaObjCxt,
|
---|
| 51 | {keyword, schemaProp, schema, schemaPath, errSchemaPath, topSchemaRef}: SubschemaArgs
|
---|
| 52 | ): SubschemaContext {
|
---|
| 53 | if (keyword !== undefined && schema !== undefined) {
|
---|
| 54 | throw new Error('both "keyword" and "schema" passed, only one allowed')
|
---|
| 55 | }
|
---|
| 56 |
|
---|
| 57 | if (keyword !== undefined) {
|
---|
| 58 | const sch = it.schema[keyword]
|
---|
| 59 | return schemaProp === undefined
|
---|
| 60 | ? {
|
---|
| 61 | schema: sch,
|
---|
| 62 | schemaPath: _`${it.schemaPath}${getProperty(keyword)}`,
|
---|
| 63 | errSchemaPath: `${it.errSchemaPath}/${keyword}`,
|
---|
| 64 | }
|
---|
| 65 | : {
|
---|
| 66 | schema: sch[schemaProp],
|
---|
| 67 | schemaPath: _`${it.schemaPath}${getProperty(keyword)}${getProperty(schemaProp)}`,
|
---|
| 68 | errSchemaPath: `${it.errSchemaPath}/${keyword}/${escapeFragment(schemaProp)}`,
|
---|
| 69 | }
|
---|
| 70 | }
|
---|
| 71 |
|
---|
| 72 | if (schema !== undefined) {
|
---|
| 73 | if (schemaPath === undefined || errSchemaPath === undefined || topSchemaRef === undefined) {
|
---|
| 74 | throw new Error('"schemaPath", "errSchemaPath" and "topSchemaRef" are required with "schema"')
|
---|
| 75 | }
|
---|
| 76 | return {
|
---|
| 77 | schema,
|
---|
| 78 | schemaPath,
|
---|
| 79 | topSchemaRef,
|
---|
| 80 | errSchemaPath,
|
---|
| 81 | }
|
---|
| 82 | }
|
---|
| 83 |
|
---|
| 84 | throw new Error('either "keyword" or "schema" must be passed')
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 | export function extendSubschemaData(
|
---|
| 88 | subschema: SubschemaContext,
|
---|
| 89 | it: SchemaObjCxt,
|
---|
| 90 | {dataProp, dataPropType: dpType, data, dataTypes, propertyName}: SubschemaArgs
|
---|
| 91 | ): void {
|
---|
| 92 | if (data !== undefined && dataProp !== undefined) {
|
---|
| 93 | throw new Error('both "data" and "dataProp" passed, only one allowed')
|
---|
| 94 | }
|
---|
| 95 |
|
---|
| 96 | const {gen} = it
|
---|
| 97 |
|
---|
| 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]
|
---|
| 105 | }
|
---|
| 106 |
|
---|
| 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
|
---|
| 112 | }
|
---|
| 113 |
|
---|
| 114 | if (dataTypes) subschema.dataTypes = dataTypes
|
---|
| 115 |
|
---|
| 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]
|
---|
| 123 | }
|
---|
| 124 | }
|
---|
| 125 |
|
---|
| 126 | export function extendSubschemaMode(
|
---|
| 127 | subschema: SubschemaContext,
|
---|
| 128 | {jtdDiscriminator, jtdMetadata, compositeRule, createErrors, allErrors}: SubschemaArgs
|
---|
| 129 | ): void {
|
---|
| 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
|
---|
| 135 | }
|
---|