@model-ts/dynamodb 3.0.3 → 3.1.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.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/__test__/client.test.js +261 -129
- package/dist/cjs/__test__/client.test.js.map +1 -1
- package/dist/cjs/provider.d.ts +149 -19
- package/dist/cjs/provider.js +131 -1
- package/dist/cjs/provider.js.map +1 -1
- package/dist/cjs/sandbox.js +2 -12
- package/dist/cjs/sandbox.js.map +1 -1
- package/dist/esm/__test__/client.test.js +262 -130
- package/dist/esm/__test__/client.test.js.map +1 -1
- package/dist/esm/provider.d.ts +149 -19
- package/dist/esm/provider.js +131 -1
- package/dist/esm/provider.js.map +1 -1
- package/dist/esm/sandbox.js +2 -12
- package/dist/esm/sandbox.js.map +1 -1
- package/package.json +4 -4
- package/src/__test__/client.test.ts +367 -163
- package/src/provider.ts +147 -3
- package/src/sandbox.ts +2 -14
package/src/provider.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Client, Key, PaginationParams } from "./client"
|
|
1
|
+
import { Client, Key, PaginationParams, QueryParams } from "./client"
|
|
2
2
|
import {
|
|
3
3
|
DynamoDBModelInstance,
|
|
4
4
|
DynamoDBModelConstructor,
|
|
@@ -375,8 +375,20 @@ export const getProvider = (client: Client) => {
|
|
|
375
375
|
|
|
376
376
|
return {
|
|
377
377
|
classProps: {
|
|
378
|
+
/**
|
|
379
|
+
* The DynamoDB document client.
|
|
380
|
+
*/
|
|
378
381
|
dynamodb: client,
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Creates operation objects for batch processing and transactions.
|
|
385
|
+
* Supports get, put, update, updateRaw, delete, softDelete, and condition operations.
|
|
386
|
+
*/
|
|
379
387
|
operation,
|
|
388
|
+
|
|
389
|
+
/**
|
|
390
|
+
* @internal
|
|
391
|
+
*/
|
|
380
392
|
__dynamoDBDecode<M extends DynamoDBModelConstructor<any>>(
|
|
381
393
|
this: M,
|
|
382
394
|
value: unknown
|
|
@@ -391,6 +403,10 @@ export const getProvider = (client: Client) => {
|
|
|
391
403
|
return decoded
|
|
392
404
|
}
|
|
393
405
|
},
|
|
406
|
+
|
|
407
|
+
/**
|
|
408
|
+
* @internal
|
|
409
|
+
*/
|
|
394
410
|
__dynamoDBEncode<
|
|
395
411
|
T extends DynamoDBModelInstance,
|
|
396
412
|
M extends DynamoDBModelConstructor<T>
|
|
@@ -403,6 +419,12 @@ export const getProvider = (client: Client) => {
|
|
|
403
419
|
})
|
|
404
420
|
},
|
|
405
421
|
|
|
422
|
+
/**
|
|
423
|
+
* Retrieves a single item from DynamoDB by its primary key.
|
|
424
|
+
* Prefer `load()` for built-in batching.
|
|
425
|
+
*
|
|
426
|
+
* @throws ItemNotFoundError if the item doesn't exist.
|
|
427
|
+
*/
|
|
406
428
|
get<M extends DynamoDBModelConstructor<any>>(
|
|
407
429
|
this: M,
|
|
408
430
|
key: Key,
|
|
@@ -416,6 +438,12 @@ export const getProvider = (client: Client) => {
|
|
|
416
438
|
})
|
|
417
439
|
},
|
|
418
440
|
|
|
441
|
+
/**
|
|
442
|
+
* Retrieves a single item from DynamoDB by its primary key.
|
|
443
|
+
* Uses built-in batching for usage in e.g. `Promise.all()`.
|
|
444
|
+
*
|
|
445
|
+
* @throws ItemNotFoundError if the item doesn't exist and `null` is not true.
|
|
446
|
+
*/
|
|
419
447
|
load<
|
|
420
448
|
M extends DynamoDBModelConstructor<any>,
|
|
421
449
|
Null extends boolean = false,
|
|
@@ -439,6 +467,10 @@ export const getProvider = (client: Client) => {
|
|
|
439
467
|
)
|
|
440
468
|
},
|
|
441
469
|
|
|
470
|
+
/**
|
|
471
|
+
* Loads multiple items from DynamoDB by their primary keys.
|
|
472
|
+
* Returns an array of items or errors.
|
|
473
|
+
*/
|
|
442
474
|
loadMany<M extends DynamoDBModelConstructor<any>>(
|
|
443
475
|
this: M,
|
|
444
476
|
keys: Key[],
|
|
@@ -454,6 +486,9 @@ export const getProvider = (client: Client) => {
|
|
|
454
486
|
)
|
|
455
487
|
},
|
|
456
488
|
|
|
489
|
+
/**
|
|
490
|
+
* Returns a page of query results using cursor-based pagination.
|
|
491
|
+
*/
|
|
457
492
|
paginate<M extends DynamoDBModelConstructor<any>>(
|
|
458
493
|
this: M,
|
|
459
494
|
args: PaginationInput,
|
|
@@ -462,6 +497,23 @@ export const getProvider = (client: Client) => {
|
|
|
462
497
|
return client.paginate(this, args, params)
|
|
463
498
|
},
|
|
464
499
|
|
|
500
|
+
/**
|
|
501
|
+
* Performs a DynamoDB query operation and returns matching items.
|
|
502
|
+
* Use `FetchAllPages: true` to automatically fetch all pages of results.
|
|
503
|
+
*/
|
|
504
|
+
async query<M extends DynamoDBModelConstructor<any>>(
|
|
505
|
+
this: M,
|
|
506
|
+
params: QueryParams
|
|
507
|
+
) {
|
|
508
|
+
const { items, meta } = await client.query(params, { items: this })
|
|
509
|
+
return Object.assign(items, { meta })
|
|
510
|
+
},
|
|
511
|
+
|
|
512
|
+
/**
|
|
513
|
+
* Stores an item in DynamoDB.
|
|
514
|
+
*
|
|
515
|
+
* @throws KeyExistsError if the item already exists and `IgnoreExistence` is not true.
|
|
516
|
+
*/
|
|
465
517
|
put<M extends DynamoDBModelConstructor<any>>(
|
|
466
518
|
this: M,
|
|
467
519
|
item: TypeOf<M>,
|
|
@@ -478,6 +530,10 @@ export const getProvider = (client: Client) => {
|
|
|
478
530
|
})
|
|
479
531
|
},
|
|
480
532
|
|
|
533
|
+
/**
|
|
534
|
+
* Performs a raw DynamoDB update operation using update expressions.
|
|
535
|
+
* Provides low-level access to DynamoDB's native update functionality.
|
|
536
|
+
*/
|
|
481
537
|
updateRaw<M extends DynamoDBModelConstructor<any>>(
|
|
482
538
|
this: M,
|
|
483
539
|
key: Key,
|
|
@@ -496,6 +552,10 @@ export const getProvider = (client: Client) => {
|
|
|
496
552
|
})
|
|
497
553
|
},
|
|
498
554
|
|
|
555
|
+
/**
|
|
556
|
+
* Deletes an item from DynamoDB by its primary key.
|
|
557
|
+
* The item will be permanently removed from the table.
|
|
558
|
+
*/
|
|
499
559
|
delete<M extends DynamoDBModelConstructor<any>>(this: M, key: Key) {
|
|
500
560
|
return client.delete<M>({
|
|
501
561
|
_model: this,
|
|
@@ -504,6 +564,10 @@ export const getProvider = (client: Client) => {
|
|
|
504
564
|
})
|
|
505
565
|
},
|
|
506
566
|
|
|
567
|
+
/**
|
|
568
|
+
* Performs a soft delete by moving the item to a deleted state.
|
|
569
|
+
* The original item is deleted and a new item with a $$DELETED$$ prefix is created.
|
|
570
|
+
*/
|
|
507
571
|
softDelete<M extends DynamoDBModelConstructor<any>>(
|
|
508
572
|
this: M,
|
|
509
573
|
item: TypeOf<M>
|
|
@@ -512,7 +576,15 @@ export const getProvider = (client: Client) => {
|
|
|
512
576
|
},
|
|
513
577
|
},
|
|
514
578
|
instanceProps: {
|
|
579
|
+
/**
|
|
580
|
+
* The DynamoDB document client instance.
|
|
581
|
+
*/
|
|
515
582
|
dynamodb: client,
|
|
583
|
+
|
|
584
|
+
/**
|
|
585
|
+
* Returns all key attributes for this instance, including primary keys and GSI keys.
|
|
586
|
+
* Used for cursor generation and key-based operations.
|
|
587
|
+
*/
|
|
516
588
|
keys<T extends DynamoDBModelInstance>(
|
|
517
589
|
this: T
|
|
518
590
|
): { PK: string; SK: string } & { [key in GSIPK]?: string } &
|
|
@@ -526,9 +598,19 @@ export const getProvider = (client: Client) => {
|
|
|
526
598
|
})).reduce((acc, cur) => Object.assign(acc, cur), {}),
|
|
527
599
|
}
|
|
528
600
|
},
|
|
601
|
+
|
|
602
|
+
/**
|
|
603
|
+
* Generates an (optionally encrypted) cursor for this instance.
|
|
604
|
+
* Cursors are used for pagination and must be treated as opaque tokens.
|
|
605
|
+
*/
|
|
529
606
|
cursor<T extends DynamoDBModelInstance>(this: T) {
|
|
530
607
|
return encodeDDBCursor(this.keys(), client.cursorEncryptionKey)
|
|
531
608
|
},
|
|
609
|
+
|
|
610
|
+
/**
|
|
611
|
+
* Stores this instance in DynamoDB.
|
|
612
|
+
* @throws KeyExistsError if the item already exists and `IgnoreExistence` is not true.
|
|
613
|
+
*/
|
|
532
614
|
put<T extends DynamoDBModelInstance>(
|
|
533
615
|
this: T,
|
|
534
616
|
params?: Omit<
|
|
@@ -543,6 +625,12 @@ export const getProvider = (client: Client) => {
|
|
|
543
625
|
...params,
|
|
544
626
|
})
|
|
545
627
|
},
|
|
628
|
+
|
|
629
|
+
/**
|
|
630
|
+
* Updates this instance with new attribute values and persists the changes to DynamoDB.
|
|
631
|
+
* Handles version conflicts and automatically manages key changes if primary keys are updated.
|
|
632
|
+
* @throws RaceConditionError if the instance is out of sync with the stored value.
|
|
633
|
+
*/
|
|
546
634
|
async update<T extends DynamoDBModelInstance>(
|
|
547
635
|
this: T,
|
|
548
636
|
attributes: Partial<ModelOf<T>["_codec"]["_A"]>
|
|
@@ -556,8 +644,8 @@ export const getProvider = (client: Client) => {
|
|
|
556
644
|
// Update in place
|
|
557
645
|
try {
|
|
558
646
|
return await client.put(op)
|
|
559
|
-
} catch (error) {
|
|
560
|
-
if (error
|
|
647
|
+
} catch (error: any) {
|
|
648
|
+
if (error?.code === "ConditionalCheckFailedException")
|
|
561
649
|
throw new RaceConditionError(
|
|
562
650
|
"The instance you are attempting to update is out of sync with the stored value."
|
|
563
651
|
)
|
|
@@ -577,6 +665,11 @@ export const getProvider = (client: Client) => {
|
|
|
577
665
|
}
|
|
578
666
|
}
|
|
579
667
|
},
|
|
668
|
+
|
|
669
|
+
/**
|
|
670
|
+
* Applies updates to this instance and returns the updated instance along with the operations to persist.
|
|
671
|
+
* Does not automatically persist the changes - use the returned operations with bulk() or individual operations.
|
|
672
|
+
*/
|
|
580
673
|
applyUpdate<T extends DynamoDBModelInstance>(
|
|
581
674
|
this: T,
|
|
582
675
|
attributes: Partial<ModelOf<T>["_codec"]["_A"]>
|
|
@@ -590,6 +683,11 @@ export const getProvider = (client: Client) => {
|
|
|
590
683
|
|
|
591
684
|
return [updatedItem, op]
|
|
592
685
|
},
|
|
686
|
+
|
|
687
|
+
/**
|
|
688
|
+
* Deletes this instance from DynamoDB.
|
|
689
|
+
* The item will be permanently removed from the table.
|
|
690
|
+
*/
|
|
593
691
|
delete<T extends DynamoDBModelInstance>(this: T): Promise<null> {
|
|
594
692
|
const { PK, SK } = this.keys()
|
|
595
693
|
|
|
@@ -599,14 +697,31 @@ export const getProvider = (client: Client) => {
|
|
|
599
697
|
key: { PK, SK },
|
|
600
698
|
})
|
|
601
699
|
},
|
|
700
|
+
|
|
701
|
+
/**
|
|
702
|
+
* Performs a soft delete on this instance.
|
|
703
|
+
* The original item is deleted and a new item with a $$DELETED$$ prefix is created.
|
|
704
|
+
*/
|
|
602
705
|
softDelete<T extends DynamoDBModelInstance>(this: T) {
|
|
603
706
|
return client.softDelete<T>(this)
|
|
604
707
|
},
|
|
708
|
+
|
|
709
|
+
/**
|
|
710
|
+
* Creates operation objects for this instance for batch processing and transactions.
|
|
711
|
+
* Supports put, update, updateRaw, delete, softDelete, and condition operations.
|
|
712
|
+
*/
|
|
605
713
|
operation: instanceOperation,
|
|
606
714
|
},
|
|
607
715
|
|
|
608
716
|
unionProps: {
|
|
717
|
+
/**
|
|
718
|
+
* The DynamoDB document client instance.
|
|
719
|
+
*/
|
|
609
720
|
dynamodb: client,
|
|
721
|
+
|
|
722
|
+
/**
|
|
723
|
+
* @internal
|
|
724
|
+
*/
|
|
610
725
|
__dynamoDBDecode<M extends DynamoDBUnion>(this: M, value: unknown) {
|
|
611
726
|
const decoded = this.from(value)
|
|
612
727
|
|
|
@@ -618,6 +733,13 @@ export const getProvider = (client: Client) => {
|
|
|
618
733
|
return decoded
|
|
619
734
|
}
|
|
620
735
|
},
|
|
736
|
+
|
|
737
|
+
/**
|
|
738
|
+
* Retrieves a single item from DynamoDB by its primary key.
|
|
739
|
+
* Prefer `load()` for built-in batching.
|
|
740
|
+
*
|
|
741
|
+
* @throws ItemNotFoundError if the item doesn't exist.
|
|
742
|
+
*/
|
|
621
743
|
async get<M extends DynamoDBUnion>(
|
|
622
744
|
this: M,
|
|
623
745
|
key: Key,
|
|
@@ -631,6 +753,12 @@ export const getProvider = (client: Client) => {
|
|
|
631
753
|
})
|
|
632
754
|
},
|
|
633
755
|
|
|
756
|
+
/**
|
|
757
|
+
* Retrieves a single item from DynamoDB by its primary key.
|
|
758
|
+
* Uses built-in batching for usage in e.g. `Promise.all()`.
|
|
759
|
+
*
|
|
760
|
+
* @throws ItemNotFoundError if the item doesn't exist and `null` is not true.
|
|
761
|
+
*/
|
|
634
762
|
load<
|
|
635
763
|
M extends DynamoDBUnion,
|
|
636
764
|
Null extends boolean = false,
|
|
@@ -654,6 +782,10 @@ export const getProvider = (client: Client) => {
|
|
|
654
782
|
)
|
|
655
783
|
},
|
|
656
784
|
|
|
785
|
+
/**
|
|
786
|
+
* Loads multiple items from DynamoDB by their primary keys.
|
|
787
|
+
* Returns an array of items or errors.
|
|
788
|
+
*/
|
|
657
789
|
loadMany<M extends DynamoDBUnion>(
|
|
658
790
|
this: M,
|
|
659
791
|
keys: Key[],
|
|
@@ -669,6 +801,9 @@ export const getProvider = (client: Client) => {
|
|
|
669
801
|
)
|
|
670
802
|
},
|
|
671
803
|
|
|
804
|
+
/**
|
|
805
|
+
* Returns a page of query results using cursor-based pagination.
|
|
806
|
+
*/
|
|
672
807
|
paginate<M extends DynamoDBUnion>(
|
|
673
808
|
this: M,
|
|
674
809
|
args: PaginationInput,
|
|
@@ -676,6 +811,15 @@ export const getProvider = (client: Client) => {
|
|
|
676
811
|
) {
|
|
677
812
|
return client.paginate(this, args, params)
|
|
678
813
|
},
|
|
814
|
+
|
|
815
|
+
/**
|
|
816
|
+
* Performs a DynamoDB query operation and returns matching items.
|
|
817
|
+
* Use `FetchAllPages: true` to automatically fetch all pages of results.
|
|
818
|
+
*/
|
|
819
|
+
async query<M extends DynamoDBUnion>(this: M, params: QueryParams) {
|
|
820
|
+
const { items, meta } = await client.query(params, { items: this })
|
|
821
|
+
return Object.assign(items, { meta })
|
|
822
|
+
},
|
|
679
823
|
},
|
|
680
824
|
}
|
|
681
825
|
}
|
package/src/sandbox.ts
CHANGED
|
@@ -5,29 +5,17 @@ import diff from "snapshot-diff"
|
|
|
5
5
|
import { Client } from "./client"
|
|
6
6
|
import { GSI_NAMES } from "./gsi"
|
|
7
7
|
|
|
8
|
-
/**
|
|
9
|
-
* Returns a random endpoint from the LOCAL_ENDPOINT environment variable.
|
|
10
|
-
*/
|
|
11
|
-
function getEndpoint() {
|
|
12
|
-
if (!process.env.LOCAL_ENDPOINT) throw new Error("LOCAL_ENDPOINT is not set")
|
|
13
|
-
|
|
14
|
-
const endpoints = process.env.LOCAL_ENDPOINT.split(",")
|
|
15
|
-
return endpoints[Math.floor(Math.random() * endpoints.length)]
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
const endpoint = getEndpoint()
|
|
19
|
-
|
|
20
8
|
const ddb = new DynamoDB({
|
|
21
9
|
accessKeyId: "xxx",
|
|
22
10
|
secretAccessKey: "xxx",
|
|
23
|
-
endpoint,
|
|
11
|
+
endpoint: process.env.LOCAL_ENDPOINT,
|
|
24
12
|
region: "local",
|
|
25
13
|
})
|
|
26
14
|
|
|
27
15
|
const docClient = new DynamoDB.DocumentClient({
|
|
28
16
|
accessKeyId: "xxx",
|
|
29
17
|
secretAccessKey: "xxx",
|
|
30
|
-
endpoint,
|
|
18
|
+
endpoint: process.env.LOCAL_ENDPOINT,
|
|
31
19
|
region: "local",
|
|
32
20
|
})
|
|
33
21
|
|