firebase-tools 15.14.0 → 15.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 (63) hide show
  1. package/lib/api.js +2 -6
  2. package/lib/command.js +23 -29
  3. package/lib/commands/dataconnect-compile.js +6 -6
  4. package/lib/commands/dataconnect-execute.js +1 -1
  5. package/lib/commands/dataconnect-sdk-generate.js +3 -3
  6. package/lib/commands/dataconnect-services-list.js +1 -1
  7. package/lib/commands/dataconnect-sql-diff.js +3 -3
  8. package/lib/commands/dataconnect-sql-grant.js +2 -2
  9. package/lib/commands/dataconnect-sql-migrate.js +4 -4
  10. package/lib/commands/dataconnect-sql-setup.js +2 -2
  11. package/lib/commands/dataconnect-sql-shell.js +4 -4
  12. package/lib/commands/ext-dev-usage.js +0 -2
  13. package/lib/commands/init.js +3 -3
  14. package/lib/commands/open.js +1 -1
  15. package/lib/commands/setup-emulators-dataconnect.js +1 -1
  16. package/lib/dataconnect/freeTrial.js +2 -2
  17. package/lib/dataconnect/load.js +2 -2
  18. package/lib/dataconnect/provisionCloudSql.js +3 -3
  19. package/lib/dataconnect/schemaMigration.js +11 -11
  20. package/lib/dataconnect/webhook.js +1 -1
  21. package/lib/deploy/functions/backend.js +1 -1
  22. package/lib/deploy/functions/build.js +3 -3
  23. package/lib/deploy/functions/deploy.js +5 -2
  24. package/lib/deploy/functions/prepare.js +53 -0
  25. package/lib/deploy/functions/release/fabricator.js +59 -46
  26. package/lib/deploy/functions/release/planner.js +1 -1
  27. package/lib/deploy/functions/runtimes/dart/index.js +3 -1
  28. package/lib/deploy/functions/runtimes/dart/triggerSupport.js +123 -0
  29. package/lib/deploy/functions/runtimes/index.js +1 -4
  30. package/lib/deploy/functions/services/ailogic.js +12 -1
  31. package/lib/deploy/functions/services/dataconnect.js +1 -1
  32. package/lib/emulator/constants.js +1 -1
  33. package/lib/emulator/controller.js +2 -2
  34. package/lib/emulator/dataconnectEmulator.js +14 -14
  35. package/lib/emulator/dataconnectToolkitController.js +2 -2
  36. package/lib/emulator/downloadableEmulatorInfo.json +31 -31
  37. package/lib/emulator/extensionsEmulator.js +1 -2
  38. package/lib/emulator/functionsEmulator.js +15 -0
  39. package/lib/emulator/hub.js +3 -3
  40. package/lib/emulator/hubExport.js +2 -2
  41. package/lib/emulator/initEmulators.js +1 -1
  42. package/lib/experiments.js +10 -5
  43. package/lib/gcp/ailogic.js +6 -3
  44. package/lib/gcp/runv2.js +9 -2
  45. package/lib/init/features/dataconnect/index.js +7 -7
  46. package/lib/init/features/dataconnect/resolver.js +2 -2
  47. package/lib/init/features/dataconnect/sdk.js +8 -8
  48. package/lib/init/features/functions/index.js +1 -1
  49. package/lib/mcp/index.js +0 -1
  50. package/lib/mcp/prompts/dataconnect/schema.js +6 -6
  51. package/lib/mcp/resources/guides/init_data_connect.js +2 -2
  52. package/lib/mcp/resources/guides/init_firestore.js +1 -1
  53. package/lib/mcp/tools/core/init.js +9 -9
  54. package/lib/mcp/tools/dataconnect/compile.js +5 -5
  55. package/lib/mcp/tools/dataconnect/execute.js +6 -6
  56. package/lib/mcp/tools/dataconnect/list_services.js +7 -7
  57. package/lib/mcp/util/dataconnect/content.js +19 -19
  58. package/lib/tsconfig.compile.tsbuildinfo +1 -1
  59. package/lib/tsconfig.publish.tsbuildinfo +1 -1
  60. package/package.json +16 -4
  61. package/templates/init/functions/dart/pubspec.yaml +6 -7
  62. package/templates/init/functions/dart/server.dart +3 -1
  63. package/lib/shortenUrl.js +0 -28
package/lib/api.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.storageOrigin = exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.crashlyticsApiOrigin = exports.messagingApiOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsTOSOrigin = exports.extensionsPublisherOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.cloudbuildOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.dynamicLinksKey = exports.dynamicLinksOrigin = exports.consoleOrigin = exports.authManagementOrigin = exports.authOrigin = exports.apphostingGitHubAppInstallationURL = exports.apphostingP4SADomain = exports.apphostingOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.developerConnectP4SADomain = exports.developerConnectOrigin = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
4
- exports.developerKnowledgeOrigin = exports.cloudTestingOrigin = exports.appTestingOrigin = exports.cloudAiCompanionOrigin = exports.aiLogicProxyOrigin = exports.vertexAIOrigin = exports.cloudSQLAdminOrigin = exports.dataConnectLocalConnString = exports.dataconnectP4SADomain = exports.dataconnectOrigin = exports.githubClientSecret = exports.githubClientId = exports.computeOrigin = exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.studioApiOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = exports.hostingApiOrigin = exports.firebaseStorageOrigin = void 0;
3
+ exports.hostingApiOrigin = exports.firebaseStorageOrigin = exports.storageOrigin = exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.crashlyticsApiOrigin = exports.messagingApiOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsTOSOrigin = exports.extensionsPublisherOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.cloudbuildOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.consoleOrigin = exports.authManagementOrigin = exports.authOrigin = exports.apphostingGitHubAppInstallationURL = exports.apphostingP4SADomain = exports.apphostingOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.developerConnectP4SADomain = exports.developerConnectOrigin = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
4
+ exports.developerKnowledgeOrigin = exports.cloudTestingOrigin = exports.appTestingOrigin = exports.cloudAiCompanionOrigin = exports.aiLogicProxyOrigin = exports.vertexAIOrigin = exports.cloudSQLAdminOrigin = exports.dataConnectLocalConnString = exports.dataconnectP4SADomain = exports.dataconnectOrigin = exports.githubClientSecret = exports.githubClientId = exports.computeOrigin = exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.studioApiOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = void 0;
5
5
  exports.getScopes = getScopes;
