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 type { Table } from "./Table.ts";
7import {
8 TransactGetItems,
9 type TransactGetItemsRequest,
10 type TransactGetItemsTables,
11} from "./TransactGetItems.ts";
12
13export const TransactGetItemsHttp = Layer.effect(
14 TransactGetItems,
15 Effect.gen(function* () {
16 const transactGetItems = yield* DynamoDB.transactGetItems;
17
18 return Effect.fn(function* (...tables: TransactGetItemsTables) {
19 const sortedTables = sortTables(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 `TransactGetItems 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.TransactGetItems(${sortedTables}))`(
44 {
45 policyStatements: [
46 {
47 Effect: "Allow",
48 Action: ["dynamodb:GetItem"],
49 Resource: sortedTables.map((table) => table.tableArn),
50 },
51 ],
52 },
53 );
54 }
55 }
56
57 return Effect.fn(`AWS.DynamoDB.TransactGetItems(${sortedTables})`)(
58 function* (request: TransactGetItemsRequest) {
59 const transactItems = yield* Effect.forEach(
60 request.TransactItems,
61 ({ Get }) =>
62 Effect.gen(function* () {
63 return {
64 Get: {
65 ...Get,
66 TableName: yield* getTableName(Get.Table),
67 },
68 };
69 }),
70 );
71
72 return yield* transactGetItems({
73 ...request,
74 TransactItems: transactItems,
75 });
76 },
77 );
78 });
79 }),
80);
81
82const sortTables = (tables: TransactGetItemsTables) =>
83 [
84 ...new Map(
85 tables.map((table) => [table.LogicalId, table] as const),
86 ).values(),
87 ].sort((a, b) =>
88 a.LogicalId.localeCompare(b.LogicalId),
89 ) as TransactGetItemsTables;