dyno-table 1.6.0 → 1.8.0-next.1

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 (74) hide show
  1. package/README.md +53 -140
  2. package/dist/batch-builder-BOBwOIUE.d.ts +398 -0
  3. package/dist/batch-builder-CKYnMRyz.d.cts +398 -0
  4. package/dist/{builder-types-DlaUSc-b.d.cts → builder-types-BTVhQSHI.d.cts} +55 -5
  5. package/dist/{builder-types-B_tCpn9F.d.ts → builder-types-CzuLR4Th.d.ts} +55 -5
  6. package/dist/builders/condition-check-builder.cjs +0 -13
  7. package/dist/builders/condition-check-builder.cjs.map +1 -1
  8. package/dist/builders/condition-check-builder.d.cts +1 -14
  9. package/dist/builders/condition-check-builder.d.ts +1 -14
  10. package/dist/builders/condition-check-builder.js +0 -13
  11. package/dist/builders/condition-check-builder.js.map +1 -1
  12. package/dist/builders/delete-builder.cjs +38 -0
  13. package/dist/builders/delete-builder.cjs.map +1 -1
  14. package/dist/builders/delete-builder.d.cts +37 -1
  15. package/dist/builders/delete-builder.d.ts +37 -1
  16. package/dist/builders/delete-builder.js +38 -0
  17. package/dist/builders/delete-builder.js.map +1 -1
  18. package/dist/builders/paginator.cjs +21 -27
  19. package/dist/builders/paginator.cjs.map +1 -1
  20. package/dist/builders/paginator.d.cts +3 -27
  21. package/dist/builders/paginator.d.ts +3 -27
  22. package/dist/builders/paginator.js +21 -27
  23. package/dist/builders/paginator.js.map +1 -1
  24. package/dist/builders/put-builder.cjs +39 -8
  25. package/dist/builders/put-builder.cjs.map +1 -1
  26. package/dist/builders/put-builder.d.cts +38 -9
  27. package/dist/builders/put-builder.d.ts +38 -9
  28. package/dist/builders/put-builder.js +39 -8
  29. package/dist/builders/put-builder.js.map +1 -1
  30. package/dist/builders/query-builder.cjs +115 -75
  31. package/dist/builders/query-builder.cjs.map +1 -1
  32. package/dist/builders/query-builder.d.cts +2 -2
  33. package/dist/builders/query-builder.d.ts +2 -2
  34. package/dist/builders/query-builder.js +115 -75
  35. package/dist/builders/query-builder.js.map +1 -1
  36. package/dist/builders/transaction-builder.cjs +0 -47
  37. package/dist/builders/transaction-builder.cjs.map +1 -1
  38. package/dist/builders/transaction-builder.d.cts +1 -48
  39. package/dist/builders/transaction-builder.d.ts +1 -48
  40. package/dist/builders/transaction-builder.js +0 -47
  41. package/dist/builders/transaction-builder.js.map +1 -1
  42. package/dist/builders/update-builder.cjs +2 -2
  43. package/dist/builders/update-builder.cjs.map +1 -1
  44. package/dist/builders/update-builder.d.cts +3 -3
  45. package/dist/builders/update-builder.d.ts +3 -3
  46. package/dist/builders/update-builder.js +2 -2
  47. package/dist/builders/update-builder.js.map +1 -1
  48. package/dist/conditions.cjs.map +1 -1
  49. package/dist/conditions.js.map +1 -1
  50. package/dist/entity.cjs +69 -37
  51. package/dist/entity.cjs.map +1 -1
  52. package/dist/entity.d.cts +30 -10
  53. package/dist/entity.d.ts +30 -10
  54. package/dist/entity.js +69 -37
  55. package/dist/entity.js.map +1 -1
  56. package/dist/index.cjs +661 -218
  57. package/dist/index.cjs.map +1 -1
  58. package/dist/index.d.cts +4 -3
  59. package/dist/index.d.ts +4 -3
  60. package/dist/index.js +660 -219
  61. package/dist/index.js.map +1 -1
  62. package/dist/{query-builder-BhrR31oO.d.ts → query-builder-CaHzZmDf.d.ts} +31 -63
  63. package/dist/{query-builder-CbHvimBk.d.cts → query-builder-DFkxojBM.d.cts} +31 -63
  64. package/dist/{table-CY9byPEg.d.cts → table-CHitMHXE.d.cts} +55 -169
  65. package/dist/{table-Des8C2od.d.ts → table-m7DQk5dK.d.ts} +55 -169
  66. package/dist/table.cjs +590 -181
  67. package/dist/table.cjs.map +1 -1
  68. package/dist/table.d.cts +4 -3
  69. package/dist/table.d.ts +4 -3
  70. package/dist/table.js +590 -181
  71. package/dist/table.js.map +1 -1
  72. package/dist/utils.cjs.map +1 -1
  73. package/dist/utils.js.map +1 -1
  74. package/package.json +1 -1
package/dist/index.js CHANGED
@@ -208,10 +208,6 @@ var Paginator = class {
208
208
  }
209
209
  /**
210
210
  * Gets the current page number (1-indexed).
211
- * Use this method when you need to:
212
- * - Track progress through dinosaur lists
213
- * - Display habitat inspection status
214
- * - Monitor security sweep progress
215
211
  *
216
212
  * @example
217
213
  * ```ts
@@ -229,11 +225,6 @@ var Paginator = class {
229
225
  }
230
226
  /**
231
227
  * Checks if there are more pages of dinosaurs or habitats to process.
232
- * Use this method when you need to:
233
- * - Check for more dinosaurs to review
234
- * - Continue habitat inspections
235
- * - Process security incidents
236
- * - Complete feeding schedules
237
228
  *
238
229
  * This method takes into account both:
239
230
  * - DynamoDB's lastEvaluatedKey mechanism
@@ -265,11 +256,6 @@ var Paginator = class {
265
256
  }
266
257
  /**
267
258
  * Retrieves the next page of dinosaurs or habitats from DynamoDB.
268
- * Use this method when you need to:
269
- * - Process dinosaur groups systematically
270
- * - Review habitat inspections in batches
271
- * - Monitor security incidents in sequence
272
- * - Schedule feeding rotations
273
259
  *
274
260
  * This method handles:
275
261
  * - Automatic continuation between groups
@@ -321,13 +307,31 @@ var Paginator = class {
321
307
  page: this.currentPage
322
308
  };
323
309
  }
324
- effectivePageSize = Math.min(effectivePageSize, remainingItems);
310
+ if (effectivePageSize !== void 0) {
311
+ effectivePageSize = Math.min(effectivePageSize, remainingItems);
312
+ } else {
313
+ effectivePageSize = remainingItems;
314
+ }
315
+ }
316
+ const query = this.queryBuilder.clone();
317
+ if (effectivePageSize !== void 0) {
318
+ query.limit(effectivePageSize);
325
319
  }
326
- const query = this.queryBuilder.clone().limit(effectivePageSize);
327
320
  if (this.lastEvaluatedKey) {
328
321
  query.startFrom(this.lastEvaluatedKey);
329
322
  }
330
- const result = await query.execute();
323
+ const generator = await query.execute();
324
+ const items = [];
325
+ let itemCount = 0;
326
+ for await (const item of generator) {
327
+ if (effectivePageSize !== void 0 && itemCount >= effectivePageSize) {
328
+ break;
329
+ }
330
+ items.push(item);
331
+ itemCount++;
332
+ }
333
+ const lastEvaluatedKey = generator.getLastEvaluatedKey();
334
+ const result = { items, lastEvaluatedKey };
331
335
  this.currentPage += 1;
332
336
  this.lastEvaluatedKey = result.lastEvaluatedKey;
333
337
  this.totalItemsRetrieved += result.items.length;
@@ -341,16 +345,6 @@ var Paginator = class {
341
345
  }
342
346
  /**
343
347
  * Gets all remaining dinosaurs or habitats and combines them into a single array.
344
- * Use this method when you need to:
345
- * - Generate complete park inventory
346
- * - Perform full security audit
347
- * - Create comprehensive feeding schedule
348
- * - Run park-wide health checks
349
- *
350
- * Note: Use with caution! This method:
351
- * - Could overwhelm systems with large dinosaur populations
352
- * - Makes multiple database requests
353
- * - May cause system strain during peak hours
354
348
  *
355
349
  * @example
356
350
  * ```ts
@@ -392,10 +386,6 @@ var FilterBuilder = class {
392
386
  selectedFields = /* @__PURE__ */ new Set();
