backend-manager 2.0.26 → 2.0.27

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "backend-manager",
3
- "version": "2.0.26",
3
+ "version": "2.0.27",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -37,7 +37,7 @@
37
37
  "cors": "^2.8.5",
38
38
  "dotenv": "^16.0.0",
39
39
  "firebase-admin": "^9.12.0",
40
- "firebase-functions": "^3.20.1",
40
+ "firebase-functions": "^3.21.0",
41
41
  "fs-jetpack": "^4.3.1",
42
42
  "hcaptcha": "^0.1.1",
43
43
  "inquirer": "^8.2.4",
@@ -47,9 +47,9 @@
47
47
  "mocha": "^9.2.2",
48
48
  "moment": "^2.29.3",
49
49
  "node-fetch": "^2.6.7",
50
- "node-powertools": "^0.0.10",
50
+ "node-powertools": "^0.0.13",
51
51
  "npm-api": "^1.0.1",
52
- "paypal-server-api": "^0.0.5",
52
+ "paypal-server-api": "^0.0.6",
53
53
  "pushid": "^1.0.0",
54
54
  "semver": "^7.3.7",
55
55
  "shortid": "^2.2.16",
@@ -65,4 +65,4 @@
65
65
  "src/",
66
66
  "templates/"
67
67
  ]
68
- }
68
+ }
package/src/cli/cli.js CHANGED
@@ -6,7 +6,7 @@
6
6
  // https://github.com/sitepoint-editors/ginit
7
7
 
8
8
  let exec = require('child_process').exec;
9
- const fs = require('fs-jetpack');
9
+ const jetpack = require('fs-jetpack');
10
10
  const path = require('path');
11
11
  const chalk = require('chalk');
12
12
  const _ = require('lodash');
@@ -49,9 +49,9 @@ let bem_fsRulesBackupRegex = /({{\s*?backend-manager\s*?}})/sgm;
49
49
  let MOCHA_PKG_SCRIPT = 'mocha ../test/ --recursive --timeout=10000';
50
50
  let NPM_CLEAN_SCRIPT = 'rm -fr node_modules && rm -fr package-lock.json && npm cache clean --force && npm install && npm rb';
51
51
  let NOFIX_TEXT = chalk.red(`There is no automatic fix for this check.`);
52
- let runtimeconfigTemplate = JSON.parse((fs.read(path.resolve(`${__dirname}/../../templates/runtimeconfig.json`))) || '{}');
53
- let bemConfigTemplate = JSON.parse((fs.read(path.resolve(`${__dirname}/../../templates/backend-manager-config.json`))) || '{}');
54
- let CLI_CONFIG = JSON5.parse((fs.read(path.resolve(`${__dirname}/config.json`))) || '{}');
52
+ let runtimeconfigTemplate = JSON.parse((jetpack.read(path.resolve(`${__dirname}/../../templates/runtimeconfig.json`))) || '{}');
53
+ let bemConfigTemplate = JSON.parse((jetpack.read(path.resolve(`${__dirname}/../../templates/backend-manager-config.json`))) || '{}');
54
+ let CLI_CONFIG = JSON5.parse((jetpack.read(path.resolve(`${__dirname}/config.json`))) || '{}');
55
55
 
56
56
  function Main() {
57
57
  }
@@ -118,16 +118,21 @@ Main.prototype.process = async function (args) {
118
118
  // ls = null;
119
119
  });
120
120
  }
