import { pipe, Predicate } from 'fp-ts/function' import * as RA from 'fp-ts/ReadonlyArray' import * as RR from 'fp-ts/ReadonlyRecord' import * as S from 'fp-ts/struct' import { IntersectionDeep, PartialDeep } from '.' import { curry } from './function' import * as $t from './Type' export type Struct = object /** * @deprecated Use `Struct` instead */ // eslint-disable-next-line @typescript-eslint/ban-types export type struct = object export const toReadonlyArray = ( a: A, ): ReadonlyArray> => RR.toReadonlyArray(a) export const lookup = (k: K) => (s: S): S[K] => s[k] export const modifyAt = (k: K, f: (a: S[K]) => S[K]) => (s: S): S => ({ ...s, [k]: f(s[k]) }) export const updateAt = (k: K, a: S[K]) => modifyAt(k, () => a) export const filterDeep = (f: Predicate*/>) => (a: A): PartialDeep => pipe( a, toReadonlyArray, RA.filter(([_, value]) => (f as Predicate)(value)), RA.map(([key, value]) => $t.struct.is(value) ? ([ key, pipe( value, filterDeep( f as Predicate*/>, ), ), ] as const) : ([key, value] as const), ), RA.reduce({} as PartialDeep, (b, [key, value]) => ({ ...b, [key]: value, })), ) export const patch = & Struct>(b: B) => (a: A): IntersectionDeep => pipe( b, toReadonlyArray, RA.map(([key, b]) => $t.struct.is(b) ? ([key, patch(b)(a[key as keyof A] as A[keyof A] & Struct)] as const) : ([key, b] as const), ), RA.reduce({} as IntersectionDeep, (ab, [key, b]) => ({ ...ab, [key]: b, })), curry(S.getAssignSemigroup>().concat)( a as IntersectionDeep, ), )