firebase-tools 11.14.1 → 11.14.2

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 (62) hide show
  1. package/lib/bin/firebase.js +3 -3
  2. package/lib/commands/deploy.js +3 -3
  3. package/lib/commands/emulators-start.js +20 -16
  4. package/lib/deploy/functions/params.js +9 -1
  5. package/lib/deploy/functions/release/fabricator.js +1 -0
  6. package/lib/deploy/hosting/convertConfig.js +2 -1
  7. package/lib/deploy/index.js +10 -0
  8. package/lib/emulator/ExpressBasedEmulator.js +92 -0
  9. package/lib/emulator/auth/cloudFunctions.js +3 -12
  10. package/lib/emulator/auth/index.js +2 -2
  11. package/lib/emulator/auth/utils.js +1 -1
  12. package/lib/emulator/commandUtils.js +21 -44
  13. package/lib/emulator/constants.js +2 -9
  14. package/lib/emulator/controller.js +129 -130
  15. package/lib/emulator/databaseEmulator.js +3 -8
  16. package/lib/emulator/dns.js +49 -0
  17. package/lib/emulator/downloadableEmulators.js +19 -13
  18. package/lib/emulator/emulatorLogger.js +14 -7
  19. package/lib/emulator/env.js +35 -0
  20. package/lib/emulator/eventarcEmulator.js +2 -8
  21. package/lib/emulator/extensions/postinstall.js +8 -8
  22. package/lib/emulator/extensionsEmulator.js +7 -7
  23. package/lib/emulator/firestoreEmulator.js +3 -11
  24. package/lib/emulator/functionsEmulator.js +24 -60
  25. package/lib/emulator/functionsEmulatorShared.js +5 -3
  26. package/lib/emulator/functionsEmulatorShell.js +1 -1
  27. package/lib/emulator/hub.js +50 -58
  28. package/lib/emulator/hubClient.js +24 -10
  29. package/lib/emulator/hubExport.js +3 -11
  30. package/lib/emulator/portUtils.js +208 -29
  31. package/lib/emulator/pubsubEmulator.js +11 -12
  32. package/lib/emulator/registry.js +11 -20
  33. package/lib/emulator/storage/apis/gcloud.js +3 -6
  34. package/lib/emulator/storage/cloudFunctions.js +2 -7
  35. package/lib/emulator/storage/metadata.js +11 -5
  36. package/lib/emulator/storage/rules/runtime.js +1 -6
  37. package/lib/emulator/ui.js +6 -7
  38. package/lib/experiments.js +10 -1
  39. package/lib/extensions/displayExtensionInfo.js +43 -6
  40. package/lib/extensions/secretsUtils.js +2 -1
  41. package/lib/frameworks/angular/index.js +1 -1
  42. package/lib/frameworks/express/index.js +1 -1
  43. package/lib/frameworks/index.js +33 -17
  44. package/lib/frameworks/next/index.js +1 -1
  45. package/lib/frameworks/nuxt/index.js +1 -1
  46. package/lib/frameworks/vite/index.js +1 -1
  47. package/lib/functions/ensureTargeted.js +21 -0
  48. package/lib/functions/env.js +33 -19
  49. package/lib/functionsShellCommandAction.js +12 -5
  50. package/lib/gcp/run.js +0 -1
  51. package/lib/handlePreviewToggles.js +2 -2
  52. package/lib/hosting/functionsProxy.js +2 -3
  53. package/lib/hosting/implicitInit.js +2 -11
  54. package/lib/hosting/runTags.js +3 -4
  55. package/lib/serve/functions.js +8 -10
  56. package/lib/serve/hosting.js +10 -4
  57. package/lib/serve/index.js +2 -2
  58. package/lib/utils.js +14 -1
  59. package/npm-shrinkwrap.json +2 -2
  60. package/package.json +1 -1
  61. package/templates/hosting/init.js +3 -2
  62. package/lib/emulator/emulatorServer.js +0 -29
@@ -9,7 +9,7 @@ const __1 = require("..");
9
9
  const prompt_1 = require("../../prompt");
10
10
  const proxy_1 = require("../../hosting/proxy");
11
11
  exports.name = "Angular";