393
387
  /**
394
388
  * Sets the maximum number of items to return.
395
- * Use this method when you need to:
396
- * - Limit the number of dinosaurs returned
397
- * - Control the size of habitat reports
398
- * - Implement manual pagination of security logs
399
389
  *
400
390
  * Note: This limit applies to the items that match the key condition
401
391
  * before any filter expressions are applied.
@@ -426,11 +416,6 @@ var FilterBuilder = class {
426
416
  }
427
417
  /**
428
418
  * Specifies a Global Secondary Index (GSI) to use for the operation.
429
- * Use this method when you need to:
430
- * - Find dinosaurs by species or status
431
- * - Search habitats by security level
432
- * - Find incidents by date
433
- * - List feeding schedules by time
434
419
  *
435
420
  * @example
436
421
  * ```typescript
@@ -459,11 +444,6 @@ var FilterBuilder = class {
459
444
  }
460
445
  /**
461
446
  * Sets whether to use strongly consistent reads for the operation.
462
- * Use this method when you need to:
463
- * - Get real-time dinosaur status updates
464
- * - Monitor critical security systems
465
- * - Track immediate habitat changes
466
- * - Verify containment protocols
467
447
  *
468
448
  * Note:
469
449
  * - Consistent reads are not available on GSIs
@@ -494,11 +474,6 @@ var FilterBuilder = class {
494
474
  }
495
475
  /**
496
476
  * Adds a filter expression to refine the operation results.
497
- * Use this method when you need to:
498
- * - Filter dinosaurs by behavior patterns
499
- * - Find habitats with specific conditions
500
- * - Search for security incidents
501
- * - Monitor feeding patterns
502
477
  *
503
478
  * @example
504
479
  * ```typescript
@@ -551,11 +526,6 @@ var FilterBuilder = class {
551
526
  }
552
527
  /**
553
528
  * Specifies which attributes to return in the results.
554
- * Use this method when you need to:
555
- * - Get specific dinosaur attributes
556
- * - Retrieve habitat statistics
557
- * - Monitor security metrics
558
- * - Optimize response size
559
529
  *
560
530
  * @example
561
531
  * ```typescript
@@ -600,11 +570,16 @@ var FilterBuilder = class {
600
570
  *
601
571
  * @example
602
572
  * ```typescript
603
- * // Create a paginator for dinosaur records
573
+ * // Create a paginator for dinosaur records with specific page size
604
574
  * const paginator = builder
605
575
  * .filter(op => op.eq('status', 'ACTIVE'))
606
576
  * .paginate(10);
607
577
  *
578
+ * // Create a paginator with automatic DynamoDB paging (no page size limit)
579
+ * const autoPaginator = builder
580
+ * .filter(op => op.eq('status', 'ACTIVE'))
581
+ * .paginate();
582
+ *
608
583
  * // Process pages of dinosaur results
609
584
  * while (paginator.hasNextPage()) {
610
585
  * const page = await paginator.getNextPage();
@@ -613,7 +588,7 @@ var FilterBuilder = class {
613
588
  * }
614
589
  * ```
615
590
  *
616
- * @param pageSize - The number of items to return per page
591
+ * @param pageSize - The number of items to return per page. If not provided, DynamoDB will automatically determine page sizes.
617
592
  * @returns A Paginator instance that manages the pagination state
618
593
  * @see Paginator for more pagination control options
619
594
  */
@@ -622,11 +597,6 @@ var FilterBuilder = class {
622
597
  }
623
598
  /**
624
599
  * Sets the starting point using a previous lastEvaluatedKey.
625
- * Use this method when you need to:
626
- * - Implement manual dinosaur list pagination
627
- * - Resume habitat inspection reviews
628
- * - Continue security incident analysis
629
- * - Store operation position between sessions
630
600
  *
631
601
  * Note: This method is typically used for manual pagination.
632
602
  * For automatic pagination, use the paginate() method instead.
@@ -639,15 +609,17 @@ var FilterBuilder = class {
639
609
  * .limit(5)
640
610
  * .execute();
641
611
  *
642
- * if (result1.lastEvaluatedKey) {
612
+ * const lastKey = result1.getLastEvaluatedKey();
613
+ * if (lastKey) {
643
614
  * // Continue listing dinosaurs
644
615
  * const result2 = await builder
645
616
  * .filter(op => op.eq('status', 'ACTIVE'))
646
- * .startFrom(result1.lastEvaluatedKey)
617
+ * .startFrom(lastKey)
647
618
  * .limit(5)
648
619
  * .execute();
649
620
  *
650
- * console.log('Additional dinosaurs:', result2.items);
621
+ * const items = await result2.toArray();
622
+ * console.log('Additional dinosaurs:', items);
651
623
  * }
652
624
  * ```
653
625
  *
@@ -660,6 +632,72 @@ var FilterBuilder = class {
660
632
  }
661
633
  };
662
634
 
635
+ // src/builders/result-iterator.ts
636
+ var ResultIterator = class {
637
+ constructor(queryBuilder, directExecutor) {
638
+ this.queryBuilder = queryBuilder;
639
+ this.directExecutor = directExecutor;
640
+ this.overallLimit = queryBuilder.getLimit();
641
+ }
642
+ lastEvaluatedKey;
643
+ itemsYielded = 0;
644
+ overallLimit;
645
+ /**
646
+ * Async iterator with automatic pagination
647
+ */
648
+ async *[Symbol.asyncIterator]() {
649
+ let hasMorePages = true;
650
+ while (hasMorePages) {
651
+ const result = await this.directExecutor();
652
+ for (const item of result.items) {
653
+ if (this.overallLimit !== void 0 && this.itemsYielded >= this.overallLimit) {
654
+ return;
655
+ }
656
+ yield item;
657
+ this.itemsYielded++;
658
+ }
659
+ if (result.lastEvaluatedKey !== null && result.lastEvaluatedKey !== void 0) {
660
+ this.lastEvaluatedKey = result.lastEvaluatedKey;
661
+ this.queryBuilder.startFrom(result.lastEvaluatedKey);
662
+ } else if (result.lastEvaluatedKey === null) {
663
+ if (this.lastEvaluatedKey === void 0) {
664
+ this.lastEvaluatedKey = null;
665
+ }
666
+ }
667
+ hasMorePages = !!result.lastEvaluatedKey && (this.overallLimit === void 0 || this.itemsYielded < this.overallLimit);
668
+ }
669
+ }
670
+ /**
671
+ * Convert to array (loads all pages).
672
+ *
673
+ * ```ts
674
+ * const result = await table.query({ pk: "foo" }).execute();
675
+ * const allItemsFromDynamo = await result.toArray();
676
+ * ```
677
+ *
678
+ * Note: This will load all pages into memory. For large datasets, consider using async iteration instead.
679
+ *```ts
680
+ * const result = await table.query({ pk: "foo" }).execute();
681
+ * for await (const item of result) {
682
+ * // Process each item
683
+ * }
684
+ * ```
685
+ */
686
+ async toArray() {
687
+ const items = [];
688
+ for await (const item of this) {
689
+ items.push(item);
690
+ }
691
+ return items;
692
+ }
693
+ /**
694
+ * Get the last evaluated key
695
+ */
696
+ getLastEvaluatedKey() {
697
+ return this.lastEvaluatedKey === null ? void 0 : this.lastEvaluatedKey;
698
+ }
699
+ };
700
+
663
701
  // src/builders/query-builder.ts
