1import * as Railway from "@/Railway";
2import * as Effect from "effect/Effect";
3import * as Redacted from "effect/Redacted";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import { Partition, Site } from "./suite-env.ts";
7
8export const MONGO_HTTP_PORT = 3000;
9
10export { Site };
11
12export const Db = Railway.mongo("Db", {
13 project: Site,
14 environment: Partition,
15});
16
17/**
18 * HTTP Service that binds Mongo via {@link Railway.ConnectMongo}
19 * and answers ping. Never returns the connection string.
20 */
21export default class MongoApi extends Railway.Service<MongoApi>()(
22 "MongoApi",
23 {
24 project: Site,
25 environment: Partition,
26 main: import.meta.url,
27 port: MONGO_HTTP_PORT,
28 build: { install: ["mongodb"] },
29 },
30 Effect.gen(function* () {
31 const conn = yield* Railway.ConnectMongo(Db);
32
33 return {
34 fetch: Effect.gen(function* () {
35 const request = yield* HttpServerRequest;
36 const path = new URL(request.url, "http://service").pathname;
37 if (path === "/ping") {
38 return yield* HttpServerResponse.json({ ok: true });
39 }
40 const url = yield* conn.connectionString;
41 const ping = yield* Railway.pingMongo(Redacted.value(url));
42 if (path === "/health" || path === "/") {
43 return yield* HttpServerResponse.json(ping);
44 }
45 return yield* HttpServerResponse.json(ping, { status: 404 });
46 }).pipe(
47 Effect.catch((error) =>
48 HttpServerResponse.json(
49 { ok: false, error: String(error) },
50 { status: 500 },
51 ),
52 ),
53 ),
54 };
55 }).pipe(Effect.provide(Railway.ConnectMongoHttp)),
56) {}