firebase-tools 14.0.1 → 14.2.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 (33) hide show
  1. package/lib/commands/apphosting-backends-create.js +2 -0
  2. package/lib/commands/apphosting-backends-delete.js +2 -0
  3. package/lib/commands/apphosting-backends-get.js +2 -0
  4. package/lib/commands/apphosting-backends-list.js +2 -0
  5. package/lib/commands/apphosting-builds-create.js +2 -0
  6. package/lib/commands/apphosting-builds-get.js +2 -0
  7. package/lib/commands/apphosting-rollouts-create.js +2 -0
  8. package/lib/commands/apphosting-rollouts-list.js +2 -0
  9. package/lib/commands/dataconnect-sql-grant.js +2 -2
  10. package/lib/commands/dataconnect-sql-setup.js +3 -3
  11. package/lib/dataconnect/freeTrial.js +9 -3
  12. package/lib/dataconnect/provisionCloudSql.js +24 -25
  13. package/lib/dataconnect/schemaMigration.js +11 -11
  14. package/lib/deploy/dataconnect/deploy.js +1 -3
  15. package/lib/deploy/dataconnect/prepare.js +1 -3
  16. package/lib/deploy/functions/release/index.js +2 -2
  17. package/lib/emulator/apphosting/serve.js +10 -2
  18. package/lib/emulator/dataconnectEmulator.js +1 -1
  19. package/lib/emulator/downloadableEmulators.js +9 -9
  20. package/lib/emulator/env.js +4 -3
  21. package/lib/emulator/extensionsEmulator.js +3 -1
  22. package/lib/emulator/functionsEmulator.js +2 -2
  23. package/lib/extensions/emulator/triggerHelper.js +5 -0
  24. package/lib/extensions/paramHelper.js +10 -1
  25. package/lib/functions/artifacts.js +1 -0
  26. package/lib/gcp/artifactregistry.js +1 -1
  27. package/lib/gcp/cloudsql/cloudsqladmin.js +10 -10
  28. package/lib/gcp/cloudsql/{permissions_setup.js → permissionsSetup.js} +15 -9
  29. package/lib/init/features/dataconnect/index.js +8 -6
  30. package/lib/init/features/dataconnect/sdk.js +1 -1
  31. package/lib/track.js +2 -2
  32. package/package.json +1 -1
  33. package/templates/init/functions/python/_gitignore +6 -1
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
+ const requireAuth_1 = require("../requireAuth");
6
7
  const requireInteractive_1 = require("../requireInteractive");
7
8
  const backend_1 = require("../apphosting/backend");
8
9
  const apphosting_1 = require("../gcp/apphosting");
@@ -12,6 +13,7 @@ exports.command = new command_1.Command("apphosting:backends:create")
12
13
  .description("create a Firebase App Hosting backend")
13
14
  .option("-a, --app <webAppId>", "specify an existing Firebase web app's ID to associate your App Hosting backend with")
14
15
  .option("-s, --service-account <serviceAccount>", "specify the service account used to run the server", "")
16
+ .before(requireAuth_1.requireAuth)
15
17
  .before(apphosting_1.ensureApiEnabled)
16
18
  .before(requireInteractive_1.default)
17
19
  .before((0, requireTosAcceptance_1.requireTosAcceptance)(firedata_1.APPHOSTING_TOS_ID))
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
+ const requireAuth_1 = require("../requireAuth");
6
7
  const error_1 = require("../error");
7
8
  const prompt_1 = require("../prompt");
8
9
  const utils = require("../utils");
@@ -13,6 +14,7 @@ const ora = require("ora");
13
14
  exports.command = new command_1.Command("apphosting:backends:delete <backend>")
14
15
  .description("delete a Firebase App Hosting backend")
15
16
  .withForce()
17
+ .before(requireAuth_1.requireAuth)
16
18
  .before(apphosting.ensureApiEnabled)
