1import type * as Credentials from "@distilled.cloud/aws/Credentials";
2import * as Presign from "@distilled.cloud/aws/Presign";
3import type * as Region from "@distilled.cloud/aws/Region";
4import * as Effect from "effect/Effect";
5import * as Layer from "effect/Layer";
6import * as Binding from "../../Binding.ts";
7import * as Output from "../../Output.ts";
8import { isBindingHost } from "../Lambda/Function.ts";
9import type { Bucket } from "./Bucket.ts";
10import {
11 PresignPutObject,
12 type PresignPutObjectRequest,
13} from "./PresignPutObject.ts";
14
15export const PresignPutObjectHttp = Layer.effect(
16 PresignPutObject,
17 Effect.gen(function* () {
18 const services = yield* Effect.context<
19 Credentials.Credentials | Region.Region
20 >();
21
22 return Effect.fn(function* (bucket: Bucket) {
23 const BucketName = yield* bucket.bucketName;
24 if (!globalThis.__ALCHEMY_RUNTIME__) {
25 const host = yield* Binding.Host;
26 if (isBindingHost(host)) {
27 yield* host.bind`Allow(${host}, AWS.S3.PresignPutObject(${bucket}))`({
28 policyStatements: [
29 {
30 Effect: "Allow",
31 Action: ["s3:PutObject"],
32 Resource: [Output.interpolate`${bucket.bucketArn}/*`],
33 },
34 ],
35 });
36 }
37 }
38 return Effect.fn(`AWS.S3.PresignPutObject(${bucket.LogicalId})`)(
39 function* (request: PresignPutObjectRequest) {
40 const bucketName = yield* BucketName;
41 return yield* Presign.presignS3Url({
42 method: "PUT",
43 bucket: bucketName,
44 key: request.key,
45 expiresIn: request.expiresIn,
46 contentType: request.contentType,
47 }).pipe(Effect.provideContext(services));
48 },
49 );
50 });
51 }),
52);