import { objectGet, objectLoop, objectSet } from '@dzeio/object-util' import SchemaArray from 'items/array' import SchemaBoolean from 'items/boolean' import SchemaNullable from 'items/nullable' import SchemaObject from 'items/object' import type SchemaItem from 'SchemaItem' export function isNull(value: unknown): value is undefined | null { return typeof value === 'undefined' || value === null } export function parseQuery(model: T, query: URLSearchParams, opts?: Parameters[1]): ReturnType { const record: Record = {} for (const [key, value] of query) { record[key] = value } return model.parse(record, opts) as ReturnType } export function parseFormData(model: T, data: FormData, opts?: Parameters[1]): ReturnType { const record: Record = {} // console.log('VALIDATE FORM DATA data', data) for (const [key, value] of data) { const hasMultipleValues = data.getAll(key).length > 1 objectSet(record, key.split('.').map((it) => /^\d+$/g.test(it) ? parseInt(it, 10) : it), hasMultipleValues ? data.getAll(key) : value) } // quick hack to handle FormData not returning Checkboxes const handleBoolean = (value: SchemaItem, keys: Array) => { if (value instanceof SchemaNullable) { handleBoolean(value.unwrap(), keys) } if (value instanceof SchemaArray) { const elements: Array | undefined = objectGet(record, keys) for (let it = 0; it < (elements?.length ?? 0); it++) { handleBoolean(value.unwrap(), [...keys, it]) } } if (value instanceof SchemaObject) { handleSchemaForBoolean(value.model as Record, keys) } if (value instanceof SchemaBoolean) { objectSet(record, keys, !!data.get(keys.join('.'))) } } const handleSchemaForBoolean = (modl: Record, keys: Array = []) => { objectLoop(modl, (value, key) => { handleBoolean(value as unknown as SchemaItem, [...keys, key]) }) } if (model instanceof SchemaObject) { handleSchemaForBoolean(model.model) } return model.parse(record, opts) as ReturnType } export function parseForm(model: T, form: HTMLFormElement, opts?: Parameters[1]): ReturnType { return parseFormData(model, new FormData(form), opts) }