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
6/**
7 * Marker served by the hosted program, proving over HTTP that the deployed
8 * instance runs THIS build of the bundle.
9 */
10export const MARKER = "ec2-dev-marker-v1";
11
12/**
13 * Hosted EC2 instance fixture for the local (floci) dev test: a
14 * public-subnet network, a security group opening the app port, and a
15 * hosted `{ fetch }` program served by the instance's Bun HTTP server on
16 * `:3000`. Under `alchemy dev` the instance runs as a docker container in
17 * the emulator; the security-group ingress makes floci publish the app
18 * port behind its host-routing mux, so
19 * `http://<instanceId>.localhost.floci.io:3000` reaches the program from
20 * the host.
21 */
22export default class DevInstance extends AWS.EC2.Instance<DevInstance>()(
23 "Ec2DevInstance",
24 Effect.gen(function* () {
25 const network = yield* AWS.EC2.Network("Ec2DevNetwork", {
26 cidrBlock: "10.83.0.0/16",
27 availabilityZones: 1,
28 });
29 const securityGroup = yield* AWS.EC2.SecurityGroup("Ec2DevSg", {
30 vpcId: network.vpcId,
31 description: "alchemy ec2 dev-mode 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: import.meta.filename,
51 imageId: AWS.EC2.amazonLinux2023(),
52 instanceType: "t3.micro",
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 if (url.pathname === "/marker") {
68 return HttpServerResponse.text(MARKER);
69 }
70 return HttpServerResponse.text("hello from ec2 dev instance");
71 }),
72 };
73 }),
74) {}