backend-manager 2.1.0 → 2.2.1

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": "2.1.0",
3
+ "version": "2.2.1",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -28,7 +28,7 @@
28
28
  "homepage": "https://itwcreativeworks.com",
29
29
  "dependencies": {
30
30
  "@firebase/rules-unit-testing": "^2.0.2",
31
- "@google-cloud/storage": "^5.19.4",
31
+ "@google-cloud/storage": "^5.20.3",
32
32
  "@sendgrid/mail": "^7.6.2",
33
33
  "@sentry/node": "^6.19.7",
34
34
  "backend-assistant": "^0.0.64",
@@ -37,12 +37,13 @@
37
37
  "cors": "^2.8.5",
38
38
  "dotenv": "^16.0.1",
39
39
  "firebase-admin": "^9.12.0",
40
- "firebase-functions": "^3.21.1",
40
+ "firebase-functions": "^3.21.2",
41
41
  "fs-jetpack": "^4.3.1",
42
42
  "hcaptcha": "^0.1.1",
43
43
  "inquirer": "^8.2.4",
44
44
  "json5": "^2.2.1",
45
45
  "lodash": "^4.17.21",
46
+ "lowdb": "^1.0.0",
46
47
  "mailchimp-api-v3": "^1.15.0",
47
48
  "mocha": "^9.2.2",
48
49
  "moment": "^2.29.3",
@@ -58,11 +59,11 @@
58
59
  "universal-analytics": "^0.5.3",
59
60
  "uuid": "^8.3.2",
60
61
  "wonderful-fetch": "^0.0.5",
61
- "yargs": "^17.5.0"
62
+ "yargs": "^17.5.1"
62
63
  },
63
64
  "files": [
64
65
  "bin/",
65
66
  "src/",
66
67
  "templates/"
67
68
  ]
68
- }
69
+ }
@@ -0,0 +1,105 @@
1
+ const fetch = require('wonderful-fetch');
2
+
3
+ function Module() {
4
+
5
+ }
6
+
7
+ Module.prototype.main = function () {
8
+ const self = this;
9
+ const Manager = self.Manager;
10
+ const Api = self.Api;
11
+ const assistant = self.assistant;
12
+ const payload = self.payload;
13
+
14
+ return new Promise(async function(resolve, reject) {
15
+
16
+ const providers = [
17
+ { name: 'google.com', prefix: ['id_token'] },
18
+ { name: 'facebook.com', prefix: ['access_token'] },
19
+ { name: 'twitter.com', prefix: ['access_token', 'oauth_token_secret'] },
20
+ { name: 'github.com', prefix: ['access_token'] },
21
+ { name: 'microsoft.com', prefix: ['id_token'] },
22
+ // { name: 'microsoft.com', prefix: ['context', 'continueUri', 'sessionId'] },
23
+ { name: 'yahoo.com', prefix: ['id_token'] },
24
+ { name: 'apple.com', prefix: ['id_token'] },
25
+ ]
26
+ const promises = []
27
+
28
+ payload.data.payload.firebaseApiKey = payload.data.payload.firebaseApiKey || false;
29
+
30
+ if (!payload.data.payload.firebaseApiKey) {
31
+ return reject(assistant.errorManager(`The <firebaseApiKey> parameter is required.`, {code: 400, sentry: false, send: false, log: false}).error)
32
+ }
33
+
34
+ function request(provider) {
35
+ return new Promise(function(resolve, reject) {
36
+ let prefix = '';
37
+ provider.prefix
38
+ .forEach((item, i) => {
39
+ prefix += `${item}=LOL&`
40
+ });
41
+
42
+ // https://firebase.google.com/docs/reference/rest/auth#section-sign-in-with-oauth-credential
43
+ fetch(`https://identitytoolkit.googleapis.com/v1/accounts:signInWithIdp?key=${payload.data.payload.firebaseApiKey}`, {
44
+ method: 'post',
45
+ json: true,
46
+ body: {
47
+ postBody: `${prefix}providerId=${provider.name}`,
48
+ requestUri: 'http://localhost',
49
+ returnIdpCredential: true,
50
+ returnSecureToken: true
51
+ }
52
+ })
53
+ .then(response => {
54
+ payload.response.data[provider.name] = true;
55
+ })
56
+ .catch(e => {
57
+ try {
58
+ const errorJson = JSON.parse(e.message);
59
+ const errorArray = errorJson.error.errors || [];
60
+ let result = true;
61
+
62
+ errorArray
63
+ .forEach((error, i) => {
64
+ if (error.message.includes('OPERATION_NOT_ALLOWED') || error.message.includes('INVALID_CREDENTIAL_OR_PROVIDER_ID')) {
65
+ result = false;
66
+ }
67
+ });
68
+
69
+ assistant.log('Provider details', provider.name, result);
70
+
71
+ payload.response.data[provider.name] = result;
72
+ } catch (e) {
73
+ assistant.errorManager(`Error parsing error: ${e}`, {sentry: true, send: false, log: true})
74
+ payload.response.data[provider.name] = false;
75
+ }
76
+ })
77
+ .finally(r => {
78
+ return resolve();
79
+ })
80
+ });
81
+ }
82
+
83
+ providers
84
+ .forEach((provider, i) => {
85
+ payload.response.data[provider.name] = false;
86
+ promises.push(request(provider))
87
+ });
88
+
89
+ assistant.log('Checking providers...', {environment: 'production'});
90
+
91
+ await Promise.all(promises)
92
+ .then(response => {
93
+ // console.log('--payload.response.data', promises.length, payload.response.data);
94
+ return resolve({data: payload.response.data});
95
+ })
96
+ .catch(e => {
97
+ return reject(assistant.errorManager(`Failed to check providers: ${e}`, {code: 500, sentry: false, send: false, log: false}).error)
98
+ })
99
+
100
+ });
101
+
102
+ };
103
+
104
+
105
+ module.exports = Module;
@@ -117,7 +117,8 @@ Module.prototype.main = function () {
117
117
  payload: {
118
118
  title: payload.data.payload.title,
119
119
  body: `"${payload.data.payload.title}" was just published on our blog. It's a great read and we think you'll enjoy the content!`,
120
- click_action: `${Manager.config.brand.url}/${postUrl}`,
120
+ // click_action: `${Manager.config.brand.url}/${postUrl}`,
121
+ click_action: `${Manager.config.brand.url}/blog`,
121
122
  icon: Manager.config.brand.brandmark,
122
123
  }
123
124
  }),
