dyno-table 1.5.0 → 1.7.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 (72) hide show
  1. package/README.md +368 -186
  2. package/dist/batch-builder-DNsz6zvh.d.cts +398 -0
  3. package/dist/batch-builder-Dz1yPGrJ.d.ts +398 -0
  4. package/dist/builders/condition-check-builder.cjs +0 -13
  5. package/dist/builders/condition-check-builder.cjs.map +1 -1
  6. package/dist/builders/condition-check-builder.d.cts +0 -13
  7. package/dist/builders/condition-check-builder.d.ts +0 -13
  8. package/dist/builders/condition-check-builder.js +0 -13
  9. package/dist/builders/condition-check-builder.js.map +1 -1
  10. package/dist/builders/delete-builder.cjs +38 -0
  11. package/dist/builders/delete-builder.cjs.map +1 -1
  12. package/dist/builders/delete-builder.d.cts +36 -0
  13. package/dist/builders/delete-builder.d.ts +36 -0
  14. package/dist/builders/delete-builder.js +38 -0
  15. package/dist/builders/delete-builder.js.map +1 -1
  16. package/dist/builders/paginator.cjs +0 -24
  17. package/dist/builders/paginator.cjs.map +1 -1
  18. package/dist/builders/paginator.d.cts +0 -24
  19. package/dist/builders/paginator.d.ts +0 -24
  20. package/dist/builders/paginator.js +0 -24
  21. package/dist/builders/paginator.js.map +1 -1
  22. package/dist/builders/put-builder.cjs +39 -8
  23. package/dist/builders/put-builder.cjs.map +1 -1
  24. package/dist/builders/put-builder.d.cts +37 -8
  25. package/dist/builders/put-builder.d.ts +37 -8
  26. package/dist/builders/put-builder.js +39 -8
  27. package/dist/builders/put-builder.js.map +1 -1
  28. package/dist/builders/query-builder.cjs +0 -53
  29. package/dist/builders/query-builder.cjs.map +1 -1
  30. package/dist/builders/query-builder.d.cts +1 -1
  31. package/dist/builders/query-builder.d.ts +1 -1
  32. package/dist/builders/query-builder.js +0 -53
  33. package/dist/builders/query-builder.js.map +1 -1
  34. package/dist/builders/transaction-builder.cjs +0 -47
  35. package/dist/builders/transaction-builder.cjs.map +1 -1
  36. package/dist/builders/transaction-builder.d.cts +0 -47
  37. package/dist/builders/transaction-builder.d.ts +0 -47
  38. package/dist/builders/transaction-builder.js +0 -47
  39. package/dist/builders/transaction-builder.js.map +1 -1
  40. package/dist/builders/update-builder.cjs +2 -2
  41. package/dist/builders/update-builder.cjs.map +1 -1
  42. package/dist/builders/update-builder.d.cts +2 -2
  43. package/dist/builders/update-builder.d.ts +2 -2
  44. package/dist/builders/update-builder.js +2 -2
  45. package/dist/builders/update-builder.js.map +1 -1
  46. package/dist/conditions.cjs.map +1 -1
  47. package/dist/conditions.js.map +1 -1
  48. package/dist/entity.cjs +162 -86
  49. package/dist/entity.cjs.map +1 -1
  50. package/dist/entity.d.cts +39 -15
  51. package/dist/entity.d.ts +39 -15
  52. package/dist/entity.js +162 -86
  53. package/dist/entity.js.map +1 -1
  54. package/dist/index.cjs +623 -231
  55. package/dist/index.cjs.map +1 -1
  56. package/dist/index.d.cts +3 -2
  57. package/dist/index.d.ts +3 -2
  58. package/dist/index.js +622 -232
  59. package/dist/index.js.map +1 -1
  60. package/dist/{query-builder-CbHvimBk.d.cts → query-builder-BDuHHrb-.d.cts} +0 -34
  61. package/dist/{query-builder-BhrR31oO.d.ts → query-builder-C6XjVEFH.d.ts} +0 -34
  62. package/dist/{table-Des8C2od.d.ts → table-BWa4tx63.d.ts} +39 -151
  63. package/dist/{table-CY9byPEg.d.cts → table-DAKlzQsK.d.cts} +39 -151
  64. package/dist/table.cjs +459 -145
  65. package/dist/table.cjs.map +1 -1
  66. package/dist/table.d.cts +3 -2
  67. package/dist/table.d.ts +3 -2
  68. package/dist/table.js +459 -145
  69. package/dist/table.js.map +1 -1
  70. package/dist/utils.cjs.map +1 -1
  71. package/dist/utils.js.map +1 -1
  72. 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
@@ -341,16 +327,6 @@ var Paginator = class {
341
327
  }
342
328
  /**
343
329
  * 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
330
  *
355
331
  * @example
356
332
  * ```ts
@@ -392,10 +368,6 @@ var FilterBuilder = class {
392
368
  selectedFields = /* @__PURE__ */ new Set();
