1import * as DirectoryService from "@/AWS/DirectoryService";
2import * as Lambda from "@/AWS/Lambda";
3import * as Duration from "effect/Duration";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6import { HttpServerRequest } from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8import path from "pathe";
9
10const main = path.resolve(import.meta.dirname, "handler.ts");
11
12export class DirectoryServiceTestFunction extends Lambda.Function<Lambda.Function>()(
13 "DirectoryServiceTestFunction",
14) {}
15
16export default DirectoryServiceTestFunction.make(
17 {
18 main,
19 functionUrl: true,
20 timeout: Duration.seconds(30),
21 },
22 Effect.gen(function* () {
23 // Account-level capabilities — no directory required, so the fixture
24 // deploys in seconds. (Directory-scoped capabilities bind to a live
25 // directory, which takes ~10 minutes to provision; they share the same
26 // scaffolding and are exercised by the gated lifecycle tests.)
27 const getDirectoryLimits = yield* DirectoryService.GetDirectoryLimits();
28 const describeDirectories = yield* DirectoryService.DescribeDirectories();
29
30 const bound = { getDirectoryLimits, describeDirectories };
31
32 return {
33 fetch: Effect.gen(function* () {
34 const request = yield* HttpServerRequest;
35 const url = new URL(request.originalUrl);
36 const pathname = url.pathname;
37
38 if (request.method === "GET" && pathname === "/bindings") {
39 return yield* HttpServerResponse.json({
40 bound: Object.keys(bound),
41 });
42 }
43
44 // Account limits: the response always carries the cloud directory
45 // counters for the region.
46 if (request.method === "GET" && pathname === "/limits") {
47 const { DirectoryLimits } = yield* getDirectoryLimits();
48 return yield* HttpServerResponse.json({
49 cloudOnlyLimit: DirectoryLimits?.CloudOnlyDirectoriesLimit,
50 cloudOnlyCount: DirectoryLimits?.CloudOnlyDirectoriesCurrentCount,
51 });
52 }
53
54 // Account-wide directory enumeration (empty in a clean account).
55 if (request.method === "GET" && pathname === "/directories") {
56 const { DirectoryDescriptions } = yield* describeDirectories();
57 return yield* HttpServerResponse.json({
58 ids: (DirectoryDescriptions ?? []).map(
59 (directory) => directory.DirectoryId,
60 ),
61 });
62 }
63
64 return yield* HttpServerResponse.json(
65 { error: "Not found", method: request.method, pathname },
66 { status: 404 },
67 );
68 }).pipe(Effect.orDie),
69 };
70 }).pipe(
71 Effect.provide(
72 Layer.mergeAll(
73 DirectoryService.GetDirectoryLimitsHttp,
74 DirectoryService.DescribeDirectoriesHttp,
75 ),
76 ),
77 ),
78);