firebase-tools 14.27.0 → 15.1.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/appUtils.js +14 -15
- package/lib/archiveDirectory.js +7 -45
- package/lib/bin/cli.js +35 -8
- package/lib/bin/mcp.js +46 -8
- package/lib/command.js +5 -1
- package/lib/commands/dataconnect-execute.js +1 -1
- package/lib/commands/dataconnect-sdk-generate.js +7 -5
- package/lib/commands/dataconnect-sql-diff.js +7 -5
- package/lib/commands/dataconnect-sql-grant.js +12 -12
- package/lib/commands/dataconnect-sql-migrate.js +6 -4
- package/lib/commands/dataconnect-sql-setup.js +6 -4
- package/lib/commands/dataconnect-sql-shell.js +6 -4
- package/lib/commands/firestore-backups-list.js +1 -1
- package/lib/commands/functions-config-clone.js +2 -2
- package/lib/commands/functions-config-export.js +137 -92
- package/lib/commands/functions-config-get.js +1 -2
- package/lib/commands/functions-config-set.js +2 -2
- package/lib/commands/functions-config-unset.js +2 -2
- package/lib/commands/help.js +1 -1
- package/lib/commands/index.js +15 -10
- package/lib/commands/init.js +8 -0
- package/lib/config.js +1 -5
- package/lib/dataconnect/load.js +18 -21
- package/lib/deploy/database/prepare.js +1 -3
- package/lib/deploy/functions/prepare.js +5 -1
- package/lib/deploy/functions/prepareFunctionsUpload.js +1 -2
- package/lib/deploy/functions/runtimes/node/index.js +11 -12
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/validate.js +49 -2
- package/lib/emulator/commandUtils.js +1 -1
- package/lib/emulator/controller.js +1 -2
- package/lib/emulator/databaseEmulator.js +1 -5
- package/lib/emulator/downloadableEmulatorInfo.json +30 -30
- package/lib/emulator/functionsEmulator.js +0 -40
- package/lib/emulator/functionsEmulatorRuntime.js +1 -118
- package/lib/emulator/functionsEmulatorShared.js +1 -6
- package/lib/experiments.js +8 -1
- package/lib/extensions/extensionsHelper.js +0 -1
- package/lib/frameworks/constants.js +1 -1
- package/lib/fsAsync.js +11 -3
- package/lib/functionsConfig.js +39 -1
- package/lib/gcp/cloudsql/cloudsqladmin.js +1 -1
- package/lib/index.js +44 -1
- package/lib/init/features/dataconnect/resolver.js +111 -0
- package/lib/init/features/index.js +4 -1
- package/lib/init/features/project.js +1 -0
- package/lib/init/index.js +5 -0
- package/lib/mcp/index.js +31 -22
- package/lib/mcp/tools/core/get_environment.js +4 -1
- package/lib/mcp/tools/dataconnect/compile.js +13 -7
- package/lib/mcp/tools/dataconnect/execute.js +10 -7
- package/lib/mcp/tools/dataconnect/generate_operation.js +7 -3
- package/lib/mcp/tools/index.js +53 -44
- package/package.json +1 -2
- package/lib/deploy/functions/runtimes/node/extractTriggers.js +0 -23
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +0 -332
- package/lib/deploy/functions/runtimes/node/triggerParser.js +0 -72
- package/lib/functions/deprecationWarnings.js +0 -21
- package/lib/functions/runtimeConfigExport.js +0 -141
- package/lib/handlePreviewToggles.js +0 -38
- package/lib/parseBoltRules.js +0 -29
|
@@ -1,16 +1,22 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.secretsAreValid = exports.functionIdsAreValid = exports.functionsDirectoryExists = exports.endpointsAreUnique = exports.cpuConfigIsValid = exports.endpointsAreValid = exports.MAX_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = exports.DEFAULT_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = void 0;
|
|
3
|
+
exports.secretsAreValid = exports.functionIdsAreValid = exports.functionsDirectoryExists = exports.endpointsAreUnique = exports.validateTimeoutConfig = exports.cpuConfigIsValid = exports.endpointsAreValid = exports.MAX_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = exports.DEFAULT_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = void 0;
|
|
4
4
|
const path = require("path");
|
|
5
5
|
const clc = require("colorette");
|
|
6
6
|
const error_1 = require("../../error");
|
|
7
7
|
const secretManager_1 = require("../../gcp/secretManager");
|
|
8
8
|
const logger_1 = require("../../logger");
|
|
9
|
+
const functionsDeployHelper_1 = require("./functionsDeployHelper");
|
|
10
|
+
const services_1 = require("./services");
|
|
9
11
|
const fsutils = require("../../fsutils");
|
|
10
12
|
const backend = require("./backend");
|
|
11
13
|
const utils = require("../../utils");
|
|
12
14
|
const secrets = require("../../functions/secrets");
|
|
13
|
-
const
|
|
15
|
+
const MAX_V1_TIMEOUT_SECONDS = 540;
|
|
16
|
+
const MAX_V2_EVENTS_TIMEOUT_SECONDS = 540;
|
|
17
|
+
const MAX_V2_SCHEDULE_TIMEOUT_SECONDS = 1800;
|
|
18
|
+
const MAX_V2_TASK_QUEUE_TIMEOUT_SECONDS = 1800;
|
|
19
|
+
const MAX_V2_HTTP_TIMEOUT_SECONDS = 3600;
|
|
14
20
|
exports.DEFAULT_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = 180;
|
|
15
21
|
exports.MAX_V2_SCHEDULE_ATTEMPT_DEADLINE_SECONDS = 1800;
|
|
16
22
|
function matchingIds(endpoints, filter) {
|
|
@@ -39,6 +45,7 @@ function validateScheduledTimeout(ep) {
|
|
|
39
45
|
function endpointsAreValid(wantBackend) {
|
|
40
46
|
const endpoints = backend.allEndpoints(wantBackend);
|
|
41
47
|
functionIdsAreValid(endpoints);
|
|
48
|
+
validateTimeoutConfig(endpoints);
|
|
42
49
|
for (const ep of endpoints) {
|
|
43
50
|
validateScheduledTimeout(ep);
|
|
44
51
|
(0, services_1.serviceForEndpoint)(ep).validateTrigger(ep, wantBackend);
|
|
@@ -116,6 +123,46 @@ function cpuConfigIsValid(endpoints) {
|
|
|
116
123
|
}
|
|
117
124
|
}
|
|
118
125
|
exports.cpuConfigIsValid = cpuConfigIsValid;
|
|
126
|
+
function validateTimeoutConfig(endpoints) {
|
|
127
|
+
const invalidEndpoints = [];
|
|
128
|
+
for (const ep of endpoints) {
|
|
129
|
+
const timeout = ep.timeoutSeconds;
|
|
130
|
+
if (!timeout) {
|
|
131
|
+
continue;
|
|
132
|
+
}
|
|
133
|
+
let limit;
|
|
134
|
+
if (ep.platform === "gcfv1") {
|
|
135
|
+
limit = MAX_V1_TIMEOUT_SECONDS;
|
|
136
|
+
}
|
|
137
|
+
else if (backend.isEventTriggered(ep)) {
|
|
138
|
+
limit = MAX_V2_EVENTS_TIMEOUT_SECONDS;
|
|
139
|
+
}
|
|
140
|
+
else if (backend.isScheduleTriggered(ep)) {
|
|
141
|
+
limit = MAX_V2_SCHEDULE_TIMEOUT_SECONDS;
|
|
142
|
+
}
|
|
143
|
+
else if (backend.isTaskQueueTriggered(ep)) {
|
|
144
|
+
limit = MAX_V2_TASK_QUEUE_TIMEOUT_SECONDS;
|
|
145
|
+
}
|
|
146
|
+
else if (backend.isHttpsTriggered(ep) || backend.isCallableTriggered(ep)) {
|
|
147
|
+
limit = MAX_V2_HTTP_TIMEOUT_SECONDS;
|
|
148
|
+
}
|
|
149
|
+
if (limit !== undefined && timeout > limit) {
|
|
150
|
+
invalidEndpoints.push({ ep, limit });
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (invalidEndpoints.length === 0) {
|
|
154
|
+
return;
|
|
155
|
+
}
|
|
156
|
+
const invalidList = invalidEndpoints
|
|
157
|
+
.sort((a, b) => backend.compareFunctions(a.ep, b.ep))
|
|
158
|
+
.map(({ ep, limit }) => `\t${(0, functionsDeployHelper_1.getFunctionLabel)(ep)}: ${ep.timeoutSeconds}s (limit: ${limit}s)`)
|
|
159
|
+
.join("\n");
|
|
160
|
+
const msg = "The following functions have timeouts that exceed the maximum allowed for their trigger type:\n\n" +
|
|
161
|
+
invalidList +
|
|
162
|
+
"\n\nFor more information, see https://firebase.google.com/docs/functions/quotas#time_limits";
|
|
163
|
+
throw new error_1.FirebaseError(msg);
|
|
164
|
+
}
|
|
165
|
+
exports.validateTimeoutConfig = validateTimeoutConfig;
|
|
119
166
|
function endpointsAreUnique(backends) {
|
|
120
167
|
const endpointToCodebases = {};
|
|
121
168
|
for (const [codebase, b] of Object.entries(backends)) {
|
|
@@ -385,5 +385,5 @@ async function checkJavaMajorVersion() {
|
|
|
385
385
|
}
|
|
386
386
|
exports.checkJavaMajorVersion = checkJavaMajorVersion;
|
|
387
387
|
exports.MIN_SUPPORTED_JAVA_MAJOR_VERSION = 21;
|
|
388
|
-
exports.JAVA_DEPRECATION_WARNING = "firebase-tools
|
|
388
|
+
exports.JAVA_DEPRECATION_WARNING = "firebase-tools no longer supports Java version before 21. " +
|
|
389
389
|
"Please install a JDK at version 21 or above to get a compatible runtime.";
|
|
@@ -180,8 +180,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
180
180
|
const deprecationNotices = [];
|
|
181
181
|
if (targets.some(downloadableEmulators_1.requiresJava)) {
|
|
182
182
|
if ((await commandUtils.checkJavaMajorVersion()) < commandUtils_1.MIN_SUPPORTED_JAVA_MAJOR_VERSION) {
|
|
183
|
-
|
|
184
|
-
deprecationNotices.push(commandUtils_1.JAVA_DEPRECATION_WARNING);
|
|
183
|
+
throw new error_1.FirebaseError(commandUtils_1.JAVA_DEPRECATION_WARNING);
|
|
185
184
|
}
|
|
186
185
|
}
|
|
187
186
|
if (options.logVerbosity) {
|
|
@@ -12,7 +12,6 @@ const constants_1 = require("./constants");
|
|
|
12
12
|
const registry_1 = require("./registry");
|
|
13
13
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
14
14
|
const error_1 = require("../error");
|
|
15
|
-
const parseBoltRules_1 = require("../parseBoltRules");
|
|
16
15
|
const utils_1 = require("../utils");
|
|
17
16
|
class DatabaseEmulator {
|
|
18
17
|
constructor(args) {
|
|
@@ -123,10 +122,7 @@ class DatabaseEmulator {
|
|
|
123
122
|
}
|
|
124
123
|
async updateRules(instance, rulesPath) {
|
|
125
124
|
var _a;
|
|
126
|
-
const
|
|
127
|
-
const content = rulesExt === ".bolt"
|
|
128
|
-
? (0, parseBoltRules_1.parseBoltRules)(rulesPath).toString()
|
|
129
|
-
: fs.readFileSync(rulesPath, "utf8");
|
|
125
|
+
const content = fs.readFileSync(rulesPath, "utf8");
|
|
130
126
|
try {
|
|
131
127
|
await registry_1.EmulatorRegistry.client(types_1.Emulators.DATABASE).put(`/.settings/rules.json`, content, {
|
|
132
128
|
headers: { Authorization: "Bearer owner" },
|
|
@@ -8,12 +8,12 @@
|
|
|
8
8
|
"downloadPathRelativeToCacheDir": "firebase-database-emulator-v4.11.2.jar"
|
|
9
9
|
},
|
|
10
10
|
"firestore": {
|
|
11
|
-
"version": "1.
|
|
12
|
-
"expectedSize":
|
|
13
|
-
"expectedChecksum": "
|
|
14
|
-
"expectedChecksumSHA256": "
|
|
15
|
-
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.
|
|
16
|
-
"downloadPathRelativeToCacheDir": "cloud-firestore-emulator-v1.
|
|
11
|
+
"version": "1.20.2",
|
|
12
|
+
"expectedSize": 123046947,
|
|
13
|
+
"expectedChecksum": "3b04168138ff8ab17025fe7756e05dc9",
|
|
14
|
+
"expectedChecksumSHA256": "4a117fc297b1441eac1b7756e80442e86ef88865b9e3caf6f59eabf83da574f8",
|
|
15
|
+
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/cloud-firestore-emulator-v1.20.2.jar",
|
|
16
|
+
"downloadPathRelativeToCacheDir": "cloud-firestore-emulator-v1.20.2.jar"
|
|
17
17
|
},
|
|
18
18
|
"storage": {
|
|
19
19
|
"version": "1.1.3",
|
|
@@ -54,36 +54,36 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-
|
|
57
|
+
"version": "3.0.1",
|
|
58
|
+
"expectedSize": 30212960,
|
|
59
|
+
"expectedChecksum": "5a556a6e52d8e4707be9e65555cf6fc0",
|
|
60
|
+
"expectedChecksumSHA256": "04507e034d26a9e1053a246508351881473c82daf86357a28472e112f50e0128",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v3.0.1",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
|
|
63
63
|
},
|
|
64
64
|
"darwin_arm64": {
|
|
65
|
-
"version": "
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-
|
|
65
|
+
"version": "3.0.1",
|
|
66
|
+
"expectedSize": 29680322,
|
|
67
|
+
"expectedChecksum": "31b21517979ce3acc408c432023a97e5",
|
|
68
|
+
"expectedChecksumSHA256": "36e2db3abf7a024436ba045805153a5f7ae2845f34658c187c38aeff329c6626",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v3.0.1",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
|
|
71
71
|
},
|
|
72
72
|
"win32": {
|
|
73
|
-
"version": "
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-
|
|
73
|
+
"version": "3.0.1",
|
|
74
|
+
"expectedSize": 30712832,
|
|
75
|
+
"expectedChecksum": "953603294bf7112a5100936db813f928",
|
|
76
|
+
"expectedChecksumSHA256": "4a71d6ce535302a28215e08cc3b645818cf8d8204f4bb2512455d3b7d3c17df1",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v3.0.1",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1.exe"
|
|
79
79
|
},
|
|
80
80
|
"linux": {
|
|
81
|
-
"version": "
|
|
82
|
-
"expectedSize":
|
|
83
|
-
"expectedChecksum": "
|
|
84
|
-
"expectedChecksumSHA256": "
|
|
85
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-
|
|
86
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-
|
|
81
|
+
"version": "3.0.1",
|
|
82
|
+
"expectedSize": 30138552,
|
|
83
|
+
"expectedChecksum": "48d5f03c2edea8d4c6b200dccc9bf8a8",
|
|
84
|
+
"expectedChecksumSHA256": "cdf2d37f69b4372c0757afcc6c6ed4d7c6162fe7d29d9191e20e1411e116a665",
|
|
85
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v3.0.1",
|
|
86
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-3.0.1"
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
}
|
|
@@ -6,7 +6,6 @@ const path = require("path");
|
|
|
6
6
|
const express = require("express");
|
|
7
7
|
const clc = require("colorette");
|
|
8
8
|
const http = require("http");
|
|
9
|
-
const jwt = require("jsonwebtoken");
|
|
10
9
|
const cors = require("cors");
|
|
11
10
|
const semver = require("semver");
|
|
12
11
|
const url_1 = require("url");
|
|
@@ -1098,31 +1097,6 @@ class FunctionsEmulator {
|
|
|
1098
1097
|
}
|
|
1099
1098
|
return registry_1.EmulatorRegistry.getInfo(emulator);
|
|
1100
1099
|
}
|
|
1101
|
-
tokenFromAuthHeader(authHeader) {
|
|
1102
|
-
const match = /^Bearer (.*)$/.exec(authHeader);
|
|
1103
|
-
if (!match) {
|
|
1104
|
-
return;
|
|
1105
|
-
}
|
|
1106
|
-
let idToken = match[1];
|
|
1107
|
-
logger_1.logger.debug(`ID Token: ${idToken}`);
|
|
1108
|
-
if (idToken && idToken.includes("=")) {
|
|
1109
|
-
idToken = idToken.replace(/[=]+?\./g, ".");
|
|
1110
|
-
logger_1.logger.debug(`ID Token contained invalid padding, new value: ${idToken}`);
|
|
1111
|
-
}
|
|
1112
|
-
try {
|
|
1113
|
-
const decoded = jwt.decode(idToken, { complete: true });
|
|
1114
|
-
if (!decoded || typeof decoded !== "object") {
|
|
1115
|
-
logger_1.logger.debug(`Failed to decode ID Token: ${decoded}`);
|
|
1116
|
-
return;
|
|
1117
|
-
}
|
|
1118
|
-
const claims = decoded.payload;
|
|
1119
|
-
claims.uid = claims.sub;
|
|
1120
|
-
return claims;
|
|
1121
|
-
}
|
|
1122
|
-
catch (e) {
|
|
1123
|
-
return;
|
|
1124
|
-
}
|
|
1125
|
-
}
|
|
1126
1100
|
async handleHttpsTrigger(req, res) {
|
|
1127
1101
|
var _a;
|
|
1128
1102
|
const method = req.method;
|
|
@@ -1150,20 +1124,6 @@ class FunctionsEmulator {
|
|
|
1150
1124
|
req.headers["content-length"] = reqBody.length.toString();
|
|
1151
1125
|
}
|
|
1152
1126
|
}
|
|
1153
|
-
const isCallable = trigger.labels && trigger.labels["deployment-callable"] === "true";
|
|
1154
|
-
const authHeader = req.header("Authorization");
|
|
1155
|
-
if (authHeader && isCallable && trigger.platform !== "gcfv2") {
|
|
1156
|
-
const token = this.tokenFromAuthHeader(authHeader);
|
|
1157
|
-
if (token) {
|
|
1158
|
-
const contextAuth = {
|
|
1159
|
-
uid: token.uid,
|
|
1160
|
-
token: token,
|
|
1161
|
-
};
|
|
1162
|
-
req.headers[functionsEmulatorShared_1.HttpConstants.ORIGINAL_AUTH_HEADER] = req.headers["authorization"];
|
|
1163
|
-
delete req.headers["authorization"];
|
|
1164
|
-
req.headers[functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER] = encodeURIComponent(JSON.stringify(contextAuth));
|
|
1165
|
-
}
|
|
1166
|
-
}
|
|
1167
1127
|
void (0, track_1.trackEmulator)(EVENT_INVOKE_GA4, {
|
|
1168
1128
|
function_service: (0, functionsEmulatorShared_1.getFunctionService)(trigger),
|
|
1169
1129
|
});
|
|
@@ -1,6 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
const fs = require("fs");
|
|
4
3
|
const express = require("express");
|
|
5
4
|
const path = require("path");
|
|
6
5
|
const bodyParser = require("body-parser");
|
|
@@ -138,7 +137,7 @@ async function assertResolveDeveloperNodeModule(name) {
|
|
|
138
137
|
async function verifyDeveloperNodeModules() {
|
|
139
138
|
const modBundles = [
|
|
140
139
|
{ name: "firebase-admin", isDev: false, minVersion: "8.9.0" },
|
|
141
|
-
{ name: "firebase-functions", isDev: false, minVersion: "3.
|
|
140
|
+
{ name: "firebase-functions", isDev: false, minVersion: "3.16.0" },
|
|
142
141
|
];
|
|
143
142
|
for (const modBundle of modBundles) {
|
|
144
143
|
const resolution = await resolveDeveloperNodeModule(modBundle.name);
|
|
@@ -264,87 +263,10 @@ async function initializeFirebaseFunctionsStubs() {
|
|
|
264
263
|
httpsProvider.onRequest = (handler) => {
|
|
265
264
|
return httpsProvider[onRequestInnerMethodName](handler, {});
|
|
266
265
|
};
|
|
267
|
-
const onCallInnerMethodName = "_onCallWithOptions";
|
|
268
|
-
const onCallMethodOriginal = httpsProvider[onCallInnerMethodName];
|
|
269
|
-
if (onCallMethodOriginal.length === 3) {
|
|
270
|
-
httpsProvider[onCallInnerMethodName] = (opts, handler, deployOpts) => {
|
|
271
|
-
const wrapped = wrapCallableHandler(handler);
|
|
272
|
-
const cf = onCallMethodOriginal(opts, wrapped, deployOpts);
|
|
273
|
-
return cf;
|
|
274
|
-
};
|
|
275
|
-
}
|
|
276
|
-
else {
|
|
277
|
-
httpsProvider[onCallInnerMethodName] = (handler, opts) => {
|
|
278
|
-
const wrapped = wrapCallableHandler(handler);
|
|
279
|
-
const cf = onCallMethodOriginal(wrapped, opts);
|
|
280
|
-
return cf;
|
|
281
|
-
};
|
|
282
|
-
}
|
|
283
|
-
httpsProvider.onCall = function (optsOrHandler, handler) {
|
|
284
|
-
if (onCallMethodOriginal.length === 3) {
|
|
285
|
-
let opts;
|
|
286
|
-
if (arguments.length === 1) {
|
|
287
|
-
opts = {};
|
|
288
|
-
handler = optsOrHandler;
|
|
289
|
-
}
|
|
290
|
-
else {
|
|
291
|
-
opts = optsOrHandler;
|
|
292
|
-
}
|
|
293
|
-
return httpsProvider[onCallInnerMethodName](opts, handler, {});
|
|
294
|
-
}
|
|
295
|
-
else {
|
|
296
|
-
return httpsProvider[onCallInnerMethodName](optsOrHandler, {});
|
|
297
|
-
}
|
|
298
|
-
};
|
|
299
|
-
}
|
|
300
|
-
function wrapCallableHandler(handler) {
|
|
301
|
-
const newHandler = (data, context) => {
|
|
302
|
-
if (context.rawRequest) {
|
|
303
|
-
const authContext = context.rawRequest.header(functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER);
|
|
304
|
-
if (authContext) {
|
|
305
|
-
logDebug("Callable functions auth override", {
|
|
306
|
-
key: functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER,
|
|
307
|
-
value: authContext,
|
|
308
|
-
});
|
|
309
|
-
context.auth = JSON.parse(decodeURIComponent(authContext));
|
|
310
|
-
delete context.rawRequest.headers[functionsEmulatorShared_1.HttpConstants.CALLABLE_AUTH_HEADER];
|
|
311
|
-
}
|
|
312
|
-
else {
|
|
313
|
-
logDebug("No callable functions auth found");
|
|
314
|
-
}
|
|
315
|
-
const originalAuth = context.rawRequest.header(functionsEmulatorShared_1.HttpConstants.ORIGINAL_AUTH_HEADER);
|
|
316
|
-
if (originalAuth) {
|
|
317
|
-
context.rawRequest.headers["authorization"] = originalAuth;
|
|
318
|
-
delete context.rawRequest.headers[functionsEmulatorShared_1.HttpConstants.ORIGINAL_AUTH_HEADER];
|
|
319
|
-
}
|
|
320
|
-
}
|
|
321
|
-
return handler(data, context);
|
|
322
|
-
};
|
|
323
|
-
return newHandler;
|
|
324
266
|
}
|
|
325
267
|
function getDefaultConfig() {
|
|
326
268
|
return JSON.parse(process.env.FIREBASE_CONFIG || "{}");
|
|
327
269
|
}
|
|
328
|
-
function initializeRuntimeConfig() {
|
|
329
|
-
if (!process.env.CLOUD_RUNTIME_CONFIG) {
|
|
330
|
-
const configPath = `${process.cwd()}/.runtimeconfig.json`;
|
|
331
|
-
try {
|
|
332
|
-
const configContent = fs.readFileSync(configPath, "utf8");
|
|
333
|
-
if (configContent) {
|
|
334
|
-
try {
|
|
335
|
-
JSON.parse(configContent.toString());
|
|
336
|
-
logDebug(`Found local functions config: ${configPath}`);
|
|
337
|
-
process.env.CLOUD_RUNTIME_CONFIG = configContent.toString();
|
|
338
|
-
}
|
|
339
|
-
catch (e) {
|
|
340
|
-
new types_1.EmulatorLog("SYSTEM", "function-runtimeconfig-json-invalid", "").log();
|
|
341
|
-
}
|
|
342
|
-
}
|
|
343
|
-
}
|
|
344
|
-
catch (e) {
|
|
345
|
-
}
|
|
346
|
-
}
|
|
347
|
-
}
|
|
348
270
|
async function initializeFirebaseAdminStubs() {
|
|
349
271
|
const adminResolution = await assertResolveDeveloperNodeModule("firebase-admin");
|
|
350
272
|
const localAdminModule = require(adminResolution.resolution);
|
|
@@ -453,43 +375,6 @@ function warnAboutStorageProd() {
|
|
|
453
375
|
}
|
|
454
376
|
new types_1.EmulatorLog("WARN_ONCE", "runtime-status", "The Firebase Storage emulator is not running, so calls to Firebase Storage will affect production.").log();
|
|
455
377
|
}
|
|
456
|
-
async function initializeFunctionsConfigHelper() {
|
|
457
|
-
const functionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
|
|
458
|
-
if ((0, functionsEmulatorUtils_1.compareVersionStrings)(functionsResolution.version, "7.0.0") >= 0) {
|
|
459
|
-
logDebug("Detected firebase-functions v7+, skipping config helper.");
|
|
460
|
-
return;
|
|
461
|
-
}
|
|
462
|
-
const localFunctionsModule = require(functionsResolution.resolution);
|
|
463
|
-
logDebug("Checked functions.config()", {
|
|
464
|
-
config: localFunctionsModule.config(),
|
|
465
|
-
});
|
|
466
|
-
const originalConfig = localFunctionsModule.config();
|
|
467
|
-
const proxiedConfig = new Proxied(originalConfig)
|
|
468
|
-
.any((parentConfig, parentKey) => {
|
|
469
|
-
const isInternal = parentKey.startsWith("Symbol(") || parentKey.startsWith("inspect");
|
|
470
|
-
if (!parentConfig[parentKey] && !isInternal) {
|
|
471
|
-
new types_1.EmulatorLog("SYSTEM", "functions-config-missing-value", "", {
|
|
472
|
-
key: parentKey,
|
|
473
|
-
}).log();
|
|
474
|
-
}
|
|
475
|
-
return parentConfig[parentKey];
|
|
476
|
-
})
|
|
477
|
-
.finalize();
|
|
478
|
-
const functionsModuleProxy = new Proxied(localFunctionsModule);
|
|
479
|
-
const proxiedFunctionsModule = functionsModuleProxy
|
|
480
|
-
.when("config", () => () => {
|
|
481
|
-
return proxiedConfig;
|
|
482
|
-
})
|
|
483
|
-
.finalize();
|
|
484
|
-
const v = require.cache[functionsResolution.resolution];
|
|
485
|
-
require.cache[functionsResolution.resolution] = Object.assign(v, {
|
|
486
|
-
exports: proxiedFunctionsModule,
|
|
487
|
-
path: path.dirname(functionsResolution.resolution),
|
|
488
|
-
});
|
|
489
|
-
logDebug("firebase-functions has been stubbed.", {
|
|
490
|
-
functionsResolution,
|
|
491
|
-
});
|
|
492
|
-
}
|
|
493
378
|
function rawBodySaver(req, res, buf) {
|
|
494
379
|
req.rawBody = buf;
|
|
495
380
|
}
|
|
@@ -580,9 +465,7 @@ async function initializeRuntime() {
|
|
|
580
465
|
new types_1.EmulatorLog("INFO", "runtime-status", `Your functions could not be parsed due to an issue with your node_modules (see above)`).log();
|
|
581
466
|
return;
|
|
582
467
|
}
|
|
583
|
-
initializeRuntimeConfig();
|
|
584
468
|
initializeNetworkFiltering();
|
|
585
|
-
await initializeFunctionsConfigHelper();
|
|
586
469
|
await initializeFirebaseFunctionsStubs();
|
|
587
470
|
await initializeFirebaseAdminStubs();
|
|
588
471
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toBackendInfo = exports.getSecretLocalPath = exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.emulatedFunctionsFromEndpoints = exports.prepareEndpoints = exports.eventServiceImplemented = exports.EmulatedTrigger = exports.
|
|
3
|
+
exports.toBackendInfo = exports.getSecretLocalPath = exports.getSignatureType = exports.formatHost = exports.findModuleRoot = exports.waitForBody = exports.getServiceFromEventType = exports.getFunctionService = exports.getTemporarySocketPath = exports.getEmulatedTriggersFromDefinitions = exports.emulatedFunctionsByRegion = exports.emulatedFunctionsFromEndpoints = exports.prepareEndpoints = exports.eventServiceImplemented = exports.EmulatedTrigger = exports.EVENTARC_SOURCE_ENV = void 0;
|
|
4
4
|
const os = require("os");
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const fs = require("fs");
|
|
@@ -23,11 +23,6 @@ const V2_EVENTS = [
|
|
|
23
23
|
...events.v2.FIRESTORE_EVENTS,
|
|
24
24
|
];
|
|
25
25
|
exports.EVENTARC_SOURCE_ENV = "EVENTARC_CLOUD_EVENT_SOURCE";
|
|
26
|
-
class HttpConstants {
|
|
27
|
-
}
|
|
28
|
-
exports.HttpConstants = HttpConstants;
|
|
29
|
-
HttpConstants.CALLABLE_AUTH_HEADER = "x-callable-context-auth";
|
|
30
|
-
HttpConstants.ORIGINAL_AUTH_HEADER = "x-original-auth";
|
|
31
26
|
class EmulatedTrigger {
|
|
32
27
|
constructor(definition, module) {
|
|
33
28
|
this.definition = definition;
|
package/lib/experiments.js
CHANGED
|
@@ -26,7 +26,7 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
26
26
|
"of deploys. This has been made an experiment due to backend bugs that are " +
|
|
27
27
|
"temporarily causing failures in some regions with this optimization enabled",
|
|
28
28
|
public: true,
|
|
29
|
-
default:
|
|
29
|
+
default: false,
|
|
30
30
|
},
|
|
31
31
|
deletegcfartifacts: {
|
|
32
32
|
shortDescription: `Add the ${(0, colorette_1.bold)("functions:deletegcfartifacts")} command to purge docker build images`,
|
|
@@ -39,6 +39,13 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
39
39
|
`Registry. The ${(0, colorette_1.bold)("functions:deletegcfartifacts")} command ` +
|
|
40
40
|
"will delete all Docker images created by Google Cloud Functions irrespective " +
|
|
41
41
|
"of how that image was created.",
|
|
42
|
+
public: false,
|
|
43
|
+
},
|
|
44
|
+
legacyRuntimeConfigCommands: {
|
|
45
|
+
shortDescription: "Expose legacy functions.config() CLI commands",
|
|
46
|
+
fullDescription: "The Cloud Runtime Config API is deprecated. Enable this experiment to continue using the " +
|
|
47
|
+
"`functions:config:*` commands while you migrate to the Firebase Functions params APIs.",
|
|
48
|
+
default: true,
|
|
42
49
|
public: true,
|
|
43
50
|
},
|
|
44
51
|
runfunctions: {
|
|
@@ -411,7 +411,6 @@ async function ensureExtensionsPublisherApiEnabled(options) {
|
|
|
411
411
|
exports.ensureExtensionsPublisherApiEnabled = ensureExtensionsPublisherApiEnabled;
|
|
412
412
|
async function archiveAndUploadSource(extPath, bucketName) {
|
|
413
413
|
const zippedSource = await (0, archiveDirectory_1.archiveDirectory)(extPath, {
|
|
414
|
-
type: "zip",
|
|
415
414
|
ignore: ["node_modules", ".git"],
|
|
416
415
|
});
|
|
417
416
|
const res = await (0, storage_1.uploadObject)(zippedSource, bucketName);
|
|
@@ -22,7 +22,7 @@ exports.FIREBASE_FUNCTIONS_VERSION = "^6.0.1";
|
|
|
22
22
|
exports.FIREBASE_ADMIN_VERSION = "^11.11.1";
|
|
23
23
|
exports.SHARP_VERSION = "^0.32 || ^0.33";
|
|
24
24
|
exports.NODE_VERSION = parseInt(process.versions.node, 10);
|
|
25
|
-
exports.VALID_ENGINES = { node: [
|
|
25
|
+
exports.VALID_ENGINES = { node: [20, 22, 24] };
|
|
26
26
|
exports.VALID_LOCALE_FORMATS = [/^ALL_[a-z]+$/, /^[a-z]+_ALL$/, /^[a-z]+(_[a-z]+)?$/];
|
|
27
27
|
exports.DEFAULT_REGION = "us-central1";
|
|
28
28
|
exports.ALLOWED_SSR_REGIONS = [
|
package/lib/fsAsync.js
CHANGED
|
@@ -7,8 +7,10 @@ const _ = require("lodash");
|
|
|
7
7
|
const minimatch = require("minimatch");
|
|
8
8
|
const path_1 = require("path");
|
|
9
9
|
async function readdirRecursiveHelper(options) {
|
|
10
|
-
const dirContents = (0, fs_extra_1.readdirSync)(options.path);
|
|
11
|
-
const fullPaths = dirContents
|
|
10
|
+
const dirContents = (0, fs_extra_1.readdirSync)(options.path, { withFileTypes: true });
|
|
11
|
+
const fullPaths = dirContents
|
|
12
|
+
.filter((n) => !options.ignoreSymlinks || !n.isSymbolicLink())
|
|
13
|
+
.map((n) => (0, path_1.join)(options.path, n.name));
|
|
12
14
|
const filteredPaths = fullPaths.filter((p) => !options.filter(p));
|
|
13
15
|
const filePromises = [];
|
|
14
16
|
for (const p of filteredPaths) {
|
|
@@ -20,7 +22,12 @@ async function readdirRecursiveHelper(options) {
|
|
|
20
22
|
continue;
|
|
21
23
|
}
|
|
22
24
|
if (options.maxDepth > 1) {
|
|
23
|
-
filePromises.push(readdirRecursiveHelper({
|
|
25
|
+
filePromises.push(readdirRecursiveHelper({
|
|
26
|
+
path: p,
|
|
27
|
+
filter: options.filter,
|
|
28
|
+
maxDepth: options.maxDepth - 1,
|
|
29
|
+
ignoreSymlinks: options.ignoreSymlinks,
|
|
30
|
+
}));
|
|
24
31
|
}
|
|
25
32
|
}
|
|
26
33
|
const files = await Promise.all(filePromises);
|
|
@@ -49,6 +56,7 @@ async function readdirRecursive(options) {
|
|
|
49
56
|
path: options.path,
|
|
50
57
|
filter: filter,
|
|
51
58
|
maxDepth,
|
|
59
|
+
ignoreSymlinks: !!options.ignoreSymlinks,
|
|
52
60
|
});
|
|
53
61
|
}
|
|
54
62
|
exports.readdirRecursive = readdirRecursive;
|
package/lib/functionsConfig.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.parseUnsetArgs = exports.parseSetArgs = exports.materializeAll = exports.materializeConfig = exports.setVariablesRecursive = exports.getFirebaseConfig = exports.getAppEngineLocation = exports.idsToVarName = exports.varNameToIds = exports.ensureApi = exports.RESERVED_NAMESPACES = void 0;
|
|
3
|
+
exports.parseUnsetArgs = exports.parseSetArgs = exports.materializeAll = exports.materializeConfig = exports.setVariablesRecursive = exports.getFirebaseConfig = exports.getAppEngineLocation = exports.idsToVarName = exports.varNameToIds = exports.ensureApi = exports.ensureLegacyRuntimeConfigCommandsEnabled = exports.logFunctionsConfigDeprecationWarning = exports.getFunctionsConfigDeprecationMessage = exports.RESERVED_NAMESPACES = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const clc = require("colorette");
|
|
6
6
|
const api_1 = require("./api");
|
|
@@ -9,8 +9,46 @@ const ensureApiEnabled_1 = require("./ensureApiEnabled");
|
|
|
9
9
|
const error_1 = require("./error");
|
|
10
10
|
const projectUtils_1 = require("./projectUtils");
|
|
11
11
|
const runtimeconfig = require("./gcp/runtimeconfig");
|
|
12
|
+
const experiments = require("./experiments");
|
|
13
|
+
const utils_1 = require("./utils");
|
|
12
14
|
exports.RESERVED_NAMESPACES = ["firebase"];
|
|
13
15
|
const apiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.firebaseApiOrigin)() });
|
|
16
|
+
const LEGACY_RUNTIME_CONFIG_EXPERIMENT = "legacyRuntimeConfigCommands";
|
|
17
|
+
const FUNCTIONS_CONFIG_DEPRECATION_MESSAGE = `DEPRECATION NOTICE: Action required before March 2026
|
|
18
|
+
|
|
19
|
+
The functions.config() API and the Cloud Runtime Config service are deprecated. Deploys that rely on functions.config() will fail once Runtime Config shuts down in March 2026.
|
|
20
|
+
|
|
21
|
+
The legacy functions:config:* CLI commands are deprecated and will be removed before March 2026.
|
|
22
|
+
|
|
23
|
+
Learn how to migrate from functions.config() to the params package:
|
|
24
|
+
|
|
25
|
+
https://firebase.google.com/docs/functions/config-env#migrate-config
|
|
26
|
+
|
|
27
|
+
To convert existing functions.config() values to params, try the interactive migration command:
|
|
28
|
+
|
|
29
|
+
firebase functions:config:export
|
|
30
|
+
`;
|
|
31
|
+
const LEGACY_GUIDANCE_MESSAGE = `${FUNCTIONS_CONFIG_DEPRECATION_MESSAGE}
|
|
32
|
+
|
|
33
|
+
To run this legacy command temporarily, run the following command and try again:
|
|
34
|
+
|
|
35
|
+
firebase experiments:enable ${LEGACY_RUNTIME_CONFIG_EXPERIMENT}
|
|
36
|
+
`;
|
|
37
|
+
function getFunctionsConfigDeprecationMessage() {
|
|
38
|
+
return FUNCTIONS_CONFIG_DEPRECATION_MESSAGE;
|
|
39
|
+
}
|
|
40
|
+
exports.getFunctionsConfigDeprecationMessage = getFunctionsConfigDeprecationMessage;
|
|
41
|
+
function logFunctionsConfigDeprecationWarning() {
|
|
42
|
+
(0, utils_1.logWarningToStderr)(FUNCTIONS_CONFIG_DEPRECATION_MESSAGE);
|
|
43
|
+
}
|
|
44
|
+
exports.logFunctionsConfigDeprecationWarning = logFunctionsConfigDeprecationWarning;
|
|
45
|
+
function ensureLegacyRuntimeConfigCommandsEnabled() {
|
|
46
|
+
if (experiments.isEnabled(LEGACY_RUNTIME_CONFIG_EXPERIMENT)) {
|
|
47
|
+
return;
|
|
48
|
+
}
|
|
49
|
+
throw new error_1.FirebaseError(LEGACY_GUIDANCE_MESSAGE, { exit: 1 });
|
|
50
|
+
}
|
|
51
|
+
exports.ensureLegacyRuntimeConfigCommandsEnabled = ensureLegacyRuntimeConfigCommandsEnabled;
|
|
14
52
|
function keyToIds(key) {
|
|
15
53
|
const keyParts = key.split(".");
|
|
16
54
|
const variable = keyParts.slice(1).join("/");
|
|
@@ -51,7 +51,7 @@ function instanceConsoleLink(projectId, instanceId) {
|
|
|
51
51
|
return `https://console.cloud.google.com/sql/instances/${instanceId}/overview?project=${projectId}`;
|
|
52
52
|
}
|
|
53
53
|
exports.instanceConsoleLink = instanceConsoleLink;
|
|
54
|
-
exports.DEFAULT_DATABASE_VERSION = "
|
|
54
|
+
exports.DEFAULT_DATABASE_VERSION = "POSTGRES_17";
|
|
55
55
|
async function createInstance(args) {
|
|
56
56
|
const databaseFlags = [{ name: "cloudsql.iam_authentication", value: "on" }];
|
|
57
57
|
if (args.enableGoogleMlIntegration) {
|
package/lib/index.js
CHANGED
|
@@ -3,6 +3,7 @@ const program = require("commander");
|
|
|
3
3
|
const clc = require("colorette");
|
|
4
4
|
const leven = require("leven");
|
|
5
5
|
const logger_1 = require("./logger");
|
|
6
|
+
const command_1 = require("./command");
|
|
6
7
|
const pkg = require("../package.json");
|
|
7
8
|
program.version(pkg.version);
|
|
8
9
|
program.option("-P, --project <alias_or_project_id>", "the Firebase project to use for this command");
|
|
@@ -13,6 +14,7 @@ program.option("--non-interactive", "error out of the command instead of waiting
|
|
|
13
14
|
program.option("-i, --interactive", "force prompts to be displayed");
|
|
14
15
|
program.option("--debug", "print verbose debug output and keep a debug log file");
|
|
15
16
|
program.option("-c, --config <path>", "path to the firebase.json file to use for configuration");
|
|
17
|
+
program.allowUnknownOption();
|
|
16
18
|
const client = {
|
|
17
19
|
cli: program,
|
|
18
20
|
logger: require("./logger"),
|
|
@@ -23,6 +25,26 @@ const client = {
|
|
|
23
25
|
return client.cli.commands[i];
|
|
24
26
|
}
|
|
25
27
|
}
|
|
28
|
+
const keys = name.split(":");
|
|
29
|
+
let obj = client;
|
|
30
|
+
for (const key of keys) {
|
|
31
|
+
if (!obj || (typeof obj !== "object" && typeof obj !== "function")) {
|
|
32
|
+
return;
|
|
33
|
+
}
|
|
34
|
+
const nextKey = Object.keys(obj).find((k) => k.toLowerCase() === key.toLowerCase());
|
|
35
|
+
if (!nextKey) {
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
obj = obj[nextKey];
|
|
39
|
+
}
|
|
40
|
+
if ((0, command_1.isCommandModule)(obj)) {
|
|
41
|
+
obj.load();
|
|
42
|
+
for (let i = 0; i < client.cli.commands.length; i++) {
|
|
43
|
+
if (client.cli.commands[i]._name === name) {
|
|
44
|
+
return client.cli.commands[i];
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
}
|
|
26
48
|
return;
|
|
27
49
|
},
|
|
28
50
|
};
|
|
@@ -53,8 +75,29 @@ const RENAMED_COMMANDS = {
|
|
|
53
75
|
"prefs:token": "login:ci",
|
|
54
76
|
};
|
|
55
77
|
program.action((_, args) => {
|
|
56
|
-
(0, logger_1.useConsoleLoggers)();
|
|
57
78
|
const cmd = args[0];
|
|
79
|
+
const keys = cmd.split(":");
|
|
80
|
+
let obj = client;
|
|
81
|
+
let hit = true;
|
|
82
|
+
for (const key of keys) {
|
|
83
|
+
if (!obj || (typeof obj !== "object" && typeof obj !== "function")) {
|
|
84
|
+
hit = false;
|
|
85
|
+
break;
|
|
86
|
+
}
|
|
87
|
+
const nextKey = Object.keys(obj).find((k) => k.toLowerCase() === key.toLowerCase());
|
|
88
|
+
if (!nextKey) {
|
|
89
|
+
hit = false;
|
|
90
|
+
break;
|
|
91
|
+
}
|
|
92
|
+
obj = obj[nextKey];
|
|
93
|
+
}
|
|
94
|
+
if (hit && (0, command_1.isCommandModule)(obj)) {
|
|
95
|
+
obj.load();
|
|
96
|
+
client.cli.allowUnknownOption(false);
|
|
97
|
+
client.cli.parse(process.argv);
|
|
98
|
+
return;
|
|
99
|
+
}
|
|
100
|
+
(0, logger_1.useConsoleLoggers)();
|
|
58
101
|
logger_1.logger.error(clc.bold(clc.red("Error:")), clc.bold(cmd), "is not a Firebase command");
|
|
59
102
|
if (RENAMED_COMMANDS[cmd]) {
|
|
60
103
|
logger_1.logger.error();
|