6
6
  exports.setScopes = setScopes;
7
7
  const constants_1 = require("./emulator/constants");
@@ -43,10 +43,6 @@ const authManagementOrigin = () => utils.envOverride("FIREBASE_AUTH_MANAGEMENT_U
43
43
  exports.authManagementOrigin = authManagementOrigin;
44
44
  const consoleOrigin = () => utils.envOverride("FIREBASE_CONSOLE_URL", "https://console.firebase.google.com");
45
45
  exports.consoleOrigin = consoleOrigin;
46
- const dynamicLinksOrigin = () => utils.envOverride("FIREBASE_DYNAMIC_LINKS_URL", "https://firebasedynamiclinks.googleapis.com");
47
- exports.dynamicLinksOrigin = dynamicLinksOrigin;
48
- const dynamicLinksKey = () => utils.envOverride("FIREBASE_DYNAMIC_LINKS_KEY", "AIzaSyB6PtY5vuiSB8MNgt20mQffkOlunZnHYiQ");
49
- exports.dynamicLinksKey = dynamicLinksKey;
50
46
  const eventarcOrigin = () => utils.envOverride("EVENTARC_URL", "https://eventarc.googleapis.com");
51
47
  exports.eventarcOrigin = eventarcOrigin;
52
48
  const firebaseApiOrigin = () => utils.envOverride("FIREBASE_API_URL", "https://firebase.googleapis.com");
package/lib/command.js CHANGED
@@ -111,23 +111,22 @@ class Command {
111
111
  });
112
112
  }
113
113
  const duration = Math.floor((process.uptime() - start) * 1000);
114
- try {
115
- const trackSuccess = (0, track_1.trackGA4)("command_execution", {
116
- command_name: this.name,
117
- result: "success",
118
- interactive: (0, utils_1.getInheritedOption)(options, "nonInteractive") ? "false" : "true",
119
- }, duration);
120
- const tracks = [trackSuccess];
121
- if (isEmulator) {
122
- tracks.push((0, track_1.trackEmulator)("command_success", {
114
+ const trackSuccess = (0, track_1.trackGA4)("command_execution", {
115
+ command_name: this.name,
116
+ result: "success",
117
+ interactive: (0, utils_1.getInheritedOption)(options, "nonInteractive") ? "false" : "true",
118
+ }, duration);
119
+ if (!isEmulator) {
120
+ await (0, utils_1.withTimeout)(5000, trackSuccess);
121
+ }
122
+ else {
123
+ await (0, utils_1.withTimeout)(5000, Promise.all([
124
+ trackSuccess,
125
+ (0, track_1.trackEmulator)("command_success", {
123
126
  command_name: this.name,
124
127
  duration,
125
- }));
126
- }
127
- await (0, utils_1.withTimeout)(1000, Promise.all(tracks));
128
- }
129
- catch (gaErr) {
130
- logger_1.logger.debug("Analytics tracking failed during success path:", gaErr);
128
+ }),
129
+ ]));
131
130
  }
132
131
  process.exit();
133
132
  })
@@ -141,25 +140,20 @@ class Command {
141
140
  });
142
141
  }
143
142
  const duration = Math.floor((process.uptime() - start) * 1000);
144
- try {
145
- const trackError = (0, track_1.trackGA4)("command_execution", {
143
+ await (0, utils_1.withTimeout)(5000, Promise.all([
144
+ (0, track_1.trackGA4)("command_execution", {
146
145
  command_name: this.name,
147
146
  result: "error",
148
147
  interactive: (0, utils_1.getInheritedOption)(options, "nonInteractive") ? "false" : "true",
149
- }, duration);
150
- const tracks = [trackError];
151
- if (isEmulator) {
152
- tracks.push((0, track_1.trackEmulator)("command_error", {
148
+ }, duration),
149
+ isEmulator
150
+ ? (0, track_1.trackEmulator)("command_error", {
153
151
  command_name: this.name,
154
152
  duration,
155
- error_type: err?.exit === 1 ? "user" : "unexpected",
156
- }));
157
- }
158
- await (0, utils_1.withTimeout)(1000, Promise.all(tracks));
159
- }
160
- catch (gaErr) {
161
- logger_1.logger.debug("Analytics tracking failed during error path:", gaErr);
162
- }
153
+ error_type: err.exit === 1 ? "user" : "unexpected",
154
+ })
155
+ : Promise.resolve(),
156
+ ]));
163
157
  client.errorOut(err);
164
158
  });
165
159
  });
@@ -12,18 +12,18 @@ const hub_1 = require("../emulator/hub");
12
12
  const build_1 = require("../dataconnect/build");
13
13
  const error_1 = require("../error");