393
369
  /**
394
370
  * 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
371
  *
400
372
  * Note: This limit applies to the items that match the key condition
401
373
  * before any filter expressions are applied.
@@ -426,11 +398,6 @@ var FilterBuilder = class {
426
398
  }
427
399
  /**
428
400
  * 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
401
  *
435
402
  * @example
436
403
  * ```typescript
@@ -459,11 +426,6 @@ var FilterBuilder = class {
459
426
  }
460
427
  /**
461
428
  * 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
429
  *
468
430
  * Note:
469
431
  * - Consistent reads are not available on GSIs
@@ -494,11 +456,6 @@ var FilterBuilder = class {
494
456
  }
495
457
  /**
496
458
  * 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
459
  *
503
460
  * @example
504
461
  * ```typescript
@@ -551,11 +508,6 @@ var FilterBuilder = class {
551
508
  }
552
509
  /**
553
510
  * 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
511
  *
560
512
  * @example
561
513
  * ```typescript
@@ -622,11 +574,6 @@ var FilterBuilder = class {
622
574
  }
623
575
  /**
624
576
  * 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
577
  *
631
578
  * Note: This method is typically used for manual pagination.
632
579
  * For automatic pagination, use the paginate() method instead.
@@ -893,10 +840,6 @@ var PutBuilder = class {
893
840
  }
894
841
  /**
895
842
  * 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
843
  *
901
844
  * @example
902
845
  * ```ts
@@ -1029,10 +972,6 @@ var PutBuilder = class {
1029
972
  }
1030
973
  /**
1031
974
  * 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
975
  *
1037
976
  * @example
1038
977
  * ```ts
@@ -1065,6 +1004,45 @@ var PutBuilder = class {
1065
1004
  transaction.putWithCommand(command);
1066
1005
  return this;
1067
1006
  }
1007
+ /**
1008
+ * Adds this put operation to a batch with optional entity type information.
1009
+ *
1010
+ * @example Basic Usage
1011
+ * ```ts
1012
+ * const batch = table.batchBuilder();
1013
+ *
1014
+ * // Add multiple dinosaurs to batch
1015
+ * dinosaurRepo.create(newDino1).withBatch(batch);
1016
+ * dinosaurRepo.create(newDino2).withBatch(batch);
1017
+ * dinosaurRepo.create(newDino3).withBatch(batch);
1018
+ *
1019
+ * // Execute all operations efficiently
1020
+ * await batch.execute();
1021
+ * ```
1022
+ *
1023
+ * @example Typed Usage
1024
+ * ```ts
1025
+ * const batch = table.batchBuilder<{
1026
+ * User: UserEntity;
1027
+ * Order: OrderEntity;
1028
+ * }>();
1029
+ *
1030
+ * // Add operations with type information
1031
+ * userRepo.create(newUser).withBatch(batch, 'User');
1032
+ * orderRepo.create(newOrder).withBatch(batch, 'Order');
1033
+ *
1034
+ * // Execute and get typed results
1035
+ * const result = await batch.execute();
1036
+ * const users: UserEntity[] = result.reads.itemsByType.User;
1037
+ * ```
1038
+ *
1039
+ * @param batch - The batch builder to add this operation to
1040
+ * @param entityType - Optional entity type key for type tracking
1041
+ */
1042
+ withBatch(batch, entityType) {
1043
+ const command = this.toDynamoCommand();
1044
+ batch.putWithCommand(command, entityType);
1045
+ }
1068
1046
  /**
1069
1047
  * Executes the put operation against DynamoDB.
1070
1048
  *
@@ -1259,6 +1237,44 @@ var DeleteBuilder = class {
1259
1237
  const command = this.toDynamoCommand();
1260
1238
  transaction.deleteWithCommand(command);
1261
1239
  }
1240
+ /**
1241
+ * Adds this delete operation to a batch with optional entity type information.
1242
+ *
1243
+ * @example Basic Usage
1244
+ * ```ts
1245
+ * const batch = table.batchBuilder();
1246
+ *
1247
+ * // Remove multiple dinosaurs in batch
1248
+ * dinosaurRepo.delete({ id: 'old-dino-1' }).withBatch(batch);
1249
+ * dinosaurRepo.delete({ id: 'old-dino-2' }).withBatch(batch);
1250
+ * dinosaurRepo.delete({ id: 'old-dino-3' }).withBatch(batch);
1251
+ *
1252
+ * // Execute all deletions efficiently
1253
+ * await batch.execute();
1254
+ * ```
1255
+ *
1256
+ * @example Typed Usage
1257
+ * ```ts
1258
+ * const batch = table.batchBuilder<{
1259
+ * User: UserEntity;
1260
+ * Order: OrderEntity;
1261
+ * }>();
1262
+ *
1263
+ * // Add operations with type information
1264
+ * userRepo.delete({ id: 'user-1' }).withBatch(batch, 'User');
1265
+ * orderRepo.delete({ id: 'order-1' }).withBatch(batch, 'Order');
1266
+ *
1267
+ * // Execute batch operations
1268
+ * await batch.execute();
1269
+ * ```
1270
+ *
1271
+ * @param batch - The batch builder to add this operation to
1272
+ * @param entityType - Optional entity type key for type tracking
1273
+ */
1274
+ withBatch(batch, entityType) {
1275
+ const command = this.toDynamoCommand();
1276
+ batch.deleteWithCommand(command, entityType);
1277
+ }
1262
1278
  /**
1263
1279
  * Executes the delete operation against DynamoDB.
1264
1280
  *
@@ -1501,11 +1517,11 @@ var UpdateBuilder = class {
1501
1517
  * Sets which item attributes to include in the response.
1502
1518
  *
1503
1519
  * Available options:
1504
- * - ALL_NEW: All attributes after the update
1520
+ * - ALL_NEW: All attributes after the update (default)
1505
1521
  * - UPDATED_NEW: Only updated attributes, new values
1506
1522
  * - ALL_OLD: All attributes before the update
1507
1523
  * - UPDATED_OLD: Only updated attributes, old values
1508
- * - NONE: No attributes returned (default)
1524
+ * - NONE: No attributes returned
1509
1525
  *
1510
1526
  * @example
1511
1527
  * ```typescript
@@ -1824,10 +1840,6 @@ var TransactionBuilder = class {
1824
1840
  }
1825
1841
  /**
1826
1842
  * 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
1843
  *
1832
1844
  * The method automatically checks for duplicate items within the transaction
1833
1845
  * to prevent multiple operations on the same item.
@@ -1885,10 +1897,6 @@ var TransactionBuilder = class {
1885
1897
  }
1886
1898
  /**
1887
1899
  * 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
1900
  *
1893
1901
  * This method is particularly useful when working with PutBuilder
1894
1902
  * to maintain consistency in put operations across your application.
@@ -1920,10 +1928,6 @@ var TransactionBuilder = class {
1920
1928
  }
1921
1929
  /**
1922
1930
  * 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
1931
  *
1928
1932
  * The method automatically checks for duplicate items within the transaction
1929
1933
  * to prevent multiple operations on the same item.
@@ -1981,10 +1985,6 @@ var TransactionBuilder = class {
1981
1985
  }
1982
1986
  /**
1983
1987
  * 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
1988
  *
1989
1989
  * This method is particularly useful when working with DeleteBuilder
1990
1990
  * to maintain consistency in delete operations across your application.
@@ -2031,11 +2031,6 @@ var TransactionBuilder = class {
2031
2031
  }
2032
2032
  /**
2033
2033
  * 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
2034
  *
2040
2035
  * The method supports all DynamoDB update expressions:
2041
2036
  * - SET: Modify or add attributes
@@ -2113,10 +2108,6 @@ var TransactionBuilder = class {
2113
2108
  }
2114
2109
  /**
2115
2110
  * 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
2111
  *
2121
2112
  * This method is particularly useful when working with UpdateBuilder
2122
2113
  * to maintain consistency in update operations across your application.
@@ -2166,11 +2157,6 @@ var TransactionBuilder = class {
2166
2157
  }
2167
2158
  /**
2168
2159
  * 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
2160
  *
2175
2161
  * Condition checks are particularly useful for:
2176
2162
  * - Implementing optimistic locking
@@ -2237,10 +2223,6 @@ var TransactionBuilder = class {
2237
2223
  }
2238
2224
  /**
2239
2225
  * 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
2226
  *
2245
2227
  * This method is particularly useful when working with ConditionCheckBuilder
2246
2228
  * to maintain consistency in condition checks across your application.
@@ -2288,10 +2270,6 @@ var TransactionBuilder = class {
2288
2270
  }
2289
2271
  /**
2290
2272
  * 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
2273
  *
2296
2274
  * @example
2297
2275
  * ```typescript
@@ -2319,11 +2297,6 @@ var TransactionBuilder = class {
2319
2297
  }
2320
2298
  /**
2321
2299
  * 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
2300
  *
2328
2301
  * The method resolves all expression placeholders with their actual values,
2329
2302
  * making it easier to understand the transaction's operations.
@@ -2352,10 +2325,6 @@ var TransactionBuilder = class {
2352
2325
  }
2353
2326
  /**
2354
2327
  * 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
2328
  *
2360
2329
  * The transaction will only succeed if all operations succeed.
2361
2330
  * If any operation fails, the entire transaction is rolled back.
@@ -2479,10 +2448,6 @@ var ConditionCheckBuilder = class {
2479
2448
  }
2480
2449
  /**
2481
2450
  * 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
2451
  *
2487
2452
  * @example
2488
2453
  * ```typescript
@@ -2578,10 +2543,6 @@ var ConditionCheckBuilder = class {
2578
2543
  }
2579
2544
  /**
2580
2545
  * 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
2546
  *
2586
2547
  * @example
2587
2548
  * ```ts
@@ -2611,11 +2572,6 @@ var ConditionCheckBuilder = class {
2611
2572
  /**
2612
2573
  * Gets a human-readable representation of the condition check command
2613
2574
  * 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
2575
  *
2620
2576
  * @example
2621
2577
  * ```ts
@@ -2638,6 +2594,283 @@ var ConditionCheckBuilder = class {
2638
2594
  }
2639
2595
  };
2640
2596
 
2597
+ // src/builders/batch-builder.ts
2598
+ var BatchError = class extends Error {
2599
+ operation;
2600
+ cause;
2601
+ constructor(message, operation, cause) {
2602
+ super(message);
2603
+ this.name = "BatchError";
2604
+ this.operation = operation;
2605
+ this.cause = cause;
2606
+ }
2607
+ };
2608
+ var BatchBuilder = class {
2609
+ constructor(batchWriteExecutor, batchGetExecutor, config) {
2610
+ this.batchWriteExecutor = batchWriteExecutor;
2611
+ this.batchGetExecutor = batchGetExecutor;
2612
+ this.config = config;
2613
+ }
2614
+ writeItems = [];
2615
+ getItems = [];
2616
+ /**
2617
+ * Checks if the batch is empty (contains no operations)
2618
+ *
2619
+ * @returns true if the batch contains no operations
2620
+ */
2621
+ isEmpty() {
2622
+ return this.writeItems.length === 0 && this.getItems.length === 0;
2623
+ }
2624
+ /**
2625
+ * Gets the count of operations in the batch
2626
+ *
2627
+ * @returns Object containing the count of write and read operations
2628
+ */
2629
+ getOperationCount() {
2630
+ return {
2631
+ writes: this.writeItems.length,
2632
+ reads: this.getItems.length
2633
+ };
2634
+ }
2635
+ /**
2636
+ * Validates that the batch is not empty before execution
2637
+ *
2638
+ * @throws {BatchError} If the batch is empty
2639
+ */
2640
+ validateNotEmpty() {
2641
+ if (this.isEmpty()) {
2642
+ throw new BatchError(
2643
+ "Cannot execute empty batch. Add operations using entity builders with .withBatch()",
2644
+ "write"
2645
+ );
2646
+ }
2647
+ }
2648
+ /**
2649
+ * Adds a put operation to the batch with entity type information.
2650
+ * This method is used internally by entity builders.
2651
+ *
2652
+ * @param command - The complete put command configuration
2653
+ * @param entityType - The entity type name for type tracking
2654
+ * @returns The batch builder for method chaining
2655
+ * @internal
2656
+ */
2657
+ putWithCommand(command, entityType) {
2658
+ const batchItem = {
2659
+ type: "Put",
2660
+ params: command,
2661
+ entityType
2662
+ };
2663
+ this.writeItems.push(batchItem);
2664
+ return this;
2665
+ }
2666
+ /**
2667
+ * Adds a delete operation to the batch with entity type information.
2668
+ * This method is used internally by entity builders.
2669
+ *
2670
+ * @param command - The complete delete command configuration
2671
+ * @param entityType - The entity type name for type tracking
2672
+ * @returns The batch builder for method chaining
2673
+ * @internal
2674
+ */
2675
+ deleteWithCommand(command, entityType) {
2676
+ const batchItem = {
2677
+ type: "Delete",
2678
+ params: command,
2679
+ entityType
2680
+ };
2681
+ this.writeItems.push(batchItem);
2682
+ return this;
2683
+ }
2684
+ /**
2685
+ * Adds a get operation to the batch with entity type information.
2686
+ * This method is used internally by entity builders.
2687
+ *
2688
+ * @param command - The complete get command configuration
2689
+ * @param entityType - The entity type name for type tracking
2690
+ * @returns The batch builder for method chaining
2691
+ * @internal
2692
+ */
2693
+ getWithCommand(command, entityType) {
2694
+ const batchItem = {
2695
+ type: "Get",
2696
+ params: command,
2697
+ entityType
2698
+ };
2699
+ this.getItems.push(batchItem);
2700
+ return this;
2701
+ }
2702
+ /**
2703
+ * Executes all write operations in the batch.
2704
+ *
2705
+ * @returns A promise that resolves to any unprocessed operations
2706
+ * @private
2707
+ */
2708
+ async executeWrites() {
2709
+ if (this.writeItems.length === 0) {
2710
+ return { unprocessedItems: [] };
2711
+ }
2712
+ try {
2713
+ const operations = this.writeItems.map((item) => {
2714
+ if (item.type === "Put") {
2715
+ return {
2716
+ type: "put",
2717
+ item: item.params.item
2718
+ };
2719
+ }
2720
+ if (item.type === "Delete") {
2721
+ let key;
2722
+ if (typeof item.params.key === "object" && item.params.key !== null && "pk" in item.params.key) {
2723
+ key = item.params.key;
2724
+ } else {
2725
+ const tableKey = item.params.key;
2726
+ key = {
2727
+ pk: tableKey[this.config.partitionKey],
2728
+ sk: this.config.sortKey ? tableKey[this.config.sortKey] : void 0
2729
+ };
2730
+ }
2731
+ return {
2732
+ type: "delete",
2733
+ key
2734
+ };
2735
+ }
2736
+ throw new BatchError(`Unsupported batch item type for write operation: ${item.type}`, "write");
2737
+ });
2738
+ return await this.batchWriteExecutor(operations);
2739
+ } catch (error) {
2740
+ throw new BatchError(
2741
+ `Failed to execute batch write operations: ${error instanceof Error ? error.message : "Unknown error"}`,
2742
+ "write",
2743
+ error instanceof Error ? error : void 0
2744
+ );
2745
+ }
2746
+ }
2747
+ /**
2748
+ * Executes all get operations in the batch.
2749
+ *
2750
+ * @returns A promise that resolves to the retrieved items
2751
+ * @private
2752
+ */
2753
+ async executeGets() {
2754
+ if (this.getItems.length === 0) {
2755
+ return { items: [], unprocessedKeys: [] };
2756
+ }
2757
+ try {
2758
+ const keys = this.getItems.map((item) => {
2759
+ if (item.type === "Get") {
2760
+ if (typeof item.params.key === "object" && item.params.key !== null && "pk" in item.params.key) {
2761
+ return item.params.key;
2762
+ }
2763
+ const tableKey = item.params.key;
2764
+ return {
2765
+ pk: tableKey[this.config.partitionKey],
2766
+ sk: this.config.sortKey ? tableKey[this.config.sortKey] : void 0
2767
+ };
2768
+ }
2769
+ throw new BatchError(`Unsupported batch item type for get operation: ${item.type}`, "read");
2770
+ });
2771
+ return await this.batchGetExecutor(keys);
2772
+ } catch (error) {
2773
+ throw new BatchError(
2774
+ `Failed to execute batch get operations: ${error instanceof Error ? error.message : "Unknown error"}`,
2775
+ "read",
2776
+ error instanceof Error ? error : void 0
2777
+ );
2778
+ }
2779
+ }
2780
+ /**
2781
+ * Groups retrieved items by their entity type.
2782
+ * @private
2783
+ */
2784
+ groupItemsByType(items) {
2785
+ const grouped = {};
2786
+ for (const item of this.getItems) {
2787
+ if (item.entityType) {
2788
+ const entityType = item.entityType;
2789
+ if (!grouped[entityType]) {
2790
+ grouped[entityType] = [];
2791
+ }
2792
+ }
2793
+ }
2794
+ for (const item of items) {
2795
+ const entityType = item.entityType;
2796
+ if (entityType && grouped[entityType]) {
2797
+ grouped[entityType].push(item);
2798
+ }
2799
+ }
2800
+ return grouped;
2801
+ }
2802
+ /**
2803
+ * Executes all operations in the batch with typed results.
2804
+ * Performs write operations first, then get operations.
2805
+ *
2806
+ * @returns A promise that resolves to a TypedBatchResult with entity type information
2807
+ * @throws {BatchError} If the batch is empty or if operations fail
2808
+ */
2809
+ async execute() {
2810
+ this.validateNotEmpty();
2811
+ const errors = [];
2812
+ let writeResults = { unprocessedItems: [] };
2813
+ let getResults = {
2814
+ items: [],
2815
+ unprocessedKeys: []
2816
+ };
2817
+ if (this.writeItems.length > 0) {
2818
+ try {
2819
+ writeResults = await this.executeWrites();
2820
+ } catch (error) {
2821
+ if (error instanceof BatchError) {
2822
+ errors.push(error);
2823
+ } else {
2824
+ errors.push(
2825
+ new BatchError(
2826
+ "Unexpected error during write operations",
2827
+ "write",
2828
+ error instanceof Error ? error : void 0
2829
+ )
2830
+ );
2831
+ }
2832
+ }
2833
+ }
2834
+ if (this.getItems.length > 0) {
2835
+ try {
2836
+ getResults = await this.executeGets();
2837
+ } catch (error) {
2838
+ if (error instanceof BatchError) {
2839
+ errors.push(error);
2840
+ } else {
2841
+ errors.push(
2842
+ new BatchError(
2843
+ "Unexpected error during read operations",
2844
+ "read",
2845
+ error instanceof Error ? error : void 0
2846
+ )
2847
+ );
2848
+ }
2849
+ }
2850
+ }
2851
+ if (errors.length > 0 && (writeResults.unprocessedItems.length === this.writeItems.length || getResults.unprocessedKeys.length === this.getItems.length)) {
2852
+ throw errors[0];
2853
+ }
2854
+ const totalOperations = this.writeItems.length + this.getItems.length;
2855
+ const success = errors.length === 0 && writeResults.unprocessedItems.length === 0 && getResults.unprocessedKeys.length === 0;
2856
+ return {
2857
+ success,
2858
+ writes: {
2859
+ processed: this.writeItems.length - writeResults.unprocessedItems.length,
2860
+ unprocessed: writeResults.unprocessedItems
2861
+ },
2862
+ reads: {
2863
+ itemsByType: this.groupItemsByType(getResults.items),
2864
+ items: getResults.items,
2865
+ found: getResults.items.length,
2866
+ unprocessed: getResults.unprocessedKeys
2867
+ },
2868
+ totalOperations,
2869
+ errors: errors.length > 0 ? errors : void 0
2870
+ };
2871
+ }
2872
+ };
2873
+
2641
2874
  // src/builders/get-builder.ts
