idea-aws 3.8.9 → 3.10.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/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/src/attachments.js +2 -9
- package/dist/src/cognito.d.ts +7 -0
- package/dist/src/cognito.js +17 -7
- package/dist/src/comprehend.js +1 -5
- package/dist/src/dynamoDB.js +24 -27
- package/dist/src/genericController.d.ts +29 -1
- package/dist/src/genericController.js +31 -5
- package/dist/src/logger.d.ts +19 -0
- package/dist/src/logger.js +53 -0
- package/dist/src/resourceController.d.ts +22 -5
- package/dist/src/resourceController.js +88 -44
- package/dist/src/s3.js +8 -10
- package/dist/src/secretsManager.js +3 -14
- package/dist/src/ses.js +8 -15
- package/dist/src/sns.js +2 -8
- package/dist/src/streamController.js +3 -2
- package/dist/src/translate.js +1 -5
- package/index.ts +2 -0
- package/package.json +8 -7
package/dist/index.d.ts
CHANGED
package/dist/index.js
CHANGED
package/dist/src/attachments.js
CHANGED
|
@@ -3,9 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Attachments = void 0;
|
|
4
4
|
const dynamoDB_1 = require("./dynamoDB");
|
|
5
5
|
const s3_1 = require("./s3");
|
|
6
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
7
|
-
let ideaWarmStart_ddb = null;
|
|
8
|
-
let ideaWarmStart_s3 = null;
|
|
9
6
|
/**
|
|
10
7
|
* A custom class that takes advantage of DynamoDB and S3 to easily manage attachments.
|
|
11
8
|
*/
|
|
@@ -16,12 +13,8 @@ class Attachments {
|
|
|
16
13
|
*/
|
|
17
14
|
this.S3_ATTACHMENTS_BUCKET = process.env['S3_ATTACHMENTS_BUCKET'] || 'idea-attachments';
|
|
18
15
|
this.IUID_ATTACHMENTS_PREFIX = process.env['IUID_ATTACHMENTS_PREFIX'] || 'ATT';
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
this.dynamo = ideaWarmStart_ddb;
|
|
22
|
-
if (!ideaWarmStart_s3)
|
|
23
|
-
ideaWarmStart_s3 = new s3_1.S3();
|
|
24
|
-
this.s3 = ideaWarmStart_s3;
|
|
16
|
+
this.dynamo = new dynamoDB_1.DynamoDB();
|
|
17
|
+
this.s3 = new s3_1.S3();
|
|
25
18
|
}
|
|
26
19
|
/**
|
|
27
20
|
* Get a signedURL to put an attachment.
|
package/dist/src/cognito.d.ts
CHANGED
|
@@ -30,6 +30,13 @@ export declare class Cognito {
|
|
|
30
30
|
* Identify a user by its userId (sub), returning its attributes.
|
|
31
31
|
*/
|
|
32
32
|
getUserBySub(sub: string, cognitoUserPoolId: string): Promise<CognitoUserGeneric>;
|
|
33
|
+
/**
|
|
34
|
+
* Get all the users of the pool.
|
|
35
|
+
*/
|
|
36
|
+
getAllUsers(cognitoUserPoolId: string, options?: {
|
|
37
|
+
pagination?: string;
|
|
38
|
+
users: CognitoUser[];
|
|
39
|
+
}): Promise<CognitoUser[]>;
|
|
33
40
|
/**
|
|
34
41
|
* Create a new user (by its email) in the pool specified.
|
|
35
42
|
* @return userId of the new user
|
package/dist/src/cognito.js
CHANGED
|
@@ -3,16 +3,12 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Cognito = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
5
|
const idea_toolbox_1 = require("idea-toolbox");
|
|
6
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
7
|
-
let ideaWarmStart_cognito = null;
|
|
8
6
|
/**
|
|
9
7
|
* A wrapper for AWS Cognito.
|
|
10
8
|
*/
|
|
11
9
|
class Cognito {
|
|
12
10
|
constructor() {
|
|
13
|
-
|
|
14
|
-
ideaWarmStart_cognito = new aws_sdk_1.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
|
|
15
|
-
this.cognito = ideaWarmStart_cognito;
|
|
11
|
+
this.cognito = new aws_sdk_1.CognitoIdentityServiceProvider({ apiVersion: '2016-04-18' });
|
|
16
12
|
}
|
|
17
13
|
/**
|
|
18
14
|
* Change the region in which to find the user pool.
|
|
@@ -20,8 +16,7 @@ class Cognito {
|
|
|
20
16
|
*/
|
|
21
17
|
setRegion(region) {
|
|
22
18
|
// there is no quick way to change the region without re-creating the object
|
|
23
|
-
|
|
24
|
-
this.cognito = ideaWarmStart_cognito;
|
|
19
|
+
this.cognito = new aws_sdk_1.CognitoIdentityServiceProvider({ apiVersion: this.cognito.config.apiVersion, region });
|
|
25
20
|
}
|
|
26
21
|
/**
|
|
27
22
|
* Get the attributes of the user, from the authorizer claims.
|
|
@@ -72,6 +67,21 @@ class Cognito {
|
|
|
72
67
|
throw new Error('User not found');
|
|
73
68
|
return this.mapCognitoUserAttributesAsPlainObject(user);
|
|
74
69
|
}
|
|
70
|
+
/**
|
|
71
|
+
* Get all the users of the pool.
|
|
72
|
+
*/
|
|
73
|
+
async getAllUsers(cognitoUserPoolId, options = { users: [] }) {
|
|
74
|
+
const params = { UserPoolId: cognitoUserPoolId };
|
|
75
|
+
if (options.pagination)
|
|
76
|
+
params.PaginationToken = options.pagination;
|
|
77
|
+
const res = await this.cognito.listUsers(params).promise();
|
|
78
|
+
const pagination = res.PaginationToken;
|
|
79
|
+
const users = options.users.concat(res.Users.map(u => new idea_toolbox_1.CognitoUser(this.mapCognitoUserAttributesAsPlainObject(u))));
|
|
80
|
+
if (pagination)
|
|
81
|
+
return await this.getAllUsers(cognitoUserPoolId, { pagination, users });
|
|
82
|
+
else
|
|
83
|
+
return users;
|
|
84
|
+
}
|
|
75
85
|
/**
|
|
76
86
|
* Create a new user (by its email) in the pool specified.
|
|
77
87
|
* @return userId of the new user
|
package/dist/src/comprehend.js
CHANGED
|
@@ -2,16 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Comprehend = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
6
|
-
let ideaWarmStart_comprehend = null;
|
|
7
5
|
/**
|
|
8
6
|
* A wrapper for Amazon Comprehend.
|
|
9
7
|
*/
|
|
10
8
|
class Comprehend {
|
|
11
9
|
constructor() {
|
|
12
|
-
|
|
13
|
-
ideaWarmStart_comprehend = new aws_sdk_1.Comprehend({ apiVersion: '2017-11-27' });
|
|
14
|
-
this.comprehend = ideaWarmStart_comprehend;
|
|
10
|
+
this.comprehend = new aws_sdk_1.Comprehend({ apiVersion: '2017-11-27' });
|
|
15
11
|
}
|
|
16
12
|
/**
|
|
17
13
|
* Inspects text and returns an inference of the prevailing sentiment (POSITIVE, NEUTRAL, MIXED, or NEGATIVE).
|
package/dist/src/dynamoDB.js
CHANGED
|
@@ -6,17 +6,14 @@ const uuid_1 = require("uuid");
|
|
|
6
6
|
const nanoid_1 = require("nanoid");
|
|
7
7
|
const NanoID = (0, nanoid_1.customAlphabet)('0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz', 25);
|
|
8
8
|
const shortid_1 = require("shortid");
|
|
9
|
-
const
|
|
10
|
-
|
|
11
|
-
let ideaWarmStart_ddb = null;
|
|
9
|
+
const logger_1 = require("./logger");
|
|
10
|
+
const logger = new logger_1.Logger();
|
|
12
11
|
/**
|
|
13
12
|
* A wrapper for AWS DynamoDB.
|
|
14
13
|
*/
|
|
15
14
|
class DynamoDB {
|
|
16
15
|
constructor() {
|
|
17
|
-
|
|
18
|
-
ideaWarmStart_ddb = new aws_sdk_1.DynamoDB.DocumentClient();
|
|
19
|
-
this.dynamo = ideaWarmStart_ddb;
|
|
16
|
+
this.dynamo = new aws_sdk_1.DynamoDB.DocumentClient();
|
|
20
17
|
}
|
|
21
18
|
/**
|
|
22
19
|
* Convert a JSON object from dynamoDB format to simple JSON.
|
|
@@ -104,7 +101,7 @@ class DynamoDB {
|
|
|
104
101
|
* @param key the key of the counter
|
|
105
102
|
*/
|
|
106
103
|
async getAtomicCounterByKey(key) {
|
|
107
|
-
|
|
104
|
+
logger.debug(`Get atomic counter for ${key}`);
|
|
108
105
|
const result = await this.update({
|
|
109
106
|
TableName: 'idea_atomicCounters',
|
|
110
107
|
Key: { key },
|
|
@@ -121,7 +118,7 @@ class DynamoDB {
|
|
|
121
118
|
* Get an item of a DynamoDB table.
|
|
122
119
|
*/
|
|
123
120
|
async get(params) {
|
|
124
|
-
|
|
121
|
+
logger.debug(`Get ${params.TableName}`);
|
|
125
122
|
const result = await this.dynamo.get(params).promise();
|
|
126
123
|
if (!result?.Item)
|
|
127
124
|
throw new Error('Not found');
|
|
@@ -131,21 +128,21 @@ class DynamoDB {
|
|
|
131
128
|
* Put an item in a DynamoDB table.
|
|
132
129
|
*/
|
|
133
130
|
async put(params) {
|
|
134
|
-
|
|
131
|
+
logger.debug(`Put ${params.TableName}`);
|
|
135
132
|
return await this.dynamo.put(params).promise();
|
|
136
133
|
}
|
|
137
134
|
/**
|
|
138
135
|
* Update an item of a DynamoDB table.
|
|
139
136
|
*/
|
|
140
137
|
async update(params) {
|
|
141
|
-
|
|
138
|
+
logger.debug(`Update ${params.TableName}`);
|
|
142
139
|
return await this.dynamo.update(params).promise();
|
|
143
140
|
}
|
|
144
141
|
/**
|
|
145
142
|
* Delete an item of a DynamoDB table.
|
|
146
143
|
*/
|
|
147
144
|
async delete(params) {
|
|
148
|
-
|
|
145
|
+
logger.debug(`Delete ${params.TableName}`);
|
|
149
146
|
return await this.dynamo.delete(params).promise();
|
|
150
147
|
}
|
|
151
148
|
/**
|
|
@@ -154,7 +151,7 @@ class DynamoDB {
|
|
|
154
151
|
*/
|
|
155
152
|
async batchGet(table, keys, ignoreErr) {
|
|
156
153
|
if (!keys.length) {
|
|
157
|
-
|
|
154
|
+
logger.debug(`Batch get ${table}: no elements to get`);
|
|
158
155
|
return [];
|
|
159
156
|
}
|
|
160
157
|
return await this.batchGetHelper(table, keys, [], Boolean(ignoreErr));
|
|
@@ -165,7 +162,7 @@ class DynamoDB {
|
|
|
165
162
|
[table]: { Keys: keys.slice(currentChunk, currentChunk + chunkSize) }
|
|
166
163
|
}
|
|
167
164
|
};
|
|
168
|
-
|
|
165
|
+
logger.debug(`Batch get ${table}: ${currentChunk} of ${keys.length}`);
|
|
169
166
|
let result;
|
|
170
167
|
try {
|
|
171
168
|
result = await this.dynamo.batchGet(batch).promise();
|
|
@@ -190,7 +187,7 @@ class DynamoDB {
|
|
|
190
187
|
*/
|
|
191
188
|
async batchPut(table, items) {
|
|
192
189
|
if (!items.length)
|
|
193
|
-
return
|
|
190
|
+
return logger.debug(`Batch write (put) ${table}: no elements to write`);
|
|
194
191
|
await this.batchWriteHelper(table, items, true);
|
|
195
192
|
}
|
|
196
193
|
/**
|
|
@@ -200,11 +197,11 @@ class DynamoDB {
|
|
|
200
197
|
*/
|
|
201
198
|
async batchDelete(table, keys) {
|
|
202
199
|
if (!keys.length)
|
|
203
|
-
return
|
|
200
|
+
return logger.debug(`Batch write (delete) ${table}: no elements to write`);
|
|
204
201
|
await this.batchWriteHelper(table, keys, false);
|
|
205
202
|
}
|
|
206
203
|
async batchWriteHelper(table, itemsOrKeys, isPut, currentChunk = 0, chunkSize = 25) {
|
|
207
|
-
|
|
204
|
+
logger.debug(`Batch write (${isPut ? 'put' : 'delete'}) ${table}: ${currentChunk} of ${itemsOrKeys.length}`);
|
|
208
205
|
let requests;
|
|
209
206
|
if (isPut)
|
|
210
207
|
requests = itemsOrKeys.slice(currentChunk, currentChunk + chunkSize).map(i => ({ PutRequest: { Item: i } }));
|
|
@@ -229,7 +226,7 @@ class DynamoDB {
|
|
|
229
226
|
params.RequestItems = response.UnprocessedItems;
|
|
230
227
|
attempts++;
|
|
231
228
|
const waitSeconds = getRandomInt(attempts * 5);
|
|
232
|
-
|
|
229
|
+
logger.debug(`Batch write throttled: waiting ${waitSeconds} seconds to retry`);
|
|
233
230
|
await wait(waitSeconds);
|
|
234
231
|
}
|
|
235
232
|
else {
|
|
@@ -242,9 +239,9 @@ class DynamoDB {
|
|
|
242
239
|
* @param params the params to apply to DynamoDB's function
|
|
243
240
|
*/
|
|
244
241
|
async query(params) {
|
|
245
|
-
|
|
242
|
+
logger.debug(`Query ${params.TableName}`);
|
|
246
243
|
const result = await this.queryScanHelper(params, [], true);
|
|
247
|
-
|
|
244
|
+
logger.debug(`Results query ${params.TableName}: ${result?.length || 0}`);
|
|
248
245
|
return result;
|
|
249
246
|
}
|
|
250
247
|
/**
|
|
@@ -252,9 +249,9 @@ class DynamoDB {
|
|
|
252
249
|
* @param params the params to apply to DynamoDB's function
|
|
253
250
|
*/
|
|
254
251
|
async scan(params) {
|
|
255
|
-
|
|
252
|
+
logger.debug(`Scan ${params.TableName}`);
|
|
256
253
|
const result = await this.queryScanHelper(params, [], false);
|
|
257
|
-
|
|
254
|
+
logger.debug(`Results scan ${params.TableName}: ${result?.length || 0}`);
|
|
258
255
|
return result;
|
|
259
256
|
}
|
|
260
257
|
async queryScanHelper(params, items, isQuery) {
|
|
@@ -276,9 +273,9 @@ class DynamoDB {
|
|
|
276
273
|
* @param params the params to apply to DynamoDB's function
|
|
277
274
|
*/
|
|
278
275
|
async queryClassic(params) {
|
|
279
|
-
|
|
276
|
+
logger.debug(`Query classic ${params.TableName}`);
|
|
280
277
|
const result = await this.dynamo.query(params).promise();
|
|
281
|
-
|
|
278
|
+
logger.debug(`Results query classic ${params.TableName}: ${result?.Items?.length || 0}`);
|
|
282
279
|
return result;
|
|
283
280
|
}
|
|
284
281
|
/**
|
|
@@ -286,9 +283,9 @@ class DynamoDB {
|
|
|
286
283
|
* @param params the params to apply to DynamoDB's function
|
|
287
284
|
*/
|
|
288
285
|
async scanClassic(params) {
|
|
289
|
-
|
|
286
|
+
logger.debug(`Scan classic ${params.TableName}`);
|
|
290
287
|
const result = await this.dynamo.scan(params).promise();
|
|
291
|
-
|
|
288
|
+
logger.debug(`Results scan classic ${params.TableName}: ${result?.Items?.length || 0}`);
|
|
292
289
|
return result;
|
|
293
290
|
}
|
|
294
291
|
/**
|
|
@@ -297,8 +294,8 @@ class DynamoDB {
|
|
|
297
294
|
*/
|
|
298
295
|
async transactWrites(ops) {
|
|
299
296
|
if (!ops.length)
|
|
300
|
-
return
|
|
301
|
-
|
|
297
|
+
return logger.debug('Transaction writes: no elements to write');
|
|
298
|
+
logger.debug('Transaction writes');
|
|
302
299
|
await this.dynamo.transactWrite({ TransactItems: ops.slice(0, 10) }).promise();
|
|
303
300
|
}
|
|
304
301
|
/**
|
|
@@ -7,6 +7,7 @@ import { Translate } from './translate';
|
|
|
7
7
|
import { Comprehend } from './comprehend';
|
|
8
8
|
import { SecretsManager } from './secretsManager';
|
|
9
9
|
import { Attachments } from './attachments';
|
|
10
|
+
import { Logger } from './logger';
|
|
10
11
|
/**
|
|
11
12
|
* An abstract class to inherit to manage some resources with an AWS Lambda function.
|
|
12
13
|
*/
|
|
@@ -23,6 +24,7 @@ export declare abstract class GenericController {
|
|
|
23
24
|
protected _secrets: SecretsManager;
|
|
24
25
|
protected _attachments: Attachments;
|
|
25
26
|
tables: any;
|
|
27
|
+
protected logger: Logger;
|
|
26
28
|
protected logRequestsWithKey: string;
|
|
27
29
|
/**
|
|
28
30
|
* Initialize a new GenericController helper object.
|
|
@@ -37,31 +39,57 @@ export declare abstract class GenericController {
|
|
|
37
39
|
/**
|
|
38
40
|
* Default callback for the Lambda.
|
|
39
41
|
*/
|
|
40
|
-
protected done(err:
|
|
42
|
+
protected done(err: any, res?: any): void;
|
|
43
|
+
/**
|
|
44
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
45
|
+
*/
|
|
41
46
|
protected get dynamoDB(): DynamoDB;
|
|
42
47
|
protected set dynamoDB(dynamoDB: DynamoDB);
|
|
48
|
+
/**
|
|
49
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
50
|
+
*/
|
|
43
51
|
protected get cognito(): Cognito;
|
|
44
52
|
protected set cognito(cognito: Cognito);
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
55
|
+
*/
|
|
45
56
|
protected get s3(): S3;
|
|
46
57
|
protected set s3(s3: S3);
|
|
58
|
+
/**
|
|
59
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
60
|
+
*/
|
|
47
61
|
protected get ses(): SES;
|
|
48
62
|
protected set ses(ses: SES);
|
|
63
|
+
/**
|
|
64
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
65
|
+
*/
|
|
49
66
|
protected get sns(): SNS;
|
|
50
67
|
protected set sns(sns: SNS);
|
|
68
|
+
/**
|
|
69
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
70
|
+
*/
|
|
51
71
|
protected get translate(): Translate;
|
|
52
72
|
protected set translate(translate: Translate);
|
|
73
|
+
/**
|
|
74
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
75
|
+
*/
|
|
53
76
|
protected get comprehend(): Comprehend;
|
|
54
77
|
protected set comprehend(comprehend: Comprehend);
|
|
78
|
+
/**
|
|
79
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
80
|
+
*/
|
|
55
81
|
protected get secrets(): SecretsManager;
|
|
56
82
|
protected set secrets(secrets: SecretsManager);
|
|
57
83
|
/**
|
|
58
84
|
* Manage attachments (through SignedURLs).
|
|
85
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
59
86
|
*/
|
|
60
87
|
get attachments(): Attachments;
|
|
61
88
|
set attachments(attachments: Attachments);
|
|
62
89
|
}
|
|
63
90
|
/**
|
|
64
91
|
* The initial options for a constructor of class GenericController.
|
|
92
|
+
* @deprecated following new IAC standards.
|
|
65
93
|
*/
|
|
66
94
|
export interface GenericControllerOptions {
|
|
67
95
|
/**
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.GenericController = void 0;
|
|
4
|
-
const idea_toolbox_1 = require("idea-toolbox");
|
|
5
4
|
const dynamoDB_1 = require("./dynamoDB");
|
|
6
5
|
const cognito_1 = require("./cognito");
|
|
7
6
|
const s3_1 = require("./s3");
|
|
@@ -11,6 +10,7 @@ const translate_1 = require("./translate");
|
|
|
11
10
|
const comprehend_1 = require("./comprehend");
|
|
12
11
|
const secretsManager_1 = require("./secretsManager");
|
|
13
12
|
const attachments_1 = require("./attachments");
|
|
13
|
+
const logger_1 = require("./logger");
|
|
14
14
|
/**
|
|
15
15
|
* An abstract class to inherit to manage some resources with an AWS Lambda function.
|
|
16
16
|
*/
|
|
@@ -21,23 +21,27 @@ class GenericController {
|
|
|
21
21
|
* @param callback the callback to resolve or reject the execution
|
|
22
22
|
*/
|
|
23
23
|
constructor(event, callback, options = {}) {
|
|
24
|
+
this.logger = new logger_1.Logger();
|
|
24
25
|
this.event = event;
|
|
25
26
|
this.callback = callback;
|
|
26
27
|
this.tables = options.tables || {};
|
|
27
|
-
// set the logs to print objects deeper
|
|
28
|
-
// eslint-disable-next-line @typescript-eslint/no-var-requires
|
|
29
|
-
require('util').inspect.defaultOptions.depth = null;
|
|
30
28
|
}
|
|
31
29
|
/**
|
|
32
30
|
* Default callback for the Lambda.
|
|
33
31
|
*/
|
|
34
32
|
done(err, res) {
|
|
35
|
-
|
|
33
|
+
if (err)
|
|
34
|
+
this.logger.info('END-FAILED', { error: err.message || err.errorMessage });
|
|
35
|
+
else
|
|
36
|
+
this.logger.info('END-SUCCESS');
|
|
36
37
|
this.callback(err, res);
|
|
37
38
|
}
|
|
38
39
|
///
|
|
39
40
|
/// AWS SERVICES
|
|
40
41
|
///
|
|
42
|
+
/**
|
|
43
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
44
|
+
*/
|
|
41
45
|
get dynamoDB() {
|
|
42
46
|
if (!this._dynamoDB)
|
|
43
47
|
this._dynamoDB = new dynamoDB_1.DynamoDB();
|
|
@@ -46,6 +50,9 @@ class GenericController {
|
|
|
46
50
|
set dynamoDB(dynamoDB) {
|
|
47
51
|
this._dynamoDB = dynamoDB;
|
|
48
52
|
}
|
|
53
|
+
/**
|
|
54
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
55
|
+
*/
|
|
49
56
|
get cognito() {
|
|
50
57
|
if (!this._cognito)
|
|
51
58
|
this._cognito = new cognito_1.Cognito();
|
|
@@ -54,6 +61,9 @@ class GenericController {
|
|
|
54
61
|
set cognito(cognito) {
|
|
55
62
|
this._cognito = cognito;
|
|
56
63
|
}
|
|
64
|
+
/**
|
|
65
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
66
|
+
*/
|
|
57
67
|
get s3() {
|
|
58
68
|
if (!this._s3)
|
|
59
69
|
this._s3 = new s3_1.S3();
|
|
@@ -62,6 +72,9 @@ class GenericController {
|
|
|
62
72
|
set s3(s3) {
|
|
63
73
|
this._s3 = s3;
|
|
64
74
|
}
|
|
75
|
+
/**
|
|
76
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
77
|
+
*/
|
|
65
78
|
get ses() {
|
|
66
79
|
if (!this._ses)
|
|
67
80
|
this._ses = new ses_1.SES();
|
|
@@ -70,6 +83,9 @@ class GenericController {
|
|
|
70
83
|
set ses(ses) {
|
|
71
84
|
this._ses = ses;
|
|
72
85
|
}
|
|
86
|
+
/**
|
|
87
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
88
|
+
*/
|
|
73
89
|
get sns() {
|
|
74
90
|
if (!this._sns)
|
|
75
91
|
this._sns = new sns_1.SNS();
|
|
@@ -78,6 +94,9 @@ class GenericController {
|
|
|
78
94
|
set sns(sns) {
|
|
79
95
|
this._sns = sns;
|
|
80
96
|
}
|
|
97
|
+
/**
|
|
98
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
99
|
+
*/
|
|
81
100
|
get translate() {
|
|
82
101
|
if (!this._translate)
|
|
83
102
|
this._translate = new translate_1.Translate();
|
|
@@ -86,6 +105,9 @@ class GenericController {
|
|
|
86
105
|
set translate(translate) {
|
|
87
106
|
this._translate = translate;
|
|
88
107
|
}
|
|
108
|
+
/**
|
|
109
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
110
|
+
*/
|
|
89
111
|
get comprehend() {
|
|
90
112
|
if (!this._comprehend)
|
|
91
113
|
this._comprehend = new comprehend_1.Comprehend();
|
|
@@ -94,6 +116,9 @@ class GenericController {
|
|
|
94
116
|
set comprehend(comprehend) {
|
|
95
117
|
this._comprehend = comprehend;
|
|
96
118
|
}
|
|
119
|
+
/**
|
|
120
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
121
|
+
*/
|
|
97
122
|
get secrets() {
|
|
98
123
|
if (!this._secrets)
|
|
99
124
|
this._secrets = new secretsManager_1.SecretsManager();
|
|
@@ -107,6 +132,7 @@ class GenericController {
|
|
|
107
132
|
///
|
|
108
133
|
/**
|
|
109
134
|
* Manage attachments (through SignedURLs).
|
|
135
|
+
* @deprecated use external object to improve cold starts. See most recent projects for reference.
|
|
110
136
|
*/
|
|
111
137
|
get attachments() {
|
|
112
138
|
if (!this._attachments)
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Manage structured logging.
|
|
3
|
+
*/
|
|
4
|
+
export declare class Logger {
|
|
5
|
+
level: string;
|
|
6
|
+
private originalLevel;
|
|
7
|
+
constructor({ level }?: {
|
|
8
|
+
level?: string;
|
|
9
|
+
});
|
|
10
|
+
isEnabled(level: number): boolean;
|
|
11
|
+
appendError(params: any, err: Error): any;
|
|
12
|
+
log(levelName: string, message: string, params: any): void;
|
|
13
|
+
debug(msg: string, params?: any): void;
|
|
14
|
+
info(msg: string, params?: any): void;
|
|
15
|
+
warn(msg: string, err: Error | any, params?: any): void;
|
|
16
|
+
error(msg: string, err: Error | any, params?: any): void;
|
|
17
|
+
enableDebug(): () => void;
|
|
18
|
+
resetLevel(): void;
|
|
19
|
+
}
|
|
@@ -0,0 +1,53 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Logger = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Manage structured logging.
|
|
6
|
+
*/
|
|
7
|
+
class Logger {
|
|
8
|
+
constructor({ level = process.env.LOG_LEVEL } = {}) {
|
|
9
|
+
this.level = (level || 'DEBUG').toUpperCase();
|
|
10
|
+
this.originalLevel = this.level;
|
|
11
|
+
}
|
|
12
|
+
isEnabled(level) {
|
|
13
|
+
return level >= (LogLevels[this.level] || LogLevels.DEBUG);
|
|
14
|
+
}
|
|
15
|
+
appendError(params, err) {
|
|
16
|
+
if (!err)
|
|
17
|
+
return params;
|
|
18
|
+
return { ...(params || {}), errorName: err.name, errorMessage: err.message, stackTrace: err.stack };
|
|
19
|
+
}
|
|
20
|
+
log(levelName, message, params) {
|
|
21
|
+
const level = LogLevels[levelName];
|
|
22
|
+
if (!this.isEnabled(level))
|
|
23
|
+
return;
|
|
24
|
+
const logMsg = { ...params, level, sLevel: levelName, message };
|
|
25
|
+
const consoleMethods = { DEBUG: console.debug, INFO: console.info, WARN: console.warn, ERROR: console.error };
|
|
26
|
+
// re-order message and params to appear earlier in the log row
|
|
27
|
+
consoleMethods[levelName](JSON.stringify({ message, ...params, ...logMsg }, (_, value) => typeof value === 'bigint' ? value.toString() : value));
|
|
28
|
+
}
|
|
29
|
+
debug(msg, params = {}) {
|
|
30
|
+
this.log('DEBUG', msg, params);
|
|
31
|
+
}
|
|
32
|
+
info(msg, params = {}) {
|
|
33
|
+
this.log('INFO', msg, params);
|
|
34
|
+
}
|
|
35
|
+
warn(msg, err, params = {}) {
|
|
36
|
+
const parameters = this.appendError(params, err);
|
|
37
|
+
this.log('WARN', msg, parameters);
|
|
38
|
+
}
|
|
39
|
+
error(msg, err, params = {}) {
|
|
40
|
+
const parameters = this.appendError(params, err);
|
|
41
|
+
this.log('ERROR', msg, parameters);
|
|
42
|
+
}
|
|
43
|
+
enableDebug() {
|
|
44
|
+
this.level = 'DEBUG';
|
|
45
|
+
return () => this.resetLevel();
|
|
46
|
+
}
|
|
47
|
+
resetLevel() {
|
|
48
|
+
this.level = this.originalLevel;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
exports.Logger = Logger;
|
|
52
|
+
// levels here are identical to bunyan practices (https://github.com/trentm/node-bunyan#levels)
|
|
53
|
+
const LogLevels = { DEBUG: 20, INFO: 30, WARN: 40, ERROR: 50 };
|
|
@@ -1,28 +1,39 @@
|
|
|
1
|
+
import 'source-map-support/register';
|
|
2
|
+
import { APIGatewayProxyEventV2, APIGatewayProxyEvent, Callback } from 'aws-lambda';
|
|
1
3
|
import { CognitoUser } from 'idea-toolbox';
|
|
4
|
+
import { Logger } from './logger';
|
|
2
5
|
import { GenericController, GenericControllerOptions } from './genericController';
|
|
3
6
|
/**
|
|
4
7
|
* An abstract class to inherit to manage API requests (AWS API Gateway) in an AWS Lambda function.
|
|
5
8
|
*/
|
|
6
9
|
export declare abstract class ResourceController extends GenericController {
|
|
10
|
+
protected event: APIGatewayProxyEventV2 | APIGatewayProxyEvent;
|
|
11
|
+
protected callback: Callback;
|
|
7
12
|
protected authorization: string;
|
|
8
13
|
protected claims: any;
|
|
9
14
|
protected principalId: string;
|
|
10
|
-
protected
|
|
15
|
+
protected cognitoUser: CognitoUser;
|
|
11
16
|
protected stage: string;
|
|
12
17
|
protected httpMethod: string;
|
|
13
|
-
body: any;
|
|
14
|
-
queryParams: any;
|
|
18
|
+
protected body: any;
|
|
19
|
+
protected queryParams: any;
|
|
15
20
|
protected resource: string;
|
|
16
21
|
protected path: string;
|
|
22
|
+
protected pathParameters: any;
|
|
17
23
|
protected resourceId: string;
|
|
24
|
+
protected returnStatusCode?: number;
|
|
25
|
+
protected logger: Logger;
|
|
18
26
|
protected logRequestsWithKey: string;
|
|
19
27
|
protected currentLang: string;
|
|
20
28
|
protected defaultLang: string;
|
|
21
29
|
protected translations: any;
|
|
22
30
|
protected templateMatcher: RegExp;
|
|
23
|
-
constructor(event:
|
|
31
|
+
constructor(event: APIGatewayProxyEventV2 | APIGatewayProxyEvent, callback: Callback, options?: ResourceControllerOptions);
|
|
32
|
+
private initFromEventV2;
|
|
33
|
+
private initFromEventV1;
|
|
24
34
|
handleRequest: () => Promise<void>;
|
|
25
|
-
|
|
35
|
+
private controlHandlerError;
|
|
36
|
+
protected done(err: any, res?: any, statusCode?: number): void;
|
|
26
37
|
/**
|
|
27
38
|
* To @override
|
|
28
39
|
*/
|
|
@@ -175,3 +186,9 @@ export interface InternalAPIRequestParams {
|
|
|
175
186
|
*/
|
|
176
187
|
body?: any;
|
|
177
188
|
}
|
|
189
|
+
/**
|
|
190
|
+
* Explicitly define a specific type of error to use in the RC's handler, to distinguish it from the normal errors.
|
|
191
|
+
*/
|
|
192
|
+
export declare class RCError extends Error {
|
|
193
|
+
constructor(message: string);
|
|
194
|
+
}
|
|
@@ -1,10 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.ResourceController = void 0;
|
|
4
|
-
|
|
3
|
+
exports.RCError = exports.ResourceController = void 0;
|
|
4
|
+
require("source-map-support/register");
|
|
5
5
|
const fs_1 = require("fs");
|
|
6
6
|
const aws_sdk_1 = require("aws-sdk");
|
|
7
7
|
const idea_toolbox_1 = require("idea-toolbox");
|
|
8
|
+
const logger_1 = require("./logger");
|
|
8
9
|
const genericController_1 = require("./genericController");
|
|
9
10
|
/**
|
|
10
11
|
* An abstract class to inherit to manage API requests (AWS API Gateway) in an AWS Lambda function.
|
|
@@ -12,6 +13,7 @@ const genericController_1 = require("./genericController");
|
|
|
12
13
|
class ResourceController extends genericController_1.GenericController {
|
|
13
14
|
constructor(event, callback, options = {}) {
|
|
14
15
|
super(event, callback, options);
|
|
16
|
+
this.logger = new logger_1.Logger();
|
|
15
17
|
this.templateMatcher = /{{\s?([^{}\s]*)\s?}}/g;
|
|
16
18
|
///
|
|
17
19
|
/// REQUEST HANDLERS
|
|
@@ -43,7 +45,7 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
43
45
|
response = await this.headResource();
|
|
44
46
|
break;
|
|
45
47
|
default:
|
|
46
|
-
this.done(new
|
|
48
|
+
this.done(new RCError('Unsupported method'));
|
|
47
49
|
}
|
|
48
50
|
}
|
|
49
51
|
else {
|
|
@@ -68,35 +70,25 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
68
70
|
response = await this.headResources();
|
|
69
71
|
break;
|
|
70
72
|
default:
|
|
71
|
-
this.done(new
|
|
73
|
+
this.done(new RCError('Unsupported method'));
|
|
72
74
|
}
|
|
73
75
|
}
|
|
74
76
|
this.done(null, response);
|
|
75
77
|
}
|
|
76
78
|
catch (err) {
|
|
77
|
-
|
|
78
|
-
this.done(new Error(errorMessage));
|
|
79
|
+
this.done(this.controlHandlerError(err, 'HANDLER-ERROR', 'Operation failed'));
|
|
79
80
|
}
|
|
80
81
|
}
|
|
81
82
|
catch (err) {
|
|
82
|
-
|
|
83
|
-
this.done(new Error(errorMessage));
|
|
83
|
+
this.done(this.controlHandlerError(err, 'AUTH-CHECK-ERROR', 'Forbidden'));
|
|
84
84
|
}
|
|
85
85
|
};
|
|
86
|
-
this.
|
|
87
|
-
this.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
this.resource = (event.resource || '').replace('+', ''); // {proxy+} -> {proxy}
|
|
93
|
-
this.path = event.path || '';
|
|
94
|
-
this.resourceId =
|
|
95
|
-
event.pathParameters && event.pathParameters[options.resourceId || 'proxy']
|
|
96
|
-
? decodeURIComponent(event.pathParameters[options.resourceId || 'proxy'])
|
|
97
|
-
: '';
|
|
98
|
-
this.queryParams = event.queryStringParameters || {};
|
|
99
|
-
this.body = (event.body ? JSON.parse(event.body) : {}) || {};
|
|
86
|
+
this.event = event;
|
|
87
|
+
this.callback = callback;
|
|
88
|
+
if (event.version === '2.0')
|
|
89
|
+
this.initFromEventV2(event, options);
|
|
90
|
+
else
|
|
91
|
+
this.initFromEventV1(event, options);
|
|
100
92
|
this.logRequestsWithKey = options.logRequestsWithKey;
|
|
101
93
|
// acquire some info about the client, if available
|
|
102
94
|
let version = '?', platform = '?';
|
|
@@ -110,15 +102,55 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
110
102
|
}
|
|
111
103
|
// print the initial log
|
|
112
104
|
const info = { principalId: this.principalId, queryParams: this.queryParams, body: this.body, version, platform };
|
|
113
|
-
|
|
105
|
+
this.logger.info(`START: ${this.httpMethod} ${this.path}`, info);
|
|
106
|
+
}
|
|
107
|
+
initFromEventV2(event, options) {
|
|
108
|
+
this.authorization = event.headers.authorization;
|
|
109
|
+
const contextFromAuthorizer = event.requestContext?.authorizer?.lambda || {};
|
|
110
|
+
this.principalId = contextFromAuthorizer.principalId;
|
|
111
|
+
this.stage = event.requestContext.stage;
|
|
112
|
+
this.httpMethod = event.requestContext.http.method;
|
|
113
|
+
this.resource = event.routeKey.replace('+', ''); // {proxy+} -> {proxy}
|
|
114
|
+
this.path = event.rawPath;
|
|
115
|
+
this.pathParameters = {};
|
|
116
|
+
for (const param in event.pathParameters)
|
|
117
|
+
this.pathParameters[param] = event.pathParameters[param] ? decodeURIComponent(event.pathParameters[param]) : null;
|
|
118
|
+
this.resourceId = this.pathParameters[options.resourceId || 'proxy'];
|
|
119
|
+
this.queryParams = event.queryStringParameters || {};
|
|
120
|
+
this.body = (event.body ? JSON.parse(event.body) : {}) || {};
|
|
114
121
|
}
|
|
115
|
-
|
|
116
|
-
|
|
122
|
+
initFromEventV1(event, options) {
|
|
123
|
+
this.authorization = event.headers.Authorization;
|
|
124
|
+
this.claims = event.requestContext.authorizer?.claims || {};
|
|
125
|
+
this.principalId = this.claims.sub;
|
|
126
|
+
this.cognitoUser = this.principalId ? new idea_toolbox_1.CognitoUser(this.claims) : null;
|
|
127
|
+
this.stage = event.requestContext.stage;
|
|
128
|
+
this.httpMethod = event.httpMethod;
|
|
129
|
+
this.resource = event.resource.replace('+', ''); // {proxy+} -> {proxy}
|
|
130
|
+
this.path = event.path;
|
|
131
|
+
this.pathParameters = {};
|
|
132
|
+
for (const param in event.pathParameters)
|
|
133
|
+
this.pathParameters[param] = event.pathParameters[param] ? decodeURIComponent(event.pathParameters[param]) : null;
|
|
134
|
+
this.resourceId = this.pathParameters[options.resourceId || 'proxy'];
|
|
135
|
+
this.queryParams = event.queryStringParameters || {};
|
|
136
|
+
this.body = (event.body ? JSON.parse(event.body) : {}) || {};
|
|
137
|
+
}
|
|
138
|
+
controlHandlerError(err = {}, context, replaceWithErrorMessage) {
|
|
139
|
+
if (err instanceof RCError)
|
|
140
|
+
return new Error(err.message);
|
|
141
|
+
this.logger.error(context, err);
|
|
142
|
+
return new Error(replaceWithErrorMessage);
|
|
143
|
+
}
|
|
144
|
+
done(err, res, statusCode = this.returnStatusCode || (err ? 400 : 200)) {
|
|
145
|
+
if (err)
|
|
146
|
+
this.logger.info('END-FAILED', { statusCode, error: err.message || err.errorMessage });
|
|
147
|
+
else
|
|
148
|
+
this.logger.info('END-SUCCESS', { statusCode });
|
|
117
149
|
// if configured, store the log of the request
|
|
118
150
|
if (this.logRequestsWithKey)
|
|
119
151
|
this.storeLog(!err);
|
|
120
152
|
this.callback(null, {
|
|
121
|
-
statusCode: statusCode
|
|
153
|
+
statusCode: String(statusCode),
|
|
122
154
|
body: err ? JSON.stringify({ message: err.message }) : JSON.stringify(res || {}),
|
|
123
155
|
headers: { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*' }
|
|
124
156
|
});
|
|
@@ -133,73 +165,73 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
133
165
|
* To @override
|
|
134
166
|
*/
|
|
135
167
|
async getResource() {
|
|
136
|
-
throw new
|
|
168
|
+
throw new RCError('Unsupported method');
|
|
137
169
|
}
|
|
138
170
|
/**
|
|
139
171
|
* To @override
|
|
140
172
|
*/
|
|
141
173
|
async postResource() {
|
|
142
|
-
throw new
|
|
174
|
+
throw new RCError('Unsupported method');
|
|
143
175
|
}
|
|
144
176
|
/**
|
|
145
177
|
* To @override
|
|
146
178
|
*/
|
|
147
179
|
async putResource() {
|
|
148
|
-
throw new
|
|
180
|
+
throw new RCError('Unsupported method');
|
|
149
181
|
}
|
|
150
182
|
/**
|
|
151
183
|
* To @override
|
|
152
184
|
*/
|
|
153
185
|
async deleteResource() {
|
|
154
|
-
throw new
|
|
186
|
+
throw new RCError('Unsupported method');
|
|
155
187
|
}
|
|
156
188
|
/**
|
|
157
189
|
* To @override
|
|
158
190
|
*/
|
|
159
191
|
async headResource() {
|
|
160
|
-
throw new
|
|
192
|
+
throw new RCError('Unsupported method');
|
|
161
193
|
}
|
|
162
194
|
/**
|
|
163
195
|
* To @override
|
|
164
196
|
*/
|
|
165
197
|
async getResources() {
|
|
166
|
-
throw new
|
|
198
|
+
throw new RCError('Unsupported method');
|
|
167
199
|
}
|
|
168
200
|
/**
|
|
169
201
|
* To @override
|
|
170
202
|
*/
|
|
171
203
|
async postResources() {
|
|
172
|
-
throw new
|
|
204
|
+
throw new RCError('Unsupported method');
|
|
173
205
|
}
|
|
174
206
|
/**
|
|
175
207
|
* To @override
|
|
176
208
|
*/
|
|
177
209
|
async putResources() {
|
|
178
|
-
throw new
|
|
210
|
+
throw new RCError('Unsupported method');
|
|
179
211
|
}
|
|
180
212
|
/**
|
|
181
213
|
* To @override
|
|
182
214
|
*/
|
|
183
215
|
async patchResource() {
|
|
184
|
-
throw new
|
|
216
|
+
throw new RCError('Unsupported method');
|
|
185
217
|
}
|
|
186
218
|
/**
|
|
187
219
|
* To @override
|
|
188
220
|
*/
|
|
189
221
|
async patchResources() {
|
|
190
|
-
throw new
|
|
222
|
+
throw new RCError('Unsupported method');
|
|
191
223
|
}
|
|
192
224
|
/**
|
|
193
225
|
* To @override
|
|
194
226
|
*/
|
|
195
227
|
async deleteResources() {
|
|
196
|
-
throw new
|
|
228
|
+
throw new RCError('Unsupported method');
|
|
197
229
|
}
|
|
198
230
|
/**
|
|
199
231
|
* To @override
|
|
200
232
|
*/
|
|
201
233
|
async headResources() {
|
|
202
|
-
throw new
|
|
234
|
+
throw new RCError('Unsupported method');
|
|
203
235
|
}
|
|
204
236
|
///
|
|
205
237
|
/// HELPERS
|
|
@@ -256,23 +288,25 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
256
288
|
// create a copy of the event
|
|
257
289
|
const event = JSON.parse(JSON.stringify(this.event));
|
|
258
290
|
// change only the event attributes we need; e.g. the authorization is unchanged
|
|
259
|
-
event.
|
|
260
|
-
|
|
261
|
-
event.
|
|
291
|
+
if (!event.requestContext)
|
|
292
|
+
event.requestContext = {};
|
|
293
|
+
event.requestContext.stage = params.stage || this.stage;
|
|
294
|
+
event.requestContext.httpMethod = event.httpMethod = params.httpMethod;
|
|
295
|
+
event.routeKey = event.resource = params.resource;
|
|
262
296
|
event.pathParameters = params.pathParams || {};
|
|
263
297
|
event.queryStringParameters = params.queryParams || {};
|
|
264
298
|
event.body = JSON.stringify(params.body || {});
|
|
265
299
|
// parse the path
|
|
266
|
-
event.
|
|
300
|
+
event.rawPath = event.path = params.resource;
|
|
267
301
|
for (const p in event.pathParameters)
|
|
268
302
|
if (event.pathParameters[p])
|
|
269
|
-
event.
|
|
303
|
+
event.rawPath = event.path = event.path.replace(`{${p}}`, event.pathParameters[p]);
|
|
270
304
|
// set a flag to make the invoked to recognise that is an internal request
|
|
271
305
|
event.internalAPIRequest = true;
|
|
272
306
|
// invoke the lambda with the event prepaired, simulating an API request
|
|
273
307
|
new aws_sdk_1.Lambda().invoke({
|
|
274
308
|
FunctionName: params.lambda,
|
|
275
|
-
Qualifier: event.stage,
|
|
309
|
+
Qualifier: event.requestContext.stage,
|
|
276
310
|
InvocationType: 'RequestResponse',
|
|
277
311
|
Payload: JSON.stringify(event)
|
|
278
312
|
}, (err, res) => {
|
|
@@ -374,3 +408,13 @@ class ResourceController extends genericController_1.GenericController {
|
|
|
374
408
|
}
|
|
375
409
|
}
|
|
376
410
|
exports.ResourceController = ResourceController;
|
|
411
|
+
/**
|
|
412
|
+
* Explicitly define a specific type of error to use in the RC's handler, to distinguish it from the normal errors.
|
|
413
|
+
*/
|
|
414
|
+
class RCError extends Error {
|
|
415
|
+
constructor(message) {
|
|
416
|
+
super(message);
|
|
417
|
+
Object.setPrototypeOf(this, RCError.prototype);
|
|
418
|
+
}
|
|
419
|
+
}
|
|
420
|
+
exports.RCError = RCError;
|
package/dist/src/s3.js
CHANGED
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.GetObjectTypes = exports.S3 = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
5
|
const idea_toolbox_1 = require("idea-toolbox");
|
|
6
|
-
|
|
7
|
-
|
|
6
|
+
const logger_1 = require("./logger");
|
|
7
|
+
const logger = new logger_1.Logger();
|
|
8
8
|
/**
|
|
9
9
|
* A wrapper for AWS Simple Storage Service.
|
|
10
10
|
*/
|
|
@@ -17,9 +17,7 @@ class S3 {
|
|
|
17
17
|
this.DEFAULT_DOWNLOAD_BUCKET = 'idea-downloads';
|
|
18
18
|
this.DEFAULT_DOWNLOAD_BUCKET_SEC_TO_EXP = 180;
|
|
19
19
|
this.DEFAULT_UPLOAD_BUCKET_SEC_TO_EXP = 300;
|
|
20
|
-
|
|
21
|
-
ideaWarmStart_s3 = new aws_sdk_1.S3({ apiVersion: '2006-03-01', signatureVersion: 'v4' });
|
|
22
|
-
this.s3 = ideaWarmStart_s3;
|
|
20
|
+
this.s3 = new aws_sdk_1.S3({ apiVersion: '2006-03-01', signatureVersion: 'v4' });
|
|
23
21
|
}
|
|
24
22
|
/**
|
|
25
23
|
* Create a download link of a piece of data (through S3).
|
|
@@ -67,14 +65,14 @@ class S3 {
|
|
|
67
65
|
* Make a copy of an object of the bucket.
|
|
68
66
|
*/
|
|
69
67
|
async copyObject(options) {
|
|
70
|
-
|
|
68
|
+
logger.debug(`S3 copy object: ${options.key}`);
|
|
71
69
|
await this.s3.copyObject({ CopySource: options.copySource, Bucket: options.bucket, Key: options.key }).promise();
|
|
72
70
|
}
|
|
73
71
|
/**
|
|
74
72
|
* Get an object from a S3 bucket.
|
|
75
73
|
*/
|
|
76
74
|
async getObject(options) {
|
|
77
|
-
|
|
75
|
+
logger.debug(`S3 get object: ${options.type}`);
|
|
78
76
|
const result = await this.s3.getObject({ Bucket: options.bucket, Key: options.key }).promise();
|
|
79
77
|
switch (options.type) {
|
|
80
78
|
case GetObjectTypes.JSON:
|
|
@@ -96,21 +94,21 @@ class S3 {
|
|
|
96
94
|
params.ACL = options.acl;
|
|
97
95
|
if (options.metadata)
|
|
98
96
|
params.Metadata = options.metadata;
|
|
99
|
-
|
|
97
|
+
logger.debug(`S3 put object: ${options.key}`);
|
|
100
98
|
return await this.s3.putObject(params).promise();
|
|
101
99
|
}
|
|
102
100
|
/**
|
|
103
101
|
* Delete an object from an S3 bucket.
|
|
104
102
|
*/
|
|
105
103
|
async deleteObject(options) {
|
|
106
|
-
|
|
104
|
+
logger.debug(`S3 delete object: ${options.key}`);
|
|
107
105
|
return await this.s3.deleteObject({ Bucket: options.bucket, Key: options.key }).promise();
|
|
108
106
|
}
|
|
109
107
|
/**
|
|
110
108
|
* List the objects of an S3 bucket.
|
|
111
109
|
*/
|
|
112
110
|
async listObjects(options) {
|
|
113
|
-
|
|
111
|
+
logger.debug(`S3 list object: ${options.prefix}`);
|
|
114
112
|
return await this.s3.listObjects({ Bucket: options.bucket, Prefix: options.prefix }).promise();
|
|
115
113
|
}
|
|
116
114
|
/**
|
|
@@ -2,30 +2,19 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.SecretsManager = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
|
-
const idea_toolbox_1 = require("idea-toolbox");
|
|
6
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
7
|
-
let ideaWarmStart_secretsManager = null;
|
|
8
5
|
/**
|
|
9
6
|
* A wrapper for AWS Secrets manager.
|
|
10
7
|
*/
|
|
11
8
|
class SecretsManager {
|
|
12
9
|
constructor() {
|
|
13
|
-
|
|
14
|
-
ideaWarmStart_secretsManager = new aws_sdk_1.SecretsManager();
|
|
15
|
-
this.sm = ideaWarmStart_secretsManager;
|
|
10
|
+
this.sm = new aws_sdk_1.SecretsManager();
|
|
16
11
|
}
|
|
17
12
|
/**
|
|
18
13
|
* Get a secret string from the Secret Manager by its id.
|
|
19
14
|
*/
|
|
20
15
|
async getStringById(secretId) {
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
return result.SecretString;
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
(0, idea_toolbox_1.logger)('SECRET NOT FOUND', err, secretId);
|
|
27
|
-
throw new Error('Not found');
|
|
28
|
-
}
|
|
16
|
+
const result = await this.sm.getSecretValue({ SecretId: secretId }).promise();
|
|
17
|
+
return result.SecretString;
|
|
29
18
|
}
|
|
30
19
|
}
|
|
31
20
|
exports.SecretsManager = SecretsManager;
|
package/dist/src/ses.js
CHANGED
|
@@ -3,10 +3,9 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SES = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
5
|
const nodemailer_1 = require("nodemailer");
|
|
6
|
-
const idea_toolbox_1 = require("idea-toolbox");
|
|
7
6
|
const dynamoDB_1 = require("./dynamoDB");
|
|
8
|
-
|
|
9
|
-
|
|
7
|
+
const logger_1 = require("./logger");
|
|
8
|
+
const logger = new logger_1.Logger();
|
|
10
9
|
/**
|
|
11
10
|
* A wrapper for AWS Simple Email Service.
|
|
12
11
|
*/
|
|
@@ -24,10 +23,8 @@ class SES {
|
|
|
24
23
|
Source: sesParams.sourceName ? `${sesParams.sourceName} <${sesParams.source}>` : sesParams.source,
|
|
25
24
|
SourceArn: sesParams.sourceArn
|
|
26
25
|
};
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
ideaWarmStart_ses = new aws_sdk_1.SES({ region: sesParams.region });
|
|
30
|
-
return await ideaWarmStart_ses.sendTemplatedEmail(request).promise();
|
|
26
|
+
logger.debug('SES send templated email');
|
|
27
|
+
return await new aws_sdk_1.SES({ region: sesParams.region }).sendTemplatedEmail(request).promise();
|
|
31
28
|
}
|
|
32
29
|
/**
|
|
33
30
|
* Send an email through AWS Simple Email Service.
|
|
@@ -61,10 +58,8 @@ class SES {
|
|
|
61
58
|
Source: sesParams.sourceName ? `${sesParams.sourceName} <${sesParams.source}>` : sesParams.source,
|
|
62
59
|
SourceArn: sesParams.sourceArn
|
|
63
60
|
};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
ideaWarmStart_ses = new aws_sdk_1.SES({ region: sesParams.region });
|
|
67
|
-
return await ideaWarmStart_ses.sendEmail(request).promise();
|
|
61
|
+
logger.debug('SES send email');
|
|
62
|
+
return await new aws_sdk_1.SES({ region: sesParams.region }).sendEmail(request).promise();
|
|
68
63
|
}
|
|
69
64
|
async sendEmailWithNodemailer(emailData, sesParams) {
|
|
70
65
|
const mailOptions = {};
|
|
@@ -82,10 +77,8 @@ class SES {
|
|
|
82
77
|
if (emailData.text)
|
|
83
78
|
mailOptions.text = emailData.text;
|
|
84
79
|
mailOptions.attachments = emailData.attachments;
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
ideaWarmStart_ses = new aws_sdk_1.SES({ region: sesParams.region });
|
|
88
|
-
return await (0, nodemailer_1.createTransport)({ SES: ideaWarmStart_ses }).sendMail(mailOptions);
|
|
80
|
+
logger.debug('SES send email (Nodemailer)');
|
|
81
|
+
return await (0, nodemailer_1.createTransport)({ SES: new aws_sdk_1.SES({ region: sesParams.region }) }).sendMail(mailOptions);
|
|
89
82
|
}
|
|
90
83
|
prepareEmailDestination(emailData) {
|
|
91
84
|
return {
|
package/dist/src/sns.js
CHANGED
|
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.SNS = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
5
|
const idea_toolbox_1 = require("idea-toolbox");
|
|
6
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
7
|
-
let ideaWarmStart_sns = null;
|
|
8
6
|
/**
|
|
9
7
|
* A wrapper for AWS Simple Notification Service.
|
|
10
8
|
*/
|
|
@@ -29,9 +27,7 @@ class SNS {
|
|
|
29
27
|
throw new Error('Unsupported platform');
|
|
30
28
|
}
|
|
31
29
|
(0, idea_toolbox_1.logger)('SNS ADD PLATFORM ENDPOINT');
|
|
32
|
-
|
|
33
|
-
ideaWarmStart_sns = new aws_sdk_1.SNS({ apiVersion: '2010-03-31', region: snsParams.region });
|
|
34
|
-
const result = await ideaWarmStart_sns
|
|
30
|
+
const result = await new aws_sdk_1.SNS({ apiVersion: '2010-03-31', region: snsParams.region })
|
|
35
31
|
.createPlatformEndpoint({ PlatformApplicationArn: platformARN, Token: token })
|
|
36
32
|
.promise();
|
|
37
33
|
return result.EndpointArn;
|
|
@@ -60,9 +56,7 @@ class SNS {
|
|
|
60
56
|
throw new Error('Unsupported platform');
|
|
61
57
|
}
|
|
62
58
|
(0, idea_toolbox_1.logger)('SNS PUBLISH IN TOPIC');
|
|
63
|
-
|
|
64
|
-
ideaWarmStart_sns = new aws_sdk_1.SNS({ apiVersion: '2010-03-31', region: snsParams.region });
|
|
65
|
-
return await ideaWarmStart_sns
|
|
59
|
+
return await new aws_sdk_1.SNS({ apiVersion: '2010-03-31', region: snsParams.region })
|
|
66
60
|
.publish({ MessageStructure: 'json', Message: JSON.stringify(structuredMessage), TargetArn: snsParams.endpoint })
|
|
67
61
|
.promise();
|
|
68
62
|
}
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.StreamController = void 0;
|
|
4
|
-
const idea_toolbox_1 = require("idea-toolbox");
|
|
5
4
|
const genericController_1 = require("./genericController");
|
|
5
|
+
const logger_1 = require("./logger");
|
|
6
|
+
const logger = new logger_1.Logger();
|
|
6
7
|
/**
|
|
7
8
|
* An abstract class to inherit to manage AWS DDB streams in an AWS Lambda function.
|
|
8
9
|
*/
|
|
@@ -10,7 +11,7 @@ class StreamController extends genericController_1.GenericController {
|
|
|
10
11
|
constructor(event, callback, options = {}) {
|
|
11
12
|
super(event, callback, options);
|
|
12
13
|
this.records = event.Records || [];
|
|
13
|
-
|
|
14
|
+
logger.info(`START STREAM: ${this.records.length || 0} records`);
|
|
14
15
|
}
|
|
15
16
|
}
|
|
16
17
|
exports.StreamController = StreamController;
|
package/dist/src/translate.js
CHANGED
|
@@ -3,8 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.Translate = void 0;
|
|
4
4
|
const aws_sdk_1 = require("aws-sdk");
|
|
5
5
|
const idea_toolbox_1 = require("idea-toolbox");
|
|
6
|
-
// declare libs as global vars to be reused in warm starts by the Lambda function
|
|
7
|
-
let ideaWarmStart_translate = null;
|
|
8
6
|
/**
|
|
9
7
|
* A wrapper for Amazon Translate.
|
|
10
8
|
*/
|
|
@@ -13,9 +11,7 @@ class Translate {
|
|
|
13
11
|
* Initialize a new Translate helper object.
|
|
14
12
|
*/
|
|
15
13
|
constructor() {
|
|
16
|
-
|
|
17
|
-
ideaWarmStart_translate = new aws_sdk_1.Translate({ apiVersion: '2017-07-01' });
|
|
18
|
-
this.translate = ideaWarmStart_translate;
|
|
14
|
+
this.translate = new aws_sdk_1.Translate({ apiVersion: '2017-07-01' });
|
|
19
15
|
this.sourceLanguageCode = 'en';
|
|
20
16
|
this.targetLanguageCode = 'en';
|
|
21
17
|
this.terminologyNames = new Array();
|
package/index.ts
CHANGED
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "idea-aws",
|
|
3
|
-
"version": "3.
|
|
3
|
+
"version": "3.10.0",
|
|
4
4
|
"description": "AWS wrappers to use in IDEA's back-ends",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
@@ -35,19 +35,20 @@
|
|
|
35
35
|
},
|
|
36
36
|
"homepage": "https://uatisdeproblem.github.io/IDEA-AWS",
|
|
37
37
|
"dependencies": {
|
|
38
|
-
"idea-toolbox": "^6.5.
|
|
39
|
-
"nanoid": "^3.
|
|
40
|
-
"nodemailer": "^6.
|
|
38
|
+
"idea-toolbox": "^6.5.9",
|
|
39
|
+
"nanoid": "^3.2.0",
|
|
40
|
+
"nodemailer": "^6.7.2",
|
|
41
41
|
"shortid": "^2.2.16",
|
|
42
|
+
"source-map-support": "^0.5.21",
|
|
42
43
|
"uuid": "^8.3.2"
|
|
43
44
|
},
|
|
44
45
|
"devDependencies": {
|
|
45
46
|
"@tsconfig/node14": "^1.0.0",
|
|
46
|
-
"@types/aws-lambda": "^8.10.
|
|
47
|
+
"@types/aws-lambda": "^8.10.91",
|
|
47
48
|
"@types/node": "^14.14.26",
|
|
48
49
|
"@types/nodemailer": "^6.4.4",
|
|
49
|
-
"@types/shortid": "0.0.29",
|
|
50
|
-
"@types/uuid": "^8.3.
|
|
50
|
+
"@types/shortid": "^0.0.29",
|
|
51
|
+
"@types/uuid": "^8.3.4",
|
|
51
52
|
"@typescript-eslint/eslint-plugin": "^4.31.1",
|
|
52
53
|
"@typescript-eslint/parser": "^4.31.1",
|
|
53
54
|
"aws-sdk": "^2.991.0",
|