firebase-tools 15.22.4 → 15.23.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/apiv2.js +91 -32
  2. package/lib/apphosting/backend.js +11 -4
  3. package/lib/commands/functions-delete.js +5 -3
  4. package/lib/commands/functions-lifecycle-list.js +94 -0
  5. package/lib/commands/functions-lifecycle-run.js +29 -0
  6. package/lib/commands/index.js +3 -0
  7. package/lib/database/import.js +3 -3
  8. package/lib/dataconnect/webhook.js +1 -2
  9. package/lib/deploy/functions/backend.js +9 -0
  10. package/lib/deploy/functions/build.js +3 -0
  11. package/lib/deploy/functions/prepare.js +90 -1
  12. package/lib/deploy/functions/prompts.js +62 -0
  13. package/lib/deploy/functions/release/fabricator.js +79 -4
  14. package/lib/deploy/functions/release/index.js +40 -25
  15. package/lib/deploy/functions/release/lifecycle.js +44 -51
  16. package/lib/deploy/functions/release/planner.js +41 -5
  17. package/lib/deploy/functions/runtimes/discovery/index.js +4 -3
  18. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +18 -1
  19. package/lib/deploy/functions/runtimes/node/index.js +1 -2
  20. package/lib/deploy/functions/runtimes/python/index.js +1 -2
  21. package/lib/deploy/hosting/uploader.js +2 -3
  22. package/lib/downloadUtils.js +3 -1
  23. package/lib/emulator/auth/operations.js +18 -8
  24. package/lib/emulator/downloadableEmulatorInfo.json +24 -24
  25. package/lib/emulator/storage/apis/gcloud.js +61 -0
  26. package/lib/emulator/storage/multipart.js +82 -2
  27. package/lib/emulator/taskQueue.js +3 -11
  28. package/lib/extensions/extensionsHelper.js +6 -4
  29. package/lib/gcp/iam.js +68 -2
  30. package/lib/gcp/knownRoles.json +99 -0
  31. package/lib/gcp/resourceManager.js +42 -1
  32. package/lib/gemini/fdcExperience.js +2 -2
  33. package/lib/hosting/initMiddleware.js +1 -1
  34. package/lib/hosting/proxy.js +42 -20
  35. package/lib/management/apps.js +4 -2
  36. package/lib/profiler.js +1 -2
  37. package/lib/streamUtils.js +24 -0
  38. package/lib/track.js +1 -2
  39. package/lib/tsconfig.compile.tsbuildinfo +1 -1
  40. package/lib/tsconfig.publish.tsbuildinfo +1 -1
  41. package/lib/utils.js +4 -21
  42. package/package.json +2 -4
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.proxyRequestHandler = proxyRequestHandler;
4
4
  exports.errorRequestHandler = errorRequestHandler;
5
5
  const lodash_1 = require("lodash");
6
- const node_fetch_1 = require("node-fetch");
7
6
  const stream_1 = require("stream");
8
7
  const url_1 = require("url");
9
8
  const apiv2_1 = require("../apiv2");
@@ -41,7 +40,7 @@ function proxyRequestHandler(url, rewriteIdentifier, options = {}) {
41
40
  passThrough = new stream_1.PassThrough();
42
41
  req.pipe(passThrough);
43
42
  }
