@comicrelief/lambda-wrapper 1.10.1 → 1.10.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.
@@ -4,22 +4,18 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.STATUS_TYPES = void 0;
7
-
8
7
  var _Model = _interopRequireDefault(require("./Model.model"));
9
-
10
8
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
11
-
12
9
  const STATUS_TYPES = {
13
10
  OK: 'OK',
14
11
  ACCEPTABLE_FAILURE: 'ACCEPTABLE_FAILURE',
15
12
  APPLICATION_FAILURE: 'APPLICATION_FAILURE'
16
13
  };
14
+
17
15
  /**
18
16
  * StatusModel Class
19
17
  */
20
-
21
18
  exports.STATUS_TYPES = STATUS_TYPES;
22
-
23
19
  class StatusModel extends _Model.default {
24
20
  /**
25
21
  * StatusModel constructor
@@ -32,51 +28,44 @@ class StatusModel extends _Model.default {
32
28
  this.setService(service);
33
29
  this.setStatus(status);
34
30
  }
31
+
35
32
  /**
36
33
  * Get Service
37
34
  *
38
35
  * @returns {*}
39
36
  */
40
-
41
-
42
37
  getService() {
43
38
  return this.service;
44
39
  }
40
+
45
41
  /**
46
42
  * Set Service
47
43
  *
48
44
  * @param service
49
45
  */
50
-
51
-
52
46
  setService(service) {
53
47
  this.service = service;
54
48
  }
49
+
55
50
  /**
56
51
  * Set the status
57
52
  *
58
53
  * @param status
59
54
  */
60
-
61
-
62
55
  setStatus(status) {
63
56
  if (typeof STATUS_TYPES[status] === 'undefined') {
64
57
  throw new TypeError(`${StatusModel.name} - ${status} is not a valid status type`);
65
58
  }
66
-
67
59
  this.status = status;
68
60
  }
61
+
69
62
  /**
70
63
  * Get status
71
64
  *
72
65
  * @returns {string|*}
73
66
  */
74
-
75
-
76
67
  getStatus() {
77
68
  return this.status;
78
69
  }
79
-
80
70
  }
81
-
82
71
  exports.default = StatusModel;
@@ -4,39 +4,35 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.ServiceStatesHttpCodes = exports.ServiceStates = exports.S3_NO_SUCH_KEY_ERROR_CODE = void 0;
7
-
8
7
  var _awsSdk = require("aws-sdk");
9
-
10
8
  var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
11
-
12
9
  var _LambdaTermination = _interopRequireDefault(require("../Wrapper/LambdaTermination"));
13
-
14
10
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
15
-
16
11
  /**
17
12
  * Error.code for S3 404 errors
18
13
  */
19
14
  const S3_NO_SUCH_KEY_ERROR_CODE = 'NoSuchKey';
15
+
20
16
  /**
21
17
  * Represents the service states
22
18
  */
23
-
24
19
  exports.S3_NO_SUCH_KEY_ERROR_CODE = S3_NO_SUCH_KEY_ERROR_CODE;
25
20
  const ServiceStates = {
26
21
  OK: 'OK',
27
22
  TEMPORARILY_PAUSED: 'TEMPORARILY_PAUSED',
28
23
  INDEFINITELY_PAUSED: 'INDEFINITELY_PAUSED'
29
24
  };
25
+
30
26
  /**
31
27
  * Maps service states to HTTP codes
32
28
  */
33
-
34
29
  exports.ServiceStates = ServiceStates;
35
30
  const ServiceStatesHttpCodes = {
36
31
  [ServiceStates.OK]: 200,
37
32
  [ServiceStates.TEMPORARILY_PAUSED]: 409,
38
33
  [ServiceStates.INDEFINITELY_PAUSED]: 409
39
34
  };
35
+
40
36
  /**
41
37
  * BaseConfigService class
42
38
  *
@@ -44,9 +40,7 @@ const ServiceStatesHttpCodes = {
44
40
  * so that `defaultConfig` and possibly `s3Config` can be
45
41
  * overriden / extended.
46
42
  */
47
-
48
43
  exports.ServiceStatesHttpCodes = ServiceStatesHttpCodes;
