firebase-tools 11.30.0 → 12.0.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 (55) hide show
  1. package/lib/api.js +4 -2
  2. package/lib/commands/ext-configure.js +2 -1
  3. package/lib/commands/ext-dev-deprecate.js +24 -20
  4. package/lib/commands/ext-dev-list.js +12 -11
  5. package/lib/commands/ext-dev-publish.js +13 -47
  6. package/lib/commands/ext-dev-register.js +8 -5
  7. package/lib/commands/ext-dev-undeprecate.js +4 -4
  8. package/lib/commands/ext-dev-upload.js +88 -0
  9. package/lib/commands/ext-dev-usage.js +3 -3
  10. package/lib/commands/ext-install.js +5 -10
  11. package/lib/commands/ext-uninstall.js +0 -1
  12. package/lib/commands/ext-update.js +4 -10
  13. package/lib/commands/index.js +9 -19
  14. package/lib/deploy/extensions/planner.js +13 -7
  15. package/lib/deploy/extensions/prepare.js +16 -32
  16. package/lib/emulator/storage/rules/config.js +17 -7
  17. package/lib/experiments.js +7 -6
  18. package/lib/extensions/extensionsApi.js +24 -151
  19. package/lib/extensions/extensionsHelper.js +282 -145
  20. package/lib/extensions/manifest.js +1 -8
  21. package/lib/extensions/publisherApi.js +215 -0
  22. package/lib/extensions/refs.js +1 -1
  23. package/lib/extensions/resolveSource.js +1 -18
  24. package/lib/extensions/tos.js +78 -0
  25. package/lib/extensions/warnings.js +21 -41
  26. package/lib/frameworks/angular/index.js +67 -185
  27. package/lib/frameworks/angular/interfaces.js +2 -0
  28. package/lib/frameworks/angular/utils.js +274 -0
  29. package/lib/frameworks/constants.js +5 -2
  30. package/lib/frameworks/index.js +60 -28
  31. package/lib/frameworks/next/index.js +86 -40
  32. package/lib/frameworks/next/utils.js +29 -12
  33. package/lib/frameworks/utils.js +11 -4
  34. package/lib/functions/python.js +1 -1
  35. package/lib/hosting/api.js +32 -1
  36. package/package.json +2 -2
  37. package/templates/extensions/POSTINSTALL.md +2 -2
  38. package/templates/extensions/PREINSTALL.md +1 -1
  39. package/templates/extensions/extension.yaml +10 -6
  40. package/templates/extensions/javascript/WELCOME.md +1 -1
  41. package/templates/extensions/typescript/WELCOME.md +1 -1
  42. package/templates/extensions/typescript/index.ts +1 -1
  43. package/templates/init/functions/javascript/index.js +16 -6
  44. package/templates/init/functions/javascript/package.lint.json +4 -4
  45. package/templates/init/functions/javascript/package.nolint.json +4 -4
  46. package/templates/init/functions/typescript/index.ts +16 -6
  47. package/templates/init/functions/typescript/package.lint.json +4 -4
  48. package/templates/init/functions/typescript/package.nolint.json +4 -4
  49. package/lib/commands/ext-dev-emulators-exec.js +0 -27
  50. package/lib/commands/ext-dev-emulators-start.js +0 -24
  51. package/lib/commands/ext-dev-extension-delete.js +0 -45
  52. package/lib/commands/ext-dev-unpublish.js +0 -49
  53. package/lib/commands/ext-sources-create.js +0 -24
  54. package/lib/extensions/askUserForConsent.js +0 -33
  55. package/npm-shrinkwrap.json +0 -12368
package/lib/api.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.githubClientSecret = exports.githubClientId = exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = exports.hostingApiOrigin = exports.firebaseStorageOrigin = exports.storageOrigin = exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.dynamicLinksKey = exports.dynamicLinksOrigin = exports.deployOrigin = exports.consoleOrigin = exports.authOrigin = exports.appengineOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
4
- exports.setScopes = exports.getScopes = void 0;
3
+ exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = exports.hostingApiOrigin = exports.firebaseStorageOrigin = exports.storageOrigin = exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsTOSOrigin = exports.extensionsPublisherOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.dynamicLinksKey = exports.dynamicLinksOrigin = exports.deployOrigin = exports.consoleOrigin = exports.authOrigin = exports.appengineOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
4
+ exports.setScopes = exports.getScopes = exports.githubClientSecret = exports.githubClientId = void 0;
5
5
  const constants_1 = require("./emulator/constants");
6
6
  const logger_1 = require("./logger");
7
7
  const scopes = require("./scopes");
