@webda/aws 4.0.0-beta.2 → 4.0.0-beta.4
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/deployers/awsdeployer.d.ts +340 -0
- package/lib/deployers/awsdeployer.d.ts.map +1 -0
- package/lib/deployers/awsdeployer.js +673 -0
- package/lib/deployers/awsdeployer.js.map +1 -0
- package/lib/deployers/cloudformation.service.d.ts +438 -0
- package/lib/deployers/cloudformation.service.d.ts.map +1 -0
- package/lib/deployers/cloudformation.service.js +889 -0
- package/lib/deployers/cloudformation.service.js.map +1 -0
- package/lib/deployers/index.d.ts +4 -254
- package/lib/deployers/index.d.ts.map +1 -1
- package/lib/deployers/index.js +4 -542
- package/lib/deployers/index.js.map +1 -1
- package/lib/deployers/lambda-entrypoint.d.ts +33 -1
- package/lib/deployers/lambda-entrypoint.d.ts.map +1 -1
- package/lib/deployers/lambda-entrypoint.js +44 -10
- package/lib/deployers/lambda-entrypoint.js.map +1 -1
- package/lib/deployers/lambdapackager.service.d.ts +123 -0
- package/lib/deployers/lambdapackager.service.d.ts.map +1 -0
- package/lib/deployers/lambdapackager.service.js +149 -0
- package/lib/deployers/lambdapackager.service.js.map +1 -0
- package/lib/deployers/zip.d.ts +42 -0
- package/lib/deployers/zip.d.ts.map +1 -0
- package/lib/deployers/zip.js +129 -0
- package/lib/deployers/zip.js.map +1 -0
- package/lib/index.d.ts +1 -0
- package/lib/index.d.ts.map +1 -1
- package/lib/index.js +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} +60 -28
- package/lib/services/cloudwatchlogger.service.js.map +1 -0
- package/lib/services/contributors.d.ts +36 -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 +298 -0
- package/lib/services/dynamodb.service.d.ts.map +1 -0
- package/lib/services/dynamodb.service.js +986 -0
- package/lib/services/dynamodb.service.js.map +1 -0
- package/lib/services/index.d.ts +11 -31
- package/lib/services/index.d.ts.map +1 -1
- 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 -12
- package/lib/services/route53.service.d.ts.map +1 -0
- package/lib/services/{route53.js → route53.service.js} +25 -28
- 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} +93 -55
- 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} +40 -22
- package/lib/services/secretsmanager.service.js.map +1 -0
- package/lib/services/{sqsqueue.d.ts → sqsqueue.service.d.ts} +60 -35
- package/lib/services/sqsqueue.service.d.ts.map +1 -0
- package/lib/services/{sqsqueue.js → sqsqueue.service.js} +53 -28
- package/lib/services/sqsqueue.service.js.map +1 -0
- package/package.json +56 -64
- package/webda.module.json +1425 -264
- package/lib/deployers/cloudformation.d.ts +0 -317
- package/lib/deployers/cloudformation.d.ts.map +0 -1
- package/lib/deployers/cloudformation.js +0 -837
- package/lib/deployers/cloudformation.js.map +0 -1
- package/lib/deployers/cloudformation.spec.d.ts +0 -2
- package/lib/deployers/cloudformation.spec.d.ts.map +0 -1
- package/lib/deployers/cloudformation.spec.js +0 -530
- package/lib/deployers/cloudformation.spec.js.map +0 -1
- package/lib/deployers/index.spec.d.ts +0 -9
- package/lib/deployers/index.spec.d.ts.map +0 -1
- package/lib/deployers/index.spec.js +0 -595
- package/lib/deployers/index.spec.js.map +0 -1
- package/lib/deployers/lambdapackager.d.ts +0 -28
- package/lib/deployers/lambdapackager.d.ts.map +0 -1
- package/lib/deployers/lambdapackager.js +0 -26
- package/lib/deployers/lambdapackager.js.map +0 -1
- package/lib/deployers/lambdapackager.spec.d.ts +0 -2
- package/lib/deployers/lambdapackager.spec.d.ts.map +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 -11
- package/lib/index.spec.d.ts.map +0 -1
- package/lib/index.spec.js +0 -42
- package/lib/index.spec.js.map +0 -1
- package/lib/services/aws-mixin.d.ts +0 -25
- package/lib/services/aws-mixin.d.ts.map +0 -1
- package/lib/services/aws-mixin.js +0 -18
- package/lib/services/aws-mixin.js.map +0 -1
- package/lib/services/cloudwatchlogger.d.ts +0 -82
- package/lib/services/cloudwatchlogger.d.ts.map +0 -1
- package/lib/services/cloudwatchlogger.js.map +0 -1
- package/lib/services/cloudwatchlogger.spec.d.ts +0 -2
- package/lib/services/cloudwatchlogger.spec.d.ts.map +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 -174
- package/lib/services/dynamodb.d.ts.map +0 -1
- package/lib/services/dynamodb.js +0 -711
- package/lib/services/dynamodb.js.map +0 -1
- package/lib/services/dynamodb.spec.d.ts +0 -24
- package/lib/services/dynamodb.spec.d.ts.map +0 -1
- package/lib/services/dynamodb.spec.js +0 -344
- package/lib/services/dynamodb.spec.js.map +0 -1
- package/lib/services/lambdacaller.d.ts +0 -69
- package/lib/services/lambdacaller.d.ts.map +0 -1
- package/lib/services/lambdacaller.js +0 -63
- package/lib/services/lambdacaller.js.map +0 -1
- package/lib/services/lambdacaller.spec.d.ts +0 -2
- package/lib/services/lambdacaller.spec.d.ts.map +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 -87
- package/lib/services/lambdaserver.d.ts.map +0 -1
- package/lib/services/lambdaserver.js +0 -263
- package/lib/services/lambdaserver.js.map +0 -1
- package/lib/services/lambdaserver.spec.d.ts +0 -2
- package/lib/services/lambdaserver.spec.d.ts.map +0 -1
- package/lib/services/lambdaserver.spec.js +0 -417
- package/lib/services/lambdaserver.spec.js.map +0 -1
- package/lib/services/route53.d.ts.map +0 -1
- package/lib/services/route53.js.map +0 -1
- package/lib/services/route53.spec.d.ts +0 -2
- package/lib/services/route53.spec.d.ts.map +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 -163
- package/lib/services/s3binary.d.ts.map +0 -1
- package/lib/services/s3binary.js.map +0 -1
- package/lib/services/s3binary.spec.d.ts +0 -2
- package/lib/services/s3binary.spec.d.ts.map +0 -1
- package/lib/services/s3binary.spec.js +0 -284
- package/lib/services/s3binary.spec.js.map +0 -1
- package/lib/services/secretsmanager.d.ts +0 -81
- package/lib/services/secretsmanager.d.ts.map +0 -1
- package/lib/services/secretsmanager.js.map +0 -1
- package/lib/services/secretsmanager.spec.d.ts +0 -2
- package/lib/services/secretsmanager.spec.d.ts.map +0 -1
- package/lib/services/secretsmanager.spec.js +0 -66
- package/lib/services/secretsmanager.spec.js.map +0 -1
- package/lib/services/sqsqueue.d.ts.map +0 -1
- package/lib/services/sqsqueue.js.map +0 -1
- package/lib/services/sqsqueue.spec.d.ts +0 -2
- package/lib/services/sqsqueue.spec.d.ts.map +0 -1
- package/lib/services/sqsqueue.spec.js +0 -157
- package/lib/services/sqsqueue.spec.js.map +0 -1
- package/lib/shell.d.ts +0 -13
- package/lib/shell.d.ts.map +0 -1
- 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
|
-
const db = new DynamoDB({});
|
|
59
|
-
let ExclusiveStartKey;
|
|
60
|
-
const props = await db.describeTable({
|
|
61
|
-
TableName: source
|
|
62
|
-
});
|
|
63
|
-
output.startProgress("copyTable", props.Table.ItemCount, `Copying ${source} to ${target}`);
|
|
64
|
-
do {
|
|
65
|
-
const info = await db.scan({
|
|
66
|
-
TableName: source,
|
|
67
|
-
ExclusiveStartKey
|
|
68
|
-
});
|
|
69
|
-
do {
|
|
70
|
-
const items = [];
|
|
71
|
-
while (info.Items.length && items.length < 25) {
|
|
72
|
-
items.push(info.Items.shift());
|
|
73
|
-
}
|
|
74
|
-
if (!items.length) {
|
|
75
|
-
break;
|
|
76
|
-
}
|
|
77
|
-
const 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
|
-
const 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
|
-
const filter = new WebdaQL.AndExpression([]);
|
|
118
|
-
let KeyConditionExpression = "";
|
|
119
|
-
let ExpressionAttributeValues = {};
|
|
120
|
-
const 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
|
-
const attr = `a${count++}`;
|
|
184
|
-
let fullAttr = `#${attr}`;
|
|
185
|
-
child.attribute.slice(1).forEach(v => {
|
|
186
|
-
const 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
|
-
const 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 (const 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
|
-
const params = {
|
|
316
|
-
TableName: this.parameters.table,
|
|
317
|
-
Key: {
|
|
318
|
-
uuid
|
|
319
|
-
}
|
|
320
|
-
};
|
|
321
|
-
const 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
|
-
const params = {
|
|
355
|
-
TableName: this.parameters.table,
|
|
356
|
-
Key: {
|
|
357
|
-
uuid: uid
|
|
358
|
-
}
|
|
359
|
-
};
|
|
360
|
-
const 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
|
-
const params = {
|
|
392
|
-
TableName: this.parameters.table,
|
|
393
|
-
Key: {
|
|
394
|
-
uuid
|
|
395
|
-
}
|
|
396
|
-
};
|
|
397
|
-
const attrValues = {};
|
|
398
|
-
const 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
|
-
const 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
|
-
const attrValues = {};
|
|
489
|
-
const attrs = {};
|
|
490
|
-
let skipUpdate = true;
|
|
491
|
-
let i = 1;
|
|
492
|
-
for (const 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
|
-
const 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
|
-
const 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
|
-
const data = await this._client.scan({
|
|
559
|
-
TableName: this.parameters.table,
|
|
560
|
-
Limit: this.parameters.scanPage,
|
|
561
|
-
ExclusiveStartKey: paging
|
|
562
|
-
});
|
|
563
|
-
for (const 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
|
-
const params = {
|
|
579
|
-
RequestItems: {}
|
|
580
|
-
};
|
|
581
|
-
params["RequestItems"][this.parameters.table] = {
|
|
582
|
-
Keys: uids.map(value => {
|
|
583
|
-
return {
|
|
584
|
-
uuid: value
|
|
585
|
-
};
|
|
586
|
-
})
|
|
587
|
-
};
|
|
588
|
-
const 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
|
-
const params = {
|
|
596
|
-
TableName: this.parameters.table,
|
|
597
|
-
Key: {
|
|
598
|
-
uuid: uid
|
|
599
|
-
}
|
|
600
|
-
};
|
|
601
|
-
const 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
|
-
const 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
|
-
const 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
|
-
const params = {
|
|
672
|
-
TableName: this.parameters.table
|
|
673
|
-
};
|
|
674
|
-
const result = await this._client.scan(params);
|
|
675
|
-
const promises = [];
|
|
676
|
-
for (const 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
|
-
const resources = {};
|
|
689
|
-
this.parameters.CloudFormation = this.parameters.CloudFormation || {};
|
|
690
|
-
this.parameters.CloudFormation.Table = this.parameters.CloudFormation.Table || {};
|
|
691
|
-
const KeySchema = this.parameters.CloudFormation.KeySchema || [{ KeyType: "HASH", AttributeName: "uuid" }];
|
|
692
|
-
const 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
|