49
-
50
44
  class BaseConfigService extends _DependencyAware.default {
51
45
  /**
52
46
  * Returns the basic config.
@@ -61,83 +55,77 @@ class BaseConfigService extends _DependencyAware.default {
61
55
  state: ServiceStates.OK
62
56
  };
63
57
  }
58
+
64
59
  /**
65
60
  * Returns the S3 configuration
66
61
  * used to retrieve / update the
67
62
  * service configuration.
68
63
  */
69
-
70
-
71
64
  static get s3config() {
72
65
  return {
73
66
  Bucket: process.env.SERVICE_CONFIG_S3_BUCKET,
74
67
  Key: process.env.SERVICE_CONFIG_S3_KEY
75
68
  };
76
69
  }
70
+
77
71
  /**
78
72
  * Returns an S3 client
79
73
  *
80
74
  * @returns {S3}
81
75
  */
82
-
83
-
84
76
  static get client() {
85
77
  return new _awsSdk.S3({
86
78
  region: process.env.REGION
87
79
  });
88
80
  }
81
+
89
82
  /**
90
83
  * Returns an S3 client
91
84
  *
92
85
  * @returns {S3}
93
86
  */
94
-
95
-
96
87
  get client() {
97
88
  return this.constructor.client;
98
89
  }
90
+
99
91
  /**
100
92
  * Deletes the configuration stored on S3.
101
93
  * Helpful in feature tests.
102
94
  */
103
-
104
-
105
95
  async delete() {
106
96
  return this.client.deleteObject(this.constructor.s3config).promise();
107
97
  }
98
+
108
99
  /**
109
100
  * Puts the given configuration on S3
110
101
  *
111
102
  * @param config
112
103
  */
113
-
114
-
115
104
  async put(config) {
116
- await this.client.putObject({ ...this.constructor.s3config,
105
+ await this.client.putObject({
106
+ ...this.constructor.s3config,
117
107
  Body: JSON.stringify(config)
118
108
  }).promise();
119
109
  return config;
120
110
  }
111
+
121
112
  /**
122
113
  * Gets the service configuration.
123
114
  */
124
-
125
-
126
115
  async get() {
127
116
  const response = await this.client.getObject(this.constructor.s3config).promise();
128
117
  const body = String(response.Body);
129
-
130
118
  if (!body) {
131
119
  // Empty strings are not valid configurations
132
120
  throw new Error('Configuration file is empty');
133
121
  }
134
-
135
122
  try {
136
123
  return JSON.parse(body);
137
124
  } catch {
138
125
  throw new Error('Invalid configuration file');
139
126
  }
140
127
  }
128
+
141
129
  /**
142
130
  * Gets or creates the service configuration.
143
131
  *
@@ -145,8 +133,6 @@ class BaseConfigService extends _DependencyAware.default {
145
133
  * the default configuration
146
134
  * is uploaded and returned instead.
147
135
  */
148
-
149
-
150
136
  async getOrCreate() {
151
137
  try {
152
138
  return await this.get();
@@ -155,10 +141,10 @@ class BaseConfigService extends _DependencyAware.default {
155
141
  // Throw directly any other error
156
142
  throw error;
157
143
  }
158
-
159
144
  return this.put(this.constructor.defaultConfig);
160
145
  }
161
146
  }
147
+
162
148
  /**
163
149
  * Patches the existing configuration
164
150
  * or the default configuration
@@ -166,26 +152,26 @@ class BaseConfigService extends _DependencyAware.default {
166
152
  *
167
153
  * @param partialConfig
168
154
  */
169
-
170
-
171
155
  async patch(partialConfig) {
172
156
  let base = this.constructor.defaultConfig;
173
-
174
157
  try {
175
158
  base = await this.get();
176
159
  } catch (error) {
177
160
  if (error.code !== S3_NO_SUCH_KEY_ERROR_CODE) {
178
161
  // Throw directly any other error
179
162
  throw error;
180
- } // Config doesn't exist
181
- // keep using `this.constructor.defaultConfig`
163
+ }
182
164
 
165
+ // Config doesn't exist
166
+ // keep using `this.constructor.defaultConfig`
183
167
  }
184
168
 
185
- return this.put({ ...base,
169
+ return this.put({
170
+ ...base,
186
171
  ...partialConfig
187
172
  });
188
173
  }
174
+
189
175
  /**
190
176
  * Performs a health check
191
177
  * given the currentConfig.
@@ -195,31 +181,24 @@ class BaseConfigService extends _DependencyAware.default {
195
181
  *
196
182
  * @param currentConfig
197
183
  */
198
-
199
-
200
184
  async healthCheck(currentConfig = null) {
201
185
  const config = currentConfig || (await this.getOrCreate());
202
186
  return ServiceStatesHttpCodes[config.state] || 500;
203
187
  }
188
+
204
189
  /**
205
190
  * Ensures that the application is healthy
206
191
  * or throws a LambdaTermination
207
192
  *
208
193
  * @param currentConfig
209
194
  */
210
-
211
-
212
195
  async ensureHealthy(currentConfig = null) {
213
196
  const statusCode = await this.healthCheck(currentConfig);
214
-
215
197
  if (statusCode < 400) {
216
198
  return statusCode;
217
199
  }
218
-
219
200
  const message = 'Application is not healthy.';
220
201
  throw new _LambdaTermination.default(message, statusCode, message, message);
221
202
  }
222
-
223
203
  }
224
-
225
204
  exports.default = BaseConfigService;
@@ -4,26 +4,19 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = exports.DEFAULT_HTTP_TIMEOUT = exports.COMICRELIEF_TEST_METADATA_HEADER = void 0;
7
-
8
7
  var _axios = _interopRequireWildcard(require("axios"));
9
-
10
8
  var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
11
-
12
9
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
13
-
14
10
  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); }
15
-
16
11
  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; }
