firebase-tools 14.2.2 → 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 (118) 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/commands/apphosting-backends-delete.js +5 -5
  10. package/lib/commands/apphosting-secrets-set.js +2 -6
  11. package/lib/commands/apps-create.js +2 -3
  12. package/lib/commands/apps-sdkconfig.js +2 -7
  13. package/lib/commands/database-import.js +4 -6
  14. package/lib/commands/database-remove.js +4 -6
  15. package/lib/commands/database-set.js +6 -6
  16. package/lib/commands/database-update.js +5 -5
  17. package/lib/commands/dataconnect-sql-shell.js +4 -6
  18. package/lib/commands/ext-dev-deprecate.js +1 -0
  19. package/lib/commands/ext-dev-init.js +3 -12
  20. package/lib/commands/ext-dev-register.js +2 -4
  21. package/lib/commands/ext-dev-undeprecate.js +1 -2
  22. package/lib/commands/ext-dev-usage.js +1 -3
  23. package/lib/commands/ext-export.js +1 -2
  24. package/lib/commands/ext-install.js +1 -0
  25. package/lib/commands/ext-sdk-install.js +1 -0
  26. package/lib/commands/ext-update.js +1 -0
  27. package/lib/commands/firestore-backups-delete.js +1 -2
  28. package/lib/commands/firestore-backups-schedules-delete.js +1 -2
  29. package/lib/commands/firestore-databases-delete.js +1 -5
  30. package/lib/commands/firestore-delete.js +6 -6
  31. package/lib/commands/functions-artifacts-setpolicy.js +12 -2
  32. package/lib/commands/functions-config-export.js +5 -9
  33. package/lib/commands/functions-delete.js +5 -5
  34. package/lib/commands/functions-deletegcfartifacts.js +4 -4
  35. package/lib/commands/functions-secrets-destroy.js +8 -10
  36. package/lib/commands/functions-secrets-prune.js +12 -13
  37. package/lib/commands/functions-secrets-set.js +11 -15
  38. package/lib/commands/hosting-channel-create.js +1 -2
  39. package/lib/commands/hosting-channel-delete.js +4 -4
  40. package/lib/commands/hosting-channel-open.js +2 -3
  41. package/lib/commands/hosting-disable.js +5 -5
  42. package/lib/commands/hosting-sites-delete.js +4 -4
  43. package/lib/commands/init.js +41 -58
  44. package/lib/commands/login.js +1 -5
  45. package/lib/commands/logout.js +2 -3
  46. package/lib/commands/open.js +1 -2
  47. package/lib/commands/projects-create.js +1 -2
  48. package/lib/commands/remoteconfig-rollback.js +5 -5
  49. package/lib/commands/use.js +110 -110
  50. package/lib/config.js +1 -2
  51. package/lib/dataconnect/build.js +2 -4
  52. package/lib/dataconnect/client.js +20 -1
  53. package/lib/dataconnect/schemaMigration.js +1 -6
  54. package/lib/deploy/functions/params.js +10 -17
  55. package/lib/deploy/functions/prompts.js +6 -28
  56. package/lib/emulator/commandUtils.js +4 -13
  57. package/lib/emulator/controller.js +1 -2
  58. package/lib/emulator/downloadableEmulators.js +12 -12
  59. package/lib/emulator/initEmulators.js +9 -20
  60. package/lib/extensions/askUserForEventsConfig.js +6 -15
  61. package/lib/extensions/askUserForParam.js +23 -52
  62. package/lib/extensions/checkProjectBilling.js +3 -9
  63. package/lib/extensions/diagnose.js +3 -6
  64. package/lib/extensions/extensionsHelper.js +17 -27
  65. package/lib/extensions/manifest.js +1 -2
  66. package/lib/extensions/tos.js +10 -2
  67. package/lib/extensions/utils.js +1 -10
  68. package/lib/frameworks/index.js +1 -2
  69. package/lib/frameworks/next/index.js +7 -4
  70. package/lib/frameworks/vite/index.js +1 -2
  71. package/lib/functions/secrets.js +14 -15
  72. package/lib/gcp/auth.js +29 -1
  73. package/lib/gif/fdcExperience.js +45 -0
  74. package/lib/hosting/interactive.js +2 -3
  75. package/lib/init/features/account.js +2 -4
  76. package/lib/init/features/database.js +11 -20
  77. package/lib/init/features/dataconnect/index.js +7 -14
  78. package/lib/init/features/dataconnect/sdk.js +15 -22
  79. package/lib/init/features/emulators.js +19 -41
  80. package/lib/init/features/firestore/index.js +2 -6
  81. package/lib/init/features/firestore/indexes.js +17 -31
  82. package/lib/init/features/firestore/rules.js +17 -31
  83. package/lib/init/features/functions/index.js +9 -16
  84. package/lib/init/features/functions/javascript.js +16 -30
  85. package/lib/init/features/functions/npm-dependencies.js +4 -8
  86. package/lib/init/features/functions/python.js +1 -3
  87. package/lib/init/features/functions/typescript.js +24 -43
  88. package/lib/init/features/genkit/index.js +23 -38
  89. package/lib/init/features/hosting/github.js +20 -51
  90. package/lib/init/features/hosting/index.js +36 -57
  91. package/lib/init/features/project.js +6 -16
  92. package/lib/init/features/remoteconfig.js +2 -8
  93. package/lib/init/features/storage.js +1 -3
  94. package/lib/management/apps.js +19 -44
  95. package/lib/management/projects.js +17 -28
  96. package/lib/mcp/index.js +12 -1
  97. package/lib/mcp/tools/auth/index.js +7 -1
  98. package/lib/mcp/tools/auth/set_sms_region_policy.js +36 -0
  99. package/lib/mcp/tools/core/consult_firebase_assistant.js +27 -0
  100. package/lib/mcp/tools/core/index.js +6 -1
  101. package/lib/mcp/tools/dataconnect/converter.js +33 -0
  102. package/lib/mcp/tools/dataconnect/generate_dataconnect_operation.js +33 -0
  103. package/lib/mcp/tools/dataconnect/generate_dataconnect_schema.js +25 -0
  104. package/lib/mcp/tools/dataconnect/get_dataconnect_connector.js +31 -0
  105. package/lib/mcp/tools/dataconnect/get_dataconnect_schema.js +31 -0
  106. package/lib/mcp/tools/dataconnect/index.js +11 -1
  107. package/lib/mcp/tools/firestore/{get_documents.js → get_firestore_documents.js} +5 -5
  108. package/lib/mcp/tools/firestore/index.js +7 -3
  109. package/lib/mcp/tools/firestore/{list_collections.js → list_firestore_collections.js} +3 -3
  110. package/lib/mcp/tools/index.js +2 -1
  111. package/lib/mcp/tools/storage/get_storage_rules.js +26 -0
  112. package/lib/mcp/tools/storage/index.js +5 -0
  113. package/lib/prompt.js +78 -65
  114. package/lib/requireTosAcceptance.js +4 -0
  115. package/lib/rulesDeploy.js +10 -15
  116. package/lib/track.js +1 -34
  117. package/lib/utils.js +27 -5
  118. package/package.json +2 -3