664
702
  var QueryBuilder = class _QueryBuilder extends FilterBuilder {
665
703
  keyCondition;
@@ -781,16 +819,16 @@ var QueryBuilder = class _QueryBuilder extends FilterBuilder {
781
819
  return clone;
782
820
  }
783
821
  /**
784
- * Executes the query against DynamoDB.
822
+ * Executes the query against DynamoDB and returns a generator that behaves like an array.
785
823
  *
786
- * The method returns both the matched items and, if there are more results,
787
- * a lastEvaluatedKey that can be used with startFrom() to continue the query.
824
+ * The generator automatically handles pagination and provides array-like methods
825
+ * for processing results efficiently without loading everything into memory at once.
788
826
  *
789
827
  * @example
790
828
  * ```typescript
791
829
  * try {
792
- * // Find active carnivores in specific habitat
793
- * const result = await new QueryBuilder(executor, eq('habitatId', 'PADDOCK-A'))
830
+ * // Find active carnivores with automatic pagination
831
+ * const results = await new QueryBuilder(executor, eq('habitatId', 'PADDOCK-A'))
794
832
  * .useIndex('species-status-index')
795
833
  * .filter(op =>
796
834
  * op.and([
@@ -800,25 +838,27 @@ var QueryBuilder = class _QueryBuilder extends FilterBuilder {
800
838
  * ])
801
839
  * )
802
840
  * .sortDescending()
803
- * .limit(5)
804
841
  * .execute();
805
842
  *
806
- * console.log(`Found ${result.items.length} dangerous dinosaurs`);
807
- *
808
- * if (result.lastEvaluatedKey) {
809
- * console.log('Additional threats detected');
843
+ * // Use like an array with automatic pagination
844
+ * for await (const dinosaur of results) {
845
+ * console.log(`Processing ${dinosaur.name}`);
810
846
  * }
847
+ *
848
+ * // Or convert to array and use array methods
849
+ * const allItems = await results.toArray();
850
+ * const dangerousOnes = allItems.filter(dino => dino.aggressionLevel > 9);
851
+ * const totalCount = allItems.length;
811
852
  * } catch (error) {
812
853
  * console.error('Security scan failed:', error);
813
854
  * }
814
855
  * ```
815
856
  *
816
- * @returns A promise that resolves to an object containing:
817
- * - items: Array of items matching the query
818
- * - lastEvaluatedKey: Token for continuing the query, if more items exist
857
+ * @returns A promise that resolves to a ResultGenerator that behaves like an array
819
858
  */
820
859
  async execute() {
821
- return this.executor(this.keyCondition, this.options);
860
+ const directExecutor = () => this.executor(this.keyCondition, this.options);
861
+ return new ResultIterator(this, directExecutor);
822
862
  }
823
863
  };
824
864
 
@@ -893,10 +933,6 @@ var PutBuilder = class {
893
933
  }
