1import * as Fly from "@/Fly";
2import * as Drizzle from "@/Drizzle/Postgres.ts";
3import * as Effect from "effect/Effect";
4import * as Result from "effect/Result";
5import { HttpServerRequest } from "effect/http/HttpServerRequest";
6import * as HttpServerResponse from "effect/http/HttpServerResponse";
7
8export const POSTGRES_PORT = 3000;
9
10export const MpgSite = Fly.App("MpgSite", {
11 enableSubdomains: true,
12});
13
14export const Db = Fly.Postgres("Db", {
15 region: "iad",
16 plan: "basic",
17 volumeSizeGb: 10,
18});
19
20export const MpgIp = Fly.IpAssignment("Shared", {
21 app: MpgSite,
22 type: "shared_v4",
23});
24
25/**
26 * HTTP Service that binds Managed Postgres via {@link Fly.ConnectPostgres}
27 * and answers SELECT 1. Never returns the connection string.
28 */
29export default class PostgresApi extends Fly.Service<PostgresApi>()(
30 "PostgresApi",
31 {
32 app: MpgSite,
33 main: import.meta.url,
34 region: "iad",
35 port: POSTGRES_PORT,
36 guest: { cpuKind: "shared", cpus: 1, memoryMb: 512 },
37 build: { install: ["pg"] },
38 },
39 Effect.gen(function* () {
40 const conn = yield* Fly.ConnectPostgres(Db);
41 const db = yield* Drizzle.Postgres(conn.connectionString);
42 const direct = yield* Drizzle.Postgres(conn.directConnectionString);
43
44 return {
45 fetch: Effect.gen(function* () {
46 const request = yield* HttpServerRequest;
47 const path = new URL(request.url, "http://service").pathname;
48 if (path === "/ping") {
49 return yield* HttpServerResponse.json({ ok: true });
50 }
51 const client = path === "/direct" ? direct : db;
52 const result = yield* Effect.result(client.execute("select 1 as ok"));
53 if (Result.isFailure(result)) {
54 const error = result.failure;
55 return yield* HttpServerResponse.json(
56 {
57 ok: false,
58 error:
59 error instanceof Error
60 ? `${error.name}: ${error.message}`
61 : String(error),
62 },
63 { status: 500 },
64 );
65 }
66 const rows = result.success;
67 if (path === "/health" || path === "/direct" || path === "/") {
68 return yield* HttpServerResponse.json({ rows });
69 }
70 return yield* HttpServerResponse.json({ rows }, { status: 404 });
71 }),
72 };
73 }).pipe(Effect.provide(Fly.ConnectPostgresHttp)),
74) {}