@webda/aws 4.0.0-beta.2 → 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.
Files changed (151) hide show
  1. package/README.md +64 -7
  2. package/lib/index.d.ts.map +1 -1
  3. package/lib/index.js.map +1 -1
  4. package/lib/services/aws-parameters.d.ts +33 -0
  5. package/lib/services/aws-parameters.d.ts.map +1 -0
  6. package/lib/services/aws-parameters.js +18 -0
  7. package/lib/services/aws-parameters.js.map +1 -0
  8. package/lib/services/awscommands.service.d.ts +39 -0
  9. package/lib/services/awscommands.service.d.ts.map +1 -0
  10. package/lib/services/awscommands.service.js +127 -0
  11. package/lib/services/awscommands.service.js.map +1 -0
  12. package/lib/services/cloudwatchlogger.service.d.ts +131 -0
  13. package/lib/services/cloudwatchlogger.service.d.ts.map +1 -0
  14. package/lib/services/{cloudwatchlogger.js → cloudwatchlogger.service.js} +60 -28
  15. package/lib/services/cloudwatchlogger.service.js.map +1 -0
  16. package/lib/services/contributors.d.ts +37 -0
  17. package/lib/services/contributors.d.ts.map +1 -0
  18. package/lib/services/contributors.js +2 -0
  19. package/lib/services/contributors.js.map +1 -0
  20. package/lib/services/dynamodb.service.d.ts +297 -0
  21. package/lib/services/dynamodb.service.d.ts.map +1 -0
  22. package/lib/services/dynamodb.service.js +985 -0
  23. package/lib/services/dynamodb.service.js.map +1 -0
  24. package/lib/services/index.d.ts +11 -31
  25. package/lib/services/index.d.ts.map +1 -1
  26. package/lib/services/index.js +11 -8
  27. package/lib/services/index.js.map +1 -1
  28. package/lib/services/lambdacaller.service.d.ts +81 -0
  29. package/lib/services/lambdacaller.service.d.ts.map +1 -0
  30. package/lib/services/lambdacaller.service.js +75 -0
  31. package/lib/services/lambdacaller.service.js.map +1 -0
  32. package/lib/services/lambdaserver.service.d.ts +127 -0
  33. package/lib/services/lambdaserver.service.d.ts.map +1 -0
  34. package/lib/services/lambdaserver.service.js +294 -0
  35. package/lib/services/lambdaserver.service.js.map +1 -0
  36. package/lib/services/{route53.d.ts → route53.service.d.ts} +21 -12
  37. package/lib/services/route53.service.d.ts.map +1 -0
  38. package/lib/services/{route53.js → route53.service.js} +25 -28
  39. package/lib/services/route53.service.js.map +1 -0
  40. package/lib/services/s3binary.service.d.ts +215 -0
  41. package/lib/services/s3binary.service.d.ts.map +1 -0
  42. package/lib/services/{s3binary.js → s3binary.service.js} +93 -55
  43. package/lib/services/s3binary.service.js.map +1 -0
  44. package/lib/services/secretsmanager.service.d.ts +102 -0
  45. package/lib/services/secretsmanager.service.d.ts.map +1 -0
  46. package/lib/services/{secretsmanager.js → secretsmanager.service.js} +40 -22
  47. package/lib/services/secretsmanager.service.js.map +1 -0
  48. package/lib/services/{sqsqueue.d.ts → sqsqueue.service.d.ts} +60 -35
  49. package/lib/services/sqsqueue.service.d.ts.map +1 -0
  50. package/lib/services/{sqsqueue.js → sqsqueue.service.js} +53 -28
  51. package/lib/services/sqsqueue.service.js.map +1 -0
  52. package/package.json +58 -63
  53. package/webda.module.json +743 -280
  54. package/lib/deployers/cloudformation.d.ts +0 -317
  55. package/lib/deployers/cloudformation.d.ts.map +0 -1
  56. package/lib/deployers/cloudformation.js +0 -837
  57. package/lib/deployers/cloudformation.js.map +0 -1
  58. package/lib/deployers/cloudformation.spec.d.ts +0 -2
  59. package/lib/deployers/cloudformation.spec.d.ts.map +0 -1
  60. package/lib/deployers/cloudformation.spec.js +0 -530
  61. package/lib/deployers/cloudformation.spec.js.map +0 -1
  62. package/lib/deployers/index.d.ts +0 -255
  63. package/lib/deployers/index.d.ts.map +0 -1
  64. package/lib/deployers/index.js +0 -543
  65. package/lib/deployers/index.js.map +0 -1
  66. package/lib/deployers/index.spec.d.ts +0 -9
  67. package/lib/deployers/index.spec.d.ts.map +0 -1
  68. package/lib/deployers/index.spec.js +0 -595
  69. package/lib/deployers/index.spec.js.map +0 -1
  70. package/lib/deployers/lambda-entrypoint.d.ts +0 -2
  71. package/lib/deployers/lambda-entrypoint.d.ts.map +0 -1
  72. package/lib/deployers/lambda-entrypoint.js +0 -13
  73. package/lib/deployers/lambda-entrypoint.js.map +0 -1
  74. package/lib/deployers/lambdapackager.d.ts +0 -28
  75. package/lib/deployers/lambdapackager.d.ts.map +0 -1
  76. package/lib/deployers/lambdapackager.js +0 -26
  77. package/lib/deployers/lambdapackager.js.map +0 -1
  78. package/lib/deployers/lambdapackager.spec.d.ts +0 -2
  79. package/lib/deployers/lambdapackager.spec.d.ts.map +0 -1
  80. package/lib/deployers/lambdapackager.spec.js +0 -44
  81. package/lib/deployers/lambdapackager.spec.js.map +0 -1
  82. package/lib/index.spec.d.ts +0 -11
  83. package/lib/index.spec.d.ts.map +0 -1
  84. package/lib/index.spec.js +0 -42
  85. package/lib/index.spec.js.map +0 -1
  86. package/lib/services/aws-mixin.d.ts +0 -25
  87. package/lib/services/aws-mixin.d.ts.map +0 -1
  88. package/lib/services/aws-mixin.js +0 -18
  89. package/lib/services/aws-mixin.js.map +0 -1
  90. package/lib/services/cloudwatchlogger.d.ts +0 -82
  91. package/lib/services/cloudwatchlogger.d.ts.map +0 -1
  92. package/lib/services/cloudwatchlogger.js.map +0 -1
  93. package/lib/services/cloudwatchlogger.spec.d.ts +0 -2
  94. package/lib/services/cloudwatchlogger.spec.d.ts.map +0 -1
  95. package/lib/services/cloudwatchlogger.spec.js +0 -104
  96. package/lib/services/cloudwatchlogger.spec.js.map +0 -1
  97. package/lib/services/dynamodb.d.ts +0 -174
  98. package/lib/services/dynamodb.d.ts.map +0 -1
  99. package/lib/services/dynamodb.js +0 -711
  100. package/lib/services/dynamodb.js.map +0 -1
  101. package/lib/services/dynamodb.spec.d.ts +0 -24
  102. package/lib/services/dynamodb.spec.d.ts.map +0 -1
  103. package/lib/services/dynamodb.spec.js +0 -344
  104. package/lib/services/dynamodb.spec.js.map +0 -1
  105. package/lib/services/lambdacaller.d.ts +0 -69
  106. package/lib/services/lambdacaller.d.ts.map +0 -1
  107. package/lib/services/lambdacaller.js +0 -63
  108. package/lib/services/lambdacaller.js.map +0 -1
  109. package/lib/services/lambdacaller.spec.d.ts +0 -2
  110. package/lib/services/lambdacaller.spec.d.ts.map +0 -1
  111. package/lib/services/lambdacaller.spec.js +0 -70
  112. package/lib/services/lambdacaller.spec.js.map +0 -1
  113. package/lib/services/lambdaserver.d.ts +0 -87
  114. package/lib/services/lambdaserver.d.ts.map +0 -1
  115. package/lib/services/lambdaserver.js +0 -263
  116. package/lib/services/lambdaserver.js.map +0 -1
  117. package/lib/services/lambdaserver.spec.d.ts +0 -2
  118. package/lib/services/lambdaserver.spec.d.ts.map +0 -1
  119. package/lib/services/lambdaserver.spec.js +0 -417
  120. package/lib/services/lambdaserver.spec.js.map +0 -1
  121. package/lib/services/route53.d.ts.map +0 -1
  122. package/lib/services/route53.js.map +0 -1
  123. package/lib/services/route53.spec.d.ts +0 -2
  124. package/lib/services/route53.spec.d.ts.map +0 -1
  125. package/lib/services/route53.spec.js +0 -102
  126. package/lib/services/route53.spec.js.map +0 -1
  127. package/lib/services/s3binary.d.ts +0 -163
  128. package/lib/services/s3binary.d.ts.map +0 -1
  129. package/lib/services/s3binary.js.map +0 -1
  130. package/lib/services/s3binary.spec.d.ts +0 -2
  131. package/lib/services/s3binary.spec.d.ts.map +0 -1
  132. package/lib/services/s3binary.spec.js +0 -284
  133. package/lib/services/s3binary.spec.js.map +0 -1
  134. package/lib/services/secretsmanager.d.ts +0 -81
  135. package/lib/services/secretsmanager.d.ts.map +0 -1
  136. package/lib/services/secretsmanager.js.map +0 -1
  137. package/lib/services/secretsmanager.spec.d.ts +0 -2
  138. package/lib/services/secretsmanager.spec.d.ts.map +0 -1
  139. package/lib/services/secretsmanager.spec.js +0 -66
  140. package/lib/services/secretsmanager.spec.js.map +0 -1
  141. package/lib/services/sqsqueue.d.ts.map +0 -1
  142. package/lib/services/sqsqueue.js.map +0 -1
  143. package/lib/services/sqsqueue.spec.d.ts +0 -2
  144. package/lib/services/sqsqueue.spec.d.ts.map +0 -1
  145. package/lib/services/sqsqueue.spec.js +0 -157
  146. package/lib/services/sqsqueue.spec.js.map +0 -1
  147. package/lib/shell.d.ts +0 -13
  148. package/lib/shell.d.ts.map +0 -1
  149. package/lib/shell.js +0 -42
  150. package/lib/shell.js.map +0 -1
  151. package/webda.shell.json +0 -11