121
- if (this.options['config:get']) {
121
+
122
+ if (this.options['firestore:indexes:get'] || this.options['firestore:indexes'] || this.options['indexes:get']) {
123
+ return await cmd_indexesGet(self);
124
+ }
125
+
126
+ if (this.options['functions:config:get'] || this.options['config:get']) {
122
127
  return await cmd_configGet(self);
123
128
  }
124
129
 
125
- if (this.options['config:set']) {
130
+ if (this.options['functions:config:set'] || this.options['config:set']) {
126
131
  await cmd_configSet(self);
127
132
  return await cmd_configGet(self);
128
133
  }
129
134
 
130
- if (this.options['config:unset'] || this.options['config:delete'] || this.options['config:remove']) {
135
+ if (this.options['functions:config:unset'] || this.options['config:unset'] || this.options['config:delete'] || this.options['config:remove']) {
131
136
  await cmd_configUnset(self);
132
137
  return await cmd_configGet(self);
133
138
  }
@@ -200,28 +205,28 @@ module.exports = Main;
200
205
 
201
206
  Main.prototype.getRulesFile = function () {
202
207
  let self = this;
203
- this.default.firestoreRulesWhole = (fs.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `-${self.default.version}-`);
208
+ this.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `-${self.default.version}-`);
204
209
  this.default.firestoreRulesCore = this.default.firestoreRulesWhole.match(bem_fsRulesRegex)[0];
205
210
 
206
211
  };
207
212
 
208
213
  Main.prototype.setup = async function () {
209
214
  let self = this;
210
- let cwd = fs.cwd();
215
+ let cwd = jetpack.cwd();
211
216
  log(chalk.green(`\n---- RUNNING v${this.default.version} SETUP ----`));
212
- this.package = fs.read(`${this.firebaseProjectPath}/functions/package.json`) || '{}';
213
- this.firebaseJSON = fs.read(`${this.firebaseProjectPath}/firebase.json`) || '{}';
214
- this.firebaseRC = fs.read(`${this.firebaseProjectPath}/.firebaserc`) || '{}';
215
- this.runtimeConfigJSON = fs.read(`${this.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}';
216
- this.projectPackage = fs.read(`${this.firebaseProjectPath}/package.json`) || '{}';
217
- this.gitignore = fs.read(`${this.firebaseProjectPath}/functions/.gitignore`) || '';
217
+ this.package = jetpack.read(`${this.firebaseProjectPath}/functions/package.json`) || '{}';
218
+ this.firebaseJSON = jetpack.read(`${this.firebaseProjectPath}/firebase.json`) || '{}';
219
+ this.firebaseRC = jetpack.read(`${this.firebaseProjectPath}/.firebaserc`) || '{}';
220
+ this.runtimeConfigJSON = jetpack.read(`${this.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}';
221
+ this.projectPackage = jetpack.read(`${this.firebaseProjectPath}/package.json`) || '{}';
222
+ this.gitignore = jetpack.read(`${this.firebaseProjectPath}/functions/.gitignore`) || '';
218
223
  if (!this.package) {
219
224
  log(chalk.red(`Missing functions/package.json :(`));
220
225
  return;
221
226
  }
222
227
  // console.log('cwd', cwd, cwd.endsWith('functions'));
223
228
  if (!cwd.endsWith('functions') && !cwd.endsWith('functions/')) {
224
- log(chalk.red(`Please run ${chalk.bold('bm setup')} from the ${chalk.bold('functions')} folder. Run ${chalk.bold('cd functions')}.`));
229
+ log(chalk.red(`Please run ${chalk.bold('npx bm setup')} from the ${chalk.bold('functions')} folder. Run ${chalk.bold('cd functions')}.`));
225
230
  return;
226
231
  }
227
232
 
@@ -234,8 +239,8 @@ Main.prototype.setup = async function () {
234
239
  self.getRulesFile();
235
240
 
236
241
  this.default.firestoreRulesVersionRegex = new RegExp(`///---version-${self.default.version}---///`)
237
- // bem_giRegex = new RegExp(fs.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)).replace(/\./g, '\\.'), 'm' )
238
- bem_giRegex = new RegExp(fs.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)), 'm' )
242
+ // bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)).replace(/\./g, '\\.'), 'm' )
243
+ bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)), 'm' )
239
244
 
240
245
  // tests
241
246
  this.projectName = this.firebaseRC.projects.default;
@@ -248,14 +253,14 @@ Main.prototype.setup = async function () {
248
253
  }
249
254
 