@@ -45,6 +45,8 @@ exports.hostingOrigin = utils.envOverride("FIREBASE_HOSTING_URL", "https://web.a
45
45
  exports.identityOrigin = utils.envOverride("FIREBASE_IDENTITY_URL", "https://identitytoolkit.googleapis.com");
46
46
  exports.iamOrigin = utils.envOverride("FIREBASE_IAM_URL", "https://iam.googleapis.com");
47
47
  exports.extensionsOrigin = utils.envOverride("FIREBASE_EXT_URL", "https://firebaseextensions.googleapis.com");
48
+ exports.extensionsPublisherOrigin = utils.envOverride("FIREBASE_EXT_PUBLISHER_URL", "https://firebaseextensionspublisher.googleapis.com");
49
+ exports.extensionsTOSOrigin = utils.envOverride("FIREBASE_EXT_TOS_URL", "https://firebaseextensionstos-pa.googleapis.com");
48
50
  exports.realtimeOrigin = utils.envOverride("FIREBASE_REALTIME_URL", "https://firebaseio.com");
49
51
  exports.rtdbManagementOrigin = utils.envOverride("FIREBASE_RTDB_MANAGEMENT_URL", "https://firebasedatabase.googleapis.com");
50
52
  exports.rtdbMetadataOrigin = utils.envOverride("FIREBASE_RTDB_METADATA_URL", "https://metadata-dot-firebase-prod.appspot.com");
@@ -18,6 +18,7 @@ const manifest = require("../extensions/manifest");
18
18
  const functional_1 = require("../functional");
19
19
  const paramHelper_1 = require("../extensions/paramHelper");
20
20
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
21
+ const tos_1 = require("../extensions/tos");
21
22
  marked_1.marked.setOptions({
22
23
  renderer: new TerminalRenderer(),
23
24
  });
@@ -90,7 +91,7 @@ exports.command = new command_1.Command("ext:configure <extensionInstanceId>")
90
91
  nonInteractive: false,
91
92
  force: true,
92
93
  });
93
- manifest.showPostDeprecationNotice();
94
+ (0, tos_1.displayDeveloperTOSWarning)();
94
95
  return;
95
96
  });
96
97
  function infoImmutableParams(immutableParams, paramValues) {
@@ -8,27 +8,34 @@ const utils = require("../utils");
8
8
  const command_1 = require("../command");
9
9
  const prompt_1 = require("../prompt");
10
10
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
11
- const extensionsApi_1 = require("../extensions/extensionsApi");
11
+ const publisherApi_1 = require("../extensions/publisherApi");
12
12
  const versionHelper_1 = require("../extensions/versionHelper");
13
13
  const requireAuth_1 = require("../requireAuth");
14
14
  const error_1 = require("../error");
15
- exports.command = new command_1.Command("ext:dev:deprecate <extensionRef> <versionPredicate>")
15
+ exports.command = new command_1.Command("ext:dev:deprecate <extensionRef> [versionPredicate]")
16
16
  .description("deprecate extension versions that match the version predicate")
17
17
  .option("-m, --message <deprecationMessage>", "deprecation message")
18
18
  .option("-f, --force", "override deprecation message for existing deprecated extension versions that match")
19
19
  .before(requireAuth_1.requireAuth)
20
- .before(extensionsHelper_1.ensureExtensionsApiEnabled)
20
+ .before(extensionsHelper_1.ensureExtensionsPublisherApiEnabled)
21
21
  .action(async (extensionRef, versionPredicate, options) => {
22
- const { publisherId, extensionId, version } = refs.parse(extensionRef);
22
+ const ref = refs.parse(extensionRef);
23
+ return deprecate(ref, versionPredicate, options);
24
+ });
25
+ async function deprecate(extensionRef, versionPredicate, options) {
26
+ const { publisherId, extensionId, version } = extensionRef;
23
27
  if (version) {
24
28
  throw new error_1.FirebaseError(`The input extension reference must be of the format ${clc.bold("<publisherId>/<extensionId>")}. Version should be supplied in the version predicate argument.`);
25
29
  }
26
30
  if (!publisherId || !extensionId) {
27
- 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
+ throw new error_1.FirebaseError(`Error parsing publisher ID and extension ID from extension reference '${clc.bold(refs.toExtensionRef(extensionRef))}'. Please use the format '${clc.bold("<publisherId>/<extensionId>")}'.`);
32
+ }
33
+ let filter = "";
34
+ if (versionPredicate) {
35
+ const { comparator, targetSemVer } = (0, versionHelper_1.parseVersionPredicate)(versionPredicate);
36
+ filter = `id${comparator}"${targetSemVer}"`;
28
37
  }
29
- const { comparator, targetSemVer } = (0, versionHelper_1.parseVersionPredicate)(versionPredicate);
30
- const filter = `id${comparator}"${targetSemVer}"`;
31
- const extensionVersions = await (0, extensionsApi_1.listExtensionVersions)(extensionRef, filter);
38
+ const extensionVersions = await (0, publisherApi_1.listExtensionVersions)(refs.toExtensionRef(extensionRef), filter);
32
39
  const filteredExtensionVersions = extensionVersions
33
40
  .sort((ev1, ev2) => {
34
41
  return -semver.compare(ev1.spec.version, ev2.spec.version);
@@ -42,23 +49,20 @@ exports.command = new command_1.Command("ext:dev:deprecate <extensionRef> <versi
42
49
  return true;
43
50
  });
44
51
  if (filteredExtensionVersions.length > 0) {
45
- if (!options.force) {
46
- const confirmMessage = "You are about to deprecate these extension version(s). Do you wish to continue?";
47
- const consent = await (0, prompt_1.promptOnce)({
48
- type: "confirm",
49
- message: confirmMessage,
50
- default: false,
51
- });
52
- if (!consent) {
53
- throw new error_1.FirebaseError("Deprecation canceled.");
54
- }
52
+ const consent = await (0, prompt_1.confirm)({
53
+ default: false,
54
+ force: options.force,
55
+ nonInteractive: options.nonInteractive,
56
+ });
57
+ if (!consent) {
58
+ throw new error_1.FirebaseError("Deprecation canceled.");
55
59
  }
56
60
  }
57
61
  else {
58
62
  throw new error_1.FirebaseError("No extension versions matched the version predicate.");
59
63
  }
60
64
  await utils.allSettled(filteredExtensionVersions.map(async (extensionVersion) => {
61
- await (0, extensionsApi_1.deprecateExtensionVersion)(extensionVersion.ref, options.deprecationMessage);
65
+ await (0, publisherApi_1.deprecateExtensionVersion)(extensionVersion.ref, options.message);
62
66
  }));
63
67
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, "successfully deprecated extension version(s).");
64
- });
68
+ }
@@ -6,41 +6,42 @@ const Table = require("cli-table");
6
6
  const command_1 = require("../command");
