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 +11 -2
- package/lib/commands/apphosting-backends-list.js +3 -3
- package/lib/commands/apphosting-builds-create.js +3 -2
- package/lib/commands/index.js +1 -1
- package/lib/commands/init.js +3 -3
- package/lib/deploy/functions/runtimes/index.js +2 -0
- package/lib/deploy/functions/runtimes/python/index.js +4 -1
- package/lib/deploy/functions/services/firestore.js +1 -1
- package/lib/emulator/storage/rules/runtime.js +1 -1
- package/lib/experiments.js +2 -2
- package/lib/firestore/delete.js +3 -3
- package/lib/gcp/apphosting.js +8 -7
- package/lib/gcp/firestore.js +14 -5
- package/lib/hosting/options.js +2 -1
- package/lib/metaprogramming.js +3 -0
- package/package.json +1 -1
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
|
|
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
|
-
(
|
|
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
|
|
24
|
+
branch,
|
|
24
25
|
},
|
|
25
26
|
},
|
|
26
27
|
});
|
package/lib/commands/index.js
CHANGED
|
@@ -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("
|
|
147
|
+
if (experiments.isEnabled("apphosting")) {
|
|
148
148
|
client.apphosting = {};
|
|
149
149
|
client.apphosting.backends = {};
|
|
150
150
|
client.apphosting.backends.list = loadCommand("apphosting-backends-list");
|
package/lib/commands/init.js
CHANGED
|
@@ -69,10 +69,10 @@ const choices = [
|
|
|
69
69
|
checked: false,
|
|
70
70
|
},
|
|
71
71
|
];
|
|
72
|
-
if ((0, experiments_1.isEnabled)("
|
|
72
|
+
if ((0, experiments_1.isEnabled)("apphosting")) {
|
|
73
73
|
choices.push({
|
|
74
|
-
value: "
|
|
75
|
-
name: "
|
|
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 = "
|
|
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,
|
package/lib/experiments.js
CHANGED
|
@@ -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
|
-
|
|
75
|
+
apphosting: {
|
|
76
76
|
shortDescription: "Allow CLI option for Frameworks",
|
|
77
|
-
default:
|
|
77
|
+
default: false,
|
|
78
78
|
public: false,
|
|
79
79
|
},
|
|
80
80
|
});
|
package/lib/firestore/delete.js
CHANGED
|
@@ -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");
|
package/lib/gcp/apphosting.js
CHANGED
|
@@ -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
|
|
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, "
|
|
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.
|
|
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
|
}
|
package/lib/gcp/firestore.js
CHANGED
|
@@ -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
|
|
7
|
+
const prodOnlyClient = new apiv2_1.Client({
|
|
8
8
|
auth: true,
|
|
9
9
|
apiVersion: "v1",
|
|
10
10
|
urlPrefix: api_1.firestoreOrigin,
|
|
11
11
|
});
|
|
12
|
-
|
|
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 };
|
package/lib/hosting/options.js
CHANGED
package/lib/metaprogramming.js
CHANGED