import { isObject, objectClone, objectLoop } from '@dzeio/object-util' import SchemaItem from '../SchemaItem' import { SchemaInfer, ValidationResult } from '../types' type ModelInfer> = { [key in keyof M]: SchemaInfer } export default class SchemaObject = any> extends SchemaItem> { public id = 'object' public constructor(public readonly model: T) { super([model]) } public override parse(input: unknown, options?: { fast?: boolean }): ValidationResult> { // check errors from itself const { valid, object, errors = [] } = super.parse(input, options) // skip checking childs if self is not valid (maybe still try to check childs whan fast is false ?) if (!valid) { return { valid, object, errors } as ValidationResult> } const clone = objectClone(object) // loop through the childs objectLoop(this.model, (childSchema, key) => { const childValue = clone[key] // parse the child const child = childSchema.parse(childValue) // add errors if (!child.valid) { errors.push(...child.errors.map((it) => ({ ...it, field: it.field ? `${key}.${it.field}` : key }))) } // @ts-expect-error while it's a generic we know by proof above that it's valid ! // eslint-disable-next-line @typescript-eslint/no-unsafe-assignment clone[key] = child.object // skip rest of items if current one is invalid return child.valid || !options?.fast }) // answer ! return { valid: errors.length === 0, errors: errors, object: clone } as ValidationResult> } public override isOfType(input: unknown): input is ModelInfer { return isObject(input) } }