7
7
  const error_1 = require("../error");
8
8
  const utils_1 = require("../utils");
9
- const extensionsApi_1 = require("../extensions/extensionsApi");
9
+ const publisherApi_1 = require("../extensions/publisherApi");
10
10
  const logger_1 = require("../logger");
11
11
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
12
12
  const requireAuth_1 = require("../requireAuth");
13
- const extensionsUtils = require("../extensions/utils");
14
13
  exports.command = new command_1.Command("ext:dev:list <publisherId>")
15
- .description("list all published extensions associated with this publisher ID")
14
+ .description("list all extensions uploaded under publisher ID")
16
15
  .before(requireAuth_1.requireAuth)
17
16
  .action(async (publisherId) => {
18
17
  let extensions;
19
18
  try {
20
- extensions = await (0, extensionsApi_1.listExtensions)(publisherId);
19
+ extensions = await (0, publisherApi_1.listExtensions)(publisherId);
21
20
  }
22
21
  catch (err) {
23
22
  throw new error_1.FirebaseError(err);
24
23
  }
25
24
  if (extensions.length < 1) {
26
- throw new error_1.FirebaseError(`There are no published extensions associated with publisher ID ${clc.bold(publisherId)}. This could happen for two reasons:\n` +
25
+ throw new error_1.FirebaseError(`There are no extensions uploaded under publisher ID ${clc.bold(publisherId)}. This could happen for two reasons:\n` +
27
26
  " - The publisher ID doesn't exist or could be misspelled\n" +
28
- " - This publisher has not published any extensions\n\n" +
27
+ " - This publisher has not uploaded any extensions\n\n" +
29
28
  "If you are expecting some extensions to appear, please make sure you have the correct publisher ID and try again.");
30
29
  }
31
30
  const table = new Table({
32
- head: ["Extension ID", "Version", "Published"],
31
+ head: ["Extension ID", "State", "Latest Version", "Version in Extensions Hub"],
33
32
  style: { head: ["yellow"] },
34
33
  });
35
- const sorted = extensions.sort((a, b) => new Date(b.createTime).valueOf() - new Date(a.createTime).valueOf());
34
+ const sorted = extensions.sort((a, b) => a.ref.localeCompare(b.ref));
36
35
  sorted.forEach((extension) => {
36
+ var _a, _b;
37
37
  table.push([
38
38
  (0, utils_1.last)(extension.ref.split("/")),
39
- extension.latestVersion,
40
- extension.createTime ? extensionsUtils.formatTimestamp(extension.createTime) : "",
39
+ (0, extensionsHelper_1.unpackExtensionState)(extension),
40
+ (_a = extension.latestVersion) !== null && _a !== void 0 ? _a : "-",
41
+ (_b = extension.latestApprovedVersion) !== null && _b !== void 0 ? _b : "-",
41
42
  ]);
42
43
  });
43
- (0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `list of published extensions for publisher ${clc.bold(publisherId)}:`);
44
+ (0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `list of uploaded extensions for publisher ${clc.bold(publisherId)}:`);
44
45
  logger_1.logger.info(table.toString());
45
46
  return { extensions: sorted };
46
47
  });
@@ -1,66 +1,32 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const clc = require("colorette");
5
4
  const marked_1 = require("marked");
6
5
  const TerminalRenderer = require("marked-terminal");
7
6
  const command_1 = require("../command");
8
- const extensionsHelper_1 = require("../extensions/extensionsHelper");
9
- const refs = require("../extensions/refs");
10
- const localHelper_1 = require("../extensions/localHelper");
11
- const publishHelpers_1 = require("../extensions/publishHelpers");
12
7
  const requireAuth_1 = require("../requireAuth");
13
- const error_1 = require("../error");
14
- const utils = require("../utils");
8
+ const ext_dev_upload_1 = require("./ext-dev-upload");
9
+ const utils_1 = require("../utils");
10
+ const extensionsHelper_1 = require("../extensions/extensionsHelper");
15
11
  marked_1.marked.setOptions({
16
12
  renderer: new TerminalRenderer(),
17
13
  });
18
14
  exports.command = new command_1.Command("ext:dev:publish <extensionRef>")
19
- .description(`publish a new version of an extension`)
15
+ .description(`Deprecated. Use ext:dev:upload instead`)
20
16
  .option(`-s, --stage <stage>`, `release stage (supports "alpha", "beta", "rc", and "stable")`)
21
- .option(`--repo <repo>`, `Public Git repo URI (only required for first version from repo, cannot be changed)`)
17
+ .option(`--repo <repo>`, `Public GitHub repo URI that contains the extension source`)
22
18
  .option(`--ref <ref>`, `commit hash, branch, or tag to build from the repo (defaults to HEAD)`)
23
- .option(`--root <root>`, `root directory that contains this Extension (defaults to previous version's root or root of repo if none set)`)
19
+ .option(`--root <root>`, `root directory that contains this extension (defaults to last uploaded root or "/" if none set)`)
24
20
  .withForce()
25
- .help("if you have not previously published a version of this extension, this will " +
26
- "create the extension. If you have previously published a version of this extension, this version must " +
21
+ .help("if you have not previously uploaded a version of this extension, this will " +
22
+ "create the extension. If you have previously uploaded a version of this extension, this version must " +
27
23
  "be greater than previous versions.")
28
24
  .before(requireAuth_1.requireAuth)
25
+ .before(extensionsHelper_1.ensureExtensionsPublisherApiEnabled)
29
26
  .action(async (extensionRef, options) => {
30
- var _a;
31
- const { publisherId, extensionId, version } = refs.parse(extensionRef);
32
- if (version) {
33
- throw new error_1.FirebaseError(`The input extension reference must be of the format ${clc.bold("<publisherId>/<extensionId>")}. Version should not be supplied and will be inferred directly from extension.yaml. Please increment the version in extension.yaml if you would like to bump/specify a version.`);
34
- }
35
- if (!publisherId || !extensionId) {
36
- 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>")}'.`);
37
- }
38
- let res;
39
- if (options.repo || options.root || options.ref) {
40
- res = await (0, extensionsHelper_1.publishExtensionVersionFromRemoteRepo)({
41
- publisherId,
42
- extensionId,
43
- repoUri: options.repo,
44
- sourceRef: options.ref,
45
- extensionRoot: options.root,
46
- nonInteractive: options.nonInteractive,
47
- force: options.force,
48
- stage: options.stage,
49
- });
50
- }
51
- else {
52
- const extensionYamlDirectory = (0, localHelper_1.findExtensionYaml)(process.cwd());
53
- res = await (0, extensionsHelper_1.publishExtensionVersionFromLocalSource)({
54
- publisherId,
55
- extensionId,
56
- rootDirectory: extensionYamlDirectory,
57
- nonInteractive: options.nonInteractive,
58
- force: options.force,
59
- stage: (_a = options.stage) !== null && _a !== void 0 ? _a : "stable",
60
- });
61
- }
62
- if (res) {
63
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
27
+ (0, utils_1.logLabeledWarning)("Extensions", "ext:dev:publish has been deprecated and will be removed in the future. Please use ext:dev:upload instead.");
28
+ if (!options.repo && !options.ref && !options.root) {
29
+ options.local = true;
64
30
  }
65
- return res;
31
+ return (0, ext_dev_upload_1.uploadExtensionAction)(extensionRef, options);
66
32
  });
@@ -4,21 +4,22 @@ exports.command = void 0;
4
4
  const clc = require("colorette");
5
5
  const marked_1 = require("marked");
6
6
  const command_1 = require("../command");
7
- const extensionsApi_1 = require("../extensions/extensionsApi");
7
+ const publisherApi_1 = require("../extensions/publisherApi");
8
8
  const projectUtils_1 = require("../projectUtils");
9
9
  const prompt_1 = require("../prompt");
10
10
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
11
- const askUserForConsent_1 = require("../extensions/askUserForConsent");
11
+ const tos_1 = require("../extensions/tos");
12
12
  const requirePermissions_1 = require("../requirePermissions");
13
13
  const error_1 = require("../error");
14
14
  const utils = require("../utils");
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"])
18
+ .before(extensionsHelper_1.ensureExtensionsPublisherApiEnabled)
18
19
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
19
20
  .action(async (options) => {
20
- await (0, askUserForConsent_1.promptForPublisherTOS)();
21
21
  const projectId = (0, projectUtils_1.needProjectId)(options);
22
+ await (0, tos_1.acceptLatestPublisherTOS)(options, projectId);
22
23
  const msg = "What would you like to register as your publisher ID? " +
23
24
  "This value identifies you in Firebase's registry of extensions as the author of your extensions. " +
24
25
  "Examples: my-company-name, MyGitHubUsername.\n\n" +
@@ -29,8 +30,9 @@ exports.command = new command_1.Command("ext:dev:register")
29
30
  message: msg,
30
31
  default: projectId,
31
32
  });
33
+ let profile;
32
34
  try {
33
- await (0, extensionsApi_1.registerPublisherProfile)(projectId, publisherId);
35
+ profile = await (0, publisherApi_1.registerPublisherProfile)(projectId, publisherId);
34
36
  }
35
37
  catch (err) {
36
38
  if (err.status === 409) {
@@ -43,5 +45,6 @@ exports.command = new command_1.Command("ext:dev:register")
43
45
  }
44
46
  throw new error_1.FirebaseError(`Failed to register publisher ID ${clc.bold(publisherId)} for project ${clc.bold(projectId)}: ${err.message}`);
45
47
  }
46
- return utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `Publisher ID '${clc.bold(publisherId)}' has been registered to project ${clc.bold(projectId)}`);
48
+ utils.logLabeledSuccess(extensionsHelper_1.logPrefix, `Publisher ID '${clc.bold(publisherId)}' has been registered to project ${clc.bold(projectId)}. View and edit your profile at ${utils.consoleUrl(projectId, `/publisher`)}`);
49
+ return profile;
47
50
  });
