backend-manager 2.0.27 → 2.0.30

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.27",
3
+ "version": "2.0.30",
4
4
  "description": "Quick tools for developing Firebase functions",
5
5
  "main": "src/manager/index.js",
6
6
  "bin": {
@@ -65,4 +65,4 @@
65
65
  "src/",
66
66
  "templates/"
67
67
  ]
68
- }
68
+ }
package/src/cli/cli.js CHANGED
@@ -57,57 +57,57 @@ function Main() {
57
57
  }
58
58
 
59
59
  Main.prototype.process = async function (args) {
60
- let self = this;
61
- this.options = {};
62
- this.argv = argv;
63
- this.firebaseProjectPath = process.cwd();
64
- this.firebaseProjectPath = this.firebaseProjectPath.match(/\/functions$/) ? this.firebaseProjectPath.replace(/\/functions$/, '') : this.firebaseProjectPath;
65
- this.testCount = 0;
66
- this.testTotal = 0;
67
- this.default = {};
68
- this.packageJSON = require('../../package.json');
69
- this.default.version = this.packageJSON.version;
60
+ const self = this;
61
+ self.options = {};
62
+ self.argv = argv;
63
+ self.firebaseProjectPath = process.cwd();
64
+ self.firebaseProjectPath = self.firebaseProjectPath.match(/\/functions$/) ? self.firebaseProjectPath.replace(/\/functions$/, '') : self.firebaseProjectPath;
65
+ self.testCount = 0;
66
+ self.testTotal = 0;
67
+ self.default = {};
68
+ self.packageJSON = require('../../package.json');
69
+ self.default.version = self.packageJSON.version;
70
70
 
71
71
  for (var i = 0; i < args.length; i++) {
72
- this.options[args[i]] = true;
72
+ self.options[args[i]] = true;
73
73
  }
74
74
  // console.log(args);
75
75
  // console.log(options);
76
- if (this.options.v || this.options.version || this.options['-v'] || this.options['-version']) {
77
- console.log(`Backend manager is version: ${this.default.version}`);
76
+ if (self.options.v || self.options.version || self.options['-v'] || self.options['-version']) {
77
+ console.log(`Backend manager is version: ${self.default.version}`);
78
78
  }
79
79
 
80
80
  // https://gist.github.com/timneutkens/f2933558b8739bbf09104fb27c5c9664
81
- if (this.options.clear) {
81
+ if (self.options.clear) {
82
82
  process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
83
83
  console.clear();
84
84
  process.stdout.write("\u001b[3J\u001b[2J\u001b[1J");
85
85
  }
86
- if (this.options.cwd) {
87
- console.log('cwd: ', this.firebaseProjectPath);
86
+ if (self.options.cwd) {
87
+ console.log('cwd: ', self.firebaseProjectPath);
88
88
  }
89
- if (this.options.setup) {
89
+ if (self.options.setup) {
90
90
  await cmd_configGet(self).catch(e => log(chalk.red(`Failed to run config:get`)));
91
91
  await self.setup();
92
92
  }
93
- if ((this.options.i || this.options.install) && (this.options.local || this.options.dev || this.options.development)) {
93
+ if ((self.options.i || self.options.install) && (self.options.local || self.options.dev || self.options.development)) {
94
94
  await uninstallPkg('backend-manager');
95
95
  return await installPkg('file:../../../ITW-Creative-Works/backend-manager');
96
96
  // await uninstallPkg('backend-assistant');
97
97
  // return await installPkg('file:../../backend-assistant');
98
98
  }
99
- if ((this.options.i || this.options.install) && (this.options.live || this.options.prod || this.options.production)) {
99
+ if ((self.options.i || self.options.install) && (self.options.live || self.options.prod || self.options.production)) {
100
100
  await uninstallPkg('backend-manager');
101
101
  return await installPkg('backend-manager');
102
102
  // return await installPkg('backend-assistant');
103
103
  }
104
- if (this.options.serve) {
105
- if (!this.options.quick && !this.options.q) {
104
+ if (self.options.serve) {
105
+ if (!self.options.quick && !self.options.q) {
106
106
  }
107
107
  await cmd_configGet(self);
108
108
  await self.setup();
109
109
 
110
- let port = this.argv.port || _.get(self.argv, '_', [])[1] || '5000';
110
+ let port = self.argv.port || _.get(self.argv, '_', [])[1] || '5000';
111
111
  let ls = spawn(`firebase serve --port ${port}`, {shell: true});
112
112
 
113
113
  ls.stdout.on('data', (data) => {
@@ -119,31 +119,31 @@ Main.prototype.process = async function (args) {
119
119
  });
120
120
  }
121
121
 
122
- if (this.options['firestore:indexes:get'] || this.options['firestore:indexes'] || this.options['indexes:get']) {
123
- return await cmd_indexesGet(self);
122
+ if (self.options['firestore:indexes:get'] || self.options['firestore:indexes'] || self.options['indexes:get']) {
123
+ return await cmd_indexesGet(self, undefined, true);
124
124
  }
125
125
 
126
- if (this.options['functions:config:get'] || this.options['config:get']) {
126
+ if (self.options['functions:config:get'] || self.options['config:get']) {
127
127
  return await cmd_configGet(self);
128
128
  }
129
129
 
130
- if (this.options['functions:config:set'] || this.options['config:set']) {
130
+ if (self.options['functions:config:set'] || self.options['config:set']) {
131
131
  await cmd_configSet(self);
132
132
  return await cmd_configGet(self);
133
133
  }
134
134
 
135
- if (this.options['functions:config:unset'] || this.options['config:unset'] || this.options['config:delete'] || this.options['config:remove']) {
135
+ if (self.options['functions:config:unset'] || self.options['config:unset'] || self.options['config:delete'] || self.options['config:remove']) {
136
136
  await cmd_configUnset(self);
137
137
  return await cmd_configGet(self);
138
138
  }
139
139
 
140
- if (this.options['rules:default'] || this.options['rules:getdefault']) {
140
+ if (self.options['rules:default'] || self.options['rules:getdefault']) {
141
141
  self.getRulesFile();
142
142
  console.log(self.default.firestoreRulesWhole.match(bem_fsRulesDefaultRegex)[0].replace(' ///', '///'));
143
143
  return;
144
144
  }
145
145
 
146
- if (this.options.deploy) {
146
+ if (self.options.deploy) {
147
147
  await self.setup();
148
148
 
149
149
  // Quick check that not using local packages
@@ -166,7 +166,7 @@ Main.prototype.process = async function (args) {
166
166
  });
167
167
 
168
168
  }
169
- if (this.options['test']) {
169
+ if (self.options['test']) {
170
170
  await self.setup();
171
171
  // firebase emulators:exec --only firestore 'npm test'
172
172
  // let ls = spawn('firebase', ['emulators:exec', '--only', 'firestore', 'npm test']);
@@ -180,7 +180,7 @@ Main.prototype.process = async function (args) {
180
180
  });
181
181
  }
182
182
 
183
- if (this.options['clean:npm']) {
183
+ if (self.options['clean:npm']) {
184
184
  // await self.setup();
185
185
  // firebase emulators:exec --only firestore 'npm test'
186
186
  let ls = spawn(`${NPM_CLEAN_SCRIPT}`, {shell: true});
@@ -192,10 +192,10 @@ Main.prototype.process = async function (args) {
192
192
  });
193
193
  }
194
194
 
195
- // if (this.options['url']) {
195
+ // if (self.options['url']) {
196
196
  // // await self.setup();
197
197
  // // firebase emulators:exec --only firestore 'npm test'
198
- // log(this.projectUrl)
198
+ // log(self.projectUrl)
199
199
  // }
200
200
 
201
201
  };
@@ -204,23 +204,25 @@ module.exports = Main;
204
204
 
205
205
 
206
206
  Main.prototype.getRulesFile = function () {
207
- let self = this;
208
- this.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `-${self.default.version}-`);
209
- this.default.firestoreRulesCore = this.default.firestoreRulesWhole.match(bem_fsRulesRegex)[0];
207
+ const self = this;
208
+ self.default.firestoreRulesWhole = (jetpack.read(path.resolve(`${__dirname}/../../templates/firestore.rules`))).replace('=0.0.0-', `-${self.default.version}-`);
209
+ self.default.firestoreRulesCore = self.default.firestoreRulesWhole.match(bem_fsRulesRegex)[0];
210
210
 
211
211
  };
212
212
 
213
213
  Main.prototype.setup = async function () {
214
- let self = this;
214
+ const self = this;
215
215
  let cwd = jetpack.cwd();
216
- log(chalk.green(`\n---- RUNNING v${this.default.version} SETUP ----`));
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`) || '';
223
- if (!this.package) {
216
+ log(chalk.green(`\n---- RUNNING SETUP v${self.default.version} ----`));
217
+ self.package = jetpack.read(`${self.firebaseProjectPath}/functions/package.json`) || '{}';
218
+ self.firebaseJSON = jetpack.read(`${self.firebaseProjectPath}/firebase.json`) || '{}';
219
+ self.firebaseRC = jetpack.read(`${self.firebaseProjectPath}/.firebaserc`) || '{}';
220
+ self.runtimeConfigJSON = jetpack.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}';
221
+ self.remoteconfigJSON = jetpack.read(`${self.firebaseProjectPath}/remoteconfig.template.json`) || '{}';
222
+ self.projectPackage = jetpack.read(`${self.firebaseProjectPath}/package.json`) || '{}';
223
+
224
+ self.gitignore = jetpack.read(`${self.firebaseProjectPath}/functions/.gitignore`) || '';
225
+ if (!self.package) {
224
226
  log(chalk.red(`Missing functions/package.json :(`));
225
227
  return;
226
228
  }
@@ -230,34 +232,37 @@ Main.prototype.setup = async function () {
230
232
  return;
231
233
  }
232
234
 
233
- this.package = JSON.parse(this.package);
234
- this.firebaseJSON = JSON.parse(this.firebaseJSON);
235
- this.firebaseRC = JSON.parse(this.firebaseRC);
236
- this.runtimeConfigJSON = JSON.parse(this.runtimeConfigJSON);
237
- this.projectPackage = JSON.parse(this.projectPackage);
235
+ self.package = JSON.parse(self.package);
236
+ self.firebaseJSON = JSON.parse(self.firebaseJSON);
237
+ self.firebaseRC = JSON.parse(self.firebaseRC);
238
+ self.runtimeConfigJSON = JSON.parse(self.runtimeConfigJSON);
239
+ self.remoteconfigJSON = JSON.parse(self.remoteconfigJSON);
240
+ self.projectPackage = JSON.parse(self.projectPackage);
241
+
242
+ self.remoteconfigJSONExists = Object.keys(self.remoteconfigJSON).length > 0;
238
243
 
239
244
  self.getRulesFile();
240
245
 
241
- this.default.firestoreRulesVersionRegex = new RegExp(`///---version-${self.default.version}---///`)
246
+ self.default.firestoreRulesVersionRegex = new RegExp(`///---version-${self.default.version}---///`)
242
247
  // bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)).replace(/\./g, '\\.'), 'm' )
243
248
  bem_giRegex = new RegExp(jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`)), 'm' )
244
249
 
245
250
  // tests
246
- this.projectName = this.firebaseRC.projects.default;
247
- this.projectUrl = `https://console.firebase.google.com/project/${this.projectName}`;
248
- log(chalk.black(`Id: `, chalk.bold(`${this.projectName}`)));
249
- log(chalk.black(`Url:`, chalk.bold(`${this.projectUrl}`)));
251
+ self.projectName = self.firebaseRC.projects.default;
252
+ self.projectUrl = `https://console.firebase.google.com/project/${self.projectName}`;
253
+ log(chalk.black(`Id: `, chalk.bold(`${self.projectName}`)));
254
+ log(chalk.black(`Url:`, chalk.bold(`${self.projectUrl}`)));
250
255
 
251
256
  if (!self.package || !self.package.engines || !self.package.engines.node) {
252
257
  throw new Error('Missing <engines.node> in package.json')
253
258
  }
254
259
 
255
- await this.test('is a firebase project', async function () {
260
+ await self.test('is a firebase project', async function () {
256
261
  let exists = jetpack.exists(`${self.firebaseProjectPath}/firebase.json`);
257
262
  return exists;
258
263
  }, fix_isFirebase);
259
264
 
260
- await this.test('.nvmrc file has proper version', async function () {
265
+ await self.test('.nvmrc file has proper version', async function () {
261
266
  // return !!self.package.dependencies && !!self.package.devDependencies;
262
267
  // let gitignore = jetpack.read(path.resolve(`${__dirname}/../../templates/gitignore.md`));
263
268
  let nvmrc = jetpack.read(`${self.firebaseProjectPath}/functions/.nvmrc`) || '';
@@ -265,7 +270,7 @@ Main.prototype.setup = async function () {
265
270
 
266
271
  }, fix_nvmrc);
267
272
 
268
- await this.test(`using node ${CLI_CONFIG.node}`, function () {
273
+ await self.test(`using node ${CLI_CONFIG.node}`, function () {
269
274
  let processMajor = parseInt(process.versions.node.split('.')[0]);
270
275
  let engineMajor = parseInt(self.package.engines.node.split('.')[0]);
271
276
  if (processMajor < engineMajor) {
@@ -274,19 +279,19 @@ Main.prototype.setup = async function () {
274
279
  return self.package.engines.node.toString() === CLI_CONFIG.node && processMajor >= engineMajor;
275
280
  }, fix_nodeVersion);
276
281
 
277
- // await this.test('project level package.json exists', async function () {
282
+ // await self.test('project level package.json exists', async function () {
278
283
  // return !!(self.projectPackage && self.projectPackage.version && self.projectPackage.name);
279
284
  // }, fix_projpackage);
280
285
 
281
- await this.test('functions level package.json exists', async function () {
286
+ await self.test('functions level package.json exists', async function () {
282
287
  return !!self.package && !!self.package.dependencies && !!self.package.devDependencies && !!self.package.version;
283
288
  }, fix_functionspackage);
284
289
 
285
- // await this.test('functions level package.json has updated version', async function () {
290
+ // await self.test('functions level package.json has updated version', async function () {
286
291
  // return self.package.version === self.projectPackage.version;
287
292
  // }, fix_packageversion);
288
293
 
289
- await this.test('using updated firebase-admin', async function () {
294
+ await self.test('using updated firebase-admin', async function () {
290
295
  let pkg = 'firebase-admin';
291
296
  // let latest = semver.clean(await getPkgVersion(pkg));
292
297
  let latest = semver.clean(cleanPackageVersion(self.packageJSON.dependencies['firebase-admin']));
@@ -302,7 +307,7 @@ Main.prototype.setup = async function () {
302
307
  return !(semver.gt(latest, mine)) || majorVersionMismatch;
303
308
  }, fix_fba);
304
309
 
305
- await this.test('using updated firebase-functions', async function () {
310
+ await self.test('using updated firebase-functions', async function () {
306
311
  let pkg = 'firebase-functions';
307
312
  // let latest = semver.clean(await getPkgVersion(pkg));
308
313
  let latest = semver.clean(cleanPackageVersion(self.packageJSON.dependencies['firebase-functions']));
@@ -318,7 +323,7 @@ Main.prototype.setup = async function () {
318
323
  return !(semver.gt(latest, mine)) || majorVersionMismatch;
319
324
  }, fix_fbf);
320
325
 
321
- await this.test('using updated backend-manager', async function () {
326
+ await self.test('using updated backend-manager', async function () {
322
327
  let pkg = 'backend-manager';
323
328
  let latest = semver.clean(await getPkgVersion(pkg));
324
329
  let mine = cleanPackageVersion(self.package.dependencies[pkg] || '0.0.0');
@@ -338,35 +343,35 @@ Main.prototype.setup = async function () {
338
343
  bemPackageVersionWarning(pkg, bemv, latest);
339
344
  }());
340
345
 
341
- // await this.test('using updated backend-assistant', async function () {
346
+ // await self.test('using updated backend-assistant', async function () {
342
347
  // let pkg = 'backend-assistant';
343
348
  // let latest = semver.clean(await getPkgVersion(pkg));
344
349
  // let mine = (self.package.dependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
345
350
  // return isLocal(mine) || !(semver.gt(latest, mine));
346
351
  // }, fix_bea);
347
352
 
348
- // await this.test('using updated ultimate-jekyll-poster', async function () {
353
+ // await self.test('using updated ultimate-jekyll-poster', async function () {
349
354
  // let pkg = 'ultimate-jekyll-poster';
350
355
  // let latest = semver.clean(await getPkgVersion(pkg));
351
356
  // let mine = (self.package.dependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
352
357
  // return isLocal(mine) || !(semver.gt(latest, mine));
353
358
  // }, fix_ujp);
354
359
 
355
- // await this.test('using updated @firebase/testing', async function () {
360
+ // await self.test('using updated @firebase/testing', async function () {
356
361
  // let pkg = '@firebase/testing';
357
362
  // let latest = semver.clean(await getPkgVersion(pkg));
358
363
  // let mine = (self.package.devDependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
359
364
  // return isLocal(mine) || !(semver.gt(latest, mine));
360
365
  // }, fix_fbTesting);
361
366
 
362
- // await this.test('using updated mocha', async function () {
367
+ // await self.test('using updated mocha', async function () {
363
368
  // let pkg = 'mocha';
364
369
  // let latest = semver.clean(await getPkgVersion(pkg));
365
370
  // let mine = (self.package.devDependencies[pkg] || '0.0.0').replace('^', '').replace('~', '');
366
371
  // return isLocal(mine) || !(semver.gt(latest, mine));
367
372
  // }, fix_mocha);
368
373
 
369
- await this.test('using proper .runtimeconfig', async function () {
374
+ await self.test('using proper .runtimeconfig', async function () {
370
375
  let runtimeconfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/.runtimeconfig.json`) || '{}');
371
376
  let ogPaths = getObjectPaths(runtimeconfigTemplate).split('\n');
372
377
  let pass = true;
@@ -382,7 +387,7 @@ Main.prototype.setup = async function () {
382
387
 
383
388
  }, fix_runtimeConfig);
384
389
 
385
- await this.test('using proper backend-manager-config.json', async function () {
390
+ await self.test('using proper backend-manager-config.json', async function () {
386
391
  let bemConfig = JSON.parse(jetpack.read(`${self.firebaseProjectPath}/functions/backend-manager-config.json`) || '{}');
387
392
  let ogPaths = getObjectPaths(bemConfigTemplate).split('\n');
388
393
  let pass = true;
@@ -398,12 +403,12 @@ Main.prototype.setup = async function () {
398
403
 
399
404
  }, fix_bemConfig);
400
405
 
401
- await this.test('has service-account.json', function () {
406
+ await self.test('has service-account.json', function () {
402
407
  let exists = jetpack.exists(`${self.firebaseProjectPath}/functions/service-account.json`);
403
408
  return !!exists;
404
409
  }, fix_serviceAccount);
405
410
 
406
- await this.test('has correct .gitignore', function () {
411
+ await self.test('has correct .gitignore', function () {
407
412
  let match = self.gitignore.match(bem_giRegexOuter);
408
413
  if (!match) {
409
414
  return false;
@@ -417,32 +422,37 @@ Main.prototype.setup = async function () {
417
422
 
418
423
 
419
424
  // Check firebase.json fields
420
- await this.test('firestore rules in JSON', function () {
425
+ await self.test('firestore rules in JSON', function () {
421
426
  const firestore = _.get(self.firebaseJSON, 'firestore', {});
422
427
  return (firestore.rules === 'firestore.rules')
423
428
  }, fix_firestoreRules);
424
429
 
425
- await this.test('firestore indexes in JSON', function () {
430
+ await self.test('firestore indexes in JSON', function () {
426
431
  let firestore = _.get(self.firebaseJSON, 'firestore', {});
427
432
  return (firestore.indexes === 'firestore.indexes.json')
428
433
  }, fix_firestoreIndexes);
429
434
 
430
- await this.test('realtime rules in JSON', function () {
435
+ await self.test('realtime rules in JSON', function () {
431
436
  const database = _.get(self.firebaseJSON, 'database', {});
432
437
  return (database.rules === 'database.rules.json')
433
438
  }, fix_realtimeRules);
434
439
 
435
- await this.test('storage rules in JSON', function () {
440
+ await self.test('storage rules in JSON', function () {
436
441
  const storage = _.get(self.firebaseJSON, 'storage', {});
437
442
  return (storage.rules === 'storage.rules')
438
443
  }, fix_storageRules);
439
444
 
440
- await this.test('remoteconfig template in JSON', function () {
445
+ await self.test('remoteconfig template in JSON', function () {
441
446
  const remoteconfig = _.get(self.firebaseJSON, 'remoteconfig', {});
442
- return (remoteconfig.template === 'remoteconfig.template.json')
447
+
448
+ if (self.remoteconfigJSONExists) {
449
+ return (remoteconfig.template === 'remoteconfig.template.json')
450
+ } else {
451
+ return (remoteconfig.template === '')
452
+ }
443
453
  }, fix_remoteconfigTemplate);
444
454
 
445
- await this.test('firestore indexes synced', async function () {
455
+ await self.test('firestore indexes synced', async function () {
446
456
  const tempPath = '_firestore.indexes.json'
447
457
  const liveIndexes = await cmd_indexesGet(self, tempPath, false);
448
458
 
@@ -454,7 +464,10 @@ Main.prototype.setup = async function () {
454
464
  const equal = _.isEqual(liveIndexes, localIndexes);
455
465
 
456
466
  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.`));
467
+ console.log(chalk.red(`To fix this...`));
468
+ console.log(chalk.red(` - ${chalk.bold('npx bm indexes:get')} to overwrite Firestore's local indexes with the live indexes`));
469
+ console.log(chalk.red(' OR'));
470
+ console.log(chalk.red(` - ${chalk.bold('firebase deploy --only firestore:indexes')} to replace the live indexes.`));
458
471
  }
459
472
 
460
473
  jetpack.remove(`${self.firebaseProjectPath}/${tempPath}`)
@@ -464,7 +477,7 @@ Main.prototype.setup = async function () {
464
477
 
465
478
 
466
479
  // Update actual files
467
- await this.test('update firestore rules file', function () {
480
+ await self.test('update firestore rules file', function () {
468
481
  let exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.rules`);
469
482
  let contents = jetpack.read(`${self.firebaseProjectPath}/firestore.rules`) || '';
470
483
  let containsCore = contents.match(bem_fsRulesRegex);
@@ -473,45 +486,45 @@ Main.prototype.setup = async function () {
473
486
  return (!!exists && !!containsCore && !!matchesVersion);
474
487
  }, fix_firestoreRulesFile);
475
488
 
476
- await this.test('update firestore indexes file', function () {
489
+ await self.test('update firestore indexes file', function () {
477
490
  let exists = jetpack.exists(`${self.firebaseProjectPath}/firestore.indexes.json`);
478
491
  return (!!exists);
479
492
  }, fix_firestoreIndexesFile);
480
493
 
481
- await this.test('update realtime rules file', function () {
494
+ await self.test('update realtime rules file', function () {
482
495
  let exists = jetpack.exists(`${self.firebaseProjectPath}/database.rules.json`);
483
496
  return (!!exists);
484
497
  }, fix_realtimeRulesFile);
485
498
 
486
- await this.test('update storage rules file', function () {
499
+ await self.test('update storage rules file', function () {
487
500
  let exists = jetpack.exists(`${self.firebaseProjectPath}/storage.rules`);
488
501
  return (!!exists);
489
502
  }, fix_storageRulesFile);
490
503
 
491
- await this.test('update remoteconfig template file', function () {
504
+ await self.test('update remoteconfig template file', function () {
492
505
  let exists = jetpack.exists(`${self.firebaseProjectPath}/remoteconfig.template.json`);
493
506
  return (!!exists);
494
507
  }, fix_remoteconfigTemplateFile);
495
508
 
496
509
  // Hosting
497
- await this.test('hosting is set to dedicated folder in JSON', function () {
510
+ await self.test('hosting is set to dedicated folder in JSON', function () {
498
511
  let hosting = _.get(self.firebaseJSON, 'hosting', {});
499
512
  return (hosting.public && (hosting.public === 'public' || hosting.public !== '.'))
500
513
  }, fix_firebaseHosting);
501
514
 
502
- await this.test('update backend-manager-tests.js', function () {
515
+ await self.test('update backend-manager-tests.js', function () {
503
516
  jetpack.write(`${self.firebaseProjectPath}/test/backend-manager-tests.js`,
504
517
  (jetpack.read(path.resolve(`${__dirname}/../../templates/backend-manager-tests.js`)))
505
518
  )
506
519
  return true;
507
520
  }, NOFIX);
508
521
 
509
- // await this.test('has mocha package.json script', function () {
522
+ // await self.test('has mocha package.json script', function () {
510
523
  // let script = _.get(self.package, 'scripts.test', '')
511
524
  // return script === MOCHA_PKG_SCRIPT;
512
525
  // }, fix_mochaScript);
513
526
 
514
- // await this.test('has clean:npm package.json script', function () {
527
+ // await self.test('has clean:npm package.json script', function () {
515
528
  // let script = _.get(self.package, 'scripts.clean:npm', '')
516
529
  // return script === NPM_CLEAN_SCRIPT;
517
530
  // }, fix_cleanNpmScript);
@@ -526,8 +539,8 @@ Main.prototype.setup = async function () {
526
539
  }
527
540
 
528
541
 
529
- const prepareStatsURL = `https://us-central1-${_.get(this.firebaseRC, 'projects.default')}.cloudfunctions.net/bm_api?authenticationToken=${_.get(this.runtimeConfigJSON, 'backend_manager.key')}`;
530
- // const prepareStatsURL = `https://us-central1-${_.get(this.firebaseRC, 'projects.default')}.cloudfunctions.net/bm_api?authenticationToken=undefined`;
542
+ const prepareStatsURL = `https://us-central1-${_.get(self.firebaseRC, 'projects.default')}.cloudfunctions.net/bm_api?authenticationToken=${_.get(self.runtimeConfigJSON, 'backend_manager.key')}`;
543
+ // const prepareStatsURL = `https://us-central1-${_.get(self.firebaseRC, 'projects.default')}.cloudfunctions.net/bm_api?authenticationToken=undefined`;
531
544
  const statsFetchResult = await fetch(prepareStatsURL, {
532
545
  method: 'post',
533
546
  body: JSON.stringify({
@@ -597,7 +610,7 @@ function getObjectPaths(object, parent) {
597
610
  }
598
611
 
599
612
  Main.prototype.test = async function(name, fn, fix, args) {
600
- let self = this;
613
+ const self = this;
601
614
  let status;
602
615
  let passed = await fn();
603
616
  return new Promise(async function(resolve, reject) {
@@ -772,7 +785,12 @@ async function fix_fba(self) {
772
785
  return await installPkg('firebase-admin', `@${self.packageJSON.dependencies['firebase-admin']}`)
773
786
  };
774
787
  async function fix_bem(self) {
775
- return await installPkg('backend-manager')
788
+ await installPkg('backend-manager');
789
+
790
+ console.log(chalk.green(`Process has exited since a new version of backend-manager was installed. Run ${chalk.bold('npx bm setup')} again.`));
791
+ process.exit(0);
792
+
793
+ return;
776
794
  };
777
795
  // async function fix_bea(self) {
778
796
  // return await installPkg('backend-assistant')
@@ -837,7 +855,7 @@ function fix_storageRules(self) {
837
855
 
838
856
  function fix_remoteconfigTemplate(self) {
839
857
  return new Promise(function(resolve, reject) {
840
- _.set(self.firebaseJSON, 'remoteconfig.template', 'remoteconfig.template.json')
858
+ _.set(self.firebaseJSON, 'remoteconfig.template', self.remoteconfigJSONExists ? 'remoteconfig.template.json' : '')
841
859
  jetpack.write(`${self.firebaseProjectPath}/firebase.json`, JSON.stringify(self.firebaseJSON, null, 2));
842
860
  resolve();
843
861
  });
@@ -1017,8 +1035,8 @@ async function cmd_configGet(self, filePath) {
1017
1035
 
1018
1036
  async function cmd_configSet(self, newPath, newValue) {
1019
1037
  return new Promise(async function(resolve, reject) {
1020
- // console.log(this.options);
1021
- // console.log(this.argv);
1038
+ // console.log(self.options);
1039
+ // console.log(self.argv);
1022
1040
  newPath = newPath || await inquirer.prompt([
1023
1041
  {
1024
1042
  type: 'input',
@@ -1094,8 +1112,8 @@ async function cmd_configSet(self, newPath, newValue) {
1094
1112
 
1095
1113
  async function cmd_configUnset(self) {
1096
1114
  return new Promise(async function(resolve, reject) {
1097
- // console.log(this.options);
1098
- // console.log(this.argv);
1115
+ // console.log(self.options);
1116
+ // console.log(self.argv);
1099
1117
  await inquirer
1100
1118
  .prompt([
1101
1119
  /* Pass your questions in here */
@@ -11,7 +11,7 @@ Module.prototype.main = function () {
11
11
 
12
12
  return new Promise(async function(resolve, reject) {
13
13
 
14
- if (payload.user.authenticated || payload.user.roles.admin) {
14
+ if (payload.user.roles.admin) {
15
15
 
16
16
  // console.log('---payload.data.payload', payload.data.payload);
17
17
 
@@ -1,6 +1,31 @@
1
1
  {
2
2
  "rules": {
3
- ".read": true,
4
- ".write": true
3
+ "gatherings": {
4
+ ".read": false,
5
+ ".write": false,
6
+ "online": {
7
+ ".read": "auth.uid != null && query.equalTo == auth.uid",
8
+ ".write": false,
9
+ ".indexOn": ["uid"],
10
+ "$uid": {
11
+ ".read": "
12
+ // Allowed if user is signed in AND is the owner of the doc
13
+ (auth != null && auth.uid == data.child('uid').val())
14
+ ",
15
+ ".write": "
16
+ // Allowed if the user is signed in AND is the owner of the existing doc
17
+ (auth != null && auth.uid == data.child('uid').val())
18
+ // Allowed if the user is signed in AND is the owner of the new doc
19
+ || (auth != null && auth.uid == newData.child('uid').val())
20
+ // Allowed if it's a delete
21
+ || (!newData.exists())
22
+ // Allowed if the existing doc has no owner
23
+ || (data.child('uid').val() == '')
24
+ // Allowed if the new doc has no owner
25
+ || (newData.child('uid').val() == '')
26
+ ",
27
+ }
28
+ }
29
+ }
5
30
  }
6
31
  }