1import * as AWS from "@/AWS";
2import * as Effect from "effect/Effect";
3import { HttpServerRequest } from "effect/http/HttpServerRequest";
4import * as HttpServerResponse from "effect/http/HttpServerResponse";
5
6export const SandboxBuildRole = AWS.IAM.Role("MicrovmSandboxBuildRole");
7
8/**
9 * Effectful MicroVM image exposing BOTH a raw `fetch` handler and a typed RPC
10 * `Shape` (the `hello` method). The runtime serves the RPC methods over the
11 * `/__rpc__/*` protocol and falls through to `fetch` for everything else;
12 * callers reach RPC with {@link AWS.Lambda.connectMicrovm} and `fetch` with a
13 * plain HTTPS request to the MicroVM endpoint.
14 *
15 * The class (a typed handle) is imported by the Lambda orchestrator; the
16 * `.make()` Live layer is provided on the stack and is what gets bundled into
17 * the image.
18 */
19export class Sandbox extends AWS.Lambda.MicrovmImage<
20 Sandbox,
21 {
22 hello: (message: string) => Effect.Effect<string>;
23 }
24>()("MicrovmSandbox") {}
25
26export default Sandbox.make(
27 SandboxBuildRole.pipe(
28 Effect.map((buildRole) => ({
29 main: import.meta.filename,
30 buildRole,
31 resources: [{ minimumMemoryInMiB: 512 }],
32 cpuConfigurations: [{ architecture: "ARM_64" }],
33 })),
34 ),
35 Effect.gen(function* () {
36 return {
37 // Raw HTTP route (the fetch path).
38 fetch: Effect.gen(function* () {
39 const request = yield* HttpServerRequest;
40 const url = new URL(request.url, "http://microvm");
41 if (url.pathname === "/echo") {
42 return yield* HttpServerResponse.json({
43 message: url.searchParams.get("message") ?? "",
44 });
45 }
46 return HttpServerResponse.text("hello from effectful microvm");
47 }),
48 // Tagged RPC method (the RPC path).
49 hello: (message: string) => Effect.succeed(`hello, ${message}!`),
50 };
51 }),
52);