@@ -0,0 +1,985 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { ConditionalCheckFailedException, DynamoDB, DynamoDBClient } from "@aws-sdk/client-dynamodb";
36
+ import { DynamoDBDocument } from "@aws-sdk/lib-dynamodb";
37
+ import { EventRepository, InstanceCache, MemoryRepository, Store, StoreNotFoundError, StoreParameters, UpdateConditionFailError, useModel, useModelMetadata, WebdaError } from "@webda/core";
38
+ import * as WebdaQL from "@webda/ql";
39
+ import { loadAWSParameters } from "./aws-parameters.js";
40
+ /**
41
+ * Name of the DynamoDB hash key attribute
42
+ */
43
+ const KEY_ATTRIBUTE = "uuid";
44
+ /**
45
+ * Attribute storing the model identifier, used to rebuild subclasses
46
+ */
47
+ const TYPE_ATTRIBUTE = "__type";
48
+ /**
49
+ * Define DynamoDB parameters
50
+ */
51
+ export class DynamoStoreParameters extends StoreParameters {
52
+ /**
53
+ * @override
54
+ * @param params - raw parameters
55
+ * @returns this
56
+ */
57
+ load(params = {}) {
58
+ super.load(params);
59
+ loadAWSParameters(this);
60
+ if (this.table === undefined) {
61
+ throw new WebdaError.CodeError("DYNAMODB_TABLE_PARAMETER_REQUIRED", "Need to define a table at least");
62
+ }
63
+ this.globalIndexes ?? (this.globalIndexes = {});
64
+ this.tables ?? (this.tables = {});
65
+ return this;
66
+ }
67
+ }
68
+ /**
69
+ * Serialize a date for DynamoDB
70
+ * @param date - the date to serialize
71
+ * @returns ISO string
72
+ */
73
+ function serializeDate(date) {
74
+ return date.toISOString();
75
+ }
76
+ /**
77
+ * Clean an object to store in DynamoDB
78
+ *
79
+ * Dates are converted to ISO strings, empty strings and undefined values are removed
80
+ *
81
+ * @param object - the value to clean
82
+ * @returns the cleaned value
83
+ */
84
+ export function cleanObject(object) {
85
+ if (object === null || typeof object !== "object")
86
+ return object;
87
+ if (object instanceof Date) {
88
+ return serializeDate(object);
89
+ }
90
+ if (typeof object.toJSON === "function" && !Array.isArray(object)) {
91
+ const json = object.toJSON();
92
+ if (json !== object) {
93
+ return cleanObject(json);
94
+ }
95
+ }
96
+ const res = Array.isArray(object) ? [] : {};
97
+ for (const i in object) {
98
+ if (object[i] === "" || object[i] === undefined || typeof object[i] === "function") {
99
+ continue;
100
+ }
101
+ res[i] = cleanObject(object[i]);
102
+ }
103
+ return res;
104
+ }
105
+ /**
106
+ * DynamoDB-backed repository for a single model class
107
+ *
108
+ * Every object is stored as one item, keyed by the string primary key in the
109
+ * `uuid` hash key attribute.
110
+ */
111
+ export class DynamoRepository extends MemoryRepository {
112
+ /**
113
+ * Create a new DynamoRepository
114
+ * @param model - the model class
115
+ * @param pks - primary key field names
116
+ * @param client - the DynamoDB document client
117
+ * @param table - the table name
118
+ * @param globalIndexes - global secondary indexes usable by queries
119
+ * @param scanPage - scan page size used by __clean
120
+ * @param storeName - store name used in errors
121
+ */
122
+ constructor(model, pks, client, table, globalIndexes = {}, scanPage, storeName = table) {
123
+ // Pass an empty Map — we do NOT use in-memory storage
124
+ super(model, pks, undefined, new Map());
125
+ this.client = client;
126
+ this.table = table;
127
+ this.globalIndexes = globalIndexes;
128
+ this.scanPage = scanPage;
129
+ this.storeName = storeName;
130
+ }
131
+ /**
132
+ * The backing table name
133
+ * @returns the table name
134
+ */
135
+ getTable() {
136
+ return this.table;
137
+ }
138
+ /**
139
+ * Return the DynamoDB key of an object or primary key
140
+ * @param primaryKey - the object or primary key
141
+ * @returns the string key
142
+ */
143
+ getKey(primaryKey) {
144
+ return this.getPrimaryKey(primaryKey).toString();
145
+ }
146
+ /**
147
+ * Convert a model or plain object to a DynamoDB item
148
+ * @param data - the object to convert
149
+ * @returns the item
150
+ */
151
+ toItem(data) {
152
+ const item = cleanObject(data);
153
+ item[KEY_ATTRIBUTE] = this.getKey(data);
154
+ item[TYPE_ATTRIBUTE] = data?.constructor?.Metadata?.Identifier ?? this.model.Metadata?.Identifier;
155
+ if (item[TYPE_ATTRIBUTE] === undefined) {
156
+ delete item[TYPE_ATTRIBUTE];
157
+ }
158
+ return item;
159
+ }
160
+ /**
161
+ * Convert a DynamoDB item to a model instance
162
+ *
163
+ * The `__type` attribute is used to instantiate the right subclass
164
+ * @param item - the DynamoDB item
165
+ * @returns the model instance
166
+ */
167
+ fromItem(item) {
168
+ const data = { ...item };
169
+ let model = this.model;
170
+ const type = data[TYPE_ATTRIBUTE];
171
+ delete data[TYPE_ATTRIBUTE];
172
+ if (type && type !== this.model.Metadata?.Identifier) {
173
+ try {
174
+ model = useModel(type) ?? this.model;
175
+ }
176
+ catch {
177
+ model = this.model;
178
+ }
179
+ }
180
+ if (!this.pks.includes(KEY_ATTRIBUTE)) {
181
+ delete data[KEY_ATTRIBUTE];
182
+ }
183
+ const instance = new model({});
184
+ if (typeof instance.load === "function") {
185
+ instance.load(data);
186
+ }
187
+ else {
188
+ Object.assign(instance, data);
189
+ }
190
+ if (type) {
191
+ Object.defineProperty(instance, TYPE_ATTRIBUTE, {
192
+ value: type,
193
+ enumerable: false,
194
+ configurable: true,
195
+ writable: true
196
+ });
197
+ }
198
+ return instance;
199
+ }
200
+ /**
201
+ * Add a write condition to the DynamoDB parameters
202
+ * @param params - the DynamoDB parameters
203
+ * @param writeCondition - the expected value
204
+ * @param field - the field to check
205
+ */
206
+ setWriteCondition(params, writeCondition, field) {
207
+ params.ExpressionAttributeNames ?? (params.ExpressionAttributeNames = {});
208
+ params.ExpressionAttributeValues ?? (params.ExpressionAttributeValues = {});
209
+ params.ExpressionAttributeNames["#cf"] = field;
210
+ if (writeCondition instanceof Date) {
211
+ writeCondition = serializeDate(writeCondition);
212
+ }
213
+ params.ExpressionAttributeValues[":cf"] = writeCondition;
214
+ params.ConditionExpression = params.ConditionExpression
215
+ ? `${params.ConditionExpression} AND #cf = :cf`
216
+ : "#cf = :cf";
217
+ }
218
+ /**
219
+ * Build a document path expression for an attribute like `team.id`
220
+ * @param attribute - the attribute path
221
+ * @param names - expression attribute names to fill
222
+ * @param prefix - placeholder prefix
223
+ * @returns the path expression
224
+ */
225
+ attributePath(attribute, names, prefix) {
226
+ return attribute
227
+ .split(".")
228
+ .map((part, i) => {
229
+ names[`#${prefix}${i}`] = part;
230
+ return `#${prefix}${i}`;
231
+ })
232
+ .join(".");
233
+ }
234
+ /** @override */
235
+ async get(primaryKey) {
236
+ const key = this.getKey(primaryKey);
237
+ const item = (await this.client.get({
238
+ TableName: this.table,
239
+ Key: { [KEY_ATTRIBUTE]: key }
240
+ })).Item;
241
+ if (!item) {
242
+ throw new StoreNotFoundError(key, this.storeName);
243
+ }
244
+ return this.fromItem(item);
245
+ }
246
+ /** @override */
247
+ async exists(primaryKey) {
248
+ const item = (await this.client.get({
249
+ TableName: this.table,
250
+ Key: { [KEY_ATTRIBUTE]: this.getKey(primaryKey) },
251
+ ProjectionExpression: "#k",
252
+ ExpressionAttributeNames: { "#k": KEY_ATTRIBUTE }
253
+ })).Item;
254
+ return item !== undefined;
255
+ }
256
+ /** @override */
257
+ async create(data, save = true) {
258
+ // Build once so a generated primary key is kept (and not reset by an undefined one in data)
259
+ const item = this.buildItem(data);
260
+ if (save === false) {
261
+ return item;
262
+ }
263
+ const key = this.getKey(item);
264
+ try {
265
+ await this.client.put({
266
+ TableName: this.table,
267
+ Item: this.toItem(item),
268
+ ConditionExpression: "attribute_not_exists(#k)",
269
+ ExpressionAttributeNames: { "#k": KEY_ATTRIBUTE }
270
+ });
271
+ }
272
+ catch (err) {
273
+ if (err instanceof ConditionalCheckFailedException) {
274
+ throw new Error(`Already exists: ${key}`);
275
+ }
276
+ throw err;
277
+ }
278
+ return item;
279
+ }
280
+ /** @override */
281
+ async update(data, conditionField, condition) {
282
+ const key = this.getKey(data);
283
+ const params = {
284
+ TableName: this.table,
285
+ Item: this.toItem(data),
286
+ ConditionExpression: "attribute_exists(#k)",
287
+ ExpressionAttributeNames: { "#k": KEY_ATTRIBUTE }
288
+ };
289
+ if (conditionField) {
290
+ this.setWriteCondition(params, condition, conditionField);
291
+ }
292
+ try {
293
+ await this.client.put(params);
294
+ }
295
+ catch (err) {
296
+ if (err instanceof ConditionalCheckFailedException) {
297
+ if (!conditionField) {
298
+ throw new StoreNotFoundError(key, this.storeName);
299
+ }
300
+ throw new UpdateConditionFailError(key, conditionField, condition);
301
+ }
302
+ throw err;
303
+ }
304
+ }
305
+ /** @override */
306
+ async patch(primaryKey, data, conditionField, condition) {
307
+ const key = this.getKey(primaryKey);
308
+ const object = cleanObject(data);
309
+ const sets = [];
310
+ const ExpressionAttributeValues = {};
311
+ const ExpressionAttributeNames = { "#k": KEY_ATTRIBUTE };
312
+ let i = 1;
313
+ for (const attr in object) {
314
+ if (attr === KEY_ATTRIBUTE || this.pks.includes(attr) || object[attr] === undefined) {
315
+ continue;
316
+ }
317
+ sets.push(`#a${i} = :v${i}`);
318
+ ExpressionAttributeValues[`:v${i}`] = object[attr];
319
+ ExpressionAttributeNames[`#a${i}`] = attr;
320
+ i++;
321
+ }
322
+ if (!sets.length) {
323
+ return;
324
+ }
325
+ const params = {
326
+ TableName: this.table,
327
+ Key: { [KEY_ATTRIBUTE]: key },
328
+ UpdateExpression: "SET " + sets.join(", "),
329
+ ConditionExpression: "attribute_exists(#k)",
330
+ ExpressionAttributeValues,
331
+ ExpressionAttributeNames
332
+ };
333
+ // The Write Condition checks the value before writing
334
+ if (conditionField) {
335
+ this.setWriteCondition(params, condition, conditionField);
336
+ }
337
+ try {
338
+ await this.client.update(params);
339
+ }
340
+ catch (err) {
341
+ if (err instanceof ConditionalCheckFailedException) {
342
+ if (!conditionField) {
343
+ throw new StoreNotFoundError(key, this.storeName);
344
+ }
345
+ throw new UpdateConditionFailError(key, conditionField, condition);
346
+ }
347
+ throw err;
348
+ }
349
+ }
350
+ /** @override */
351
+ async delete(primaryKey, conditionField, condition) {
352
+ const key = this.getKey(primaryKey);
353
+ const params = {
354
+ TableName: this.table,
355
+ Key: { [KEY_ATTRIBUTE]: key }
356
+ };
357
+ if (conditionField) {
358
+ this.setWriteCondition(params, condition, conditionField);
359
+ }
360
+ try {
361
+ await this.client.delete(params);
362
+ }
363
+ catch (err) {
364
+ if (err instanceof ConditionalCheckFailedException) {
365
+ throw new UpdateConditionFailError(key, conditionField, condition);
366
+ }
367
+ throw err;
368
+ }
369
+ }
370
+ /** @override */
371
+ async removeAttribute(primaryKey, attribute, conditionField, condition) {
372
+ const key = this.getKey(primaryKey);
373
+ const ExpressionAttributeNames = { "#k": KEY_ATTRIBUTE };
374
+ const params = {
375
+ TableName: this.table,
376
+ Key: { [KEY_ATTRIBUTE]: key },
377
+ UpdateExpression: `REMOVE ${this.attributePath(String(attribute), ExpressionAttributeNames, "r")}`,
378
+ ConditionExpression: "attribute_exists(#k)",
379
+ ExpressionAttributeNames
380
+ };
381
+ if (conditionField) {
382
+ this.setWriteCondition(params, condition, conditionField);
383
+ }
384
+ try {
385
+ await this.client.update(params);
386
+ }
387
+ catch (err) {
388
+ if (err instanceof ConditionalCheckFailedException) {
389
+ if (!conditionField) {
390
+ throw new StoreNotFoundError(key, this.storeName);
391
+ }
392
+ throw new UpdateConditionFailError(key, conditionField, condition);
393
+ }
394
+ throw err;
395
+ }
396
+ }
397
+ /** @override */
398
+ async incrementAttributes(primaryKey, info, conditionField, condition) {
399
+ const key = this.getKey(primaryKey);
400
+ const entries = Array.isArray(info)
401
+ ? info.map((e) => typeof e === "string" ? { property: e, value: 1 } : { property: e.property, value: e.value ?? 1 })
402
+ : Object.entries(info).map(([property, value]) => ({ property: String(property), value: value }));
403
+ if (!entries.length) {
404
+ return;
405
+ }
406
+ const ExpressionAttributeNames = { "#k": KEY_ATTRIBUTE };
407
+ const ExpressionAttributeValues = {};
408
+ const adds = entries.map((p, i) => {
409
+ ExpressionAttributeValues[`:v${i}`] = p.value;
410
+ return `${this.attributePath(p.property, ExpressionAttributeNames, `a${i}_`)} :v${i}`;
411
+ });
412
+ const params = {
413
+ TableName: this.table,
414
+ Key: { [KEY_ATTRIBUTE]: key },
415
+ UpdateExpression: "ADD " + adds.join(", "),
416
+ ConditionExpression: "attribute_exists(#k)",
417
+ ExpressionAttributeValues,
418
+ ExpressionAttributeNames
419
+ };
420
+ if (conditionField) {
421
+ this.setWriteCondition(params, condition, conditionField);
422
+ }
423
+ try {
424
+ await this.client.update(params);
425
+ }
426
+ catch (err) {
427
+ if (err instanceof ConditionalCheckFailedException) {
428
+ if (!conditionField) {
429
+ throw new StoreNotFoundError(key, this.storeName);
430
+ }
431
+ throw new UpdateConditionFailError(key, conditionField, condition);
432
+ }
433
+ throw err;
434
+ }
435
+ }
436
+ /** @override */
437
+ async upsertItemToCollection(primaryKey, collection, item, index, itemWriteConditionField, itemWriteCondition) {
438
+ const key = this.getKey(primaryKey);
439
+ const prop = String(collection);
440
+ const ExpressionAttributeNames = { "#k": KEY_ATTRIBUTE, "#col": prop };
441
+ const ExpressionAttributeValues = {};
442
+ const params = {
443
+ TableName: this.table,
444
+ Key: { [KEY_ATTRIBUTE]: key },
445
+ ConditionExpression: "attribute_exists(#k)",
446
+ ExpressionAttributeNames,
447
+ ExpressionAttributeValues
448
+ };
449
+ if (index === undefined) {
450
+ params.UpdateExpression = "SET #col = list_append(if_not_exists(#col, :empty_list), :item)";
451
+ ExpressionAttributeValues[":item"] = [cleanObject(item)];
452
+ ExpressionAttributeValues[":empty_list"] = [];
453
+ }
454
+ else {
455
+ params.UpdateExpression = `SET #col[${index}] = :item`;
456
+ ExpressionAttributeValues[":item"] = cleanObject(item);
457
+ if (itemWriteCondition !== undefined) {
458
+ ExpressionAttributeValues[":condValue"] = itemWriteCondition;
459
+ ExpressionAttributeNames["#field"] = itemWriteConditionField;
460
+ params.ConditionExpression += ` AND #col[${index}].#field = :condValue`;
461
+ }
462
+ }
463
+ try {
464
+ await this.client.update(params);
465
+ }
466
+ catch (err) {
467
+ if (err instanceof ConditionalCheckFailedException) {
468
+ if (itemWriteCondition === undefined) {
469
+ throw new StoreNotFoundError(key, this.storeName);
470
+ }
471
+ throw new UpdateConditionFailError(key, itemWriteConditionField, itemWriteCondition);
472
+ }
473
+ else if (err.name === "ValidationException") {
474
+ throw new StoreNotFoundError(key, this.storeName);
475
+ }
476
+ throw err;
477
+ }
478
+ }
479
+ /** @override */
480
+ async deleteItemFromCollection(primaryKey, collection, index, itemWriteConditionField, itemWriteCondition) {
481
+ const key = this.getKey(primaryKey);
482
+ const ExpressionAttributeNames = { "#k": KEY_ATTRIBUTE, "#col": String(collection) };
483
+ const params = {
484
+ TableName: this.table,
485
+ Key: { [KEY_ATTRIBUTE]: key },
486
+ UpdateExpression: `REMOVE #col[${index}]`,
487
+ ConditionExpression: "attribute_exists(#k)",
488
+ ExpressionAttributeNames
489
+ };
490
+ if (itemWriteCondition !== undefined) {
491
+ params.ExpressionAttributeValues = { ":condValue": itemWriteCondition };
492
+ ExpressionAttributeNames["#field"] = itemWriteConditionField;
493
+ params.ConditionExpression += ` AND #col[${index}].#field = :condValue`;
494
+ }
495
+ try {
496
+ await this.client.update(params);
497
+ }
498
+ catch (err) {
499
+ if (err instanceof ConditionalCheckFailedException) {
500
+ if (itemWriteCondition === undefined) {
501
+ throw new StoreNotFoundError(key, this.storeName);
502
+ }
503
+ throw new UpdateConditionFailError(key, itemWriteConditionField, itemWriteCondition);
504
+ }
505
+ else if (err.name === "ValidationException") {
506
+ throw new StoreNotFoundError(key, this.storeName);
507
+ }
508
+ throw err;
509
+ }
510
+ }
511
+ /**
512
+ * Translate a WebdaQL query into a DynamoDB scan or query
513
+ *
514
+ * A query on the hash key or on a global index hash key with `=` uses a DynamoDB Query,
515
+ * anything else is a Scan. The part of the expression DynamoDB cannot evaluate is
516
+ * returned in `filter` and must be applied on the results.
517
+ *
518
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/Query.html
519
+ * @see https://docs.aws.amazon.com/amazondynamodb/latest/developerguide/GSI.html
520
+ * @param query - the parsed query
521
+ * @returns the items and the residual filter
522
+ */
523
+ async find(query) {
524
+ let scan = true;
525
+ let IndexName = undefined;
526
+ let result;
527
+ const limit = query.limit ?? 1000;
528
+ const primaryKeys = { [KEY_ATTRIBUTE]: null };
529
+ Object.keys(this.globalIndexes).forEach(name => {
530
+ primaryKeys[this.globalIndexes[name].key] = name;
531
+ });
532
+ // We could use PartQL but localstack is not compatible
533
+ const filter = new WebdaQL.AndExpression([]);
534
+ let KeyConditionExpression = "";
535
+ let ExpressionAttributeValues = {};
536
+ const FilterExpression = [];
537
+ let ExpressionAttributeNames = {};
538
+ let indexNode;
539
+ let sortOrder = "ASC";
540
+ let processingExpression;
541
+ if (!(query.filter instanceof WebdaQL.AndExpression)) {
542
+ processingExpression = new WebdaQL.AndExpression([query.filter]);
543
+ }
544
+ else {
545
+ processingExpression = query.filter;
546
+ }
547
+ // A FALSE conjunct matches nothing: do not hit DynamoDB (never fail open)
548
+ if (processingExpression.children.some(c => c instanceof WebdaQL.BooleanExpression && !c.value)) {
549
+ return { results: [], filter, continuationToken: undefined };
550
+ }
551
+ // A TRUE conjunct is neutral
552
+ processingExpression = new WebdaQL.AndExpression(processingExpression.children.filter(c => !(c instanceof WebdaQL.BooleanExpression)));
553
+ // Search for the index
554
+ processingExpression.children.some(child => {
555
+ if (child instanceof WebdaQL.ComparisonExpression) {
556
+ // Primary key requires equal operator
557
+ if (child.operator === "=" && child.attribute.length === 1 && primaryKeys[child.attribute[0]] !== undefined) {
558
+ // Query not scan
559
+ scan = false;
560
+ IndexName = primaryKeys[child.attribute[0]] ?? undefined;
561
+ indexNode = child;
562
+ KeyConditionExpression = `#${child.attribute[0]} = :${child.attribute[0]}`;
563
+ ExpressionAttributeNames[`#${child.attribute[0]}`] = child.attribute[0];
564
+ ExpressionAttributeValues[`:${child.attribute[0]}`] = child.value;
565
+ if (IndexName && query.orderBy && this.globalIndexes[IndexName].sort) {
566
+ const sortKey = this.globalIndexes[IndexName].sort;
567
+ // Might update sort order
568
+ query.orderBy.forEach(order => {
569
+ if (order.field === sortKey) {
570
+ sortOrder = order.direction;
571
+ }
572
+ });
573
+ }
574
+ return true;
575
+ }
576
+ }
577
+ return false;
578
+ });
579
+ let count = 1;
580
+ // Build the Query/Filter
581
+ processingExpression.children.forEach(child => {
582
+ if (child === indexNode) {
583
+ return;
584
+ }
585
+ // Only work on Comparison Node for now
586
+ if (child instanceof WebdaQL.ComparisonExpression) {
587
+ let operator = child.operator;
588
+ // DynamoDB does not manage LIKE
589
+ if (child.operator === "LIKE") {
590
+ filter.children.push(child);
591
+ return;
592
+ }
593
+ // != is <> in Dynamo
594
+ if (operator === "!=") {
595
+ operator = "<>";
596
+ }
597
+ // DynamoDB does not allow more than 100 items in IN
598
+ if (child.operator === "IN" && child.value.length > 100) {
599
+ filter.children.push(child);
600
+ return;
601
+ }
602
+ const isSortKey = IndexName && this.globalIndexes[IndexName].sort === child.attribute[0];
603
+ // A sort key cannot be used in a filter expression and IN is not allowed in a key condition
604
+ if (isSortKey && child.operator === "IN") {
605
+ filter.children.push(child);
606
+ return;
607
+ }
608
+ // Function conditions (IS NULL / IS NOT NULL) are not allowed on a sort key either
609
+ if (isSortKey && (child.operator === "IS NULL" || child.operator === "IS NOT NULL")) {
610
+ filter.children.push(child);
611
+ return;
612
+ }
613
+ // Subfields like team.id needs to be #a1.#a2
614
+ const attr = `a${count++}`;
615
+ let fullAttr = `#${attr}`;
616
+ child.attribute.slice(1).forEach(v => {
617
+ const subAttr = `#a${count++}`;
618
+ fullAttr += `.${subAttr}`;
619
+ ExpressionAttributeNames[subAttr] = v;
620
+ });
621
+ ExpressionAttributeNames[`#${attr}`] = child.attribute[0];
622
+ // IS NULL matches a missing attribute or one stored with the NULL type (JS null).
623
+ // Empty strings are not stored (see cleanObject), so they also match IS NULL here.
624
+ if (child.operator === "IS NULL" || child.operator === "IS NOT NULL") {
625
+ ExpressionAttributeValues[`:${attr}`] = "NULL";
626
+ FilterExpression.push(child.operator === "IS NULL"
627
+ ? `(attribute_not_exists(${fullAttr}) OR attribute_type(${fullAttr}, :${attr}))`
628
+ : `(attribute_exists(${fullAttr}) AND NOT attribute_type(${fullAttr}, :${attr}))`);
629
+ return;
630
+ }
631
+ let valueExpression = `:${attr}`;
632
+ if (child.operator === "IN") {
633
+ // Need to follow `a IN (b, c, d)
634
+ valueExpression = "(" + valueExpression;
635
+ ExpressionAttributeValues[`:${attr}`] = child.value[0];
636
+ child.value.slice(1).forEach(v => {
637
+ const subAttr = `:a${count++}`;
638
+ valueExpression += `, ${subAttr}`;
639
+ ExpressionAttributeValues[subAttr] = v;
640
+ });
641
+ valueExpression += ")";
642
+ }
643
+ else {
644
+ // For all other just give the value
645
+ ExpressionAttributeValues[`:${attr}`] = child.value;
646
+ }
647
+ // Manage CONTAINS
648
+ if (child.operator === "CONTAINS") {
649
+ FilterExpression.push(`contains(${fullAttr}, :${attr})`);
650
+ return;
651
+ }
652
+ // If this is a sort key
653
+ if (isSortKey) {
654
+ // Sort key
655
+ KeyConditionExpression += ` AND ${fullAttr} ${operator} ${valueExpression}`;
656
+ return;
657
+ }
658
+ // Otherwise fallback to normal Filter
659
+ FilterExpression.push(`${fullAttr} ${operator} ${valueExpression}`);
660
+ }
661
+ else {
662
+ filter.children.push(child);
663
+ }
664
+ });
665
+ if (!Object.keys(ExpressionAttributeNames).length) {
666
+ ExpressionAttributeNames = undefined;
667
+ }
668
+ if (!Object.keys(ExpressionAttributeValues).length) {
669
+ ExpressionAttributeValues = undefined;
670
+ }
671
+ let ExclusiveStartKey = query.continuationToken
672
+ ? JSON.parse(Buffer.from(query.continuationToken, "base64").toString())
673
+ : undefined;
674
+ // Scan if not primary key was provided
675
+ if (scan) {
676
+ const Items = [];
677
+ do {
678
+ result = await this.client.scan({
679
+ TableName: this.table,
680
+ FilterExpression: FilterExpression.length ? FilterExpression.join(" AND ") : undefined,
681
+ ExclusiveStartKey,
682
+ ExpressionAttributeNames,
683
+ ExpressionAttributeValues,
684
+ Limit: limit - Items.length
685
+ });
686
+ Items.push(...result.Items);
687
+ result.Items = Items;
688
+ ExclusiveStartKey = result.LastEvaluatedKey;
689
+ } while (Items.length < limit && result.LastEvaluatedKey);
690
+ }
691
+ else {
692
+ result = await this.client.query({
693
+ TableName: this.table,
694
+ IndexName,
695
+ ExclusiveStartKey,
696
+ KeyConditionExpression,
697
+ FilterExpression: FilterExpression.length ? FilterExpression.join(" AND ") : undefined,
698
+ ExpressionAttributeNames,
699
+ ExpressionAttributeValues,
700
+ Limit: limit,
701
+ ScanIndexForward: sortOrder === "ASC"
702
+ });
703
+ }
704
+ return {
705
+ results: result.Items.map(c => this.fromItem(c)),
706
+ filter,
707
+ continuationToken: result.LastEvaluatedKey
708
+ ? Buffer.from(JSON.stringify(result.LastEvaluatedKey)).toString("base64")
709
+ : undefined
710
+ };
711
+ }
712
+ /**
713
+ * Query the table
714
+ *
715
+ * Pages are retrieved until the limit is reached, applying the part of the
716
+ * filter that DynamoDB cannot evaluate and restricting to the model hierarchy
717
+ * @override
718
+ * @param query - the WebdaQL query
719
+ * @returns the results and the continuation token
720
+ */
721
+ async query(query) {
722
+ const parsed = typeof query === "string" ? WebdaQL.parse(query) : query;
723
+ const limit = parsed.limit ?? 1000;
724
+ const ids = this.buildClassFilterIdentifiers();
725
+ const results = [];
726
+ let continuationToken = parsed.continuationToken;
727
+ do {
728
+ const page = await this.find({
729
+ ...parsed,
730
+ filter: parsed.filter,
731
+ limit: limit - results.length,
732
+ continuationToken
733
+ });
734
+ results.push(...page.results.filter(item => {
735
+ const type = item[TYPE_ATTRIBUTE];
736
+ if (ids && type && !ids.includes(type)) {
737
+ return false;
738
+ }
739
+ return page.filter.eval(item);
740
+ }));
741
+ continuationToken = page.continuationToken;
742
+ } while (results.length < limit && continuationToken);
743
+ return {
744
+ results,
745
+ continuationToken: results.length >= limit ? continuationToken : undefined
746
+ };
747
+ }
748
+ /**
749
+ * Iterate over the query results
750
+ * @override
751
+ * @param query - the WebdaQL query
752
+ */
753
+ async *iterate(query) {
754
+ const parsed = WebdaQL.parse(query);
755
+ if (!parsed.limit) {
756
+ parsed.limit = 100;
757
+ }
758
+ do {
759
+ const res = await this.query(parsed);
760
+ for (const item of res.results) {
761
+ yield item;
762
+ }
763
+ parsed.continuationToken = res.continuationToken;
764
+ } while (parsed.continuationToken);
765
+ }
766
+ /**
767
+ * Delete all items from the table (used in tests)
768
+ */
769
+ async __clean() {
770
+ let ExclusiveStartKey;
771
+ do {
772
+ const result = await this.client.scan({
773
+ TableName: this.table,
774
+ Limit: this.scanPage,
775
+ ExclusiveStartKey
776
+ });
777
+ await Promise.all((result.Items ?? []).map(item => this.client.delete({ TableName: this.table, Key: { [KEY_ATTRIBUTE]: item[KEY_ATTRIBUTE] } })));
778
+ ExclusiveStartKey = result.LastEvaluatedKey;
779
+ } while (ExclusiveStartKey);
780
+ }
781
+ }
782
+ /**
783
+ * DynamoStore handles the DynamoDB
784
+ *
785
+ * Parameters:
786
+ * accessKeyId: '' // try WEBDA_AWS_KEY env variable if not found
787
+ * secretAccessKey: '' // try WEBDA_AWS_SECRET env variable if not found
788
+ * table: ''
789
+ * region: ''
790
+ *
791
+ * The table must have a `uuid` string hash key
792
+ *
793
+ * @WebdaModda
794
+ */
795
+ let DynamoStore = (() => {
796
+ var _a;
797
+ let _classSuper = Store;
798
+ let _instanceExtraInitializers = [];
799
+ let _getRepository_decorators;
800
+ return _a = class DynamoStore extends _classSuper {
801
+ constructor() {
802
+ super(...arguments);
803
+ this._client = __runInitializers(this, _instanceExtraInitializers);
804
+ }
805
+ /**
806
+ * Create the AWS client
807
+ * @returns this
808
+ */
809
+ resolve() {
810
+ super.resolve();
811
+ this._client = DynamoDBDocument.from(new DynamoDBClient(this.parameters), {
812
+ marshallOptions: {
813
+ removeUndefinedValues: true,
814
+ convertClassInstanceToMap: true
815
+ }
816
+ });
817
+ return this;
818
+ }
819
+ /**
820
+ * Copy one DynamoDB table to another
821
+ *
822
+ * @param output - worker output to report progress
823
+ * @param source - source table
824
+ * @param target - target table
825
+ */
826
+ static async copyTable(output, source, target) {
827
+ const db = new DynamoDB({});
828
+ let ExclusiveStartKey;
829
+ const props = await db.describeTable({
830
+ TableName: source
831
+ });
832
+ output.startProgress("copyTable", props.Table.ItemCount, `Copying ${source} to ${target}`);
833
+ do {
834
+ const info = await db.scan({
835
+ TableName: source,
836
+ ExclusiveStartKey
837
+ });
838
+ do {
839
+ const items = [];
840
+ while (info.Items.length && items.length < 25) {
841
+ items.push(info.Items.shift());
842
+ }
843
+ if (!items.length) {
844
+ break;
845
+ }
846
+ await db.batchWriteItem({
847
+ RequestItems: {
848
+ [target]: items.map(Item => ({
849
+ PutRequest: { Item }
850
+ }))
851
+ }
852
+ });
853
+ output.incrementProgress(items.length, "copyTable");
854
+ } while (true);
855
+ ExclusiveStartKey = info.LastEvaluatedKey;
856
+ } while (ExclusiveStartKey);
857
+ }
858
+ /**
859
+ * Resolve the table name for a given model class
860
+ *
861
+ * `tables[identifier]` overrides the default `table`
862
+ * @param model - the model class
863
+ * @returns the table name
864
+ */
865
+ resolveTable(model) {
866
+ const meta = useModelMetadata(model);
867
+ return (meta && this.parameters.tables?.[meta.Identifier]) || this.parameters.table;
868
+ }
869
+ /**
870
+ * Build the DynamoRepository for a model
871
+ *
872
+ * The result is cached per model class
873
+ * @param model - the model class
874
+ * @returns a repository backed by this store's DynamoDB table
875
+ */
876
+ getRepository(model) {
877
+ const meta = useModelMetadata(model);
878
+ const inner = new DynamoRepository(model, meta.PrimaryKey, this._client, this.resolveTable(model), this.parameters.globalIndexes, this.parameters.scanPage, this.getName());
879
+ // Wrap in EventRepository so typed CRUD events fire; consumers reach them
880
+ // via useRepository(model).on(...).
881
+ return new EventRepository(model, meta.PrimaryKey, inner);
882
+ }
883
+ /**
884
+ * Return the underlying DynamoRepository for each model this store manages
885
+ * @returns the repositories
886
+ */
887
+ getRepositories() {
888
+ const repos = [];
889
+ for (const modelId of Object.keys(this._modelsHierarchy ?? {})) {
890
+ let model;
891
+ try {
892
+ model = useModel(modelId);
893
+ }
894
+ catch {
895
+ continue;
896
+ }
897
+ if (!model) {
898
+ continue;
899
+ }
900
+ const repo = this.getRepository(model);
901
+ repos.push((repo.repository ?? repo));
902
+ }
903
+ return repos;
904
+ }
905
+ /**
906
+ * IAM policy required by the store
907
+ * @param accountId - AWS account id
908
+ * @returns the policy statement
909
+ */
910
+ getARNPolicy(accountId) {
911
+ const region = this.parameters.region || "us-east-1";
912
+ const tables = new Set([this.parameters.table, ...Object.values(this.parameters.tables ?? {})]);
913
+ return {
914
+ Sid: this.constructor.name + this.getName(),
915
+ Effect: "Allow",
916
+ Action: [
917
+ "dynamodb:BatchGetItem",
918
+ "dynamodb:BatchWriteItem",
919
+ "dynamodb:DeleteItem",
920
+ "dynamodb:GetItem",
921
+ "dynamodb:GetRecords",
922
+ "dynamodb:GetShardIterator",
923
+ "dynamodb:PutItem",
924
+ "dynamodb:Query",
925
+ "dynamodb:Scan",
926
+ "dynamodb:UpdateItem"
927
+ ],
928
+ Resource: [...tables].map(table => "arn:aws:dynamodb:" + region + ":" + accountId + ":table/" + table)
929
+ };
930
+ }
931
+ /**
932
+ * Delete all items from the managed tables (used in tests)
933
+ */
934
+ async __clean() {
935
+ const done = new Set();
936
+ for (const repo of this.getRepositories()) {
937
+ if (done.has(repo.getTable())) {
938
+ continue;
939
+ }
940
+ done.add(repo.getTable());
941
+ await repo.__clean();
942
+ }
943
+ }
944
+ /**
945
+ * CloudFormation resources for the table
946
+ * @param deployer - the deployer requesting the resources
947
+ * @returns the resources
948
+ */
949
+ getCloudFormation(deployer) {
950
+ if (this.parameters.CloudFormationSkip) {
951
+ return {};
952
+ }
953
+ const resources = {};
954
+ this.parameters.CloudFormation = this.parameters.CloudFormation || {};
955
+ this.parameters.CloudFormation.Table = this.parameters.CloudFormation.Table || {};
956
+ const KeySchema = this.parameters.CloudFormation.KeySchema || [{ KeyType: "HASH", AttributeName: KEY_ATTRIBUTE }];
957
+ const AttributeDefinitions = this.parameters.CloudFormation.AttributeDefinitions || [];
958
+ this.parameters.CloudFormation.Table.BillingMode =
959
+ this.parameters.CloudFormation.Table.BillingMode || "PAY_PER_REQUEST";
960
+ AttributeDefinitions.push({ AttributeName: KEY_ATTRIBUTE, AttributeType: "S" });
961
+ resources[this.getName() + "DynamoTable"] = {
962
+ Type: "AWS::DynamoDB::Table",
963
+ Properties: {
964
+ ...this.parameters.CloudFormation.Table,
965
+ TableName: this.parameters.table,
966
+ KeySchema,
967
+ AttributeDefinitions,
968
+ Tags: deployer.getDefaultTags(this.parameters.CloudFormation.Table.Tags)
969
+ }
970
+ };
971
+ // Add any Other resources with prefix of the service
972
+ return resources;
973
+ }
974
+ },
975
+ (() => {
976
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
977
+ _getRepository_decorators = [InstanceCache()];
978
+ __esDecorate(_a, null, _getRepository_decorators, { kind: "method", name: "getRepository", static: false, private: false, access: { has: obj => "getRepository" in obj, get: obj => obj.getRepository }, metadata: _metadata }, null, _instanceExtraInitializers);
979
+ if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
980
+ })(),
981
+ _a;
982
+ })();
983
+ export { DynamoStore };
984
+ export default DynamoStore;
985
+ //# sourceMappingURL=dynamodb.service.js.map