17
-
18
12
  const COMICRELIEF_TEST_METADATA_HEADER = 'x-comicrelief-test-metadata';
19
13
  exports.COMICRELIEF_TEST_METADATA_HEADER = COMICRELIEF_TEST_METADATA_HEADER;
20
14
  const DEFAULT_HTTP_TIMEOUT = 10 * 1000;
15
+
21
16
  /**
22
17
  * HTTPService class
23
18
  */
24
-
25
19
  exports.DEFAULT_HTTP_TIMEOUT = DEFAULT_HTTP_TIMEOUT;
26
-
27
20
  class HTTPService extends _DependencyAware.default {
28
21
  constructor(di) {
29
22
  super(di);
@@ -31,23 +24,21 @@ class HTTPService extends _DependencyAware.default {
31
24
  timeout: DEFAULT_HTTP_TIMEOUT
32
25
  };
33
26
  }
27
+
34
28
  /**
35
29
  * Sets the default timeout
36
30
  *
37
31
  * @param {number} ms
38
32
  */
39
-
40
-
41
33
  setDefaultTimeout(ms) {
42
34
  this.config.timeout = ms;
43
35
  }
36
+
44
37
  /**
45
38
  * Performs and HTTP Request
46
39
  *
47
40
  * @param config
48
41
  */
49
-
50
-
51
42
  async request(config) {
52
43
  const mergedConfig = {
53
44
  timeout: this.config.timeout,
@@ -56,15 +47,11 @@ class HTTPService extends _DependencyAware.default {
56
47
  };
57
48
  const lambdaRequest = this.getContainer().get(this.definitions.REQUEST);
58
49
  const testMetadata = lambdaRequest.getHeader(COMICRELIEF_TEST_METADATA_HEADER);
59
-
60
50
  if (testMetadata) {
61
51
  mergedConfig.headers = mergedConfig.headers || {};
62
52
  mergedConfig.headers[COMICRELIEF_TEST_METADATA_HEADER] = testMetadata;
63
53
  }
64
-
65
54
  return _axios.default.request(mergedConfig);
66
55
  }
67
-
68
56
  }
69
-
70
57
  exports.default = HTTPService;
@@ -4,26 +4,16 @@ Object.defineProperty(exports, "__esModule", {
4
4
  value: true
5
5
  });
6
6
  exports.default = void 0;
7
-
8
7
  var Sentry = _interopRequireWildcard(require("@sentry/node"));
9
-
10
8
  var _epsagon = _interopRequireDefault(require("epsagon"));
11
-
12
9
  var _winston = _interopRequireDefault(require("winston"));
13
-
14
10
  var _DependencyAware = _interopRequireDefault(require("../DependencyInjection/DependencyAware.class"));
15
-
16
11
  var _DependencyInjection = _interopRequireDefault(require("../DependencyInjection/DependencyInjection.class"));
17
-
18
12
  function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
19
-
20
13
  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); }