250
255
  await this.test('is a firebase project', async function () {
251
- let exists = fs.exists(`${self.firebaseProjectPath}/firebase.json`);
256
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/firebase.json`);
252
257
  return exists;
253
258
  }, fix_isFirebase);
254
259
 
255
260
  await this.test('.nvmrc file has proper version', async function () {
256
261
  // return !!self.package.dependencies && !!self.package.devDependencies;
257
- // let gitignore = fs.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
258
- let nvmrc = fs.read(`${self.firebaseProjectPath}/functions/.nvmrc`) || '';
262
+ // let gitignore = jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
263
+ let nvmrc = jetpack.read(`${self.firebaseProjectPath}/functions/.nvmrc`) || '';
259
264
  return nvmrc === `v${CLI_CONFIG.node}/*`
260
265
 
261
266
  }, fix_nvmrc);
@@ -362,7 +367,7 @@ Main.prototype.setup = async function () {
362
367
  // }, fix_mocha);
363
368
 
364
369
  await this.test('using proper .runtimeconfig', async function () {
365
- let runtimeconfig = JSON.parse(fs.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}');
370
+ let runtimeconfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}');
366
371
  let ogPaths = getObjectPaths(runtimeconfigTemplate).split('\n');
367
372
  let pass = true;
368
373
  for (var i = 0, l = ogPaths.length; i < l; i++) {
@@ -378,7 +383,7 @@ Main.prototype.setup = async function () {
378
383
  }, fix_runtimeConfig);
379
384
 
380
385
  await this.test('using proper backend-manager-config.json', async function () {
381
- let bemConfig = JSON.parse(fs.read(`${self.firebaseProjectPath}/functions/backend-manager-config.json`) || '{}');
386
+ let bemConfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/backend-manager-config.json`) || '{}');
382
387
  let ogPaths = getObjectPaths(bemConfigTemplate).split('\n');
383
388
  let pass = true;
384
389
  for (var i = 0, l = ogPaths.length; i < l; i++) {
@@ -394,7 +399,7 @@ Main.prototype.setup = async function () {
394
399
  }, fix_bemConfig);
395
400
 
396
401
  await this.test('has service-account.json', function () {
397
- let exists = fs.exists(`${self.firebaseProjectPath}/functions/service-account.json`);
402
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/functions/service-account.json`);
398
403
  return !!exists;
399
404
  }, fix_serviceAccount);
400
405
 
@@ -403,31 +408,100 @@ Main.prototype.setup = async function () {
403
408
  if (!match) {
404
409
  return false;
405
410
  } else {
406
- let gitignore = fs.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
411
+ let gitignore = jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
407
412
  let file = gitignore.match(bem_giRegexOuter) ? RegExp.$1 : 'BAD1';
408
413
  let file2 = match[0].match(bem_giRegexOuter) ? RegExp.$1 : 'BAD2';
409
414
  return file === file2;
410
415
  }
411
416
  }, fix_gitignore);
412
417
 
418
+
419
+ // Check firebase.json fields
413
420
  await this.test('firestore rules in JSON', function () {
414
- let firestore = _.get(self.firebaseJSON, 'firestore', {});
421
+ const firestore = _.get(self.firebaseJSON, 'firestore', {});
415
422
  return (firestore.rules === 'firestore.rules')
416
423
  }, fix_firestoreRules);
417
424
 
425
+ await this.test('firestore indexes in JSON', function () {
426
+ let firestore = _.get(self.firebaseJSON, 'firestore', {});
427
+ return (firestore.indexes === 'firestore.indexes.json')
428
+ }, fix_firestoreIndexes);
429
+
418
430
  await this.test('realtime rules in JSON', function () {
419
- let firestore = _.get(self.firebaseJSON, 'database', {});
420
- return (firestore.rules === 'security.rules.json')
431
+ const database = _.get(self.firebaseJSON, 'database', {});
432
+ return (database.rules === 'database.rules.json')
421
433
  }, fix_realtimeRules);
422
434
 
435
+ await this.test('storage rules in JSON', function () {
436
+ const storage = _.get(self.firebaseJSON, 'storage', {});
437
+ return (storage.rules === 'storage.rules')
438
+ }, fix_storageRules);
439
+
440
+ await this.test('remoteconfig template in JSON', function () {
441
+ const remoteconfig = _.get(self.firebaseJSON, 'remoteconfig', {});
442
+ return (remoteconfig.template === 'remoteconfig.template.json')
443
+ }, fix_remoteconfigTemplate);
444
+
445
+ await this.test('firestore indexes synced', async function () {
446
+ const tempPath = '_firestore.indexes.json'
447
+ const liveIndexes = await cmd_indexesGet(self, tempPath, false);
448
+
449
+ const localIndexes_exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
450
+ let localIndexes
451
+ if (localIndexes_exists) {
452
+ localIndexes = require(`${self.firebaseProjectPath}/firestore.indexes.json`)
453
+ }
454
+ const equal = _.isEqual(liveIndexes, localIndexes);
455
+
456
+ if (localIndexes_exists && !equal) {
457
+ console.log(chalk.red(`Run ${chalk.bold('npx bm indexes:get')} to overwrite the local Firestore indexes with the live ones.`));
458
+ }
459
+
460
+ jetpack.remove(`${self.firebaseProjectPath}/${tempPath}`)
461
+
462
+ return !localIndexes_exists || equal
463
+ }, NOFIX);
464
+
465
+
466
+ // Update actual files
467
+ await this.test('update firestore rules file', function () {
468
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.rules`);
469
+ let contents = jetpack.read(`${self.firebaseProjectPath}/firestore.rules`) || '';
470
+ let containsCore = contents.match(bem_fsRulesRegex);
471
+ let matchesVersion = contents.match(self.default.firestoreRulesVersionRegex);
472
+
473
+ return (!!exists && !!containsCore && !!matchesVersion);
474
+ }, fix_firestoreRulesFile);
475
+
476
+ await this.test('update firestore indexes file', function () {
477
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
478
+ return (!!exists);
479
+ }, fix_firestoreIndexesFile);
480
+
481
+ await this.test('update realtime rules file', function () {
482
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/database.rules.json`);
483
+ return (!!exists);
484
+ }, fix_realtimeRulesFile);
485
+
486
+ await this.test('update storage rules file', function () {
487
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/storage.rules`);
488
+ return (!!exists);
489
+ }, fix_storageRulesFile);
490
+
491
+ await this.test('update remoteconfig template file', function () {
492
+ let exists = jetpack.exists(`${self.firebaseProjectPath}/remoteconfig.template.json`);
493
+ return (!!exists);
494
+ }, fix_remoteconfigTemplateFile);
495
+
496
+ // Hosting
423
497
  await this.test('hosting is set to dedicated folder in JSON', function () {
424
498
  let hosting = _.get(self.firebaseJSON, 'hosting', {});
425
499
  return (hosting.public && (hosting.public === 'public' || hosting.public !== '.'))
426
500
  }, fix_firebaseHosting);
427
501
 
428
502
  await this.test('update backend-manager-tests.js', function () {
429
- fs.write(`${self.firebaseProjectPath}/test/backend-manager-tests.js`,
430
- (fs.read(path.resolve(`${__dirname}/../../templates/backend-manager-tests.js`)))
503
+ jetpack.write(`${self.firebaseProjectPath}/test/backend-manager-tests.js`,
504
+ (jetpack.read(path.resolve(`${__dirname}/../../templates/backend-manager-tests.js`)))
431
505
  )
432
506
  return true;
433
507
  }, NOFIX);
@@ -442,27 +516,7 @@ Main.prototype.setup = async function () {
442
516
  // return script === NPM_CLEAN_SCRIPT;
443
517
  // }, fix_cleanNpmScript);
444
518
 
445
- await this.test('ignore firestore indexes file', function () {
446
- let firestore = _.get(self.firebaseJSON, 'firestore', {});
447
- return (firestore.indexes === '')
448
- }, fix_firebaseIndexes);
449
519
 
450
- await this.test('update firestore rules file', function () {
451
- let exists = fs.exists(`${self.firebaseProjectPath}/firestore.rules`);
452
- let contents = fs.read(`${self.firebaseProjectPath}/firestore.rules`) || '';
453
- let containsCore = contents.match(bem_fsRulesRegex);
454
- let matchesVersion = contents.match(self.default.firestoreRulesVersionRegex);
455
-
456
- // console.log('exists', !!exists);
457
- // console.log('containsCore', !!containsCore);
458
- // console.log('matchesVersion', !!matchesVersion);
459
- return (!!exists && !!containsCore && !!matchesVersion);
460
- }, fix_firestoreRulesFile);
461
-
462
- await this.test('update realtime rules file', function () {
463
- let exists = fs.exists(`${self.firebaseProjectPath}/security.rules.json`);
464
- return (!!exists);
465
- }, fix_realtimeRulesFile);
466
520
 
467
521
 
468
522
  if (self.package.dependencies['backend-manager'].includes('file:')) {
@@ -512,18 +566,11 @@ Main.prototype.setup = async function () {
512
566
 
513
567
  console.log(chalk.green(`Checks finished. Passed ${self.testCount}/${self.testTotal} tests.`));
514
568
  if (self.testCount !== self.testTotal) {
515
- console.log(chalk.yellow(`You should continue to run ${chalk.bold('bm setup')} until you pass all tests and fix all errors.`));
569
+ console.log(chalk.yellow(`You should continue to run ${chalk.bold('npx bm setup')} until you pass all tests and fix all errors.`));
516
570
  }
517
571
 
518
572
  return;
519
573
 
520
- // await this.test('deleted firestore indexes', function () {
521
- // let indexes = fs.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
522
- // return (!indexes);
523
- // }, fix_fsindexes);
524
-
525
- // console.log(self.package);
526
-
527
574
  };
528
575
 
529
576
  // https://stackoverflow.com/questions/41802259/javascript-deep-check-objects-have-same-keys
@@ -600,9 +647,9 @@ function bemPackageVersionWarning(package, current, latest) {
600
647
  async function fix_runtimeConfig(self) {
601
648
  return new Promise(function(resolve, reject) {
602
649
  log(NOFIX_TEXT);
603
- log(chalk.red(`You need to run ${chalk.bold(`bm config:set`)} for each of these keys:`));
650
+ log(chalk.red(`You need to run ${chalk.bold(`npx bm config:set`)} for each of these keys:`));
604
651
  let objectKeys = getObjectPaths(runtimeconfigTemplate).split('\n');
605
- let theirConfig = JSON.parse(fs.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}');
652
+ let theirConfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}');
606
653
  for (var i = 0, l = objectKeys.length; i < l; i++) {
607
654
  let item = objectKeys[i];
608
655
  if (!item) {return}
@@ -614,7 +661,7 @@ async function fix_runtimeConfig(self) {
614
661
  }
615
662
  }
616
663
  // console.log('objectKeys', objectKeys);
617
- // log(chalk.red(`You need to run ${chalk.bold(`bm config:set`)} for each of these keys: \n${getObjectPaths(runtimeconfigTemplate)}`));
664
+ // log(chalk.red(`You need to run ${chalk.bold(`npx bm config:set`)} for each of these keys: \n${getObjectPaths(runtimeconfigTemplate)}`));
618
665
  reject();
619
666
  });
620
667
  };
@@ -624,9 +671,9 @@ async function fix_bemConfig(self) {
624
671
  log(NOFIX_TEXT);
625
672
  log(chalk.red(`You need to open backend-manager-config.json and set each of these keys:`));
626
673
  let objectKeys = getObjectPaths(bemConfigTemplate).split('\n');
627
- let theirConfig = JSON.parse(fs.read(`${self.firebaseProjectPath}/functions/backend-manager-config.json`) || '{}');
674
+ let theirConfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/backend-manager-config.json`) || '{}');
628
675
  if (Object.keys(theirConfig).length < 1) {
629
- fs.write(`${self.firebaseProjectPath}/functions/backend-manager-config.json`, bemConfigTemplate)
676
+ jetpack.write(`${self.firebaseProjectPath}/functions/backend-manager-config.json`, bemConfigTemplate)
630
677
  }
631
678
  for (var i = 0, l = objectKeys.length; i < l; i++) {
632
679
  let item = objectKeys[i];
@@ -655,7 +702,7 @@ async function fix_serviceAccount(self) {
655
702
  // function fix_mochaScript(self) {
656
703
  // return new Promise(function(resolve, reject) {
657
704
  // _.set(self.package, 'scripts.test', MOCHA_PKG_SCRIPT);
658
- // fs.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
705
+ // jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
659
706
  // resolve();
660
707
  // });
661
708
  // }
@@ -664,7 +711,7 @@ function fix_nodeVersion(self) {
664
711
  return new Promise(function(resolve, reject) {
665
712
  _.set(self.package, 'engines.node', CLI_CONFIG.node)
666
713
 
667
- fs.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
714
+ jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
668
715
  resolve();
669
716
  });
670
717
  };
@@ -672,7 +719,7 @@ function fix_nodeVersion(self) {
672
719
  function fix_nvmrc(self) {
673
720
  return new Promise(function(resolve, reject) {
674
721
 
675
- fs.write(`${self.firebaseProjectPath}/functions/.nvmrc`, `v${CLI_CONFIG.node}/*`);
722
+ jetpack.write(`${self.firebaseProjectPath}/functions/.nvmrc`, `v${CLI_CONFIG.node}/*`);
676
723
  resolve();
677
724
  });
678
725
  };
@@ -691,7 +738,7 @@ function fix_projpackage(self) {
691
738
  self.projectPackage.dependencies = self.projectPackage.dependencies || {};
692
739
  self.projectPackage.devDependencies = self.projectPackage.devDependencies || {};
693
740
 
694
- fs.write(`${self.firebaseProjectPath}/package.json`, JSON.stringify(self.projectPackage, null, 2) );
741
+ jetpack.write(`${self.firebaseProjectPath}/package.json`, JSON.stringify(self.projectPackage, null, 2) );
695
742
  resolve();
696
743
  });
697
744
  };
@@ -702,7 +749,7 @@ function fix_functionspackage(self) {
702
749
  self.package.devDependencies = self.package.devDependencies || {};
703
750
  self.package.version = self.package.version || '0.0.1';
704
751
 
705
- fs.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
752
+ jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
706
753
  resolve();
707
754
  });
708
755
  };
@@ -711,7 +758,7 @@ function fix_packageversion(self) {
711
758
  return new Promise(function(resolve, reject) {
712
759
  self.package.version = self.projectPackage.version;
713
760
 
714
- fs.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
761
+ jetpack.write(`${self.firebaseProjectPath}/functions/package.json`, JSON.stringify(self.package, null, 2) );
715
762
  resolve();
716
763
  });
717
764
  };
@@ -742,7 +789,7 @@ async function fix_bem(self) {
742
789
 
743
790
  function fix_gitignore(self) {
744
791
  return new Promise(function(resolve, reject) {
745
- let gi = (fs.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)));
792
+ let gi = (jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)));
746
793
  if (self.gitignore.match(bem_giRegexOuter)) {
747
794
  self.gitignore = self.gitignore.replace(bem_giRegexOuter, gi);
748
795
  } else {
@@ -751,7 +798,7 @@ function fix_gitignore(self) {
751
798
  self.gitignore = self.gitignore.replace(/\n\s*\n$/mg, '\n')
752
799
  // self.gitignore = `${self.gitignore}\n${gi}`.replace(/$\n/m,'');
753
800
  // self.gitignore = self.gitignore.replace(/$\n/m,'');
754
- fs.write(`${self.firebaseProjectPath}/functions/.gitignore`, self.gitignore);
801
+ jetpack.write(`${self.firebaseProjectPath}/functions/.gitignore`, self.gitignore);
755
802
  resolve();
756
803
  });
757
804
  };
@@ -759,31 +806,39 @@ function fix_gitignore(self) {
759
806
  function fix_firestoreRules(self) {
760
807
  return new Promise(function(resolve, reject) {
761
808
  _.set(self.firebaseJSON, 'firestore.rules', 'firestore.rules')
762
- fs.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
809
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
810
+ resolve();
811
+ });
812
+ };
813
+
814
+ function fix_firestoreIndexes(self) {
815
+ return new Promise(function(resolve, reject) {
816
+ _.set(self.firebaseJSON, 'firestore.indexes', 'firestore.indexes.json')
817
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
763
818
  resolve();
764
819
  });
765
820
  };
766
821
 
767
822
  function fix_realtimeRules(self) {
768
823
  return new Promise(function(resolve, reject) {
769
- _.set(self.firebaseJSON, 'database.rules', 'security.rules.json')
770
- fs.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
824
+ _.set(self.firebaseJSON, 'database.rules', 'database.rules.json')
825
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
771
826
  resolve();
772
827
  });
773
828
  };
774
829
 
775
- function fix_firebaseHosting(self) {
830
+ function fix_storageRules(self) {
776
831
  return new Promise(function(resolve, reject) {
777
- _.set(self.firebaseJSON, 'hosting.public', 'public')
778
- fs.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
832
+ _.set(self.firebaseJSON, 'storage.rules', 'storage.rules')
833
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
779
834
  resolve();
780
835
  });
781
836
  };
782
837
 
783
- function fix_firebaseIndexes(self) {
838
+ function fix_remoteconfigTemplate(self) {
784
839
  return new Promise(function(resolve, reject) {
785
- _.set(self.firebaseJSON, 'firestore.indexes', "")
786
- fs.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
840
+ _.set(self.firebaseJSON, 'remoteconfig.template', 'remoteconfig.template.json')
841
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
787
842
  resolve();
788
843
  });
789
844
  };
@@ -791,13 +846,13 @@ function fix_firebaseIndexes(self) {
791
846
  function fix_firestoreRulesFile(self) {
792
847
  return new Promise(function(resolve, reject) {
793
848
  let path = `${self.firebaseProjectPath}/firestore.rules`;
794
- let exists = fs.exists(path);
795
- let contents = fs.read(path) || '';
849
+ let exists = jetpack.exists(path);
850
+ let contents = jetpack.read(path) || '';
796
851
 
797
852
  if (!exists || !contents) {
798
853
  log(chalk.yellow(`Writing new firestore.rules file...`));
799
- fs.write(path, self.default.firestoreRulesWhole)
800
- contents = fs.read(path) || '';
854
+ jetpack.write(path, self.default.firestoreRulesWhole)
855
+ contents = jetpack.read(path) || '';
801
856
  }
802
857
 
803
858
  let hasTemplate = contents.match(bem_fsRulesRegex) || contents.match(bem_fsRulesBackupRegex);
@@ -812,32 +867,85 @@ function fix_firestoreRulesFile(self) {
812
867
  // console.log('replace wih', self.default.firestoreRulesCore);
813
868
  contents = contents.replace(bem_fsRulesBackupRegex, self.default.firestoreRulesCore)
814
869
  contents = contents.replace(bem_fsRulesRegex, self.default.firestoreRulesCore)
815
- fs.write(path, contents)
870
+ jetpack.write(path, contents)
816
871
  log(chalk.yellow(`Writing core rules to firestore.rules file...`));
817
872
  }
818
873
  resolve();
819
874
  });
820
875
  };
821
876
 
877
+ function fix_firestoreIndexesFile(self) {
878
+ return new Promise(async function(resolve, reject) {
879
+ const name = 'firestore.indexes.json';
880
+ let filePath = `${self.firebaseProjectPath}/${name}`;
881
+ let exists = jetpack.exists(filePath);
882
+
883
+ if (!exists) {
884
+ log(chalk.yellow(`Writing new ${name} file...`));
885
+ await cmd_indexesGet(self, name, false);
886
+ }
887
+
888
+ resolve();
889
+ });
890
+ };
891
+
822
892
  function fix_realtimeRulesFile(self) {
823
893
  return new Promise(function(resolve, reject) {
824
- let filePath = `${self.firebaseProjectPath}/security.rules.json`;
825
- let exists = fs.exists(filePath);
826
- let contents = fs.read(filePath) || '';
894
+ const name = 'database.rules.json';
895
+ let filePath = `${self.firebaseProjectPath}/${name}`;
896
+ let exists = jetpack.exists(filePath);
897
+ let contents = jetpack.read(filePath) || '';
898
+
899
+ if (!exists) {
900
+ log(chalk.yellow(`Writing new ${name} file...`));
901
+ jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
902
+ contents = jetpack.read(filePath) || '';
903
+ }
904
+
905
+ resolve();
906
+ });
907
+ };
908
+
909
+ function fix_storageRulesFile(self) {
910
+ return new Promise(function(resolve, reject) {
911
+ const name = 'storage.rules';
912
+ let filePath = `${self.firebaseProjectPath}/${name}`;
913
+ let exists = jetpack.exists(filePath);
914
+ let contents = jetpack.read(filePath) || '';
915
+
916
+ if (!exists) {
917
+ log(chalk.yellow(`Writing new ${name} file...`));
918
+ jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
919
+ contents = jetpack.read(filePath) || '';
920
+ }
921
+
922
+ resolve();
923
+ });
924
+ };
925
+
926
+ function fix_remoteconfigTemplateFile(self) {
927
+ return new Promise(function(resolve, reject) {
928
+ const name = 'remoteconfig.template.json'
929
+ let filePath = `${self.firebaseProjectPath}/${name}`;
930
+ let exists = jetpack.exists(filePath);
931
+ let contents = jetpack.read(filePath) || '';
827
932
 
828
933
  if (!exists) {
829
- log(chalk.yellow(`Writing new security.rules.json file...`));
830
- fs.write(filePath, fs.read(path.resolve(`${__dirname}/../../templates/security.rules.json`)))
831
- contents = fs.read(filePath) || '';
934
+ log(chalk.yellow(`Writing new ${name} file...`));
935
+ jetpack.write(filePath, jetpack.read(path.resolve(`${__dirname}/../../templates/${name}`)))
936
+ contents = jetpack.read(filePath) || '';
832
937
  }
833
938
 
834
939
  resolve();
835
940
  });
836
941
  };
837
942
 
838
- function fix_fsindexes(self) {
943
+
944
+ // Hosting
945
+ function fix_firebaseHosting(self) {
839
946
  return new Promise(function(resolve, reject) {
840
- fs.remove(`${self.firebaseProjectPath}/firestore.indexes.json`)
947
+ _.set(self.firebaseJSON, 'hosting.public', 'public')
948
+ jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
841
949
  resolve();
842
950
  });
843
951
  };
@@ -855,130 +963,165 @@ function getPkgVersion(package) {
855
963
  });
856
964
  }
857
965
 
858
-
859
-
860
- async function cmd_configGet(self) {
861
- return new Promise(function(resolve, reject) {
862
- let cmd = exec(`firebase functions:config:get > ${self.firebaseProjectPath}/functions/.runtimeconfig.json`, function (error, stdout, stderr) {
863
- if (error) {
966
+ async function cmd_indexesGet(self, filePath, log) {
967
+ return new Promise(function(resolve, reject) {
968
+ const finalPath = `${self.firebaseProjectPath}/${filePath || 'firestore.indexes.json'}`;
969
+ let existingIndexes;
970
+ try {
971
+ existingIndexes = require(`${self.firebaseProjectPath}/firestore.indexes.json`)
972
+ } catch (e) {
973
+ if (log !== false) {
974
+ console.error('Failed to read existing local indexes', e);
975
+ }
976
+ }
977
+ let cmd = exec(`firebase firestore:indexes > ${finalPath}`, function (error, stdout, stderr) {
978
+ if (error) {
979
+ if (log !== false) {
864
980
  console.error(error);
865
- reject(error);
866
- } else {
867
- console.log(chalk.green(`Saving config to: ${self.firebaseProjectPath}/functions/.runtimeconfig.json`));
981
+ }
982
+ reject(error);
983
+ } else {
984
+ const newIndexes = require(finalPath);
985
+ if (log !== false) {
986
+ console.log(chalk.green(`Saving indexes to: ${finalPath}`));
868
987
  console.log(stdout);
869
- resolve();
988
+
989
+ const equal = (_.isEqual(newIndexes, existingIndexes));
990
+
991
+ if (!equal) {
992
+ console.log(chalk.red(`The live and local index files did not match and have been overwritten by the ${chalk.bold('live indexes')}`));
993
+ }
994
+
870
995
  }
871
- });
996
+ resolve(newIndexes);
997
+ }
872
998
  });
873
- }
999
+ });
1000
+ }
874
1001
 
875
- async function cmd_configSet(self, newPath, newValue) {
876
- return new Promise(async function(resolve, reject) {
877
- // console.log(this.options);
878
- // console.log(this.argv);
879
- newPath = newPath || await inquirer.prompt([
880
- {
881
- type: 'input',
882
- name: 'path',
883
- default: 'service.key'
884
- }
885
- ]).then(answers => answers.path)
1002
+ async function cmd_configGet(self, filePath) {
1003
+ return new Promise(function(resolve, reject) {
1004
+ const finalPath = `${self.firebaseProjectPath}/${filePath || 'functions/.runtimeconfig.json'}`;
1005
+ let cmd = exec(`firebase functions:config:get > ${finalPath}`, function (error, stdout, stderr) {
1006
+ if (error) {
1007
+ console.error(error);
1008
+ reject(error);
1009
+ } else {
1010
+ console.log(chalk.green(`Saving config to: ${finalPath}`));
1011
+ console.log(stdout);
1012
+ resolve(require(finalPath));
1013
+ }
1014
+ });
1015
+ });
1016
+ }
1017
+
1018
+ async function cmd_configSet(self, newPath, newValue) {
1019
+ return new Promise(async function(resolve, reject) {
1020
+ // console.log(this.options);
1021
+ // console.log(this.argv);
1022
+ newPath = newPath || await inquirer.prompt([
1023
+ {
1024
+ type: 'input',
1025
+ name: 'path',
1026
+ default: 'service.key'
1027
+ }
1028
+ ]).then(answers => answers.path)
886
1029
 
1030
+ try {
1031
+ const object = JSON5.parse(newPath)
887
1032
  try {
888
- const object = JSON5.parse(newPath)
889
- try {
890
- if (typeof object === 'object') {
891
- const keyify = (obj, prefix = '') =>
892
- Object.keys(obj).reduce((res, el) => {
893
- if( Array.isArray(obj[el]) ) {
894
- return res;
895
- } else if( typeof obj[el] === 'object' && obj[el] !== null ) {
896
- return [...res, ...keyify(obj[el], prefix + el + '.')];
897
- }
898
- return [...res, prefix + el];
899
- }, []);
900
- const pathArray = keyify(object);
901
- for (var i = 0; i < pathArray.length; i++) {
902
- const pathName = pathArray[i];
903
- const pathValue = _.get(object, pathName);
904
- // console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)} = ${chalk.bold(pathValue)}`));
905
- console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)}`));
906
- await cmd_configSet(self, pathName, pathValue)
907
- .catch(e => {
908
- log(chalk.red(`Failed to save object path: ${e}`));
909
- })
910
- }
911
- return resolve();
1033
+ if (typeof object === 'object') {
1034
+ const keyify = (obj, prefix = '') =>
1035
+ Object.keys(obj).reduce((res, el) => {
1036
+ if( Array.isArray(obj[el]) ) {
1037
+ return res;
1038
+ } else if( typeof obj[el] === 'object' && obj[el] !== null ) {
1039
+ return [...res, ...keyify(obj[el], prefix + el + '.')];
1040
+ }
1041
+ return [...res, prefix + el];
1042
+ }, []);
1043
+ const pathArray = keyify(object);
1044
+ for (var i = 0; i < pathArray.length; i++) {
1045
+ const pathName = pathArray[i];
1046
+ const pathValue = _.get(object, pathName);
1047
+ // console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)} = ${chalk.bold(pathValue)}`));
1048
+ console.log(chalk.blue(`Setting object: ${chalk.bold(pathName)}`));
1049
+ await cmd_configSet(self, pathName, pathValue)
1050
+ .catch(e => {
1051
+ log(chalk.red(`Failed to save object path: ${e}`));
1052
+ })
912
1053
  }
913
- } catch (e) {
914
- log(chalk.red(`Failed to save object: ${e}`));
915
- return reject(e)
1054
+ return resolve();
916
1055
  }
917
1056
  } catch (e) {
1057
+ log(chalk.red(`Failed to save object: ${e}`));
1058
+ return reject(e)
918
1059
  }
1060
+ } catch (e) {
1061
+ }
919
1062
 
920
- newValue = newValue || await inquirer.prompt([
921
- {
922
- type: 'input',
923
- name: 'value',
924
- default: '123-abc'
925
- }
926
- ]).then(answers => answers.value)
927
-
928
- let isInvalid = false;
929
- if (newPath !== newPath.toLowerCase()) {
930
- isInvalid = true;
931
- newPath = newPath.replace(/([A-Z])/g, '_$1').trim().toLowerCase();
1063
+ newValue = newValue || await inquirer.prompt([
1064
+ {
1065
+ type: 'input',
1066
+ name: 'value',
1067
+ default: '123-abc'
932
1068
  }
933
- log(chalk.yellow(`Saving to ${chalk.bold(newPath)}...`));
934
- let cmd = exec(`firebase functions:config:set ${newPath}="${newValue}"`, function (error, stdout, stderr) {
935
- if (error) {
936
- log(chalk.red(`Failed to save ${chalk.bold(newPath)}: ${error}`));
937
- reject(error);
1069
+ ]).then(answers => answers.value)
1070
+
1071
+ let isInvalid = false;
1072
+ if (newPath !== newPath.toLowerCase()) {
1073
+ isInvalid = true;
1074
+ newPath = newPath.replace(/([A-Z])/g, '_$1').trim().toLowerCase();
1075
+ }
1076
+ log(chalk.yellow(`Saving to ${chalk.bold(newPath)}...`));
1077
+ let cmd = exec(`firebase functions:config:set ${newPath}="${newValue}"`, function (error, stdout, stderr) {
1078
+ if (error) {
1079
+ log(chalk.red(`Failed to save ${chalk.bold(newPath)}: ${error}`));
1080
+ reject(error);
1081
+ } else {
1082
+ console.log(stdout);
1083
+ if (isInvalid) {
1084
+ log(chalk.red(`!!! Your path contained an invalid uppercase character`));
1085
+ log(chalk.red(`!!! It was set to: ${chalk.bold(newPath)}`));
938
1086
  } else {
939
- console.log(stdout);
940
- if (isInvalid) {
941
- log(chalk.red(`!!! Your path contained an invalid uppercase character`));
942
- log(chalk.red(`!!! It was set to: ${chalk.bold(newPath)}`));
943
- } else {
944
- log(chalk.green(`Successfully saved to ${chalk.bold(newPath)}`));
945
- }
946
- resolve();
1087
+ log(chalk.green(`Successfully saved to ${chalk.bold(newPath)}`));
947
1088
  }
948
- });
1089
+ resolve();
1090
+ }
949
1091
  });
950
- }
1092
+ });
1093
+ }
951
1094
 
952
- async function cmd_configUnset(self) {
953
- return new Promise(async function(resolve, reject) {
954
- // console.log(this.options);
955
- // console.log(this.argv);
956
- await inquirer
957
- .prompt([
958
- /* Pass your questions in here */
959
- {
960
- type: 'input',
961
- name: 'path',
962
- default: 'service.key'
1095
+ async function cmd_configUnset(self) {
1096
+ return new Promise(async function(resolve, reject) {
1097
+ // console.log(this.options);
1098
+ // console.log(this.argv);
1099
+ await inquirer
1100
+ .prompt([
1101
+ /* Pass your questions in here */
1102
+ {
1103
+ type: 'input',
1104
+ name: 'path',
1105
+ default: 'service.key'
1106
+ }
1107
+ ])
1108
+ .then(answers => {
1109
+ // Use user feedback for... whatever!!
1110
+ // console.log('answer', answers);
1111
+ log(chalk.yellow(`Deleting ${chalk.bold(answers.path)}...`));
1112
+ let cmd = exec(`firebase functions:config:unset ${answers.path}`, function (error, stdout, stderr) {
1113
+ if (error) {
1114
+ log(chalk.red(`Failed to delete ${chalk.bold(answers.path)}: ${error}`));
1115
+ reject(error);
1116
+ } else {
1117
+ console.log(stdout);
1118
+ log(chalk.green(`Successfully deleted ${chalk.bold(answers.path)}`));
1119
+ resolve();
963
1120
  }
964
- ])
965
- .then(answers => {
966
- // Use user feedback for... whatever!!
967
- // console.log('answer', answers);
968
- log(chalk.yellow(`Deleting ${chalk.bold(answers.path)}...`));
969
- let cmd = exec(`firebase functions:config:unset ${answers.path}`, function (error, stdout, stderr) {
970
- if (error) {
971
- log(chalk.red(`Failed to delete ${chalk.bold(answers.path)}: ${error}`));
972
- reject(error);
973
- } else {
974
- console.log(stdout);
975
- log(chalk.green(`Successfully deleted ${chalk.bold(answers.path)}`));
976
- resolve();
977
- }
978
- });
979
1121
  });
980
- });
981
- }
1122
+ });
1123
+ });
1124
+ }
982
1125
 
