firebase-tools 11.0.0 → 11.2.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/accountExporter.js +11 -4
- package/lib/accountImporter.js +93 -95
- package/lib/api.js +77 -218
- package/lib/apiv2.js +5 -4
- package/lib/appdistribution/client.js +23 -34
- package/lib/auth.js +72 -52
- package/lib/bin/firebase.js +42 -47
- package/lib/checkValidTargetFilters.js +36 -25
- package/lib/commands/appdistribution-distribute.js +2 -1
- package/lib/commands/appdistribution-testers-add.js +2 -1
- package/lib/commands/appdistribution-testers-remove.js +2 -1
- package/lib/commands/apps-android-sha-create.js +2 -1
- package/lib/commands/apps-android-sha-delete.js +2 -1
- package/lib/commands/apps-android-sha-list.js +2 -1
- package/lib/commands/apps-create.js +2 -1
- package/lib/commands/apps-list.js +2 -1
- package/lib/commands/apps-sdkconfig.js +2 -1
- package/lib/commands/auth-export.js +2 -1
- package/lib/commands/auth-import.js +7 -10
- package/lib/commands/crashlytics-symbols-upload.js +2 -1
- package/lib/commands/database-get.js +4 -3
- package/lib/commands/database-instances-create.js +2 -1
- package/lib/commands/database-instances-list.js +3 -3
- package/lib/commands/database-profile.js +4 -4
- package/lib/commands/database-push.js +4 -4
- package/lib/commands/database-remove.js +3 -3
- package/lib/commands/database-rules-canary.js +2 -1
- package/lib/commands/database-rules-get.js +2 -1
- package/lib/commands/database-rules-list.js +2 -1
- package/lib/commands/database-rules-release.js +2 -1
- package/lib/commands/database-rules-stage.js +2 -1
- package/lib/commands/database-set.js +3 -3
- package/lib/commands/database-settings-get.js +2 -1
- package/lib/commands/database-settings-set.js +2 -1
- package/lib/commands/database-update.js +2 -1
- package/lib/commands/deploy.js +26 -25
- package/lib/commands/emulators-exec.js +2 -1
- package/lib/commands/emulators-export.js +2 -1
- package/lib/commands/emulators-start.js +2 -1
- package/lib/commands/experimental-functions-shell.js +10 -8
- package/lib/commands/ext-configure.js +6 -1
- package/lib/commands/ext-dev-deprecate.js +2 -1
- package/lib/commands/ext-dev-emulators-exec.js +3 -2
- package/lib/commands/ext-dev-emulators-start.js +3 -2
- package/lib/commands/ext-dev-extension-delete.js +2 -1
- package/lib/commands/ext-dev-init.js +2 -1
- package/lib/commands/ext-dev-list.js +8 -8
- package/lib/commands/ext-dev-publish.js +2 -1
- package/lib/commands/ext-dev-register.js +2 -1
- package/lib/commands/ext-dev-undeprecate.js +2 -1
- package/lib/commands/ext-dev-unpublish.js +2 -1
- package/lib/commands/ext-dev-usage.js +2 -1
- package/lib/commands/ext-export.js +2 -1
- package/lib/commands/ext-info.js +14 -14
- package/lib/commands/ext-install.js +6 -1
- package/lib/commands/ext-list.js +2 -1
- package/lib/commands/ext-sources-create.js +2 -1
- package/lib/commands/ext-uninstall.js +7 -1
- package/lib/commands/ext-update.js +6 -1
- package/lib/commands/ext.js +4 -4
- package/lib/commands/firestore-delete.js +2 -1
- package/lib/commands/firestore-indexes-list.js +2 -1
- package/lib/commands/functions-config-clone.js +4 -3
- package/lib/commands/functions-config-export.js +2 -1
- package/lib/commands/functions-config-get.js +2 -1
- package/lib/commands/functions-config-set.js +2 -1
- package/lib/commands/functions-config-unset.js +2 -1
- package/lib/commands/functions-delete.js +3 -8
- package/lib/commands/functions-deletegcfartifacts.js +2 -1
- package/lib/commands/functions-list.js +2 -1
- package/lib/commands/functions-log.js +2 -1
- package/lib/commands/functions-secrets-access.js +2 -1
- package/lib/commands/functions-secrets-destroy.js +2 -1
- package/lib/commands/functions-secrets-get.js +2 -1
- package/lib/commands/functions-secrets-prune.js +2 -1
- package/lib/commands/functions-secrets-set.js +2 -1
- package/lib/commands/functions-shell.js +12 -10
- package/lib/commands/help.js +2 -1
- package/lib/commands/hosting-channel-create.js +2 -1
- package/lib/commands/hosting-channel-delete.js +2 -1
- package/lib/commands/hosting-channel-deploy.js +2 -1
- package/lib/commands/hosting-channel-list.js +2 -1
- package/lib/commands/hosting-channel-open.js +2 -1
- package/lib/commands/hosting-clone.js +2 -1
- package/lib/commands/hosting-disable.js +2 -1
- package/lib/commands/hosting-sites-create.js +2 -1
- package/lib/commands/hosting-sites-delete.js +2 -1
- package/lib/commands/hosting-sites-get.js +2 -1
- package/lib/commands/hosting-sites-list.js +2 -1
- package/lib/commands/index.js +23 -13
- package/lib/commands/init.js +47 -43
- package/lib/commands/login-add.js +2 -1
- package/lib/commands/login-ci.js +2 -1
- package/lib/commands/login-list.js +2 -1
- package/lib/commands/login-use.js +2 -1
- package/lib/commands/login.js +2 -1
- package/lib/commands/logout.js +2 -1
- package/lib/commands/open.js +7 -7
- package/lib/commands/projects-addfirebase.js +2 -1
- package/lib/commands/projects-create.js +2 -1
- package/lib/commands/projects-list.js +2 -1
- package/lib/commands/remoteconfig-get.js +2 -1
- package/lib/commands/remoteconfig-rollback.js +2 -1
- package/lib/commands/remoteconfig-versions-list.js +2 -1
- package/lib/commands/serve.js +30 -30
- package/lib/commands/setup-emulators-database.js +2 -1
- package/lib/commands/setup-emulators-firestore.js +2 -1
- package/lib/commands/setup-emulators-pubsub.js +2 -1
- package/lib/commands/setup-emulators-storage.js +2 -1
- package/lib/commands/setup-emulators-ui.js +2 -1
- package/lib/commands/target-apply.js +2 -1
- package/lib/commands/target-clear.js +2 -1
- package/lib/commands/target-remove.js +2 -1
- package/lib/commands/target.js +2 -1
- package/lib/commands/use.js +54 -53
- package/lib/config.js +7 -6
- package/lib/deploy/database/deploy.js +3 -2
- package/lib/deploy/database/index.js +8 -5
- package/lib/deploy/database/prepare.js +22 -20
- package/lib/deploy/database/release.js +12 -9
- package/lib/deploy/extensions/secrets.js +3 -3
- package/lib/deploy/firestore/prepare.js +2 -2
- package/lib/deploy/functions/build.js +33 -20
- package/lib/deploy/functions/ensure.js +1 -11
- package/lib/deploy/functions/prepare.js +3 -13
- package/lib/deploy/functions/prepareFunctionsUpload.js +2 -3
- package/lib/deploy/functions/release/fabricator.js +0 -1
- package/lib/deploy/functions/release/index.js +1 -5
- package/lib/deploy/functions/runtimes/discovery/index.js +18 -3
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +188 -54
- package/lib/deploy/functions/runtimes/golang/index.js +2 -22
- package/lib/deploy/functions/runtimes/node/index.js +3 -7
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +15 -3
- package/lib/deploy/functions/services/database.js +14 -0
- package/lib/deploy/functions/services/index.js +14 -0
- package/lib/deploy/index.js +3 -3
- package/lib/deploy/lifecycleHooks.js +27 -27
- package/lib/deploy/remoteconfig/functions.js +18 -14
- package/lib/deploy/remoteconfig/prepare.js +2 -2
- package/lib/deploy/storage/prepare.js +1 -1
- package/lib/emulator/auth/apiSpec.js +14 -46
- package/lib/emulator/auth/index.js +1 -1
- package/lib/emulator/auth/operations.js +342 -93
- package/lib/emulator/auth/server.js +2 -2
- package/lib/emulator/auth/state.js +34 -32
- package/lib/emulator/commandUtils.js +1 -1
- package/lib/emulator/constants.js +1 -1
- package/lib/emulator/controller.js +7 -6
- package/lib/emulator/databaseEmulator.js +11 -9
- package/lib/emulator/download.js +1 -1
- package/lib/emulator/events/types.js +2 -3
- package/lib/emulator/firestoreEmulator.js +12 -14
- package/lib/emulator/functionsEmulator.js +65 -77
- package/lib/emulator/functionsEmulatorRuntime.js +7 -7
- package/lib/emulator/hostingEmulator.js +1 -1
- package/lib/emulator/hub.js +1 -1
- package/lib/emulator/hubClient.js +11 -22
- package/lib/emulator/hubExport.js +26 -16
- package/lib/emulator/loggingEmulator.js +1 -1
- package/lib/emulator/pubsubEmulator.js +1 -1
- package/lib/emulator/storage/crc.js +4 -4
- package/lib/emulator/storage/index.js +1 -1
- package/lib/emulator/types.js +1 -1
- package/lib/errorOut.js +2 -2
- package/lib/extensions/askUserForConsent.js +1 -2
- package/lib/extensions/askUserForParam.js +15 -18
- package/lib/extensions/emulator/optionsHelper.js +4 -4
- package/lib/extensions/extensionsApi.js +1 -22
- package/lib/extensions/extensionsHelper.js +6 -6
- package/lib/extensions/listExtensions.js +9 -10
- package/lib/extensions/manifest.js +2 -2
- package/lib/extensions/resolveSource.js +11 -7
- package/lib/extensions/secretsUtils.js +3 -3
- package/lib/extensions/types.js +24 -0
- package/lib/extensions/updateHelper.js +1 -1
- package/lib/extensions/utils.js +1 -2
- package/lib/extensions/warnings.js +3 -3
- package/lib/firestore/checkDatabaseType.js +4 -5
- package/lib/firestore/encodeFirestoreValue.js +11 -8
- package/lib/firestore/indexes.js +17 -34
- package/lib/fsAsync.js +3 -3
- package/lib/functions/events/v2.js +7 -1
- package/lib/functionsConfig.js +17 -14
- package/lib/functionsConfigClone.js +46 -46
- package/lib/gcp/cloudfunctions.js +2 -15
- package/lib/gcp/cloudfunctionsv2.js +17 -2
- package/lib/gcp/iam.js +1 -1
- package/lib/gcp/index.js +10 -10
- package/lib/gcp/rules.js +1 -1
- package/lib/gcp/runtimeconfig.js +45 -47
- package/lib/gcp/storage.js +2 -4
- package/lib/hosting/cloudRunProxy.js +19 -15
- package/lib/hosting/proxy.js +1 -1
- package/lib/index.js +29 -28
- package/lib/init/features/database.js +11 -5
- package/lib/init/features/functions/index.js +1 -1
- package/lib/init/features/functions/javascript.js +23 -20
- package/lib/init/features/functions/npm-dependencies.js +17 -14
- package/lib/init/features/functions/typescript.js +27 -24
- package/lib/init/features/hosting/github.js +6 -5
- package/lib/init/features/hosting/index.js +2 -2
- package/lib/loadCJSON.js +9 -6
- package/lib/localFunction.js +4 -4
- package/lib/logError.js +15 -12
- package/lib/management/apps.js +47 -43
- package/lib/management/database.js +33 -31
- package/lib/management/projects.js +13 -7
- package/lib/parseBoltRules.js +15 -14
- package/lib/previews.js +1 -1
- package/lib/profileReport.js +504 -512
- package/lib/profiler.js +4 -4
- package/lib/prompt.js +1 -2
- package/lib/rc.js +1 -1
- package/lib/requireAuth.js +0 -1
- package/lib/responseToError.js +8 -5
- package/lib/rtdb.js +31 -29
- package/lib/rulesDeploy.js +2 -2
- package/lib/scopes.js +9 -9
- package/lib/serve/index.js +4 -5
- package/lib/utils.js +30 -6
- package/npm-shrinkwrap.json +877 -279
- package/package.json +19 -16
- package/standalone/package.json +1 -1
package/lib/auth.js
CHANGED
|
@@ -2,15 +2,15 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.logout = exports.getAccessToken = exports.findAccountByEmail = exports.loginGithub = exports.loginGoogle = exports.setGlobalDefaultAccount = exports.setProjectAccount = exports.loginAdditionalAccount = exports.selectAccount = exports.setRefreshToken = exports.setActiveAccount = exports.getAllAccounts = exports.getAdditionalAccounts = exports.getProjectDefaultAccount = exports.getGlobalDefaultAccount = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
|
+
const FormData = require("form-data");
|
|
5
6
|
const fs = require("fs");
|
|
6
|
-
const jwt = require("jsonwebtoken");
|
|
7
7
|
const http = require("http");
|
|
8
|
+
const jwt = require("jsonwebtoken");
|
|
8
9
|
const opn = require("open");
|
|
9
10
|
const path = require("path");
|
|
10
11
|
const portfinder = require("portfinder");
|
|
11
12
|
const url = require("url");
|
|
12
13
|
const util = require("util");
|
|
13
|
-
const api = require("./api");
|
|
14
14
|
const apiv2 = require("./apiv2");
|
|
15
15
|
const configstore_1 = require("./configstore");
|
|
16
16
|
const error_1 = require("./error");
|
|
@@ -23,6 +23,7 @@ const uuid_1 = require("uuid");
|
|
|
23
23
|
const crypto_1 = require("crypto");
|
|
24
24
|
const cli_color_1 = require("cli-color");
|
|
25
25
|
const track_1 = require("./track");
|
|
26
|
+
const api_1 = require("./api");
|
|
26
27
|
portfinder.basePort = 9005;
|
|
27
28
|
function getGlobalDefaultAccount() {
|
|
28
29
|
const user = configstore_1.configstore.get("user");
|
|
@@ -72,7 +73,6 @@ function setActiveAccount(options, account) {
|
|
|
72
73
|
}
|
|
73
74
|
exports.setActiveAccount = setActiveAccount;
|
|
74
75
|
function setRefreshToken(token) {
|
|
75
|
-
api.setRefreshToken(token);
|
|
76
76
|
apiv2.setRefreshToken(token);
|
|
77
77
|
}
|
|
78
78
|
exports.setRefreshToken = setRefreshToken;
|
|
@@ -175,10 +175,10 @@ function queryParamString(args) {
|
|
|
175
175
|
return tokens.join("&");
|
|
176
176
|
}
|
|
177
177
|
function getLoginUrl(callbackUrl, userHint) {
|
|
178
|
-
return (
|
|
178
|
+
return (api_1.authOrigin +
|
|
179
179
|
"/o/oauth2/auth?" +
|
|
180
180
|
queryParamString({
|
|
181
|
-
client_id:
|
|
181
|
+
client_id: api_1.clientId,
|
|
182
182
|
scope: SCOPES.join(" "),
|
|
183
183
|
response_type: "code",
|
|
184
184
|
state: _nonce,
|
|
@@ -187,22 +187,29 @@ function getLoginUrl(callbackUrl, userHint) {
|
|
|
187
187
|
}));
|
|
188
188
|
}
|
|
189
189
|
async function getTokensFromAuthorizationCode(code, callbackUrl, verifier) {
|
|
190
|
-
var _a, _b;
|
|
191
|
-
let res;
|
|
192
190
|
const params = {
|
|
193
191
|
code: code,
|
|
194
|
-
client_id:
|
|
195
|
-
client_secret:
|
|
192
|
+
client_id: api_1.clientId,
|
|
193
|
+
client_secret: api_1.clientSecret,
|
|
196
194
|
redirect_uri: callbackUrl,
|
|
197
195
|
grant_type: "authorization_code",
|
|
198
196
|
};
|
|
199
197
|
if (verifier) {
|
|
200
198
|
params["code_verifier"] = verifier;
|
|
201
199
|
}
|
|
200
|
+
let res;
|
|
202
201
|
try {
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
202
|
+
const client = new apiv2.Client({ urlPrefix: api_1.authOrigin, auth: false });
|
|
203
|
+
const form = new FormData();
|
|
204
|
+
for (const [k, v] of Object.entries(params)) {
|
|
205
|
+
form.append(k, v);
|
|
206
|
+
}
|
|
207
|
+
res = await client.request({
|
|
208
|
+
method: "POST",
|
|
209
|
+
path: "/o/oauth2/token",
|
|
210
|
+
body: form,
|
|
211
|
+
headers: form.getHeaders(),
|
|
212
|
+
skipLog: { body: true, queryParams: true, resBody: true },
|
|
206
213
|
});
|
|
207
214
|
}
|
|
208
215
|
catch (err) {
|
|
@@ -214,8 +221,8 @@ async function getTokensFromAuthorizationCode(code, callbackUrl, verifier) {
|
|
|
214
221
|
}
|
|
215
222
|
throw invalidCredentialError();
|
|
216
223
|
}
|
|
217
|
-
if (!
|
|
218
|
-
logger_1.logger.debug("Token Fetch Error:", res.
|
|
224
|
+
if (!res.body.access_token && !res.body.refresh_token) {
|
|
225
|
+
logger_1.logger.debug("Token Fetch Error:", res.status, res.body);
|
|
219
226
|
throw invalidCredentialError();
|
|
220
227
|
}
|
|
221
228
|
lastAccessToken = Object.assign({
|
|
@@ -225,25 +232,35 @@ async function getTokensFromAuthorizationCode(code, callbackUrl, verifier) {
|
|
|
225
232
|
}
|
|
226
233
|
const GITHUB_SCOPES = ["read:user", "repo", "public_repo"];
|
|
227
234
|
function getGithubLoginUrl(callbackUrl) {
|
|
228
|
-
return (
|
|
235
|
+
return (api_1.githubOrigin +
|
|
229
236
|
"/login/oauth/authorize?" +
|
|
230
237
|
queryParamString({
|
|
231
|
-
client_id:
|
|
238
|
+
client_id: api_1.githubClientId,
|
|
232
239
|
state: _nonce,
|
|
233
240
|
redirect_uri: callbackUrl,
|
|
234
241
|
scope: GITHUB_SCOPES.join(" "),
|
|
235
242
|
}));
|
|
236
243
|
}
|
|
237
244
|
async function getGithubTokensFromAuthorizationCode(code, callbackUrl) {
|
|
238
|
-
const
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
245
|
+
const client = new apiv2.Client({ urlPrefix: api_1.githubOrigin, auth: false });
|
|
246
|
+
const data = {
|
|
247
|
+
client_id: api_1.githubClientId,
|
|
248
|
+
client_secret: api_1.githubClientSecret,
|
|
249
|
+
code,
|
|
250
|
+
redirect_uri: callbackUrl,
|
|
251
|
+
state: _nonce,
|
|
252
|
+
};
|
|
253
|
+
const form = new FormData();
|
|
254
|
+
for (const [k, v] of Object.entries(data)) {
|
|
255
|
+
form.append(k, v);
|
|
256
|
+
}
|
|
257
|
+
const headers = form.getHeaders();
|
|
258
|
+
headers.accept = "application/json";
|
|
259
|
+
const res = await client.request({
|
|
260
|
+
method: "POST",
|
|
261
|
+
path: "/login/oauth/access_token",
|
|
262
|
+
body: form,
|
|
263
|
+
headers,
|
|
247
264
|
});
|
|
248
265
|
return res.body.access_token;
|
|
249
266
|
}
|
|
@@ -259,10 +276,10 @@ async function respondWithFile(req, res, statusCode, filename) {
|
|
|
259
276
|
function urlsafeBase64(base64string) {
|
|
260
277
|
return base64string.replace(/\+/g, "-").replace(/=+$/, "").replace(/\//g, "_");
|
|
261
278
|
}
|
|
262
|
-
async function loginRemotely(
|
|
279
|
+
async function loginRemotely() {
|
|
263
280
|
var _a;
|
|
264
281
|
const authProxyClient = new apiv2.Client({
|
|
265
|
-
urlPrefix:
|
|
282
|
+
urlPrefix: api_1.authProxyOrigin,
|
|
266
283
|
auth: false,
|
|
267
284
|
});
|
|
268
285
|
const sessionId = (0, uuid_1.v4)();
|
|
@@ -271,7 +288,7 @@ async function loginRemotely(userHint) {
|
|
|
271
288
|
const attestToken = (_a = (await authProxyClient.post("/attest", {
|
|
272
289
|
session_id: sessionId,
|
|
273
290
|
})).body) === null || _a === void 0 ? void 0 : _a.token;
|
|
274
|
-
const loginUrl = `${
|
|
291
|
+
const loginUrl = `${api_1.authProxyOrigin}/login?code_challenge=${codeChallenge}&session=${sessionId}&attest=${attestToken}`;
|
|
275
292
|
logger_1.logger.info();
|
|
276
293
|
logger_1.logger.info("To sign in to the Firebase CLI:");
|
|
277
294
|
logger_1.logger.info();
|
|
@@ -290,7 +307,7 @@ async function loginRemotely(userHint) {
|
|
|
290
307
|
message: "Enter authorization code:",
|
|
291
308
|
});
|
|
292
309
|
try {
|
|
293
|
-
const tokens = await getTokensFromAuthorizationCode(code, `${
|
|
310
|
+
const tokens = await getTokensFromAuthorizationCode(code, `${api_1.authProxyOrigin}/complete`, codeVerifier);
|
|
294
311
|
void (0, track_1.track)("login", "google_remote");
|
|
295
312
|
return {
|
|
296
313
|
user: jwt.decode(tokens.id_token),
|
|
@@ -325,7 +342,6 @@ async function loginWithLocalhostGitHub(port) {
|
|
|
325
342
|
async function loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, getTokens) {
|
|
326
343
|
return new Promise((resolve, reject) => {
|
|
327
344
|
const server = http.createServer(async (req, res) => {
|
|
328
|
-
let tokens;
|
|
329
345
|
const query = url.parse(`${req.url}`, true).query || {};
|
|
330
346
|
const queryState = query.state;
|
|
331
347
|
const queryCode = query.code;
|
|
@@ -362,16 +378,15 @@ async function loginWithLocalhost(port, callbackUrl, authUrl, successTemplate, g
|
|
|
362
378
|
}
|
|
363
379
|
async function loginGoogle(localhost, userHint) {
|
|
364
380
|
if (localhost) {
|
|
365
|
-
const port = await getPort();
|
|
366
381
|
try {
|
|
367
382
|
const port = await getPort();
|
|
368
383
|
return await loginWithLocalhostGoogle(port, userHint);
|
|
369
384
|
}
|
|
370
385
|
catch (_a) {
|
|
371
|
-
return await loginRemotely(
|
|
386
|
+
return await loginRemotely();
|
|
372
387
|
}
|
|
373
388
|
}
|
|
374
|
-
return await loginRemotely(
|
|
389
|
+
return await loginRemotely();
|
|
375
390
|
}
|
|
376
391
|
exports.loginGoogle = loginGoogle;
|
|
377
392
|
async function loginGithub() {
|
|
@@ -442,24 +457,33 @@ function logoutCurrentSession(refreshToken) {
|
|
|
442
457
|
deleteAccount(account);
|
|
443
458
|
}
|
|
444
459
|
async function refreshTokens(refreshToken, authScopes) {
|
|
445
|
-
var _a, _b
|
|
460
|
+
var _a, _b;
|
|
446
461
|
logger_1.logger.debug("> refreshing access token with scopes:", JSON.stringify(authScopes));
|
|
447
462
|
try {
|
|
448
|
-
const
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
463
|
+
const client = new apiv2.Client({ urlPrefix: api_1.googleOrigin, auth: false });
|
|
464
|
+
const data = {
|
|
465
|
+
refresh_token: refreshToken,
|
|
466
|
+
client_id: api_1.clientId,
|
|
467
|
+
client_secret: api_1.clientSecret,
|
|
468
|
+
grant_type: "refresh_token",
|
|
469
|
+
scope: (authScopes || []).join(" "),
|
|
470
|
+
};
|
|
471
|
+
const form = new FormData();
|
|
472
|
+
for (const [k, v] of Object.entries(data)) {
|
|
473
|
+
form.append(k, v);
|
|
474
|
+
}
|
|
475
|
+
const res = await client.request({
|
|
476
|
+
method: "POST",
|
|
477
|
+
path: "/oauth2/v3/token",
|
|
478
|
+
body: form,
|
|
479
|
+
headers: form.getHeaders(),
|
|
480
|
+
skipLog: { body: true, queryParams: true, resBody: true },
|
|
481
|
+
resolveOnHTTPError: true,
|
|
458
482
|
});
|
|
459
483
|
if (res.status === 401 || res.status === 400) {
|
|
460
484
|
return { access_token: refreshToken };
|
|
461
485
|
}
|
|
462
|
-
if (typeof
|
|
486
|
+
if (typeof res.body.access_token !== "string") {
|
|
463
487
|
throw invalidCredentialError();
|
|
464
488
|
}
|
|
465
489
|
lastAccessToken = Object.assign({
|
|
@@ -475,7 +499,7 @@ async function refreshTokens(refreshToken, authScopes) {
|
|
|
475
499
|
return lastAccessToken;
|
|
476
500
|
}
|
|
477
501
|
catch (err) {
|
|
478
|
-
if (((
|
|
502
|
+
if (((_b = (_a = err === null || err === void 0 ? void 0 : err.context) === null || _a === void 0 ? void 0 : _a.body) === null || _b === void 0 ? void 0 : _b.error) === "invalid_scope") {
|
|
479
503
|
throw new error_1.FirebaseError("This command requires new authorization scopes not granted to your current session. Please run " +
|
|
480
504
|
clc.bold("firebase login --reauth") +
|
|
481
505
|
"\n\n" +
|
|
@@ -498,12 +522,8 @@ async function logout(refreshToken) {
|
|
|
498
522
|
}
|
|
499
523
|
logoutCurrentSession(refreshToken);
|
|
500
524
|
try {
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
data: {
|
|
504
|
-
token: refreshToken,
|
|
505
|
-
},
|
|
506
|
-
});
|
|
525
|
+
const client = new apiv2.Client({ urlPrefix: api_1.authOrigin, auth: false });
|
|
526
|
+
await client.get("/o/oauth2/revoke", { queryParams: { token: refreshToken } });
|
|
507
527
|
}
|
|
508
528
|
catch (thrown) {
|
|
509
529
|
const err = thrown instanceof Error ? thrown : new Error(thrown);
|
package/lib/bin/firebase.js
CHANGED
|
@@ -1,42 +1,38 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
"use strict";
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
4
|
const semver = require("semver");
|
|
4
5
|
const pkg = require("../../package.json");
|
|
5
6
|
const nodeVersion = process.version;
|
|
6
7
|
if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
|
|
7
|
-
console.error(
|
|
8
|
-
pkg.version +
|
|
9
|
-
" is incompatible with Node.js " +
|
|
10
|
-
nodeVersion +
|
|
11
|
-
" Please upgrade Node.js to version " +
|
|
12
|
-
pkg.engines.node);
|
|
8
|
+
console.error(`Firebase CLI v${pkg.version} is incompatible with Node.js ${nodeVersion} Please upgrade Node.js to version ${pkg.engines.node}`);
|
|
13
9
|
process.exit(1);
|
|
14
10
|
}
|
|
15
|
-
const
|
|
11
|
+
const updateNotifierPkg = require("update-notifier");
|
|
16
12
|
const clc = require("cli-color");
|
|
17
13
|
const TerminalRenderer = require("marked-terminal");
|
|
18
|
-
const
|
|
19
|
-
marked
|
|
14
|
+
const updateNotifier = updateNotifierPkg({ pkg: pkg });
|
|
15
|
+
const marked_1 = require("marked");
|
|
16
|
+
marked_1.marked.setOptions({
|
|
20
17
|
renderer: new TerminalRenderer(),
|
|
21
18
|
});
|
|
22
19
|
const updateMessage = `Update available ${clc.xterm(240)("{currentVersion}")} → ${clc.green("{latestVersion}")}\n` +
|
|
23
20
|
`To update to the latest version using npm, run\n${clc.cyan("npm install -g firebase-tools")}\n` +
|
|
24
|
-
`For other CLI management options, visit the ${marked("[CLI documentation](https://firebase.google.com/docs/cli#update-cli)")}`;
|
|
21
|
+
`For other CLI management options, visit the ${(0, marked_1.marked)("[CLI documentation](https://firebase.google.com/docs/cli#update-cli)")}`;
|
|
25
22
|
updateNotifier.notify({ defer: true, isGlobal: true, message: updateMessage });
|
|
23
|
+
const node_path_1 = require("node:path");
|
|
24
|
+
const triple_beam_1 = require("triple-beam");
|
|
25
|
+
const cli_color_1 = require("cli-color");
|
|
26
|
+
const fs = require("node:fs");
|
|
27
|
+
const configstore_1 = require("../configstore");
|
|
28
|
+
const errorOut_1 = require("../errorOut");
|
|
29
|
+
const handlePreviewToggles_1 = require("../handlePreviewToggles");
|
|
30
|
+
const logger_1 = require("../logger");
|
|
26
31
|
const client = require("..");
|
|
27
|
-
const errorOut = require("../errorOut").errorOut;
|
|
28
|
-
const winston = require("winston");
|
|
29
|
-
const { SPLAT } = require("triple-beam");
|
|
30
|
-
const { logger } = require("../logger");
|
|
31
|
-
const fs = require("fs");
|
|
32
32
|
const fsutils = require("../fsutils");
|
|
33
|
-
const path = require("path");
|
|
34
|
-
const ansiStrip = require("cli-color/strip");
|
|
35
|
-
const { configstore } = require("../configstore");
|
|
36
|
-
const _ = require("lodash");
|
|
37
|
-
let args = process.argv.slice(2);
|
|
38
|
-
const { handlePreviewToggles } = require("../handlePreviewToggles");
|
|
39
33
|
const utils = require("../utils");
|
|
34
|
+
const winston = require("winston");
|
|
35
|
+
let args = process.argv.slice(2);
|
|
40
36
|
let cmd;
|
|
41
37
|
function findAvailableLogFile() {
|
|
42
38
|
const candidates = ["firebase-debug.log"];
|
|
@@ -44,7 +40,7 @@ function findAvailableLogFile() {
|
|
|
44
40
|
candidates.push(`firebase-debug.${i}.log`);
|
|
45
41
|
}
|
|
46
42
|
for (const c of candidates) {
|
|
47
|
-
const logFilename =
|
|
43
|
+
const logFilename = (0, node_path_1.join)(process.cwd(), c);
|
|
48
44
|
try {
|
|
49
45
|
const fd = fs.openSync(logFilename, "r+");
|
|
50
46
|
fs.closeSync(fd);
|
|
@@ -59,43 +55,43 @@ function findAvailableLogFile() {
|
|
|
59
55
|
throw new Error("Unable to obtain permissions for firebase-debug.log");
|
|
60
56
|
}
|
|
61
57
|
const logFilename = findAvailableLogFile();
|
|
62
|
-
if (!process.env.DEBUG &&
|
|
58
|
+
if (!process.env.DEBUG && args.includes("--debug")) {
|
|
63
59
|
process.env.DEBUG = "true";
|
|
64
60
|
}
|
|
65
61
|
process.env.IS_FIREBASE_CLI = "true";
|
|
66
|
-
logger.add(new winston.transports.File({
|
|
62
|
+
logger_1.logger.add(new winston.transports.File({
|
|
67
63
|
level: "debug",
|
|
68
64
|
filename: logFilename,
|
|
69
65
|
format: winston.format.printf((info) => {
|
|
70
|
-
const segments = [info.message, ...(info[SPLAT] || [])].map(utils.tryStringify);
|
|
71
|
-
return `[${info.level}] ${
|
|
66
|
+
const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(utils.tryStringify);
|
|
67
|
+
return `[${info.level}] ${(0, cli_color_1.strip)(segments.join(" "))}`;
|
|
72
68
|
}),
|
|
73
69
|
}));
|
|
74
|
-
logger.debug(
|
|
75
|
-
logger.debug("Command: ", process.argv.join(" "));
|
|
76
|
-
logger.debug("CLI Version: ", pkg.version);
|
|
77
|
-
logger.debug("Platform: ", process.platform);
|
|
78
|
-
logger.debug("Node Version: ", process.version);
|
|
79
|
-
logger.debug("Time: ", new Date().toString());
|
|
70
|
+
logger_1.logger.debug("-".repeat(70));
|
|
71
|
+
logger_1.logger.debug("Command: ", process.argv.join(" "));
|
|
72
|
+
logger_1.logger.debug("CLI Version: ", pkg.version);
|
|
73
|
+
logger_1.logger.debug("Platform: ", process.platform);
|
|
74
|
+
logger_1.logger.debug("Node Version: ", process.version);
|
|
75
|
+
logger_1.logger.debug("Time: ", new Date().toString());
|
|
80
76
|
if (utils.envOverrides.length) {
|
|
81
|
-
logger.debug("Env Overrides:", utils.envOverrides.join(", "));
|
|
77
|
+
logger_1.logger.debug("Env Overrides:", utils.envOverrides.join(", "));
|
|
82
78
|
}
|
|
83
|
-
logger.debug(
|
|
84
|
-
logger.debug();
|
|
85
|
-
require("../fetchMOTD")
|
|
86
|
-
|
|
79
|
+
logger_1.logger.debug("-".repeat(70));
|
|
80
|
+
logger_1.logger.debug();
|
|
81
|
+
const fetchMOTD_1 = require("../fetchMOTD");
|
|
82
|
+
(0, fetchMOTD_1.fetchMOTD)();
|
|
83
|
+
process.on("exit", (code) => {
|
|
87
84
|
code = process.exitCode || code;
|
|
88
85
|
if (!process.env.DEBUG && code < 2 && fsutils.fileExistsSync(logFilename)) {
|
|
89
86
|
fs.unlinkSync(logFilename);
|
|
90
87
|
}
|
|
91
88
|
if (code > 0 && process.stdout.isTTY) {
|
|
92
|
-
const lastError = configstore.get("lastError") || 0;
|
|
89
|
+
const lastError = configstore_1.configstore.get("lastError") || 0;
|
|
93
90
|
const timestamp = Date.now();
|
|
94
91
|
if (lastError > timestamp - 120000) {
|
|
95
92
|
let help;
|
|
96
93
|
if (code === 1 && cmd) {
|
|
97
|
-
|
|
98
|
-
help = "Having trouble? Try " + clc.bold("firebase " + commandName + " --help");
|
|
94
|
+
help = "Having trouble? Try " + clc.bold("firebase [command] --help");
|
|
99
95
|
}
|
|
100
96
|
else {
|
|
101
97
|
help = "Having trouble? Try again or contact support with contents of firebase-debug.log";
|
|
@@ -105,19 +101,18 @@ process.on("exit", function (code) {
|
|
|
105
101
|
console.log(help);
|
|
106
102
|
}
|
|
107
103
|
}
|
|
108
|
-
configstore.set("lastError", timestamp);
|
|
104
|
+
configstore_1.configstore.set("lastError", timestamp);
|
|
109
105
|
}
|
|
110
106
|
else {
|
|
111
|
-
configstore.delete("lastError");
|
|
107
|
+
configstore_1.configstore.delete("lastError");
|
|
112
108
|
}
|
|
113
109
|
});
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
errorOut(err);
|
|
110
|
+
process.on("uncaughtException", (err) => {
|
|
111
|
+
(0, errorOut_1.errorOut)(err);
|
|
117
112
|
});
|
|
118
|
-
if (!handlePreviewToggles(args)) {
|
|
113
|
+
if (!(0, handlePreviewToggles_1.handlePreviewToggles)(args)) {
|
|
119
114
|
cmd = client.cli.parse(process.argv);
|
|
120
|
-
args = args.filter(
|
|
115
|
+
args = args.filter((arg) => {
|
|
121
116
|
return arg.indexOf("-") < 0;
|
|
122
117
|
});
|
|
123
118
|
if (!args.length) {
|
|
@@ -1,34 +1,45 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
return
|
|
18
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.checkValidTargetFilters = void 0;
|
|
4
|
+
const deploy_1 = require("./commands/deploy");
|
|
5
|
+
const error_1 = require("./error");
|
|
6
|
+
function targetsForTypes(only, ...types) {
|
|
7
|
+
return only.filter((t) => {
|
|
8
|
+
if (t.includes(":")) {
|
|
9
|
+
return types.includes(t.split(":")[0]);
|
|
10
|
+
}
|
|
11
|
+
else {
|
|
12
|
+
return types.includes(t);
|
|
13
|
+
}
|
|
14
|
+
});
|
|
15
|
+
}
|
|
16
|
+
function targetsHaveFilters(...targets) {
|
|
17
|
+
return targets.some((t) => t.includes(":"));
|
|
18
|
+
}
|
|
19
|
+
function targetsHaveNoFilters(...targets) {
|
|
20
|
+
return targets.some((t) => !t.includes(":"));
|
|
21
|
+
}
|
|
22
|
+
async function checkValidTargetFilters(options) {
|
|
23
|
+
const only = (options.only || "").split(",");
|
|
24
|
+
return new Promise((resolve, reject) => {
|
|
25
|
+
if (!only.length) {
|
|
19
26
|
return resolve();
|
|
20
27
|
}
|
|
21
28
|
if (options.except) {
|
|
22
|
-
return reject(new FirebaseError("Cannot specify both --only and --except"
|
|
23
|
-
exit: 1,
|
|
24
|
-
}));
|
|
29
|
+
return reject(new error_1.FirebaseError("Cannot specify both --only and --except"));
|
|
25
30
|
}
|
|
26
|
-
|
|
27
|
-
|
|
31
|
+
const nonFilteredTypes = deploy_1.VALID_DEPLOY_TARGETS.filter((t) => !["hosting", "functions"].includes(t));
|
|
32
|
+
const targetsForNonFilteredTypes = targetsForTypes(only, ...nonFilteredTypes);
|
|
33
|
+
if (targetsForNonFilteredTypes.length && targetsHaveFilters(...targetsForNonFilteredTypes)) {
|
|
34
|
+
return reject(new error_1.FirebaseError("Filters specified with colons (e.g. --only functions:func1,functions:func2) are only supported for functions and hosting"));
|
|
28
35
|
}
|
|
29
|
-
|
|
30
|
-
|
|
36
|
+
const targetsForFunctions = targetsForTypes(only, "functions");
|
|
37
|
+
if (targetsForFunctions.length &&
|
|
38
|
+
targetsHaveFilters(...targetsForFunctions) &&
|
|
39
|
+
targetsHaveNoFilters(...targetsForFunctions)) {
|
|
40
|
+
return reject(new error_1.FirebaseError('Cannot specify "--only functions" and "--only functions:<filter>" at the same time'));
|
|
31
41
|
}
|
|
32
42
|
return resolve();
|
|
33
43
|
});
|
|
34
|
-
}
|
|
44
|
+
}
|
|
45
|
+
exports.checkValidTargetFilters = checkValidTargetFilters;
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const fs = require("fs-extra");
|
|
4
5
|
const command_1 = require("../command");
|
|
5
6
|
const utils = require("../utils");
|
|
@@ -18,7 +19,7 @@ function getReleaseNotes(releaseNotes, releaseNotesFile) {
|
|
|
18
19
|
}
|
|
19
20
|
return "";
|
|
20
21
|
}
|
|
21
|
-
|
|
22
|
+
exports.command = new command_1.Command("appdistribution:distribute <release-binary-file>")
|
|
22
23
|
.description("upload a release binary")
|
|
23
24
|
.option("--app <app_id>", "the app id of your Firebase app")
|
|
24
25
|
.option("--release-notes <string>", "release notes to include")
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const command_1 = require("../command");
|
|
4
5
|
const utils = require("../utils");
|
|
5
6
|
const requireAuth_1 = require("../requireAuth");
|
|
6
7
|
const client_1 = require("../appdistribution/client");
|
|
7
8
|
const options_parser_util_1 = require("../appdistribution/options-parser-util");
|
|
8
|
-
|
|
9
|
+
exports.command = new command_1.Command("appdistribution:testers:add [emails...]")
|
|
9
10
|
.description("add testers to project")
|
|
10
11
|
.option("--file <file>", "a path to a file containing a list of tester emails to be added")
|
|
11
12
|
.before(requireAuth_1.requireAuth)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const command_1 = require("../command");
|
|
4
5
|
const utils = require("../utils");
|
|
5
6
|
const requireAuth_1 = require("../requireAuth");
|
|
@@ -7,7 +8,7 @@ const error_1 = require("../error");
|
|
|
7
8
|
const client_1 = require("../appdistribution/client");
|
|
8
9
|
const options_parser_util_1 = require("../appdistribution/options-parser-util");
|
|
9
10
|
const logger_1 = require("../logger");
|
|
10
|
-
|
|
11
|
+
exports.command = new command_1.Command("appdistribution:testers:remove [emails...]")
|
|
11
12
|
.description("remove testers from a project")
|
|
12
13
|
.option("--file <file>", "a path to a file containing a list of tester emails to be removed")
|
|
13
14
|
.before(requireAuth_1.requireAuth)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const clc = require("cli-color");
|
|
4
5
|
const command_1 = require("../command");
|
|
5
6
|
const projectUtils_1 = require("../projectUtils");
|
|
@@ -15,7 +16,7 @@ function getCertHashType(shaHash) {
|
|
|
15
16
|
return apps_1.ShaCertificateType.SHA_256.toString();
|
|
16
17
|
return apps_1.ShaCertificateType.SHA_CERTIFICATE_TYPE_UNSPECIFIED.toString();
|
|
17
18
|
}
|
|
18
|
-
|
|
19
|
+
exports.command = new command_1.Command("apps:android:sha:create <appId> <shaHash>")
|
|
19
20
|
.description("add a SHA certificate hash for a given app id.")
|
|
20
21
|
.before(requireAuth_1.requireAuth)
|
|
21
22
|
.action(async (appId = "", shaHash = "", options) => {
|
|
@@ -1,12 +1,13 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const clc = require("cli-color");
|
|
4
5
|
const command_1 = require("../command");
|
|
5
6
|
const projectUtils_1 = require("../projectUtils");
|
|
6
7
|
const apps_1 = require("../management/apps");
|
|
7
8
|
const requireAuth_1 = require("../requireAuth");
|
|
8
9
|
const utils_1 = require("../utils");
|
|
9
|
-
|
|
10
|
+
exports.command = new command_1.Command("apps:android:sha:delete <appId> <shaId>")
|
|
10
11
|
.description("delete a SHA certificate hash for a given app id.")
|
|
11
12
|
.before(requireAuth_1.requireAuth)
|
|
12
13
|
.action(async (appId = "", shaId = "", options) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const Table = require("cli-table");
|
|
4
5
|
const command_1 = require("../command");
|
|
5
6
|
const projectUtils_1 = require("../projectUtils");
|
|
@@ -29,7 +30,7 @@ function logCertificatesCount(count = 0) {
|
|
|
29
30
|
logger_1.logger.info("");
|
|
30
31
|
logger_1.logger.info(`${count} SHA hash(es) total.`);
|
|
31
32
|
}
|
|
32
|
-
|
|
33
|
+
exports.command = new command_1.Command("apps:android:sha:list <appId>")
|
|
33
34
|
.description("list the SHA certificate hashes for a given app id. ")
|
|
34
35
|
.before(requireAuth_1.requireAuth)
|
|
35
36
|
.action(async (appId = "", options) => {
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const clc = require("cli-color");
|
|
4
5
|
const ora = require("ora");
|
|
5
6
|
const command_1 = require("../command");
|
|
@@ -121,7 +122,7 @@ async function initiateWebAppCreation(options) {
|
|
|
121
122
|
throw err;
|
|
122
123
|
}
|
|
123
124
|
}
|
|
124
|
-
|
|
125
|
+
exports.command = new command_1.Command("apps:create [platform] [displayName]")
|
|
125
126
|
.description("create a new Firebase app. [platform] can be IOS, ANDROID or WEB (case insensitive).")
|
|
126
127
|
.option("-a, --package-name <packageName>", "required package name for the Android app")
|
|
127
128
|
.option("-b, --bundle-id <bundleId>", "required bundle id for the iOS app")
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const clc = require("cli-color");
|
|
4
5
|
const ora = require("ora");
|
|
5
6
|
const Table = require("cli-table");
|
|
@@ -28,7 +29,7 @@ function logAppCount(count = 0) {
|
|
|
28
29
|
logger_1.logger.info("");
|
|
29
30
|
logger_1.logger.info(`${count} app(s) total.`);
|
|
30
31
|
}
|
|
31
|
-
|
|
32
|
+
exports.command = new command_1.Command("apps:list [platform]")
|
|
32
33
|
.description("list the registered apps of a Firebase project. " +
|
|
33
34
|
"Optionally filter apps by [platform]: IOS, ANDROID or WEB (case insensitive)")
|
|
34
35
|
.before(requireAuth_1.requireAuth)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
3
4
|
const ora = require("ora");
|
|
4
5
|
const fs = require("fs-extra");
|
|
5
6
|
const command_1 = require("../command");
|
|
@@ -32,7 +33,7 @@ async function selectAppInteractively(apps, appPlatform) {
|
|
|
32
33
|
choices,
|
|
33
34
|
});
|
|
34
35
|
}
|
|
35
|
-
|
|
36
|
+
exports.command = new command_1.Command("apps:sdkconfig [platform] [appId]")
|
|
36
37
|
.description("print the Google Services config of a Firebase app. " +
|
|
37
38
|
"[platform] can be IOS, ANDROID or WEB (case insensitive)")
|
|
38
39
|
.option("-o, --out [file]", "(optional) write config output to a file")
|