firebase-tools 13.2.1 → 13.3.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.
package/lib/auth.js CHANGED
@@ -307,7 +307,7 @@ async function loginRemotely() {
307
307
  const tokens = await getTokensFromAuthorizationCode(code, `${api_1.authProxyOrigin}/complete`, codeVerifier);
308
308
  void (0, track_1.trackGA4)("login", { method: "google_remote" });
309
309
  return {
310
- user: jwt.decode(tokens.id_token),
310
+ user: jwt.decode(tokens.id_token, { json: true }),
311
311
  tokens: tokens,
312
312
  scopes: SCOPES,
313
313
  };
@@ -323,7 +323,7 @@ async function loginWithLocalhostGoogle(port, userHint) {
323
323
  const tokens = await loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, getTokensFromAuthorizationCode);
324
324
  void (0, track_1.trackGA4)("login", { method: "google_localhost" });
325
325
  return {
326
- user: jwt.decode(tokens.id_token),
326
+ user: jwt.decode(tokens.id_token, { json: true }),
327
327
  tokens: tokens,
328
328
  scopes: tokens.scopes,
329
329
  };
@@ -477,6 +477,15 @@ async function refreshTokens(refreshToken, authScopes) {
477
477
  skipLog: { body: true, queryParams: true, resBody: true },
478
478
  resolveOnHTTPError: true,
479
479
  });
480
+ const forceReauthErrs = [
481
+ { error: "invalid_grant", error_subtype: "invalid_rapt" },
482
+ ];
483
+ const matches = (a, b) => {
484
+ return a.error === b.error && a.error_subtype === b.error_subtype;
485
+ };
486
+ if (forceReauthErrs.some((a) => matches(a, res.body))) {
487
+ throw invalidCredentialError();
488
+ }
480
489
  if (res.status === 401 || res.status === 400) {
481
490
  return { access_token: refreshToken };
482
491
  }
@@ -14,7 +14,7 @@ exports.command = new command_1.Command("apphosting:backends:list")
14
14
  .option("-l, --location <location>", "App Backend location", "-")
15
15
  .before(apphosting.ensureApiEnabled)
