firebase-tools 11.21.0 → 11.23.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 (94) hide show
  1. package/lib/commands/ext-configure.js +3 -3
  2. package/lib/commands/ext-dev-init.js +16 -4
  3. package/lib/commands/ext-dev-publish.js +3 -3
  4. package/lib/commands/ext-dev-register.js +2 -2
  5. package/lib/commands/ext-info.js +3 -3
  6. package/lib/commands/ext-install.js +2 -2
  7. package/lib/commands/ext-uninstall.js +2 -2
  8. package/lib/commands/ext-update.js +2 -2
  9. package/lib/commands/hosting-channel-create.js +2 -2
  10. package/lib/commands/hosting-channel-delete.js +2 -2
  11. package/lib/commands/hosting-channel-deploy.js +2 -2
  12. package/lib/commands/hosting-clone.js +2 -2
  13. package/lib/deploy/functions/release/fabricator.js +3 -0
  14. package/lib/deploy/functions/runtimes/discovery/index.js +1 -1
  15. package/lib/deploy/functions/runtimes/index.js +5 -2
  16. package/lib/deploy/functions/runtimes/node/index.js +70 -27
  17. package/lib/deploy/functions/runtimes/node/versioning.js +4 -2
  18. package/lib/deploy/functions/runtimes/python/index.js +132 -0
  19. package/lib/deploy/hosting/convertConfig.js +2 -1
  20. package/lib/emulator/auth/apiSpec.js +21 -1
  21. package/lib/emulator/controller.js +5 -5
  22. package/lib/emulator/downloadableEmulators.js +6 -6
  23. package/lib/emulator/extensionsEmulator.js +3 -2
  24. package/lib/emulator/functionsEmulator.js +119 -87
  25. package/lib/emulator/functionsEmulatorRuntime.js +26 -42
  26. package/lib/emulator/functionsRuntimeWorker.js +51 -35
  27. package/lib/emulator/hub.js +6 -6
  28. package/lib/emulator/pubsubEmulator.js +12 -9
  29. package/lib/emulator/storage/apis/shared.js +2 -1
  30. package/lib/emulator/storage/cloudFunctions.js +1 -1
  31. package/lib/emulator/storage/files.js +18 -11
  32. package/lib/emulator/types.js +9 -9
  33. package/lib/extensions/askUserForConsent.js +4 -4
  34. package/lib/extensions/askUserForEventsConfig.js +2 -2
  35. package/lib/extensions/askUserForParam.js +34 -3
  36. package/lib/extensions/billingMigrationHelper.js +4 -4
  37. package/lib/extensions/change-log.js +4 -4
  38. package/lib/extensions/displayExtensionInfo.js +4 -4
  39. package/lib/extensions/emulator/optionsHelper.js +3 -3
  40. package/lib/extensions/emulator/specHelper.js +17 -16
  41. package/lib/extensions/extensionsApi.js +2 -2
  42. package/lib/extensions/extensionsHelper.js +6 -6
  43. package/lib/extensions/provisioningHelper.js +2 -2
  44. package/lib/extensions/updateHelper.js +2 -2
  45. package/lib/extensions/warnings.js +5 -5
  46. package/lib/firestore/checkDatabaseType.js +3 -3
  47. package/lib/frameworks/angular/index.js +6 -4
  48. package/lib/frameworks/index.js +47 -11
  49. package/lib/frameworks/lit/index.js +5 -1
  50. package/lib/frameworks/next/index.js +48 -20
  51. package/lib/frameworks/next/utils.js +1 -1
  52. package/lib/frameworks/nuxt/index.js +18 -26
  53. package/lib/frameworks/nuxt/interfaces.js +2 -0
  54. package/lib/frameworks/nuxt/utils.js +13 -0
  55. package/lib/frameworks/nuxt2/index.js +91 -0
  56. package/lib/frameworks/preact/index.js +5 -1
  57. package/lib/frameworks/react/index.js +5 -1
  58. package/lib/frameworks/svelte/index.js +5 -1
  59. package/lib/frameworks/vite/index.js +6 -4
  60. package/lib/functions/python.js +16 -0
  61. package/lib/gcp/cloudfunctionsv2.js +8 -0
  62. package/lib/getDefaultHostingSite.js +3 -1
  63. package/lib/init/features/firestore/index.js +1 -3
  64. package/lib/init/features/functions/index.js +10 -0
  65. package/lib/init/features/functions/python.js +48 -0
  66. package/lib/init/features/hosting/index.js +3 -2
  67. package/lib/projectUtils.js +2 -2
  68. package/lib/rc.js +4 -4
  69. package/lib/serve/functions.js +1 -3
  70. package/npm-shrinkwrap.json +1295 -276
  71. package/package.json +2 -2
  72. package/templates/extensions/extension.yaml +1 -1
  73. package/templates/extensions/integration-test.env +2 -0
  74. package/templates/extensions/integration-test.json +14 -0
  75. package/templates/extensions/javascript/WELCOME.md +14 -5
  76. package/templates/extensions/javascript/index.js +10 -10
  77. package/templates/extensions/javascript/integration-test.js +13 -0
  78. package/templates/extensions/javascript/package.lint.json +12 -4
  79. package/templates/extensions/javascript/package.nolint.json +11 -2
  80. package/templates/extensions/typescript/WELCOME.md +18 -5
  81. package/templates/extensions/typescript/_mocharc +10 -0
  82. package/templates/extensions/typescript/index.ts +16 -15
  83. package/templates/extensions/typescript/integration-test.ts +13 -0
  84. package/templates/extensions/typescript/package.lint.json +16 -4
  85. package/templates/extensions/typescript/package.nolint.json +12 -4
  86. package/templates/init/functions/javascript/_eslintrc +16 -2
  87. package/templates/init/functions/javascript/package.lint.json +4 -4
  88. package/templates/init/functions/javascript/package.nolint.json +3 -3
  89. package/templates/init/functions/python/_gitignore +0 -0
  90. package/templates/init/functions/python/main.py +13 -0
  91. package/templates/init/functions/python/requirements.txt +1 -0
  92. package/templates/init/functions/typescript/_eslintrc +1 -0
  93. package/templates/init/functions/typescript/package.lint.json +4 -4
  94. package/templates/init/functions/typescript/package.nolint.json +4 -3
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const TerminalRenderer = require("marked-terminal");
6
6
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
7
7
  const command_1 = require("../command");