12
- exports.support = "expirimental";
12
+ exports.support = "experimental";
13
13
  exports.type = 3;
14
14
  const CLI_COMMAND = (0, path_1.join)("node_modules", ".bin", process.platform === "win32" ? "ng.cmd" : "ng");
15
15
  async function discover(dir) {
@@ -7,7 +7,7 @@ const promises_1 = require("fs/promises");
7
7
  const path_1 = require("path");
8
8
  const { dynamicImport } = require(true && "../../dynamicImport");
9
9
  exports.name = "Express.js";
10
- exports.support = "expirimental";
10
+ exports.support = "experimental";
11
11
  exports.type = 0;
12
12
  async function getConfig(root) {
13
13
  var _a, _b;
@@ -25,9 +25,11 @@ const constants_1 = require("../emulator/constants");
25
25
  const error_1 = require("../error");
26
26
  const requireHostingSite_1 = require("../requireHostingSite");
27
27
  const experiments = require("../experiments");
28
+ const ensureTargeted_1 = require("../functions/ensureTargeted");
29
+ const implicitInit_1 = require("../hosting/implicitInit");
28
30
  const { dynamicImport } = require(true && "../dynamicImport");
29
31
  const SupportLevelWarnings = {
30
- ["expirimental"]: clc.yellow(`This is an expirimental integration, proceed with caution.`),
32
+ ["experimental"]: clc.yellow(`This is an experimental integration, proceed with caution.`),
31
33
  ["community-supported"]: clc.yellow(`This is a community-supported integration, support is best effort.`),
32
34
  };
33
35
  exports.FIREBASE_FRAMEWORKS_VERSION = "^0.6.0";
@@ -79,14 +81,14 @@ async function discover(dir, warn = true) {
79
81
  }
80
82
  if (frameworksDiscovered.length > 1) {
81
83
  if (warn)
82
- console.error("Multiple conflicting frameworks discovered. TODO link");
84
+ console.error("Multiple conflicting frameworks discovered.");
83
85
  return;
84
86
  }
85
87
  if (frameworksDiscovered.length === 1)
86
88
  return frameworksDiscovered[0];
87
89
  }
88
90
  if (warn)
89
- console.warn("We can't detirmine the web framework in use. TODO link");
91
+ console.warn("Could not determine the web framework in use.");
90
92
  return;
91
93
  }
92
94
  exports.discover = discover;
@@ -151,7 +153,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
151
153
  if (publicDir)
152
154
  throw new Error(`hosting.public and hosting.source cannot both be set in firebase.json`);
153
155
  const getProjectPath = (...args) => (0, path_1.join)(projectRoot, source, ...args);
154
- const functionName = `ssr${site.replace(/-/g, "")}`;
156
+ const functionName = `ssr${site.toLowerCase().replace(/-/g, "")}`;
155
157
  const usesFirebaseAdminSdk = !!findDependency("firebase-admin", { cwd: getProjectPath() });
156
158
  const usesFirebaseJsSdk = !!findDependency("@firebase/app", { cwd: getProjectPath() });
157
159
  if (usesFirebaseAdminSdk) {
@@ -173,7 +175,7 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
173
175
  if (info.name === types_1.Emulators.STORAGE)
174
176
  process.env[constants_1.Constants.FIREBASE_STORAGE_EMULATOR_HOST] = (0, functionsEmulatorShared_1.formatHost)(info);
175
177
  }
