backend-manager 3.2.169 → 3.2.171

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 (88) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +1 -1
  3. package/dist/cli/cli.js +1534 -0
  4. package/dist/manager/functions/core/actions/api/admin/backup.js +338 -0
  5. package/dist/manager/functions/core/actions/api/admin/create-post.js +388 -0
  6. package/dist/manager/functions/core/actions/api/admin/cron.js +37 -0
  7. package/dist/manager/functions/core/actions/api/admin/database-read.js +35 -0
  8. package/dist/manager/functions/core/actions/api/admin/database-write.js +39 -0
  9. package/dist/manager/functions/core/actions/api/admin/edit-post.js +158 -0
  10. package/dist/manager/functions/core/actions/api/admin/firestore-query.js +165 -0
  11. package/dist/manager/functions/core/actions/api/admin/firestore-read.js +38 -0
  12. package/dist/manager/functions/core/actions/api/admin/firestore-write.js +54 -0
  13. package/dist/manager/functions/core/actions/api/admin/get-stats.js +269 -0
  14. package/dist/manager/functions/core/actions/api/admin/payment-processor.js +57 -0
  15. package/dist/manager/functions/core/actions/api/admin/run-hook.js +95 -0
  16. package/dist/manager/functions/core/actions/api/admin/send-notification.js +197 -0
  17. package/dist/manager/functions/core/actions/api/admin/sync-users.js +125 -0
  18. package/dist/manager/functions/core/actions/api/admin/templates/post.html +16 -0
  19. package/dist/manager/functions/core/actions/api/firebase/get-providers.js +102 -0
  20. package/dist/manager/functions/core/actions/api/general/emails/general:download-app-link.js +21 -0
  21. package/dist/manager/functions/core/actions/api/general/fetch-post.js +99 -0
  22. package/dist/manager/functions/core/actions/api/general/generate-uuid.js +41 -0
  23. package/dist/manager/functions/core/actions/api/general/send-email.js +112 -0
  24. package/dist/manager/functions/core/actions/api/handler/create-post.js +146 -0
  25. package/dist/manager/functions/core/actions/api/special/setup-electron-manager-client.js +103 -0
  26. package/dist/manager/functions/core/actions/api/template.js +33 -0
  27. package/dist/manager/functions/core/actions/api/test/authenticate.js +22 -0
  28. package/dist/manager/functions/core/actions/api/test/create-test-accounts.js +27 -0
  29. package/dist/manager/functions/core/actions/api/test/lab.js +55 -0
  30. package/dist/manager/functions/core/actions/api/test/redirect.js +26 -0
  31. package/dist/manager/functions/core/actions/api/test/webhook.js +30 -0
  32. package/dist/manager/functions/core/actions/api/user/create-custom-token.js +32 -0
  33. package/dist/manager/functions/core/actions/api/user/delete.js +68 -0
  34. package/dist/manager/functions/core/actions/api/user/get-active-sessions.js +45 -0
  35. package/dist/manager/functions/core/actions/api/user/get-subscription-info.js +49 -0
  36. package/dist/manager/functions/core/actions/api/user/oauth2/discord.js +114 -0
  37. package/dist/manager/functions/core/actions/api/user/oauth2/google.js +99 -0
  38. package/dist/manager/functions/core/actions/api/user/oauth2.js +476 -0
  39. package/dist/manager/functions/core/actions/api/user/regenerate-api-keys.js +54 -0
  40. package/dist/manager/functions/core/actions/api/user/resolve.js +32 -0
  41. package/dist/manager/functions/core/actions/api/user/sign-out-all-sessions.js +118 -0
  42. package/dist/manager/functions/core/actions/api/user/sign-up copy.js +544 -0
  43. package/dist/manager/functions/core/actions/api/user/sign-up.js +99 -0
  44. package/dist/manager/functions/core/actions/api/user/submit-feedback.js +96 -0
  45. package/dist/manager/functions/core/actions/api/user/validate-settings.js +86 -0
  46. package/dist/manager/functions/core/actions/api.js +354 -0
  47. package/dist/manager/functions/core/actions/create-post-handler.js +184 -0
  48. package/dist/manager/functions/core/actions/generate-uuid.js +62 -0
  49. package/dist/manager/functions/core/actions/sign-up-handler.js +205 -0
  50. package/dist/manager/functions/core/admin/create-post.js +206 -0
  51. package/dist/manager/functions/core/admin/firestore-write.js +72 -0
  52. package/dist/manager/functions/core/admin/get-stats.js +218 -0
  53. package/dist/manager/functions/core/admin/query.js +198 -0
  54. package/dist/manager/functions/core/admin/send-notification.js +206 -0
  55. package/dist/manager/functions/core/cron/daily/ghostii-auto-publisher.js +377 -0
  56. package/dist/manager/functions/core/cron/daily/reset-usage.js +197 -0
  57. package/dist/manager/functions/core/cron/daily.js +114 -0
  58. package/dist/manager/functions/core/events/auth/before-create.js +124 -0
  59. package/dist/manager/functions/core/events/auth/before-signin.js +62 -0
  60. package/dist/manager/functions/core/events/auth/on-create copy.js +121 -0
  61. package/dist/manager/functions/core/events/auth/on-create.js +564 -0
  62. package/dist/manager/functions/core/events/auth/on-delete.js +72 -0
  63. package/dist/manager/functions/core/events/firestore/on-subscription.js +107 -0
  64. package/dist/manager/functions/test/authenticate.js +38 -0
  65. package/dist/manager/functions/test/create-test-accounts.js +144 -0
  66. package/dist/manager/functions/test/webhook.js +37 -0
  67. package/dist/manager/functions/wrappers/mailchimp/addToList.js +25 -0
  68. package/dist/manager/helpers/analytics copy.js +217 -0
  69. package/dist/manager/helpers/analytics.js +467 -0
  70. package/dist/manager/helpers/api-manager.js +324 -0
  71. package/dist/manager/helpers/assistant.js +1043 -0
  72. package/dist/manager/helpers/metadata.js +32 -0
  73. package/dist/manager/helpers/middleware.js +154 -0
  74. package/dist/manager/helpers/roles.js +69 -0
  75. package/dist/manager/helpers/settings.js +158 -0
  76. package/dist/manager/helpers/subscription-resolver-new.js +828 -0
  77. package/dist/manager/helpers/subscription-resolver.js +842 -0
  78. package/dist/manager/helpers/usage.js +381 -0
  79. package/dist/manager/helpers/user.js +198 -0
  80. package/dist/manager/helpers/utilities.js +292 -0
  81. package/dist/manager/index.js +1076 -0
  82. package/dist/manager/libraries/openai.js +460 -0
  83. package/dist/manager/routes/restart/index.js +52 -0
  84. package/dist/manager/routes/test/index.js +43 -0
  85. package/dist/manager/schemas/restart.js +13 -0
  86. package/dist/manager/schemas/test.js +13 -0
  87. package/dist/require.js +3 -0
  88. package/package.json +19 -9