@@ -18,7 +18,7 @@ const manifest = require("../extensions/manifest");
18
18
  const functional_1 = require("../functional");
19
19
  const paramHelper_1 = require("../extensions/paramHelper");
20
20
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
21
- marked.setOptions({
21
+ marked_1.marked.setOptions({
22
22
  renderer: new TerminalRenderer(),
23
23
  });
24
24
  exports.command = new command_1.Command("ext:configure <extensionInstanceId>")
@@ -98,7 +98,7 @@ function infoImmutableParams(immutableParams, paramValues) {
98
98
  return;
99
99
  }
100
100
  const plural = immutableParams.length > 1;
101
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, marked(`The following param${plural ? "s are" : " is"} immutable and won't be changed:`));
101
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`The following param${plural ? "s are" : " is"} immutable and won't be changed:`));
102
102
  for (const { param } of immutableParams) {
103
103
  logger_1.logger.info(`param: ${param}, value: ${paramValues[param]}`);
104
104
  }
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
- const { marked } = require("marked");
6
+ const marked_1 = require("marked");
7
7
  const TerminalRenderer = require("marked-terminal");
8
8
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
9
9
  const command_1 = require("../command");
@@ -12,13 +12,15 @@ const error_1 = require("../error");
12
12
  const prompt_1 = require("../prompt");
13
13
  const logger_1 = require("../logger");
14
14
  const npmDependencies = require("../init/features/functions/npm-dependencies");
15
- marked.setOptions({
15
+ marked_1.marked.setOptions({
16
16
  renderer: new TerminalRenderer(),
17
17
  });
18
18
  const TEMPLATE_ROOT = path.resolve(__dirname, "../../templates/extensions/");
19
19
  const FUNCTIONS_ROOT = path.resolve(__dirname, "../../templates/init/functions/");
20
20
  function readCommonTemplates() {
21
21
  return {
22
+ integrationTestFirebaseJsonTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "integration-test.json"), "utf8"),
23
+ integrationTestEnvTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "integration-test.env"), "utf8"),
22
24
  extSpecTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "extension.yaml"), "utf8"),
23
25
  preinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "PREINSTALL.md"), "utf8"),