@@ -8,14 +8,14 @@ const utils = require("../utils");
8
8
  const command_1 = require("../command");
9
9
  const prompt_1 = require("../prompt");
10
10
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
11
- const extensionsApi_1 = require("../extensions/extensionsApi");
11
+ const publisherApi_1 = require("../extensions/publisherApi");
12
12
  const versionHelper_1 = require("../extensions/versionHelper");
13
13
  const requireAuth_1 = require("../requireAuth");
14
14
  const error_1 = require("../error");
15
15
  exports.command = new command_1.Command("ext:dev:undeprecate <extensionRef> <versionPredicate>")
16
16
  .description("undeprecate extension versions that match the version predicate")
17
17
  .before(requireAuth_1.requireAuth)
18
- .before(extensionsHelper_1.ensureExtensionsApiEnabled)
18
+ .before(extensionsHelper_1.ensureExtensionsPublisherApiEnabled)
19
19
  .action(async (extensionRef, versionPredicate, options) => {
20
20
  const { publisherId, extensionId, version } = refs.parse(extensionRef);
21
21
  if (version) {
@@ -26,7 +26,7 @@ exports.command = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
26
26
  }
27
27
  const { comparator, targetSemVer } = (0, versionHelper_1.parseVersionPredicate)(versionPredicate);
28
28
  const filter = `id${comparator}"${targetSemVer}"`;
29
- const extensionVersions = await (0, extensionsApi_1.listExtensionVersions)(extensionRef, filter);
29
+ const extensionVersions = await (0, publisherApi_1.listExtensionVersions)(extensionRef, filter);
30
30
  extensionVersions
31
31
  .sort((ev1, ev2) => {
32
32
  return -semver.compare(ev1.spec.version, ev2.spec.version);
@@ -51,7 +51,7 @@ exports.command = new command_1.Command("ext:dev:undeprecate <extensionRef> <ver
51
51
  throw new error_1.FirebaseError("No extension versions matched the version predicate.");
52
52
  }
53
53
  await utils.allSettled(extensionVersions.map(async (extensionVersion) => {
54
- await (0, extensionsApi_1.undeprecateExtensionVersion)(extensionVersion.ref);
54
+ await (0, publisherApi_1.undeprecateExtensionVersion)(extensionVersion.ref);
55
55
  }));
56
56
  utils.logLabeledSuccess(extensionsHelper_1.logPrefix, "successfully undeprecated extension version(s).");
57
57
  });
@@ -0,0 +1,88 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.uploadExtensionAction = exports.command = void 0;
4
+ const clc = require("colorette");
5
+ const marked_1 = require("marked");
6
+ const TerminalRenderer = require("marked-terminal");
7
+ const command_1 = require("../command");
8
+ const extensionsHelper_1 = require("../extensions/extensionsHelper");
9
+ const refs = require("../extensions/refs");
10
+ const localHelper_1 = require("../extensions/localHelper");
11
+ const publishHelpers_1 = require("../extensions/publishHelpers");
12
+ const requireAuth_1 = require("../requireAuth");
13
+ const error_1 = require("../error");
14
+ const tos_1 = require("../extensions/tos");
15
+ const utils = require("../utils");
16
+ const publisherApi_1 = require("../extensions/publisherApi");
17
+ const extensionsHelper_2 = require("../extensions/extensionsHelper");
18
+ const projects_1 = require("../management/projects");
19
+ marked_1.marked.setOptions({
20
+ renderer: new TerminalRenderer(),
21
+ });
22
+ exports.command = new command_1.Command("ext:dev:upload <extensionRef>")
23
+ .description(`upload a new version of an extension`)
24
+ .option(`-s, --stage <stage>`, `release stage (supports "alpha", "beta", "rc", and "stable")`)
25
+ .option(`--repo <repo>`, `Public GitHub repo URI that contains the extension source`)
26
+ .option(`--ref <ref>`, `commit hash, branch, or tag to build from the repo (defaults to HEAD)`)
27
+ .option(`--root <root>`, `root directory that contains this extension (defaults to last uploaded root or "/" if none set)`)
28
+ .option(`--local`, `upload from local source instead`)
29
+ .withForce()
30
+ .help("if you have not previously uploaded a version of this extension, this will " +
31
+ "create the extension. If you have previously uploaded a version of this extension, this version must " +
32
+ "be greater than previous versions.")
33
+ .before(requireAuth_1.requireAuth)
34
+ .before(extensionsHelper_1.ensureExtensionsPublisherApiEnabled)
35
+ .action(uploadExtensionAction);
36
+ async function uploadExtensionAction(extensionRef, options) {
37
+ const { publisherId, extensionId, version } = refs.parse(extensionRef);
38
+ if (version) {
39
+ throw new error_1.FirebaseError(`The input extension reference must be of the format ${clc.bold("<publisherId>/<extensionId>")}. Version should not be supplied and will be inferred directly from extension.yaml. Please increment the version in extension.yaml if you would like to bump/specify a version.`);
40
+ }
41
+ if (!publisherId || !extensionId) {
42
+ 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>")}'.`);
43
+ }
44
+ let profile;
45
+ try {
46
+ profile = await (0, publisherApi_1.getPublisherProfile)("-", publisherId);
47
+ }
48
+ catch (err) {
49
+ if (err.status === 404) {
50
+ throw (0, extensionsHelper_1.getMissingPublisherError)(publisherId);
51
+ }
52
+ throw err;
53
+ }
54
+ const projectNumber = `${(0, extensionsHelper_2.getPublisherProjectFromName)(profile.name)}`;
55
+ const { projectId } = await (0, projects_1.getFirebaseProject)(projectNumber);
56
+ await (0, tos_1.acceptLatestPublisherTOS)(options, projectNumber);
57
+ let res;
58
+ if (options.local) {
59
+ const extensionYamlDirectory = (0, localHelper_1.findExtensionYaml)(process.cwd());
60
+ res = await (0, extensionsHelper_1.uploadExtensionVersionFromLocalSource)({
61
+ publisherId,
62
+ extensionId,
63
+ rootDirectory: extensionYamlDirectory,
64
+ nonInteractive: options.nonInteractive,
65
+ force: options.force,
66
+ stage: options.stage,
67
+ });
68
+ }
69
+ else {
70
+ res = await (0, extensionsHelper_1.uploadExtensionVersionFromGitHubSource)({
71
+ publisherId,
72
+ extensionId,
73
+ repoUri: options.repo,
74
+ sourceRef: options.ref,
75
+ extensionRoot: options.root,
76
+ nonInteractive: options.nonInteractive,
77
+ force: options.force,
78
+ stage: options.stage,
79
+ });
80
+ }
81
+ if (res) {
82
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
83
+ const version = res.ref.split("@")[1];
84
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[View in Console](${utils.consoleUrl(projectId, `/publisher/extensions/${extensionId}/v/${version}`)})`));
85
+ }
86
+ return res;
87
+ }
88
+ exports.uploadExtensionAction = uploadExtensionAction;
@@ -9,7 +9,7 @@ const cloudmonitoring_1 = require("../gcp/cloudmonitoring");
9
9
  const requireAuth_1 = require("../requireAuth");
10
10
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
11
11
  const metricsUtils_1 = require("../extensions/metricsUtils");
12
- const extensionsApi_1 = require("../extensions/extensionsApi");
12
+ const publisherApi_1 = require("../extensions/publisherApi");
13
13
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
14
14
  const error_1 = require("../error");
15
15
  const logger_1 = require("../logger");
@@ -33,7 +33,7 @@ exports.command = new command_1.Command("ext:dev:usage <publisherId>")
33
33
  publisherId = input;
34
34
  let extensions;
35
35
  try {
36
- extensions = await (0, extensionsApi_1.listExtensions)(publisherId);
36
+ extensions = await (0, publisherApi_1.listExtensions)(publisherId);
37
37
  }
38
38
  catch (err) {
39
39
  throw new error_1.FirebaseError(err);
@@ -57,7 +57,7 @@ exports.command = new command_1.Command("ext:dev:usage <publisherId>")
57
57
  }),
58
58
  });
59
59
  }
60
- const profile = await (0, extensionsApi_1.getPublisherProfile)("-", publisherId);
60
+ const profile = await (0, publisherApi_1.getPublisherProfile)("-", publisherId);
61
61
  const projectNumber = (0, extensionsHelper_1.getPublisherProjectFromName)(profile.name);
62
62
  const past45d = new Date();
63
63
  past45d.setDate(past45d.getDate() - 45);
@@ -13,25 +13,21 @@ const projectUtils_1 = require("../projectUtils");
13
13
  const extensionsApi = require("../extensions/extensionsApi");
14
14
  const refs = require("../extensions/refs");
15
15
  const secretsUtils = require("../extensions/secretsUtils");
16
- const warnings_1 = require("../extensions/warnings");
17
16
  const paramHelper = require("../extensions/paramHelper");
18
17
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
19
- const prompt_1 = require("../prompt");
20
18
  const utils_1 = require("../extensions/utils");
21
19
  const requirePermissions_1 = require("../requirePermissions");
22
20
  const utils = require("../utils");
23
21
  const track_1 = require("../track");
24
- const experiments = require("../experiments");
22
+ const prompt_1 = require("../prompt");
25
23
  const manifest = require("../extensions/manifest");
24
+ const tos_1 = require("../extensions/tos");
26
25
  marked_1.marked.setOptions({
27
26
  renderer: new TerminalRenderer(),
28
27
  });
29
28
  exports.command = new command_1.Command("ext:install [extensionName]")
30
- .description("install an official extension if [extensionName] or [extensionName@version] is provided; " +
31
- (experiments.isEnabled("extdev")
32
- ? "install a local extension if [localPathOrUrl] or [url#root] is provided; install a published extension (not authored by Firebase) if [publisherId/extensionId] is provided "
33
- : "") +
34
- "or run with `-i` to see all available extensions.")
29
+ .description("add an uploaded extension to firebase.json if [publisherId/extensionId] is provided;" +
30
+ "or, add a local extension if [localPath] is provided")
35
31
  .option("--local", "deprecated")
36
32
  .withForce()
37
33
  .before(requirePermissions_1.requirePermissions, ["firebaseextensions.instances.create"])
@@ -118,7 +114,6 @@ exports.command = new command_1.Command("ext:install [extensionName]")
118
114
  async function infoExtensionVersion(args) {
119
115
  const ref = refs.parse(args.extensionName);
120
116
  await (0, displayExtensionInfo_1.displayExtInfo)(args.extensionName, ref.publisherId, args.extensionVersion.spec, true);
121
- await (0, warnings_1.displayWarningPrompts)(ref.publisherId, args.extensionVersion);
122
117
  }
123
118
  async function installToManifest(options) {
124
119
  var _a, _b, _c;
@@ -162,5 +157,5 @@ async function installToManifest(options) {
162
157
  extensionSpec: spec,
163
158
  },
164
159
  ], config, { nonInteractive, force: force !== null && force !== void 0 ? force : false });
165
- manifest.showPostDeprecationNotice();
160
+ (0, tos_1.displayDeveloperTOSWarning)();
166
161
  }
@@ -26,5 +26,4 @@ exports.command = new command_1.Command("ext:uninstall <extensionInstanceId>")
26
26
  }
27
27
  const config = manifest.loadConfig(options);
28
28
  manifest.removeFromManifest(instanceId, config);
29
- manifest.showPostDeprecationNotice();
30
29
  });
@@ -14,19 +14,17 @@ const updateHelper_1 = require("../extensions/updateHelper");
14
14
  const secretsUtils = require("../extensions/secretsUtils");
15
15
  const refs = require("../extensions/refs");
16
16
  const projectUtils_1 = require("../projectUtils");
17
- const prompt_1 = require("../prompt");
18
17
  const requirePermissions_1 = require("../requirePermissions");
19
18
  const utils = require("../utils");
20
- const experiments = require("../experiments");
19
+ const prompt_1 = require("../prompt");
21
20
  const manifest = require("../extensions/manifest");
22
21
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
22
+ const tos_1 = require("../extensions/tos");
23
23
  marked_1.marked.setOptions({
24
24
  renderer: new TerminalRenderer(),
25
25
  });
26
26
  exports.command = new command_1.Command("ext:update <extensionInstanceId> [updateSource]")
27
- .description(experiments.isEnabled("extdev")
28
- ? "update an existing extension instance to the latest version or from a local or URL source"
29
- : "update an existing extension instance to the latest version")
27
+ .description("update an existing extension instance to the latest version, or to a specific version if provided")
30
28
  .before(requirePermissions_1.requirePermissions, [
31
29
  "firebaseextensions.instances.update",
32
30
  "firebaseextensions.instances.get",
@@ -34,14 +32,10 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
34
32
  .before(extensionsHelper_1.ensureExtensionsApiEnabled)
35
33
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
36
34
  .before(extensionsHelper_1.diagnoseAndFixProject)
37
- .option("--local", "deprecated")
38
35
  .withForce()
39
36
  .action(async (instanceId, updateSource, options) => {
40
37
  const projectId = (0, projectUtils_1.getProjectId)(options);
41
38
  const config = manifest.loadConfig(options);
42
- if (options.local) {
43
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, "As of firebase-tools@11.0.0, the `--local` flag is no longer required, as it is the default behavior.");
44
- }
45
39
  const oldRefOrPath = manifest.getInstanceTarget(instanceId, config);
46
40
  if ((0, extensionsHelper_1.isLocalPath)(oldRefOrPath)) {
47
41
  throw new error_1.FirebaseError(`Updating an extension with local source is not neccessary. ` +
@@ -107,6 +101,6 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
107
101
  nonInteractive: options.nonInteractive,
108
102
  force: true,
109
103
  });
110
- manifest.showPostDeprecationNotice();
104
+ (0, tos_1.displayDeveloperTOSWarning)();
111
105
  return;
112
106
  });
@@ -80,25 +80,15 @@ function load(client) {
80
80
  client.ext.list = loadCommand("ext-list");
81
81
  client.ext.uninstall = loadCommand("ext-uninstall");
82
82
  client.ext.update = loadCommand("ext-update");
83
- if (experiments.isEnabled("ext")) {
84
- client.ext.sources = {};
85
- client.ext.sources.create = loadCommand("ext-sources-create");
86
- }
87
- if (experiments.isEnabled("extdev")) {
88
- client.ext.dev = {};
89
- client.ext.dev.init = loadCommand("ext-dev-init");
90
- client.ext.dev.list = loadCommand("ext-dev-list");
91
- client.ext.dev.register = loadCommand("ext-dev-register");
92
- client.ext.dev.emulators = {};
93
- client.ext.dev.emulators.start = loadCommand("ext-dev-emulators-start");
94
- client.ext.dev.emulators.exec = loadCommand("ext-dev-emulators-exec");
95
- client.ext.dev.deprecate = loadCommand("ext-dev-deprecate");
96
- client.ext.dev.undeprecate = loadCommand("ext-dev-undeprecate");
97
- client.ext.dev.unpublish = loadCommand("ext-dev-unpublish");
98
- client.ext.dev.publish = loadCommand("ext-dev-publish");
99
- client.ext.dev.delete = loadCommand("ext-dev-extension-delete");
100
- client.ext.dev.usage = loadCommand("ext-dev-usage");
101
- }
83
+ client.ext.dev = {};
84
+ client.ext.dev.init = loadCommand("ext-dev-init");
85
+ client.ext.dev.list = loadCommand("ext-dev-list");
86
+ client.ext.dev.register = loadCommand("ext-dev-register");
87
+ client.ext.dev.deprecate = loadCommand("ext-dev-deprecate");
88
+ client.ext.dev.undeprecate = loadCommand("ext-dev-undeprecate");
89
+ client.ext.dev.upload = loadCommand("ext-dev-upload");
90
+ client.ext.dev.publish = loadCommand("ext-dev-publish");
91
+ client.ext.dev.usage = loadCommand("ext-dev-usage");
102
92
  client.firestore = {};
103
93
  client.firestore.delete = loadCommand("firestore-delete");
104
94
  client.firestore.indexes = loadCommand("firestore-indexes-list");
@@ -129,17 +129,23 @@ async function want(args) {
129
129
  exports.want = want;
130
130
  async function resolveVersion(ref) {
131
131
  const extensionRef = refs.toExtensionRef(ref);
132
+ const extension = await extensionsApi.getExtension(extensionRef);
133
+ if (!ref.version || ref.version === "latest-approved") {
134
+ if (!extension.latestApprovedVersion) {
135
+ throw new error_1.FirebaseError(`${extensionRef} has not been published to Extensions Hub (https://extensions.dev). To install it, you must specify the version you want to install.`);
136
+ }
137
+ return extension.latestApprovedVersion;
138
+ }
139
+ if (ref.version === "latest") {
140
+ if (!extension.latestVersion) {
141
+ throw new error_1.FirebaseError(`${extensionRef} has no stable non-deprecated versions. If you wish to install a prerelease version, you must specify the version you want to install.`);
142
+ }
143
+ return extension.latestVersion;
144
+ }
132
145
  const versions = await extensionsApi.listExtensionVersions(extensionRef, undefined, true);
133
146
  if (versions.length === 0) {
134
147
  throw new error_1.FirebaseError(`No versions found for ${extensionRef}`);
135
148
  }
136
- if (!ref.version || ref.version === "latest") {
137
- return versions
138
- .filter((ev) => ev.spec.version !== undefined)
139
- .map((ev) => ev.spec.version)
140
- .sort(semver.compare)
141
- .pop();
142
- }
143
149
  const maxSatisfying = semver.maxSatisfying(versions.map((ev) => ev.spec.version), ref.version);
144
150
  if (!maxSatisfying) {
145
151
  throw new error_1.FirebaseError(`No version of ${extensionRef} matches requested version ${ref.version}`);