firebase-tools 14.2.1 → 14.3.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 (148) hide show
  1. package/lib/api.js +4 -2
  2. package/lib/apphosting/backend.js +12 -23
  3. package/lib/apphosting/config.js +9 -20
  4. package/lib/apphosting/githubConnections.js +52 -80
  5. package/lib/apphosting/repo.js +22 -36
  6. package/lib/apphosting/secrets/dialogs.js +2 -3
  7. package/lib/apphosting/utils.js +1 -3
  8. package/lib/auth.js +1 -4
  9. package/lib/bin/cli.js +131 -0
  10. package/lib/bin/firebase.js +7 -123
  11. package/lib/bin/mcp.js +38 -0
  12. package/lib/commands/apphosting-backends-delete.js +5 -5
  13. package/lib/commands/apphosting-secrets-set.js +2 -6
  14. package/lib/commands/apps-create.js +2 -3
  15. package/lib/commands/apps-sdkconfig.js +2 -7
  16. package/lib/commands/database-import.js +4 -6
  17. package/lib/commands/database-remove.js +4 -6
  18. package/lib/commands/database-set.js +6 -6
  19. package/lib/commands/database-update.js +5 -5
  20. package/lib/commands/dataconnect-sql-shell.js +4 -6
  21. package/lib/commands/ext-dev-deprecate.js +1 -0
  22. package/lib/commands/ext-dev-init.js +3 -12
  23. package/lib/commands/ext-dev-register.js +2 -4
  24. package/lib/commands/ext-dev-undeprecate.js +1 -2
  25. package/lib/commands/ext-dev-usage.js +1 -3
  26. package/lib/commands/ext-export.js +1 -2
  27. package/lib/commands/ext-install.js +1 -0
  28. package/lib/commands/ext-sdk-install.js +1 -0
  29. package/lib/commands/ext-update.js +1 -0
  30. package/lib/commands/firestore-backups-delete.js +1 -2
  31. package/lib/commands/firestore-backups-schedules-delete.js +1 -2
  32. package/lib/commands/firestore-databases-delete.js +1 -5
  33. package/lib/commands/firestore-delete.js +6 -6
  34. package/lib/commands/functions-artifacts-setpolicy.js +12 -2
  35. package/lib/commands/functions-config-export.js +5 -9
  36. package/lib/commands/functions-delete.js +5 -5
  37. package/lib/commands/functions-deletegcfartifacts.js +4 -4
  38. package/lib/commands/functions-secrets-destroy.js +8 -10
  39. package/lib/commands/functions-secrets-prune.js +12 -13
  40. package/lib/commands/functions-secrets-set.js +11 -15
  41. package/lib/commands/hosting-channel-create.js +1 -2
  42. package/lib/commands/hosting-channel-delete.js +4 -4
  43. package/lib/commands/hosting-channel-open.js +2 -3
  44. package/lib/commands/hosting-disable.js +5 -5
  45. package/lib/commands/hosting-sites-delete.js +4 -4
  46. package/lib/commands/index.js +3 -0
  47. package/lib/commands/init.js +41 -58
  48. package/lib/commands/login.js +1 -5
  49. package/lib/commands/logout.js +2 -3
  50. package/lib/commands/mcp.js +11 -0
  51. package/lib/commands/open.js +1 -2
  52. package/lib/commands/projects-create.js +1 -2
  53. package/lib/commands/remoteconfig-rollback.js +5 -5
  54. package/lib/commands/use.js +110 -110
  55. package/lib/config.js +1 -2
  56. package/lib/dataconnect/build.js +2 -4
  57. package/lib/dataconnect/client.js +20 -1
  58. package/lib/dataconnect/schemaMigration.js +1 -6
  59. package/lib/deploy/functions/params.js +10 -17
  60. package/lib/deploy/functions/prompts.js +6 -28
  61. package/lib/emulator/commandUtils.js +12 -19
  62. package/lib/emulator/controller.js +1 -2
  63. package/lib/emulator/downloadableEmulators.js +12 -12
  64. package/lib/emulator/env.js +19 -20
  65. package/lib/emulator/functionsEmulator.js +0 -1
  66. package/lib/emulator/hub.js +2 -1
  67. package/lib/emulator/initEmulators.js +9 -20
  68. package/lib/emulator/ui.js +0 -2
  69. package/lib/experiments.js +5 -0
  70. package/lib/extensions/askUserForEventsConfig.js +6 -15
  71. package/lib/extensions/askUserForParam.js +23 -52
  72. package/lib/extensions/checkProjectBilling.js +3 -9
  73. package/lib/extensions/diagnose.js +3 -6
  74. package/lib/extensions/extensionsHelper.js +17 -27
  75. package/lib/extensions/manifest.js +1 -2
  76. package/lib/extensions/tos.js +10 -2
  77. package/lib/extensions/utils.js +1 -10
  78. package/lib/frameworks/index.js +5 -3
  79. package/lib/frameworks/next/index.js +7 -4
  80. package/lib/frameworks/vite/index.js +1 -2
  81. package/lib/functions/secrets.js +14 -15
  82. package/lib/gcp/auth.js +84 -1
  83. package/lib/gcp/firestore.js +12 -1
  84. package/lib/gif/fdcExperience.js +45 -0
  85. package/lib/hosting/api.js +4 -0
  86. package/lib/hosting/interactive.js +2 -3
  87. package/lib/init/features/account.js +2 -4
  88. package/lib/init/features/database.js +11 -20
  89. package/lib/init/features/dataconnect/index.js +7 -14
  90. package/lib/init/features/dataconnect/sdk.js +14 -19
  91. package/lib/init/features/emulators.js +19 -41
  92. package/lib/init/features/firestore/index.js +2 -6
  93. package/lib/init/features/firestore/indexes.js +17 -31
  94. package/lib/init/features/firestore/rules.js +17 -31
  95. package/lib/init/features/functions/index.js +9 -16
  96. package/lib/init/features/functions/javascript.js +16 -30
  97. package/lib/init/features/functions/npm-dependencies.js +4 -8
  98. package/lib/init/features/functions/python.js +1 -3
  99. package/lib/init/features/functions/typescript.js +24 -43
  100. package/lib/init/features/genkit/index.js +23 -38
  101. package/lib/init/features/hosting/github.js +20 -51
  102. package/lib/init/features/hosting/index.js +36 -57
  103. package/lib/init/features/project.js +6 -16
  104. package/lib/init/features/remoteconfig.js +2 -8
  105. package/lib/init/features/storage.js +1 -3
  106. package/lib/logger.js +11 -2
  107. package/lib/management/apps.js +19 -44
  108. package/lib/management/projects.js +17 -28
  109. package/lib/mcp/errors.js +15 -0
  110. package/lib/mcp/index.js +120 -0
  111. package/lib/mcp/tool.js +11 -0
  112. package/lib/mcp/tools/auth/disable_auth_user.js +30 -0
  113. package/lib/mcp/tools/auth/get_auth_user.js +29 -0
  114. package/lib/mcp/tools/auth/index.js +13 -0
  115. package/lib/mcp/tools/auth/set_auth_claims.js +34 -0
  116. package/lib/mcp/tools/auth/set_sms_region_policy.js +36 -0
  117. package/lib/mcp/tools/core/consult_firebase_assistant.js +27 -0
  118. package/lib/mcp/tools/core/get_firebase_directory.js +20 -0
  119. package/lib/mcp/tools/core/index.js +11 -0
  120. package/lib/mcp/tools/core/set_firebase_directory.js +33 -0
  121. package/lib/mcp/tools/dataconnect/converter.js +33 -0
  122. package/lib/mcp/tools/dataconnect/generate_dataconnect_operation.js +33 -0
  123. package/lib/mcp/tools/dataconnect/generate_dataconnect_schema.js +25 -0
  124. package/lib/mcp/tools/dataconnect/get_dataconnect_connector.js +31 -0
  125. package/lib/mcp/tools/dataconnect/get_dataconnect_schema.js +31 -0
  126. package/lib/mcp/tools/dataconnect/index.js +15 -0
  127. package/lib/mcp/tools/dataconnect/list_dataconnect_services.js +23 -0
  128. package/lib/mcp/tools/firestore/converter.js +57 -0
  129. package/lib/mcp/tools/firestore/get_firestore_documents.js +48 -0
  130. package/lib/mcp/tools/firestore/get_firestore_rules.js +26 -0
  131. package/lib/mcp/tools/firestore/index.js +11 -0
  132. package/lib/mcp/tools/firestore/list_firestore_collections.js +30 -0
  133. package/lib/mcp/tools/index.js +15 -0
  134. package/lib/mcp/tools/project/get_project.js +22 -0
  135. package/lib/mcp/tools/project/get_sdk_config.js +38 -0
  136. package/lib/mcp/tools/project/index.js +7 -0
  137. package/lib/mcp/tools/project/list_apps.js +29 -0
  138. package/lib/mcp/tools/storage/get_storage_rules.js +26 -0
  139. package/lib/mcp/tools/storage/index.js +5 -0
  140. package/lib/mcp/types.js +4 -0
  141. package/lib/mcp/util.js +52 -0
  142. package/lib/prompt.js +78 -65
  143. package/lib/requireTosAcceptance.js +4 -0
  144. package/lib/rulesDeploy.js +10 -15
  145. package/lib/track.js +1 -34
  146. package/lib/utils.js +27 -5
  147. package/package.json +6 -4
  148. package/templates/init/dataconnect/connector.yaml +3 -0
