1import * as Cloudflare from "alchemy/Cloudflare";
2import * as Neon from "alchemy/Neon";
3import * as Effect from "effect/Effect";
4import * as Layer from "effect/Layer";
5import { HttpServerRequest } from "effect/http/HttpServerRequest";
6import * as HttpServerResponse from "effect/http/HttpServerResponse";
7import { CloudflareHyperdrive } from "../../../src/CloudflareHyperdrive.ts";
8import { BetterAuth } from "../../../src/index.ts";
9
10export const HdProject = Neon.Project("BetterAuthHdPg");
11
12export const Hyperdrive = Effect.gen(function* () {
13 const project = yield* HdProject;
14 return yield* Cloudflare.Hyperdrive.Connection("BetterAuthHd", {
15 origin: project.origin,
16 // auth reads must never be stale
17 caching: { disabled: true },
18 });
19});
20
21// Hyperdrive's connection string only exists inside the Worker — the Neon
22// origin URL drives the deploy-time migration Action instead.
23const AuthDatabase = Layer.unwrap(
24 Effect.gen(function* () {
25 const project = yield* HdProject;
26 const connection = yield* Hyperdrive;
27 return CloudflareHyperdrive(connection, {
28 migrate: project.connectionUri,
29 });
30 }),
31);
32
33export default class HyperdriveAuthWorker extends Cloudflare.Worker<HyperdriveAuthWorker>()(
34 "BetterAuthHdWorker",
35 {
36 main: import.meta.url,
37 compatibility: {
38 date: "2026-03-17",
39 flags: ["nodejs_compat"],
40 },
41 },
42 Effect.gen(function* () {
43 const auth = yield* BetterAuth({
44 basePath: "/auth",
45 emailAndPassword: { enabled: true },
46 });
47
48 return {
49 fetch: Effect.gen(function* () {
50 const request = yield* HttpServerRequest;
51 if (request.url.startsWith("/auth")) {
52 return yield* auth.fetch;
53 }
54 if (request.url.startsWith("/me")) {
55 const session = yield* auth
56 .getSession()
57 .pipe(
58 Effect.catchTag("BetterAuthApiError", () => Effect.succeed(null)),
59 );
60 return yield* HttpServerResponse.json({
61 email: session?.user.email ?? null,
62 });
63 }
64 return HttpServerResponse.text("ok");
65 }),
66 };
67 }).pipe(Effect.provide(AuthDatabase)),
68) {}