1import * as AWS from "@/AWS";
2import * as Effect from "effect/Effect";
3import { HttpServerRequest } from "effect/http/HttpServerRequest";
4import * as HttpServerResponse from "effect/http/HttpServerResponse";
5import { isolatedProject } from "../../../IsolatedProject.ts";
6
7/**
8 * The isolated consumer project this instance's program is bundled from
9 * (see `test/IsolatedProject.ts`): `main` lives outside the repository, so
10 * the bundle `cwd` resolves none of alchemy's dependencies and the bun
11 * bootstrap's own imports must be anchored by the bundler.
12 */
13export const project = isolatedProject("ec2-instance", import.meta.filename);
14
15/**
16 * Minimal hosted `AWS.EC2.Instance` program served from an isolated project.
17 * The props Effect provisions a one-AZ public network and a security group
18 * opening the app port; `/health` answering 200 from the instance's public
19 * IP proves the generated bootstrap booted under the systemd unit — with its
20 * imports left external bun dies at module load and nothing ever listens.
21 */
22export default class IsolatedProjectInstance extends AWS.EC2.Instance<IsolatedProjectInstance>()(
23 "Ec2IsolatedProjectInstance",
24 Effect.gen(function* () {
25 const network = yield* AWS.EC2.Network("Ec2IsolatedProjectNetwork", {
26 cidrBlock: "10.83.0.0/16",
27 availabilityZones: 1,
28 });
29 const securityGroup = yield* AWS.EC2.SecurityGroup("Ec2IsolatedProjectSg", {
30 vpcId: network.vpcId,
31 description: "alchemy ec2 isolated-project e2e",
32 ingress: [
33 {
34 ipProtocol: "tcp",
35 fromPort: 3000,
36 toPort: 3000,
37 cidrIpv4: "0.0.0.0/0",
38 description: "app",
39 },
40 ],
41 egress: [
42 {
43 ipProtocol: "-1",
44 cidrIpv4: "0.0.0.0/0",
45 description: "all outbound",
46 },
47 ],
48 });
49 return {
50 main: project.main,
51 imageId: AWS.EC2.amazonLinux2023(),
52 instanceType: "t3.small",
53 subnetId: network.publicSubnetIds[0],
54 securityGroupIds: [securityGroup.groupId],
55 associatePublicIpAddress: true,
56 port: 3000,
57 };
58 }),
59 Effect.gen(function* () {
60 return {
61 fetch: Effect.gen(function* () {
62 const request = yield* HttpServerRequest;
63 const url = new URL(request.url, "http://instance");
64 if (url.pathname === "/health") {
65 return yield* HttpServerResponse.json({ ok: true });
66 }
67 return HttpServerResponse.text("hello from isolated project");
68 }),
69 };
70 }),
71) {}