24
26
  postinstallTemplate: fs.readFileSync(path.join(TEMPLATE_ROOT, "POSTINSTALL.md"), "utf8"),
@@ -61,9 +63,9 @@ exports.command = new command_1.Command("ext:dev:init")
61
63
  throw new error_1.FirebaseError(`${lang} is not supported.`);
62
64
  }
63
65
  }
64
- await npmDependencies.askInstallDependencies({}, config);
66
+ await npmDependencies.askInstallDependencies({ source: "functions" }, config);
65
67
  const welcome = fs.readFileSync(path.join(TEMPLATE_ROOT, lang, "WELCOME.md"), "utf8");
66
- return logger_1.logger.info("\n" + marked(welcome));
68
+ return logger_1.logger.info("\n" + (0, marked_1.marked)(welcome));
67
69
  }
68
70
  catch (err) {
69
71
  if (!(err instanceof error_1.FirebaseError)) {
@@ -80,7 +82,9 @@ async function typescriptSelected(config) {
80
82
  const tsconfigTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "tsconfig.json"), "utf8");
81
83
  const tsconfigDevTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "tsconfig.dev.json"), "utf8");
82
84
  const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "index.ts"), "utf8");
85
+ const integrationTestTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "integration-test.ts"), "utf8");
83
86
  const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "_gitignore"), "utf8");
87
+ const mocharcTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "_mocharc"), "utf8");
84
88
  const eslintTemplate = fs.readFileSync(path.join(FUNCTIONS_ROOT, "typescript", "_eslintrc"), "utf8");
85
89
  const lint = await (0, prompt_1.promptOnce)({
86
90
  name: "lint",
@@ -93,7 +97,11 @@ async function typescriptSelected(config) {
93
97
  await config.askWriteProjectFile("PREINSTALL.md", templates.preinstallTemplate);
94
98
  await config.askWriteProjectFile("POSTINSTALL.md", templates.postinstallTemplate);
95
99
  await config.askWriteProjectFile("CHANGELOG.md", templates.changelogTemplate);
100
+ await config.askWriteProjectFile("functions/.mocharc.json", mocharcTemplate);
96
101
  await config.askWriteProjectFile("functions/src/index.ts", indexTemplate);
102
+ await config.askWriteProjectFile("functions/integration-tests/integration-test.spec.ts", integrationTestTemplate);
103
+ await config.askWriteProjectFile("functions/integration-tests/firebase.json", templates.integrationTestFirebaseJsonTemplate);
104
+ await config.askWriteProjectFile("functions/integration-tests/extensions/greet-the-world.env", templates.integrationTestEnvTemplate);
97
105
  if (lint) {
98
106
  await config.askWriteProjectFile("functions/package.json", packageLintingTemplate);
99
107
  await config.askWriteProjectFile("functions/.eslintrc.js", eslintTemplate);
@@ -109,6 +117,7 @@ async function typescriptSelected(config) {
109
117
  }
110
118
  async function javascriptSelected(config) {
111
119
  const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "index.js"), "utf8");
120
+ const integrationTestTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "integration-test.js"), "utf8");
112
121
  const packageLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "package.lint.json"), "utf8");
113
122
  const packageNoLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "package.nolint.json"), "utf8");
114
123
  const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "_gitignore"), "utf8");
