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 BatchGetItem,
8 type BatchGetItemRequest,
9 type BatchGetItemTables,
10} from "./BatchGetItem.ts";
11
12export const BatchGetItemHttp = Layer.effect(
13 BatchGetItem,
14 Effect.gen(function* () {
15 const batchGetItem = yield* DynamoDB.batchGetItem;
16
17 return Effect.fn(function* (...tables: BatchGetItemTables) {
18 const sortedTables = sortTables(tables);
19 const tableNames = new Map(
20 yield* Effect.forEach(sortedTables, (table) =>
21 Effect.gen(function* () {
22 return [table.LogicalId, yield* table.tableName] as const;
23 }),
24 ),
25 );
26
27 const getTableName = Effect.fn(function* (tableId: string) {
28 const TableName = tableNames.get(tableId);
29 if (!TableName) {
30 return yield* Effect.die(
31 new Error(
32 `BatchGetItem request references unbound table '${tableId}'`,
33 ),
34 );
35 }
36 return yield* TableName;
37 });
38
39 if (!globalThis.__ALCHEMY_RUNTIME__) {
40 const host = yield* Binding.Host;
41 if (isBindingHost(host)) {
42 yield* host.bind`Allow(${host}, AWS.DynamoDB.BatchGetItem(${sortedTables}))`(
43 {
44 policyStatements: [
45 {
46 Effect: "Allow",
47 Action: ["dynamodb:BatchGetItem"],
48 Resource: sortedTables.map((table) => table.tableArn),
49 },
50 ],
51 },
52 );
53 }
54 }
55
56 return Effect.fn(`AWS.DynamoDB.BatchGetItem(${sortedTables})`)(function* (
57 request: BatchGetItemRequest,
58 ) {
59 const requestItems = yield* Effect.forEach(
60 Object.entries(request.RequestItems),
61 ([tableId, keys]) =>
62 Effect.gen(function* () {
63 return [yield* getTableName(tableId), keys] as const;
64 }),
65 );
66
67 return yield* batchGetItem({
68 ...request,
69 RequestItems: Object.fromEntries(requestItems),
70 });
71 });
72 });
73 }),
74);
75
76const sortTables = (tables: BatchGetItemTables) =>
77 [
78 ...new Map(
79 tables.map((table) => [table.LogicalId, table] as const),
80 ).values(),
81 ].sort((a, b) =>
82 a.LogicalId.localeCompare(b.LogicalId),
83 ) as BatchGetItemTables;