import { Effect, Layer, ManagedRuntime } from "effect" import * as ServiceMap from "effect/ServiceMap" import { Instance } from "@/project/instance" import { Context } from "@/util/context" import { InstanceRef } from "./instance-ref" export const memoMap = Layer.makeMemoMapUnsafe() function attach(effect: Effect.Effect): Effect.Effect { try { const ctx = Instance.current return Effect.provideService(effect, InstanceRef, ctx) } catch (err) { if (!(err instanceof Context.NotFound)) throw err } return effect } export function makeRuntime(service: ServiceMap.Service, layer: Layer.Layer) { let rt: ManagedRuntime.ManagedRuntime | undefined const getRuntime = () => (rt ??= ManagedRuntime.make(layer, { memoMap })) return { runSync: (fn: (svc: S) => Effect.Effect) => getRuntime().runSync(attach(service.use(fn))), runPromiseExit: (fn: (svc: S) => Effect.Effect, options?: Effect.RunOptions) => getRuntime().runPromiseExit(attach(service.use(fn)), options), runPromise: (fn: (svc: S) => Effect.Effect, options?: Effect.RunOptions) => getRuntime().runPromise(attach(service.use(fn)), options), runFork: (fn: (svc: S) => Effect.Effect) => getRuntime().runFork(attach(service.use(fn))), runCallback: (fn: (svc: S) => Effect.Effect) => getRuntime().runCallback(attach(service.use(fn))), } }