firebase-tools 15.12.1-main.0 → 15.14.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 (42) hide show
  1. package/lib/apphosting/backend.js +12 -12
  2. package/lib/apphosting/constants.js +1 -1
  3. package/lib/apphosting/prompts.js +35 -0
  4. package/lib/command.js +36 -23
  5. package/lib/commands/apphosting-backends-list.js +5 -1
  6. package/lib/commands/ext-info.js +5 -1
  7. package/lib/deploy/functions/prepare.js +3 -1
  8. package/lib/deploy/functions/prepareFunctionsUpload.js +20 -9
  9. package/lib/deploy/functions/release/index.js +5 -0
  10. package/lib/deploy/functions/runtimes/supported/index.js +0 -4
  11. package/lib/deploy/functions/services/ailogic.js +5 -4
  12. package/lib/deploy/functions/services/index.js +2 -2
  13. package/lib/deploy/functions/validate.js +7 -1
  14. package/lib/emulator/controller.js +11 -0
  15. package/lib/emulator/downloadableEmulatorInfo.json +24 -24
  16. package/lib/emulator/downloadableEmulators.js +1 -0
  17. package/lib/emulator/functionsEmulator.js +5 -6
  18. package/lib/emulator/functionsRuntimeWorker.js +1 -1
  19. package/lib/experiments.js +1 -1
  20. package/lib/extensions/listExtensions.js +2 -0
  21. package/lib/frameworks/next/constants.js +2 -1
  22. package/lib/frameworks/next/index.js +3 -2
  23. package/lib/frameworks/next/utils.js +50 -12
  24. package/lib/functions/events/v2.js +10 -1
  25. package/lib/gcp/ailogic.js +7 -6
  26. package/lib/gcp/apphosting.js +6 -0
  27. package/lib/init/features/apphosting.js +11 -2
  28. package/lib/init/features/functions/index.js +7 -4
  29. package/lib/mcp/index.js +2 -1
  30. package/lib/mcp/tools/core/read_resources.js +1 -1
  31. package/lib/tsconfig.compile.tsbuildinfo +1 -1
  32. package/lib/tsconfig.publish.tsbuildinfo +1 -1
  33. package/package.json +2 -2
  34. package/schema/firebase-config.json +3 -0
  35. package/templates/extensions/typescript/package.lint.json +1 -1
  36. package/templates/extensions/typescript/package.nolint.json +1 -1
  37. package/templates/extensions/typescript/tsconfig.json +1 -0
  38. package/templates/init/functions/typescript/package-ongraphrequest.lint.json +1 -1
  39. package/templates/init/functions/typescript/package-ongraphrequest.nolint.json +1 -1
  40. package/templates/init/functions/typescript/package.lint.json +1 -1
  41. package/templates/init/functions/typescript/package.nolint.json +1 -1
  42. package/templates/init/functions/typescript/tsconfig.json +1 -0
@@ -35,7 +35,7 @@ const node_fetch_1 = require("node-fetch");
35
35
  const rollout_1 = require("./rollout");
36
36
  const fuzzy = require("fuzzy");
37
37
  const experiments_1 = require("../experiments");
38
- const DEFAULT_RUNTIME = "nodejs";
38
+ const prompts_1 = require("./prompts");
39
39
  const DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME = "firebase-app-hosting-compute";
