1import * as Cloudflare from "@/Cloudflare/index.ts";
2import * as Neon from "@/Neon/index.ts";
3import * as SQL from "@/SQL/Postgres.ts";
4import * as Effect from "effect/Effect";
5import { HttpServerRequest } from "effect/http/HttpServerRequest";
6import * as HttpServerResponse from "effect/http/HttpServerResponse";
7
8/**
9 * Hyperdrive Connection for the local-emulation test: the `dev` origin
10 * points at the same real Neon Postgres the live Hyperdrive tests use, so
11 * the local passthrough binding actually serves SQL. Caching is disabled
12 * for prop parity with the live suites (Hyperdrive's default SELECT cache
13 * poisons read-after-write assertions; the local passthrough has no cache).
14 */
15export const LocalHyperdrive = Effect.gen(function* () {
16 const project = yield* Neon.Project("HyperdriveLocalProject");
17 return yield* Cloudflare.Hyperdrive.Connection("HyperdriveLocalConnection", {
18 origin: project.origin,
19 caching: { disabled: true },
20 dev: project.origin,
21 });
22});
23
24/**
25 * Effect-native Worker binding the locally-emulated Hyperdrive Connection.
26 * `/query` runs a trivial SQL statement through `SQL.Postgres` over the
27 * binding's connection string — under `alchemy dev` that string points
28 * straight at the `dev` origin (the local runtime's origin passthrough).
29 */
30export default class HyperdriveLocalWorker extends Cloudflare.Worker<HyperdriveLocalWorker>()(
31 "HyperdriveLocalWorker",
32 { main: import.meta.url },
33 Effect.gen(function* () {
34 const hd = yield* Cloudflare.Hyperdrive.Connect(LocalHyperdrive);
35 const sql = yield* SQL.Postgres({ url: hd.connectionString });
36
37 return {
38 fetch: Effect.gen(function* () {
39 const request = yield* HttpServerRequest;
40 const url = new URL(request.url, "http://x");
41 if (url.pathname === "/query") {
42 const rows = (yield* sql`
43 SELECT 1 + 1 AS sum, current_database() AS db
44 `) as ReadonlyArray<{ sum: number; db: string }>;
45 const host = yield* hd.host;
46 return yield* HttpServerResponse.json({ row: rows[0], host });
47 }
48 return HttpServerResponse.text("Not Found", { status: 404 });
49 }).pipe(
50 Effect.catchCause((cause) =>
51 HttpServerResponse.json({ error: String(cause) }, { status: 500 }),
52 ),
53 ),
54 };
55 }).pipe(Effect.provide(Cloudflare.Hyperdrive.ConnectBinding)),
56) {}