@@ -0,0 +1,1076 @@
1
+ // Libraries
2
+ const path = require('path');
3
+ const { get, merge } = require('lodash');
4
+ const jetpack = require('fs-jetpack');
5
+ const JSON5 = require('json5');
6
+ const EventEmitter = require('events');
7
+ // const EventEmitter = require('events').EventEmitter;
8
+ const util = require('util');
9
+
10
+ // const { debug, log, error, warn } = require('firebase-functions/lib/logger');
11
+ // let User;
12
+ // let Analytics;
13
+ // Paths
14
+ const core = './functions/core';
15
+ const wrappers = './functions/wrappers';
16
+
17
+ const BEM_CONFIG_TEMPLATE_PATH = path.resolve(__dirname, '../../templates/backend-manager-config.json');
18
+
19
+ function Manager(exporter, options) {
20
+ const self = this;
21
+
22
+ // Constants
23
+ self.SERVER_UUID = '11111111-1111-1111-1111-111111111111';
24
+
25
+ // Modable
26
+ self.libraries = {};
27
+ self.handlers = {};
28
+
29
+ self._internal = {
30
+ storage: {},
31
+ };
32
+
33
+ self.interface = {}
34
+
35
+ // Setup EventEmitter
36
+ EventEmitter.call(self);
37
+
38
+ // Return
39
+ return self;
40
+ }
41
+
42
+ // Inherit from EventEmitter
43
+ util.inherits(Manager, EventEmitter);
44
+
45
+ Manager.prototype.init = function (exporter, options) {
46
+ const self = this;
47
+
48
+ // Set options defaults
49
+ options = options || {};
50
+ options.initialize = typeof options.initialize === 'undefined' ? true : options.initialize;
51
+ options.log = typeof options.log === 'undefined' ? false : options.log;
52
+ options.projectType = typeof options.projectType === 'undefined' ? 'firebase' : options.projectType; // firebase, custom
53
+ options.routes = typeof options.routes === 'undefined' ? '/routes' : options.routes;
54
+ options.schemas = typeof options.schemas === 'undefined' ? '/schemas' : options.schemas;
55
+ options.setupFunctions = typeof options.setupFunctions === 'undefined' ? true : options.setupFunctions;
56
+ options.setupFunctionsLegacy = typeof options.setupFunctionsLegacy === 'undefined' ? false : options.setupFunctionsLegacy;
57
+ options.setupFunctionsIdentity = typeof options.setupFunctionsIdentity === 'undefined' ? true : options.setupFunctionsIdentity;
58
+ options.setupServer = typeof options.setupServer === 'undefined' ? true : options.setupServer;
59
+ options.initializeLocalStorage = typeof options.initializeLocalStorage === 'undefined' ? false : options.initializeLocalStorage;
60
+ options.resourceZone = typeof options.resourceZone === 'undefined' ? 'us-central1' : options.resourceZone;
61
+ options.sentry = typeof options.sentry === 'undefined' ? true : options.sentry;
62
+ options.reportErrorsInDev = typeof options.reportErrorsInDev === 'undefined' ? false : options.reportErrorsInDev;
63
+ options.firebaseConfig = options.firebaseConfig;
64
+ options.useFirebaseLogger = typeof options.useFirebaseLogger === 'undefined' ? true : options.useFirebaseLogger;
65
+ options.serviceAccountPath = typeof options.serviceAccountPath === 'undefined' ? 'service-account.json' : options.serviceAccountPath;
66
+ options.backendManagerConfigPath = typeof options.backendManagerConfigPath === 'undefined' ? 'backend-manager-config.json' : options.backendManagerConfigPath;
67
+ options.fetchStats = typeof options.fetchStats === 'undefined' ? true : options.fetchStats;
68
+ options.checkNodeVersion = typeof options.checkNodeVersion === 'undefined' ? true : options.checkNodeVersion;
69
+ options.uniqueAppName = options.uniqueAppName || undefined;
70
+ options.assistant = options.assistant || {};
71
+ options.cwd = typeof options.cwd === 'undefined' ? process.cwd() : options.cwd;
72
+ options.projectPackageDirectory = typeof options.projectPackageDirectory === 'undefined' ? undefined : options.projectPackageDirectory;
73
+ // options.assistant.optionsLogString = options.assistant.optionsLogString || undefined;
74
+
75
+ // Load libraries
76
+ self.libraries = {
77
+ // Third-party
78
+ functions: options.projectType === 'firebase'
79
+ ? require('firebase-functions')
80
+ : null,
81
+ admin: require('firebase-admin'),
82
+ cors: require('cors')({ origin: true }),
83
+ sentry: null,
84
+
85
+ // First-party
86
+ Assistant: require('./helpers/assistant.js'),
87
+ localDatabase: null,
88
+ User: null,
89
+ Analytics: null,
90
+ };
91
+
92
+ // Set properties
93
+ self.cwd = options.cwd;
94
+ self.rootDirectory = __dirname;
95
+
96
+ // Set options
97
+ self.options = options;
98
+ self.project = options.firebaseConfig || JSON.parse(process.env.FIREBASE_CONFIG || '{}');
99
+ self.project.resourceZone = options.resourceZone;
100
+ self.project.serviceAccountPath = path.resolve(self.cwd, options.serviceAccountPath);
101
+ self.project.backendManagerConfigPath = path.resolve(self.cwd, options.backendManagerConfigPath);
102
+
103
+ // Load package.json
104
+ self.package = resolveProjectPackage(options.projectPackageDirectory || self.cwd);
105
+
106
+ // Load config
107
+ self.config = merge(
108
+ // Load basic config
109
+ merge({}, requireJSON5(BEM_CONFIG_TEMPLATE_PATH, true), requireJSON5(self.project.backendManagerConfigPath, true)),
110
+ // Load ENV config as a fallback
111
+ requireJSON5(path.resolve(self.cwd, '.runtimeconfig.json'), options.projectType === 'firebase'),
112
+ // Finally, load the functions config
113
+ self.libraries.functions
114
+ ? self.libraries.functions.config()
115
+ : {},
116
+ );
117
+
118
+ // Get app ID
119
+ const appId = self.config?.app?.id;
120
+
121
+ // Init assistant
122
+ self.assistant = self.Assistant().init(undefined, options.assistant);
123
+
124
+ // Set more properties (need to wait for assistant to determine if DEV)
125
+ self.project.functionsUrl = self.assistant.isDevelopment()
126
+ ? `http://localhost:5001/${self.project.projectId}/${self.project.resourceZone}`
127
+ : `https://${self.project.resourceZone}-${self.project.projectId}.cloudfunctions.net`;
128
+
129
+ // Set environment
130
+ process.env.ENVIRONMENT = !process.env.ENVIRONMENT
131
+ ? self.assistant.meta.environment
132
+ : process.env.ENVIRONMENT;
133
+
134
+ // Use the working Firebase logger that they disabled for whatever reason
135
+ if (
136
+ process.env.GCLOUD_PROJECT
137
+ && self.assistant.meta.environment !== 'development'
138
+ && options.useFirebaseLogger
139
+ ) {
140
+ // require('firebase-functions/lib/logger/compat'); // Old way
141
+ require('firebase-functions/logger/compat'); // firebase-functions@4 and above?
142
+ }
143
+
144
+ // Handle dev environments
145
+ if (self.assistant.isDevelopment()) {
146
+ const semverMajor = require('semver/functions/major')
147
+ const semverCoerce = require('semver/functions/coerce')
148
+ const semverUsing = semverMajor(semverCoerce(process.versions.node));
149
+ const semverRequired = semverMajor(semverCoerce(self.package?.engines?.node || '0.0.0'));
150
+
151
+ // Fix firebase-tools overwriting console.log
152
+ // https://stackoverflow.com/questions/56026747/firebase-console-log-on-localhost
153
+ if (process.env.GCLOUD_PROJECT) {
154
+ function logFix() {
155
+ console.error(...arguments);
156
+ }
157
+ console.log = logFix;
158
+ console.info = logFix;
159
+ }
160
+
161
+ // Reject if package.json does not exist
162
+ if (semverUsing !== semverRequired) {
163
+ const msg = `Node.js version mismatch: using ${semverUsing} but asked for ${semverRequired}`;
164
+ if (options.checkNodeVersion) {
165
+ self.assistant.error(new Error(msg));
166
+ return process.exit(1);
167
+ } else {
168
+ self.assistant.log(msg);
169
+ }
170
+ }
171
+ }
172
+
173
+ if (options.log) {
174
+ // self.assistant.log('process.env', process.env)
175
+ self.assistant.log('Resolved serviceAccountPath', self.project.serviceAccountPath);
176
+ self.assistant.log('Resolved backendManagerConfigPath', self.project.backendManagerConfigPath);
177
+ }
178
+
179
+ if (!appId) {
180
+ self.assistant.warn('⚠️ Missing config.app.id');
181
+ }
182
+
183
+ // Setup sentry
184
+ if (self.options.sentry) {
185
+ const sentryRelease = `${appId || self.project.projectId}@${self.package.version}`;
186
+ const sentryDSN = self.config?.sentry?.dsn || '';
187
+ // self.assistant.log('Sentry', sentryRelease, sentryDSN);
188
+
189
+ self.libraries.sentry = require('@sentry/node');
190
+ self.libraries.sentry.init({
191
+ dsn: sentryDSN,
192
+ release: sentryRelease,
193
+ beforeSend(event, hint) {
194
+ if (self.assistant.isDevelopment() && !self.options.reportErrorsInDev) {
195
+ self.assistant.error(new Error('[Sentry] Skipping Sentry because we\'re in development'), hint)
196
+ return null;
197
+ }
198
+ event.tags = event.tags || {};
199
+ event.tags['function.name'] = self.assistant.meta.name;
200
+ event.tags['function.type'] = self.assistant.meta.type;
201
+ event.tags['environment'] = self.assistant.meta.environment;
202
+ return event;
203
+ },
204
+ });
205
+ }
206
+
207
+ // Setup options features
208
+ if (self.options.initialize) {
209
+ // Initialize Firebase
210
+ try {
211
+ // Initialize Firebase
212
+ if (process.env.GOOGLE_APPLICATION_CREDENTIALS) {
213
+ self.libraries.initializedAdmin = self.libraries.admin.initializeApp();
214
+ // self.app = self.libraries.initializedAdmin;
215
+ } else {
216
+ const serviceAccount = require(self.project.serviceAccountPath);
217
+ self.libraries.initializedAdmin = self.libraries.admin.initializeApp({
218
+ credential: self.libraries.admin.credential.cert(serviceAccount),
219
+ databaseURL: self.project.databaseURL || `https://${self.project.projectId}.firebaseio.com`,
220
+ }, options.uniqueAppName);
221
+ // self.app = self.libraries.initializedAdmin;
222
+
223
+ const loadedProjectId = serviceAccount.project_id;
224
+ if (!loadedProjectId || !loadedProjectId.includes(appId)) {
225
+ self.assistant.error(`Loaded app may have wrong service account: ${loadedProjectId} =/= ${appId}`);
226
+ }
227
+ }
228
+
229
+ } catch (e) {
230
+ self.assistant.error('Failed to call .initializeApp()', e);
231
+ }
232
+
233
+ // Update firebase settings
234
+ try {
235
+ // Update project config
236
+ self.libraries.admin.auth().projectConfigManager().updateProjectConfig({
237
+ emailPrivacyConfig: {
238
+ enableImprovedEmailPrivacy: true,
239
+ },
240
+ });
241
+ } catch (e) {
242
+ self.assistant.error('Failed to call .updateProjectConfig()', e);
243
+ } finally {
244
+
245
+ }
246
+ // admin.firestore().settings({/* your settings... */ timestampsInSnapshots: true})
247
+ }
248
+
249
+ // Setup main functions
250
+ if (options.projectType === 'firebase' && options.setupFunctions) {
251
+ self.setupFunctions(exporter, options);
252
+ }
253
+
254
+ // Setup custom server
255
+ if (options.projectType === 'custom' && options.setupServer) {
256
+ self.setupCustomServer(exporter, options);
257
+ }
258
+
259
+ // Set dotenv
260
+ try {
261
+ const env = require('dotenv').config();
262
+ } catch (e) {
263
+ self.assistant.error(new Error(`Failed to set up environment variables from .env file: ${e.message}`));
264
+ }
265
+
266
+ // Setup LocalDatabase
267
+ if (options.initializeLocalStorage) {
268
+ self.storage();
269
+ }
270
+
271
+ // Fetch stats
272
+ if (self.assistant.isDevelopment() && options.fetchStats) {
273
+ setTimeout(function () {
274
+ self.assistant.log('Fetching meta/stats...');
275
+ self.libraries.admin
276
+ .firestore().doc('meta/stats')
277
+ .get()
278
+ .then(doc => {
279
+ self.assistant.log('meta/stats', doc.data());
280
+ })
281
+ }, 100);
282
+ }
283
+
284
+ // Send analytics
285
+ self.Analytics({
286
+ assistant: self.assistant,
287
+ uuid: self.SERVER_UUID,
288
+ })
289
+ .event({
290
+ name: 'admin/initialized',
291
+ params: {
292
+ // screen_class: 'MainActivity',
293
+ },
294
+ });
295
+
296
+ // Return
297
+ return self;
298
+ };
299
+
300
+ // HELPERS
301
+ Manager.prototype._process = function (mod, options) {
302
+ const self = this;
303
+
304
+ return new Promise(async function(resolve, reject) {
305
+ const name = mod.assistant.meta.name;
306
+ const hook = self.handlers && self.handlers[name];
307
+ const req = mod.req;
308
+ const res = mod.res;
309
+ let error;
310
+
311
+ function _reject(e, log) {
312
+ if (log) {
313
+ // self.assistant.error(e);
314
+ mod.assistant.respond(e, {code: 500, sentry: true});
315
+ }
316
+ // res.status(500).send(e.message);
317
+ return resolve()
318
+ }
319
+
320
+ // Run pre
321
+ if (hook) {
322
+ await hook(mod, 'pre').catch(e => {error = e});
323
+ }
324
+ if (error) { return _reject(error, true) }
325
+
326
+ // Run main
327
+ await mod.main().catch(e => {error = e});
328
+ if (error) { return _reject(error, false) }
329
+
330
+ // Run post
331
+ if (hook) {
332
+ await hook(mod, 'post').catch(e => {error = e});
333
+ }
334
+ if (error) { return _reject(error, true) }
335
+
336
+ // Fin
337
+ return resolve();
338
+ });
339
+ };
340
+
341
+ Manager.prototype._preProcess = function (mod) {
342
+ const self = this;
343
+ const name = mod.assistant.meta.name;
344
+ return new Promise(async function(resolve, reject) {
345
+ if (self.handlers && self.handlers[name]) {
346
+ let result;
347
+ try {
348
+ result = self.handlers[name](mod)
349
+ } catch (e) {
350
+ mod.assistant.error(e);
351
+ return reject(e);
352
+ }
353
+ if (Promise.resolve(result) == result) {
354
+ result
355
+ .then(r => {
356
+ return resolve(r);
357
+ })
358
+ .catch(e => {
359
+ mod.assistant.error(e);
360
+ return reject(e);
361
+ })
362
+ } else {
363
+ return resolve(result);
364
+ }
365
+ } else {
366
+ return resolve(null);
367
+ }
368
+ });
369
+ };
370
+
371
+ // Manager.prototype.Assistant = function(ref, options) {
372
+ // const self = this;
373
+ // ref = ref || {};
374
+ // options = options || {};
375
+ // return (new self.libraries.Assistant()).init({
376
+ // req: ref.req,
377
+ // res: ref.res,
378
+ // admin: self.libraries.admin,
379
+ // functions: self.libraries.functions,
380
+ // }, {
381
+ // accept: options.accept,
382
+ // })
383
+ // };
384
+
385
+ Manager.prototype.Assistant = function(ref, options) {
386
+ const self = this;
387
+
388
+ // Set options defaults
389
+ ref = ref || {};
390
+ options = options || {};
391
+
392
+ // Create assistant instance
393
+ return (new self.libraries.Assistant()).init({
394
+ req: ref.req,
395
+ res: ref.res,
396
+ admin: self.libraries.admin,
397
+ functions: self.libraries.functions,
398
+ Manager: self,
399
+ }, options)
400
+ };
401
+
402
+ Manager.prototype.User = function () {
403
+ const self = this;
404
+ self.libraries.User = self.libraries.User || require('./helpers/user.js');
405
+ return new self.libraries.User(self, ...arguments);
406
+ };
407
+
408
+ Manager.prototype.Analytics = function () {
409
+ const self = this;
410
+ self.libraries.Analytics = self.libraries.Analytics || require('./helpers/analytics.js');
411
+ return new self.libraries.Analytics(self, ...arguments);
412
+ };
413
+
414
+ Manager.prototype.ApiManager = function () {
415
+ const self = this;
416
+ self.libraries.ApiManager = self.libraries.ApiManager || require('./helpers/api-manager.js');
417
+ return new self.libraries.ApiManager(self, ...arguments);
418
+ };
419
+
420
+ Manager.prototype.Roles = function () {
421
+ const self = this;
422
+ self.libraries.Roles = self.libraries.Roles || require('./helpers/roles.js');
423
+ return new self.libraries.Roles(self, ...arguments);
424
+ };
425
+
426
+ Manager.prototype.SubscriptionResolver = function () {
427
+ const self = this;
428
+ self.libraries.SubscriptionResolver = self.libraries.SubscriptionResolver || require('./helpers/subscription-resolver.js');
429
+ return new self.libraries.SubscriptionResolver(self, ...arguments);
430
+ };
431
+
432
+ Manager.prototype.Usage = function () {
433
+ const self = this;
434
+ self.libraries.Usage = self.libraries.Usage || require('./helpers/usage.js');
435
+ return new self.libraries.Usage(self, ...arguments);
436
+ };
437
+
438
+ Manager.prototype.Middleware = function () {
439
+ const self = this;
440
+ self.libraries.Middleware = self.libraries.Middleware || require('./helpers/middleware.js');
441
+ return new self.libraries.Middleware(self, ...arguments);
442
+ };
443
+
444
+ Manager.prototype.Settings = function () {
445
+ const self = this;
446
+ self.libraries.Settings = self.libraries.Settings || require('./helpers/settings.js');
447
+ return new self.libraries.Settings(self, ...arguments);
448
+ };
449
+
450
+ Manager.prototype.Metadata = function () {
451
+ const self = this;
452
+ self.libraries.Metadata = self.libraries.Metadata || require('./helpers/metadata.js');
453
+ return new self.libraries.Metadata(self, ...arguments);
454
+ };
455
+
456
+ // For importing API libraries
457
+ Manager.prototype.Api = function () {
458
+ const self = this;
459
+ // self.libraries.Api = self.libraries.Api || require('./helpers/subscription-resolver.js');
460
+ // return new self.libraries.Api(...arguments);
461
+ // return self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, }))
462
+
463
+ const Api = (new (require(`${core}/actions/api.js`))()).init(self, { req: {}, res: {}, });
464
+
465
+ return Api;
466
+ };
467
+
468
+ // Manager.prototype.Api = function () {
469
+ // const self = this;
470
+ // // self.libraries.Api = self.libraries.Api || require('./helpers/subscription-resolver.js');
471
+ // // return new self.libraries.Api(...arguments);
472
+ // // return self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, }))
473
+ // return new Promise(function(resolve, reject) {
474
+ // const Api = (new (require(`${core}/actions/api.js`))()).init(self, { req: {}, res: {}, });
475
+
476
+ // Api.main()
477
+
478
+ // return Api;
479
+ // });
480
+ // };
481
+
482
+ // Manager.prototype.Utilities = function () {
483
+ // const self = this;
484
+ // self.libraries.Utilities = self.libraries.Utilities || require('./helpers/utilities.js');
485
+ // return new self.libraries.Utilities(self, ...arguments);
486
+ // };
487
+
488
+ Manager.prototype.Utilities = function () {
489
+ const self = this;
490
+
491
+ if (!self._internal.utilities) {
492
+ self.libraries.Utilities = require('./helpers/utilities.js');
493
+ self._internal.utilities = new self.libraries.Utilities(self, ...arguments);
494
+ }
495
+
496
+ return self._internal.utilities;
497
+ };
498
+
499
+ Manager.prototype.storage = function (options) {
500
+ const self = this;
501
+ options = options || {};
502
+ options.name = options.name || 'main';
503
+
504
+ if (!self._internal.storage[options.name]) {
505
+ options.temporary = typeof options.temporary === 'undefined' ? false : options.temporary;
506
+ options.clear = typeof options.clear === 'undefined' ? true : options.clear;
507
+ options.log = typeof options.log === 'undefined' ? false : options.log;
508
+
509
+ // Set path
510
+ const subfolder = `storage/${self.options.uniqueAppName || 'primary'}/${options.name}`;
511
+
512
+ // Setup lowdb
513
+ const low = require('lowdb');
514
+ const FileSync = require('lowdb/adapters/FileSync');
515
+ const location = options.temporary
516
+ ? `${require('os').tmpdir()}/${subfolder}.json`
517
+ : `./.data/${subfolder}.json`;
518
+ const adapter = new FileSync(location);
519
+
520
+ // Log
521
+ if (options.log) {
522
+ self.assistant.log('storage(): Location', location);
523
+ }
524
+
525
+ // Clear temporary storage
526
+ if (
527
+ options.temporary
528
+ && self.assistant.isDevelopment()
529
+ && options.clear
530
+ ) {
531
+ self.assistant.log('Removed temporary file @', location);
532
+ jetpack.remove(location);
533
+ }
534
+
535
+ // Setup options
536
+ options.clearInvalid = typeof options.clearInvalid === 'undefined'
537
+ ? true
538
+ : options.clearInvalid;
539
+
540
+ function _setup() {
541
+ if (!jetpack.exists(location)) {
542
+ jetpack.write(location, {});
543
+ }
544
+ self._internal.storage[options.name] = low(adapter);
545
+
546
+ self._internal.storage[options.name].set('_location', location)
547
+ }
548
+
549
+ try {
550
+ _setup()
551
+ } catch (e) {
552
+ self.assistant.error(`Could not setup storage: ${location}`, e);
553
+
554
+ try {
555
+ if (options.clearInvalid) {
556
+ self.assistant.log(`Clearing invalid storage: ${location}`);
557
+ jetpack.write(location, {});
558
+ }
559
+ _setup()
560
+ } catch (e) {
561
+ self.assistant.error(`Failed to clear invalid storage: ${location}`, e);
562
+ }
563
+ }
564
+ }
565
+
566
+ return self._internal.storage[options.name]
567
+ };
568
+
569
+ Manager.prototype.getCustomServer = function () {
570
+ const self = this;
571
+
572
+ if (!self._internal.server || !self._internal.app) {
573
+ throw new Error('Server not set up');
574
+ }
575
+
576
+ return {
577
+ server: self._internal.server,
578
+ app: self._internal.app,
579
+ };
580
+ };
581
+
582
+ Manager.prototype.install = function (controller, options) {
583
+ const self = this;
584
+
585
+ // Set options defaults
586
+ options = options || {};
587
+ options.prefix = typeof options.prefix === 'undefined' ? null : options.prefix;
588
+ options.dir = typeof options.dir === 'undefined' ? '' : options.dir;
589
+ options.log = typeof options.log === 'undefined' ? false : options.log;
590
+
591
+ // Fix dir
592
+ options.dir = path.resolve(self.cwd, options.dir);
593
+
594
+ // If dir is a single file, install it. if its a directory, install all
595
+ const isDirectory = jetpack.exists(options.dir) === 'dir';
596
+
597
+ if (options.log) {
598
+ self.assistant.log(`Installing from ${options.dir}, prefix=${options.prefix}, isDirectory=${isDirectory}...`);
599
+ }
600
+
601
+ function _install(prefix, file) {
602
+ if (!file.includes('.js')) {return}
603
+ const name = file.replace('.js', '');
604
+ const _prefix = prefix ? `${prefix}_${name}` : name;
605
+
606
+ const fullPath = path.resolve(options.dir, file);
607
+
608
+ if (options.log) {
609
+ self.assistant.log(`Installing ${_prefix} from ${fullPath}...`);
610
+ }
611
+
612
+ controller[`${_prefix}`] = require(fullPath);
613
+ }
614
+
615
+ if (isDirectory) {
616
+ jetpack.list(options.dir)
617
+ .forEach(file => _install(options.prefix, file))
618
+ } else {
619
+ _install(options.prefix, options.dir);
620
+ }
621
+ };
622
+
623
+ Manager.prototype.require = function (p) {
624
+ return require(p);
625
+ };
626
+
627
+ Manager.prototype.debug = function () {
628
+ return {
629
+ throwException: function () {
630
+ throw new Error('TEST_ERROR');
631
+ },
632
+ throwRejection: function () {
633
+ Promise.reject(new Error('TEST_ERROR'));
634
+ }
635
+ }
636
+ }
637
+
638
+ // Setup functions
639
+ Manager.prototype.setupFunctions = function (exporter, options) {
640
+ const self = this;
641
+
642
+ // Log
643
+ if (options.log) {
644
+ self.assistant.log('Setting up Firebase functions...');
645
+ }
646
+
647
+ // Setup functions
648
+ exporter.bm_api =
649
+ self.libraries.functions
650
+ .runWith({memory: '256MB', timeoutSeconds: 60 * 5})
651
+ // TODO: Replace this with new API
652
+ .https.onRequest(async (req, res) => self._process((new (require(`${core}/actions/api.js`))()).init(self, { req: req, res: res, })));
653
+
654
+ // Setup legacy functions
655
+ if (options.setupFunctionsLegacy) {
656
+ exporter.bm_signUpHandler =
657
+ self.libraries.functions
658
+ .runWith({memory: '256MB', timeoutSeconds: 60})
659
+ .https.onRequest(async (req, res) => {
660
+ const Module = require(`${core}/actions/sign-up-handler.js`);
661
+ Module.init(self, { req: req, res: res, });
662
+
663
+ return self._preProcess(Module)
664
+ .then(r => Module.main())
665
+ .catch(e => {
666
+ self.assistant.error(e);
667
+ return res.status(500).send(e.message);
668
+ });
669
+ });
670
+
671
+ // Admin
672
+ exporter.bm_createPost =
673
+ self.libraries.functions
674
+ .runWith({memory: '256MB', timeoutSeconds: 60})
675
+ .https.onRequest(async (req, res) => {
676
+ const Module = require(`${core}/admin/create-post.js`);
677
+ Module.init(self, { req: req, res: res, });
678
+
679
+ return self._preProcess(Module)
680
+ .then(r => Module.main())
681
+ .catch(e => {
682
+ self.assistant.error(e);
683
+ return res.status(500).send(e.message);
684
+ });
685
+ });
686
+
687
+ exporter.bm_firestoreWrite =
688
+ self.libraries.functions
689
+ .runWith({memory: '256MB', timeoutSeconds: 60})
690
+ .https.onRequest(async (req, res) => {
691
+ const Module = require(`${core}/admin/firestore-write.js`);
692
+ Module.init(self, { req: req, res: res, });
693
+
694
+ return self._preProcess(Module)
695
+ .then(r => Module.main())
696
+ .catch(e => {
697
+ self.assistant.error(e);
698
+ return res.status(500).send(e.message);
699
+ });
700
+ });
701
+
702
+ exporter.bm_getStats =
703
+ self.libraries.functions
704
+ .runWith({memory: '256MB', timeoutSeconds: 420})
705
+ .https.onRequest(async (req, res) => {
706
+ const Module = require(`${core}/admin/get-stats.js`);
707
+ Module.init(self, { req: req, res: res, });
708
+
709
+ return self._preProcess(Module)
710
+ .then(r => Module.main())
711
+ .catch(e => {
712
+ self.assistant.error(e);
713
+ return res.status(500).send(e.message);
714
+ });
715
+ });
716
+
717
+ exporter.bm_sendNotification =
718
+ self.libraries.functions
719
+ .runWith({memory: '1GB', timeoutSeconds: 420})
720
+ .https.onRequest(async (req, res) => {
721
+ const Module = require(`${core}/admin/send-notification.js`);
722
+ Module.init(self, { req: req, res: res, });
723
+
724
+ return self._preProcess(Module)
725
+ .then(r => Module.main())
726
+ .catch(e => {
727
+ self.assistant.error(e);
728
+ return res.status(500).send(e.message);
729
+ });
730
+ });
731
+
732
+ exporter.bm_query =
733
+ self.libraries.functions
734
+ .runWith({memory: '256MB', timeoutSeconds: 60})
735
+ .https.onRequest(async (req, res) => {
736
+ const Module = require(`${core}/admin/query.js`);
737
+ Module.init(self, { req: req, res: res, });
738
+
739
+ return self._preProcess(Module)
740
+ .then(r => Module.main())
741
+ .catch(e => {
742
+ self.assistant.error(e);
743
+ return res.status(500).send(e.message);
744
+ });
745
+ });
746
+
747
+ exporter.bm_createPostHandler =
748
+ self.libraries.functions
749
+ .runWith({memory: '256MB', timeoutSeconds: 60})
750
+ .https.onRequest(async (req, res) => {
751
+ const Module = require(`${core}/actions/create-post-handler.js`);
752
+ Module.init(self, { req: req, res: res, });
753
+
754
+ return self._preProcess(Module)
755
+ .then(r => Module.main())
756
+ .catch(e => {
757
+ self.assistant.error(e);
758
+ return res.status(500).send(e.message);
759
+ });
760
+ });
761
+
762
+ exporter.bm_generateUuid =
763
+ self.libraries.functions
764
+ .runWith({memory: '256MB', timeoutSeconds: 60})
765
+ .https.onRequest(async (req, res) => {
766
+ const Module = require(`${core}/actions/generate-uuid.js`);
767
+ Module.init(self, { req: req, res: res, });
768
+
769
+ return self._preProcess(Module)
770
+ .then(r => Module.main())
771
+ .catch(e => {
772
+ self.assistant.error(e);
773
+ return res.status(500).send(e.message);
774
+ });
775
+ });
776
+
777
+ // Test
778
+ exporter.bm_test_authenticate =
779
+ self.libraries.functions
780
+ .runWith({memory: '256MB', timeoutSeconds: 60})
781
+ .https.onRequest(async (req, res) => {
782
+ const Module = require(`${test}/authenticate.js`);
783
+ Module.init(self, { req: req, res: res, });
784
+
785
+ return self._preProcess(Module)
786
+ .then(r => Module.main())
787
+ .catch(e => {
788
+ self.assistant.error(e);
789
+ return res.status(500).send(e.message);
790
+ });
791
+ });
792
+
793
+ exporter.bm_test_createTestAccounts =
794
+ self.libraries.functions
795
+ .runWith({memory: '256MB', timeoutSeconds: 60})
796
+ .https.onRequest(async (req, res) => {
797
+ const Module = require(`${test}/create-test-accounts.js`);
798
+ Module.init(self, { req: req, res: res, });
799
+
800
+ return self._preProcess(Module)
801
+ .then(r => Module.main())
802
+ .catch(e => {
803
+ self.assistant.error(e);
804
+ return res.status(500).send(e.message);
805
+ });
806
+ });
807
+
808
+ exporter.bm_test_webhook =
809
+ self.libraries.functions
810
+ .runWith({memory: '256MB', timeoutSeconds: 60})
811
+ .https.onRequest(async (req, res) => {
812
+ const Module = require(`${test}/webhook.js`);
813
+ Module.init(self, { req: req, res: res, });
814
+
815
+ return self._preProcess(Module)
816
+ .then(r => Module.main())
817
+ .catch(e => {
818
+ self.assistant.error(e);
819
+ return res.status(500).send(e.message);
820
+ });
821
+ });
822
+ }
823
+
824
+ // Setup identity functions
825
+ if (options.setupFunctionsIdentity) {
826
+ exporter.bm_authBeforeCreate =
827
+ self.libraries.functions
828
+ .runWith({memory: '256MB', timeoutSeconds: 60})
829
+ .auth.user()
830
+ .beforeCreate(async (user, context) => self._process((new (require(`${core}/events/auth/before-create.js`))()).init(self, { user: user, context: context})));
831
+
832
+ exporter.bm_authBeforeSignIn =
833
+ self.libraries.functions
834
+ .runWith({memory: '256MB', timeoutSeconds: 60})
835
+ .auth.user()
836
+ .beforeSignIn(async (user, context) => self._process((new (require(`${core}/events/auth/before-signin.js`))()).init(self, { user: user, context: context})));
837
+ }
838
+
839
+ // Setup events
840
+ exporter.bm_authOnCreate =
841
+ self.libraries.functions
842
+ .runWith({memory: '256MB', timeoutSeconds: 60})
843
+ .auth.user()
844
+ .onCreate(async (user, context) => self._process((new (require(`${core}/events/auth/on-create.js`))()).init(self, { user: user, context: context})));
845
+
846
+ exporter.bm_authOnDelete =
847
+ self.libraries.functions
848
+ .runWith({memory: '256MB', timeoutSeconds: 60})
849
+ .auth.user()
850
+ .onDelete(async (user, context) => self._process((new (require(`${core}/events/auth/on-delete.js`))()).init(self, { user: user, context: context})));
851
+
852
+ exporter.bm_subOnWrite =
853
+ self.libraries.functions
854
+ .runWith({memory: '256MB', timeoutSeconds: 60})
855
+ .firestore.document('notifications/subscriptions/all/{token}')
856
+ .onWrite(async (change, context) => self._process((new (require(`${core}/events/firestore/on-subscription.js`))()).init(self, { change: change, context: context, })));
857
+
858
+ // Setup cron jobs
859
+ exporter.bm_cronDaily =
860
+ self.libraries.functions
861
+ .runWith({ memory: '256MB', timeoutSeconds: 60 * 5})
862
+ .pubsub.schedule('every 24 hours')
863
+ .onRun(async (context) => self._process((new (require(`${core}/cron/daily.js`))()).init(self, { context: context, })));
864
+ };
865
+
866
+ // Setup Custom Server
867
+ Manager.prototype.setupCustomServer = function (_library, options) {
868
+ const self = this;
869
+
870
+ // Require
871
+ const glob = require('glob').globSync;
872
+
873
+ // Log
874
+ if (options.log) {
875
+ self.assistant.log('Setting up custom server...');
876
+ }
877
+
878
+ // Setup fastify
879
+ // const app = library({
880
+ // logger: true,
881
+ // // querystringParser: str => querystring.parse(str.toLowerCase())
882
+ // });
883
+
884
+ // Setup express
885
+ const app = require('express')({
886
+ logger: true,
887
+ // querystringParser: str => querystring.parse(str.toLowerCase())
888
+ });
889
+
890
+ // Setup body parser
891
+ app.use(require('body-parser').json());
892
+
893
+ // Designate paths
894
+ const managerRoutesPath = path.normalize(`${__dirname}/routes`);
895
+ const managerSchemasPath = path.normalize(`${__dirname}/schemas`);
896
+ const customRoutesPath = path.normalize(`${self.cwd}${options.routes}`);
897
+ const customSchemasPath = path.normalize(`${self.cwd}${options.schemas}`);
898
+
899
+ // Create routes
900
+ const routes = [];
901
+
902
+ // Push function
903
+ function _push(dir, isManager) {
904
+ // Get all files
905
+ glob('**/index.js', { cwd: dir })
906
+ .forEach((file) => {
907
+ // Build the item
908
+ const item = {
909
+ name: file.replace('/index.js', ''),
910
+ namespace: file,
911
+ path: path.resolve(dir, file),
912
+ dir: dir,
913
+ isManager: isManager,
914
+ }
915
+
916
+ // If it exists in routes, replace it
917
+ const existing = routes.findIndex(r => r.name === item.name);
918
+ if (existing > -1) {
919
+ routes[existing] = item;
920
+ return;
921
+ }
922
+
923
+ // Otherwise, push it
924
+ routes.push(item);
925
+ });
926
+ }
927
+
928
+ // Push routes
929
+ // _push(`${__dirname}/routes`)
930
+ _push(managerRoutesPath, true)
931
+ _push(customRoutesPath, false)
932
+
933
+ // Log routes
934
+ // if (options.log) {
935
+ // self.assistant.log('Routes:', routes);
936
+ // }
937
+
938
+ // Install process
939
+ routes.forEach((file) => {
940
+ // self.assistant.log('---file', file);
941
+ // Require the file
942
+ const cors = self.libraries.cors;
943
+
944
+ // Log
945
+ if (options.log) {
946
+ self.assistant.log(`Initializing route: ${file.name} @ ${file.path}`);
947
+ }
948
+
949
+ // Register the route
950
+ app.all(`/${file.name}`, async (req, res) => {
951
+ return cors(req, res, async () => {
952
+ // self.Middleware(req, res).run(file.name, {schema: file.name})
953
+ self.Middleware(req, res).run(file.name, {
954
+ schema: file.name,
955
+ routesDir: file.isManager ? managerRoutesPath : customRoutesPath,
956
+ schemasDir: file.isManager ? managerSchemasPath : customSchemasPath,
957
+ })
958
+ });
959
+ })
960
+
961
+ // app.all(`/${name}`, async (req, res) => {
962
+ // return cors(req, res, async () => {
963
+ // // Fix req/res
964
+ // req.body = req.body || {};
965
+ // req.query = Object.assign({}, req.query || {});
966
+
967
+ // // Manager.Middleware(req, res).run('tools/screenshot', {schema: 'screenshot'})
968
+ // const handler = new (require(file.path))();
969
+ // const assistant = self.Assistant({req: req, res: res}, {functionName: name, functionType: 'http'});
970
+ // // const apiUser = await ApiManager.getUser(assistant);
971
+
972
+ // // Set handler properties
973
+ // handler.Manager = self;
974
+ // handler.assistant = assistant;
975
+ // handler.apiUser = null;
976
+
977
+ // // Log
978
+ // if (options.log) {
979
+ // self.assistant.log(`[Request] ${name} @ ${filepath}`, req.body, req.query);
980
+ // }
981
+
982
+ // // Execute the route
983
+ // try {
984
+ // await handler.process(req, res);
985
+ // } catch (e) {
986
+ // assistant.respond(e, {code: e.code});
987
+ // }
988
+ // });
989
+ // })
990
+ });
991
+
992
+ // Run the server!
993
+ const server = app.listen({ port: process.env.PORT || 3000, host: '0.0.0.0' }, () => {
994
+ const address = server.address();
995
+
996
+ // Check if there's an error
997
+ if (server.address() === null) {
998
+ self.assistant.error(e);
999
+ process.exit(1);
1000
+ }
1001
+
1002
+ // Log
1003
+ if (options.log) {
1004
+ self.assistant.log(`Server listening on ${address.address}:${address.port}`);
1005
+ }
1006
+
1007
+ // Set server and app to internal
1008
+ self._internal.server = server;
1009
+ self._internal.app = app;
1010
+
1011
+ // Emit event
1012
+ self.emit('online', new Event('online'), server, app);
1013
+ });
1014
+ }
1015
+
1016
+ // Setup Custom Server
1017
+ Manager.prototype.getApp = function (id) {
1018
+ const self = this;
1019
+
1020
+ // Get the app
1021
+ return new Promise(function(resolve, reject) {
1022
+ const fetch = require('wonderful-fetch');
1023
+
1024
+ // Set ID
1025
+ id = id || self.config.app.id;
1026
+
1027
+ // If no ID, reject
1028
+ if (!id) {
1029
+ return reject(new Error('No ID provided'));
1030
+ }
1031
+
1032
+ // Fetch the app
1033
+ fetch(`https://us-central1-itw-creative-works.cloudfunctions.net/getApp`, {
1034
+ method: 'post',
1035
+ response: 'json',
1036
+ timeout: 30000,
1037
+ tries: 3,
1038
+ body: {
1039
+ id: id,
1040
+ }
1041
+ })
1042
+ .then((r) => resolve(r))
1043
+ .catch((e) => reject(e));
1044
+ });
1045
+ }
1046
+
1047
+ function resolveProjectPackage(dir) {
1048
+ try {
1049
+ return require(path.resolve(dir, 'functions', 'package.json'));
1050
+ } catch (e) {}
1051
+
1052
+ try {
1053
+ return require(path.resolve(dir, 'package.json'));
1054
+ } catch (e) {}
1055
+ }
1056
+
1057
+ function requireJSON5(file, throwError) {
1058
+ // Set throwError
1059
+ throwError = typeof throwError === 'undefined' ? true : throwError;
1060
+
1061
+ // Load JSON5
1062
+ try {
1063
+ return JSON5.parse(jetpack.read(file))
1064
+ } catch (e) {
1065
+ // If we're not throwing an error, just return
1066
+ if (!throwError) {
1067
+ return {};
1068
+ }
1069
+
1070
+ // Otherwise, throw the error
1071
+ console.error(`Failed to load JSON at ${file}:`, e);
1072
+ throw e;
1073
+ }
1074
+ }
1075
+
1076
+ module.exports = Manager;