894
934
  /**
895
935
  * Adds a condition that must be satisfied for the put operation to succeed.
896
- * Use this method when you need to:
897
- * - Prevent overwriting existing items (optimistic locking)
898
- * - Ensure items meet certain criteria before replacement
899
- * - Implement complex business rules for item updates
900
936
  *
901
937
  * @example
902
938
  * ```ts
@@ -1029,10 +1065,6 @@ var PutBuilder = class {
1029
1065
  }
1030
1066
  /**
1031
1067
  * Adds this put operation to a transaction.
1032
- * Use this method when you need to:
1033
- * - Transfer dinosaurs between habitats
1034
- * - Initialize new breeding programs
1035
- * - Update multiple facility records
1036
1068
  *
1037
1069
  * @example
1038
1070
  * ```ts
@@ -1065,6 +1097,45 @@ var PutBuilder = class {
1065
1097
  transaction.putWithCommand(command);
1066
1098
  return this;
1067
1099
  }
1100
+ /**
1101
+ * Adds this put operation to a batch with optional entity type information.
1102
+ *
1103
+ * @example Basic Usage
1104
+ * ```ts
1105
+ * const batch = table.batchBuilder();
1106
+ *
1107
+ * // Add multiple dinosaurs to batch
1108
+ * dinosaurRepo.create(newDino1).withBatch(batch);
1109
+ * dinosaurRepo.create(newDino2).withBatch(batch);
1110
+ * dinosaurRepo.create(newDino3).withBatch(batch);
1111
+ *
1112
+ * // Execute all operations efficiently
1113
+ * await batch.execute();
1114
+ * ```
1115
+ *
1116
+ * @example Typed Usage
1117
+ * ```ts
1118
+ * const batch = table.batchBuilder<{
1119
+ * User: UserEntity;
1120
+ * Order: OrderEntity;
1121
+ * }>();
1122
+ *
1123
+ * // Add operations with type information
1124
+ * userRepo.create(newUser).withBatch(batch, 'User');
1125
+ * orderRepo.create(newOrder).withBatch(batch, 'Order');
1126
+ *
1127
+ * // Execute and get typed results
1128
+ * const result = await batch.execute();
1129
+ * const users: UserEntity[] = result.reads.itemsByType.User;
1130
+ * ```
1131
+ *
1132
+ * @param batch - The batch builder to add this operation to
1133
+ * @param entityType - Optional entity type key for type tracking
1134
+ */
1135
+ withBatch(batch, entityType) {
1136
+ const command = this.toDynamoCommand();
1137
+ batch.putWithCommand(command, entityType);
1138
+ }
1068
1139
  /**
1069
1140
  * Executes the put operation against DynamoDB.
1070
1141
  *
@@ -1259,6 +1330,44 @@ var DeleteBuilder = class {
1259
1330
  const command = this.toDynamoCommand();
1260
1331
  transaction.deleteWithCommand(command);
1261
1332
  }
1333
+ /**
1334
+ * Adds this delete operation to a batch with optional entity type information.
1335
+ *
1336
+ * @example Basic Usage
1337
+ * ```ts
1338
+ * const batch = table.batchBuilder();
1339
+ *
1340
+ * // Remove multiple dinosaurs in batch
1341
+ * dinosaurRepo.delete({ id: 'old-dino-1' }).withBatch(batch);
1342
+ * dinosaurRepo.delete({ id: 'old-dino-2' }).withBatch(batch);
1343
+ * dinosaurRepo.delete({ id: 'old-dino-3' }).withBatch(batch);
1344
+ *
1345
+ * // Execute all deletions efficiently
1346
+ * await batch.execute();
1347
+ * ```
1348
+ *
1349
+ * @example Typed Usage
1350
+ * ```ts
1351
+ * const batch = table.batchBuilder<{
1352
+ * User: UserEntity;
1353
+ * Order: OrderEntity;
1354
+ * }>();
1355
+ *
1356
+ * // Add operations with type information
1357
+ * userRepo.delete({ id: 'user-1' }).withBatch(batch, 'User');
1358
+ * orderRepo.delete({ id: 'order-1' }).withBatch(batch, 'Order');
1359
+ *
1360
+ * // Execute batch operations
1361
+ * await batch.execute();
1362
+ * ```
1363
+ *
1364
+ * @param batch - The batch builder to add this operation to
1365
+ * @param entityType - Optional entity type key for type tracking
1366
+ */
1367
+ withBatch(batch, entityType) {
1368
+ const command = this.toDynamoCommand();
1369
+ batch.deleteWithCommand(command, entityType);
1370
+ }
1262
1371
  /**
1263
1372
  * Executes the delete operation against DynamoDB.
1264
1373
  *
@@ -1501,11 +1610,11 @@ var UpdateBuilder = class {
1501
1610
  * Sets which item attributes to include in the response.
1502
1611
  *
1503
1612
  * Available options:
1504
- * - ALL_NEW: All attributes after the update
1613
+ * - ALL_NEW: All attributes after the update (default)
1505
1614
  * - UPDATED_NEW: Only updated attributes, new values
1506
1615
  * - ALL_OLD: All attributes before the update
1507
1616
  * - UPDATED_OLD: Only updated attributes, old values
1508
- * - NONE: No attributes returned (default)
1617
+ * - NONE: No attributes returned
1509
1618
  *
1510
1619
  * @example
1511
1620
  * ```typescript
@@ -1824,10 +1933,6 @@ var TransactionBuilder = class {
1824
1933
  }
1825
1934
  /**
1826
1935
  * Adds a put operation to the transaction.
1827
- * Use this method when you need to:
1828
- * - Insert new items as part of a transaction
1829
- * - Replace existing items atomically
1830
- * - Ensure items meet certain conditions before insertion
1831
1936
  *
1832
1937
  * The method automatically checks for duplicate items within the transaction
1833
1938
  * to prevent multiple operations on the same item.
@@ -1885,10 +1990,6 @@ var TransactionBuilder = class {
1885
1990
  }
1886
1991
  /**
1887
1992
  * Adds a pre-configured put operation to the transaction.
1888
- * Use this method when you need to:
1889
- * - Reuse put commands from PutBuilder
1890
- * - Add complex put operations with pre-configured parameters
1891
- * - Integrate with existing put command configurations
1892
1993
  *
1893
1994
  * This method is particularly useful when working with PutBuilder
1894
1995
  * to maintain consistency in put operations across your application.
@@ -1920,10 +2021,6 @@ var TransactionBuilder = class {
1920
2021
  }
1921
2022
  /**
1922
2023
  * Adds a delete operation to the transaction.
1923
- * Use this method when you need to:
1924
- * - Remove items as part of a transaction
1925
- * - Conditionally delete items
1926
- * - Ensure items exist before deletion
1927
2024
  *
1928
2025
  * The method automatically checks for duplicate items within the transaction
1929
2026
  * to prevent multiple operations on the same item.
@@ -1981,10 +2078,6 @@ var TransactionBuilder = class {
1981
2078
  }
1982
2079
  /**
1983
2080
  * Adds a pre-configured delete operation to the transaction.
1984
- * Use this method when you need to:
1985
- * - Reuse delete commands from DeleteBuilder
1986
- * - Add complex delete operations with pre-configured parameters
1987
- * - Integrate with existing delete command configurations
1988
2081
  *
1989
2082
  * This method is particularly useful when working with DeleteBuilder
1990
2083
  * to maintain consistency in delete operations across your application.
@@ -2031,11 +2124,6 @@ var TransactionBuilder = class {
2031
2124
  }
2032
2125
  /**
2033
2126
  * Adds an update operation to the transaction.
2034
- * Use this method when you need to:
2035
- * - Modify existing items as part of a transaction
2036
- * - Update multiple attributes atomically
2037
- * - Apply conditional updates
2038
- * - Perform complex attribute manipulations
2039
2127
  *
2040
2128
  * The method supports all DynamoDB update expressions:
2041
2129
  * - SET: Modify or add attributes
@@ -2113,10 +2201,6 @@ var TransactionBuilder = class {
2113
2201
  }
2114
2202
  /**
2115
2203
  * Adds a pre-configured update operation to the transaction.
2116
- * Use this method when you need to:
2117
- * - Reuse update commands from UpdateBuilder
2118
- * - Add complex update operations with pre-configured parameters
2119
- * - Integrate with existing update command configurations
2120
2204
  *
2121
2205
  * This method is particularly useful when working with UpdateBuilder
2122
2206
  * to maintain consistency in update operations across your application.
@@ -2166,11 +2250,6 @@ var TransactionBuilder = class {
2166
2250
  }
2167
2251
  /**
2168
2252
  * Adds a condition check operation to the transaction.
2169
- * Use this method when you need to:
2170
- * - Validate item state without modifying it
2171
- * - Ensure data consistency across tables
2172
- * - Implement complex business rules
2173
- * - Verify preconditions for other operations
2174
2253
  *
2175
2254
  * Condition checks are particularly useful for:
2176
2255
  * - Implementing optimistic locking
@@ -2237,10 +2316,6 @@ var TransactionBuilder = class {
2237
2316
  }
2238
2317
  /**
2239
2318
  * Adds a pre-configured condition check operation to the transaction.
2240
- * Use this method when you need to:
2241
- * - Reuse condition checks from ConditionCheckBuilder
2242
- * - Add complex condition checks with pre-configured parameters
2243
- * - Integrate with existing condition check configurations
2244
2319
  *
2245
2320
  * This method is particularly useful when working with ConditionCheckBuilder
2246
2321
  * to maintain consistency in condition checks across your application.
@@ -2288,10 +2363,6 @@ var TransactionBuilder = class {
2288
2363
  }
2289
2364
  /**
2290
2365
  * Sets options for the transaction execution.
2291
- * Use this method when you need to:
2292
- * - Enable idempotent transactions
2293
- * - Track consumed capacity
2294
- * - Monitor item collection metrics
2295
2366
  *
2296
2367
  * @example
2297
2368
  * ```typescript
@@ -2319,11 +2390,6 @@ var TransactionBuilder = class {
2319
2390
  }
2320
2391
  /**
2321
2392
  * Gets a human-readable representation of the transaction items.
2322
- * Use this method when you need to:
2323
- * - Debug complex transactions
2324
- * - Verify operation parameters
2325
- * - Log transaction details
2326
- * - Troubleshoot condition expressions
2327
2393
  *
2328
2394
  * The method resolves all expression placeholders with their actual values,
2329
2395
  * making it easier to understand the transaction's operations.
@@ -2352,10 +2418,6 @@ var TransactionBuilder = class {
2352
2418
  }
2353
2419
  /**
2354
2420
  * Executes all operations in the transaction atomically.
2355
- * Use this method when you need to:
2356
- * - Perform multiple operations atomically
2357
- * - Ensure all-or-nothing execution
2358
- * - Maintain data consistency across operations
2359
2421
  *
2360
2422
  * The transaction will only succeed if all operations succeed.
2361
2423
  * If any operation fails, the entire transaction is rolled back.
@@ -2479,10 +2541,6 @@ var ConditionCheckBuilder = class {
2479
2541
  }
2480
2542
  /**
2481
2543
  * Adds a condition that must be satisfied for the check to succeed.
2482
- * Use this method when you need to:
2483
- * - Validate complex item states
2484
- * - Check multiple attributes together
2485
- * - Ensure safety conditions are met
2486
2544
  *
2487
2545
  * @example
2488
2546
  * ```typescript
@@ -2578,10 +2636,6 @@ var ConditionCheckBuilder = class {
2578
2636
  }
2579
2637
  /**
2580
2638
  * Adds this condition check operation to a transaction.
2581
- * Use this method when you need to:
2582
- * - Verify habitat safety before transfers
2583
- * - Ensure proper feeding conditions
2584
- * - Validate security protocols
2585
2639
  *
2586
2640
  * @example
2587
2641
  * ```ts
@@ -2611,11 +2665,6 @@ var ConditionCheckBuilder = class {
2611
2665
  /**
2612
2666
  * Gets a human-readable representation of the condition check command
2613
2667
  * with all expression placeholders replaced by their actual values.
2614
- * Use this method when you need to:
2615
- * - Debug complex condition expressions
2616
- * - Verify condition parameters
2617
- * - Log safety checks
2618
- * - Troubleshoot condition failures
2619
2668
  *
2620
2669
  * @example
2621
2670
  * ```ts
@@ -2638,6 +2687,283 @@ var ConditionCheckBuilder = class {
2638
2687
  }
2639
2688
  };
2640
2689
 
2690
+ // src/builders/batch-builder.ts
2691
+ var BatchError = class extends Error {
2692
+ operation;
2693
+ cause;
2694
+ constructor(message, operation, cause) {
2695
+ super(message);
2696
+ this.name = "BatchError";
2697
+ this.operation = operation;
2698
+ this.cause = cause;
2699
+ }
2700
+ };
2701
+ var BatchBuilder = class {
2702
+ constructor(batchWriteExecutor, batchGetExecutor, config) {
2703
+ this.batchWriteExecutor = batchWriteExecutor;
2704
+ this.batchGetExecutor = batchGetExecutor;
2705
+ this.config = config;
2706
+ }
2707
+ writeItems = [];
2708
+ getItems = [];
2709
+ /**
2710
+ * Checks if the batch is empty (contains no operations)
2711
+ *
2712
+ * @returns true if the batch contains no operations
2713
+ */
2714
+ isEmpty() {
2715
+ return this.writeItems.length === 0 && this.getItems.length === 0;
2716
+ }
2717
+ /**
2718
+ * Gets the count of operations in the batch
2719
+ *
2720
+ * @returns Object containing the count of write and read operations
2721
+ */
2722
+ getOperationCount() {
2723
+ return {
2724
+ writes: this.writeItems.length,
2725
+ reads: this.getItems.length
2726
+ };
2727
+ }
2728
+ /**
2729
+ * Validates that the batch is not empty before execution
2730
+ *
2731
+ * @throws {BatchError} If the batch is empty
2732
+ */
2733
+ validateNotEmpty() {
2734
+ if (this.isEmpty()) {
2735
+ throw new BatchError(
2736
+ "Cannot execute empty batch. Add operations using entity builders with .withBatch()",
2737
+ "write"
2738
+ );
2739
+ }
2740
+ }
2741
+ /**
2742
+ * Adds a put operation to the batch with entity type information.
2743
+ * This method is used internally by entity builders.
2744
+ *
2745
+ * @param command - The complete put command configuration
2746
+ * @param entityType - The entity type name for type tracking
2747
+ * @returns The batch builder for method chaining
2748
+ * @internal
2749
+ */
2750
+ putWithCommand(command, entityType) {
2751
+ const batchItem = {
2752
+ type: "Put",
2753
+ params: command,
2754
+ entityType
2755
+ };
2756
+ this.writeItems.push(batchItem);
2757
+ return this;
2758
+ }
2759
+ /**
2760
+ * Adds a delete operation to the batch with entity type information.
2761
+ * This method is used internally by entity builders.
2762
+ *
2763
+ * @param command - The complete delete command configuration
2764
+ * @param entityType - The entity type name for type tracking
2765
+ * @returns The batch builder for method chaining
2766
+ * @internal
2767
+ */
2768
+ deleteWithCommand(command, entityType) {
2769
+ const batchItem = {
2770
+ type: "Delete",
2771
+ params: command,
2772
+ entityType
2773
+ };
2774
+ this.writeItems.push(batchItem);
2775
+ return this;
2776
+ }
2777
+ /**
2778
+ * Adds a get operation to the batch with entity type information.
2779
+ * This method is used internally by entity builders.
2780
+ *
2781
+ * @param command - The complete get command configuration
2782
+ * @param entityType - The entity type name for type tracking
2783
+ * @returns The batch builder for method chaining
2784
+ * @internal
2785
+ */
2786
+ getWithCommand(command, entityType) {
2787
+ const batchItem = {
2788
+ type: "Get",
2789
+ params: command,
2790
+ entityType
2791
+ };
2792
+ this.getItems.push(batchItem);
2793
+ return this;
2794
+ }
2795
+ /**
2796
+ * Executes all write operations in the batch.
2797
+ *
2798
+ * @returns A promise that resolves to any unprocessed operations
2799
+ * @private
2800
+ */
2801
+ async executeWrites() {
2802
+ if (this.writeItems.length === 0) {
2803
+ return { unprocessedItems: [] };
2804
+ }
2805
+ try {
2806
+ const operations = this.writeItems.map((item) => {
2807
+ if (item.type === "Put") {
2808
+ return {
2809
+ type: "put",
2810
+ item: item.params.item
2811
+ };
2812
+ }
2813
+ if (item.type === "Delete") {
2814
+ let key;
2815
+ if (typeof item.params.key === "object" && item.params.key !== null && "pk" in item.params.key) {
2816
+ key = item.params.key;
2817
+ } else {
2818
+ const tableKey = item.params.key;
2819
+ key = {
2820
+ pk: tableKey[this.config.partitionKey],
2821
+ sk: this.config.sortKey ? tableKey[this.config.sortKey] : void 0
2822
+ };
2823
+ }
2824
+ return {
2825
+ type: "delete",
2826
+ key
2827
+ };
2828
+ }
2829
+ throw new BatchError(`Unsupported batch item type for write operation: ${item.type}`, "write");
2830
+ });
2831
+ return await this.batchWriteExecutor(operations);
2832
+ } catch (error) {
2833
+ throw new BatchError(
2834
+ `Failed to execute batch write operations: ${error instanceof Error ? error.message : "Unknown error"}`,
2835
+ "write",
2836
+ error instanceof Error ? error : void 0
2837
+ );
2838
+ }
2839
+ }
2840
+ /**
2841
+ * Executes all get operations in the batch.
2842
+ *
2843
+ * @returns A promise that resolves to the retrieved items
2844
+ * @private
2845
+ */
2846
+ async executeGets() {
2847
+ if (this.getItems.length === 0) {
2848
+ return { items: [], unprocessedKeys: [] };
2849
+ }
2850
+ try {
2851
+ const keys = this.getItems.map((item) => {
2852
+ if (item.type === "Get") {
2853
+ if (typeof item.params.key === "object" && item.params.key !== null && "pk" in item.params.key) {
2854
+ return item.params.key;
2855
+ }
2856
+ const tableKey = item.params.key;
2857
+ return {
2858
+ pk: tableKey[this.config.partitionKey],
2859
+ sk: this.config.sortKey ? tableKey[this.config.sortKey] : void 0
2860
+ };
2861
+ }
2862
+ throw new BatchError(`Unsupported batch item type for get operation: ${item.type}`, "read");
2863
+ });
2864
+ return await this.batchGetExecutor(keys);
2865
+ } catch (error) {
2866
+ throw new BatchError(
2867
+ `Failed to execute batch get operations: ${error instanceof Error ? error.message : "Unknown error"}`,
2868
+ "read",
2869
+ error instanceof Error ? error : void 0
2870
+ );
2871
+ }
2872
+ }
2873
+ /**
2874
+ * Groups retrieved items by their entity type.
2875
+ * @private
2876
+ */
2877
+ groupItemsByType(items) {
2878
+ const grouped = {};
2879
+ for (const item of this.getItems) {
2880
+ if (item.entityType) {
2881
+ const entityType = item.entityType;
2882
+ if (!grouped[entityType]) {
2883
+ grouped[entityType] = [];
2884
+ }
2885
+ }
2886
+ }
2887
+ for (const item of items) {
2888
+ const entityType = item.entityType;
2889
+ if (entityType && grouped[entityType]) {
2890
+ grouped[entityType].push(item);
2891
+ }
2892
+ }
2893
+ return grouped;
2894
+ }
2895
+ /**
2896
+ * Executes all operations in the batch with typed results.
2897
+ * Performs write operations first, then get operations.
2898
+ *
2899
+ * @returns A promise that resolves to a TypedBatchResult with entity type information
2900
+ * @throws {BatchError} If the batch is empty or if operations fail
2901
+ */
2902
+ async execute() {
2903
+ this.validateNotEmpty();
2904
+ const errors = [];
2905
+ let writeResults = { unprocessedItems: [] };
2906
+ let getResults = {
2907
+ items: [],
2908
+ unprocessedKeys: []
2909
+ };
2910
+ if (this.writeItems.length > 0) {
2911
+ try {
2912
+ writeResults = await this.executeWrites();
2913
+ } catch (error) {
2914
+ if (error instanceof BatchError) {
2915
+ errors.push(error);
2916
+ } else {
2917
+ errors.push(
2918
+ new BatchError(
2919
+ "Unexpected error during write operations",
2920
+ "write",
2921
+ error instanceof Error ? error : void 0
2922
+ )
2923
+ );
2924
+ }
2925
+ }
2926
+ }
2927
+ if (this.getItems.length > 0) {
2928
+ try {
2929
+ getResults = await this.executeGets();
2930
+ } catch (error) {
2931
+ if (error instanceof BatchError) {
2932
+ errors.push(error);
2933
+ } else {
2934
+ errors.push(
2935
+ new BatchError(
2936
+ "Unexpected error during read operations",
2937
+ "read",
2938
+ error instanceof Error ? error : void 0
2939
+ )
2940
+ );
2941
+ }
2942
+ }
2943
+ }
2944
+ if (errors.length > 0 && (writeResults.unprocessedItems.length === this.writeItems.length || getResults.unprocessedKeys.length === this.getItems.length)) {
2945
+ throw errors[0];
2946
+ }
2947
+ const totalOperations = this.writeItems.length + this.getItems.length;
2948
+ const success = errors.length === 0 && writeResults.unprocessedItems.length === 0 && getResults.unprocessedKeys.length === 0;
2949
+ return {
2950
+ success,
2951
+ writes: {
2952
+ processed: this.writeItems.length - writeResults.unprocessedItems.length,
2953
+ unprocessed: writeResults.unprocessedItems
2954
+ },
2955
+ reads: {
2956
+ itemsByType: this.groupItemsByType(getResults.items),
2957
+ items: getResults.items,
2958
+ found: getResults.items.length,
2959
+ unprocessed: getResults.unprocessedKeys
2960
+ },
2961
+ totalOperations,
2962
+ errors: errors.length > 0 ? errors : void 0
2963
+ };
2964
+ }
2965
+ };
2966
+
2641
2967
  // src/builders/get-builder.ts
