@allthings/cloud-toolkit 5.1.0 → 5.2.0-beta.2
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/dist/alagarr.cjs.js +690 -0
- package/dist/alagarr.esm.mjs +663 -0
- package/dist/base64.cjs.js +7 -0
- package/dist/base64.esm.mjs +4 -0
- package/dist/dynamodb.cjs.js +195 -0
- package/dist/dynamodb.esm.mjs +193 -0
- package/dist/lambda.cjs.js +40 -0
- package/dist/lambda.esm.mjs +38 -0
- package/dist/logger.cjs.js +35 -0
- package/dist/logger.esm.mjs +33 -0
- package/dist/parameterStore.cjs.js +84 -0
- package/dist/parameterStore.esm.mjs +79 -0
- package/dist/ses.cjs.js +62 -0
- package/dist/ses.esm.mjs +57 -0
- package/dist/sqs.cjs.js +102 -0
- package/dist/sqs.esm.mjs +100 -0
- package/dist/utils.cjs.js +41 -0
- package/dist/utils.esm.mjs +33 -0
- package/package.json +77 -1
|
@@ -0,0 +1,195 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clientDynamodb = require('@aws-sdk/client-dynamodb');
|
|
4
|
+
var libDynamodb = require('@aws-sdk/lib-dynamodb');
|
|
5
|
+
var Bottleneck = require('bottleneck');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
8
|
+
region: 'eu-central-2',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const splitEvery = (every, list) => Array.from({ length: Math.ceil(list.length / every) }).map((_, count) => list.slice(count * every, count * every + every));
|
|
12
|
+
const until = async (predicate, transformer, initialValue, iterationCount = 0) => {
|
|
13
|
+
const transformed = await transformer(initialValue, iterationCount);
|
|
14
|
+
return (await predicate(transformed, iterationCount))
|
|
15
|
+
? transformed
|
|
16
|
+
: until(predicate, transformer, transformed, iterationCount + 1);
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
const DEFAULT_BATCH_ITEMS_MAX_RETRIES = 50;
|
|
20
|
+
let queue;
|
|
21
|
+
const makeKey = (key) => {
|
|
22
|
+
if (typeof key === 'string') {
|
|
23
|
+
return { id: key };
|
|
24
|
+
}
|
|
25
|
+
return key;
|
|
26
|
+
};
|
|
27
|
+
const deleteItem = async (config, documentClient, table, key, options = {}) => {
|
|
28
|
+
try {
|
|
29
|
+
const { ReturnValues = 'NONE' } = options;
|
|
30
|
+
const command = new libDynamodb.DeleteCommand({
|
|
31
|
+
Key: makeKey(key),
|
|
32
|
+
ReturnValues,
|
|
33
|
+
TableName: config.tableNamePrefix + table,
|
|
34
|
+
});
|
|
35
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
36
|
+
return result.Attributes;
|
|
37
|
+
}
|
|
38
|
+
catch (error) {
|
|
39
|
+
if (config.logger) {
|
|
40
|
+
config.logger.error(error);
|
|
41
|
+
}
|
|
42
|
+
return undefined;
|
|
43
|
+
}
|
|
44
|
+
};
|
|
45
|
+
const getItem = async (config, documentClient, table, key, options = {}) => {
|
|
46
|
+
try {
|
|
47
|
+
const { ConsistentRead = false } = options;
|
|
48
|
+
const command = new libDynamodb.GetCommand({
|
|
49
|
+
ConsistentRead,
|
|
50
|
+
Key: makeKey(key),
|
|
51
|
+
TableName: config.tableNamePrefix + table,
|
|
52
|
+
});
|
|
53
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
54
|
+
return result.Item;
|
|
55
|
+
}
|
|
56
|
+
catch (error) {
|
|
57
|
+
if (config.logger) {
|
|
58
|
+
config.logger.error(error);
|
|
59
|
+
}
|
|
60
|
+
return undefined;
|
|
61
|
+
}
|
|
62
|
+
};
|
|
63
|
+
const putItem = async (config, documentClient, table, Item) => {
|
|
64
|
+
try {
|
|
65
|
+
const { expires, ...data } = Item;
|
|
66
|
+
const command = new libDynamodb.PutCommand({
|
|
67
|
+
Item: expires === null ? data : Item,
|
|
68
|
+
TableName: config.tableNamePrefix + table,
|
|
69
|
+
});
|
|
70
|
+
return (await queue.schedule(() => documentClient.send(command))) && Item;
|
|
71
|
+
}
|
|
72
|
+
catch (error) {
|
|
73
|
+
if (config.logger) {
|
|
74
|
+
config.logger.error(error);
|
|
75
|
+
}
|
|
76
|
+
return undefined;
|
|
77
|
+
}
|
|
78
|
+
};
|
|
79
|
+
const updateItem = async (config, documentClient, table, key, options = {}) => {
|
|
80
|
+
try {
|
|
81
|
+
const command = new libDynamodb.UpdateCommand({
|
|
82
|
+
Key: makeKey(key),
|
|
83
|
+
...options,
|
|
84
|
+
ReturnValues: 'ALL_NEW',
|
|
85
|
+
TableName: config.tableNamePrefix + table,
|
|
86
|
+
});
|
|
87
|
+
const result = await queue.schedule(async () => documentClient.send(command));
|
|
88
|
+
return result.Attributes;
|
|
89
|
+
}
|
|
90
|
+
catch (error) {
|
|
91
|
+
if (config.logger) {
|
|
92
|
+
config.logger.error(error);
|
|
93
|
+
}
|
|
94
|
+
return undefined;
|
|
95
|
+
}
|
|
96
|
+
};
|
|
97
|
+
const hasNoUnprocessedItems = ({ UnprocessedItems, }) => !UnprocessedItems || Object.keys(UnprocessedItems).length === 0;
|
|
98
|
+
const makeBatchWriteRequestWithExponentialBackoff = (documentClient, table, batchWriteMaxRetries) => async (batchItems, retries) => {
|
|
99
|
+
if (retries > batchWriteMaxRetries) {
|
|
100
|
+
throw new Error('Reached maximum number of DynamoDB BatchWrite request retries.');
|
|
101
|
+
}
|
|
102
|
+
if (batchItems === undefined) {
|
|
103
|
+
throw new Error('makeBatchWriteRequestWithExponentialBackoff: batchItems must not be undefined.');
|
|
104
|
+
}
|
|
105
|
+
const command = new libDynamodb.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 libDynamodb.ScanCommand({
|
|
133
|
+
...options,
|
|
134
|
+
ConsistentRead,
|
|
135
|
+
TableName: config.tableNamePrefix + table,
|
|
136
|
+
});
|
|
137
|
+
return await queue.schedule(() => documentClient.send(command));
|
|
138
|
+
}
|
|
139
|
+
catch (error) {
|
|
140
|
+
if (config.logger) {
|
|
141
|
+
config.logger.error(error);
|
|
142
|
+
}
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
};
|
|
146
|
+
const queryTable = async (config, documentClient, table, options = {}) => {
|
|
147
|
+
try {
|
|
148
|
+
const { ConsistentRead = false } = options;
|
|
149
|
+
const command = new libDynamodb.QueryCommand({
|
|
150
|
+
...options,
|
|
151
|
+
ConsistentRead,
|
|
152
|
+
TableName: config.tableNamePrefix + table,
|
|
153
|
+
});
|
|
154
|
+
return await queue.schedule(() => documentClient.send(command));
|
|
155
|
+
}
|
|
156
|
+
catch (error) {
|
|
157
|
+
if (config.logger) {
|
|
158
|
+
config.logger.error(error);
|
|
159
|
+
}
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
};
|
|
163
|
+
const dynamodb = (userConfig) => {
|
|
164
|
+
const { clientConfig, ...config } = {
|
|
165
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
166
|
+
...userConfig,
|
|
167
|
+
};
|
|
168
|
+
const ddbClient = new clientDynamodb.DynamoDBClient(config.dockerConfig
|
|
169
|
+
? {
|
|
170
|
+
credentials: {
|
|
171
|
+
accessKeyId: 'foobarkey',
|
|
172
|
+
secretAccessKey: 'foobarsecret',
|
|
173
|
+
},
|
|
174
|
+
endpoint: config.dockerConfig.endpoint,
|
|
175
|
+
region: 'local',
|
|
176
|
+
retryMode: 'standard',
|
|
177
|
+
}
|
|
178
|
+
: { retryMode: 'standard', ...clientConfig });
|
|
179
|
+
const documentClient = libDynamodb.DynamoDBDocumentClient.from(ddbClient);
|
|
180
|
+
queue = new Bottleneck({
|
|
181
|
+
maxConcurrent: config.queueConfig?.queueConcurrency ?? 25,
|
|
182
|
+
minTime: config.queueConfig?.queueDelay ?? undefined,
|
|
183
|
+
});
|
|
184
|
+
return {
|
|
185
|
+
batchWriteItems: (table, items) => batchWriteItems(config, documentClient, table, items),
|
|
186
|
+
deleteItem: (table, key, options) => deleteItem(config, documentClient, table, key, options),
|
|
187
|
+
getItem: (table, key, options) => getItem(config, documentClient, table, key, options),
|
|
188
|
+
putItem: (table, item) => putItem(config, documentClient, table, item),
|
|
189
|
+
queryTable: (table, options) => queryTable(config, documentClient, table, options),
|
|
190
|
+
scanTable: (table, options) => scanTable(config, documentClient, table, options),
|
|
191
|
+
updateItem: (table, key, options) => updateItem(config, documentClient, table, key, options),
|
|
192
|
+
};
|
|
193
|
+
};
|
|
194
|
+
|
|
195
|
+
module.exports = dynamodb;
|
|
@@ -0,0 +1,193 @@
|
|
|
1
|
+
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
|
|
2
|
+
import { DynamoDBDocumentClient, UpdateCommand, ScanCommand, QueryCommand, PutCommand, GetCommand, DeleteCommand, BatchWriteCommand } from '@aws-sdk/lib-dynamodb';
|
|
3
|
+
import Bottleneck from 'bottleneck';
|
|
4
|
+
|
|
5
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
6
|
+
region: 'eu-central-2',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const splitEvery = (every, list) => Array.from({ length: Math.ceil(list.length / every) }).map((_, count) => list.slice(count * every, count * every + every));
|
|
10
|
+
const until = async (predicate, transformer, initialValue, iterationCount = 0) => {
|
|
11
|
+
const transformed = await transformer(initialValue, iterationCount);
|
|
12
|
+
return (await predicate(transformed, iterationCount))
|
|
13
|
+
? transformed
|
|
14
|
+
: until(predicate, transformer, transformed, iterationCount + 1);
|
|
15
|
+
};
|
|
16
|
+
|
|
17
|
+
const DEFAULT_BATCH_ITEMS_MAX_RETRIES = 50;
|
|
18
|
+
let queue;
|
|
19
|
+
const makeKey = (key) => {
|
|
20
|
+
if (typeof key === 'string') {
|
|
21
|
+
return { id: key };
|
|
22
|
+
}
|
|
23
|
+
return key;
|
|
24
|
+
};
|
|
25
|
+
const deleteItem = async (config, documentClient, table, key, options = {}) => {
|
|
26
|
+
try {
|
|
27
|
+
const { ReturnValues = 'NONE' } = options;
|
|
28
|
+
const command = new DeleteCommand({
|
|
29
|
+
Key: makeKey(key),
|
|
30
|
+
ReturnValues,
|
|
31
|
+
TableName: config.tableNamePrefix + table,
|
|
32
|
+
});
|
|
33
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
34
|
+
return result.Attributes;
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (config.logger) {
|
|
38
|
+
config.logger.error(error);
|
|
39
|
+
}
|
|
40
|
+
return undefined;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const getItem = async (config, documentClient, table, key, options = {}) => {
|
|
44
|
+
try {
|
|
45
|
+
const { ConsistentRead = false } = options;
|
|
46
|
+
const command = new GetCommand({
|
|
47
|
+
ConsistentRead,
|
|
48
|
+
Key: makeKey(key),
|
|
49
|
+
TableName: config.tableNamePrefix + table,
|
|
50
|
+
});
|
|
51
|
+
const result = await queue.schedule(() => documentClient.send(command));
|
|
52
|
+
return result.Item;
|
|
53
|
+
}
|
|
54
|
+
catch (error) {
|
|
55
|
+
if (config.logger) {
|
|
56
|
+
config.logger.error(error);
|
|
57
|
+
}
|
|
58
|
+
return undefined;
|
|
59
|
+
}
|
|
60
|
+
};
|
|
61
|
+
const putItem = async (config, documentClient, table, Item) => {
|
|
62
|
+
try {
|
|
63
|
+
const { expires, ...data } = Item;
|
|
64
|
+
const command = new PutCommand({
|
|
65
|
+
Item: expires === null ? data : Item,
|
|
66
|
+
TableName: config.tableNamePrefix + table,
|
|
67
|
+
});
|
|
68
|
+
return (await queue.schedule(() => documentClient.send(command))) && Item;
|
|
69
|
+
}
|
|
70
|
+
catch (error) {
|
|
71
|
+
if (config.logger) {
|
|
72
|
+
config.logger.error(error);
|
|
73
|
+
}
|
|
74
|
+
return undefined;
|
|
75
|
+
}
|
|
76
|
+
};
|
|
77
|
+
const updateItem = async (config, documentClient, table, key, options = {}) => {
|
|
78
|
+
try {
|
|
79
|
+
const command = new UpdateCommand({
|
|
80
|
+
Key: makeKey(key),
|
|
81
|
+
...options,
|
|
82
|
+
ReturnValues: 'ALL_NEW',
|
|
83
|
+
TableName: config.tableNamePrefix + table,
|
|
84
|
+
});
|
|
85
|
+
const result = await queue.schedule(async () => documentClient.send(command));
|
|
86
|
+
return result.Attributes;
|
|
87
|
+
}
|
|
88
|
+
catch (error) {
|
|
89
|
+
if (config.logger) {
|
|
90
|
+
config.logger.error(error);
|
|
91
|
+
}
|
|
92
|
+
return undefined;
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
const hasNoUnprocessedItems = ({ UnprocessedItems, }) => !UnprocessedItems || Object.keys(UnprocessedItems).length === 0;
|
|
96
|
+
const makeBatchWriteRequestWithExponentialBackoff = (documentClient, table, batchWriteMaxRetries) => async (batchItems, retries) => {
|
|
97
|
+
if (retries > batchWriteMaxRetries) {
|
|
98
|
+
throw new Error('Reached maximum number of DynamoDB BatchWrite request retries.');
|
|
99
|
+
}
|
|
100
|
+
if (batchItems === undefined) {
|
|
101
|
+
throw new Error('makeBatchWriteRequestWithExponentialBackoff: batchItems must not be undefined.');
|
|
102
|
+
}
|
|
103
|
+
const command = new BatchWriteCommand({
|
|
104
|
+
RequestItems: batchItems.UnprocessedItems ?? {
|
|
105
|
+
[table]: batchItems.map((Item) => ({
|
|
106
|
+
PutRequest: { Item },
|
|
107
|
+
})),
|
|
108
|
+
},
|
|
109
|
+
ReturnConsumedCapacity: 'TOTAL',
|
|
110
|
+
ReturnItemCollectionMetrics: 'SIZE',
|
|
111
|
+
});
|
|
112
|
+
return documentClient.send(command);
|
|
113
|
+
};
|
|
114
|
+
const batchWriteItems = async (config, documentClient, table, items) => {
|
|
115
|
+
try {
|
|
116
|
+
const batches = splitEvery(25, items);
|
|
117
|
+
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))));
|
|
118
|
+
return result && items;
|
|
119
|
+
}
|
|
120
|
+
catch (error) {
|
|
121
|
+
if (config.logger) {
|
|
122
|
+
config.logger.error(error);
|
|
123
|
+
}
|
|
124
|
+
return undefined;
|
|
125
|
+
}
|
|
126
|
+
};
|
|
127
|
+
const scanTable = async (config, documentClient, table, options = {}) => {
|
|
128
|
+
try {
|
|
129
|
+
const { ConsistentRead = false } = options;
|
|
130
|
+
const command = new ScanCommand({
|
|
131
|
+
...options,
|
|
132
|
+
ConsistentRead,
|
|
133
|
+
TableName: config.tableNamePrefix + table,
|
|
134
|
+
});
|
|
135
|
+
return await queue.schedule(() => documentClient.send(command));
|
|
136
|
+
}
|
|
137
|
+
catch (error) {
|
|
138
|
+
if (config.logger) {
|
|
139
|
+
config.logger.error(error);
|
|
140
|
+
}
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
};
|
|
144
|
+
const queryTable = async (config, documentClient, table, options = {}) => {
|
|
145
|
+
try {
|
|
146
|
+
const { ConsistentRead = false } = options;
|
|
147
|
+
const command = new QueryCommand({
|
|
148
|
+
...options,
|
|
149
|
+
ConsistentRead,
|
|
150
|
+
TableName: config.tableNamePrefix + table,
|
|
151
|
+
});
|
|
152
|
+
return await queue.schedule(() => documentClient.send(command));
|
|
153
|
+
}
|
|
154
|
+
catch (error) {
|
|
155
|
+
if (config.logger) {
|
|
156
|
+
config.logger.error(error);
|
|
157
|
+
}
|
|
158
|
+
return undefined;
|
|
159
|
+
}
|
|
160
|
+
};
|
|
161
|
+
const dynamodb = (userConfig) => {
|
|
162
|
+
const { clientConfig, ...config } = {
|
|
163
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
164
|
+
...userConfig,
|
|
165
|
+
};
|
|
166
|
+
const ddbClient = new DynamoDBClient(config.dockerConfig
|
|
167
|
+
? {
|
|
168
|
+
credentials: {
|
|
169
|
+
accessKeyId: 'foobarkey',
|
|
170
|
+
secretAccessKey: 'foobarsecret',
|
|
171
|
+
},
|
|
172
|
+
endpoint: config.dockerConfig.endpoint,
|
|
173
|
+
region: 'local',
|
|
174
|
+
retryMode: 'standard',
|
|
175
|
+
}
|
|
176
|
+
: { retryMode: 'standard', ...clientConfig });
|
|
177
|
+
const documentClient = DynamoDBDocumentClient.from(ddbClient);
|
|
178
|
+
queue = new Bottleneck({
|
|
179
|
+
maxConcurrent: config.queueConfig?.queueConcurrency ?? 25,
|
|
180
|
+
minTime: config.queueConfig?.queueDelay ?? undefined,
|
|
181
|
+
});
|
|
182
|
+
return {
|
|
183
|
+
batchWriteItems: (table, items) => batchWriteItems(config, documentClient, table, items),
|
|
184
|
+
deleteItem: (table, key, options) => deleteItem(config, documentClient, table, key, options),
|
|
185
|
+
getItem: (table, key, options) => getItem(config, documentClient, table, key, options),
|
|
186
|
+
putItem: (table, item) => putItem(config, documentClient, table, item),
|
|
187
|
+
queryTable: (table, options) => queryTable(config, documentClient, table, options),
|
|
188
|
+
scanTable: (table, options) => scanTable(config, documentClient, table, options),
|
|
189
|
+
updateItem: (table, key, options) => updateItem(config, documentClient, table, key, options),
|
|
190
|
+
};
|
|
191
|
+
};
|
|
192
|
+
|
|
193
|
+
export { dynamodb as default };
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var clientLambda = require('@aws-sdk/client-lambda');
|
|
4
|
+
|
|
5
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
6
|
+
region: 'eu-central-2',
|
|
7
|
+
};
|
|
8
|
+
|
|
9
|
+
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
10
|
+
try {
|
|
11
|
+
const invokeCommand = new clientLambda.InvokeCommand({
|
|
12
|
+
FunctionName: config.functionName,
|
|
13
|
+
InvocationType: invocationType,
|
|
14
|
+
Payload: Buffer.from(JSON.stringify(payload)),
|
|
15
|
+
});
|
|
16
|
+
const result = await lambdaClient.send(invokeCommand);
|
|
17
|
+
if (config.logger) {
|
|
18
|
+
config.logger.info(JSON.stringify(result));
|
|
19
|
+
}
|
|
20
|
+
return true;
|
|
21
|
+
}
|
|
22
|
+
catch (error) {
|
|
23
|
+
if (config.logger) {
|
|
24
|
+
config.logger.error(error);
|
|
25
|
+
}
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
const lambda = (userConfig) => {
|
|
30
|
+
const { clientConfig, ...config } = {
|
|
31
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
32
|
+
...userConfig,
|
|
33
|
+
};
|
|
34
|
+
const lambdaClient = new clientLambda.LambdaClient(clientConfig);
|
|
35
|
+
return {
|
|
36
|
+
invokeLambda: (invocationType, payload) => invokeLambda(lambdaClient, config, invocationType, payload),
|
|
37
|
+
};
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
module.exports = lambda;
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import { LambdaClient, InvokeCommand } from '@aws-sdk/client-lambda';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
4
|
+
region: 'eu-central-2',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const invokeLambda = async (lambdaClient, config, invocationType, payload) => {
|
|
8
|
+
try {
|
|
9
|
+
const invokeCommand = new InvokeCommand({
|
|
10
|
+
FunctionName: config.functionName,
|
|
11
|
+
InvocationType: invocationType,
|
|
12
|
+
Payload: Buffer.from(JSON.stringify(payload)),
|
|
13
|
+
});
|
|
14
|
+
const result = await lambdaClient.send(invokeCommand);
|
|
15
|
+
if (config.logger) {
|
|
16
|
+
config.logger.info(JSON.stringify(result));
|
|
17
|
+
}
|
|
18
|
+
return true;
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
if (config.logger) {
|
|
22
|
+
config.logger.error(error);
|
|
23
|
+
}
|
|
24
|
+
return false;
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
const lambda = (userConfig) => {
|
|
28
|
+
const { clientConfig, ...config } = {
|
|
29
|
+
...DEFAULT_AWS_CONFIGURATION,
|
|
30
|
+
...userConfig,
|
|
31
|
+
};
|
|
32
|
+
const lambdaClient = new LambdaClient(clientConfig);
|
|
33
|
+
return {
|
|
34
|
+
invokeLambda: (invocationType, payload) => invokeLambda(lambdaClient, config, invocationType, payload),
|
|
35
|
+
};
|
|
36
|
+
};
|
|
37
|
+
|
|
38
|
+
export { lambda as default };
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var winston = require('winston');
|
|
4
|
+
|
|
5
|
+
const logger = (config) => {
|
|
6
|
+
const loggerConfig = {
|
|
7
|
+
defaultMeta: {
|
|
8
|
+
...config.defaultLogInformation,
|
|
9
|
+
deploymentStage: config.deploymentStage,
|
|
10
|
+
service: config.service,
|
|
11
|
+
},
|
|
12
|
+
format: winston.format.combine(winston.format.timestamp({
|
|
13
|
+
format: 'DD-MM-YYYY HH:mm:ss',
|
|
14
|
+
}), winston.format.json()),
|
|
15
|
+
level: config.level || 'info',
|
|
16
|
+
};
|
|
17
|
+
if (config.datadogApiKey) {
|
|
18
|
+
const httpOptions = {
|
|
19
|
+
host: 'http-intake.logs.datadoghq.eu',
|
|
20
|
+
path: `/api/v2/logs?dd-api-key=${config.datadogApiKey}&ddsource=nodejs&service=${config.service}`,
|
|
21
|
+
port: 443,
|
|
22
|
+
ssl: true,
|
|
23
|
+
};
|
|
24
|
+
return winston.createLogger({
|
|
25
|
+
...loggerConfig,
|
|
26
|
+
transports: [new winston.transports.Http(httpOptions)],
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
return winston.createLogger({
|
|
30
|
+
...loggerConfig,
|
|
31
|
+
transports: [new winston.transports.Console({ forceConsole: true })],
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
module.exports = logger;
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { format, createLogger, transports } from 'winston';
|
|
2
|
+
|
|
3
|
+
const logger = (config) => {
|
|
4
|
+
const loggerConfig = {
|
|
5
|
+
defaultMeta: {
|
|
6
|
+
...config.defaultLogInformation,
|
|
7
|
+
deploymentStage: config.deploymentStage,
|
|
8
|
+
service: config.service,
|
|
9
|
+
},
|
|
10
|
+
format: format.combine(format.timestamp({
|
|
11
|
+
format: 'DD-MM-YYYY HH:mm:ss',
|
|
12
|
+
}), format.json()),
|
|
13
|
+
level: config.level || 'info',
|
|
14
|
+
};
|
|
15
|
+
if (config.datadogApiKey) {
|
|
16
|
+
const httpOptions = {
|
|
17
|
+
host: 'http-intake.logs.datadoghq.eu',
|
|
18
|
+
path: `/api/v2/logs?dd-api-key=${config.datadogApiKey}&ddsource=nodejs&service=${config.service}`,
|
|
19
|
+
port: 443,
|
|
20
|
+
ssl: true,
|
|
21
|
+
};
|
|
22
|
+
return createLogger({
|
|
23
|
+
...loggerConfig,
|
|
24
|
+
transports: [new transports.Http(httpOptions)],
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
return createLogger({
|
|
28
|
+
...loggerConfig,
|
|
29
|
+
transports: [new transports.Console({ forceConsole: true })],
|
|
30
|
+
});
|
|
31
|
+
};
|
|
32
|
+
|
|
33
|
+
export { logger as default };
|
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
|
+
|
|
5
|
+
var clientSsm = require('@aws-sdk/client-ssm');
|
|
6
|
+
|
|
7
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
8
|
+
region: 'eu-central-2',
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
const DEFAULT_CLIENT_CONFIG = {
|
|
12
|
+
clientConfig: DEFAULT_AWS_CONFIGURATION,
|
|
13
|
+
onlyDefault: false,
|
|
14
|
+
prefix: process.env.SSM_PARAM_PATH,
|
|
15
|
+
};
|
|
16
|
+
const getSecrets = async (ssm, config, parameters_, defaultValues) => {
|
|
17
|
+
if (config.onlyDefault) {
|
|
18
|
+
return defaultValues;
|
|
19
|
+
}
|
|
20
|
+
try {
|
|
21
|
+
const command = new clientSsm.GetParametersCommand({
|
|
22
|
+
Names: parameters_.map((parameter) => `${config.prefix ?? ''}${parameter}`),
|
|
23
|
+
WithDecryption: true,
|
|
24
|
+
});
|
|
25
|
+
const parameters = await ssm.send(command);
|
|
26
|
+
return (parameters?.Parameters?.map((parameter) => {
|
|
27
|
+
const defaultIfNoParameter = !parameter.Value && parameter.Name
|
|
28
|
+
? defaultValues.find((defaultValue) => defaultValue.name === parameter.Name)
|
|
29
|
+
: defaultValues[0];
|
|
30
|
+
return {
|
|
31
|
+
name: parameter.Name ?? defaultIfNoParameter?.name ?? '',
|
|
32
|
+
value: parameter.Value ?? defaultIfNoParameter?.value ?? '',
|
|
33
|
+
};
|
|
34
|
+
}) ?? defaultValues);
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
if (config.logger) {
|
|
38
|
+
config.logger.error(error);
|
|
39
|
+
}
|
|
40
|
+
return defaultValues;
|
|
41
|
+
}
|
|
42
|
+
};
|
|
43
|
+
const getSecret = async (ssm, config, parameter_, defaultValue) => {
|
|
44
|
+
if (config.onlyDefault) {
|
|
45
|
+
if (defaultValue === undefined) {
|
|
46
|
+
throw new Error(`Cannot retrieve parameter ${parameter_}: onlyDefault is enabled and no default value was provided`);
|
|
47
|
+
}
|
|
48
|
+
return defaultValue;
|
|
49
|
+
}
|
|
50
|
+
try {
|
|
51
|
+
const parameter = await ssm.send(new clientSsm.GetParameterCommand({
|
|
52
|
+
Name: `${config.prefix ?? ''}${parameter_}`,
|
|
53
|
+
WithDecryption: true,
|
|
54
|
+
}));
|
|
55
|
+
const value = parameter?.Parameter?.Value;
|
|
56
|
+
if (value === undefined) {
|
|
57
|
+
throw new Error(`Could not retrieve parameter ${parameter_} from AWS SSM parameter store`);
|
|
58
|
+
}
|
|
59
|
+
return value;
|
|
60
|
+
}
|
|
61
|
+
catch (error) {
|
|
62
|
+
if (config.logger) {
|
|
63
|
+
config.logger.error(error);
|
|
64
|
+
}
|
|
65
|
+
if (defaultValue === undefined) {
|
|
66
|
+
throw error;
|
|
67
|
+
}
|
|
68
|
+
return defaultValue;
|
|
69
|
+
}
|
|
70
|
+
};
|
|
71
|
+
const parameterStore = (userConfig) => {
|
|
72
|
+
const { clientConfig, ...config } = {
|
|
73
|
+
...DEFAULT_CLIENT_CONFIG,
|
|
74
|
+
...userConfig,
|
|
75
|
+
};
|
|
76
|
+
const ssm = new clientSsm.SSMClient(clientConfig);
|
|
77
|
+
return {
|
|
78
|
+
getSecret: (parameter, defaultValue) => getSecret(ssm, config, parameter, defaultValue),
|
|
79
|
+
getSecrets: (parameters, defaultValues = []) => getSecrets(ssm, config, parameters, defaultValues),
|
|
80
|
+
};
|
|
81
|
+
};
|
|
82
|
+
|
|
83
|
+
exports.DEFAULT_CLIENT_CONFIG = DEFAULT_CLIENT_CONFIG;
|
|
84
|
+
exports.default = parameterStore;
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
import { SSMClient, GetParametersCommand, GetParameterCommand } from '@aws-sdk/client-ssm';
|
|
2
|
+
|
|
3
|
+
const DEFAULT_AWS_CONFIGURATION = {
|
|
4
|
+
region: 'eu-central-2',
|
|
5
|
+
};
|
|
6
|
+
|
|
7
|
+
const DEFAULT_CLIENT_CONFIG = {
|
|
8
|
+
clientConfig: DEFAULT_AWS_CONFIGURATION,
|
|
9
|
+
onlyDefault: false,
|
|
10
|
+
prefix: process.env.SSM_PARAM_PATH,
|
|
11
|
+
};
|
|
12
|
+
const getSecrets = async (ssm, config, parameters_, defaultValues) => {
|
|
13
|
+
if (config.onlyDefault) {
|
|
14
|
+
return defaultValues;
|
|
15
|
+
}
|
|
16
|
+
try {
|
|
17
|
+
const command = new GetParametersCommand({
|
|
18
|
+
Names: parameters_.map((parameter) => `${config.prefix ?? ''}${parameter}`),
|
|
19
|
+
WithDecryption: true,
|
|
20
|
+
});
|
|
21
|
+
const parameters = await ssm.send(command);
|
|
22
|
+
return (parameters?.Parameters?.map((parameter) => {
|
|
23
|
+
const defaultIfNoParameter = !parameter.Value && parameter.Name
|
|
24
|
+
? defaultValues.find((defaultValue) => defaultValue.name === parameter.Name)
|
|
25
|
+
: defaultValues[0];
|
|
26
|
+
return {
|
|
27
|
+
name: parameter.Name ?? defaultIfNoParameter?.name ?? '',
|
|
28
|
+
value: parameter.Value ?? defaultIfNoParameter?.value ?? '',
|
|
29
|
+
};
|
|
30
|
+
}) ?? defaultValues);
|
|
31
|
+
}
|
|
32
|
+
catch (error) {
|
|
33
|
+
if (config.logger) {
|
|
34
|
+
config.logger.error(error);
|
|
35
|
+
}
|
|
36
|
+
return defaultValues;
|
|
37
|
+
}
|
|
38
|
+
};
|
|
39
|
+
const getSecret = async (ssm, config, parameter_, defaultValue) => {
|
|
40
|
+
if (config.onlyDefault) {
|
|
41
|
+
if (defaultValue === undefined) {
|
|
42
|
+
throw new Error(`Cannot retrieve parameter ${parameter_}: onlyDefault is enabled and no default value was provided`);
|
|
43
|
+
}
|
|
44
|
+
return defaultValue;
|
|
45
|
+
}
|
|
46
|
+
try {
|
|
47
|
+
const parameter = await ssm.send(new GetParameterCommand({
|
|
48
|
+
Name: `${config.prefix ?? ''}${parameter_}`,
|
|
49
|
+
WithDecryption: true,
|
|
50
|
+
}));
|
|
51
|
+
const value = parameter?.Parameter?.Value;
|
|
52
|
+
if (value === undefined) {
|
|
53
|
+
throw new Error(`Could not retrieve parameter ${parameter_} from AWS SSM parameter store`);
|
|
54
|
+
}
|
|
55
|
+
return value;
|
|
56
|
+
}
|
|
57
|
+
catch (error) {
|
|
58
|
+
if (config.logger) {
|
|
59
|
+
config.logger.error(error);
|
|
60
|
+
}
|
|
61
|
+
if (defaultValue === undefined) {
|
|
62
|
+
throw error;
|
|
63
|
+
}
|
|
64
|
+
return defaultValue;
|
|
65
|
+
}
|
|
66
|
+
};
|
|
67
|
+
const parameterStore = (userConfig) => {
|
|
68
|
+
const { clientConfig, ...config } = {
|
|
69
|
+
...DEFAULT_CLIENT_CONFIG,
|
|
70
|
+
...userConfig,
|
|
71
|
+
};
|
|
72
|
+
const ssm = new SSMClient(clientConfig);
|
|
73
|
+
return {
|
|
74
|
+
getSecret: (parameter, defaultValue) => getSecret(ssm, config, parameter, defaultValue),
|
|
75
|
+
getSecrets: (parameters, defaultValues = []) => getSecrets(ssm, config, parameters, defaultValues),
|
|
76
|
+
};
|
|
77
|
+
};
|
|
78
|
+
|
|
79
|
+
export { DEFAULT_CLIENT_CONFIG, parameterStore as default };
|