import type { Fun, Nested, DurableState, MutableState, EventState, NestedFun, DurableFun, MutableArgs, EventArgs } from './types' export * from './types' export function nested(init: NestedFun) { const self = ((key, ...args) => { if (!self.map.has(key)) self.map.set(key, init(key, ...args)) return self.map.get(key) }) as Nested self.map = new Map() self.has = (key = '') => self.map.has(key) return self } export const durable = (fun: DurableFun, ret?: Ret) => { const self = (arg: T, ...args: unknown[]) => { if (arg !== Object(arg)) fun(arg as any, ...args) else for (const key in arg) fun(key, arg[key], ...args) return ret ?? self } return self as DurableState } export const mutable = (...args: MutableArgs | []) => { const map = new Map() const memo = durable((key, fun) => { // @ts-ignore if (typeof fun !== 'function') return (memo[key] = fun) // @ts-ignore if (!map.has(key)) memo[key] = (...args: any[]) => map.get(key)?.(...args) map.set(key, fun as Fun) }) as MutableState if (args.length) memo(...(args as any)) return memo } export function event(...args: EventArgs | []) { const set = nested(() => new Set()) const self = durable((key, fun) => { // @ts-ignore if (typeof fun !== 'function') return (self[key] = fun) if (!set.has(key)) // @ts-ignore self[key] = (...args: any[]) => { set(key).forEach((fun) => fun(...args)) } if (set(key).has(fun)) { set(key).delete(fun) } else set(key).add(fun) }) as EventState if (args.length) self(...(args as any)) return self } export default event