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