dyno-table 2.2.1 → 2.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (102) hide show
  1. package/README.md +200 -1860
  2. package/dist/builders.cjs +55 -0
  3. package/dist/builders.d.cts +4 -0
  4. package/dist/builders.d.ts +4 -0
  5. package/dist/builders.js +2 -0
  6. package/dist/chunk-2EWNZOUK.js +618 -0
  7. package/dist/chunk-2WIBY7PZ.js +46 -0
  8. package/dist/chunk-7UJJ7JXM.cjs +63 -0
  9. package/dist/chunk-DTFJJASK.js +3200 -0
  10. package/dist/chunk-EODPMYPE.js +558 -0
  11. package/dist/chunk-KA3VPIPS.cjs +560 -0
  12. package/dist/chunk-NTA6GDPP.cjs +622 -0
  13. package/dist/chunk-PB7BBCZO.cjs +32 -0
  14. package/dist/chunk-QVRMYGC4.js +29 -0
  15. package/dist/chunk-XYL43FDX.cjs +3217 -0
  16. package/dist/conditions.cjs +67 -62
  17. package/dist/conditions.js +1 -48
  18. package/dist/entity.cjs +14 -625
  19. package/dist/entity.d.cts +2 -10
  20. package/dist/entity.d.ts +2 -10
  21. package/dist/entity.js +2 -626
  22. package/dist/index-2cbm07Bi.d.ts +2797 -0
  23. package/dist/index-DlN8G9hd.d.cts +2797 -0
  24. package/dist/index.cjs +111 -4460
  25. package/dist/index.d.cts +2 -10
  26. package/dist/index.d.ts +2 -10
  27. package/dist/index.js +5 -4442
  28. package/dist/standard-schema.cjs +0 -2
  29. package/dist/standard-schema.js +0 -2
  30. package/dist/table.cjs +7 -3796
  31. package/dist/table.d.cts +163 -12
  32. package/dist/table.d.ts +163 -12
  33. package/dist/table.js +3 -3799
  34. package/dist/types.cjs +0 -2
  35. package/dist/types.js +0 -2
  36. package/dist/utils.cjs +10 -30
  37. package/dist/utils.js +1 -31
  38. package/package.json +6 -66
  39. package/dist/batch-builder-BiQDIZ7p.d.cts +0 -398
  40. package/dist/batch-builder-CNsLS6sR.d.ts +0 -398
  41. package/dist/builder-types-BTVhQSHI.d.cts +0 -169
  42. package/dist/builder-types-CzuLR4Th.d.ts +0 -169
  43. package/dist/builders/condition-check-builder.cjs +0 -422
  44. package/dist/builders/condition-check-builder.cjs.map +0 -1
  45. package/dist/builders/condition-check-builder.d.cts +0 -153
  46. package/dist/builders/condition-check-builder.d.ts +0 -153
  47. package/dist/builders/condition-check-builder.js +0 -420
  48. package/dist/builders/condition-check-builder.js.map +0 -1
  49. package/dist/builders/delete-builder.cjs +0 -484
  50. package/dist/builders/delete-builder.cjs.map +0 -1
  51. package/dist/builders/delete-builder.d.cts +0 -211
  52. package/dist/builders/delete-builder.d.ts +0 -211
  53. package/dist/builders/delete-builder.js +0 -482
  54. package/dist/builders/delete-builder.js.map +0 -1
  55. package/dist/builders/paginator.cjs +0 -193
  56. package/dist/builders/paginator.cjs.map +0 -1
  57. package/dist/builders/paginator.d.cts +0 -155
  58. package/dist/builders/paginator.d.ts +0 -155
  59. package/dist/builders/paginator.js +0 -191
  60. package/dist/builders/paginator.js.map +0 -1
  61. package/dist/builders/put-builder.cjs +0 -554
  62. package/dist/builders/put-builder.cjs.map +0 -1
  63. package/dist/builders/put-builder.d.cts +0 -319
  64. package/dist/builders/put-builder.d.ts +0 -319
  65. package/dist/builders/put-builder.js +0 -552
  66. package/dist/builders/put-builder.js.map +0 -1
  67. package/dist/builders/query-builder.cjs +0 -757
  68. package/dist/builders/query-builder.cjs.map +0 -1
  69. package/dist/builders/query-builder.d.cts +0 -6
  70. package/dist/builders/query-builder.d.ts +0 -6
  71. package/dist/builders/query-builder.js +0 -755
  72. package/dist/builders/query-builder.js.map +0 -1
  73. package/dist/builders/transaction-builder.cjs +0 -906
  74. package/dist/builders/transaction-builder.cjs.map +0 -1
  75. package/dist/builders/transaction-builder.d.cts +0 -464
  76. package/dist/builders/transaction-builder.d.ts +0 -464
  77. package/dist/builders/transaction-builder.js +0 -904
  78. package/dist/builders/transaction-builder.js.map +0 -1
  79. package/dist/builders/update-builder.cjs +0 -668
  80. package/dist/builders/update-builder.cjs.map +0 -1
  81. package/dist/builders/update-builder.d.cts +0 -374
  82. package/dist/builders/update-builder.d.ts +0 -374
  83. package/dist/builders/update-builder.js +0 -666
  84. package/dist/builders/update-builder.js.map +0 -1
  85. package/dist/conditions.cjs.map +0 -1
  86. package/dist/conditions.js.map +0 -1
  87. package/dist/entity.cjs.map +0 -1
  88. package/dist/entity.js.map +0 -1
  89. package/dist/index.cjs.map +0 -1
  90. package/dist/index.js.map +0 -1
  91. package/dist/query-builder-D3URwK9k.d.cts +0 -477
  92. package/dist/query-builder-cfEkU0_w.d.ts +0 -477
  93. package/dist/standard-schema.cjs.map +0 -1
  94. package/dist/standard-schema.js.map +0 -1
  95. package/dist/table-ClST8nkR.d.cts +0 -276
  96. package/dist/table-vE3cGoDy.d.ts +0 -276
  97. package/dist/table.cjs.map +0 -1
  98. package/dist/table.js.map +0 -1
  99. package/dist/types.cjs.map +0 -1
  100. package/dist/types.js.map +0 -1
  101. package/dist/utils.cjs.map +0 -1
  102. package/dist/utils.js.map +0 -1