17
19
  .action(async (backendId, options) => {
18
20
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -3,12 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
4
  const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
+ const requireAuth_1 = require("../requireAuth");
6
7
  const error_1 = require("../error");
7
8
  const utils_1 = require("../utils");
8
9
  const apphosting = require("../gcp/apphosting");
9
10
  const apphosting_backends_list_1 = require("./apphosting-backends-list");
10
11
  exports.command = new command_1.Command("apphosting:backends:get <backend>")
11
12
  .description("print info about a Firebase App Hosting backend")
13
+ .before(requireAuth_1.requireAuth)
12
14
  .before(apphosting.ensureApiEnabled)
13
15
  .action(async (backend, options) => {
14
16
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -6,11 +6,13 @@ const utils_1 = require("../utils");
6
6
  const error_1 = require("../error");
7
7
  const logger_1 = require("../logger");
8
8
  const projectUtils_1 = require("../projectUtils");
9
+ const requireAuth_1 = require("../requireAuth");
9
10
  const apphosting = require("../gcp/apphosting");
10
11
  const Table = require("cli-table3");
11
12
  const TABLE_HEAD = ["Backend", "Repository", "URL", "Primary Region", "Updated Date"];
12
13
  exports.command = new command_1.Command("apphosting:backends:list")
13
14
  .description("list Firebase App Hosting backends")
15
+ .before(requireAuth_1.requireAuth)
14
16
  .before(apphosting.ensureApiEnabled)
15
17
  .action(async (options) => {
16
18
  var _a;
@@ -5,12 +5,14 @@ const apphosting = require("../gcp/apphosting");
5
5
  const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
+ const requireAuth_1 = require("../requireAuth");
8
9
  const utils_1 = require("../utils");
9
10
  exports.command = new command_1.Command("apphosting:builds:create <backendId>")
10
11
  .description("create a build for an App Hosting backend")
11
12
  .option("-l, --location <location>", "specify the region of the backend")
12
13
  .option("-i, --id <buildId>", "id of the build (defaults to autogenerating a random id)", "")
13
14
  .option("-b, --branch <branch>", "repository branch to deploy (defaults to 'main')", "main")
15
+ .before(requireAuth_1.requireAuth)
14
16
  .before(apphosting.ensureApiEnabled)
15
17
  .action(async (backendId, options) => {
16
18
  var _a, _b;
@@ -5,10 +5,12 @@ const apphosting = require("../gcp/apphosting");
5
5
  const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
+ const requireAuth_1 = require("../requireAuth");
8
9
  const utils_1 = require("../utils");
9
10
  exports.command = new command_1.Command("apphosting:builds:get <backendId> <buildId>")
10
11
  .description("get a build for an App Hosting backend")
11
12
  .option("-l, --location <location>", "specify the region of the backend")
13
+ .before(requireAuth_1.requireAuth)
12
14
  .before(apphosting.ensureApiEnabled)
13
15
  .action(async (backendId, buildId, options) => {
14
16
  var _a;
@@ -4,6 +4,7 @@ exports.command = void 0;
4
4
  const apphosting = require("../gcp/apphosting");
5
5
  const command_1 = require("../command");
6
6
  const projectUtils_1 = require("../projectUtils");
7
+ const requireAuth_1 = require("../requireAuth");
7
8
  const error_1 = require("../error");
8
9
  const rollout_1 = require("../apphosting/rollout");
9
10
  exports.command = new command_1.Command("apphosting:rollouts:create <backendId>")
@@ -11,6 +12,7 @@ exports.command = new command_1.Command("apphosting:rollouts:create <backendId>"
11
12
  .option("-b, --git-branch <gitBranch>", "repository branch to deploy (mutually exclusive with -g)")
12
13
  .option("-g, --git-commit <gitCommit>", "git commit to deploy (mutually exclusive with -b)")
13
14
  .withForce("Skip confirmation before creating rollout")
15
+ .before(requireAuth_1.requireAuth)
14
16
  .before(apphosting.ensureApiEnabled)
15
17
  .action(async (backendId, options) => {
16
18
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -5,10 +5,12 @@ const apphosting = require("../gcp/apphosting");
5
5
  const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
+ const requireAuth_1 = require("../requireAuth");
8
9
  const utils_1 = require("../utils");
9
10
  exports.command = new command_1.Command("apphosting:rollouts:list <backendId>")
10
11
  .description("list rollouts of an App Hosting backend")
11
12
  .option("-l, --location <location>", "region of the rollouts (defaults to listing rollouts from all regions)")
13
+ .before(requireAuth_1.requireAuth)
12
14
  .before(apphosting.ensureApiEnabled)
13
15
  .action(async (backendId, options) => {
14
16
  var _a;
@@ -9,8 +9,8 @@ const fileUtils_1 = require("../dataconnect/fileUtils");
9
9
  const schemaMigration_1 = require("../dataconnect/schemaMigration");
10
10
  const requireAuth_1 = require("../requireAuth");
11
11
  const error_1 = require("../error");
12
- const permissions_setup_1 = require("../gcp/cloudsql/permissions_setup");
13
- const allowedRoles = Object.keys(permissions_setup_1.fdcSqlRoleMap);
12
+ const permissionsSetup_1 = require("../gcp/cloudsql/permissionsSetup");
13
+ const allowedRoles = Object.keys(permissionsSetup_1.fdcSqlRoleMap);
14
14
  exports.command = new command_1.Command("dataconnect:sql:grant [serviceId]")
15
15
  .description("grants the SQL role <role> to the provided user or service account <email>")
16
16
  .option("-R, --role <role>", "The SQL role to grant. One of: owner, writer, or reader.")
@@ -8,7 +8,7 @@ const error_1 = require("../error");
8
8
  const requireAuth_1 = require("../requireAuth");
9
9
  const requirePermissions_1 = require("../requirePermissions");
10
10
  const ensureApis_1 = require("../dataconnect/ensureApis");
11
- const permissions_setup_1 = require("../gcp/cloudsql/permissions_setup");
11
+ const permissionsSetup_1 = require("../gcp/cloudsql/permissionsSetup");
12
12
  const permissions_1 = require("../gcp/cloudsql/permissions");
13
13
  const schemaMigration_1 = require("../dataconnect/schemaMigration");
14
14
  const connect_1 = require("../gcp/cloudsql/connect");
@@ -35,6 +35,6 @@ exports.command = new command_1.Command("dataconnect:sql:setup [serviceId]")
35
35
  await (0, schemaMigration_1.ensureServiceIsConnectedToCloudSql)(serviceName, instanceName, databaseId, true);
36
36
  const { user, mode } = await (0, connect_1.getIAMUser)(options);
37
37
  await cloudSqlAdminClient.createUser(projectId, instanceId, mode, user);
38
- const schemaInfo = await (0, permissions_setup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
39
- await (0, permissions_setup_1.setupSQLPermissions)(instanceId, databaseId, schemaInfo, options);
38
+ const schemaInfo = await (0, permissionsSetup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
39
+ await (0, permissionsSetup_1.setupSQLPermissions)(instanceId, databaseId, schemaInfo, options);
40
40
  });
@@ -1,16 +1,17 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.upgradeInstructions = exports.printFreeTrialUnavailable = exports.isFreeTrialError = exports.getFreeTrialInstanceId = exports.checkFreeTrialInstanceUsed = exports.freeTrialTermsLink = void 0;
4
+ const clc = require("colorette");
4
5
  const cloudmonitoring_1 = require("../gcp/cloudmonitoring");
5
6
  const cloudsqladmin_1 = require("../gcp/cloudsql/cloudsqladmin");
6
7
  const utils = require("../utils");
7
- const clc = require("colorette");
8
8
  function freeTrialTermsLink() {
9
9
  return "https://firebase.google.com/pricing";
10
10
  }
11
11
  exports.freeTrialTermsLink = freeTrialTermsLink;
12
12
  const FREE_TRIAL_METRIC = "sqladmin.googleapis.com/fdc_lifetime_free_trial_per_project";
13
13
  async function checkFreeTrialInstanceUsed(projectId) {
14
+ utils.logLabeledBullet("dataconnect", "Checking Cloud SQL no cost trial eligibility...");
14
15
  const past7d = new Date();
15
16
  past7d.setDate(past7d.getDate() - 7);
16
17
  const query = {
@@ -20,12 +21,17 @@ async function checkFreeTrialInstanceUsed(projectId) {
20
21
  };
21
22
  try {
22
23
  const ts = await (0, cloudmonitoring_1.queryTimeSeries)(query, projectId);
24
+ let used = true;
23
25
  if (ts.length) {
24
- return ts[0].points.some((p) => p.value.int64Value);
26
+ used = ts[0].points.some((p) => p.value.int64Value);
27
+ }
28
+ if (used) {
29
+ utils.logLabeledWarning("dataconnect", "CloudSQL no cost trial has already been used on this project.");
25
30
  }
26
- return true;
31
+ return used;
27
32
  }
28
33
  catch (err) {
34
+ utils.logLabeledSuccess("dataconnect", "CloudSQL no cost trial available!");
29
35
  return false;
30
36
  }
31
37
  }
@@ -8,10 +8,9 @@ const utils_1 = require("../utils");
8
8
  const logger_1 = require("../logger");
9
9
  const GOOGLE_ML_INTEGRATION_ROLE = "roles/aiplatform.user";
10
10
  const freeTrial_1 = require("./freeTrial");
11
- const error_1 = require("../error");
12
11
  async function provisionCloudSql(args) {
13
12
  let connectionName = "";
14
- const { projectId, locationId, instanceId, databaseId, configYamlPath, enableGoogleMlIntegration, waitForCreation, silent, dryRun, } = args;
13
+ const { projectId, location, instanceId, databaseId, enableGoogleMlIntegration, waitForCreation, silent, dryRun, } = args;
15
14
  try {
16
15
  const existingInstance = await cloudSqlAdminClient.getInstance(projectId, instanceId);
17
16
  silent || utils.logLabeledBullet("dataconnect", `Found existing instance ${instanceId}.`);
@@ -35,31 +34,31 @@ async function provisionCloudSql(args) {
35
34
  }
36
35
  cmekWarning();
37
36
  const cta = dryRun ? "It will be created on your next deploy" : "Creating it now.";
37
+ const freeTrialUsed = await (0, freeTrial_1.checkFreeTrialInstanceUsed)(projectId);
38
38
  silent ||
39
- utils.logLabeledBullet("dataconnect", `CloudSQL instance '${instanceId}' not found.` +
40
- cta +
41
- `\nThis instance is provided under the terms of the Data Connect no-cost trial ${(0, freeTrial_1.freeTrialTermsLink)()}` +
42
- `\nMonitor the progress at ${cloudSqlAdminClient.instanceConsoleLink(projectId, instanceId)}`);
39
+ utils.logLabeledBullet("dataconnect", `CloudSQL instance '${instanceId}' not found.` + cta + freeTrialUsed
40
+ ? ""
41
+ : `\nThis instance is provided under the terms of the Data Connect no-cost trial ${(0, freeTrial_1.freeTrialTermsLink)()}` +
42
+ dryRun
43
+ ? `\nMonitor the progress at ${cloudSqlAdminClient.instanceConsoleLink(projectId, instanceId)}`
44
+ : "");
43
45
  if (!dryRun) {
44
- try {
45
- const newInstance = await (0, utils_1.promiseWithSpinner)(() => cloudSqlAdminClient.createInstance(projectId, locationId, instanceId, enableGoogleMlIntegration, waitForCreation), "Creating your instance...");
46
- if (newInstance) {
47
- silent || utils.logLabeledBullet("dataconnect", "Instance created");
48
- connectionName = (newInstance === null || newInstance === void 0 ? void 0 : newInstance.connectionName) || "";
49
- }
50
- else {
51
- silent ||
52
- utils.logLabeledBullet("dataconnect", "Cloud SQL instance creation started - it should be ready shortly. Database and users will be created on your next deploy.");
53
- return connectionName;
54
- }
46
+ const newInstance = await (0, utils_1.promiseWithSpinner)(() => cloudSqlAdminClient.createInstance({
47
+ projectId,
48
+ location,
49
+ instanceId,
50
+ enableGoogleMlIntegration,
51
+ waitForCreation,
52
+ freeTrial: !freeTrialUsed,
53
+ }), "Creating your instance...");
54
+ if (newInstance) {
55
+ silent || utils.logLabeledBullet("dataconnect", "Instance created");
56
+ connectionName = (newInstance === null || newInstance === void 0 ? void 0 : newInstance.connectionName) || "";
55
57
  }
56
- catch (err) {
57
- if (await (0, freeTrial_1.isFreeTrialError)(err, projectId)) {
58
- const freeTrialInstanceId = await (0, freeTrial_1.getFreeTrialInstanceId)(projectId);
59
- (0, freeTrial_1.printFreeTrialUnavailable)(projectId, configYamlPath, freeTrialInstanceId);
60
- throw new error_1.FirebaseError("No-cost Cloud SQL trial has already been used on this project.");
61
- }
62
- throw err;
58
+ else {
59
+ silent ||
60
+ utils.logLabeledBullet("dataconnect", "Cloud SQL instance creation started - it should be ready shortly. Database and users will be created on your next deploy.");
61
+ return connectionName;
63
62
  }
64
63
  }
65
64
  }
@@ -114,7 +113,7 @@ function getUpdateReason(instance, requireGoogleMlIntegration) {
114
113
  }
115
114
  exports.getUpdateReason = getUpdateReason;
116
115
  function cmekWarning() {
117
- const message = "The no-cost Cloud SQL trial instance does not support customer managed encryption keys.\n" +
116
+ const message = "Cloud SQL instances created via the Firebase CLI do not support customer managed encryption keys.\n" +
118
117
  "If you'd like to use a CMEK to encrypt your data, first create a CMEK encrypted instance (https://cloud.google.com/sql/docs/postgres/configure-cmek#createcmekinstance).\n" +
119
118
  "Then, edit your `dataconnect.yaml` file to use the encrypted instance and redeploy.";
120
119
  utils.logLabeledWarning("dataconnect", message);
@@ -7,7 +7,7 @@ const types_1 = require("./types");
7
7
  const client_1 = require("./client");
8
8
  const connect_1 = require("../gcp/cloudsql/connect");
9
9
  const projectUtils_1 = require("../projectUtils");
10
- const permissions_setup_1 = require("../gcp/cloudsql/permissions_setup");
10
+ const permissionsSetup_1 = require("../gcp/cloudsql/permissionsSetup");
11
11
  const permissions_1 = require("../gcp/cloudsql/permissions");
12
12
  const prompt_1 = require("../prompt");
13
13
  const logger_1 = require("../logger");
@@ -18,13 +18,13 @@ const cloudSqlAdminClient = require("../gcp/cloudsql/cloudsqladmin");
18
18
  const errors = require("./errors");
19
19
  async function setupSchemaIfNecessary(instanceId, databaseId, options) {
20
20
  await (0, connect_1.setupIAMUsers)(instanceId, databaseId, options);
21
- const schemaInfo = await (0, permissions_setup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
22
- if (schemaInfo.setupStatus !== permissions_setup_1.SchemaSetupStatus.BrownField &&
23
- schemaInfo.setupStatus !== permissions_setup_1.SchemaSetupStatus.GreenField) {
24
- return await (0, permissions_setup_1.setupSQLPermissions)(instanceId, databaseId, schemaInfo, options, true);
21
+ const schemaInfo = await (0, permissionsSetup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
22
+ if (schemaInfo.setupStatus !== permissionsSetup_1.SchemaSetupStatus.BrownField &&
23
+ schemaInfo.setupStatus !== permissionsSetup_1.SchemaSetupStatus.GreenField) {
24
+ return await (0, permissionsSetup_1.setupSQLPermissions)(instanceId, databaseId, schemaInfo, options, true);
25
25
  }
26
26
  else {
27
- logger_1.logger.info(`Detected schema "${schemaInfo.name}" is setup in ${schemaInfo.setupStatus} mode. Skipping Setup.`);
27
+ logger_1.logger.debug(`Detected schema "${schemaInfo.name}" is setup in ${schemaInfo.setupStatus} mode. Skipping Setup.`);
28
28
  }
29
29
  return schemaInfo.setupStatus;
30
30
  }
@@ -173,14 +173,14 @@ async function grantRoleToUserInSchema(options, schema) {
173
173
  const { instanceId, databaseId } = getIdentifiers(schema);
174
174
  const projectId = (0, projectUtils_1.needProjectId)(options);
175
175
  const { user, mode } = (0, connect_1.toDatabaseUser)(email);
176
- const fdcSqlRole = permissions_setup_1.fdcSqlRoleMap[role](databaseId);
176
+ const fdcSqlRole = permissionsSetup_1.fdcSqlRoleMap[role](databaseId);
177
177
  await (0, connect_1.setupIAMUsers)(instanceId, databaseId, options);
178
178
  const userIsCSQLAdmin = await (0, cloudsqladmin_1.iamUserIsCSQLAdmin)(options);
179
179
  if (!userIsCSQLAdmin) {
180
180
  throw new error_1.FirebaseError(`Only users with 'roles/cloudsql.admin' can grant SQL roles. If you do not have this role, ask your database administrator to run this command or manually grant ${fdcSqlRole} to ${user}`);
181
181
  }
182
182
  const schemaSetupStatus = await setupSchemaIfNecessary(instanceId, databaseId, options);
183
- if (schemaSetupStatus !== permissions_setup_1.SchemaSetupStatus.GreenField &&
183
+ if (schemaSetupStatus !== permissionsSetup_1.SchemaSetupStatus.GreenField &&
184
184
  fdcSqlRole === (0, permissions_1.firebaseowner)(databaseId, permissions_1.DEFAULT_SCHEMA)) {
185
185
  throw new error_1.FirebaseError(`Owner rule isn't available in brownfield databases. If you would like Data Connect to manage and own your database schema, run 'firebase dataconnect:sql:setup'`);
186
186
  }
@@ -260,13 +260,13 @@ async function handleIncompatibleSchemaError(args) {
260
260
  Please ask a user with 'roles/cloudsql.admin' to apply the following commands.\n
261
261
  ${commandsToExecuteBySuperUser.join("\n")}`);
262
262
  }
263
- const schemaInfo = await (0, permissions_setup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
264
- if (schemaInfo.setupStatus !== permissions_setup_1.SchemaSetupStatus.GreenField) {
263
+ const schemaInfo = await (0, permissionsSetup_1.getSchemaMetadata)(instanceId, databaseId, permissions_1.DEFAULT_SCHEMA, options);
264
+ if (schemaInfo.setupStatus !== permissionsSetup_1.SchemaSetupStatus.GreenField) {
265
265
  throw new error_1.FirebaseError(`Brownfield database are protected from SQL changes by Data Connect.\n` +
266
266
  `You can use the SQL diff generated by 'firebase dataconnect:sql:diff' to assist you in applying the required changes to your CloudSQL database. Connector deployment will succeed when there is no required diff changes.\n` +
267
267
  `If you would like Data Connect to manage your database schema, run 'firebase dataconnect:sql:setup'`);
268
268
  }
269
- if (!(await (0, permissions_setup_1.checkSQLRoleIsGranted)(options, instanceId, databaseId, (0, permissions_1.firebaseowner)(databaseId), (await (0, connect_1.getIAMUser)(options)).user))) {
269
+ if (!(await (0, permissionsSetup_1.checkSQLRoleIsGranted)(options, instanceId, databaseId, (0, permissions_1.firebaseowner)(databaseId), (await (0, connect_1.getIAMUser)(options)).user))) {
270
270
  throw new error_1.FirebaseError(`Command aborted. Only users granted firebaseowner SQL role can run migrations.`);
271
271
  }
272
272
  if (commandsToExecuteBySuperUser.length) {
@@ -8,7 +8,6 @@ const provisionCloudSql_1 = require("../../dataconnect/provisionCloudSql");
8
8
  const names_1 = require("../../dataconnect/names");
9
9
  const api_1 = require("../../api");
10
10
  const ensureApiEnabled = require("../../ensureApiEnabled");
11
- const node_path_1 = require("node:path");
12
11
  const prompt_1 = require("../../prompt");
13
12
  async function default_1(context, options) {
14
13
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -64,10 +63,9 @@ async function default_1(context, options) {
64
63
  const enableGoogleMlIntegration = (0, types_1.requiresVector)(s.deploymentMetadata);
65
64
  return (0, provisionCloudSql_1.provisionCloudSql)({
66
65
  projectId,
67
- locationId: (0, names_1.parseServiceName)(s.serviceName).location,
66
+ location: (0, names_1.parseServiceName)(s.serviceName).location,
68
67
  instanceId,
69
68
  databaseId,
70
- configYamlPath: (0, node_path_1.join)(s.sourceDirectory, "dataconnect.yaml"),
71
69
  enableGoogleMlIntegration,
72
70
  waitForCreation: true,
73
71
  });
@@ -17,7 +17,6 @@ const names_1 = require("../../dataconnect/names");
17
17
  const error_1 = require("../../error");
18
18
  const types_1 = require("../../dataconnect/types");
19
19
  const schemaMigration_1 = require("../../dataconnect/schemaMigration");
20
- const node_path_1 = require("node:path");
21
20
  const freeTrial_1 = require("../../dataconnect/freeTrial");
22
21
  async function default_1(context, options) {
23
22
  var _a;
@@ -73,10 +72,9 @@ async function default_1(context, options) {
73
72
  const enableGoogleMlIntegration = (0, types_1.requiresVector)(s.deploymentMetadata);
74
73
  return (0, provisionCloudSql_1.provisionCloudSql)({
75
74
  projectId,
76
- locationId: (0, names_1.parseServiceName)(s.serviceName).location,
75
+ location: (0, names_1.parseServiceName)(s.serviceName).location,
77
76
  instanceId,
78
77
  databaseId,
79
- configYamlPath: (0, node_path_1.join)(s.sourceDirectory, "dataconnect.yaml"),
80
78
  enableGoogleMlIntegration,
81
79
  waitForCreation: true,
82
80
  dryRun: options.dryRun,
@@ -123,8 +123,8 @@ async function setupArtifactCleanupPolicies(options, projectId, locations) {
123
123
  `${locationsWithErrors.join(", ")}.` +
124
124
  "This could result in a small monthly bill as container images accumulate over time.");
125
125
  throw new error_1.FirebaseError(`Functions successfully deployed but could not set up cleanup policy in ` +
126
- `${locationsWithErrors.length > 1 ? "regions" : "region"} ${locationsWithErrors.join(", ")}.` +
127
- `Pass the --force option to automatically set up a cleanup policy or` +
126
+ `${locationsWithErrors.length > 1 ? "regions" : "region"} ${locationsWithErrors.join(", ")}. ` +
127
+ `Pass the --force option to automatically set up a cleanup policy or ` +
128
128
  "run 'firebase functions:artifacts:setpolicy' to set up a cleanup policy to automatically delete old images.");
129
129
  }
130
130
  }
@@ -75,12 +75,20 @@ async function serve(projectId, port, startCommand, backendRelativeDir) {
75
75
  const environmentVariablesToInject = Object.assign(Object.assign(Object.assign({}, getEmulatorEnvs()), Object.fromEntries(await Promise.all(resolveEnv))), { PORT: port.toString() });
76
76
  if (startCommand) {
77
77
  developmentServer_2.logger.logLabeled("BULLET", types_1.Emulators.APPHOSTING, `running custom start command: '${startCommand}'`);
78
- await (0, spawn_1.spawnWithCommandString)(startCommand, backendRoot, environmentVariablesToInject);
78
+ (0, spawn_1.spawnWithCommandString)(startCommand, backendRoot, environmentVariablesToInject)
79
+ .catch((err) => {
80
+ developmentServer_2.logger.logLabeled("ERROR", types_1.Emulators.APPHOSTING, `failed to start Dev Server: ${err}`);
81
+ })
82
+ .then(() => developmentServer_2.logger.logLabeled("BULLET", types_1.Emulators.APPHOSTING, `Dev Server stopped`));
79
83
  return;
80
84
  }
81
85
  const detectedStartCommand = await (0, developmentServer_1.detectStartCommand)(backendRoot);
82
86
  developmentServer_2.logger.logLabeled("BULLET", types_1.Emulators.APPHOSTING, `starting app with: '${detectedStartCommand}'`);
83
- await (0, spawn_1.spawnWithCommandString)(detectedStartCommand, backendRoot, environmentVariablesToInject);
87
+ (0, spawn_1.spawnWithCommandString)(detectedStartCommand, backendRoot, environmentVariablesToInject)
88
+ .catch((err) => {
89
+ developmentServer_2.logger.logLabeled("ERROR", types_1.Emulators.APPHOSTING, `failed to start Dev Server: ${err}`);
90
+ })
91
+ .then(() => developmentServer_2.logger.logLabeled("BULLET", types_1.Emulators.APPHOSTING, `Dev Server stopped`));
84
92
  }
85
93
  function availablePort(host, port) {
86
94
  return (0, portUtils_1.checkListenable)({
@@ -246,7 +246,7 @@ class DataConnectEmulator {
246
246
  return false;
247
247
  }
248
248
  static async getEnv(account, extraEnv = {}) {
249
- const credsEnv = await (0, env_1.getCredentialsEnvironment)(account, emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT), "dataconnect");
249
+ const credsEnv = await (0, env_1.getCredentialsEnvironment)(account, emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT), "dataconnect", true);
250
250
  return Object.assign(Object.assign(Object.assign({}, process.env), extraEnv), credsEnv);
251
251
  }
252
252
  }
@@ -48,20 +48,20 @@ const EMULATOR_UPDATE_DETAILS = {
48
48
  },
49
49
  dataconnect: process.platform === "darwin"
50
50
  ? {
51
- version: "2.0.0",
52
- expectedSize: 26440448,
53
- expectedChecksum: "64fd9ad182e59a46b9462757db6d5aac",
51
+ version: "2.2.0",
52
+ expectedSize: 26538752,
53
+ expectedChecksum: "15304de22f04e51db155b1c76229e3f3",
54
54
  }
55
55
  : process.platform === "win32"
56
56
  ? {
57
- version: "2.0.0",
58
- expectedSize: 26884096,
59
- expectedChecksum: "92d654dfbb07fee4e1db2328ba6e00a7",
57
+ version: "2.2.0",
58
+ expectedSize: 26982912,
59
+ expectedChecksum: "a7677c4dfe78275eab7320b1ff777e9e",
60
60
  }
61
61
  : {
62
- version: "2.0.0",
63
- expectedSize: 26353816,
64
- expectedChecksum: "29c7a57a00cb11f44f9b0ffb4710bbd2",
62
+ version: "2.2.0",
63
+ expectedSize: 26452120,
64
+ expectedChecksum: "ef332cc135bc05e43121020e5c1fef09",
65
65
  },
66
66
  };
67
67
  exports.DownloadDetails = {
@@ -37,16 +37,17 @@ function setEnvVarsForEmulators(env, emulators) {
37
37
  break;
38
38
  case types_1.Emulators.DATACONNECT:
39
39
  env[constants_1.Constants.FIREBASE_DATACONNECT_EMULATOR_HOST] = `http://${host}`;
40
- env[constants_1.Constants.FIREBASE_DATACONNECT_ENV_ALT] = `http://${host}`;
40
+ env[constants_1.Constants.FIREBASE_DATACONNECT_ENV_ALT] = host;
41
41
  env["FIREBASE_DATACONNECT_EMULATOR_HOST"] = host;
42
42
  }
43
43
  }
44
44
  }
45
45
  exports.setEnvVarsForEmulators = setEnvVarsForEmulators;
46
- async function getCredentialsEnvironment(account, logger, logLabel) {
46
+ async function getCredentialsEnvironment(account, logger, logLabel, silent = false) {
47
47
  const credentialEnv = {};
48
48
  if (await (0, defaultCredentials_1.hasDefaultCredentials)()) {
49
- logger.logLabeled("WARN", logLabel, `Application Default Credentials detected. Non-emulated services will access production using these credentials. Be careful!`);
49
+ !silent &&
50
+ logger.logLabeled("WARN", logLabel, `Application Default Credentials detected. Non-emulated services will access production using these credentials. Be careful!`);
50
51
  }
51
52
  else if (account) {
52
53
  const defaultCredPath = await (0, defaultCredentials_1.getCredentialPathAsync)(account);
@@ -20,6 +20,7 @@ const validation_1 = require("./extensions/validation");
20
20
  const registry_1 = require("./registry");
21
21
  const types_1 = require("./types");
22
22
  const common_1 = require("../extensions/runtimes/common");
23
+ const paramHelper_1 = require("../extensions/paramHelper");
23
24
  class ExtensionsEmulator {
24
25
  constructor(args) {
25
26
  this.want = [];
@@ -170,7 +171,8 @@ class ExtensionsEmulator {
170
171
  async toEmulatableBackend(instance) {
171
172
  const extensionDir = await this.ensureSourceCode(instance);
172
173
  const functionsDir = path.join(extensionDir, "functions");
173
- const env = Object.assign(this.autoPopulatedParams(instance), instance.params);
174
+ const params = (0, paramHelper_1.populateDefaultParams)(instance.params, await planner.getExtensionSpec(instance));
175
+ const env = Object.assign(this.autoPopulatedParams(instance), params);
174
176
  const { extensionTriggers, runtime, nonSecretEnv, secretEnvVariables } = await (0, optionsHelper_1.getExtensionFunctionInfo)(instance, env);
175
177
  const emulatableBackend = {
176
178
  functionsDir,
@@ -663,11 +663,11 @@ class FunctionsEmulator {
663
663
  logger_1.logger.debug("Found a v2 firestore trigger.");
664
664
  const database = (_a = eventTrigger.eventFilters) === null || _a === void 0 ? void 0 : _a.database;
665
665
  if (!database) {
666
- throw new error_1.FirebaseError("A database must be supplied.");
666
+ throw new error_1.FirebaseError(`A database must be supplied for event trigger ${key}`);
667
667
  }
668
668
  const namespace = (_b = eventTrigger.eventFilters) === null || _b === void 0 ? void 0 : _b.namespace;
669
669
  if (!namespace) {
670
- throw new error_1.FirebaseError("A namespace must be supplied.");
670
+ throw new error_1.FirebaseError(`A namespace must be supplied for event trigger ${key}`);
671
671
  }
672
672
  let doc;
673
673
  let match;
@@ -16,6 +16,7 @@ const SUPPORTED_SYSTEM_PARAMS = {
16
16
  },
17
17
  };
18
18
  function functionResourceToEmulatedTriggerDefintion(resource, systemParams = {}) {
19
+ var _a, _b;
19
20
  const resourceType = resource.type;
20
21
  if (resource.type === types_2.FUNCTIONS_RESOURCE_TYPE) {
21
22
  const etd = {
@@ -91,6 +92,10 @@ function functionResourceToEmulatedTriggerDefintion(resource, systemParams = {})
91
92
  eventFilterPathPatterns[filter.attribute] = filter.value;
92
93
  }
93
94
  }
95
+ if (properties.eventTrigger.eventType.includes("google.cloud.firestore")) {
96
+ eventFilters["database"] = (_a = eventFilters["database"]) !== null && _a !== void 0 ? _a : "(default)";
97
+ eventFilters["namespace"] = (_b = eventFilters["namespace"]) !== null && _b !== void 0 ? _b : "(default)";
98
+ }
94
99
  etd.eventTrigger.eventFilters = eventFilters;
95
100
  etd.eventTrigger.eventFilterPathPatterns = eventFilterPathPatterns;
96
101
  }
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.isSystemParam = exports.readEnvFile = exports.promptForNewParams = exports.getParamsForUpdate = exports.getParams = exports.setNewDefaults = exports.buildBindingOptionsWithBaseValue = exports.getBaseParamBindings = void 0;
3
+ exports.populateDefaultParams = exports.isSystemParam = exports.readEnvFile = exports.promptForNewParams = exports.getParamsForUpdate = exports.getParams = exports.setNewDefaults = exports.buildBindingOptionsWithBaseValue = exports.getBaseParamBindings = void 0;
4
4
  const path = require("path");
5
5
  const clc = require("colorette");
6
6
  const fs = require("fs-extra");
@@ -138,3 +138,12 @@ function isSystemParam(paramName) {
138
138
  return regex.test(paramName);
139
139
  }
140
140
  exports.isSystemParam = isSystemParam;
141
+ function populateDefaultParams(params, spec) {
142
+ var _a;
143
+ const ret = Object.assign({}, params);
144
+ for (const p of spec.params) {
145
+ ret[p.param] = (_a = ret[p.param]) !== null && _a !== void 0 ? _a : p.default;
146
+ }
147
+ return ret;
148
+ }
149
+ exports.populateDefaultParams = populateDefaultParams;
@@ -93,6 +93,7 @@ async function setCleanupPolicy(repository, daysToKeep) {
93
93
  const update = {
94
94
  name: repository.name,
95
95
  cleanupPolicies: Object.assign(Object.assign({}, repository.cleanupPolicies), generateCleanupPolicy(daysToKeep)),
96
+ cleanupPolicyDryRun: false,
96
97
  labels,
97
98
  };
98
99
  await exports.updateRepository(update);
@@ -28,7 +28,7 @@ async function getRepository(repoPath) {
28
28
  }
29
29
  exports.getRepository = getRepository;
30
30
  async function updateRepository(repo) {
31
- const updateMask = proto.fieldMasks(repo, "cleanupPolicies", "labels");
31
+ const updateMask = proto.fieldMasks(repo, "cleanupPolicies", "cleanupPolicyDryRun", "labels");
32
32
  if (updateMask.length === 0) {
33
33
  const res = await client.get(repo.name);
34
34
  return res.body;
@@ -50,16 +50,16 @@ function instanceConsoleLink(projectId, instanceId) {
50
50
  return `https://console.cloud.google.com/sql/instances/${instanceId}/overview?project=${projectId}`;
51
51
  }
52
52
  exports.instanceConsoleLink = instanceConsoleLink;
53
- async function createInstance(projectId, location, instanceId, enableGoogleMlIntegration, waitForCreation) {
53
+ async function createInstance(args) {
54
54
  const databaseFlags = [{ name: "cloudsql.iam_authentication", value: "on" }];
55
- if (enableGoogleMlIntegration) {
55
+ if (args.enableGoogleMlIntegration) {
56
56
  databaseFlags.push({ name: "cloudsql.enable_google_ml_integration", value: "on" });
57
57
  }
58
58
  let op;
59
59
  try {
60
- op = await client.post(`projects/${projectId}/instances`, {
61
- name: instanceId,
62
- region: location,
60
+ op = await client.post(`projects/${args.projectId}/instances`, {
61
+ name: args.instanceId,
62
+ region: args.location,
63
63
  databaseVersion: "POSTGRES_15",
64
64
  settings: {
65
65
  tier: "db-f1-micro",
@@ -67,10 +67,10 @@ async function createInstance(projectId, location, instanceId, enableGoogleMlInt
67
67
  ipConfiguration: {
68
68
  authorizedNetworks: [],
69
69
  },
70
- enableGoogleMlIntegration,
70
+ enableGoogleMlIntegration: args.enableGoogleMlIntegration,
71
71
  databaseFlags,
72
72
  storageAutoResize: false,
73
- userLabels: { "firebase-data-connect": "ft" },
73
+ userLabels: { "firebase-data-connect": args.freeTrial ? "ft" : "nt" },
74
74
  insightsConfig: {
75
75
  queryInsightsEnabled: true,
76
76
  queryPlansPerMinute: 5,
@@ -80,13 +80,13 @@ async function createInstance(projectId, location, instanceId, enableGoogleMlInt
80
80
  });
81
81
  }
82
82
  catch (err) {
83
- handleAllowlistError(err, location);
83
+ handleAllowlistError(err, args.location);
84
84
  throw err;
85
85
  }
86
- if (!waitForCreation) {
86
+ if (!args.waitForCreation) {
87
87
  return;
88
88
  }
89
- const opName = `projects/${projectId}/operations/${op.body.name}`;
89
+ const opName = `projects/${args.projectId}/operations/${op.body.name}`;
90
90
  const pollRes = await operationPoller.pollOperation({
91
91
  apiOrigin: (0, api_1.cloudSQLAdminOrigin)(),
92
92
  apiVersion: API_VERSION,
@@ -1,17 +1,18 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.brownfieldSqlSetup = exports.setupBrownfieldAsGreenfield = exports.getSchemaMetadata = exports.greenFieldSchemaSetup = exports.setupSQLPermissions = exports.checkSQLRoleIsGranted = exports.fdcSqlRoleMap = exports.SchemaSetupStatus = void 0;
4
+ const clc = require("colorette");
4
5
  const permissions_1 = require("./permissions");
5
6
  const cloudsqladmin_1 = require("./cloudsqladmin");
6
7
  const connect_1 = require("./connect");
7
8
  const logger_1 = require("../../logger");
8
9
  const prompt_1 = require("../../prompt");
9
- const clc = require("colorette");
10
10
  const error_1 = require("../../error");
11
11
  const projectUtils_1 = require("../../projectUtils");
12
12
  const connect_2 = require("./connect");
13
13
  const lodash_1 = require("lodash");
14
14
  const connect_3 = require("./connect");
15
+ const utils = require("../../utils");
15
16
  var SchemaSetupStatus;
16
17
  (function (SchemaSetupStatus) {
17
18
  SchemaSetupStatus["NotSetup"] = "not-setup";
@@ -65,8 +66,13 @@ async function checkSQLRoleIsGranted(options, instanceId, databaseId, grantedRol
65
66
  }
66
67
  exports.checkSQLRoleIsGranted = checkSQLRoleIsGranted;
67
68
  async function setupSQLPermissions(instanceId, databaseId, schemaInfo, options, silent = false) {
69
+ const logFn = silent
70
+ ? logger_1.logger.debug
71
+ : (message) => {
72
+ return utils.logLabeledBullet("dataconnect", message);
73
+ };
68
74
  const schema = schemaInfo.name;
69
- logger_1.logger.info(`Detected schema "${schema}" setup status is ${schemaInfo.setupStatus}. Running setup...`);
75
+ logFn(`Detected schema "${schema}" setup status is ${schemaInfo.setupStatus}. Running setup...`);
70
76
  const userIsCSQLAdmin = await (0, cloudsqladmin_1.iamUserIsCSQLAdmin)(options);
71
77
  if (!userIsCSQLAdmin) {
72
78
  throw new error_1.FirebaseError(`Missing required IAM permission to setup SQL schemas. SQL schema setup requires 'roles/cloudsql.admin' or an equivalent role.`);
@@ -75,23 +81,23 @@ async function setupSQLPermissions(instanceId, databaseId, schemaInfo, options,
75
81
  let runGreenfieldSetup = false;
76
82
  if (schemaInfo.setupStatus === SchemaSetupStatus.GreenField) {
77
83
  runGreenfieldSetup = true;
78
- logger_1.logger.info(`Database ${databaseId} has already been setup as greenfield project. Rerunning setup to repair any missing permissions.`);
84
+ logFn(`Database ${databaseId} has already been setup as greenfield project. Rerunning setup to repair any missing permissions.`);
79
85
  }
80
86
  if (schemaInfo.tables.length === 0) {
81
87
  runGreenfieldSetup = true;
82
- logger_1.logger.info(`Found no tables in schema "${schema}", assuming greenfield project.`);
88
+ logFn(`Found no tables in schema "${schema}", assuming greenfield project.`);
83
89
  }
84
90
  if (runGreenfieldSetup) {
85
91
  const greenfieldSetupCmds = await greenFieldSchemaSetup(instanceId, databaseId, schema, options);
86
92
  await (0, connect_2.executeSqlCmdsAsSuperUser)(options, instanceId, databaseId, greenfieldSetupCmds, silent, true);
87
- logger_1.logger.info(clc.green("Database setup complete."));
93
+ logFn(clc.green("Database setup complete."));
88
94
  return SchemaSetupStatus.GreenField;
89
95
  }
90
96
  if (options.nonInteractive || options.force) {
91
97
  throw new error_1.FirebaseError(`Schema "${schema}" isn't set up and can only be set up in interactive mode.`);
92
98
  }
93
99
  const currentTablesOwners = [...new Set(schemaInfo.tables.map((t) => t.owner))];
94
- logger_1.logger.info(`We found some existing object owners [${currentTablesOwners.join(", ")}] in your cloudsql "${schema}" schema.`);
100
+ logFn(`We found some existing object owners [${currentTablesOwners.join(", ")}] in your cloudsql "${schema}" schema.`);
95
101
  const shouldSetupGreenfield = await (0, prompt_1.confirm)({
96
102
  message: clc.yellow("Would you like FDC to handle SQL migrations for you moving forward?\n" +
97
103
  `This means we will transfer schema and tables ownership to ${(0, permissions_1.firebaseowner)(databaseId, schema)}\n` +
@@ -101,14 +107,14 @@ async function setupSQLPermissions(instanceId, databaseId, schemaInfo, options,
101
107
  if (shouldSetupGreenfield) {
102
108
  await setupBrownfieldAsGreenfield(instanceId, databaseId, schemaInfo, options, silent);
103
109
  logger_1.logger.info(clc.green("Database setup complete."));
104
- logger_1.logger.info(clc.yellow("IMPORTANT: please uncomment 'schemaValidation: \"COMPATIBLE\"' in your dataconnect.yaml file to avoid dropping any existing tables by mistake."));
110
+ logFn(clc.yellow("IMPORTANT: please uncomment 'schemaValidation: \"COMPATIBLE\"' in your dataconnect.yaml file to avoid dropping any existing tables by mistake."));
105
111
  return SchemaSetupStatus.GreenField;
106
112
  }
107
113
  else {
108
- logger_1.logger.info(clc.yellow("Setting up database in brownfield mode.\n" +
114
+ logFn(clc.yellow("Setting up database in brownfield mode.\n" +
109
115
  `Note: SQL migrations can't be done through ${clc.bold("firebase dataconnect:sql:migrate")} in this mode.`));
110
116
  await brownfieldSqlSetup(instanceId, databaseId, schemaInfo, options, silent);
111
- logger_1.logger.info(clc.green("Brownfield database setup complete."));
117
+ logFn(clc.green("Brownfield database setup complete."));
112
118
  return SchemaSetupStatus.BrownField;
113
119
  }
114
120
  }
@@ -83,12 +83,12 @@ async function askQuestions(setup, isBillingEnabled) {
83
83
  info.cloudSqlInstanceId === "" ||
84
84
  info.locationId === "" ||
85
85
  info.cloudSqlDatabase === "";
86
- const shouldConfigureBackend = isBillingEnabled && requiredConfigUnset
87
- ? await (0, prompt_1.confirm)({
86
+ const shouldConfigureBackend = isBillingEnabled &&
87
+ requiredConfigUnset &&
88
+ (await (0, prompt_1.confirm)({
88
89
  message: `Would you like to configure your backend resources now?`,
89
90
  default: true,
90
- })
91
- : false;
91
+ }));
92
92
  if (shouldConfigureBackend) {
93
93
  info = await promptForService(info);
94
94
  info = await promptForCloudSQL(setup, info);
@@ -115,10 +115,9 @@ async function actuate(setup, config, info) {
115
115
  if (setup.projectId && info.shouldProvisionCSQL) {
116
116
  await (0, provisionCloudSql_1.provisionCloudSql)({
117
117
  projectId: setup.projectId,
118
- locationId: info.locationId,
118
+ location: info.locationId,
119
119
  instanceId: info.cloudSqlInstanceId,
120
120
  databaseId: info.cloudSqlDatabase,
121
- configYamlPath: (0, path_1.join)(config.get("dataconnect.source"), "dataconnect.yaml"),
122
121
  enableGoogleMlIntegration: false,
123
122
  waitForCreation: false,
124
123
  });
@@ -269,6 +268,9 @@ async function promptForCloudSQL(setup, info) {
269
268
  if (!(await (0, freeTrial_1.checkFreeTrialInstanceUsed)(setup.projectId))) {
270
269
  choices.push({ name: "Create a new free trial instance", value: "", location: "" });
271
270
  }
271
+ else {
272
+ choices.push({ name: "Create a new CloudSQL instance", value: "", location: "" });
273
+ }
272
274
  info.cloudSqlInstanceId = await (0, prompt_1.promptOnce)({
273
275
  message: `Which CloudSQL instance would you like to use?`,
274
276
  type: "list",
@@ -84,7 +84,7 @@ async function askQuestions(setup, config) {
84
84
  {
85
85
  type: "checkbox",
86
86
  name: "fdcFrameworks",
87
- message: `Which ${hasFrameworkEnabled && "additional "}frameworks would you like to generate SDKs for? ` +
87
+ message: `Which ${hasFrameworkEnabled ? "additional " : ""}frameworks would you like to generate SDKs for? ` +
88
88
  "Press Space to select features, then Enter to confirm your choices.",
89
89
  choices: unusedFrameworks.map((frameworkStr) => ({
90
90
  value: frameworkStr,
package/lib/track.js CHANGED
@@ -154,7 +154,7 @@ function session(propertyName) {
154
154
  const validateOnly = !!process.env.FIREBASE_CLI_MP_VALIDATE;
155
155
  if (!usageEnabled() && propertyName !== "vscode") {
156
156
  if (validateOnly) {
157
- logger_1.logger.warn("Google Analytics is DISABLED. To enable, (re)login and opt in to collection.");
157
+ logger_1.logger.debug("Google Analytics is DISABLED. To enable, (re)login and opt in to collection.");
158
158
  }
159
159
  return;
160
160
  }
@@ -181,7 +181,7 @@ function isDebugMode() {
181
181
  if (account === null || account === void 0 ? void 0 : account.user.email.endsWith("@google.com")) {
182
182
  try {
183
183
  require("../tsconfig.json");
184
- logger_1.logger.info(`Using Google Analytics in DEBUG mode. Emulators (+ UI) events will be shown in GA Debug View only.`);
184
+ logger_1.logger.debug(`Using Google Analytics in DEBUG mode. Emulators (+ UI) events will be shown in GA Debug View only.`);
185
185
  return true;
186
186
  }
187
187
  catch (_a) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "14.0.1",
3
+ "version": "14.2.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -1 +1,6 @@
1
- *.local
1
+ # Python bytecode
2
+ __pycache__/
3
+
4
+ # Python virtual environment
5
+ venv/
6
+ *.local