2642
2968
  var GetBuilder = class {
2643
2969
  /**
@@ -2659,10 +2985,6 @@ var GetBuilder = class {
2659
2985
  selectedFields = /* @__PURE__ */ new Set();
2660
2986
  /**
2661
2987
  * Specifies which attributes to return in the get results.
2662
- * Use this method when you need to:
2663
- * - Reduce data transfer by selecting specific dinosaur attributes
2664
- * - Optimize response size for dinosaur records
2665
- * - Focus on relevant dinosaur characteristics only
2666
2988
  *
2667
2989
  * @example
2668
2990
  * ```typescript
@@ -2716,6 +3038,60 @@ var GetBuilder = class {
2716
3038
  this.params.consistentRead = consistentRead;
2717
3039
  return this;
2718
3040
  }
3041
+ /**
3042
+ * Adds this get operation to a batch with optional entity type information.
3043
+ *
3044
+ * @example Basic Usage
3045
+ * ```ts
3046
+ * const batch = table.batchBuilder();
3047
+ *
3048
+ * // Add multiple get operations to batch
3049
+ * dinosaurRepo.get({ id: 'dino-1' }).withBatch(batch);
3050
+ * dinosaurRepo.get({ id: 'dino-2' }).withBatch(batch);
3051
+ * dinosaurRepo.get({ id: 'dino-3' }).withBatch(batch);
3052
+ *
3053
+ * // Execute all gets efficiently
3054
+ * const results = await batch.execute();
3055
+ * ```
3056
+ *
3057
+ * @example Typed Usage
3058
+ * ```ts
3059
+ * const batch = table.batchBuilder<{
3060
+ * User: UserEntity;
3061
+ * Order: OrderEntity;
3062
+ * }>();
3063
+ *
3064
+ * // Add operations with type information
3065
+ * userRepo.get({ id: 'user-1' }).withBatch(batch, 'User');
3066
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch, 'Order');
3067
+ *
3068
+ * // Execute and get typed results
3069
+ * const result = await batch.execute();
3070
+ * const users: UserEntity[] = result.reads.itemsByType.User;
3071
+ * const orders: OrderEntity[] = result.reads.itemsByType.Order;
3072
+ * ```
3073
+ *
3074
+ * @param batch - The batch builder to add this operation to
3075
+ * @param entityType - Optional entity type key for type tracking
3076
+ */
3077
+ withBatch(batch, entityType) {
3078
+ const command = this.toDynamoCommand();
3079
+ batch.getWithCommand(command, entityType);
3080
+ }
3081
+ /**
3082
+ * Converts the builder configuration to a DynamoDB command
3083
+ */
3084
+ toDynamoCommand() {
3085
+ const expressionParams = {
3086
+ expressionAttributeNames: {}};
3087
+ const projectionExpression = Array.from(this.selectedFields).map((p) => generateAttributeName(expressionParams, p)).join(", ");
3088
+ const { expressionAttributeNames } = expressionParams;
3089
+ return {
3090
+ ...this.params,
3091
+ projectionExpression: projectionExpression.length > 0 ? projectionExpression : void 0,
3092
+ expressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : void 0
3093
+ };
3094
+ }
2719
3095
  /**
2720
3096
  * Executes the get operation against DynamoDB.
2721
3097
  *
@@ -2741,15 +3117,8 @@ var GetBuilder = class {
2741
3117
  * - item: The retrieved dinosaur or undefined if not found
2742
3118
  */
2743
3119
  async execute() {
2744
- const expressionParams = {
2745
- expressionAttributeNames: {}};
2746
- const projectionExpression = Array.from(this.selectedFields).map((p) => generateAttributeName(expressionParams, p)).join(", ");
2747
- const { expressionAttributeNames } = expressionParams;
2748
- return this.executor({
2749
- ...this.params,
2750
- projectionExpression: projectionExpression.length > 0 ? projectionExpression : void 0,
2751
- expressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : void 0
2752
- });
3120
+ const command = this.toDynamoCommand();
3121
+ return this.executor(command);
2753
3122
  }
2754
3123
  };