176
- if (usesFirebaseJsSdk) {
178
+ if (usesFirebaseJsSdk && types_1.EMULATORS_SUPPORTED_BY_USE_EMULATOR.includes(info.name)) {
177
179
  firebaseDefaults || (firebaseDefaults = {});
178
180
  firebaseDefaults.emulatorHosts || (firebaseDefaults.emulatorHosts = {});
179
181
  firebaseDefaults.emulatorHosts[info.name] = (0, functionsEmulatorShared_1.formatHost)(info);
@@ -191,16 +193,25 @@ async function prepareFrameworks(targetNames, context, options, emulators = [])
191
193
  firebaseDefaults.config = firebaseConfig;
192
194
  }
193
195
  else {
194
- console.warn(`No Firebase app associated with site ${site}, unable to provide authenticated server context.
195
- You can link a Web app to a Hosting site here https://console.firebase.google.com/project/_/settings/general/web`);
196
- if (!options.nonInteractive) {
197
- const continueDeploy = await (0, prompt_1.promptOnce)({
198
- type: "confirm",
199
- default: true,
200
- message: "Would you like to continue with the deploy?",
201
- });
202
- if (!continueDeploy)
203
- (0, process_1.exit)(1);
196
+ const defaultConfig = await (0, implicitInit_1.implicitInit)(options);
197
+ if (defaultConfig.json) {
198
+ console.warn(`No Firebase app associated with site ${site}, injecting project default config.
199
+ You can link a Web app to a Hosting site here https://console.firebase.google.com/project/${project}/settings/general/web`);
200
+ firebaseDefaults || (firebaseDefaults = {});
201
+ firebaseDefaults.config = JSON.parse(defaultConfig.json);
202
+ }
203
+ else {
204
+ console.warn(`No Firebase app associated with site ${site}, unable to provide authenticated server context.
205
+ You can link a Web app to a Hosting site here https://console.firebase.google.com/project/${project}/settings/general/web`);
206
+ if (!options.nonInteractive) {
207
+ const continueDeploy = await (0, prompt_1.promptOnce)({
208
+ type: "confirm",
209
+ default: true,
210
+ message: "Would you like to continue with the deploy?",
211
+ });
212
+ if (!continueDeploy)
213
+ (0, process_1.exit)(1);
214
+ }
204
215
  }
205
216
  }
206
217
  }
@@ -248,6 +259,7 @@ You can link a Web app to a Hosting site here https://console.firebase.google.co
248
259
  rewrite.function.pinTag = true;
249
260
  }
250
261
  config.rewrites.push(rewrite);
262
+ const codebase = `firebase-frameworks-${site}`;
251
263
  const existingFunctionsConfig = options.config.get("functions")
252
264
  ? [].concat(options.config.get("functions"))
253
265
  : [];
@@ -255,11 +267,15 @@ You can link a Web app to a Hosting site here https://console.firebase.google.co
255
267
  ...existingFunctionsConfig,
256
268
  {
257
269
  source: (0, path_1.relative)(projectRoot, functionsDist),
258
- codebase: `firebase-frameworks-${site}`,
270
+ codebase,
259
271
  },
260
272
  ]);
