firebase-tools 13.14.2 → 13.15.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 (34) hide show
  1. package/lib/bin/firebase.js +2 -4
  2. package/lib/commands/deploy.js +7 -1
  3. package/lib/commands/ext-configure.js +1 -6
  4. package/lib/commands/ext-dev-init.js +2 -4
  5. package/lib/commands/ext-dev-upload.js +4 -6
  6. package/lib/commands/ext-info.js +3 -5
  7. package/lib/commands/ext-install.js +0 -5
  8. package/lib/commands/ext-uninstall.js +0 -5
  9. package/lib/commands/ext-update.js +0 -5
  10. package/lib/commands/firestore-databases-create.js +19 -1
  11. package/lib/commands/functions-secrets-set.js +9 -6
  12. package/lib/commands/hosting-channel-create.js +1 -1
  13. package/lib/commands/hosting-channel-delete.js +1 -1
  14. package/lib/commands/hosting-channel-deploy.js +1 -1
  15. package/lib/commands/hosting-clone.js +1 -2
  16. package/lib/dataconnect/fileUtils.js +22 -1
  17. package/lib/dataconnect/types.js +8 -1
  18. package/lib/emulator/dataconnectEmulator.js +2 -0
  19. package/lib/emulator/downloadableEmulators.js +11 -12
  20. package/lib/extensions/askUserForParam.js +1 -1
  21. package/lib/extensions/change-log.js +2 -4
  22. package/lib/extensions/displayExtensionInfo.js +0 -5
  23. package/lib/extensions/extensionsHelper.js +5 -7
  24. package/lib/extensions/provisioningHelper.js +1 -1
  25. package/lib/extensions/updateHelper.js +1 -2
  26. package/lib/extensions/warnings.js +2 -7
  27. package/lib/firestore/api.js +8 -7
  28. package/lib/firestore/pretty-print.js +21 -1
  29. package/lib/firestore/pretty-print.test.js +8 -0
  30. package/lib/init/features/dataconnect/index.js +19 -8
  31. package/lib/init/features/dataconnect/sdk.js +23 -23
  32. package/lib/rulesDeploy.js +14 -12
  33. package/package.json +3 -3
  34. package/lib/extensions/billingMigrationHelper.js +0 -61
@@ -10,12 +10,10 @@ if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
10
10
  }
11
11
  const updateNotifierPkg = require("update-notifier-cjs");
12
12
  const clc = require("colorette");
13
- const TerminalRenderer = require("marked-terminal");
13
+ const marked_terminal_1 = require("marked-terminal");
14
14
  const updateNotifier = updateNotifierPkg({ pkg });
15
15
  const marked_1 = require("marked");
16
- marked_1.marked.setOptions({
17
- renderer: new TerminalRenderer(),
18
- });
16
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
19
17
  const node_path_1 = require("node:path");
20
18
  const triple_beam_1 = require("triple-beam");
21
19
  const stripAnsi = require("strip-ansi");
@@ -107,7 +107,13 @@ exports.command = new command_1.Command("deploy")
107
107
  await (0, requireHostingSite_1.requireHostingSite)(options);
108
108
  }
109
109
  catch (err) {
110
- if (err === getDefaultHostingSite_1.errNoDefaultSite) {
110
+ const isPermissionError = err instanceof error_1.FirebaseError &&
111
+ err.original instanceof error_1.FirebaseError &&
112
+ err.original.status === 403;
113
+ if (isPermissionError) {
114
+ throw err;
115
+ }
116
+ else if (err === getDefaultHostingSite_1.errNoDefaultSite) {
111
117
  createSite = true;
112
118
  }
113
119
  }
@@ -1,8 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const marked_1 = require("marked");
5
- const TerminalRenderer = require("marked-terminal");
6
4
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
7
5
  const command_1 = require("../command");
8
6
  const error_1 = require("../error");
@@ -19,9 +17,6 @@ const functional_1 = require("../functional");
19
17
  const paramHelper_1 = require("../extensions/paramHelper");
20
18
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
21
19
  const tos_1 = require("../extensions/tos");
22
- marked_1.marked.setOptions({
23
- renderer: new TerminalRenderer(),
24
- });
25
20
  exports.command = new command_1.Command("ext:configure <extensionInstanceId>")
26
21
  .description("configure an existing extension instance")
27
22
  .withForce()
@@ -99,7 +94,7 @@ function infoImmutableParams(immutableParams, paramValues) {
99
94
  return;
100
95
  }
101
96
  const plural = immutableParams.length > 1;
102
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`The following param${plural ? "s are" : " is"} immutable and won't be changed:`));
97
+ utils.logLabeledWarning(extensionsHelper_1.logPrefix, `The following param${plural ? "s are" : " is"} immutable and won't be changed:`);
103
98
  for (const { param } of immutableParams) {
104
99
  logger_1.logger.info(`param: ${param}, value: ${paramValues[param]}`);
105
100
  }
@@ -2,7 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const marked_1 = require("marked");
5
- const TerminalRenderer = require("marked-terminal");
5
+ const marked_terminal_1 = require("marked-terminal");
6
6
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
7
7
  const command_1 = require("../command");
8
8
  const config_1 = require("../config");
@@ -11,9 +11,7 @@ const prompt_1 = require("../prompt");
11
11
  const logger_1 = require("../logger");
12
12
  const npmDependencies = require("../init/features/functions/npm-dependencies");
13
13
  const templates_1 = require("../templates");