2755
3124
 
@@ -2762,10 +3131,6 @@ var ScanBuilder = class _ScanBuilder extends FilterBuilder {
2762
3131
  }
2763
3132
  /**
2764
3133
  * Creates a deep clone of this ScanBuilder instance.
2765
- * Use this method when you need to:
2766
- * - Create scan templates
2767
- * - Run multiple variations of a scan
2768
- * - Implement pagination (used internally by paginate())
2769
3134
  *
2770
3135
  * @returns A new ScanBuilder instance with the same configuration
2771
3136
  */
@@ -2776,46 +3141,43 @@ var ScanBuilder = class _ScanBuilder extends FilterBuilder {
2776
3141
  return clone;
2777
3142
  }
2778
3143
  /**
2779
- * Executes the scan against DynamoDB.
2780
- * Use this method when you need to:
2781
- * - Search across the entire table
2782
- * - Find items matching specific criteria
2783
- * - Perform full table analysis
2784
- * - Generate reports across all data
3144
+ * Executes the scan against DynamoDB and returns a generator that behaves like an array.
2785
3145
  *
2786
- * The method returns both the matched items and, if there are more results,
2787
- * a lastEvaluatedKey that can be used with startFrom() to continue the scan.
3146
+ * The generator automatically handles pagination and provides array-like methods
3147
+ * for processing results efficiently without loading everything into memory at once.
2788
3148
  *
2789
3149
  * @example
2790
3150
  * ```typescript
2791
3151
  * try {
2792
- * // Find all dinosaurs with high aggression levels
2793
- * const result = await new ScanBuilder(executor)
3152
+ * // Find all dinosaurs with high aggression levels with automatic pagination
3153
+ * const results = await new ScanBuilder(executor)
2794
3154
  * .filter(op =>
2795
3155
  * op.and([
2796
3156
  * op.eq('status', 'ACTIVE'),
2797
3157
  * op.gt('aggressionLevel', 7)
2798
3158
  * ])
2799
3159
  * )
2800
- * .limit(20)
2801
3160
  * .execute();
2802
3161
  *
2803
- * console.log(`Found ${result.items.length} potentially dangerous dinosaurs`);
2804
- *
2805
- * if (result.lastEvaluatedKey) {
2806
- * console.log('More results available');
3162
+ * // Use like an array with automatic pagination
3163
+ * for await (const dinosaur of results) {
3164
+ * console.log(`Processing dangerous dinosaur: ${dinosaur.name}`);
2807
3165
  * }
3166
+ *
3167
+ * // Or convert to array and use array methods
3168
+ * const allItems = await results.toArray();
3169
+ * const criticalThreats = allItems.filter(dino => dino.aggressionLevel > 9);
3170
+ * const totalCount = allItems.length;
2808
3171
  * } catch (error) {
2809
3172
  * console.error('Security scan failed:', error);
2810
3173
  * }
2811
3174
  * ```
2812
3175
  *
2813
- * @returns A promise that resolves to an object containing:
2814
- * - items: Array of items matching the scan criteria
2815
- * - lastEvaluatedKey: Token for continuing the scan, if more items exist
3176
+ * @returns A promise that resolves to a ResultGenerator that behaves like an array
2816
3177
  */