@@ -57,6 +57,8 @@ Module.prototype.main = function() {
57
57
  await lib.main()
58
58
  .then(result => {
59
59
  result = result || {};
60
+ // console.log('---result', result);
61
+ // console.log('---self.payload.response.data', self.payload.response.data);
60
62
  self.payload.response.status = result.status || self.payload.response.status || 200;
61
63
  self.payload.response.data = result.data || self.payload.response.data || {};
62
64
  })
@@ -76,6 +78,7 @@ Module.prototype.main = function() {
76
78
  }
77
79
 
78
80
  if (self.payload.response.status === 200) {
81
+ self.assistant.log(`Finished: ${resolved.command}`, self.payload, JSON.stringify(self.payload), {environment: 'production'})
79
82
  return res.status(self.payload.response.status).json(self.payload.response.data);
80
83
  } else {
81
84
  console.error(`Error executing ${resolved.command} @ ${resolved.path}`, self.payload.response.error)
@@ -29,6 +29,7 @@ Manager.prototype.init = function (exporter, options) {
29
29
  options = options || {};
30
30
  options.initialize = typeof options.initialize === 'undefined' ? true : options.initialize;
31
31
  options.setupFunctions = typeof options.setupFunctions === 'undefined' ? true : options.setupFunctions;
32
+ options.setupLocalDatabase = typeof options.setupLocalDatabase === 'undefined' ? false : options.setupLocalDatabase;
32
33
  options.sentry = typeof options.sentry === 'undefined' ? true : options.sentry;
33
34
  options.reportErrorsInDev = typeof options.reportErrorsInDev === 'undefined' ? false : options.reportErrorsInDev;
34
35
  options.firebaseConfig = options.firebaseConfig;
@@ -40,11 +41,15 @@ Manager.prototype.init = function (exporter, options) {
40
41
 
41
42
  // Load libraries
42
43
  self.libraries = {
44
+ // Third-party
43
45
  functions: require('firebase-functions'),
44
46
  admin: require('firebase-admin'),
45
47
  cors: require('cors')({ origin: true }),
46
- Assistant: require('backend-assistant'),
47
48
  sentry: null,
49
+
50
+ // First-party
51
+ Assistant: require('backend-assistant'),
52
+ localDatabase: null,
48
53
  User: null,
49
54
  Analytics: null,
50
55
  };
@@ -76,23 +81,7 @@ Manager.prototype.init = function (exporter, options) {
76
81
  require('firebase-functions/lib/logger/compat');
77
82
  }
78
83
 
79
- // Setup options features
80
- if (self.options.initialize) {
81
- // console.log('Initializing:', self.project);
82
- try {
83
- // console.log('----self.project.databaseURL', self.project.databaseURL);
84
- self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
85
- credential: self.libraries.admin.credential.cert(
86
- require(path.resolve(self.cwd, options.serviceAccountPath))
87
- ),
88
- databaseURL: self.project.databaseURL,
89
- }, options.uniqueAppName);
90
- } catch (e) {
91
- console.error('Failed to call .initializeApp()', e);
92
- }
93
- // admin.firestore().settings({/* your settings... */ timestampsInSnapshots: true})
94
- }
95
-
84
+ // Setup sentry
96
85
  if (self.options.sentry) {
97
86
  const sentryRelease = `${get(self.config, 'app.id') || self.project.projectId}@${self.package.version}`;
98
87
  const sentryDSN = get(self.config, 'sentry.dsn', '');
@@ -116,6 +105,23 @@ Manager.prototype.init = function (exporter, options) {
116
105
  });
117
106
  }
118
107
 
108
+ // Setup options features
109
+ if (self.options.initialize) {
110
+ // console.log('Initializing:', self.project);
111
+ try {
112
+ // console.log('----self.project.databaseURL', self.project.databaseURL);
113
+ self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
114
+ credential: self.libraries.admin.credential.cert(
115
+ require(path.resolve(self.cwd, options.serviceAccountPath))
116
+ ),
117
+ databaseURL: self.project.databaseURL,
118
+ }, options.uniqueAppName);
119
+ } catch (e) {
120
+ console.error('Failed to call .initializeApp()', e);
121
+ }
122
+ // admin.firestore().settings({/* your settings... */ timestampsInSnapshots: true})
123
+ }
124
+
119
125
  // Main functions