44
- const headers = new node_fetch_1.Headers({
43
+ const headers = new Headers({
45
44
  "X-Forwarded-Host": req.headers.host || "",
46
45
  "X-Original-Url": req.url || "",
47
46
  Pragma: "no-cache",
@@ -83,13 +82,14 @@ function proxyRequestHandler(url, rewriteIdentifier, options = {}) {
83
82
  });
84
83
  }
85
84
  catch (err) {
85
+ logger_1.logger.error("[PROXY ERROR]", err);
86
86
  const isAbortError = err instanceof error_1.FirebaseError && err.original?.name.includes("AbortError");
87
87
  const isTimeoutError = err instanceof error_1.FirebaseError &&
88
- err.original instanceof node_fetch_1.FetchError &&
89
- err.original.code === "ETIMEDOUT";
88
+ (err.original?.code === "ETIMEDOUT" ||
89
+ err.original?.cause?.code === "ETIMEDOUT");
90
90
  const isSocketTimeoutError = err instanceof error_1.FirebaseError &&
91
- err.original instanceof node_fetch_1.FetchError &&
92
- err.original.code === "ESOCKETTIMEDOUT";
91
+ (err.original?.code === "ESOCKETTIMEDOUT" ||
92
+ err.original?.cause?.code === "ESOCKETTIMEDOUT");
93
93
  if (isAbortError || isTimeoutError || isSocketTimeoutError) {
94
94
  res.statusCode = 504;
95
95
  return res.end("Timed out waiting for function to respond.\n");
@@ -97,38 +97,60 @@ function proxyRequestHandler(url, rewriteIdentifier, options = {}) {
97
97
  res.statusCode = 500;
98
98
  return res.end(`An internal error occurred while proxying for ${rewriteIdentifier}\n`);
99
99
  }
100
+ finally {
101
+ if (passThrough) {
102
+ passThrough.resume();
103
+ }
104
+ }
105
+ const resHeaders = {};
106
+ for (const [key, value] of proxyRes.response.headers.entries()) {
107
+ resHeaders[key.toLowerCase()] = value;
108
+ }
100
109
  if (proxyRes.status === 404) {
101
- const cascade = proxyRes.response.headers.get("x-cascade");
102
- if (options.forceCascade || (cascade && cascade.toUpperCase() === "PASS")) {
110
+ const cascade = resHeaders["x-cascade"];
111
+ if (options.forceCascade ||
112
+ (typeof cascade === "string" && cascade.toUpperCase() === "PASS")) {
103
113
  return next();
104
114
  }
105
115
  }
106
- if (!proxyRes.response.headers.get("cache-control")) {
107
- proxyRes.response.headers.set("cache-control", "private");
116
+ if (!resHeaders["cache-control"]) {
117
+ resHeaders["cache-control"] = "private";
108
118
  }
109
- const cc = proxyRes.response.headers.get("cache-control");
110
- if (cc && !cc.includes("private")) {
111
- proxyRes.response.headers.delete("set-cookie");
119
+ const cc = resHeaders["cache-control"];
120
+ if (typeof cc === "string" && !cc.includes("private")) {
121
+ delete resHeaders["set-cookie"];
112
122
  }
113
- proxyRes.response.headers.set("vary", makeVary(proxyRes.response.headers.get("vary")));
114
- const location = proxyRes.response.headers.get("location");
115
- if (location) {
123
+ const vary = resHeaders["vary"];
124
+ resHeaders["vary"] = makeVary(typeof vary === "string" ? vary : null);
125
+ const location = resHeaders["location"];
126
+ if (typeof location === "string" && location) {
116
127
  try {
117
128
  const locationURL = new url_1.URL(location);
118
129
  if (locationURL.origin === u.origin) {
119
130
  const unborkedLocation = location.replace(locationURL.origin, "");
120
- proxyRes.response.headers.set("location", unborkedLocation);
131
+ resHeaders["location"] = unborkedLocation;
121
132
  }
122
133
  }
123
134
  catch (e) {
124
135
  logger_1.logger.debug(`[hosting] had trouble parsing location header, but this may be okay: "${location}"`);
125
136
  }
126
137
  }
127
- for (const [key, value] of Object.entries(proxyRes.response.headers.raw())) {
128
- res.setHeader(key, value);
138
+ for (const key of Object.keys(resHeaders)) {
139
+ const value = resHeaders[key];
140
+ if (key === "set-cookie") {
141
+ if (typeof proxyRes.response.headers.getSetCookie === "function") {
142
+ res.setHeader(key, proxyRes.response.headers.getSetCookie());
143
+ }
144
+ else {
145
+ res.setHeader(key, value);
146
+ }
147
+ }
148
+ else {
149
+ res.setHeader(key, value);
150
+ }
129
151
  }
130
152
  res.statusCode = proxyRes.status;
131
- proxyRes.response.body.pipe(res);
153
+ proxyRes.body.pipe(res);
132
154
  };
133
155
  }
134
156
  function errorRequestHandler(error) {
@@ -84,9 +84,11 @@ https://firebase.google.com/docs/flutter/setup
84
84
  async function initiateIosAppCreation(options) {
85
85
  if (!options.nonInteractive) {
86
86
  options.displayName = options.displayName || (await getDisplayName());
87
+ const promptAppStoreId = !options.bundleId;
87
88
  options.bundleId = options.bundleId || (await (0, prompt_1.input)("Please specify your iOS app bundle ID:"));
88
- options.appStoreId =
89
- options.appStoreId || (await (0, prompt_1.input)("Please specify your iOS app App Store ID:"));
89
+ if (promptAppStoreId && !options.appStoreId) {
90
+ options.appStoreId = await (0, prompt_1.input)("Please specify your iOS app App Store ID:");
91
+ }
90
92
  }
91
93
  if (!options.bundleId) {
92
94
  throw new error_1.FirebaseError("Bundle ID for iOS app cannot be empty");
package/lib/profiler.js CHANGED
@@ -5,7 +5,6 @@ const fs = require("fs");
5
5
  const ora = require("ora");
6
6
  const readline = require("readline");
7
7
  const tmp = require("tmp");
8
- const abort_controller_1 = require("abort-controller");
9
8
  const apiv2_1 = require("./apiv2");
10
9
  const api_1 = require("./database/api");
11
10
  const logger_1 = require("./logger");
@@ -26,7 +25,7 @@ async function profiler(options) {
26
25
  color: "yellow",
27
26
  });
28
27
  const outputFormat = options.raw ? "RAW" : options.parent.json ? "JSON" : "TXT";
29
- const controller = new abort_controller_1.default();
28
+ const controller = new AbortController();
30
29
  const generateReport = () => {
31
30
  rl.close();
32
31
  spinner.stop();
@@ -0,0 +1,24 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.stringToStream = stringToStream;
4
+ exports.streamToString = streamToString;
5
+ const stream_1 = require("stream");
6
+ function stringToStream(text) {
7
+ if (!text) {
8
+ return undefined;
9
+ }
10
+ const s = new stream_1.Readable();
11
+ s.push(text);
12
+ s.push(null);
13
+ return s;
14
+ }
15
+ function streamToString(s) {
16
+ return new Promise((resolve, reject) => {
17
+ let b = "";
18
+ s.on("error", reject);
19
+ s.on("data", (d) => {
20
+ b += d.toString();
21
+ });
22
+ s.once("end", () => resolve(b));
23
+ });
24
+ }
package/lib/track.js CHANGED
@@ -8,7 +8,6 @@ exports.trackVSCode = trackVSCode;
8
8
  exports.emulatorSession = emulatorSession;
9
9
  exports.vscodeSession = vscodeSession;
10
10
  exports.cliSession = cliSession;
11
- const node_fetch_1 = require("node-fetch");
12
11
  const crypto_1 = require("crypto");
13
12
  const auth_1 = require("./auth");
14
13
  const configstore_1 = require("./configstore");
@@ -134,7 +133,7 @@ async function _ga4Track(args) {
134
133
  logger_1.logger.info(`Sending Analytics for event ${eventName} to property ${session.measurementId}`, params, body);
135
134
  }
136
135
  try {
137
- const response = await (0, node_fetch_1.default)(url, {
136
+ const response = await fetch(url, {
138
137
  method: "POST",
139
138
  headers: {
140
139
  "content-type": "application/json;charset=UTF-8",