983
1126
 
984
1127
  // HELPER
@@ -7,13 +7,15 @@ const { get, merge } = require('lodash');
7
7
 
8
8
 
9
9
  function Manager(exporter, options) {
10
+ const self = this;
10
11
  // Constants
11
- this.SERVER_UUID = '11111111-1111-1111-1111-111111111111';
12
+ self.SERVER_UUID = '11111111-1111-1111-1111-111111111111';
12
13
 
13
14
  // Modable
14
- this.libraries = {};
15
- this.handlers = {};
16
- return this;
15
+ self.libraries = {};
16
+ self.handlers = {};
17
+
18
+ return self;
17
19
  }
18
20
 
19
21
  Manager.prototype.init = function (exporter, options) {
@@ -92,7 +94,7 @@ Manager.prototype.init = function (exporter, options) {
92
94
  }
93
95
 
94
96
  if (self.options.sentry) {
95
- const sentryRelease = `${self.config.app.id || self.project.projectId}@${self.package.version}`;
97
+ const sentryRelease = `${get(self.config, 'app.id') || self.project.projectId}@${self.package.version}`;
96
98
  const sentryDSN = get(self.config, 'sentry.dsn', '');
97
99
  // console.log('Sentry', sentryRelease, sentryDSN);
98
100
 
@@ -0,0 +1,4 @@
1
+ {
2
+ "indexes": [],
3
+ "fieldOverrides": []
4
+ }
File without changes
@@ -0,0 +1,8 @@
1
+ rules_version = '2';
2
+ service firebase.storage {
3
+ match /b/{bucket}/o {
4
+ match /{allPaths=**} {
5
+ allow read, write: if request.auth!=null;
6
+ }
7
+ }
8
+ }