14
- marked_1.marked.setOptions({
15
- renderer: new TerminalRenderer(),
16
- });
14
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
17
15
  function readCommonTemplates() {
18
16
  return {
19
17
  integrationTestFirebaseJsonTemplate: (0, templates_1.readTemplateSync)("extensions/integration-test.json"),
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.uploadExtensionAction = exports.command = void 0;
4
4
  const clc = require("colorette");
5
5
  const marked_1 = require("marked");
6
- const TerminalRenderer = require("marked-terminal");
6
+ const marked_terminal_1 = require("marked-terminal");
7
7
  const command_1 = require("../command");
8
8
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
9
9
  const refs = require("../extensions/refs");
@@ -16,9 +16,7 @@ const utils = require("../utils");
16
16
  const publisherApi_1 = require("../extensions/publisherApi");
17
17
  const extensionsHelper_2 = require("../extensions/extensionsHelper");
18
18
  const projects_1 = require("../management/projects");
19
- marked_1.marked.setOptions({
20
- renderer: new TerminalRenderer(),
21
- });
19
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
22
20
  exports.command = new command_1.Command("ext:dev:upload <extensionRef>")
23
21
  .description(`upload a new version of an extension`)
24
22
  .option(`-s, --stage <stage>`, `release stage (supports "alpha", "beta", "rc", and "stable")`)
@@ -79,9 +77,9 @@ async function uploadExtensionAction(extensionRef, options) {
79
77
  });
80
78
  }
81
79
  if (res) {
82
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
80
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, await (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
83
81
  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}`)})`));
82
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, await (0, marked_1.marked)(`[View in Console](${utils.consoleUrl(projectId, `/publisher/extensions/${extensionId}/v/${version}`)})`));
85
83
  }
86
84
  return res;
87
85
  }
@@ -11,7 +11,7 @@ const logger_1 = require("../logger");
11
11
  const requirePermissions_1 = require("../requirePermissions");
12
12
  const utils = require("../utils");
13
13
  const marked_1 = require("marked");
14
- const TerminalRenderer = require("marked-terminal");
14
+ const marked_terminal_1 = require("marked-terminal");
15
15
  const FUNCTION_TYPE_REGEX = /\..+\.function/;
16
16
  exports.command = new command_1.Command("ext:info <extensionName>")
17
17
  .description("display information about an extension by name (extensionName@x.y.z for a specific version)")
@@ -108,10 +108,8 @@ exports.command = new command_1.Command("ext:info <extensionName>")
108
108
  logger_1.logger.info(lines.join("\n\n"));
109
109
  }
110
110
  else {
111
- marked_1.marked.setOptions({
112
- renderer: new TerminalRenderer(),
113
- });
114
- logger_1.logger.info((0, marked_1.marked)(lines.join("\n")));
111
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
112
+ logger_1.logger.info(await (0, marked_1.marked)(lines.join("\n")));
115
113
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `to install this extension, type ` +
116
114
  clc.bold(`firebase ext:install ${extensionName} --project=YOUR_PROJECT`));
117
115
  }
@@ -2,9 +2,7 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const marked_1 = require("marked");
6
5
  const semver = require("semver");
7
- const TerminalRenderer = require("marked-terminal");
8
6
  const displayExtensionInfo_1 = require("../extensions/displayExtensionInfo");
9
7
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
10
8
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
@@ -25,9 +23,6 @@ const track_1 = require("../track");
25
23
  const prompt_1 = require("../prompt");
26
24
  const manifest = require("../extensions/manifest");
27
25
  const tos_1 = require("../extensions/tos");
28
- marked_1.marked.setOptions({
29
- renderer: new TerminalRenderer(),
30
- });
31
26
  exports.command = new command_1.Command("ext:install [extensionRef]")
32
27
  .description("add an uploaded extension to firebase.json if [publisherId/extensionId] is provided;" +
33
28
  "or, add a local extension if [localPath] is provided")
@@ -1,17 +1,12 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const marked_1 = require("marked");
5
- const TerminalRenderer = require("marked-terminal");
6
4
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
7
5
  const command_1 = require("../command");
8
6
  const extensionsHelper_1 = require("../extensions/extensionsHelper");
9
7
  const requirePermissions_1 = require("../requirePermissions");
10
8
  const utils_1 = require("../utils");
11
9
  const manifest = require("../extensions/manifest");
12
- marked_1.marked.setOptions({
13
- renderer: new TerminalRenderer(),
14
- });
15
10
  exports.command = new command_1.Command("ext:uninstall <extensionInstanceId>")
16
11
  .description("uninstall an extension that is installed in your Firebase project by instance ID")
17
12
  .option("--local", "deprecated")
@@ -2,8 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const clc = require("colorette");
5
- const marked_1 = require("marked");
6
- const TerminalRenderer = require("marked-terminal");
7
5
  const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
8
6
  const command_1 = require("../command");
9
7
  const error_1 = require("../error");
@@ -20,9 +18,6 @@ const prompt_1 = require("../prompt");
20
18
  const manifest = require("../extensions/manifest");
21
19
  const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
22
20
  const tos_1 = require("../extensions/tos");
23
- marked_1.marked.setOptions({
24
- renderer: new TerminalRenderer(),
25
- });
26
21
  exports.command = new command_1.Command("ext:update <extensionInstanceId> [updateSource]")
27
22
  .description("update an existing extension instance to the latest version, or to a specific version if provided")
