import { Effect, Fiber } from "effect" import { WorkspaceContext } from "@/control-plane/workspace-context" import { Instance, type InstanceContext } from "@/project/instance" import type { WorkspaceID } from "@/control-plane/schema" import { LocalContext } from "@/util" import { InstanceRef, WorkspaceRef } from "./instance-ref" import { attachWith } from "./run-service" export interface Shape { readonly promise: (effect: Effect.Effect) => Promise readonly fork: (effect: Effect.Effect) => Fiber.Fiber } function restore(instance: InstanceContext | undefined, workspace: WorkspaceID | undefined, fn: () => R): R { if (instance && workspace !== undefined) { return WorkspaceContext.restore(workspace, () => Instance.restore(instance, fn)) } if (instance) return Instance.restore(instance, fn) if (workspace !== undefined) return WorkspaceContext.restore(workspace, fn) return fn() } export function make(): Effect.Effect { return Effect.gen(function* () { const ctx = yield* Effect.context() const value = yield* InstanceRef const instance = value ?? (() => { try { return Instance.current } catch (err) { if (!(err instanceof LocalContext.NotFound)) throw err } })() const workspace = (yield* WorkspaceRef) ?? WorkspaceContext.workspaceID const attach = (effect: Effect.Effect) => attachWith(effect, { instance, workspace }) const wrap = (effect: Effect.Effect) => attach(effect).pipe(Effect.provide(ctx)) as Effect.Effect return { promise: (effect: Effect.Effect) => restore(instance, workspace, () => Effect.runPromise(wrap(effect))), fork: (effect: Effect.Effect) => restore(instance, workspace, () => Effect.runFork(wrap(effect))), } satisfies Shape }) }