@comicrelief/lambda-wrapper 1.10.2 → 2.0.0-beta.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (89) hide show
  1. package/README.md +196 -50
  2. package/dist/core/DependencyAwareClass.d.ts +16 -0
  3. package/dist/core/DependencyAwareClass.d.ts.map +1 -0
  4. package/dist/core/DependencyAwareClass.js +20 -0
  5. package/dist/core/DependencyAwareClass.js.map +1 -0
  6. package/dist/core/DependencyInjection.d.ts +62 -0
  7. package/dist/core/DependencyInjection.d.ts.map +1 -0
  8. package/dist/core/DependencyInjection.js +105 -0
  9. package/dist/core/DependencyInjection.js.map +1 -0
  10. package/dist/core/LambdaWrapper.d.ts +73 -0
  11. package/dist/core/LambdaWrapper.d.ts.map +1 -0
  12. package/dist/core/LambdaWrapper.js +170 -0
  13. package/dist/core/LambdaWrapper.js.map +1 -0
  14. package/dist/core/config.d.ts +20 -0
  15. package/dist/core/config.d.ts.map +1 -0
  16. package/dist/core/config.js +21 -0
  17. package/dist/core/config.js.map +1 -0
  18. package/dist/index.d.ts +28 -0
  19. package/dist/index.d.ts.map +1 -0
  20. package/dist/index.js +57 -143
  21. package/dist/index.js.map +1 -0
  22. package/dist/models/ResponseModel.d.ts +73 -0
  23. package/dist/models/ResponseModel.d.ts.map +1 -0
  24. package/dist/models/ResponseModel.js +100 -0
  25. package/dist/models/ResponseModel.js.map +1 -0
  26. package/dist/models/SQSMessageModel.d.ts +46 -0
  27. package/dist/models/SQSMessageModel.d.ts.map +1 -0
  28. package/dist/models/SQSMessageModel.js +65 -0
  29. package/dist/models/SQSMessageModel.js.map +1 -0
  30. package/dist/services/BaseConfigService.d.ts +101 -0
  31. package/dist/services/BaseConfigService.d.ts.map +1 -0
  32. package/dist/services/BaseConfigService.js +180 -0
  33. package/dist/services/BaseConfigService.js.map +1 -0
  34. package/dist/services/HTTPService.d.ts +29 -0
  35. package/dist/services/HTTPService.d.ts.map +1 -0
  36. package/dist/services/HTTPService.js +55 -0
  37. package/dist/services/HTTPService.js.map +1 -0
  38. package/dist/services/LoggerService.d.ts +102 -0
  39. package/dist/services/LoggerService.d.ts.map +1 -0
  40. package/dist/services/LoggerService.js +249 -0
  41. package/dist/services/LoggerService.js.map +1 -0
  42. package/dist/services/RequestService.d.ts +119 -0
  43. package/dist/services/RequestService.d.ts.map +1 -0
  44. package/dist/services/RequestService.js +293 -0
  45. package/dist/services/RequestService.js.map +1 -0
  46. package/dist/services/SQSService.d.ts +263 -0
  47. package/dist/services/SQSService.d.ts.map +1 -0
  48. package/dist/services/SQSService.js +411 -0
  49. package/dist/services/SQSService.js.map +1 -0
  50. package/dist/services/TimerService.d.ts +22 -0
  51. package/dist/services/TimerService.d.ts.map +1 -0
  52. package/dist/services/TimerService.js +40 -0
  53. package/dist/services/TimerService.js.map +1 -0
  54. package/dist/types/Status.d.ts +6 -0
  55. package/dist/types/Status.d.ts.map +1 -0
  56. package/dist/types/Status.js +3 -0
  57. package/dist/types/Status.js.map +1 -0
  58. package/dist/utils/LambdaTermination.d.ts +14 -0
  59. package/dist/utils/LambdaTermination.d.ts.map +1 -0
  60. package/dist/utils/LambdaTermination.js +23 -0
  61. package/dist/utils/LambdaTermination.js.map +1 -0
  62. package/dist/utils/PromisifiedDelay.d.ts +17 -0
  63. package/dist/utils/PromisifiedDelay.d.ts.map +1 -0
  64. package/dist/utils/PromisifiedDelay.js +48 -0
  65. package/dist/utils/PromisifiedDelay.js.map +1 -0
  66. package/package.json +36 -26
  67. package/.eslintrc.yml +0 -16
  68. package/.github/dependabot.yml +0 -11
  69. package/.github/workflows/main.yml +0 -74
  70. package/babel.config.js +0 -13
  71. package/dist/Config/Dependencies.js +0 -33
  72. package/dist/DependencyInjection/DependencyAware.class.js +0 -40
  73. package/dist/DependencyInjection/DependencyInjection.class.js +0 -115
  74. package/dist/Model/CloudEvent.model.js +0 -138
  75. package/dist/Model/Model.model.js +0 -39
  76. package/dist/Model/Response.model.js +0 -135
  77. package/dist/Model/SQS/MarketingPreference.constraints.json +0 -28
  78. package/dist/Model/SQS/MarketingPreference.model.js +0 -583
  79. package/dist/Model/SQS/Message.model.js +0 -92
  80. package/dist/Model/Status.model.js +0 -71
  81. package/dist/Service/BaseConfig.service.js +0 -204
  82. package/dist/Service/HTTP.service.js +0 -57
  83. package/dist/Service/Logger.service.js +0 -256
  84. package/dist/Service/Request.service.js +0 -294
  85. package/dist/Service/SQS.service.js +0 -367
  86. package/dist/Service/Timer.service.js +0 -46
  87. package/dist/Wrapper/LambdaTermination.js +0 -34
  88. package/dist/Wrapper/LambdaWrapper.js +0 -143
  89. package/dist/Wrapper/PromisifiedDelay.js +0 -55