28
23
  .before(requirePermissions_1.requirePermissions, [
@@ -16,6 +16,9 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
16
16
  .option("--location <locationId>", "Region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations. (required)")
17
17
  .option("--delete-protection <deleteProtectionState>", "Whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
18
18
  .option("--point-in-time-recovery <enablement>", "Whether to enable the PITR feature on this database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
19
+ .option("-k, --kms-key-name <kmsKeyName>", "The resource ID of a Cloud KMS key. If set, the database created will be a " +
20
+ "Customer-managed Encryption Key (CMEK) database encrypted with this key. " +
21
+ "This feature is allowlist only in initial launch.")
19
22
  .before(requirePermissions_1.requirePermissions, ["datastore.databases.create"])
20
23
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
21
24
  .action(async (database, options) => {
@@ -42,7 +45,22 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
42
45
  const pointInTimeRecoveryEnablement = options.pointInTimeRecovery === types.PointInTimeRecoveryEnablementOption.ENABLED
43
46
  ? types.PointInTimeRecoveryEnablement.ENABLED
44
47
  : types.PointInTimeRecoveryEnablement.DISABLED;
45
- const databaseResp = await api.createDatabase(options.project, database, options.location, type, deleteProtectionState, pointInTimeRecoveryEnablement);
48
+ let cmekConfig;
49
+ if (options.kmsKeyName) {
50
+ cmekConfig = {
51
+ kmsKeyName: options.kmsKeyName,
52
+ };
53
+ }
54
+ const createDatabaseReq = {
55
+ project: options.project,
56
+ databaseId: database,
57
+ locationId: options.location,
58
+ type,
59
+ deleteProtectionState,
60
+ pointInTimeRecoveryEnablement,
61
+ cmekConfig,
62
+ };
63
+ const databaseResp = await api.createDatabase(createDatabaseReq);
46
64
  if (options.json) {
47
65
  logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
48
66
  }
@@ -54,12 +54,15 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
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
56
  if (!options.force) {
57
- const confirm = await (0, prompt_1.promptOnce)({
58
- name: "redeploy",
59
- type: "confirm",
60
- default: true,
61
- message: `Do you want to re-deploy the functions and destroy the stale version of secret ${secret.name}?`,
62
- }, options);
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
+ }
63
66
  if (!confirm) {
64
67
  (0, utils_1.logBullet)("Please deploy your functions for the change to take effect by running:\n\t" +
65
68
  clc.bold("firebase deploy --only functions"));
@@ -65,7 +65,7 @@ exports.command = new command_1.Command("hosting:channel:create [channelId]")
65
65
  await (0, api_1.addAuthDomains)(projectId, [channel.url]);
66
66
  }
67
67
  catch (e) {
68
- (0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
68
+ (0, utils_1.logLabeledWarning)(LOG_TAG, await (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
69
69
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
70
70
  }
71
71
  logger_1.logger.info();
@@ -39,7 +39,7 @@ exports.command = new command_1.Command("hosting:channel:delete <channelId>")
39
39
  await (0, api_1.removeAuthDomain)(projectId, channel.url);
40
40
  }
41
41
  catch (e) {
42
- (0, utils_1.logLabeledWarning)("hosting:channel", (0, marked_1.marked)(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
42
+ (0, utils_1.logLabeledWarning)("hosting:channel", await (0, marked_1.marked)(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
43
43
  logger_1.logger.debug("[hosting] unable to remove auth domain", e);
44
44
  }
45
45
  }
@@ -133,7 +133,7 @@ async function syncAuthState(projectId, sites) {
133
133
  logger_1.logger.debug("[hosting] added auth domain for urls", urlNames);
134
134
  }
135
135
  catch (e) {
136
- (0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
136
+ (0, utils_1.logLabeledWarning)(LOG_TAG, await (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
137
137
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
138
138
  }
139
139
  try {
@@ -8,7 +8,6 @@ const error_1 = require("../error");
8
8
  const api_1 = require("../hosting/api");
9
9
  const utils = require("../utils");
10
10
  const requireAuth_1 = require("../requireAuth");
11
- const marked_1 = require("marked");
12
11
  const logger_1 = require("../logger");
13
12
  exports.command = new command_1.Command("hosting:clone <source> <targetChannel>")
14
13
  .description("clone a version from one site to another")
@@ -68,7 +67,7 @@ For example, to copy the content for a site \`my-site\` from a preview channel \
68
67
  await (0, api_1.addAuthDomains)(tProjectId, [tChannel.url]);
69
68
  }
70
69
  catch (e) {
71
- utils.logLabeledWarning("hosting:clone", (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${utils.consoleUrl(targetSiteId, "/authentication/providers")}`));
70
+ utils.logLabeledWarning("hosting:clone", `Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${utils.consoleUrl(targetSiteId, "/authentication/providers")}`);
72
71
  logger_1.logger.debug("[hosting] unable to add auth domain", e);
73
72
  }
74
73
  }
@@ -1,9 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.pickService = exports.readGQLFiles = exports.readConnectorYaml = exports.readDataConnectYaml = exports.readFirebaseJson = void 0;
3
+ exports.getPlatformFromFolder = exports.pickService = exports.readGQLFiles = exports.readConnectorYaml = exports.readDataConnectYaml = exports.readFirebaseJson = void 0;
4
4
  const fs = require("fs-extra");
5
5
  const path = require("path");
6
6
  const error_1 = require("../error");
7
+ const types_1 = require("./types");
7
8
  const utils_1 = require("../utils");
8
9
  const load_1 = require("./load");
9
10
  function readFirebaseJson(config) {
@@ -92,3 +93,23 @@ async function pickService(projectId, config, serviceId) {
92
93
  return serviceInfo;
93
94
  }
94
95
  exports.pickService = pickService;
96
+ const WEB_INDICATORS = ["package.json", "package-lock.json", "node_modules"];
97
+ const IOS_INDICATORS = ["info.plist", "podfile", "package.swift"];
98
+ const ANDROID_INDICATORS = ["androidmanifest.xml", "build.gradle"];
99
+ const IOS_INDICATORS_2 = [".xcworkspace", ".xcodeproj"];
100
+ async function getPlatformFromFolder(dirPath) {
101
+ const fileNames = await fs.readdir(dirPath);
102
+ for (const fileName of fileNames) {
103
+ const cleanedFileName = fileName.toLowerCase();
104
+ if (WEB_INDICATORS.some((indicator) => indicator === cleanedFileName))
105
+ return types_1.Platform.WEB;
106
+ if (ANDROID_INDICATORS.some((indicator) => indicator === cleanedFileName))
107
+ return types_1.Platform.ANDROID;
108
+ if (IOS_INDICATORS.some((indicator) => indicator === cleanedFileName))
109
+ return types_1.Platform.IOS;
110
+ if (IOS_INDICATORS_2.some((indicator) => cleanedFileName.endsWith(indicator)))
111
+ return types_1.Platform.IOS;
112
+ }
113
+ return types_1.Platform.UNDETERMINED;
114
+ }
115
+ exports.getPlatformFromFolder = getPlatformFromFolder;
@@ -1,12 +1,19 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.toDatasource = exports.requiresVector = exports.SCHEMA_ID = void 0;
3
+ exports.toDatasource = exports.Platform = exports.requiresVector = exports.SCHEMA_ID = void 0;
4
4
  exports.SCHEMA_ID = "main";
5
5
  function requiresVector(dm) {
6
6
  var _a, _b, _c, _d;
7
7
  return (_d = (_c = (_b = (_a = dm === null || dm === void 0 ? void 0 : dm.primaryDataSource) === null || _a === void 0 ? void 0 : _a.postgres) === null || _b === void 0 ? void 0 : _b.requiredExtensions) === null || _c === void 0 ? void 0 : _c.includes("vector")) !== null && _d !== void 0 ? _d : false;
8
8
  }
9
9
  exports.requiresVector = requiresVector;
10
+ var Platform;
11
+ (function (Platform) {
12
+ Platform["ANDROID"] = "ANDROID";
13
+ Platform["WEB"] = "WEB";
14
+ Platform["IOS"] = "IOS";
15
+ Platform["UNDETERMINED"] = "UNDETERMINED";
16
+ })(Platform = exports.Platform || (exports.Platform = {}));
10
17
  function toDatasource(projectId, locationId, ds) {
11
18
  if (ds.postgresql) {
12
19
  return {
@@ -53,6 +53,8 @@ class DataConnectEmulator {
53
53
  auto_download: this.args.auto_download,
54
54
  listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
55
55
  config_dir: resolvedConfigDir,
56
+ enable_output_schema_extensions: true,
57
+ enable_output_generated_sdk: true,
56
58
  });
57
59
  this.usingExistingEmulator = false;
58
60
  }
@@ -46,20 +46,20 @@ const EMULATOR_UPDATE_DETAILS = {
46
46
  },
47
47
  dataconnect: process.platform === "darwin"
48
48
  ? {
49
- version: "1.3.1",
50
- expectedSize: 24175424,
51
- expectedChecksum: "9ce1ee2ed6994ca62df6dfef3fdece62",
49
+ version: "1.3.2",
50
+ expectedSize: 24195840,
51
+ expectedChecksum: "b60f4501c657bec4dc8df3f3ec7ab3fd",
52
52
  }
53
53
  : process.platform === "win32"
54
54
  ? {
55
- version: "1.3.1",
56
- expectedSize: 24587264,
57
- expectedChecksum: "1d31fd26506cfc9b822fdb8e8834d14c",
55
+ version: "1.3.2",
56
+ expectedSize: 24610304,
57
+ expectedChecksum: "37d5e08f4df5e07b41160b8f2fd90135",
58
58
  }
59
59
  : {
60
- version: "1.3.1",
61
- expectedSize: 24088728,
62
- expectedChecksum: "223f7eebde618ba92788579dd35fec43",
60
+ version: "1.3.2",
61
+ expectedSize: 24109208,
62
+ expectedChecksum: "52b09c69bc9a3a84b01a3a7311817229",
63
63
  },
64
64
  };
65
65
  exports.DownloadDetails = {
@@ -243,9 +243,8 @@ const Commands = {
243
243
  optionalArgs: [
244
244
  "listen",
245
245
  "config_dir",
246
- "disable_sdk_generation",
247
- "resolvers_emulator",
248
- "rpc_retry_count",
246
+ "enable_output_schema_extensions",
247
+ "enable_output_generated_sdk",
249
248
  ],
250
249
  joinArgs: true,
251
250
  shell: false,
@@ -122,7 +122,7 @@ async function askForParam(args) {
122
122
  let secretLocations = [];
123
123
  const description = paramSpec.description || "";
124
124
  const label = paramSpec.label.trim();
125
- logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(0, marked_1.marked)(description).trim()}`);
125
+ logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(await (0, marked_1.marked)(description)).trim()}`);
126
126
  while (!valid) {
127
127
  switch (paramSpec.type) {
128
128
  case types_1.ParamType.SELECT:
@@ -5,16 +5,14 @@ const clc = require("colorette");
5
5
  const marked_1 = require("marked");
6
6
  const path = require("path");
7
7
  const semver = require("semver");
8
- const TerminalRenderer = require("marked-terminal");
8
+ const marked_terminal_1 = require("marked-terminal");
9
9
  const Table = require("cli-table");
10
10
  const extensionsApi_1 = require("./extensionsApi");
11
11
  const localHelper_1 = require("./localHelper");
12
12
  const logger_1 = require("../logger");
13
13
  const refs = require("./refs");
14
14
  const utils_1 = require("../utils");
15
- marked_1.marked.setOptions({
16
- renderer: new TerminalRenderer(),
17
- });
15
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
18
16
  const EXTENSIONS_CHANGELOG = "CHANGELOG.md";
19
17
  const VERSION_LINE_REGEX = /##.+?(\d+\.\d+\.\d+(?:-((\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?).*/;
20
18
  async function getReleaseNotesForUpdate(args) {
@@ -2,18 +2,13 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.retrieveRoleInfo = exports.displayResources = exports.displayEvents = exports.displayExternalServices = exports.displayExtensionVersionInfo = void 0;
4
4
  const clc = require("colorette");
5
- const marked_1 = require("marked");
6
5
  const semver = require("semver");
7
- const TerminalRenderer = require("marked-terminal");
8
6
  const path = require("path");
9
7
  const refs = require("../extensions/refs");
10
8
  const logger_1 = require("../logger");
11
9
  const types_1 = require("./types");
12
10
  const iam = require("../gcp/iam");
13
11
  const secretsUtils_1 = require("./secretsUtils");
14
- marked_1.marked.setOptions({
15
- renderer: new TerminalRenderer(),
16
- });
17
12
  const TASKS_ROLE = "cloudtasks.enqueuer";
18
13
  const TASKS_API = "cloudtasks.googleapis.com";
19
14
  async function displayExtensionVersionInfo(args) {
@@ -9,11 +9,9 @@ const fs = require("fs-extra");
9
9
  const node_fetch_1 = require("node-fetch");
10
10
  const path = require("path");
11
11
  const marked_1 = require("marked");
12
+ const marked_terminal_1 = require("marked-terminal");
12
13
  const unzip_1 = require("./../unzip");
13
- const TerminalRenderer = require("marked-terminal");
14
- marked_1.marked.setOptions({
15
- renderer: new TerminalRenderer(),
16
- });
14
+ marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
17
15
  const api_1 = require("../api");
18
16
  const archiveDirectory_1 = require("../archiveDirectory");
19
17
  const utils_1 = require("./utils");
@@ -417,12 +415,12 @@ function validateReleaseNotes(rootDirectory, newVersion, extension) {
417
415
  catch (err) {
418
416
  throw new error_1.FirebaseError("No CHANGELOG.md file found. " +
419
417
  "Please create one and add an entry for this version. " +
420
- (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details."));
418
+ "See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
421
419
  }
422
420
  if (!notes && !semver.prerelease(newVersion) && extension) {
423
421
  throw new error_1.FirebaseError(`No entry for version ${newVersion} found in CHANGELOG.md. ` +
424
422
  "Please add one so users know what has changed in this version. " +
425
- (0, marked_1.marked)("See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details."));
423
+ "See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
426
424
  }
427
425
  return notes;
428
426
  }
@@ -701,7 +699,7 @@ async function uploadExtensionVersionFromLocalSource(args) {
701
699
  }
702
700
  exports.uploadExtensionVersionFromLocalSource = uploadExtensionVersionFromLocalSource;
703
701
  function getMissingPublisherError(publisherId) {
704
- return new error_1.FirebaseError((0, marked_1.marked)(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`));
702
+ return new error_1.FirebaseError(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`);
705
703
  }
706
704
  exports.getMissingPublisherError = getMissingPublisherError;
707
705
  async function createSourceFromLocation(projectId, sourceUri) {
@@ -64,7 +64,7 @@ async function checkProducts(projectId, usedProducts) {
64
64
  "without server-side code.\n";
65
65
  errorMessage += ` https://console.firebase.google.com/project/${projectId}/authentication/users`;
66
66
  }
67
- throw new error_1.FirebaseError((0, marked_1.marked)(errorMessage), { exit: 2 });
67
+ throw new error_1.FirebaseError(await (0, marked_1.marked)(errorMessage), { exit: 2 });
68
68
  }
69
69
  }
70
70
  function getUsedProducts(spec) {
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.inferUpdateSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
4
4
  const clc = require("colorette");
5
5
  const semver = require("semver");
6
- const marked_1 = require("marked");
7
6
  const error_1 = require("../error");
8
7
  const logger_1 = require("../logger");
9
8
  const extensionsApi = require("./extensionsApi");
@@ -47,7 +46,7 @@ function warningUpdateToOtherSource(sourceOrigin) {
47
46
  targetText = "URL";
48
47
  }
49
48
  const warning = `All the instance's resources and logic will be overwritten to use the source code and files from the ${targetText}.\n`;
50
- logger_1.logger.info((0, marked_1.marked)(warning));
49
+ logger_1.logger.info(warning);
51
50
  }
52
51
  exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
53
52
  async function update(updateOptions) {
@@ -2,11 +2,6 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.outOfBandChangesWarning = exports.displayWarningsForDeploy = void 0;
4
4
  const clc = require("colorette");
5
- const TerminalRenderer = require("marked-terminal");
6
- const marked_1 = require("marked");
7
- marked_1.marked.setOptions({
8
- renderer: new TerminalRenderer(),
9
- });
10
5
  const extensionsHelper_1 = require("./extensionsHelper");
11
6
  const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
12
7
  const planner_1 = require("../deploy/extensions/planner");
@@ -29,9 +24,9 @@ async function displayWarningsForDeploy(instancesToCreate) {
29
24
  const unpublishedExtensions = uploadedExtensionInstances.filter((i) => { var _a, _b; return ((_b = (_a = i.extensionVersion) === null || _a === void 0 ? void 0 : _a.listing) === null || _b === void 0 ? void 0 : _b.state) !== "APPROVED"; });
30
25
  if (unpublishedExtensions.length) {
31
26
  const humanReadableList = unpublishedExtensions.map(toListEntry).join("\n");
32
- utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
27
+ utils.logLabeledBullet(extensionsHelper_1.logPrefix, `The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
33
28
  "Unpublished extensions have not been reviewed by " +
34
- "Firebase. Please make sure you trust the extension publisher before installing this extension.", { gfm: false }));
29
+ "Firebase. Please make sure you trust the extension publisher before installing this extension.");
35
30
  }
36
31
  return unpublishedExtensions.length > 0;
37
32
  }
@@ -420,15 +420,16 @@ class FirestoreApi {
420
420
  }
421
421
  return database;
422
422
  }
423
- async createDatabase(project, databaseId, locationId, type, deleteProtectionState, pointInTimeRecoveryEnablement) {
424
- const url = `/projects/${project}/databases`;
423
+ async createDatabase(req) {
424
+ const url = `/projects/${req.project}/databases`;
425
425
  const payload = {
426
- type,
427
- locationId,
428
- deleteProtectionState,
429
- pointInTimeRecoveryEnablement,
426
+ locationId: req.locationId,
427
+ type: req.type,
428
+ deleteProtectionState: req.deleteProtectionState,
429
+ pointInTimeRecoveryEnablement: req.pointInTimeRecoveryEnablement,
430
+ cmekConfig: req.cmekConfig,
430
431
  };
431
- const options = { queryParams: { databaseId: databaseId } };
432
+ const options = { queryParams: { databaseId: req.databaseId } };
432
433
  const res = await this.apiClient.post(url, payload, options);
433
434
  const database = res.body.response;
434
435
  if (!database) {
@@ -33,13 +33,33 @@ class PrettyPrint {
33
33
  logger_1.logger.info(table.toString());
34
34
  }
35
35
  prettyPrintDatabase(database) {
36
+ let colValueWidth = Math.max(50, 5 + database.name.length);
37
+ if (database.cmekConfig) {
38
+ colValueWidth = Math.max(140, 20 + database.cmekConfig.kmsKeyName.length);
39
+ }
36
40
  const table = new Table({
37
41
  head: ["Field", "Value"],
38
- colWidths: [25, Math.max(50, 5 + database.name.length)],
42
+ colWidths: [30, colValueWidth],
39
43
  });
40
44
  table.push(["Name", clc.yellow(database.name)], ["Create Time", clc.yellow(database.createTime)], ["Last Update Time", clc.yellow(database.updateTime)], ["Type", clc.yellow(database.type)], ["Location", clc.yellow(database.locationId)], ["Delete Protection State", clc.yellow(database.deleteProtectionState)], ["Point In Time Recovery", clc.yellow(database.pointInTimeRecoveryEnablement)], ["Earliest Version Time", clc.yellow(database.earliestVersionTime)], ["Version Retention Period", clc.yellow(database.versionRetentionPeriod)]);
45
+ if (database.cmekConfig) {
46
+ table.push(["KMS Key Name", clc.yellow(database.cmekConfig.kmsKeyName)]);
47
+ if (database.cmekConfig.activeKeyVersion) {
48
+ table.push([
49
+ "Active Key Versions",
50
+ clc.yellow(this.prettyStringArray(database.cmekConfig.activeKeyVersion)),
51
+ ]);
52
+ }
53
+ }
41
54
  logger_1.logger.info(table.toString());
42
55
  }
56
+ prettyStringArray(stringArray) {
57
+ let result = "";
58
+ stringArray.forEach((str) => {
59
+ result += `${str}\n`;
60
+ });
61
+ return result;
62
+ }
43
63
  prettyPrintBackups(backups) {
44
64
  if (backups.length === 0) {
45
65
  logger_1.logger.info("No backups found.");
@@ -51,3 +51,11 @@ describe("firebaseConsoleDatabaseUrl", () => {
51
51
  (0, chai_1.expect)(printer.firebaseConsoleDatabaseUrl("example-project", "(default)")).to.equal("https://console.firebase.google.com/project/example-project/firestore/databases/-default-/data");
52
52
  });
53
53
  });
54
+ describe("prettyStringArray", () => {
55
+ it("should correctly print an array of strings", () => {
56
+ (0, chai_1.expect)(printer.prettyStringArray(["kms-key-1", "kms-key-2"])).to.equal("kms-key-1\nkms-key-2\n");
57
+ });
58
+ it("should print nothing if the array is empty", () => {
59
+ (0, chai_1.expect)(printer.prettyStringArray([])).to.equal("");
60
+ });
61
+ });
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.doSetup = void 0;
3
+ exports.actuate = exports.doSetup = void 0;
4
4
  const path_1 = require("path");
5
5
  const clc = require("colorette");
6
6
  const prompt_1 = require("../../../prompt");
@@ -20,7 +20,7 @@ const SCHEMA_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/sche
20
20
  const QUERIES_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/queries.gql");
21
21
  const MUTATIONS_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/mutations.gql");
22
22
  const defaultConnector = {
23
- id: "default-connector",
23
+ id: "default",
24
24
  files: [
25
25
  {
26
26
  path: "queries.gql",
@@ -33,6 +33,13 @@ const defaultConnector = {
33
33
  ],
34
34
  };
35
35
  async function doSetup(setup, config) {
36
+ const info = await askQuestions(setup, config);
37
+ await actuate(setup, config, info);
38
+ logger_1.logger.info("");
39
+ (0, utils_1.logSuccess)(`If you'd like to generate an SDK for your new connector, run ${clc.bold("firebase init dataconnect:sdk")}`);
40
+ }
41
+ exports.doSetup = doSetup;
42
+ async function askQuestions(setup, config) {
36
43
  var _a, _b, _c;
37
44
  let info = {
38
45
  serviceId: "",
@@ -43,6 +50,7 @@ async function doSetup(setup, config) {
43
50
  isNewDatabase: false,
44
51
  connectors: [defaultConnector],
45
52
  schemaGql: [],
53
+ shouldProvisionCSQL: false,
46
54
  };
47
55
  info = await promptForService(setup, info);
48
56
  if (info.cloudSqlInstanceId === "") {
@@ -59,13 +67,17 @@ async function doSetup(setup, config) {
59
67
  default: defaultConnectionString,
60
68
  });
61
69
  setup.rcfile.dataconnectEmulatorConfig = { postgres: { localConnectionString } };
62
- await writeFiles(config, info);
63
- if (setup.projectId &&
70
+ info.shouldProvisionCSQL = !!(setup.projectId &&
64
71
  (info.isNewInstance || info.isNewDatabase) &&
65
72
  (await (0, prompt_1.confirm)({
66
73
  message: "Would you like to provision your CloudSQL instance and database now? This will take a few minutes.",
67
74
  default: true,
68
- }))) {
75
+ })));
76
+ return info;
77
+ }
78
+ async function actuate(setup, config, info) {
79
+ await writeFiles(config, info);
80
+ if (setup.projectId && info.shouldProvisionCSQL) {
69
81
  await (0, provisionCloudSql_1.provisionCloudSql)({
70
82
  projectId: setup.projectId,
71
83
  locationId: info.locationId,
@@ -75,12 +87,11 @@ async function doSetup(setup, config) {
75
87
  waitForCreation: false,
76
88
  });
77
89
  }
78
- logger_1.logger.info("");
79
- (0, utils_1.logSuccess)(`If you'd like to generate an SDK for your new connector, run ${clc.bold("firebase init dataconnect:sdk")}`);
80
90
  }
81
- exports.doSetup = doSetup;
91
+ exports.actuate = actuate;
82
92
  async function writeFiles(config, info) {
83
93
  const dir = config.get("dataconnect.source") || "dataconnect";
94
+ console.log(dir);
84
95
  const subbedDataconnectYaml = subDataconnectYamlValues(Object.assign(Object.assign({}, info), { connectorIds: info.connectors.map((c) => `"./${c.id}"`).join(", ") }));
85
96
  config.set("dataconnect", { source: dir });
86
97
  await config.askWriteProjectFile((0, path_1.join)(dir, "dataconnect.yaml"), subbedDataconnectYaml);
@@ -10,6 +10,7 @@ const load_1 = require("../../../dataconnect/load");
10
10
  const logger_1 = require("../../../logger");
11
11
  const dataconnectEmulator_1 = require("../../../emulator/dataconnectEmulator");
12
12
  const error_1 = require("../../../error");
13
+ const lodash_1 = require("lodash");
13
14
  const IOS = "ios";
14
15
  const WEB = "web";
15
16
  const ANDROID = "android";
@@ -40,15 +41,21 @@ async function askQuestions(setup, config) {
40
41
  type: "list",
41
42
  choices: connectorChoices,
42
43
  });
43
- const platforms = await (0, prompt_1.promptOnce)({
44
- message: "Which platforms do you want to set up a generated SDK for?",
45
- type: "checkbox",
46
- choices: [
47
- { name: "iOS (Swift)", value: IOS },
48
- { name: "Web (JavaScript)", value: WEB },
49
- { name: "Androd (Kotlin)", value: ANDROID },
50
- ],
51
- });
44
+ let platforms = [];
45
+ while (!platforms.length) {
46
+ platforms = await (0, prompt_1.promptOnce)({
47
+ message: "Which platforms do you want to set up a generated SDK for?",
48
+ type: "checkbox",
49
+ choices: [
50
+ { name: "iOS (Swift)", value: IOS },
51
+ { name: "Web (JavaScript)", value: WEB },
52
+ { name: "Androd (Kotlin)", value: ANDROID },
53
+ ],
54
+ });
55
+ if (!platforms.length) {
56
+ logger_1.logger.info("You must pick at least one platform.");
57
+ }
58
+ }
52
59
  const newConnectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
53
60
  if (!newConnectorYaml.generate) {
54
61
  newConnectorYaml.generate = {};
@@ -58,9 +65,10 @@ async function askQuestions(setup, config) {
58
65
  message: `What directory do you want to write your Swift SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
59
66
  type: "input",
60
67
  default: ((_a = newConnectorYaml.generate.swiftSdk) === null || _a === void 0 ? void 0 : _a.outputDir) ||
61
- `./../.dataconnect/generated/${newConnectorYaml.connectorId}/swift-sdk`,
68
+ `./../gensdk/${newConnectorYaml.connectorId}/swift-sdk`,
62
69
  });
63
- const swiftSdk = { outputDir };
70
+ const pkg = (0, lodash_1.camelCase)(newConnectorYaml.connectorId);
71
+ const swiftSdk = { outputDir, package: pkg };
64
72
  newConnectorYaml.generate.swiftSdk = swiftSdk;
65
73
  }
66
74
  if (platforms.includes(WEB)) {
@@ -68,13 +76,9 @@ async function askQuestions(setup, config) {
68
76
  message: `What directory do you want to write your JavaScript SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
69
77
  type: "input",
70
78
  default: ((_b = newConnectorYaml.generate.javascriptSdk) === null || _b === void 0 ? void 0 : _b.outputDir) ||
71
- `./../.dataconnect/generated/${newConnectorYaml.connectorId}/javascript-sdk`,
72
- });
73
- const pkg = await (0, prompt_1.promptOnce)({
74
- message: "What package name do you want to use for your JavaScript SDK?",
75
- type: "input",
76
- default: (_d = (_c = newConnectorYaml.generate.javascriptSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`,
79
+ `./../gensdk/${newConnectorYaml.connectorId}/javascript-sdk`,
77
80
  });
81
+ const pkg = (_d = (_c = newConnectorYaml.generate.javascriptSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`;
78
82
  const packageJSONDir = await (0, prompt_1.promptOnce)({
79
83
  message: "Which directory contains the package.json that you would like to add the JavaScript SDK dependency to? (Leave blank to skip)",
80
84
  type: "input",
@@ -94,13 +98,9 @@ async function askQuestions(setup, config) {
94
98
  message: `What directory do you want to write your Kotlin SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
95
99
  type: "input",
96
100
  default: ((_f = newConnectorYaml.generate.kotlinSdk) === null || _f === void 0 ? void 0 : _f.outputDir) ||
97
- `./../.dataconnect/generated/${newConnectorYaml.connectorId}/kotlin-sdk/src/main/kotlin/${newConnectorYaml.connectorId}`,
98
- });
99
- const pkg = await (0, prompt_1.promptOnce)({
100
- message: "What package name do you want to use for your Kotlin SDK?",
101
- type: "input",
102
- default: (_h = (_g = newConnectorYaml.generate.kotlinSdk) === null || _g === void 0 ? void 0 : _g.package) !== null && _h !== void 0 ? _h : `com.google.firebase.dataconnect.connectors.${connectorInfo.connectorYaml.connectorId}`,
101
+ `./../gensdk/${newConnectorYaml.connectorId}/kotlin-sdk`,
103
102
  });
103
+ const pkg = (_h = (_g = newConnectorYaml.generate.kotlinSdk) === null || _g === void 0 ? void 0 : _g.package) !== null && _h !== void 0 ? _h : `connectors.${(0, lodash_1.snakeCase)(connectorInfo.connectorYaml.connectorId)}`;
104
104
  const kotlinSdk = {
105
105
  outputDir,
106
106
  package: pkg,
@@ -71,12 +71,13 @@ class RulesDeploy {
71
71
  if (await (0, resourceManager_1.serviceAccountHasRoles)(projectNumber, saEmail, [CROSS_SERVICE_RULES_ROLE], true)) {
72
72
  return;
73
73
  }
74
- const addRole = await (0, prompt_1.promptOnce)({
75
- type: "confirm",
76
- name: "rulesRole",
77
- message: `Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?`,
78
- default: true,
79
- }, this.options);
74
+ const addRole = this.options.force ||
75
+ (await (0, prompt_1.promptOnce)({
76
+ type: "confirm",
77
+ name: "rulesRole",
78
+ message: `Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?`,
79
+ default: true,
80
+ }, this.options));
80
81
  if (addRole) {
81
82
  await (0, resourceManager_1.addServiceAccountToRoles)(projectNumber, saEmail, [CROSS_SERVICE_RULES_ROLE], true);
82
83
  utils.logLabeledBullet(RulesetType[this.type], "updated service account for cross-service rules...");
@@ -118,12 +119,13 @@ class RulesDeploy {
118
119
  utils.logLabeledBullet(RulesetType[this.type], "quota exceeded error while uploading rules");
119
120
  const history = await gcp.rules.listAllRulesets(this.options.project);
120
121
  if (history.length > RULESET_COUNT_LIMIT) {
121
- const confirm = await (0, prompt_1.promptOnce)({
122
- type: "confirm",
123
- name: "force",
124
- message: `You have ${history.length} rules, do you want to delete the oldest ${RULESETS_TO_GC} to free up space?`,
125
- default: false,
126
- }, this.options);
122
+ const confirm = this.options.force ||
123
+ (await (0, prompt_1.promptOnce)({
124
+ type: "confirm",
125
+ name: "force",
126
+ message: `You have ${history.length} rules, do you want to delete the oldest ${RULESETS_TO_GC} to free up space?`,
127
+ default: false,
128
+ }, this.options));
127
129
  if (confirm) {
128
130
  const releases = await gcp.rules.listAllReleases(this.options.project);
129
131
  const unreleased = history.filter((ruleset) => {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "13.14.2",
3
+ "version": "13.15.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -94,8 +94,8 @@
94
94
  "leven": "^3.1.0",
95
95
  "libsodium-wrappers": "^0.7.10",
96
96
  "lodash": "^4.17.21",
97
- "marked": "^4.0.14",
98
- "marked-terminal": "^5.1.1",
97
+ "marked": "^13.0.2",
98
+ "marked-terminal": "^7.0.0",
99
99
  "mime": "^2.5.2",
100
100
  "minimatch": "^3.0.4",
101
101
  "morgan": "^1.10.0",
@@ -1,61 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.displayNode10CreateBillingNotice = exports.displayNode10UpdateBillingNotice = void 0;
4
- const marked_1 = require("marked");
5
- const TerminalRenderer = require("marked-terminal");
6
- const error_1 = require("../error");
7
- const extensionsHelper_1 = require("./extensionsHelper");
8
- const prompt_1 = require("../prompt");
9
- const utils = require("../utils");
10
- const utils_1 = require("./utils");
11
- marked_1.marked.setOptions({
12
- renderer: new TerminalRenderer(),
13
- });
14
- const urlPricingExamples = "https://cloud.google.com/functions/pricing#pricing_examples";
15
- const urlFAQ = "https://firebase.google.com/support/faq/#extensions-pricing";
16
- const billingMsgUpdate = "This update includes an upgrade to Node.js 10 from Node.js 8, which is no" +
17
- " longer maintained. Starting with this update, you will be charged a" +
18
- " small amount (typically around $0.01/month) for the Firebase resources" +
19
- " required by this extension (even if it is not used), in addition to any" +
20
- " charges associated with its usage.\n\n" +
21
- `See pricing examples: **[${urlPricingExamples}](${urlPricingExamples})**\n` +
22
- `See the FAQ: **[${urlFAQ}](${urlFAQ})**\n`;
23
- const billingMsgCreate = "You will be charged around $0.01/month for the Firebase resources" +
24
- " required by this extension (even if it is not used). Additionally," +
25
- " using this extension will contribute to your project's overall usage" +
26
- " level of Firebase services. However, you'll only be charged for usage" +
27
- " that exceeds Firebase's free tier for those services.\n\n" +
28
- `See pricing examples: **[${urlPricingExamples}](${urlPricingExamples})**\n` +
29
- `See the FAQ: **[${urlFAQ}](${urlFAQ})**\n`;
30
- const defaultSpecVersion = "v1beta";
31
- const defaultRuntimes = {
32
- v1beta: "nodejs8",
33
- };
34
- function hasRuntime(spec, runtime) {
35
- const specVersion = spec.specVersion || defaultSpecVersion;
36
- const defaultRuntime = defaultRuntimes[specVersion];
37
- const resources = spec.resources || [];
38
- return resources.some((r) => runtime === ((0, utils_1.getResourceRuntime)(r) || defaultRuntime));
39
- }
40
- function displayNode10UpdateBillingNotice(curSpec, newSpec) {
41
- if (hasRuntime(curSpec, "nodejs8") && hasRuntime(newSpec, "nodejs10")) {
42
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgUpdate));
43
- }
44
- }
45
- exports.displayNode10UpdateBillingNotice = displayNode10UpdateBillingNotice;
46
- async function displayNode10CreateBillingNotice(spec, prompt) {
47
- if (hasRuntime(spec, "nodejs10")) {
48
- utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgCreate));
49
- if (prompt) {
50
- const continueUpdate = await (0, prompt_1.promptOnce)({
51
- type: "confirm",
52
- message: "Do you wish to continue?",
53
- default: true,
54
- });
55
- if (!continueUpdate) {
56
- throw new error_1.FirebaseError(`Cancelled.`, { exit: 2 });
57
- }
58
- }
59
- }
60
- }
61
- exports.displayNode10CreateBillingNotice = displayNode10CreateBillingNotice;