@constellar/core
Version:
state manipulation primitives
1 lines • 67.5 kB
Source Map (JSON)
{"version":3,"file":"index.cjs","sources":["../src/machines/core.ts","../src/utils/arrays/index.ts","../src/utils/functions/flow.ts","../src/utils/functions/guards.ts","../src/utils/functions/misc.ts","../src/utils/functions/pipe.ts","../src/utils/functions/shallowEqual.ts","../src/machines/effects.ts","../src/machines/listener.ts","../src/machines/multi-state.ts","../src/machines/utils.ts","../src/machines/object.ts","../src/machines/simple-state.ts","../src/optics/collections/index.ts","../src/optics/core/index.ts","../src/optics/extra/index.ts"],"sourcesContent":["import { Typed } from '../utils'\n\nexport interface IMachine<\n\tEvent,\n\tState,\n\tRWCtx extends unknown[],\n\tTransformed,\n\tSubState,\n\tFinal,\n> {\n\tgetFinal: (transformed: Transformed) => Final | undefined\n\tinit: () => State\n\treducer: (\n\t\tevent: Event,\n\t\ttransformed: Transformed,\n\t\t...args: RWCtx\n\t) => State | undefined\n\ttransform: (state: State) => Transformed\n\tvisit: <Acc>(\n\t\tacc: Acc,\n\t\tfold: (subState: SubState, acc: Acc, index: string) => Acc,\n\t\ttransformed: Transformed,\n\t) => Acc\n}\n\nexport type MessageCtx<Message extends Typed> = [\n\t(emit: Sendable<Message>) => void,\n]\n\n// when event is just { type: string }, we can use string as shorthand\nexport type Sendable<T extends Typed> =\n\t| T\n\t| (T extends { type: infer U }\n\t\t\t? { type: U } extends T\n\t\t\t\t? U\n\t\t\t\t: never\n\t\t\t: T extends void\n\t\t\t\t? void\n\t\t\t\t: never)\n\nexport function fromSendable<Event extends Typed>(\n\tevent: Sendable<Event>,\n): Event {\n\treturn typeof event === 'string'\n\t\t? // Sendable type guarantees that resulting event is valid\n\t\t\t({ type: event } as unknown as Event)\n\t\t: event\n}\n\nexport function withSend<Event extends Typed>(emit: (event: Event) => void) {\n\treturn (e: Sendable<Event>) => emit(fromSendable(e)) as undefined\n}\n","// since Array.prototype.splice is not available on Hermes\n\nexport function prepend<T>(x: T, xs: T[]) {\n\treturn [x, ...xs]\n}\n\nexport function append<T>(x: T, xs: T[]) {\n\treturn [...xs, x]\n}\n\nexport function insert<T>(index: number, x: T, xs: T[]) {\n\tif (index < 0) index += xs.length\n\tif (index < 0) return xs\n\tif (index > xs.length) return xs\n\treturn [...xs.slice(0, index), x, ...xs.slice(index)]\n}\n\nexport function replace<T>(x: T, index: number, xs: T[]) {\n\tif (index < 0) index += xs.length\n\tif (index < 0) return xs\n\tif (index >= xs.length) return xs\n\tif (Object.is(xs[index], x)) return xs\n\treturn [...xs.slice(0, index), x, ...xs.slice(index + 1)]\n}\n\nexport function remove<T>(index: number, xs: T[]) {\n\tif (index < 0) index += xs.length\n\tif (index < 0) return xs\n\tif (index >= xs.length) return xs\n\treturn [...xs.slice(0, index), ...xs.slice(index + 1)]\n}\n\nexport function insertValue<X>(element: X, xs: X[]) {\n\tfor (const x of xs) {\n\t\tif (Object.is(x, element)) return xs\n\t}\n\treturn xs.concat(element)\n}\n\nexport function removeValue<X>(element: X, xs: X[]) {\n\tlet dirty = false\n\tconst res: X[] = []\n\tfor (const x of xs) {\n\t\tif (Object.is(x, element)) {\n\t\t\tdirty = true\n\t\t} else res.push(x)\n\t}\n\treturn dirty ? res : xs\n}\n","export function flow<TArgs, R1, R2, R3, R4, R5, R6, R7>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n\tf6: (a: R5) => R6,\n\tf7: (a: R6) => R7,\n): R7\nexport function flow<TArgs, R1, R2, R3, R4, R5, R6>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n\tf6: (a: R5) => R6,\n): R6\nexport function flow<TArgs, R1, R2, R3, R4, R5>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n): R5\nexport function flow<TArgs, R1, R2, R3, R4>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n): R4\nexport function flow<TArgs, R1, R2, R3>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n): R3\nexport function flow<TArgs, R1, R2>(\n\targs: TArgs,\n\tf1: (args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n): R2\nexport function flow<TArgs, R1>(args: TArgs, f1: (args: TArgs) => R1): R1\n\n// definition here: https://blog.logrocket.com/how-to-create-compose-function-typescript\nexport function flow<T>(args: T, ...fns: Array<(a: T) => T>) {\n\treturn fns.reduce((acc, cb) => cb(acc), args)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nexport function isFunction<T>(x: T): x is ((...args: any[]) => any) & T {\n\treturn typeof x === 'function'\n}\n\nexport function isUndefined(v: unknown): v is undefined {\n\treturn v === undefined\n}\n\nexport function isNever(_v: unknown): _v is never {\n\treturn false\n}\n","import { Init } from '..'\nimport { isFunction } from './guards'\n\nexport const noop = () => {}\n\nexport function apply<P, Q>(f: (p: P) => Q, p: P) {\n\treturn f(p)\n}\n\nexport function id<T>(t: T) {\n\treturn t\n}\n\nexport function pipe2<P, Q, R>(f: (p: P) => Q, g: (q: Q) => R): (p: P) => R {\n\tif (f === id) return g as unknown as (p: P) => R\n\tif (g === id) return f as unknown as (p: P) => R\n\treturn (p: P) => g(f(p))\n}\n\nexport function fromInit<T>(init: Init<T, void>): T {\n\treturn isFunction(init) ? init() : init\n}\n\nexport function toInit<T, P = void>(init: Init<T, P>): (p: P) => T {\n\treturn isFunction(init) ? (p) => init(p) : () => init\n}\n\nexport function isEmpty(obj?: object) {\n\tif (!obj) return true\n\tfor (const _ of Object.keys(obj)) {\n\t\treturn false\n\t}\n\treturn true\n}\n\nexport function curry1<A, Args extends unknown[], R>(\n\tf: (...args: [A, ...Args]) => R,\n) {\n\treturn function (a: A) {\n\t\treturn function (...args: Args) {\n\t\t\treturn f(a, ...args)\n\t\t}\n\t}\n}\n\nexport function curry<P extends unknown[], Q extends unknown[], R>(\n\tf: (...args: [...P, ...Q]) => R,\n\t...args: P\n) {\n\treturn (...args2: Q) => f(...args, ...args2)\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n// types from https://github.com/selfrefactor/rambda/blob/master/index.d.ts\n// types from rambda\nexport function pipe<TArgs extends any[], R1, R2, R3, R4, R5, R6, R7, TResult>(\n\t...funcs: [\n\t\tf1: (...args: TArgs) => R1,\n\t\tf2: (a: R1) => R2,\n\t\tf3: (a: R2) => R3,\n\t\tf4: (a: R3) => R4,\n\t\tf5: (a: R4) => R5,\n\t\tf6: (a: R5) => R6,\n\t\tf7: (a: R6) => R7,\n\t\t...func: Array<(a: any) => any>,\n\t\tfnLast: (a: any) => TResult,\n\t]\n): (...args: TArgs) => TResult // fallback overload if number of piped functions greater than 7\nexport function pipe<TArgs extends any[], R1, R2, R3, R4, R5, R6, R7>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n\tf6: (a: R5) => R6,\n\tf7: (a: R6) => R7,\n): (...args: TArgs) => R7\nexport function pipe<TArgs extends any[], R1, R2, R3, R4, R5, R6>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n\tf6: (a: R5) => R6,\n): (...args: TArgs) => R6\nexport function pipe<TArgs extends any[], R1, R2, R3, R4, R5>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n\tf5: (a: R4) => R5,\n): (...args: TArgs) => R5\nexport function pipe<TArgs extends any[], R1, R2, R3, R4>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n\tf4: (a: R3) => R4,\n): (...args: TArgs) => R4\nexport function pipe<TArgs extends any[], R1, R2, R3>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n\tf3: (a: R2) => R3,\n): (...args: TArgs) => R3\nexport function pipe<TArgs extends any[], R1, R2>(\n\tf1: (...args: TArgs) => R1,\n\tf2: (a: R1) => R2,\n): (...args: TArgs) => R2\nexport function pipe<TArgs extends any[], R1>(\n\tf1: (...args: TArgs) => R1,\n): (...args: TArgs) => R1\n\n// definition here: https://blog.logrocket.com/how-to-create-compose-function-typescript\nexport function pipe<T>(fn1: (a: T) => T, ...fns: Array<(a: T) => T>) {\n\treturn fns.reduce((prevFn, nextFn) => (value) => nextFn(prevFn(value)), fn1)\n}\n","// taken from https://romgrk.com/posts/react-fast-memo/\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nexport function shallowEqual(a: any, b: any) {\n\tif (a === b) {\n\t\treturn true\n\t}\n\tif (!(a instanceof Object) || !(b instanceof Object)) {\n\t\treturn false\n\t}\n\n\tlet aLength = 0\n\tlet bLength = 0\n\n\tfor (const key in a) {\n\t\taLength += 1\n\n\t\tif (!Object.is(a[key], b[key])) {\n\t\t\treturn false\n\t\t}\n\t\tif (!(key in b)) {\n\t\t\treturn false\n\t\t}\n\t}\n\n\tfor (const _ in b) {\n\t\tbLength += 1\n\t}\n\n\treturn aLength === bLength\n}\n","import { shallowEqual } from '../utils'\n\n/* eslint-disable @typescript-eslint/no-explicit-any */\n\nexport type EffectsHandlers<Event, SubState> = SubState extends {\n\teffects?: unknown\n}\n\t? {\n\t\t\t[Key in keyof Exclude<SubState['effects'], undefined>]: (\n\t\t\t\te: Exclude<Exclude<SubState['effects'], undefined>[Key], undefined>,\n\t\t\t\tsend: (event: Event) => void,\n\t\t\t) => (() => void) | void\n\t\t}\n\t: never\n\nexport class MachineEffects<Event, SubState> {\n\tprivate last = new Map<\n\t\tstring,\n\t\tMap<string, { args: any; unmount: (() => void) | void }>\n\t>()\n\tconstructor(private effectsHandlers: EffectsHandlers<Event, SubState>) {}\n\tprivate foldSubState(send: (event: Event) => void) {\n\t\treturn (subState: SubState, acc: Set<string>, index: string) => {\n\t\t\tif (this.effectsHandlers === undefined) return acc\n\t\t\tacc.add(index)\n\t\t\tfor (const entry of Object.entries(this.effectsHandlers)) {\n\t\t\t\tconst [effect, cb] = entry as [string, any]\n\t\t\t\tconst args = ((subState as any).effects as any)?.[effect]\n\t\t\t\tlet fromIndex = this.last.get(index)\n\t\t\t\tif (!fromIndex) {\n\t\t\t\t\tfromIndex = new Map()\n\t\t\t\t\tthis.last.set(index, fromIndex)\n\t\t\t\t}\n\t\t\t\tconst last = fromIndex.get(effect)\n\t\t\t\tif (shallowEqual(last?.args, args)) continue\n\t\t\t\tlast?.unmount?.()\n\t\t\t\tfromIndex.set(effect, {\n\t\t\t\t\targs,\n\t\t\t\t\tunmount: args === undefined ? undefined : cb(args, send),\n\t\t\t\t})\n\t\t\t}\n\t\t\treturn acc\n\t\t}\n\t}\n\tflush(indices?: Set<string>) {\n\t\tthis.last.forEach((fromIndex, index) => {\n\t\t\tif (indices?.has(index)) return\n\t\t\tfromIndex.forEach(({ unmount }) => unmount?.())\n\t\t\tfromIndex.clear()\n\t\t})\n\t}\n\tupdate(\n\t\tvisit: (\n\t\t\tf: (subState: SubState, acc: Set<string>, index: string) => Set<string>,\n\t\t\tacc: Set<string>,\n\t\t) => Set<string>,\n\t\tsend: (event: Event) => void,\n\t) {\n\t\tthis.flush(visit(this.foldSubState(send), new Set<string>()))\n\t}\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\n\nimport { isFunction, Typed } from '../utils'\nimport { fromSendable, Sendable } from './core'\n\nexport type Listener<Message extends Typed> =\n\t| ((message: Message) => void)\n\t| {\n\t\t\t[K in Message['type']]: (message: { type: K } & Message) => void\n\t }\n\nexport function toListener<Message extends Typed>(\n\tlistener: Listener<Message>,\n): (message: Sendable<Message>) => void {\n\tif (isFunction(listener))\n\t\treturn (message: Sendable<Message>) => listener(fromSendable(message))\n\treturn (message) => {\n\t\tconst m = fromSendable(message)\n\t\t;(listener as any)[m.type](m)\n\t}\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { fromSendable, IMachine, MessageCtx, Sendable } from '.'\nimport { Init, isEmpty, isFunction, Prettify, toInit, Typed } from '../utils'\n\ntype ArgOfInit<T> = T extends (p: infer R) => any ? R : void\n\ntype AnyStates<\n\tEvent extends Typed,\n\tState extends Typed,\n\tCtx extends unknown[],\n\tDerivedLocal,\n\tDerived,\n> = {\n\t[StateType in State['type']]: {\n\t\talways?:\n\t\t\t| (<S extends { type: StateType } & Derived & DerivedLocal & State>(\n\t\t\t\t\tstate: S,\n\t\t\t ) => Sendable<State> | undefined)\n\t\t\t| Sendable<State>\n\t\tevents?: Partial<{\n\t\t\t[EventType in Event['type']]:\n\t\t\t\t| (<\n\t\t\t\t\t\tE extends { type: EventType } & Event,\n\t\t\t\t\t\tS extends { type: StateType } & Derived & DerivedLocal & State,\n\t\t\t\t >(\n\t\t\t\t\t\tevent: E,\n\t\t\t\t\t\tstate: S,\n\t\t\t\t\t\t...args: Ctx\n\t\t\t\t ) => Sendable<State> | undefined | void)\n\t\t\t\t| Sendable<State>\n\t\t}>\n\t\twildcard?:\n\t\t\t| (<\n\t\t\t\t\tE extends { type: Event } & Event,\n\t\t\t\t\tS extends { type: StateType } & Derived & DerivedLocal & State,\n\t\t\t >(\n\t\t\t\t\tevent: E,\n\t\t\t\t\tstate: S,\n\t\t\t\t\t...args: Ctx\n\t\t\t ) => Sendable<State> | undefined | void)\n\t\t\t| Sendable<State>\n\t}\n} & (DerivedLocal extends { [K in keyof DerivedLocal]: never }\n\t? { [StateType in State['type']]: object }\n\t: {\n\t\t\t[StateType in State['type']]: {\n\t\t\t\tderive:\n\t\t\t\t\t| ((state: Prettify<{ type: StateType } & State>) => DerivedLocal)\n\t\t\t\t\t| DerivedLocal\n\t\t\t}\n\t\t})\n\ntype AnyMachine<\n\tEvent extends Typed,\n\tState extends Typed,\n\tCtx extends unknown[] = [],\n\tDerivedLocal = object,\n\tDerived = object,\n> = {\n\tderive?: ((s: Prettify<DerivedLocal & State>) => Derived) | Derived\n\tinit: Init<Sendable<State>, any>\n\tstates: AnyStates<Event, State, Ctx, DerivedLocal, Derived>\n}\n\nexport type IsFinal<\n\tType extends string,\n\tStates extends Record<Type, unknown>,\n> = States[Type] extends {\n\talways: unknown\n}\n\t? never\n\t: States[Type] extends { wildcard: unknown }\n\t\t? never\n\t\t: States[Type] extends { events: unknown }\n\t\t\t? keyof States[Type]['events'] extends never\n\t\t\t\t? { type: Type }\n\t\t\t\t: never\n\t\t\t: { type: Type }\n\ntype FinalStatesByKey<States extends Record<string, unknown>> = {\n\t[Type in keyof States & string]: IsFinal<Type, States>\n}\ntype FinalStates<States extends Record<string, unknown>> =\n\tFinalStatesByKey<States>[keyof States & string]\n\ntype Final<\n\tState extends Typed,\n\tStates extends Record<string, unknown>,\n> = FinalStates<States> & State\n\nexport function multiStateMachine<\n\tEvent extends Typed,\n\tState extends Typed,\n\tDerivedLocal = object,\n\tDerived = object,\n\tMessage extends Typed = { type: never },\n>() {\n\treturn multiStateBaseMachine<\n\t\tEvent,\n\t\tState,\n\t\tDerivedLocal,\n\t\tDerived,\n\t\tMessageCtx<Message>\n\t>()\n}\n\nexport function multiStateBaseMachine<\n\tEvent extends Typed,\n\tState extends Typed,\n\tDerivedLocal,\n\tDerived,\n\tCtx extends unknown[],\n>() {\n\treturn function <\n\t\tMachine extends AnyMachine<Event, State, Ctx, DerivedLocal, Derived>,\n\t>({ derive, init, states }: Machine) {\n\t\tconst init0 = toInit(init)\n\t\tfunction fromAlways(s: State) {\n\t\t\twhile (true) {\n\t\t\t\tlet s_ = (states as any)[s.type].always\n\t\t\t\tif (s_ === undefined) break\n\t\t\t\tif (isFunction(s_)) s_ = s_(s)\n\t\t\t\tif (s_ === undefined) break\n\t\t\t\ts = s_\n\t\t\t}\n\t\t\treturn s\n\t\t}\n\t\ttype Transformed = Derived & DerivedLocal & State\n\t\treturn function (\n\t\t\tinitialArg: ArgOfInit<Machine['init']>,\n\t\t): IMachine<\n\t\t\tSendable<Event>,\n\t\t\tState,\n\t\t\tCtx,\n\t\t\tTransformed,\n\t\t\tTransformed,\n\t\t\tPrettify<Final<State, Machine['states']>>\n\t\t> {\n\t\t\treturn {\n\t\t\t\tgetFinal: (s) => {\n\t\t\t\t\tconst state = (states as any)[s.type]\n\t\t\t\t\tif (state.always) return undefined\n\t\t\t\t\tif (state.wildcard) return undefined\n\t\t\t\t\tif (!isEmpty(state.events)) return undefined\n\t\t\t\t\treturn s as any\n\t\t\t\t},\n\t\t\t\tinit: () => fromAlways(fromSendable(init0(initialArg))),\n\t\t\t\treducer: (event, s, ...args) => {\n\t\t\t\t\tconst e = fromSendable(event)\n\t\t\t\t\tconst state = (states as any)[s.type]\n\t\t\t\t\tlet res = state?.events?.[e.type]\n\t\t\t\t\tif (isFunction(res)) res = res(e, s, ...args)\n\t\t\t\t\telse if (res === undefined) {\n\t\t\t\t\t\tres = state?.wildcard\n\t\t\t\t\t\tif (isFunction(res)) res = res(e, s, ...args)\n\t\t\t\t\t}\n\t\t\t\t\tif (res === undefined) return undefined\n\t\t\t\t\treturn fromAlways(fromSendable(res))\n\t\t\t\t},\n\t\t\t\ttransform: (s, ...args) => {\n\t\t\t\t\tconst localDerive = (states as any)[s.type].derive\n\t\t\t\t\tconst d1 = localDerive\n\t\t\t\t\t\t? join(s, localDerive, ...args)\n\t\t\t\t\t\t: (s as DerivedLocal & State)\n\t\t\t\t\tconst d2 = derive\n\t\t\t\t\t\t? join(d1, derive, ...args)\n\t\t\t\t\t\t: (d1 as Derived & DerivedLocal & State)\n\t\t\t\t\treturn d2\n\t\t\t\t},\n\t\t\t\tvisit: (acc, fold, state, ...args) =>\n\t\t\t\t\tfold(state, acc, state.type, ...args),\n\t\t\t}\n\t\t}\n\t}\n}\n\nfunction join<A, B, Ctx extends unknown[]>(\n\ta: A,\n\tb: ((a: A, ...args: Ctx) => B) | B,\n\t...args: Ctx\n): A & B {\n\tconst x = isFunction(b) ? b(a, ...args) : b\n\treturn { ...a, ...x }\n}\n","import { Typed } from '../utils'\nimport { IMachine, MessageCtx } from './core'\n\nexport function isDisabled<\n\tEvent,\n\tState,\n\tMessage extends Typed,\n\tTransformed,\n\tSubState,\n\tFinal,\n>(\n\tmachine: IMachine<\n\t\tEvent,\n\t\tState,\n\t\tMessageCtx<Message>,\n\t\tTransformed,\n\t\tSubState,\n\t\tFinal\n\t>,\n\ttransformed: Transformed,\n\tevent: Event,\n) {\n\tlet touched = false\n\tconst res = machine.reducer(event, transformed, () => {\n\t\ttouched = true\n\t})\n\treturn !touched && res === undefined\n}\n\nexport function nextState<\n\tEvent,\n\tState,\n\tMessage extends Typed,\n\tTransformed,\n\tSubState,\n\tFinal,\n>(\n\tmachine: IMachine<\n\t\tEvent,\n\t\tState,\n\t\tMessageCtx<Message>,\n\t\tTransformed,\n\t\tSubState,\n\t\tFinal\n\t>,\n\ttransformed: Transformed,\n\tevent: Event,\n) {\n\tconst nextState = machine.reducer(event, transformed, () => {})\n\tif (nextState === undefined) return transformed\n\treturn machine.transform(nextState)\n}\n","import { Typed } from '../utils'\nimport { IMachine, MessageCtx, Sendable } from './core'\nimport { EffectsHandlers, MachineEffects } from './effects'\nimport { Listener, toListener } from './listener'\nimport { isDisabled, nextState } from './utils'\n\nclass ObjectMachine<\n\tEvent,\n\tState,\n\tMessage extends Typed,\n\tTransformed,\n\tSubState,\n\tFinal,\n> {\n\tprivate effects: MachineEffects<Event, SubState> | undefined\n\tprivate onFinal?: (final: Final) => void\n\tprivate onMessage: (event: Sendable<Message>) => void\n\tprivate queue: Event[] = []\n\tpublic final: Final | undefined\n\tpublic state: Transformed\n\tconstructor(\n\t\tprivate machine: IMachine<\n\t\t\tEvent,\n\t\t\tState,\n\t\t\tMessageCtx<Message>,\n\t\t\tTransformed,\n\t\t\tSubState,\n\t\t\tFinal\n\t\t>,\n\t\topts?: {\n\t\t\tevents?: EffectsHandlers<Event, SubState>\n\t\t\tonFinal?: (final: Final) => void\n\t\t\tonMessage?: Listener<Message>\n\t\t},\n\t) {\n\t\tthis.onMessage = opts?.onMessage ? toListener(opts.onMessage) : () => {}\n\t\tthis.onFinal = opts?.onFinal\n\t\tthis.state = machine.transform(machine.init())\n\t\tthis.final = machine.getFinal(this.state)\n\t\tif (opts?.events) {\n\t\t\tthis.effects = new MachineEffects(opts.events)\n\t\t\tthis.effects.update(this.visit.bind(this), this.send.bind(this))\n\t\t}\n\t}\n\tprivate onChange() {\n\t\tif (!this.effects) return\n\t\tconst run = this.queue.length === 0\n\t\tthis.effects.update(this.visit.bind(this), this.send.bind(this))\n\t\tif (!run) return\n\t\twhile (true) {\n\t\t\tconst event = this.queue.shift()\n\t\t\tif (event === undefined) break\n\t\t\tthis.send(event)\n\t\t}\n\t}\n\tflush() {\n\t\tthis.effects?.flush()\n\t}\n\tisDisabled(event: Event) {\n\t\treturn isDisabled(this.machine, this.state, event)\n\t}\n\tnext(event: Event) {\n\t\treturn nextState(this.machine, this.state, event)\n\t}\n\tsend(event: Event) {\n\t\tconst state = this.machine.reducer(event, this.state, this.onMessage)\n\t\tif (state !== undefined) {\n\t\t\tthis.state = this.machine.transform(state)\n\t\t\tthis.final = this.machine.getFinal(this.state)\n\t\t\tthis.onChange()\n\t\t\tif (this.onFinal && this.final !== undefined) this.onFinal(this.final)\n\t\t}\n\t}\n\tvisit<Acc>(\n\t\tfold: (subState: SubState, acc: Acc, index: string) => Acc,\n\t\tacc: Acc,\n\t) {\n\t\treturn this.machine.visit(acc, fold, this.state)\n\t}\n}\n\nexport function objectMachine<\n\tEvent,\n\tState,\n\tMessage extends Typed,\n\tTransformed,\n\tSubState,\n\tFinal,\n>(\n\tmachine: IMachine<\n\t\tEvent,\n\t\tState,\n\t\tMessageCtx<Message>,\n\t\tTransformed,\n\t\tSubState,\n\t\tFinal\n\t>,\n\topts?: {\n\t\tevents?: EffectsHandlers<Event, SubState>\n\t\tonFinal?: (final: Final) => void\n\t\tonMessage?: Listener<Message>\n\t},\n) {\n\treturn new ObjectMachine(machine, opts)\n}\n\nexport function promiseMachine<Event, State, Transformed, SubState, Final>(\n\tmachine: IMachine<\n\t\tEvent,\n\t\tState,\n\t\tMessageCtx<{ type: never }>,\n\t\tTransformed,\n\t\tSubState,\n\t\tFinal\n\t>,\n\tevents: EffectsHandlers<Event, SubState>,\n) {\n\treturn new Promise<Final>((resolve) => {\n\t\tnew ObjectMachine(machine, { events: events, onFinal: resolve })\n\t})\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport { fromSendable, IMachine, MessageCtx, Sendable } from '.'\nimport { id, Init, isFunction, Prettify, toInit, Typed } from '../utils'\n\ntype ExtractEvent<Transition> = Transition extends (\n\te: infer E,\n\t...args: any[]\n) => any\n\t? E\n\t: void\n\ntype UnionValues<T> = T extends Record<string, unknown> ? T[keyof T] : never\n\ntype ExtractEventObject<Transitions extends Record<string, unknown>> = {\n\t[K in keyof Transitions]: { type: K } & ExtractEvent<Transitions[K]>\n}\n\ntype ExtractEvents<Transitions extends Record<PropertyKey, unknown>> =\n\tUnionValues<ExtractEventObject<Transitions>>\n\ntype Transition<State, Transformed, Ctx extends unknown[]> =\n\t| ((e: any, s: Transformed, ...args: Ctx) => State | undefined)\n\t| State\n\ntype Transitions<State, Transformed, Ctx extends unknown[]> = Record<\n\tany,\n\tTransition<State, Transformed, Ctx>\n>\n\nexport function simpleStateMachine<Message extends Typed = { type: never }>() {\n\treturn simpleStateBaseMachine<MessageCtx<Message>>()\n}\n\nexport function simpleStateBaseMachine<RWCtx extends unknown[]>() {\n\treturn function <\n\t\tState,\n\t\tT extends Transitions<State, Transformed, RWCtx>,\n\t\tTransformed = State,\n\t\tInitialArg = void,\n\t\tFinal = never,\n\t>(\n\t\t{\n\t\t\tevents,\n\t\t\tinit,\n\t\t\ttransform,\n\t\t}: {\n\t\t\tevents: T\n\t\t\tinit: Init<State, InitialArg>\n\t\t\ttransform?: (s: State) => Transformed\n\t\t},\n\t\tgetFinal?: (s: Transformed) => Final | undefined,\n\t) {\n\t\treturn (\n\t\t\tinitialArg: InitialArg,\n\t\t): IMachine<\n\t\t\tSendable<Prettify<ExtractEvents<T>> & Typed>,\n\t\t\tState,\n\t\t\tRWCtx,\n\t\t\tTransformed,\n\t\t\tTransformed,\n\t\t\tFinal\n\t\t> => {\n\t\t\treturn {\n\t\t\t\tgetFinal: getFinal ?? (() => undefined),\n\t\t\t\tinit: () => toInit(init)(initialArg),\n\t\t\t\treducer: (event, transformed, ...ctx) => {\n\t\t\t\t\tconst e = fromSendable(event as any)\n\t\t\t\t\tif (getFinal?.(transformed) !== undefined) return undefined\n\t\t\t\t\t// we want to pass through unknown events\n\t\t\t\t\tlet res = events[e?.type] as any\n\t\t\t\t\tif (res === undefined) return undefined\n\t\t\t\t\tif (isFunction(res)) res = res(e, transformed, ...ctx)\n\t\t\t\t\treturn res\n\t\t\t\t},\n\t\t\t\ttransform: transform ?? (id as any),\n\t\t\t\tvisit: (acc, fold, state, ...args) => fold(state, acc, '', ...args),\n\t\t\t}\n\t\t}\n\t}\n}\n","import { Init, noop } from '../../utils'\n\nexport type UnfoldForm<Part, Index> = () =>\n\t| { index: Index; part: Part }\n\t| undefined\n\nexport type Unfolder<Part, Whole, Index> = (w: Whole) => UnfoldForm<Part, Index>\n\nexport const fromArray = <T>(xs: T[]): UnfoldForm<T, number> => {\n\tlet index = 0\n\treturn function () {\n\t\tif (index === xs.length) return undefined\n\t\treturn { index, part: xs[index++]! }\n\t}\n}\n\nexport function toArray<V>(): FoldForm<V, V[], Ctx> {\n\treturn {\n\t\tfoldFn: (v, acc) => {\n\t\t\tacc.push(v)\n\t\t\treturn acc\n\t\t},\n\t\tinit: () => [],\n\t}\n}\n\nexport function toFirst<Part, Fail, Ctx extends { close: () => void }>(\n\tfail: Fail,\n): FoldForm<Part, Fail | Part, Ctx> {\n\treturn {\n\t\tfoldFn: (p, _, { close }) => (close(), p),\n\t\tinit: fail,\n\t}\n}\n\nexport type Ctx = { close: () => void }\n\nexport const ctxNull: Ctx = { close: noop }\n\n// TODO:\nexport interface ICtx<Whole, Index> {\n\tclose: () => void\n\tindex: Index\n\twhole: Whole\n}\n\nexport type FoldFn<Part, Acc, Ctx> = (p: Part, acc: Acc, ctx: Ctx) => Acc\nexport type Refold<Part, Whole, C> = <Acc>(\n\tfold: FoldFn<Part, Acc, C>,\n) => FoldFn<Whole, Acc, C>\n\nexport interface FoldForm<Part, Acc, C> {\n\tfoldFn: FoldFn<Part, Acc, C>\n\tinit: Init<Acc>\n}\n","/* eslint-disable @typescript-eslint/no-explicit-any */\nimport {\n\tapply,\n\tfromInit,\n\tid,\n\tInit,\n\tisFunction,\n\tisNever,\n\tisUndefined,\n\tModify,\n\tnoop,\n\tpipe2,\n} from '../../utils'\nimport {\n\tCtx,\n\tctxNull,\n\tFoldFn,\n\tFoldForm,\n\tICtx,\n\ttoFirst,\n\tUnfolder,\n} from '../collections'\n\nfunction foldFrom<Part, Whole, Acc, Index>(\n\tacc: Acc,\n\tfoldPart: (w: Part, acc: Acc, ctx: Ctx) => Acc,\n\twhole: Whole,\n\tunfolder: Unfolder<Part, Whole, Index>,\n\tonClose: () => void,\n) {\n\tconst unfold = unfolder(whole)\n\tlet alive = true\n\tconst ctx: ICtx<Whole, Index> = {\n\t\tclose: () => {\n\t\t\tonClose()\n\t\t\talive = false\n\t\t},\n\t\tindex: undefined as Index,\n\t\twhole,\n\t}\n\twhile (alive) {\n\t\tconst r = unfold()\n\t\tif (r === undefined) break\n\t\tctx.index = r.index\n\t\tacc = foldPart(r.part, acc, ctx)\n\t}\n\treturn acc\n}\n\nexport const REMOVE = Symbol('REMOVE')\nfunction isRemove(v: unknown) {\n\treturn v === REMOVE\n}\n\nexport function forbidden<Part, Whole>(_part: Part, _whole: Whole): Whole {\n\tthrow new Error('forbidden')\n}\n\n// S (setter) extends void | unknown; use `void` to represent a prism, `never` otherwise\nexport type PRISM = void\nexport type NON_PRISM = never\ntype Setter<Part, Whole, S> = (p: Part, w: S | Whole) => Whole\n\ntype Mapper<Part, Whole> = (mod: (p: Part) => Part, w: Whole) => Whole\ntype Com<Part, Whole> = (p: Part, w: Whole) => Whole\ntype Getter<Part, Whole, Fail> = (w: Whole) => Fail | Part\n\nexport interface IOptic<Part, Whole, Fail, Command, S> {\n\tcom: Com<Command, Whole>\n\tgetter?: Getter<Part, Whole, Fail>\n\tisCommand: (v: unknown) => v is Command\n\tisFailure: (v: unknown) => v is Fail\n\tmapper: Mapper<Part, Whole>\n\trefold: <Acc>(fold: FoldFn<Part, Acc, Ctx>) => FoldFn<Whole, Acc, Ctx>\n\tsetter?: Setter<Part, Whole, S>\n}\n\nexport class COptic<Part, Whole, Fail, Command, S>\n\timplements IOptic<Part, Whole, Fail, Command, S>\n{\n\tcom: Com<Command, Whole>\n\tgetter?: Getter<Part, Whole, Fail>\n\tisCommand: (v: unknown) => v is Command\n\tisFailure: (v: unknown) => v is Fail\n\tmapper: Mapper<Part, Whole>\n\trefold: <Acc>(fold: FoldFn<Part, Acc, Ctx>) => FoldFn<Whole, Acc, Ctx>\n\tsetter?: Setter<Part, Whole, S>\n\tconstructor(opts: {\n\t\tcom: Com<Command, Whole>\n\t\tgetter?: Getter<Part, Whole, Fail>\n\t\tisCommand: (v: unknown) => v is Command\n\t\tisFailure: (v: unknown) => v is Fail\n\t\tmapper: Mapper<Part, Whole>\n\t\trefold: <Acc>(fold: FoldFn<Part, Acc, Ctx>) => FoldFn<Whole, Acc, Ctx>\n\t\tsetter?: Setter<Part, Whole, S>\n\t}) {\n\t\tthis.com = opts.com\n\t\tthis.getter = opts.getter\n\t\tthis.isCommand = opts.isCommand\n\t\tthis.isFailure = opts.isFailure\n\t\tthis.mapper = opts.mapper\n\t\tthis.refold = opts.refold\n\t\tthis.setter = opts.setter\n\t}\n\tstatic eq<Whole>() {\n\t\treturn new COptic({\n\t\t\tcom: id,\n\t\t\tgetter: id<Whole>,\n\t\t\tisCommand: isNever,\n\t\t\tisFailure: isNever,\n\t\t\tmapper: apply,\n\t\t\trefold: id,\n\t\t\tsetter: id,\n\t\t})\n\t}\n\tcommand(token: Command, whole: Whole) {\n\t\treturn this.com(token, whole)\n\t}\n\tfold<Acc>(form: FoldForm<Part, Acc, Ctx>, whole: Whole) {\n\t\treturn this.refold(form.foldFn)(whole, fromInit(form.init), ctxNull)\n\t}\n\tmodify(mod: Modify<Part>, whole: Whole) {\n\t\treturn this.mapper(mod, whole)\n\t}\n\tput(part: Part, whole: S | Whole) {\n\t\tif (this.setter) return this.setter!(part, whole)\n\t\treturn this.mapper(() => part, whole as Whole)\n\t}\n\tupdate(arg: ((p: Part) => Part) | Command | Part) {\n\t\tif (this.isCommand(arg)) return (whole: Whole) => this.com(arg, whole)\n\t\tif (isFunction(arg)) return (whole: Whole) => this.modify(arg, whole)\n\t\treturn (whole: Whole) => this.put(arg, whole)\n\t}\n\tview<A = undefined>(\n\t\twhole: Whole,\n\t\tor?: Init<A, Fail>,\n\t): (Fail extends never ? never : A) | Part {\n\t\tconst res = this.getter\n\t\t\t? this.getter(whole)\n\t\t\t: this.fold(toFirst<Part, Fail, Ctx>(undefined as Fail), whole)\n\t\tif (this.isFailure(res)) {\n\t\t\tif (isFunction(or)) return or(res)\n\t\t\treturn or as any\n\t\t}\n\t\treturn res\n\t}\n}\n\nexport type Focus<Part, Whole, Fail, Command, T> = (\n\teq: COptic<Whole, Whole, never, never, void>,\n) => COptic<Part, Whole, Fail, Command, T>\n\nexport function focus<Whole>() {\n\treturn function <Part, Fail, Command, S>(\n\t\to: Focus<Part, Whole, Fail, Command, S>,\n\t) {\n\t\treturn o(COptic.eq<Whole>())\n\t}\n}\n\nfunction composeGetter<P, Q, R, F>(\n\tisFailure: (v: unknown) => v is F,\n\tf?: (p: P) => F | Q,\n\tg?: (q: Q) => R,\n): ((p: P) => F | R) | undefined {\n\tif (!f || !g) return undefined\n\tif (isFailure === isNever) return pipe2(f as any, g)\n\treturn function (p: P) {\n\t\tconst q = f(p)\n\t\tif (isFailure(q)) return q\n\t\treturn g(q)\n\t}\n}\n\nfunction composeFailure<F1, F2>(\n\tf1: (v: unknown) => v is F1,\n\tf2: (v: unknown) => v is F2,\n): (v: unknown) => v is F1 | F2 {\n\tif (f1 === isNever) return f2\n\tif (f2 === isNever) return f1\n\tif ((f1 as unknown) === f2) return f1\n\t/* c8 ignore start */\n\tthrow new Error('unexpected failure value')\n}\n/* c8 ignore stop */\n\nfunction composeMapper<Micro, Part, Whole>(\n\tthisMapper: Mapper<Part, Whole>,\n\toMapper: Mapper<Micro, Part>,\n): Mapper<Micro, Whole> {\n\tif (thisMapper === apply) return oMapper as any\n\treturn (f, w) => thisMapper((p) => oMapper(f, p), w)\n}\n\nfunction makeMapper<Part, Whole>(\n\tsetter: Setter<Part, Whole, NON_PRISM>,\n\tgetter: Getter<Part, Whole, never>,\n): (mod: (p: Part) => Part, w: Whole) => Whole {\n\tif (setter === id && getter === id) return id as any\n\tif (setter === id) return (f, w) => f(getter(w)) as any\n\tif (getter === id) return (f, w) => setter(f(w as any), w) as any\n\treturn (mod: (v: Part) => Part, w: Whole) => {\n\t\treturn setter(mod(getter(w)), w)\n\t}\n}\n\nfunction composeSetter<Whole, Mega, Fail, Part, SL>(\n\tlGetter: Getter<Whole, Mega, Fail> | undefined,\n\tlSetter: Setter<Whole, Mega, SL> | undefined,\n\trIsFailure: (v: unknown) => v is Fail,\n\trSetter: Setter<Part, Whole, NON_PRISM> | undefined,\n): Setter<Part, Mega, NON_PRISM & SL> | undefined {\n\tif (!lGetter || !lSetter || !rSetter) return undefined\n\tconst set: (p: Part, w: NON_PRISM | Whole, m: Mega | SL) => Mega =\n\t\tlSetter === id\n\t\t\t? (b, t) => rSetter(b, t) as any\n\t\t\t: (b, t, w) => lSetter(rSetter(b, t), w)\n\treturn (b, w) => {\n\t\tconst t = lGetter(w)\n\t\tif (rIsFailure(t)) return w\n\t\treturn set(b, t, w)\n\t}\n}\n\nfunction composePrismSetter<Whole, Mega, Fail, Part, SL>(\n\tlGetter: Getter<Whole, Mega, Fail> | undefined,\n\tlSetter: Setter<Whole, Mega, SL> | undefined,\n\trSetter: Setter<Part, Whole, PRISM>,\n): Setter<Part, Mega, PRISM & SL> | undefined {\n\tif (!lGetter || !lSetter || !rSetter) return undefined\n\tconst set: (p: Part, m: Mega | SL) => Mega =\n\t\tlSetter === id ? (b) => rSetter(b) as any : (b, w) => lSetter(rSetter(b), w)\n\treturn (b, w) => set(b, w)\n}\n\ninterface IOpticBase<Part, Whole, Fail, Command, S> {\n\tcommand: Com<Command, Whole>\n\tgetter?: Getter<Part, Whole, Fail>\n\tisCommand: (v: unknown) => v is Command\n\tisFailure: (v: unknown) => v is Fail\n\tmapper?: Mapper<Part, Whole>\n\trefold?: <Acc>(mod: FoldFn<Part, Acc, Ctx>) => FoldFn<Whole, Acc, Ctx>\n\tsetter?: Setter<Part, Whole, S>\n}\n\ninterface IOptional<Part, Whole, Fail, Command, S>\n\textends IOpticBase<Part, Whole, Fail, Command, S> {\n\tgetter: Getter<Part, Whole, Fail>\n\tsetter: Setter<Part, Whole, S>\n}\ninterface ITraversal<Part, Whole, Fail, Command>\n\textends IOpticBase<Part, Whole, Fail, Command, NON_PRISM> {\n\tmapper: Mapper<Part, Whole>\n\trefold: <Acc>(foldPart: FoldFn<Part, Acc, Ctx>) => FoldFn<Whole, Acc, Ctx>\n}\n\ntype IOpticArgs<Part, Whole, Fail, Command, S> =\n\t| IOptional<Part, Whole, Fail, Command, S>\n\t| ITraversal<Part, Whole, Fail, Command>\n\nexport function opticPrism<Part, Whole, Fail, Command>(\n\tr: IOptional<Part, Whole, Fail, Command, PRISM>,\n) {\n\treturn function <Mega, FL, CL, SL>(l: IOptic<Whole, Mega, FL, CL, SL>) {\n\t\treturn new COptic<Part, Mega, Fail | FL, Command, PRISM & SL>({\n\t\t\tcom: (c, a) => l.mapper((p) => r.command(c, p), a),\n\t\t\tgetter: composeGetter(l.isFailure, l.getter, r.getter),\n\t\t\tisCommand: r.isCommand,\n\t\t\tisFailure: composeFailure(l.isFailure, r.isFailure),\n\t\t\tmapper: composeMapper(\n\t\t\t\tl.mapper,\n\t\t\t\t(r.mapper as any) ??\n\t\t\t\t\t((mod: Modify<Part>, v) => {\n\t\t\t\t\t\tconst b = r.getter!(v)\n\t\t\t\t\t\tif (r.isFailure(b)) return v\n\t\t\t\t\t\treturn r.setter(mod(b))\n\t\t\t\t\t}),\n\t\t\t),\n\t\t\trefold: pipe2(\n\t\t\t\tr.refold ??\n\t\t\t\t\t(<Acc>(foldPart: FoldFn<Part, Acc, Ctx>): FoldFn<Whole, Acc, Ctx> =>\n\t\t\t\t\t\t(v, acc, ctx) => {\n\t\t\t\t\t\t\tconst b = r.getter(v)\n\t\t\t\t\t\t\tif (r.isFailure(b)) return acc\n\t\t\t\t\t\t\treturn foldPart(b, acc, ctx)\n\t\t\t\t\t\t}),\n\t\t\t\tl.refold,\n\t\t\t),\n\t\t\tsetter: composePrismSetter(l.getter, l.setter, r.setter),\n\t\t})\n\t}\n}\n\nexport function opticNonPrism<Part, Whole, Fail, Command>(\n\tr: IOpticArgs<Part, Whole, Fail, Command, NON_PRISM>,\n) {\n\treturn function <Mega, FL, CL, SL>(l: IOptic<Whole, Mega, FL, CL, SL>) {\n\t\treturn new COptic<Part, Mega, Fail | FL, Command, NON_PRISM & SL>({\n\t\t\tcom: (c, a) => l.mapper((p) => r.command(c, p), a),\n\t\t\tgetter: composeGetter(l.isFailure, l.getter, r.getter),\n\t\t\tisCommand: r.isCommand,\n\t\t\tisFailure: composeFailure(l.isFailure, r.isFailure),\n\t\t\tmapper: composeMapper(\n\t\t\t\tl.mapper,\n\t\t\t\t(r.mapper as any) ??\n\t\t\t\t\t((mod: Modify<Part>, v) => {\n\t\t\t\t\t\tconst b = r.getter!(v)\n\t\t\t\t\t\tif (r.isFailure(b)) return v\n\t\t\t\t\t\treturn r.setter!(mod(b), v)\n\t\t\t\t\t}),\n\t\t\t),\n\t\t\trefold: pipe2(\n\t\t\t\tr.refold ??\n\t\t\t\t\t(<Acc>(foldPart: FoldFn<Part, Acc, Ctx>): FoldFn<Whole, Acc, Ctx> =>\n\t\t\t\t\t\t(v, acc, ctx) => {\n\t\t\t\t\t\t\tconst b = r.getter!(v)\n\t\t\t\t\t\t\tif (r.isFailure(b)) return acc\n\t\t\t\t\t\t\treturn foldPart(b, acc, ctx)\n\t\t\t\t\t\t}),\n\t\t\t\tl.refold,\n\t\t\t),\n\t\t\tsetter: composeSetter(l.getter, l.setter, l.isFailure, r.setter),\n\t\t})\n\t}\n}\n\nexport function iso<Part, Whole>({\n\tgetter,\n\tmapper,\n\tsetter,\n}: {\n\tgetter: (whole: Whole) => Part\n\tmapper?: Mapper<Part, Whole>\n\tsetter: (part: Part) => Whole\n}) {\n\treturn opticPrism({\n\t\tcommand: forbidden,\n\t\tgetter,\n\t\tisCommand: isNever,\n\t\tisFailure: isNever,\n\t\tmapper: mapper ?? makeMapper(setter, getter),\n\t\trefold:\n\t\t\tgetter === id\n\t\t\t\t? (id as any)\n\t\t\t\t: <Acc, Ctx>(fold: FoldFn<Part, Acc, Ctx>) =>\n\t\t\t\t\t\t(v: Whole, acc: Acc, ctx: Ctx) =>\n\t\t\t\t\t\t\tfold(getter(v) as any, acc, ctx),\n\t\tsetter,\n\t})\n}\n\nexport function lens<Part, Whole>({\n\tgetter,\n\tmapper,\n\tsetter,\n}: {\n\tgetter: (whole: Whole) => Part\n\tmapper?: Mapper<Part, Whole>\n\tsetter: (part: Part, whole: Whole) => Whole\n}) {\n\treturn opticNonPrism({\n\t\tcommand: forbidden,\n\t\tgetter,\n\t\tisCommand: isNever,\n\t\tisFailure: isNever,\n\t\tmapper: mapper ?? makeMapper(setter, getter),\n\t\trefold:\n\t\t\tgetter === id\n\t\t\t\t? (id as any)\n\t\t\t\t: <Acc, Ctx>(fold: FoldFn<Part, Acc, Ctx>) =>\n\t\t\t\t\t\t(v: Whole, acc: Acc, ctx: Ctx) =>\n\t\t\t\t\t\t\tfold(getter(v) as any, acc, ctx),\n\t\tsetter,\n\t})\n}\n\nexport function prism<Part, Whole>({\n\tgetter,\n\tmapper,\n\tsetter,\n}: {\n\tgetter: Getter<Part, Whole, undefined>\n\tmapper?: Mapper<Part, Whole>\n\tsetter: Setter<Part, Whole, PRISM>\n}) {\n\treturn opticPrism({\n\t\tcommand: forbidden,\n\t\tgetter,\n\t\tisCommand: isNever,\n\t\tisFailure: isUndefined,\n\t\tmapper,\n\t\tsetter,\n\t})\n}\n\n// TODO: merge optional and removable\n\nexport function optional<Part, Whole>({\n\tgetter,\n\tmapper,\n\tsetter,\n}: {\n\tgetter: Getter<Part, Whole, undefined>\n\tmapper?: Mapper<Part, Whole>\n\tsetter: Setter<Part, Whole, NON_PRISM>\n}) {\n\treturn opticNonPrism<Part, Whole, undefined, never>({\n\t\tcommand: forbidden,\n\t\tgetter,\n\t\tisCommand: isNever,\n\t\tisFailure: isUndefined,\n\t\tmapper,\n\t\tsetter,\n\t})\n}\n\nexport function removable<Part, Whole>({\n\tgetter,\n\tmapper,\n\tremover,\n\tsetter,\n}: {\n\tgetter: Getter<Part, Whole, undefined>\n\tmapper?: Mapper<Part, Whole>\n\tremover: Modify<Whole>\n\tsetter: Setter<Part, Whole, never>\n}) {\n\treturn opticNonPrism({\n\t\tcommand: (_, a) => remover(a),\n\t\tgetter,\n\t\tisCommand: isRemove,\n\t\tisFailure: isUndefined,\n\t\tmapper,\n\t\tsetter,\n\t})\n}\n\nexport function traversal<Part, Whole, Index>({\n\tcoll,\n\tform,\n}: {\n\tcoll: Unfolder<Part, Whole, Index>\n\tform: () => FoldForm<Part, Whole, Ctx>\n}) {\n\treturn opticNonPrism<Part, Whole, undefined, never>({\n\t\tcommand: forbidden,\n\t\tisCommand: isNever,\n\t\tisFailure: isUndefined,\n\t\tmapper: (mod, whole: Whole) => {\n\t\t\tconst { foldFn, init } = form()\n\t\t\tconst acc = fromInit(init)\n\t\t\treturn foldFrom(\n\t\t\t\tacc,\n\t\t\t\t(p, acc, ctx) => foldFn(mod(p), acc, ctx),\n\t\t\t\twhole,\n\t\t\t\tcoll,\n\t\t\t\tnoop,\n\t\t\t)\n\t\t},\n\t\trefold: <Acc>(foldPart: (p: Part, acc: Acc, ctx: Ctx) => Acc) => {\n\t\t\treturn function (whole: Whole, acc: Acc, { close }: Ctx) {\n\t\t\t\treturn foldFrom(acc, foldPart, whole, coll, close)\n\t\t\t}\n\t\t},\n\t})\n}\n\n// optics modifier\n\n// FIXME: type inference is problematic when value can be command\n// we need to cast is as any\n\nexport function disabled<Part>(value: ((p: Part) => Part) | Part) {\n\treturn function <Whole, Fail, Command, S>(\n\t\to: COptic<Part, Whole, Fail, Command, S>,\n\t) {\n\t\tconst getter = (whole: Whole) => Object.is(o.update(value)(whole), whole)\n\t\tconst setter: Setter<boolean, Whole, NON_PRISM> = (\n\t\t\td: boolean,\n\t\t\twhole: Whole,\n\t\t) => {\n\t\t\tif (d && !getter(whole)) return o.update(value)(whole)\n\t\t\treturn whole\n\t\t}\n\t\treturn new COptic<boolean, Whole, never, never, NON_PRISM>({\n\t\t\tcom: id,\n\t\t\tgetter,\n\t\t\tisCommand: isNever,\n\t\t\tisFailure: isNever,\n\t\t\tmapper: makeMapper(setter, getter),\n\t\t\trefold: (fold) => (v, acc, ctx) => fold(getter(v), acc, ctx),\n\t\t\tsetter,\n\t\t})\n\t}\n}\n\n// TODO: exclude traversals by type\n// prism in prism out\nexport function valueOr<Part>(value: Init<Part>) {\n\treturn function <Whole, Fail, Command, S>(\n\t\to: IOptic<Part, Whole, Fail, Command, S>,\n\t) {\n\t\tif (!(o.getter && o.setter))\n\t\t\tthrow new Error(\"valueOr don't work with traversals\")\n\t\tconst getter = (whole: Whole) => {\n\t\t\tconst part = o.getter!(whole)\n\t\t\tif (o.isFailure(part)) return fromInit(value)\n\t\t\treturn part\n\t\t}\n\t\treturn new COptic<Part, Whole, never, Command, S>({\n\t\t\tcom: o.com,\n\t\t\tgetter,\n\t\t\tisCommand: o.isCommand,\n\t\t\tisFailure: isNever,\n\t\t\tmapper: makeMapper(o.setter, getter),\n\t\t\trefold: (foldPart) => {\n\t\t\t\tconst lastFold = o.refold(foldPart)\n\t\t\t\treturn (whole, acc, ctx) =>\n\t\t\t\t\to.isFailure(o.getter!(whole))\n\t\t\t\t\t\t? foldPart(getter(whole), acc, ctx)\n\t\t\t\t\t\t: lastFold(whole, acc, ctx)\n\t\t\t},\n\t\t\tsetter: o.setter,\n\t\t})\n\t}\n}\n","import {\n\tappend,\n\tid,\n\tinsertValue,\n\tprepend,\n\tremove,\n\tremoveValue,\n\treplace,\n} from '../../utils'\nimport { fromArray, toArray } from '../collections'\nimport {\n\tCOptic,\n\tforbidden,\n\tIOptic,\n\tiso,\n\tlens,\n\tNON_PRISM,\n\toptional,\n\tprism,\n\tremovable,\n\tREMOVE,\n\ttraversal,\n} from '../core'\n\n// getters\n\nexport function to<Micro, Part>(\n\tgetter: (v: Part) => Micro,\n): <Mega, FL, CL, SL>(\n\tl: IOptic<Part, Mega, FL, CL, SL>,\n) => COptic<Micro, Mega, FL, never, SL>\nexport function to<Micro, Part>(\n\tgetter: (v: Part) => Micro | undefined,\n): <Mega, FL, CL, SL>(\n\tl: IOptic<Part, Mega, FL, CL, SL>,\n) => COptic<Micro, Mega, FL | undefined, never, SL>\nexport function to<Micro, Part>(getter: (v: Part) => Micro | undefined) {\n\treturn optional<Micro, Part>({\n\t\tgetter,\n\t\tsetter: forbidden,\n\t})\n}\n\n// isomorphisms\n\nexport function reread<Whole>(mod: (a: Whole) => Whole) {\n\treturn iso<Whole, Whole>({\n\t\tgetter: mod,\n\t\tsetter: id,\n\t\t// optics-ts setter is equivalent to: `setter: (_v, a) => a`\n\t})\n}\n\nexport function rewrite<Whole>(setter: (next: Whole, last: Whole) => Whole) {\n\treturn lens<Whole, Whole>({\n\t\tgetter: id,\n\t\tsetter,\n\t})\n}\n\nexport function dedupe<Whole>(\n\tareEqual: (a: Whole, b: Whole) => unknown = Object.is,\n) {\n\treturn rewrite<Whole>((next, last) => {\n\t\tif (areEqual(next, last)) return last\n\t\treturn next\n\t})\n}\n\nexport function linear(m: number, b = 0) {\n\treturn iso<number, number>({\n\t\tgetter: (x) => m * x + b,\n\t\tsetter: (y) => (y - b) / m,\n\t})\n}\n\n// lenses\n\n// focus on nth element of tuple, use `at` for arrays\nexport function nth<Index extends keyof O & number, O extends unknown[]>(\n\tindex: Index,\n) {\n\treturn lens<O[Index], O>({\n\t\tgetter: (o) => o[index],\n\t\tsetter: (v, o) => replace(v, index, o) as O,\n\t})\n}\n\n// we could have a sorted version\nexport function includes<X>(x: X) {\n\treturn lens<boolean, X[]>({\n\t\tgetter: (xs) => xs.includes(x),\n\t\tsetter: (v, xs) => (v ? insertValue(x, xs) : removeValue(x, xs)),\n\t})\n}\n\n// prisms\n\nexport function when<Part, Micro extends Part>(\n\tp: (v: Part) => v is Micro,\n): <Mega, FL, CL, SL>(\n\tl: IOptic<Part, Mega, FL, CL, SL>,\n) => COptic<Micro, Mega, FL | undefined, never, SL & void>\nexport function when<Part>(\n\tp: (v: Part) => unknown,\n): <Mega, FL, CL, SL>(\n\tl: IOptic<Part, Mega, FL, CL, SL>,\n) => COptic<Part, Mega, FL | undefined, never, SL & void>\nexport function when<V>(p: (v: V) => unknown) {\n\treturn prism<V, V>({\n\t\tgetter: (v) => (p(v) ? v : undefined),\n\t\tsetter: id,\n\t})\n}\n\nexport function strToNum() {\n\treturn prism<number, string>({\n\t\tgetter: (str) => {\n\t\t\tconst parsed = parseInt(str)\n\t\t\tif (isNaN(parsed)) return undefined\n\t\t\treturn parsed\n\t\t},\n\t\tsetter: (num) => String(num),\n\t})\n}\n\n// removables\n\ntype OptionalKeys<T> = {\n\t[K in keyof T]: object extends Pick<T, K> ? K : never\n}[keyof T]\n\nexport function prop<Key extends keyof O, O extends object>(\n\tkey: Key,\n): <A, F1, C, S>(\n\tp: IOptic<O, A, F1, C, S>,\n) => COptic<\n\tExclude<O[Key], undefined>,\n\tA,\n\tF1 | (Key extends OptionalKeys<O> ? undefined : never),\n\tKey extends OptionalKeys<O> ? typeof REMOVE : never,\n\tNON_PRISM\n>\nexport function prop<Key extends keyof O, O extends object>(key: Key) {\n\treturn removable<Exclude<O[Key], undefined>, O>({\n\t\tgetter: (o) => o[key] as Exclude<O[Key], undefined>,\n\t\tremover: (o) => {\n\t\t\tif (!(key in o)) return o\n\t\t\tconst res = { ...o }\n\t\t\tdelete res[key]\n\t\t\treturn res\n\t\t},\n\t\tsetter: (v, o) => {\n\t\t\t// the second check is to differentiate between a key not existing\n\t\t\t// and a key existing with a value of undefined\n\t\t\tif (Object.is(o[key], v) && key in o) return o\n\t\t\treturn { ...o, [key]: v }\n\t\t},\n\t})\n}\n\nexport function at<X>(index: number) {\n\treturn removable<X, X[]>({\n\t\tgetter: (xs) => xs.at(index),\n\t\tremover: (xs) => remove(index, xs),\n\t\tsetter: (x: X, xs) => replace(x, index, xs),\n\t})\n}\n\nexport function findOne<X, Y extends X>(\n\tp: (x: X) => x is Y,\n): <Mega, F2, C2, S>(\n\to: IOptic<X[], Mega, F2, C2, S>,\n) => COptic<Y, Mega, F2 | undefined, typeof REMOVE, NON_PRISM>\nexport function findOne<X>(\n\tp: (x: X) => unknown,\n): <Mega, F2, C2, S>(\n\to: IOptic<X[], Mega, F2, C2, S>,\n) => COptic<X, Mega, F2 | undefined, typeof REMOVE, NON_PRISM>\nexport function findOne<X>(p: (x: X) => unknown) {\n\treturn removable<X, X[]>({\n\t\tgetter: (xs) => xs.find(p),\n\t\tmapper: (f, xs) => {\n\t\t\tconst index = xs.findIndex(p)\n\t\t\tif (index < 0) return xs\n\t\t\tconst x = f(xs[index]!)\n\t\t\treturn [...xs.slice(0, index), x, ...xs.slice(index + 1)]\n\t\t},\n\t\tremover: (xs) => {\n\t\t\tconst index = xs.findIndex(p)\n\t\t\tif (index < 0) return xs\n\t\t\treturn [...xs.slice(0, index), ...xs.slice(index + 1)]\n\t\t},\n\t\tsetter: (x, xs) => {\n\t\t\tconst index = xs.findIndex(p)\n\t\t\tif (index < 0) return append(x, xs)\n\t\t\treturn [...xs.slice(0, index), x, ...xs.slice(index + 1)]\n\t\t},\n\t})\n}\n\n// defective (when setting a value not respecting predicate)\nexport function findMany<X, Y extends X>(\n\tp: (x: X) => x is Y,\n): <A, F, C, S>(\n\to: IOptic<X[], A, F, C, S>,\n) => COptic<Y[], A, F, never, NON_PRISM>\nexport function findMany<X>(\n\tp: (x: X) => unknown,\n): <A, F, C, S>(\n\to: IOptic<X[], A, F, C, S>,\n) => COptic<X[], A, F, never, NON_PRISM>\nexport function findMany<X>(p: (x: X) => unknown) {\n\treturn lens<X[], X[]>({\n\t\tgetter: (xs) => xs.filter(p),\n\t\tsetter: (fs, xs) => {\n\t\t\tlet dirty = false\n\t\t\tconst rs: X[] = []\n\t\t\tlet i = 0\n\t\t\tlet j = 0\n\t\t\tlet k = 0\n\t\t\tfor (i = 0; i < xs.length; i++) {\n\t\t\t\tconst x = xs[i]!\n\t\t\t\tif (p(x)) {\n\t\t\t\t\tif (j < fs.length) {\n\t\t\t\t\t\tdirty = dirty || !Object.is(fs[j], x)\n\t\t\t\t\t\trs[k] = fs[j]!\n\t\t\t\t\t\tj++\n\t\t\t\t\t\tk++\n\t\t\t\t\t} else {\n\t\t\t\t\t\tdirty = true\n\t\t\t\t\t}\n\t\t\t\t} else {\n\t\t\t\t\trs[k] = x\n\t\t\t\t\tk++\n\t\t\t\t}\n\t\t\t}\n\t\t\tfor (; j < fs.length; j++, k++) {\n\t\t\t\tdirty = true\n\t\t\t\trs[k] = fs[j]!\n\t\t\t}\n\t\t\treturn dirty ? rs : xs\n\t\t},\n\t\t// if needed, implementing a custom mapper could improve speed\n\t})\n}\n\nexport function tail<X>() {\n\treturn removable<X[], X[]>({\n\t\tgetter: (last) => (last.length ? last.slice(1) : undefined),\n\t\tremover: (last) => (last.length ? last.slice(0, 1) : last),\n\t\tsetter: (next, last) => (last.length ? [last[0]!, ...next] : last),\n\t})\n}\n\n// defective\n// aka prepend\n// can represent a stack, although foot is more efficient\nexport function head<X>() {\n\treturn removable<X, X[]>({\n\t\tgetter: (xs) => xs.at(0),\n\t\tremover: (last) => (last.length ? last.slice(1) : last),\n\t\tsetter: prepend,\n\t})\n}\n\n// defective\n// aka foot, append\n// can represent a stack\nexport function stack<X>() {\n\treturn removable<X, X[]>({\n\t\tgetter: (xs) => xs.at(-1),\n\t\tremover: (last) => (last.length ? last.slice(0, -1) : last),\n\t\tsetter: append,\n\t})\n}\n\n// defective\nexport function queue<X>() {\n\treturn removable<X, X[]>({\n\t\tgetter: (xs) => xs.at(0),\n\t\tremover: (last) => (last.length ? last.slice(1) : last),\n\t\tsetter: append,\n\t})\n}\n\n// traversals\nexport function elems<X>() {\n\treturn traversal<X, X[], number>({\n\t\tcoll: fromArray<X>,\n\t\tform: toArray<X>,\n\t})\n}\n"],"names":["fromSendable","event","withSend","emit","prepend","x","xs","append","insert","index","replace","remove","insertValue","element","removeValue","dirty","res","flow","args","fns","acc","cb","isFunction","isUndefined","v","isNever","_v","noop","apply","f","p","id","pipe2","g","fromInit","init","toInit","isEmpty","obj","_","curry1","a","curry","args2","pipe","fn1","prevFn","nextFn","value","shallowEqual","b","aLength","bLength","key","MachineEffects","effectsHandlers","__publicField","send","subState","entry","effect","_a","fromIndex","last","_b","indices","unmount","visit","toListener","listener","message","m","multiStateMachine","multiStateBaseMachine","derive","states","init0","fromAlways","s","s_","initialArg","state","e","localDerive","d1","join","fold","isDisabled","machine","transformed","touched","nextState","ObjectMachine","opts","run","objectMachine","promiseMachine","events","resolve","simpleStateMachine","simpleStateBaseMachine","transform","getFinal","ctx","fromArray","toArray","toFirst","fail","close","ctxNull","foldFrom","foldPart","whole","unfolder","onClose","unfold","alive","r","REMOVE","isRemove","forbidden","_part","_whole","COptic","token","form","mod","part","arg","or","focus","o","composeGetter","isFailure","q","composeFailure","f1","f2","composeMapper","thisMapper","oMapper","w","makeMapper","setter","getter","composeSetter","lGetter","lSetter","rIsFailure","rSetter","set","t","composePrismSetter","opticPrism","l","c","opticNonPrism","iso","mapper","lens","prism","optional","removable","remover","traversal","coll","foldFn","disabled","d","valueOr","lastFold","to","reread","rewrite","dedupe","areEqual","next","linear","y","nth","includes","when","strToNum","str","parsed","num","prop","at","findOne","findMany","fs","rs","i","j","k","tail","head","stack","queue","elems"],"mappings":"wPAwCO,SAASA,EACfC,EACQ,CACR,OAAO,OAAOA,GAAU,SAErB,CAAE,KAAMA,CAAM,EACdA,CACJ,CAEO,SAASC,GAA8BC,EAA8B,CAC3E,OAAQ,GAAuBA,EAAKH,EAAa,CAAC,CAAC,CACpD,CCjDgB,SAAAI,EAAWC,EAAMC,EAAS,CAClC,MAAA,CAACD,EAAG,GAAGC,CAAE,CACjB,CAEgB,SAAAC,EAAUF,EAAMC,EAAS,CACjC,MAAA,CAAC,GAAGA,EAAID,CAAC,CACjB,CAEgB,SAAAG,GAAUC,EAAeJ,EAAMC,EAAS,CAGnD,OAFAG,EAAQ,IAAGA,GAASH,EAAG,QACvBG,EAAQ,GACRA,EAAQH,EAAG,OAAeA,EACvB,CAAC,GAAGA,EAAG,MAAM,EAAGG,CAAK,EAAGJ,EAAG,GAAGC,EAAG,MAAMG,CAAK,CAAC,CACrD,CAEgB,SAAAC,EAAWL,EAAMI,EAAeH,EAAS,CAIxD,OAHIG,EAAQ,IAAGA,GAASH,EAAG,QACvBG,EAAQ,GACRA,GAASH,EAAG,QACZ,OAAO,GAAGA,EAAGG,CAAK,EAAGJ,CAAC,EAAUC,EAC7B,CAAC,GAAGA,EAAG,MAAM,EAAGG,CAAK,EAAGJ,EAAG,GAAGC,EAAG,MAAMG,EAAQ,CAAC,CAAC,CACzD,CAEgB,SAAAE,EAAUF,EAAeH,EAAS,CAG7C,OAFAG,EAAQ,IAAGA,GAASH,EAAG,QACvBG,EAAQ,GACRA,GAASH,EAAG,OAAeA,EACxB,CAAC,GAAGA,EAA