@@ -0,0 +1,560 @@
1
+ 'use strict';
2
+
3
+ var chunkXYL43FDX_cjs = require('./chunk-XYL43FDX.cjs');
4
+ var chunk7UJJ7JXM_cjs = require('./chunk-7UJJ7JXM.cjs');
5
+
6
+ // src/utils/chunk-array.ts
7
+ function* chunkArray(array, size) {
8
+ if (size <= 0) {
9
+ throw new Error("Chunk size must be greater than 0");
10
+ }
11
+ for (let i = 0; i < array.length; i += size) {
12
+ yield array.slice(i, i + size);
13
+ }
14
+ }
15
+
16
+ // src/table.ts
17
+ var DDB_BATCH_WRITE_LIMIT = 25;
18
+ var DDB_BATCH_GET_LIMIT = 100;
19
+ var Table = class {
20
+ dynamoClient;
21
+ tableName;
22
+ /**
23
+ * The column name of the partitionKey for the Table
24
+ */
25
+ partitionKey;
26
+ /**
27
+ * The column name of the sortKey for the Table
28
+ */
29
+ sortKey;
30
+ /**
31
+ * The Global Secondary Indexes that are configured on this table
32
+ */
33
+ gsis;
34
+ constructor(config) {
35
+ this.dynamoClient = config.client;
36
+ this.tableName = config.tableName;
37
+ this.partitionKey = config.indexes.partitionKey;
38
+ this.sortKey = config.indexes.sortKey;
39
+ this.gsis = config.indexes.gsis || {};
40
+ }
41
+ createKeyForPrimaryIndex(keyCondition) {
42
+ const primaryCondition = { [this.partitionKey]: keyCondition.pk };
43
+ if (this.sortKey) {
44
+ if (!keyCondition.sk) {
45
+ throw new Error("Sort key has not been provided but the Table has a sort key");
46
+ }
47
+ primaryCondition[this.sortKey] = keyCondition.sk;
48
+ }
49
+ return primaryCondition;
50
+ }
51
+ /**
52
+ * Creates a new item in the table, it will fail if the item already exists.
53
+ *
54
+ * By default, this method returns the input values passed to the create operation
55
+ * upon successful creation.
56
+ *
57
+ * You can customise the return behaviour by chaining the `.returnValues()` method:
58
+ *
59
+ * @param item The item to create
60
+ * @returns A PutBuilder instance for chaining additional conditions and executing the create operation
61
+ *
62
+ * @example
63
+ * ```ts
64
+ * // Create with default behavior (returns input values)
65
+ * const result = await table.create({
66
+ * id: 'user-123',
67
+ * name: 'John Doe',
68
+ * email: 'john@example.com'
69
+ * }).execute();
70
+ * console.log(result); // Returns the input object
71
+ *
72
+ * // Create with no return value for better performance
73
+ * await table.create(userData).returnValues('NONE').execute();
74
+ *
75
+ * // Create and get fresh data from dynamodb using a strongly consistent read
76
+ * const freshData = await table.create(userData).returnValues('CONSISTENT').execute();
77
+ *
78
+ * // Create and get previous values (if the item was overwritten)
79
+ * const oldData = await table.create(userData).returnValues('ALL_OLD').execute();
80
+ * ```
81
+ */
82
+ create(item) {
83
+ return this.put(item).condition((op) => op.attributeNotExists(this.partitionKey)).returnValues("INPUT");
84
+ }
85
+ get(keyCondition) {
86
+ const executor = async (params) => {
87
+ try {
88
+ const result = await this.dynamoClient.get({
89
+ TableName: params.tableName,
90
+ Key: this.createKeyForPrimaryIndex(keyCondition),
91
+ ProjectionExpression: params.projectionExpression,
92
+ ExpressionAttributeNames: params.expressionAttributeNames,
93
+ ConsistentRead: params.consistentRead
94
+ });
95
+ return {
96
+ item: result.Item ? result.Item : void 0
97
+ };
98
+ } catch (error) {
99
+ console.error("Error getting item:", error);
100
+ throw error;
101
+ }
102
+ };
103
+ return new chunkXYL43FDX_cjs.GetBuilder(executor, keyCondition, this.tableName);
104
+ }
105
+ /**
106
+ * Updates an item in the table
107
+ *
108
+ * @param item The item to update
109
+ * @returns A PutBuilder instance for chaining conditions and executing the put operation
110
+ */
111
+ put(item) {
112
+ const executor = async (params) => {
113
+ try {
114
+ const result = await this.dynamoClient.put({
115
+ TableName: params.tableName,
116
+ Item: params.item,
117
+ ConditionExpression: params.conditionExpression,
118
+ ExpressionAttributeNames: params.expressionAttributeNames,
119
+ ExpressionAttributeValues: params.expressionAttributeValues,
120
+ // CONSISTENT and INPUT are not valid ReturnValues for DDB, so we set NONE as we are not interested in its
121
+ // response and will be handling these cases separately
122
+ ReturnValues: params.returnValues === "CONSISTENT" || params.returnValues === "INPUT" ? "NONE" : params.returnValues
123
+ });
124
+ if (params.returnValues === "INPUT") {
125
+ return params.item;
126
+ }
127
+ if (params.returnValues === "CONSISTENT") {
128
+ const getResult = await this.dynamoClient.get({
129
+ TableName: params.tableName,
130
+ Key: this.createKeyForPrimaryIndex({
131
+ pk: params.item[this.partitionKey],
132
+ ...this.sortKey && { sk: params.item[this.sortKey] }
133
+ }),
134
+ ConsistentRead: true
135
+ });
136
+ return getResult.Item;
137
+ }
138
+ return result.Attributes;
139
+ } catch (error) {
140
+ console.error("Error creating item:", error);
141
+ throw error;
142
+ }
143
+ };
144
+ return new chunkXYL43FDX_cjs.PutBuilder(executor, item, this.tableName);
145
+ }
146
+ /**
147
+ * Creates a query builder for complex queries
148
+ * If useIndex is called on the returned QueryBuilder, it will use the GSI configuration
149
+ */
150
+ query(keyCondition) {
151
+ const pkAttributeName = this.partitionKey;
152
+ const skAttributeName = this.sortKey;
153
+ let keyConditionExpression = chunk7UJJ7JXM_cjs.eq(pkAttributeName, keyCondition.pk);
154
+ if (keyCondition.sk) {
155
+ if (!skAttributeName) {
156
+ throw new Error("Sort key is not defined for Index");
157
+ }
158
+ const keyConditionOperator = {
159
+ eq: (value) => chunk7UJJ7JXM_cjs.eq(skAttributeName, value),
160
+ lt: (value) => chunk7UJJ7JXM_cjs.lt(skAttributeName, value),
161
+ lte: (value) => chunk7UJJ7JXM_cjs.lte(skAttributeName, value),
162
+ gt: (value) => chunk7UJJ7JXM_cjs.gt(skAttributeName, value),
163
+ gte: (value) => chunk7UJJ7JXM_cjs.gte(skAttributeName, value),
164
+ between: (lower, upper) => chunk7UJJ7JXM_cjs.between(skAttributeName, lower, upper),
165
+ beginsWith: (value) => chunk7UJJ7JXM_cjs.beginsWith(skAttributeName, value),
166
+ and: (...conditions) => chunk7UJJ7JXM_cjs.and(...conditions)
167
+ };
168
+ const skCondition = keyCondition.sk(keyConditionOperator);
169
+ keyConditionExpression = chunk7UJJ7JXM_cjs.and(chunk7UJJ7JXM_cjs.eq(pkAttributeName, keyCondition.pk), skCondition);
170
+ }
171
+ const executor = async (originalKeyCondition, options) => {
172
+ let finalKeyCondition = originalKeyCondition;
173
+ if (options.indexName) {
174
+ const gsiName = String(options.indexName);
175
+ const gsi = this.gsis[gsiName];
176
+ if (!gsi) {
177
+ throw new Error(`GSI with name "${gsiName}" does not exist on table "${this.tableName}"`);
178
+ }
179
+ const gsiPkAttributeName = gsi.partitionKey;
180
+ const gsiSkAttributeName = gsi.sortKey;
181
+ let pkValue;
182
+ let skValue;
183
+ let extractedSkCondition;
184
+ if (originalKeyCondition.type === "eq") {
185
+ pkValue = originalKeyCondition.value;
186
+ } else if (originalKeyCondition.type === "and" && originalKeyCondition.conditions) {
187
+ const pkCondition = originalKeyCondition.conditions.find(
188
+ (c) => c.type === "eq" && c.attr === pkAttributeName
189
+ );
190
+ if (pkCondition && pkCondition.type === "eq") {
191
+ pkValue = pkCondition.value;
192
+ }
193
+ const skConditions = originalKeyCondition.conditions.filter((c) => c.attr === skAttributeName);
194
+ if (skConditions.length > 0) {
195
+ if (skConditions.length === 1) {
196
+ extractedSkCondition = skConditions[0];
197
+ if (extractedSkCondition && extractedSkCondition.type === "eq") {
198
+ skValue = extractedSkCondition.value;
199
+ }
200
+ } else if (skConditions.length > 1) {
201
+ extractedSkCondition = chunk7UJJ7JXM_cjs.and(...skConditions);
202
+ }
203
+ }
204
+ }
205
+ if (!pkValue) {
206
+ throw new Error("Could not extract partition key value from key condition");
207
+ }
208
+ let gsiKeyCondition = chunk7UJJ7JXM_cjs.eq(gsiPkAttributeName, pkValue);
209
+ if (skValue && gsiSkAttributeName) {
210
+ gsiKeyCondition = chunk7UJJ7JXM_cjs.and(gsiKeyCondition, chunk7UJJ7JXM_cjs.eq(gsiSkAttributeName, skValue));
211
+ } else if (extractedSkCondition && gsiSkAttributeName) {
212
+ if (extractedSkCondition.attr === skAttributeName) {
213
+ const updatedSkCondition = {
214
+ ...extractedSkCondition,
215
+ attr: gsiSkAttributeName
216
+ };
217
+ gsiKeyCondition = chunk7UJJ7JXM_cjs.and(gsiKeyCondition, updatedSkCondition);
218
+ } else {
219
+ gsiKeyCondition = chunk7UJJ7JXM_cjs.and(gsiKeyCondition, extractedSkCondition);
220
+ }
221
+ }
222
+ finalKeyCondition = gsiKeyCondition;
223
+ }
224
+ const expressionParams = {
225
+ expressionAttributeNames: {},
226
+ expressionAttributeValues: {},
227
+ valueCounter: { count: 0 }
228
+ };
229
+ const keyConditionExpression2 = chunkXYL43FDX_cjs.buildExpression(finalKeyCondition, expressionParams);
230
+ let filterExpression;
231
+ if (options.filter) {
232
+ filterExpression = chunkXYL43FDX_cjs.buildExpression(options.filter, expressionParams);
233
+ }
234
+ const projectionExpression = options.projection?.map((p) => chunkXYL43FDX_cjs.generateAttributeName(expressionParams, p)).join(", ");
235
+ const { expressionAttributeNames, expressionAttributeValues } = expressionParams;
236
+ const { indexName, limit, consistentRead, scanIndexForward, lastEvaluatedKey } = options;
237
+ const params = {
238
+ TableName: this.tableName,
239
+ KeyConditionExpression: keyConditionExpression2,
240
+ FilterExpression: filterExpression,
241
+ ExpressionAttributeNames: expressionAttributeNames,
242
+ ExpressionAttributeValues: expressionAttributeValues,
243
+ IndexName: indexName,
244
+ Limit: limit,
245
+ ConsistentRead: consistentRead,
246
+ ScanIndexForward: scanIndexForward,
247
+ ProjectionExpression: projectionExpression,
248
+ ExclusiveStartKey: lastEvaluatedKey
249
+ };
250
+ try {
251
+ const result = await this.dynamoClient.query(params);
252
+ return {
253
+ items: result.Items,
254
+ lastEvaluatedKey: result.LastEvaluatedKey
255
+ };
256
+ } catch (error) {
257
+ console.log(chunkXYL43FDX_cjs.debugCommand(params));
258
+ console.error("Error querying items:", error);
259
+ throw error;
260
+ }
261
+ };
262
+ return new chunkXYL43FDX_cjs.QueryBuilder(executor, keyConditionExpression);
263
+ }
264
+ /**
265
+ * Creates a scan builder for scanning the entire table
266
+ * Use this when you need to:
267
+ * - Process all items in a table
268
+ * - Apply filters to a large dataset
269
+ * - Use a GSI for scanning
270
+ *
271
+ * @returns A ScanBuilder instance for chaining operations
272
+ */
273
+ scan() {
274
+ const executor = async (options) => {
275
+ const expressionParams = {
276
+ expressionAttributeNames: {},
277
+ expressionAttributeValues: {},
278
+ valueCounter: { count: 0 }
279
+ };
280
+ let filterExpression;
281
+ if (options.filter) {
282
+ filterExpression = chunkXYL43FDX_cjs.buildExpression(options.filter, expressionParams);
283
+ }
284
+ const projectionExpression = options.projection?.map((p) => chunkXYL43FDX_cjs.generateAttributeName(expressionParams, p)).join(", ");
285
+ const { expressionAttributeNames, expressionAttributeValues } = expressionParams;
286
+ const { indexName, limit, consistentRead, lastEvaluatedKey } = options;
287
+ const params = {
288
+ TableName: this.tableName,
289
+ FilterExpression: filterExpression,
290
+ ExpressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : void 0,
291
+ ExpressionAttributeValues: Object.keys(expressionAttributeValues).length > 0 ? expressionAttributeValues : void 0,
292
+ IndexName: indexName,
293
+ Limit: limit,
294
+ ConsistentRead: consistentRead,
295
+ ProjectionExpression: projectionExpression,
296
+ ExclusiveStartKey: lastEvaluatedKey
297
+ };
298
+ try {
299
+ const result = await this.dynamoClient.scan(params);
300
+ return {
301
+ items: result.Items,
302
+ lastEvaluatedKey: result.LastEvaluatedKey
303
+ };
304
+ } catch (error) {
305
+ console.log(chunkXYL43FDX_cjs.debugCommand(params));
306
+ console.error("Error scanning items:", error);
307
+ throw error;
308
+ }
309
+ };
310
+ return new chunkXYL43FDX_cjs.ScanBuilder(executor);
311
+ }
312
+ delete(keyCondition) {
313
+ const executor = async (params) => {
314
+ try {
315
+ const result = await this.dynamoClient.delete({
316
+ TableName: params.tableName,
317
+ Key: this.createKeyForPrimaryIndex(keyCondition),
318
+ ConditionExpression: params.conditionExpression,
319
+ ExpressionAttributeNames: params.expressionAttributeNames,
320
+ ExpressionAttributeValues: params.expressionAttributeValues,
321
+ ReturnValues: params.returnValues
322
+ });
323
+ return {
324
+ item: result.Attributes
325
+ };
326
+ } catch (error) {
327
+ console.error("Error deleting item:", error);
328
+ throw error;
329
+ }
330
+ };
331
+ return new chunkXYL43FDX_cjs.DeleteBuilder(executor, this.tableName, keyCondition);
332
+ }
333
+ /**
334
+ * Updates an item in the table
335
+ *
336
+ * @param keyCondition The primary key of the item to update
337
+ * @returns An UpdateBuilder instance for chaining update operations and conditions
338
+ */
339
+ update(keyCondition) {
340
+ const executor = async (params) => {
341
+ try {
342
+ const result = await this.dynamoClient.update({
343
+ TableName: params.tableName,
344
+ Key: this.createKeyForPrimaryIndex(keyCondition),
345
+ UpdateExpression: params.updateExpression,
346
+ ConditionExpression: params.conditionExpression,
347
+ ExpressionAttributeNames: params.expressionAttributeNames,
348
+ ExpressionAttributeValues: params.expressionAttributeValues,
349
+ ReturnValues: params.returnValues
350
+ });
351
+ return {
352
+ item: result.Attributes
353
+ };
354
+ } catch (error) {
355
+ console.error("Error updating item:", error);
356
+ throw error;
357
+ }
358
+ };
359
+ return new chunkXYL43FDX_cjs.UpdateBuilder(executor, this.tableName, keyCondition);
360
+ }
361
+ /**
362
+ * Creates a transaction builder for performing multiple operations atomically
363
+ */
364
+ transactionBuilder() {
365
+ const executor = async (params) => {
366
+ await this.dynamoClient.transactWrite(params);
367
+ };
368
+ return new chunkXYL43FDX_cjs.TransactionBuilder(executor, {
369
+ partitionKey: this.partitionKey,
370
+ sortKey: this.sortKey
371
+ });
372
+ }
373
+ /**
374
+ * Creates a batch builder for performing multiple operations efficiently with optional type inference
375
+ *
376
+ * @example Basic Usage
377
+ * ```typescript
378
+ * const batch = table.batchBuilder();
379
+ *
380
+ * // Add operations
381
+ * userRepo.create(newUser).withBatch(batch);
382
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch);
383
+ *
384
+ * // Execute operations
385
+ * const result = await batch.execute();
386
+ * ```
387
+ *
388
+ * @example Typed Usage
389
+ * ```typescript
390
+ * // Define entity types for the batch
391
+ * const batch = table.batchBuilder<{
392
+ * User: UserEntity;
393
+ * Order: OrderEntity;
394
+ * Product: ProductEntity;
395
+ * }>();
396
+ *
397
+ * // Add operations with type information
398
+ * userRepo.create(newUser).withBatch(batch, 'User');
399
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch, 'Order');
400
+ * productRepo.delete({ id: 'old-product' }).withBatch(batch, 'Product');
401
+ *
402
+ * // Execute and get typed results
403
+ * const result = await batch.execute();
404
+ * const users: UserEntity[] = result.reads.itemsByType.User;
405
+ * const orders: OrderEntity[] = result.reads.itemsByType.Order;
406
+ * ```
407
+ */
408
+ batchBuilder() {
409
+ const batchWriteExecutor = async (operations) => {
410
+ return this.batchWrite(operations);
411
+ };
412
+ const batchGetExecutor = async (keys) => {
413
+ return this.batchGet(keys);
414
+ };
415
+ return new chunkXYL43FDX_cjs.BatchBuilder(batchWriteExecutor, batchGetExecutor, {
416
+ partitionKey: this.partitionKey,
417
+ sortKey: this.sortKey
418
+ });
419
+ }
420
+ /**
421
+ * Executes a transaction using a callback function
422
+ *
423
+ * @param callback A function that receives a transaction context and performs operations on it
424
+ * @param options Optional transaction options
425
+ * @returns A promise that resolves when the transaction is complete
426
+ */
427
+ async transaction(callback, options) {
428
+ const transactionExecutor = async (params) => {
429
+ await this.dynamoClient.transactWrite(params);
430
+ };
431
+ const transaction = new chunkXYL43FDX_cjs.TransactionBuilder(transactionExecutor, {
432
+ partitionKey: this.partitionKey,
433
+ sortKey: this.sortKey
434
+ });
435
+ if (options) {
436
+ transaction.withOptions(options);
437
+ }
438
+ const result = await callback(transaction);
439
+ await transaction.execute();
440
+ return result;
441
+ }
442
+ /**
443
+ * Creates a condition check operation for use in transactions
444
+ *
445
+ * This is useful for when you require a transaction to succeed only when a specific condition is met on a
446
+ * a record within the database that you are not directly updating.
447
+ *
448
+ * For example, you are updating a record and you want to ensure that another record exists and/or has a specific value before proceeding.
449
+ */
450
+ conditionCheck(keyCondition) {
451
+ return new chunkXYL43FDX_cjs.ConditionCheckBuilder(this.tableName, keyCondition);
452
+ }
453
+ /**
454
+ * Performs a batch get operation to retrieve multiple items at once
455
+ *
456
+ * @param keys Array of primary keys to retrieve
457
+ * @returns A promise that resolves to the retrieved items
458
+ */
459
+ async batchGet(keys) {
460
+ const allItems = [];
461
+ const allUnprocessedKeys = [];
462
+ for (const chunk of chunkArray(keys, DDB_BATCH_GET_LIMIT)) {
463
+ const formattedKeys = chunk.map((key) => ({
464
+ [this.partitionKey]: key.pk,
465
+ ...this.sortKey ? { [this.sortKey]: key.sk } : {}
466
+ }));
467
+ const params = {
468
+ RequestItems: {
469
+ [this.tableName]: {
470
+ Keys: formattedKeys
471
+ }
472
+ }
473
+ };
474
+ try {
475
+ const result = await this.dynamoClient.batchGet(params);
476
+ if (result.Responses?.[this.tableName]) {
477
+ allItems.push(...result.Responses[this.tableName]);
478
+ }
479
+ const unprocessedKeysArray = result.UnprocessedKeys?.[this.tableName]?.Keys || [];
480
+ const unprocessedKeys = unprocessedKeysArray.map((key) => ({
481
+ pk: key[this.partitionKey],
482
+ sk: this.sortKey ? key[this.sortKey] : void 0
483
+ }));
484
+ if (unprocessedKeys.length > 0) {
485
+ allUnprocessedKeys.push(...unprocessedKeys);
486
+ }
487
+ } catch (error) {
488
+ console.error("Error in batch get operation:", error);
489
+ throw error;
490
+ }
491
+ }
492
+ return {
493
+ items: allItems,
494
+ unprocessedKeys: allUnprocessedKeys
495
+ };
496
+ }
497
+ /**
498
+ * Performs a batch write operation to put or delete multiple items at once
499
+ *
500
+ * @param operations Array of put or delete operations
501
+ * @returns A promise that resolves to any unprocessed operations
502
+ */
503
+ async batchWrite(operations) {
504
+ const allUnprocessedItems = [];
505
+ for (const chunk of chunkArray(operations, DDB_BATCH_WRITE_LIMIT)) {
506
+ const writeRequests = chunk.map((operation) => {
507
+ if (operation.type === "put") {
508
+ return {
509
+ PutRequest: {
510
+ Item: operation.item
511
+ }
512
+ };
513
+ }
514
+ return {
515
+ DeleteRequest: {
516
+ Key: this.createKeyForPrimaryIndex(operation.key)
517
+ }
518
+ };
519
+ });
520
+ const params = {
521
+ RequestItems: {
522
+ [this.tableName]: writeRequests
523
+ }
524
+ };
525
+ try {
526
+ const result = await this.dynamoClient.batchWrite(params);
527
+ const unprocessedRequestsArray = result.UnprocessedItems?.[this.tableName] || [];
528
+ if (unprocessedRequestsArray.length > 0) {
529
+ const unprocessedItems = unprocessedRequestsArray.map((request) => {
530
+ if (request?.PutRequest?.Item) {
531
+ return {
532
+ type: "put",
533
+ item: request.PutRequest.Item
534
+ };
535
+ }
536
+ if (request?.DeleteRequest?.Key) {
537
+ return {
538
+ type: "delete",
539
+ key: {
540
+ pk: request.DeleteRequest.Key[this.partitionKey],
541
+ sk: this.sortKey ? request.DeleteRequest.Key[this.sortKey] : void 0
542
+ }
543
+ };
544
+ }
545
+ throw new Error("Invalid unprocessed item format returned from DynamoDB");
546
+ });
547
+ allUnprocessedItems.push(...unprocessedItems);
548
+ }
549
+ } catch (error) {
550
+ console.error("Error in batch write operation:", error);
551
+ throw error;
552
+ }
553
+ }
554
+ return {
555
+ unprocessedItems: allUnprocessedItems
556
+ };
557
+ }
558
+ };
559
+
560
+ exports.Table = Table;