40
40
  const apphostingPollerOptions = {
41
41
  apiOrigin: (0, api_1.apphostingOrigin)(),
@@ -101,17 +101,15 @@ async function doSetup(projectId, nonInteractive, webAppName, backendId, service
101
101
  }
102
102
  if (runtime === undefined && (0, experiments_1.isEnabled)("abiu")) {
103
103
  if (nonInteractive) {
104
- runtime = DEFAULT_RUNTIME;
104
+ runtime = prompts_1.DEFAULT_RUNTIME;
105
105
  }
106
106
  else {
107
- runtime = await (0, prompt_1.select)({
108
- message: "Which runtime do you want to use?",
109
- choices: [
110
- { name: "Node.js (default)", value: DEFAULT_RUNTIME },
111
- { name: "Node.js 22", value: "nodejs22" },
112
- ],
113
- default: DEFAULT_RUNTIME,
114
- });
107
+ runtime = await (0, prompts_1.promptRuntime)(projectId, location);
108
+ }
109
+ }
110
+ if (automaticBaseImageUpdatesDisabled === undefined && (0, experiments_1.isEnabled)("abiu")) {
111
+ if (!nonInteractive) {
112
+ automaticBaseImageUpdatesDisabled = !(await (0, prompts_1.promptAutomaticBaseImageUpdates)());
115
113
  }
116
114
  }
117
115
  const webApp = await app_1.webApps.getOrCreateWebApp(projectId, webAppName ? webAppName : null, backendId);
@@ -257,9 +255,11 @@ async function createBackend(projectId, location, backendId, serviceAccount, rep
257
255
  labels: deploymentTool.labels(),
258
256
  serviceAccount: serviceAccount || defaultServiceAccount,
259
257
  appId: webAppId,
260
- runtime: { value: runtime ?? "" },
261
- automaticBaseImageUpdatesDisabled,
262
258
  };
259
+ if ((0, experiments_1.isEnabled)("abiu")) {
260
+ backendReqBody.runtime = { value: runtime ?? "" };
261
+ backendReqBody.automaticBaseImageUpdatesDisabled = automaticBaseImageUpdatesDisabled;
262
+ }
263
263
  async function createBackendAndPoll() {
264
264
  const op = await apphosting.createBackend(projectId, location, backendReqBody, backendId);
265
265
  return await poller.pollOperation({
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.ALLOWED_DEPLOY_METHODS = exports.DEFAULT_DEPLOY_METHOD = exports.DEFAULT_LOCATION = void 0;
4
- exports.DEFAULT_LOCATION = "us-central1";
4
+ exports.DEFAULT_LOCATION = "us-east4";
5
5
  exports.DEFAULT_DEPLOY_METHOD = "github";
6
6
  exports.ALLOWED_DEPLOY_METHODS = [{ name: "Deploy using github", value: "github" }];
@@ -0,0 +1,35 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.DEFAULT_RUNTIME = void 0;
4
+ exports.promptRuntime = promptRuntime;
5
+ exports.promptAutomaticBaseImageUpdates = promptAutomaticBaseImageUpdates;
6
+ const prompt_1 = require("../prompt");
7
+ const utils_1 = require("../utils");
8
+ const apphosting = require("../gcp/apphosting");
9
+ exports.DEFAULT_RUNTIME = "nodejs";
10
+ async function promptRuntime(projectId, location) {
11
+ const choices = [{ name: "Node.js (default)", value: exports.DEFAULT_RUNTIME }];
12
+ try {
13
+ const supportedRuntimes = await apphosting.listSupportedRuntimes(projectId, location);
14
+ for (const r of supportedRuntimes) {
15
+ if (r.runtimeId !== exports.DEFAULT_RUNTIME) {
16
+ choices.push({ name: r.runtimeId, value: r.runtimeId });
17
+ }
18
+ }
19
+ }
20
+ catch (err) {
21
+ (0, utils_1.logWarning)("Failed to list supported runtimes. Falling back to hardcoded list.");
22
+ choices.push({ name: "nodejs22", value: "nodejs22" });
23
+ }
24
+ return await (0, prompt_1.select)({
25
+ message: "Which runtime do you want to use?",
26
+ choices: choices,
27
+ default: exports.DEFAULT_RUNTIME,
28
+ });
29
+ }
30
+ async function promptAutomaticBaseImageUpdates() {
31
+ return await (0, prompt_1.confirm)({
32
+ message: "Would you like to enable Automatic Base Image Updates (ABIU)?",
33
+ default: true,
34
+ });
35
+ }
package/lib/command.js CHANGED
@@ -111,22 +111,23 @@ class Command {
111
111
  });
112
112
  }
113
113
  const duration = Math.floor((process.uptime() - start) * 1000);
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", {
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", {
126
123
  command_name: this.name,
127
124
  duration,
128
- }),
129
- ]));
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);
130
131
  }
131
132
  process.exit();
132
133
  })
@@ -140,20 +141,25 @@ class Command {
140
141
  });
141
142
  }
142
143
  const duration = Math.floor((process.uptime() - start) * 1000);