@@ -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
  }
@@ -27,12 +27,12 @@ exports.command = new command_1.Command("functions:deletegcfartifacts")
27
27
  const dockerHelper = {};
28
28
  try {
29
29
  const gcfPaths = await (0, containerCleaner_1.listGcfPaths)(projectId, regions, dockerHelper);
30
- const confirmDeletion = await (0, prompt_1.promptOnce)({
31
- type: "confirm",
32
- name: "force",
30
+ const confirmDeletion = await (0, prompt_1.confirm)({
33
31
  default: false,
34
32
  message: getConfirmationMessage(gcfPaths),
35
- }, options);
33
+ force: options.force,
34
+ nonInteractive: options.nonInteractive,
35
+ });
36
36
  if (!confirmDeletion) {
37
37
  throw new error_1.FirebaseError("Command aborted.", { exit: 1 });
38
38
  }
@@ -40,16 +40,14 @@ exports.command = new command_1.Command("functions:secrets:destroy <KEY>[@versio
40
40
  return;
41
41
  }
42
42
  }
43
- if (!options.force) {
44
- const confirm = await (0, prompt_1.promptOnce)({
45
- name: "destroy",
46
- type: "confirm",
47
- default: true,
48
- message: `Are you sure you want to destroy ${sv.secret.name}@${sv.versionId}`,
49
- }, options);
50
- if (!confirm) {
51
- return;
52
- }
43
+ const areYouSure = await (0, prompt_1.confirm)({
44
+ message: `Are you sure you want to destroy ${sv.secret.name}@${sv.versionId}`,
45
+ default: true,
46
+ nonInteractive: options.nonInteractive,
47
+ force: options.force,
48
+ });
49
+ if (!areYouSure) {
50
+ return;
53
51
  }
54
52
  await (0, secretManager_1.destroySecretVersion)(projectId, name, version);
55
53
  (0, utils_1.logBullet)(`Destroyed secret version ${name}@${sv.versionId}`);
@@ -38,20 +38,19 @@ exports.command = new command_1.Command("functions:secrets:prune")
38
38
  }
