firebase-tools 11.0.0 → 11.2.0

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 (223) hide show
  1. package/lib/accountExporter.js +11 -4
  2. package/lib/accountImporter.js +93 -95
  3. package/lib/api.js +77 -218
  4. package/lib/apiv2.js +5 -4
  5. package/lib/appdistribution/client.js +23 -34
  6. package/lib/auth.js +72 -52
  7. package/lib/bin/firebase.js +42 -47
  8. package/lib/checkValidTargetFilters.js +36 -25
  9. package/lib/commands/appdistribution-distribute.js +2 -1
  10. package/lib/commands/appdistribution-testers-add.js +2 -1
  11. package/lib/commands/appdistribution-testers-remove.js +2 -1
  12. package/lib/commands/apps-android-sha-create.js +2 -1
  13. package/lib/commands/apps-android-sha-delete.js +2 -1
  14. package/lib/commands/apps-android-sha-list.js +2 -1
  15. package/lib/commands/apps-create.js +2 -1
  16. package/lib/commands/apps-list.js +2 -1
  17. package/lib/commands/apps-sdkconfig.js +2 -1
  18. package/lib/commands/auth-export.js +2 -1
  19. package/lib/commands/auth-import.js +7 -10
  20. package/lib/commands/crashlytics-symbols-upload.js +2 -1
  21. package/lib/commands/database-get.js +4 -3
  22. package/lib/commands/database-instances-create.js +2 -1
  23. package/lib/commands/database-instances-list.js +3 -3
  24. package/lib/commands/database-profile.js +4 -4
  25. package/lib/commands/database-push.js +4 -4
  26. package/lib/commands/database-remove.js +3 -3
  27. package/lib/commands/database-rules-canary.js +2 -1
  28. package/lib/commands/database-rules-get.js +2 -1
  29. package/lib/commands/database-rules-list.js +2 -1
  30. package/lib/commands/database-rules-release.js +2 -1
  31. package/lib/commands/database-rules-stage.js +2 -1
  32. package/lib/commands/database-set.js +3 -3
  33. package/lib/commands/database-settings-get.js +2 -1
  34. package/lib/commands/database-settings-set.js +2 -1
  35. package/lib/commands/database-update.js +2 -1
  36. package/lib/commands/deploy.js +26 -25
  37. package/lib/commands/emulators-exec.js +2 -1
  38. package/lib/commands/emulators-export.js +2 -1
  39. package/lib/commands/emulators-start.js +2 -1
  40. package/lib/commands/experimental-functions-shell.js +10 -8
  41. package/lib/commands/ext-configure.js +6 -1
  42. package/lib/commands/ext-dev-deprecate.js +2 -1
  43. package/lib/commands/ext-dev-emulators-exec.js +3 -2
  44. package/lib/commands/ext-dev-emulators-start.js +3 -2
  45. package/lib/commands/ext-dev-extension-delete.js +2 -1
  46. package/lib/commands/ext-dev-init.js +2 -1
  47. package/lib/commands/ext-dev-list.js +8 -8
  48. package/lib/commands/ext-dev-publish.js +2 -1
  49. package/lib/commands/ext-dev-register.js +2 -1
  50. package/lib/commands/ext-dev-undeprecate.js +2 -1
  51. package/lib/commands/ext-dev-unpublish.js +2 -1
  52. package/lib/commands/ext-dev-usage.js +2 -1
  53. package/lib/commands/ext-export.js +2 -1
  54. package/lib/commands/ext-info.js +14 -14
  55. package/lib/commands/ext-install.js +6 -1
  56. package/lib/commands/ext-list.js +2 -1
  57. package/lib/commands/ext-sources-create.js +2 -1
  58. package/lib/commands/ext-uninstall.js +7 -1
  59. package/lib/commands/ext-update.js +6 -1
  60. package/lib/commands/ext.js +4 -4
  61. package/lib/commands/firestore-delete.js +2 -1
  62. package/lib/commands/firestore-indexes-list.js +2 -1
  63. package/lib/commands/functions-config-clone.js +4 -3
  64. package/lib/commands/functions-config-export.js +2 -1
  65. package/lib/commands/functions-config-get.js +2 -1
  66. package/lib/commands/functions-config-set.js +2 -1
  67. package/lib/commands/functions-config-unset.js +2 -1
  68. package/lib/commands/functions-delete.js +3 -8
  69. package/lib/commands/functions-deletegcfartifacts.js +2 -1
  70. package/lib/commands/functions-list.js +2 -1
  71. package/lib/commands/functions-log.js +2 -1
  72. package/lib/commands/functions-secrets-access.js +2 -1
  73. package/lib/commands/functions-secrets-destroy.js +2 -1
  74. package/lib/commands/functions-secrets-get.js +2 -1
  75. package/lib/commands/functions-secrets-prune.js +2 -1
  76. package/lib/commands/functions-secrets-set.js +2 -1
  77. package/lib/commands/functions-shell.js +12 -10
  78. package/lib/commands/help.js +2 -1
  79. package/lib/commands/hosting-channel-create.js +2 -1
  80. package/lib/commands/hosting-channel-delete.js +2 -1
  81. package/lib/commands/hosting-channel-deploy.js +2 -1
  82. package/lib/commands/hosting-channel-list.js +2 -1
  83. package/lib/commands/hosting-channel-open.js +2 -1
  84. package/lib/commands/hosting-clone.js +2 -1
  85. package/lib/commands/hosting-disable.js +2 -1
  86. package/lib/commands/hosting-sites-create.js +2 -1
  87. package/lib/commands/hosting-sites-delete.js +2 -1
  88. package/lib/commands/hosting-sites-get.js +2 -1
  89. package/lib/commands/hosting-sites-list.js +2 -1
  90. package/lib/commands/index.js +23 -13
  91. package/lib/commands/init.js +47 -43
  92. package/lib/commands/login-add.js +2 -1
  93. package/lib/commands/login-ci.js +2 -1
  94. package/lib/commands/login-list.js +2 -1
  95. package/lib/commands/login-use.js +2 -1
  96. package/lib/commands/login.js +2 -1
  97. package/lib/commands/logout.js +2 -1
  98. package/lib/commands/open.js +7 -7
  99. package/lib/commands/projects-addfirebase.js +2 -1
  100. package/lib/commands/projects-create.js +2 -1
  101. package/lib/commands/projects-list.js +2 -1
  102. package/lib/commands/remoteconfig-get.js +2 -1
  103. package/lib/commands/remoteconfig-rollback.js +2 -1
  104. package/lib/commands/remoteconfig-versions-list.js +2 -1
  105. package/lib/commands/serve.js +30 -30
  106. package/lib/commands/setup-emulators-database.js +2 -1
  107. package/lib/commands/setup-emulators-firestore.js +2 -1
  108. package/lib/commands/setup-emulators-pubsub.js +2 -1
  109. package/lib/commands/setup-emulators-storage.js +2 -1
  110. package/lib/commands/setup-emulators-ui.js +2 -1
  111. package/lib/commands/target-apply.js +2 -1
  112. package/lib/commands/target-clear.js +2 -1
  113. package/lib/commands/target-remove.js +2 -1
  114. package/lib/commands/target.js +2 -1
  115. package/lib/commands/use.js +54 -53
  116. package/lib/config.js +7 -6
  117. package/lib/deploy/database/deploy.js +3 -2
  118. package/lib/deploy/database/index.js +8 -5
  119. package/lib/deploy/database/prepare.js +22 -20
  120. package/lib/deploy/database/release.js +12 -9
  121. package/lib/deploy/extensions/secrets.js +3 -3
  122. package/lib/deploy/firestore/prepare.js +2 -2
  123. package/lib/deploy/functions/build.js +33 -20
  124. package/lib/deploy/functions/ensure.js +1 -11
  125. package/lib/deploy/functions/prepare.js +3 -13
  126. package/lib/deploy/functions/prepareFunctionsUpload.js +2 -3
  127. package/lib/deploy/functions/release/fabricator.js +0 -1
  128. package/lib/deploy/functions/release/index.js +1 -5
  129. package/lib/deploy/functions/runtimes/discovery/index.js +18 -3
  130. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +188 -54
  131. package/lib/deploy/functions/runtimes/golang/index.js +2 -22
  132. package/lib/deploy/functions/runtimes/node/index.js +3 -7
  133. package/lib/deploy/functions/runtimes/node/parseTriggers.js +15 -3
  134. package/lib/deploy/functions/services/database.js +14 -0
  135. package/lib/deploy/functions/services/index.js +14 -0
  136. package/lib/deploy/index.js +3 -3
  137. package/lib/deploy/lifecycleHooks.js +27 -27
  138. package/lib/deploy/remoteconfig/functions.js +18 -14
  139. package/lib/deploy/remoteconfig/prepare.js +2 -2
  140. package/lib/deploy/storage/prepare.js +1 -1
  141. package/lib/emulator/auth/apiSpec.js +14 -46
  142. package/lib/emulator/auth/index.js +1 -1
  143. package/lib/emulator/auth/operations.js +342 -93
  144. package/lib/emulator/auth/server.js +2 -2
  145. package/lib/emulator/auth/state.js +34 -32
  146. package/lib/emulator/commandUtils.js +1 -1
  147. package/lib/emulator/constants.js +1 -1
  148. package/lib/emulator/controller.js +7 -6
  149. package/lib/emulator/databaseEmulator.js +11 -9
  150. package/lib/emulator/download.js +1 -1
  151. package/lib/emulator/events/types.js +2 -3
  152. package/lib/emulator/firestoreEmulator.js +12 -14
  153. package/lib/emulator/functionsEmulator.js +65 -77
  154. package/lib/emulator/functionsEmulatorRuntime.js +7 -7
  155. package/lib/emulator/hostingEmulator.js +1 -1
  156. package/lib/emulator/hub.js +1 -1
  157. package/lib/emulator/hubClient.js +11 -22
  158. package/lib/emulator/hubExport.js +26 -16
  159. package/lib/emulator/loggingEmulator.js +1 -1
  160. package/lib/emulator/pubsubEmulator.js +1 -1
  161. package/lib/emulator/storage/crc.js +4 -4
  162. package/lib/emulator/storage/index.js +1 -1
  163. package/lib/emulator/types.js +1 -1
  164. package/lib/errorOut.js +2 -2
  165. package/lib/extensions/askUserForConsent.js +1 -2
  166. package/lib/extensions/askUserForParam.js +15 -18
  167. package/lib/extensions/emulator/optionsHelper.js +4 -4
  168. package/lib/extensions/extensionsApi.js +1 -22
  169. package/lib/extensions/extensionsHelper.js +6 -6
  170. package/lib/extensions/listExtensions.js +9 -10
  171. package/lib/extensions/manifest.js +2 -2
  172. package/lib/extensions/resolveSource.js +11 -7
  173. package/lib/extensions/secretsUtils.js +3 -3
  174. package/lib/extensions/types.js +24 -0
  175. package/lib/extensions/updateHelper.js +1 -1
  176. package/lib/extensions/utils.js +1 -2
  177. package/lib/extensions/warnings.js +3 -3
  178. package/lib/firestore/checkDatabaseType.js +4 -5
  179. package/lib/firestore/encodeFirestoreValue.js +11 -8
  180. package/lib/firestore/indexes.js +17 -34
  181. package/lib/fsAsync.js +3 -3
  182. package/lib/functions/events/v2.js +7 -1
  183. package/lib/functionsConfig.js +17 -14
  184. package/lib/functionsConfigClone.js +46 -46
  185. package/lib/gcp/cloudfunctions.js +2 -15
  186. package/lib/gcp/cloudfunctionsv2.js +17 -2
  187. package/lib/gcp/iam.js +1 -1
  188. package/lib/gcp/index.js +10 -10
  189. package/lib/gcp/rules.js +1 -1
  190. package/lib/gcp/runtimeconfig.js +45 -47
  191. package/lib/gcp/storage.js +2 -4
  192. package/lib/hosting/cloudRunProxy.js +19 -15
  193. package/lib/hosting/proxy.js +1 -1
  194. package/lib/index.js +29 -28
  195. package/lib/init/features/database.js +11 -5
  196. package/lib/init/features/functions/index.js +1 -1
  197. package/lib/init/features/functions/javascript.js +23 -20
  198. package/lib/init/features/functions/npm-dependencies.js +17 -14
  199. package/lib/init/features/functions/typescript.js +27 -24
  200. package/lib/init/features/hosting/github.js +6 -5
  201. package/lib/init/features/hosting/index.js +2 -2
  202. package/lib/loadCJSON.js +9 -6
  203. package/lib/localFunction.js +4 -4
  204. package/lib/logError.js +15 -12
  205. package/lib/management/apps.js +47 -43
  206. package/lib/management/database.js +33 -31
  207. package/lib/management/projects.js +13 -7
  208. package/lib/parseBoltRules.js +15 -14
  209. package/lib/previews.js +1 -1
  210. package/lib/profileReport.js +504 -512
  211. package/lib/profiler.js +4 -4
  212. package/lib/prompt.js +1 -2
  213. package/lib/rc.js +1 -1
  214. package/lib/requireAuth.js +0 -1
  215. package/lib/responseToError.js +8 -5
  216. package/lib/rtdb.js +31 -29
  217. package/lib/rulesDeploy.js +2 -2
  218. package/lib/scopes.js +9 -9
  219. package/lib/serve/index.js +4 -5
  220. package/lib/utils.js +30 -6
  221. package/npm-shrinkwrap.json +877 -279
  222. package/package.json +19 -16
  223. package/standalone/package.json +1 -1
