1import * as EC2 from "@/AWS/EC2";
2import * as Lambda from "@/AWS/Lambda";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import path from "pathe";
7
8const main = path.resolve(import.meta.dirname, "network-function.ts");
9
10export class NetworkTestFunction extends Lambda.Function<Lambda.Function>()(
11 "NetworkTestFunction",
12) {}
13
14/**
15 * Runtime-safety regression fixture for the `EC2.Network` composite.
16 *
17 * The Lambda runtime re-executes this layer at function init, so `Network`
18 * must not perform deploy-time-only work on the runtime path:
19 *
20 * - numeric `availabilityZones` triggers AZ auto-discovery via
21 * `ec2:DescribeAvailabilityZones` — the function role has no EC2
22 * permissions, so calling it at init fails with `UnauthorizedOperation`
23 * - `gatewayEndpoints` needs the region, which must come from the `Region`
24 * service (provided by the runtime), not `AWSEnvironment` (deploy-only)
25 *
26 * A 200 from `/network` proves the composition INITs cleanly and that the
27 * resources it yields resolve their attributes from the injected environment.
28 */
29export default NetworkTestFunction.make(
30 {
31 main,
32 functionUrl: true,
33 },
34 Effect.gen(function* () {
35 const network = yield* EC2.Network("Network", {
36 cidrBlock: "10.77.0.0/16",
37 // numeric — exercises the ec2:DescribeAvailabilityZones discovery path
38 availabilityZones: 2,
39 // exercises the region lookup for the endpoint service name
40 gatewayEndpoints: ["s3"],
41 });
42
43 const VpcId = yield* network.vpcId;
44 const SubnetId = yield* network.publicSubnetIds[0];
45
46 return {
47 fetch: Effect.gen(function* () {
48 const request = yield* HttpServerRequest;
49 const url = new URL(request.originalUrl);
50
51 if (request.method === "GET" && url.pathname === "/network") {
52 const vpcId = yield* VpcId;
53 const subnetId = yield* SubnetId;
54 return yield* HttpServerResponse.json({ vpcId, subnetId });
55 }
56
57 return HttpServerResponse.text("ok");
58 }).pipe(Effect.orDie),
59 };
60 }),
61);