39
39
  (0, utils_1.logBullet)(`Found ${pruned.length} unused active secret versions:\n\t` +
40
40
  pruned.map((sv) => `${sv.secret}@${sv.version}`).join("\n\t"));
41
- if (!options.force) {
42
- const confirm = await (0, prompt_1.promptOnce)({
43
- name: "destroy",
44
- type: "confirm",
45
- default: true,
41
+ const confirmed = options.destroy ||
42
+ (await (0, prompt_1.confirm)({
46
43
  message: `Do you want to destroy unused secret versions?`,
47
- }, options);
48
- if (!confirm) {
49
- (0, utils_1.logBullet)("Run the following commands to destroy each unused secret version:\n\t" +
50
- pruned
51
- .map((sv) => `firebase functions:secrets:destroy ${sv.secret}@${sv.version}`)
52
- .join("\n\t"));
53
- return;
54
- }
44
+ default: true,
45
+ force: options.force,
46
+ nonInteractive: options.nonInteractive,
47
+ }));
48
+ if (!confirmed) {
49
+ (0, utils_1.logBullet)("Run the following commands to destroy each unused secret version:\n\t" +
50
+ pruned
51
+ .map((sv) => `firebase functions:secrets:destroy ${sv.secret}@${sv.version}`)
52
+ .join("\n\t"));
53
+ return;
55
54
  }
56
55
  await Promise.all(pruned.map((sv) => (0, secretManager_1.destroySecretVersion)(projectId, sv.secret, sv.version)));
57
56
  (0, utils_1.logSuccess)("Destroyed all unused secrets!");
@@ -53,21 +53,17 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
53
53
  }
54
54
  (0, utils_1.logBullet)(`${endpointsToUpdate.length} functions are using stale version of secret ${secret.name}:\n\t` +
55
55
  endpointsToUpdate.map((e) => `${e.id}(${e.region})`).join("\n\t"));