2642
2875
  var GetBuilder = class {
2643
2876
  /**
@@ -2659,10 +2892,6 @@ var GetBuilder = class {
2659
2892
  selectedFields = /* @__PURE__ */ new Set();
2660
2893
  /**
2661
2894
  * 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
2895
  *
2667
2896
  * @example
2668
2897
  * ```typescript
@@ -2716,6 +2945,60 @@ var GetBuilder = class {
2716
2945
  this.params.consistentRead = consistentRead;
2717
2946
  return this;
2718
2947
  }
2948
+ /**
2949
+ * Adds this get operation to a batch with optional entity type information.
2950
+ *
2951
+ * @example Basic Usage
2952
+ * ```ts
2953
+ * const batch = table.batchBuilder();
2954
+ *
2955
+ * // Add multiple get operations to batch
2956
+ * dinosaurRepo.get({ id: 'dino-1' }).withBatch(batch);
2957
+ * dinosaurRepo.get({ id: 'dino-2' }).withBatch(batch);
2958
+ * dinosaurRepo.get({ id: 'dino-3' }).withBatch(batch);
2959
+ *
2960
+ * // Execute all gets efficiently
2961
+ * const results = await batch.execute();
2962
+ * ```
2963
+ *
2964
+ * @example Typed Usage
2965
+ * ```ts
2966
+ * const batch = table.batchBuilder<{
2967
+ * User: UserEntity;
2968
+ * Order: OrderEntity;
2969
+ * }>();
2970
+ *
2971
+ * // Add operations with type information
2972
+ * userRepo.get({ id: 'user-1' }).withBatch(batch, 'User');
2973
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch, 'Order');
2974
+ *
2975
+ * // Execute and get typed results
2976
+ * const result = await batch.execute();
2977
+ * const users: UserEntity[] = result.reads.itemsByType.User;
2978
+ * const orders: OrderEntity[] = result.reads.itemsByType.Order;
2979
+ * ```
2980
+ *
2981
+ * @param batch - The batch builder to add this operation to
2982
+ * @param entityType - Optional entity type key for type tracking
2983
+ */
2984
+ withBatch(batch, entityType) {
2985
+ const command = this.toDynamoCommand();
2986
+ batch.getWithCommand(command, entityType);
2987
+ }
2988
+ /**
2989
+ * Converts the builder configuration to a DynamoDB command
2990
+ */
2991
+ toDynamoCommand() {
2992
+ const expressionParams = {
2993
+ expressionAttributeNames: {}};
2994
+ const projectionExpression = Array.from(this.selectedFields).map((p) => generateAttributeName(expressionParams, p)).join(", ");
2995
+ const { expressionAttributeNames } = expressionParams;
2996
+ return {
2997
+ ...this.params,
2998
+ projectionExpression: projectionExpression.length > 0 ? projectionExpression : void 0,
2999
+ expressionAttributeNames: Object.keys(expressionAttributeNames).length > 0 ? expressionAttributeNames : void 0
3000
+ };
3001
+ }
2719
3002
  /**
2720
3003
  * Executes the get operation against DynamoDB.
2721
3004
  *
@@ -2741,15 +3024,8 @@ var GetBuilder = class {
2741
3024
  * - item: The retrieved dinosaur or undefined if not found
2742
3025
  */
2743
3026
  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
- });
3027
+ const command = this.toDynamoCommand();
3028
+ return this.executor(command);
2753
3029
  }
