firebase-tools 10.0.1 → 10.1.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 (216) hide show
  1. package/lib/api.js +1 -0
  2. package/lib/apiv2.js +2 -2
  3. package/lib/appdistribution/client.js +1 -1
  4. package/lib/appdistribution/options-parser-util.js +1 -1
  5. package/lib/auth.js +2 -2
  6. package/lib/command.js +26 -26
  7. package/lib/commands/appdistribution-distribute.js +4 -4
  8. package/lib/commands/appdistribution-testers-add.js +2 -2
  9. package/lib/commands/appdistribution-testers-remove.js +2 -2
  10. package/lib/commands/apps-android-sha-create.js +2 -2
  11. package/lib/commands/apps-android-sha-delete.js +2 -2
  12. package/lib/commands/apps-android-sha-list.js +2 -2
  13. package/lib/commands/apps-create.js +9 -9
  14. package/lib/commands/apps-list.js +3 -3
  15. package/lib/commands/apps-sdkconfig.js +8 -8
  16. package/lib/commands/database-get.js +1 -1
  17. package/lib/commands/database-instances-create.js +4 -4
  18. package/lib/commands/database-instances-list.js +4 -4
  19. package/lib/commands/database-profile.js +1 -1
  20. package/lib/commands/database-push.js +1 -1
  21. package/lib/commands/database-remove.js +2 -2
  22. package/lib/commands/database-set.js +2 -2
  23. package/lib/commands/database-settings-get.js +1 -1
  24. package/lib/commands/database-settings-set.js +1 -1
  25. package/lib/commands/database-update.js +2 -2
  26. package/lib/commands/ext-configure.js +2 -2
  27. package/lib/commands/ext-dev-deprecate.js +4 -4
  28. package/lib/commands/ext-dev-extension-delete.js +3 -3
  29. package/lib/commands/ext-dev-init.js +3 -3
  30. package/lib/commands/ext-dev-list.js +1 -1
  31. package/lib/commands/ext-dev-publish.js +3 -3
  32. package/lib/commands/ext-dev-register.js +5 -5
  33. package/lib/commands/ext-dev-undeprecate.js +4 -4
  34. package/lib/commands/ext-dev-unpublish.js +3 -3
  35. package/lib/commands/ext-dev-usage.js +145 -0
  36. package/lib/commands/ext-export.js +8 -8
  37. package/lib/commands/ext-info.js +4 -4
  38. package/lib/commands/ext-install.js +26 -22
  39. package/lib/commands/ext-list.js +2 -2
  40. package/lib/commands/ext-sources-create.js +2 -2
  41. package/lib/commands/ext-uninstall.js +3 -3
  42. package/lib/commands/ext-update.js +17 -17
  43. package/lib/commands/ext.js +3 -3
  44. package/lib/commands/firestore-delete.js +1 -1
  45. package/lib/commands/functions-config-export.js +11 -11
  46. package/lib/commands/functions-delete.js +3 -3
  47. package/lib/commands/functions-deletegcfartifacts.js +4 -4
  48. package/lib/commands/functions-list.js +1 -1
  49. package/lib/commands/functions-log.js +1 -1
  50. package/lib/commands/hosting-channel-create.js +12 -12
  51. package/lib/commands/hosting-channel-delete.js +9 -9
  52. package/lib/commands/hosting-channel-deploy.js +17 -17
  53. package/lib/commands/hosting-channel-list.js +5 -5
  54. package/lib/commands/hosting-channel-open.js +9 -9
  55. package/lib/commands/hosting-clone.js +15 -15
  56. package/lib/commands/hosting-disable.js +1 -1
  57. package/lib/commands/hosting-sites-create.js +7 -7
  58. package/lib/commands/hosting-sites-delete.js +7 -7
  59. package/lib/commands/hosting-sites-get.js +2 -2
  60. package/lib/commands/hosting-sites-list.js +3 -3
  61. package/lib/commands/index.js +1 -0
  62. package/lib/commands/login.js +2 -2
  63. package/lib/commands/logout.js +1 -1
  64. package/lib/commands/open.js +1 -1
  65. package/lib/commands/projects-addfirebase.js +2 -2
  66. package/lib/commands/projects-create.js +2 -2
  67. package/lib/commands/projects-list.js +1 -1
  68. package/lib/commands/remoteconfig-get.js +3 -3
  69. package/lib/commands/remoteconfig-rollback.js +3 -3
  70. package/lib/commands/remoteconfig-versions-list.js +1 -1
  71. package/lib/commands/setup-emulators-storage.js +1 -1
  72. package/lib/config.js +6 -6
  73. package/lib/database/api.js +2 -2
  74. package/lib/deploy/extensions/deploy.js +4 -4
  75. package/lib/deploy/extensions/deploymentSummary.js +5 -4
  76. package/lib/deploy/extensions/index.js +1 -0
  77. package/lib/deploy/extensions/params.js +1 -1
  78. package/lib/deploy/extensions/planner.js +3 -3
  79. package/lib/deploy/extensions/prepare.js +9 -9
  80. package/lib/deploy/extensions/release.js +1 -1
  81. package/lib/deploy/extensions/secrets.js +7 -7
  82. package/lib/deploy/extensions/validate.js +2 -2
  83. package/lib/deploy/functions/backend.js +6 -4
  84. package/lib/deploy/functions/checkIam.js +7 -7
  85. package/lib/deploy/functions/containerCleaner.js +3 -3
  86. package/lib/deploy/functions/deploy.js +4 -4
  87. package/lib/deploy/functions/ensureCloudBuildEnabled.js +3 -3
  88. package/lib/deploy/functions/index.js +1 -0
  89. package/lib/deploy/functions/prepare.js +13 -13
  90. package/lib/deploy/functions/prompts.js +5 -5
  91. package/lib/deploy/functions/release/executor.js +4 -1
  92. package/lib/deploy/functions/release/fabricator.js +5 -5
  93. package/lib/deploy/functions/release/index.js +2 -2
  94. package/lib/deploy/functions/release/planner.js +6 -6
  95. package/lib/deploy/functions/release/reporter.js +8 -4
  96. package/lib/deploy/functions/runtimes/discovery/index.js +2 -2
  97. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +14 -14
  98. package/lib/deploy/functions/runtimes/golang/index.js +6 -6
  99. package/lib/deploy/functions/runtimes/node/index.js +3 -3
  100. package/lib/deploy/functions/runtimes/node/parseTriggers.js +3 -3
  101. package/lib/deploy/functions/services/storage.js +1 -1
  102. package/lib/deploy/functions/triggerRegionHelper.js +1 -1
  103. package/lib/deploy/hosting/deploy.js +7 -7
  104. package/lib/deploy/hosting/uploader.js +1 -1
  105. package/lib/deploy/hosting/validate.js +3 -3
  106. package/lib/deploy/remoteconfig/prepare.js +3 -3
  107. package/lib/deploy/remoteconfig/release.js +3 -3
  108. package/lib/deploy/storage/deploy.js +1 -1
  109. package/lib/deploy/storage/release.js +2 -2
  110. package/lib/detectProjectRoot.js +5 -5
  111. package/lib/emulator/auth/apiSpec.js +13 -7
  112. package/lib/emulator/auth/handlers.js +3 -3
  113. package/lib/emulator/auth/index.js +1 -1
  114. package/lib/emulator/auth/operations.js +256 -248
  115. package/lib/emulator/auth/server.js +11 -8
  116. package/lib/emulator/auth/state.js +12 -12
  117. package/lib/emulator/auth/widget_ui.js +1 -1
  118. package/lib/emulator/commandUtils.js +5 -5
  119. package/lib/emulator/controller.js +16 -11
  120. package/lib/emulator/downloadableEmulators.js +2 -2
  121. package/lib/emulator/emulatorLogger.js +1 -1
  122. package/lib/emulator/functionsEmulator.js +101 -74
  123. package/lib/emulator/functionsEmulatorRuntime.js +32 -17
  124. package/lib/emulator/functionsEmulatorShell.js +3 -2
  125. package/lib/emulator/functionsRuntimeWorker.js +1 -1
  126. package/lib/emulator/hubExport.js +2 -2
  127. package/lib/emulator/storage/apis/firebase.js +2 -2
  128. package/lib/emulator/storage/apis/gcloud.js +2 -2
  129. package/lib/emulator/storage/cloudFunctions.js +1 -1
  130. package/lib/emulator/storage/files.js +14 -14
  131. package/lib/emulator/storage/index.js +2 -2
  132. package/lib/emulator/storage/metadata.js +7 -6
  133. package/lib/emulator/storage/rules/runtime.js +5 -5
  134. package/lib/emulator/storage/server.js +2 -2
  135. package/lib/ensureApiEnabled.js +7 -7
  136. package/lib/error.js +3 -3
  137. package/lib/extensions/askUserForConsent.js +2 -3
  138. package/lib/extensions/askUserForParam.js +10 -10
  139. package/lib/extensions/billingMigrationHelper.js +1 -1
  140. package/lib/extensions/changelog.js +3 -3
  141. package/lib/extensions/displayExtensionInfo.js +5 -5
  142. package/lib/extensions/emulator/optionsHelper.js +1 -1
  143. package/lib/extensions/emulator/specHelper.js +1 -1
  144. package/lib/extensions/emulator/triggerHelper.js +1 -1
  145. package/lib/extensions/export.js +6 -6
  146. package/lib/extensions/extensionsApi.js +14 -1
  147. package/lib/extensions/extensionsHelper.js +38 -29
  148. package/lib/extensions/listExtensions.js +1 -1
  149. package/lib/extensions/localHelper.js +1 -1
  150. package/lib/extensions/metricsTypeDef.js +2 -0
  151. package/lib/extensions/metricsUtils.js +98 -0
  152. package/lib/extensions/paramHelper.js +6 -6
  153. package/lib/extensions/provisioningHelper.js +6 -4
  154. package/lib/extensions/resolveSource.js +1 -1
  155. package/lib/extensions/secretsUtils.js +3 -3
  156. package/lib/extensions/updateHelper.js +9 -9
  157. package/lib/extensions/utils.js +1 -1
  158. package/lib/extensions/warnings.js +10 -9
  159. package/lib/fetchWebSetup.js +2 -2
  160. package/lib/filterTargets.js +2 -2
  161. package/lib/firestore/indexes.js +2 -2
  162. package/lib/fsAsync.js +3 -3
  163. package/lib/fsutils.js +2 -2
  164. package/lib/functional.js +2 -1
  165. package/lib/functions/env.js +1 -1
  166. package/lib/functions/runtimeConfigExport.js +4 -4
  167. package/lib/functionsConfig.js +3 -3
  168. package/lib/functionsShellCommandAction.js +4 -3
  169. package/lib/gcp/cloudmonitoring.js +74 -0
  170. package/lib/gcp/cloudscheduler.js +1 -1
  171. package/lib/gcp/iam.js +2 -2
  172. package/lib/gcp/resourceManager.js +2 -2
  173. package/lib/gcp/secretManager.js +3 -2
  174. package/lib/getDefaultDatabaseInstance.js +1 -1
  175. package/lib/getDefaultHostingSite.js +1 -1
  176. package/lib/getProjectNumber.js +2 -2
  177. package/lib/handlePreviewToggles.js +5 -5
  178. package/lib/hosting/api.js +6 -6
  179. package/lib/hosting/cloudRunProxy.js +6 -6
  180. package/lib/hosting/functionsProxy.js +3 -3
  181. package/lib/hosting/implicitInit.js +2 -2
  182. package/lib/hosting/normalizedHostingConfigs.js +3 -3
  183. package/lib/hosting/proxy.js +2 -2
  184. package/lib/init/features/account.js +7 -7
  185. package/lib/init/features/database.js +9 -9
  186. package/lib/init/features/emulators.js +8 -8
  187. package/lib/init/features/firestore/index.js +3 -3
  188. package/lib/init/features/firestore/indexes.js +2 -2
  189. package/lib/init/features/firestore/rules.js +2 -2
  190. package/lib/init/features/functions/golang.js +4 -4
  191. package/lib/init/features/functions/index.js +4 -4
  192. package/lib/init/features/hosting/github.js +31 -31
  193. package/lib/init/features/project.js +8 -8
  194. package/lib/init/features/remoteconfig.js +2 -2
  195. package/lib/init/features/storage.js +2 -2
  196. package/lib/listFiles.js +1 -1
  197. package/lib/management/apps.js +3 -3
  198. package/lib/management/projects.js +6 -6
  199. package/lib/previews.js +2 -2
  200. package/lib/profiler.js +1 -1
  201. package/lib/projectPath.js +1 -1
  202. package/lib/projectUtils.js +1 -1
  203. package/lib/prompt.js +0 -1
  204. package/lib/rc.js +1 -1
  205. package/lib/requireAuth.js +2 -2
  206. package/lib/requireDatabaseInstance.js +1 -1
  207. package/lib/requireHostingSite.js +1 -1
  208. package/lib/requirePermissions.js +4 -4
  209. package/lib/rulesDeploy.js +2 -2
  210. package/lib/serve/functions.js +14 -7
  211. package/lib/serve/hosting.js +7 -7
  212. package/lib/utils.js +3 -2
  213. package/npm-shrinkwrap.json +24926 -0
  214. package/package.json +23 -23
  215. package/standalone/firepit.js +4 -4
  216. package/templates/init/hosting/index.html +1 -1
