| 1 | import type * as Cloudflare from "@/Cloudflare"; |
| 2 | import { Container, getContainer } from "@cloudflare/containers"; |
| 3 | import type { AsyncContainerWorker } from "./stack.ts"; |
| 4 | |
| 5 | /** |
| 6 | * Container-backed Durable Object class hosted by a plain async Worker — the |
| 7 | * class implementation comes from the `@cloudflare/containers` npm package |
| 8 | * (the exact shape from issue #953, where the class is `@cloudflare/sandbox`'s |
| 9 | * `Sandbox`). `Container.fetch` forwards requests to the echo server listening |
| 10 | * on port 8080 inside the container. |
| 11 | */ |
| 12 | export class AsyncEchoObject extends Container { |
| 13 | defaultPort = 8080; |
| 14 | } |
| 15 | |
| 16 | // InferEnv maps the Container binding to DurableObjectNamespace<AsyncEchoObject>, |
| 17 | // which is exactly what `getContainer` expects. |
| 18 | type Env = Cloudflare.InferEnv<typeof AsyncContainerWorker>; |
| 19 | |
| 20 | export default { |
| 21 | async fetch(request: Request, env: Env) { |
| 22 | const url = new URL(request.url); |
| 23 | // Reports what `env.ECHO` actually IS at runtime. A `durable_object_ |
| 24 | // namespace` binding has `idFromName`; when the Worker instead uploads the |
| 25 | // Container declaration as a `json` binding, this echoes that json back |
| 26 | // (`{"_id":"Effect","op":"alchemy/EffectClass"}`) and `getContainer` below |
| 27 | // dies with `t.idFromName is not a function`. |
| 28 | if (url.pathname === "/binding") { |
| 29 | const binding = env.ECHO as unknown; |
| 30 | return Response.json({ |
| 31 | kind: |
| 32 | typeof (binding as { idFromName?: unknown } | null)?.idFromName === |
| 33 | "function" |
| 34 | ? "durable_object_namespace" |
| 35 | : JSON.stringify(binding), |
| 36 | }); |
| 37 | } |
| 38 | if (url.pathname === "/hello") { |
| 39 | return getContainer(env.ECHO, "default").fetch(request); |
| 40 | } |
| 41 | return new Response("ok"); |
| 42 | }, |
| 43 | }; |