@@ -2,134 +2,18 @@
2
2
  "use strict";
3
3
  Object.defineProperty(exports, "__esModule", { value: true });
4
4
  const semver = require("semver");
5
+ const experiments_1 = require("../experiments");
5
6
  const pkg = require("../../package.json");
6
7
  const nodeVersion = process.version;
7
8
  if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
8
9
  console.error(`Firebase CLI v${pkg.version} is incompatible with Node.js ${nodeVersion} Please upgrade Node.js to version ${pkg.engines.node}`);
9
10
  process.exit(1);
10
11
  }
11
- const updateNotifierPkg = require("update-notifier-cjs");
12
- const clc = require("colorette");
13
- const marked_terminal_1 = require("marked-terminal");
14
- const updateNotifier = updateNotifierPkg({ pkg });
15
- const marked_1 = require("marked");
16
- marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
17
- const node_path_1 = require("node:path");
18
- const triple_beam_1 = require("triple-beam");
19
- const node_util_1 = require("node:util");
20
- const fs = require("node:fs");
21
- const configstore_1 = require("../configstore");
22
- const errorOut_1 = require("../errorOut");
23
- const handlePreviewToggles_1 = require("../handlePreviewToggles");
24
- const logger_1 = require("../logger");
25
- const client = require("..");
26
- const fsutils = require("../fsutils");
27
- const utils = require("../utils");
28
- const winston = require("winston");
29
- const args = process.argv.slice(2);
30
- let cmd;
31
- function findAvailableLogFile() {
32
- const candidates = ["firebase-debug.log"];
33
- for (let i = 1; i < 10; i++) {
34
- candidates.push(`firebase-debug.${i}.log`);
35
- }
36
- for (const c of candidates) {
37
- const logFilename = (0, node_path_1.join)(process.cwd(), c);
38
- try {
39
- const fd = fs.openSync(logFilename, "r+");
40
- fs.closeSync(fd);
41
- return logFilename;
42
- }
43
- catch (e) {
44
- if (e.code === "ENOENT") {
45
- return logFilename;
46
- }
47
- }
48
- }
49
- throw new Error("Unable to obtain permissions for firebase-debug.log");
50
- }
51
- const logFilename = findAvailableLogFile();
52
- if (!process.env.DEBUG && args.includes("--debug")) {
53
- process.env.DEBUG = "true";
12
+ if ((0, experiments_1.isEnabled)("mcp") && process.argv[2] === "experimental:mcp") {
13
+ const { mcp } = require("./mcp");
14
+ mcp();
54
15
  }
55
- process.env.IS_FIREBASE_CLI = "true";
56
- logger_1.logger.add(new winston.transports.File({
57
- level: "debug",
58
- filename: logFilename,
59
- format: winston.format.printf((info) => {
60
- const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(utils.tryStringify);
61
- return `[${info.level}] ${(0, node_util_1.stripVTControlCharacters)(segments.join(" "))}`;
62
- }),
63
- }));
64
- logger_1.logger.debug("-".repeat(70));
65
- logger_1.logger.debug("Command: ", process.argv.join(" "));
66
- logger_1.logger.debug("CLI Version: ", pkg.version);
67
- logger_1.logger.debug("Platform: ", process.platform);
68
- logger_1.logger.debug("Node Version: ", process.version);
69
- logger_1.logger.debug("Time: ", new Date().toString());
70
- if (utils.envOverrides.length) {
71
- logger_1.logger.debug("Env Overrides:", utils.envOverrides.join(", "));
72
- }
73
- logger_1.logger.debug("-".repeat(70));
74
- logger_1.logger.debug();
75
- const experiments_1 = require("../experiments");
76
- const fetchMOTD_1 = require("../fetchMOTD");
77
- (0, experiments_1.enableExperimentsFromCliEnvVariable)();
78
- (0, fetchMOTD_1.fetchMOTD)();
79
- process.on("exit", (code) => {
80
- code = process.exitCode || code;
81
- if (!process.env.DEBUG && code < 2 && fsutils.fileExistsSync(logFilename)) {
82
- fs.unlinkSync(logFilename);
83
- }
84
- if (code > 0 && process.stdout.isTTY) {
85
- const lastError = configstore_1.configstore.get("lastError") || 0;
86
- const timestamp = Date.now();
87
- if (lastError > timestamp - 120000) {
88
- let help;
89
- if (code === 1 && cmd) {
90
- help = "Having trouble? Try " + clc.bold("firebase [command] --help");
91
- }
92
- else {
93
- help = "Having trouble? Try again or contact support with contents of firebase-debug.log";
94
- }
95
- if (cmd) {
96
- console.log();
97
- console.log(help);
98
- }
99
- }
100
- configstore_1.configstore.set("lastError", timestamp);
101
- }
102
- else {
103
- configstore_1.configstore.delete("lastError");
104
- }
105
- try {
106
- const installMethod = !process.env.FIREPIT_VERSION ? "npm" : "automatic script";
107
- const updateCommand = !process.env.FIREPIT_VERSION
108
- ? "npm install -g firebase-tools"
109
- : "curl -sL https://firebase.tools | upgrade=true bash";
110
- const updateMessage = `Update available ${clc.gray("{currentVersion}")} → ${clc.green("{latestVersion}")}\n` +
111
- `To update to the latest version using ${installMethod}, run\n${clc.cyan(updateCommand)}\n` +
112
- `For other CLI management options, visit the ${(0, marked_1.marked)("[CLI documentation](https://firebase.google.com/docs/cli#update-cli)")}`;
113
- updateNotifier.notify({ defer: false, isGlobal: true, message: updateMessage });
114
- }
115
- catch (err) {
116
- logger_1.logger.debug("Error when notifying about new CLI updates:");
117
- if (err instanceof Error) {
118
- logger_1.logger.debug(err);
119
- }
120
- else {
121
- logger_1.logger.debug(`${err}`);
122
- }
123
- }
124
- });
125
- process.on("uncaughtException", (err) => {
126
- (0, errorOut_1.errorOut)(err);
127
- });
128
- if (!(0, handlePreviewToggles_1.handlePreviewToggles)(args)) {
129
- if (!args.length) {
130
- client.cli.help();
131
- }
132
- else {
133
- cmd = client.cli.parse(process.argv);
134
- }
16
+ else {
17
+ const { cli } = require("./cli");
18
+ cli(pkg);
135
19
  }
package/lib/bin/mcp.js ADDED
@@ -0,0 +1,38 @@
1
+ #!/usr/bin/env node
2
+ "use strict";
3
+ Object.defineProperty(exports, "__esModule", { value: true });
4
+ exports.mcp = void 0;
5
+ const logger_1 = require("../logger");
6
+ (0, logger_1.silenceStdout)();
7
+ const index_1 = require("../mcp/index");
8
+ const util_1 = require("util");
9
+ const types_1 = require("../mcp/types");
10
+ const STARTUP_MESSAGE = `
11
+ This is a running process of the Firebase MCP server. This command should only be executed by an MCP client. An example MCP client configuration might be:
12
+
13
+ {
14
+ "mcpServers": {
15
+ "firebase": {
16
+ "command": "firebase",
17
+ "args": ["experimental:mcp", "--dir", "/path/to/firebase/project"]
18
+ }
19
+ }
20
+ }
21
+ `;
22
+ async function mcp() {
23
+ const { values } = (0, util_1.parseArgs)({
24
+ options: {
25
+ only: { type: "string", default: "" },
26
+ dir: { type: "string" },
27
+ },
28
+ allowPositionals: true,
29
+ });
30
+ const activeFeatures = (values.only || "")
31
+ .split(",")
32
+ .filter((f) => types_1.SERVER_FEATURES.includes(f));
33
+ const server = new index_1.FirebaseMcpServer({ activeFeatures, projectRoot: values.dir });
34
+ await server.start();
35
+ if (process.stdin.isTTY)
36
+ process.stderr.write(STARTUP_MESSAGE);
37
+ }
38
+ exports.mcp = mcp;
@@ -21,12 +21,12 @@ exports.command = new command_1.Command("apphosting:backends:delete <backend>")
21
21
  const backends = await (0, backend_1.chooseBackends)(projectId, backendId, "Please select the backends you'd like to delete:", options.force);
22
22
  utils.logWarning("You are about to permanently delete these backend(s):");
23
23
  (0, apphosting_backends_list_1.printBackendsTable)(backends);
24
- const confirmDeletion = await (0, prompt_1.promptOnce)({
25
- type: "confirm",
26
- name: "force",
27
- default: false,
24
+ const confirmDeletion = await (0, prompt_1.confirm)({
28
25
  message: "Are you sure?",
29
- }, options);
26
+ default: false,
27
+ force: options.force,
28
+ nonInteractive: options.nonInteractive,
29
+ });
30
30
  if (!confirmDeletion) {
31
31
  return;
32
32
  }
@@ -46,9 +46,7 @@ exports.command = new command_1.Command("apphosting:secrets:set <secretName>")
46
46
  if (!created) {
47
47
  return;
48
48
  }
49
- const type = await prompt.promptOnce({
50
- type: "list",
51
- name: "type",
49
+ const type = await prompt.select({
52
50
  message: "Is this secret for production or only local testing?",
53
51
  choices: [
54
52
  { name: "Production", value: "production" },
@@ -56,9 +54,7 @@ exports.command = new command_1.Command("apphosting:secrets:set <secretName>")
56
54
  ],
57
55
  });
58
56
  if (type === "local") {
59
- const emailList = await prompt.promptOnce({
60
- type: "input",
61
- name: "emails",
57
+ const emailList = await prompt.input({
62
58
  message: "Please enter a comma separated list of user or groups who should have access to this secret:",
63
59
  });
64
60
  if (emailList.length) {
@@ -6,9 +6,9 @@ const command_1 = require("../command");
6
6
  const projectUtils_1 = require("../projectUtils");
7
7
  const error_1 = require("../error");
8
8
  const apps_1 = require("../management/apps");
9
- const prompt_1 = require("../prompt");
10
9
  const requireAuth_1 = require("../requireAuth");
11
10
  const logger_1 = require("../logger");
11
+ const prompt_1 = require("../prompt");
12
12
  function logPostAppCreationInformation(appMetadata, appPlatform) {
13
13
  logger_1.logger.info("");
14
14
  logger_1.logger.info(`🎉🎉🎉 Your Firebase ${appPlatform} App is ready! 🎉🎉🎉`);
@@ -41,8 +41,7 @@ exports.command = new command_1.Command("apps:create [platform] [displayName]")
41
41
  .action(async (platform = "", displayName, options) => {
42
42
  const projectId = (0, projectUtils_1.needProjectId)(options);
43
43
  if (!options.nonInteractive && !platform) {
44
- platform = await (0, prompt_1.promptOnce)({
45
- type: "list",
44
+ platform = await (0, prompt_1.select)({
46
45
  message: "Please choose the platform of the app:",
47
46
  choices: [
48
47
  { name: "iOS", value: apps_1.AppPlatform.IOS },
@@ -26,8 +26,7 @@ async function selectAppInteractively(apps, appPlatform) {
26
26
  value: app,
27
27
  };
28
28
  });
29
- return await (0, prompt_1.promptOnce)({
30
- type: "list",
29
+ return await (0, prompt_1.select)({
31
30
  message: `Select the ${appPlatform === apps_1.AppPlatform.ANY ? "" : appPlatform + " "}` +
32
31
  "app to get the configuration data:",
33
32
  choices,
@@ -88,11 +87,7 @@ exports.command = new command_1.Command("apps:sdkconfig [platform] [appId]")
88
87
  if (options.nonInteractive) {
89
88
  throw new error_1.FirebaseError(`${filename} already exists`);
90
89
  }
91
- const overwrite = await (0, prompt_1.promptOnce)({
92
- type: "confirm",
93
- default: false,
94
- message: `${filename} already exists. Do you want to overwrite?`,
95
- });
90
+ const overwrite = await (0, prompt_1.confirm)(`${filename} already exists. Do you want to overwrite?`);
96
91
  if (!overwrite) {
97
92
  return fileInfo;
98
93
  }
@@ -49,13 +49,11 @@ exports.command = new command_1.Command("database:import <path> [infile]")
49
49
  if (options.disableTriggers) {
50
50
  dbUrl.searchParams.set("disableTriggers", "true");
51
51
  }
52
- const confirm = await (0, prompt_1.promptOnce)({
53
- type: "confirm",
54
- name: "force",
55
- default: false,
52
+ const areYouSure = await (0, prompt_1.confirm)({
56
53
  message: "You are about to import data to " + clc.cyan(dbPath) + ". Are you sure?",
57
- }, options);
58
- if (!confirm) {
54
+ force: options.force,
55
+ });
56
+ if (!areYouSure) {
59
57
  throw new error_1.FirebaseError("Command aborted.");
60
58
  }
61
59
  const inStream = fs.createReadStream(infile);
@@ -27,13 +27,11 @@ exports.command = new command_1.Command("database:remove <path>")
27
27
  }
28
28
  const origin = (0, api_1.realtimeOriginOrEmulatorOrCustomUrl)(options.instanceDetails.databaseUrl);
29
29
  const databaseUrl = utils.getDatabaseUrl(origin, options.instance, path);
30
- const confirm = await (0, prompt_1.promptOnce)({
31
- type: "confirm",
32
- name: "force",
33
- default: false,
30
+ const areYouSure = await (0, prompt_1.confirm)({
34
31
  message: "You are about to remove all data at " + clc.cyan(databaseUrl) + ". Are you sure?",
35
- }, options);
36
- if (!confirm) {
32
+ force: options.force,
33
+ });
34
+ if (!areYouSure) {
37
35
  return utils.reject("Command aborted.", { exit: 1 });
38
36
  }
39
37
  const removeOps = new remove_1.default(options.instance, path, origin, !!options.disableTriggers);
@@ -36,13 +36,13 @@ exports.command = new command_1.Command("database:set <path> [infile]")
36
36
  if (options.disableTriggers) {
37
37
  dbJsonURL.searchParams.set("disableTriggers", "true");
38
38
  }
39
- const confirm = await (0, prompt_1.promptOnce)({
40
- type: "confirm",
41
- name: "force",
42
- default: false,
39
+ const confirmed = await (0, prompt_1.confirm)({
43
40
  message: "You are about to overwrite all data at " + clc.cyan(dbPath) + ". Are you sure?",
44
- }, options);
45
- if (!confirm) {
41
+ default: false,
42
+ force: options.force,
43
+ nonInteractive: options.nonInteractive,
44
+ });
45
+ if (!confirmed) {
46
46
  throw new error_1.FirebaseError("Command aborted.");
47
47
  }
48
48
  const inStream = utils.stringToStream(options.data) || (infile ? fs.createReadStream(infile) : process.stdin);
@@ -32,12 +32,12 @@ exports.command = new command_1.Command("database:update <path> [infile]")
32
32
  }
33
33
  const origin = (0, api_1.realtimeOriginOrEmulatorOrCustomUrl)(options.instanceDetails.databaseUrl);
34
34
  const url = utils.getDatabaseUrl(origin, options.instance, path);
35
- const confirmed = await (0, prompt_1.promptOnce)({
36
- type: "confirm",
37
- name: "force",
38
- default: false,
35
+ const confirmed = await (0, prompt_1.confirm)({
39
36
  message: `You are about to modify data at ${clc.cyan(url)}. Are you sure?`,
40
- }, options);
37
+ default: false,
38
+ force: options.force,
39
+ nonInteractive: options.nonInteractive,
40
+ });
41
41
  if (!confirmed) {
42
42
  throw new error_1.FirebaseError("Command aborted.");
43
43
  }
@@ -35,11 +35,9 @@ const sqlKeywords = [
35
35
  ];
36
36
  async function promptForQuery() {
37
37
  let query = "";
38
- let line = "";
38
+ const line = "";
39
39
  do {
40
- const question = {
41
- type: "input",
42
- name: "line",
40
+ let line = await (0, prompt_1.input)({
43
41
  message: query ? "> " : "Enter your SQL query (or '.exit'):",
44
42
  transformer: (input) => {
45
43
  return input
@@ -47,8 +45,8 @@ async function promptForQuery() {
47
45
  .map((word) => (sqlKeywords.includes(word.toUpperCase()) ? clc.cyan(word) : word))
48
46
  .join(" ");
49
47
  },
50
- };
51
- ({ line } = await (0, prompt_1.prompt)({ nonInteractive: false }, [question]));
48
+ nonInteractive: false,
49
+ });
52
50
  line = line.trimEnd();
53
51
  if (line.toLowerCase() === ".exit") {
54
52
  return ".exit";
@@ -50,6 +50,7 @@ async function deprecate(extensionRef, versionPredicate, options) {
50
50
  });
51
51
  if (filteredExtensionVersions.length > 0) {
52
52
  const consent = await (0, prompt_1.confirm)({
53
+ message: "Continue?",
53
54
  default: false,
54
55
  force: options.force,
55
56
  nonInteractive: options.nonInteractive,
@@ -30,9 +30,7 @@ exports.command = new command_1.Command("ext:dev:init")
30
30
  const config = new config_1.Config({}, { projectDir: cwd, cwd: cwd });
31
31
  try {
32
32
  let welcome;
33
- const lang = await (0, prompt_1.promptOnce)({
34
- type: "list",
35
- name: "language",
33
+ const lang = await (0, prompt_1.select)({
36
34
  message: "In which language do you want to write the Cloud Functions for your extension?",
37
35
  default: "javascript",
38
36
  choices: [
@@ -83,9 +81,7 @@ async function typescriptSelected(config) {
83
81
  const gitignoreTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/_gitignore");
84
82
  const mocharcTemplate = (0, templates_1.readTemplateSync)("extensions/typescript/_mocharc");
85
83
  const eslintTemplate = (0, templates_1.readTemplateSync)("init/functions/typescript/_eslintrc");
86
- const lint = await (0, prompt_1.promptOnce)({
87
- name: "lint",
88
- type: "confirm",
84
+ const lint = await (0, prompt_1.confirm)({
89
85
  message: "Do you want to use ESLint to catch probable bugs and enforce style?",
90
86
  default: true,
91
87
  });
@@ -119,12 +115,7 @@ async function javascriptSelected(config) {
119
115
  const packageNoLintingTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/package.nolint.json");
120
116
  const gitignoreTemplate = (0, templates_1.readTemplateSync)("extensions/javascript/_gitignore");
121
117
  const eslintTemplate = (0, templates_1.readTemplateSync)("init/functions/javascript/_eslintrc");
122
- const lint = await (0, prompt_1.promptOnce)({
123
- name: "lint",
124
- type: "confirm",
125
- message: "Do you want to use ESLint to catch probable bugs and enforce style?",
126
- default: false,
127
- });
118
+ const lint = await (0, prompt_1.confirm)("Do you want to use ESLint to catch probable bugs and enforce style?");
128
119
  const templates = readCommonTemplates();
129
120
  await config.askWriteProjectFile("extension.yaml", templates.extSpecTemplate);
130
121
  await config.askWriteProjectFile("PREINSTALL.md", templates.preinstallTemplate);
@@ -6,12 +6,12 @@ const marked_1 = require("marked");
6
6
  const command_1 = require("../command");
7
7
  const publisherApi_1 = require("../extensions/publisherApi");
8
8
  const projectUtils_1 = require("../projectUtils");
9
- const prompt_1 = require("../prompt");
10
9
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
11
10
  const tos_1 = require("../extensions/tos");
12
11
  const requirePermissions_1 = require("../requirePermissions");
13
12
  const error_1 = require("../error");
14
13
  const utils = require("../utils");
14
+ const prompt_1 = require("../prompt");
15
15
  exports.command = new command_1.Command("ext:dev:register")
16
16
  .description("register a publisher ID; run this before publishing your first extension")
17
17
  .before(requirePermissions_1.requirePermissions, ["firebaseextensions.sources.create"])
@@ -24,9 +24,7 @@ exports.command = new command_1.Command("ext:dev:register")
24
24
  "This value identifies you in Firebase's registry of extensions as the author of your extensions. " +
25
25
  "Examples: my-company-name, MyGitHubUsername.\n\n" +
26
26
  "You can only do this once for each project.";
27
- const publisherId = await (0, prompt_1.promptOnce)({
28
- name: "publisherId",
29
- type: "input",
27
+ const publisherId = await (0, prompt_1.input)({
30
28
  message: msg,
31
29
  default: projectId,
32
30
  });
@@ -37,8 +37,7 @@ exports.command = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
37
37
  if (extensionVersions.length > 0) {
38
38
  if (!options.force) {
39
39
  const confirmMessage = "You are about to undeprecate these extension version(s). Do you wish to continue?";
40
- const consent = await (0, prompt_1.promptOnce)({
41
- type: "confirm",
40
+ const consent = await (0, prompt_1.confirm)({
42
41
  message: confirmMessage,
43
42
  default: false,
44
43
  });
@@ -44,9 +44,7 @@ exports.command = new command_1.Command("ext:dev:usage <publisherId>")
44
44
  " - This publisher has not published any extensions\n\n" +
45
45
  "If you are expecting some extensions to appear, please make sure you have the correct publisher ID and try again.");
46
46
  }
47
- extensionName = await (0, prompt_1.promptOnce)({
48
- type: "list",
49
- name: "extension",
47
+ extensionName = await (0, prompt_1.select)({
50
48
  message: "Which published extension do you want to view the stats for?",
51
49
  choices: extensions.map((e) => {
52
50
  const [_, name] = e.ref.split("/");
@@ -37,9 +37,8 @@ exports.command = new command_1.Command("ext:export")
37
37
  (0, export_1.displayExportInfo)(withRefSubbed, withoutRef);
38
38
  if (!options.nonInteractive &&
39
39
  !options.force &&
40
- !(await (0, prompt_1.promptOnce)({
40
+ !(await (0, prompt_1.confirm)({
41
41
  message: "Do you wish to add these Extension instances to firebase.json?",
42
- type: "confirm",
43
42
  default: true,
44
43
  }))) {
45
44
  logger_1.logger.info("Exiting. No changes made.");
@@ -75,6 +75,7 @@ exports.command = new command_1.Command("ext:install [extensionRefOrLocalPath]")
75
75
  throw new error_1.FirebaseError(`Failed to parse ${clc.bold(extensionRef)} as an extension version or a path to a local extension. Please specify a valid reference.`);
76
76
  }
77
77
  if (!(await (0, prompt_1.confirm)({
78
+ message: "Continue?",
78
79
  nonInteractive: options.nonInteractive,
79
80
  force: options.force,
80
81
  default: true,
@@ -75,6 +75,7 @@ exports.command = new command_1.Command("ext:sdk:install <extensionName>")
75
75
  }
76
76
  }
77
77
  if (!(await (0, prompt_1.confirm)({
78
+ message: "Continue?",
78
79
  nonInteractive: options.nonInteractive,
79
80
  force: options.force,
80
81
  default: true,
@@ -52,6 +52,7 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
52
52
  }
53
53
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `Updating ${clc.bold(instanceId)} from version ${clc.bold(oldExtensionVersion.ref)} to version ${clc.bold(newExtensionVersion.ref)}.`);
54
54
  if (!(await (0, prompt_1.confirm)({
55
+ message: "Continue?",
55
56
  nonInteractive: options.nonInteractive,
56
57
  force: options.force,
57
58
  default: false,
@@ -19,8 +19,7 @@ exports.command = new command_1.Command("firestore:backups:delete <backup>")
19
19
  const backup = await (0, firestore_1.getBackup)(backupName);
20
20
  if (!options.force) {
21
21
  const confirmMessage = `You are about to delete ${backupName}. Do you wish to continue?`;
22
- const consent = await (0, prompt_1.promptOnce)({
23
- type: "confirm",
22
+ const consent = await (0, prompt_1.confirm)({
24
23
  message: confirmMessage,
25
24
  default: false,
26
25
  });
@@ -19,8 +19,7 @@ exports.command = new command_1.Command("firestore:backups:schedules:delete <bac
19
19
  const backupSchedule = await (0, firestore_1.getBackupSchedule)(backupScheduleName);
20
20
  if (!options.force) {
21
21
  const confirmMessage = `You are about to delete ${backupScheduleName}. Do you wish to continue?`;
22
- const consent = await (0, prompt_1.promptOnce)({
23
- type: "confirm",
22
+ const consent = await (0, prompt_1.confirm)({
24
23
  message: confirmMessage,
25
24
  default: false,
26
25
  });
@@ -21,11 +21,7 @@ exports.command = new command_1.Command("firestore:databases:delete <database>")
21
21
  const printer = new pretty_print_1.PrettyPrint();
22
22
  if (!options.force) {
23
23
  const confirmMessage = `You are about to delete projects/${options.project}/databases/${database}. Do you wish to continue?`;
24
- const consent = await (0, prompt_1.promptOnce)({
25
- type: "confirm",
26
- message: confirmMessage,
27
- default: false,
28
- });
24
+ const consent = await (0, prompt_1.confirm)(confirmMessage);
29
25
  if (!consent) {
30
26
  throw new error_1.FirebaseError("Delete database canceled.");
31
27
  }
@@ -71,13 +71,13 @@ exports.command = new command_1.Command("firestore:delete [path]")
71
71
  allCollections: options.allCollections,
72
72
  databaseId: options.database,
73
73
  });
74
- const confirm = await (0, prompt_1.promptOnce)({
75
- type: "confirm",
76
- name: "force",
77
- default: false,
74
+ const confirmed = await (0, prompt_1.confirm)({
78
75
  message: confirmationMessage(deleteOp, options),
79
- }, options);
80
- if (!confirm) {
76
+ default: false,
77
+ force: options.force,
78
+ nonInteractive: options.nonInteractive,
79
+ });
80
+ if (!confirmed) {
81
81
  return utils.reject("Command aborted.", { exit: 1 });
82
82
  }
83
83
  if (options.allCollections) {
@@ -62,7 +62,12 @@ exports.command = new command_1.Command("functions:artifacts:setpolicy")
62
62
  if (existingPolicy) {
63
63
  (0, utils_1.logBullet)(`Note: This will remove the existing cleanup policy from the repository.`);
64
64
  }
65
- const confirmOptOut = await (0, prompt_1.confirm)(Object.assign(Object.assign({}, options), { default: true, message: "Do you want to continue?" }));
65
+ const confirmOptOut = await (0, prompt_1.confirm)({
66
+ message: "Do you want to continue?",
67
+ default: true,
68
+ force: options.force,
69
+ nonInteractive: options.nonInteractive,
70
+ });
66
71
  if (!confirmOptOut) {
67
72
  throw new error_1.FirebaseError("Command aborted.", { exit: 1 });
68
73
  }
@@ -103,7 +108,12 @@ exports.command = new command_1.Command("functions:artifacts:setpolicy")
103
108
  if (artifacts.hasCleanupOptOut(repository)) {
104
109
  (0, utils_1.logBullet)(`Note: This repository was previously opted out from cleanup policy. This action will remove the opt-out status.`);
105
110
  }
106
- const confirmSetup = await (0, prompt_1.confirm)(Object.assign(Object.assign({}, options), { default: true, message: "Do you want to continue?" }));
111
+ const confirmSetup = await (0, prompt_1.confirm)({
112
+ message: "Do you want to continue?",
113
+ default: true,
114
+ force: options.force,
115
+ nonInteractive: options.nonInteractive,
116
+ });
107
117
  if (!confirmSetup) {
108
118
  throw new error_1.FirebaseError("Command aborted.", { exit: 1 });
109
119
  }
@@ -42,13 +42,11 @@ async function checkRequiredPermission(pInfos) {
42
42
  }
43
43
  (0, utils_1.logWarning)("You are missing the following permissions to read functions config on project " +
44
44
  `${clc.bold(pInfo.projectId)}:\n\t${result.missing.join("\n\t")}`);
45
- const confirm = await (0, prompt_1.promptOnce)({
46
- type: "confirm",
47
- name: "skip",
48
- default: true,
45
+ const confirmed = await (0, prompt_1.confirm)({
49
46
  message: `Continue without importing configs from project ${pInfo.projectId}?`,
47
+ default: true,
50
48
  });
51
- if (!confirm) {
49
+ if (!confirmed) {
52
50
  throw new error_1.FirebaseError("Command aborted!");
53
51
  }
54
52
  }
@@ -56,12 +54,10 @@ async function checkRequiredPermission(pInfos) {
56
54
  async function promptForPrefix(errMsg) {
57
55
  (0, utils_1.logWarning)("The following configs keys could not be exported as environment variables:\n");
58
56
  (0, utils_1.logWarning)(errMsg);
59
- return await (0, prompt_1.promptOnce)({
60
- type: "input",
61
- name: "prefix",
57
+ return await (0, prompt_1.input)({
62
58
  default: "CONFIG_",
63
59
  message: "Enter a PREFIX to rename invalid environment variable keys:",
64
- }, {});
60
+ });
65
61
  }
66
62
  function fromEntries(itr) {
67
63
  const obj = {};
@@ -56,14 +56,14 @@ exports.command = new command_1.Command("functions:delete [filters...]")
56
56
  throw new error_1.FirebaseError(`The specified filters do not match any existing functions in project ${clc.bold(context.projectId)}.`);
57
57
  }
58
58
  const deleteList = allEpToDelete.map((func) => `\t${helper.getFunctionLabel(func)}`).join("\n");
59
- const confirmDeletion = await (0, prompt_1.promptOnce)({
60
- type: "confirm",
61
- name: "force",
62
- default: false,
59
+ const confirmDeletion = await (0, prompt_1.confirm)({
63
60
  message: "You are about to delete the following Cloud Functions:\n" +
64
61
  deleteList +
65
62
  "\n Are you sure?",
66
- }, options);
63
+ default: false,
64
+ force: options.force,
65
+ nonInteractive: options.nonInteractive,
66
+ });
67
67
  if (!confirmDeletion) {
68
68
  throw new error_1.FirebaseError("Command aborted.");
69
69
  }