backend-manager 3.2.171 → 3.2.173

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 (87) hide show
  1. package/package.json +5 -5
  2. package/src/cli/cli.js +27 -11
  3. package/dist/cli/cli.js +0 -1534
  4. package/dist/manager/functions/core/actions/api/admin/backup.js +0 -338
  5. package/dist/manager/functions/core/actions/api/admin/create-post.js +0 -388
  6. package/dist/manager/functions/core/actions/api/admin/cron.js +0 -37
  7. package/dist/manager/functions/core/actions/api/admin/database-read.js +0 -35
  8. package/dist/manager/functions/core/actions/api/admin/database-write.js +0 -39
  9. package/dist/manager/functions/core/actions/api/admin/edit-post.js +0 -158
  10. package/dist/manager/functions/core/actions/api/admin/firestore-query.js +0 -165
  11. package/dist/manager/functions/core/actions/api/admin/firestore-read.js +0 -38
  12. package/dist/manager/functions/core/actions/api/admin/firestore-write.js +0 -54
  13. package/dist/manager/functions/core/actions/api/admin/get-stats.js +0 -269
  14. package/dist/manager/functions/core/actions/api/admin/payment-processor.js +0 -57
  15. package/dist/manager/functions/core/actions/api/admin/run-hook.js +0 -95
  16. package/dist/manager/functions/core/actions/api/admin/send-notification.js +0 -197
  17. package/dist/manager/functions/core/actions/api/admin/sync-users.js +0 -125
  18. package/dist/manager/functions/core/actions/api/admin/templates/post.html +0 -16
  19. package/dist/manager/functions/core/actions/api/firebase/get-providers.js +0 -102
  20. package/dist/manager/functions/core/actions/api/general/emails/general:download-app-link.js +0 -21
  21. package/dist/manager/functions/core/actions/api/general/fetch-post.js +0 -99
  22. package/dist/manager/functions/core/actions/api/general/generate-uuid.js +0 -41
  23. package/dist/manager/functions/core/actions/api/general/send-email.js +0 -112
  24. package/dist/manager/functions/core/actions/api/handler/create-post.js +0 -146
  25. package/dist/manager/functions/core/actions/api/special/setup-electron-manager-client.js +0 -103
  26. package/dist/manager/functions/core/actions/api/template.js +0 -33
  27. package/dist/manager/functions/core/actions/api/test/authenticate.js +0 -22
  28. package/dist/manager/functions/core/actions/api/test/create-test-accounts.js +0 -27
  29. package/dist/manager/functions/core/actions/api/test/lab.js +0 -55
  30. package/dist/manager/functions/core/actions/api/test/redirect.js +0 -26
  31. package/dist/manager/functions/core/actions/api/test/webhook.js +0 -30
  32. package/dist/manager/functions/core/actions/api/user/create-custom-token.js +0 -32
  33. package/dist/manager/functions/core/actions/api/user/delete.js +0 -68
  34. package/dist/manager/functions/core/actions/api/user/get-active-sessions.js +0 -45
  35. package/dist/manager/functions/core/actions/api/user/get-subscription-info.js +0 -49
  36. package/dist/manager/functions/core/actions/api/user/oauth2/discord.js +0 -114
  37. package/dist/manager/functions/core/actions/api/user/oauth2/google.js +0 -99
  38. package/dist/manager/functions/core/actions/api/user/oauth2.js +0 -476
  39. package/dist/manager/functions/core/actions/api/user/regenerate-api-keys.js +0 -54
  40. package/dist/manager/functions/core/actions/api/user/resolve.js +0 -32
  41. package/dist/manager/functions/core/actions/api/user/sign-out-all-sessions.js +0 -118
  42. package/dist/manager/functions/core/actions/api/user/sign-up copy.js +0 -544
  43. package/dist/manager/functions/core/actions/api/user/sign-up.js +0 -99
  44. package/dist/manager/functions/core/actions/api/user/submit-feedback.js +0 -96
  45. package/dist/manager/functions/core/actions/api/user/validate-settings.js +0 -86
  46. package/dist/manager/functions/core/actions/api.js +0 -354
  47. package/dist/manager/functions/core/actions/create-post-handler.js +0 -184
  48. package/dist/manager/functions/core/actions/generate-uuid.js +0 -62
  49. package/dist/manager/functions/core/actions/sign-up-handler.js +0 -205
  50. package/dist/manager/functions/core/admin/create-post.js +0 -206
  51. package/dist/manager/functions/core/admin/firestore-write.js +0 -72
  52. package/dist/manager/functions/core/admin/get-stats.js +0 -218
  53. package/dist/manager/functions/core/admin/query.js +0 -198
  54. package/dist/manager/functions/core/admin/send-notification.js +0 -206
  55. package/dist/manager/functions/core/cron/daily/ghostii-auto-publisher.js +0 -377
  56. package/dist/manager/functions/core/cron/daily/reset-usage.js +0 -197
  57. package/dist/manager/functions/core/cron/daily.js +0 -114
  58. package/dist/manager/functions/core/events/auth/before-create.js +0 -124
  59. package/dist/manager/functions/core/events/auth/before-signin.js +0 -62
  60. package/dist/manager/functions/core/events/auth/on-create copy.js +0 -121
  61. package/dist/manager/functions/core/events/auth/on-create.js +0 -564
  62. package/dist/manager/functions/core/events/auth/on-delete.js +0 -72
  63. package/dist/manager/functions/core/events/firestore/on-subscription.js +0 -107
  64. package/dist/manager/functions/test/authenticate.js +0 -38
  65. package/dist/manager/functions/test/create-test-accounts.js +0 -144
  66. package/dist/manager/functions/test/webhook.js +0 -37
  67. package/dist/manager/functions/wrappers/mailchimp/addToList.js +0 -25
  68. package/dist/manager/helpers/analytics copy.js +0 -217
  69. package/dist/manager/helpers/analytics.js +0 -467
  70. package/dist/manager/helpers/api-manager.js +0 -324
  71. package/dist/manager/helpers/assistant.js +0 -1043
  72. package/dist/manager/helpers/metadata.js +0 -32
  73. package/dist/manager/helpers/middleware.js +0 -154
  74. package/dist/manager/helpers/roles.js +0 -69
  75. package/dist/manager/helpers/settings.js +0 -158
  76. package/dist/manager/helpers/subscription-resolver-new.js +0 -828
  77. package/dist/manager/helpers/subscription-resolver.js +0 -842
  78. package/dist/manager/helpers/usage.js +0 -381
  79. package/dist/manager/helpers/user.js +0 -198
  80. package/dist/manager/helpers/utilities.js +0 -292
  81. package/dist/manager/index.js +0 -1076
  82. package/dist/manager/libraries/openai.js +0 -460
  83. package/dist/manager/routes/restart/index.js +0 -52
  84. package/dist/manager/routes/test/index.js +0 -43
  85. package/dist/manager/schemas/restart.js +0 -13
  86. package/dist/manager/schemas/test.js +0 -13
  87. package/dist/require.js +0 -3
