import hash , { HashResult } from '@rakered/hash' ; const parsers = { 'datetime-local' : ( el ) => ( el . value === '' ? undefined : new Date ( el . value ) ) , checkbox : ( el ) => Boolean ( el . checked ) && el . value !== 'on' ? el . value : Boolean ( el . checked ) , number : ( el ) => ( el . value === '' ? undefined : Number ( el . value ) ) , password : ( el ) => ( el . value === '' ? undefined : hash ( el . value ) ) , radio : ( el ) => ( el . checked ? el . value : undefined ) , range : ( el ) => ( el . value === '' ? undefined : Number ( el . value ) ) , text : ( el ) => el . value . trim ( ) , } ; export type HashedPassword = HashResult ; export interface Event { readonly currentTarget : EventTarget | null ; preventDefault ( ) : void ; } export type DataType = string | number | boolean | Date | HashedPassword | FormData ; export interface FormData { [ key ] : DataType | DataType [ ] ; } export function getFormData < T extends FormData > ( target ) { const form = 'currentTarget' in target ? target . currentTarget : target ; const elements = form . elements ; const data = { } ; for ( const element of elements ) { if ( ! element . name ) { continue ; } const parse = parsers [ element . type ] || parsers . text ; const value = parse ( element ) ?? undefined ; if ( typeof value === 'undefined' ) { continue ; } const path = element . name . replace ( /\[([^\]]+)?\]/g , '.$1' ) . split ( '.' ) ; let pointer = data ; for ( let i = 0 ; i < path . length - 1 ; i ++ ) { pointer [ path [ i ] ] = pointer [ path [ i ] ] || ( /^$|^[0-9]*$/ . test ( path [ i + 1 ] ) ? [ ] : { } ) ; pointer = pointer [ path [ i ] ] ; } if ( Array . isArray ( pointer ) ) { if ( typeof value === 'boolean' ) { continue ; } pointer . push ( value ) ; } else { pointer [ path [ path . length - 1 ] ] = value ; } } return data as T ; }