261
- if (!targetNames.includes("functions"))
273
+ if (!targetNames.includes("functions")) {
262
274
  targetNames.unshift("functions");
275
+ }
276
+ if (options.only) {
277
+ options.only = (0, ensureTargeted_1.ensureTargeted)(options.only, codebase);
278
+ }
263
279
  if (await (0, fs_extra_1.pathExists)(functionsDist)) {
264
280
  const functionsDistStat = await (0, fs_extra_1.stat)(functionsDist);
265
281
  if (functionsDistStat === null || functionsDistStat === void 0 ? void 0 : functionsDistStat.isDirectory()) {
@@ -14,7 +14,7 @@ const logger_1 = require("../../logger");
14
14
  const error_1 = require("../../error");
15
15
  const CLI_COMMAND = (0, path_1.join)("node_modules", ".bin", process.platform === "win32" ? "next.cmd" : "next");
16
16
  exports.name = "Next.js";
17
- exports.support = "expirimental";
17
+ exports.support = "experimental";
18
18
  exports.type = 2;
19
19
  function getNextVersion(cwd) {
20
20
  var _a;
@@ -7,7 +7,7 @@ const path_1 = require("path");
7
7
  const semver_1 = require("semver");
8
8
  const __1 = require("..");
9
9
  exports.name = "Nuxt";
10
- exports.support = "expirimental";
10
+ exports.support = "experimental";
11
11
  exports.type = 4;
12
12
  async function discover(dir) {
13
13
  if (!(await (0, fs_extra_1.pathExists)((0, path_1.join)(dir, "package.json"))))
@@ -9,7 +9,7 @@ const __1 = require("..");
9
9
  const proxy_1 = require("../../hosting/proxy");
10
10
  const prompt_1 = require("../../prompt");
11
11
  exports.name = "Vite";
12
- exports.support = "expirimental";
12
+ exports.support = "experimental";
13
13
  exports.type = 4;
14
14
  const CLI_COMMAND = (0, path_1.join)("node_modules", ".bin", process.platform === "win32" ? "vite.cmd" : "vite");
15
15
  const initViteTemplate = (template) => async (setup) => await init(setup, template);
@@ -0,0 +1,21 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ensureTargeted = void 0;
4
+ function ensureTargeted(only, codebase, id) {
5
+ const parts = only.split(",");
6
+ if (parts.includes("functions")) {
7
+ return only;
8
+ }
9
+ let newTarget = `functions:${codebase}`;
10
+ if (parts.includes(newTarget)) {
11
+ return only;
12
+ }
13
+ if (id) {
14
+ newTarget = `${newTarget}:${id}`;
15
+ if (parts.includes(newTarget)) {
16
+ return only;
17
+ }
18
+ }
19
+ return `${only},${newTarget}`;
20
+ }
21
+ exports.ensureTargeted = ensureTargeted;
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.writeUserEnvs = exports.hasUserEnvs = exports.parseStrict = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
3
+ exports.loadFirebaseEnvs = exports.loadUserEnvs = exports.checkForDuplicateKeys = exports.writeUserEnvs = exports.hasUserEnvs = exports.parseStrict = exports.validateKey = exports.KeyValidationError = exports.parse = void 0;
4
4
  const clc = require("colorette");
5
5
  const fs = require("fs");
6
6
  const path = require("path");
@@ -161,32 +161,46 @@ function writeUserEnvs(toWrite, envOpts) {
161
161
  return;
162
162
  }
163
163
  const { functionsSource, projectId, projectAlias, isEmulator } = envOpts;
164
- const envFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
165
- const projectScopedFileName = `.env.${projectId}`;
166
- const projectScopedFileExists = envFiles.includes(projectScopedFileName);
167
- if (!projectScopedFileExists) {
168
- createEnvFile(envOpts);
169
- }
170
- const currentEnvs = loadUserEnvs(envOpts);
164
+ const allEnvFiles = findEnvfiles(functionsSource, projectId, projectAlias, isEmulator);
165
+ const targetEnvFile = envOpts.isEmulator
166
+ ? FUNCTIONS_EMULATOR_DOTENV
167
+ : `.env.${envOpts.projectId}`;
168
+ const targetEnvFileExists = allEnvFiles.includes(targetEnvFile);
169
+ if (!targetEnvFileExists) {
170
+ fs.writeFileSync(path.join(envOpts.functionsSource, targetEnvFile), "", { flag: "wx" });
171
+ (0, utils_1.logBullet)(clc.yellow(clc.bold("functions: ")) +
172
+ `Created new local file ${targetEnvFile} to store param values. We suggest explicitly adding or excluding this file from version control.`);
173
+ }
174
+ const fullEnvs = loadUserEnvs(envOpts);
175
+ const prodEnvs = isEmulator
176
+ ? loadUserEnvs(Object.assign(Object.assign({}, envOpts), { isEmulator: false }))
177
+ : loadUserEnvs(envOpts);
178
+ checkForDuplicateKeys(isEmulator || false, Object.keys(toWrite), fullEnvs, prodEnvs);
171
179
  for (const k of Object.keys(toWrite)) {
172
180
  validateKey(k);
173
- if (currentEnvs.hasOwnProperty(k)) {
174
- throw new error_1.FirebaseError(`Attempted to write param-defined key ${k} to .env files, but it was already defined.`);
175
- }
176
181
  }
177
- (0, utils_1.logBullet)(clc.cyan(clc.bold("functions: ")) +
178
- `Writing new parameter values to disk: ${projectScopedFileName}`);
182
+ (0, utils_1.logBullet)(clc.cyan(clc.bold("functions: ")) + `Writing new parameter values to disk: ${targetEnvFile}`);
183
+ let lines = "";
179
184
  for (const k of Object.keys(toWrite)) {
180
- fs.appendFileSync(path.join(functionsSource, projectScopedFileName), formatUserEnvForWrite(k, toWrite[k]));
185
+ lines += formatUserEnvForWrite(k, toWrite[k]);
181
186
  }
187
+ fs.appendFileSync(path.join(functionsSource, targetEnvFile), lines);
182
188
  }
183
189
  exports.writeUserEnvs = writeUserEnvs;
184
- function createEnvFile(envOpts) {
185
- const fileToWrite = envOpts.isEmulator ? FUNCTIONS_EMULATOR_DOTENV : `.env.${envOpts.projectId}`;
186
- logger_1.logger.debug(`Creating ${fileToWrite}...`);
187
- fs.writeFileSync(path.join(envOpts.functionsSource, fileToWrite), "", { flag: "wx" });
188
- return fileToWrite;
190
+ function checkForDuplicateKeys(isEmulator, keys, fullEnv, envsWithoutLocal) {
191
+ for (const key of keys) {
192
+ const definedInEnv = fullEnv.hasOwnProperty(key);
193
+ if (definedInEnv) {
194
+ if (envsWithoutLocal && isEmulator && envsWithoutLocal.hasOwnProperty(key)) {
195
+ (0, utils_1.logWarning)(clc.cyan(clc.yellow("functions: ")) +
196
+ `Writing parameter ${key} to emulator-specific config .env.local. This will overwrite your existing definition only when emulating.`);
197
+ continue;
198
+ }
199
+ throw new error_1.FirebaseError(`Attempted to write param-defined key ${key} to .env files, but it was already defined.`);
200
+ }
201
+ }
189
202
  }
203
+ exports.checkForDuplicateKeys = checkForDuplicateKeys;
190
204
  function formatUserEnvForWrite(key, value) {
191
205
  const escapedValue = value.replace(ALL_ESCAPABLE_CHARACTERS_RE, (match) => CHARACTERS_TO_ESCAPE_SEQUENCES[match]);
192
206
  if (escapedValue !== value) {
@@ -15,9 +15,10 @@ const commandUtils = require("./emulator/commandUtils");
15
15
  const types_1 = require("./emulator/types");
16
16
  const hubClient_1 = require("./emulator/hubClient");
17
17
  const portUtils_1 = require("./emulator/portUtils");
18
+ const constants_1 = require("./emulator/constants");
18
19
  const serveFunctions = new functions_1.FunctionsServer();
19
20
  const actionFunction = async (options) => {
20
- var _a, _b;
21
+ var _a, _b, _c, _d, _e, _f;
21
22
  if (typeof options.port === "string") {
22
23
  options.port = parseInt(options.port, 10);
23
24
  }
@@ -34,16 +35,22 @@ const actionFunction = async (options) => {
34
35
  }
35
36
  const runningEmulators = types_1.EMULATORS_SUPPORTED_BY_FUNCTIONS.filter((e) => remoteEmulators[e] !== undefined);
36
37
  const otherEmulators = types_1.EMULATORS_SUPPORTED_BY_FUNCTIONS.filter((e) => remoteEmulators[e] === undefined);
38
+ let host = constants_1.Constants.getDefaultHost();
39
+ let port = 5000;
37
40
  const functionsInfo = remoteEmulators[types_1.Emulators.FUNCTIONS];
38
41
  if (functionsInfo) {
39
42
  utils.logLabeledWarning("functions", `You are already running the Cloud Functions emulator on port ${functionsInfo.port}. Running the emulator and the Functions shell simultaenously can result in unexpected behavior.`);
40
43
  }
41
44
  else if (!options.port) {
42
- options.port = (_b = (_a = options.config.src.emulators) === null || _a === void 0 ? void 0 : _a.functions) === null || _b === void 0 ? void 0 : _b.port;
43
- }
44
- if (!options.port) {
45
- options.port = await (0, portUtils_1.findAvailablePort)("localhost", 5000);
45
+ port = (_c = (_b = (_a = options.config.src.emulators) === null || _a === void 0 ? void 0 : _a.functions) === null || _b === void 0 ? void 0 : _b.port) !== null && _c !== void 0 ? _c : port;
46
+ host = (_f = (_e = (_d = options.config.src.emulators) === null || _d === void 0 ? void 0 : _d.functions) === null || _e === void 0 ? void 0 : _e.host) !== null && _f !== void 0 ? _f : host;
47
+ options.host = host;
46
48
  }
49
+ const listen = (await (0, portUtils_1.resolveHostAndAssignPorts)({
50
+ [types_1.Emulators.FUNCTIONS]: { host, port },
51
+ })).functions;
52
+ options.host = listen[0].address;
53
+ options.port = listen[0].port;
47
54
  return serveFunctions
48
55
  .start(options, {
49
56
  quiet: true,
package/lib/gcp/run.js CHANGED
@@ -37,7 +37,6 @@ async function getService(name) {
37
37
  exports.getService = getService;
38
38
  async function updateService(name, service) {
39
39
  delete service.status;
40
- delete service.spec.template.metadata.name;
41
40
  service = await exports.replaceService(name, service);
42
41
  let retry = 0;
43
42
  while (!exports.serviceIsResolved(service)) {
@@ -12,7 +12,7 @@ function handlePreviewToggles(args) {
12
12
  const isValid = experiments.isValidExperiment(name);
13
13
  if (args[0] === "--open-sesame") {
14
14
  console.log(`${(0, colorette_1.bold)("firebase --open-sesame")} is deprecated and wil be removed in a future ` +
15
- `version. Use the new "expirments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:enable")}`);
15
+ `version. Use the new "experiments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:enable")}`);
16
16
  if (isValid) {
17
17
  console.log(`Enabling experiment ${(0, colorette_1.bold)(name)} ...`);
18
18
  experiments.setEnabled(name, true);
@@ -24,7 +24,7 @@ function handlePreviewToggles(args) {
24
24
  }
25
25
  else if (args[0] === "--close-sesame") {
26
26
  console.log(`${(0, colorette_1.bold)("firebase --open-sesame")} is deprecated and wil be removed in a future ` +
27
- `version. Use the new "expirments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:disable")}`);
27
+ `version. Use the new "experiments" family of commands, including ${(0, colorette_1.bold)("firebase experiments:disable")}`);
28
28
  if (isValid) {
29
29
  console.log(`Disabling experiment ${(0, colorette_1.bold)(name)}...`);
30
30
  experiments.setEnabled(name, false);
@@ -31,9 +31,8 @@ function functionsProxy(options) {
31
31
  let destLabel = "live";
32
32
  if ((0, lodash_1.includes)(options.targets, "functions")) {
33
33
  destLabel = "local";
34
- const functionsEmu = registry_1.EmulatorRegistry.get(types_1.Emulators.FUNCTIONS);
35
- if (functionsEmu) {
36
- url = functionsEmulator_1.FunctionsEmulator.getHttpFunctionUrl(functionsEmu.getInfo().host, functionsEmu.getInfo().port, projectId, functionId, region);
34
+ if (registry_1.EmulatorRegistry.isRunning(types_1.Emulators.FUNCTIONS)) {
35
+ url = functionsEmulator_1.FunctionsEmulator.getHttpFunctionUrl(projectId, functionId, region);
37
36
  }
38
37
  }
39
38
  resolve((0, proxy_1.proxyRequestHandler)(url, `${destLabel} Function ${region}/${functionId}`));
@@ -39,19 +39,10 @@ async function implicitInit(options) {
39
39
  for (const e of types_1.EMULATORS_SUPPORTED_BY_USE_EMULATOR) {
40
40
  const info = registry_1.EmulatorRegistry.getInfo(e);
41
41
  if (info) {
42
- let host = info.host;
43
- if (host === "0.0.0.0") {
44
- host = "127.0.0.1";
45
- }
46
- else if (host === "::") {
47
- host = "[::1]";
48
- }
49
- else if (host.includes(":")) {
50
- host = `[${host}]`;
51
- }
52
42
  emulators[e] = {
53
- host,
43
+ host: info.host,
54
44
  port: info.port,
45
+ hostAndPort: registry_1.EmulatorRegistry.url(e).host,
55
46
  };
56
47
  }
57
48
  }
@@ -92,11 +92,10 @@ async function ensureLatestRevisionTagged(services, defaultTag) {
92
92
  for (const service of services) {
93
93
  const { projectNumber, region, serviceId } = run.gcpIds(service);
94
94
  tags[region] = tags[region] || {};
95
- const latestRevisionTarget = (_a = service.status) === null || _a === void 0 ? void 0 : _a.traffic.find((target) => target.latestRevision);
96
- if (!latestRevisionTarget) {
97
- throw new error_1.FirebaseError(`Assertion failed: service ${service.metadata.name} has no latestRevision traffic target`);
95
+ const latestRevision = (_a = service.status) === null || _a === void 0 ? void 0 : _a.latestReadyRevisionName;
96
+ if (!latestRevision) {
97
+ throw new error_1.FirebaseError(`Assertion failed: service ${service.metadata.name} has no ready revision`);
98
98
  }
99
- const latestRevision = latestRevisionTarget.revisionName;
100
99
  const alreadyTagged = service.spec.traffic.find((target) => target.revisionName === latestRevision && target.tag);
101
100
  if (alreadyTagged) {
102
101
  tags[region][serviceId] = alreadyTagged.tag;
@@ -3,17 +3,18 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.FunctionsServer = void 0;
4
4
  const path = require("path");
5
5
  const functionsEmulator_1 = require("../emulator/functionsEmulator");
6
- const emulatorServer_1 = require("../emulator/emulatorServer");
7
6
  const functionsEmulatorUtils_1 = require("../emulator/functionsEmulatorUtils");
8
7
  const projectUtils_1 = require("../projectUtils");
9
8
  const auth_1 = require("../auth");
10
9
  const projectConfig = require("../functions/projectConfig");
11
10
  const utils = require("../utils");
11
+ const registry_1 = require("../emulator/registry");
12
12
  class FunctionsServer {
13
13
  assertServer() {
14
- if (!this.emulatorServer || !this.backends) {
14
+ if (!this.emulator || !this.backends) {
15
15
  throw new Error("Must call start() before calling any other operation!");
16
16
  }
17
+ return this.emulator;
17
18
  }
18
19
  async start(options, partialArgs) {
19
20
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -49,20 +50,17 @@ class FunctionsServer {
49
50
  args.port = port;
50
51
  }
51
52
  }
52
- this.emulatorServer = new emulatorServer_1.EmulatorServer(new functionsEmulator_1.FunctionsEmulator(args));
53
- await this.emulatorServer.start();
53
+ this.emulator = new functionsEmulator_1.FunctionsEmulator(args);
54
+ return registry_1.EmulatorRegistry.start(this.emulator);
54
55
  }
55
56
  async connect() {
56
- this.assertServer();
57
- await this.emulatorServer.connect();
57
+ await this.assertServer().connect();
58
58
  }
59
59
  async stop() {
60
- this.assertServer();
61
- await this.emulatorServer.stop();
60
+ await this.assertServer().stop();
62
61
  }
63
62
  get() {
64
- this.assertServer();
65
- return this.emulatorServer.get();
63
+ return this.assertServer();
66
64
  }
67
65
  }
68
66
  exports.FunctionsServer = FunctionsServer;
@@ -16,6 +16,7 @@ const emulatorLogger_1 = require("../emulator/emulatorLogger");
16
16
  const types_1 = require("../emulator/types");
17
17
  const utils_1 = require("../utils");
18
18
  const child_process_1 = require("child_process");
19
+ const requireHostingSite_1 = require("../requireHostingSite");
19
20
  const MAX_PORT_ATTEMPTS = 10;
20
21
  let attempts = 0;
21
22
  let destroyServer = undefined;
@@ -101,10 +102,15 @@ function stop() {
101
102
  exports.stop = stop;
102
103
  async function start(options) {
103
104
  const init = await (0, implicitInit_1.implicitInit)(options);
104
- let configs = config.extract(options);
105
- configs = config.filterOnly(configs, options.only);
106
- configs = config.filterExcept(configs, options.except);
107
- config.validate(configs, options);
105
+ if (!options.site) {
106
+ try {
107
+ await (0, requireHostingSite_1.requireHostingSite)(options);
108
+ }
109
+ catch (_a) {
110
+ options.site = JSON.parse(init.json).projectId;
111
+ }
112
+ }
113
+ const configs = config.hostingConfig(options);
108
114
  for (let i = 0; i < configs.length; i++) {
109
115
  const port = i === 0 ? options.port : options.port + 4 + i;
110
116
  startServer(options, configs[i], port, init);
@@ -7,6 +7,7 @@ const experiments = require("../experiments");
7
7
  const track_1 = require("../track");
8
8
  const projectUtils_1 = require("../projectUtils");
9
9
  const constants_1 = require("../emulator/constants");
10
+ const config = require("../hosting/config");
10
11
  const { FunctionsServer } = require("./functions");
11
12
  const TARGETS = {
12
13
  hosting: require("./hosting"),
@@ -15,8 +16,7 @@ const TARGETS = {
15
16
  async function serve(options) {
16
17
  const targetNames = options.targets || [];
17
18
  options.port = parseInt(options.port, 10);
18
- if (targetNames.includes("hosting") &&
19
- [].concat(options.config.get("hosting")).some((it) => it.source)) {
19
+ if (targetNames.includes("hosting") && config.extract(options).some((it) => it.source)) {
20
20
  experiments.assertEnabled("webframeworks", "emulate a web framework");
21
21
  await (0, frameworks_1.prepareFrameworks)(targetNames, options, options);
22
22
  }
package/lib/utils.js CHANGED
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
3
+ exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
4
4
  const _ = require("lodash");
5
5
  const url = require("url");
6
6
  const clc = require("colorette");
@@ -472,3 +472,16 @@ function randomInt(min, max) {
472
472
  return Math.floor(Math.random() * (max - min) + min);
473
473
  }
474
474
  exports.randomInt = randomInt;
475
+ function connectableHostname(hostname) {
476
+ if (hostname === "0.0.0.0") {
477
+ hostname = "127.0.0.1";
478
+ }
479
+ else if (hostname === "::") {
480
+ hostname = "::1";
481
+ }
482
+ else if (hostname === "[::]") {
483
+ hostname = "[::1]";
484
+ }
485
+ return hostname;
486
+ }
487
+ exports.connectableHostname = connectableHostname;
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.14.1",
3
+ "version": "11.14.2",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "firebase-tools",
9
- "version": "11.14.1",
9
+ "version": "11.14.2",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@google-cloud/pubsub": "^3.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.14.1",
3
+ "version": "11.14.2",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -7,7 +7,7 @@ if (firebaseConfig) {
7
7
  if (firebaseEmulators) {
8
8
  console.log("Automatically connecting Firebase SDKs to running emulators:");
9
9
  Object.keys(firebaseEmulators).forEach(function (key) {
10
- console.log('\t' + key + ': http://' + firebaseEmulators[key].host + ':' + firebaseEmulators[key].port);
10
+ console.log('\t' + key + ': http://' + firebaseEmulators[key].hostAndPort);
11
11
  });
12
12
 
13
13
  if (firebaseEmulators.database && typeof firebase.database === 'function') {
@@ -23,7 +23,8 @@ if (firebaseConfig) {
23
23
  }
24
24
 
25
25
  if (firebaseEmulators.auth && typeof firebase.auth === 'function') {
26
- firebase.auth().useEmulator('http://' + firebaseEmulators.auth.host + ':' + firebaseEmulators.auth.port);
26
+ // TODO: Consider using location.protocol + '//' instead (may help HTTPS).
27
+ firebase.auth().useEmulator('http://' + firebaseEmulators.auth.hostAndPort);
27
28
  }
28
29
 
29
30
  if (firebaseEmulators.storage && typeof firebase.storage === 'function') {
@@ -1,29 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.EmulatorServer = void 0;
4
- const registry_1 = require("./registry");
5
- const portUtils = require("./portUtils");
6
- const error_1 = require("../error");
7
- class EmulatorServer {
8
- constructor(instance) {
9
- this.instance = instance;
10
- }
11
- async start() {
12
- const { port, host } = this.instance.getInfo();
13
- const portOpen = await portUtils.checkPortOpen(port, host);
14
- if (!portOpen) {
15
- throw new error_1.FirebaseError(`Port ${port} is not open on ${host}, could not start ${this.instance.getName()} emulator.`);
16
- }
17
- await registry_1.EmulatorRegistry.start(this.instance);
18
- }
19
- async connect() {
20
- await this.instance.connect();
21
- }
22
- async stop() {
23
- await registry_1.EmulatorRegistry.stop(this.instance.getName());
24
- }
25
- get() {
26
- return this.instance;
27
- }
28
- }
29
- exports.EmulatorServer = EmulatorServer;