56
- if (!options.force) {
57
- let confirm = false;
58
- if (!options.nonInteractive) {
59
- confirm = await (0, prompt_1.promptOnce)({
60
- name: "redeploy",
61
- type: "confirm",
62
- default: true,
63
- message: `Do you want to re-deploy the functions and destroy the stale version of secret ${secret.name}?`,
64
- }, options);
65
- }
66
- if (!confirm) {
67
- (0, utils_1.logBullet)("Please deploy your functions for the change to take effect by running:\n\t" +
68
- clc.bold("firebase deploy --only functions"));
69
- return;
70
- }
56
+ const redeploy = options.nonInteractive
57
+ ? false
58
+ : await (0, prompt_1.confirm)({
59
+ message: `Do you want to re-deploy the functions and destroy the stale version of secret ${secret.name}?`,
60
+ default: true,
61
+ force: options.force,
62
+ });
63
+ if (!redeploy) {
64
+ (0, utils_1.logBullet)("Please deploy your functions for the change to take effect by running:\n\t" +
65
+ clc.bold("firebase deploy --only functions"));
66
+ return;
71
67
  }
72
68
  const updateOps = endpointsToUpdate.map(async (e) => {
73
69
  (0, utils_1.logBullet)(`Updating function ${e.id}(${e.region})...`);
@@ -45,8 +45,7 @@ exports.command = new command_1.Command("hosting:channel:create [channelId]")
45
45
  }
46
46
  channelId =
47
47
  channelId ||
48
- (await (0, prompt_1.promptOnce)({
49
- type: "input",
48
+ (await (0, prompt_1.input)({
50
49
  message: "Please provide a URL-friendly name for the channel:",
51
50
  validate: (s) => s.length > 0,
52
51
  }));
@@ -24,12 +24,12 @@ exports.command = new command_1.Command("hosting:channel:delete <channelId>")
24
24
  const siteId = options.site;
25
25
  channelId = (0, api_1.normalizeName)(channelId);
26
26
  const channel = await (0, api_1.getChannel)(projectId, siteId, channelId);
27
- const confirmed = await (0, prompt_1.promptOnce)({
28
- name: "force",
29
- type: "confirm",
27
+ const confirmed = await (0, prompt_1.confirm)({
30
28
  message: `Are you sure you want to delete the Hosting Channel ${(0, colorette_1.underline)(channelId)} for site ${(0, colorette_1.underline)(siteId)}?`,
31
29
  default: false,
32
- }, options);
30
+ force: options.force,
31
+ nonInteractive: options.nonInteractive,
32
+ });
33
33
  if (!confirmed) {
34
34
  return;
35
35
  }
@@ -11,8 +11,8 @@ const requirePermissions_1 = require("../requirePermissions");
11
11
  const projectUtils_1 = require("../projectUtils");
12
12
  const requireConfig_1 = require("../requireConfig");
13
13
  const utils_1 = require("../utils");
14
- const prompt_1 = require("../prompt");
15
14
  const requireHostingSite_1 = require("../requireHostingSite");
15
+ const prompt_1 = require("../prompt");
16
16
  exports.command = new command_1.Command("hosting:channel:open [channelId]")
17
17
  .description("opens the URL for a Firebase Hosting channel")
18
18
  .help("if unable to open the URL in a browser, it will be displayed in the output")
@@ -29,8 +29,7 @@ exports.command = new command_1.Command("hosting:channel:open [channelId]")
29
29
  }
30
30
  const channels = await (0, api_1.listChannels)(projectId, siteId);
31
31
  (0, lodash_1.sortBy)(channels, ["name"]);
32
- channelId = await (0, prompt_1.promptOnce)({
33
- type: "list",
32
+ channelId = await (0, prompt_1.select)({
34
33
  message: "Which channel would you like to open?",
35
34
  choices: channels.map((c) => (0, lodash_1.last)(c.name.split("/")) || c.name),
36
35
  });
@@ -17,12 +17,12 @@ exports.command = new command_1.Command("hosting:disable")
17
17
  .before(requireHostingSite_1.requireHostingSite)
18
18
  .action(async (options) => {
19
19
  const siteToDisable = options.site;
20
- const confirm = await (0, prompt_1.promptOnce)({
21
- type: "confirm",
22
- name: "force",
20
+ const confirmed = await (0, prompt_1.confirm)({
23
21
  message: `Are you sure you want to disable Firebase Hosting for the site ${clc.underline(siteToDisable)}\n${clc.underline("This will immediately make your site inaccessible!")}`,
24
- }, options);
25
- if (!confirm) {
22
+ force: options.force,
23
+ nonInteractive: options.nonInteractive,
24
+ });
25
+ if (!confirmed) {
26
26
  return;
27
27
  }
28
28
  const c = new apiv2_1.Client({ urlPrefix: (0, api_1.hostingApiOrigin)(), apiVersion: "v1beta1", auth: true });
@@ -24,12 +24,12 @@ exports.command = new command_1.Command("hosting:sites:delete <siteId>")
24
24
  }
25
25
  logger_1.logger.info(`Deleting a site is a permanent action. If you delete a site, Firebase doesn't maintain records of deployed files or deployment history, and the site ${(0, colorette_1.underline)(siteId)} cannot be reactivated by you or anyone else.`);
26
26
  logger_1.logger.info();
27
- const confirmed = await (0, prompt_1.promptOnce)({
28
- name: "force",
29
- type: "confirm",
27
+ const confirmed = await (0, prompt_1.confirm)({
30
28
  message: `Are you sure you want to delete the Hosting site ${(0, colorette_1.underline)(siteId)} for project ${(0, colorette_1.underline)(projectId)}? `,
31
29
  default: false,
32
- }, options);
30
+ force: options.force,
31
+ nonInteractive: options.nonInteractive,
32
+ });
33
33
  if (!confirmed) {
34
34
  return;
35
35
  }