1import * as Cloudflare from "alchemy/Cloudflare";
2import * as PrismaPostgres from "alchemy/Prisma/ORM/Postgres";
3import * as Effect from "effect/Effect";
4import * as Schema from "effect/Schema";
5import { makeSchemas } from "alchemy/Prisma/ORM/Schema";
6import * as HttpServerRequest from "effect/http/HttpServerRequest";
7import * as HttpServerResponse from "effect/http/HttpServerResponse";
8import { Hyperdrive } from "./Db.ts";
9import { contract } from "./prisma/contract.ts";
10
11const schemas = makeSchemas(contract);
12
13export default class Api extends Cloudflare.Worker<Api>()(
14 "Api",
15 {
16 main: import.meta.url,
17 },
18 Effect.gen(function* () {
19 const conn = yield* Cloudflare.Hyperdrive.Connect(Hyperdrive);
20 const db = yield* PrismaPostgres.Postgres(conn.connectionString, {
21 contract,
22 });
23
24 return {
25 fetch: Effect.gen(function* () {
26 const request = yield* HttpServerRequest.HttpServerRequest;
27 switch (request.method) {
28 case "GET": {
29 if (request.url === "/") {
30 const users = yield* db.orm.public.User.all();
31 return yield* HttpServerResponse.json({ users });
32 }
33 const id = request.url.split("/").pop() ?? "";
34 const user = yield* db.orm.public.User.where({ id })
35 .include("posts")
36 .first();
37 return yield* HttpServerResponse.json({ user });
38 }
39 case "POST": {
40 const values = yield* Effect.sync(() => ({
41 name: crypto.randomUUID(),
42 email: crypto.randomUUID(),
43 }));
44 const row = yield* db.orm.public.User.create(values);
45 const user = yield* Schema.decodeUnknownEffect(schemas.public.User)(
46 row,
47 );
48 return yield* HttpServerResponse.json({ user });
49 }
50 case "DELETE": {
51 const id = request.url.split("/").pop() ?? "";
52 const user = yield* db.orm.public.User.where({ id }).delete();
53 return yield* HttpServerResponse.json({ user });
54 }
55 default: {
56 return yield* HttpServerResponse.json(
57 { error: "Method not allowed" },
58 { status: 405 },
59 );
60 }
61 }
62 }).pipe(
63 Effect.catch((cause) =>
64 HttpServerResponse.json(
65 { ok: false, error: cause._tag },
66 { status: 500 },
67 ),
68 ),
69 ),
70 };
71 }).pipe(Effect.provide(Cloudflare.Hyperdrive.ConnectBinding)),
72) {}