1import * as Cloudflare from "@/Cloudflare";
2import { Layer } from "effect";
3import * as Effect from "effect/Effect";
4import * as HttpClientRequest from "effect/http/HttpClientRequest";
5
6export class ExternalContainer extends Cloudflare.Container<ExternalContainer>()(
7 "ExternalContainer",
8 {
9 // Use a template string rather than `path.join(import.meta.dirname, …)`:
10 // this module is bundled into the Worker (it defines the DO), and
11 // `import.meta.dirname` is `undefined` in the Worker runtime — calling
12 // `path.join(undefined, …)` there throws a ScriptStartupError at module
13 // load. `context` is only consumed at build time, so a plain string is
14 // sufficient and never evaluates `path.join` at runtime.
15 context: `${import.meta.dirname}/context`,
16 observability: { logs: { enabled: true } },
17 },
18) {}
19
20/**
21 * Durable Object that binds and starts the {@link ExternalContainer} and
22 * proxies an HTTP request to the nginx server running on port 8080 inside it.
23 */
24export class ExternalContainerObject extends Cloudflare.DurableObject<ExternalContainerObject>()(
25 "ExternalContainerObject",
26 Effect.gen(function* () {
27 const container = yield* ExternalContainer;
28
29 return Effect.gen(function* () {
30 const { fetch } = yield* container.getTcpPort(8080);
31
32 return {
33 hello: Effect.fn("hello")(function* () {
34 const response = yield* fetch(
35 HttpClientRequest.get("http://container/"),
36 );
37 return yield* response.text;
38 }),
39 };
40 });
41 }).pipe(
42 Effect.provide(
43 Layer.mergeAll(
44 Cloudflare.Containers.layer(ExternalContainer, {
45 enableInternet: true,
46 }),
47 ),
48 ),
49 ),
50) {}