@@ -125,6 +134,9 @@ async function javascriptSelected(config) {
125
134
  await config.askWriteProjectFile("POSTINSTALL.md", templates.postinstallTemplate);
126
135
  await config.askWriteProjectFile("CHANGELOG.md", templates.changelogTemplate);
127
136
  await config.askWriteProjectFile("functions/index.js", indexTemplate);
137
+ await config.askWriteProjectFile("functions/integration-tests/integration-test.spec.js", integrationTestTemplate);
138
+ await config.askWriteProjectFile("functions/integration-tests/firebase.json", templates.integrationTestFirebaseJsonTemplate);
139
+ await config.askWriteProjectFile("functions/integration-tests/extensions/greet-the-world.env", templates.integrationTestEnvTemplate);
128
140
  if (lint) {
129
141
  await config.askWriteProjectFile("functions/package.json", packageLintingTemplate);
130
142
  await config.askWriteProjectFile("functions/.eslintrc.js", eslintTemplate);
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const { marked } = require("marked");
5
+ const marked_1 = require("marked");
6
6
  const TerminalRenderer = require("marked-terminal");
7
7
  const command_1 = require("../command");
8
8
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
@@ -12,7 +12,7 @@ const publishHelpers_1 = require("../extensions/publishHelpers");
12
12
  const requireAuth_1 = require("../requireAuth");
13
13
  const error_1 = require("../error");
14
14
  const utils = require("../utils");
15
- marked.setOptions({
15
+ marked_1.marked.setOptions({
16
16
  renderer: new TerminalRenderer(),
17
17
  });
18
18
  exports.command = new command_1.Command("ext:dev:publish <extensionRef>")
@@ -42,7 +42,7 @@ exports.command = new command_1.Command("ext:dev:publish <extensionRef>")
42
42
  stage: (_a = options.stage) !== null && _a !== void 0 ? _a : "stable",
43
43
  });
44
44
  if (res) {
45
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
45
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
46
46
  }
47
47
  return res;
48
48
  });
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const { marked } = require("marked");
5
+ const marked_1 = require("marked");
6
6
  const command_1 = require("../command");
7
7
  const extensionsApi_1 = require("../extensions/extensionsApi");
8
8
  const projectUtils_1 = require("../projectUtils");
@@ -38,7 +38,7 @@ exports.command = new command_1.Command("ext:dev:register")
38
38
  " This can happen for either of two reasons:\n\n" +
39
39
  ` - Publisher ID '${clc.bold(publisherId)}' is registered to another project\n` +
40
40
  ` - Project '${clc.bold(projectId)}' already has a publisher ID\n\n` +
41
- ` Try again with a unique publisher ID or a new project. If your business’s name has been registered to another project, contact Firebase support ${marked("(https://firebase.google.com/support/troubleshooter/contact).")}`;
41
+ ` Try again with a unique publisher ID or a new project. If your business’s name has been registered to another project, contact Firebase support ${(0, marked_1.marked)("(https://firebase.google.com/support/troubleshooter/contact).")}`;
42
42
  throw new error_1.FirebaseError(error, { exit: 1 });
43
43
  }
44
44
  throw new error_1.FirebaseError(`Failed to register publisher ID ${clc.bold(publisherId)} for project ${clc.bold(projectId)}: ${err.message}`);
@@ -10,7 +10,7 @@ const localHelper_1 = require("../extensions/localHelper");
10
10
  const logger_1 = require("../logger");
11
11
  const requirePermissions_1 = require("../requirePermissions");
12
12
  const utils = require("../utils");
13
- const { marked } = require("marked");
13
+ const marked_1 = require("marked");
14
14
  const TerminalRenderer = require("marked-terminal");
15
15
  const FUNCTION_TYPE_REGEX = /\..+\.function/;
16
16
  exports.command = new command_1.Command("ext:info <extensionName>")
@@ -108,10 +108,10 @@ exports.command = new command_1.Command("ext:info <extensionName>")
108
108
  logger_1.logger.info(lines.join("\n\n"));
109
109
  }
