1import { ReadBucket } from "@/Neon/ReadBucket";
2import { ReadBucketHttp } from "@/Neon/ReadBucketHttp";
3import { ReadWriteBucket } from "@/Neon/ReadWriteBucket";
4import { ReadWriteBucketHttp } from "@/Neon/ReadWriteBucketHttp";
5import { CurrentRuntimeContext } from "@/RuntimeContext";
6import { StorageBindingError } from "@/Neon/StorageBinding";
7import * as Effect from "effect/Effect";
8import * as Layer from "effect/Layer";
9import { HttpServerRequest } from "effect/http/HttpServerRequest";
10import * as HttpServerResponse from "effect/http/HttpServerResponse";
11import { StorageBucket } from "./StorageResources.ts";
12
13export const storageHttpHandler = Effect.gen(function* () {
14 const bucket = yield* StorageBucket;
15 const files = yield* ReadWriteBucket(bucket);
16 const reader = yield* ReadBucket(bucket);
17 const runtime = yield* CurrentRuntimeContext;
18 if (!runtime)
19 return yield* Effect.die(
20 new StorageBindingError({
21 message: "Storage HTTP fixture requires a runtime host",
22 }),
23 );
24 return {
25 fetch: Effect.gen(function* () {
26 const request = yield* HttpServerRequest;
27 if (request.url.endsWith("/write")) {
28 yield* files.put("external.txt", "external roundtrip", {
29 ContentType: "text/plain",
30 });
31 return HttpServerResponse.text("ok");
32 }
33 const item = yield* reader.head("external.txt");
34 return yield* HttpServerResponse.json({
35 size: item?.ContentLength,
36 hasAccountKey: (yield* runtime.get("NEON_API_KEY")) !== undefined,
37 });
38 }).pipe(
39 Effect.catch(() =>
40 Effect.succeed(
41 HttpServerResponse.text("Storage request failed", { status: 500 }),
42 ),
43 ),
44 ),
45 };
46}).pipe(Effect.provide(Layer.mergeAll(ReadWriteBucketHttp, ReadBucketHttp)));