1import * as Prisma from "alchemy/Prisma";
2import * as SQL from "alchemy/SQL/Postgres";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6import { Connection, Project } from "./Database.ts";
7
8export default class Api extends Prisma.Compute<Api>()(
9 "Api",
10 Effect.gen(function* () {
11 const project = yield* Project;
12 return {
13 project,
14 main: import.meta.filename,
15 regionId: "eu-west-3",
16 branchGitName: "main",
17 port: 3000,
18 healthCheck: { path: "/api/health" },
19 destroyOldDeployment: true,
20 };
21 }),
22 Effect.gen(function* () {
23 const db = yield* Prisma.Connect(Connection);
24 const sql = yield* SQL.Postgres({ url: db.databaseUrl });
25
26 return {
27 fetch: Effect.gen(function* () {
28 const request = yield* HttpServerRequest;
29 const headers = { "access-control-allow-origin": "*" };
30 if (request.method !== "GET") {
31 return HttpServerResponse.text("Method not allowed", {
32 status: 405,
33 headers: { ...headers, allow: "GET" },
34 });
35 }
36 if (request.url === "/api/health") {
37 return yield* HttpServerResponse.json({ ok: true }, { headers });
38 }
39 if (request.url === "/api/time") {
40 const rows = yield* sql<{
41 time: string;
42 }>`SELECT current_timestamp::text AS time`;
43 return yield* HttpServerResponse.json(rows[0], { headers });
44 }
45 return HttpServerResponse.text("Not found", { status: 404, headers });
46 }).pipe(
47 Effect.catchTag("SqlError", () =>
48 Effect.succeed(
49 HttpServerResponse.text("Database unavailable", {
50 status: 503,
51 headers: { "access-control-allow-origin": "*" },
52 }),
53 ),
54 ),
55 ),
56 };
57 }).pipe(Effect.provide(Prisma.ConnectBinding)),
58) {}