16
16
  .action(async (options) => {
17
- var _a, _b, _c;
17
+ var _a, _b, _c, _d;
18
18
  const projectId = (0, projectUtils_1.needProjectId)(options);
19
19
  const location = options.location;
20
20
  const table = new Table({ head: TABLE_HEAD, style: { head: ["green"] } });
@@ -25,12 +25,12 @@ exports.command = new command_1.Command("apphosting:backends:list")
25
25
  catch (err) {
26
26
  throw new error_1.FirebaseError(`Unable to list backends present for project: ${projectId}. Please check the parameters you have provided.`, { original: err });
27
27
  }
28
- const backends = backendRes === null || backendRes === void 0 ? void 0 : backendRes.backends;
28
+ const backends = (_a = backendRes.backends) !== null && _a !== void 0 ? _a : [];
29
29
  for (const backend of backends) {
30
30
  const [backendLocation, , backendId] = backend.name.split("/").slice(3, 6);
31
31
  table.push([
32
32
  backendId,
33
- (_c = (_b = (_a = backend.codebase) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.split("/").pop()) !== null && _c !== void 0 ? _c : "",
33
+ (_d = (_c = (_b = backend.codebase) === null || _b === void 0 ? void 0 : _b.repository) === null || _c === void 0 ? void 0 : _c.split("/").pop()) !== null && _d !== void 0 ? _d : "",
34
34
  backendLocation,
35
35
  backend.uri.startsWith("https:") ? backend.uri : "https://" + backend.uri,
36
36
  (0, utils_1.datetimeString)(new Date(backend.createTime)),
@@ -12,15 +12,16 @@ exports.command = new command_1.Command("apphosting:builds:create <backendId>")
12
12
  .option("-b, --branch <branch>", "Repository branch to deploy. Defaults to 'main'", "main")
13
13
  .before(apphosting.ensureApiEnabled)
14
14
  .action(async (backendId, options) => {
15
+ var _a;
15
16
  const projectId = (0, projectUtils_1.needProjectId)(options);
16
17
  const location = options.location;
17
18
  const buildId = options.buildId ||
18
19
  (await apphosting.getNextRolloutId(projectId, location, backendId));
19
- const branch = options.branch;
20
+ const branch = (_a = options.branch) !== null && _a !== void 0 ? _a : "main";
20
21
  const op = await apphosting.createBuild(projectId, location, backendId, buildId, {
21
22
  source: {
22
23
  codebase: {
23
- branch: "main",
24
+ branch,
24
25
  },
25
26
  },
26
27
  });
@@ -144,7 +144,7 @@ function load(client) {
144
144
  client.internaltesting.functions = {};
145
145
  client.internaltesting.functions.discover = loadCommand("internaltesting-functions-discover");
146
146
  }
147
- if (experiments.isEnabled("internalframeworks")) {
147
+ if (experiments.isEnabled("apphosting")) {
148
148
  client.apphosting = {};
149
149
  client.apphosting.backends = {};
150
150
  client.apphosting.backends.list = loadCommand("apphosting-backends-list");
@@ -69,10 +69,10 @@ const choices = [
69
69
  checked: false,
70
70
  },
71
71
  ];
72
- if ((0, experiments_1.isEnabled)("internalframeworks")) {
72
+ if ((0, experiments_1.isEnabled)("apphosting")) {
73
73
  choices.push({
74
- value: "internalframeworks",
75
- name: "Frameworks: Get started with Frameworks projects.",
74
+ value: "apphosting",
75
+ name: "App Hosting: Get started with App Hosting projects.",
76
76
  checked: false,
77
77
  });
78
78
  }
@@ -14,6 +14,7 @@ const RUNTIMES = [
14
14
  "nodejs20",
15
15
  "python310",
16
16
  "python311",
17
+ "python312",
17
18
  ];
18
19
  const EXPERIMENTAL_RUNTIMES = [];
19
20
  const DEPRECATED_RUNTIMES = ["nodejs6", "nodejs8"];
@@ -36,6 +37,7 @@ const MESSAGE_FRIENDLY_RUNTIMES = {
36
37
  nodejs20: "Node.js 20",
37
38
  python310: "Python 3.10",
38
39
  python311: "Python 3.11",
40
+ python312: "Python 3.12",
39
41
  };
40
42
  function getHumanFriendlyRuntimeName(runtime) {
41
43
  return MESSAGE_FRIENDLY_RUNTIMES[runtime] || runtime;
@@ -11,7 +11,7 @@ const discovery = require("../discovery");
11
11
  const logger_1 = require("../../../../logger");
12
12
  const python_1 = require("../../../../functions/python");
13
13
  const error_1 = require("../../../../error");
14
- exports.LATEST_VERSION = "python311";
14
+ exports.LATEST_VERSION = "python312";
15
15
  async function tryCreateDelegate(context) {
16
16
  const requirementsTextPath = path.join(context.sourceDir, "requirements.txt");
17
17
  if (!(await (0, util_1.promisify)(fs.exists)(requirementsTextPath))) {
@@ -35,6 +35,9 @@ function getPythonBinary(runtime) {
35
35
  else if (runtime === "python311") {
36
36
  return "python3.11";
37
37
  }
38
+ else if (runtime === "python312") {
39
+ return "python3.12";
40
+ }
38
41
  return "python";
39
42
  }
40
43
  exports.getPythonBinary = getPythonBinary;
@@ -9,7 +9,7 @@ async function getDatabase(project, databaseId) {
9
9
  if (dbCache.has(key)) {
10
10
  return dbCache.get(key);
11
11
  }
12
- const db = await firestore.getDatabase(project, databaseId);
12
+ const db = await firestore.getDatabase(project, databaseId, false);
13
13
  dbCache.set(key, db);
14
14
  return db;
15
15
  }
@@ -331,7 +331,7 @@ function createAuthExpressionValue(opts) {
331
331
  return toExpressionValue(null);
332
332
  }
333
333
  else {
334
- const tokenPayload = jwt.decode(opts.token);
334
+ const tokenPayload = jwt.decode(opts.token, { json: true });
335
335
  const jsonValue = {
336
336
  uid: tokenPayload.user_id,
337
337
  token: tokenPayload,
@@ -72,9 +72,9 @@ exports.ALL_EXPERIMENTS = experiments({
72
72
  "These commands are not meant for public consumption and may break or disappear " +
73
73
  "without a notice.",
74
74
  },
75
- internalframeworks: {
75
+ apphosting: {
76
76
  shortDescription: "Allow CLI option for Frameworks",
77
- default: true,
77
+ default: false,
78
78
  public: false,
79
79
  },
80
80
  });
@@ -219,7 +219,7 @@ class FirestoreDelete {
219
219
  }
220
220
  numPendingDeletes++;
221
221
  firestore
222
- .deleteDocuments(this.project, toDelete)
222
+ .deleteDocuments(this.project, toDelete, true)
223
223
  .then((numDeleted) => {
224
224
  FirestoreDelete.progressBar.tick(numDeleted);
225
225
  numDocsDeleted += numDeleted;
@@ -280,7 +280,7 @@ class FirestoreDelete {
280
280
  let initialDelete;
281
281
  if (this.isDocumentPath) {
282
282
  const doc = { name: this.root + "/" + this.path };
283
- initialDelete = firestore.deleteDocument(doc).catch((err) => {
283
+ initialDelete = firestore.deleteDocument(doc, true).catch((err) => {
284
284
  logger_1.logger.debug("deletePath:initialDelete:error", err);
285
285
  if (this.allDescendants) {
286
286
  return Promise.resolve();
@@ -297,7 +297,7 @@ class FirestoreDelete {
297
297
  }
298
298
  deleteDatabase() {
299
299
  return firestore
300
- .listCollectionIds(this.project)
300
+ .listCollectionIds(this.project, true)
301
301
  .catch((err) => {
302
302
  logger_1.logger.debug("deleteDatabase:listCollectionIds:error", err);
303
303
  return utils.reject("Unable to list collection IDs");
@@ -8,6 +8,7 @@ const api_1 = require("../api");
8
8
  const ensureApiEnabled_1 = require("../ensureApiEnabled");
9
9
  const deploymentTool = require("../deploymentTool");
10
10
  const error_1 = require("../error");
11
+ const metaprogramming_1 = require("../metaprogramming");
11
12
  exports.API_HOST = new URL(api_1.apphostingOrigin).host;
12
13
  exports.API_VERSION = "v1alpha";
13
14
  exports.client = new apiv2_1.Client({
@@ -15,6 +16,10 @@ exports.client = new apiv2_1.Client({
15
16
  auth: true,
16
17
  apiVersion: exports.API_VERSION,
17
18
  });
19
+ (0, metaprogramming_1.assertImplements)();
20
+ (0, metaprogramming_1.assertImplements)();
21
+ (0, metaprogramming_1.assertImplements)();
22
+ (0, metaprogramming_1.assertImplements)();
18
23
  async function createBackend(projectId, location, backendReqBoby, backendId) {
19
24
  const res = await exports.client.post(`projects/${projectId}/locations/${location}/backends`, Object.assign(Object.assign({}, backendReqBoby), { labels: Object.assign(Object.assign({}, backendReqBoby.labels), deploymentTool.labels()) }), { queryParams: { backendId } });
20
25
  return res.body;
@@ -92,11 +97,7 @@ async function listRollouts(projectId, location, backendId) {
92
97
  }
93
98
  exports.listRollouts = listRollouts;
94
99
  async function updateTraffic(projectId, location, backendId, traffic) {
95
- const trafficCopy = Object.assign({}, traffic);
96
- if ("rolloutPolicy" in traffic) {
97
- trafficCopy.rolloutPolicy = {};
98
- }
99
- const fieldMasks = proto.fieldMasks(trafficCopy);
100
+ const fieldMasks = proto.fieldMasks(traffic, "rolloutPolicy");
100
101
  const queryParams = {
101
102
  updateMask: fieldMasks.join(","),
102
103
  };
@@ -125,7 +126,7 @@ async function listLocations(projectId) {
125
126
  exports.listLocations = listLocations;
126
127
  async function ensureApiEnabled(options) {
127
128
  const projectId = (0, projectUtils_1.needProjectId)(options);
128
- return await (0, ensureApiEnabled_1.ensure)(projectId, exports.API_HOST, "frameworks", true);
129
+ return await (0, ensureApiEnabled_1.ensure)(projectId, exports.API_HOST, "app hosting", true);
129
130
  }
130
131
  exports.ensureApiEnabled = ensureApiEnabled;
131
132
  async function getNextRolloutId(projectId, location, backendId, counter) {
@@ -133,7 +134,7 @@ async function getNextRolloutId(projectId, location, backendId, counter) {
133
134
  const date = new Date();
134
135
  const year = date.getUTCFullYear();
135
136
  const month = String(date.getUTCMonth() + 1).padStart(2, "0");
136
- const day = String(date.getUTCDay()).padStart(2, "0");
137
+ const day = String(date.getUTCDate()).padStart(2, "0");
137
138
  if (counter) {
138
139
  return `build-${year}-${month}-${day}-${String(counter).padStart(3, "0")}`;
139
140
  }
@@ -4,12 +4,18 @@ exports.deleteDocuments = exports.deleteDocument = exports.listCollectionIds = e
4
4
  const api_1 = require("../api");
5
5
  const apiv2_1 = require("../apiv2");
6
6
  const logger_1 = require("../logger");
7
- const apiClient = new apiv2_1.Client({
7
+ const prodOnlyClient = new apiv2_1.Client({
8
8
  auth: true,
9
9
  apiVersion: "v1",
10
10
  urlPrefix: api_1.firestoreOrigin,
11
11
  });
12
- async function getDatabase(project, database) {
12
+ const emuOrProdClient = new apiv2_1.Client({
13
+ auth: true,
14
+ apiVersion: "v1",
15
+ urlPrefix: api_1.firestoreOriginOrEmulator,
16
+ });
17
+ async function getDatabase(project, database, allowEmulator = false) {
18
+ const apiClient = allowEmulator ? emuOrProdClient : prodOnlyClient;
13
19
  const url = `projects/${project}/databases/${database}`;
14
20
  try {
15
21
  const resp = await apiClient.get(url);
@@ -21,7 +27,8 @@ async function getDatabase(project, database) {
21
27
  }
22
28
  }
23
29
  exports.getDatabase = getDatabase;
24
- function listCollectionIds(project) {
30
+ function listCollectionIds(project, allowEmulator = false) {
31
+ const apiClient = allowEmulator ? emuOrProdClient : prodOnlyClient;
25
32
  const url = "projects/" + project + "/databases/(default)/documents:listCollectionIds";
26
33
  const data = {
27
34
  pageSize: 2147483647,
@@ -31,11 +38,13 @@ function listCollectionIds(project) {
31
38
  });
32
39
  }
33
40
  exports.listCollectionIds = listCollectionIds;
34
- async function deleteDocument(doc) {
41
+ async function deleteDocument(doc, allowEmulator = false) {
42
+ const apiClient = allowEmulator ? emuOrProdClient : prodOnlyClient;
35
43
  return apiClient.delete(doc.name);
36
44
  }
37
45
  exports.deleteDocument = deleteDocument;
38
- async function deleteDocuments(project, docs) {
46
+ async function deleteDocuments(project, docs, allowEmulator = false) {
47
+ const apiClient = allowEmulator ? emuOrProdClient : prodOnlyClient;
39
48
  const url = "projects/" + project + "/databases/(default)/documents:commit";
40
49
  const writes = docs.map((doc) => {
41
50
  return { delete: doc.name };
@@ -1,3 +1,4 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- const optionsAreHostingOptions = true;
3
+ const metaprogramming_1 = require("../metaprogramming");
4
+ (0, metaprogramming_1.assertImplements)();
@@ -1,2 +1,5 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.assertImplements = void 0;
4
+ function assertImplements() { }
5
+ exports.assertImplements = assertImplements;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "13.2.1",
3
+ "version": "13.3.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {