65 lines
2.4 KiB
TypeScript
65 lines
2.4 KiB
TypeScript
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<T extends SchemaItem>(model: T, query: URLSearchParams, opts?: Parameters<T['parse']>[1]): ReturnType<T['parse']> {
|
|
const record: Record<string, unknown> = {}
|
|
for (const [key, value] of query) {
|
|
record[key] = value
|
|
}
|
|
|
|
return model.parse(record, opts) as ReturnType<T['parse']>
|
|
}
|
|
|
|
export function parseFormData<T extends SchemaItem>(model: T, data: FormData, opts?: Parameters<T['parse']>[1]): ReturnType<T['parse']> {
|
|
const record: Record<string, unknown> = {}
|
|
// 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<string | number>) => {
|
|
if (value instanceof SchemaNullable) {
|
|
handleBoolean(value.unwrap(), keys)
|
|
}
|
|
|
|
if (value instanceof SchemaArray) {
|
|
const elements: Array<unknown> | 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<string, SchemaItem>, keys)
|
|
}
|
|
|
|
if (value instanceof SchemaBoolean) {
|
|
objectSet(record, keys, !!data.get(keys.join('.')))
|
|
}
|
|
}
|
|
const handleSchemaForBoolean = (modl: Record<string, SchemaItem>, keys: Array<string | number> = []) => {
|
|
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<T['parse']>
|
|
}
|
|
|
|
export function parseForm<T extends SchemaItem>(model: T, form: HTMLFormElement, opts?: Parameters<T['parse']>[1]): ReturnType<T['parse']> {
|
|
return parseFormData(model, new FormData(form), opts)
|
|
}
|