120
126
  if (options.setupFunctions) {
121
127
  exporter.bm_api =
@@ -348,13 +354,30 @@ Manager.prototype.init = function (exporter, options) {
348
354
  }
349
355
 
350
356
  // Set dotenv
351
- // if (self.assistant.meta.environment === 'development') {
357
+ try {
358
+ require('dotenv').config();
359
+ } catch (e) {
360
+ console.error('Failed to set up environment variables from .env file');
361
+ }
362
+
363
+ // Setup LocalDatabase
364
+ if (options.setupLocalDatabase) {
365
+ const low = require('lowdb');
366
+ const FileSync = require('lowdb/adapters/FileSync');
367
+ // const dbPath = path.resolve(process.cwd(), './.data/db.json');
368
+ const dbPath = './.data/db.json';
369
+ const adapter = new FileSync(dbPath);
370
+ const jetpack = require('fs-jetpack');
371
+
352
372
  try {
353
- require('dotenv').config();
373
+ if (!jetpack.exists(dbPath)) {
374
+ jetpack.write(dbPath, {});
375
+ }
376
+ self.libraries.localDatabase = low(adapter);
354
377
  } catch (e) {
355
- console.error('Failed to set up environment variables from .env file');
378
+ console.error('Could not load .data', e);
356
379
  }
357
- // }
380
+ }
358
381
 
359
382
  return self;
360
383
  };
@@ -438,22 +461,46 @@ Manager.prototype.Assistant = function(ref, options) {
438
461
  };
439
462
 
440
463
  Manager.prototype.User = function () {
441
- this.libraries.User = this.libraries.User || require('./helpers/user.js');
442
- return new this.libraries.User(...arguments);
464
+ const self = this;
465
+ self.libraries.User = self.libraries.User || require('./helpers/user.js');
466
+ return new self.libraries.User(...arguments);
443
467
  };
444
468
 
445
469
  Manager.prototype.Analytics = function () {
446
470
  const self = this;
447
- this.libraries.Analytics = this.libraries.Analytics || require('./helpers/analytics.js');
448
- return new this.libraries.Analytics(self, ...arguments);
471
+ self.libraries.Analytics = self.libraries.Analytics || require('./helpers/analytics.js');
472
+ return new self.libraries.Analytics(self, ...arguments);
449
473
  };
450
474
 
451
475
  Manager.prototype.ApiManager = function () {
452
476
  const self = this;
453
- this.libraries.ApiManager = this.libraries.ApiManager || require('./helpers/api-manager.js');
454
- return new this.libraries.ApiManager(self, ...arguments);
477
+ self.libraries.ApiManager = self.libraries.ApiManager || require('./helpers/api-manager.js');
478
+ return new self.libraries.ApiManager(self, ...arguments);
455
479
  };
456
480
 
481
+ // Manager.prototype.LocalDatabase = function () {
482
+ // const self = this;
483
+ // if (!self.libraries.LocalDatabase) {
484
+ // const low = require('lowdb');
485
+ // const FileSync = require('lowdb/adapters/FileSync');
486
+ // // const dbPath = path.resolve(process.cwd(), './.data/db.json');
487
+ // const dbPath = './.data/db.json';
488
+ // const adapter = new FileSync(dbPath);
489
+ // const jetpack = require('fs-jetpack');
490
+ //
491
+ // try {
492
+ // if (!jetpack.exists(dbPath)) {
493
+ // jetpack.write(dbPath, {});
494
+ // }
495
+ // self.localDatabase = low(adapter);
496
+ // } catch (e) {
497
+ // console.error('Could not load .data', e);
498
+ // }
499
+ // }
500
+ // self.libraries.LocalDatabase = self.libraries.LocalDatabase || require('./helpers/api-manager.js');
501
+ // return new self.libraries.LocalDatabase(self, ...arguments);
502
+ // };
503
+
457
504
  Manager.prototype.require = function (p) {
458
505
  return require(p);
459
506
  };