@@ -1,294 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = exports.REQUEST_TYPES = exports.HTTP_METHODS_WITH_PAYLOADS = exports.HTTP_METHODS_WITHOUT_PAYLOADS = exports.ERROR_TYPES = void 0;
7
- var _querystring = _interopRequireDefault(require("querystring"));
8
- var _useragent = _interopRequireDefault(require("useragent"));
9
- var _validate = _interopRequireDefault(require("validate.js/validate"));
10
- var _xml2js = _interopRequireDefault(require("xml2js"));
11
- var _Dependencies = require("../Config/Dependencies");
12
- var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
13
- var _Response = _interopRequireDefault(require("../Model/Response.model"));
14
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
- /* eslint-disable class-methods-use-this */
16
- /* eslint-disable sonarjs/no-duplicate-string */const REQUEST_TYPES = {
17
- DELETE: 'DELETE',
18
- GET: 'GET',
19
- HEAD: 'HEAD',
20
- OPTIONS: 'OPTIONS',
21
- PATCH: 'PATCH',
22
- POST: 'POST',
23
- PUT: 'PUT'
24
- };
25
- exports.REQUEST_TYPES = REQUEST_TYPES;
26
- const HTTP_METHODS_WITHOUT_PAYLOADS = [REQUEST_TYPES.DELETE, REQUEST_TYPES.GET, REQUEST_TYPES.HEAD, REQUEST_TYPES.OPTIONS];
27
- exports.HTTP_METHODS_WITHOUT_PAYLOADS = HTTP_METHODS_WITHOUT_PAYLOADS;
28
- const HTTP_METHODS_WITH_PAYLOADS = [REQUEST_TYPES.PATCH, REQUEST_TYPES.POST, REQUEST_TYPES.PUT];
29
-
30
- // Define action specific error types
31
- exports.HTTP_METHODS_WITH_PAYLOADS = HTTP_METHODS_WITH_PAYLOADS;
32
- const ERROR_TYPES = {
33
- VALIDATION_ERROR: new _Response.default({}, 400, 'required fields are missing')
34
- };
35
-
36
- /**
37
- * RequestService class
38
- */
39
- exports.ERROR_TYPES = ERROR_TYPES;
40
- class RequestService extends _DependencyAware.default {
41
- /**
42
- * Get a parameter from the request.
43
- *
44
- * @param parameter
45
- * @param ifNull
46
- * @param requestType
47
- */
48
- get(parameter, ifNull = null, requestType = null) {
49
- const queryParameters = this.getAll(requestType);
50
- if (queryParameters === null) {
51
- return ifNull;
52
- }
53
- return typeof queryParameters[parameter] !== 'undefined' ? queryParameters[parameter] : ifNull;
54
- }
55
-
56
- /**
57
- * Get all HTTP headers included in the request.
58
- *
59
- * @returns {object} An object with a key for each header.
60
- */
61
- getAllHeaders() {
62
- return {
63
- ...this.getContainer().getEvent().headers
64
- };
65
- }
66
-
67
- /**
68
- * Get an HTTP header from the request.
69
- *
70
- * The header name is case-insensitive.
71
- *
72
- * @param {string} name The name of the header.
73
- * @param {string} [whenMissing] Value to return if the header is missing.
74
- * (default: empty string)
75
- * @returns {string}
76
- */
77
- getHeader(name, whenMissing = '') {
78
- const headers = this.getAllHeaders();
79
- if (!headers) {
80
- return whenMissing;
81
- }
82
- const lowerName = name.toLowerCase();
83
- const key = Object.keys(headers).find(k => k.toLowerCase() === lowerName);
84
- return key && headers[key] || whenMissing;
85
- }
86
-
87
- /**
88
- * Get authorization token
89
- *
90
- * @returns {*}
91
- */
92
- getAuthorizationToken() {
93
- const authorization = this.getHeader('Authorization');
94
- if (!authorization) {
95
- return null;
96
- }
97
- const tokenParts = authorization.split(' ');
98
- const tokenValue = tokenParts[1];
99
- if (!(tokenParts[0].toLowerCase() === 'bearer' && tokenValue)) {
100
- return null;
101
- }
102
- return tokenValue;
103
- }
104
-
105
- /**
106
- * Get a path parameter
107
- *
108
- * @param parameter
109
- * @param ifNull mixed
110
- */
111
- getPathParameter(parameter = null, ifNull = {}) {
112
- const event = this.getContainer().getEvent();
113
-
114
- // If no parameter has been requested, return all path parameters
115
- if (parameter === null && typeof event.pathParameters === 'object') {
116
- return event.pathParameters;
117
- }
118
-
119
- // If a specifc parameter has been requested, return the parameter if it exists
120
- if (typeof parameter === 'string' && typeof event.pathParameters === 'object' && event.pathParameters !== null && typeof event.pathParameters[parameter] !== 'undefined') {
121
- return event.pathParameters[parameter];
122
- }
123
- return ifNull;
124
- }
125
-
126
- /**
127
- * Get all request parameters
128
- *
129
- * @param requestType
130
- * @returns {{}}
131
- */
132
- // eslint-disable-next-line sonarjs/cognitive-complexity
133
- getAll(requestType = null) {
134
- const event = this.getContainer().getEvent();
135
- if (HTTP_METHODS_WITHOUT_PAYLOADS.includes(event.httpMethod) || HTTP_METHODS_WITHOUT_PAYLOADS.includes(requestType)) {
136
- // get simple parameters
137
- const params = {
138
- ...event.queryStringParameters
139
- };
140
- // add array parameters as arrays
141
- Object.keys(params).filter(key => key.endsWith('[]')).forEach(key => {
142
- params[key] = event.multiValueQueryStringParameters[key];
143
- });
144
- return params;
145
- }
146
- if (HTTP_METHODS_WITH_PAYLOADS.includes(event.httpMethod) || HTTP_METHODS_WITH_PAYLOADS.includes(requestType)) {
147
- const contentType = this.getHeader('Content-Type');
148
- let queryParameters = {};
149
- if (contentType.includes('application/x-www-form-urlencoded')) {
150
- queryParameters = _querystring.default.parse(event.body);
151
- }
152
- if (contentType.includes('application/json')) {
153
- try {
154
- queryParameters = JSON.parse(event.body);
155
- } catch {
156
- queryParameters = {};
157
- }
158
- }
159
- if (contentType.includes('text/xml')) {
160
- _xml2js.default.parseString(event.body, (error, result) => {
161
- queryParameters = error ? {} : result;
162
- });
163
- }
164
- if (contentType.includes('multipart/form-data')) {
165
- queryParameters = this.parseForm(true);
166
- }
167
- return typeof queryParameters !== 'undefined' ? queryParameters : {};
168
- }
169
- return null;
170
- }
171
-
172
- /**
173
- * Fetch the request IP address
174
- *
175
- * @returns {*}
176
- */
177
- getIp() {
178
- const event = this.getContainer().getEvent();
179
- if (typeof event.requestContext !== 'undefined' && typeof event.requestContext.identity !== 'undefined' && typeof event.requestContext.identity.sourceIp !== 'undefined') {
180
- return event.requestContext.identity.sourceIp;
181
- }
182
- return null;
183
- }
184
-
185
- /**
186
- * Get user agent
187
- *
188
- * @returns {*}
189
- */
190
- getUserBrowserAndDevice() {
191
- const userAgent = this.getHeader('user-agent', null);
192
- if (userAgent === null) {
193
- return null;
194
- }
195
- try {
196
- const agent = _useragent.default.parse(userAgent);
197
- const os = agent.os.toJSON();
198
- return {
199
- 'browser-type': agent.family,
200
- 'browser-version': agent.toVersion(),
201
- 'device-type': agent.device.family,
202
- 'operating-system': os.family,
203
- 'operating-system-version': agent.os.toVersion()
204
- };
205
- } catch {
206
- this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER).label('user-agent-parsing-failed');
207
- return null;
208
- }
209
- }
210
-
211
- /**
212
- * Test a request against validation constraints
213
- *
214
- * @param constraints
215
- * @returns {Promise<any>}
216
- */
217
- validateAgainstConstraints(constraints) {
218
- const Logger = this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER);
219
- return new Promise((resolve, reject) => {
220
- const validation = (0, _validate.default)(this.getAll(), constraints);
221
- if (typeof validation === 'undefined') {
222
- resolve();
223
- } else {
224
- Logger.label('request-validation-failed');
225
- const validationErrorResponse = ERROR_TYPES.VALIDATION_ERROR;
226
- validationErrorResponse.setBodyVariable('validation_errors', validation);
227
- reject(validationErrorResponse);
228
- }
229
- });
230
- }
231
-
232
- /**
233
- * Fetch the request multipart form
234
- *
235
- * @param useBuffer
236
- * @returns {*}
237
- */
238
- parseForm(useBuffer) {
239
- const event = this.getContainer().getEvent();
240
- const boundary = this.getBoundary(event);
241
- const body = event.isBase64Encoded ? Buffer.from(event.body, 'base64').toString('binary').trim() : event.body;
242
- const result = {};
243
- body.split(boundary).forEach(item => {
244
- if (/filename=".+"/g.test(item)) {
245
- result[item.match(/name=".+";/g)[0].slice(6, -2)] = {
246
- type: 'file',
247
- filename: item.match(/filename=".+"/g)[0].slice(10, -1),
248
- contentType: item.match(/Content-Type:\s.+/g)[0].slice(14),
249
- content: useBuffer ? Buffer.from(item.slice(item.search(/Content-Type:\s.+/g) + item.match(/Content-Type:\s.+/g)[0].length + 4, -4), 'binary') : item.slice(item.search(/Content-Type:\s.+/g) + item.match(/Content-Type:\s.+/g)[0].length + 4, -4)
250
- };
251
- } else if (/name=".+"/g.test(item)) {
252
- result[item.match(/name=".+"/g)[0].slice(6, -1)] = item.slice(item.search(/name=".+"/g) + item.match(/name=".+"/g)[0].length + 4, -4);
253
- }
254
- });
255
- return result;
256
- }
257
-
258
- /**
259
- * Fetch the request AWS event Records
260
- *
261
- * @returns {*}
262
- */
263
- getAWSRecords() {
264
- const event = this.getContainer().getEvent();
265
- const eventRecord = event.Records && event.Records[0];
266
- if (typeof event.Records !== 'undefined' && typeof event.Records[0] !== 'undefined' && typeof eventRecord.eventSource !== 'undefined') {
267
- return eventRecord;
268
- }
269
- return null;
270
- }
271
-
272
- /**
273
- * Gets a value independently from
274
- * the case of the key
275
- *
276
- * @param object
277
- * @param key
278
- */
279
- getValueIgnoringKeyCase(object, key) {
280
- const foundKey = Object.keys(object).find(currentKey => currentKey.toLocaleLowerCase() === key.toLowerCase());
281
- return object[foundKey];
282
- }
283
-
284
- /**
285
- * Returns the content type
286
- * assoiated with the request
287
- *
288
- * @param event
289
- */
290
- getBoundary(event) {
291
- return this.getValueIgnoringKeyCase(event.headers, 'Content-Type').split('=')[1];
292
- }
293
- }
294
- exports.default = RequestService;
@@ -1,367 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = exports.SQS_PUBLISH_FAILURE_MODES = exports.SQS_OFFLINE_MODES = void 0;
7
- var _alai = _interopRequireDefault(require("alai"));
8
- var _each = _interopRequireDefault(require("async/each"));
9
- var _awsSdk = _interopRequireDefault(require("aws-sdk"));
10
- var _uuid = require("uuid");
11
- var _Dependencies = require("../Config/Dependencies");
12
- var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
13
- var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
14
- var _Message = _interopRequireDefault(require("../Model/SQS/Message.model"));
15
- var _Status = _interopRequireWildcard(require("../Model/Status.model"));
16
- function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
17
- function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
18
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
- /**
20
- * Allowed values for `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`.
21
- */
22
- const SQS_OFFLINE_MODES = {
23
- /**
24
- * When running offline, messages will trigger the consumer function directly
25
- * via a Lambda endpoint, set using `process.env.SERVICE_LAMBDA_URL`. This is
26
- * the default.
27
- */
28
- DIRECT: 'direct',
29
- /**
30
- * When running offline, send messages to an offline SQS service defined by
31
- * `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_HOST`.
32
- */
33
- LOCAL: 'local',
34
- /**
35
- * When running offline, send messages to AWS as normal.
36
- */
37
- AWS: 'aws'
38
- };
39
-
40
- /**
41
- * Defines the preferred behaviour
42
- * for SQSService.prototype.publish
43
- * should AWS SQS fail.
44
- */
45
- exports.SQS_OFFLINE_MODES = SQS_OFFLINE_MODES;
46
- const SQS_PUBLISH_FAILURE_MODES = {
47
- /**
48
- * Catches the exception and logs it.
49
- * This is the default behaviour
50
- * for LambdaWrapper 1.8.0 and below
51
- * and for LambdaWrapper 1.8.2 and above
52
- */
53
- CATCH: 'catch',
54
- /**
55
- * Throws the exception so that the caller
56
- * can handle it directly.
57
- */
58
- THROW: 'throw'
59
- };
60
-
61
- /**
62
- * SQSService class
63
- */
64
- exports.SQS_PUBLISH_FAILURE_MODES = SQS_PUBLISH_FAILURE_MODES;
65
- class SQSService extends _DependencyAware.default {
66
- /**
67
- * SQSService constructor
68
- *
69
- * @param di DependencyInjection
70
- */
71
- constructor(di) {
72
- super(di);
73
- const {
74
- LAMBDA_WRAPPER_OFFLINE_SQS_HOST: offlineHost = 'localhost',
75
- LAMBDA_WRAPPER_OFFLINE_SQS_PORT: offlinePort = '4576',
76
- LAMBDA_WRAPPER_OFFLINE_SQS_MODE: offlineMode = SQS_OFFLINE_MODES.DIRECT,
77
- AWS_ACCOUNT_ID,
78
- REGION
79
- } = process.env;
80
- const container = this.getContainer();
81
- const context = container.getContext();
82
- const queues = container.getConfiguration('QUEUES');
83
- const accountId = context && context.invokedFunctionArn && _alai.default.parse(context) || AWS_ACCOUNT_ID;
84
- this.queues = {};
85
- this.$lambda = null;
86
- this.$sqs = null;
87
- if (container.isOffline && !Object.values(SQS_OFFLINE_MODES).includes(offlineMode)) {
88
- throw new Error(`Invalid LAMBDA_WRAPPER_OFFLINE_SQS_MODE: ${offlineMode}\n` + `Please use one of: ${Object.values(SQS_OFFLINE_MODES).join(', ')}`);
89
- }
90
-
91
- // Add the queues from configuration
92
- if (queues !== null && Object.keys(queues).length > 0) {
93
- Object.keys(queues).forEach(queueDefinition => {
94
- if (container.isOffline && offlineMode === SQS_OFFLINE_MODES.LOCAL) {
95
- // custom URL when using an offline SQS service such as Localstack
96
- this.queues[queueDefinition] = `http://${offlineHost}:${offlinePort}/queue/${queues[queueDefinition]}`;
97
- } else {
98
- // default AWS queue URL
99
- this.queues[queueDefinition] = `https://sqs.${REGION}.amazonaws.com/${accountId}/${queues[queueDefinition]}`;
100
- }
101
- });
102
- }
103
- }
104
-
105
- /**
106
- * Returns an SQS client instance
107
- */
108
- get sqs() {
109
- if (!this.$sqs) {
110
- this.$sqs = new _awsSdk.default.SQS({
111
- region: process.env.REGION,
112
- httpOptions: {
113
- // longest publish on NOTV took 5 seconds
114
- connectTimeout: 8 * 1000,
115
- timeout: 8 * 1000
116
- },
117
- maxRetries: 3 // default is 3, we can change that
118
- });
119
- }
120
-
121
- return this.$sqs;
122
- }
123
-
124
- /**
125
- * Returns a Lambda client instance
126
- */
127
- get lambda() {
128
- if (!this.$lambda) {
129
- const endpoint = process.env.SERVICE_LAMBDA_URL;
130
- if (!endpoint) {
131
- throw new Error('process.env.SERVICE_LAMBDA_URL must be defined.');
132
- }
133
-
134
- // move to subprocess
135
- this.$lambda = new _awsSdk.default.Lambda({
136
- region: process.env.AWS_REGION,
137
- endpoint
138
- });
139
- }
140
- return this.$lambda;
141
- }
142
-
143
- /**
144
- * Returns the mode to use for offline SQS.
145
- *
146
- * This is configured by `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`. The
147
- * default is `SQS_OFFLINE_MODES.LAMBDA`.
148
- */
149
- static get offlineMode() {
150
- return process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE || SQS_OFFLINE_MODES.DIRECT;
151
- }
152
-
153
- /**
154
- * Batch delete messages
155
- *
156
- * @param queue strung
157
- * @param messageModels [SQSMessageModel]
158
- * @returns {Promise<any>}
159
- */
160
- batchDelete(queue, messageModels) {
161
- const container = this.getContainer();
162
- const queueUrl = this.queues[queue];
163
- const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
164
- const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
165
- const timerId = `sqs-batch-delete-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
166
- return new Promise(resolve => {
167
- const messagesForDeletion = [];
168
- Timer.start(timerId);
169
- // assuming openFiles is an array of file names
170
- (0, _each.default)(messageModels, (messageModel, callback) => {
171
- if (messageModel instanceof _Message.default && messageModel.isForDeletion() === true) {
172
- messagesForDeletion.push({
173
- Id: messageModel.getMessageId(),
174
- ReceiptHandle: messageModel.getReceiptHandle()
175
- });
176
- }
177
- callback();
178
- }, loopError => {
179
- if (loopError) {
180
- Logger.error(loopError);
181
- resolve();
182
- }
183
- this.sqs.deleteMessageBatch({
184
- Entries: messagesForDeletion,
185
- QueueUrl: queueUrl
186
- }, error => {
187
- Timer.stop(timerId);
188
- if (error) {
189
- Logger.error(error);
190
- }
191
- resolve();
192
- });
193
- });
194
- });
195
- }
196
-
197
- /**
198
- * Check SQS status
199
- *
200
- * @returns {Promise<any>}
201
- */
202
- checkStatus() {
203
- const container = this.getContainer();
204
- const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
205
- const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
206
- const timerId = `sqs-list-queues-${(0, _uuid.v4)()}`;
207
- return new Promise(resolve => {
208
- Timer.start(timerId);
209
- this.sqs.listQueues({}, (error, data) => {
210
- Timer.stop(timerId);
211
- const statusModel = new _Status.default('SQS', _Status.STATUS_TYPES.OK);
212
- if (error) {
213
- Logger.error(error);
214
- statusModel.setStatus(_Status.STATUS_TYPES.APPLICATION_FAILURE);
215
- }
216
- if (typeof data.QueueUrls === 'undefined' || data.QueueUrls.length === 0) {
217
- statusModel.setStatus(_Status.STATUS_TYPES.APPLICATION_FAILURE);
218
- }
219
- resolve(statusModel);
220
- });
221
- });
222
- }
223
-
224
- /**
225
- * Get number of messages in a queue
226
- *
227
- * @param queue
228
- * @returns {Promise<any>}
229
- */
230
- getMessageCount(queue) {
231
- const container = this.getContainer();
232
- const queueUrl = this.queues[queue];
233
- const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
234
- const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
235
- const timerId = `sqs-get-queue-attributes-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
236
- return new Promise(resolve => {
237
- Timer.start(timerId);
238
- this.sqs.getQueueAttributes({
239
- AttributeNames: ['ApproximateNumberOfMessages'],
240
- QueueUrl: queueUrl
241
- }, (error, data) => {
242
- Timer.stop(timerId);
243
- if (error) {
244
- Logger.error(error);
245
- resolve(0);
246
- }
247
- resolve(Number.parseInt(data.Attributes.ApproximateNumberOfMessages, 10));
248
- });
249
- });
250
- }
251
-
252
- /**
253
- * Publish to message queue
254
- *
255
- * When running within serverless-offline, messages can be published to a
256
- * local Lambda or SQS service instead of to AWS, depending on the offline
257
- * mode specified by `process.env.LAMBDA_WRAPPER_OFFLINE_SQS_MODE`.
258
- *
259
- * @param queue string
260
- * @param messageObject object
261
- * @param messageGroupId string
262
- * @param {'catch' | 'throw'} failureMode Choose how failures are handled:
263
- * - `catch`: errors will be caught and logged. This is the default.
264
- * - `throw`: errors will be thrown, causing promise to reject.
265
- * @returns {Promise<any>}
266
- */
267
- async publish(queue, messageObject, messageGroupId = null, failureMode = SQS_PUBLISH_FAILURE_MODES.CATCH) {
268
- if (!Object.values(SQS_PUBLISH_FAILURE_MODES).includes(failureMode)) {
269
- throw new Error(`Invalid value for 'failureMode': ${failureMode}`);
270
- }
271
- const container = this.getContainer();
272
- const queueUrl = this.queues[queue];
273
- const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
274
- const timerId = `sqs-send-message-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
275
- Timer.start(timerId);
276
- const messageParameters = {
277
- MessageBody: JSON.stringify(messageObject),
278
- QueueUrl: queueUrl
279
- };
280
- if (queueUrl.includes('.fifo')) {
281
- messageParameters.MessageDeduplicationId = (0, _uuid.v4)();
282
- messageParameters.MessageGroupId = messageGroupId !== null ? messageGroupId : (0, _uuid.v4)();
283
- }
284
- try {
285
- if (container.isOffline && this.constructor.offlineMode === SQS_OFFLINE_MODES.DIRECT) {
286
- await this.publishOffline(queue, messageParameters);
287
- } else {
288
- await this.sqs.sendMessage(messageParameters).promise();
289
- }
290
- } catch (error) {
291
- if (failureMode === SQS_PUBLISH_FAILURE_MODES.CATCH) {
292
- container.get(_Dependencies.DEFINITIONS.LOGGER).error(error);
293
- return null;
294
- }
295
- throw error;
296
- }
297
- return queue;
298
- }
299
-
300
- /**
301
- * Sends a message to a queue consumer running in serverless-offline.
302
- *
303
- * This method invokes the consumer function directly instead of sending the
304
- * message to SQS, which requires a real or emulated SQS service not provided
305
- * by serverless-offline. This works very well for local testing.
306
- *
307
- * @param queue
308
- * @param messageParameters
309
- */
310
- async publishOffline(queue, messageParameters) {
311
- const container = this.getContainer();
312
- if (!container.isOffline) {
313
- throw new Error('Can only publishOffline while running serverless offline.');
314
- }
315
- const consumers = container.getConfiguration('QUEUE_CONSUMERS') || {};
316
- const FunctionName = consumers[queue];
317
- if (!FunctionName) {
318
- throw new Error(`Queue consumer for queue ${queue} was not found. Please configure your application's QUEUE_CONSUMERS.`);
319
- }
320
- const InvocationType = 'RequestResponse';
321
- const Payload = JSON.stringify({
322
- Records: [{
323
- body: messageParameters.MessageBody
324
- }]
325
- });
326
- const parameters = {
327
- FunctionName,
328
- InvocationType,
329
- Payload
330
- };
331
- await this.lambda.invoke(parameters).promise();
332
- }
333
-
334
- /**
335
- * Receive from message queue
336
- *
337
- * @param queue string
338
- * @param timeout number
339
- * @returns {Promise<any>}
340
- */
341
- receive(queue, timeout = 15) {
342
- const container = this.getContainer();
343
- const queueUrl = this.queues[queue];
344
- const Logger = container.get(_Dependencies.DEFINITIONS.LOGGER);
345
- const Timer = container.get(_Dependencies.DEFINITIONS.TIMER);
346
- const timerId = `sqs-receive-message-${(0, _uuid.v4)()} - Queue: '${queueUrl}'`;
347
- return new Promise((resolve, reject) => {
348
- Timer.start(timerId);
349
- this.sqs.receiveMessage({
350
- QueueUrl: queueUrl,
351
- VisibilityTimeout: timeout,
352
- MaxNumberOfMessages: 10
353
- }, (error, data) => {
354
- Timer.stop(timerId);
355
- if (error) {
356
- Logger.error(error);
357
- return reject(error);
358
- }
359
- if (typeof data.Messages === 'undefined') {
360
- return resolve([]);
361
- }
362
- return resolve(data.Messages.map(message => new _Message.default(message)));
363
- });
364
- });
365
- }
366
- }
367
- exports.default = SQSService;
@@ -1,46 +0,0 @@
1
- "use strict";
2
-
3
- Object.defineProperty(exports, "__esModule", {
4
- value: true
5
- });
6
- exports.default = void 0;
7
- var _Dependencies = require("../Config/Dependencies");
8
- var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
9
- var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
10
- function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
- /**
12
- * TimerService class
13
- */
14
- class TimerService extends _DependencyAware.default {
15
- /**
16
- * TimerService constructor
17
- *
18
- * @param di
19
- */
20
- constructor(di) {
21
- super(di);
22
- this.timers = {};
23
- }
24
-
25
- /**
26
- * Start timer
27
- *
28
- * @param identifier
29
- */
30
- start(identifier) {
31
- this.timers[identifier] = Date.now();
32
- }
33
-
34
- /**
35
- * Stop timer
36
- *
37
- * @param identifier
38
- */
39
- stop(identifier) {
40
- if (typeof this.timers[identifier] !== 'undefined') {
41
- const duration = Date.now() - this.timers[identifier];
42
- this.getContainer().get(_Dependencies.DEFINITIONS.LOGGER).info(`Timing - ${identifier} took ${duration}ms to complete`);
43
- }
44
- }
45
- }
46
- exports.default = TimerService;