@allthings/cloud-toolkit 1.3.0-dev.2 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +24 -10
- package/dist/lib.cjs.js +201 -6
- package/dist/lib.esm.js +201 -7
- package/dist/lib.umd.min.js +1 -1
- package/dist/src/aws/dynamodb.d.ts +47 -0
- package/dist/src/aws/dynamodb.test.d.ts +1 -0
- package/dist/src/aws/index.d.ts +1 -0
- package/dist/src/aws/parameterStore.d.ts +6 -2
- package/dist/src/index.d.ts +1 -1
- package/dist/src/logger/logger.d.ts +2 -1
- package/dist/src/logger/logger.test.d.ts +1 -0
- package/dist/src/utils.d.ts +2 -0
- package/package.json +7 -6
package/README.md
CHANGED
|
@@ -3,17 +3,31 @@ Standardizes the setup of aws, datadog and other things
|
|
|
3
3
|
|
|
4
4
|
## Available functions
|
|
5
5
|
### parameter store
|
|
6
|
-
| function | description |
|
|
7
|
-
|
|
8
|
-
| getSecret | Retrieves a single secret from parameter store by providing the path |
|
|
9
|
-
| getSecrets | Retrieves multiple secrets from parameter store by providing an array of paths |
|
|
6
|
+
| function | parameters | description |
|
|
7
|
+
|------------|-----------------------------------------|--------------------------------------------------------------------------------|
|
|
8
|
+
| getSecret | parameter<br/>defaultValue (optional) | Retrieves a single secret from parameter store by providing the path |
|
|
9
|
+
| getSecrets | parameters<br/>defaultValues (optional) | Retrieves multiple secrets from parameter store by providing an array of paths |
|
|
10
10
|
|
|
11
11
|
### ses
|
|
12
|
-
| function | description |
|
|
13
|
-
|
|
14
|
-
| sendMail | Sends an email via SES or provided SMTP config |
|
|
12
|
+
| function | parameters | description |
|
|
13
|
+
|----------|------------|------------------------------------------------|
|
|
14
|
+
| sendMail | options | Sends an email via SES or provided SMTP config |
|
|
15
15
|
|
|
16
16
|
### lambda
|
|
17
|
-
| function | description |
|
|
18
|
-
|
|
19
|
-
| invokeLambda | Invokes set lambda with invocations type and payload |
|
|
17
|
+
| function | parameters | description |
|
|
18
|
+
|--------------|----------------------------|------------------------------------------------------|
|
|
19
|
+
| invokeLambda | invocationType<br/>payload | Invokes set lambda with invocations type and payload |
|
|
20
|
+
|
|
21
|
+
### dynamodb
|
|
22
|
+
| function | parameters | description |
|
|
23
|
+
|-----------------|--------------------------------------|----------------------------------------------------------|
|
|
24
|
+
| batchWriteItems | table<br/>items | Creates multiple item in a defined table |
|
|
25
|
+
| deleteItem | table<br/>key<br/>options (optional) | Deletes database item from defined table by given key |
|
|
26
|
+
| getItem | table<br/>key<br/>options (optional) | Returns item from Database by defined table and key |
|
|
27
|
+
| putItem | table<br/>key | Creates one item in defined table |
|
|
28
|
+
| queryTable | table<br/>options (optional) | Returns result items of query |
|
|
29
|
+
| scanTable | table<br/>options (optional) | Returns result items of scan |
|
|
30
|
+
| updateItem | table<br/>key<br/>options (optional) | Updates item in database by provided table and given key |
|
|
31
|
+
|
|
32
|
+
### logger
|
|
33
|
+
A winston instance will be created with default log levels https://github.com/winstonjs/winston?tab=readme-ov-file#logging
|
package/dist/lib.cjs.js
CHANGED
|
@@ -1,5 +1,8 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
|
+
var clientDynamodb = require('@aws-sdk/client-dynamodb');
|
|
4
|
+
var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
5
|
+
var Bottleneck = require('bottleneck');
|
|
3
6
|
var clientLambda = require('@aws-sdk/client-lambda');
|
|
4
7
|
var clientSsm = require('@aws-sdk/client-ssm');
|
|
5
8
|
var aws = require('@aws-sdk/client-ses');
|
|
@@ -29,6 +32,189 @@ const DEFAULT_AWS_CONFIGURATION = {
|
|
|
29
32
|
region: 'eu-central-2',
|
|
30
33
|
};
|
|
31
34
|
|
|
35
|
+
const splitEvery = (every, list) => Array.from({ length: Math.ceil(list.length / every) }).map((_, count) => list.slice(count * every, count * every + every));
|
|
36
|
+
const until = async (predicate, transformer, initialValue, iterationCount = 0) => {
|
|
37
|
+
const transformed = await transformer(initialValue, iterationCount);
|
|
38
|
+
return (await predicate(transformed, iterationCount))
|
|
39
|
+
? transformed
|
|
40
|
+
: until(predicate, transformer, transformed, iterationCount + 1);
|
|
41
|
+
};
|
|
42
|
+
|
|
43
|
+
const DEFAULT_BATCH_ITEMS_MAX_RETRIES = 50;
|
|
44
|
+
let queue;
|
|
45
|
+
const makeKey = (key) => {
|
|
46
|
+
if (typeof key === 'string') {
|
|
47
|
+
return { id: key };
|
|
48
|
+
}
|
|
49
|
+
return key;
|
|
50
|
+
};
|
|
51
|
+
const deleteItem = async (config, documentClient, table, key, options = {}) => {
|
|
52
|
+
try {
|
|
53
|
+
const { ReturnValues = 'NONE' } = options;
|
|
54
|
+
const command = new libDynamodb.DeleteCommand({
|
|
55
|
+
Key: makeKey(key),
|
|
56
|
+
ReturnValues,
|
|
57
|
+
TableName: config.tableNamePrefix + table,
|
|
58
|
+
});
|
|
59
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
60
|
+
return result.Attributes;
|
|
61
|
+
}
|
|
62
|
+
catch (error) {
|
|
63
|
+
if (config.logger) {
|
|
64
|
+
config.logger('error', error);
|
|
65
|
+
}
|
|
66
|
+
return undefined;
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
const getItem = async (config, documentClient, table, key, options = {}) => {
|
|
70
|
+
try {
|
|
71
|
+
const { ConsistentRead = false } = options;
|
|
72
|
+
const command = new libDynamodb.GetCommand({
|
|
73
|
+
ConsistentRead,
|
|
74
|
+
Key: makeKey(key),
|
|
75
|
+
TableName: config.tableNamePrefix + table,
|
|
76
|
+
});
|
|
77
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
78
|
+
return result.Item;
|
|
79
|
+
}
|
|
80
|
+
catch (error) {
|
|
81
|
+
if (config.logger) {
|
|
82
|
+
config.logger('error', error);
|
|
83
|
+
}
|
|
84
|
+
return undefined;
|
|
85
|
+
}
|
|
86
|
+
};
|
|
87
|
+
const putItem = async (config, documentClient, table, Item) => {
|
|
88
|
+
try {
|
|
89
|
+
const { expires, ...data } = Item;
|
|
90
|
+
const command = new libDynamodb.PutCommand({
|
|
91
|
+
Item: expires === null ? data : Item,
|
|
92
|
+
TableName: config.tableNamePrefix + table,
|
|
93
|
+
});
|
|
94
|
+
return (await queue.schedule(() => documentClient.send(command))) && Item;
|
|
95
|
+
}
|
|
96
|
+
catch (error) {
|
|
97
|
+
if (config.logger) {
|
|
98
|
+
config.logger('error', error);
|
|
99
|
+
}
|
|
100
|
+
return undefined;
|
|
101
|
+
}
|
|
102
|
+
};
|
|
103
|
+
const updateItem = async (config, documentClient, table, key, options = {}) => {
|
|
104
|
+
try {
|
|
105
|
+
const command = new libDynamodb.UpdateCommand({
|
|
106
|
+
Key: makeKey(key),
|
|
107
|
+
...options,
|
|
108
|
+
ReturnValues: 'ALL_NEW',
|
|
109
|
+
TableName: config.tableNamePrefix + table,
|
|
110
|
+
});
|
|
111
|
+
const result = await queue.schedule(async () => documentClient.send(command));
|
|
112
|
+
return result.Attributes;
|
|
113
|
+
}
|
|
114
|
+
catch (error) {
|
|
115
|
+
if (config.logger) {
|
|
116
|
+
config.logger('error', error);
|
|
117
|
+
}
|
|
118
|
+
return undefined;
|
|
119
|
+
}
|
|
120
|
+
};
|
|
121
|
+
const hasNoUnprocessedItems = ({ UnprocessedItems, }) => !UnprocessedItems || Object.keys(UnprocessedItems).length === 0;
|
|
122
|
+
const makeBatchWriteRequestWithExponentialBackoff = (documentClient, table, batchWriteMaxRetries) => async (batchItems, retries) => {
|
|
123
|
+
if (retries > batchWriteMaxRetries) {
|
|
124
|
+
throw new Error('Reached maximum number of DynamoDB BatchWrite request retries.');
|
|
125
|
+
}
|
|
126
|
+
const command = new libDynamodb.BatchWriteCommand({
|
|
127
|
+
RequestItems: batchItems.UnprocessedItems ?? {
|
|
128
|
+
[table]: batchItems.map((Item) => ({
|
|
129
|
+
PutRequest: { Item },
|
|
130
|
+
})),
|
|
131
|
+
},
|
|
132
|
+
ReturnConsumedCapacity: 'TOTAL',
|
|
133
|
+
ReturnItemCollectionMetrics: 'SIZE',
|
|
134
|
+
});
|
|
135
|
+
return documentClient.send(command);
|
|
136
|
+
};
|
|
137
|
+
const batchWriteItems = async (config, documentClient, table, items) => {
|
|
138
|
+
try {
|
|
139
|
+
const batches = splitEvery(25, items);
|
|
140
|
+
const result = await Promise.all(batches.map(async (batch) => queue.schedule(async () => until(hasNoUnprocessedItems, makeBatchWriteRequestWithExponentialBackoff(documentClient, config.tableNamePrefix + table, config.batchWriteMaxRetries ?? DEFAULT_BATCH_ITEMS_MAX_RETRIES), batch))));
|
|
141
|
+
return result && items;
|
|
142
|
+
}
|
|
143
|
+
catch (error) {
|
|
144
|
+
if (config.logger) {
|
|
145
|
+
config.logger('error', error);
|
|
146
|
+
}
|
|
147
|
+
return undefined;
|
|
148
|
+
}
|
|
149
|
+
};
|
|
150
|
+
const scanTable = async (config, documentClient, table, options = {}) => {
|
|
151
|
+
try {
|
|
152
|
+
const { ConsistentRead = false } = options;
|
|
153
|
+
const command = new libDynamodb.ScanCommand({
|
|
154
|
+
...options,
|
|
155
|
+
ConsistentRead,
|
|
156
|
+
TableName: config.tableNamePrefix + table,
|
|
157
|
+
});
|
|
158
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
159
|
+
return result;
|
|
160
|
+
}
|
|
161
|
+
catch (error) {
|
|
162
|
+
if (config.logger) {
|
|
163
|
+
config.logger('error', error);
|
|
164
|
+
}
|
|
165
|
+
return undefined;
|
|
166
|
+
}
|
|
167
|
+
};
|
|
168
|
+
const queryTable = async (config, documentClient, table, options = {}) => {
|
|
169
|
+
try {
|
|
170
|
+
const { ConsistentRead = false } = options;
|
|
171
|
+
const command = new libDynamodb.QueryCommand({
|
|
172
|
+
...options,
|
|
173
|
+
ConsistentRead,
|
|
174
|
+
TableName: config.tableNamePrefix + table,
|
|
175
|
+
});
|
|
176
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
177
|
+
return result;
|
|
178
|
+
}
|
|
179
|
+
catch (error) {
|
|
180
|
+
if (config.logger) {
|
|
181
|
+
config.logger('error', error);
|
|
182
|
+
}
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
};
|
|
186
|
+
const dynamodb = (userConfig) => {
|
|
187
|
+
const { clientConfig, ...config } = {
|
|
188
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
189
|
+
...userConfig,
|
|
190
|
+
};
|
|
191
|
+
const ddbClient = new clientDynamodb.DynamoDBClient(config.dockerConfig
|
|
192
|
+
? {
|
|
193
|
+
credentials: {
|
|
194
|
+
accessKeyId: 'foobarkey',
|
|
195
|
+
secretAccessKey: 'foobarsecret',
|
|
196
|
+
},
|
|
197
|
+
endpoint: config.dockerConfig.endpoint,
|
|
198
|
+
region: 'local',
|
|
199
|
+
retryMode: 'standard',
|
|
200
|
+
}
|
|
201
|
+
: { retryMode: 'standard', ...clientConfig });
|
|
202
|
+
const documentClient = libDynamodb.DynamoDBDocumentClient.from(ddbClient);
|
|
203
|
+
queue = new Bottleneck({
|
|
204
|
+
maxConcurrent: config.queueConfig?.queueConcurrency ?? 25,
|
|
205
|
+
minTime: config.queueConfig?.queueDelay ?? undefined,
|
|
206
|
+
});
|
|
207
|
+
return {
|
|
208
|
+
batchWriteItems: (table, items) => batchWriteItems(config, documentClient, table, items),
|
|
209
|
+
deleteItem: (table, key, options) => deleteItem(config, documentClient, table, key, options),
|
|
210
|
+
getItem: (table, key, options) => getItem(config, documentClient, table, key, options),
|
|
211
|
+
putItem: (table, item) => putItem(config, documentClient, table, item),
|
|
212
|
+
queryTable: (table, options) => queryTable(config, documentClient, table, options),
|
|
213
|
+
scanTable: (table, options) => scanTable(config, documentClient, table, options),
|
|
214
|
+
updateItem: (table, key, options) => updateItem(config, documentClient, table, key, options),
|
|
215
|
+
};
|
|
216
|
+
};
|
|
217
|
+
|
|
32
218
|
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
33
219
|
try {
|
|
34
220
|
const invokeCommand = new clientLambda.InvokeCommand({
|
|
@@ -65,9 +251,9 @@ const DEFAULT_CLIENT_CONFIG$1 = {
|
|
|
65
251
|
onlyDefault: false,
|
|
66
252
|
prefix: process.env.SSM_PARAM_PATH,
|
|
67
253
|
};
|
|
68
|
-
const getSecrets = async (ssm, config, parameters_,
|
|
254
|
+
const getSecrets = async (ssm, config, parameters_, defaultValues) => {
|
|
69
255
|
if (config.onlyDefault) {
|
|
70
|
-
return
|
|
256
|
+
return defaultValues;
|
|
71
257
|
}
|
|
72
258
|
try {
|
|
73
259
|
const command = new clientSsm.GetParametersCommand({
|
|
@@ -75,13 +261,21 @@ const getSecrets = async (ssm, config, parameters_, defaultValue) => {
|
|
|
75
261
|
WithDecryption: true,
|
|
76
262
|
});
|
|
77
263
|
const parameters = await ssm.send(command);
|
|
78
|
-
return (parameters?.Parameters?.map((parameter) =>
|
|
264
|
+
return (parameters?.Parameters?.map((parameter) => {
|
|
265
|
+
const defaultIfNoParameter = !parameter.Value && parameter.Name
|
|
266
|
+
? defaultValues.find((defaultValue) => defaultValue.name === parameter.Name)
|
|
267
|
+
: defaultValues[0];
|
|
268
|
+
return {
|
|
269
|
+
name: parameter.Name ?? defaultIfNoParameter?.name ?? '',
|
|
270
|
+
value: parameter.Value ?? defaultIfNoParameter?.value ?? '',
|
|
271
|
+
};
|
|
272
|
+
}) ?? defaultValues);
|
|
79
273
|
}
|
|
80
274
|
catch (error) {
|
|
81
275
|
if (config.logger) {
|
|
82
276
|
config.logger('error', error);
|
|
83
277
|
}
|
|
84
|
-
return
|
|
278
|
+
return defaultValues;
|
|
85
279
|
}
|
|
86
280
|
};
|
|
87
281
|
const getSecret = async (ssm, config, parameter_, defaultValue) => {
|
|
@@ -110,7 +304,7 @@ const parameterStore = (userConfig) => {
|
|
|
110
304
|
const ssm = new clientSsm.SSMClient(clientConfig);
|
|
111
305
|
return {
|
|
112
306
|
getSecret: (parameter, defaultValue = '') => getSecret(ssm, config, parameter, defaultValue),
|
|
113
|
-
getSecrets: (parameters,
|
|
307
|
+
getSecrets: (parameters, defaultValues = []) => getSecrets(ssm, config, parameters, defaultValues),
|
|
114
308
|
};
|
|
115
309
|
};
|
|
116
310
|
|
|
@@ -184,12 +378,13 @@ const logger = (config) => {
|
|
|
184
378
|
}
|
|
185
379
|
return winston.createLogger({
|
|
186
380
|
...loggerConfig,
|
|
187
|
-
transports: [new winston.transports.Console()],
|
|
381
|
+
transports: [new winston.transports.Console({ forceConsole: true })],
|
|
188
382
|
});
|
|
189
383
|
};
|
|
190
384
|
|
|
191
385
|
exports.DEFAULT_PARAMETER_STORE_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG$1;
|
|
192
386
|
exports.DEFAULT_SES_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG;
|
|
387
|
+
exports.dynamodb = dynamodb;
|
|
193
388
|
exports.lambda = lambda;
|
|
194
389
|
exports.logger = logger;
|
|
195
390
|
exports.parameterStore = parameterStore;
|
package/dist/lib.esm.js
CHANGED
|
@@ -1,3 +1,6 @@
|
|
|
1
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
2
|
+
import { DynamoDBDocumentClient, DeleteCommand, GetCommand, PutCommand, UpdateCommand, ScanCommand, QueryCommand, BatchWriteCommand } from '@aws-sdk/lib-dynamodb';
|
|
3
|
+
import Bottleneck from 'bottleneck';
|
|
1
4
|
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
|
|
2
5
|
import { SSMClient, GetParametersCommand, GetParameterCommand } from '@aws-sdk/client-ssm';
|
|
3
6
|
import * as aws from '@aws-sdk/client-ses';
|
|
@@ -8,6 +11,189 @@ const DEFAULT_AWS_CONFIGURATION = {
|
|
|
8
11
|
region: 'eu-central-2',
|
|
9
12
|
};
|
|
10
13
|
|
|
14
|
+
const splitEvery = (every, list) => Array.from({ length: Math.ceil(list.length / every) }).map((_, count) => list.slice(count * every, count * every + every));
|
|
15
|
+
const until = async (predicate, transformer, initialValue, iterationCount = 0) => {
|
|
16
|
+
const transformed = await transformer(initialValue, iterationCount);
|
|
17
|
+
return (await predicate(transformed, iterationCount))
|
|
18
|
+
? transformed
|
|
19
|
+
: until(predicate, transformer, transformed, iterationCount + 1);
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
const DEFAULT_BATCH_ITEMS_MAX_RETRIES = 50;
|
|
23
|
+
let queue;
|
|
24
|
+
const makeKey = (key) => {
|
|
25
|
+
if (typeof key === 'string') {
|
|
26
|
+
return { id: key };
|
|
27
|
+
}
|
|
28
|
+
return key;
|
|
29
|
+
};
|
|
30
|
+
const deleteItem = async (config, documentClient, table, key, options = {}) => {
|
|
31
|
+
try {
|
|
32
|
+
const { ReturnValues = 'NONE' } = options;
|
|
33
|
+
const command = new DeleteCommand({
|
|
34
|
+
Key: makeKey(key),
|
|
35
|
+
ReturnValues,
|
|
36
|
+
TableName: config.tableNamePrefix + table,
|
|
37
|
+
});
|
|
38
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
39
|
+
return result.Attributes;
|
|
40
|
+
}
|
|
41
|
+
catch (error) {
|
|
42
|
+
if (config.logger) {
|
|
43
|
+
config.logger('error', error);
|
|
44
|
+
}
|
|
45
|
+
return undefined;
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
const getItem = async (config, documentClient, table, key, options = {}) => {
|
|
49
|
+
try {
|
|
50
|
+
const { ConsistentRead = false } = options;
|
|
51
|
+
const command = new GetCommand({
|
|
52
|
+
ConsistentRead,
|
|
53
|
+
Key: makeKey(key),
|
|
54
|
+
TableName: config.tableNamePrefix + table,
|
|
55
|
+
});
|
|
56
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
57
|
+
return result.Item;
|
|
58
|
+
}
|
|
59
|
+
catch (error) {
|
|
60
|
+
if (config.logger) {
|
|
61
|
+
config.logger('error', error);
|
|
62
|
+
}
|
|
63
|
+
return undefined;
|
|
64
|
+
}
|
|
65
|
+
};
|
|
66
|
+
const putItem = async (config, documentClient, table, Item) => {
|
|
67
|
+
try {
|
|
68
|
+
const { expires, ...data } = Item;
|
|
69
|
+
const command = new PutCommand({
|
|
70
|
+
Item: expires === null ? data : Item,
|
|
71
|
+
TableName: config.tableNamePrefix + table,
|
|
72
|
+
});
|
|
73
|
+
return (await queue.schedule(() => documentClient.send(command))) && Item;
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
if (config.logger) {
|
|
77
|
+
config.logger('error', error);
|
|
78
|
+
}
|
|
79
|
+
return undefined;
|
|
80
|
+
}
|
|
81
|
+
};
|
|
82
|
+
const updateItem = async (config, documentClient, table, key, options = {}) => {
|
|
83
|
+
try {
|
|
84
|
+
const command = new UpdateCommand({
|
|
85
|
+
Key: makeKey(key),
|
|
86
|
+
...options,
|
|
87
|
+
ReturnValues: 'ALL_NEW',
|
|
88
|
+
TableName: config.tableNamePrefix + table,
|
|
89
|
+
});
|
|
90
|
+
const result = await queue.schedule(async () => documentClient.send(command));
|
|
91
|
+
return result.Attributes;
|
|
92
|
+
}
|
|
93
|
+
catch (error) {
|
|
94
|
+
if (config.logger) {
|
|
95
|
+
config.logger('error', error);
|
|
96
|
+
}
|
|
97
|
+
return undefined;
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
const hasNoUnprocessedItems = ({ UnprocessedItems, }) => !UnprocessedItems || Object.keys(UnprocessedItems).length === 0;
|
|
101
|
+
const makeBatchWriteRequestWithExponentialBackoff = (documentClient, table, batchWriteMaxRetries) => async (batchItems, retries) => {
|
|
102
|
+
if (retries > batchWriteMaxRetries) {
|
|
103
|
+
throw new Error('Reached maximum number of DynamoDB BatchWrite request retries.');
|
|
104
|
+
}
|
|
105
|
+
const command = new BatchWriteCommand({
|
|
106
|
+
RequestItems: batchItems.UnprocessedItems ?? {
|
|
107
|
+
[table]: batchItems.map((Item) => ({
|
|
108
|
+
PutRequest: { Item },
|
|
109
|
+
})),
|
|
110
|
+
},
|
|
111
|
+
ReturnConsumedCapacity: 'TOTAL',
|
|
112
|
+
ReturnItemCollectionMetrics: 'SIZE',
|
|
113
|
+
});
|
|
114
|
+
return documentClient.send(command);
|
|
115
|
+
};
|
|
116
|
+
const batchWriteItems = async (config, documentClient, table, items) => {
|
|
117
|
+
try {
|
|
118
|
+
const batches = splitEvery(25, items);
|
|
119
|
+
const result = await Promise.all(batches.map(async (batch) => queue.schedule(async () => until(hasNoUnprocessedItems, makeBatchWriteRequestWithExponentialBackoff(documentClient, config.tableNamePrefix + table, config.batchWriteMaxRetries ?? DEFAULT_BATCH_ITEMS_MAX_RETRIES), batch))));
|
|
120
|
+
return result && items;
|
|
121
|
+
}
|
|
122
|
+
catch (error) {
|
|
123
|
+
if (config.logger) {
|
|
124
|
+
config.logger('error', error);
|
|
125
|
+
}
|
|
126
|
+
return undefined;
|
|
127
|
+
}
|
|
128
|
+
};
|
|
129
|
+
const scanTable = async (config, documentClient, table, options = {}) => {
|
|
130
|
+
try {
|
|
131
|
+
const { ConsistentRead = false } = options;
|
|
132
|
+
const command = new ScanCommand({
|
|
133
|
+
...options,
|
|
134
|
+
ConsistentRead,
|
|
135
|
+
TableName: config.tableNamePrefix + table,
|
|
136
|
+
});
|
|
137
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
138
|
+
return result;
|
|
139
|
+
}
|
|
140
|
+
catch (error) {
|
|
141
|
+
if (config.logger) {
|
|
142
|
+
config.logger('error', error);
|
|
143
|
+
}
|
|
144
|
+
return undefined;
|
|
145
|
+
}
|
|
146
|
+
};
|
|
147
|
+
const queryTable = async (config, documentClient, table, options = {}) => {
|
|
148
|
+
try {
|
|
149
|
+
const { ConsistentRead = false } = options;
|
|
150
|
+
const command = new QueryCommand({
|
|
151
|
+
...options,
|
|
152
|
+
ConsistentRead,
|
|
153
|
+
TableName: config.tableNamePrefix + table,
|
|
154
|
+
});
|
|
155
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
156
|
+
return result;
|
|
157
|
+
}
|
|
158
|
+
catch (error) {
|
|
159
|
+
if (config.logger) {
|
|
160
|
+
config.logger('error', error);
|
|
161
|
+
}
|
|
162
|
+
return undefined;
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
const dynamodb = (userConfig) => {
|
|
166
|
+
const { clientConfig, ...config } = {
|
|
167
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
168
|
+
...userConfig,
|
|
169
|
+
};
|
|
170
|
+
const ddbClient = new DynamoDBClient(config.dockerConfig
|
|
171
|
+
? {
|
|
172
|
+
credentials: {
|
|
173
|
+
accessKeyId: 'foobarkey',
|
|
174
|
+
secretAccessKey: 'foobarsecret',
|
|
175
|
+
},
|
|
176
|
+
endpoint: config.dockerConfig.endpoint,
|
|
177
|
+
region: 'local',
|
|
178
|
+
retryMode: 'standard',
|
|
179
|
+
}
|
|
180
|
+
: { retryMode: 'standard', ...clientConfig });
|
|
181
|
+
const documentClient = DynamoDBDocumentClient.from(ddbClient);
|
|
182
|
+
queue = new Bottleneck({
|
|
183
|
+
maxConcurrent: config.queueConfig?.queueConcurrency ?? 25,
|
|
184
|
+
minTime: config.queueConfig?.queueDelay ?? undefined,
|
|
185
|
+
});
|
|
186
|
+
return {
|
|
187
|
+
batchWriteItems: (table, items) => batchWriteItems(config, documentClient, table, items),
|
|
188
|
+
deleteItem: (table, key, options) => deleteItem(config, documentClient, table, key, options),
|
|
189
|
+
getItem: (table, key, options) => getItem(config, documentClient, table, key, options),
|
|
190
|
+
putItem: (table, item) => putItem(config, documentClient, table, item),
|
|
191
|
+
queryTable: (table, options) => queryTable(config, documentClient, table, options),
|
|
192
|
+
scanTable: (table, options) => scanTable(config, documentClient, table, options),
|
|
193
|
+
updateItem: (table, key, options) => updateItem(config, documentClient, table, key, options),
|
|
194
|
+
};
|
|
195
|
+
};
|
|
196
|
+
|
|
11
197
|
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
12
198
|
try {
|
|
13
199
|
const invokeCommand = new InvokeCommand({
|
|
@@ -44,9 +230,9 @@ const DEFAULT_CLIENT_CONFIG$1 = {
|
|
|
44
230
|
onlyDefault: false,
|
|
45
231
|
prefix: process.env.SSM_PARAM_PATH,
|
|
46
232
|
};
|
|
47
|
-
const getSecrets = async (ssm, config, parameters_,
|
|
233
|
+
const getSecrets = async (ssm, config, parameters_, defaultValues) => {
|
|
48
234
|
if (config.onlyDefault) {
|
|
49
|
-
return
|
|
235
|
+
return defaultValues;
|
|
50
236
|
}
|
|
51
237
|
try {
|
|
52
238
|
const command = new GetParametersCommand({
|
|
@@ -54,13 +240,21 @@ const getSecrets = async (ssm, config, parameters_, defaultValue) => {
|
|
|
54
240
|
WithDecryption: true,
|
|
55
241
|
});
|
|
56
242
|
const parameters = await ssm.send(command);
|
|
57
|
-
return (parameters?.Parameters?.map((parameter) =>
|
|
243
|
+
return (parameters?.Parameters?.map((parameter) => {
|
|
244
|
+
const defaultIfNoParameter = !parameter.Value && parameter.Name
|
|
245
|
+
? defaultValues.find((defaultValue) => defaultValue.name === parameter.Name)
|
|
246
|
+
: defaultValues[0];
|
|
247
|
+
return {
|
|
248
|
+
name: parameter.Name ?? defaultIfNoParameter?.name ?? '',
|
|
249
|
+
value: parameter.Value ?? defaultIfNoParameter?.value ?? '',
|
|
250
|
+
};
|
|
251
|
+
}) ?? defaultValues);
|
|
58
252
|
}
|
|
59
253
|
catch (error) {
|
|
60
254
|
if (config.logger) {
|
|
61
255
|
config.logger('error', error);
|
|
62
256
|
}
|
|
63
|
-
return
|
|
257
|
+
return defaultValues;
|
|
64
258
|
}
|
|
65
259
|
};
|
|
66
260
|
const getSecret = async (ssm, config, parameter_, defaultValue) => {
|
|
@@ -89,7 +283,7 @@ const parameterStore = (userConfig) => {
|
|
|
89
283
|
const ssm = new SSMClient(clientConfig);
|
|
90
284
|
return {
|
|
91
285
|
getSecret: (parameter, defaultValue = '') => getSecret(ssm, config, parameter, defaultValue),
|
|
92
|
-
getSecrets: (parameters,
|
|
286
|
+
getSecrets: (parameters, defaultValues = []) => getSecrets(ssm, config, parameters, defaultValues),
|
|
93
287
|
};
|
|
94
288
|
};
|
|
95
289
|
|
|
@@ -163,8 +357,8 @@ const logger = (config) => {
|
|
|
163
357
|
}
|
|
164
358
|
return createLogger({
|
|
165
359
|
...loggerConfig,
|
|
166
|
-
transports: [new transports.Console()],
|
|
360
|
+
transports: [new transports.Console({ forceConsole: true })],
|
|
167
361
|
});
|
|
168
362
|
};
|
|
169
363
|
|
|
170
|
-
export { DEFAULT_CLIENT_CONFIG$1 as DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, lambda, logger, parameterStore, ses };
|
|
364
|
+
export { DEFAULT_CLIENT_CONFIG$1 as DEFAULT_PARAMETER_STORE_CLIENT_CONFIG, DEFAULT_CLIENT_CONFIG as DEFAULT_SES_CLIENT_CONFIG, dynamodb, lambda, logger, parameterStore, ses };
|