2817
3178
  async execute() {
2818
- return this.executor(this.options);
3179
+ const directExecutor = () => this.executor(this.options);
3180
+ return new ResultIterator(this, directExecutor);
2819
3181
  }
2820
3182
  };
2821
3183
 
@@ -3176,6 +3538,53 @@ var Table = class {
3176
3538
  sortKey: this.sortKey
3177
3539
  });
3178
3540
  }
3541
+ /**
3542
+ * Creates a batch builder for performing multiple operations efficiently with optional type inference
3543
+ *
3544
+ * @example Basic Usage
3545
+ * ```typescript
3546
+ * const batch = table.batchBuilder();
3547
+ *
3548
+ * // Add operations
3549
+ * userRepo.create(newUser).withBatch(batch);
3550
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch);
3551
+ *
3552
+ * // Execute operations
3553
+ * const result = await batch.execute();
3554
+ * ```
3555
+ *
3556
+ * @example Typed Usage
3557
+ * ```typescript
3558
+ * // Define entity types for the batch
3559
+ * const batch = table.batchBuilder<{
3560
+ * User: UserEntity;
3561
+ * Order: OrderEntity;
3562
+ * Product: ProductEntity;
3563
+ * }>();
3564
+ *
3565
+ * // Add operations with type information
3566
+ * userRepo.create(newUser).withBatch(batch, 'User');
3567
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch, 'Order');
3568
+ * productRepo.delete({ id: 'old-product' }).withBatch(batch, 'Product');
3569
+ *
3570
+ * // Execute and get typed results
3571
+ * const result = await batch.execute();
3572
+ * const users: UserEntity[] = result.reads.itemsByType.User;
3573
+ * const orders: OrderEntity[] = result.reads.itemsByType.Order;
3574
+ * ```
3575
+ */
3576
+ batchBuilder() {
3577
+ const batchWriteExecutor = async (operations) => {
3578
+ return this.batchWrite(operations);
3579
+ };
3580
+ const batchGetExecutor = async (keys) => {
3581
+ return this.batchGet(keys);
3582
+ };
3583
+ return new BatchBuilder(batchWriteExecutor, batchGetExecutor, {
3584
+ partitionKey: this.partitionKey,
3585
+ sortKey: this.sortKey
3586
+ });
3587
+ }
3179
3588
  /**
3180
3589
  * Executes a transaction using a callback function
3181
3590
  *
@@ -3316,9 +3725,55 @@ var Table = class {
3316
3725
  }
3317
3726
  };
3318
3727
 
3728
+ // src/builders/entity-aware-builders.ts
3729
+ function createEntityAwareBuilder(builder, entityName) {
3730
+ return new Proxy(builder, {
3731
+ get(target, prop, receiver) {
3732
+ if (prop === "entityName") {
3733
+ return entityName;
3734
+ }
3735
+ if (prop === "withBatch" && typeof target[prop] === "function") {
3736
+ return (batch, entityType) => {
3737
+ const typeToUse = entityType ?? entityName;
3738
+ const fn = target[prop];
3739
+ return fn.call(target, batch, typeToUse);
3740
+ };
3741
+ }
3742
+ return Reflect.get(target, prop, receiver);
3743
+ }
3744
+ });
3745
+ }
3746
+ function createEntityAwarePutBuilder(builder, entityName) {
3747
+ return createEntityAwareBuilder(builder, entityName);
3748
+ }
3749
+ function createEntityAwareGetBuilder(builder, entityName) {
3750
+ return createEntityAwareBuilder(builder, entityName);
3751
+ }
3752
+ function createEntityAwareDeleteBuilder(builder, entityName) {
3753
+ return createEntityAwareBuilder(builder, entityName);
3754
+ }
3755
+
3319
3756
  // src/entity.ts
3320
3757
  function defineEntity(config) {
3321
3758
  const entityTypeAttributeName = config.settings?.entityTypeAttributeName ?? "entityType";
3759
+ const wrapMethodWithPreparation = (originalMethod, prepareFn, context) => {
3760
+ const wrappedMethod = (...args) => {
3761
+ prepareFn();
3762
+ return originalMethod.call(context, ...args);
3763
+ };
3764
+ Object.setPrototypeOf(wrappedMethod, originalMethod);
3765
+ const propertyNames = Object.getOwnPropertyNames(originalMethod);
3766
+ for (let i = 0; i < propertyNames.length; i++) {
3767
+ const prop = propertyNames[i];
3768
+ if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3769
+ const descriptor = Object.getOwnPropertyDescriptor(originalMethod, prop);
3770
+ if (descriptor && descriptor.writable !== false && !descriptor.get) {
3771
+ wrappedMethod[prop] = originalMethod[prop];
3772
+ }
3773
+ }
3774
+ }
3775
+ return wrappedMethod;
3776
+ };
3322
3777
  const generateTimestamps = (timestampTypes) => {
3323
3778
  if (!config.settings?.timestamps) return {};
3324
3779
  const timestamps = {};
@@ -3423,24 +3878,17 @@ function defineEntity(config) {
3423
3878
  };
3424
3879
  const originalWithTransaction = builder.withTransaction;
3425
3880
  if (originalWithTransaction) {
3426
- const wrappedWithTransaction = (transaction) => {
3427
- prepareValidatedItemSync();
3428
- return originalWithTransaction.call(builder, transaction);
3429
- };
3430
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
3431
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
3432
- for (let i = 0; i < propertyNames.length; i++) {
3433
- const prop = propertyNames[i];
3434
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3435
- try {
3436
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
3437
- } catch (e) {
3438
- }
3439
- }
3440
- }
3441
- builder.withTransaction = wrappedWithTransaction;
3881
+ builder.withTransaction = wrapMethodWithPreparation(
3882
+ originalWithTransaction,
3883
+ prepareValidatedItemSync,
3884
+ builder
3885
+ );
3442
3886
  }
3443
- return builder;
3887
+ const originalWithBatch = builder.withBatch;
3888
+ if (originalWithBatch) {
3889
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
3890
+ }
3891
+ return createEntityAwarePutBuilder(builder, config.name);
3444
3892
  },
3445
3893
  upsert: (data) => {
3446
3894
  const builder = table.put({});
@@ -3527,26 +3975,19 @@ function defineEntity(config) {
3527
3975
  };
3528
3976
  const originalWithTransaction = builder.withTransaction;
3529
3977
  if (originalWithTransaction) {
3530
- const wrappedWithTransaction = (transaction) => {
3531
- prepareValidatedItemSync();
3532
- return originalWithTransaction.call(builder, transaction);
3533
- };
3534
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
3535
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
3536
- for (let i = 0; i < propertyNames.length; i++) {
3537
- const prop = propertyNames[i];
3538
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3539
- try {
3540
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
3541
- } catch (e) {
3542
- }
3543
- }
3544
- }
3545
- builder.withTransaction = wrappedWithTransaction;
3978
+ builder.withTransaction = wrapMethodWithPreparation(
3979
+ originalWithTransaction,
3980
+ prepareValidatedItemSync,
3981
+ builder
3982
+ );
3546
3983
  }
3547
- return builder;
3984
+ const originalWithBatch = builder.withBatch;
3985
+ if (originalWithBatch) {
3986
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
3987
+ }
3988
+ return createEntityAwarePutBuilder(builder, config.name);
3548
3989
  },
3549
- get: (key) => table.get(config.primaryKey.generateKey(key)),
3990
+ get: (key) => createEntityAwareGetBuilder(table.get(config.primaryKey.generateKey(key)), config.name),
3550
3991
  update: (key, data) => {
3551
3992
  const primaryKeyObj = config.primaryKey.generateKey(key);
3552
3993
  const builder = table.update(primaryKeyObj);
@@ -3558,13 +3999,13 @@ function defineEntity(config) {
3558
3999
  delete: (key) => {
3559
4000
  const builder = table.delete(config.primaryKey.generateKey(key));
3560
4001
  builder.condition(eq(entityTypeAttributeName, config.name));
3561
- return builder;
4002
+ return createEntityAwareDeleteBuilder(builder, config.name);
3562
4003
  },
3563
4004
  query: Object.entries(config.queries || {}).reduce((acc, [key, inputCallback]) => {
3564
4005
  acc[key] = (input) => {
3565
4006
  const queryEntity = {
3566
4007
  scan: repository.scan,
3567
- get: (key2) => table.get(key2),
4008
+ get: (key2) => createEntityAwareGetBuilder(table.get(key2), config.name),
3568
4009
  query: (keyCondition) => {
3569
4010
  return table.query(keyCondition);
3570
4011
  }
@@ -3669,6 +4110,6 @@ function sortKey(strings, ...keys) {
3669
4110
  };
3670
4111
  }
3671
4112
 
3672
- export { DeleteBuilder, PutBuilder, QueryBuilder, Table, TransactionBuilder, UpdateBuilder, and, attributeExists, attributeNotExists, beginsWith, between, contains, createIndex, createQueries, defineEntity, eq, gt, gte, inArray, lt, lte, ne, not, or, partitionKey, sortKey };
4113
+ export { BatchBuilder, BatchError, DeleteBuilder, PutBuilder, QueryBuilder, Table, TransactionBuilder, UpdateBuilder, and, attributeExists, attributeNotExists, beginsWith, between, contains, createIndex, createQueries, defineEntity, eq, gt, gte, inArray, lt, lte, ne, not, or, partitionKey, sortKey };
3673
4114
  //# sourceMappingURL=index.js.map
3674
4115
  //# sourceMappingURL=index.js.map