@@ -381,12 +381,12 @@ function wrapValidateBody(pluginContext) {
381
381
  if (op.validateBody && !op._authEmulatorValidateBodyWrapped) {
382
382
  const validateBody = op.validateBody.bind(op);
383
383
  op.validateBody = (body) => {
384
- return validateAndFixRestMappingRequestBody(validateBody, body, pluginContext.api);
384
+ return validateAndFixRestMappingRequestBody(validateBody, body);
385
385
  };
386
386
  op._authEmulatorValidateBodyWrapped = true;
387
387
  }
388
388
  }
389
- function validateAndFixRestMappingRequestBody(validate, body, api) {
389
+ function validateAndFixRestMappingRequestBody(validate, body) {
390
390
  var _a;
391
391
  body = convertKeysToCamelCase(body);
392
392
  let result;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.decodeRefreshToken = exports.encodeRefreshToken = exports.BlockingFunctionEvents = exports.UsageMode = exports.TenantProjectState = exports.AgentProjectState = exports.ProjectState = exports.SIGNIN_METHOD_EMAIL_LINK = exports.PROVIDER_GAME_CENTER = exports.PROVIDER_CUSTOM = exports.PROVIDER_ANONYMOUS = exports.PROVIDER_PHONE = exports.PROVIDER_PASSWORD = void 0;
3
+ exports.decodeRefreshToken = exports.encodeRefreshToken = exports.BlockingFunctionEvents = exports.TenantProjectState = exports.AgentProjectState = exports.ProjectState = exports.SIGNIN_METHOD_EMAIL_LINK = exports.PROVIDER_GAME_CENTER = exports.PROVIDER_CUSTOM = exports.PROVIDER_ANONYMOUS = exports.PROVIDER_PHONE = exports.PROVIDER_PASSWORD = void 0;
4
4
  const utils_1 = require("./utils");
5
5
  const cloudFunctions_1 = require("./cloudFunctions");
6
6
  const errors_1 = require("./errors");
@@ -22,16 +22,17 @@ class ProjectState {
22
22
  this.oobs = new Map();
23
23
  this.verificationCodes = new Map();
24
24
  this.temporaryProofs = new Map();
25
+ this.pendingLocalIds = new Set();
25
26
  }
26
27
  get projectNumber() {
27
28
  return "12345";
28
29
  }
29
- createUser(props) {
30
+ generateLocalId() {
30
31
  for (let i = 0; i < 10; i++) {
31
32
  const localId = (0, utils_1.randomId)(28);
32
- const user = this.createUserWithLocalId(localId, props);
33
- if (user) {
34
- return user;
33
+ if (!this.users.has(localId) && !this.pendingLocalIds.has(localId)) {
34
+ this.pendingLocalIds.add(localId);
35
+ return localId;
35
36
  }
36
37
  }
37
38
  throw new Error("Cannot generate a random unique localId after 10 tries.");
@@ -40,12 +41,10 @@ class ProjectState {
40
41
  if (this.users.has(localId)) {
41
42
  return undefined;
42
43
  }
43
- const timestamp = new Date();
44
44
  this.users.set(localId, {
45
45
  localId,
46
- createdAt: props.createdAt || timestamp.getTime().toString(),
47
- lastLoginAt: timestamp.getTime().toString(),
48
46
  });
47
+ this.pendingLocalIds.delete(localId);
49
48
  const user = this.updateUserByLocalId(localId, props, {
50
49
  upsertProviders: props.providerUserInfo,
51
50
  });
@@ -412,7 +411,6 @@ class AgentProjectState extends ProjectState {
412
411
  this._authCloudFunction = new cloudFunctions_1.AuthCloudFunction(this.projectId);
413
412
  this._config = {
414
413
  signIn: { allowDuplicateEmails: false },
415
- usageMode: UsageMode.DEFAULT,
416
414
  blockingFunctions: {},
417
415
  };
418
416
  }
@@ -425,12 +423,6 @@ class AgentProjectState extends ProjectState {
425
423
  set oneAccountPerEmail(oneAccountPerEmail) {
426
424
  this._config.signIn.allowDuplicateEmails = !oneAccountPerEmail;
427
425
  }
428
- get usageMode() {
429
- return this._config.usageMode;
430
- }
431
- set usageMode(usageMode) {
432
- this._config.usageMode = usageMode;
433
- }
434
426
  get allowPasswordSignup() {
435
427
  return true;
436
428
  }
@@ -455,18 +447,31 @@ class AgentProjectState extends ProjectState {
455
447
  set blockingFunctionsConfig(blockingFunctions) {
456
448
  this._config.blockingFunctions = blockingFunctions;
457
449
  }
458
- updateConfig(update, updateMask) {
459
- var _a, _b, _c, _d;
460
- if (update.usageMode) {
461
- (0, errors_1.assert)(update.usageMode !== UsageMode.USAGE_MODE_UNSPECIFIED, "INVALID_USAGE_MODE: ((Invalid usage mode provided.))");
462
- if (update.usageMode === UsageMode.PASSTHROUGH) {
463
- (0, errors_1.assert)(this.getUserCount() === 0, "USERS_STILL_EXIST: ((Users are present, unable to set passthrough mode.))");
464
- }
450
+ shouldForwardCredentialToBlockingFunction(type) {
451
+ var _a, _b, _c, _d, _e, _f;
452
+ switch (type) {
453
+ case "accessToken":
454
+ return (_b = (_a = this._config.blockingFunctions.forwardInboundCredentials) === null || _a === void 0 ? void 0 : _a.accessToken) !== null && _b !== void 0 ? _b : false;
455
+ case "idToken":
456
+ return (_d = (_c = this._config.blockingFunctions.forwardInboundCredentials) === null || _c === void 0 ? void 0 : _c.idToken) !== null && _d !== void 0 ? _d : false;
457
+ case "refreshToken":
458
+ return (_f = (_e = this._config.blockingFunctions.forwardInboundCredentials) === null || _e === void 0 ? void 0 : _e.refreshToken) !== null && _f !== void 0 ? _f : false;
465
459
  }
460
+ }
461
+ getBlockingFunctionUri(event) {
462
+ const triggers = this.blockingFunctionsConfig.triggers;
463
+ if (triggers) {
464
+ return Object.prototype.hasOwnProperty.call(triggers, event)
465
+ ? triggers[event].functionUri
466
+ : undefined;
467
+ }
468
+ return undefined;
469
+ }
470
+ updateConfig(update, updateMask) {
471
+ var _a, _b, _c;
466
472
  if (!updateMask) {
467
473
  this.oneAccountPerEmail = (_b = !((_a = update.signIn) === null || _a === void 0 ? void 0 : _a.allowDuplicateEmails)) !== null && _b !== void 0 ? _b : true;
468
474
  this.blockingFunctionsConfig = (_c = update.blockingFunctions) !== null && _c !== void 0 ? _c : {};
469
- this.usageMode = (_d = update.usageMode) !== null && _d !== void 0 ? _d : UsageMode.DEFAULT;
470
475
  return this.config;
471
476
  }
472
477
  return applyMask(updateMask, this.config, update);
@@ -542,9 +547,6 @@ class TenantProjectState extends ProjectState {
542
547
  get authCloudFunction() {
543
548
  return this.parentProject.authCloudFunction;
544
549
  }
545
- get usageMode() {
546
- return this.parentProject.usageMode;
547
- }
548
550
  get tenantConfig() {
549
551
  return this._tenantConfig;
550
552
  }
@@ -563,6 +565,12 @@ class TenantProjectState extends ProjectState {
563
565
  get enableEmailLinkSignin() {
564
566
  return this._tenantConfig.enableEmailLinkSignin;
565
567
  }
568
+ shouldForwardCredentialToBlockingFunction(type) {
569
+ return this.parentProject.shouldForwardCredentialToBlockingFunction(type);
570
+ }
571
+ getBlockingFunctionUri(event) {
572
+ return this.parentProject.getBlockingFunctionUri(event);
573
+ }
566
574
  delete() {
567
575
  this.parentProject.deleteTenant(this.tenantId);
568
576
  }
@@ -592,12 +600,6 @@ class TenantProjectState extends ProjectState {
592
600
  }
593
601
  }
594
602
  exports.TenantProjectState = TenantProjectState;
595
- var UsageMode;
596
- (function (UsageMode) {
597
- UsageMode["USAGE_MODE_UNSPECIFIED"] = "USAGE_MODE_UNSPECIFIED";
598
- UsageMode["DEFAULT"] = "DEFAULT";
599
- UsageMode["PASSTHROUGH"] = "PASSTHROUGH";
600
- })(UsageMode = exports.UsageMode || (exports.UsageMode = {}));
601
603
  var BlockingFunctionEvents;
602
604
  (function (BlockingFunctionEvents) {
603
605
  BlockingFunctionEvents["BEFORE_CREATE"] = "beforeCreate";
@@ -76,7 +76,7 @@ function warnEmulatorNotSupported(options, emulator) {
76
76
  type: "confirm",
77
77
  default: false,
78
78
  message: "Do you want to continue?",
79
- }).then((confirm) => {
79
+ }).then(() => {
80
80
  if (!opts.confirm) {
81
81
  return utils.reject("Command aborted.", { exit: 1 });
82
82
  }
@@ -67,7 +67,7 @@ class Constants {
67
67
  return service;
68
68
  }
69
69
  }
70
- static getDefaultHost(emulator) {
70
+ static getDefaultHost() {
71
71
  return DEFAULT_HOST;
72
72
  }
73
73
  static getDefaultPort(emulator) {
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.exportEmulatorData = exports.startAll = exports.shouldStart = exports.filterEmulatorTargets = exports.cleanShutdown = exports.onExit = exports.exportOnExit = exports.startEmulator = void 0;
4
- const _ = require("lodash");
5
4
  const clc = require("cli-color");
6
5
  const fs = require("fs");
7
6
  const path = require("path");
@@ -47,7 +46,7 @@ async function getAndCheckAddress(emulator, options) {
47
46
  if (emulator === types_1.Emulators.EXTENSIONS) {
48
47
  emulator = types_1.Emulators.FUNCTIONS;
49
48
  }
50
- let host = ((_b = (_a = options.config.src.emulators) === null || _a === void 0 ? void 0 : _a[emulator]) === null || _b === void 0 ? void 0 : _b.host) || constants_1.Constants.getDefaultHost(emulator);
49
+ let host = ((_b = (_a = options.config.src.emulators) === null || _a === void 0 ? void 0 : _a[emulator]) === null || _b === void 0 ? void 0 : _b.host) || constants_1.Constants.getDefaultHost();
51
50
  if (host === "localhost" && utils.isRunningInWSL()) {
52
51
  host = "127.0.0.1";
53
52
  }
@@ -135,7 +134,7 @@ function filterEmulatorTargets(options) {
135
134
  const only = onlyOptions.split(",").map((o) => {
136
135
  return o.split(":")[0];
137
136
  });
138
- targets = _.intersection(targets, only);
137
+ targets = targets.filter((t) => only.includes(t));
139
138
  }
140
139
  return targets;
141
140
  }
@@ -234,7 +233,7 @@ async function startAll(options, showUI = true) {
234
233
  const requested = onlyOptions.split(",").map((o) => {
235
234
  return o.split(":")[0];
236
235
  });
237
- const ignored = _.difference(requested, targets);
236
+ const ignored = requested.filter((k) => !targets.includes(k));
238
237
  for (const name of ignored) {
239
238
  if ((0, types_1.isEmulator)(name)) {
240
239
  emulatorLogger_1.EmulatorLogger.forEmulator(name).logLabeled("WARN", name, `Not starting the ${clc.bold(name)} emulator, make sure you have run ${clc.bold("firebase init")}.`);
@@ -246,7 +245,7 @@ async function startAll(options, showUI = true) {
246
245
  }
247
246
  if (previews_1.previews.frameworkawareness) {
248
247
  const config = options.config.get("hosting");
249
- if (Array.isArray(config) ? config.some((it) => it.source) : config.source) {
248
+ if (Array.isArray(config) ? config.some((it) => it.source) : config === null || config === void 0 ? void 0 : config.source) {
250
249
  await (0, frameworks_1.prepareFrameworks)(targets, options, options);
251
250
  }
252
251
  }
@@ -473,7 +472,9 @@ async function startAll(options, showUI = true) {
473
472
  await startEmulator(hostingEmulator);
474
473
  }
475
474
  if (showUI && !shouldStart(options, types_1.Emulators.UI)) {
476
- hubLogger.logLabeled("WARN", "emulators", "The Emulator UI requires a project ID to start. Configure your default project with 'firebase use' or pass the --project flag.");
475
+ hubLogger.logLabeled("WARN", "emulators", "The Emulator UI is not starting, either because none of the emulated " +
476
+ "products have an interaction layer in Emulator UI or it cannot " +
477
+ "determine the Project ID. Pass the --project flag to specify a project.");
477
478
  }
478
479
  if (showUI && (shouldStart(options, types_1.Emulators.UI) || START_LOGGING_EMULATOR)) {
479
480
  const loggingAddr = await getAndCheckAddress(types_1.Emulators.LOGGING, options);
@@ -6,14 +6,14 @@ const clc = require("cli-color");
6
6
  const fs = require("fs");
7
7
  const path = require("path");
8
8
  const http = require("http");
9
- const api = require("../api");
10
9
  const downloadableEmulators = require("./downloadableEmulators");
11
10
  const types_1 = require("../emulator/types");
12
11
  const constants_1 = require("./constants");
13
12
  const registry_1 = require("./registry");
14
13
  const emulatorLogger_1 = require("./emulatorLogger");
15
14
  const error_1 = require("../error");
16
- const parseBoltRules = require("../parseBoltRules");
15
+ const parseBoltRules_1 = require("../parseBoltRules");
16
+ const apiv2_1 = require("../apiv2");
17
17
  class DatabaseEmulator {
18
18
  constructor(args) {
19
19
  this.args = args;
@@ -34,7 +34,7 @@ class DatabaseEmulator {
34
34
  continue;
35
35
  }
36
36
  this.rulesWatcher = chokidar.watch(c.rules, { persistent: true, ignoreInitial: true });
37
- this.rulesWatcher.on("change", async (event, stats) => {
37
+ this.rulesWatcher.on("change", async () => {
38
38
  await new Promise((res) => setTimeout(res, 5));
39
39
  this.logger.logLabeled("BULLET", "database", `Change detected, updating rules for ${c.instance}...`);
40
40
  try {
@@ -72,7 +72,7 @@ class DatabaseEmulator {
72
72
  return downloadableEmulators.stop(types_1.Emulators.DATABASE);
73
73
  }
74
74
  getInfo() {
75
- const host = this.args.host || constants_1.Constants.getDefaultHost(types_1.Emulators.DATABASE);
75
+ const host = this.args.host || constants_1.Constants.getDefaultHost();
76
76
  const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.DATABASE);
77
77
  return {
78
78
  name: this.getName(),
@@ -125,15 +125,17 @@ class DatabaseEmulator {
125
125
  var _a;
126
126
  const rulesExt = path.extname(rulesPath);
127
127
  const content = rulesExt === ".bolt"
128
- ? parseBoltRules(rulesPath).toString()
128
+ ? (0, parseBoltRules_1.parseBoltRules)(rulesPath).toString()
129
129
  : fs.readFileSync(rulesPath, "utf8");
130
130
  const info = this.getInfo();
131
131
  try {
132
- await api.request("PUT", `/.settings/rules.json?ns=${instance}`, {
133
- origin: `http://${registry_1.EmulatorRegistry.getInfoHostString(info)}`,
132
+ const client = new apiv2_1.Client({
133
+ urlPrefix: `http://${registry_1.EmulatorRegistry.getInfoHostString(info)}`,
134
+ auth: false,
135
+ });
136
+ await client.put(`/.settings/rules.json`, content, {
134
137
  headers: { Authorization: "Bearer owner" },
135
- data: content,
136
- json: false,
138
+ queryParams: { ns: instance },
137
139
  });
138
140
  }
139
141
  catch (e) {
@@ -34,7 +34,7 @@ async function downloadEmulator(name) {
34
34
  exports.downloadEmulator = downloadEmulator;
35
35
  async function downloadExtensionVersion(extensionVersionRef, sourceDownloadUri, targetDir) {
36
36
  const emulatorLogger = emulatorLogger_1.EmulatorLogger.forExtension({ ref: extensionVersionRef });
37
- emulatorLogger.logLabeled("BULLET", "extensions", `Starting download for ${extensionVersionRef} source code...`);
37
+ emulatorLogger.logLabeled("BULLET", "extensions", `Starting download for ${extensionVersionRef} source code to ${targetDir}..`);
38
38
  try {
39
39
  fs.mkdirSync(targetDir);
40
40
  }
@@ -1,13 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EventUtils = void 0;
4
- const _ = require("lodash");
5
4
  class EventUtils {
6
5
  static isEvent(proto) {
7
- return _.has(proto, "context") && _.has(proto, "data");
6
+ return proto.context && proto.data;
8
7
  }
9
8
  static isLegacyEvent(proto) {
10
- return _.has(proto, "data") && _.has(proto, "resource");
9
+ return proto.data && proto.resource;
11
10
  }
12
11
  static isBinaryCloudEvent(req) {
13
12
  return !!(req.header("ce-type") &&
@@ -5,12 +5,12 @@ const chokidar = require("chokidar");
5
5
  const fs = require("fs");
6
6
  const clc = require("cli-color");
7
7
  const path = require("path");
8
- const api = require("../api");
9
8
  const utils = require("../utils");
10
9
  const downloadableEmulators = require("./downloadableEmulators");
11
10
  const types_1 = require("../emulator/types");
12
11
  const registry_1 = require("./registry");
13
12
  const constants_1 = require("./constants");
13
+ const apiv2_1 = require("../apiv2");
14
14
  class FirestoreEmulator {
15
15
  constructor(args) {
16
16
  this.args = args;
@@ -23,7 +23,7 @@ class FirestoreEmulator {
23
23
  if (this.args.rules && this.args.projectId) {
24
24
  const rulesPath = this.args.rules;
25
25
  this.rulesWatcher = chokidar.watch(rulesPath, { persistent: true, ignoreInitial: true });
26
- this.rulesWatcher.on("change", async (event, stats) => {
26
+ this.rulesWatcher.on("change", async () => {
27
27
  await new Promise((res) => setTimeout(res, 5));
28
28
  utils.logLabeledBullet("firestore", "Change detected, updating rules...");
29
29
  const newContent = fs.readFileSync(rulesPath, "utf8").toString();
@@ -53,7 +53,7 @@ class FirestoreEmulator {
53
53
  return downloadableEmulators.stop(types_1.Emulators.FIRESTORE);
54
54
  }
55
55
  getInfo() {
56
- const host = this.args.host || constants_1.Constants.getDefaultHost(types_1.Emulators.FIRESTORE);
56
+ const host = this.args.host || constants_1.Constants.getDefaultHost();
57
57
  const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.FIRESTORE);
58
58
  return {
59
59
  name: this.getName(),
@@ -65,7 +65,7 @@ class FirestoreEmulator {
65
65
  getName() {
66
66
  return types_1.Emulators.FIRESTORE;
67
67
  }
68
- updateRules(content) {
68
+ async updateRules(content) {
69
69
  const projectId = this.args.projectId;
70
70
  const info = this.getInfo();
71
71
  const body = {
@@ -79,17 +79,15 @@ class FirestoreEmulator {
79
79
  ],
80
80
  },
81
81
  };
82
- return api
83
- .request("PUT", `/emulator/v1/projects/${projectId}:securityRules`, {
84
- origin: `http://${registry_1.EmulatorRegistry.getInfoHostString(info)}`,
85
- data: body,
86
- })
87
- .then((res) => {
88
- if (res.body && res.body.issues) {
89
- return res.body.issues;
90
- }
91
- return [];
82
+ const client = new apiv2_1.Client({
83
+ urlPrefix: `http://${registry_1.EmulatorRegistry.getInfoHostString(info)}`,
84
+ auth: false,
92
85
  });
86
+ const res = await client.put(`/emulator/v1/projects/${projectId}:securityRules`, body);
87
+ if (res.body && Array.isArray(res.body.issues)) {
88
+ return res.body.issues;
89
+ }
90
+ return [];
93
91
  }
94
92
  prettyPrintRulesIssue(filePath, issue) {
95
93
  const relativePath = path.relative(process.cwd(), filePath);
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FunctionsEmulator = void 0;
4
- const _ = require("lodash");
5
4
  const fs = require("fs");
6
5
  const path = require("path");
7
6
  const express = require("express");
@@ -11,7 +10,6 @@ const jwt = require("jsonwebtoken");
11
10
  const cors = require("cors");
12
11
  const url_1 = require("url");
13
12
  const events_1 = require("events");
14
- const api = require("../api");
15
13
  const logger_1 = require("../logger");
16
14
  const track_1 = require("../track");
17
15
  const constants_1 = require("./constants");
@@ -34,6 +32,8 @@ const runtimes = require("../deploy/functions/runtimes");
34
32
  const backend = require("../deploy/functions/backend");
35
33
  const functionsEnv = require("../functions/env");
36
34
  const v1_1 = require("../functions/events/v1");
35
+ const apiv2_1 = require("../apiv2");
36
+ const build_1 = require("../deploy/functions/build");
37
37
  const EVENT_INVOKE = "functions:invoke";
38
38
  const DATABASE_PATH_PATTERN = new RegExp("^projects/[^/]+/instances/([^/]+)/refs(/.*)$");
39
39
  class FunctionsEmulator {
@@ -43,6 +43,7 @@ class FunctionsEmulator {
43
43
  this.triggerGeneration = 0;
44
44
  this.logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FUNCTIONS);
45
45
  this.multicastTriggers = {};
46
+ this.blockingFunctionsConfig = {};
46
47
  emulatorLogger_1.EmulatorLogger.verbosity = this.args.quiet ? emulatorLogger_1.Verbosity.QUIET : emulatorLogger_1.Verbosity.DEBUG;
47
48
  if (this.args.debugPort) {
48
49
  this.args.disabledRuntimeFeatures = this.args.disabledRuntimeFeatures || {};
@@ -54,16 +55,6 @@ class FunctionsEmulator {
54
55
  : types_1.FunctionsExecutionMode.AUTO;
55
56
  this.workerPool = new functionsRuntimeWorker_1.RuntimeWorkerPool(mode);
56
57
  this.workQueue = new workQueue_1.WorkQueue(mode);
57
- this.blockingFunctionsConfig = {
58
- triggers: {
59
- beforeCreate: {
60
- functionUri: "",
61
- },
62
- beforeSignIn: {
63
- functionUri: "",
64
- },
65
- },
66
- };
67
58
  }
68
59
  static getHttpFunctionUrl(host, port, projectId, name, region) {
69
60
  return `http://${host}:${port}/${projectId}/${region}/${name}`;
@@ -105,7 +96,6 @@ class FunctionsEmulator {
105
96
  const listBackendsRoute = `/backends`;
106
97
  const backgroundHandler = (req, res) => {
107
98
  var _a;
108
- const region = req.params.region;
109
99
  const triggerId = req.params.trigger_name;
110
100
  const projectId = req.params.project_id;
111
101
  const reqBody = req.rawBody;
@@ -232,7 +222,7 @@ class FunctionsEmulator {
232
222
  ],
233
223
  persistent: true,
234
224
  });
235
- const debouncedLoadTriggers = _.debounce(() => this.loadTriggers(backend), 1000);
225
+ const debouncedLoadTriggers = (0, utils_1.debounce)(() => this.loadTriggers(backend), 1000);
236
226
  watcher.on("change", (filePath) => {
237
227
  this.logger.log("DEBUG", `File ${filePath} changed, reloading triggers`);
238
228
  return debouncedLoadTriggers();
@@ -260,6 +250,7 @@ class FunctionsEmulator {
260
250
  if (!emulatableBackend.nodeBinary) {
261
251
  throw new error_1.FirebaseError(`No node binary for ${emulatableBackend.functionsDir}. This should never happen.`);
262
252
  }
253
+ this.blockingFunctionsConfig = {};
263
254
  let triggerDefinitions;
264
255
  if (emulatableBackend.predefinedTriggers) {
265
256
  triggerDefinitions = (0, functionsEmulatorShared_1.emulatedFunctionsByRegion)(emulatableBackend.predefinedTriggers, emulatableBackend.secretEnv);
@@ -280,7 +271,9 @@ class FunctionsEmulator {
280
271
  logger_1.logger.debug(`Building ${runtimeDelegate.name} source`);
281
272
  await runtimeDelegate.build();
282
273
  logger_1.logger.debug(`Analyzing ${runtimeDelegate.name} backend spec`);
283
- const discoveredBackend = await runtimeDelegate.discoverSpec(runtimeConfig, Object.assign(Object.assign(Object.assign(Object.assign({}, this.getSystemEnvs()), this.getEmulatorEnvs()), { FIREBASE_CONFIG: this.getFirebaseConfig() }), emulatableBackend.env));
274
+ const environment = Object.assign(Object.assign(Object.assign(Object.assign({}, this.getSystemEnvs()), this.getEmulatorEnvs()), { FIREBASE_CONFIG: this.getFirebaseConfig() }), emulatableBackend.env);
275
+ const discoveredBuild = await runtimeDelegate.discoverBuild(runtimeConfig, environment);
276
+ const discoveredBackend = (0, build_1.resolveBackend)(discoveredBuild, environment);
284
277
  const endpoints = backend.allEndpoints(discoveredBackend);
285
278
  (0, functionsEmulatorShared_1.prepareEndpoints)(endpoints);
286
279
  for (const e of endpoints) {
@@ -348,7 +341,7 @@ class FunctionsEmulator {
348
341
  added = this.addBlockingTrigger(url, definition.blockingTrigger);
349
342
  }
350
343
  else {
351
- this.logger.log("WARN", `Unsupported function type on ${definition.name}. Expected either httpsTrigger or eventTrigger.`);
344
+ this.logger.log("WARN", `Unsupported function type on ${definition.name}. Expected either an httpsTrigger, eventTrigger, or blockingTrigger.`);
352
345
  }
353
346
  const ignored = !added;
354
347
  this.addTriggerRecord(definition, { backend: emulatableBackend, ignored, url });
@@ -371,9 +364,8 @@ class FunctionsEmulator {
371
364
  }
372
365
  }
373
366
  async performPostLoadOperations() {
374
- var _a, _b, _c, _d;
375
- if (((_b = (_a = this.blockingFunctionsConfig.triggers) === null || _a === void 0 ? void 0 : _a.beforeCreate) === null || _b === void 0 ? void 0 : _b.functionUri) === "" &&
376
- ((_d = (_c = this.blockingFunctionsConfig.triggers) === null || _c === void 0 ? void 0 : _c.beforeSignIn) === null || _d === void 0 ? void 0 : _d.functionUri) === "") {
367
+ if (!this.blockingFunctionsConfig.triggers &&
368
+ !this.blockingFunctionsConfig.forwardInboundCredentials) {
377
369
  return;
378
370
  }
379
371
  const authEmu = registry_1.EmulatorRegistry.get(types_1.Emulators.AUTH);
@@ -382,15 +374,12 @@ class FunctionsEmulator {
382
374
  }
383
375
  const path = `/identitytoolkit.googleapis.com/v2/projects/${this.getProjectId()}/config?updateMask=blockingFunctions`;
384
376
  try {
385
- await api.request("PATCH", path, {
386
- origin: `http://${registry_1.EmulatorRegistry.getInfoHostString(authEmu.getInfo())}`,
387
- headers: {
388
- Authorization: "Bearer owner",
389
- },
390
- data: {
391
- blockingFunctions: this.blockingFunctionsConfig,
392
- },
393
- json: true,
377
+ const client = new apiv2_1.Client({
378
+ urlPrefix: `http://${registry_1.EmulatorRegistry.getInfoHostString(authEmu.getInfo())}`,
379
+ auth: false,
380
+ });
381
+ await client.patch(path, { blockingFunctions: this.blockingFunctionsConfig }, {
382
+ headers: { Authorization: "Bearer owner" },
394
383
  });
395
384
  }
396
385
  catch (err) {
@@ -398,15 +387,15 @@ class FunctionsEmulator {
398
387
  throw err;
399
388
  }
400
389
  }
401
- addRealtimeDatabaseTrigger(projectId, key, eventTrigger) {
390
+ async addRealtimeDatabaseTrigger(projectId, key, eventTrigger) {
402
391
  const databaseEmu = registry_1.EmulatorRegistry.get(types_1.Emulators.DATABASE);
403
392
  if (!databaseEmu) {
404
- return Promise.resolve(false);
393
+ return false;
405
394
  }
406
395
  const result = DATABASE_PATH_PATTERN.exec(eventTrigger.resource);
407
396
  if (result === null || result.length !== 3) {
408
397
  this.logger.log("WARN", `Event function "${key}" has malformed "resource" member. ` + `${eventTrigger.resource}`);
409
- return Promise.reject();
398
+ throw new error_1.FirebaseError(`Event function ${key} has malformed resource member`);
410
399
  }
411
400
  const instance = result[1];
412
401
  const bundle = JSON.stringify({
@@ -423,24 +412,20 @@ class FunctionsEmulator {
423
412
  else {
424
413
  this.logger.log("WARN", `No project in use. Registering function for sentinel namespace '${constants_1.Constants.DEFAULT_DATABASE_EMULATOR_NAMESPACE}'`);
425
414
  }
426
- return api
427
- .request("POST", setTriggersPath, {
428
- origin: `http://${registry_1.EmulatorRegistry.getInfoHostString(databaseEmu.getInfo())}`,
429
- headers: {
430
- Authorization: "Bearer owner",
431
- },
432
- data: bundle,
433
- json: false,
434
- })
435
- .then(() => {
436
- return true;
437
- })
438
- .catch((err) => {
415
+ const client = new apiv2_1.Client({
416
+ urlPrefix: `http://${registry_1.EmulatorRegistry.getInfoHostString(databaseEmu.getInfo())}`,
417
+ auth: false,
418
+ });
419
+ try {
420
+ await client.post(setTriggersPath, bundle, { headers: { Authorization: "Bearer owner" } });
421
+ }
422
+ catch (err) {
439
423
  this.logger.log("WARN", "Error adding Realtime Database function: " + err);
440
424
  throw err;
441
- });
425
+ }
426
+ return true;
442
427
  }
443
- addFirestoreTrigger(projectId, key, eventTrigger) {
428
+ async addFirestoreTrigger(projectId, key, eventTrigger) {
444
429
  const firestoreEmu = registry_1.EmulatorRegistry.get(types_1.Emulators.FIRESTORE);
445
430
  if (!firestoreEmu) {
446
431
  return Promise.resolve(false);
@@ -449,19 +434,18 @@ class FunctionsEmulator {
449
434
  eventTrigger: Object.assign(Object.assign({}, eventTrigger), { service: "firestore.googleapis.com" }),
450
435
  });
451
436
  logger_1.logger.debug(`addFirestoreTrigger`, JSON.stringify(bundle));
452
- return api
453
- .request("PUT", `/emulator/v1/projects/${projectId}/triggers/${key}`, {
454
- origin: `http://${registry_1.EmulatorRegistry.getInfoHostString(firestoreEmu.getInfo())}`,
455
- data: bundle,
456
- json: false,
457
- })
458
- .then(() => {
459
- return true;
460
- })
461
- .catch((err) => {
437
+ const client = new apiv2_1.Client({
438
+ urlPrefix: `http://${registry_1.EmulatorRegistry.getInfoHostString(firestoreEmu.getInfo())}`,
439
+ auth: false,
440
+ });
441
+ try {
442
+ await client.put(`/emulator/v1/projects/${projectId}/triggers/${key}`, bundle);
443
+ }
444
+ catch (err) {
462
445
  this.logger.log("WARN", "Error adding firestore function: " + err);
463
446
  throw err;
464
- });
447
+ }
448
+ return true;
465
449
  }
466
450
  async addPubsubTrigger(triggerName, key, eventTrigger, signatureType, schedule) {
467
451
  const pubsubEmulator = registry_1.EmulatorRegistry.get(types_1.Emulators.PUBSUB);
@@ -508,33 +492,31 @@ class FunctionsEmulator {
508
492
  addBlockingTrigger(url, blockingTrigger) {
509
493
  logger_1.logger.debug(`addBlockingTrigger`, JSON.stringify({ blockingTrigger }));
510
494
  const eventType = blockingTrigger.eventType;
511
- if (v1_1.AUTH_BLOCKING_EVENTS.includes(eventType)) {
512
- if (blockingTrigger.eventType === v1_1.BEFORE_CREATE_EVENT) {
513
- this.blockingFunctionsConfig.triggers = Object.assign(Object.assign({}, this.blockingFunctionsConfig.triggers), { beforeCreate: {
514
- functionUri: url,
515
- } });
516
- }
517
- else {
518
- this.blockingFunctionsConfig.triggers = Object.assign(Object.assign({}, this.blockingFunctionsConfig.triggers), { beforeSignIn: {
519
- functionUri: url,
520
- } });
521
- }
522
- this.blockingFunctionsConfig.forwardInboundCredentials = {
523
- accessToken: blockingTrigger.options.accessToken,
524
- idToken: blockingTrigger.options.idToken,
525
- refreshToken: blockingTrigger.options.refreshToken,
526
- };
527
- }
528
- else {
495
+ if (!v1_1.AUTH_BLOCKING_EVENTS.includes(eventType)) {
529
496
  return false;
530
497
  }
498
+ if (blockingTrigger.eventType === v1_1.BEFORE_CREATE_EVENT) {
499
+ this.blockingFunctionsConfig.triggers = Object.assign(Object.assign({}, this.blockingFunctionsConfig.triggers), { beforeCreate: {
500
+ functionUri: url,
501
+ } });
502
+ }
503
+ else {
504
+ this.blockingFunctionsConfig.triggers = Object.assign(Object.assign({}, this.blockingFunctionsConfig.triggers), { beforeSignIn: {
505
+ functionUri: url,
506
+ } });
507
+ }
508
+ this.blockingFunctionsConfig.forwardInboundCredentials = {
509
+ accessToken: !!blockingTrigger.options.accessToken,
510
+ idToken: !!blockingTrigger.options.idToken,
511
+ refreshToken: !!blockingTrigger.options.refreshToken,
512
+ };
531
513
  return true;
532
514
  }
533
515
  getProjectId() {
534
516
  return this.args.projectId;
535
517
  }
536
518
  getInfo() {
537
- const host = this.args.host || constants_1.Constants.getDefaultHost(types_1.Emulators.FUNCTIONS);
519
+ const host = this.args.host || constants_1.Constants.getDefaultHost();
538
520
  const port = this.args.port || constants_1.Constants.getDefaultPort(types_1.Emulators.FUNCTIONS);
539
521
  return {
540
522
  name: this.getName(),
@@ -617,7 +599,13 @@ class FunctionsEmulator {
617
599
  this.logger.logLabeled("SUCCESS", "functions", `Using node@${requestedMajorVersion} from host.`);
618
600
  }
619
601
  else {
620
- this.logger.log("WARN", `Your requested "node" version "${requestedMajorVersion}" doesn't match your global version "${hostMajorVersion}". Using node@${hostMajorVersion} from host.`);
602
+ if (process.env.FIREPIT_VERSION) {
603
+ this.logger.log("WARN", `You've requested "node" version "${requestedMajorVersion}", but the standalone Firebase CLI comes with bundled Node "${hostMajorVersion}".`);
604
+ this.logger.log("INFO", `To use a different Node.js version, consider removing the standalone Firebase CLI and switching to "firebase-tools" on npm.`);
605
+ }
606
+ else {
607
+ this.logger.log("WARN", `Your requested "node" version "${requestedMajorVersion}" doesn't match your global version "${hostMajorVersion}". Using node@${hostMajorVersion} from host.`);
608
+ }
621
609
  }
622
610
  return process.execPath;
623
611
  }