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
@@ -68,68 +68,81 @@ class Fabricator {
68
68
  totalTime: 0,
69
69
  results: [],
70
70
  };
71
- const deployChangesets = Object.values(plan).map(async (changes) => {
72
- const results = await this.applyChangeset(changes);
73
- summary.results.push(...results);
74
- return;
71
+ const changesets = Object.values(plan);
72
+ const scraperV1 = new sourceTokenScraper_1.SourceTokenScraper();
73
+ const scraperV2 = new sourceTokenScraper_1.SourceTokenScraper();
74
+ const createAndUpdatePromises = changesets.map((changes) => {
75
+ return this.applyUpserts(changes, scraperV1, scraperV2);
75
76
  });
76
- const promiseResults = await utils.allSettled(deployChangesets);
77
- const errs = promiseResults
78
- .filter((r) => r.status === "rejected")
79
- .map((r) => r.reason);
80
- if (errs.length) {
81
- logger_1.logger.debug("Fabricator.applyRegionalChanges returned an unhandled exception. This should never happen", JSON.stringify(errs, null, 2));
82
- }
77
+ const createAndUpdateResultsArray = await Promise.allSettled(createAndUpdatePromises);
78
+ summary.results = createAndUpdateResultsArray.reduce((acc, r) => {
79
+ if (r.status === "fulfilled") {
80
+ return [...acc, ...r.value];
81
+ }
82
+ logger_1.logger.debug("Fabricator.applyUpserts returned an unhandled exception.", JSON.stringify(r.reason, null, 2));
83
+ return acc;
84
+ }, []);
85
+ const hasFailures = summary.results.some((r) => r.error);
86
+ if (hasFailures) {
87
+ utils.logLabeledWarning("functions", "Deploys failed. Skipping deletes.");
88
+ summary.results = changesets.reduce((accum, changes) => {
89
+ const currentAborts = changes.endpointsToDelete.map((endpoint) => ({
90
+ endpoint,
91
+ durationMs: 0,
92
+ error: new reporter.AbortedDeploymentError(endpoint),
93
+ }));
94
+ return [...accum, ...currentAborts];
95
+ }, summary.results);
96
+ summary.totalTime = timer.stop();
97
+ return summary;
98
+ }
99
+ const deleteResultsArray = await Promise.allSettled(changesets.map((changes) => this.applyDeletes(changes)));
100
+ const deleteResults = deleteResultsArray.reduce((acc, r) => {
101
+ if (r.status === "fulfilled") {
102
+ return [...acc, ...r.value];
103
+ }
104
+ logger_1.logger.debug("Fabricator.applyDeletes returned an unhandled exception. This should never happen", JSON.stringify(r.reason, null, 2));
105
+ return acc;
106
+ }, []);
107
+ summary.results.push(...deleteResults);
83
108
  summary.totalTime = timer.stop();
84
109
  return summary;
85
110
  }
86
- async applyChangeset(changes) {
87
- const deployResults = [];
88
- const handle = async (op, endpoint, fn) => {
89
- const timer = new timer_1.Timer();
90
- const result = { endpoint };
91
- try {
92
- await fn();
93
- this.logOpSuccess(op, endpoint);
94
- }
95
- catch (err) {
96
- result.error = err;
97
- }
98
- result.durationMs = timer.stop();
99
- deployResults.push(result);
100
- };
101
- const upserts = [];
102
- const scraperV1 = new sourceTokenScraper_1.SourceTokenScraper();
103
- const scraperV2 = new sourceTokenScraper_1.SourceTokenScraper();
111
+ async applyUpserts(changes, scraperV1, scraperV2) {
112
+ const ops = [];
104
113
  for (const endpoint of changes.endpointsToCreate) {
105
114
  this.logOpStart("creating", endpoint);
106
- upserts.push(handle("create", endpoint, () => this.createEndpoint(endpoint, scraperV1, scraperV2)));
115
+ ops.push(this.wrapOperation("create", endpoint, () => this.createEndpoint(endpoint, scraperV1, scraperV2)));
107
116
  }
108
117
  for (const endpoint of changes.endpointsToSkip) {
109
118
  utils.logSuccess(this.getLogSuccessMessage("skip", endpoint));
110
119
  }
111
120
  for (const update of changes.endpointsToUpdate) {
112
121
  this.logOpStart("updating", update.endpoint);
113
- upserts.push(handle("update", update.endpoint, () => this.updateEndpoint(update, scraperV1, scraperV2)));
122
+ ops.push(this.wrapOperation("update", update.endpoint, () => this.updateEndpoint(update, scraperV1, scraperV2)));
114
123
  }
115
- await utils.allSettled(upserts);
116
- if (deployResults.find((r) => r.error)) {
117
- for (const endpoint of changes.endpointsToDelete) {
118
- deployResults.push({
119
- endpoint,
120
- durationMs: 0,
121
- error: new reporter.AbortedDeploymentError(endpoint),
122
- });
123
- }
124
- return deployResults;
125
- }
126
- const deletes = [];
124
+ return Promise.all(ops);
125
+ }
126
+ async applyDeletes(changes) {
127
+ const ops = [];
127
128
  for (const endpoint of changes.endpointsToDelete) {
128
129
  this.logOpStart("deleting", endpoint);
129
- deletes.push(handle("delete", endpoint, () => this.deleteEndpoint(endpoint)));
130
+ ops.push(this.wrapOperation("delete", endpoint, () => this.deleteEndpoint(endpoint)));
131
+ }
132
+ return Promise.all(ops);
133
+ }
134
+ async wrapOperation(op, endpoint, fn) {
135
+ const timer = new timer_1.Timer();
136
+ const result = { endpoint };
137
+ try {
138
+ await fn();
139
+ this.logOpSuccess(op, endpoint);
140
+ }
141
+ catch (err) {
142
+ result.error = err;
130
143
  }
131
- await utils.allSettled(deletes);
132
- return deployResults;
144
+ result.durationMs = timer.stop();
145
+ return result;
133
146
  }
134
147
  async createEndpoint(endpoint, scraperV1, scraperV2) {
135
148
  endpoint.labels = { ...endpoint.labels, ...deploymentTool.labels() };
@@ -178,7 +178,7 @@ function checkForIllegalUpdate(want, have) {
178
178
  return "an HTTPS";
179
179
  }
180
180
  else if (backend.isDataConnectGraphqlTriggered(e)) {
181
- return "a Data Connect HTTPS";
181
+ return "a SQL Connect HTTPS";
182
182
  }
183
183
  else if (backend.isCallableTriggered(e)) {
184
184
  return "a callable";
@@ -13,12 +13,14 @@ const error_1 = require("../../../../error");
13
13
  const utils_1 = require("../../../../utils");
14
14
  const registry_1 = require("../../../../emulator/registry");
15
15
  const types_1 = require("../../../../emulator/types");
16
+ const experiments = require("../../../../experiments");
16
17
  async function tryCreateDelegate(context) {
17
18
  const pubspecYamlPath = path.join(context.sourceDir, "pubspec.yaml");
18
19
  if (!(await (0, util_1.promisify)(fs.exists)(pubspecYamlPath))) {
19
20
  logger_1.logger.debug("Customer code is not Dart code.");
20
21
  return;
21
22
  }
23
+ experiments.assertEnabled("dartfunctions", "use Dart functions");
22
24
  const runtime = context.runtime ?? supported.latest("dart");
23
25
  if (!supported.isRuntime(runtime)) {
24
26
  throw new error_1.FirebaseError(`Runtime ${runtime} is not a valid Dart runtime`);
@@ -28,7 +30,7 @@ async function tryCreateDelegate(context) {
28
30
  }
29
31
  return Promise.resolve(new Delegate(context.projectId, context.sourceDir, runtime));
30
32
  }
31
- const MIN_DART_SDK_VERSION = "3.8.0";
33
+ const MIN_DART_SDK_VERSION = "3.9.0";
32
34
  exports.DART_ENTRY_POINT = "bin/server.dart";
33
35
  class Delegate {
34
36
  constructor(projectId, sourceDir, runtime) {
@@ -0,0 +1,123 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.endpointSupportLevel = endpointSupportLevel;
4
+ exports.isDartEndpoint = isDartEndpoint;
5
+ exports.classifyNonProductionEndpoints = classifyNonProductionEndpoints;
6
+ exports.triggerTypeLabel = triggerTypeLabel;
7
+ exports.groupByTriggerLabel = groupByTriggerLabel;
8
+ const backend = require("../../backend");
9
+ const supported = require("../supported");
10
+ const constants_1 = require("../../../../emulator/constants");
11
+ const EMULATOR_ONLY_SERVICES = new Set([
12
+ constants_1.Constants.SERVICE_FIRESTORE,
13
+ constants_1.Constants.SERVICE_REALTIME_DATABASE,
14
+ constants_1.Constants.SERVICE_STORAGE,
15
+ ]);
16
+ const EXPERIMENTAL_SERVICES = new Set([
17
+ constants_1.Constants.SERVICE_PUBSUB,
18
+ constants_1.Constants.SERVICE_EVENTARC,
19
+ constants_1.Constants.SERVICE_AUTH,
20
+ constants_1.Constants.SERVICE_FIREALERTS,
21
+ constants_1.Constants.SERVICE_REMOTE_CONFIG,
22
+ constants_1.Constants.SERVICE_TEST_LAB,
23
+ constants_1.Constants.SERVICE_CLOUD_TASKS,
24
+ ]);
25
+ function endpointSupportLevel(ep) {
26
+ if (backend.isHttpsTriggered(ep) || backend.isCallableTriggered(ep)) {
27
+ if (backend.isTaskQueueTriggered(ep)) {
28
+ return "experimental";
29
+ }
30
+ return "production";
31
+ }
32
+ if (backend.isScheduleTriggered(ep)) {
33
+ return "experimental";
34
+ }
35
+ if (backend.isBlockingTriggered(ep)) {
36
+ return "experimental";
37
+ }
38
+ if (backend.isEventTriggered(ep)) {
39
+ if (ep.eventTrigger.channel) {
40
+ return "experimental";
41
+ }
42
+ const service = ep.eventTrigger.eventType
43
+ ? serviceFromEventType(ep.eventTrigger.eventType)
44
+ : undefined;
45
+ if (service && EMULATOR_ONLY_SERVICES.has(service)) {
46
+ return "emulatorOnly";
47
+ }
48
+ if (service && EXPERIMENTAL_SERVICES.has(service)) {
49
+ return "experimental";
50
+ }
51
+ }
52
+ return "experimental";
53
+ }
54
+ function isDartEndpoint(ep) {
55
+ return supported.runtimeIsLanguage(ep.runtime, "dart");
56
+ }
57
+ function classifyNonProductionEndpoints(endpoints) {
58
+ const emulatorOnly = [];
59
+ const experimental = [];
60
+ for (const ep of endpoints) {
61
+ switch (endpointSupportLevel(ep)) {
62
+ case "production":
63
+ break;
64
+ case "emulatorOnly":
65
+ emulatorOnly.push(ep);
66
+ break;
67
+ case "experimental":
68
+ experimental.push(ep);
69
+ break;
70
+ }
71
+ }
72
+ return { emulatorOnly, experimental };
73
+ }
74
+ function triggerTypeLabel(ep) {
75
+ if (backend.isScheduleTriggered(ep))
76
+ return "scheduler";
77
+ if (backend.isTaskQueueTriggered(ep))
78
+ return "tasks";
79
+ if (backend.isBlockingTriggered(ep))
80
+ return "identity";
81
+ if (backend.isCallableTriggered(ep))
82
+ return "callable";
83
+ if (backend.isHttpsTriggered(ep))
84
+ return "https";
85
+ if (backend.isEventTriggered(ep)) {
86
+ if (ep.eventTrigger.channel)
87
+ return "eventarc";
88
+ const svc = serviceFromEventType(ep.eventTrigger.eventType);
89
+ return svc ? constants_1.Constants.getServiceName(svc) : ep.eventTrigger.eventType;
90
+ }
91
+ return "unknown";
92
+ }
93
+ function groupByTriggerLabel(endpoints) {
94
+ const groups = new Map();
95
+ for (const ep of endpoints) {
96
+ const label = triggerTypeLabel(ep);
97
+ const ids = groups.get(label) ?? [];
98
+ ids.push(ep.id);
99
+ groups.set(label, ids);
100
+ }
101
+ return groups;
102
+ }
103
+ function serviceFromEventType(eventType) {
104
+ if (eventType.includes("firestore"))
105
+ return constants_1.Constants.SERVICE_FIRESTORE;
106
+ if (eventType.includes("database"))
107
+ return constants_1.Constants.SERVICE_REALTIME_DATABASE;
108
+ if (eventType.includes("pubsub"))
109
+ return constants_1.Constants.SERVICE_PUBSUB;
110
+ if (eventType.includes("storage"))
111
+ return constants_1.Constants.SERVICE_STORAGE;
112
+ if (eventType.includes("eventarc"))
113
+ return constants_1.Constants.SERVICE_EVENTARC;
114
+ if (eventType.includes("firebasealerts"))
115
+ return constants_1.Constants.SERVICE_FIREALERTS;
116
+ if (eventType.includes("auth"))
117
+ return constants_1.Constants.SERVICE_AUTH;
118
+ if (eventType.includes("remoteconfig"))
119
+ return constants_1.Constants.SERVICE_REMOTE_CONFIG;
120
+ if (eventType.includes("testlab") || eventType.includes("testing"))
121
+ return constants_1.Constants.SERVICE_TEST_LAB;
122
+ return undefined;
123
+ }
@@ -7,13 +7,10 @@ const python = require("./python");
7
7
  const validate = require("../validate");
8
8
  const error_1 = require("../../../error");
9
9
  const supported = require("./supported");
10
- const experiments = require("../../../experiments");
11
10
  const factories = [
12
11
  node.tryCreateDelegate,
13
12
  python.tryCreateDelegate,
14
- (ctx) => experiments.isEnabled("functionsrunapionly")
15
- ? dart.tryCreateDelegate(ctx)
16
- : Promise.resolve(undefined),
13
+ dart.tryCreateDelegate,
17
14
  ];
18
15
  async function getRuntimeDelegate(context) {
19
16
  const { projectDir, sourceDir, runtime } = context;
@@ -8,6 +8,7 @@ const ailogicApi = require("../../../gcp/ailogic");
8
8
  const ailogic_1 = require("../../../gcp/ailogic");
9
9
  Object.defineProperty(exports, "AI_LOGIC_BEFORE_GENERATE_CONTENT", { enumerable: true, get: function () { return ailogic_1.AI_LOGIC_BEFORE_GENERATE_CONTENT; } });
10
10
  Object.defineProperty(exports, "AI_LOGIC_AFTER_GENERATE_CONTENT", { enumerable: true, get: function () { return ailogic_1.AI_LOGIC_AFTER_GENERATE_CONTENT; } });
11
+ const utils_1 = require("../../../utils");
11
12
  exports.AI_LOGIC_EVENTS = [
12
13
  ailogic_1.AI_LOGIC_BEFORE_GENERATE_CONTENT,
13
14
  ailogic_1.AI_LOGIC_AFTER_GENERATE_CONTENT,
@@ -63,7 +64,17 @@ class AILogicService {
63
64
  if (!isAILogicEvent(ep)) {
64
65
  return;
65
66
  }
66
- await ailogicApi.deleteBlockingFunction(ep);
67
+ try {
68
+ await ailogicApi.deleteBlockingFunction(ep);
69
+ }
70
+ catch (err) {
71
+ if ((0, error_1.getErrStatus)(err) === 404) {
72
+ (0, utils_1.logLabeledWarning)("functions", `Tried deleting trigger registration for function ${ep.id} but it is not currently registered`);
73
+ }
74
+ else {
75
+ throw err;
76
+ }
77
+ }
67
78
  }
68
79
  }
69
80
  exports.AILogicService = AILogicService;
@@ -12,7 +12,7 @@ function ensureDataConnectTriggerRegion(endpoint) {
12
12
  endpoint.eventTrigger.region = endpoint.region;
13
13
  }
14
14
  if (endpoint.eventTrigger.region !== endpoint.region) {
15
- throw new error_1.FirebaseError("The Firebase Data Connect trigger location must match the function region.");
15
+ throw new error_1.FirebaseError("The Firebase SQL Connect trigger location must match the function region.");
16
16
  }
17
17
  return Promise.resolve();
18
18
  }
@@ -49,7 +49,7 @@ exports.EMULATOR_DESCRIPTION = {
49
49
  storage: "Storage Emulator",
50
50
  extensions: "Extensions Emulator",
51
51
  eventarc: "Eventarc Emulator",
52
- dataconnect: "Data Connect Emulator",
52
+ dataconnect: "SQL Connect Emulator",
53
53
  tasks: "Cloud Tasks Emulator",
54
54
  };
55
55
  exports.DEFAULT_HOST = "localhost";
@@ -567,10 +567,10 @@ async function startAll(options, showUI = true, runningTestScript = false) {
567
567
  if (listenForEmulator.dataconnect) {
568
568
  const config = (0, load_1.readFirebaseJson)(options.config);
569
569
  if (!config.length) {
570
- throw new error_1.FirebaseError("No Data Connect service found in firebase.json");
570
+ throw new error_1.FirebaseError("No SQL Connect service found in firebase.json");
571
571
  }
572
572
  else if (config.length > 1) {
573
- logger_1.logger.warn(`TODO: Add support for multiple services in the Data Connect emulator. Currently emulating first service ${config[0].source}`);
573
+ logger_1.logger.warn(`TODO: Add support for multiple services in the SQL Connect emulator. Currently emulating first service ${config[0].source}`);
574
574
  }
575
575
  const args = {
576
576
  listen: listenForEmulator.dataconnect,
@@ -87,10 +87,10 @@ class DataConnectEmulator {
87
87
  connStr = `postgres://${connectableHost}:${pgPort}/${dbId}?sslmode=disable`;
88
88
  server.on("error", (err) => {
89
89
  if (err instanceof error_1.FirebaseError) {
90
- this.logger.logLabeled("ERROR", "Data Connect", `${err}`);
90
+ this.logger.logLabeled("ERROR", "SQL Connect", `${err}`);
91
91
  }
92
92
  else {
93
- this.logger.logLabeled("ERROR", "dataconnect", `Postgres threw an unexpected error, shutting down the Data Connect emulator: ${err}`);
93
+ this.logger.logLabeled("ERROR", "dataconnect", `Postgres threw an unexpected error, shutting down the SQL Connect emulator: ${err}`);
94
94
  }
95
95
  void (0, controller_1.cleanShutdown)();
96
96
  });
@@ -103,14 +103,14 @@ class DataConnectEmulator {
103
103
  async connect() {
104
104
  const emuInfo = await this.emulatorClient.getInfo();
105
105
  if (!emuInfo) {
106
- this.logger.logLabeled("ERROR", "dataconnect", "Could not connect to Data Connect emulator. Check dataconnect-debug.log for more details.");
106
+ this.logger.logLabeled("ERROR", "dataconnect", "Could not connect to SQL Connect emulator. Check dataconnect-debug.log for more details.");
107
107
  return Promise.reject();
108
108
  }
109
109
  return Promise.resolve();
110
110
  }
111
111
  async stop() {
112
112
  if (this.usingExistingEmulator) {
113
- this.logger.logLabeled("INFO", "dataconnect", "Skipping cleanup of Data Connect emulator, as it was not started by this process.");
113
+ this.logger.logLabeled("INFO", "dataconnect", "Skipping cleanup of SQL Connect emulator, as it was not started by this process.");
114
114
  return;
115
115
  }
116
116
  if (this.postgresServer) {
@@ -149,7 +149,7 @@ class DataConnectEmulator {
149
149
  await this.postgresServer.exportData(path.join(this.args.config.path(exportPath), "postgres.tar.gz"));
150
150
  }
151
151
  else {
152
- throw new error_1.FirebaseError("The Data Connect emulator is currently connected to a separate Postgres instance. Export is not supported.");
152
+ throw new error_1.FirebaseError("The SQL Connect emulator is currently connected to a separate Postgres instance. Export is not supported.");
153
153
  }
154
154
  }
155
155
  static async generate(args) {
@@ -176,7 +176,7 @@ class DataConnectEmulator {
176
176
  }
177
177
  catch (e) {
178
178
  if ((0, downloadableEmulators_1.isIncomaptibleArchError)(e)) {
179
- reject(new error_1.FirebaseError(`Unknown system error when running the Data Connect toolkit. ` +
179
+ reject(new error_1.FirebaseError(`Unknown system error when running the SQL Connect toolkit. ` +
180
180
  `You may be able to fix this by installing Rosetta: ` +
181
181
  `softwareupdate --install-rosetta`));
182
182
  }
@@ -195,17 +195,17 @@ class DataConnectEmulator {
195
195
  const env = await DataConnectEmulator.getEnv(args.account);
196
196
  const res = childProcess.spawnSync(commandInfo.binary, cmd, { encoding: "utf-8", env });
197
197
  if ((0, downloadableEmulators_1.isIncomaptibleArchError)(res.error)) {
198
- throw new error_1.FirebaseError(`Unkown system error when running the Data Connect toolkit. ` +
198
+ throw new error_1.FirebaseError(`Unkown system error when running the SQL Connect toolkit. ` +
199
199
  `You may be able to fix this by installing Rosetta: ` +
200
200
  `softwareupdate --install-rosetta`);
201
201
  }
202
202
  if (res.error) {
203
- throw new error_1.FirebaseError(`Error starting up Data Connect build: ${res.error.message}`, {
203
+ throw new error_1.FirebaseError(`Error starting up SQL Connect build: ${res.error.message}`, {
204
204
  original: res.error,
205
205
  });
206
206
  }
207
207
  if (res.status !== 0) {
208
- throw new error_1.FirebaseError(`Unable to build your Data Connect schema and connectors (exit code ${res.status}): ${res.stderr}`);
208
+ throw new error_1.FirebaseError(`Unable to build your SQL Connect schema and connectors (exit code ${res.status}): ${res.stderr}`);
209
209
  }
210
210
  if (res.stderr) {
211
211
  emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATACONNECT).log("DEBUG", res.stderr);
@@ -219,27 +219,27 @@ class DataConnectEmulator {
219
219
  }
220
220
  async connectToPostgres(connectionString, database, serviceId) {
221
221
  if (!connectionString) {
222
- const msg = `No Postgres connection found. The Data Connect emulator will not be able to execute operations.`;
222
+ const msg = `No Postgres connection found. The SQL Connect emulator will not be able to execute operations.`;
223
223
  throw new error_1.FirebaseError(msg);
224
224
  }
225
225
  const MAX_RETRIES = 3;
226
226
  for (let i = 1; i <= MAX_RETRIES; i++) {
227
227
  try {
228
- this.logger.logLabeled("DEBUG", "Data Connect", `Connecting to ${connectionString}}...`);
228
+ this.logger.logLabeled("DEBUG", "SQL Connect", `Connecting to ${connectionString}}...`);
229
229
  connectionString.toString();
230
230
  await this.emulatorClient.configureEmulator({
231
231
  connectionString: connectionString.toString(),
232
232
  database,
233
233
  serviceId,
234
234
  });
235
- this.logger.logLabeled("DEBUG", "Data Connect", `Successfully connected to ${connectionString}}`);
235
+ this.logger.logLabeled("DEBUG", "SQL Connect", `Successfully connected to ${connectionString}}`);
236
236
  return true;
237
237
  }
238
238
  catch (err) {
239
239
  if (i === MAX_RETRIES) {
240
240
  throw err;
241
241
  }
242
- this.logger.logLabeled("DEBUG", "Data Connect", `Retrying connectToPostgress call (${i} of ${MAX_RETRIES} attempts): ${err}`);
242
+ this.logger.logLabeled("DEBUG", "SQL Connect", `Retrying connectToPostgress call (${i} of ${MAX_RETRIES} attempts): ${err}`);
243
243
  await new Promise((resolve) => setTimeout(resolve, 2000));
244
244
  }
245
245
  }
@@ -271,7 +271,7 @@ class DataConnectEmulatorClient {
271
271
  }
272
272
  catch (err) {
273
273
  if (err.status === 500) {
274
- throw new error_1.FirebaseError(`Data Connect emulator: ${err?.context?.body?.message}`);
274
+ throw new error_1.FirebaseError(`SQL Connect emulator: ${err?.context?.body?.message}`);
275
275
  }
276
276
  throw err;
277
277
  }
@@ -7,7 +7,7 @@ const portUtils = require("./portUtils");
7
7
  const utils_1 = require("../utils");
8
8
  const dataconnectEmulator_1 = require("./dataconnectEmulator");
9
9
  const downloadableEmulators_1 = require("./downloadableEmulators");
10
- const name = "Data Connect Toolkit";
10
+ const name = "SQL Connect Toolkit";
11
11
  class DataConnectToolkitController {
12
12
  static async start(args) {
13
13
  if (this.isRunning || this.instance) {
@@ -28,7 +28,7 @@ class DataConnectToolkitController {
28
28
  this.isRunning = false;
29
29
  }
30
30
  catch (e) {
31
- throw new error_1.FirebaseError(`Data Connect Toolkit failed to stop with error: ${e}`);
31
+ throw new error_1.FirebaseError(`SQL Connect Toolkit failed to stop with error: ${e}`);
32
32
  }
33
33
  }
34
34
  static getVersion() {
@@ -44,46 +44,46 @@
44
44
  }
45
45
  },
46
46
  "pubsub": {
47
- "version": "0.8.29",
48
- "expectedSize": 52906482,
49
- "expectedChecksum": "8345b0a923dda5634dd56a25f913cf37",
50
- "expectedChecksumSHA256": "31228112fb95a6818d13a88e801f4be6fb5ea5b601175b74528cc61823ea5507",
51
- "remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.29.zip",
52
- "downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.29.zip",
53
- "binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.29/pubsub-emulator/bin/cloud-pubsub-emulator"
47
+ "version": "0.8.30",
48
+ "expectedSize": 52917173,
49
+ "expectedChecksum": "f7935320d11894d0c4cd26dd064ee42f",
50
+ "expectedChecksumSHA256": "aabf028a55ec3f06fe2223471dad26623be542848abebd7563f8f0b8697dd2a3",
51
+ "remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.30.zip",
52
+ "downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.30.zip",
53
+ "binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.30/pubsub-emulator/bin/cloud-pubsub-emulator"
54
54
  },
55
55
  "dataconnect": {
56
56
  "darwin": {
57
- "version": "3.4.1",
58
- "expectedSize": 32274112,
59
- "expectedChecksum": "ccd7e0be14784f6ac6f6b2102180e062",
60
- "expectedChecksumSHA256": "2ae6cb5c5da239d272f29b1f14c4630a45ed8e841f8eadd330189dc821fb93bd",
61
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.4.1",
62
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.1"
57
+ "version": "3.4.5",
58
+ "expectedSize": 32269984,
59
+ "expectedChecksum": "5c50dbd6f508998f748195691b5b0678",
60
+ "expectedChecksumSHA256": "2053e5c47dbe52c923be196cfd7ff70b31f9e2fbde0e7eaeb20c31ee91e8a8b2",
61
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.4.5",
62
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.5"
63
63
  },
64
64
  "darwin_arm64": {
65
- "version": "3.4.1",
66
- "expectedSize": 30437282,
67
- "expectedChecksum": "ea76099299d6f50862d9a0bb194bb921",
68
- "expectedChecksumSHA256": "ec51f9bcc0668ca25713c57385d2f12a2776ee64170dcdd861968be30925c7be",
69
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.4.1",
70
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.1"
65
+ "version": "3.4.5",
66
+ "expectedSize": 30437250,
67
+ "expectedChecksum": "40f531afa3664284bc319f9721388816",
68
+ "expectedChecksumSHA256": "8dd59223a43b0e07ac2c7e40abb5e1a56ea7b7b787d23ceed20f8fe9af9c88e0",
69
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.4.5",
70
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.5"
71
71
  },
72
72
  "win32": {
73
- "version": "3.4.1",
74
- "expectedSize": 32315904,
75
- "expectedChecksum": "2d433690efb1e7931d0d5ab4fe5a6d25",
76
- "expectedChecksumSHA256": "7d8ecff49ac0492569c855badbabd5b1600a2ff63814900a1bbea8b16d96d76a",
77
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.4.1",
78
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.1.exe"
73
+ "version": "3.4.5",
74
+ "expectedSize": 32311296,
75
+ "expectedChecksum": "406caa49a4d48c03ade3da4a4a6b08b3",
76
+ "expectedChecksumSHA256": "e6e392f5bc3c32faa95d9b1139497492e51c46cb354e30e65c20d575ee3ba9cf",
77
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.4.5",
78
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.5.exe"
79
79
  },
80
80
  "linux": {
81
- "version": "3.4.1",
82
- "expectedSize": 31432888,
83
- "expectedChecksum": "8e11775e6df3d5dbe583f1f346f299f6",
84
- "expectedChecksumSHA256": "7124f38854f72c7aa0daff91439825725cb31db138bc1c15976ca97aa27837c4",
85
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.4.1",
86
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.1"
81
+ "version": "3.4.5",
82
+ "expectedSize": 31428792,
83
+ "expectedChecksum": "2e09522cff69142b6882e71516ad0e3c",
84
+ "expectedChecksumSHA256": "86565d7724762e45a76a4627791b60248cfea81f332d45709d69be0e71a3c6ec",
85
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.4.5",
86
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.4.5"
87
87
  }
88
88
  }
89
89
  }
@@ -12,7 +12,6 @@ const ensureApiEnabled_1 = require("../ensureApiEnabled");
12
12
  const error_1 = require("../error");
13
13
  const optionsHelper_1 = require("../extensions/emulator/optionsHelper");
14
14
  const refs_1 = require("../extensions/refs");
15
- const shortenUrl_1 = require("../shortenUrl");
16
15
  const constants_1 = require("./constants");
17
16
  const download_1 = require("./download");
18
17
  const emulatorLogger_1 = require("./emulatorLogger");
@@ -218,7 +217,7 @@ class ExtensionsEmulator {
218
217
  style: { head: ["yellow"] },
219
218
  });
220
219
  for (const apiToWarn of apisToWarn) {
221
- const enablementUri = await (0, shortenUrl_1.shortenUrl)((0, ensureApiEnabled_1.enableApiURI)(this.args.projectId, apiToWarn.apiName));
220
+ const enablementUri = (0, ensureApiEnabled_1.enableApiURI)(this.args.projectId, apiToWarn.apiName);
222
221
  table.push([
223
222
  apiToWarn.apiName,
224
223
  apiToWarn.instanceIds.join(", "),
@@ -37,6 +37,7 @@ const env_1 = require("./env");
37
37
  const python_1 = require("../functions/python");
38
38
  const supported_1 = require("../deploy/functions/runtimes/supported");
39
39
  const dart_1 = require("../deploy/functions/runtimes/dart");
40
+ const triggerSupport_1 = require("../deploy/functions/runtimes/dart/triggerSupport");
40
41
  const EVENT_INVOKE_GA4 = "functions_invoke";
41
42
  const DATABASE_PATH_PATTERN = new RegExp("^projects/[^/]+/instances/([^/]+)/refs(/.*)$");
42
43
  class IPCConn {
@@ -388,6 +389,7 @@ class FunctionsEmulator {
388
389
  for (const e of endpoints) {
389
390
  e.codebase = emulatableBackend.codebase;
390
391
  }
392
+ this.logDartTriggerSupportWarnings(endpoints);
391
393
  return (0, functionsEmulatorShared_1.emulatedFunctionsFromEndpoints)(endpoints);
392
394
  }
393
395
  }
@@ -525,6 +527,19 @@ class FunctionsEmulator {
525
527
  }
526
528
  }
527
529
  }
530
+ logDartTriggerSupportWarnings(endpoints) {
531
+ const dartEndpoints = endpoints.filter(triggerSupport_1.isDartEndpoint);
532
+ if (dartEndpoints.length === 0) {
533
+ return;
534
+ }
535
+ const { emulatorOnly, experimental } = (0, triggerSupport_1.classifyNonProductionEndpoints)(dartEndpoints);
536
+ (0, triggerSupport_1.groupByTriggerLabel)(emulatorOnly).forEach((ids, label) => {
537
+ this.logger.logLabeled("WARN", "functions", `Dart ${clc.bold(label)} triggers work in the emulator but cannot be deployed to production yet: ${ids.join(", ")}`);
538
+ });
539
+ (0, triggerSupport_1.groupByTriggerLabel)(experimental).forEach((ids, label) => {
540
+ this.logger.logLabeled("WARN", "functions", `Dart ${clc.bold(label)} triggers are experimental and not yet fully supported: ${ids.join(", ")}`);
541
+ });
542
+ }
528
543
  async removeTriggers(toRemove) {
529
544
  for (const triggerKey of toRemove) {
530
545
  const definition = this.triggers[triggerKey].def;
@@ -117,13 +117,13 @@ class EmulatorHub extends ExpressBasedEmulator_1.ExpressBasedEmulator {
117
117
  app.post(EmulatorHub.PATH_CLEAR_DATA_CONNECT, async (req, res) => {
118
118
  if (req.headers.origin) {
119
119
  res.status(403).json({
120
- message: `Clear Data Connect cannot be triggered by external callers.`,
120
+ message: `Clear SQL Connect cannot be triggered by external callers.`,
121
121
  });
122
122
  }
123
- utils.logLabeledBullet("emulators", `Clearing data from Data Connect data sources.`);
123
+ utils.logLabeledBullet("emulators", `Clearing data from SQL Connect data sources.`);
124
124
  const instance = registry_1.EmulatorRegistry.get(types_1.Emulators.DATACONNECT);
125
125
  if (!instance) {
126
- res.status(400).json({ error: "The Data Connect emulator is not running." });
126
+ res.status(400).json({ error: "The SQL Connect emulator is not running." });
127
127
  return;
128
128
  }
129
129
  await instance.clearData();