1import * as Cloudflare from "@/Cloudflare/index.ts";
2import type { Bucket } from "@/Cloudflare/R2/Bucket.ts";
3import * as Effect from "effect/Effect";
4import { HttpServerRequest } from "effect/http/HttpServerRequest";
5import * as HttpServerResponse from "effect/http/HttpServerResponse";
6
7/**
8 * Shared Worker implementation for the presign fixtures: mints presigned
9 * URLs for `bucket` and exposes the native binding so the test can verify
10 * that uploads through a presigned URL land in the same bucket.
11 *
12 * - `GET /presign-put?key=&contentType=` → `{ url }`
13 * - `GET /presign-get?key=&contentType=` → `{ url }`
14 * - `GET /read?key=` → `{ value, contentType }` via the native binding
15 * - `PUT /write?key=` → writes the body via the native binding
16 */
17export const presignWorker = (bucket: Effect.Effect<Bucket, never, any>) =>
18 Effect.gen(function* () {
19 const b = yield* bucket;
20 const presignPut = yield* Cloudflare.R2.PresignPutObject(b);
21 const presignGet = yield* Cloudflare.R2.PresignGetObject(b);
22 const r2 = yield* Cloudflare.R2.ReadWriteBucket(b);
23 return {
24 fetch: Effect.gen(function* () {
25 const request = yield* HttpServerRequest;
26 const url = new URL(request.url, "http://x");
27 const key = url.searchParams.get("key") ?? "";
28 const contentType = url.searchParams.get("contentType") ?? undefined;
29 switch (url.pathname) {
30 case "/presign-put":
31 return yield* HttpServerResponse.json({
32 url: yield* presignPut({ key, contentType }).pipe(Effect.orDie),
33 });
34 case "/presign-get":
35 return yield* HttpServerResponse.json({
36 url: yield* presignGet({ key, contentType }).pipe(Effect.orDie),
37 });
38 case "/read": {
39 const object = yield* r2.get(key).pipe(Effect.orDie);
40 return yield* HttpServerResponse.json({
41 value:
42 object === null
43 ? null
44 : yield* object.text().pipe(Effect.orDie),
45 contentType: object?.httpMetadata?.contentType ?? null,
46 });
47 }
48 case "/write": {
49 const body = yield* request.text.pipe(Effect.orDie);
50 yield* r2.put(key, body).pipe(Effect.orDie);
51 return HttpServerResponse.text("ok");
52 }
53 default:
54 return HttpServerResponse.text("ok");
55 }
56 }),
57 };
58 }).pipe(
59 Effect.provide(Cloudflare.R2.PresignPutObjectToken),
60 Effect.provide(Cloudflare.R2.PresignGetObjectToken),
61 Effect.provide(Cloudflare.R2.ReadWriteBucketBinding),
62 );