110
110
  else {
111
- marked.setOptions({
111
+ marked_1.marked.setOptions({
112
112
  renderer: new TerminalRenderer(),
113
113
  });
114
- logger_1.logger.info(marked(lines.join("\n")));
114
+ logger_1.logger.info((0, marked_1.marked)(lines.join("\n")));
115
115
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `to install this extension, type ` +
116
116
  clc.bold(`firebase ext:install ${extensionName} --project=YOUR_PROJECT`));
117
117
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const { marked } = require("marked");
5
+ const marked_1 = require("marked");
6
6
  const TerminalRenderer = require("marked-terminal");
7
7
  const displayExtensionInfo_1 = require("../extensions/displayExtensionInfo");
8
8
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
@@ -21,7 +21,7 @@ const utils = require("../utils");
21
21
  const track_1 = require("../track");
22
22
  const experiments = require("../experiments");
23
23
  const manifest = require("../extensions/manifest");
24
- marked.setOptions({
24
+ marked_1.marked.setOptions({
25
25
  renderer: new TerminalRenderer(),
26
26
  });
27
27
  exports.command = new command_1.Command("ext:install [extensionName]")
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const { marked } = require("marked");
4
+ const marked_1 = require("marked");
5
5
  const TerminalRenderer = require("marked-terminal");
6
6
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
7
7
  const command_1 = require("../command");
@@ -9,7 +9,7 @@ const extensionsHelper_1 = require("../extensions/extensionsHelper");
9
9
  const requirePermissions_1 = require("../requirePermissions");
10
10
  const utils_1 = require("../utils");
11
11
  const manifest = require("../extensions/manifest");
12
- marked.setOptions({
12
+ marked_1.marked.setOptions({
13
13
  renderer: new TerminalRenderer(),
14
14
  });
15
15
  exports.command = new command_1.Command("ext:uninstall <extensionInstanceId>")
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const { marked } = require("marked");
5
+ const marked_1 = require("marked");
6
6
  const TerminalRenderer = require("marked-terminal");
7
7
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
8
8
  const command_1 = require("../command");
@@ -18,7 +18,7 @@ const utils = require("../utils");
18
18
  const experiments = require("../experiments");
19
19
  const manifest = require("../extensions/manifest");
20
20
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
21
- marked.setOptions({
21
+ marked_1.marked.setOptions({
22
22
  renderer: new TerminalRenderer(),
23
23
  });
24
24
  exports.command = new command_1.Command("ext:update <extensionInstanceId> [updateSource]")
@@ -12,7 +12,7 @@ const requirePermissions_1 = require("../requirePermissions");
12
12
  const projectUtils_1 = require("../projectUtils");
13
13
  const logger_1 = require("../logger");
14
14
  const requireConfig_1 = require("../requireConfig");
15
- const { marked } = require("marked");
15
+ const marked_1 = require("marked");
16
16
  const requireHostingSite_1 = require("../requireHostingSite");
17
17
  const LOG_TAG = "hosting:channel";
18
18
  exports.command = new command_1.Command("hosting:channel:create [channelId]")
@@ -54,7 +54,7 @@ exports.command = new command_1.Command("hosting:channel:create [channelId]")
54
54
  await (0, api_1.addAuthDomains)(projectId, [channel.url]);
55
55
  }
56
56
  catch (e) {
57
- (0, utils_1.logLabeledWarning)(LOG_TAG, marked(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
57
+ (0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
58
58
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
59
59
  }
60
60
  logger_1.logger.info();
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const colorette_1 = require("colorette");
5
- const { marked } = require("marked");
5
+ const marked_1 = require("marked");
6
6
  const command_1 = require("../command");
7
7
  const utils_1 = require("../utils");
8
8
  const api_1 = require("../hosting/api");
@@ -39,7 +39,7 @@ exports.command = new command_1.Command("hosting:channel:delete <channelId>")
39
39
  await (0, api_1.removeAuthDomain)(projectId, channel.url);
40
40
  }
41
41
  catch (e) {
42
- (0, utils_1.logLabeledWarning)("hosting:channel", marked(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
42
+ (0, utils_1.logLabeledWarning)("hosting:channel", (0, marked_1.marked)(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
43
43
  logger_1.logger.debug("[hosting] unable to remove auth domain", e);
44
44
  }
45
45
  }
@@ -13,7 +13,7 @@ const requireConfig_1 = require("../requireConfig");
13
13
  const expireUtils_1 = require("../hosting/expireUtils");
14
14
  const utils_1 = require("../utils");
15
15
  const config_1 = require("../hosting/config");
16
- const { marked } = require("marked");
16
+ const marked_1 = require("marked");
17
17
  const requireHostingSite_1 = require("../requireHostingSite");
18
18
  const LOG_TAG = "hosting:channel";
19
19
  exports.command = new command_1.Command("hosting:channel:deploy [channelId]")
@@ -128,7 +128,7 @@ async function syncAuthState(projectId, sites) {
128
128
  logger_1.logger.debug("[hosting] added auth domain for urls", urlNames);
129
129
  }
130
130
  catch (e) {
131
- (0, utils_1.logLabeledWarning)(LOG_TAG, marked(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
131
+ (0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
132
132
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
133
133
  }
134
134
  try {
@@ -8,7 +8,7 @@ const error_1 = require("../error");
8
8
  const api_1 = require("../hosting/api");
9
9
  const utils = require("../utils");
10
10
  const requireAuth_1 = require("../requireAuth");
11
- const { marked } = require("marked");
11
+ const marked_1 = require("marked");
12
12
  const logger_1 = require("../logger");
13
13
  exports.command = new command_1.Command("hosting:clone <source> <targetChannel>")
14
14
  .description("clone a version from one site to another")
@@ -68,7 +68,7 @@ For example, to copy the content for a site \`my-site\` from a preview channel \
68
68
  await (0, api_1.addAuthDomains)(tProjectId, [tChannel.url]);
69
69
  }
70
70
  catch (e) {
71
- utils.logLabeledWarning("hosting:clone", marked(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${utils.consoleUrl(targetSiteId, "/authentication/providers")}`));
71
+ utils.logLabeledWarning("hosting:clone", (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${utils.consoleUrl(targetSiteId, "/authentication/providers")}`));
72
72
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
73
73
  }
74
74
  }
@@ -249,6 +249,9 @@ class Fabricator {
249
249
  await this.executor
250
250
  .run(async () => {
251
251
  try {
252
+ if ((await eventarc.getChannel(channel)) !== undefined) {
253
+ return;
254
+ }
252
255
  const op = await eventarc.createChannel({ name: channel });
253
256
  return await poller.pollOperation(Object.assign(Object.assign({}, eventarcPollerOptions), { pollerName: `create-${channel}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
254
257
  }
@@ -54,7 +54,7 @@ async function detectFromPort(port, project, runtime, timeout = 30000) {
54
54
  });
55
55
  while (true) {
56
56
  try {
57
- res = await Promise.race([(0, node_fetch_1.default)(`http://localhost:${port}/__/functions.yaml`), timedOut]);
57
+ res = await Promise.race([(0, node_fetch_1.default)(`http://127.0.0.1:${port}/__/functions.yaml`), timedOut]);
58
58
  break;
59
59
  }
60
60
  catch (err) {
@@ -2,10 +2,11 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getRuntimeDelegate = exports.getHumanFriendlyRuntimeName = exports.isValidRuntime = exports.isDeprecatedRuntime = void 0;
4
4
  const node = require("./node");
5
+ const python = require("./python");
5
6
  const validate = require("../validate");
6
7
  const error_1 = require("../../../error");
7
8
  const RUNTIMES = ["nodejs10", "nodejs12", "nodejs14", "nodejs16", "nodejs18"];
8
- const EXPERIMENTAL_RUNTIMES = [];
9
+ const EXPERIMENTAL_RUNTIMES = ["python310", "python311"];
9
10
  const DEPRECATED_RUNTIMES = ["nodejs6", "nodejs8"];
10
11
  function isDeprecatedRuntime(runtime) {
11
12
  return DEPRECATED_RUNTIMES.includes(runtime);
@@ -23,12 +24,14 @@ const MESSAGE_FRIENDLY_RUNTIMES = {
23
24
  nodejs14: "Node.js 14",
24
25
  nodejs16: "Node.js 16",
25
26
  nodejs18: "Node.js 18",
27
+ python310: "Python 3.10",
28
+ python311: "Python 3.11 (Preview)",
26
29
  };
27
30
  function getHumanFriendlyRuntimeName(runtime) {
28
31
  return MESSAGE_FRIENDLY_RUNTIMES[runtime] || runtime;
29
32
  }
30
33
  exports.getHumanFriendlyRuntimeName = getHumanFriendlyRuntimeName;
31
- const factories = [node.tryCreateDelegate];
34
+ const factories = [node.tryCreateDelegate, python.tryCreateDelegate];
32
35
  async function getRuntimeDelegate(context) {
33
36
  const { projectDir, sourceDir, runtime } = context;
34
37
  validate.functionsDirectoryExists(sourceDir, projectDir);
@@ -16,6 +16,7 @@ const discovery = require("../discovery");
16
16
  const validate = require("./validate");
17
17
  const versioning = require("./versioning");
18
18
  const parseTriggers = require("./parseTriggers");
19
+ const fsutils_1 = require("../../../../fsutils");
19
20
  const MIN_FUNCTIONS_SDK_VERSION = "3.20.0";
20
21
  async function tryCreateDelegate(context) {
21
22
  const packageJsonPath = path.join(context.sourceDir, "package.json");
@@ -39,6 +40,7 @@ class Delegate {
39
40
  this.runtime = runtime;
40
41
  this.name = "nodejs";
41
42
  this._sdkVersion = undefined;
43
+ this._bin = "";
42
44
  }
43
45
  get sdkVersion() {
44
46
  if (this._sdkVersion === undefined) {
@@ -46,6 +48,38 @@ class Delegate {
46
48
  }
47
49
  return this._sdkVersion;
48
50
  }
51
+ get bin() {
52
+ if (this._bin === "") {
53
+ this._bin = this.getNodeBinary();
54
+ }
55
+ return this._bin;
56
+ }
57
+ getNodeBinary() {
58
+ const requestedVersion = semver.coerce(this.runtime);
59
+ if (!requestedVersion) {
60
+ throw new error_1.FirebaseError(`Could not determine version of the requested runtime: ${this.runtime}`);
61
+ }
62
+ const hostVersion = process.versions.node;
63
+ const localNodePath = path.join(this.sourceDir, "node_modules/node");
64
+ const localNodeVersion = versioning.findModuleVersion("node", localNodePath);
65
+ if (localNodeVersion) {
66
+ if (semver.major(requestedVersion) === semver.major(localNodeVersion)) {
67
+ (0, utils_1.logLabeledSuccess)("functions", `Using node@${semver.major(localNodeVersion)} from local cache.`);
68
+ return localNodePath;
69
+ }
70
+ }
71
+ if (semver.major(requestedVersion) === semver.major(hostVersion)) {
72
+ (0, utils_1.logLabeledSuccess)("functions", `Using node@${semver.major(hostVersion)} from host.`);
73
+ return process.execPath;
74
+ }
75
+ if (!process.env.FIREPIT_VERSION) {
76
+ (0, utils_1.logLabeledWarning)("functions", `Your requested "node" version "${semver.major(requestedVersion)}" doesn't match your global version "${semver.major(hostVersion)}". Using node@${semver.major(hostVersion)} from host.`);
77
+ return process.execPath;
78
+ }
79
+ (0, utils_1.logLabeledWarning)("functions", `You've requested "node" version "${semver.major(requestedVersion)}", but the standalone Firebase CLI comes with bundled Node "${semver.major(hostVersion)}".`);
80
+ (0, utils_1.logLabeledSuccess)("functions", `To use a different Node.js version, consider removing the standalone Firebase CLI and switching to "firebase-tools" on npm.`);
81
+ return process.execPath;
82
+ }
49
83
  validate() {
50
84
  versioning.checkFunctionsSDKVersion(this.sdkVersion);
51
85
  const relativeDir = path.relative(this.projectDir, this.sourceDir);
@@ -57,35 +91,44 @@ class Delegate {
57
91
  watch() {
58
92
  return Promise.resolve(() => Promise.resolve());
59
93
  }
60
- serve(port, config, envs) {
94
+ serveAdmin(port, config, envs) {
61
95
  var _a;
62
- const env = Object.assign(Object.assign({}, envs), { PORT: port.toString(), FUNCTIONS_CONTROL_API: "true", HOME: process.env.HOME, PATH: process.env.PATH, NODE_ENV: process.env.NODE_ENV });
96
+ const env = Object.assign(Object.assign({}, envs), { PORT: port, FUNCTIONS_CONTROL_API: "true", HOME: process.env.HOME, PATH: process.env.PATH, NODE_ENV: process.env.NODE_ENV });
63
97
  if (Object.keys(config || {}).length) {
64
98
  env.CLOUD_RUNTIME_CONFIG = JSON.stringify(config);
65
99
  }
100
+ const sourceNodeModulesPath = path.join(this.sourceDir, "node_modules");
66
101
  const sdkPath = require.resolve("firebase-functions", { paths: [this.sourceDir] });
67
- const binPath = sdkPath.substring(0, sdkPath.lastIndexOf("node_modules") + 12);
68
- const childProcess = spawn(path.join(binPath, ".bin", "firebase-functions"), [this.sourceDir], {
69
- env,
70
- cwd: this.sourceDir,
71
- stdio: ["ignore", "pipe", "inherit"],
72
- });
73
- (_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (chunk) => {
74
- logger_1.logger.debug(chunk.toString());
75
- });
76
- return Promise.resolve(async () => {
77
- const p = new Promise((resolve, reject) => {
78
- childProcess.once("exit", resolve);
79
- childProcess.once("error", reject);
80
- });
81
- await (0, node_fetch_1.default)(`http://localhost:${port}/__/quitquitquit`);
82
- setTimeout(() => {
83
- if (!childProcess.killed) {
84
- childProcess.kill("SIGKILL");
85
- }
86
- }, 10000);
87
- return p;
88
- });
102
+ const sdkNodeModulesPath = sdkPath.substring(0, sdkPath.lastIndexOf("node_modules") + 12);
103
+ for (const nodeModulesPath of [sourceNodeModulesPath, sdkNodeModulesPath]) {
104
+ const binPath = path.join(nodeModulesPath, ".bin", "firebase-functions");
105
+ if ((0, fsutils_1.fileExistsSync)(binPath)) {
106
+ logger_1.logger.debug(`Found firebase-functions binary at '${binPath}'`);
107
+ const childProcess = spawn(binPath, [this.sourceDir], {
108
+ env,
109
+ cwd: this.sourceDir,
110
+ stdio: ["ignore", "pipe", "inherit"],
111
+ });
112
+ (_a = childProcess.stdout) === null || _a === void 0 ? void 0 : _a.on("data", (chunk) => {
113
+ logger_1.logger.debug(chunk.toString());
114
+ });
115
+ return Promise.resolve(async () => {
116
+ const p = new Promise((resolve, reject) => {
117
+ childProcess.once("exit", resolve);
118
+ childProcess.once("error", reject);
119
+ });
120
+ await (0, node_fetch_1.default)(`http://localhost:${port}/__/quitquitquit`);
121
+ setTimeout(() => {
122
+ if (!childProcess.killed) {
123
+ childProcess.kill("SIGKILL");
124
+ }
125
+ }, 10000);
126
+ return p;
127
+ });
128
+ }
129
+ }
130
+ throw new error_1.FirebaseError("Failed to find location of Firebase Functions SDK. " +
131
+ "Please file a bug on Github (https://github.com/firebase/firebase-tools/).");
89
132
  }
90
133
  async discoverBuild(config, env) {
91
134
  if (!semver.valid(this.sdkVersion)) {
@@ -99,9 +142,9 @@ class Delegate {
99
142
  }
100
143
  let discovered = await discovery.detectFromYaml(this.sourceDir, this.projectId, this.runtime);
101
144
  if (!discovered) {
102
- const getPort = (0, util_1.promisify)(portfinder.getPort);
103
- const port = await getPort();
104
- const kill = await this.serve(port, config, env);
145
+ const basePort = 8000 + (0, utils_1.randomInt)(0, 1000);
146
+ const port = await portfinder.getPortPromise({ port: basePort });
147
+ const kill = await this.serveAdmin(port.toString(), config, env);
105
148
  try {
106
149
  discovered = await discovery.detectFromPort(port, this.projectId, this.runtime);
107
150
  }
@@ -4,12 +4,13 @@ exports.checkFunctionsSDKVersion = exports.getLatestSDKVersion = exports.getFunc
4
4
  const fs = require("fs");
5
5
  const path = require("path");
6
6
  const clc = require("colorette");
7
- const semver = require("semver");
8
7
  const spawn = require("cross-spawn");
9
- const utils = require("../../../../utils");
8
+ const semver = require("semver");
10
9
  const logger_1 = require("../../../../logger");
11
10
  const track_1 = require("../../../../track");
11
+ const utils = require("../../../../utils");
12
12
  const MIN_SDK_VERSION = "2.0.0";
13
+ const NPM_COMMAND_TIMEOUT_MILLIES = 10000;
13
14
  exports.FUNCTIONS_SDK_VERSION_TOO_OLD_WARNING = clc.bold(clc.yellow("functions: ")) +
14
15
  "You must have a " +
15
16
  clc.bold("firebase-functions") +
@@ -53,6 +54,7 @@ function getLatestSDKVersion() {
53
54
  var _a;
54
55
  const child = spawn.sync("npm", ["show", "firebase-functions", "--json=true"], {
55
56
  encoding: "utf8",
57
+ timeout: NPM_COMMAND_TIMEOUT_MILLIES,
56
58
  });
57
59
  if (child.error) {
58
60
  logger_1.logger.debug("checkFunctionsSDKVersion was unable to fetch information from NPM", child.error.stack);