1import * as Effect from "effect/Effect";
2import * as Layer from "effect/Layer";
3import {
4 PresignGetObject,
5 type PresignGetObjectRequest,
6} from "./PresignGetObject.ts";
7import { makePresignBinding, presignR2Url } from "./PresignToken.ts";
8
9/**
10 * Implementation of {@link PresignGetObject} that signs URLs with S3
11 * credentials derived from an API token. Signing is local SigV4 — no request
12 * is made to R2.
13 *
14 * Deployed, it mints a scoped account API token with
15 * `Workers R2 Storage Read` (access key id = token id, secret = SHA-256 of
16 * the token value) and signs URLs for `{accountId}.r2.cloudflarestorage.com`.
17 * Under `alchemy dev`, a locally-emulated bucket is signed with fixed local
18 * credentials for the Worker's local S3 endpoint, and no token is created.
19 *
20 * @layer
21 * @provides Cloudflare.R2.PresignGetObject
22 * @product R2
23 */
24export const PresignGetObjectToken = Layer.effect(
25 PresignGetObject,
26 Effect.suspend(() =>
27 makePresignBinding<PresignGetObjectRequest>({
28 name: "Cloudflare.R2.PresignGetObject",
29 access: "read",
30 presign: (credentials, request) =>
31 presignR2Url(credentials, {
32 method: "GET",
33 key: request.key,
34 expiresIn: request.expiresIn,
35 query: {
36 ...(request.contentType !== undefined
37 ? { "response-content-type": request.contentType }
38 : {}),
39 ...(request.contentDisposition !== undefined
40 ? { "response-content-disposition": request.contentDisposition }
41 : {}),
42 },
43 }),
44 }),
45 ),
46);