21
-
22
14
  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; }
23
-
24
15
  // Instantiate the sentry client
25
16
  const sentryIsAvailable = typeof process.env.RAVEN_DSN !== 'undefined' && typeof process.env.RAVEN_DSN === 'string' && process.env.RAVEN_DSN !== 'undefined';
26
-
27
17
  if (sentryIsAvailable) {
28
18
  Sentry.init({
29
19
  dsn: process.env.RAVEN_DSN,
@@ -31,11 +21,10 @@ if (sentryIsAvailable) {
31
21
  environment: process.env.STAGE
32
22
  });
33
23
  }
24
+
34
25
  /**
35
26
  * LoggerService class
36
27
  */
37
-
38
-
39
28
  class LoggerService extends _DependencyAware.default {
40
29
  constructor(di) {
41
30
  super(di);
@@ -43,8 +32,9 @@ class LoggerService extends _DependencyAware.default {
43
32
  this.winston = null;
44
33
  const container = this.getContainer();
45
34
  const event = container.getEvent();
46
- const context = container.getContext(); // Set sentry client context
35
+ const context = container.getContext();
47
36
 
37
+ // Set sentry client context
48
38
  if (sentryIsAvailable && !container.isOffline) {
49
39
  Sentry.configureScope(scope => {
50
40
  scope.setTags({
@@ -64,6 +54,7 @@ class LoggerService extends _DependencyAware.default {
64
54
  this.sentry = Sentry;
65
55
  }
66
56
  }
57
+
67
58
  /**
68
59
  * Returns a Winston logger object
69
60
  * configured for our lambdas.
@@ -74,15 +65,12 @@ class LoggerService extends _DependencyAware.default {
74
65
  * in a `serverless-offline` context
75
66
  * the log output to console will be pretty printed.
76
67
  */
77
-
78
-
79
68
  getLogger() {
80
69
  const loggerFormats = [_winston.default.format.json({
81
70
  replacer: (key, value) => {
82
71
  if (value instanceof Buffer) {
83
72
  return value.toString('base64');
84
73
  }
85
-
86
74
  if (value instanceof Error) {
87
75
  const error = {};
88
76
  Object.getOwnPropertyNames(value).forEach(objectKey => {
@@ -90,21 +78,19 @@ class LoggerService extends _DependencyAware.default {
90
78
  });
91
79
  return error;
92
80
  }
93
-
94
81
  return value;
95
82
  }
96
83
  })];
97
-
98
84
  if (this.getContainer().isOffline) {
99
85
  loggerFormats.push(_winston.default.format.prettyPrint());
100
86
  }
101
-
102
87
  return _winston.default.createLogger({
103
88
  level: 'info',
104
89
  format: _winston.default.format.combine(...loggerFormats),
105
90
  transports: [new _winston.default.transports.Console()]
106
91
  });
107
92
  }
93
+
108
94
  /**
109
95
  * Returns the logger.
110
96
  *
@@ -112,15 +98,13 @@ class LoggerService extends _DependencyAware.default {
112
98
  * if it has been already generated,
113
99
  * otherwise it generates one.
114
100
  */
115
-
116
-
117
101
  get logger() {
118
102
  if (!this.winston) {
119
103
  this.winston = this.getLogger();
120
104
  }
121
-
122
105
  return this.winston;
123
106
  }
107
+
124
108
  /**
125
109
  * While handling an error, lambda wrapper should
126
110
  * recognise axios errors and trim down the information.
@@ -133,86 +117,77 @@ class LoggerService extends _DependencyAware.default {
133
117
  *
134
118
  * @param {object} error
135
119
  */
136
-
137
-
138
120
  static processAxiosError(error) {
139
121
  const processed = {
140
122
  config: error.config,
141
123
  message: error.message
142
- }; // It's pretty common for axios errors
124
+ };
125
+
126
+ // It's pretty common for axios errors
143
127
  // to not have.response e.g.when there's
144
128
  // a network error or timeout.
145
129
  // These errors will have .request but not .response.
146
-
147
130
  if (error.response) {
148
131
  processed.response = {
149
132
  status: error.response.status,
150
133
  data: error.response.data
151
134
  };
152
135
  }
153
-
154
136
  return processed;
155
137
  }
138
+
156
139
  /**
157
140
  * Transform the original message
158
141
  * before it is passed to the winston logger
159
142
  *
160
143
  * @param {string|object} message
161
144
  */
162
-
163
-
164
145
  processMessage(message = '') {
165
146
  let processed = message;
166
-
167
147
  if (processed && processed.isAxiosError) {
168
148
  processed = this.constructor.processAxiosError(processed);
169
149
  }
170
-
171
150
  return processed;
172
151
  }
152
+
173
153
  /**
174
154
  * Log Error Message
175
155
  *
176
156
  * @param error object
177
157
  * @param message string
178
158
  */
179
-
180
-
181
159
  error(error, message = '') {
182
160
  if (sentryIsAvailable && error instanceof Error) {
183
161
  Sentry.captureException(error);
184
162
  }
185
-
186
163
  if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined' && error instanceof Error) {
187
164
  _epsagon.default.setError(error);
188
165
  }
189
-
190
166
  this.logger.log('error', message, {
191
167
  error: this.processMessage(error)
192
168
  });
193
169
  this.label('error', true);
194
170
  this.metric('error', 'error', true);
195
171
  }
172
+
196
173
  /**
197
174
  * Get sentry client
198
175
  *
199
176
  * @returns {null|*}
200
177
  */
201
-
202
-
203
178
  getSentry() {
204
179
  return this.sentry;
205
180
  }
181
+
206
182
  /**
207
183
  * Log Information Message
208
184
  *
209
185
  * @param message string
210
186
  */
211
-
212
-
213
187
  info(message) {
214
188
  this.logger.log('info', this.processMessage(message));
215
189
  }
190
+
216
191
  /**
217
192
  * Logs an error, using `LoggerService.error`
218
193
  * or `LoggerService.info` based on
@@ -224,34 +199,29 @@ class LoggerService extends _DependencyAware.default {
224
199
  *
225
200
  * @param error
226
201
  */
227
-
228
-
229
202
  warning(error) {
230
203
  const softWarningValues = ['true', '1'];
231
-
232
204
  if (softWarningValues.includes(process.env.LOGGER_SOFT_WARNING)) {
233
205
  return this.info(error);
234
206
  }
235
-
236
207
  return this.error(error);
237
208
  }
209
+
238
210
  /**
239
211
  * Add a label
240
212
  *
241
213
  * @param descriptor string
242
214
  * @param silent boolean
243
215
  */
244
-
245
-
246
216
  label(descriptor, silent = false) {
247
217
  if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined') {
248
218
  _epsagon.default.label(descriptor, true);
249
219
  }
250
-
251
220
  if (silent === false) {
252
221
  this.logger.log('info', `label - ${descriptor}`);
253
222
  }
254
223
  }
224
+
255
225
  /**
256
226
  * Add a metric
257
227
  *
@@ -259,17 +229,15 @@ class LoggerService extends _DependencyAware.default {
259
229
  * @param stat integer | string
260
230
  * @param silent boolean
261
231
  */
262
-
263
-
264
232
  metric(descriptor, stat, silent = false) {
265
233
  if (typeof process.env.EPSAGON_TOKEN === 'string' && process.env.EPSAGON_TOKEN !== 'undefined' && typeof process.env.EPSAGON_SERVICE_NAME === 'string' && process.env.EPSAGON_SERVICE_NAME !== 'undefined') {
266
234
  _epsagon.default.label(descriptor, stat);
267
235
  }
268
-
269
236
  if (silent === false) {
270
237
  this.logger.log('info', `metric - ${descriptor} - ${stat}`);
271
238
  }
272
239
  }
240
+
273
241
  /**
274
242
  * Logs an object so that it can be inspected
275
243
  *
@@ -277,17 +245,12 @@ class LoggerService extends _DependencyAware.default {
277
245
  * @param object - The object to be stored in logs
278
246
  * @param level - 'error', 'warning' or 'info'
279
247
  */
280
-
281
-
282
248
  object(action, object, level = 'info') {
283
249
  if (!['error', 'warning', 'info'].includes(level)) {
284
250
  throw new Error('Unrecognised log level');
285
251
  }
286
-
287
252
  const payload = JSON.stringify(object, null, 4);
288
253
  return this[level](`${action}: '${payload}'`);
289
254
  }
290
-
291
255
  }
292
-
293
256
  exports.default = LoggerService;