2754
3030
  };
2755
3031
 
@@ -2762,10 +3038,6 @@ var ScanBuilder = class _ScanBuilder extends FilterBuilder {
2762
3038
  }
2763
3039
  /**
2764
3040
  * 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
3041
  *
2770
3042
  * @returns A new ScanBuilder instance with the same configuration
2771
3043
  */
@@ -2777,11 +3049,6 @@ var ScanBuilder = class _ScanBuilder extends FilterBuilder {
2777
3049
  }
2778
3050
  /**
2779
3051
  * 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
2785
3052
  *
2786
3053
  * The method returns both the matched items and, if there are more results,
2787
3054
  * a lastEvaluatedKey that can be used with startFrom() to continue the scan.
@@ -3176,6 +3443,53 @@ var Table = class {
3176
3443
  sortKey: this.sortKey
3177
3444
  });
3178
3445
  }
3446
+ /**
3447
+ * Creates a batch builder for performing multiple operations efficiently with optional type inference
3448
+ *
3449
+ * @example Basic Usage
3450
+ * ```typescript
3451
+ * const batch = table.batchBuilder();
3452
+ *
3453
+ * // Add operations
3454
+ * userRepo.create(newUser).withBatch(batch);
3455
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch);
3456
+ *
3457
+ * // Execute operations
3458
+ * const result = await batch.execute();
3459
+ * ```
3460
+ *
3461
+ * @example Typed Usage
3462
+ * ```typescript
3463
+ * // Define entity types for the batch
3464
+ * const batch = table.batchBuilder<{
3465
+ * User: UserEntity;
3466
+ * Order: OrderEntity;
3467
+ * Product: ProductEntity;
3468
+ * }>();
3469
+ *
3470
+ * // Add operations with type information
3471
+ * userRepo.create(newUser).withBatch(batch, 'User');
3472
+ * orderRepo.get({ id: 'order-1' }).withBatch(batch, 'Order');
3473
+ * productRepo.delete({ id: 'old-product' }).withBatch(batch, 'Product');
3474
+ *
3475
+ * // Execute and get typed results
3476
+ * const result = await batch.execute();
3477
+ * const users: UserEntity[] = result.reads.itemsByType.User;
3478
+ * const orders: OrderEntity[] = result.reads.itemsByType.Order;
3479
+ * ```
3480
+ */
3481
+ batchBuilder() {
3482
+ const batchWriteExecutor = async (operations) => {
3483
+ return this.batchWrite(operations);
3484
+ };
3485
+ const batchGetExecutor = async (keys) => {
3486
+ return this.batchGet(keys);
3487
+ };
3488
+ return new BatchBuilder(batchWriteExecutor, batchGetExecutor, {
3489
+ partitionKey: this.partitionKey,
3490
+ sortKey: this.sortKey
3491
+ });
3492
+ }
3179
3493
  /**
3180
3494
  * Executes a transaction using a callback function
3181
3495
  *
@@ -3316,9 +3630,55 @@ var Table = class {
3316
3630
  }
3317
3631
  };
3318
3632
 
3633
+ // src/builders/entity-aware-builders.ts
3634
+ function createEntityAwareBuilder(builder, entityName) {
3635
+ return new Proxy(builder, {
3636
+ get(target, prop, receiver) {
3637
+ if (prop === "entityName") {
3638
+ return entityName;
3639
+ }
3640
+ if (prop === "withBatch" && typeof target[prop] === "function") {
3641
+ return (batch, entityType) => {
3642
+ const typeToUse = entityType ?? entityName;
3643
+ const fn = target[prop];
3644
+ return fn.call(target, batch, typeToUse);
3645
+ };
3646
+ }
3647
+ return Reflect.get(target, prop, receiver);
3648
+ }
3649
+ });
3650
+ }
3651
+ function createEntityAwarePutBuilder(builder, entityName) {
3652
+ return createEntityAwareBuilder(builder, entityName);
3653
+ }
3654
+ function createEntityAwareGetBuilder(builder, entityName) {
3655
+ return createEntityAwareBuilder(builder, entityName);
3656
+ }
3657
+ function createEntityAwareDeleteBuilder(builder, entityName) {
3658
+ return createEntityAwareBuilder(builder, entityName);
3659
+ }
3660
+
3319
3661
  // src/entity.ts
3320
3662
  function defineEntity(config) {
3321
3663
  const entityTypeAttributeName = config.settings?.entityTypeAttributeName ?? "entityType";
3664
+ const wrapMethodWithPreparation = (originalMethod, prepareFn, context) => {
3665
+ const wrappedMethod = (...args) => {
3666
+ prepareFn();
3667
+ return originalMethod.call(context, ...args);
3668
+ };
3669
+ Object.setPrototypeOf(wrappedMethod, originalMethod);
3670
+ const propertyNames = Object.getOwnPropertyNames(originalMethod);
3671
+ for (let i = 0; i < propertyNames.length; i++) {
3672
+ const prop = propertyNames[i];
3673
+ if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3674
+ const descriptor = Object.getOwnPropertyDescriptor(originalMethod, prop);
3675
+ if (descriptor && descriptor.writable !== false && !descriptor.get) {
3676
+ wrappedMethod[prop] = originalMethod[prop];
3677
+ }
3678
+ }
3679
+ }
3680
+ return wrappedMethod;
3681
+ };
3322
3682
  const generateTimestamps = (timestampTypes) => {
3323
3683
  if (!config.settings?.timestamps) return {};
3324
3684
  const timestamps = {};
@@ -3341,39 +3701,33 @@ function defineEntity(config) {
3341
3701
  createRepository: (table) => {
3342
3702
  const repository = {
3343
3703
  create: (data) => {
3344
- const primaryKey = config.primaryKey.generateKey(data);
3345
- const indexes = Object.entries(config.indexes ?? {}).reduce(
3346
- (acc, [indexName, index]) => {
3347
- const key = index.generateKey(data);
3348
- const gsiConfig = table.gsis[indexName];
3349
- if (!gsiConfig) {
3350
- throw new Error(`GSI configuration not found for index: ${indexName}`);
3351
- }
3352
- if (key.pk) {
3353
- acc[gsiConfig.partitionKey] = key.pk;
3354
- }
3355
- if (key.sk && gsiConfig.sortKey) {
3356
- acc[gsiConfig.sortKey] = key.sk;
3357
- }
3358
- return acc;
3359
- },
3360
- {}
3361
- );
3362
- const builder = table.create({
3363
- ...data,
3364
- [entityTypeAttributeName]: config.name,
3365
- [table.partitionKey]: primaryKey.pk,
3366
- ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
3367
- ...indexes,
3368
- ...generateTimestamps(["createdAt", "updatedAt"])
3369
- });
3704
+ const builder = table.create({});
3370
3705
  const prepareValidatedItemAsync = async () => {
3371
- const validationResult = await config.schema["~standard"].validate(data);
3372
- if ("issues" in validationResult && validationResult.issues) {
3373
- throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
3706
+ const validationResult = config.schema["~standard"].validate(data);
3707
+ const validatedData = validationResult instanceof Promise ? await validationResult : validationResult;
3708
+ if ("issues" in validatedData && validatedData.issues) {
3709
+ throw new Error(`Validation failed: ${validatedData.issues.map((i) => i.message).join(", ")}`);
3374
3710
  }
3711
+ const primaryKey = config.primaryKey.generateKey(validatedData.value);
3712
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
3713
+ (acc, [indexName, index]) => {
3714
+ const key = index.generateKey(validatedData.value);
3715
+ const gsiConfig = table.gsis[indexName];
3716
+ if (!gsiConfig) {
3717
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
3718
+ }
3719
+ if (key.pk) {
3720
+ acc[gsiConfig.partitionKey] = key.pk;
3721
+ }
3722
+ if (key.sk && gsiConfig.sortKey) {
3723
+ acc[gsiConfig.sortKey] = key.sk;
3724
+ }
3725
+ return acc;
3726
+ },
3727
+ {}
3728
+ );
3375
3729
  const validatedItem = {
3376
- ...validationResult.value,
3730
+ ...validatedData.value,
3377
3731
  [entityTypeAttributeName]: config.name,
3378
3732
  [table.partitionKey]: primaryKey.pk,
3379
3733
  ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
@@ -3386,11 +3740,31 @@ function defineEntity(config) {
3386
3740
  const prepareValidatedItemSync = () => {
3387
3741
  const validationResult = config.schema["~standard"].validate(data);
3388
3742
  if (validationResult instanceof Promise) {
3389
- throw new Error("Async validation is not supported in withTransaction. Use execute() instead.");
3743
+ throw new Error(
3744
+ "Async validation is not supported in create method. The schema must support synchronous validation for transaction compatibility."
3745
+ );
3390
3746
  }
3391
3747
  if ("issues" in validationResult && validationResult.issues) {
3392
3748
  throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
3393
3749
  }
3750
+ const primaryKey = config.primaryKey.generateKey(validationResult.value);
3751
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
3752
+ (acc, [indexName, index]) => {
3753
+ const key = index.generateKey(validationResult.value);
3754
+ const gsiConfig = table.gsis[indexName];
3755
+ if (!gsiConfig) {
3756
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
3757
+ }
3758
+ if (key.pk) {
3759
+ acc[gsiConfig.partitionKey] = key.pk;
3760
+ }
3761
+ if (key.sk && gsiConfig.sortKey) {
3762
+ acc[gsiConfig.sortKey] = key.sk;
3763
+ }
3764
+ return acc;
3765
+ },
3766
+ {}
3767
+ );
3394
3768
  const validatedItem = {
3395
3769
  ...validationResult.value,
3396
3770
  [entityTypeAttributeName]: config.name,
@@ -3409,45 +3783,50 @@ function defineEntity(config) {
3409
3783
  };
3410
3784
  const originalWithTransaction = builder.withTransaction;
3411
3785
  if (originalWithTransaction) {
3412
- const wrappedWithTransaction = (transaction) => {
3413
- prepareValidatedItemSync();
3414
- return originalWithTransaction.call(builder, transaction);
3415
- };
3416
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
3417
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
3418
- for (let i = 0; i < propertyNames.length; i++) {
3419
- const prop = propertyNames[i];
3420
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3421
- try {
3422
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
3423
- } catch (e) {
3424
- }
3425
- }
3426
- }
3427
- builder.withTransaction = wrappedWithTransaction;
3786
+ builder.withTransaction = wrapMethodWithPreparation(
3787
+ originalWithTransaction,
3788
+ prepareValidatedItemSync,
3789
+ builder
3790
+ );
3428
3791
  }
3429
- return builder;
3792
+ const originalWithBatch = builder.withBatch;
3793
+ if (originalWithBatch) {
3794
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
3795
+ }
3796
+ return createEntityAwarePutBuilder(builder, config.name);
3430
3797
  },
3431
3798
  upsert: (data) => {
3432
- const primaryKey = config.primaryKey.generateKey(data);
3433
- const builder = table.put({
3434
- [table.partitionKey]: primaryKey.pk,
3435
- ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
3436
- ...data,
3437
- [entityTypeAttributeName]: config.name,
3438
- ...generateTimestamps(["createdAt", "updatedAt"])
3439
- });
3799
+ const builder = table.put({});
3440
3800
  const prepareValidatedItemAsync = async () => {
3441
- const validationResult = await config.schema["~standard"].validate(data);
3442
- if ("issues" in validationResult && validationResult.issues) {
3443
- throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
3801
+ const validationResult = config.schema["~standard"].validate(data);
3802
+ const validatedData = validationResult instanceof Promise ? await validationResult : validationResult;
3803
+ if ("issues" in validatedData && validatedData.issues) {
3804
+ throw new Error(`Validation failed: ${validatedData.issues.map((i) => i.message).join(", ")}`);
3444
3805
  }
3445
- const primaryKey2 = config.primaryKey.generateKey(validationResult.value);
3806
+ const primaryKey = config.primaryKey.generateKey(validatedData.value);
3807
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
3808
+ (acc, [indexName, index]) => {
3809
+ const key = index.generateKey(validatedData.value);
3810
+ const gsiConfig = table.gsis[indexName];
3811
+ if (!gsiConfig) {
3812
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
3813
+ }
3814
+ if (key.pk) {
3815
+ acc[gsiConfig.partitionKey] = key.pk;
3816
+ }
3817
+ if (key.sk && gsiConfig.sortKey) {
3818
+ acc[gsiConfig.sortKey] = key.sk;
3819
+ }
3820
+ return acc;
3821
+ },
3822
+ {}
3823
+ );
3446
3824
  const validatedItem = {
3447
- [table.partitionKey]: primaryKey2.pk,
3448
- ...table.sortKey ? { [table.sortKey]: primaryKey2.sk } : {},
3449
- ...validationResult.value,
3825
+ [table.partitionKey]: primaryKey.pk,
3826
+ ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
3827
+ ...validatedData.value,
3450
3828
  [entityTypeAttributeName]: config.name,
3829
+ ...indexes,
3451
3830
  ...generateTimestamps(["createdAt", "updatedAt"])
3452
3831
  };
3453
3832
  Object.assign(builder, { item: validatedItem });
@@ -3461,12 +3840,30 @@ function defineEntity(config) {
3461
3840
  if ("issues" in validationResult && validationResult.issues) {
3462
3841
  throw new Error(`Validation failed: ${validationResult.issues.map((i) => i.message).join(", ")}`);
3463
3842
  }
3464
- const primaryKey2 = config.primaryKey.generateKey(validationResult.value);
3843
+ const primaryKey = config.primaryKey.generateKey(validationResult.value);
3844
+ const indexes = Object.entries(config.indexes ?? {}).reduce(
3845
+ (acc, [indexName, index]) => {
3846
+ const key = index.generateKey(validationResult.value);
3847
+ const gsiConfig = table.gsis[indexName];
3848
+ if (!gsiConfig) {
3849
+ throw new Error(`GSI configuration not found for index: ${indexName}`);
3850
+ }
3851
+ if (key.pk) {
3852
+ acc[gsiConfig.partitionKey] = key.pk;
3853
+ }
3854
+ if (key.sk && gsiConfig.sortKey) {
3855
+ acc[gsiConfig.sortKey] = key.sk;
3856
+ }
3857
+ return acc;
3858
+ },
3859
+ {}
3860
+ );
3465
3861
  const validatedItem = {
3466
- [table.partitionKey]: primaryKey2.pk,
3467
- ...table.sortKey ? { [table.sortKey]: primaryKey2.sk } : {},
3862
+ [table.partitionKey]: primaryKey.pk,
3863
+ ...table.sortKey ? { [table.sortKey]: primaryKey.sk } : {},
3468
3864
  ...validationResult.value,
3469
3865
  [entityTypeAttributeName]: config.name,
3866
+ ...indexes,
3470
3867
  ...generateTimestamps(["createdAt", "updatedAt"])
3471
3868
  };
3472
3869
  Object.assign(builder, { item: validatedItem });
@@ -3483,26 +3880,19 @@ function defineEntity(config) {
3483
3880
  };
3484
3881
  const originalWithTransaction = builder.withTransaction;
3485
3882
  if (originalWithTransaction) {
3486
- const wrappedWithTransaction = (transaction) => {
3487
- prepareValidatedItemSync();
3488
- return originalWithTransaction.call(builder, transaction);
3489
- };
3490
- Object.setPrototypeOf(wrappedWithTransaction, originalWithTransaction);
3491
- const propertyNames = Object.getOwnPropertyNames(originalWithTransaction);
3492
- for (let i = 0; i < propertyNames.length; i++) {
3493
- const prop = propertyNames[i];
3494
- if (prop !== "length" && prop !== "name" && prop !== "prototype") {
3495
- try {
3496
- wrappedWithTransaction[prop] = originalWithTransaction[prop];
3497
- } catch (e) {
3498
- }
3499
- }
3500
- }
3501
- builder.withTransaction = wrappedWithTransaction;
3883
+ builder.withTransaction = wrapMethodWithPreparation(
3884
+ originalWithTransaction,
3885
+ prepareValidatedItemSync,
3886
+ builder
3887
+ );
3502
3888
  }
3503
- return builder;
3889
+ const originalWithBatch = builder.withBatch;
3890
+ if (originalWithBatch) {
3891
+ builder.withBatch = wrapMethodWithPreparation(originalWithBatch, prepareValidatedItemSync, builder);
3892
+ }
3893
+ return createEntityAwarePutBuilder(builder, config.name);
3504
3894
  },
3505
- get: (key) => table.get(config.primaryKey.generateKey(key)),
3895
+ get: (key) => createEntityAwareGetBuilder(table.get(config.primaryKey.generateKey(key)), config.name),
3506
3896
  update: (key, data) => {
3507
3897
  const primaryKeyObj = config.primaryKey.generateKey(key);
3508
3898
  const builder = table.update(primaryKeyObj);
@@ -3514,13 +3904,13 @@ function defineEntity(config) {
3514
3904
  delete: (key) => {
3515
3905
  const builder = table.delete(config.primaryKey.generateKey(key));
3516
3906
  builder.condition(eq(entityTypeAttributeName, config.name));
3517
- return builder;
3907
+ return createEntityAwareDeleteBuilder(builder, config.name);
3518
3908
  },
3519
3909
  query: Object.entries(config.queries || {}).reduce((acc, [key, inputCallback]) => {
3520
3910
  acc[key] = (input) => {
3521
3911
  const queryEntity = {
3522
3912
  scan: repository.scan,
3523
- get: (key2) => table.get(key2),
3913
+ get: (key2) => createEntityAwareGetBuilder(table.get(key2), config.name),
3524
3914
  query: (keyCondition) => {
3525
3915
  return table.query(keyCondition);
3526
3916
  }
@@ -3625,6 +4015,6 @@ function sortKey(strings, ...keys) {
3625
4015
  };
3626
4016
  }
3627
4017
 
3628
- 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 };
4018
+ 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 };
3629
4019
  //# sourceMappingURL=index.js.map
3630
4020
  //# sourceMappingURL=index.js.map