143
- await (0, utils_1.withTimeout)(5000, Promise.all([
144
- (0, track_1.trackGA4)("command_execution", {
144
+ try {
145
+ const trackError = (0, track_1.trackGA4)("command_execution", {
145
146
  command_name: this.name,
146
147
  result: "error",
147
148
  interactive: (0, utils_1.getInheritedOption)(options, "nonInteractive") ? "false" : "true",
148
- }, duration),
149
- isEmulator
150
- ? (0, track_1.trackEmulator)("command_error", {
149
+ }, duration);
150
+ const tracks = [trackError];
151
+ if (isEmulator) {
152
+ tracks.push((0, track_1.trackEmulator)("command_error", {
151
153
  command_name: this.name,
152
154
  duration,
153
- error_type: err.exit === 1 ? "user" : "unexpected",
154
- })
155
- : Promise.resolve(),
156
- ]));
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
+ }
157
163
  client.errorOut(err);
158
164
  });
159
165
  });
@@ -178,6 +184,13 @@ class Command {
178
184
  if ((0, utils_1.getInheritedOption)(options, "config")) {
179
185
  options.configPath = (0, utils_1.getInheritedOption)(options, "config");
180
186
  }
187
+ const onlyOption = (0, utils_1.getInheritedOption)(options, "only");
188
+ if (onlyOption) {
189
+ options.only = onlyOption
190
+ .split(/[\s,]+/)
191
+ .filter(Boolean)
192
+ .join(",");
193
+ }
181
194
  try {
182
195
  options.config = config_1.Config.load(options);
183
196
  }
@@ -50,7 +50,11 @@ function printBackendsTable(backends) {
50
50
  ];
51
51
  if (abiuEnabled) {
52
52
  let abiuStatus = "N/A";
53
- if (backend.automaticBaseImageUpdatesDisabled !== undefined) {
53
+ const runtimeValue = backend.runtime?.value ?? "";
54
+ if (runtimeValue === "" || runtimeValue === "nodejs") {
55
+ abiuStatus = "Disabled";
56
+ }
57
+ else {
54
58
  abiuStatus = backend.automaticBaseImageUpdatesDisabled ? "Disabled" : "Enabled";
55
59
  }
56
60
  row.push(abiuStatus);
@@ -19,6 +19,7 @@ exports.command = new command_1.Command("ext:info <extensionName>")
19
19
  .before(checkMinRequiredVersion_1.checkMinRequiredVersion, "extMinVersion")
20
20
  .action(async (extensionName, options) => {
21
21
  let spec;
22
+ let version;
22
23
  if ((0, localHelper_1.isLocalExtension)(extensionName)) {
23
24
  if (!options.markdown) {
24
25
  utils.logLabeledBullet(extensionsHelper_1.logPrefix, `reading extension from directory: ${extensionName}`);
@@ -39,7 +40,7 @@ exports.command = new command_1.Command("ext:info <extensionName>")
39
40
  const [name, version] = extensionName.split("@");
40
41
  extensionName = `firebase/${name}@${version || "latest"}`;
41
42
  }
42
- const version = await extensionsApi.getExtensionVersion(extensionName);
43
+ version = await extensionsApi.getExtensionVersion(extensionName);
43
44
  spec = version.spec;
44
45
  }
45
46
  if (!options.markdown) {
@@ -56,6 +57,9 @@ exports.command = new command_1.Command("ext:info <extensionName>")
56
57
  const url = spec.author?.url;
57
58
  const urlMarkdown = url ? `(**[${url}](${url})**)` : "";
58
59
  lines.push(`**Author**: ${authorName} ${urlMarkdown}`);
60
+ if (version?.sourceDownloadUri) {
61
+ lines.push(`**Download URL**: ${version.sourceDownloadUri}`);
62
+ }
59
63
  if (spec.description) {
60
64
  lines.push(`**Description**: ${spec.description}`);
61
65
  }
@@ -169,7 +169,9 @@ async function prepare(context, options, payload) {
169
169
  const exportType = backend.someEndpoint(wantBackend, (e) => e.platform === "run")
170
170
  ? "tar.gz"
171
171
  : "zip";
172
- const packagedSource = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(options.config.projectDir, sourceDir, localCfg, [...schPathSet], undefined, { exportType });
172
+ const isDart = supported.runtimeIsLanguage(wantBuilds[codebase].runtime, "dart");
173
+ const executablePaths = isDart ? ["bin/server"] : [];
174
+ const packagedSource = await (0, prepareFunctionsUpload_1.prepareFunctionsUpload)(options.config.projectDir, sourceDir, localCfg, [...schPathSet], undefined, { exportType, executablePaths });
173
175
  source.functionsSourceV2 = packagedSource?.pathToSource;
174
176
  source.functionsSourceV2Hash = packagedSource?.hash;
175
177
  }
@@ -1,6 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.getFunctionsConfig = getFunctionsConfig;
4
+ exports.addFilesToArchive = addFilesToArchive;
4
5
  exports.prepareFunctionsUpload = prepareFunctionsUpload;
5
6
  exports.convertToSortedKeyValueArray = convertToSortedKeyValueArray;
6
7
  const archiver = require("archiver");
@@ -45,6 +46,24 @@ async function pipeAsync(from, to) {
45
46
  to.on("error", reject);
46
47
  });
47
48
  }
49
+ async function addFilesToArchive(archive, files, sourceDir, executablePaths) {
50
+ const hashes = [];
51
+ for (const file of files) {
52
+ const name = path.relative(sourceDir, file.name);
53
+ const normalizedName = name.split(path.sep).join("/");
54
+ const fileHash = await (0, hash_1.getSourceHash)(file.name);
55
+ hashes.push(fileHash);
56
+ let mode = file.mode;
57
+ if (executablePaths?.includes(normalizedName)) {
58
+ mode = 0o755;
59
+ }
60
+ archive.file(file.name, {
61
+ name: normalizedName,
62
+ mode,
63
+ });
64
+ }
65
+ return hashes;
66
+ }
48
67
  async function packageSource(projectDir, sourceDir, config, additionalSources, runtimeConfig, options) {
49
68
  const exportType = options?.exportType || "zip";
50
69
  const postfix = `.${exportType}`;
@@ -60,15 +79,7 @@ async function packageSource(projectDir, sourceDir, config, additionalSources, r
60
79
  ignore.push("firebase-debug.log", "firebase-debug.*.log", CONFIG_DEST_FILE);
61
80
  try {
62
81
  const files = await fsAsync.readdirRecursive({ path: sourceDir, ignore: ignore });
63
- for (const file of files) {
64
- const name = path.relative(sourceDir, file.name);
65
- const fileHash = await (0, hash_1.getSourceHash)(file.name);
66
- hashes.push(fileHash);
67
- archive.file(file.name, {
68
- name,
69
- mode: file.mode,
70
- });
71
- }
82
+ hashes.push(...(await addFilesToArchive(archive, files, sourceDir, options?.executablePaths)));
72
83
  for (const name of additionalSources) {
73
84
  const absPath = utils.resolveWithin(projectDir, name);
74
85
  if (!fs.existsSync(absPath)) {
@@ -18,6 +18,7 @@ const error_1 = require("../../../error");
18
18
  const getProjectNumber_1 = require("../../../getProjectNumber");
19
19
  const extensions_1 = require("../../extensions");
20
20
  const artifacts = require("../../../functions/artifacts");
21
+ const supported_1 = require("../runtimes/supported");
21
22
  async function release(context, options, payload) {
22
23
  if (context.extensions && payload.extensions) {
23
24
  await (0, extensions_1.release)(context.extensions, options, payload.extensions);
@@ -88,6 +89,10 @@ async function release(context, options, payload) {
88
89
  reporter.printErrors(summary);
89
90
  const wantBackend = backend.merge(...Object.values(payload.functions).map((p) => p.wantBackend));
90
91
  printTriggerUrls(wantBackend, projectNumber);
92
+ if (backend.someEndpoint(wantBackend, (endpoint) => (0, supported_1.runtimeIsLanguage)(endpoint.runtime, "dart"))) {
93
+ utils.logLabeledBullet("functions", "Dart functions may not yet be visible in the Firebase Console. " +
94
+ `View them in the Cloud Console at https://console.cloud.google.com/run/services?project=${context.projectId}`);
95
+ }
91
96
  await setupArtifactCleanupPolicies(options, options.projectId, Object.keys(wantBackend.endpoints));
92
97
  const allErrors = summary.results.filter((r) => r.error).map((r) => r.error);
93
98
  if (allErrors.length) {
@@ -16,7 +16,6 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
16
16
  Object.defineProperty(exports, "__esModule", { value: true });
17
17
  exports.isRuntime = isRuntime;
18
18
  exports.runtimeIsLanguage = runtimeIsLanguage;
19
- exports.isLanguageRuntime = isLanguageRuntime;
20
19
  exports.latest = latest;
21
20
  exports.isDecommissioned = isDecommissioned;
22
21
  exports.guardVersionSupport = guardVersionSupport;
@@ -28,9 +27,6 @@ function isRuntime(maybe) {
28
27
  return maybe in types_1.RUNTIMES;
29
28
  }
30
29
  function runtimeIsLanguage(runtime, language) {
31
- return runtime.startsWith(language);
32
- }
33
- function isLanguageRuntime(runtime, language) {
34
30
  return !!runtime && runtime.startsWith(language);
35
31
  }
36
32
  function latest(language, runtimes = Object.keys(types_1.RUNTIMES)) {
@@ -5,11 +5,12 @@ exports.isAILogicEvent = isAILogicEvent;
5
5
  const backend = require("../backend");
6
6
  const error_1 = require("../../../error");
7
7
  const ailogicApi = require("../../../gcp/ailogic");
8
- exports.AI_LOGIC_BEFORE_GENERATE_CONTENT = "firebase.vertexai.v1beta.beforeGenerateContent";
9
- exports.AI_LOGIC_AFTER_GENERATE_CONTENT = "firebase.vertexai.v1beta.afterGenerateContent";
8
+ const ailogic_1 = require("../../../gcp/ailogic");
9
+ Object.defineProperty(exports, "AI_LOGIC_BEFORE_GENERATE_CONTENT", { enumerable: true, get: function () { return ailogic_1.AI_LOGIC_BEFORE_GENERATE_CONTENT; } });
10
+ Object.defineProperty(exports, "AI_LOGIC_AFTER_GENERATE_CONTENT", { enumerable: true, get: function () { return ailogic_1.AI_LOGIC_AFTER_GENERATE_CONTENT; } });
10
11
  exports.AI_LOGIC_EVENTS = [
11
- exports.AI_LOGIC_BEFORE_GENERATE_CONTENT,
12
- exports.AI_LOGIC_AFTER_GENERATE_CONTENT,
12
+ ailogic_1.AI_LOGIC_BEFORE_GENERATE_CONTENT,
13
+ ailogic_1.AI_LOGIC_AFTER_GENERATE_CONTENT,
13
14
  ];
14
15
  function isAILogicEvent(endpoint) {
15
16
  if (!backend.isBlockingTriggered(endpoint)) {
@@ -124,8 +124,8 @@ const EVENT_SERVICE_MAPPING = {
124
124
  "google.cloud.firestore.document.v1.updated.withAuthContext": firestoreService,
125
125
  "google.cloud.firestore.document.v1.deleted.withAuthContext": firestoreService,
126
126
  "google.firebase.dataconnect.connector.v1.mutationExecuted": dataconnectService,
127
- "firebase.vertexai.v1beta.beforeGenerateContent": aiLogicService,
128
- "firebase.vertexai.v1beta.afterGenerateContent": aiLogicService,
127
+ "google.firebase.ailogic.v1.beforeGenerate": aiLogicService,
128
+ "google.firebase.ailogic.v1.afterGenerate": aiLogicService,
129
129
  };
130
130
  function serviceForEndpoint(endpoint) {
131
131
  if (backend.isEventTriggered(endpoint)) {
@@ -55,7 +55,13 @@ function endpointsAreValid(wantBackend) {
55
55
  validateTimeoutConfig(endpoints);
56
56
  for (const ep of endpoints) {
57
57
  validateScheduledTimeout(ep);
58
- (0, services_1.serviceForEndpoint)(ep).validateTrigger(ep, wantBackend);
58
+ const service = (0, services_1.serviceForEndpoint)(ep);
59
+ if (backend.isBlockingTriggered(ep)) {
60
+ if (service.name === "noop") {
61
+ throw new error_1.FirebaseError(`Unrecognized blocking trigger type: ${ep.blockingTrigger.eventType}. Please update your CLI with ${clc.bold("npm install -g firebase-tools@latest")}.`, { exit: 1 });
62
+ }
63
+ }
64
+ service.validateTrigger(ep, wantBackend);
59
65
  }
60
66
  const gcfV1WithConcurrency = matchingIds(endpoints, (endpoint) => (endpoint.concurrency || 1) !== 1 && endpoint.platform === "gcfv1");
61
67
  if (gcfV1WithConcurrency.length) {
@@ -419,10 +419,20 @@ async function startAll(options, showUI = true, runningTestScript = false) {
419
419
  const firestoreLogger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.FIRESTORE);
420
420
  const firestoreAddr = legacyGetFirstAddr(types_1.Emulators.FIRESTORE);
421
421
  const websocketPort = legacyGetFirstAddr("firestore.websocket").port;
422
+ const prodEdition = options.config.data.firestore?.edition;
423
+ const emulatorEdition = options.config.src.emulators?.firestore?.edition;
424
+ if (prodEdition !== emulatorEdition) {
425
+ firestoreLogger.logLabeled("WARN", "firestore", `The edition configured in your firebase.json#firestore and firebase.json#emulators.firestore do not match. The latter will be used to start up the Firestore emulator.`);
426
+ }
427
+ const edition = (emulatorEdition || prodEdition || "standard").toLowerCase();
428
+ if (edition !== "standard" && edition !== "enterprise") {
429
+ throw new error_1.FirebaseError("The Firestore emulator edition must be either 'standard' or 'enterprise'.", { exit: 1 });
430
+ }
422
431
  const args = {
423
432
  host: firestoreAddr.host,
424
433
  port: firestoreAddr.port,
425
434
  websocket_port: websocketPort,
435
+ "database-edition": edition,
426
436
  project_id: projectId,
427
437
  auto_download: true,
428
438
  };
@@ -472,6 +482,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
472
482
  }
473
483
  const firestoreEmulator = new firestoreEmulator_1.FirestoreEmulator(args);
474
484
  await startEmulator(firestoreEmulator);
485
+ firestoreLogger.logLabeled("SUCCESS", types_1.Emulators.FIRESTORE, `Firestore Emulator was started in ${edition} edition.`);
475
486
  firestoreLogger.logLabeled("SUCCESS", types_1.Emulators.FIRESTORE, `Firestore Emulator UI websocket is running on ${websocketPort}.`);
476
487
  }
477
488
  if (listenForEmulator.database) {
@@ -54,36 +54,36 @@
54
54
  },
55
55
  "dataconnect": {
56
56
  "darwin": {
57
- "version": "3.3.1",
58
- "expectedSize": 32105392,
59
- "expectedChecksum": "dfe6ff725864c37889c238aac24be304",
60
- "expectedChecksumSHA256": "1ccfebb4c0ff85f0503b907aa589658774bb6d4fac0180c3fa6bdff3a865090d",
61
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.3.1",
62
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.3.1"
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"
63
63
  },
64
64
  "darwin_arm64": {
65
- "version": "3.3.1",
66
- "expectedSize": 30287922,
67
- "expectedChecksum": "59af3cb51c78e8114d634afea811f8cc",
68
- "expectedChecksumSHA256": "75bde31d15c4cc14de7071ff50cdd0d8fb644491e0c9ee3c1da82fdaf8d976a9",
69
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.3.1",
70
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.3.1"
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"
71
71
  },
72
72
  "win32": {
73
- "version": "3.3.1",
74
- "expectedSize": 32148992,
75
- "expectedChecksum": "3205dc92bbc7edb4c5821641486dc70c",
76
- "expectedChecksumSHA256": "fa7796077728414b0682f6ccf1df0fc7b2f56bb590f1e62698dbb7c1ddaf0fb0",
77
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.3.1",
78
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.3.1.exe"
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"
79
79
  },
80
80
  "linux": {
81
- "version": "3.3.1",
82
- "expectedSize": 31264952,
83
- "expectedChecksum": "85ffdef78810e0074ac94c453a200daa",
84
- "expectedChecksumSHA256": "f232e03165c28f72bc99dfbd2dde1bcaf8298045817b60d72d407da7dae9e9f1",
85
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.3.1",
86
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-3.3.1"
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"
87
87
  }
88
88
  }
89
89
  }
@@ -199,6 +199,7 @@ const Commands = {
199
199
  "host",
200
200
  "rules",
201
201
  "websocket_port",
202
+ "database-edition",
202
203
  "functions_emulator",
203
204
  "seed_from_export",
204
205
  "project_id",
@@ -232,7 +232,7 @@ class FunctionsEmulator {
232
232
  "Content-Type": "application/json",
233
233
  "Content-Length": `${reqBody.length}`,
234
234
  };
235
- const isDart = (0, supported_1.isLanguageRuntime)(record.backend.runtime, "dart");
235
+ const isDart = (0, supported_1.runtimeIsLanguage)(record.backend.runtime, "dart");
236
236
  const path = isDart ? `/${trigger.entryPoint}` : `/`;
237
237
  return new Promise((resolve, reject) => {
238
238
  const req = http.request({
@@ -271,7 +271,7 @@ class FunctionsEmulator {
271
271
  for (const backend of this.staticBackends) {
272
272
  this.logger.logLabeled("BULLET", "functions", `Watching "${backend.functionsDir}" for Cloud Functions...`);
273
273
  await this.loadTriggers(backend, true);
274
- const isDart = (0, supported_1.isLanguageRuntime)(backend.runtime, "dart");
274
+ const isDart = (0, supported_1.runtimeIsLanguage)(backend.runtime, "dart");
275
275
  if (isDart) {
276
276
  const runtimeDelegateContext = {
277
277
  projectId: this.args.projectId,
@@ -1168,10 +1168,10 @@ class FunctionsEmulator {
1168
1168
  const runtimeEnv = this.getRuntimeEnvs(backend, trigger);
1169
1169
  const secretEnvs = await this.resolveSecretEnvs(backend, trigger);
1170
1170
  let runtime;
1171
- if ((0, supported_1.isLanguageRuntime)(backend.runtime, "python")) {
1171
+ if ((0, supported_1.runtimeIsLanguage)(backend.runtime, "python")) {
1172
1172
  runtime = await this.startPython(backend, { ...runtimeEnv, ...secretEnvs });
1173
1173
  }
1174
- else if ((0, supported_1.isLanguageRuntime)(backend.runtime, "dart")) {
1174
+ else if ((0, supported_1.runtimeIsLanguage)(backend.runtime, "dart")) {
1175
1175
  runtime = await this.startDart(backend, { ...runtimeEnv, ...secretEnvs });
1176
1176
  }
1177
1177
  else {
@@ -1242,8 +1242,7 @@ class FunctionsEmulator {
1242
1242
  this.logger.log("DEBUG", `[functions] Runtime ready! Sending request!`);
1243
1243
  const url = new url_1.URL(`${req.protocol}://${req.hostname}${req.url}`);
1244
1244
  let path = `${url.pathname}${url.search}`.replace(new RegExp(`\/${this.args.projectId}\/[^\/]*\/${req.params.trigger_name}\/?`), "/");
1245
- const isDart = (0, supported_1.isLanguageRuntime)(record.backend.runtime, "dart");
1246
- if (isDart) {
1245
+ if ((0, supported_1.runtimeIsLanguage)(record.backend.runtime, "dart")) {
1247
1246
  const isBackgroundRoute = req.url.startsWith("/functions/projects/");
1248
1247
  if (isBackgroundRoute || path === "/") {
1249
1248
  path = `/${trigger.entryPoint}`;
@@ -231,7 +231,7 @@ class RuntimeWorkerPool {
231
231
  if (this.mode === types_1.FunctionsExecutionMode.SEQUENTIAL) {
232
232
  return "~shared~";
233
233
  }
234
- if ((0, supported_1.isLanguageRuntime)(runtime, "dart")) {
234
+ if ((0, supported_1.runtimeIsLanguage)(runtime, "dart")) {
235
235
  return "~dart-shared~";
236
236
  }
237
237
  return triggerId || "~diagnostic~";
@@ -169,7 +169,7 @@ exports.ALL_EXPERIMENTS = experiments({
169
169
  },
170
170
  fdcrealtime: {
171
171
  shortDescription: "Enable Firebase Data Connect realtime feature.",
172
- default: false,
172
+ default: true,
173
173
  public: false,
174
174
  },
175
175
  });
@@ -43,6 +43,8 @@ async function listExtensions(projectId) {
43
43
  state,
44
44
  version,
45
45
  updateTime,
46
+ params: instance.config.params,
47
+ systemParams: instance.config.systemParams,
46
48
  });
47
49
  });
48
50
  (0, utils_1.logLabeledBullet)(extensionsHelper_1.logPrefix, `list of extensions installed in ${clc.bold(projectId)}:`);
@@ -1,10 +1,11 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.WEBPACK_LAYERS = exports.ESBUILD_VERSION = exports.CONFIG_FILES = exports.SERVER_REFERENCE_MANIFEST = exports.APP_PATHS_MANIFEST = exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
3
+ exports.WEBPACK_LAYERS = exports.ESBUILD_VERSION = exports.CONFIG_FILES = exports.SERVER_REFERENCE_MANIFEST = exports.APP_PATHS_MANIFEST = exports.ROUTES_MANIFEST = exports.PRERENDER_MANIFEST = exports.PAGES_MANIFEST = exports.FUNCTIONS_CONFIG_MANIFEST = exports.MIDDLEWARE_MANIFEST = exports.IMAGES_MANIFEST = exports.EXPORT_MARKER = exports.APP_PATH_ROUTES_MANIFEST = void 0;
4
4
  exports.APP_PATH_ROUTES_MANIFEST = "app-path-routes-manifest.json";
5
5
  exports.EXPORT_MARKER = "export-marker.json";
6
6
  exports.IMAGES_MANIFEST = "images-manifest.json";
7
7
  exports.MIDDLEWARE_MANIFEST = "middleware-manifest.json";
8
+ exports.FUNCTIONS_CONFIG_MANIFEST = "functions-config-manifest.json";
8
9
  exports.PAGES_MANIFEST = "pages-manifest.json";
9
10
  exports.PRERENDER_MANIFEST = "prerender-manifest.json";
10
11
  exports.ROUTES_MANIFEST = "routes-manifest.json";
@@ -255,16 +255,17 @@ async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
255
255
  await (0, fs_extra_1.copy)(publicPath, (0, path_1.join)(destDir, basePath));
256
256
  }
257
257
  await (0, fs_extra_1.copy)((0, path_1.join)(sourceDir, distDir, "static"), (0, path_1.join)(destDir, basePath, "_next", "static"));
258
- const [middlewareManifest, prerenderManifest, routesManifest, pagesManifest, appPathRoutesManifest, serverReferenceManifest,] = await Promise.all([
258
+ const [middlewareManifest, prerenderManifest, routesManifest, pagesManifest, appPathRoutesManifest, serverReferenceManifest, functionsConfigManifest,] = await Promise.all([
259
259
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.MIDDLEWARE_MANIFEST)),
260
260
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.PRERENDER_MANIFEST)),
261
261
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.ROUTES_MANIFEST)),
262
262
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.PAGES_MANIFEST)),
263
263
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, constants_2.APP_PATH_ROUTES_MANIFEST)).catch(() => ({})),
264
264
  (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.SERVER_REFERENCE_MANIFEST)).catch(() => ({ node: {}, edge: {}, encryptionKey: "" })),
265
+ (0, utils_1.readJSON)((0, path_1.join)(sourceDir, distDir, "server", constants_2.FUNCTIONS_CONFIG_MANIFEST)).catch(() => ({ version: 0, functions: {} })),
265
266
  ]);
266
267
  const appPathRoutesEntries = Object.entries(appPathRoutesManifest);
267
- const middlewareMatcherRegexes = (0, utils_2.getMiddlewareMatcherRegexes)(middlewareManifest);
268
+ const middlewareMatcherRegexes = (0, utils_2.getMiddlewareMatcherRegexes)(middlewareManifest, functionsConfigManifest);
268
269
  const { redirects = [], rewrites = [], headers = [] } = routesManifest;
269
270
  const rewritesRegexesNotSupportedByHosting = (0, utils_2.getNextjsRewritesToUse)(rewrites)
270
271
  .filter((rewrite) => !(0, utils_2.isRewriteSupportedByHosting)(rewrite))