package/dist/cli/cli.js DELETED
@@ -1,1534 +0,0 @@
1
- // CLI GUIDE:
2
- // https://www.twilio.com/blog/how-to-build-a-cli-with-node-js
3
- // https://www.npmjs.com/package/@dkundel/create-project
4
-
5
- // https://www.sitepoint.com/javascript-command-line-interface-cli-node-js/
6
- // https://github.com/sitepoint-editors/ginit
7
-
8
- const jetpack = require('fs-jetpack');
9
- const path = require('path');
10
- const chalk = require('chalk');
11
- const _ = require('lodash');
12
- const log = console.log;
13
- const Npm = require('npm-api');
14
- const semver = require('semver');
15
- const inquirer = require('inquirer');
16
- const { spawn, child, exec, fork } = require('child_process');
17
- const JSON5 = require('json5');
18
- const fetch = require('wonderful-fetch');
19
- const argv = require('yargs').argv;
20
- const powertools = require('node-powertools');
21
-
22
- // function parseArgumentsIntoOptions(rawArgs) {
23
- // const args = arg(
24
- // {
25
- // '--git': Boolean,
26
- // '--yes': Boolean,
27
- // '--install': Boolean,
28
- // '-g': '--git',
29
- // '-y': '--yes',
30
- // '-i': '--install',
31
- // },
32
- // {
33
- // argv: rawArgs.slice(2),
34
- // }
35
- // );
36
- // return {
37
- // skipPrompts: args['--yes'] || false,
38
- // git: args['--git'] || false,
39
- // template: args._[0],
40
- // runInstall: args['--install'] || false,
41
- // };
42
- // }
43
-
44
- let bem_giRegex = 'Set in .setup()'
45
- let bem_giRegexOuter = /# BEM>>>(.*\n?)# <<<BEM/sg;
46
- let bem_allRulesRegex = /(\/\/\/---backend-manager---\/\/\/)(.*?)(\/\/\/---------end---------\/\/\/)/sgm;
47
- let bem_allRulesDefaultRegex = /(\/\/\/---default-rules---\/\/\/)(.*?)(\/\/\/---------end---------\/\/\/)/sgm;
48
- let bem_allRulesBackupRegex = /({{\s*?backend-manager\s*?}})/sgm;
49
- let MOCHA_PKG_SCRIPT = 'mocha ../test/ --recursive --timeout=10000';
50
- let NPM_CLEAN_SCRIPT = 'rm -fr node_modules && rm -fr package-lock.json && npm cache clean --force && npm install && npm rb';
51
- let NOFIX_TEXT = chalk.red(`There is no automatic fix for this check.`);
52
- let runtimeconfigTemplate = loadJSON(`${__dirname}/../../templates/runtimeconfig.json`);
53
- let bemConfigTemplate = loadJSON(`${__dirname}/../../templates/backend-manager-config.json`);
54
-
55
- function Main() {
56
- }
57
-
58
- Main.prototype.process = async function (args) {
59
- const self = this;
60
- self.options = {};
61
- self.argv = argv;
62
- self.firebaseProjectPath = process.cwd();
63
- self.firebaseProjectPath = self.firebaseProjectPath.match(/\/functions$/) ? self.firebaseProjectPath.replace(/\/functions$/, '') : self.firebaseProjectPath;
64
- self.testCount = 0;
65
- self.testTotal = 0;
66
- self.default = {};
67
- self.packageJSON = require('../../package.json');
68
- self.default.version = self.packageJSON.version;
69
-
70
- for (var i = 0; i < args.length; i++) {
71
- self.options[args[i]] = true;
72
- }
73
- // console.log(args);
74
- // console.log(options);
75
- if (self.options.v || self.options.version || self.options['-v'] || self.options['-version']) {
76
- console.log(`Backend manager is version: ${self.default.version}`);
77
- }
78
-
79
- // https://gist.github.com/timneutkens/f2933558b8739bbf09104fb27c5c9664
80
- if (self.options.clear) {
81
- process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
82
- console.clear();
83
- process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
84
- }
85
-
86
- // Log CWD
87
- if (self.options.cwd) {
88
- console.log('cwd: ', self.firebaseProjectPath);
89
- }
90
-
91
- // Run setup
92
- if (self.options.setup) {
93
- // console.log(`Running Setup`);
94
- // console.log(`node:`, process.versions.node);
95
- // console.log(`pwd:`, await execute('pwd').catch(e => e));
96
- // console.log(`node:`, await execute('node --version').catch(e => e));
97
- // console.log(`firebase-tools:`, await execute('firebase --version').catch(e => e));
98
- // console.log('');
99
- await cmd_configGet(self).catch(e => log(chalk.red(`Failed to run config:get`)));
100
- await self.setup();
101
- }
102
-
103
- // Install local BEM
104
- if ((self.options.i || self.options.install) && (self.options.local || self.options.dev || self.options.development)) {
105
- await uninstallPkg('backend-manager');
106
- // return await installPkg('file:../../../ITW-Creative-Works/backend-manager');
107
- return await installPkg('file:/Users/ian/Developer/Repositories/ITW-Creative-Works/backend-manager');
108
- }
109
-
110
- // Install live BEM
111
- if ((self.options.i || self.options.install) && (self.options.live || self.options.prod || self.options.production)) {
112
- await uninstallPkg('backend-manager');
113
- return await installPkg('backend-manager');
114
- }
115
-
116
- // Serve firebase
117
- if (self.options.serve) {
118
- if (!self.options.quick && !self.options.q) {
119
- }
120
- await cmd_configGet(self);
121
- await self.setup();
122
-
123
- let port = self.argv.port || _.get(self.argv, '_', [])[1] || '5000';
124
- let ls = spawn(`firebase serve --port ${port}`, {shell: true});
125
-
126
- ls.stdout.on('data', (data) => {
127
- console.log(`${cleanOutput(data)}`);
128
- });
129
- ls.stderr.on('data', (data) => {
130
- console.error(chalk.red(`${cleanOutput(data)}`));
131
- // ls = null;
132
- });
133
- }
134
-
135
- // Get indexes
136
- if (self.options['firestore:indexes:get'] || self.options['firestore:indexes'] || self.options['indexes:get']) {
137
- return await cmd_indexesGet(self, undefined, true);
138
- }
139
-
140
- // Get config
141
- if (self.options['functions:config:get'] || self.options['config:get']) {
142
- return await cmd_configGet(self);
143
- }
144
-
145
- // Set config
146
- if (self.options['functions:config:set'] || self.options['config:set']) {
147
- await cmd_configSet(self);
148
- return await cmd_configGet(self);
149
- }
150
-
151
- // Unset config
152
- if (self.options['functions:config:unset'] || self.options['config:unset'] || self.options['config:delete'] || self.options['config:remove']) {
153
- await cmd_configUnset(self);
154
- return await cmd_configGet(self);
155
- }
156
-
157
- // Get rules
158
- if (self.options['rules:default'] || self.options['rules:getdefault']) {
159
- self.getRulesFile();
160
- console.log(self.default.firestoreRulesWhole.match(bem_allRulesDefaultRegex)[0].replace(' ///', '///'));
161
- return;
162
- }
163
-
164
- // Deploy
165
- if (self.options.deploy) {
166
- await self.setup();
167
-
168
- // Quick check that not using local packages
169
- let deps = JSON.stringify(self.package.dependencies)
170
- let hasLocal = deps.includes('file:');
171
- if (hasLocal) {
172
- log(chalk.red(`Please remove local packages before deploying!`));
173
- return;
174
- }
175
- // let ls = spawn('firebase', ['deploy', '--only', 'functions']);
176
- // let ls = spawn('firebase', ['deploy', '--only', 'functions,firestore:rules']);
177
- let ls = spawn('firebase deploy --only functions,firestore:rules', {shell: true});
178
- ls.stdout.on('data', (data) => {
179
- // console.log(`${cleanOutput(data)}`);
180
- console.log(`${cleanOutput(data)}`);
181
- });
182
- ls.stderr.on('data', (data) => {
183
- console.error(chalk.red(`${cleanOutput(data)}`));
184
- // ls = null;
185
- });
186
- }
187
-
188
- // Test
189
- if (self.options['test']) {
190
- await self.setup();
191
- // firebase emulators:exec --only firestore 'npm test'
192
- // let ls = spawn('firebase', ['emulators:exec', '--only', 'firestore', 'npm test']);
193
- // https://stackoverflow.com/questions/9722407/how-do-you-install-and-run-mocha-the-node-js-testing-module-getting-mocha-co
194
- let ls = spawn(`firebase emulators:exec --only firestore "npx ${MOCHA_PKG_SCRIPT}"`, {shell: true});
195
- ls.stdout.on('data', (data) => {
196
- console.log(`${cleanOutput(data)}`);
197
- });
198
- ls.stderr.on('data', (data) => {
199
- console.error(chalk.red(`${cleanOutput(data)}`));
200
- });
201
- }
202
-
203
- // Clean
204
- if (self.options['clean:npm']) {
205
- // await self.setup();
206
- // firebase emulators:exec --only firestore 'npm test'
207
- let ls = spawn(`${NPM_CLEAN_SCRIPT}`, {shell: true});
208
- ls.stdout.on('data', (data) => {
209
- console.log(`${cleanOutput(data)}`);
210
- });
211
- ls.stderr.on('data', (data) => {
212
- console.error(chalk.red(`${cleanOutput(data)}`));
213
- });
214
- }
215
-
216
- // if (self.options['url']) {
217
- // // await self.setup();
218
- // // firebase emulators:exec --only firestore 'npm test'
219
- // log(self.projectUrl)
220
- // }
221
-
222
- };
223
-
224
- module.exports = Main;
225
-
226
-
227
- Main.prototype.getRulesFile = function () {
228
- const self = this;
229
- self.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `=${self.default.version}-`);
230
- self.default.firestoreRulesCore = self.default.firestoreRulesWhole.match(bem_allRulesRegex)[0];
231
-
232
- self.default.databaseRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/database.rules.json`))).replace('=0.0.0-', `=${self.default.version}-`);
233
- self.default.databaseRulesCore = self.default.databaseRulesWhole.match(bem_allRulesRegex)[0];
234
- };
235
-
236
- Main.prototype.setup = async function () {
237
- const self = this;
238
- let cwd = jetpack.cwd();
239
-
240
- log(chalk.green(`\n---- RUNNING SETUP v${self.default.version} ----`));
241
-
242
- // Load files
243
- self.package = loadJSON(`${self.firebaseProjectPath}/functions/package.json`);
244
- self.firebaseJSON = loadJSON(`${self.firebaseProjectPath}/firebase.json`);
245
- self.firebaseRC = loadJSON(`${self.firebaseProjectPath}/.firebaserc`);
246
- self.runtimeConfigJSON = loadJSON(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`);
247
- self.remoteconfigJSON = loadJSON(`${self.firebaseProjectPath}/remoteconfig.template.json`);
248
- self.projectPackage = loadJSON(`${self.firebaseProjectPath}/package.json`);
249
- self.bemConfigJSON = loadJSON(`${self.firebaseProjectPath}/functions/backend-manager-config.json`);
250
- self.gitignore = jetpack.read(`${self.firebaseProjectPath}/functions/.gitignore`) || '';
251
-
252
- // Check if package exists
253
- if (!hasContent(self.package)) {
254
- log(chalk.red(`Missing functions/package.json :(`));
255
- return;
256
- }
257
-
258
- // Check if we're running from the functions folder
259
- if (!cwd.endsWith('functions') && !cwd.endsWith('functions/')) {
260
- log(chalk.red(`Please run ${chalk.bold('npx bm setup')} from the ${chalk.bold('functions')} folder. Run ${chalk.bold('cd functions')}.`));
261
- return;
262
- }
263
-
264
- // Load the rules files
265
- self.getRulesFile();
266
-
267
- self.default.rulesVersionRegex = new RegExp(`///---version=${self.default.version}---///`)
268
- // bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)).replace(/\./g, '\\.'), 'm' )
269
- bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)), 'm' )
270
-
271
- // tests
272
- self.projectName = self.firebaseRC.projects.default;
273
- self.projectUrl = `https://console.firebase.google.com/project/${self.projectName}`;
274
-
275
- self.bemApiURL = `https://us-central1-${self?.firebaseRC?.projects?.default}.cloudfunctions.net/bm_api?authenticationToken=${self?.runtimeConfigJSON?.backend_manager?.key}`;
276
-
277
- // Log
278
- log(`ID: `, chalk.bold(`${self.projectName}`));
279
- log(`URL:`, chalk.bold(`${self.projectUrl}`));
280
-
281
- if (!self.package || !self.package.engines || !self.package.engines.node) {
282
- throw new Error('Missing <engines.node> in package.json')
283
- }
284
-
285
- // Tests
286
- await self.test('is a firebase project', async function () {
287
- let exists = jetpack.exists(`${self.firebaseProjectPath}/firebase.json`);
288
-
289
- return exists;
290
- }, fix_isFirebase);
291
-
292
- await self.test(`using at least Node.js v${self.packageJSON.engines.node}`, function () {
293
- const engineReqMajor = parseInt(self.packageJSON.engines.node.split('.')[0]);
294
- const engineHasMajor = parseInt(self.package.engines.node.split('.')[0]);
295
- const processMajor = parseInt(process.versions.node.split('.')[0]);
296
-
297
- if (processMajor < engineReqMajor) {
298
- return new Error(`Please use at least version ${engineReqMajor} of Node.js with this project. You need to update your package.json and your .nvmrc file. Then, make sure to run ${chalk.bold(`nvm use ${engineReqMajor}`)}`)
299
- }
300
-
301
- if (engineHasMajor !== engineReqMajor) {
302
- console.log(chalk.yellow(`You are using Node.js version ${processMajor} but this project suggests ${engineReqMajor}.`));
303
- }
304
-
305
- return engineHasMajor >= engineReqMajor;
306
- }, fix_nodeVersion);
307
-
308
- await self.test('.nvmrc file has proper version', async function () {
309
- const engineReqMajor = parseInt(self.packageJSON.engines.node.split('.')[0]);
310
- const nvmrc = parseInt((jetpack.read(`${self.firebaseProjectPath}/functions/.nvmrc`) || '0').trim().replace(/v|\/|\*/g, ''));
311
-
312
- // return nvmrc === `v${self.packageJSON.engines.node}/*`
313
- return nvmrc >= engineReqMajor;
314
- }, fix_nvmrc);
315
-
316
- // await self.test('project level package.json exists', async function () {
317
- // return !!(self.projectPackage && self.projectPackage.version && self.projectPackage.name);
318
- // }, fix_projpackage);
319
-
320
- await self.test('functions level package.json exists', async function () {
321
- return !!self.package && !!self.package.dependencies && !!self.package.devDependencies && !!self.package.version;
322
- }, fix_functionspackage);
323
-
324
- // await self.test('functions level package.json has updated version', async function () {
325
- // return self.package.version === self.projectPackage.version;
326
- // }, fix_packageversion);
327
-
328
- await self.test('using updated firebase-admin', async function () {
329
- let pkg = 'firebase-admin';
330
- // let latest = semver.clean(await getPkgVersion(pkg));
331
- let latest = semver.clean(cleanPackageVersion(self.packageJSON.dependencies['firebase-admin']));
332
- let mine = cleanPackageVersion(self.package.dependencies[pkg] || '0.0.0');
333
- const majorVersionMismatch = ((semver.major(latest) > semver.major(mine)));
334
- let bemv = cleanPackageVersion(self.packageJSON.dependencies[pkg]);
335
- bemPackageVersionWarning(pkg, bemv, latest);
336
-
337
- if (majorVersionMismatch) {
338
- console.log(chalk.red(`Version ${chalk.bold(latest)} of ${chalk.bold(pkg)} available but you must install this manually because it is a major update.`));
339
- }
340
-
341
- return !(semver.gt(latest, mine)) || majorVersionMismatch;
342
- }, fix_fba);
343
-
344
- await self.test('using updated firebase-functions', async function () {
345
- let pkg = 'firebase-functions';
346
- // let latest = semver.clean(await getPkgVersion(pkg));
347
- let latest = semver.clean(cleanPackageVersion(self.packageJSON.dependencies['firebase-functions']));
348
- let mine = cleanPackageVersion(self.package.dependencies[pkg] || '0.0.0');
349
- const majorVersionMismatch = ((semver.major(latest) > semver.major(mine)));
350
- let bemv = cleanPackageVersion(self.packageJSON.dependencies[pkg]);
351
- bemPackageVersionWarning(pkg, bemv, latest);
352
-
353
- if (majorVersionMismatch) {
354
- console.log(chalk.red(`Version ${chalk.bold(latest)} of ${chalk.bold(pkg)} available but you must install this manually because it is a major update.`));
355
- }
356
-
357
- return !(semver.gt(latest, mine)) || majorVersionMismatch;
358
- }, fix_fbf);
359
-
360
- await self.test('using updated backend-manager', async function () {
361
- let pkg = 'backend-manager';
362
- let latest = semver.clean(await getPkgVersion(pkg));
363
- let mine = cleanPackageVersion(self.package.dependencies[pkg] || '0.0.0');
364
- const majorVersionMismatch = !isLocal(mine) && ((semver.major(latest) > semver.major(mine)));
365
-
366
- if (majorVersionMismatch) {
367
- console.log(chalk.red(`Version ${chalk.bold(latest)} of ${chalk.bold(pkg)} available but you must install this manually because it is a major update.`));
368
- }
369
-
370
- return isLocal(mine) || !(semver.gt(latest, mine)) || majorVersionMismatch;
371
- }, fix_bem);
372
-
373
- // await self.test('using updated ultimate-jekyll-poster', async function () {
374
- // let pkg = 'ultimate-jekyll-poster';
375
- // let latest = semver.clean(await getPkgVersion(pkg));
376
- // let mine = (self.package.dependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
377
- // return isLocal(mine) || !(semver.gt(latest, mine));
378
- // }, fix_ujp);
379
-
380
- // await self.test('using updated @firebase/testing', async function () {
381
- // let pkg = '@firebase/testing';
382
- // let latest = semver.clean(await getPkgVersion(pkg));
383
- // let mine = (self.package.devDependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
384
- // return isLocal(mine) || !(semver.gt(latest, mine));
385
- // }, fix_fbTesting);
386
-
387
- // await self.test('using updated mocha', async function () {
388
- // let pkg = 'mocha';
389
- // let latest = semver.clean(await getPkgVersion(pkg));
390
- // let mine = (self.package.devDependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
391
- // return isLocal(mine) || !(semver.gt(latest, mine));
392
- // }, fix_mocha);
393
- await self.test(`has "npm start" script`, function () {
394
- return self.package.scripts.start
395
- }, fix_startScript);
396
-
397
- await self.test(`has "npm dist" script`, function () {
398
- return self.package.scripts.dist
399
- }, fix_distScript);
400
-
401
- await self.test('using proper .runtimeconfig', async function () {
402
- // Set pass
403
- let pass = true;
404
-
405
- // Loop through all the keys in the template
406
- powertools.getKeys(runtimeconfigTemplate).forEach((key) => {
407
- const userValue = _.get(self.runtimeConfigJSON, key, undefined);
408
-
409
- // If the user value is undefined, then we need to set pass to false
410
- if (typeof userValue === 'undefined') {
411
- pass = false;
412
- }
413
- });
414
-
415
- // Return result
416
- return pass;
417
- }, fix_runtimeConfig);
418
-
419
- await self.test('using proper backend-manager-config.json', async function () {
420
- // Set pass
421
- let pass = true;
422
-
423
- // Loop through all the keys in the template
424
- powertools.getKeys(bemConfigTemplate).forEach((key) => {
425
- const userValue = _.get(self.bemConfigJSON, key, undefined);
426
-
427
- // If the user value is undefined, then we need to set pass to false
428
- if (typeof userValue === 'undefined') {
429
- pass = false;
430
- }
431
- });
432
-
433
- // Return result
434
- return pass;
435
- }, fix_bemConfig);
436
-
437
- await self.test('has correct ID in backend-manager-config.json', async function () {
438
- // Check if the project name matches the projectId
439
- if (self.projectName !== self.bemConfigJSON?.firebaseConfig?.projectId) {
440
- console.error(chalk.red('Mismatch between project name and firebaseConfig.projectId in backend-manager-config.json'));
441
- return false;
442
- }
443
-
444
- // Return pass
445
- return true;
446
- }, NOFIX);
447
-
448
- await self.test('has service-account.json', function () {
449
- let exists = jetpack.exists(`${self.firebaseProjectPath}/functions/service-account.json`);
450
- return !!exists;
451
- }, fix_serviceAccount);
452
-
453
- await self.test('has correct .gitignore', function () {
454
- let match = self.gitignore.match(bem_giRegexOuter);
455
- if (!match) {
456
- return false;
457
- } else {
458
- let gitignore = jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
459
- let file = gitignore.match(bem_giRegexOuter) ? RegExp.$1 : 'BAD1';
460
- let file2 = match[0].match(bem_giRegexOuter) ? RegExp.$1 : 'BAD2';
461
- return file === file2;
462
- }
463
- }, fix_gitignore);
464
-
465
- // Check firebase.json fields
466
- await self.test('firestore rules in JSON', () => {
467
- return self.firebaseJSON?.firestore?.rules === 'firestore.rules'
468
- }, fix_firestoreRules);
469
-
470
- await self.test('firestore indexes in JSON', () => {
471
- return self.firebaseJSON?.firestore?.indexes === 'firestore.indexes.json';
472
- }, fix_firestoreIndexes);
473
-
474
- await self.test('realtime rules in JSON', () => {
475
- return self.firebaseJSON?.database?.rules === 'database.rules.json';
476
- }, fix_realtimeRules);
477
-
478
- await self.test('storage rules in JSON', () => {
479
- return self.firebaseJSON?.storage?.rules === 'storage.rules';
480
- }, fix_storageRules);
481
-
482
- await self.test('remoteconfig template in JSON', () => {
483
- if (hasContent(self.remoteconfigJSON)) {
484
- return self.firebaseJSON?.remoteconfig?.template === 'remoteconfig.template.json';
485
- } else {
486
- return self.firebaseJSON?.remoteconfig?.template === '';
487
- }
488
- }, fix_remoteconfigTemplate);
489
-
490
- await self.test('firestore indexes synced', async function () {
491
- const tempPath = '_firestore.indexes.json'
492
- const liveIndexes = await cmd_indexesGet(self, tempPath, false);
493
-
494
- const localIndexes_exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
495
- let localIndexes
496
- if (localIndexes_exists) {
497
- localIndexes = require(`${self.firebaseProjectPath}/firestore.indexes.json`)
498
- }
499
- const equal = _.isEqual(liveIndexes, localIndexes);
500
-
501
- if (localIndexes_exists && !equal) {
502
- console.log(chalk.red(`To fix this...`));
503
- console.log(chalk.red(` - ${chalk.bold('npx bm indexes:get')} to overwrite Firestore's local indexes with the live indexes`));
504
- console.log(chalk.red(' OR'));
505
- console.log(chalk.red(` - ${chalk.bold('firebase deploy --only firestore:indexes')} to replace the live indexes.`));
506
- }
507
-
508
- jetpack.remove(`${self.firebaseProjectPath}/${tempPath}`)
509
-
510
- return !localIndexes_exists || equal
511
- }, fix_indexesSync);
512
-
513
- // await self.test('add roles/datastore.importExportAdmin', async function () {
514
- // const result = await cmd_iamImportExport(self).catch(e => e);
515
- // return !(result instanceof Error);
516
- // }, NOFIX);
517
-
518
- await self.test('set storage lifecycle policy', async function () {
519
- const result = await cmd_setStorageLifecycle(self).catch(e => e);
520
- return !(result instanceof Error);
521
- }, fix_setStoragePolicy);
522
-
523
- // Update actual files
524
- await self.test('update firestore rules file', function () {
525
- const exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.rules`);
526
- const contents = jetpack.read(`${self.firebaseProjectPath}/firestore.rules`) || '';
527
- const containsCore = contents.match(bem_allRulesRegex);
528
- const matchesVersion = contents.match(self.default.rulesVersionRegex);
529
-
530
- return (!!exists && !!containsCore && !!matchesVersion);
531
- }, fix_firestoreRulesFile);
532
-
533
- await self.test('update firestore indexes file', function () {
534
- const exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
535
- return (!!exists);
536
- }, fix_firestoreIndexesFile);
537
-
538
- await self.test('update realtime rules file', function () {
539
- const exists = jetpack.exists(`${self.firebaseProjectPath}/database.rules.json`);
540
- const contents = jetpack.read(`${self.firebaseProjectPath}/database.rules.json`) || '';
541
- const containsCore = contents.match(bem_allRulesRegex);
542
- const matchesVersion = contents.match(self.default.rulesVersionRegex);
543
-
544
- return (!!exists && !!containsCore && !!matchesVersion);
545
- }, fix_realtimeRulesFile);
546
-
547
- await self.test('update storage rules file', function () {
548
- let exists = jetpack.exists(`${self.firebaseProjectPath}/storage.rules`);
549
- return (!!exists);
550
- }, fix_storageRulesFile);
551
-
552
- await self.test('update remoteconfig template file', function () {
553
- let exists = jetpack.exists(`${self.firebaseProjectPath}/remoteconfig.template.json`);
554
- return (!!exists);
555
- }, fix_remoteconfigTemplateFile);
556
-
557
- // Hosting
558
- await self.test('hosting is set to dedicated folder in JSON', function () {
559
- let hosting = _.get(self.firebaseJSON, 'hosting', {});
560
- return (hosting.public && (hosting.public === 'public' || hosting.public !== '.'))
561
- }, fix_firebaseHostingFolder);
562
-
563
- // Hosting
564
- // await self.test('hosting has auth page', async function () {
565
- // return await fix_firebaseHostingAuth(self);
566
- // }, NOFIX);
567
-
568
- await self.test('update backend-manager-tests.js', function () {
569
- jetpack.write(`${self.firebaseProjectPath}/test/backend-manager-tests.js`,
570
- (jetpack.read(path.resolve(`${__dirname}/../../templates/backend-manager-tests.js`)))
571
- )
572
- return true;
573
- }, NOFIX);
574
-
575
- await self.test('create public .html files', function () {
576
- const options = {url: self.bemConfigJSON.brand.url}
577
- // index.html
578
- const templateIndex = jetpack.read(path.resolve(`${__dirname}/../../templates/public/index.html`));
579
- jetpack.write(`${self.firebaseProjectPath}/public/index.html`,
580
- powertools.template(templateIndex, options)
581
- )
582
-
583
- // 404.html
584
- const template404 = jetpack.read(path.resolve(`${__dirname}/../../templates/public/404.html`));
585
- jetpack.write(`${self.firebaseProjectPath}/public/404.html`,
586
- powertools.template(template404, options)
587
- )
588
- return true;
589
- }, NOFIX);
590
-
591
- // await self.test('add roles/datastore.importExportAdmin', function () {
592
- // const result = await cmd_iamImportExport(self);
593
- // console.log('---result', result);
594
- // return true;
595
- // }, NOFIX);
596
-
597
- // await self.test('has mocha package.json script', function () {
598
- // let script = _.get(self.package, 'scripts.test', '')
599
- // return script === MOCHA_PKG_SCRIPT;
600
- // }, fix_mochaScript);
601
-
602
- // await self.test('has clean:npm package.json script', function () {
603
- // let script = _.get(self.package, 'scripts.clean:npm', '')
604
- // return script === NPM_CLEAN_SCRIPT;
605
- // }, fix_cleanNpmScript);
606
-
607
-
608
-
609
-
610
- if (self.package.dependencies['backend-manager'].includes('file:')) {
611
- console.log('\n' + chalk.yellow(chalk.bold('Warning: ') + 'You are using the local ' + chalk.bold('backend-manager')));
612
- } else {
613
- console.log('\n');
614
- }
615
-
616
- const statsFetchResult = await fetch(self.bemApiURL, {
617
- method: 'post',
618
- timeout: 30000,
619
- response: 'json',
620
- body: {
621
- command: 'admin:get-stats',
622
- },
623
- })
624
- .then(json => json)
625
- .catch(e => e);
626
-
627
- if (statsFetchResult instanceof Error) {
628
- if (!statsFetchResult.message.includes('network timeout')) {
629
- console.log(chalk.yellow(`Ran into error while fetching stats endpoint`, statsFetchResult));
630
- }
631
- } else {
632
- // console.log(chalk.green(`Stats fetched/created properly.`, JSON.stringify(statsFetchResult)));
633
- console.log(chalk.green(`Stats fetched/created properly.`));
634
- }
635
-
636
- console.log(chalk.green(`Checks finished. Passed ${self.testCount}/${self.testTotal} tests.`));
637
- if (self.testCount !== self.testTotal) {
638
- console.log(chalk.yellow(`You should continue to run ${chalk.bold('npx bm setup')} until you pass all tests and fix all errors.`));
639
- }
640
-
641
- // Notify parent that finished with test results
642
- if (process.send) {
643
- process.send({
644
- sender: 'electron-manager',
645
- command: 'setup:complete',
646
- payload: {
647
- passed: self.testCount === self.testTotal,
648
- }
649
- });
650
- }
651
-
652
- return;
653
-
654
- };
655
-
656
- Main.prototype.test = async function(name, fn, fix, args) {
657
- const self = this;
658
- let status;
659
- let passed = await fn();
660
- return new Promise(async function(resolve, reject) {
661
- if (passed instanceof Error) {
662
- log(chalk.red(passed));
663
- process.exit(0);
664
- } else if (passed) {
665
- status = chalk.green('passed');
666
- self.testCount++;
667
- self.testTotal++;
668
- } else {
669
- status = chalk.red('failed');
670
- self.testTotal++;
671
- }
672
- log(chalk.bold(`[${self.testTotal}]`), `${name}:`, status);
673
- if (!passed) {
674
- log(chalk.yellow(`Fixing...`));
675
- fix(self, args)
676
- .then(function (result) {
677
- log(chalk.green(`...done~!`));
678
- resolve();
679
- })
680
- } else {
681
- resolve();
682
- }
683
- });
684
- }
685
-
686
- function cleanPackageVersion(v) {
687
- return v.replace('^', '').replace('~', '');
688
- }
689
-
690
- // FIXES
691
- function NOFIX() {
692
- return new Promise(function(resolve, reject) {
693
- log(NOFIX_TEXT);
694
- reject();
695
- });
696
- }
697
-
698
- function bemPackageVersionWarning(package, current, latest) {
699
- if (semver.gt(latest, current)) {
700
- log(chalk.yellow(`${package} needs to be updated in backend-manager: ${current} => ${latest}`));
701
- }
702
- }
703
-
704
- async function fix_runtimeConfig(self) {
705
- return new Promise(function(resolve, reject) {
706
- // Log
707
- log(NOFIX_TEXT);
708
- log(chalk.red(`You need to run ${chalk.bold(`npx bm config:set`)} for each of these keys:`));
709
-
710
- // Log what keys are missing
711
- powertools.getKeys(runtimeconfigTemplate).forEach((key) => {
712
- const userValue = _.get(self.runtimeConfigJSON, key, undefined);
713
-
714
- if (typeof userValue === 'undefined') {
715
- log(chalk.red.bold(`${key}`));
716
- } else {
717
- log(chalk.red(`${key} (${userValue})`));
718
- }
719
- });
720
-
721
- // Reject
722
- reject();
723
- });
724
- };
725
-
726
- async function fix_bemConfig(self) {
727
- return new Promise(function(resolve, reject) {
728
- // Log
729
- log(NOFIX_TEXT);
730
- log(chalk.red(`You need to open backend-manager-config.json and set each of these keys:`));
731
-
732
- // Write if it doesnt exist
733
- if (!hasContent(self.bemConfigJSON)) {
734
- // jetpack.write(`${self.firebaseProjectPath}/functions/backend-manager-config.json`, bemConfigTemplate)
735
- jetpack.write(`${self.firebaseProjectPath}/functions/backend-manager-config.json`, {})
736
- }
737
-
738
- // Log what keys are missing
739
- powertools.getKeys(bemConfigTemplate).forEach((key) => {
740
- const userValue = _.get(self.bemConfigJSON, key, undefined);
741
-
742
- if (typeof userValue === 'undefined') {
743
- log(chalk.red.bold(`${key}`));
744
- } else {
745
- log(chalk.red(`${key} (${userValue})`));
746
- }
747
- });
748
-
749
- // Reject
750
- reject();
751
- });
752
- };
753
-
754
- async function fix_serviceAccount(self) {
755
- return new Promise(function(resolve, reject) {
756
- log(NOFIX_TEXT);
757
- log(chalk.red(`Please install a service account --> ` + chalk.yellow.red(`${self.projectUrl}/settings/serviceaccounts/adminsdk`)));
758
- reject();
759
- });
760
- };
761
-
762
- // function fix_mochaScript(self) {
763
- // return new Promise(function(resolve, reject) {
764
- // _.set(self.package, 'scripts.test', MOCHA_PKG_SCRIPT);
765
- // jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
766
- // resolve();
767
- // });
768
- // }
769
-
770
- function fix_startScript(self) {
771
- return new Promise(function(resolve, reject) {
772
- _.set(self.package, 'scripts.start', 'firebase serve');
773
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
774
- resolve();
775
- });
776
- }
777
-
778
- function fix_distScript(self) {
779
- return new Promise(function(resolve, reject) {
780
- _.set(self.package, 'scripts.dist', 'firebase deploy');
781
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
782
- resolve();
783
- });
784
- }
785
-
786
- function fix_setupScript(self) {
787
- return new Promise(function(resolve, reject) {
788
- _.set(self.package, 'scripts.setup', 'npx bm setup');
789
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
790
- resolve();
791
- });
792
- }
793
-
794
- function fix_nodeVersion(self) {
795
- return new Promise(function(resolve, reject) {
796
- if (false) {
797
- _.set(self.package, 'engines.node', self.packageJSON.engines.node)
798
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
799
-
800
- resolve();
801
- }
802
-
803
- throw new Error('Please manually fix your outdated Node.js version')
804
- });
805
- };
806
-
807
- function fix_nvmrc(self) {
808
- return new Promise(function(resolve, reject) {
809
- var v = self.packageJSON.engines.node;
810
-
811
- jetpack.write(`${self.firebaseProjectPath}/functions/.nvmrc`, `v${v}/*`);
812
-
813
- log(chalk.red(`Please run ${chalk.bold(`nmv use ${v}`)} to use the correct version of Node.js`));
814
-
815
- throw '';
816
- });
817
- };
818
-
819
- async function fix_isFirebase(self) {
820
- log(chalk.red(`This is not a firebase project. Please use ${chalk.bold('firebase-init')} to set up.`));
821
- throw '';
822
- };
823
-
824
- function fix_projpackage(self) {
825
- return new Promise(function(resolve, reject) {
826
- self.projectPackage = self.projectPackage || {};
827
- self.projectPackage.name = self.projectPackage.name || self.projectName;
828
- self.projectPackage.version = self.projectPackage.version || '0.0.1';
829
- self.projectPackage.dependencies = self.projectPackage.dependencies || {};
830
- self.projectPackage.devDependencies = self.projectPackage.devDependencies || {};
831
-
832
- jetpack.write(`${self.firebaseProjectPath}/package.json`, JSON.stringify(self.projectPackage, null, 2) );
833
- resolve();
834
- });
835
- };
836
-
837
- function fix_functionspackage(self) {
838
- return new Promise(function(resolve, reject) {
839
- self.package.dependencies = self.package.dependencies || {};
840
- self.package.devDependencies = self.package.devDependencies || {};
841
- self.package.version = self.package.version || '0.0.1';
842
-
843
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
844
- resolve();
845
- });
846
- };
847
-
848
- function fix_packageversion(self) {
849
- return new Promise(function(resolve, reject) {
850
- self.package.version = self.projectPackage.version;
851
-
852
- jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
853
- resolve();
854
- });
855
- };
856
-
857
- async function fix_fbf(self) {
858
- // console.log('----FIX FBF'); return Promise.resolve();
859
- return await installPkg('firebase-functions', `@${self.packageJSON.dependencies['firebase-functions']}`)
860
- };
861
- async function fix_fba(self) {
862
- // console.log('----FIX FBA'); return Promise.resolve();
863
- return await installPkg('firebase-admin', `@${self.packageJSON.dependencies['firebase-admin']}`)
864
- };
865
- async function fix_bem(self) {
866
- await installPkg('backend-manager');
867
-
868
- console.log(chalk.green(`Process has exited since a new version of backend-manager was installed. Run ${chalk.bold('npx bm setup')} again.`));
869
- process.exit(0);
870
-
871
- return;
872
- };
873
-
874
- // async function fix_ujp(self) {
875
- // return await installPkg('ultimate-jekyll-poster')
876
- // };
877
- // async function fix_fbTesting(self) {
878
- // return await installPkg('@firebase/testing', '', '--save-dev')
879
- // };
880
- // async function fix_mocha(self) {
881
- // return await installPkg('mocha', '', '--save-dev')
882
- // };
883
-
884
- function fix_gitignore(self) {
885
- return new Promise(function(resolve, reject) {
886
- let gi = (jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)));
887
- if (self.gitignore.match(bem_giRegexOuter)) {
888
- self.gitignore = self.gitignore.replace(bem_giRegexOuter, gi);
889
- } else {
890
- self.gitignore = gi;
891
- }
892
- self.gitignore = self.gitignore.replace(/\n\s*\n$/mg, '\n')
893
- // self.gitignore = `${self.gitignore}\n${gi}`.replace(/$\n/m,'');
894
- // self.gitignore = self.gitignore.replace(/$\n/m,'');
895
- jetpack.write(`${self.firebaseProjectPath}/functions/.gitignore`, self.gitignore);
896
- resolve();
897
- });
898
- };
899
-
900
- function fix_firestoreRules(self) {
901
- return new Promise(function(resolve, reject) {
902
- _.set(self.firebaseJSON, 'firestore.rules', 'firestore.rules')
903
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
904
- resolve();
905
- });
906
- };
907
-
908
- function fix_firestoreIndexes(self) {
909
- return new Promise(function(resolve, reject) {
910
- _.set(self.firebaseJSON, 'firestore.indexes', 'firestore.indexes.json')
911
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
912
- resolve();
913
- });
914
- };
915
-
916
- function fix_realtimeRules(self) {
917
- return new Promise(function(resolve, reject) {
918
- _.set(self.firebaseJSON, 'database.rules', 'database.rules.json')
919
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
920
- resolve();
921
- });
922
- };
923
-
924
- function fix_storageRules(self) {
925
- return new Promise(function(resolve, reject) {
926
- _.set(self.firebaseJSON, 'storage.rules', 'storage.rules')
927
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
928
- resolve();
929
- });
930
- };
931
-
932
- function fix_remoteconfigTemplate(self) {
933
- return new Promise(function(resolve, reject) {
934
-
935
- _.set(self.firebaseJSON, 'remoteconfig.template', hasContent(self.remoteconfigJSON) ? 'remoteconfig.template.json' : '')
936
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
937
- resolve();
938
- });
939
- };
940
-
941
- function fix_indexesSync(self) {
942
- return new Promise(function(resolve, reject) {
943
- inquirer.prompt([
944
- {
945
- type: 'confirm',
946
- name: 'replace',
947
- message: 'Would you like to replace the local indexes?',
948
- default: true,
949
- }
950
- ])
951
- .then(async (answer) => {
952
- if (answer.replace) {
953
- cmd_indexesGet(self, undefined, true)
954
- .then(r => {
955
- return resolve();
956
- })
957
- } else {
958
- return reject();
959
- }
960
- })
961
- });
962
- };
963
-
964
- function fix_setStoragePolicy(self) {
965
- return new Promise(function(resolve, reject) {
966
- // fetch(self.bemApiURL, {
967
- // method: 'post',
968
- // timeout: 30000,
969
- // response: 'json',
970
- // body: {
971
- // command: 'admin:backup',
972
- // },
973
- // })
974
- // .then(json => {
975
- // console.log('Response', json);
976
- // return resolve();
977
- // })
978
- // .catch(e => {
979
- // console.error(chalk.red(`There is no automatic fix. Please run: \n${chalk.bold('firebase deploy && npx bm setup')}`));
980
- // return reject();
981
- // });
982
- // Log
983
- console.error(chalk.red(`There is no automatic fix. Please run: \n${chalk.bold('firebase deploy && npx bm setup')}`));
984
-
985
- // Reject
986
- return reject();
987
- });
988
- };
989
-
990
- function fix_firestoreRulesFile(self) {
991
- return new Promise(function(resolve, reject) {
992
- const name = 'firestore.rules'
993
- let path = `${self.firebaseProjectPath}/${name}`;
994
- let exists = jetpack.exists(path);
995
- let contents = jetpack.read(path) || '';
996
-
997
- if (!exists || !contents) {
998
- log(chalk.yellow(`Writing new ${name} file...`));
999
- jetpack.write(path, self.default.firestoreRulesWhole)
1000
- contents = jetpack.read(path) || '';
1001
- }
1002
-
1003
- let hasTemplate = contents.match(bem_allRulesRegex) || contents.match(bem_allRulesBackupRegex);
1004
-
1005
- if (!hasTemplate) {
1006
- log(chalk.red(`Could not find rules template. Please edit ${name} file and add`), chalk.red(`{{backend-manager}}`), chalk.red(`to it.`));
1007
- return resolve()
1008
- }
1009
-
1010
- let matchesVersion = contents.match(self.default.rulesVersionRegex);
1011
- if (!matchesVersion) {
1012
- // console.log('replace wih', self.default.firestoreRulesCore);
1013
- contents = contents.replace(bem_allRulesBackupRegex, self.default.firestoreRulesCore)
1014
- contents = contents.replace(bem_allRulesRegex, self.default.firestoreRulesCore)
1015
- jetpack.write(path, contents)
1016
- log(chalk.yellow(`Writing core rules to ${name} file...`));
1017
- }
1018
- resolve();
1019
- });
1020
- };
1021
-
1022
- function fix_realtimeRulesFile(self) {
1023
- return new Promise(function(resolve, reject) {
1024
- const name = 'database.rules.json'
1025
- let path = `${self.firebaseProjectPath}/${name}`;
1026
- let exists = jetpack.exists(path);
1027
- let contents = jetpack.read(path) || '';
1028
-
1029
- if (!exists || !contents) {
1030
- log(chalk.yellow(`Writing new ${name} file...`));
1031
- jetpack.write(path, self.default.databaseRulesWhole)
1032
- contents = jetpack.read(path) || '';
1033
- }
1034
-
1035
- let hasTemplate = contents.match(bem_allRulesRegex) || contents.match(bem_allRulesBackupRegex);
1036
-
1037
- if (!hasTemplate) {
1038
- log(chalk.red(`Could not find rules template. Please edit ${name} file and add`), chalk.red(`{{backend-manager}}`), chalk.red(`to it.`));
1039
- return resolve()
1040
- }
1041
-
1042
- let matchesVersion = contents.match(self.default.rulesVersionRegex);
1043
- if (!matchesVersion) {
1044
- // console.log('replace wih', self.default.databaseRulesCore);
1045
- contents = contents.replace(bem_allRulesBackupRegex, self.default.databaseRulesCore)
1046
- contents = contents.replace(bem_allRulesRegex, self.default.databaseRulesCore)
1047
- jetpack.write(path, contents)
1048
- log(chalk.yellow(`Writing core rules to ${name} file...`));
1049
- }
1050
- resolve();
1051
- });
1052
- };
1053
-
1054
- // function fix_realtimeRulesFile(self) {
1055
- // return new Promise(function(resolve, reject) {
1056
- // const name = 'database.rules.json';
1057
- // let filePath = `${self.firebaseProjectPath}/${name}`;
1058
- // let exists = jetpack.exists(filePath);
1059
- // let contents = jetpack.read(filePath) || '';
1060
- //
1061
- // if (!exists) {
1062
- // log(chalk.yellow(`Writing new ${name} file...`));
1063
- // jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
1064
- // contents = jetpack.read(filePath) || '';
1065
- // }
1066
- //
1067
- // resolve();
1068
- // });
1069
- // };
1070
-
1071
- function fix_firestoreIndexesFile(self) {
1072
- return new Promise(async function(resolve, reject) {
1073
- const name = 'firestore.indexes.json';
1074
- let filePath = `${self.firebaseProjectPath}/${name}`;
1075
- let exists = jetpack.exists(filePath);
1076
-
1077
- if (!exists) {
1078
- log(chalk.yellow(`Writing new ${name} file...`));
1079
- await cmd_indexesGet(self, name, false);
1080
- }
1081
-
1082
- resolve();
1083
- });
1084
- };
1085
-
1086
- function fix_storageRulesFile(self) {
1087
- return new Promise(function(resolve, reject) {
1088
- const name = 'storage.rules';
1089
- let filePath = `${self.firebaseProjectPath}/${name}`;
1090
- let exists = jetpack.exists(filePath);
1091
- let contents = jetpack.read(filePath) || '';
1092
-
1093
- if (!exists) {
1094
- log(chalk.yellow(`Writing new ${name} file...`));
1095
- jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
1096
- contents = jetpack.read(filePath) || '';
1097
- }
1098
-
1099
- resolve();
1100
- });
1101
- };
1102
-
1103
- function fix_remoteconfigTemplateFile(self) {
1104
- return new Promise(function(resolve, reject) {
1105
- const name = 'remoteconfig.template.json'
1106
- let filePath = `${self.firebaseProjectPath}/${name}`;
1107
- let exists = jetpack.exists(filePath);
1108
- let contents = jetpack.read(filePath) || '';
1109
-
1110
- if (!exists) {
1111
- log(chalk.yellow(`Writing new ${name} file...`));
1112
- jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
1113
- contents = jetpack.read(filePath) || '';
1114
- }
1115
-
1116
- resolve();
1117
- });
1118
- };
1119
-
1120
-
1121
- // Hosting
1122
- function fix_firebaseHostingFolder(self) {
1123
- return new Promise(function(resolve, reject) {
1124
- _.set(self.firebaseJSON, 'hosting.public', 'public')
1125
- jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
1126
- resolve();
1127
- });
1128
- };
1129
-
1130
- function fix_firebaseHostingAuth(self) {
1131
- return new Promise(async function(resolve, reject) {
1132
- const url = `${self.bemConfigJSON.brand.url}/server/auth/handler`;
1133
-
1134
- await fetch(url, {
1135
- method: 'get',
1136
- cacheBreaker: true,
1137
- tries: 2,
1138
- response: 'text',
1139
- })
1140
- .then(async (text) => {
1141
- // Save to file
1142
- jetpack.write(`${self.firebaseProjectPath}/public/auth/handler/index.html`, text);
1143
-
1144
- resolve(true)
1145
- })
1146
- .catch(async (e) => {
1147
- log(chalk.red(`Failed to fetch auth handler. Please ensure it is live @ ${url}.`));
1148
-
1149
- reject(false)
1150
- })
1151
- });
1152
- };
1153
-
1154
- function getPkgVersion(package) {
1155
- return new Promise(async function(resolve, reject) {
1156
- let npm = new Npm();
1157
- npm.repo(package)
1158
- .package()
1159
- .then(function(pkg) {
1160
- resolve(pkg.version);
1161
- }, function(err) {
1162
- resolve('0.0.0');
1163
- });
1164
- });
1165
- }
1166
-
1167
- async function cmd_indexesGet(self, filePath, log) {
1168
- return new Promise(function(resolve, reject) {
1169
- const finalPath = `${self.firebaseProjectPath}/${filePath || 'firestore.indexes.json'}`;
1170
- let existingIndexes;
1171
- try {
1172
- existingIndexes = require(`${self.firebaseProjectPath}/firestore.indexes.json`)
1173
- } catch (e) {
1174
- if (log !== false) {
1175
- console.error('Failed to read existing local indexes', e);
1176
- }
1177
- }
1178
- let cmd = exec(`firebase firestore:indexes > ${finalPath}`, function (error, stdout, stderr) {
1179
- if (error) {
1180
- if (log !== false) {
1181
- console.error(error);
1182
- }
1183
- reject(error);
1184
- } else {
1185
- const newIndexes = require(finalPath);
1186
- if (log !== false) {
1187
- console.log(chalk.green(`Saving indexes to: ${finalPath}`));
1188
- console.log(stdout);
1189
-
1190
- const equal = (_.isEqual(newIndexes, existingIndexes));
1191
-
1192
- if (!equal) {
1193
- console.log(chalk.red(`The live and local index files did not match and have been overwritten by the ${chalk.bold('live indexes')}`));
1194
- }
1195
-
1196
- }
1197
- resolve(newIndexes);
1198
- }
1199
- });
1200
- });
1201
- }
1202
-
1203
- async function execute(command, cwd) {
1204
- cwd = cwd || process.cwd();
1205
- return new Promise(function(resolve, reject) {
1206
- exec(command, { cwd: cwd, stdio: 'inherit' })
1207
- .on('error', function(err) {
1208
- reject(err);
1209
- })
1210
- .on('close', function (one, two, three) {
1211
- console.log('===', one, two, three);
1212
- resolve()
1213
- })
1214
- // fork(command, function (error, stdout, stderr) {
1215
- // if (error) {
1216
- // reject(error);
1217
- // } else {
1218
- // resolve(stdout);
1219
- // }
1220
- // });
1221
-
1222
- });
1223
- }
1224
-
1225
- // async function execute(command, args, cwd) {
1226
- // cwd = cwd || process.cwd();
1227
- // return new Promise(function(resolve, reject) {
1228
- // spawn(command, args, { cwd: cwd, stdio: 'inherit' })
1229
- // .on('error', function(err) {
1230
- // reject(err);
1231
- // })
1232
- // .on('close', function (one, two, three) {
1233
- // console.log('===', one, two, three);
1234
- // resolve()
1235
- // })
1236
- // // fork(command, function (error, stdout, stderr) {
1237
- // // if (error) {
1238
- // // reject(error);
1239
- // // } else {
1240
- // // resolve(stdout);
1241
- // // }
1242
- // // });
1243
-
1244
- // });
1245
- // }
1246
-
1247
- async function cmd_configGet(self, filePath) {
1248
- return new Promise(function(resolve, reject) {
1249
- const finalPath = `${self.firebaseProjectPath}/${filePath || 'functions/.runtimeconfig.json'}`;
1250
-
1251
- const max = 10;
1252
- let retries = 0;
1253
-
1254
- function _attempt() {
1255
- exec(`firebase functions:config:get > ${finalPath}`, function (error, stdout, stderr) {
1256
- if (error) {
1257
- console.error(chalk.red(`Failed to get config: ${error}`));
1258
-
1259
- // If retries are exhausted, reject
1260
- if (retries++ > max) {
1261
- return reject(error);
1262
- }
1263
-
1264
- // Retry
1265
- const delay = 2500 * retries
1266
- console.error(chalk.yellow(`Retrying config:get ${retries}/${max} in ${delay}ms...`));
1267
- setTimeout(_attempt, delay);
1268
- } else {
1269
- console.log(chalk.green(`Saving config to: ${finalPath}`));
1270
- console.log(stdout);
1271
- resolve(require(finalPath));
1272
- }
1273
- });
1274
- }
1275
-
1276
- // Start the attempts
1277
- _attempt();
1278
- });
1279
- }
1280
-
1281
- async function cmd_configSet(self, newPath, newValue) {
1282
- return new Promise(async function(resolve, reject) {
1283
- // console.log(self.options);
1284
- // console.log(self.argv);
1285
- newPath = newPath || await inquirer.prompt([
1286
- {
1287
- type: 'input',
1288
- name: 'path',
1289
- default: 'service.key'
1290
- }
1291
- ]).then(answers => answers.path);
1292
-
1293
- let object = null;
1294
-
1295
- try {
1296
- object = JSON5.parse(newPath);
1297
- } catch (e) {
1298
- }
1299
-
1300
- const isObject = object && typeof object === 'object';
1301
-
1302
- // If it's a string, ensure some things
1303
- if (!isObject) {
1304
- // Validate path
1305
- if (!newPath.includes('.')) {
1306
- console.log(chalk.red(`Path needs 2 parts (one.two): ${newPath}`));
1307
- return reject();
1308
- }
1309
-
1310
- // Make sure it's only letters, numbers, periods, and underscores
1311
- if (newPath.match(/[^a-zA-Z0-9._]/)) {
1312
- console.log(chalk.red(`Path contains invalid characters: ${newPath}`));
1313
- return reject();
1314
- }
1315
- }
1316
-
1317
- try {
1318
- if (isObject) {
1319
- const keyify = (obj, prefix = '') =>
1320
- Object.keys(obj).reduce((res, el) => {
1321
- if( Array.isArray(obj[el]) ) {
1322
- return res;
1323
- } else if( typeof obj[el] === 'object' && obj[el] !== null ) {
1324
- return [...res, ...keyify(obj[el], prefix + el + '.')];
1325
- }
1326
- return [...res, prefix + el];
1327
- }, []);
1328
- const pathArray = keyify(object);
1329
- for (var i = 0; i < pathArray.length; i++) {
1330
- const pathName = pathArray[i];
1331
- const pathValue = _.get(object, pathName);
1332
- // console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)} = ${chalk.bold(pathValue)}`));
1333
- console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)}`));
1334
- await cmd_configSet(self, pathName, pathValue)
1335
- .catch(e => {
1336
- log(chalk.red(`Failed to save object path: ${e}`));
1337
- })
1338
- }
1339
- return resolve();
1340
- }
1341
- } catch (e) {
1342
- log(chalk.red(`Failed to save object: ${e}`));
1343
- return reject(e)
1344
- }
1345
-
1346
- newValue = newValue || await inquirer.prompt([
1347
- {
1348
- type: 'input',
1349
- name: 'value',
1350
- default: '123-abc'
1351
- }
1352
- ]).then(answers => answers.value)
1353
-
1354
- let isInvalid = false;
1355
- if (newPath !== newPath.toLowerCase()) {
1356
- isInvalid = true;
1357
- newPath = newPath.replace(/([A-Z])/g, '_$1').trim().toLowerCase();
1358
- }
1359
- log(chalk.yellow(`Saving to ${chalk.bold(newPath)}...`));
1360
- let cmd = exec(`firebase functions:config:set ${newPath}="${newValue}"`, function (error, stdout, stderr) {
1361
- if (error) {
1362
- log(chalk.red(`Failed to save ${chalk.bold(newPath)}: ${error}`));
1363
- reject(error);
1364
- } else {
1365
- console.log(stdout);
1366
- if (isInvalid) {
1367
- log(chalk.red(`!!! Your path contained an invalid uppercase character`));
1368
- log(chalk.red(`!!! It was set to: ${chalk.bold(newPath)}`));
1369
- } else {
1370
- log(chalk.green(`Successfully saved to ${chalk.bold(newPath)}`));
1371
- }
1372
- resolve();
1373
- }
1374
- });
1375
- });
1376
- }
1377
-
1378
- async function cmd_configUnset(self) {
1379
- return new Promise(async function(resolve, reject) {
1380
- // console.log(self.options);
1381
- // console.log(self.argv);
1382
- await inquirer
1383
- .prompt([
1384
- /* Pass your questions in here */
1385
- {
1386
- type: 'input',
1387
- name: 'path',
1388
- default: 'service.key'
1389
- }
1390
- ])
1391
- .then(answers => {
1392
- // Use user feedback for... whatever!!
1393
- // console.log('answer', answers);
1394
- log(chalk.yellow(`Deleting ${chalk.bold(answers.path)}...`));
1395
- let cmd = exec(`firebase functions:config:unset ${answers.path}`, function (error, stdout, stderr) {
1396
- if (error) {
1397
- log(chalk.red(`Failed to delete ${chalk.bold(answers.path)}: ${error}`));
1398
- reject(error);
1399
- } else {
1400
- console.log(stdout);
1401
- log(chalk.green(`Successfully deleted ${chalk.bold(answers.path)}`));
1402
- resolve();
1403
- }
1404
- });
1405
- });
1406
- });
1407
- }
1408
-
1409
- async function cmd_iamImportExport(self) {
1410
- return new Promise(function(resolve, reject) {
1411
- const command = `
1412
- gcloud projects add-iam-policy-binding {projectId} \
1413
- --member serviceAccount:{projectId}@appspot.gserviceaccount.com \
1414
- --role roles/datastore.importExportAdmin
1415
- `
1416
- .replace(/{projectId}/ig, self.projectName)
1417
-
1418
- let cmd = exec(command, function (error, stdout, stderr) {
1419
- if (error) {
1420
- console.log(chalk.red(`Failed to run command`, error));
1421
- reject(error);
1422
- } else {
1423
- // console.log(chalk.green(`Added permission`));
1424
- resolve(stdout);
1425
- }
1426
- });
1427
- });
1428
- }
1429
-
1430
- async function cmd_setStorageLifecycle(self) {
1431
- return new Promise(function(resolve, reject) {
1432
- const command = `gsutil lifecycle set {config} gs://{bucket}`
1433
- .replace(/{config}/ig, path.resolve(`${__dirname}/../../templates/storage-lifecycle-config-1-day.json`))
1434
- .replace(/{bucket}/ig, `us.artifacts.${self.projectName}.appspot.com`)
1435
- const command2 = `gsutil lifecycle set {config} gs://{bucket}`
1436
- .replace(/{config}/ig, path.resolve(`${__dirname}/../../templates/storage-lifecycle-config-30-days.json`))
1437
- .replace(/{bucket}/ig, `bm-backup-firestore-${self.projectName}`)
1438
-
1439
- exec(command, function (error, stdout, stderr) {
1440
- if (error) {
1441
- console.log(chalk.red(`Failed to run command`, error));
1442
- reject(error);
1443
- } else {
1444
- exec(command2, function (error, stdout, stderr) {
1445
- if (error) {
1446
- console.log(chalk.red(`Failed to run command`, error));
1447
- reject(error);
1448
- } else {
1449
- // console.log(chalk.green(`Added lifecycle`));
1450
- resolve(stdout);
1451
- }
1452
- })
1453
- }
1454
- });
1455
- });
1456
- }
1457
-
1458
- // HELPER
1459
-
1460
- function initMocha() {
1461
-
1462
- }
1463
-
1464
- function isLocal(name) {
1465
- return name.indexOf('file:') > -1;
1466
- }
1467
-
1468
- function installPkg(name, version, type) {
1469
- let v;
1470
- let t;
1471
- if (name.indexOf('file:') > -1) {
1472
- v = '';
1473
- } else if (!version) {
1474
- v = '@latest';
1475
- } else {
1476
- v = version;
1477
- }
1478
-
1479
- if (!type) {
1480
- t = ''
1481
- } else if (type === 'dev' || type === '--save-dev') {
1482
- t = ' --save-dev';
1483
- }
1484
-
1485
- let latest = version ? '' : '@latest';
1486
- return new Promise(function(resolve, reject) {
1487
- let command = `npm i ${name}${v}${t}`;
1488
- console.log('Running ', command);
1489
- let cmd = exec(command, function (error, stdout, stderr) {
1490
- if (error) {
1491
- reject(error);
1492
- } else {
1493
- resolve();
1494
- }
1495
- });
1496
- });
1497
- }
1498
-
1499
- function uninstallPkg(name) {
1500
- return new Promise(function(resolve, reject) {
1501
- let command = `npm uninstall ${name}`;
1502
- console.log('Running ', command);
1503
- let cmd = exec(command, function (error, stdout, stderr) {
1504
- if (error) {
1505
- reject(error);
1506
- } else {
1507
- resolve();
1508
- }
1509
- });
1510
- });
1511
- }
1512
- function loadJSON(path) {
1513
- const contents = jetpack.read(path);
1514
- if (!contents) {
1515
- return {};
1516
- }
1517
-
1518
- return JSON5.parse(contents);
1519
- }
1520
-
1521
- function hasContent(object) {
1522
- return Object.keys(object).length > 0;
1523
- }
1524
-
1525
- function cleanOutput(data) {
1526
- try {
1527
- data = (data + '').replace(/\n$/, '')
1528
- } catch (e) {
1529
-
1530
- }
1531
-
1532
- // Return
1533
- return data;
1534
- }