14
14
  exports.command = new command_1.Command("dataconnect:compile")
15
- .description("compile your Data Connect schema and connector config and GQL files.")
16
- .option("--service <serviceId>", "the serviceId of the Data Connect service. If not provided, compiles all services.")
17
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
15
+ .description("compile your SQL Connect schema and connector config and GQL files.")
16
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service. If not provided, compiles all services.")
17
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
18
18
  .action(async (options) => {
19
19
  const projectId = (0, projectUtils_1.getProjectId)(options);
20
20
  const config = options.config;
21
21
  if (!config || !config.has("dataconnect")) {
22
- throw new error_1.FirebaseError(`No Data Connect project directory found. Please run ${clc.bold("firebase init dataconnect")} to set it up first.`);
22
+ throw new error_1.FirebaseError(`No SQL Connect project directory found. Please run ${clc.bold("firebase init dataconnect")} to set it up first.`);
23
23
  }
24
24
  const serviceInfos = await (0, load_1.pickServices)(projectId || hub_1.EmulatorHub.MISSING_PROJECT_PLACEHOLDER, config, options.service, options.location);
25
25
  if (!serviceInfos.length) {
26
- throw new error_1.FirebaseError("No Data Connect services found to compile.");
26
+ throw new error_1.FirebaseError("No SQL Connect services found to compile.");
27
27
  }
28
28
  for (const serviceInfo of serviceInfos) {
29
29
  const configDir = serviceInfo.sourceDirectory;
@@ -41,6 +41,6 @@ exports.command = new command_1.Command("dataconnect:compile")
41
41
  configDir,
42
42
  account,
43
43
  });
44
- (0, utils_1.logLabeledSuccess)("dataconnect", `Successfully compiled Data Connect service: ${clc.bold(serviceInfo.dataConnectYaml.serviceId)}`);
44
+ (0, utils_1.logLabeledSuccess)("dataconnect", `Successfully compiled SQL Connect service: ${clc.bold(serviceInfo.dataConnectYaml.serviceId)}`);
45
45
  }
46
46
  });
@@ -23,7 +23,7 @@ const logger_1 = require("../logger");
23
23
  const responseToError_1 = require("../responseToError");
24
24
  let stdinUsedFor = undefined;
25
25
  exports.command = new command_1.Command("dataconnect:execute [file] [operationName]")
26
- .description("execute a Data Connect query or mutation. If FIREBASE_DATACONNECT_EMULATOR_HOST is set (such as during 'firebase emulator:exec', executes against the emulator instead.")
26
+ .description("execute a SQL Connect query or mutation. If FIREBASE_DATACONNECT_EMULATOR_HOST is set (such as during 'firebase emulator:exec', executes against the emulator instead.")
27
27
  .option("--service <serviceId>", "The service ID to execute against (optional if there's only one service)")
28
28
  .option("--location <locationId>", "The location ID to execute against (optional if there's only one service). Ignored by the emulator.")
29
29
  .option("--vars, --variables <vars>", "Supply variables to the operation execution, which must be a JSON object whose keys are variable names. If vars begin with the character @, the rest is interpreted as a file name to read from, or - to read from stdin.")
@@ -15,9 +15,9 @@ const error_1 = require("../error");
15
15
  const init_1 = require("./init");
16
16
  const hub_1 = require("../emulator/hub");
17
17
  exports.command = new command_1.Command("dataconnect:sdk:generate")
18
- .description("generate typed SDKs to use Data Connect in your apps")
19
- .option("--service <serviceId>", "the serviceId of the Data Connect service. If not provided, generates SDKs for all services.")
20
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
18
+ .description("generate typed SDKs to use SQL Connect in your apps")
19
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service. If not provided, generates SDKs for all services.")
20
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
21
21
  .option("--watch", "watch for changes to your connector GQL files and regenerate your SDKs when updates occur")
