firebase-tools 14.7.0 → 14.8.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.
@@ -16,7 +16,6 @@ const planner = require("../deploy/functions/release/planner");
16
16
  const fabricator = require("../deploy/functions/release/fabricator");
17
17
  const executor = require("../deploy/functions/release/executor");
18
18
  const reporter = require("../deploy/functions/release/reporter");
19
- const containerCleaner = require("../deploy/functions/containerCleaner");
20
19
  const getProjectNumber_1 = require("../getProjectNumber");
21
20
  exports.command = new command_1.Command("functions:delete [filters...]")
22
21
  .description("delete one or more Cloud Functions by name or group name.")
@@ -91,5 +90,4 @@ exports.command = new command_1.Command("functions:delete [filters...]")
91
90
  exit: 1,
92
91
  });
93
92
  }
94
- await containerCleaner.cleanupBuildImages([], allEpToDelete);
95
93
  });
@@ -120,10 +120,10 @@ async function ensureGenkitMonitoringRoles(projectId, projectNumber, want, have,
120
120
  .map((endpoint) => endpoint.serviceAccount || "")
121
121
  .filter((value, index, self) => self.indexOf(value) === index);
122
122
  const defaultServiceAccountIndex = serviceAccounts.indexOf("");
123
- if (defaultServiceAccountIndex) {
123
+ if (defaultServiceAccountIndex !== -1) {
124
124
  serviceAccounts[defaultServiceAccountIndex] = await gce.getDefaultServiceAccount(projectNumber);
125
125
  }
126
- const members = serviceAccounts.map((sa) => `serviceAccount:${sa}`);
126
+ const members = serviceAccounts.filter((sa) => !!sa).map((sa) => `serviceAccount:${sa}`);
127
127
  const requiredBindings = [];
128
128
  for (const monitoringRole of exports.GENKIT_MONITORING_ROLES) {
129
129
  requiredBindings.push({
@@ -19,16 +19,17 @@ var __asyncGenerator = (this && this.__asyncGenerator) || function (thisArg, _ar
19
19
  function settle(f, v) { if (f(v), q.shift(), q.length) resume(q[0][0], q[0][1]); }
20
20
  };
21
21
  Object.defineProperty(exports, "__esModule", { value: true });
22
- exports.fromNodeSocket = exports.PGliteExtendedQueryPatch = exports.PostgresServer = exports.TRUNCATE_TABLES_SQL = void 0;
22
+ exports.fromNodeSocket = exports.PostgresServer = exports.TRUNCATE_TABLES_SQL = void 0;
23
23
  const pglite_1 = require("@electric-sql/pglite");
24
24
  const { dynamicImport } = require(true && "../../dynamicImport");
25
25
  const net = require("node:net");
26
26
  const node_stream_1 = require("node:stream");
27
27
  const fs = require("fs");
28
+ const path = require("node:path");
28
29
  const pg_gateway_1 = require("pg-gateway");
29
30
  const logger_1 = require("../../logger");
30
31
  const error_1 = require("../../error");
31
- const node_string_decoder_1 = require("node:string_decoder");
32
+ const fsutils_1 = require("../../fsutils");
32
33
  exports.TRUNCATE_TABLES_SQL = `
33
34
  DO $do$
34
35
  DECLARE _clear text;
@@ -45,22 +46,43 @@ class PostgresServer {
45
46
  async createPGServer(host = "127.0.0.1", port) {
46
47
  const getDb = this.getDb.bind(this);
47
48
  const server = net.createServer(async (socket) => {
48
- const connection = await fromNodeSocket(socket, {
49
- serverVersion: "16.3 (PGlite 0.2.0)",
49
+ await fromNodeSocket(socket, {
50
+ serverVersion: "17.4 (PGlite 0.3.3)",
50
51
  auth: { method: "trust" },
51
- async onMessage(data, { isAuthenticated }) {
52
- if (!isAuthenticated) {
53
- return;
54
- }
55
- const db = await getDb();
56
- if (data[0] === pg_gateway_1.FrontendMessageCode.Terminate) {
57
- await db.query("DEALLOCATE ALL");
58
- }
59
- const result = await db.execProtocolRaw(data);
60
- return extendedQueryPatch.filterResponse(data, result);
52
+ onMessage(data, { isAuthenticated }) {
53
+ return __asyncGenerator(this, arguments, function* onMessage_1() {
54
+ var _a, e_1, _b, _c;
55
+ if (!isAuthenticated) {
56
+ return yield __await(void 0);
57
+ }
58
+ const db = yield __await(getDb());
59
+ if (data[0] === pg_gateway_1.FrontendMessageCode.Terminate) {
60
+ yield __await(db.query("DEALLOCATE ALL"));
61
+ }
62
+ const response = yield __await(db.execProtocolRaw(data));
63
+ try {
64
+ for (var _d = true, _e = __asyncValues((0, pg_gateway_1.getMessages)(response)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a;) {
65
+ _c = _f.value;
66
+ _d = false;
67
+ try {
68
+ const message = _c;
69
+ yield yield __await(message);
70
+ }
71
+ finally {
72
+ _d = true;
73
+ }
74
+ }
75
+ }
76
+ catch (e_1_1) { e_1 = { error: e_1_1 }; }
77
+ finally {
78
+ try {
79
+ if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
80
+ }
81
+ finally { if (e_1) throw e_1.error; }
82
+ }
83
+ });
61
84
  },
62
85
  });
63
- const extendedQueryPatch = new PGliteExtendedQueryPatch(connection);
64
86
  socket.on("end", () => {
65
87
  logger_1.logger.debug("Postgres client disconnected");
66
88
  });
@@ -79,30 +101,15 @@ class PostgresServer {
79
101
  }
80
102
  async getDb() {
81
103
  if (!this.db) {
82
- if (this.dataDirectory && !fs.existsSync(this.dataDirectory)) {
83
- fs.mkdirSync(this.dataDirectory, { recursive: true });
84
- }
85
- const vector = (await dynamicImport("@electric-sql/pglite/vector")).vector;
86
- const uuidOssp = (await dynamicImport("@electric-sql/pglite/contrib/uuid_ossp")).uuid_ossp;
87
- const pgliteArgs = {
88
- debug: this.debug,
89
- extensions: {
90
- vector,
91
- uuidOssp,
92
- },
93
- dataDir: this.dataDirectory,
94
- };
95
- if (this.importPath) {
96
- logger_1.logger.debug(`Importing from ${this.importPath}`);
97
- const rf = fs.readFileSync(this.importPath);
98
- const file = new File([rf], this.importPath);
99
- pgliteArgs.loadDataDir = file;
100
- }
101
- this.db = await this.forceCreateDB(pgliteArgs);
102
- await this.db.waitReady;
104
+ this.db = await this.forceCreateDB();
103
105
  }
104
106
  return this.db;
105
107
  }
108
+ async getExtensions() {
109
+ const vector = (await dynamicImport("@electric-sql/pglite/vector")).vector;
110
+ const uuidOssp = (await dynamicImport("@electric-sql/pglite/contrib/uuid_ossp")).uuid_ossp;
111
+ return { vector, uuidOssp };
112
+ }
106
113
  async clearDb() {
107
114
  const db = await this.getDb();
108
115
  await db.query(exports.TRUNCATE_TABLES_SQL);
@@ -113,18 +120,92 @@ class PostgresServer {
113
120
  const arrayBuff = await dump.arrayBuffer();
114
121
  fs.writeFileSync(exportPath, new Uint8Array(arrayBuff));
115
122
  }
116
- async forceCreateDB(pgliteArgs) {
123
+ async migrateDb(pgliteArgs) {
124
+ if (!this.baseDataDirectory) {
125
+ throw new error_1.FirebaseError("Cannot migrate database without a data directory.");
126
+ }
127
+ const { PGlite: PGlite02 } = await dynamicImport("pglite-2");
128
+ const pgDump = (await dynamicImport("@electric-sql/pglite-tools/pg_dump")).pgDump;
129
+ logger_1.logger.info("Opening database with Postgres 16...");
130
+ const extensions = await this.getExtensions();
131
+ const dataDir = this.baseDataDirectory;
132
+ const oldDb = new PGlite02(Object.assign(Object.assign({}, pgliteArgs), { dataDir }));
133
+ await oldDb.waitReady;
134
+ const oldVersion = await oldDb.query("SELECT version();");
135
+ logger_1.logger.debug(`Old database version: ${oldVersion.rows[0].version}`);
136
+ if (!oldVersion.rows[0].version.includes("PostgreSQL 16")) {
137
+ await oldDb.close();
138
+ throw new error_1.FirebaseError("Migration started, but DB version is not PostgreSQL 16.");
139
+ }
140
+ logger_1.logger.info("Dumping data from old database...");
141
+ const dumpDir = await oldDb.dumpDataDir("none");
142
+ const tempOldDb = await PGlite02.create({
143
+ loadDataDir: dumpDir,
144
+ extensions,
145
+ });
146
+ const dumpResult = await pgDump({ pg: tempOldDb, args: ["--verbose", "--verbose"] });
147
+ await tempOldDb.close();
148
+ await oldDb.close();
149
+ logger_1.logger.info(`Moving old database directory to ${this.baseDataDirectory}/pg16...`);
150
+ const pg16Dir = this.getVersionedDataDir(16);
151
+ (0, fsutils_1.moveAll)(this.baseDataDirectory, pg16Dir);
152
+ logger_1.logger.info("If you need to use an older version of the Firebase CLI, you can restore from that directory.");
153
+ logger_1.logger.info("Creating new database with Postgres 17...");
154
+ const pg17Dir = this.getVersionedDataDir(17);
155
+ const newDb = new pglite_1.PGlite(Object.assign(Object.assign({}, pgliteArgs), { dataDir: pg17Dir }));
156
+ await newDb.waitReady;
157
+ logger_1.logger.info("Importing data into new database...");
158
+ const dumpText = await dumpResult.text();
159
+ await newDb.exec(dumpText);
160
+ await newDb.exec("SET SEARCH_PATH = public;");
161
+ logger_1.logger.info("Postgres database migration successful.");
162
+ return newDb;
163
+ }
164
+ getVersionedDataDir(version) {
165
+ if (!this.baseDataDirectory) {
166
+ return;
167
+ }
168
+ return path.join(this.baseDataDirectory, `pg${version}`);
169
+ }
170
+ async forceCreateDB() {
171
+ const baseArgs = {
172
+ debug: this.debug,
173
+ extensions: await this.getExtensions(),
174
+ };
175
+ const pg17Dir = this.getVersionedDataDir(17);
176
+ if (pg17Dir && !fs.existsSync(pg17Dir)) {
177
+ fs.mkdirSync(pg17Dir, { recursive: true });
178
+ }
179
+ if (this.importPath) {
180
+ logger_1.logger.debug(`Importing from ${this.importPath}`);
181
+ const rf = fs.readFileSync(this.importPath);
182
+ const file = new File([rf], this.importPath);
183
+ baseArgs.loadDataDir = file;
184
+ }
185
+ if (this.baseDataDirectory && fs.existsSync(this.baseDataDirectory)) {
186
+ const versionFilePath = path.join(this.baseDataDirectory, "PG_VERSION");
187
+ if (fs.existsSync(versionFilePath)) {
188
+ const version = fs.readFileSync(versionFilePath, "utf-8").trim();
189
+ logger_1.logger.debug(`Found Postgres version file with version: ${version}`);
190
+ if (version === "16") {
191
+ logger_1.logger.info("Detected a Postgres 16 data directory from an older version of firebase-tools. Migrating to Postgres 17...");
192
+ return this.migrateDb(baseArgs);
193
+ }
194
+ }
195
+ }
117
196
  try {
118
- const db = await pglite_1.PGlite.create(pgliteArgs);
197
+ const db = new pglite_1.PGlite(Object.assign(Object.assign({}, baseArgs), { dataDir: pg17Dir }));
198
+ await db.waitReady;
119
199
  return db;
120
200
  }
121
201
  catch (err) {
122
- if (pgliteArgs.dataDir && (0, error_1.hasMessage)(err) && /Database already exists/.test(err.message)) {
123
- fs.rmSync(pgliteArgs.dataDir, { force: true, recursive: true });
124
- const db = await pglite_1.PGlite.create(pgliteArgs);
202
+ if (pg17Dir && (0, error_1.hasMessage)(err) && /Database already exists/.test(err.message)) {
203
+ fs.rmSync(pg17Dir, { force: true, recursive: true });
204
+ const db = new pglite_1.PGlite(Object.assign(Object.assign({}, baseArgs), { dataDir: pg17Dir }));
205
+ await db.waitReady;
125
206
  return db;
126
207
  }
127
- logger_1.logger.debug(`Error from pglite: ${err}`);
208
+ logger_1.logger.warn(`Error from pglite: ${err}`);
128
209
  throw new error_1.FirebaseError("Unexpected error starting up Postgres.");
129
210
  }
130
211
  }
@@ -140,71 +221,12 @@ class PostgresServer {
140
221
  constructor(args) {
141
222
  this.db = undefined;
142
223
  this.server = undefined;
143
- this.dataDirectory = args.dataDirectory;
224
+ this.baseDataDirectory = args.dataDirectory;
144
225
  this.importPath = args.importPath;
145
226
  this.debug = args.debug ? 5 : 0;
146
227
  }
147
228
  }
148
229
  exports.PostgresServer = PostgresServer;
149
- class PGliteExtendedQueryPatch {
150
- constructor(connection) {
151
- this.connection = connection;
152
- this.isExtendedQuery = false;
153
- this.eqpErrored = false;
154
- }
155
- filterResponse(message, response) {
156
- return __asyncGenerator(this, arguments, function* filterResponse_1() {
157
- var _a, e_1, _b, _c;
158
- const pipelineStartMessages = [
159
- pg_gateway_1.FrontendMessageCode.Parse,
160
- pg_gateway_1.FrontendMessageCode.Bind,
161
- pg_gateway_1.FrontendMessageCode.Close,
162
- ];
163
- const decoder = new node_string_decoder_1.StringDecoder();
164
- const decoded = decoder.write(message);
165
- logger_1.logger.debug(decoded);
166
- if (pipelineStartMessages.includes(message[0])) {
167
- this.isExtendedQuery = true;
168
- }
169
- if (message[0] === pg_gateway_1.FrontendMessageCode.Sync) {
170
- this.isExtendedQuery = false;
171
- this.eqpErrored = false;
172
- return yield __await(this.connection.createReadyForQuery());
173
- }
174
- try {
175
- for (var _d = true, _e = __asyncValues((0, pg_gateway_1.getMessages)(response)), _f; _f = yield __await(_e.next()), _a = _f.done, !_a;) {
176
- _c = _f.value;
177
- _d = false;
178
- try {
179
- const message = _c;
180
- if (this.eqpErrored) {
181
- continue;
182
- }
183
- if (this.isExtendedQuery && message[0] === pg_gateway_1.BackendMessageCode.ErrorMessage) {
184
- this.eqpErrored = true;
185
- }
186
- if (this.isExtendedQuery && message[0] === pg_gateway_1.BackendMessageCode.ReadyForQuery) {
187
- logger_1.logger.debug("Filtered out a ReadyForQuery.");
188
- continue;
189
- }
190
- yield yield __await(message);
191
- }
192
- finally {
193
- _d = true;
194
- }
195
- }
196
- }
197
- catch (e_1_1) { e_1 = { error: e_1_1 }; }
198
- finally {
199
- try {
200
- if (!_d && !_a && (_b = _e.return)) yield __await(_b.call(_e));
201
- }
202
- finally { if (e_1) throw e_1.error; }
203
- }
204
- });
205
- }
206
- }
207
- exports.PGliteExtendedQueryPatch = PGliteExtendedQueryPatch;
208
230
  async function fromNodeSocket(socket, options) {
209
231
  const rs = node_stream_1.Readable.toWeb(socket);
210
232
  const ws = node_stream_1.Writable.toWeb(socket);
@@ -54,28 +54,28 @@
54
54
  },
55
55
  "dataconnect": {
56
56
  "darwin": {
57
- "version": "2.7.0",
58
- "expectedSize": 27542272,
59
- "expectedChecksum": "8b68e45ccae2d2cf35bea368e7ce379c",
60
- "expectedChecksumSHA256": "6dce6ea23c39e4e44dbaa6db7181c9d7761dd1098589a627fa5aa0fb4a07ccd7",
61
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.7.0",
62
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.0"
57
+ "version": "2.7.1",
58
+ "expectedSize": 27607808,
59
+ "expectedChecksum": "3cf0b4dcb96639f1b7ddf3e2052ea28f",
60
+ "expectedChecksumSHA256": "76b6db1f87e14e3c39035301ae199bec0458a2e7534a1db962276a92fa99c215",
61
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.7.1",
62
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.1"
63
63
  },
64
64
  "win32": {
65
- "version": "2.7.0",
66
- "expectedSize": 28001280,
67
- "expectedChecksum": "03ef2fd3ed2f7263539f1a9d7b748ee6",
68
- "expectedChecksumSHA256": "3462f15ddc5d11371774de8f19b54468eb75eefac5f3a5623334f42154f06bc8",
69
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.7.0",
70
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.0.exe"
65
+ "version": "2.7.1",
66
+ "expectedSize": 28067328,
67
+ "expectedChecksum": "8dacedaecac242199dfcf3f6c023f89a",
68
+ "expectedChecksumSHA256": "fc098efa9aed9b1ac7d35b90da47608190f3a5562f37444012785a9793d743a0",
69
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.7.1",
70
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.1.exe"
71
71
  },
72
72
  "linux": {
73
- "version": "2.7.0",
74
- "expectedSize": 27451544,
75
- "expectedChecksum": "8b73f21f1bdf168a5f2c3137c30abc7b",
76
- "expectedChecksumSHA256": "e2d03d1d0524f8053b34376c8ad6ea1fdfb8bc48568e80a35c2e3e510754c121",
77
- "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.7.0",
78
- "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.0"
73
+ "version": "2.7.1",
74
+ "expectedSize": 27521176,
75
+ "expectedChecksum": "3c03d85c2d1de80a2f2ba13fe3b5a3ff",
76
+ "expectedChecksumSHA256": "94c35ab64bd8d206e7843513848e7375cd8f9b6a06d013b1ec541ac831cda8a8",
77
+ "remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.7.1",
78
+ "downloadPathRelativeToCacheDir": "dataconnect-emulator-2.7.1"
79
79
  }
80
80
  }
81
81
  }
@@ -8,6 +8,7 @@ const apiv2_1 = require("./apiv2");
8
8
  const utils = require("./utils");
9
9
  const error_1 = require("./error");
10
10
  const logger_1 = require("./logger");
11
+ const configstore_1 = require("./configstore");
11
12
  exports.POLL_SETTINGS = {
12
13
  pollInterval: 10000,
13
14
  pollsBeforeRetry: 12,
@@ -18,6 +19,9 @@ const apiClient = new apiv2_1.Client({
18
19
  });
19
20
  async function check(projectId, apiUri, prefix, silent = false) {
20
21
  const apiName = apiUri.startsWith("http") ? new URL(apiUri).hostname : apiUri;
22
+ if (checkAPIEnablementCache(projectId, apiName)) {
23
+ return true;
24
+ }
21
25
  const res = await apiClient.get(`/projects/${projectId}/services/${apiName}`, {
22
26
  headers: { "x-goog-quota-user": `projects/${projectId}` },
23
27
  skipLog: { resBody: true },
@@ -26,6 +30,9 @@ async function check(projectId, apiUri, prefix, silent = false) {
26
30
  if (isEnabled && !silent) {
27
31
  utils.logLabeledSuccess(prefix, `required API ${(0, colorette_1.bold)(apiName)} is enabled`);
28
32
  }
33
+ if (isEnabled) {
34
+ cacheEnabledAPI(projectId, apiName);
35
+ }
29
36
  return isEnabled;
30
37
  }
31
38
  exports.check = check;
@@ -39,6 +46,7 @@ async function enable(projectId, apiName) {
39
46
  headers: { "x-goog-quota-user": `projects/${projectId}` },
40
47
  skipLog: { resBody: true },
41
48
  });
49
+ cacheEnabledAPI(projectId, apiName);
42
50
  }
43
51
  catch (err) {
44
52
  if ((0, error_1.isBillingError)(err)) {
@@ -120,3 +128,17 @@ function enableApiURI(projectId, apiName) {
120
128
  return `https://console.cloud.google.com/apis/library/${apiName}?project=${projectId}`;
121
129
  }
122
130
  exports.enableApiURI = enableApiURI;
131
+ const API_ENABLEMENT_CACHE_KEY = "apiEnablementCache";
132
+ function checkAPIEnablementCache(projectId, apiName) {
133
+ var _a;
134
+ const cache = configstore_1.configstore.get(API_ENABLEMENT_CACHE_KEY);
135
+ return !!((_a = cache === null || cache === void 0 ? void 0 : cache[projectId]) === null || _a === void 0 ? void 0 : _a[apiName]);
136
+ }
137
+ function cacheEnabledAPI(projectId, apiName) {
138
+ const cache = (configstore_1.configstore.get(API_ENABLEMENT_CACHE_KEY) || {});
139
+ if (!cache[projectId]) {
140
+ cache[projectId] = {};
141
+ }
142
+ cache[projectId][apiName] = true;
143
+ configstore_1.configstore.set(API_ENABLEMENT_CACHE_KEY, cache);
144
+ }
package/lib/fsutils.js CHANGED
@@ -1,8 +1,10 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.listFiles = exports.readFile = exports.dirExistsSync = exports.fileExistsSync = void 0;
3
+ exports.moveAll = exports.listFiles = exports.readFile = exports.dirExistsSync = exports.fileExistsSync = void 0;
4
4
  const fs_1 = require("fs");
5
+ const path = require("path");
5
6
  const error_1 = require("./error");
7
+ const fs_extra_1 = require("fs-extra");
6
8
  function fileExistsSync(path) {
7
9
  try {
8
10
  return (0, fs_1.statSync)(path).isFile();
@@ -45,3 +47,16 @@ function listFiles(path) {
45
47
  }
46
48
  }
47
49
  exports.listFiles = listFiles;
50
+ function moveAll(srcDir, destDir) {
51
+ if (!(0, fs_1.existsSync)(destDir)) {
52
+ (0, fs_1.mkdirSync)(destDir, { recursive: true });
53
+ }
54
+ const files = listFiles(srcDir);
55
+ for (const f of files) {
56
+ const srcPath = path.join(srcDir, f);
57
+ if (srcPath === destDir)
58
+ continue;
59
+ (0, fs_extra_1.moveSync)(srcPath, path.join(destDir, f));
60
+ }
61
+ }
62
+ exports.moveAll = moveAll;
@@ -20,7 +20,7 @@ const serviceUsagePollerOptions = {
20
20
  async function generateServiceIdentity(projectNumber, service, prefix) {
21
21
  utils.logLabeledBullet(prefix, `generating the service identity for ${(0, colorette_1.bold)(service)}...`);
22
22
  try {
23
- const res = await exports.apiClient.post(`projects/${projectNumber}/services/${service}:generateServiceIdentity`);
23
+ const res = await exports.apiClient.post(`projects/${projectNumber}/services/${service}:generateServiceIdentity`, {}, { headers: { "x-goog-quota-user": `projects/${projectNumber}` } });
24
24
  return res.body;
25
25
  }
26
26
  catch (err) {
@@ -35,6 +35,6 @@ async function generateServiceIdentityAndPoll(projectNumber, service, prefix) {
35
35
  if (op.done) {
36
36
  return;
37
37
  }
38
- await poller.pollOperation(Object.assign(Object.assign({}, serviceUsagePollerOptions), { operationResourceName: op.name }));
38
+ await poller.pollOperation(Object.assign(Object.assign({}, serviceUsagePollerOptions), { operationResourceName: op.name, headers: { "x-goog-quota-user": `projects/${projectNumber}` } }));
39
39
  }
40
40
  exports.generateServiceIdentityAndPoll = generateServiceIdentityAndPoll;
@@ -34,7 +34,9 @@ class OperationPoller {
34
34
  return async () => {
35
35
  let res;
36
36
  try {
37
- res = await apiClient.get(options.operationResourceName);
37
+ res = await apiClient.get(options.operationResourceName, {
38
+ headers: options.headers,
39
+ });
38
40
  }
39
41
  catch (err) {
40
42
  if (err.status === 500 || err.status === 503) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "14.7.0",
3
+ "version": "14.8.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -60,7 +60,8 @@
60
60
  ]
61
61
  },
62
62
  "dependencies": {
63
- "@electric-sql/pglite": "^0.2.17",
63
+ "@electric-sql/pglite": "^0.3.3",
64
+ "@electric-sql/pglite-tools": "^0.2.8",
64
65
  "@google-cloud/cloud-sql-connector": "^1.3.3",
65
66
  "@google-cloud/pubsub": "^4.5.0",
66
67
  "@inquirer/prompts": "^7.4.0",
@@ -110,6 +111,7 @@
110
111
  "p-limit": "^3.0.1",
111
112
  "pg": "^8.11.3",
112
113
  "pg-gateway": "^0.3.0-beta.4",
114
+ "pglite-2": "npm:@electric-sql/pglite@0.2.17",
113
115
  "portfinder": "^1.0.32",
114
116
  "progress": "^2.0.3",
115
117
  "proxy-agent": "^6.3.0",
@@ -7,9 +7,22 @@
7
7
  * See a full list of supported triggers at https://firebase.google.com/docs/functions
8
8
  */
9
9
 
10
- const {onRequest} = require("firebase-functions/v2/https");
10
+ const {setGlobalOptions} = require("firebase-functions");
11
+ const {onRequest} = require("firebase-functions/https");
11
12
  const logger = require("firebase-functions/logger");
12
13
 
14
+ // For cost control, you can set the maximum number of containers that can be
15
+ // running at the same time. This helps mitigate the impact of unexpected
16
+ // traffic spikes by instead downgrading performance. This limit is a
17
+ // per-function limit. You can override the limit for each function using the
18
+ // `maxInstances` option in the function's options, e.g.
19
+ // `onRequest({ maxInstances: 5 }, (req, res) => { ... })`.
20
+ // NOTE: setGlobalOptions does not apply to functions using the v1 API. V1
21
+ // functions should each use functions.runWith({ maxInstances: 10 }) instead.
22
+ // In the v1 API, each function can only serve one request per container, so
23
+ // this will be the maximum concurrent request count.
24
+ setGlobalOptions({ maxInstances: 10 });
25
+
13
26
  // Create and deploy your first functions
14
27
  // https://firebase.google.com/docs/functions/get-started
15
28
 
@@ -3,8 +3,16 @@
3
3
  # Deploy with `firebase deploy`
4
4
 
5
5
  from firebase_functions import https_fn
6
+ from firebase_functions.options import set_global_options
6
7
  from firebase_admin import initialize_app
7
8
 
9
+ # For cost control, you can set the maximum number of containers that can be
10
+ # running at the same time. This helps mitigate the impact of unexpected
11
+ # traffic spikes by instead downgrading performance. This limit is a per-function
12
+ # limit. You can override the limit for each function using the max_instances
13
+ # parameter in the decorator, e.g. @https_fn.on_request(max_instances=5).
14
+ set_global_options(max_instances=10)
15
+
8
16
  # initialize_app()
9
17
  #
10
18
  #
@@ -7,12 +7,25 @@
7
7
  * See a full list of supported triggers at https://firebase.google.com/docs/functions
8
8
  */
9
9
 
10
- import {onRequest} from "firebase-functions/v2/https";
10
+ import {setGlobalOptions} from "firebase-functions";
11
+ import {onRequest} from "firebase-functions/https";
11
12
  import * as logger from "firebase-functions/logger";
12
13
 
13
14
  // Start writing functions
14
15
  // https://firebase.google.com/docs/functions/typescript
15
16
 
17
+ // For cost control, you can set the maximum number of containers that can be
18
+ // running at the same time. This helps mitigate the impact of unexpected
19
+ // traffic spikes by instead downgrading performance. This limit is a
20
+ // per-function limit. You can override the limit for each function using the
21
+ // `maxInstances` option in the function's options, e.g.
22
+ // `onRequest({ maxInstances: 5 }, (req, res) => { ... })`.
23
+ // NOTE: setGlobalOptions does not apply to functions using the v1 API. V1
24
+ // functions should each use functions.runWith({ maxInstances: 10 }) instead.
25
+ // In the v1 API, each function can only serve one request per container, so
26
+ // this will be the maximum concurrent request count.
27
+ setGlobalOptions({ maxInstances: 10 });
28
+
16
29
  // export const helloWorld = onRequest((request, response) => {
17
30
  // logger.info("Hello logs!", {structuredData: true});
18
31
  // response.send("Hello from Firebase!");