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
|
@@ -8,41 +8,200 @@ const utils_1 = require("../../utils");
|
|
|
8
8
|
const utils_2 = require("../utils");
|
|
9
9
|
const OperationBase_1 = __importDefault(require("../OperationBase"));
|
|
10
10
|
const metadata_1 = __importDefault(require("../../metadata"));
|
|
11
|
+
const errors_1 = require("../../errors");
|
|
11
12
|
/**
|
|
12
|
-
*
|
|
13
|
+
* Represents an update operation for a DynaRecord-backed entity, handling both attribute updates and relationship consistency via denormalization.
|
|
13
14
|
*
|
|
14
|
-
*
|
|
15
|
+
* This class supports updating an existing entity and managing its relational links, specifically:
|
|
16
|
+
* - Updating entity attributes while preserving schema constraints.
|
|
17
|
+
* - Managing "BelongsTo" relationship links by creating or removing associated denormalized records.
|
|
18
|
+
* - Ensuring that if a foreign key changes, the old link record is removed, preventing stale references.
|
|
15
19
|
*
|
|
16
|
-
* Only attributes defined on the model can be
|
|
20
|
+
* Only attributes defined on the model can be updated. Both compile-time and runtime checks help ensure that updated values are valid.
|
|
21
|
+
*
|
|
22
|
+
* **Example**
|
|
23
|
+
* ```typescript
|
|
24
|
+
* const updateOp = new Update(MyEntityClass);
|
|
25
|
+
* await updateOp.run("entityId", { name: "NewName", status: "active" });
|
|
26
|
+
* ```
|
|
17
27
|
*
|
|
18
28
|
* @template T - The type of the entity being updated, extending `DynaRecord`.
|
|
19
29
|
*/
|
|
20
30
|
class Update extends OperationBase_1.default {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
constructor(Entity) {
|
|
31
|
+
transactionBuilder;
|
|
32
|
+
constructor(Entity, transactionBuilder) {
|
|
24
33
|
super(Entity);
|
|
25
|
-
|
|
34
|
+
// Use the transaction builder passed to the class, or instantiate a new one
|
|
35
|
+
this.transactionBuilder = transactionBuilder ?? new dynamo_utils_1.TransactWriteBuilder();
|
|
26
36
|
}
|
|
27
37
|
/**
|
|
28
|
-
*
|
|
29
|
-
*
|
|
30
|
-
*
|
|
38
|
+
* Executes the update operation against DynamoDB.
|
|
39
|
+
*
|
|
40
|
+
* **What it does:**
|
|
41
|
+
* - Fetches the current state of the entity and any related "Has" relationship entities.
|
|
42
|
+
* - Constructs an update expression for the main entity's attributes.
|
|
43
|
+
* - Applies the same update expression to related entities and "BelongsTo" link records to maintain denormalized consistency.
|
|
44
|
+
* - Manages foreign key changes by creating new link items and removing old link items.
|
|
45
|
+
*
|
|
46
|
+
* @param id - The unique identifier of the entity being updated.
|
|
47
|
+
* @param attributes - Partial set of entity attributes to update. Must be defined on the entity's model.
|
|
48
|
+
* @returns A promise that resolves to the set of updated attributes as applied to the entity.
|
|
49
|
+
* @throws If the entity does not exist, an error is thrown.
|
|
31
50
|
*/
|
|
32
51
|
async run(id, attributes) {
|
|
33
52
|
const entityMeta = metadata_1.default.getEntity(this.EntityClass.name);
|
|
34
53
|
const entityAttrs = entityMeta.parseRawEntityDefinedAttributesPartial(attributes);
|
|
35
|
-
const updatedAttrs = this.
|
|
36
|
-
|
|
37
|
-
|
|
54
|
+
const { updatedAttrs, expression } = this.buildUpdateMetadata(entityAttrs);
|
|
55
|
+
this.buildUpdateItemTransaction(id, expression);
|
|
56
|
+
// Only need to prefetch if the entity has relationships
|
|
57
|
+
if (entityMeta.allRelationships.length > 0) {
|
|
58
|
+
const belongsToRelMetaBeingUpdated = this.getBelongsToRelMetaAndKeyForUpdatedKeys(entityAttrs);
|
|
59
|
+
const entities = await this.preFetch(id, belongsToRelMetaBeingUpdated);
|
|
60
|
+
const preFetch = this.preProcessFetchedData(id, entities, belongsToRelMetaBeingUpdated);
|
|
61
|
+
const updatedEntity = {
|
|
62
|
+
...preFetch.entityPreUpdate,
|
|
63
|
+
...updatedAttrs,
|
|
64
|
+
id
|
|
65
|
+
};
|
|
66
|
+
this.buildUpdateRelatedEntityLinks(id, preFetch.relatedEntities, expression);
|
|
67
|
+
this.buildBelongsToTransactions(preFetch.entityPreUpdate, updatedEntity, expression, preFetch.newBelongsToEntityLookup);
|
|
68
|
+
}
|
|
69
|
+
await this.commitTransaction();
|
|
38
70
|
return updatedAttrs;
|
|
39
71
|
}
|
|
72
|
+
async commitTransaction() {
|
|
73
|
+
await this.transactionBuilder.executeTransaction();
|
|
74
|
+
}
|
|
75
|
+
/**
|
|
76
|
+
* BelongsToRelationship meta data and foreign key value pair for foreign keys being updated
|
|
77
|
+
* @param attributes
|
|
78
|
+
* @returns
|
|
79
|
+
*/
|
|
80
|
+
getBelongsToRelMetaAndKeyForUpdatedKeys(attributes) {
|
|
81
|
+
return this.entityMetadata.belongsToRelationships.reduce((acc, meta) => {
|
|
82
|
+
const foreignKeyVal = (0, utils_2.extractForeignKeyFromEntity)(meta, attributes);
|
|
83
|
+
if (foreignKeyVal !== undefined)
|
|
84
|
+
acc.push({ meta, foreignKeyVal });
|
|
85
|
+
return acc;
|
|
86
|
+
}, []);
|
|
87
|
+
}
|
|
88
|
+
/**
|
|
89
|
+
* Pre-fetches the target entity and any related entities from the database. This is done using a strong read operation to ensure consistency.
|
|
90
|
+
*
|
|
91
|
+
* **What it does:**
|
|
92
|
+
* - Retrieves the main entity and all linked entities in the entity's partition.
|
|
93
|
+
* - Performs a TransactGetItem operation on entities linked bai foreign keys (BelongsTo) to support denormalizing copies to associated partitions
|
|
94
|
+
* - Filters these entities to separate the main entity and its related link records.
|
|
95
|
+
*
|
|
96
|
+
* @param id - The unique identifier of the entity being fetched.
|
|
97
|
+
* @param belongsToRelFkAndMetas - BelongsTo relationship meta objects with foreign keys used for fetching associated records
|
|
98
|
+
* @returns A promise that resolves to an object containing:
|
|
99
|
+
* - `entityPreUpdate`: The current state of the entity before updates.
|
|
100
|
+
* - `relatedEntities`: An array of related link entities.
|
|
101
|
+
* @throws If the entity does not exist, it throws a NotFoundError.
|
|
102
|
+
* @private
|
|
103
|
+
*/
|
|
104
|
+
async preFetch(id, belongsToRelFkAndMetas) {
|
|
105
|
+
const hasRelMetas = this.entityMetadata.hasRelationships;
|
|
106
|
+
const { name: tableName } = this.tableMetadata;
|
|
107
|
+
const transactionBuilder = new dynamo_utils_1.TransactGetBuilder();
|
|
108
|
+
// Get the new BelongsTo relationship entities that are being updated
|
|
109
|
+
belongsToRelFkAndMetas.forEach(({ meta, foreignKeyVal }) => {
|
|
110
|
+
if (foreignKeyVal !== null) {
|
|
111
|
+
transactionBuilder.addGet({
|
|
112
|
+
TableName: tableName,
|
|
113
|
+
Key: {
|
|
114
|
+
[this.partitionKeyAlias]: meta.target.partitionKeyValue(foreignKeyVal),
|
|
115
|
+
[this.sortKeyAlias]: meta.target.name
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
});
|
|
120
|
+
const typeAlias = this.tableMetadata.defaultAttributes.type.alias;
|
|
121
|
+
// Get linked items from entity being updates partition as well as new foreign entities if adding or updating an FK
|
|
122
|
+
const [transactionResults, selfAndLinkedEntities] = await Promise.all([
|
|
123
|
+
transactionBuilder.executeTransaction(),
|
|
124
|
+
this.EntityClass.query(id, {
|
|
125
|
+
filter: {
|
|
126
|
+
type: [
|
|
127
|
+
this.EntityClass.name,
|
|
128
|
+
...hasRelMetas.map(meta => meta.target.name)
|
|
129
|
+
]
|
|
130
|
+
}
|
|
131
|
+
})
|
|
132
|
+
]);
|
|
133
|
+
// Serialize table items to entities
|
|
134
|
+
const foreignEntities = transactionResults.reduce((acc, res) => {
|
|
135
|
+
if (res.Item !== undefined && (0, utils_1.isString)(res.Item[typeAlias])) {
|
|
136
|
+
const entityMeta = metadata_1.default.getEntity(res.Item[typeAlias]);
|
|
137
|
+
const entity = (0, utils_1.tableItemToEntity)(entityMeta.EntityClass, res.Item);
|
|
138
|
+
acc.push(entity);
|
|
139
|
+
}
|
|
140
|
+
return acc;
|
|
141
|
+
}, []);
|
|
142
|
+
return [...selfAndLinkedEntities, ...foreignEntities];
|
|
143
|
+
}
|
|
144
|
+
/**
|
|
145
|
+
* {reprocess pre-fetch data for processing
|
|
146
|
+
* @param id
|
|
147
|
+
* @param entities
|
|
148
|
+
* @param belongsToRelFkAndMetas
|
|
149
|
+
* @returns
|
|
150
|
+
*/
|
|
151
|
+
preProcessFetchedData(id, entities, belongsToRelFkAndMetas) {
|
|
152
|
+
let entityPreUpdate;
|
|
153
|
+
const relatedEntities = [];
|
|
154
|
+
const newBelongsToEntityLookup = {};
|
|
155
|
+
entities.forEach(entity => {
|
|
156
|
+
if (id === entity.id) {
|
|
157
|
+
entityPreUpdate = entity;
|
|
158
|
+
}
|
|
159
|
+
else if (belongsToRelFkAndMetas.some(obj => obj.foreignKeyVal === entity.id)) {
|
|
160
|
+
newBelongsToEntityLookup[entity.id] = entity;
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
relatedEntities.push(entity);
|
|
164
|
+
}
|
|
165
|
+
});
|
|
166
|
+
if (entityPreUpdate === undefined) {
|
|
167
|
+
throw new errors_1.NotFoundError(`${this.EntityClass.name} does not exist: ${id}`);
|
|
168
|
+
}
|
|
169
|
+
return { entityPreUpdate, relatedEntities, newBelongsToEntityLookup };
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Constructs updated attributes and the corresponding DynamoDB update expression.
|
|
173
|
+
*
|
|
174
|
+
* **What it does:**
|
|
175
|
+
* - Merges the provided attributes with `updatedAt` (automatically set to the current time).
|
|
176
|
+
* - Converts the updated attributes into a DynamoDB update expression.
|
|
177
|
+
*
|
|
178
|
+
* @param attributes - The partial attributes to be updated on the entity.
|
|
179
|
+
* @returns An object containing:
|
|
180
|
+
* - `updatedAttrs`: The final updated attribute set.
|
|
181
|
+
* - `expression`: A DynamoDB update expression to apply these changes.
|
|
182
|
+
* @private
|
|
183
|
+
*/
|
|
184
|
+
buildUpdateMetadata(attributes) {
|
|
185
|
+
const updatedAttrs = {
|
|
186
|
+
...attributes,
|
|
187
|
+
updatedAt: new Date()
|
|
188
|
+
};
|
|
189
|
+
const tableAttrs = (0, utils_1.entityToTableItem)(this.EntityClass, updatedAttrs);
|
|
190
|
+
const expression = (0, utils_2.expressionBuilder)(tableAttrs);
|
|
191
|
+
return { updatedAttrs, expression };
|
|
192
|
+
}
|
|
40
193
|
/**
|
|
41
|
-
*
|
|
42
|
-
*
|
|
43
|
-
*
|
|
194
|
+
* Adds a transaction operation to update the main entity's record.
|
|
195
|
+
*
|
|
196
|
+
* **What it does:**
|
|
197
|
+
* - Builds a DynamoDB Update transaction using the provided update expression.
|
|
198
|
+
* - Adds a condition to ensure the entity exists before updating.
|
|
199
|
+
*
|
|
200
|
+
* @param id - The unique identifier of the entity being updated.
|
|
201
|
+
* @param updateExpression - The DynamoDB update expression describing the changes.
|
|
202
|
+
* @private
|
|
44
203
|
*/
|
|
45
|
-
buildUpdateItemTransaction(id,
|
|
204
|
+
buildUpdateItemTransaction(id, updateExpression) {
|
|
46
205
|
const { name: tableName } = this.tableMetadata;
|
|
47
206
|
const pk = this.tableMetadata.partitionKeyAttribute.name;
|
|
48
207
|
const sk = this.tableMetadata.sortKeyAttribute.name;
|
|
@@ -50,76 +209,247 @@ class Update extends OperationBase_1.default {
|
|
|
50
209
|
[pk]: this.EntityClass.partitionKeyValue(id),
|
|
51
210
|
[sk]: this.EntityClass.name
|
|
52
211
|
};
|
|
53
|
-
const updatedAttrs = {
|
|
54
|
-
...attributes,
|
|
55
|
-
updatedAt: new Date()
|
|
56
|
-
};
|
|
57
212
|
const tableKeys = (0, utils_1.entityToTableItem)(this.EntityClass, keys);
|
|
58
|
-
|
|
59
|
-
const expression = (0, utils_2.expressionBuilder)(tableAttrs);
|
|
60
|
-
this.#transactionBuilder.addUpdate({
|
|
213
|
+
this.transactionBuilder.addUpdate({
|
|
61
214
|
TableName: tableName,
|
|
62
215
|
Key: tableKeys,
|
|
63
|
-
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`,
|
|
64
|
-
...
|
|
216
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`,
|
|
217
|
+
...updateExpression
|
|
65
218
|
}, `${this.EntityClass.name} with ID '${id}' does not exist`);
|
|
66
|
-
return updatedAttrs;
|
|
67
219
|
}
|
|
68
220
|
/**
|
|
69
|
-
* Builds
|
|
70
|
-
*
|
|
71
|
-
*
|
|
72
|
-
*
|
|
73
|
-
*
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
221
|
+
* Builds all necessary transactions to handle "BelongsTo" relationships when updating the entity.
|
|
222
|
+
*
|
|
223
|
+
* **What it does:**
|
|
224
|
+
* - Checks if any foreign keys for "BelongsTo" relationships have changed.
|
|
225
|
+
* - If so, updates or creates new denormalized link records in the related partitions.
|
|
226
|
+
* - Removes old link records that are no longer valid due to foreign key changes.
|
|
227
|
+
*
|
|
228
|
+
* @param entityPreUpdate - The state of the entity before the update.
|
|
229
|
+
* @param updatedEntity - The entity state after proposed updates (partial attributes).
|
|
230
|
+
* @param updateExpression - The DynamoDB update expression representing the attribute updates.
|
|
231
|
+
* @private
|
|
232
|
+
*/
|
|
233
|
+
buildBelongsToTransactions(entityPreUpdate, updatedEntity, updateExpression, newBelongsToEntityLookup) {
|
|
234
|
+
const entityId = entityPreUpdate.id;
|
|
235
|
+
for (const relMeta of this.entityMetadata.belongsToRelationships) {
|
|
236
|
+
const foreignKey = (0, utils_2.extractForeignKeyFromEntity)(relMeta, updatedEntity);
|
|
237
|
+
const isUpdatingRelationshipId = foreignKey !== undefined;
|
|
238
|
+
if (isUpdatingRelationshipId && (0, utils_1.isNullableString)(foreignKey)) {
|
|
239
|
+
// Handle removal of old link if the foreign key changed.
|
|
240
|
+
const oldFk = (0, utils_2.extractForeignKeyFromEntity)(relMeta, entityPreUpdate);
|
|
241
|
+
const isAddingForeignKey = oldFk === undefined && foreignKey !== null;
|
|
242
|
+
const isUpdatingForeignKey = oldFk !== undefined && oldFk !== foreignKey;
|
|
243
|
+
const isRemovingForeignKey = isUpdatingForeignKey && foreignKey === null;
|
|
244
|
+
if (isAddingForeignKey) {
|
|
245
|
+
this.buildPutBelongsToLinkedRecords(updatedEntity, relMeta, foreignKey, newBelongsToEntityLookup, "attribute_not_exists", `${this.EntityClass.name} already has an associated ${relMeta.target.name}`);
|
|
246
|
+
}
|
|
247
|
+
else if (isRemovingForeignKey) {
|
|
248
|
+
this.removeForeignKeysTransactions(entityId, relMeta, oldFk);
|
|
249
|
+
}
|
|
250
|
+
else if (isUpdatingForeignKey) {
|
|
251
|
+
this.updateForeignKeyTransactions(updatedEntity, relMeta, foreignKey, oldFk, newBelongsToEntityLookup);
|
|
252
|
+
}
|
|
253
|
+
else if (foreignKey !== null) {
|
|
254
|
+
this.buildUpdateBelongsToLinkedRecords(entityId, relMeta, foreignKey, updateExpression);
|
|
255
|
+
}
|
|
87
256
|
}
|
|
88
|
-
}
|
|
89
|
-
await relationshipTransactions.build(entityData);
|
|
257
|
+
}
|
|
90
258
|
}
|
|
91
259
|
/**
|
|
92
|
-
*
|
|
93
|
-
*
|
|
94
|
-
*
|
|
95
|
-
*
|
|
260
|
+
* Creates or updates the denormalized link record for a "BelongsTo" relationship to the related entity's partition.
|
|
261
|
+
*
|
|
262
|
+
* **What it does:**
|
|
263
|
+
* - Builds a DynamoDB Update transaction for the linked record identified by the relationship and foreign key.
|
|
264
|
+
* - Ensures the linked record exists before updating (if not, it will fail).
|
|
265
|
+
*
|
|
266
|
+
* @param entityId - The identifier of the main entity being updated.
|
|
267
|
+
* @param relMeta - Metadata describing the "BelongsTo" relationship.
|
|
268
|
+
* @param foreignKey - The new foreign key value after updates.
|
|
269
|
+
* @param updateExpression - The DynamoDB update expression for the attribute changes.
|
|
270
|
+
* @private
|
|
96
271
|
*/
|
|
97
|
-
|
|
272
|
+
buildUpdateBelongsToLinkedRecords(entityId, relMeta, foreignKey, updateExpression) {
|
|
98
273
|
const { name: tableName } = this.tableMetadata;
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
274
|
+
const newKey = (0, utils_2.buildBelongsToLinkKey)(this.EntityClass, entityId, relMeta, foreignKey);
|
|
275
|
+
this.transactionBuilder.addUpdate({
|
|
276
|
+
TableName: tableName,
|
|
277
|
+
Key: newKey,
|
|
278
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`,
|
|
279
|
+
...updateExpression
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
/**
|
|
283
|
+
* Builds transactions to persist an updated/new belongs to record
|
|
284
|
+
* Denormalizes data to the entity being updates's partition and a link to the foreign entities partition
|
|
285
|
+
* Ensures that the new entity foreign key exists
|
|
286
|
+
* @param updatedEntity
|
|
287
|
+
* @param relMeta
|
|
288
|
+
* @param foreignKey
|
|
289
|
+
* @param newBelongsToEntityLookup
|
|
290
|
+
* @param persistToSelfCondition
|
|
291
|
+
* @param persistToSelfConditionErrMessage
|
|
292
|
+
*/
|
|
293
|
+
buildPutBelongsToLinkedRecords(updatedEntity, relMeta, foreignKey, newBelongsToEntityLookup, persistToSelfCondition, persistToSelfConditionErrMessage) {
|
|
294
|
+
// Ensure that the new foreign key is valid and exists
|
|
295
|
+
this.buildEntityExistsCondition(relMeta, foreignKey);
|
|
296
|
+
// Denormalize entity being updated to foreign partition
|
|
297
|
+
this.buildLinkToForeignEntityTransaction(updatedEntity, relMeta, foreignKey);
|
|
298
|
+
// Add denormalized record for new entity to self
|
|
299
|
+
this.buildAddForeignEntityToSelfTransaction(updatedEntity, relMeta, foreignKey, newBelongsToEntityLookup, persistToSelfCondition, persistToSelfConditionErrMessage);
|
|
300
|
+
}
|
|
301
|
+
/**
|
|
302
|
+
* Builds a condition expression that an entity exists
|
|
303
|
+
* @param relMeta
|
|
304
|
+
* @param foreignKey
|
|
305
|
+
*/
|
|
306
|
+
buildEntityExistsCondition(relMeta, foreignKey) {
|
|
307
|
+
const errMsg = `${relMeta.target.name} with ID '${foreignKey}' does not exist`;
|
|
308
|
+
const conditionCheck = {
|
|
309
|
+
TableName: this.tableMetadata.name,
|
|
310
|
+
Key: {
|
|
311
|
+
[this.partitionKeyAlias]: relMeta.target.partitionKeyValue(foreignKey),
|
|
312
|
+
[this.sortKeyAlias]: relMeta.target.name
|
|
313
|
+
},
|
|
314
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`
|
|
315
|
+
};
|
|
316
|
+
this.transactionBuilder.addConditionCheck(conditionCheck, errMsg);
|
|
317
|
+
}
|
|
318
|
+
/**
|
|
319
|
+
* Denormalizes a link for the entity being updated to the new entities partition
|
|
320
|
+
* @param updatedEntity
|
|
321
|
+
* @param relMeta
|
|
322
|
+
* @param foreignKey
|
|
323
|
+
*/
|
|
324
|
+
buildLinkToForeignEntityTransaction(updatedEntity, relMeta, foreignKey) {
|
|
325
|
+
const key = (0, utils_2.buildBelongsToLinkKey)(this.EntityClass, updatedEntity.id, relMeta, foreignKey);
|
|
326
|
+
const tableItem = (0, utils_1.entityToTableItem)(this.EntityClass, updatedEntity);
|
|
327
|
+
this.transactionBuilder.addPut({
|
|
328
|
+
TableName: this.tableMetadata.name,
|
|
329
|
+
Item: { ...tableItem, ...key },
|
|
330
|
+
ConditionExpression: `attribute_not_exists(${this.partitionKeyAlias})`
|
|
331
|
+
}, `${relMeta.target.name} with id: ${foreignKey} already has an associated ${this.EntityClass.name}`);
|
|
332
|
+
}
|
|
333
|
+
/**
|
|
334
|
+
* Builds the transaction to add or replace the linked record for the foreign entity in the entity being updates partition
|
|
335
|
+
* @param updatedEntity
|
|
336
|
+
* @param relMeta
|
|
337
|
+
* @param foreignKey
|
|
338
|
+
* @param newBelongsToEntityLookup
|
|
339
|
+
* @param persistToSelfCondition
|
|
340
|
+
* @param persistToSelfConditionErrMessage
|
|
341
|
+
*/
|
|
342
|
+
buildAddForeignEntityToSelfTransaction(updatedEntity, relMeta, foreignKey, newBelongsToEntityLookup, persistToSelfCondition, persistToSelfConditionErrMessage) {
|
|
343
|
+
const linkedEntity = newBelongsToEntityLookup[foreignKey];
|
|
344
|
+
if (linkedEntity === undefined) {
|
|
345
|
+
throw new errors_1.NotFoundError(`${relMeta.target.name} does not exist: ${foreignKey}`);
|
|
111
346
|
}
|
|
347
|
+
const key = {
|
|
348
|
+
[this.partitionKeyAlias]: this.EntityClass.partitionKeyValue(updatedEntity.id),
|
|
349
|
+
[this.sortKeyAlias]: relMeta.target.name
|
|
350
|
+
};
|
|
351
|
+
const linkedRecordTableItem = (0, utils_1.entityToTableItem)(relMeta.target, linkedEntity);
|
|
352
|
+
this.transactionBuilder.addPut({
|
|
353
|
+
TableName: this.tableMetadata.name,
|
|
354
|
+
Item: { ...linkedRecordTableItem, ...key },
|
|
355
|
+
ConditionExpression: `${persistToSelfCondition}(${this.partitionKeyAlias})`
|
|
356
|
+
}, persistToSelfConditionErrMessage);
|
|
357
|
+
}
|
|
358
|
+
/**
|
|
359
|
+
* Removes the old link record associated with a previous "BelongsTo" foreign key when the foreign key changes.
|
|
360
|
+
*
|
|
361
|
+
* **What it does:**
|
|
362
|
+
* - Builds a DynamoDB Delete transaction to remove the stale link record from the old relationship partition.
|
|
363
|
+
*
|
|
364
|
+
* @param entityId - The identifier of the entity whose foreign key was changed.
|
|
365
|
+
* @param relMeta - Metadata describing the "BelongsTo" relationship.
|
|
366
|
+
* @param oldForeignKey - The old foreign key value that should no longer link to the entity.
|
|
367
|
+
* @private
|
|
368
|
+
*/
|
|
369
|
+
removeForeignKeysTransactions(entityId, relMeta, oldForeignKey) {
|
|
370
|
+
// Keys to delete the denormalized record from entities own partition
|
|
371
|
+
const oldKeysToSelf = {
|
|
372
|
+
[this.partitionKeyAlias]: this.EntityClass.partitionKeyValue(entityId),
|
|
373
|
+
[this.sortKeyAlias]: relMeta.target.name
|
|
374
|
+
};
|
|
375
|
+
// Keys to delete the linked record from the foreign entities partition
|
|
376
|
+
const oldKeysToForeignEntity = (0, utils_2.buildBelongsToLinkKey)(this.EntityClass, entityId, relMeta, oldForeignKey);
|
|
377
|
+
this.transactionBuilder.addDelete({
|
|
378
|
+
TableName: this.tableMetadata.name,
|
|
379
|
+
Key: oldKeysToSelf
|
|
380
|
+
}, `Failed to delete denormalized record with keys: ${JSON.stringify(oldKeysToSelf)}`);
|
|
381
|
+
this.transactionBuilder.addDelete({
|
|
382
|
+
TableName: this.tableMetadata.name,
|
|
383
|
+
Key: oldKeysToForeignEntity
|
|
384
|
+
}, `Failed to delete denormalized record with keys: ${JSON.stringify(oldKeysToForeignEntity)}`);
|
|
112
385
|
}
|
|
113
386
|
/**
|
|
114
|
-
*
|
|
387
|
+
* Builds the transactions for updating the foreign key of an entity from one key to another
|
|
388
|
+
* @param updatedEntity
|
|
389
|
+
* @param relMeta
|
|
390
|
+
* @param newForeignKey
|
|
391
|
+
* @param oldForeignKey
|
|
392
|
+
* @param newBelongsToEntityLookup
|
|
115
393
|
*/
|
|
116
|
-
|
|
117
|
-
//
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
394
|
+
updateForeignKeyTransactions(updatedEntity, relMeta, newForeignKey, oldForeignKey, newBelongsToEntityLookup) {
|
|
395
|
+
// Keys to delete the linked record from the foreign entities partition
|
|
396
|
+
const oldKeysToForeignEntity = (0, utils_2.buildBelongsToLinkKey)(this.EntityClass, updatedEntity.id, relMeta, oldForeignKey);
|
|
397
|
+
this.transactionBuilder.addDelete({
|
|
398
|
+
TableName: this.tableMetadata.name,
|
|
399
|
+
Key: oldKeysToForeignEntity
|
|
400
|
+
});
|
|
401
|
+
this.buildPutBelongsToLinkedRecords(updatedEntity, relMeta, newForeignKey, newBelongsToEntityLookup, "attribute_exists");
|
|
402
|
+
}
|
|
403
|
+
/**
|
|
404
|
+
* Builds transactions to update all related entities that exist in the main entity's partition, applying the same attribute updates.
|
|
405
|
+
*
|
|
406
|
+
* **What it does:**
|
|
407
|
+
* - For each linked entity found in `preFetch`, attempts to apply the same update expression.
|
|
408
|
+
* - Ensures each related entity exists before attempting to update.
|
|
409
|
+
*
|
|
410
|
+
* @param relatedEntities - An array of entities that are related to the primary entity and need synchronized attribute updates.
|
|
411
|
+
* @param expression - The DynamoDB update expression to apply to related entities.
|
|
412
|
+
* @private
|
|
413
|
+
*/
|
|
414
|
+
buildUpdateRelatedEntityLinks(entityId, relatedEntities, expression) {
|
|
415
|
+
const hasAndBelongsToManyLookup = this.buildHasAndBelongsToManyRelLookup();
|
|
416
|
+
relatedEntities.forEach(entity => {
|
|
417
|
+
this.transactionBuilder.addUpdate({
|
|
418
|
+
TableName: this.tableMetadata.name,
|
|
419
|
+
Key: this.buildUpdatedRelatedEntityLinkKey(entityId, entity, hasAndBelongsToManyLookup),
|
|
420
|
+
ConditionExpression: `attribute_exists(${this.partitionKeyAlias})`,
|
|
421
|
+
...expression
|
|
422
|
+
}, `${entity.constructor.name} (${entity.id}) is not associated with ${this.EntityClass.name} (${entityId})`);
|
|
423
|
+
});
|
|
424
|
+
}
|
|
425
|
+
/**
|
|
426
|
+
* Builds the table key for a related entity that needs to be updated
|
|
427
|
+
* @param id - The id of the entity being updated
|
|
428
|
+
* @param entity
|
|
429
|
+
* @param relLookup
|
|
430
|
+
* @returns
|
|
431
|
+
*/
|
|
432
|
+
buildUpdatedRelatedEntityLinkKey(id, entity, relLookup) {
|
|
433
|
+
const isHasAndBelongsToManyRel = relLookup[entity.type] !== undefined;
|
|
434
|
+
const sortKey = isHasAndBelongsToManyRel
|
|
435
|
+
? this.EntityClass.partitionKeyValue(id)
|
|
436
|
+
: this.EntityClass.name;
|
|
437
|
+
return {
|
|
438
|
+
[this.partitionKeyAlias]: entity.partitionKeyValue(),
|
|
439
|
+
[this.sortKeyAlias]: sortKey
|
|
440
|
+
};
|
|
441
|
+
}
|
|
442
|
+
/**
|
|
443
|
+
* Build a lookup object to lookup a HasAndBelongsToMany relationship for an entity. Used for processing to avoid excessive looping
|
|
444
|
+
* @returns
|
|
445
|
+
*/
|
|
446
|
+
buildHasAndBelongsToManyRelLookup() {
|
|
447
|
+
return Object.values(this.entityMetadata.relationships).reduce((acc, rel) => {
|
|
448
|
+
if (rel.type === "HasAndBelongsToMany") {
|
|
449
|
+
acc[rel.target.name] = rel;
|
|
450
|
+
}
|
|
451
|
+
return acc;
|
|
452
|
+
}, {});
|
|
123
453
|
}
|
|
124
454
|
}
|
|
125
455
|
exports.default = Update;
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type DynaRecord from "../../DynaRecord";
|
|
2
|
+
import Update from "./Update";
|
|
3
|
+
/**
|
|
4
|
+
* Runs Update operation with out committing the transaction
|
|
5
|
+
*/
|
|
6
|
+
declare class UpdateDryRun<T extends DynaRecord> extends Update<T> {
|
|
7
|
+
protected commitTransaction(): Promise<void>;
|
|
8
|
+
}
|
|
9
|
+
export default UpdateDryRun;
|
|
10
|
+
//# sourceMappingURL=UpdateDryRun.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"UpdateDryRun.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/UpdateDryRun.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,kBAAkB,CAAC;AAC/C,OAAO,MAAM,MAAM,UAAU,CAAC;AAE9B;;GAEG;AACH,cAAM,YAAY,CAAC,CAAC,SAAS,UAAU,CAAE,SAAQ,MAAM,CAAC,CAAC,CAAC;cAC/B,iBAAiB,IAAI,OAAO,CAAC,IAAI,CAAC;CAG5D;AAED,eAAe,YAAY,CAAC"}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
const Update_1 = __importDefault(require("./Update"));
|
|
7
|
+
/**
|
|
8
|
+
* Runs Update operation with out committing the transaction
|
|
9
|
+
*/
|
|
10
|
+
class UpdateDryRun extends Update_1.default {
|
|
11
|
+
async commitTransaction() {
|
|
12
|
+
// No-op
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
exports.default = UpdateDryRun;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,cAAc,SAAS,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/operations/Update/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,UAAU,CAAC;AAC7C,cAAc,SAAS,CAAC;AACxB,OAAO,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC"}
|
|
@@ -17,7 +17,9 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
|
17
17
|
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
18
18
|
};
|
|
19
19
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
20
|
-
exports.Update = void 0;
|
|
20
|
+
exports.UpdateDryRun = exports.Update = void 0;
|
|
21
21
|
var Update_1 = require("./Update");
|
|
22
22
|
Object.defineProperty(exports, "Update", { enumerable: true, get: function () { return __importDefault(Update_1).default; } });
|
|
23
23
|
__exportStar(require("./types"), exports);
|
|
24
|
+
var UpdateDryRun_1 = require("./UpdateDryRun");
|
|
25
|
+
Object.defineProperty(exports, "UpdateDryRun", { enumerable: true, get: function () { return __importDefault(UpdateDryRun_1).default; } });
|
|
@@ -44,10 +44,15 @@ export type ForeignKeyToValue<T> = {
|
|
|
44
44
|
export type RelationshipAttributeNames<T> = {
|
|
45
45
|
[K in keyof T]: Exclude<T[K], undefined> extends DynaRecord | DynaRecord[] ? K : never;
|
|
46
46
|
}[keyof T];
|
|
47
|
+
/**
|
|
48
|
+
* Entity class instance with attributes excluding relationship attributes
|
|
49
|
+
*/
|
|
50
|
+
export type EntityAttributesInstance<T extends DynaRecord> = Omit<T, RelationshipAttributeNames<T>>;
|
|
47
51
|
/**
|
|
48
52
|
* Entity attributes excluding relationship attributes
|
|
53
|
+
* Represents the raw attributes of a class (no functions)
|
|
49
54
|
*/
|
|
50
|
-
export type
|
|
55
|
+
export type EntityAttributesOnly<T extends DynaRecord> = Omit<T, RelationshipAttributeNames<T> | FunctionFields<T>>;
|
|
51
56
|
/**
|
|
52
57
|
* Entity attributes for default fields
|
|
53
58
|
*/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,OAAO,EACR,MAAM,UAAU,CAAC;AAElB;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI;KACpC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,YAAY,GAAG,CAAC,GAAG,KAAK;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;KAC/B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,GAAG,KAAK;CACjD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;KAC7B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK;CACjE,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;KAChC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,kBAAkB,GAC3C,QAAQ,CAAC,MAAM,CAAC,GAChB,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,GACrB,MAAM,GACN,CAAC,CAAC,CAAC,CAAC;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;KACzC,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,UAAU,GAAG,UAAU,EAAE,GACtE,CAAC,GACD,KAAK;CACV,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/operations/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,UAAU,MAAM,eAAe,CAAC;AAC5C,OAAO,EAAE,KAAK,aAAa,EAAE,MAAM,aAAa,CAAC;AACjD,OAAO,KAAK,EACV,UAAU,EACV,kBAAkB,EAClB,QAAQ,EACR,YAAY,EACZ,OAAO,EACR,MAAM,UAAU,CAAC;AAElB;;;;;GAKG;AACH,MAAM,MAAM,qBAAqB,CAAC,CAAC,IAAI;KACpC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,YAAY,GAAG,CAAC,GAAG,KAAK;CACtD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,gBAAgB,CAAC,CAAC,IAAI;KAC/B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,OAAO,GAAG,CAAC,GAAG,KAAK;CACjD,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;GAKG;AACH,MAAM,MAAM,cAAc,CAAC,CAAC,IAAI;KAC7B,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,CAAC,GAAG,IAAI,EAAE,GAAG,EAAE,KAAK,GAAG,GAAG,CAAC,GAAG,KAAK;CACjE,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;;;;;GAMG;AACH,MAAM,MAAM,iBAAiB,CAAC,CAAC,IAAI;KAChC,CAAC,IAAI,MAAM,CAAC,GAAG,CAAC,CAAC,CAAC,CAAC,SAAS,kBAAkB,GAC3C,QAAQ,CAAC,MAAM,CAAC,GAChB,CAAC,CAAC,CAAC,CAAC,SAAS,UAAU,GACrB,MAAM,GACN,CAAC,CAAC,CAAC,CAAC;CACX,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,0BAA0B,CAAC,CAAC,IAAI;KACzC,CAAC,IAAI,MAAM,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAAC,CAAC,EAAE,SAAS,CAAC,SAAS,UAAU,GAAG,UAAU,EAAE,GACtE,CAAC,GACD,KAAK;CACV,CAAC,MAAM,CAAC,CAAC,CAAC;AAEX;;GAEG;AACH,MAAM,MAAM,wBAAwB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CAC/D,CAAC,EACD,0BAA0B,CAAC,CAAC,CAAC,CAC9B,CAAC;AAEF;;;GAGG;AACH,MAAM,MAAM,oBAAoB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CAC3D,CAAC,EACD,0BAA0B,CAAC,CAAC,CAAC,GAAG,cAAc,CAAC,CAAC,CAAC,CAClD,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,4BAA4B,GAAG,IAAI,CAC7C,UAAU,EACV,OAAO,CAAC,MAAM,UAAU,EAAE,aAAa,CAAC,CACzC,CAAC;AAEF;;;;;;;GAOG;AACH,MAAM,MAAM,uBAAuB,CAAC,CAAC,SAAS,UAAU,IAAI,IAAI,CAC9D,iBAAiB,CAAC,CAAC,CAAC,EAClB,MAAM,UAAU,GAChB,0BAA0B,CAAC,CAAC,CAAC,GAC7B,cAAc,CAAC,CAAC,CAAC,GACjB,qBAAqB,CAAC,CAAC,CAAC,GACxB,gBAAgB,CAAC,CAAC,CAAC,CACtB,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"expressionBuilder.d.ts","sourceRoot":"","sources":["../../../../src/operations/utils/expressionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,SAAS,CAAC;AAUjB;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,eAChB,eAAe,KAC1B,
|
|
1
|
+
{"version":3,"file":"expressionBuilder.d.ts","sourceRoot":"","sources":["../../../../src/operations/utils/expressionBuilder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EACV,gBAAgB,EAGjB,MAAM,SAAS,CAAC;AAUjB;;;;GAIG;AACH,eAAO,MAAM,iBAAiB,eAChB,eAAe,KAC1B,gBAoBF,CAAC"}
|
|
@@ -10,12 +10,9 @@ const expressionBuilder = (tableAttrs) => {
|
|
|
10
10
|
const sorted = sortAttributesByOperand(tableAttrs);
|
|
11
11
|
const setExpression = buildUpdateSetExpression(sorted.set);
|
|
12
12
|
const removeExpression = buildUpdateRemoveExpression(sorted.remove);
|
|
13
|
-
const hasSetOperation = Object.keys(setExpression.ExpressionAttributeValues).length > 0;
|
|
14
13
|
return {
|
|
15
14
|
// If the operation has only REMOVE actions, it will not have expression attribute values
|
|
16
|
-
ExpressionAttributeValues:
|
|
17
|
-
? setExpression.ExpressionAttributeValues
|
|
18
|
-
: undefined,
|
|
15
|
+
ExpressionAttributeValues: setExpression.ExpressionAttributeValues,
|
|
19
16
|
ExpressionAttributeNames: {
|
|
20
17
|
...setExpression.ExpressionAttributeNames,
|
|
21
18
|
...removeExpression.ExpressionAttributeNames
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/operations/utils/index.ts"],"names":[],"mappings":"AAAA,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../../src/operations/utils/index.ts"],"names":[],"mappings":"AAAA,cAAc,qBAAqB,CAAC;AACpC,cAAc,SAAS,CAAC;AACxB,cAAc,SAAS,CAAC"}
|