@webda/aws 4.0.0-beta.1 → 4.0.0-beta.3
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 +64 -7
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -0
- package/lib/index.js.map +1 -1
- package/lib/services/aws-parameters.d.ts +33 -0
- package/lib/services/aws-parameters.d.ts.map +1 -0
- package/lib/services/aws-parameters.js +18 -0
- package/lib/services/aws-parameters.js.map +1 -0
- package/lib/services/awscommands.service.d.ts +39 -0
- package/lib/services/awscommands.service.d.ts.map +1 -0
- package/lib/services/awscommands.service.js +127 -0
- package/lib/services/awscommands.service.js.map +1 -0
- package/lib/services/cloudwatchlogger.service.d.ts +131 -0
- package/lib/services/cloudwatchlogger.service.d.ts.map +1 -0
- package/lib/services/{cloudwatchlogger.js → cloudwatchlogger.service.js} +66 -34
- package/lib/services/cloudwatchlogger.service.js.map +1 -0
- package/lib/services/contributors.d.ts +37 -0
- package/lib/services/contributors.d.ts.map +1 -0
- package/lib/services/contributors.js +2 -0
- package/lib/services/contributors.js.map +1 -0
- package/lib/services/dynamodb.service.d.ts +297 -0
- package/lib/services/dynamodb.service.d.ts.map +1 -0
- package/lib/services/dynamodb.service.js +985 -0
- package/lib/services/dynamodb.service.js.map +1 -0
- package/lib/services/index.d.ts +12 -31
- package/lib/services/index.d.ts.map +1 -0
- package/lib/services/index.js +11 -8
- package/lib/services/index.js.map +1 -1
- package/lib/services/lambdacaller.service.d.ts +81 -0
- package/lib/services/lambdacaller.service.d.ts.map +1 -0
- package/lib/services/lambdacaller.service.js +75 -0
- package/lib/services/lambdacaller.service.js.map +1 -0
- package/lib/services/lambdaserver.service.d.ts +127 -0
- package/lib/services/lambdaserver.service.d.ts.map +1 -0
- package/lib/services/lambdaserver.service.js +294 -0
- package/lib/services/lambdaserver.service.js.map +1 -0
- package/lib/services/{route53.d.ts → route53.service.d.ts} +21 -11
- package/lib/services/route53.service.d.ts.map +1 -0
- package/lib/services/{route53.js → route53.service.js} +35 -38
- package/lib/services/route53.service.js.map +1 -0
- package/lib/services/s3binary.service.d.ts +215 -0
- package/lib/services/s3binary.service.d.ts.map +1 -0
- package/lib/services/{s3binary.js → s3binary.service.js} +113 -74
- package/lib/services/s3binary.service.js.map +1 -0
- package/lib/services/secretsmanager.service.d.ts +102 -0
- package/lib/services/secretsmanager.service.d.ts.map +1 -0
- package/lib/services/{secretsmanager.js → secretsmanager.service.js} +42 -24
- package/lib/services/secretsmanager.service.js.map +1 -0
- package/lib/services/{sqsqueue.d.ts → sqsqueue.service.d.ts} +60 -34
- package/lib/services/sqsqueue.service.d.ts.map +1 -0
- package/lib/services/{sqsqueue.js → sqsqueue.service.js} +60 -35
- package/lib/services/sqsqueue.service.js.map +1 -0
- package/package.json +59 -65
- package/webda.module.json +738 -377
- package/lib/deployers/cloudformation.d.ts +0 -316
- package/lib/deployers/cloudformation.js +0 -837
- package/lib/deployers/cloudformation.js.map +0 -1
- package/lib/deployers/cloudformation.spec.d.ts +0 -1
- package/lib/deployers/cloudformation.spec.js +0 -530
- package/lib/deployers/cloudformation.spec.js.map +0 -1
- package/lib/deployers/index.d.ts +0 -254
- package/lib/deployers/index.js +0 -543
- package/lib/deployers/index.js.map +0 -1
- package/lib/deployers/index.spec.d.ts +0 -8
- package/lib/deployers/index.spec.js +0 -595
- package/lib/deployers/index.spec.js.map +0 -1
- package/lib/deployers/lambda-entrypoint.d.ts +0 -1
- package/lib/deployers/lambda-entrypoint.js +0 -11
- package/lib/deployers/lambda-entrypoint.js.map +0 -1
- package/lib/deployers/lambdapackager.d.ts +0 -27
- package/lib/deployers/lambdapackager.js +0 -26
- package/lib/deployers/lambdapackager.js.map +0 -1
- package/lib/deployers/lambdapackager.spec.d.ts +0 -1
- package/lib/deployers/lambdapackager.spec.js +0 -44
- package/lib/deployers/lambdapackager.spec.js.map +0 -1
- package/lib/index.spec.d.ts +0 -10
- package/lib/index.spec.js +0 -42
- package/lib/index.spec.js.map +0 -1
- package/lib/services/aws-mixin.d.ts +0 -24
- package/lib/services/aws-mixin.js +0 -18
- package/lib/services/aws-mixin.js.map +0 -1
- package/lib/services/cloudwatchlogger.d.ts +0 -81
- package/lib/services/cloudwatchlogger.js.map +0 -1
- package/lib/services/cloudwatchlogger.spec.d.ts +0 -1
- package/lib/services/cloudwatchlogger.spec.js +0 -104
- package/lib/services/cloudwatchlogger.spec.js.map +0 -1
- package/lib/services/dynamodb.d.ts +0 -173
- package/lib/services/dynamodb.js +0 -711
- package/lib/services/dynamodb.js.map +0 -1
- package/lib/services/dynamodb.spec.d.ts +0 -23
- package/lib/services/dynamodb.spec.js +0 -339
- package/lib/services/dynamodb.spec.js.map +0 -1
- package/lib/services/lambdacaller.d.ts +0 -68
- package/lib/services/lambdacaller.js +0 -63
- package/lib/services/lambdacaller.js.map +0 -1
- package/lib/services/lambdacaller.spec.d.ts +0 -1
- package/lib/services/lambdacaller.spec.js +0 -70
- package/lib/services/lambdacaller.spec.js.map +0 -1
- package/lib/services/lambdaserver.d.ts +0 -86
- package/lib/services/lambdaserver.js +0 -264
- package/lib/services/lambdaserver.js.map +0 -1
- package/lib/services/lambdaserver.spec.d.ts +0 -1
- package/lib/services/lambdaserver.spec.js +0 -417
- package/lib/services/lambdaserver.spec.js.map +0 -1
- package/lib/services/route53.js.map +0 -1
- package/lib/services/route53.spec.d.ts +0 -1
- package/lib/services/route53.spec.js +0 -102
- package/lib/services/route53.spec.js.map +0 -1
- package/lib/services/s3binary.d.ts +0 -162
- package/lib/services/s3binary.js.map +0 -1
- package/lib/services/s3binary.spec.d.ts +0 -1
- package/lib/services/s3binary.spec.js +0 -269
- package/lib/services/s3binary.spec.js.map +0 -1
- package/lib/services/secretsmanager.d.ts +0 -80
- package/lib/services/secretsmanager.js.map +0 -1
- package/lib/services/secretsmanager.spec.d.ts +0 -1
- package/lib/services/secretsmanager.spec.js +0 -66
- package/lib/services/secretsmanager.spec.js.map +0 -1
- package/lib/services/sqsqueue.js.map +0 -1
- package/lib/services/sqsqueue.spec.d.ts +0 -1
- package/lib/services/sqsqueue.spec.js +0 -152
- package/lib/services/sqsqueue.spec.js.map +0 -1
- package/lib/shell.d.ts +0 -12
- package/lib/shell.js +0 -42
- package/lib/shell.js.map +0 -1
- package/webda.shell.json +0 -11
package/lib/services/dynamodb.js
DELETED
|
@@ -1,711 +0,0 @@
|
|
|
1
|
-
import { ConditionalCheckFailedException, DynamoDB, DynamoDBClient } from "@aws-sdk/client-dynamodb";
|
|
2
|
-
import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
|
|
3
|
-
import { CoreModel, Store, StoreNotFoundError, StoreParameters, UpdateConditionFailError, WebdaError } from "@webda/core";
|
|
4
|
-
import * as WebdaQL from "@webda/ql";
|
|
5
|
-
import { AWSServiceParameters } from "./index.js";
|
|
6
|
-
/**
|
|
7
|
-
* Define DynamoDB parameters
|
|
8
|
-
*/
|
|
9
|
-
export class DynamoStoreParameters extends AWSServiceParameters(StoreParameters) {
|
|
10
|
-
constructor(params, service) {
|
|
11
|
-
super(params, service);
|
|
12
|
-
if (this.table === undefined) {
|
|
13
|
-
throw new WebdaError.CodeError("DYNAMODB_TABLE_PARAMETER_REQUIRED", "Need to define a table at least");
|
|
14
|
-
}
|
|
15
|
-
this.globalIndexes ?? (this.globalIndexes = {});
|
|
16
|
-
}
|
|
17
|
-
}
|
|
18
|
-
/**
|
|
19
|
-
* DynamoStore handles the DynamoDB
|
|
20
|
-
*
|
|
21
|
-
* Parameters:
|
|
22
|
-
* accessKeyId: '' // try WEBDA_AWS_KEY env variable if not found
|
|
23
|
-
* secretAccessKey: '' // try WEBDA_AWS_SECRET env variable if not found
|
|
24
|
-
* table: ''
|
|
25
|
-
* region: ''
|
|
26
|
-
*
|
|
27
|
-
* @WebdaModda
|
|
28
|
-
*/
|
|
29
|
-
export default class DynamoStore extends Store {
|
|
30
|
-
/**
|
|
31
|
-
* Load the parameters
|
|
32
|
-
*
|
|
33
|
-
* @param params
|
|
34
|
-
*/
|
|
35
|
-
loadParameters(params) {
|
|
36
|
-
return new DynamoStoreParameters(params, this);
|
|
37
|
-
}
|
|
38
|
-
/**
|
|
39
|
-
* Create the AWS client
|
|
40
|
-
*/
|
|
41
|
-
resolve() {
|
|
42
|
-
super.resolve();
|
|
43
|
-
this._client = DynamoDBDocument.from(new DynamoDBClient(this.parameters), {
|
|
44
|
-
marshallOptions: {
|
|
45
|
-
removeUndefinedValues: true
|
|
46
|
-
}
|
|
47
|
-
});
|
|
48
|
-
return this;
|
|
49
|
-
}
|
|
50
|
-
/**
|
|
51
|
-
* Copy one DynamoDB table to another
|
|
52
|
-
*
|
|
53
|
-
* @param output
|
|
54
|
-
* @param source
|
|
55
|
-
* @param target
|
|
56
|
-
*/
|
|
57
|
-
static async copyTable(output, source, target) {
|
|
58
|
-
let db = new DynamoDB({});
|
|
59
|
-
let ExclusiveStartKey;
|
|
60
|
-
let props = await db.describeTable({
|
|
61
|
-
TableName: source
|
|
62
|
-
});
|
|
63
|
-
output.startProgress("copyTable", props.Table.ItemCount, `Copying ${source} to ${target}`);
|
|
64
|
-
do {
|
|
65
|
-
let info = await db.scan({
|
|
66
|
-
TableName: source,
|
|
67
|
-
ExclusiveStartKey
|
|
68
|
-
});
|
|
69
|
-
do {
|
|
70
|
-
let items = [];
|
|
71
|
-
while (info.Items.length && items.length < 25) {
|
|
72
|
-
items.push(info.Items.shift());
|
|
73
|
-
}
|
|
74
|
-
if (!items.length) {
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
let params = {
|
|
78
|
-
RequestItems: {}
|
|
79
|
-
};
|
|
80
|
-
params.RequestItems[target] = items.map(Item => ({
|
|
81
|
-
PutRequest: { Item }
|
|
82
|
-
}));
|
|
83
|
-
await db.batchWriteItem(params);
|
|
84
|
-
output.incrementProgress(items.length, "copyTable");
|
|
85
|
-
} while (true);
|
|
86
|
-
ExclusiveStartKey = info.LastEvaluatedKey;
|
|
87
|
-
} while (ExclusiveStartKey);
|
|
88
|
-
}
|
|
89
|
-
/**
|
|
90
|
-
* @inheritdoc
|
|
91
|
-
*/
|
|
92
|
-
async _exists(uid) {
|
|
93
|
-
// Should use find + limit 1
|
|
94
|
-
return (await this._get(uid)) !== undefined;
|
|
95
|
-
}
|
|
96
|
-
/**
|
|
97
|
-
* @inheritdoc
|
|
98
|
-
*/
|
|
99
|
-
async _save(object, uid = object.uuid) {
|
|
100
|
-
return this._update(object, uid);
|
|
101
|
-
}
|
|
102
|
-
/**
|
|
103
|
-
* @override
|
|
104
|
-
*
|
|
105
|
-
* @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html
|
|
106
|
-
* @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
|
|
107
|
-
*/
|
|
108
|
-
async find(query) {
|
|
109
|
-
let scan = true;
|
|
110
|
-
let IndexName = undefined;
|
|
111
|
-
let result;
|
|
112
|
-
let primaryKeys = { uuid: null };
|
|
113
|
-
Object.keys(this.parameters.globalIndexes).forEach(name => {
|
|
114
|
-
primaryKeys[this.parameters.globalIndexes[name].key] = name;
|
|
115
|
-
});
|
|
116
|
-
// We could use PartQL but localstack is not compatible
|
|
117
|
-
let filter = new WebdaQL.AndExpression([]);
|
|
118
|
-
let KeyConditionExpression = "";
|
|
119
|
-
let ExpressionAttributeValues = {};
|
|
120
|
-
let FilterExpression = [];
|
|
121
|
-
let ExpressionAttributeNames = {};
|
|
122
|
-
let indexNode;
|
|
123
|
-
let sortOrder = "ASC";
|
|
124
|
-
let processingExpression;
|
|
125
|
-
if (!(query.filter instanceof WebdaQL.AndExpression)) {
|
|
126
|
-
processingExpression = new WebdaQL.AndExpression([query.filter]);
|
|
127
|
-
}
|
|
128
|
-
else {
|
|
129
|
-
processingExpression = query.filter;
|
|
130
|
-
}
|
|
131
|
-
// Search for the index
|
|
132
|
-
processingExpression.children.some(child => {
|
|
133
|
-
if (child instanceof WebdaQL.ComparisonExpression) {
|
|
134
|
-
// Primary key requires equal operator
|
|
135
|
-
if (child.operator === "=" && primaryKeys[child.attribute[0]] !== undefined) {
|
|
136
|
-
// Query not scan
|
|
137
|
-
scan = false;
|
|
138
|
-
IndexName = primaryKeys[child.attribute[0]];
|
|
139
|
-
indexNode = child;
|
|
140
|
-
KeyConditionExpression = `#${child.attribute[0]} = :${child.attribute[0]}`;
|
|
141
|
-
ExpressionAttributeNames[`#${child.attribute[0]}`] = child.attribute[0];
|
|
142
|
-
ExpressionAttributeValues[`:${child.attribute[0]}`] = child.value;
|
|
143
|
-
if (primaryKeys[child.attribute[0]] !== null &&
|
|
144
|
-
query.orderBy &&
|
|
145
|
-
this.parameters.globalIndexes[primaryKeys[child.attribute[0]]].sort) {
|
|
146
|
-
const sortKey = this.parameters.globalIndexes[primaryKeys[child.attribute[0]]].sort;
|
|
147
|
-
// Might update sort order
|
|
148
|
-
query.orderBy.some(order => {
|
|
149
|
-
if (order.field === sortKey) {
|
|
150
|
-
sortOrder = order.direction;
|
|
151
|
-
}
|
|
152
|
-
});
|
|
153
|
-
}
|
|
154
|
-
return true;
|
|
155
|
-
}
|
|
156
|
-
}
|
|
157
|
-
});
|
|
158
|
-
let count = 1;
|
|
159
|
-
// Build the Query/Filter
|
|
160
|
-
processingExpression.children.forEach(child => {
|
|
161
|
-
if (child === indexNode) {
|
|
162
|
-
return;
|
|
163
|
-
}
|
|
164
|
-
// Only work on Comparison Node for now
|
|
165
|
-
if (child instanceof WebdaQL.ComparisonExpression) {
|
|
166
|
-
let operator = child.operator;
|
|
167
|
-
// DynamoDB does not manage LIKE
|
|
168
|
-
if (child.operator === "LIKE") {
|
|
169
|
-
filter.children.push(child);
|
|
170
|
-
return;
|
|
171
|
-
}
|
|
172
|
-
// CONTAINS -> contains (category, :category1)
|
|
173
|
-
// != is <> in Dynamo
|
|
174
|
-
if (operator === "!=") {
|
|
175
|
-
operator = "<>";
|
|
176
|
-
}
|
|
177
|
-
// DynamoDB does not allow more than 100 items in IN
|
|
178
|
-
if (child.operator === "IN" && child.value.length > 100) {
|
|
179
|
-
filter.children.push(child);
|
|
180
|
-
return;
|
|
181
|
-
}
|
|
182
|
-
// Subfields like team.id needs to be #a1.#a2
|
|
183
|
-
let attr = `a${count++}`;
|
|
184
|
-
let fullAttr = `#${attr}`;
|
|
185
|
-
child.attribute.slice(1).forEach(v => {
|
|
186
|
-
let subAttr = `#a${count++}`;
|
|
187
|
-
fullAttr += `.${subAttr}`;
|
|
188
|
-
ExpressionAttributeNames[subAttr] = v;
|
|
189
|
-
});
|
|
190
|
-
ExpressionAttributeNames[`#${attr}`] = child.attribute[0];
|
|
191
|
-
let valueExpression = `:${attr}`;
|
|
192
|
-
if (child.operator === "IN") {
|
|
193
|
-
// Need to follow `a IN (b, c, d)
|
|
194
|
-
valueExpression = "(" + valueExpression;
|
|
195
|
-
ExpressionAttributeValues[`:${attr}`] = child.value[0];
|
|
196
|
-
child.value.splice(1).forEach(v => {
|
|
197
|
-
let subAttr = `:a${count++}`;
|
|
198
|
-
valueExpression += `, ${subAttr}`;
|
|
199
|
-
ExpressionAttributeValues[subAttr] = v;
|
|
200
|
-
});
|
|
201
|
-
valueExpression += ")";
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
// For all other just give the value
|
|
205
|
-
ExpressionAttributeValues[`:${attr}`] = child.value;
|
|
206
|
-
}
|
|
207
|
-
// Manage CONTAINS
|
|
208
|
-
if (child.operator === "CONTAINS") {
|
|
209
|
-
FilterExpression.push(`contains(${fullAttr}, :${attr})`);
|
|
210
|
-
return;
|
|
211
|
-
}
|
|
212
|
-
// If this is a sort key
|
|
213
|
-
if (IndexName && this.parameters.globalIndexes[IndexName].sort === child.attribute[0]) {
|
|
214
|
-
// Sort key
|
|
215
|
-
KeyConditionExpression += ` AND ${fullAttr} ${operator} ${valueExpression}`;
|
|
216
|
-
return;
|
|
217
|
-
}
|
|
218
|
-
// Otherwise fallback to normal Filter
|
|
219
|
-
FilterExpression.push(`${fullAttr} ${operator} ${valueExpression}`);
|
|
220
|
-
}
|
|
221
|
-
else {
|
|
222
|
-
filter.children.push(child);
|
|
223
|
-
}
|
|
224
|
-
});
|
|
225
|
-
if (!Object.keys(ExpressionAttributeNames).length) {
|
|
226
|
-
ExpressionAttributeNames = undefined;
|
|
227
|
-
}
|
|
228
|
-
if (!Object.keys(ExpressionAttributeValues).length) {
|
|
229
|
-
ExpressionAttributeValues = undefined;
|
|
230
|
-
}
|
|
231
|
-
let ExclusiveStartKey = query.continuationToken
|
|
232
|
-
? JSON.parse(Buffer.from(query.continuationToken, "base64").toString())
|
|
233
|
-
: undefined;
|
|
234
|
-
// Scan if not primary key was provided
|
|
235
|
-
if (scan) {
|
|
236
|
-
// SHould log bad query
|
|
237
|
-
const Items = [];
|
|
238
|
-
do {
|
|
239
|
-
result = await this._client.scan({
|
|
240
|
-
TableName: this.parameters.table,
|
|
241
|
-
FilterExpression: FilterExpression.length ? FilterExpression.join(" AND ") : undefined,
|
|
242
|
-
ExclusiveStartKey,
|
|
243
|
-
ExpressionAttributeNames,
|
|
244
|
-
ExpressionAttributeValues,
|
|
245
|
-
Limit: query.limit - Items.length
|
|
246
|
-
});
|
|
247
|
-
Items.push(...result.Items);
|
|
248
|
-
result.Items = Items;
|
|
249
|
-
ExclusiveStartKey = result.LastEvaluatedKey;
|
|
250
|
-
} while (Items.length < query.limit && result.LastEvaluatedKey);
|
|
251
|
-
}
|
|
252
|
-
else {
|
|
253
|
-
result = await this._client.query({
|
|
254
|
-
TableName: this.parameters.table,
|
|
255
|
-
IndexName,
|
|
256
|
-
ExclusiveStartKey,
|
|
257
|
-
KeyConditionExpression,
|
|
258
|
-
FilterExpression: FilterExpression.length ? FilterExpression.join(" AND ") : undefined,
|
|
259
|
-
ExpressionAttributeNames,
|
|
260
|
-
ExpressionAttributeValues,
|
|
261
|
-
Limit: query.limit,
|
|
262
|
-
ScanIndexForward: sortOrder === "ASC" ? true : false
|
|
263
|
-
});
|
|
264
|
-
}
|
|
265
|
-
return {
|
|
266
|
-
results: result.Items.map(c => this.initModel(c)),
|
|
267
|
-
filter,
|
|
268
|
-
continuationToken: result.Items.length >= query.limit
|
|
269
|
-
? Buffer.from(JSON.stringify(result.LastEvaluatedKey)).toString("base64")
|
|
270
|
-
: undefined
|
|
271
|
-
};
|
|
272
|
-
}
|
|
273
|
-
/**
|
|
274
|
-
* Serialize a date for DynamoDB
|
|
275
|
-
* @param date
|
|
276
|
-
* @returns
|
|
277
|
-
*/
|
|
278
|
-
_serializeDate(date) {
|
|
279
|
-
return JSON.stringify(date).replace(/"/g, "");
|
|
280
|
-
}
|
|
281
|
-
/**
|
|
282
|
-
* Clean object to store in DynamoDB
|
|
283
|
-
*
|
|
284
|
-
* @param object
|
|
285
|
-
* @returns
|
|
286
|
-
*/
|
|
287
|
-
_cleanObject(object) {
|
|
288
|
-
if (typeof object !== "object")
|
|
289
|
-
return object;
|
|
290
|
-
if (object instanceof Date) {
|
|
291
|
-
return this._serializeDate(object);
|
|
292
|
-
}
|
|
293
|
-
if (object instanceof CoreModel) {
|
|
294
|
-
object = object.toStoredJSON();
|
|
295
|
-
}
|
|
296
|
-
let res;
|
|
297
|
-
if (object instanceof Array) {
|
|
298
|
-
res = [];
|
|
299
|
-
}
|
|
300
|
-
else {
|
|
301
|
-
res = {};
|
|
302
|
-
}
|
|
303
|
-
for (let i in object) {
|
|
304
|
-
if (object[i] === "" || i.startsWith("__store")) {
|
|
305
|
-
continue;
|
|
306
|
-
}
|
|
307
|
-
res[i] = this._cleanObject(object[i]);
|
|
308
|
-
}
|
|
309
|
-
return res;
|
|
310
|
-
}
|
|
311
|
-
/**
|
|
312
|
-
* @inheritdoc
|
|
313
|
-
*/
|
|
314
|
-
async _removeAttribute(uuid, attribute, itemWriteCondition, itemWriteConditionField) {
|
|
315
|
-
let params = {
|
|
316
|
-
TableName: this.parameters.table,
|
|
317
|
-
Key: {
|
|
318
|
-
uuid
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
let attrs = {};
|
|
322
|
-
attrs["#attr"] = attribute;
|
|
323
|
-
attrs["#lastUpdate"] = "_lastUpdate";
|
|
324
|
-
params.ExpressionAttributeNames = attrs;
|
|
325
|
-
params.ConditionExpression = "attribute_exists(#uu)";
|
|
326
|
-
params.ExpressionAttributeValues = {
|
|
327
|
-
":lastUpdate": this._serializeDate(new Date())
|
|
328
|
-
};
|
|
329
|
-
params.UpdateExpression = "REMOVE #attr SET #lastUpdate = :lastUpdate";
|
|
330
|
-
if (itemWriteCondition) {
|
|
331
|
-
this.setWriteCondition(params, itemWriteCondition, itemWriteConditionField);
|
|
332
|
-
}
|
|
333
|
-
else {
|
|
334
|
-
attrs["#uu"] = "uuid";
|
|
335
|
-
params.ConditionExpression = "attribute_exists(#uu)";
|
|
336
|
-
}
|
|
337
|
-
try {
|
|
338
|
-
await this._client.update(params);
|
|
339
|
-
}
|
|
340
|
-
catch (err) {
|
|
341
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
342
|
-
if (!itemWriteConditionField) {
|
|
343
|
-
throw new StoreNotFoundError(uuid, this.getName());
|
|
344
|
-
}
|
|
345
|
-
throw new UpdateConditionFailError(uuid, itemWriteConditionField, itemWriteCondition);
|
|
346
|
-
}
|
|
347
|
-
throw err;
|
|
348
|
-
}
|
|
349
|
-
}
|
|
350
|
-
/**
|
|
351
|
-
* @inheritdoc
|
|
352
|
-
*/
|
|
353
|
-
async _deleteItemFromCollection(uid, prop, index, itemWriteCondition, itemWriteConditionField, updateDate) {
|
|
354
|
-
let params = {
|
|
355
|
-
TableName: this.parameters.table,
|
|
356
|
-
Key: {
|
|
357
|
-
uuid: uid
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
let attrs = {};
|
|
361
|
-
attrs["#" + prop] = prop;
|
|
362
|
-
attrs["#lastUpdate"] = "_lastUpdate";
|
|
363
|
-
params.ExpressionAttributeNames = attrs;
|
|
364
|
-
params.ExpressionAttributeValues = {
|
|
365
|
-
":lastUpdate": this._serializeDate(updateDate)
|
|
366
|
-
};
|
|
367
|
-
params.UpdateExpression = "REMOVE #" + prop + "[" + index + "] SET #lastUpdate = :lastUpdate";
|
|
368
|
-
if (itemWriteCondition) {
|
|
369
|
-
params.ExpressionAttributeValues[":condValue"] = itemWriteCondition;
|
|
370
|
-
attrs["#condName"] = prop;
|
|
371
|
-
attrs["#field"] = itemWriteConditionField;
|
|
372
|
-
params.ConditionExpression = "#condName[" + index + "].#field = :condValue";
|
|
373
|
-
}
|
|
374
|
-
try {
|
|
375
|
-
await this._client.update(params);
|
|
376
|
-
}
|
|
377
|
-
catch (err) {
|
|
378
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
379
|
-
throw new UpdateConditionFailError(uid, itemWriteConditionField, itemWriteCondition);
|
|
380
|
-
}
|
|
381
|
-
else if (err.name === "ValidationException") {
|
|
382
|
-
throw new StoreNotFoundError(uid, this.getName());
|
|
383
|
-
}
|
|
384
|
-
throw err;
|
|
385
|
-
}
|
|
386
|
-
}
|
|
387
|
-
/**
|
|
388
|
-
* @inheritdoc
|
|
389
|
-
*/
|
|
390
|
-
async _upsertItemToCollection(uuid, prop, item, index, itemWriteCondition, itemWriteConditionField, updateDate) {
|
|
391
|
-
let params = {
|
|
392
|
-
TableName: this.parameters.table,
|
|
393
|
-
Key: {
|
|
394
|
-
uuid
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
let attrValues = {};
|
|
398
|
-
let attrs = {};
|
|
399
|
-
attrs["#" + prop] = prop;
|
|
400
|
-
attrs["#lastUpdate"] = "_lastUpdate";
|
|
401
|
-
attrValues[":" + prop] = this._cleanObject(item);
|
|
402
|
-
attrValues[":lastUpdate"] = this._serializeDate(updateDate);
|
|
403
|
-
attrValues[":uuid"] = uuid;
|
|
404
|
-
attrs["#uuid"] = this._uuidField;
|
|
405
|
-
params.ConditionExpression = "#uuid = :uuid";
|
|
406
|
-
params.ExpressionAttributeValues = attrValues;
|
|
407
|
-
params.ExpressionAttributeNames = attrs;
|
|
408
|
-
if (index === undefined) {
|
|
409
|
-
params.UpdateExpression =
|
|
410
|
-
"SET #" +
|
|
411
|
-
prop +
|
|
412
|
-
"= list_append(if_not_exists (#" +
|
|
413
|
-
prop +
|
|
414
|
-
", :empty_list),:" +
|
|
415
|
-
prop +
|
|
416
|
-
"), #lastUpdate = :lastUpdate";
|
|
417
|
-
attrValues[":" + prop] = [attrValues[":" + prop]];
|
|
418
|
-
attrValues[":empty_list"] = [];
|
|
419
|
-
}
|
|
420
|
-
else {
|
|
421
|
-
params.UpdateExpression = "SET #" + prop + "[" + index + "] = :" + prop + ", #lastUpdate = :lastUpdate";
|
|
422
|
-
if (itemWriteCondition) {
|
|
423
|
-
attrValues[":condValue"] = itemWriteCondition;
|
|
424
|
-
attrs["#condName"] = prop;
|
|
425
|
-
attrs["#field"] = itemWriteConditionField;
|
|
426
|
-
params.ConditionExpression = "#condName[" + index + "].#field = :condValue and #uuid = :uuid";
|
|
427
|
-
}
|
|
428
|
-
}
|
|
429
|
-
try {
|
|
430
|
-
await this._client.update(params);
|
|
431
|
-
}
|
|
432
|
-
catch (err) {
|
|
433
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
434
|
-
throw new UpdateConditionFailError(uuid, itemWriteConditionField, itemWriteCondition);
|
|
435
|
-
}
|
|
436
|
-
else if (err.name === "ValidationException") {
|
|
437
|
-
throw new StoreNotFoundError(uuid, this.getName());
|
|
438
|
-
}
|
|
439
|
-
throw err;
|
|
440
|
-
}
|
|
441
|
-
}
|
|
442
|
-
/**
|
|
443
|
-
* REturn the write condition as string
|
|
444
|
-
* @param writeCondition
|
|
445
|
-
* @param field
|
|
446
|
-
* @returns
|
|
447
|
-
*/
|
|
448
|
-
setWriteCondition(params, writeCondition, field = "_lastUpdate") {
|
|
449
|
-
params.ExpressionAttributeNames ?? (params.ExpressionAttributeNames = {});
|
|
450
|
-
params.ExpressionAttributeValues ?? (params.ExpressionAttributeValues = {});
|
|
451
|
-
params.ExpressionAttributeNames["#cf"] = field;
|
|
452
|
-
if (writeCondition instanceof Date) {
|
|
453
|
-
writeCondition = this._serializeDate(writeCondition);
|
|
454
|
-
}
|
|
455
|
-
params.ExpressionAttributeValues[":cf"] = writeCondition;
|
|
456
|
-
params.ConditionExpression = "#cf = :cf";
|
|
457
|
-
}
|
|
458
|
-
/**
|
|
459
|
-
* @inheritdoc
|
|
460
|
-
*/
|
|
461
|
-
async _delete(uid, writeCondition, itemWriteConditionField) {
|
|
462
|
-
let params = {
|
|
463
|
-
TableName: this.parameters.table,
|
|
464
|
-
Key: {
|
|
465
|
-
uuid: uid
|
|
466
|
-
}
|
|
467
|
-
};
|
|
468
|
-
if (writeCondition) {
|
|
469
|
-
this.setWriteCondition(params, writeCondition, itemWriteConditionField);
|
|
470
|
-
}
|
|
471
|
-
try {
|
|
472
|
-
await this._client.delete(params);
|
|
473
|
-
}
|
|
474
|
-
catch (err) {
|
|
475
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
476
|
-
throw new UpdateConditionFailError(uid, itemWriteConditionField, writeCondition);
|
|
477
|
-
}
|
|
478
|
-
throw err;
|
|
479
|
-
}
|
|
480
|
-
}
|
|
481
|
-
/**
|
|
482
|
-
* @inheritdoc
|
|
483
|
-
*/
|
|
484
|
-
async _patch(object, uid, itemWriteCondition, itemWriteConditionField) {
|
|
485
|
-
object = this._cleanObject(object);
|
|
486
|
-
let expr = "SET ";
|
|
487
|
-
let sep = "";
|
|
488
|
-
let attrValues = {};
|
|
489
|
-
let attrs = {};
|
|
490
|
-
let skipUpdate = true;
|
|
491
|
-
let i = 1;
|
|
492
|
-
for (let attr in object) {
|
|
493
|
-
if (attr === "uuid" || object[attr] === undefined) {
|
|
494
|
-
continue;
|
|
495
|
-
}
|
|
496
|
-
skipUpdate = false;
|
|
497
|
-
expr += sep + "#a" + i + " = :v" + i;
|
|
498
|
-
attrValues[":v" + i] = object[attr];
|
|
499
|
-
attrs["#a" + i] = attr;
|
|
500
|
-
sep = ",";
|
|
501
|
-
i++;
|
|
502
|
-
}
|
|
503
|
-
if (skipUpdate) {
|
|
504
|
-
return;
|
|
505
|
-
}
|
|
506
|
-
let params = {
|
|
507
|
-
TableName: this.parameters.table,
|
|
508
|
-
Key: {
|
|
509
|
-
uuid: uid
|
|
510
|
-
},
|
|
511
|
-
UpdateExpression: expr,
|
|
512
|
-
ExpressionAttributeValues: attrValues,
|
|
513
|
-
ExpressionAttributeNames: attrs
|
|
514
|
-
};
|
|
515
|
-
// The Write Condition checks the value before writing
|
|
516
|
-
if (itemWriteCondition) {
|
|
517
|
-
this.setWriteCondition(params, itemWriteCondition, itemWriteConditionField);
|
|
518
|
-
}
|
|
519
|
-
try {
|
|
520
|
-
await this._client.update(params);
|
|
521
|
-
}
|
|
522
|
-
catch (err) {
|
|
523
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
524
|
-
throw new UpdateConditionFailError(uid, itemWriteConditionField, itemWriteCondition);
|
|
525
|
-
}
|
|
526
|
-
throw err;
|
|
527
|
-
}
|
|
528
|
-
}
|
|
529
|
-
/**
|
|
530
|
-
* @inheritdoc
|
|
531
|
-
*/
|
|
532
|
-
async _update(object, uid, itemWriteCondition, itemWriteConditionField) {
|
|
533
|
-
object = this._cleanObject(object);
|
|
534
|
-
object.uuid = uid;
|
|
535
|
-
let params = {
|
|
536
|
-
TableName: this.parameters.table,
|
|
537
|
-
Item: object
|
|
538
|
-
};
|
|
539
|
-
// The Write Condition checks the value before writing
|
|
540
|
-
if (itemWriteCondition) {
|
|
541
|
-
this.setWriteCondition(params, itemWriteCondition, itemWriteConditionField);
|
|
542
|
-
}
|
|
543
|
-
try {
|
|
544
|
-
await this._client.put(params);
|
|
545
|
-
return object;
|
|
546
|
-
}
|
|
547
|
-
catch (err) {
|
|
548
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
549
|
-
throw new UpdateConditionFailError(uid, itemWriteConditionField, itemWriteCondition);
|
|
550
|
-
}
|
|
551
|
-
throw err;
|
|
552
|
-
}
|
|
553
|
-
}
|
|
554
|
-
/**
|
|
555
|
-
* @inheritdoc
|
|
556
|
-
*/
|
|
557
|
-
async _scan(items = [], paging = undefined) {
|
|
558
|
-
let data = await this._client.scan({
|
|
559
|
-
TableName: this.parameters.table,
|
|
560
|
-
Limit: this.parameters.scanPage,
|
|
561
|
-
ExclusiveStartKey: paging
|
|
562
|
-
});
|
|
563
|
-
for (let i in data.Items) {
|
|
564
|
-
items.push(this.initModel(data.Items[i]));
|
|
565
|
-
}
|
|
566
|
-
if (data.LastEvaluatedKey) {
|
|
567
|
-
return this._scan(items, data.LastEvaluatedKey);
|
|
568
|
-
}
|
|
569
|
-
return items;
|
|
570
|
-
}
|
|
571
|
-
/**
|
|
572
|
-
* @inheritdoc
|
|
573
|
-
*/
|
|
574
|
-
async getAll(uids) {
|
|
575
|
-
if (!uids) {
|
|
576
|
-
return this._scan([]);
|
|
577
|
-
}
|
|
578
|
-
let params = {
|
|
579
|
-
RequestItems: {}
|
|
580
|
-
};
|
|
581
|
-
params["RequestItems"][this.parameters.table] = {
|
|
582
|
-
Keys: uids.map(value => {
|
|
583
|
-
return {
|
|
584
|
-
uuid: value
|
|
585
|
-
};
|
|
586
|
-
})
|
|
587
|
-
};
|
|
588
|
-
let result = await this._client.batchGet(params);
|
|
589
|
-
return result.Responses[this.parameters.table].map(this.initModel, this);
|
|
590
|
-
}
|
|
591
|
-
/**
|
|
592
|
-
* @inheritdoc
|
|
593
|
-
*/
|
|
594
|
-
async _get(uid, raiseIfNotFound = false) {
|
|
595
|
-
let params = {
|
|
596
|
-
TableName: this.parameters.table,
|
|
597
|
-
Key: {
|
|
598
|
-
uuid: uid
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
let item = (await this._client.get(params)).Item;
|
|
602
|
-
if (!item) {
|
|
603
|
-
if (raiseIfNotFound) {
|
|
604
|
-
throw new StoreNotFoundError(uid, this.getName());
|
|
605
|
-
}
|
|
606
|
-
return undefined;
|
|
607
|
-
}
|
|
608
|
-
return this.initModel(item);
|
|
609
|
-
}
|
|
610
|
-
/**
|
|
611
|
-
* @inheritdoc
|
|
612
|
-
*/
|
|
613
|
-
async _incrementAttributes(uid, parameters, updateDate) {
|
|
614
|
-
let params = {
|
|
615
|
-
TableName: this.parameters.table,
|
|
616
|
-
Key: {
|
|
617
|
-
uuid: uid
|
|
618
|
-
},
|
|
619
|
-
UpdateExpression: "SET #ud = :ud ADD ",
|
|
620
|
-
ConditionExpression: "attribute_exists(#uu)",
|
|
621
|
-
ExpressionAttributeValues: {
|
|
622
|
-
":ud": this._serializeDate(updateDate)
|
|
623
|
-
},
|
|
624
|
-
ExpressionAttributeNames: {
|
|
625
|
-
"#ud": "_lastUpdate",
|
|
626
|
-
"#uu": "uuid"
|
|
627
|
-
}
|
|
628
|
-
};
|
|
629
|
-
parameters.forEach((p, i) => {
|
|
630
|
-
params.ExpressionAttributeValues[`:v${i}`] = p.value;
|
|
631
|
-
params.ExpressionAttributeNames[`#a${i}`] = p.property;
|
|
632
|
-
});
|
|
633
|
-
params.UpdateExpression += parameters.map((_, i) => `#a${i} :v${i}`).join(",");
|
|
634
|
-
try {
|
|
635
|
-
return await this._client.update(params);
|
|
636
|
-
}
|
|
637
|
-
catch (err) {
|
|
638
|
-
if (err instanceof ConditionalCheckFailedException) {
|
|
639
|
-
throw new StoreNotFoundError(uid, this.getName());
|
|
640
|
-
}
|
|
641
|
-
throw err;
|
|
642
|
-
}
|
|
643
|
-
}
|
|
644
|
-
/**
|
|
645
|
-
* @inheritdoc
|
|
646
|
-
*/
|
|
647
|
-
getARNPolicy(accountId) {
|
|
648
|
-
let region = this.parameters.region || "us-east-1";
|
|
649
|
-
return {
|
|
650
|
-
Sid: this.constructor.name + this._name,
|
|
651
|
-
Effect: "Allow",
|
|
652
|
-
Action: [
|
|
653
|
-
"dynamodb:BatchGetItem",
|
|
654
|
-
"dynamodb:BatchWriteItem",
|
|
655
|
-
"dynamodb:DeleteItem",
|
|
656
|
-
"dynamodb:GetItem",
|
|
657
|
-
"dynamodb:GetRecords",
|
|
658
|
-
"dynamodb:GetShardIterator",
|
|
659
|
-
"dynamodb:PutItem",
|
|
660
|
-
"dynamodb:Query",
|
|
661
|
-
"dynamodb:Scan",
|
|
662
|
-
"dynamodb:UpdateItem"
|
|
663
|
-
],
|
|
664
|
-
Resource: ["arn:aws:dynamodb:" + region + ":" + accountId + ":table/" + this.parameters.table]
|
|
665
|
-
};
|
|
666
|
-
}
|
|
667
|
-
/**
|
|
668
|
-
* @inheritdoc
|
|
669
|
-
*/
|
|
670
|
-
async __clean() {
|
|
671
|
-
let params = {
|
|
672
|
-
TableName: this.parameters.table
|
|
673
|
-
};
|
|
674
|
-
let result = await this._client.scan(params);
|
|
675
|
-
let promises = [];
|
|
676
|
-
for (let i in result.Items) {
|
|
677
|
-
promises.push(this._delete(result.Items[i].uuid));
|
|
678
|
-
}
|
|
679
|
-
await Promise.all(promises);
|
|
680
|
-
}
|
|
681
|
-
/**
|
|
682
|
-
* @inheritdoc
|
|
683
|
-
*/
|
|
684
|
-
getCloudFormation(deployer) {
|
|
685
|
-
if (this.parameters.CloudFormationSkip) {
|
|
686
|
-
return {};
|
|
687
|
-
}
|
|
688
|
-
let resources = {};
|
|
689
|
-
this.parameters.CloudFormation = this.parameters.CloudFormation || {};
|
|
690
|
-
this.parameters.CloudFormation.Table = this.parameters.CloudFormation.Table || {};
|
|
691
|
-
let KeySchema = this.parameters.CloudFormation.KeySchema || [{ KeyType: "HASH", AttributeName: "uuid" }];
|
|
692
|
-
let AttributeDefinitions = this.parameters.CloudFormation.AttributeDefinitions || [];
|
|
693
|
-
this.parameters.CloudFormation.Table.BillingMode =
|
|
694
|
-
this.parameters.CloudFormation.Table.BillingMode || "PAY_PER_REQUEST";
|
|
695
|
-
AttributeDefinitions.push({ AttributeName: "uuid", AttributeType: "S" });
|
|
696
|
-
resources[this._name + "DynamoTable"] = {
|
|
697
|
-
Type: "AWS::DynamoDB::Table",
|
|
698
|
-
Properties: {
|
|
699
|
-
...this.parameters.CloudFormation.Table,
|
|
700
|
-
TableName: this.parameters.table,
|
|
701
|
-
KeySchema,
|
|
702
|
-
AttributeDefinitions,
|
|
703
|
-
Tags: deployer.getDefaultTags(this.parameters.CloudFormation.Table.Tags)
|
|
704
|
-
}
|
|
705
|
-
};
|
|
706
|
-
// Add any Other resources with prefix of the service
|
|
707
|
-
return resources;
|
|
708
|
-
}
|
|
709
|
-
}
|
|
710
|
-
export { DynamoStore };
|
|
711
|
-
//# sourceMappingURL=dynamodb.js.map
|