@@ -26,17 +26,17 @@ module.exports = new command_1.Command("ext:dev:delete <extensionRef>")
26
26
  "it will continue to run and will appear as unpublished when " +
27
27
  "listed in the Firebase console or Firebase CLI.");
28
28
  utils.logLabeledWarning("This is a permanent action", `Once deleted, you may never use the extension name '${clc.bold(extensionId)}' again.`);
29
- await extensionsApi_1.getExtension(extensionRef);
29
+ await (0, extensionsApi_1.getExtension)(extensionRef);
30
30
  const consent = await confirmDelete(publisherId, extensionId);
31
31
  if (!consent) {
32
32
  throw new error_1.FirebaseError("deletion cancelled.");
33
33
  }
34
- await extensionsApi_1.deleteExtension(extensionRef);
34
+ await (0, extensionsApi_1.deleteExtension)(extensionRef);
35
35
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, "successfully deleted all versions of this extension.");
36
36
  });
37
37
  async function confirmDelete(publisherId, extensionId) {
38
38
  const message = `You are about to delete ALL versions of ${clc.green(`${publisherId}/${extensionId}`)}.\nDo you wish to continue? `;
39
- return prompt_1.promptOnce({
39
+ return (0, prompt_1.promptOnce)({
40
40
  type: "confirm",
41
41
  message,
42
42
  default: false,
@@ -32,7 +32,7 @@ async function typescriptSelected(config) {
32
32
  const indexTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "index.ts"), "utf8");
33
33
  const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "typescript", "_gitignore"), "utf8");
34
34
  const eslintTemplate = fs.readFileSync(path.join(FUNCTIONS_ROOT, "typescript", "_eslintrc"), "utf8");
35
- const lint = await prompt_1.promptOnce({
35
+ const lint = await (0, prompt_1.promptOnce)({
36
36
  name: "lint",
37
37
  type: "confirm",
38
38
  message: "Do you want to use ESLint to catch probable bugs and enforce style?",
@@ -63,7 +63,7 @@ async function javascriptSelected(config) {
63
63
  const packageNoLintingTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "package.nolint.json"), "utf8");
64
64
  const gitignoreTemplate = fs.readFileSync(path.join(TEMPLATE_ROOT, "javascript", "_gitignore"), "utf8");
65
65
  const eslintTemplate = fs.readFileSync(path.join(FUNCTIONS_ROOT, "javascript", "_eslintrc"), "utf8");
66
- const lint = await prompt_1.promptOnce({
66
+ const lint = await (0, prompt_1.promptOnce)({
67
67
  name: "lint",
68
68
  type: "confirm",
69
69
  message: "Do you want to use ESLint to catch probable bugs and enforce style?",
@@ -91,7 +91,7 @@ exports.default = new command_1.Command("ext:dev:init")
91
91
  const cwd = options.cwd || process.cwd();
92
92
  const config = new config_1.Config({}, { projectDir: cwd, cwd: cwd });
93
93
  try {
94
- const lang = await prompt_1.promptOnce({
94
+ const lang = await (0, prompt_1.promptOnce)({
95
95
  type: "list",
96
96
  name: "language",
97
97
  message: "In which language do you want to write the Cloud Functions for your extension?",
@@ -17,7 +17,7 @@ exports.default = new command_1.Command("ext:dev:list <publisherId>")
17
17
  .action(async (publisherId) => {
18
18
  let extensions;
19
19
  try {
20
- extensions = await extensionsApi_1.listExtensions(publisherId);
20
+ extensions = await (0, extensionsApi_1.listExtensions)(publisherId);
21
21
  }
22
22
  catch (err) {
23
23
  throw new error_1.FirebaseError(err);
@@ -29,8 +29,8 @@ exports.default = new command_1.Command("ext:dev:publish <extensionRef>")
29
29
  if (!publisherId || !extensionId) {
30
30
  throw new error_1.FirebaseError(`Error parsing publisher ID and extension ID from extension reference '${clc.bold(extensionRef)}'. Please use the format '${clc.bold("<publisherId>/<extensionId>")}'.`);
31
31
  }
32
- const extensionYamlDirectory = localHelper_1.findExtensionYaml(process.cwd());
33
- const res = await extensionsHelper_1.publishExtensionVersionFromLocalSource({
32
+ const extensionYamlDirectory = (0, localHelper_1.findExtensionYaml)(process.cwd());
33
+ const res = await (0, extensionsHelper_1.publishExtensionVersionFromLocalSource)({
34
34
  publisherId,
35
35
  extensionId,
36
36
  rootDirectory: extensionYamlDirectory,
@@ -38,7 +38,7 @@ exports.default = new command_1.Command("ext:dev:publish <extensionRef>")
38
38
  force: options.force,
39
39
  });
40
40
  if (res) {
41
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`[Install Link](${publishHelpers_1.consoleInstallLink(res.ref)})`));
41
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, marked(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
42
42
  }
43
43
  return res;
44
44
  });
@@ -16,20 +16,20 @@ exports.default = new command_1.Command("ext:dev:register")
16
16
  .before(requirePermissions_1.requirePermissions, ["firebaseextensions.sources.create"])
17
17
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
18
18
  .action(async (options) => {
19
- await askUserForConsent_1.promptForPublisherTOS();
20
- const projectId = projectUtils_1.needProjectId(options);
19
+ await (0, askUserForConsent_1.promptForPublisherTOS)();
20
+ const projectId = (0, projectUtils_1.needProjectId)(options);
21
21
  const msg = "What would you like to register as your publisher ID? " +
22
22
  "This value identifies you in Firebase's registry of extensions as the author of your extensions. " +
23
23
  "Examples: my-company-name, MyGitHubUsername.\n\n" +
24
24
  "You can only do this once for each project.";
25
- const publisherId = await prompt_1.promptOnce({
25
+ const publisherId = await (0, prompt_1.promptOnce)({
26
26
  name: "publisherId",
27
27
  type: "input",
28
28
  message: msg,
29
29
  default: projectId,
30
30
  });
31
31
  try {
32
- await extensionsApi_1.registerPublisherProfile(projectId, publisherId);
32
+ await (0, extensionsApi_1.registerPublisherProfile)(projectId, publisherId);
33
33
  }
34
34
  catch (err) {
35
35
  if (err.status === 409) {
@@ -40,7 +40,7 @@ exports.default = new command_1.Command("ext:dev:register")
40
40
  ` 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
41
  throw new error_1.FirebaseError(error, { exit: 1 });
42
42
  }
43
- throw new error_1.FirebaseError(`Failed to register publisher ID ${clc.bold(publisherId)} for project ${clc.bold(projectId)}: ${err.message}`, { exit: 1 });
43
+ throw new error_1.FirebaseError(`Failed to register publisher ID ${clc.bold(publisherId)} for project ${clc.bold(projectId)}: ${err.message}`);
44
44
  }
45
45
  return utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `Publisher ID '${clc.bold(publisherId)}' has been registered to project ${clc.bold(projectId)}`);
46
46
  });
@@ -23,9 +23,9 @@ exports.default = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
23
23
  if (!publisherId || !extensionId) {
24
24
  throw new error_1.FirebaseError(`Error parsing publisher ID and extension ID from extension reference '${clc.bold(extensionRef)}'. Please use the format '${clc.bold("<publisherId>/<extensionId>")}'.`);
25
25
  }
26
- const { comparator, targetSemVer } = versionHelper_1.parseVersionPredicate(versionPredicate);
26
+ const { comparator, targetSemVer } = (0, versionHelper_1.parseVersionPredicate)(versionPredicate);
27
27
  const filter = `id${comparator}"${targetSemVer}"`;
28
- const extensionVersions = await extensionsApi_1.listExtensionVersions(extensionRef, filter);
28
+ const extensionVersions = await (0, extensionsApi_1.listExtensionVersions)(extensionRef, filter);
29
29
  extensionVersions
30
30
  .sort((ev1, ev2) => {
31
31
  return -semver.compare(ev1.spec.version, ev2.spec.version);
@@ -36,7 +36,7 @@ exports.default = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
36
36
  if (extensionVersions.length > 0) {
37
37
  if (!options.force) {
38
38
  const confirmMessage = "You are about to undeprecate these extension version(s). Do you wish to continue?";
39
- const consent = await prompt_1.promptOnce({
39
+ const consent = await (0, prompt_1.promptOnce)({
40
40
  type: "confirm",
41
41
  message: confirmMessage,
42
42
  default: false,
@@ -50,7 +50,7 @@ exports.default = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
50
50
  throw new error_1.FirebaseError("No extension versions matched the version predicate.");
51
51
  }
52
52
  await utils.allSettled(extensionVersions.map(async (extensionVersion) => {
53
- await extensionsApi_1.undeprecateExtensionVersion(extensionVersion.ref);
53
+ await (0, extensionsApi_1.undeprecateExtensionVersion)(extensionVersion.ref);
54
54
  }));
55
55
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, "successfully undeprecated extension version(s).");
56
56
  });
@@ -24,12 +24,12 @@ module.exports = new command_1.Command("ext:dev:unpublish <extensionRef>")
24
24
  if (version) {
25
25
  throw new error_1.FirebaseError(`Unpublishing a single version is not currently supported. You can only unpublish ${clc.bold("ALL versions")} of an extension. To unpublish all versions, please remove the version from the reference.`);
26
26
  }
27
- await extensionsApi_1.getExtension(extensionRef);
27
+ await (0, extensionsApi_1.getExtension)(extensionRef);
28
28
  const consent = await comfirmUnpublish(publisherId, extensionId, options);
29
29
  if (!consent) {
30
30
  throw new error_1.FirebaseError("unpublishing cancelled.");
31
31
  }
32
- await extensionsApi_1.unpublishExtension(extensionRef);
32
+ await (0, extensionsApi_1.unpublishExtension)(extensionRef);
33
33
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, "successfully unpublished all versions of this extension.");
34
34
  });
35
35
  async function comfirmUnpublish(publisherId, extensionId, options) {
@@ -40,7 +40,7 @@ async function comfirmUnpublish(publisherId, extensionId, options) {
40
40
  return true;
41
41
  }
42
42
  const message = `You are about to unpublish ALL versions of ${clc.green(`${publisherId}/${extensionId}`)}.\nDo you wish to continue? `;
43
- return prompt_1.promptOnce({
43
+ return (0, prompt_1.promptOnce)({
44
44
  type: "confirm",
45
45
  message,
46
46
  default: false,
@@ -0,0 +1,145 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ const Table = require("cli-table");
4
+ const clc = require("cli-color");
5
+ const utils = require("../utils");
6
+ const command_1 = require("../command");
7
+ const cloudmonitoring_1 = require("../gcp/cloudmonitoring");
8
+ const requireAuth_1 = require("../requireAuth");
9
+ const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
10
+ const metricsUtils_1 = require("../extensions/metricsUtils");
11
+ const extensionsApi_1 = require("../extensions/extensionsApi");
12
+ const extensionsHelper_1 = require("../extensions/extensionsHelper");
13
+ const error_1 = require("../error");
14
+ const logger_1 = require("../logger");
15
+ const prompt_1 = require("../prompt");
16
+ const shortenUrl_1 = require("../shortenUrl");
17
+ module.exports = new command_1.Command("ext:dev:usage <publisherId>")
18
+ .description("get usage for an extension")
19
+ .help("use this command to get the usage of extensions you published. " +
20
+ "Specify the publisher ID you used to publish your extensions, " +
21
+ "or the extension ref of your published extension.")
22
+ .before(requireAuth_1.requireAuth)
23
+ .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extDevMinVersion")
24
+ .action(async (input) => {
25
+ const extensionRefRegex = /^[\w\d-]+\/[\w\d-]+$/;
26
+ let extensionName;
27
+ let publisherId;
28
+ if (extensionRefRegex.test(input)) {
29
+ [publisherId, extensionName] = input.split("/");
30
+ }
31
+ else {
32
+ publisherId = input;
33
+ let extensions;
34
+ try {
35
+ extensions = await (0, extensionsApi_1.listExtensions)(publisherId);
36
+ }
37
+ catch (err) {
38
+ throw new error_1.FirebaseError(err);
39
+ }
40
+ if (extensions.length < 1) {
41
+ throw new error_1.FirebaseError(`There are no published extensions associated with publisher ID ${clc.bold(publisherId)}. This could happen for two reasons:\n` +
42
+ " - The publisher ID doesn't exist or could be misspelled\n" +
43
+ " - This publisher has not published any extensions\n\n" +
44
+ "If you are expecting some extensions to appear, please make sure you have the correct publisher ID and try again.");
45
+ }
46
+ extensionName = await (0, prompt_1.promptOnce)({
47
+ type: "list",
48
+ name: "extension",
49
+ message: "Which published extension do you want to view the stats for?",
50
+ choices: extensions.map((e) => {
51
+ const [_, name] = e.ref.split("/");
52
+ return {
53
+ name,
54
+ value: name,
55
+ };
56
+ }),
57
+ });
58
+ }
59
+ const profile = await (0, extensionsApi_1.getPublisherProfile)("-", publisherId);
60
+ const projectNumber = (0, extensionsHelper_1.getPublisherProjectFromName)(profile.name);
61
+ const past30d = new Date();
62
+ past30d.setDate(past30d.getDate() - 30);
63
+ const query = {
64
+ filter: `metric.type="firebaseextensions.googleapis.com/extension/version/active_instances" ` +
65
+ `resource.type="firebaseextensions.googleapis.com/ExtensionVersion" ` +
66
+ `resource.labels.extension="${extensionName}"`,
67
+ "interval.endTime": new Date().toJSON(),
68
+ "interval.startTime": past30d.toJSON(),
69
+ view: cloudmonitoring_1.TimeSeriesView.FULL,
70
+ "aggregation.alignmentPeriod": (60 * 60 * 24).toString() + "s",
71
+ "aggregation.perSeriesAligner": cloudmonitoring_1.Aligner.ALIGN_MAX,
72
+ };
73
+ let response;
74
+ try {
75
+ response = await (0, cloudmonitoring_1.queryTimeSeries)(query, projectNumber);
76
+ }
77
+ catch (err) {
78
+ throw new error_1.FirebaseError(`Error occurred when fetching usage data for extension ${extensionName}`, {
79
+ original: err,
80
+ });
81
+ }
82
+ if (!response) {
83
+ throw new error_1.FirebaseError(`Couldn't find any usage data for extension ${extensionName}`);
84
+ }
85
+ const metrics = (0, metricsUtils_1.parseTimeseriesResponse)(response);
86
+ const table = new Table({
87
+ head: ["Version", "Active Instances", "Changes last 7 Days", "Changes last 28 Days"],
88
+ style: {
89
+ head: ["yellow"],
90
+ },
91
+ colAligns: ["left", "right", "right", "right"],
92
+ });
93
+ metrics.forEach((m) => {
94
+ table.push((0, metricsUtils_1.buildMetricsTableRow)(m));
95
+ });
96
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `showing usage stats for ${clc.bold(extensionName)}:`);
97
+ logger_1.logger.info(table.toString());
98
+ const link = await buildCloudMonitoringLink({
99
+ projectNumber: projectNumber,
100
+ extensionName,
101
+ });
102
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `How to read this table:`);
103
+ logger_1.logger.info(`* Due to privacy considerations, numbers are reported as ranges.`);
104
+ logger_1.logger.info(`* In the absence of significant changes, we will render a '-' symbol.`);
105
+ logger_1.logger.info(`* You will need more than 10 installs over a period of more than 28 days to render sufficient data.`);
106
+ logger_1.logger.info(`For more detail, visit: ${link}`);
107
+ });
108
+ async function buildCloudMonitoringLink(args) {
109
+ const pageState = {
110
+ xyChart: {
111
+ dataSets: [
112
+ {
113
+ timeSeriesFilter: {
114
+ filter: `metric.type="firebaseextensions.googleapis.com/extension/version/active_instances"` +
115
+ ` resource.type="firebaseextensions.googleapis.com/ExtensionVersion"` +
116
+ ` resource.label.extension="${args.extensionName}"`,
117
+ minAlignmentPeriod: "86400s",
118
+ aggregations: [
119
+ {
120
+ perSeriesAligner: "ALIGN_MEAN",
121
+ crossSeriesReducer: "REDUCE_MAX",
122
+ alignmentPeriod: "86400s",
123
+ groupByFields: ['resource.label."extension"', 'resource.label."version"'],
124
+ },
125
+ {
126
+ crossSeriesReducer: "REDUCE_NONE",
127
+ alignmentPeriod: "60s",
128
+ groupByFields: [],
129
+ },
130
+ ],
131
+ },
132
+ },
133
+ ],
134
+ },
135
+ isAutoRefresh: true,
136
+ timeSelection: {
137
+ timeRange: "4w",
138
+ },
139
+ };
140
+ let uri = `https://console.cloud.google.com/monitoring/metrics-explorer?project=${args.projectNumber}` +
141
+ `&pageState=${JSON.stringify(pageState)}`;
142
+ uri = encodeURI(uri);
143
+ uri = await (0, shortenUrl_1.shortenUrl)(uri);
144
+ return uri;
145
+ }
@@ -18,21 +18,21 @@ module.exports = new command_1.Command("ext:export")
18
18
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
19
19
  .withForce()
20
20
  .action(async (options) => {
21
- const projectId = projectUtils_1.needProjectId(options);
22
- const projectNumber = await getProjectNumber_1.getProjectNumber(options);
21
+ const projectId = (0, projectUtils_1.needProjectId)(options);
22
+ const projectNumber = await (0, getProjectNumber_1.getProjectNumber)(options);
23
23
  const have = await Promise.all((await planner.have(projectId)).map(async (i) => {
24
- const subbed = await export_1.setSecretParamsToLatest(i);
25
- return export_1.parameterizeProject(projectId, projectNumber, subbed);
24
+ const subbed = await (0, export_1.setSecretParamsToLatest)(i);
25
+ return (0, export_1.parameterizeProject)(projectId, projectNumber, subbed);
26
26
  }));
27
27
  if (have.length == 0) {
28
28
  logger_1.logger.info(`No extension instances installed on ${projectId}, so there is nothing to export.`);
29
29
  return;
30
30
  }
31
- const [withRef, withoutRef] = functional_1.partition(have, (s) => !!s.ref);
32
- export_1.displayExportInfo(withRef, withoutRef);
31
+ const [withRef, withoutRef] = (0, functional_1.partition)(have, (s) => !!s.ref);
32
+ (0, export_1.displayExportInfo)(withRef, withoutRef);
33
33
  if (!options.nonInteractive &&
34
34
  !options.force &&
35
- !(await prompt_1.promptOnce({
35
+ !(await (0, prompt_1.promptOnce)({
36
36
  message: "Do you wish to add these Extension instances to firebase.json?",
37
37
  type: "confirm",
38
38
  default: true,
@@ -40,5 +40,5 @@ module.exports = new command_1.Command("ext:export")
40
40
  logger_1.logger.info("Exiting. No changes made.");
41
41
  return;
42
42
  }
43
- await export_1.writeFiles(withRef, options);
43
+ await (0, export_1.writeFiles)(withRef, options);
44
44
  });
@@ -20,15 +20,15 @@ exports.default = new command_1.Command("ext:info <extensionName>")
20
20
  .action(async (extensionName, options) => {
21
21
  var _a, _b;
22
22
  let spec;
23
- if (localHelper_1.isLocalExtension(extensionName)) {
23
+ if ((0, localHelper_1.isLocalExtension)(extensionName)) {
24
24
  if (!options.markdown) {
25
25
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `reading extension from directory: ${extensionName}`);
26
26
  }
27
- spec = await localHelper_1.getLocalExtensionSpec(extensionName);
27
+ spec = await (0, localHelper_1.getLocalExtensionSpec)(extensionName);
28
28
  }
29
29
  else {
30
- await requirePermissions_1.requirePermissions(options, ["firebaseextensions.sources.get"]);
31
- await extensionsHelper_1.ensureExtensionsApiEnabled(options);
30
+ await (0, requirePermissions_1.requirePermissions)(options, ["firebaseextensions.sources.get"]);
31
+ await (0, extensionsHelper_1.ensureExtensionsApiEnabled)(options);
32
32
  const hasPublisherId = extensionName.split("/").length >= 2;
33
33
  if (hasPublisherId) {
34
34
  const nameAndVersion = extensionName.split("/")[1];
@@ -24,33 +24,34 @@ const updateHelper_1 = require("../extensions/updateHelper");
24
24
  const utils_1 = require("../extensions/utils");
25
25
  const requirePermissions_1 = require("../requirePermissions");
26
26
  const utils = require("../utils");
27
+ const track_1 = require("../track");
27
28
  const logger_1 = require("../logger");
28
29
  const previews_1 = require("../previews");
29
30
  marked.setOptions({
30
31
  renderer: new TerminalRenderer(),
31
32
  });
32
33
  async function installExtension(options) {
33
- const { projectId, extensionName, source, extVersion, paramsEnvPath, nonInteractive, force, } = options;
34
+ const { projectId, extensionName, source, extVersion, paramsEnvPath, nonInteractive, force } = options;
34
35
  const spec = (source === null || source === void 0 ? void 0 : source.spec) || (extVersion === null || extVersion === void 0 ? void 0 : extVersion.spec);
35
36
  if (!spec) {
36
37
  throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionName}. Please make sure this is a valid extension and try again.`);
37
38
  }
38
- const spinner = ora.default();
39
+ const spinner = ora();
39
40
  try {
40
41
  await provisioningHelper.checkProductsProvisioned(projectId, spec);
41
42
  const usesSecrets = secretsUtils.usesSecrets(spec);
42
43
  if (spec.billingRequired || usesSecrets) {
43
- const enabled = await cloudbilling_1.checkBillingEnabled(projectId);
44
+ const enabled = await (0, cloudbilling_1.checkBillingEnabled)(projectId);
44
45
  if (!enabled && nonInteractive) {
45
46
  throw new error_1.FirebaseError(`This extension requires the Blaze plan, but project ${projectId} is not on the Blaze plan. ` +
46
47
  marked("Please visit https://console.cloud.google.com/billing/linkedaccount?project=${projectId} to upgrade your project."));
47
48
  }
48
49
  else if (!enabled) {
49
- await billingMigrationHelper_1.displayNode10CreateBillingNotice(spec, false);
50
- await checkProjectBilling_1.enableBilling(projectId);
50
+ await (0, billingMigrationHelper_1.displayNode10CreateBillingNotice)(spec, false);
51
+ await (0, checkProjectBilling_1.enableBilling)(projectId);
51
52
  }
52
53
  else {
53
- await billingMigrationHelper_1.displayNode10CreateBillingNotice(spec, !nonInteractive);
54
+ await (0, billingMigrationHelper_1.displayNode10CreateBillingNotice)(spec, !nonInteractive);
54
55
  }
55
56
  }
56
57
  const apis = spec.apis || [];
@@ -62,7 +63,7 @@ async function installExtension(options) {
62
63
  }
63
64
  if (apis.length) {
64
65
  askUserForConsent.displayApis(spec.displayName || spec.name, projectId, apis);
65
- const consented = await extensionsHelper_1.confirm({ nonInteractive, force, default: true });
66
+ const consented = await (0, extensionsHelper_1.confirm)({ nonInteractive, force, default: true });
66
67
  if (!consented) {
67
68
  throw new error_1.FirebaseError("Without explicit consent for the APIs listed, we cannot deploy this extension.");
68
69
  }
@@ -73,17 +74,17 @@ async function installExtension(options) {
73
74
  const roles = spec.roles ? spec.roles.map((role) => role.role) : [];
74
75
  if (roles.length) {
75
76
  await askUserForConsent.displayRoles(spec.displayName || spec.name, projectId, roles);
76
- const consented = await extensionsHelper_1.confirm({ nonInteractive, force, default: true });
77
+ const consented = await (0, extensionsHelper_1.confirm)({ nonInteractive, force, default: true });
77
78
  if (!consented) {
78
79
  throw new error_1.FirebaseError("Without explicit consent for the roles listed, we cannot deploy this extension.");
79
80
  }
80
81
  }
81
82
  let instanceId = spec.name;
82
83
  let choice;
83
- const anotherInstanceExists = await extensionsHelper_1.instanceIdExists(projectId, instanceId);
84
+ const anotherInstanceExists = await (0, extensionsHelper_1.instanceIdExists)(projectId, instanceId);
84
85
  if (anotherInstanceExists) {
85
86
  if (!nonInteractive) {
86
- choice = await extensionsHelper_1.promptForRepeatInstance(projectId, spec.name);
87
+ choice = await (0, extensionsHelper_1.promptForRepeatInstance)(projectId, spec.name);
87
88
  }
88
89
  else if (nonInteractive && force) {
89
90
  choice = "updateExisting";
@@ -99,7 +100,7 @@ async function installExtension(options) {
99
100
  let params;
100
101
  switch (choice) {
101
102
  case "installNew":
102
- instanceId = await extensionsHelper_1.promptForValidInstanceId(`${instanceId}-${utils_1.getRandomString(4)}`);
103
+ instanceId = await (0, extensionsHelper_1.promptForValidInstanceId)(`${instanceId}-${(0, utils_1.getRandomString)(4)}`);
103
104
  params = await paramHelper.getParams({
104
105
  projectId,
105
106
  paramSpecs: spec.params,
@@ -130,7 +131,7 @@ async function installExtension(options) {
130
131
  });
131
132
  spinner.text = "Updating your extension instance. This usually takes 3 to 5 minutes...";
132
133
  spinner.start();
133
- await updateHelper_1.update({
134
+ await (0, updateHelper_1.update)({
134
135
  projectId,
135
136
  instanceId,
136
137
  source,
@@ -164,16 +165,16 @@ async function installExtension(options) {
164
165
  async function infoInstallBySource(projectId, extensionName) {
165
166
  let source;
166
167
  try {
167
- source = await extensionsHelper_1.createSourceFromLocation(projectId, extensionName);
168
+ source = await (0, extensionsHelper_1.createSourceFromLocation)(projectId, extensionName);
168
169
  }
169
170
  catch (err) {
170
171
  throw new error_1.FirebaseError(`Unable to find published extension '${clc.bold(extensionName)}', ` +
171
172
  `and encountered the following error when trying to create an instance of extension '${clc.bold(extensionName)}':\n ${err.message}`);
172
173
  }
173
- displayExtensionInfo_1.displayExtInfo(extensionName, "", source.spec);
174
+ (0, displayExtensionInfo_1.displayExtInfo)(extensionName, "", source.spec);
174
175
  return source;
175
176
  }
176
- async function infoInstallByReference(extensionName) {
177
+ async function infoInstallByReference(extensionName, interactive) {
177
178
  if (extensionName.split("/").length < 2) {
178
179
  const [extensionID, version] = extensionName.split("@");
179
180
  extensionName = `firebase/${extensionID}@${version || "latest"}`;
@@ -181,11 +182,12 @@ async function infoInstallByReference(extensionName) {
181
182
  const ref = refs.parse(extensionName);
182
183
  const extension = await extensionsApi.getExtension(refs.toExtensionRef(ref));
183
184
  if (!ref.version) {
185
+ (0, track_1.track)("Extension Install", "Install by Extension Version Ref", interactive ? 1 : 0);
184
186
  extensionName = `${extensionName}@latest`;
185
187
  }
186
188
  const extVersion = await extensionsApi.getExtensionVersion(extensionName);
187
- displayExtensionInfo_1.displayExtInfo(extensionName, ref.publisherId, extVersion.spec, true);
188
- await warnings_1.displayWarningPrompts(ref.publisherId, extension.registryLaunchStage, extVersion);
189
+ (0, displayExtensionInfo_1.displayExtInfo)(extensionName, ref.publisherId, extVersion.spec, true);
190
+ await (0, warnings_1.displayWarningPrompts)(ref.publisherId, extension.registryLaunchStage, extVersion);
189
191
  return extVersion;
190
192
  }
191
193
  exports.default = new command_1.Command("ext:install [extensionName]")
@@ -200,13 +202,13 @@ exports.default = new command_1.Command("ext:install [extensionName]")
200
202
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
201
203
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
202
204
  .action(async (extensionName, options) => {
203
- const projectId = projectUtils_1.needProjectId(options);
205
+ const projectId = (0, projectUtils_1.needProjectId)(options);
204
206
  const paramsEnvPath = options.params;
205
207
  let learnMore = false;
206
208
  if (!extensionName) {
207
209
  if (options.interactive) {
208
210
  learnMore = true;
209
- extensionName = await extensionsHelper_1.promptForOfficialExtension("Which official extension do you wish to install?\n" +
211
+ extensionName = await (0, extensionsHelper_1.promptForOfficialExtension)("Which official extension do you wish to install?\n" +
210
212
  " Select an extension, then press Enter to learn more.");
211
213
  }
212
214
  else {
@@ -216,13 +218,15 @@ exports.default = new command_1.Command("ext:install [extensionName]")
216
218
  }
217
219
  let source;
218
220
  let extVersion;
219
- if (extensionsHelper_1.isLocalOrURLPath(extensionName)) {
221
+ if ((0, extensionsHelper_1.isLocalOrURLPath)(extensionName)) {
222
+ (0, track_1.track)("Extension Install", "Install by Source", options.interactive ? 1 : 0);
220
223
  source = await infoInstallBySource(projectId, extensionName);
221
224
  }
222
225
  else {
223
- extVersion = await infoInstallByReference(extensionName);
226
+ (0, track_1.track)("Extension Install", "Install by Extension Ref", options.interactive ? 1 : 0);
227
+ extVersion = await infoInstallByReference(extensionName, options.interactive);
224
228
  }
225
- if (!(await extensionsHelper_1.confirm({
229
+ if (!(await (0, extensionsHelper_1.confirm)({
226
230
  nonInteractive: options.nonInteractive,
227
231
  force: options.force,
228
232
  default: true,
@@ -12,6 +12,6 @@ module.exports = new command_1.Command("ext:list")
12
12
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
13
13
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
14
14
  .action((options) => {
15
- const projectId = projectUtils_1.needProjectId(options);
16
- return listExtensions_1.listExtensions(projectId);
15
+ const projectId = (0, projectUtils_1.needProjectId)(options);
16
+ return (0, listExtensions_1.listExtensions)(projectId);
17
17
  });
@@ -16,8 +16,8 @@ exports.default = new command_1.Command("ext:sources:create <sourceLocation>")
16
16
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
17
17
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extDevMinVersion")
18
18
  .action(async (sourceLocation, options) => {
19
- const projectId = projectUtils_1.needProjectId(options);
20
- const res = await extensionsHelper_1.createSourceFromLocation(projectId, sourceLocation);
19
+ const projectId = (0, projectUtils_1.needProjectId)(options);
20
+ const res = await (0, extensionsHelper_1.createSourceFromLocation)(projectId, sourceLocation);
21
21
  logger_1.logger.info(`Extension source creation successful for ${res.spec.name}! Your new source is ${res.name}`);
22
22
  return res;
23
23
  });
@@ -34,7 +34,7 @@ exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
34
34
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
35
35
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
36
36
  .action(async (instanceId, options) => {
37
- const projectId = projectUtils_1.needProjectId(options);
37
+ const projectId = (0, projectUtils_1.needProjectId)(options);
38
38
  let instance;
39
39
  try {
40
40
  instance = await extensionsApi.getInstance(projectId, instanceId);
@@ -72,7 +72,7 @@ exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
72
72
  `${resourcesMessage}` +
73
73
  `${artifactsMessage}`;
74
74
  logger_1.logger.info(extensionDeletionMessage);
75
- const confirmedExtensionDeletion = await prompt_1.promptOnce({
75
+ const confirmedExtensionDeletion = await (0, prompt_1.promptOnce)({
76
76
  type: "confirm",
77
77
  default: true,
78
78
  message: "Are you sure that you wish to uninstall this extension?",
@@ -81,7 +81,7 @@ exports.default = new command_1.Command("ext:uninstall <extensionInstanceId>")
81
81
  return utils.reject("Command aborted.", { exit: 1 });
82
82
  }
83
83
  }
84
- const spinner = ora.default(` ${clc.green.bold(extensionsHelper_1.logPrefix)}: uninstalling ${clc.bold(instanceId)}. This usually takes 1 to 2 minutes...`);
84
+ const spinner = ora(` ${clc.green.bold(extensionsHelper_1.logPrefix)}: uninstalling ${clc.bold(instanceId)}. This usually takes 1 to 2 minutes...`);
85
85
  spinner.start();
86
86
  try {
87
87
  spinner.info();