/* eslint-disable @typescript-eslint/no-explicit-any */ import { Effect, type NonEmptyReadonlyArray } from "effect-app" import { toNonEmptyArray } from "effect-app/Array" import { type FixEnv, get, logMany, type Pure, type PureEnvEnv, type PureLogT, set } from "effect-app/Pure" export interface PureDSL { get: Pure set: (s: S2) => Pure log: (...w: W[]) => PureLogT } export const AnyPureDSL: PureDSL = { get: get(), set: set as any, log: (...evt: any[]) => logMany(evt) } const anyDSL = makeDSL() export type AllDSL = & (( pure: (dsl: PureDSL) => Effect.Effect ) => Effect.Effect>) & AllDSLExt export interface AllDSLExt { modify: ( pure: (items: readonly S1[], dsl: PureDSL) => Effect.Effect ) => Effect.Effect> update: ( pure: (items: readonly S1[], log: (...evt: Evt[]) => PureLogT) => Effect.Effect ) => Effect.Effect> updateWith: ( upd: (item: readonly S1[]) => readonly S2[] ) => Effect.Effect> } export function makeAllDSL() { const dsl: AllDSL = anyDSL return dsl } export type OneDSL = & (( pure: (dsl: PureDSL) => Effect.Effect ) => Effect.Effect>) & OneDSLExt export interface OneDSLExt { modify: ( pure: (items: S1, dsl: PureDSL) => Effect.Effect ) => Effect.Effect | PureEnvEnv> update: ( pure: (items: S1, log: (...evt: Evt[]) => PureLogT) => Effect.Effect ) => Effect.Effect> updateWith: ( upd: (item: S1) => S2 ) => Effect.Effect> } export function makeOneDSL(): OneDSL { return anyDSL } export function makeDSL() { const dsl: PureDSL = AnyPureDSL function modify< R, E, A >( pure: ( items: S1, dsl: PureDSL ) => Effect.Effect ): Effect.Effect> { return dsl.get.pipe(Effect.flatMap((items) => pure(items, dsl))) as any } function update< R, E >( pure: ( items: S1, log: (...evt: Evt[]) => PureLogT ) => Effect.Effect ): Effect.Effect> { return dsl.get.pipe(Effect.flatMap((items) => pure(items, dsl.log).pipe(Effect.tap(dsl.set)))) as any } function withDSL< R, A, E >( pure: (dsl: PureDSL) => Effect.Effect ): Effect.Effect> { return pure(AnyPureDSL) as any } function updateWith(upd: (item: S1) => S2) { return update((_: S1) => Effect.sync(() => upd(_))) } return Object.assign( withDSL, { modify, update, updateWith } ) } export interface DSLExt extends ReturnType> {} export function ifAny(fn: (items: NonEmptyReadonlyArray) => Effect.Effect) { return (items: Iterable) => Effect.flatMapOption(Effect.sync(() => toNonEmptyArray([...items])), fn) } export function ifAny_( items: Iterable, fn: (items: NonEmptyReadonlyArray) => Effect.Effect ) { return Effect.flatMapOption(Effect.sync(() => toNonEmptyArray([...items])), fn) }