import * as Effect from "effect/Effect"; import { type Rpc } from "../../Platform.ts"; import { fromCloudflareFetcher, toCloudflareFetcher, type Fetcher, } from "../Fetcher.ts"; import { DurableObjectNamespace, DurableObjectState, } from "../Workers/DurableObject.ts"; import { Worker } from "../Workers/Worker.ts"; import type { Container } from "./Container.ts"; import type { ContainerApplication } from "./ContainerApplication.ts"; export const bindContainer = Effect.fnUntraced(function* ( containerEff: | (ContainerApplication & Rpc) | Effect.Effect, never, Req>, ) { const namespace = yield* DurableObjectNamespace.asEffect(); const container = "asEffect" in containerEff ? yield* (containerEff as any).asEffect() as Effect.Effect< ContainerApplication & Rpc > : Effect.isEffect(containerEff) ? yield* containerEff as unknown as Effect.Effect< ContainerApplication & Rpc > : containerEff; yield* container.bind`${namespace}`({ durableObjects: { namespaceId: namespace.namespaceId, }, }); const worker = yield* Worker; const className = namespace.name; yield* worker.bind`${container.LogicalId}`({ containers: [{ className }], }); // TODO(sam): register this in the Container Execution Context // const _httpEffect = yield* init; return Effect.gen(function* () { const state = yield* DurableObjectState; return { running: Effect.sync(() => state.container!.running ?? false), destroy: (error?: any) => Effect.promise(() => state.container!.destroy(error)), signal: (signo: number) => Effect.sync(() => state.container!.signal(signo)), getTcpPort: (port: number) => Effect.sync(() => fromCloudflareFetcher(state.container!.getTcpPort(port)), ), setInactivityTimeout: (durationMs: number | bigint) => Effect.sync(() => state.container!.setInactivityTimeout(durationMs)), interceptOutboundHttp: (addr: string, binding: Fetcher) => toCloudflareFetcher(binding).pipe( Effect.map((binding) => state.container!.interceptOutboundHttp(addr, binding), ), ), interceptAllOutboundHttp: (binding: Fetcher) => toCloudflareFetcher(binding).pipe( Effect.map((binding) => state.container!.interceptAllOutboundHttp(binding), ), ), monitor: () => Effect.sync(() => state.container?.monitor()), start: (options?: ContainerStartupOptions) => Effect.sync(() => state.container!.start(options)), } satisfies Container as Shape; }); });