dyna-record 0.1.4 → 0.2.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/README.md +15 -15
- package/dist/src/DynaRecord.d.ts +36 -28
- package/dist/src/DynaRecord.d.ts.map +1 -1
- package/dist/src/DynaRecord.js +39 -36
- package/dist/src/decorators/Table.d.ts.map +1 -1
- package/dist/src/decorators/attributes/BooleanAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/BooleanAttribute.js +1 -2
- package/dist/src/decorators/attributes/DateAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/DateAttribute.js +1 -2
- package/dist/src/decorators/attributes/EnumAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/EnumAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/EnumAttribute.js +2 -3
- package/dist/src/decorators/attributes/ForeignKeyAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/ForeignKeyAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/ForeignKeyAttribute.js +2 -3
- package/dist/src/decorators/attributes/IdAttribute.d.ts +32 -0
- package/dist/src/decorators/attributes/IdAttribute.d.ts.map +1 -0
- package/dist/src/decorators/attributes/IdAttribute.js +41 -0
- package/dist/src/decorators/attributes/NumberAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/NumberAttribute.js +1 -2
- package/dist/src/decorators/attributes/PartitionKeyAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/PartitionKeyAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/PartitionKeyAttribute.js +2 -3
- package/dist/src/decorators/attributes/SortKeyAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/SortKeyAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/SortKeyAttribute.js +2 -3
- package/dist/src/decorators/attributes/StringAttribute.d.ts +1 -1
- package/dist/src/decorators/attributes/StringAttribute.d.ts.map +1 -1
- package/dist/src/decorators/attributes/StringAttribute.js +2 -3
- package/dist/src/decorators/attributes/index.d.ts +1 -0
- package/dist/src/decorators/attributes/index.d.ts.map +1 -1
- package/dist/src/decorators/attributes/index.js +3 -1
- package/dist/src/decorators/attributes/serializers.d.ts +1 -1
- package/dist/src/decorators/relationships/BelongsTo.d.ts +1 -1
- package/dist/src/decorators/relationships/BelongsTo.d.ts.map +1 -1
- package/dist/src/decorators/relationships/BelongsTo.js +2 -3
- package/dist/src/decorators/relationships/HasAndBelongsToMany.d.ts +2 -2
- package/dist/src/decorators/relationships/HasAndBelongsToMany.d.ts.map +1 -1
- package/dist/src/decorators/relationships/HasAndBelongsToMany.js +3 -4
- package/dist/src/decorators/relationships/HasMany.d.ts +2 -2
- package/dist/src/decorators/relationships/HasMany.d.ts.map +1 -1
- package/dist/src/decorators/relationships/HasMany.js +3 -4
- package/dist/src/decorators/relationships/HasOne.d.ts +2 -2
- package/dist/src/decorators/relationships/HasOne.d.ts.map +1 -1
- package/dist/src/decorators/relationships/HasOne.js +3 -4
- package/dist/src/decorators/types.d.ts +2 -2
- package/dist/src/decorators/types.d.ts.map +1 -1
- package/dist/src/dynamo-utils/TransactGetBuilder.d.ts +4 -0
- package/dist/src/dynamo-utils/TransactGetBuilder.d.ts.map +1 -1
- package/dist/src/dynamo-utils/TransactGetBuilder.js +6 -0
- package/dist/src/metadata/EntityMetadata.d.ts +17 -1
- package/dist/src/metadata/EntityMetadata.d.ts.map +1 -1
- package/dist/src/metadata/EntityMetadata.js +25 -0
- package/dist/src/metadata/MetadataStorage.d.ts +6 -0
- package/dist/src/metadata/MetadataStorage.d.ts.map +1 -1
- package/dist/src/metadata/MetadataStorage.js +9 -0
- package/dist/src/metadata/TableMetadata.d.ts.map +1 -1
- package/dist/src/metadata/TableMetadata.js +2 -6
- package/dist/src/metadata/relationship-metadata/types.d.ts +4 -0
- package/dist/src/metadata/relationship-metadata/types.d.ts.map +1 -1
- package/dist/src/metadata/types.d.ts +2 -3
- package/dist/src/metadata/types.d.ts.map +1 -1
- package/dist/src/metadata/utils.d.ts.map +1 -1
- package/dist/src/operations/Create/Create.d.ts +95 -16
- package/dist/src/operations/Create/Create.d.ts.map +1 -1
- package/dist/src/operations/Create/Create.js +180 -29
- package/dist/src/operations/Delete/Delete.d.ts +29 -25
- package/dist/src/operations/Delete/Delete.d.ts.map +1 -1
- package/dist/src/operations/Delete/Delete.js +105 -104
- package/dist/src/operations/Delete/types.d.ts +0 -3
- package/dist/src/operations/Delete/types.d.ts.map +1 -1
- package/dist/src/operations/FindById/FindById.d.ts +7 -28
- package/dist/src/operations/FindById/FindById.d.ts.map +1 -1
- package/dist/src/operations/FindById/FindById.js +36 -125
- package/dist/src/operations/FindById/types.d.ts +8 -9
- package/dist/src/operations/FindById/types.d.ts.map +1 -1
- package/dist/src/operations/Query/Query.d.ts +2 -1
- package/dist/src/operations/Query/Query.d.ts.map +1 -1
- package/dist/src/operations/Query/Query.js +17 -4
- package/dist/src/operations/Query/types.d.ts +39 -5
- package/dist/src/operations/Query/types.d.ts.map +1 -1
- package/dist/src/operations/Update/Update.d.ts +185 -24
- package/dist/src/operations/Update/Update.d.ts.map +1 -1
- package/dist/src/operations/Update/Update.js +402 -72
- package/dist/src/operations/Update/UpdateDryRun.d.ts +10 -0
- package/dist/src/operations/Update/UpdateDryRun.d.ts.map +1 -0
- package/dist/src/operations/Update/UpdateDryRun.js +15 -0
- package/dist/src/operations/Update/index.d.ts +1 -0
- package/dist/src/operations/Update/index.d.ts.map +1 -1
- package/dist/src/operations/Update/index.js +3 -1
- package/dist/src/operations/types.d.ts +6 -1
- package/dist/src/operations/types.d.ts.map +1 -1
- package/dist/src/operations/utils/expressionBuilder.d.ts.map +1 -1
- package/dist/src/operations/utils/expressionBuilder.js +1 -4
- package/dist/src/operations/utils/index.d.ts +0 -1
- package/dist/src/operations/utils/index.d.ts.map +1 -1
- package/dist/src/operations/utils/index.js +0 -6
- package/dist/src/operations/utils/utils.d.ts +13 -3
- package/dist/src/operations/utils/utils.d.ts.map +1 -1
- package/dist/src/operations/utils/utils.js +33 -3
- package/dist/src/query-utils/Filters.d.ts +1 -1
- package/dist/src/query-utils/Filters.d.ts.map +1 -1
- package/dist/src/query-utils/Filters.js +7 -15
- package/dist/src/query-utils/QueryBuilder.d.ts.map +1 -1
- package/dist/src/query-utils/QueryBuilder.js +9 -1
- package/dist/src/relationships/JoinTable.d.ts +17 -7
- package/dist/src/relationships/JoinTable.d.ts.map +1 -1
- package/dist/src/relationships/JoinTable.js +77 -20
- package/dist/src/relationships/index.d.ts +0 -1
- package/dist/src/relationships/index.d.ts.map +1 -1
- package/dist/src/relationships/index.js +1 -3
- package/dist/src/types.d.ts +6 -8
- package/dist/src/types.d.ts.map +1 -1
- package/dist/src/utils.d.ts +10 -32
- package/dist/src/utils.d.ts.map +1 -1
- package/dist/src/utils.js +13 -59
- package/package.json +4 -4
- package/dist/src/operations/utils/RelationshipTransactions.d.ts +0 -64
- package/dist/src/operations/utils/RelationshipTransactions.d.ts.map +0 -1
- package/dist/src/operations/utils/RelationshipTransactions.js +0 -125
- package/dist/src/relationships/BelongsToLink.d.ts +0 -51
- package/dist/src/relationships/BelongsToLink.d.ts.map +0 -1
- package/dist/src/relationships/BelongsToLink.js +0 -57
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metadata/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,+BAA+B,EAChC,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAC3B,oBAAoB
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../../../src/metadata/utils.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EACV,oBAAoB,EACpB,mBAAmB,EACnB,qBAAqB,EACrB,kBAAkB,EAClB,+BAA+B,EAChC,MAAM,GAAG,CAAC;AACX,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,KAAK,EAAE,kCAAkC,EAAE,MAAM,SAAS,CAAC;AAClE,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,UAAU,CAAC;AAE5C;;GAEG;AACH,eAAO,MAAM,qBAAqB,QAC3B,oBAAoB,KACxB,GAAG,IAAI,mBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,uBAAuB,QAC7B,oBAAoB,KACxB,GAAG,IAAI,qBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,oBAAoB,QAC1B,oBAAoB,KACxB,GAAG,IAAI,kBAET,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iCAAiC,QACvC,oBAAoB,KACxB,GAAG,IAAI,+BAET,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,oCAAoC,QAC1C,oBAAoB,KACxB,GAAG,IAAI,kCAET,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,6BAA6B,GAAI,CAAC,SAAS,UAAU,UACxD,WAAW,CAAC,CAAC,CAAC,OACjB,qBAAqB,KACzB,OAMF,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,8BAA8B,GAAI,CAAC,SAAS,UAAU,UACzD,WAAW,CAAC,CAAC,CAAC,OACjB,qBAAqB,KACzB,OAMF,CAAC"}
|
|
@@ -2,13 +2,22 @@ import type DynaRecord from "../../DynaRecord";
|
|
|
2
2
|
import type { EntityClass } from "../../types";
|
|
3
3
|
import OperationBase from "../OperationBase";
|
|
4
4
|
import type { CreateOptions } from "./types";
|
|
5
|
-
import { type
|
|
5
|
+
import { type EntityAttributesOnly } from "../types";
|
|
6
6
|
/**
|
|
7
|
-
* Represents
|
|
7
|
+
* Represents an operation to create a new entity record in DynamoDB, including all necessary
|
|
8
|
+
* denormalized relationship records. This ensures that "BelongsTo" and "HasMany" relationships
|
|
9
|
+
* are properly maintained at the time of entity creation.
|
|
8
10
|
*
|
|
9
|
-
*
|
|
11
|
+
* **What it does:**
|
|
12
|
+
* - Converts the given attributes into a DynamoDB-compatible format.
|
|
13
|
+
* - Inserts a new entity record, ensuring no duplicate primary key conflicts.
|
|
14
|
+
* - For each "BelongsTo" relationship that includes a foreign key:
|
|
15
|
+
* - Verifies the referenced entity exists.
|
|
16
|
+
* - Creates a denormalized link record in the related entity's partition.
|
|
17
|
+
* - If the entity's relationships imply additional denormalized records in its own partition,
|
|
18
|
+
* those are also created after verifying the related entities exist.
|
|
10
19
|
*
|
|
11
|
-
* Only attributes defined on the model can be
|
|
20
|
+
* Only attributes defined on the entity model can be set, validated both at compile-time and runtime.
|
|
12
21
|
*
|
|
13
22
|
* @template T - The type of the entity being created, extending `DynaRecord`.
|
|
14
23
|
*/
|
|
@@ -16,27 +25,97 @@ declare class Create<T extends DynaRecord> extends OperationBase<T> {
|
|
|
16
25
|
#private;
|
|
17
26
|
constructor(Entity: EntityClass<T>);
|
|
18
27
|
/**
|
|
19
|
-
*
|
|
20
|
-
*
|
|
21
|
-
*
|
|
28
|
+
* Executes the create operation.
|
|
29
|
+
*
|
|
30
|
+
* **What it does:**
|
|
31
|
+
* - Parses and validates the provided attributes against the entity schema.
|
|
32
|
+
* - Generates any required reserved attributes (like `id`, `createdAt`, and `updatedAt`).
|
|
33
|
+
* - Inserts the new entity record into DynamoDB, ensuring it doesn't already exist.
|
|
34
|
+
* - For each defined "BelongsTo" relationship, ensures the related entity exists and creates
|
|
35
|
+
* a corresponding denormalized "link" record.
|
|
36
|
+
* - If the entity's creation implies that related records must also be denormalized into its own
|
|
37
|
+
* partition (due to "BelongsTo" links), retrieves and inserts those link records.
|
|
38
|
+
*
|
|
39
|
+
* @param attributes - Attributes to initialize the new entity. Must be defined on the model and valid per schema constraints.
|
|
40
|
+
* @returns A promise that resolves to the newly created entity with all attributes, including automatically set fields.
|
|
41
|
+
* @throws If the entity already exists, a uniqueness violation error is raised.
|
|
42
|
+
* @throws If a required foreign key does not correspond to an existing entity, an error is raised.
|
|
22
43
|
*/
|
|
23
|
-
run(attributes: CreateOptions<T>): Promise<
|
|
44
|
+
run(attributes: CreateOptions<T>): Promise<EntityAttributesOnly<T>>;
|
|
24
45
|
/**
|
|
25
|
-
* Builds
|
|
26
|
-
*
|
|
27
|
-
*
|
|
46
|
+
* Builds and returns entity attributes that must be reserved for system usage.
|
|
47
|
+
*
|
|
48
|
+
* **What it does:**
|
|
49
|
+
* - Generates a unique entity ID if the entity's schema does not specify an `id` field.
|
|
50
|
+
* - Sets `createdAt` and `updatedAt` to the current time.
|
|
51
|
+
* - Builds the partition and sort key values based on the entity's class and generated ID.
|
|
52
|
+
*
|
|
53
|
+
* @param entityAttrs - The user-provided entity attributes.
|
|
54
|
+
* @returns The combined attributes including all reserved fields.
|
|
55
|
+
* @private
|
|
28
56
|
*/
|
|
29
57
|
private buildReservedAttributes;
|
|
30
58
|
/**
|
|
31
|
-
*
|
|
32
|
-
*
|
|
59
|
+
* Adds a "PutItem" transaction for the new entity record.
|
|
60
|
+
*
|
|
61
|
+
* **What it does:**
|
|
62
|
+
* - Ensures the primary key does not already exist, preventing duplication.
|
|
63
|
+
*
|
|
64
|
+
* @param tableItem - The DynamoDB table item for the entity to put.
|
|
65
|
+
* @param id - The unique identifier of the new entity.
|
|
66
|
+
* @private
|
|
33
67
|
*/
|
|
34
68
|
private buildPutItemTransaction;
|
|
35
69
|
/**
|
|
36
|
-
*
|
|
37
|
-
*
|
|
70
|
+
* Adds "PutItem" transactions to create denormalized "BelongsTo" link records in the related entity's partitions.
|
|
71
|
+
*
|
|
72
|
+
* **What it does:**
|
|
73
|
+
* - For each "BelongsTo" relationship with a defined foreign key, checks that the related entity exists.
|
|
74
|
+
* - Inserts a "link" item into the related entity's partition to maintain denormalized relationships.
|
|
75
|
+
*
|
|
76
|
+
* @param entityData - The complete set of entity attributes for the new entity.
|
|
77
|
+
* @param tableItem - The main entity's DynamoDB table item.
|
|
78
|
+
* @private
|
|
38
79
|
*/
|
|
39
|
-
private
|
|
80
|
+
private buildBelongsToTransactions;
|
|
81
|
+
/**
|
|
82
|
+
* Retrieves the DynamoDB items for all entities that the new entity references via "BelongsTo" relationships.
|
|
83
|
+
*
|
|
84
|
+
* **What it does:**
|
|
85
|
+
* - For each "BelongsTo" relationship, queries DynamoDB for the related entity record.
|
|
86
|
+
* - Returns all found related items as an array.
|
|
87
|
+
* - If no relationships or no foreign keys are present, returns an empty array.
|
|
88
|
+
*
|
|
89
|
+
* @param entityData - The attributes of the entity being created.
|
|
90
|
+
* @returns A promise that resolves to an array of related DynamoDB items.
|
|
91
|
+
* @private
|
|
92
|
+
*/
|
|
93
|
+
private getBelongsToTableItems;
|
|
94
|
+
/**
|
|
95
|
+
* Adds a condition check transaction to ensure that the entity referenced by a "BelongsTo" foreign key exists.
|
|
96
|
+
*
|
|
97
|
+
* **What it does:**
|
|
98
|
+
* - Checks the existence of the related entity before creating the link item.
|
|
99
|
+
* - If the related entity does not exist, the transaction will fail, preventing creation of dangling references.
|
|
100
|
+
*
|
|
101
|
+
* @param rel - The "BelongsTo" relationship metadata.
|
|
102
|
+
* @param relationshipId - The foreign key value referencing the related entity.
|
|
103
|
+
* @private
|
|
104
|
+
*/
|
|
105
|
+
private buildRelationshipExistsConditionTransaction;
|
|
106
|
+
/**
|
|
107
|
+
* For each related entity referenced by a "BelongsTo" relationship, insert a denormalized copy of that entity
|
|
108
|
+
* into the new entity's partition. This maintains a consistent, denormalized view of relationships.
|
|
109
|
+
*
|
|
110
|
+
* **What it does:**
|
|
111
|
+
* - Adds "PutItem" operations to create link records in the newly created entity's partition.
|
|
112
|
+
* - Ensures these link records don't already exist.
|
|
113
|
+
*
|
|
114
|
+
* @param entityId - The newly created entity's ID.
|
|
115
|
+
* @param belongsToTableItems - The table items representing each related "BelongsTo" entity.
|
|
116
|
+
* @private
|
|
117
|
+
*/
|
|
118
|
+
private buildAddBelongsToLinkToSelfTransactions;
|
|
40
119
|
}
|
|
41
120
|
export default Create;
|
|
42
121
|
//# sourceMappingURL=Create.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Create.d.ts","sourceRoot":"","sources":["../../../../src/operations/Create/Create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;
|
|
1
|
+
{"version":3,"file":"Create.d.ts","sourceRoot":"","sources":["../../../../src/operations/Create/Create.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAE/C,OAAO,KAAK,EAAmB,WAAW,EAAE,MAAM,aAAa,CAAC;AAOhE,OAAO,aAAa,MAAM,kBAAkB,CAAC;AAE7C,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,SAAS,CAAC;AAC7C,OAAO,EAGL,KAAK,oBAAoB,EAC1B,MAAM,UAAU,CAAC;AAIlB;;;;;;;;;;;;;;;;;GAiBG;AACH,cAAM,MAAM,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;;gBAG7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAKlC;;;;;;;;;;;;;;;;OAgBG;IACU,GAAG,CACd,UAAU,EAAE,aAAa,CAAC,CAAC,CAAC,GAC3B,OAAO,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC;IA4BnC;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uBAAuB;IA8B/B;;;;;;;;;OASG;IACH,OAAO,CAAC,uBAAuB;IAiB/B;;;;;;;;;;OAUG;IACH,OAAO,CAAC,0BAA0B;IAgClC;;;;;;;;;;;OAWG;YACW,sBAAsB;IAmCpC;;;;;;;;;;OAUG;IACH,OAAO,CAAC,2CAA2C;IAmBnD;;;;;;;;;;;OAWG;IACH,OAAO,CAAC,uCAAuC;CA0BhD;AAED,eAAe,MAAM,CAAC"}
|
|
@@ -8,13 +8,22 @@ const dynamo_utils_1 = require("../../dynamo-utils");
|
|
|
8
8
|
const utils_1 = require("../../utils");
|
|
9
9
|
const OperationBase_1 = __importDefault(require("../OperationBase"));
|
|
10
10
|
const utils_2 = require("../utils");
|
|
11
|
-
const
|
|
11
|
+
const utils_3 = require("../../metadata/utils");
|
|
12
12
|
/**
|
|
13
|
-
* Represents
|
|
13
|
+
* Represents an operation to create a new entity record in DynamoDB, including all necessary
|
|
14
|
+
* denormalized relationship records. This ensures that "BelongsTo" and "HasMany" relationships
|
|
15
|
+
* are properly maintained at the time of entity creation.
|
|
14
16
|
*
|
|
15
|
-
*
|
|
17
|
+
* **What it does:**
|
|
18
|
+
* - Converts the given attributes into a DynamoDB-compatible format.
|
|
19
|
+
* - Inserts a new entity record, ensuring no duplicate primary key conflicts.
|
|
20
|
+
* - For each "BelongsTo" relationship that includes a foreign key:
|
|
21
|
+
* - Verifies the referenced entity exists.
|
|
22
|
+
* - Creates a denormalized link record in the related entity's partition.
|
|
23
|
+
* - If the entity's relationships imply additional denormalized records in its own partition,
|
|
24
|
+
* those are also created after verifying the related entities exist.
|
|
16
25
|
*
|
|
17
|
-
* Only attributes defined on the model can be
|
|
26
|
+
* Only attributes defined on the entity model can be set, validated both at compile-time and runtime.
|
|
18
27
|
*
|
|
19
28
|
* @template T - The type of the entity being created, extending `DynaRecord`.
|
|
20
29
|
*/
|
|
@@ -25,28 +34,55 @@ class Create extends OperationBase_1.default {
|
|
|
25
34
|
this.#transactionBuilder = new dynamo_utils_1.TransactWriteBuilder();
|
|
26
35
|
}
|
|
27
36
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
37
|
+
* Executes the create operation.
|
|
38
|
+
*
|
|
39
|
+
* **What it does:**
|
|
40
|
+
* - Parses and validates the provided attributes against the entity schema.
|
|
41
|
+
* - Generates any required reserved attributes (like `id`, `createdAt`, and `updatedAt`).
|
|
42
|
+
* - Inserts the new entity record into DynamoDB, ensuring it doesn't already exist.
|
|
43
|
+
* - For each defined "BelongsTo" relationship, ensures the related entity exists and creates
|
|
44
|
+
* a corresponding denormalized "link" record.
|
|
45
|
+
* - If the entity's creation implies that related records must also be denormalized into its own
|
|
46
|
+
* partition (due to "BelongsTo" links), retrieves and inserts those link records.
|
|
47
|
+
*
|
|
48
|
+
* @param attributes - Attributes to initialize the new entity. Must be defined on the model and valid per schema constraints.
|
|
49
|
+
* @returns A promise that resolves to the newly created entity with all attributes, including automatically set fields.
|
|
50
|
+
* @throws If the entity already exists, a uniqueness violation error is raised.
|
|
51
|
+
* @throws If a required foreign key does not correspond to an existing entity, an error is raised.
|
|
31
52
|
*/
|
|
32
53
|
async run(attributes) {
|
|
33
|
-
const
|
|
34
|
-
const
|
|
35
|
-
const reservedAttrs = this.buildReservedAttributes();
|
|
54
|
+
const entityAttrs = this.entityMetadata.parseRawEntityDefinedAttributes(attributes);
|
|
55
|
+
const reservedAttrs = this.buildReservedAttributes(entityAttrs);
|
|
36
56
|
const entityData = { ...reservedAttrs, ...entityAttrs };
|
|
37
57
|
const tableItem = (0, utils_1.entityToTableItem)(this.EntityClass, entityData);
|
|
38
|
-
this.buildPutItemTransaction(tableItem);
|
|
39
|
-
|
|
58
|
+
this.buildPutItemTransaction(tableItem, entityData.id);
|
|
59
|
+
this.buildBelongsToTransactions(entityData, tableItem);
|
|
60
|
+
// Attempt to fetch all belongs-to entities to properly create reverse denormalization links
|
|
61
|
+
const belongsToTableItems = await this.getBelongsToTableItems(entityData);
|
|
62
|
+
// If there are any belongs-to relationships, add the inverse link records into the new entity's partition
|
|
63
|
+
if (belongsToTableItems.length > 0) {
|
|
64
|
+
this.buildAddBelongsToLinkToSelfTransactions(reservedAttrs.id, belongsToTableItems);
|
|
65
|
+
}
|
|
40
66
|
await this.#transactionBuilder.executeTransaction();
|
|
41
67
|
return (0, utils_1.tableItemToEntity)(this.EntityClass, tableItem);
|
|
42
68
|
}
|
|
43
69
|
/**
|
|
44
|
-
* Builds
|
|
45
|
-
*
|
|
46
|
-
*
|
|
70
|
+
* Builds and returns entity attributes that must be reserved for system usage.
|
|
71
|
+
*
|
|
72
|
+
* **What it does:**
|
|
73
|
+
* - Generates a unique entity ID if the entity's schema does not specify an `id` field.
|
|
74
|
+
* - Sets `createdAt` and `updatedAt` to the current time.
|
|
75
|
+
* - Builds the partition and sort key values based on the entity's class and generated ID.
|
|
76
|
+
*
|
|
77
|
+
* @param entityAttrs - The user-provided entity attributes.
|
|
78
|
+
* @returns The combined attributes including all reserved fields.
|
|
79
|
+
* @private
|
|
47
80
|
*/
|
|
48
|
-
buildReservedAttributes() {
|
|
49
|
-
const
|
|
81
|
+
buildReservedAttributes(entityAttrs) {
|
|
82
|
+
const { idField } = this.entityMetadata;
|
|
83
|
+
const id = idField === undefined
|
|
84
|
+
? (0, uuid_1.v4)()
|
|
85
|
+
: entityAttrs[idField];
|
|
50
86
|
const createdAt = new Date();
|
|
51
87
|
const pk = this.tableMetadata.partitionKeyAttribute.name;
|
|
52
88
|
const sk = this.tableMetadata.sortKeyAttribute.name;
|
|
@@ -63,28 +99,143 @@ class Create extends OperationBase_1.default {
|
|
|
63
99
|
return { ...keys, ...defaultAttrs };
|
|
64
100
|
}
|
|
65
101
|
/**
|
|
66
|
-
*
|
|
67
|
-
*
|
|
102
|
+
* Adds a "PutItem" transaction for the new entity record.
|
|
103
|
+
*
|
|
104
|
+
* **What it does:**
|
|
105
|
+
* - Ensures the primary key does not already exist, preventing duplication.
|
|
106
|
+
*
|
|
107
|
+
* @param tableItem - The DynamoDB table item for the entity to put.
|
|
108
|
+
* @param id - The unique identifier of the new entity.
|
|
109
|
+
* @private
|
|
68
110
|
*/
|
|
69
|
-
buildPutItemTransaction(tableItem) {
|
|
111
|
+
buildPutItemTransaction(tableItem, id) {
|
|
70
112
|
const { name: tableName } = this.tableMetadata;
|
|
71
113
|
const putExpression = {
|
|
72
114
|
TableName: tableName,
|
|
73
115
|
Item: tableItem,
|
|
74
|
-
ConditionExpression: `attribute_not_exists(${this.partitionKeyAlias})`
|
|
116
|
+
ConditionExpression: `attribute_not_exists(${this.partitionKeyAlias})`
|
|
75
117
|
};
|
|
76
|
-
this.#transactionBuilder.addPut(putExpression);
|
|
118
|
+
this.#transactionBuilder.addPut(putExpression, `${this.EntityClass.name} with id: ${id} already exists`);
|
|
77
119
|
}
|
|
78
120
|
/**
|
|
79
|
-
*
|
|
80
|
-
*
|
|
121
|
+
* Adds "PutItem" transactions to create denormalized "BelongsTo" link records in the related entity's partitions.
|
|
122
|
+
*
|
|
123
|
+
* **What it does:**
|
|
124
|
+
* - For each "BelongsTo" relationship with a defined foreign key, checks that the related entity exists.
|
|
125
|
+
* - Inserts a "link" item into the related entity's partition to maintain denormalized relationships.
|
|
126
|
+
*
|
|
127
|
+
* @param entityData - The complete set of entity attributes for the new entity.
|
|
128
|
+
* @param tableItem - The main entity's DynamoDB table item.
|
|
129
|
+
* @private
|
|
81
130
|
*/
|
|
82
|
-
|
|
83
|
-
const
|
|
84
|
-
|
|
85
|
-
|
|
131
|
+
buildBelongsToTransactions(entityData, tableItem) {
|
|
132
|
+
const tableName = this.tableMetadata.name;
|
|
133
|
+
for (const relMeta of this.entityMetadata.belongsToRelationships) {
|
|
134
|
+
const foreignKey = (0, utils_2.extractForeignKeyFromEntity)(relMeta, entityData);
|
|
135
|
+
if (foreignKey !== undefined) {
|
|
136
|
+
// Ensure referenced entity exists before linking
|
|
137
|
+
this.buildRelationshipExistsConditionTransaction(relMeta, foreignKey);
|
|
138
|
+
const key = (0, utils_2.buildBelongsToLinkKey)(this.EntityClass, entityData.id, relMeta, foreignKey);
|
|
139
|
+
this.#transactionBuilder.addPut({
|
|
140
|
+
TableName: tableName,
|
|
141
|
+
Item: { ...tableItem, ...key },
|
|
142
|
+
ConditionExpression: `attribute_not_exists(${this.partitionKeyAlias})`
|
|
143
|
+
}, `${relMeta.target.name} with id: ${foreignKey} already has an associated ${this.EntityClass.name}`);
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
/**
|
|
148
|
+
* Retrieves the DynamoDB items for all entities that the new entity references via "BelongsTo" relationships.
|
|
149
|
+
*
|
|
150
|
+
* **What it does:**
|
|
151
|
+
* - For each "BelongsTo" relationship, queries DynamoDB for the related entity record.
|
|
152
|
+
* - Returns all found related items as an array.
|
|
153
|
+
* - If no relationships or no foreign keys are present, returns an empty array.
|
|
154
|
+
*
|
|
155
|
+
* @param entityData - The attributes of the entity being created.
|
|
156
|
+
* @returns A promise that resolves to an array of related DynamoDB items.
|
|
157
|
+
* @private
|
|
158
|
+
*/
|
|
159
|
+
async getBelongsToTableItems(entityData) {
|
|
160
|
+
const { name: tableName } = this.tableMetadata;
|
|
161
|
+
const transactionBuilder = new dynamo_utils_1.TransactGetBuilder();
|
|
162
|
+
const relMetas = this.entityMetadata.relationships;
|
|
163
|
+
const belongsToRelMetas = Object.values(relMetas).filter(relMeta => (0, utils_3.isBelongsToRelationship)(relMeta));
|
|
164
|
+
belongsToRelMetas.forEach(relMeta => {
|
|
165
|
+
const fk = (0, utils_2.extractForeignKeyFromEntity)(relMeta, entityData);
|
|
166
|
+
if (fk !== undefined) {
|
|
167
|
+
transactionBuilder.addGet({
|
|
168
|
+
TableName: tableName,
|
|
169
|
+
Key: {
|
|
170
|
+
[this.partitionKeyAlias]: relMeta.target.partitionKeyValue(fk),
|
|
171
|
+
[this.sortKeyAlias]: relMeta.target.name
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
}
|
|
175
|
+
});
|
|
176
|
+
if (transactionBuilder.hasTransactions()) {
|
|
177
|
+
const results = await transactionBuilder.executeTransaction();
|
|
178
|
+
return results.reduce((acc, res) => {
|
|
179
|
+
if (res.Item !== undefined)
|
|
180
|
+
acc.push(res.Item);
|
|
181
|
+
return acc;
|
|
182
|
+
}, []);
|
|
183
|
+
}
|
|
184
|
+
return [];
|
|
185
|
+
}
|
|
186
|
+
/**
|
|
187
|
+
* Adds a condition check transaction to ensure that the entity referenced by a "BelongsTo" foreign key exists.
|
|
188
|
+
*
|
|
189
|
+
* **What it does:**
|
|
190
|
+
* - Checks the existence of the related entity before creating the link item.
|
|
191
|
+
* - If the related entity does not exist, the transaction will fail, preventing creation of dangling references.
|
|
192
|
+
*
|
|
193
|
+
* @param rel - The "BelongsTo" relationship metadata.
|
|
194
|
+
* @param relationshipId - The foreign key value referencing the related entity.
|
|
195
|
+
* @private
|
|
196
|
+
*/
|
|
197
|
+
buildRelationshipExistsConditionTransaction(rel, relationshipId) {
|
|
198
|
+
const { name: tableName } = this.tableMetadata;
|
|
199
|
+
const errMsg = `${rel.target.name} with ID '${relationshipId}' does not exist`;
|
|
200
|
+
const conditionCheck = {
|
|
201
|
+
TableName: tableName,
|
|
202
|
+
Key: {
|
|
203
|
+
[this.partitionKeyAlias]: rel.target.partitionKeyValue(relationshipId),
|
|
204
|
+
[this.sortKeyAlias]: rel.target.name
|
|
205
|
+
},
|
|
206
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`
|
|
207
|
+
};
|
|
208
|
+
this.#transactionBuilder.addConditionCheck(conditionCheck, errMsg);
|
|
209
|
+
}
|
|
210
|
+
/**
|
|
211
|
+
* For each related entity referenced by a "BelongsTo" relationship, insert a denormalized copy of that entity
|
|
212
|
+
* into the new entity's partition. This maintains a consistent, denormalized view of relationships.
|
|
213
|
+
*
|
|
214
|
+
* **What it does:**
|
|
215
|
+
* - Adds "PutItem" operations to create link records in the newly created entity's partition.
|
|
216
|
+
* - Ensures these link records don't already exist.
|
|
217
|
+
*
|
|
218
|
+
* @param entityId - The newly created entity's ID.
|
|
219
|
+
* @param belongsToTableItems - The table items representing each related "BelongsTo" entity.
|
|
220
|
+
* @private
|
|
221
|
+
*/
|
|
222
|
+
buildAddBelongsToLinkToSelfTransactions(entityId, belongsToTableItems) {
|
|
223
|
+
const pk = this.EntityClass.partitionKeyValue(entityId);
|
|
224
|
+
const typeAlias = this.tableMetadata.defaultAttributes.type.alias;
|
|
225
|
+
belongsToTableItems.forEach(tableItem => {
|
|
226
|
+
const relationshipType = tableItem[typeAlias];
|
|
227
|
+
const key = {
|
|
228
|
+
[this.partitionKeyAlias]: pk,
|
|
229
|
+
[this.sortKeyAlias]: relationshipType
|
|
230
|
+
};
|
|
231
|
+
this.#transactionBuilder.addPut({
|
|
232
|
+
TableName: this.tableMetadata.name,
|
|
233
|
+
Item: { ...tableItem, ...key },
|
|
234
|
+
ConditionExpression: `attribute_not_exists(${this.partitionKeyAlias})`
|
|
235
|
+
},
|
|
236
|
+
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
237
|
+
`${this.EntityClass.name} already has an associated ${relationshipType}`);
|
|
86
238
|
});
|
|
87
|
-
await relationshipTransactions.build(entityData);
|
|
88
239
|
}
|
|
89
240
|
}
|
|
90
241
|
exports.default = Create;
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import DynaRecord from "../../DynaRecord";
|
|
1
|
+
import type DynaRecord from "../../DynaRecord";
|
|
2
2
|
import type { EntityClass } from "../../types";
|
|
3
3
|
import OperationBase from "../OperationBase";
|
|
4
4
|
/**
|
|
5
5
|
* Implements the operation for deleting an entity and its related data from the database within the ORM framework.
|
|
6
6
|
*
|
|
7
|
-
* Delete an entity, everything in its partition,
|
|
7
|
+
* Delete an entity, everything in its partition, denormalized records and nullifies ForeignKeys on attributes that BelongTo it
|
|
8
8
|
* If the foreign key is non nullable than it will throw a NullConstraintViolationError
|
|
9
9
|
*
|
|
10
10
|
* The `Delete` operation supports complex scenarios, such as deleting related entities in "BelongsTo" relationships, nullifying or removing foreign keys to maintain data integrity, and handling many-to-many relationships through join tables.
|
|
@@ -18,21 +18,38 @@ declare class Delete<T extends DynaRecord> extends OperationBase<T> {
|
|
|
18
18
|
* Delete an item by id
|
|
19
19
|
* - Deletes the given entity
|
|
20
20
|
* - Deletes each item in the entity's partition
|
|
21
|
-
* - For each item in the entity's partition which is
|
|
21
|
+
* - For each item in the entity's partition which is a denormalized record it:
|
|
22
22
|
* - Will nullify the associated relationship's ForeignKey attribute if the attribute is nullable
|
|
23
23
|
* @param id
|
|
24
24
|
*/
|
|
25
25
|
run(id: string): Promise<void>;
|
|
26
26
|
/**
|
|
27
|
-
*
|
|
28
|
-
* @param
|
|
27
|
+
* Prefetch the item being deleted including items in its partition from denormalized associated records
|
|
28
|
+
* @param id
|
|
29
|
+
* @returns - The item and its associated links denormalized
|
|
30
|
+
*/
|
|
31
|
+
private preFetch;
|
|
32
|
+
/**
|
|
33
|
+
* Returns true if the linked entity needs to have a foreign key nullified
|
|
34
|
+
* @param relMeta
|
|
35
|
+
* @returns
|
|
36
|
+
*/
|
|
37
|
+
private doesEntityNeedForeignKeyNullified;
|
|
38
|
+
/**
|
|
39
|
+
* Delete the entity and denormalized links from BelongsTo relationships
|
|
40
|
+
* @param self
|
|
41
|
+
*/
|
|
42
|
+
private buildDeleteSelfTransactions;
|
|
43
|
+
/**
|
|
44
|
+
* Deletes an item when given the table keys
|
|
45
|
+
* @param keys - The key to delete representing the table keys, as opposed to the entities keys
|
|
29
46
|
*/
|
|
30
47
|
private buildDeleteItemTransaction;
|
|
31
48
|
/**
|
|
32
|
-
*
|
|
33
|
-
* @param
|
|
49
|
+
* Deletes an item when given the keys of the entity. Converts the keys to the table alias
|
|
50
|
+
* @param keys - The key to delete representing the entity keys, as opposed to the table keys
|
|
34
51
|
*/
|
|
35
|
-
private
|
|
52
|
+
private buildDeleteEntityTransaction;
|
|
36
53
|
/**
|
|
37
54
|
* If the item being deleted has a foreign key reference, nullify the associated relationship's ForeignKey attribute
|
|
38
55
|
* If the ForeignKey is non nullable than it throws a NullConstraintViolationError
|
|
@@ -46,29 +63,16 @@ declare class Delete<T extends DynaRecord> extends OperationBase<T> {
|
|
|
46
63
|
*/
|
|
47
64
|
private buildDeleteAssociatedBelongsTransaction;
|
|
48
65
|
/**
|
|
49
|
-
*
|
|
50
|
-
* @param
|
|
51
|
-
* @param entityId
|
|
52
|
-
* @param foreignKeyValue
|
|
53
|
-
*/
|
|
54
|
-
private buildDeleteBelongsToHasManyTransaction;
|
|
55
|
-
/**
|
|
56
|
-
* Deletes associated BelongsToLink for a BelongsTo HasOne relationship
|
|
57
|
-
* @param relMeta
|
|
58
|
-
* @param foreignKeyValue
|
|
59
|
-
*/
|
|
60
|
-
private buildDeleteBelongsToHasOneTransaction;
|
|
61
|
-
/**
|
|
62
|
-
* Type guard to check if the item being evaluated is the currentClass
|
|
63
|
-
* @param item
|
|
64
|
-
* @returns
|
|
66
|
+
* If the item has a JoinTable entry (is part of HasAndBelongsToMany relationship) then delete both JoinTable entries
|
|
67
|
+
* @param item - Denormalized record from HasAndBelongsToMany relationship
|
|
65
68
|
*/
|
|
66
|
-
private
|
|
69
|
+
private buildDeleteJoinTableLinkTransaction;
|
|
67
70
|
/**
|
|
68
71
|
* Track validation errors and throw AggregateError after all validations have been run
|
|
69
72
|
* @param err
|
|
70
73
|
*/
|
|
71
74
|
private trackValidationError;
|
|
75
|
+
private buildKeyObject;
|
|
72
76
|
}
|
|
73
77
|
export default Delete;
|
|
74
78
|
//# sourceMappingURL=Delete.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Delete.d.ts","sourceRoot":"","sources":["../../../../src/operations/Delete/Delete.ts"],"names":[],"mappings":"AAAA,OAAO,UAAU,MAAM,kBAAkB,CAAC;
|
|
1
|
+
{"version":3,"file":"Delete.d.ts","sourceRoot":"","sources":["../../../../src/operations/Delete/Delete.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAY/C,OAAO,KAAK,EAEV,WAAW,EAEZ,MAAM,aAAa,CAAC;AAErB,OAAO,aAAa,MAAM,kBAAkB,CAAC;AA2B7C;;;;;;;;;GASG;AACH,cAAM,MAAM,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,aAAa,CAAC,CAAC,CAAC;;gBAS7C,MAAM,EAAE,WAAW,CAAC,CAAC,CAAC;IAiBlC;;;;;;;OAOG;IACU,GAAG,CAAC,EAAE,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IA8B3C;;;;OAIG;YACW,QAAQ;IA+BtB;;;;OAIG;IACH,OAAO,CAAC,iCAAiC;IASzC;;;OAGG;IACH,OAAO,CAAC,2BAA2B;IAOnC;;;OAGG;IACH,OAAO,CAAC,0BAA0B;IAalC;;;OAGG;IACH,OAAO,CAAC,4BAA4B;IAkBpC;;;;OAIG;YACW,iCAAiC;IA2B/C;;;;OAIG;IACH,OAAO,CAAC,uCAAuC;IA2B/C;;;OAGG;IACH,OAAO,CAAC,mCAAmC;IAiB3C;;;OAGG;IACH,OAAO,CAAC,oBAAoB;IAI5B,OAAO,CAAC,cAAc;CAcvB;AAED,eAAe,MAAM,CAAC"}
|