1import * as Fly from "alchemy/Fly";
2import * as Config from "effect/Config";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import { API_PORT, Marker, SECRET_NAME, Site } from "./shared.ts";
7
8/**
9 * HTTP Service: Fly injects {@link Marker} as env `{@link SECRET_NAME}`.
10 * Read it from `fetch` with `Config.String` — never the plaintext.
11 */
12export default class Api extends Fly.Service<Api>()(
13 "Api",
14 {
15 app: Site,
16 main: import.meta.url,
17 region: "iad",
18 port: API_PORT,
19 guest: { cpuKind: "shared", cpus: 1, memoryMb: 256 },
20 },
21 Effect.gen(function* () {
22 yield* Marker;
23
24 return {
25 fetch: Effect.gen(function* () {
26 const request = yield* HttpServerRequest;
27 const url = new URL(request.url, "http://service");
28 const value = yield* Config.String(SECRET_NAME).pipe(
29 Effect.orElseSucceed(() => ""),
30 );
31 const body = {
32 ok: value.length > 0,
33 name: SECRET_NAME,
34 };
35 if (url.pathname === "/health" || url.pathname === "/secret") {
36 return yield* HttpServerResponse.json(body);
37 }
38 return yield* HttpServerResponse.json(body);
39 }),
40 };
41 }),
42) {}