firebase-tools 15.12.1-main.0 → 15.13.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.
@@ -35,7 +35,7 @@ const node_fetch_1 = require("node-fetch");
35
35
  const rollout_1 = require("./rollout");
36
36
  const fuzzy = require("fuzzy");
37
37
  const experiments_1 = require("../experiments");
38
- const DEFAULT_RUNTIME = "nodejs";
38
+ const prompts_1 = require("./prompts");
39
39
  const DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME = "firebase-app-hosting-compute";
40
40
  const apphostingPollerOptions = {
41
41
  apiOrigin: (0, api_1.apphostingOrigin)(),
@@ -101,17 +101,15 @@ async function doSetup(projectId, nonInteractive, webAppName, backendId, service
101
101
  }
102
102
  if (runtime === undefined && (0, experiments_1.isEnabled)("abiu")) {
103
103
  if (nonInteractive) {
104
- runtime = DEFAULT_RUNTIME;
104
+ runtime = prompts_1.DEFAULT_RUNTIME;
105
105
  }
106
106
  else {
107
- runtime = await (0, prompt_1.select)({
108
- message: "Which runtime do you want to use?",
109
- choices: [
110
- { name: "Node.js (default)", value: DEFAULT_RUNTIME },
111
- { name: "Node.js 22", value: "nodejs22" },
112
- ],
113
- default: DEFAULT_RUNTIME,
114
- });
107
+ runtime = await (0, prompts_1.promptRuntime)(projectId, location);
108
+ }
109
+ }
110
+ if (automaticBaseImageUpdatesDisabled === undefined && (0, experiments_1.isEnabled)("abiu")) {
111
+ if (!nonInteractive) {
112
+ automaticBaseImageUpdatesDisabled = !(await (0, prompts_1.promptAutomaticBaseImageUpdates)());
115
113
  }
116
114
  }
117
115
  const webApp = await app_1.webApps.getOrCreateWebApp(projectId, webAppName ? webAppName : null, backendId);
@@ -257,9 +255,11 @@ async function createBackend(projectId, location, backendId, serviceAccount, rep
257
255
  labels: deploymentTool.labels(),
258
256
  serviceAccount: serviceAccount || defaultServiceAccount,
259
257
  appId: webAppId,
260
- runtime: { value: runtime ?? "" },
261
- automaticBaseImageUpdatesDisabled,
262
258
  };
259
+ if ((0, experiments_1.isEnabled)("abiu")) {
260
+ backendReqBody.runtime = { value: runtime ?? "" };
261
+ backendReqBody.automaticBaseImageUpdatesDisabled = automaticBaseImageUpdatesDisabled;
262
+ }
263
263
  async function createBackendAndPoll() {
264
264
  const op = await apphosting.createBackend(projectId, location, backendReqBody, backendId);
265
265
  return await poller.pollOperation({
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_RUNTIME = void 0;
4
+ exports.promptRuntime = promptRuntime;
5
+ exports.promptAutomaticBaseImageUpdates = promptAutomaticBaseImageUpdates;
6
+ const prompt_1 = require("../prompt");
7
+ const utils_1 = require("../utils");
8
+ const apphosting = require("../gcp/apphosting");
9
+ exports.DEFAULT_RUNTIME = "nodejs";
10
+ async function promptRuntime(projectId, location) {
11
+ const choices = [{ name: "Node.js (default)", value: exports.DEFAULT_RUNTIME }];
12
+ try {
13
+ const supportedRuntimes = await apphosting.listSupportedRuntimes(projectId, location);
14
+ for (const r of supportedRuntimes) {
15
+ if (r.runtimeId !== exports.DEFAULT_RUNTIME) {
16
+ choices.push({ name: r.runtimeId, value: r.runtimeId });
17
+ }
18
+ }
19
+ }
20
+ catch (err) {
21
+ (0, utils_1.logWarning)("Failed to list supported runtimes. Falling back to hardcoded list.");
22
+ choices.push({ name: "nodejs22", value: "nodejs22" });
23
+ }
24
+ return await (0, prompt_1.select)({
25
+ message: "Which runtime do you want to use?",
26
+ choices: choices,
27
+ default: exports.DEFAULT_RUNTIME,
28
+ });
29
+ }
30
+ async function promptAutomaticBaseImageUpdates() {
31
+ return await (0, prompt_1.confirm)({
32
+ message: "Would you like to enable Automatic Base Image Updates (ABIU)?",
33
+ default: true,
34
+ });
35
+ }
@@ -50,7 +50,11 @@ function printBackendsTable(backends) {
50
50
  ];
51
51
  if (abiuEnabled) {
52
52
  let abiuStatus = "N/A";
53
- if (backend.automaticBaseImageUpdatesDisabled !== undefined) {
53
+ const runtimeValue = backend.runtime?.value ?? "";
54
+ if (runtimeValue === "" || runtimeValue === "nodejs") {
55
+ abiuStatus = "Disabled";
56
+ }
57
+ else {
54
58
  abiuStatus = backend.automaticBaseImageUpdatesDisabled ? "Disabled" : "Enabled";
55
59
  }
56
60
  row.push(abiuStatus);
@@ -19,6 +19,7 @@ exports.command = new command_1.Command("ext:info <extensionName>")
19
19
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
20
20
  .action(async (extensionName, options) => {
21
21
  let spec;
22
+ let version;
22
23
  if ((0, localHelper_1.isLocalExtension)(extensionName)) {
23
24
  if (!options.markdown) {
24
25
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `reading extension from directory: ${extensionName}`);
@@ -39,7 +40,7 @@ exports.command = new command_1.Command("ext:info <extensionName>")
39
40
  const [name, version] = extensionName.split("@");
40
41
  extensionName = `firebase/${name}@${version || "latest"}`;
41
42
  }
42
- const version = await extensionsApi.getExtensionVersion(extensionName);
43
+ version = await extensionsApi.getExtensionVersion(extensionName);
43
44
  spec = version.spec;
44
45
  }
45
46
  if (!options.markdown) {
@@ -56,6 +57,9 @@ exports.command = new command_1.Command("ext:info <extensionName>")
56
57
  const url = spec.author?.url;
57
58
  const urlMarkdown = url ? `(**[${url}](${url})**)` : "";
58
59
  lines.push(`**Author**: ${authorName} ${urlMarkdown}`);
60
+ if (version?.sourceDownloadUri) {
61
+ lines.push(`**Download URL**: ${version.sourceDownloadUri}`);
62
+ }
59
63
  if (spec.description) {
60
64
  lines.push(`**Description**: ${spec.description}`);
61
65
  }
@@ -43,6 +43,8 @@ async function listExtensions(projectId) {
43
43
  state,
44
44
  version,
45
45
  updateTime,
46
+ params: instance.config.params,
47
+ systemParams: instance.config.systemParams,
46
48
  });
47
49
  });
48
50
  (0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `list of extensions installed in ${clc.bold(projectId)}:`);
@@ -16,6 +16,7 @@ exports.createRollout = createRollout;
16
16
  exports.listRollouts = listRollouts;
17
17
  exports.updateTraffic = updateTraffic;
18
18
  exports.listLocations = listLocations;
19
+ exports.listSupportedRuntimes = listSupportedRuntimes;
19
20
  exports.ensureApiEnabled = ensureApiEnabled;
20
21
  exports.getNextRolloutId = getNextRolloutId;
21
22
  const proto = require("../gcp/proto");
@@ -176,6 +177,11 @@ async function listLocations(projectId) {
176
177
  } while (pageToken);
177
178
  return locations;
178
179
  }
180
+ async function listSupportedRuntimes(projectId, location) {
181
+ const name = `projects/${projectId}/locations/${location}/supportedRuntimes`;
182
+ const res = await exports.client.get(name);
183
+ return res.body.supportedRuntimes || [];
184
+ }
179
185
  async function ensureApiEnabled(options) {
180
186
  const projectId = (0, projectUtils_1.needProjectId)(options);
181
187
  return await (0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.apphostingOrigin)(), "app hosting", true);
@@ -16,7 +16,8 @@ const templates_1 = require("../../templates");
16
16
  const utils = require("../../utils");
17
17
  const utils_1 = require("../../utils");
18
18
  const APPHOSTING_YAML_TEMPLATE = (0, templates_1.readTemplateSync)("init/apphosting/apphosting.yaml");
19
- async function doSetup(setup, config) {
19
+ async function doSetup(setup, config, options) {
20
+ const { dynamicImport } = eval("require")("../../dynamicImport");
20
21
  const projectId = setup.projectId;
21
22
  if (!(await (0, cloudbilling_1.isBillingEnabled)(setup))) {
22
23
  throw new error_1.FirebaseError(`Firebase App Hosting requires billing to be enabled on your project. To upgrade, visit the following URL: https://console.firebase.google.com/project/${projectId}/usage/details`);
@@ -51,8 +52,16 @@ async function doSetup(setup, config) {
51
52
  if (!webApp) {
52
53
  utils.logWarning(`Firebase web app not set`);
53
54
  }
55
+ const experiments = await dynamicImport("./experiments");
56
+ const prompts = await dynamicImport("./apphosting/prompts");
57
+ let runtime = experiments.isEnabled("abiu") ? prompts.DEFAULT_RUNTIME : undefined;
58
+ let automaticBaseImageUpdatesDisabled = experiments.isEnabled("abiu") ? false : undefined;
59
+ if (experiments.isEnabled("abiu") && !options.nonInteractive) {
60
+ runtime = await prompts.promptRuntime(projectId, location);
61
+ automaticBaseImageUpdatesDisabled = !(await prompts.promptAutomaticBaseImageUpdates());
62
+ }
54
63
  const createBackendSpinner = ora("Creating your new backend...").start();
55
- const backend = await (0, backend_1.createBackend)(projectId, location, backendId, null, undefined, webApp?.id);
64
+ const backend = await (0, backend_1.createBackend)(projectId, location, backendId, null, undefined, webApp?.id, "/", runtime, automaticBaseImageUpdatesDisabled);
56
65
  createBackendSpinner.succeed(`Successfully created backend!\n\t${backend.name}\n`);
57
66
  }
58
67
  (0, utils_1.logBullet)(`${clc.yellow("===")} Deploy local source setup`);
@@ -11,6 +11,7 @@ const projectConfig_1 = require("../../../functions/projectConfig");
11
11
  const error_1 = require("../../../error");
12
12
  const api_1 = require("../../../api");
13
13
  const supported = require("../../../deploy/functions/runtimes/supported");
14
+ const experiments = require("../../../experiments");
14
15
  const MAX_ATTEMPTS = 5;
15
16
  async function askQuestions(setup, config, options) {
16
17
  const projectId = setup?.rcfile?.projects?.default;
@@ -144,10 +145,12 @@ async function languageSetup(setup) {
144
145
  value: "python",
145
146
  });
146
147
  }
147
- choices.push({
148
- name: "Dart",
149
- value: "dart",
150
- });
148
+ if (experiments.isEnabled("functionsrunapionly")) {
149
+ choices.push({
150
+ name: "Dart",
151
+ value: "dart",
152
+ });
153
+ }
151
154
  const language = await (0, prompt_1.select)({
152
155
  message: "What language would you like to use to write Cloud Functions?",
153
156
  default: "javascript",
package/lib/mcp/index.js CHANGED
@@ -347,7 +347,7 @@ class FirebaseMcpServer {
347
347
  }
348
348
  }
349
349
  async mcpListResources() {
350
- await (0, track_1.trackGA4)("mcp_read_resource", { resource_name: "__list__" });
350
+ await this.trackGA4("mcp_list_resources", { resource_name: "__list__" });
351
351
  return {
352
352
  resources: resources_1.resources.map((r) => r.mcp),
353
353
  };
@@ -22,7 +22,7 @@ exports.read_resources = (0, tool_1.tool)("core", {
22
22
  }),
23
23
  }, async ({ uris }, ctx) => {
24
24
  if (!uris?.length) {
25
- void (0, track_1.trackGA4)("mcp_read_resource", { resource_name: "__list__" });
25
+ void (0, track_1.trackGA4)("mcp_list_resources", { resource_name: "__list__" });
26
26
  return (0, util_1.toContent)(resources_1.resources
27
27
  .map((r) => `Available resources:\n\n- [${r.mcp.title || r.mcp.name}](${r.mcp.uri}): ${r.mcp.description}`)
28
28
  .join("\n"));