1import * as DynamoDB from "@distilled.cloud/aws/dynamodb";
2import * as Effect from "effect/Effect";
3import * as Binding from "../../Binding.ts";
4import * as Layer from "effect/Layer";
5import { isBindingHost } from "../Lambda/Function.ts";
6import {
7 BatchWriteItem,
8 type BatchWriteItemRequest,
9 type BatchWriteItemTables,
10 sortBatchWriteItemTables,
11} from "./BatchWriteItem.ts";
12
13export const BatchWriteItemHttp = Layer.effect(
14 BatchWriteItem,
15 Effect.gen(function* () {
16 const batchWriteItem = yield* DynamoDB.batchWriteItem;
17
18 return Effect.fn(function* (...tables: BatchWriteItemTables) {
19 const sortedTables = sortBatchWriteItemTables(tables);
20 const tableNames = new Map(
21 yield* Effect.forEach(sortedTables, (table) =>
22 Effect.gen(function* () {
23 return [table.LogicalId, yield* table.tableName] as const;
24 }),
25 ),
26 );
27
28 const getTableName = Effect.fn(function* (tableId: string) {
29 const TableName = tableNames.get(tableId);
30 if (!TableName) {
31 return yield* Effect.die(
32 new Error(
33 `BatchWriteItem request references unbound table '${tableId}'`,
34 ),
35 );
36 }
37 return yield* TableName;
38 });
39
40 if (!globalThis.__ALCHEMY_RUNTIME__) {
41 const host = yield* Binding.Host;
42 if (isBindingHost(host)) {
43 yield* host.bind`Allow(${host}, AWS.DynamoDB.BatchWriteItem(${sortedTables}))`(
44 {
45 policyStatements: [
46 {
47 Effect: "Allow",
48 Action: ["dynamodb:BatchWriteItem"],
49 Resource: sortedTables.map((table) => table.tableArn),
50 },
51 ],
52 },
53 );
54 }
55 }
56
57 return Effect.fn(`AWS.DynamoDB.BatchWriteItem(${sortedTables})`)(
58 function* (request: BatchWriteItemRequest) {
59 const requestItems = yield* Effect.forEach(
60 Object.entries(request.RequestItems),
61 ([tableId, writes]) =>
62 Effect.gen(function* () {
63 return [yield* getTableName(tableId), writes] as const;
64 }),
65 );
66
67 return yield* batchWriteItem({
68 ...request,
69 RequestItems: Object.fromEntries(requestItems),
70 });
71 },
72 );
73 });
74 }),
75);