backend-manager 3.0.63 → 3.0.64

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "3.0.63",
3
+ "version": "3.0.64",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -163,6 +163,15 @@ Module.prototype.clearFirestore = function() {
163
163
  })
164
164
  }
165
165
 
166
+ // Clear temporary/usage in firestore by deleting the doc
167
+ await libraries.admin.firestore().doc(`temporary/usage`).delete()
168
+ .then(r => {
169
+ assistant.log(`cron/daily/reset-usage() [firestore]: Deleted temporary/usage`);
170
+ })
171
+ .catch(e => {
172
+ assistant.errorManager(`Error deleting temporary/usage: ${e}`, {sentry: false, send: false, log: true})
173
+ })
174
+
166
175
  return resolve();
167
176
  });
168
177
  }
@@ -33,6 +33,11 @@ BackendAssistant.prototype.init = function (ref, options) {
33
33
 
34
34
  const now = new Date();
35
35
 
36
+ // Attached libraries - used in .errorify()
37
+ self.analytics = null;
38
+ self.usage = null;
39
+
40
+ // Set meta
36
41
  self.meta = {};
37
42
 
38
43
  self.meta.startTime = {};
@@ -43,6 +48,7 @@ BackendAssistant.prototype.init = function (ref, options) {
43
48
  self.meta.environment = options.environment || self.getEnvironment();
44
49
  self.meta.type = options.functionType || process.env.FUNCTION_SIGNATURE_TYPE || 'unknown';
45
50
 
51
+ // Set ref
46
52
  self.ref = {};
47
53
  ref = ref || {};
48
54
  self.ref.res = ref.res || {};
@@ -50,14 +56,17 @@ BackendAssistant.prototype.init = function (ref, options) {
50
56
  self.ref.admin = ref.admin || {};
51
57
  self.ref.functions = ref.functions || {};
52
58
  self.ref.Manager = ref.Manager || {};
59
+ self.Manager = self.ref.Manager;
53
60
 
54
61
  // Set ID
55
62
  try {
56
- self.id = self.ref.Manager.Utilities().randomId();
63
+ self.id = self.Manager.Utilities().randomId();
57
64
  } catch {
58
65
  self.id = now.getTime();
59
66
  }
60
67
 
68
+ self.tag = `${self.meta.name}/${self.id}`;
69
+
61
70
  // Set stuff about request
62
71
  self.request = {};
63
72
  self.request.referrer = (self.ref.req.headers || {}).referrer || (self.ref.req.headers || {}).referer || '';
@@ -146,6 +155,7 @@ BackendAssistant.prototype.init = function (ref, options) {
146
155
  self.constant.pastTime.timestamp = '1999-01-01T00:00:00Z';
147
156
  self.constant.pastTime.timestampUNIX = 915148800;
148
157
 
158
+ // Log options
149
159
  if (
150
160
  (self.meta.environment === 'development')
151
161
  && ((self.request.method !== 'OPTIONS') || (self.request.method === 'OPTIONS' && options.showOptionsLog))
@@ -155,8 +165,10 @@ BackendAssistant.prototype.init = function (ref, options) {
155
165
  console.log(options.optionsLogString);
156
166
  }
157
167
 
168
+ // Set tmpdir
158
169
  self.tmpdir = path.resolve(os.tmpdir(), options.fileSavePath, uuid.v4());
159
170
 
171
+ // Set initialized
160
172
  self.initialized = true;
161
173
 
162
174
  return self;
@@ -279,7 +291,7 @@ BackendAssistant.prototype._log = function() {
279
291
  const logs = [...Array.prototype.slice.call(arguments)];
280
292
 
281
293
  // 2. Prepend log prefix log string
282
- logs.unshift(`[${self.meta.name}/${self.id} @ ${new Date().toISOString()}]:`);
294
+ logs.unshift(`[${self.tag} @ ${new Date().toISOString()}]:`);
283
295
 
284
296
  // 3. Pass along arguments to console.log
285
297
  if (logs[1] === 'error') {
@@ -335,22 +347,36 @@ BackendAssistant.prototype._log = function() {
335
347
  BackendAssistant.prototype.errorManager = function(e, options) {
336
348
  const self = this;
337
349
 
350
+ // Set options
338
351
  options = options || {};
339
- options.code = typeof options.code === 'undefined' ? 500 : options.code;
340
- options.log = typeof options.log === 'undefined' ? true : options.log;
341
- options.sentry = typeof options.sentry === 'undefined' ? true : options.sentry;
342
- options.send = typeof options.send === 'undefined' ? true : options.send;
343
-
352
+ options.code = typeof options.code === 'undefined'
353
+ ? 500
354
+ : options.code;
355
+ options.log = typeof options.log === 'undefined'
356
+ ? true
357
+ : options.log;
358
+ options.sentry = typeof options.sentry === 'undefined'
359
+ ? true
360
+ : options.sentry;
361
+ options.send = typeof options.send === 'undefined'
362
+ ? true
363
+ : options.send;
364
+
365
+ // Construct error
344
366
  const newError = e instanceof Error
345
367
  ? e
346
368
  : new Error(stringify(e));
347
369
 
370
+ options.code = newError.code || options.code;
371
+
348
372
  // Attach properties
349
373
  Object.keys(options)
350
374
  .forEach((item, i) => {
351
- Object.assign(newError , { [item]: options[item] })
375
+ Object.assign(newError, { [item]: options[item] });
352
376
  });
353
377
 
378
+ // Attach properties
379
+ _attachHeaderProperties(self, options);
354
380
 
355
381
  // Log the error
356
382
  if (options.log) {
@@ -359,12 +385,17 @@ BackendAssistant.prototype.errorManager = function(e, options) {
359
385
 
360
386
  // Send error to Sentry
361
387
  if (options.sentry) {
362
- self.ref.Manager.libraries.sentry.captureException(newError);
388
+ self.Manager.libraries.sentry.captureException(newError);
363
389
  }
364
390
 
365
391
  // Quit and respond to the request
366
392
  if (options.send && self.ref.res && self.ref.res.status) {
367
- self.ref.res.status(options.code).send(newError ? newError.message || newError : 'Unknown error');
393
+ self.ref.res
394
+ .status(options.code)
395
+ .send(newError
396
+ ? newError.message || newError
397
+ : 'Unknown error'
398
+ );
368
399
  }
369
400
 
370
401
  return {
@@ -372,6 +403,38 @@ BackendAssistant.prototype.errorManager = function(e, options) {
372
403
  }
373
404
  }
374
405
 
406
+ BackendAssistant.prototype.errorify = BackendAssistant.prototype.errorManager;
407
+
408
+ BackendAssistant.prototype.respond = function(response, options) {
409
+ const self = this;
410
+
411
+ // Set options
412
+ options = options || {};
413
+ options.code = typeof options.code === 'undefined'
414
+ ? 200
415
+ : options.code;
416
+ options.log = typeof options.log === 'undefined'
417
+ ? true
418
+ : options.log;
419
+
420
+ // Attach properties
421
+ _attachHeaderProperties(self, options);
422
+
423
+ // Log the error
424
+ if (options.log) {
425
+ self.log(`Responding with ${options.code} code:`, JSON.stringify(response));
426
+ }
427
+
428
+ // Send response
429
+ self.ref.res.status(options.code);
430
+
431
+ if (typeof response === 'string') {
432
+ self.ref.res.send(response);
433
+ } else {
434
+ self.ref.res.json(response);
435
+ }
436
+ }
437
+
375
438
  function stringify(e) {
376
439
  if (typeof e === 'string') {
377
440
  return e;
@@ -380,6 +443,21 @@ function stringify(e) {
380
443
  }
381
444
  }
382
445
 
446
+ function _attachHeaderProperties(self, options) {
447
+ // Create headers
448
+ const headers = {
449
+ code: options.code,
450
+ tag: self.tag,
451
+ usage: {
452
+ current: self?.usage?.getUsage() || {},
453
+ limits: self?.usage?.getLimit() || {},
454
+ },
455
+ additional: options.additional || {},
456
+ }
457
+
458
+ // Attach properties
459
+ self.ref.res.header('bm-properties', JSON.stringify(headers));
460
+ }
383
461
 
384
462
  BackendAssistant.prototype.authenticate = async function (options) {
385
463
  const self = this;
@@ -422,7 +500,7 @@ BackendAssistant.prototype.authenticate = async function (options) {
422
500
  // Check with custom BEM Token
423
501
  let storedApiKey;
424
502
  try {
425
- const workingConfig = _.get(self.ref.Manager, 'config') || functions.config();
503
+ const workingConfig = _.get(self.Manager, 'config') || functions.config();
426
504
  storedApiKey = _.get(workingConfig, 'backend_manager.key', '')
427
505
  } catch (e) {
428
506
 
@@ -0,0 +1,70 @@
1
+ /**
2
+ * Middleware
3
+ * Used to handle middleware for the assistant
4
+ */
5
+
6
+ const path = require('path');
7
+
8
+ function Middleware(m) {
9
+ const self = this;
10
+
11
+ self.Manager = m;
12
+ }
13
+
14
+ Middleware.prototype.run = function (library, req, res, options) {
15
+ const self = this;
16
+ const Manager = self.Manager;
17
+ const { cors } = Manager.libraries;
18
+
19
+ return cors(req, res, async () => {
20
+ const assistant = Manager.Assistant({req: req, res: res});
21
+
22
+ const data = assistant.request.data;
23
+ const geolocation = assistant.request.geolocation;
24
+ const client = assistant.request.client;
25
+
26
+ // Set options
27
+ options = options || {};
28
+ options.setupAnalytics = typeof options.setupAnalytics === 'boolean' ? options.setupAnalytics : true;
29
+ options.setupUsage = typeof options.setupUsage === 'boolean' ? options.setupUsage : true;
30
+
31
+ // Log
32
+ assistant.log(`Middleware.process(): Request (${geolocation.ip} @ ${geolocation.country}, ${geolocation.region}, ${geolocation.city})`, JSON.stringify(data));
33
+
34
+ // Load library
35
+ try {
36
+ library = path.resolve(process.cwd(), `${library}.js`);
37
+ library = new (require(library))();
38
+ } catch (e) {
39
+ assistant.errorManager(`Unable to load library @ (${library}): ${e.message}`, {sentry: true, send: true, log: true});
40
+ }
41
+
42
+ // Setup analytics
43
+ if (options.setupAnalytics) {
44
+ assistant.analytics = Manager.Analytics({
45
+ assistant: assistant,
46
+ uuid: assistant.request.geolocation.ip,
47
+ })
48
+ }
49
+
50
+ // Setup usage
51
+ if (options.setupUsage) {
52
+ assistant.usage = await Manager.Usage().init(assistant);
53
+ }
54
+
55
+ // Process
56
+ try {
57
+ library.main(assistant, req, res)
58
+ // .then(result => {
59
+ // return res.status(200).json(result);
60
+ // })
61
+ .catch(e => {
62
+ assistant.errorManager(e, {sentry: true, send: true, log: true});
63
+ });
64
+ } catch (e) {
65
+ assistant.errorManager(e, {sentry: true, send: true, log: true});
66
+ }
67
+ });
68
+ };
69
+
70
+ module.exports = Middleware;
@@ -244,7 +244,11 @@ Usage.prototype.getUsage = function (path) {
244
244
  const Manager = self.Manager;
245
245
  const assistant = self.assistant;
246
246
 
247
- return _.get(self.user, `usage.${path}.period`, 0);
247
+ if (path) {
248
+ return _.get(self.user, `usage.${path}.period`, 0);
249
+ } else {
250
+ return self.user.usage;
251
+ }
248
252
  };
249
253
 
250
254
  Usage.prototype.getLimit = function (path) {
@@ -252,7 +256,13 @@ Usage.prototype.getLimit = function (path) {
252
256
  const Manager = self.Manager;
253
257
  const assistant = self.assistant;
254
258
 
255
- return _.get(self.app, `products.${self.options.app}-${self.user.plan.id}.limits.${path}`, 0);
259
+ const key = `products.${self.options.app}-${self.user.plan.id}.limits`;
260
+
261
+ if (path) {
262
+ return _.get(self.app, `${key}.${path}`, 0);
263
+ } else {
264
+ return _.get(self.app, key, {});
265
+ }
256
266
  };
257
267
 
258
268
  Usage.prototype.update = function () {
@@ -606,6 +606,12 @@ Manager.prototype.Usage = function () {
606
606
  return new self.libraries.Usage(self, ...arguments);
607
607
  };
608
608
 
609
+ Manager.prototype.Middleware = function () {
610
+ const self = this;
611
+ self.libraries.Middleware = self.libraries.Middleware || require('./helpers/middleware.js');
612
+ return new self.libraries.Middleware(self, ...arguments);
613
+ };
614
+
609
615
  Manager.prototype.Settings = function () {
610
616
  const self = this;
611
617
  self.libraries.Settings = self.libraries.Settings || require('./helpers/settings.js');