22
22
  .action(async (options) => {
23
23
  const projectId = (0, projectUtils_1.getProjectId)(options);
@@ -10,7 +10,7 @@ const requirePermissions_1 = require("../requirePermissions");
10
10
  const ensureApis_1 = require("../dataconnect/ensureApis");
11
11
  const Table = require("cli-table3");
12
12
  exports.command = new command_1.Command("dataconnect:services:list")
13
- .description("list all deployed Data Connect services")
13
+ .description("list all deployed SQL Connect services")
14
14
  .before(requirePermissions_1.requirePermissions, [
15
15
  "dataconnect.services.list",
16
16
  "dataconnect.schemas.list",
@@ -10,9 +10,9 @@ const schemaMigration_1 = require("../dataconnect/schemaMigration");
10
10
  const requireAuth_1 = require("../requireAuth");
11
11
  const types_1 = require("../dataconnect/types");
12
12
  exports.command = new command_1.Command("dataconnect:sql:diff")
13
- .description("display the differences between the local Data Connect schema and your CloudSQL database's schema")
14
- .option("--service <serviceId>", "the serviceId of the Data Connect service")
15
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
13
+ .description("display the differences between the local SQL Connect schema and your CloudSQL database's schema")
14
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service")
15
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
16
16
  .before(requirePermissions_1.requirePermissions, [
17
17
  "firebasedataconnect.services.list",
18
18
  "firebasedataconnect.schemas.list",
@@ -17,8 +17,8 @@ exports.command = new command_1.Command("dataconnect:sql:grant")
17
17
  .description("grants the SQL role <role> to the provided user or service account <email>")
18
18
  .option("-R, --role <role>", "The SQL role to grant. One of: owner, writer, or reader.")
19
19
  .option("-E, --email <email>", "The email of the user or service account we would like to grant the role to.")
20
- .option("--service <serviceId>", "the serviceId of the Data Connect service")
21
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
20
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service")
21
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
22
22
  .before(requirePermissions_1.requirePermissions, ["firebasedataconnect.services.list"])
23
23
  .before(requireAuth_1.requireAuth)
24
24
  .action(async (options) => {
@@ -12,9 +12,9 @@ const ensureApis_1 = require("../dataconnect/ensureApis");
12
12
  const utils_1 = require("../utils");
13
13
  const types_1 = require("../dataconnect/types");
14
14
  exports.command = new command_1.Command("dataconnect:sql:migrate")
15
- .description("migrate your CloudSQL database's schema to match your local Data Connect schema")
16
- .option("--service <serviceId>", "the serviceId of the Data Connect service")
17
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
15
+ .description("migrate your CloudSQL database's schema to match your local SQL Connect schema")
16
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service")
17
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
18
18
  .before(requirePermissions_1.requirePermissions, [
19
19
  "firebasedataconnect.services.list",
20
20
  "firebasedataconnect.schemas.list",
@@ -40,7 +40,7 @@ exports.command = new command_1.Command("dataconnect:sql:migrate")
40
40
  ?.schemaValidation,
41
41
  });
42
42
  if (diffs.length) {
43
- (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema sucessfully migrated! Run 'firebase deploy' to deploy your new schema to your Data Connect service.`);
43
+ (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema sucessfully migrated! Run 'firebase deploy' to deploy your new schema to your SQL Connect service.`);
44
44
  }
45
45
  else {
46
46
  (0, utils_1.logLabeledSuccess)("dataconnect", "Database schema is already up to date!");
@@ -14,8 +14,8 @@ const load_1 = require("../dataconnect/load");
14
14
  const types_1 = require("../dataconnect/types");
15
15
  exports.command = new command_1.Command("dataconnect:sql:setup")
16
16
  .description("set up your CloudSQL database")
17
- .option("--service <serviceId>", "the serviceId of the Data Connect service")
18
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
17
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service")
18
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
19
19
  .before(requirePermissions_1.requirePermissions, [
20
20
  "firebasedataconnect.services.list",
21
21
  "firebasedataconnect.schemas.list",
@@ -74,9 +74,9 @@ async function mainShellLoop(conn) {
74
74
  }
75
75
  }
76
76
  exports.command = new command_1.Command("dataconnect:sql:shell")
77
- .description("start a shell connected directly to your Data Connect service's linked CloudSQL instance")
78
- .option("--service <serviceId>", "the serviceId of the Data Connect service")
79
- .option("--location <location>", "the location of the Data Connect service. Only needed if service ID is used in multiple locations.")
77
+ .description("start a shell connected directly to your SQL Connect service's linked CloudSQL instance")
78
+ .option("--service <serviceId>", "the serviceId of the SQL Connect service")
79
+ .option("--location <location>", "the location of the SQL Connect service. Only needed if service ID is used in multiple locations.")
80
80
  .before(requirePermissions_1.requirePermissions, ["firebasedataconnect.services.list", "cloudsql.instances.connect"])
81
81
  .before(requireAuth_1.requireAuth)
82
82
  .action(async (options) => {
@@ -106,7 +106,7 @@ exports.command = new command_1.Command("dataconnect:sql:shell")
106
106
  const conn = await pool.connect();
107
107
  await conn.query(`SET search_path TO "${schemaName}"`);
108
108
  logger_1.logger.info(`Logged in as ${username}`);
109
- logger_1.logger.info(clc.cyan("Welcome to Data Connect Cloud SQL Shell"));
109
+ logger_1.logger.info(clc.cyan("Welcome to SQL Connect Cloud SQL Shell"));
110
110
  logger_1.logger.info(clc.gray("Type your your SQL query or '.exit' to quit, queries should end with ';' or add empty line to execute."));
111
111
  await mainShellLoop(conn);
112
112
  logger_1.logger.info(clc.yellow("Exiting shell..."));
@@ -14,7 +14,6 @@ const extensionsHelper_1 = require("../extensions/extensionsHelper");
14
14
  const error_1 = require("../error");
15
15
  const logger_1 = require("../logger");
16
16
  const prompt_1 = require("../prompt");
17
- const shortenUrl_1 = require("../shortenUrl");
18
17
  exports.command = new command_1.Command("ext:dev:usage <publisherId>")
19
18
  .description("get usage statistics for an extension")
20
19
  .help("use this command to get the usage of extensions you published. " +
@@ -134,6 +133,5 @@ async function buildCloudMonitoringLink(args) {
134
133
  let uri = `https://console.cloud.google.com/monitoring/metrics-explorer?project=${args.projectNumber}` +
135
134
  `&pageState=${JSON.stringify(pageState)}`;
136
135
  uri = encodeURI(uri);
137
- uri = await (0, shortenUrl_1.shortenUrl)(uri);
138
136
  return uri;
139
137
  }
@@ -27,7 +27,7 @@ function isOutside(from, to) {
27
27
  let choices = [
28
28
  {
29
29
  value: "dataconnect",
30
- name: "Data Connect: Set up a Firebase Data Connect service",
30
+ name: "SQL Connect: Set up a Firebase SQL Connect service",
31
31
  checked: false,
32
32
  },
33
33
  {
@@ -84,7 +84,7 @@ let choices = [
84
84
  },
85
85
  {
86
86
  value: "dataconnect:sdk",
87
- name: "Data Connect: Set up a generated SDK for your Firebase Data Connect service",
87
+ name: "SQL Connect: Set up a generated SDK for your Firebase SQL Connect service",
88
88
  checked: false,
89
89
  hidden: true,
90
90
  },
@@ -97,7 +97,7 @@ let choices = [
97
97
  if ((0, experiments_1.isEnabled)("fdcwebhooks")) {
98
98
  choices.push({
99
99
  value: "dataconnect:resolver",
100
- name: "Data Connect: Set up a custom resolver for your Firebase Data Connect service",
100
+ name: "SQL Connect: Set up a custom resolver for your Firebase SQL Connect service",
101
101
  checked: false,
102
102
  hidden: true,
103
103
  });
@@ -20,7 +20,7 @@ const LINKS = [
20
20
  { name: "Crash Reporting", arg: "crash", consolePath: "/crashlytics" },
21
21
  { name: "Database: Data", arg: "database", consolePath: "/database/data" },
22
22
  { name: "Database: Rules", arg: "database:rules", consolePath: "/database/rules" },
23
- { name: "Data Connect", arg: "dataconnect", consolePath: "/dataconnect" },
23
+ { name: "SQL Connect", arg: "dataconnect", consolePath: "/dataconnect" },
24
24
  { name: "Docs", arg: "docs", url: "https://firebase.google.com/docs" },
25
25
  { name: "Dynamic Links", arg: "links", consolePath: "/durablelinks" },
26
26
  { name: "Extensions", arg: "extensions", consolePath: "/extensions" },
@@ -11,7 +11,7 @@ exports.command = new command_1.Command(`setup:emulators:${NAME}`)
11
11
  .action(async (options) => {
12
12
  await (0, downloadableEmulators_1.downloadIfNecessary)(NAME);
13
13
  if (!options.config) {
14
- logger_1.logger.info("Not currently in a Firebase project directory. Run this command from a project directory to configure the Data Connect emulator.");
14
+ logger_1.logger.info("Not currently in a Firebase project directory. Run this command from a project directory to configure the SQL Connect emulator.");
15
15
  return;
16
16
  }
17
17
  logger_1.logger.info("Setup complete!");
@@ -30,11 +30,11 @@ async function checkFreeTrialInstanceUsed(projectId) {
30
30
  return used;
31
31
  }
32
32
  function upgradeInstructions(projectId, trialUsed) {
33
- return `To provision a ${trialUsed ? "paid CloudSQL Postgres instance" : "CloudSQL Postgres instance on the Firebase Data Connect no-cost trial"}:
33
+ return `To provision a ${trialUsed ? "paid CloudSQL Postgres instance" : "CloudSQL Postgres instance on the Firebase SQL Connect no-cost trial"}:
34
34
 
35
35
  1. Please upgrade to the pay-as-you-go (Blaze) billing plan. Visit the following page:
36
36
 
37
37
  https://console.firebase.google.com/project/${projectId}/usage/details
38
38
 
39
- 2. Run ${clc.bold("firebase deploy --only dataconnect")} to deploy your Data Connect service.`;
39
+ 2. Run ${clc.bold("firebase deploy --only dataconnect")} to deploy your SQL Connect service.`;
40
40
  }
@@ -29,8 +29,8 @@ async function pickOneService(projectId, config, service, location) {
29
29
  async function pickServices(projectId, config, serviceId, location) {
30
30
  const serviceInfos = await loadAll(projectId, config);
31
31
  if (serviceInfos.length === 0) {
32
- throw new error_1.FirebaseError("No Data Connect services found in firebase.json. " +
33
- `\nYou can run ${clc.bold("firebase init dataconnect")} to add a Data Connect service.`);
32
+ throw new error_1.FirebaseError("No SQL Connect services found in firebase.json. " +
33
+ `\nYou can run ${clc.bold("firebase init dataconnect")} to add a SQL Connect service.`);
34
34
  }
35
35
  const matchingServices = serviceInfos.filter((i) => (!serviceId || i.dataConnectYaml.serviceId === serviceId) &&
36
36
  (!location || i.dataConnectYaml.location === location));
@@ -49,12 +49,12 @@ async function upsertInstance(stats, args) {
49
49
  const why = getUpdateReason(existingInstance, requireGoogleMlIntegration);
50
50
  if (why) {
51
51
  if (dryRun) {
52
- utils.logLabeledBullet("dataconnect", `Cloud SQL instance ${clc.bold(instanceId)} settings are not compatible with Firebase Data Connect. ` +
52
+ utils.logLabeledBullet("dataconnect", `Cloud SQL instance ${clc.bold(instanceId)} settings are not compatible with Firebase SQL Connect. ` +
53
53
  `It will be updated on your next deploy.` +
54
54
  why);
55
55
  }
56
56
  else {
57
- utils.logLabeledBullet("dataconnect", `Cloud SQL instance ${clc.bold(instanceId)} settings are not compatible with Firebase Data Connect. ` +
57
+ utils.logLabeledBullet("dataconnect", `Cloud SQL instance ${clc.bold(instanceId)} settings are not compatible with Firebase SQL Connect. ` +
58
58
  why);
59
59
  stats.action = "update";
60
60
  await (0, utils_1.promiseWithSpinner)(() => cloudSqlAdminClient.updateInstanceForDataConnect(existingInstance, requireGoogleMlIntegration), "Updating your Cloud SQL instance...");
@@ -92,7 +92,7 @@ async function createInstance(args) {
92
92
  function cloudSQLBeingCreated(projectId, instanceId, isFreeTrial, billingEnabled) {
93
93
  return (`Cloud SQL Instance ${clc.bold(instanceId)} is being created.` +
94
94
  (isFreeTrial
95
- ? `\nThis instance is provided under the terms of the Data Connect no-cost trial ${(0, freeTrial_1.freeTrialTermsLink)()}`
95
+ ? `\nThis instance is provided under the terms of the SQL Connect no-cost trial ${(0, freeTrial_1.freeTrialTermsLink)()}`
96
96
  : "") +
97
97
  `\n
98
98
  Meanwhile, your data are saved in a temporary database and will be migrated once complete.` +
@@ -248,7 +248,7 @@ async function grantRoleToUserInSchema(options, schema) {
248
248
  await ensureServiceIsConnectedToCloudSql(serviceName, instanceName, databaseId, false, schemaName);
249
249
  const schemaSetupStatus = await setupSchemaIfNecessary(instanceId, databaseId, schemaName, options);
250
250
  if (schemaSetupStatus !== permissionsSetup_1.SchemaSetupStatus.GreenField && role === "owner") {
251
- throw new error_1.FirebaseError(`Owner rule isn't available in ${schemaSetupStatus} databases. If you would like Data Connect to manage and own your database schema, run 'firebase dataconnect:sql:setup'`);
251
+ throw new error_1.FirebaseError(`Owner rule isn't available in ${schemaSetupStatus} databases. If you would like SQL Connect to manage and own your database schema, run 'firebase dataconnect:sql:setup'`);
252
252
  }
253
253
  await (0, permissionsSetup_1.grantRoleTo)(options, instanceId, databaseId, role, email, schemaName);
254
254
  }
@@ -275,11 +275,11 @@ function getIdentifiers(schema) {
275
275
  const postgresDatasource = schema.datasources.find((d) => d.postgresql);
276
276
  const databaseId = postgresDatasource?.postgresql?.database;
277
277
  if (!databaseId) {
278
- throw new error_1.FirebaseError("Data Connect schema must have a postgres datasource with a database name.");
278
+ throw new error_1.FirebaseError("SQL Connect schema must have a postgres datasource with a database name.");
279
279
  }
280
280
  const instanceName = postgresDatasource?.postgresql?.cloudSql?.instance;
281
281
  if (!instanceName) {
282
- throw new error_1.FirebaseError("Data Connect schema must have a postgres datasource with a CloudSQL instance.");
282
+ throw new error_1.FirebaseError("SQL Connect schema must have a postgres datasource with a CloudSQL instance.");
283
283
  }
284
284
  const instanceId = instanceName.split("/").pop();
285
285
  const schemaName = postgresDatasource?.postgresql?.schema || permissions_1.DEFAULT_SCHEMA;
@@ -325,9 +325,9 @@ async function handleIncompatibleSchemaError(args) {
325
325
  }
326
326
  const schemaInfo = await (0, permissionsSetup_1.getSchemaMetadata)(instanceId, databaseId, schemaName, options);
327
327
  if (schemaInfo.setupStatus !== permissionsSetup_1.SchemaSetupStatus.GreenField) {
328
- throw new error_1.FirebaseError(`Brownfield database are protected from SQL changes by Data Connect.\n` +
328
+ throw new error_1.FirebaseError(`Brownfield database are protected from SQL changes by SQL Connect.\n` +
329
329
  `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` +
330
- `If you would like Data Connect to manage your database schema, run 'firebase dataconnect:sql:setup'`);
330
+ `If you would like SQL Connect to manage your database schema, run 'firebase dataconnect:sql:setup'`);
331
331
  }
332
332
  if (!(await (0, permissionsSetup_1.checkSQLRoleIsGranted)(options, instanceId, databaseId, (0, permissions_1.firebaseowner)(databaseId, schemaName), (await (0, connect_1.getIAMUser)(options)).user))) {
333
333
  if (!userIsCSQLAdmin) {
@@ -387,7 +387,7 @@ async function promptForSchemaMigration(options, instanceId, databaseId, err, va
387
387
  return ans;
388
388
  }
389
389
  if (!validateOnly) {
390
- throw new error_1.FirebaseError("Command aborted. Your database schema is incompatible with your Data Connect schema. Run `firebase dataconnect:sql:migrate` to migrate your database schema");
390
+ throw new error_1.FirebaseError("Command aborted. Your database schema is incompatible with your SQL Connect schema. Run `firebase dataconnect:sql:migrate` to migrate your database schema");
391
391
  }
392
392
  else if (options.force) {
393
393
  return defaultChoice;
@@ -509,10 +509,10 @@ function displayStartSchemaDiff(validationMode) {
509
509
  function displayNoSchemaDiff(instanceId, databaseId, validationMode) {
510
510
  switch (validationMode) {
511
511
  case "COMPATIBLE":
512
- (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema of ${instanceId}:${databaseId} is compatible with Data Connect Schema.`);
512
+ (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema of ${instanceId}:${databaseId} is compatible with SQL Connect Schema.`);
513
513
  break;
514
514
  case "STRICT":
515
- (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema of ${instanceId}:${databaseId} matches Data Connect Schema exactly.`);
515
+ (0, utils_1.logLabeledSuccess)("dataconnect", `Database schema of ${instanceId}:${databaseId} matches SQL Connect Schema exactly.`);
516
516
  break;
517
517
  }
518
518
  }
@@ -522,21 +522,21 @@ function displaySchemaChanges(error, validationMode) {
522
522
  {
523
523
  switch (validationMode) {
524
524
  case "COMPATIBLE":
525
- (0, utils_1.logLabeledWarning)("dataconnect", `PostgreSQL schema is incompatible with the Data Connect Schema.
525
+ (0, utils_1.logLabeledWarning)("dataconnect", `PostgreSQL schema is incompatible with the SQL Connect Schema.
526
526
  Those SQL statements will migrate it to be compatible:
527
527
 
528
528
  ${diffsToString(error.diffs)}
529
529
  `);
530
530
  break;
531
531
  case "STRICT_AFTER_COMPATIBLE":
532
- (0, utils_1.logLabeledBullet)("dataconnect", `PostgreSQL schema contains unused SQL objects not part of the Data Connect Schema.
532
+ (0, utils_1.logLabeledBullet)("dataconnect", `PostgreSQL schema contains unused SQL objects not part of the SQL Connect Schema.
533
533
  Those SQL statements will migrate it to match exactly:
534
534
 
535
535
  ${diffsToString(error.diffs)}
536
536
  `);
537
537
  break;
538
538
  case "STRICT":
539
- (0, utils_1.logLabeledWarning)("dataconnect", `PostgreSQL schema does not match the Data Connect Schema.
539
+ (0, utils_1.logLabeledWarning)("dataconnect", `PostgreSQL schema does not match the SQL Connect Schema.
540
540
  Those SQL statements will migrate it to match exactly:
541
541
 
542
542
  ${diffsToString(error.diffs)}
@@ -27,6 +27,6 @@ async function sendVSCodeMessage(body) {
27
27
  });
28
28
  }
29
29
  catch (e) {
30
- logger_1.logger.debug(`Could not find VSCode notification endpoint: ${e}. If you are not running the Firebase Data Connect VSCode extension, this is expected and not an issue.`);
30
+ logger_1.logger.debug(`Could not find VSCode notification endpoint: ${e}. If you are not running the Firebase SQL Connect VSCode extension, this is expected and not an issue.`);
31
31
  }
32
32
  }
@@ -210,7 +210,7 @@ async function loadExistingBackend(ctx) {
210
210
  existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
211
211
  }
212
212
  unreachableRegions.gcfV1 = gcfV1Results.unreachable;
213
- if (experiments.isEnabled("functionsrunapionly")) {
213
+ if (experiments.isEnabled("functionsrunapionly") || experiments.isEnabled("dartfunctions")) {
214
214
  try {
215
215
  const runServices = await run.listServices(ctx.projectId);
216
216
  for (const service of runServices) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.AllFunctionsPlatforms = void 0;
3
+ exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.AllFunctionsPlatforms = exports.REGION_TBD = void 0;
4
4
  exports.empty = empty;
5
5
  exports.of = of;
6
6
  exports.isHttpsTriggered = isHttpsTriggered;
@@ -16,11 +16,11 @@ exports.toBackend = toBackend;
16
16
  exports.applyPrefix = applyPrefix;
17
17
  const backend = require("./backend");
18
18
  const proto = require("../../gcp/proto");
19
- const api = require("../../api");
20
19
  const params = require("./params");
21
20
  const error_1 = require("../../error");
22
21
  const functional_1 = require("../../functional");
23
22
  const cel_1 = require("./cel");
23
+ exports.REGION_TBD = "REGION_TBD";
24
24
  function empty() {
25
25
  return {
26
26
  requiredAPIs: [],
@@ -175,7 +175,7 @@ function toBackend(build, paramValues) {
175
175
  }
176
176
  let regions = [];
177
177
  if (!bdEndpoint.region) {
178
- regions = [api.functionsDefaultRegion()];
178
+ regions = [exports.REGION_TBD];
179
179
  }
180
180
  else if (Array.isArray(bdEndpoint.region)) {
181
181
  regions = params.resolveList(bdEndpoint.region, paramValues);
@@ -15,6 +15,7 @@ const gcf = require("../../gcp/cloudfunctions");
15
15
  const gcfv2 = require("../../gcp/cloudfunctionsv2");
16
16
  const backend = require("./backend");
17
17
  const experiments = require("../../experiments");
18
+ const supported = require("./runtimes/supported");
18
19
  const backend_1 = require("./backend");
19
20
  const extensions_1 = require("../extensions");
20
21
  const getProjectNumber_1 = require("../../getProjectNumber");
@@ -54,8 +55,10 @@ async function uploadSourceV2(projectId, projectNumber, source, wantBackend) {
54
55
  file: source.functionsSourceV2,
55
56
  stream: exports.createReadStream(source.functionsSourceV2),
56
57
  };
57
- if (!experiments.isEnabled("functionsrunapionly") &&
58
- !v2Endpoints.some((e) => e.platform === "run")) {
58
+ const isDart = v2Endpoints.some((e) => supported.runtimeIsLanguage(e.runtime, "dart"));
59
+ const useApiOnly = experiments.isEnabled("functionsrunapionly") ||
60
+ (isDart && experiments.isEnabled("dartfunctions"));
61
+ if (!useApiOnly && !v2Endpoints.some((e) => e.platform === "run")) {
59
62
  if (process.env.GOOGLE_CLOUD_QUOTA_PROJECT) {
60
63
  (0, utils_1.logLabeledWarning)("functions", "GOOGLE_CLOUD_QUOTA_PROJECT is not usable when uploading source for Cloud Functions.");
61
64
  }
@@ -2,6 +2,8 @@
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.EVENTARC_SOURCE_ENV = void 0;
4
4
  exports.prepare = prepare;
5
+ exports.matchRegionsForExisting = matchRegionsForExisting;
6
+ exports.resolveDefaultRegions = resolveDefaultRegions;
5
7
  exports.inferDetailsFromExisting = inferDetailsFromExisting;
6
8
  exports.updateEndpointTargetedStatus = updateEndpointTargetedStatus;
7
9
  exports.inferBlockingDetails = inferBlockingDetails;
@@ -24,6 +26,7 @@ const ensure = require("./ensure");
24
26
  const api_1 = require("../../api");
25
27
  const functionsDeployHelper_1 = require("./functionsDeployHelper");
26
28
  const utils_1 = require("../../utils");
29
+ const triggerSupport_1 = require("./runtimes/dart/triggerSupport");
27
30
  const prepareFunctionsUpload_1 = require("./prepareFunctionsUpload");
28
31
  const prompts_1 = require("./prompts");
29
32
  const projectUtils_1 = require("../../projectUtils");
@@ -190,6 +193,7 @@ async function prepare(context, options, payload) {
190
193
  payload.functions[codebase] = { wantBackend, haveBackend };
191
194
  }
192
195
  for (const [codebase, { wantBackend, haveBackend }] of Object.entries(payload.functions)) {
196
+ await resolveDefaultRegions(wantBackend, haveBackend);
193
197
  inferDetailsFromExisting(wantBackend, haveBackend, codebaseUsesEnvs.includes(codebase));
194
198
  await (0, triggerRegionHelper_1.ensureTriggerRegions)(wantBackend);
195
199
  resolveCpuAndConcurrency(wantBackend);
@@ -200,6 +204,7 @@ async function prepare(context, options, payload) {
200
204
  const haveBackend = backend.merge(...Object.values(haveBackends));
201
205
  await ensureAllRequiredAPIsEnabled(projectNumber, wantBackend);
202
206
  await warnIfNewGenkitFunctionIsMissingSecrets(wantBackend, haveBackend, options);
207
+ warnIfDartBackendHasUnsupportedTriggers(wantBackend);
203
208
  const matchingBackend = backend.matchingBackend(wantBackend, (endpoint) => {
204
209
  return (0, functionsDeployHelper_1.endpointMatchesAnyFilter)(endpoint, context.filters);
205
210
  });
@@ -214,6 +219,41 @@ async function prepare(context, options, payload) {
214
219
  validate.checkFiltersIntegrity(wantBackends, context.filters);
215
220
  (0, applyHash_1.applyBackendHashToBackends)(wantBackends, context);
216
221
  }
222
+ function moveEndpointToRegion(backend, endpoint, region) {
223
+ endpoint.region = region;
224
+ backend.endpoints[region] = backend.endpoints[region] || {};
225
+ backend.endpoints[region][endpoint.id] = endpoint;
226
+ delete backend.endpoints[build.REGION_TBD][endpoint.id];
227
+ if (Object.keys(backend.endpoints[build.REGION_TBD]).length === 0) {
228
+ delete backend.endpoints[build.REGION_TBD];
229
+ }
230
+ }
231
+ function matchRegionsForExisting(want, have) {
232
+ for (const [id, wantE] of Object.entries(want.endpoints[build.REGION_TBD] || {})) {
233
+ let matching;
234
+ for (const region of Object.keys(have.endpoints)) {
235
+ if (region === build.REGION_TBD) {
236
+ continue;
237
+ }
238
+ if (have.endpoints[region][id]) {
239
+ if (matching) {
240
+ throw new error_1.FirebaseError(`Cannot resolve default region for function ${id}. It exists in multiple regions. The region must be specified to continue.`);
241
+ }
242
+ matching = have.endpoints[region][id];
243
+ }
244
+ }
245
+ if (!matching) {
246
+ continue;
247
+ }
248
+ moveEndpointToRegion(want, wantE, matching.region);
249
+ }
250
+ }
251
+ async function resolveDefaultRegions(want, have) {
252
+ matchRegionsForExisting(want, have);
253
+ for (const endpoint of Object.values(want.endpoints[build.REGION_TBD] || {})) {
254
+ moveEndpointToRegion(want, endpoint, "us-central1");
255
+ }
256
+ }
217
257
  function inferDetailsFromExisting(want, have, usedDotenv) {
218
258
  for (const wantE of backend.allEndpoints(want)) {
219
259
  const haveE = have.endpoints[wantE.region]?.[wantE.id];
@@ -347,6 +387,19 @@ async function loadCodebases(config, options, firebaseConfig, runtimeConfig, fil
347
387
  }
348
388
  return wantBuilds;
349
389
  }
390
+ function warnIfDartBackendHasUnsupportedTriggers(want) {
391
+ const dartEndpoints = backend.allEndpoints(want).filter(triggerSupport_1.isDartEndpoint);
392
+ if (dartEndpoints.length === 0) {
393
+ return;
394
+ }
395
+ const { emulatorOnly, experimental } = (0, triggerSupport_1.classifyNonProductionEndpoints)(dartEndpoints);
396
+ const unsupported = [...emulatorOnly, ...experimental];
397
+ if (unsupported.length > 0) {
398
+ (0, utils_1.logLabeledWarning)("functions", `The following Dart functions use triggers that are not yet supported for production deployment: ${unsupported.map((ep) => ep.id).join(", ")}. ` +
399
+ "They will be deployed but may not work as expected. " +
400
+ "See https://github.com/firebase/firebase-functions-dart for current trigger support.");
401
+ }
402
+ }
350
403
  async function warnIfNewGenkitFunctionIsMissingSecrets(have, want, options) {
351
404
  if (options.force) {
352
405
  return;