firebase-tools 14.3.1 → 14.5.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/api.js +10 -2
- package/lib/apphosting/backend.js +74 -18
- package/lib/apphosting/rollout.js +2 -2
- package/lib/apphosting/secrets/dialogs.js +4 -4
- package/lib/apphosting/secrets/index.js +2 -2
- package/lib/auth.js +22 -2
- package/lib/bin/cli.js +1 -33
- package/lib/bin/mcp.js +13 -2
- package/lib/checkValidTargetFilters.js +1 -0
- package/lib/command.js +3 -2
- package/lib/commands/apphosting-secrets-grantaccess.js +1 -1
- package/lib/commands/deploy.js +1 -0
- package/lib/commands/init.js +1 -4
- package/lib/commands/login-use.js +2 -11
- package/lib/commands/use.js +9 -8
- package/lib/config.js +43 -24
- package/lib/crashlytics/listTopIssues.js +44 -0
- package/lib/dataconnect/cloudAICompanionClient.js +72 -0
- package/lib/dataconnect/cloudAICompanionTypes.js +2 -0
- package/lib/dataconnect/fileUtils.js +11 -4
- package/lib/dataconnect/schemaMigration.js +6 -7
- package/lib/deploy/apphosting/args.js +2 -0
- package/lib/deploy/apphosting/deploy.js +77 -0
- package/lib/deploy/apphosting/index.js +9 -0
- package/lib/deploy/apphosting/prepare.js +147 -0
- package/lib/deploy/apphosting/release.js +56 -0
- package/lib/deploy/apphosting/util.js +65 -0
- package/lib/deploy/extensions/v2FunctionHelper.js +2 -1
- package/lib/deploy/firestore/deploy.js +47 -4
- package/lib/deploy/functions/checkIam.js +3 -3
- package/lib/deploy/functions/ensure.js +2 -1
- package/lib/deploy/functions/prepare.js +23 -16
- package/lib/deploy/functions/release/fabricator.js +4 -4
- package/lib/deploy/functions/release/index.js +1 -1
- package/lib/deploy/functions/runtimes/python/index.js +3 -0
- package/lib/deploy/functions/runtimes/supported/types.js +17 -11
- package/lib/deploy/index.js +2 -0
- package/lib/emulator/apphosting/index.js +1 -0
- package/lib/emulator/apphosting/serve.js +77 -3
- package/lib/emulator/auth/widget_ui.js +2 -1
- package/lib/emulator/controller.js +18 -4
- package/lib/emulator/dataconnectEmulator.js +9 -2
- package/lib/emulator/downloadableEmulatorInfo.json +81 -0
- package/lib/emulator/downloadableEmulators.js +28 -108
- package/lib/experiments.js +1 -1
- package/lib/extensions/manifest.js +2 -5
- package/lib/frameworks/angular/index.js +1 -1
- package/lib/frameworks/angular/utils.js +17 -6
- package/lib/fsAsync.js +9 -2
- package/lib/gcp/apphosting.js +13 -1
- package/lib/gcp/auth.js +32 -2
- package/lib/gcp/cloudbilling.js +12 -1
- package/lib/gcp/cloudfunctions.js +1 -2
- package/lib/gcp/cloudfunctionsv2.js +1 -2
- package/lib/gcp/cloudscheduler.js +2 -2
- package/lib/gcp/computeEngine.js +19 -2
- package/lib/gcp/devConnect.js +6 -1
- package/lib/gcp/firestore.js +24 -1
- package/lib/gcp/iam.js +1 -5
- package/lib/gcp/run.js +19 -1
- package/lib/gcp/storage.js +25 -1
- package/lib/index.js +1 -2
- package/lib/init/features/apphosting.js +85 -6
- package/lib/init/features/database.js +63 -52
- package/lib/init/features/dataconnect/index.js +78 -79
- package/lib/init/features/dataconnect/sdk.js +19 -6
- package/lib/init/features/emulators.js +12 -7
- package/lib/init/features/firestore/index.js +80 -39
- package/lib/init/features/firestore/indexes.js +29 -31
- package/lib/init/features/firestore/rules.js +35 -48
- package/lib/init/features/functions/index.js +2 -0
- package/lib/init/features/functions/javascript.js +3 -2
- package/lib/init/features/functions/typescript.js +3 -2
- package/lib/init/features/genkit/index.js +18 -10
- package/lib/init/features/hosting/github.js +3 -2
- package/lib/init/features/hosting/index.js +9 -8
- package/lib/init/features/index.js +10 -5
- package/lib/init/features/remoteconfig.js +3 -2
- package/lib/init/features/storage.js +31 -8
- package/lib/init/index.js +80 -24
- package/lib/logger.js +71 -7
- package/lib/management/projects.js +24 -1
- package/lib/mcp/errors.js +1 -1
- package/lib/mcp/index.js +142 -46
- package/lib/mcp/tool.js +2 -1
- package/lib/mcp/tools/apphosting/fetch_logs.js +69 -0
- package/lib/mcp/tools/apphosting/index.js +6 -0
- package/lib/mcp/tools/apphosting/list_backends.js +51 -0
- package/lib/mcp/tools/auth/get_user.js +16 -7
- package/lib/mcp/tools/auth/index.js +8 -1
- package/lib/mcp/tools/auth/list_users.js +47 -0
- package/lib/mcp/tools/auth/set_claims.js +20 -11
- package/lib/mcp/tools/auth/set_sms_region_policy.js +1 -1
- package/lib/mcp/tools/core/consult_assistant.js +1 -1
- package/lib/mcp/tools/core/create_android_sha.js +40 -0
- package/lib/mcp/tools/core/create_app.js +90 -0
- package/lib/mcp/tools/core/create_project.js +68 -0
- package/lib/mcp/tools/core/get_admin_sdk_config.js +26 -0
- package/lib/mcp/tools/core/get_environment.js +51 -0
- package/lib/mcp/tools/core/get_sdk_config.js +6 -3
- package/lib/mcp/tools/core/index.js +21 -2
- package/lib/mcp/tools/core/init.js +153 -0
- package/lib/mcp/tools/core/list_apps.js +10 -5
- package/lib/mcp/tools/core/list_projects.js +45 -0
- package/lib/mcp/tools/core/update_environment.js +55 -0
- package/lib/mcp/tools/crashlytics/index.js +5 -0
- package/lib/mcp/tools/crashlytics/list_top_issues.js +34 -0
- package/lib/mcp/tools/dataconnect/converter.js +13 -1
- package/lib/mcp/tools/dataconnect/emulator.js +32 -0
- package/lib/mcp/tools/dataconnect/execute_graphql.js +24 -8
- package/lib/mcp/tools/dataconnect/execute_graphql_read.js +24 -8
- package/lib/mcp/tools/dataconnect/execute_mutation.js +27 -15
- package/lib/mcp/tools/dataconnect/execute_query.js +26 -14
- package/lib/mcp/tools/dataconnect/generate_operation.js +7 -7
- package/lib/mcp/tools/dataconnect/generate_schema.js +1 -1
- package/lib/mcp/tools/dataconnect/get_connector.js +7 -7
- package/lib/mcp/tools/dataconnect/get_schema.js +5 -5
- package/lib/mcp/tools/dataconnect/index.js +1 -5
- package/lib/mcp/tools/dataconnect/list_services.js +1 -1
- package/lib/mcp/tools/firestore/converter.js +47 -1
- package/lib/mcp/tools/firestore/delete_document.js +37 -0
- package/lib/mcp/tools/firestore/index.js +12 -2
- package/lib/mcp/tools/firestore/list_collections.js +1 -6
- package/lib/mcp/tools/firestore/query_collection.js +122 -0
- package/lib/mcp/tools/index.js +37 -16
- package/lib/mcp/tools/messaging/index.js +5 -0
- package/lib/mcp/tools/messaging/send_message.js +42 -0
- package/lib/mcp/tools/remoteconfig/get_template.js +27 -0
- package/lib/mcp/tools/remoteconfig/index.js +7 -0
- package/lib/mcp/tools/remoteconfig/publish_template.js +34 -0
- package/lib/mcp/tools/remoteconfig/rollback_template.js +29 -0
- package/lib/mcp/tools/rules/get_rules.js +29 -0
- package/lib/mcp/tools/rules/validate_rules.js +98 -0
- package/lib/mcp/tools/storage/get_download_url.js +8 -5
- package/lib/mcp/tools/storage/index.js +7 -2
- package/lib/mcp/types.js +10 -1
- package/lib/mcp/util.js +165 -2
- package/lib/mcp/util.test.js +468 -0
- package/lib/messaging/interfaces.js +2 -0
- package/lib/messaging/sendMessage.js +48 -0
- package/lib/prompt.js +1 -1
- package/lib/remoteconfig/publish.js +39 -0
- package/lib/requireAuth.js +2 -2
- package/lib/track.js +1 -1
- package/lib/utils.js +2 -37
- package/package.json +2 -1
- package/schema/connector-yaml.json +12 -0
- package/schema/extension-yaml.json +17 -4
- package/schema/firebase-config.json +65 -10
- package/standalone/package.json +1 -1
- package/templates/dataconnect-prompts/operation-generation-cursor-windsurf-rule.txt +273 -0
- package/templates/dataconnect-prompts/schema-generation-cursor-windsurf-rule.txt +653 -0
- package/templates/genkit/firebase.1.0.0.template +5 -0
- package/templates/init/firestore/firestore.rules +2 -0
- package/templates/init/functions/javascript/package.lint.json +1 -1
- package/templates/init/functions/javascript/package.nolint.json +1 -1
- package/templates/init/functions/typescript/package.lint.json +2 -2
- package/templates/init/functions/typescript/package.nolint.json +3 -3
- package/lib/mcp/tools/directory/get_project_directory.js +0 -20
- package/lib/mcp/tools/directory/index.js +0 -6
- package/lib/mcp/tools/directory/set_project_directory.js +0 -33
- package/lib/mcp/tools/firestore/get_rules.js +0 -26
package/lib/api.js
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
4
|
-
exports.setScopes = exports.getScopes = exports.vertexAIOrigin = exports.cloudSQLAdminOrigin = exports.dataConnectLocalConnString = exports.dataconnectP4SADomain = exports.dataconnectOrigin = exports.githubClientSecret = exports.githubClientId = exports.computeOrigin = exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = void 0;
|
|
3
|
+
exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.crashlyticsApiOrigin = exports.messagingApiOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsTOSOrigin = exports.extensionsPublisherOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.cloudCompanionOrigin = exports.cloudbuildOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.dynamicLinksKey = exports.dynamicLinksOrigin = exports.consoleOrigin = exports.authManagementOrigin = exports.authOrigin = exports.apphostingGitHubAppInstallationURL = exports.apphostingP4SADomain = exports.apphostingOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.developerConnectP4SADomain = exports.developerConnectOrigin = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
|
|
4
|
+
exports.setScopes = exports.getScopes = exports.cloudAiCompanionOrigin = exports.vertexAIOrigin = exports.cloudSQLAdminOrigin = exports.dataConnectLocalConnString = exports.dataconnectP4SADomain = exports.dataconnectOrigin = exports.githubClientSecret = exports.githubClientId = exports.computeOrigin = exports.secretManagerOrigin = exports.githubApiOrigin = exports.githubOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = exports.hostingApiOrigin = exports.firebaseStorageOrigin = exports.storageOrigin = void 0;
|
|
5
5
|
const constants_1 = require("./emulator/constants");
|
|
6
6
|
const logger_1 = require("./logger");
|
|
7
7
|
const scopes = require("./scopes");
|
|
@@ -37,6 +37,8 @@ const apphostingGitHubAppInstallationURL = () => utils.envOverride("FIREBASE_APP
|
|
|
37
37
|
exports.apphostingGitHubAppInstallationURL = apphostingGitHubAppInstallationURL;
|
|
38
38
|
const authOrigin = () => utils.envOverride("FIREBASE_AUTH_URL", "https://accounts.google.com");
|
|
39
39
|
exports.authOrigin = authOrigin;
|
|
40
|
+
const authManagementOrigin = () => utils.envOverride("FIREBASE_AUTH_MANAGEMENT_URL", "https://identitytoolkit.googleapis.com");
|
|
41
|
+
exports.authManagementOrigin = authManagementOrigin;
|
|
40
42
|
const consoleOrigin = () => utils.envOverride("FIREBASE_CONSOLE_URL", "https://console.firebase.google.com");
|
|
41
43
|
exports.consoleOrigin = consoleOrigin;
|
|
42
44
|
const dynamicLinksOrigin = () => utils.envOverride("FIREBASE_DYNAMIC_LINKS_URL", "https://firebasedynamiclinks.googleapis.com");
|
|
@@ -100,6 +102,10 @@ const rtdbMetadataOrigin = () => utils.envOverride("FIREBASE_RTDB_METADATA_URL",
|
|
|
100
102
|
exports.rtdbMetadataOrigin = rtdbMetadataOrigin;
|
|
101
103
|
const remoteConfigApiOrigin = () => utils.envOverride("FIREBASE_REMOTE_CONFIG_URL", "https://firebaseremoteconfig.googleapis.com");
|
|
102
104
|
exports.remoteConfigApiOrigin = remoteConfigApiOrigin;
|
|
105
|
+
const messagingApiOrigin = () => utils.envOverride("FIREBASE_MESSAGING_CONFIG_URL", "https://fcm.googleapis.com");
|
|
106
|
+
exports.messagingApiOrigin = messagingApiOrigin;
|
|
107
|
+
const crashlyticsApiOrigin = () => utils.envOverride("FIREBASE_CRASHLYTICS_URL", "https://firebasecrashlytics.googleapis.com");
|
|
108
|
+
exports.crashlyticsApiOrigin = crashlyticsApiOrigin;
|
|
103
109
|
const resourceManagerOrigin = () => utils.envOverride("FIREBASE_RESOURCEMANAGER_URL", "https://cloudresourcemanager.googleapis.com");
|
|
104
110
|
exports.resourceManagerOrigin = resourceManagerOrigin;
|
|
105
111
|
const rulesOrigin = () => utils.envOverride("FIREBASE_RULES_URL", "https://firebaserules.googleapis.com");
|
|
@@ -138,6 +144,8 @@ const cloudSQLAdminOrigin = () => utils.envOverride("CLOUD_SQL_URL", "https://sq
|
|
|
138
144
|
exports.cloudSQLAdminOrigin = cloudSQLAdminOrigin;
|
|
139
145
|
const vertexAIOrigin = () => utils.envOverride("VERTEX_AI_URL", "https://aiplatform.googleapis.com");
|
|
140
146
|
exports.vertexAIOrigin = vertexAIOrigin;
|
|
147
|
+
const cloudAiCompanionOrigin = () => utils.envOverride("CLOUD_AI_COMPANION_URL", "https://cloudaicompanion.googleapis.com");
|
|
148
|
+
exports.cloudAiCompanionOrigin = cloudAiCompanionOrigin;
|
|
141
149
|
function getScopes() {
|
|
142
150
|
return Array.from(commandScopes);
|
|
143
151
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getBackend = exports.getBackendForAmbiguousLocation = exports.chooseBackends = exports.getBackendForLocation = exports.promptLocation = exports.deleteBackendAndPoll = exports.setDefaultTrafficPolicy = exports.createBackend = exports.ensureAppHostingComputeServiceAccount = exports.createGitRepoLink = exports.doSetup = void 0;
|
|
3
|
+
exports.getBackend = exports.getBackendForAmbiguousLocation = exports.chooseBackends = exports.promptExistingBackend = exports.getBackendForLocation = exports.promptLocation = exports.deleteBackendAndPoll = exports.setDefaultTrafficPolicy = exports.createBackend = exports.promptNewBackendId = exports.ensureAppHostingComputeServiceAccount = exports.createGitRepoLink = exports.ensureRequiredApisEnabled = exports.doSetupSourceDeploy = exports.doSetup = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const poller = require("../operation-poller");
|
|
6
6
|
const apphosting = require("../gcp/apphosting");
|
|
@@ -19,6 +19,7 @@ const app_1 = require("./app");
|
|
|
19
19
|
const ora = require("ora");
|
|
20
20
|
const node_fetch_1 = require("node-fetch");
|
|
21
21
|
const rollout_1 = require("./rollout");
|
|
22
|
+
const fuzzy = require("fuzzy");
|
|
22
23
|
const DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME = "firebase-app-hosting-compute";
|
|
23
24
|
const apphostingPollerOptions = {
|
|
24
25
|
apiOrigin: (0, api_1.apphostingOrigin)(),
|
|
@@ -51,14 +52,7 @@ async function awaitTlsReady(url) {
|
|
|
51
52
|
} while (!ready);
|
|
52
53
|
}
|
|
53
54
|
async function doSetup(projectId, webAppName, serviceAccount) {
|
|
54
|
-
await
|
|
55
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.developerConnectOrigin)(), "apphosting", true),
|
|
56
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudbuildOrigin)(), "apphosting", true),
|
|
57
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.secretManagerOrigin)(), "apphosting", true),
|
|
58
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudRunApiOrigin)(), "apphosting", true),
|
|
59
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "apphosting", true),
|
|
60
|
-
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.iamOrigin)(), "apphosting", true),
|
|
61
|
-
]);
|
|
55
|
+
await ensureRequiredApisEnabled(projectId);
|
|
62
56
|
await ensureAppHostingComputeServiceAccount(projectId, serviceAccount);
|
|
63
57
|
const location = await promptLocation(projectId, "Select a primary region to host your backend:\n");
|
|
64
58
|
const gitRepositoryLink = await githubConnections.linkGitHubRepository(projectId, location);
|
|
@@ -76,7 +70,7 @@ async function doSetup(projectId, webAppName, serviceAccount) {
|
|
|
76
70
|
(0, utils_1.logWarning)(`Firebase web app not set`);
|
|
77
71
|
}
|
|
78
72
|
const createBackendSpinner = ora("Creating your new backend...").start();
|
|
79
|
-
const backend = await createBackend(projectId, location, backendId,
|
|
73
|
+
const backend = await createBackend(projectId, location, backendId, serviceAccount, gitRepositoryLink, webApp === null || webApp === void 0 ? void 0 : webApp.id, rootDir);
|
|
80
74
|
createBackendSpinner.succeed(`Successfully created backend!\n\t${backend.name}\n`);
|
|
81
75
|
await setDefaultTrafficPolicy(projectId, location, backendId, branch);
|
|
82
76
|
const confirmRollout = await (0, prompt_1.confirm)({
|
|
@@ -112,6 +106,34 @@ async function doSetup(projectId, webAppName, serviceAccount) {
|
|
|
112
106
|
(0, utils_1.logSuccess)(`Your backend is now deployed at:\n\thttps://${backend.uri}`);
|
|
113
107
|
}
|
|
114
108
|
exports.doSetup = doSetup;
|
|
109
|
+
async function doSetupSourceDeploy(projectId, backendId) {
|
|
110
|
+
const location = await promptLocation(projectId, "Select a primary region to host your backend:\n");
|
|
111
|
+
const webAppSpinner = ora("Creating a new web app...\n").start();
|
|
112
|
+
const webApp = await app_1.webApps.getOrCreateWebApp(projectId, null, backendId);
|
|
113
|
+
if (!webApp) {
|
|
114
|
+
(0, utils_1.logWarning)(`Firebase web app not set`);
|
|
115
|
+
}
|
|
116
|
+
webAppSpinner.stop();
|
|
117
|
+
const createBackendSpinner = ora("Creating your new backend...").start();
|
|
118
|
+
const backend = await createBackend(projectId, location, backendId, null, undefined, webApp === null || webApp === void 0 ? void 0 : webApp.id);
|
|
119
|
+
createBackendSpinner.succeed(`Successfully created backend!\n\t${backend.name}\n`);
|
|
120
|
+
return {
|
|
121
|
+
backend,
|
|
122
|
+
location,
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
exports.doSetupSourceDeploy = doSetupSourceDeploy;
|
|
126
|
+
async function ensureRequiredApisEnabled(projectId) {
|
|
127
|
+
await Promise.all([
|
|
128
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.developerConnectOrigin)(), "apphosting", true),
|
|
129
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudbuildOrigin)(), "apphosting", true),
|
|
130
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.secretManagerOrigin)(), "apphosting", true),
|
|
131
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudRunApiOrigin)(), "apphosting", true),
|
|
132
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "apphosting", true),
|
|
133
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.iamOrigin)(), "apphosting", true),
|
|
134
|
+
]);
|
|
135
|
+
}
|
|
136
|
+
exports.ensureRequiredApisEnabled = ensureRequiredApisEnabled;
|
|
115
137
|
async function createGitRepoLink(projectId, location, connectionId) {
|
|
116
138
|
await Promise.all([
|
|
117
139
|
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.developerConnectOrigin)(), "apphosting", true),
|
|
@@ -130,7 +152,7 @@ async function createGitRepoLink(projectId, location, connectionId) {
|
|
|
130
152
|
await githubConnections.linkGitHubRepository(projectId, location, connectionId);
|
|
131
153
|
}
|
|
132
154
|
exports.createGitRepoLink = createGitRepoLink;
|
|
133
|
-
async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount) {
|
|
155
|
+
async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount, deployFromSource = false) {
|
|
134
156
|
const sa = serviceAccount || defaultComputeServiceAccountEmail(projectId);
|
|
135
157
|
const name = `projects/${projectId}/serviceAccounts/${sa}`;
|
|
136
158
|
try {
|
|
@@ -147,6 +169,14 @@ async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount)
|
|
|
147
169
|
throw new error_1.FirebaseError(`Failed to create backend due to missing delegation permissions for ${sa}. Make sure you have the iam.serviceAccounts.actAs permission.`, { original: err });
|
|
148
170
|
}
|
|
149
171
|
}
|
|
172
|
+
if (deployFromSource) {
|
|
173
|
+
const policy = await (0, resourceManager_1.getIamPolicy)(projectId);
|
|
174
|
+
const objectViewerBinding = policy.bindings.find((binding) => binding.role === "roles/storage.objectViewer");
|
|
175
|
+
if (!objectViewerBinding ||
|
|
176
|
+
!objectViewerBinding.members.includes(`serviceAccount:${defaultComputeServiceAccountEmail(projectId)}`)) {
|
|
177
|
+
await (0, resourceManager_1.addServiceAccountToRoles)(projectId, defaultComputeServiceAccountEmail(projectId), ["roles/storage.objectViewer"], true);
|
|
178
|
+
}
|
|
179
|
+
}
|
|
150
180
|
}
|
|
151
181
|
exports.ensureAppHostingComputeServiceAccount = ensureAppHostingComputeServiceAccount;
|
|
152
182
|
async function promptNewBackendId(projectId, location) {
|
|
@@ -168,17 +198,20 @@ async function promptNewBackendId(projectId, location) {
|
|
|
168
198
|
(0, utils_1.logWarning)(`Backend with id ${backendId} already exists in ${location}`);
|
|
169
199
|
}
|
|
170
200
|
}
|
|
201
|
+
exports.promptNewBackendId = promptNewBackendId;
|
|
171
202
|
function defaultComputeServiceAccountEmail(projectId) {
|
|
172
203
|
return `${DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME}@${projectId}.iam.gserviceaccount.com`;
|
|
173
204
|
}
|
|
174
|
-
async function createBackend(projectId, location, backendId,
|
|
205
|
+
async function createBackend(projectId, location, backendId, serviceAccount, repository, webAppId, rootDir = "/") {
|
|
175
206
|
const defaultServiceAccount = defaultComputeServiceAccountEmail(projectId);
|
|
176
207
|
const backendReqBody = {
|
|
177
208
|
servingLocality: "GLOBAL_ACCESS",
|
|
178
|
-
codebase:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
209
|
+
codebase: repository
|
|
210
|
+
? {
|
|
211
|
+
repository: `${repository.name}`,
|
|
212
|
+
rootDirectory: rootDir,
|
|
213
|
+
}
|
|
214
|
+
: undefined,
|
|
182
215
|
labels: deploymentTool.labels(),
|
|
183
216
|
serviceAccount: serviceAccount || defaultServiceAccount,
|
|
184
217
|
appId: webAppId,
|
|
@@ -203,6 +236,7 @@ async function provisionDefaultComputeServiceAccount(projectId) {
|
|
|
203
236
|
"roles/firebaseapphosting.computeRunner",
|
|
204
237
|
"roles/firebase.sdkAdminServiceAgent",
|
|
205
238
|
"roles/developerconnect.readTokenAccessor",
|
|
239
|
+
"roles/storage.objectViewer",
|
|
206
240
|
], true);
|
|
207
241
|
}
|
|
208
242
|
async function setDefaultTrafficPolicy(projectId, location, backendId, codebaseBranch) {
|
|
@@ -225,11 +259,11 @@ async function promptLocation(projectId, prompt = "Please select a location:") {
|
|
|
225
259
|
if (allowedLocations.length === 1) {
|
|
226
260
|
return allowedLocations[0];
|
|
227
261
|
}
|
|
228
|
-
const location =
|
|
262
|
+
const location = await (0, prompt_1.select)({
|
|
229
263
|
default: constants_1.DEFAULT_LOCATION,
|
|
230
264
|
message: prompt,
|
|
231
265
|
choices: allowedLocations,
|
|
232
|
-
})
|
|
266
|
+
});
|
|
233
267
|
(0, utils_1.logSuccess)(`Location set to ${location}.\n`);
|
|
234
268
|
return location;
|
|
235
269
|
}
|
|
@@ -245,6 +279,28 @@ async function getBackendForLocation(projectId, location, backendId) {
|
|
|
245
279
|
}
|
|
246
280
|
}
|
|
247
281
|
exports.getBackendForLocation = getBackendForLocation;
|
|
282
|
+
async function promptExistingBackend(projectId, promptMessage) {
|
|
283
|
+
const { backends } = await apphosting.listBackends(projectId, "-");
|
|
284
|
+
const backendId = await (0, prompt_1.search)({
|
|
285
|
+
message: promptMessage,
|
|
286
|
+
source: (input = "") => {
|
|
287
|
+
return new Promise((resolve) => resolve([
|
|
288
|
+
...fuzzy
|
|
289
|
+
.filter(input, backends, {
|
|
290
|
+
extract: (backend) => apphosting.parseBackendName(backend.name).id,
|
|
291
|
+
})
|
|
292
|
+
.map((result) => {
|
|
293
|
+
return {
|
|
294
|
+
name: apphosting.parseBackendName(result.original.name).id,
|
|
295
|
+
value: apphosting.parseBackendName(result.original.name).id,
|
|
296
|
+
};
|
|
297
|
+
}),
|
|
298
|
+
]));
|
|
299
|
+
},
|
|
300
|
+
});
|
|
301
|
+
return backendId;
|
|
302
|
+
}
|
|
303
|
+
exports.promptExistingBackend = promptExistingBackend;
|
|
248
304
|
async function chooseBackends(projectId, backendId, chooseBackendPrompt, force) {
|
|
249
305
|
let { unreachable, backends } = await apphosting.listBackends(projectId, "-");
|
|
250
306
|
if (unreachable && unreachable.length !== 0) {
|
|
@@ -19,8 +19,8 @@ const apphostingPollerOptions = {
|
|
|
19
19
|
const GIT_COMMIT_SHA_REGEX = /^(?:[0-9a-f]{40}|[0-9a-f]{7})$/;
|
|
20
20
|
async function createRollout(backendId, projectId, branch, commit, force) {
|
|
21
21
|
const backend = await (0, backend_1.getBackend)(projectId, backendId);
|
|
22
|
-
if (!backend.codebase.repository) {
|
|
23
|
-
throw new error_1.FirebaseError(`Backend ${backendId} is
|
|
22
|
+
if (!backend.codebase || !backend.codebase.repository) {
|
|
23
|
+
throw new error_1.FirebaseError(`Backend ${backendId} is missing a connected repository. If you would like to deploy from a branch or commit of a GitHub repository, you can connect one through the Firebase Console. If you would like to deploy from local source, run 'firebase deploy'.`);
|
|
24
24
|
}
|
|
25
25
|
const { location } = apphosting.parseBackendName(backend.name);
|
|
26
26
|
const { repoLink, owner, repo, readToken } = await (0, devConnect_1.getRepoDetailsFromBackend)(projectId, location, backend.codebase.repository);
|
|
@@ -9,11 +9,11 @@ const prompt = require("../../prompt");
|
|
|
9
9
|
const utils = require("../../utils");
|
|
10
10
|
const logger_1 = require("../../logger");
|
|
11
11
|
const env = require("../../functions/env");
|
|
12
|
-
function toMetadata(projectNumber, backends) {
|
|
12
|
+
async function toMetadata(projectNumber, backends) {
|
|
13
13
|
const metadata = [];
|
|
14
14
|
for (const backend of backends) {
|
|
15
15
|
const [, , , location, , id] = backend.name.split("/");
|
|
16
|
-
metadata.push(Object.assign({ location, id }, (0, _1.serviceAccountsForBackend)(projectNumber, backend)));
|
|
16
|
+
metadata.push(Object.assign({ location, id }, (await (0, _1.serviceAccountsForBackend)(projectNumber, backend))));
|
|
17
17
|
}
|
|
18
18
|
return metadata.sort((left, right) => {
|
|
19
19
|
const cmplocation = left.location.localeCompare(right.location);
|
|
@@ -86,12 +86,12 @@ async function selectBackendServiceAccounts(projectNumber, projectId, options) {
|
|
|
86
86
|
message: "To use this secret, your backend's service account must be granted access. Would you like to grant access now?",
|
|
87
87
|
});
|
|
88
88
|
if (grant) {
|
|
89
|
-
return (0, _1.toMulti)((0, _1.serviceAccountsForBackend)(projectNumber, listBackends.backends[0]));
|
|
89
|
+
return (0, _1.toMulti)(await (0, _1.serviceAccountsForBackend)(projectNumber, listBackends.backends[0]));
|
|
90
90
|
}
|
|
91
91
|
utils.logBullet(exports.GRANT_ACCESS_IN_FUTURE);
|
|
92
92
|
return { buildServiceAccounts: [], runServiceAccounts: [] };
|
|
93
93
|
}
|
|
94
|
-
const metadata = toMetadata(projectNumber, listBackends.backends);
|
|
94
|
+
const metadata = await toMetadata(projectNumber, listBackends.backends);
|
|
95
95
|
if (metadata.every(matchesServiceAccounts(metadata[0]))) {
|
|
96
96
|
utils.logBullet("To use this secret, your backend's service account must be granted access.");
|
|
97
97
|
utils.logBullet("All of your backends share the following " +
|
|
@@ -21,7 +21,7 @@ function toMulti(accounts) {
|
|
|
21
21
|
return m;
|
|
22
22
|
}
|
|
23
23
|
exports.toMulti = toMulti;
|
|
24
|
-
function serviceAccountsForBackend(projectNumber, backend) {
|
|
24
|
+
async function serviceAccountsForBackend(projectNumber, backend) {
|
|
25
25
|
if (backend.serviceAccount) {
|
|
26
26
|
return {
|
|
27
27
|
buildServiceAccount: backend.serviceAccount,
|
|
@@ -30,7 +30,7 @@ function serviceAccountsForBackend(projectNumber, backend) {
|
|
|
30
30
|
}
|
|
31
31
|
return {
|
|
32
32
|
buildServiceAccount: gcb.getDefaultServiceAccount(projectNumber),
|
|
33
|
-
runServiceAccount: gce.getDefaultServiceAccount(projectNumber),
|
|
33
|
+
runServiceAccount: await gce.getDefaultServiceAccount(projectNumber),
|
|
34
34
|
};
|
|
35
35
|
}
|
|
36
36
|
exports.serviceAccountsForBackend = serviceAccountsForBackend;
|
package/lib/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.addAdditionalAccount = exports.logout = exports.getAccessToken = exports.haveValidTokens = exports.isExpired = exports.loggedIn = 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;
|
|
3
|
+
exports.addAdditionalAccount = exports.logout = exports.getAccessToken = exports.haveValidTokens = exports.isExpired = exports.loggedIn = exports.findAccountByEmail = exports.loginGithub = exports.loginGoogle = exports.setGlobalDefaultAccount = exports.setProjectAccount = exports.loginAdditionalAccount = exports.selectAccount = exports.setRefreshToken = exports.setActiveAccount = exports.assertAccount = exports.getAllAccounts = exports.getAdditionalAccounts = exports.getProjectDefaultAccount = exports.getGlobalDefaultAccount = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const FormData = require("form-data");
|
|
6
6
|
const http = require("http");
|
|
@@ -62,6 +62,16 @@ function getAllAccounts() {
|
|
|
62
62
|
return res;
|
|
63
63
|
}
|
|
64
64
|
exports.getAllAccounts = getAllAccounts;
|
|
65
|
+
function assertAccount(email, options) {
|
|
66
|
+
const allAccounts = getAllAccounts();
|
|
67
|
+
const accountExists = allAccounts.some((a) => a.user.email === email);
|
|
68
|
+
if (!accountExists) {
|
|
69
|
+
throw new error_1.FirebaseError(`Account ${email} does not exist, ${(options === null || options === void 0 ? void 0 : options.mcp)
|
|
70
|
+
? `use the 'firebase_get_environment' tool to see available accounts or instruct the user to use the 'firebase login:add' terminal command to add a new account.`
|
|
71
|
+
: `run "${clc.bold("firebase login:list")} to see valid accounts`}`);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
exports.assertAccount = assertAccount;
|
|
65
75
|
function setActiveAccount(options, account) {
|
|
66
76
|
if (account.tokens.refresh_token) {
|
|
67
77
|
setRefreshToken(account.tokens.refresh_token);
|
|
@@ -121,7 +131,17 @@ function setProjectAccount(projectDir, email) {
|
|
|
121
131
|
configstore_1.configstore.set("activeAccounts", activeAccounts);
|
|
122
132
|
}
|
|
123
133
|
exports.setProjectAccount = setProjectAccount;
|
|
124
|
-
function setGlobalDefaultAccount(
|
|
134
|
+
function setGlobalDefaultAccount(accountOrEmail) {
|
|
135
|
+
let account;
|
|
136
|
+
if (typeof accountOrEmail === "string") {
|
|
137
|
+
const accountFromEmail = getAllAccounts().find((acc) => acc.user.email === accountOrEmail);
|
|
138
|
+
if (!accountFromEmail)
|
|
139
|
+
throw new error_1.FirebaseError(`Account '${accountOrEmail}' is not a signed-in user on this device.`);
|
|
140
|
+
account = accountFromEmail;
|
|
141
|
+
}
|
|
142
|
+
else {
|
|
143
|
+
account = accountOrEmail;
|
|
144
|
+
}
|
|
125
145
|
configstore_1.configstore.set("user", account.user);
|
|
126
146
|
configstore_1.configstore.set("tokens", account.tokens);
|
|
127
147
|
const additionalAccounts = getAdditionalAccounts();
|
package/lib/bin/cli.js
CHANGED
|
@@ -6,9 +6,6 @@ const clc = require("colorette");
|
|
|
6
6
|
const marked_terminal_1 = require("marked-terminal");
|
|
7
7
|
const marked_1 = require("marked");
|
|
8
8
|
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
9
|
-
const node_path_1 = require("node:path");
|
|
10
|
-
const triple_beam_1 = require("triple-beam");
|
|
11
|
-
const node_util_1 = require("node:util");
|
|
12
9
|
const fs = require("node:fs");
|
|
13
10
|
const configstore_1 = require("../configstore");
|
|
14
11
|
const errorOut_1 = require("../errorOut");
|
|
@@ -17,46 +14,17 @@ const logger_1 = require("../logger");
|
|
|
17
14
|
const client = require("..");
|
|
18
15
|
const fsutils = require("../fsutils");
|
|
19
16
|
const utils = require("../utils");
|
|
20
|
-
const winston = require("winston");
|
|
21
17
|
const experiments_1 = require("../experiments");
|
|
22
18
|
const fetchMOTD_1 = require("../fetchMOTD");
|
|
23
19
|
function cli(pkg) {
|
|
24
20
|
const updateNotifier = updateNotifierPkg({ pkg });
|
|
25
21
|
const args = process.argv.slice(2);
|
|
26
22
|
let cmd;
|
|
27
|
-
function findAvailableLogFile() {
|
|
28
|
-
const candidates = ["firebase-debug.log"];
|
|
29
|
-
for (let i = 1; i < 10; i++) {
|
|
30
|
-
candidates.push(`firebase-debug.${i}.log`);
|
|
31
|
-
}
|
|
32
|
-
for (const c of candidates) {
|
|
33
|
-
const logFilename = (0, node_path_1.join)(process.cwd(), c);
|
|
34
|
-
try {
|
|
35
|
-
const fd = fs.openSync(logFilename, "r+");
|
|
36
|
-
fs.closeSync(fd);
|
|
37
|
-
return logFilename;
|
|
38
|
-
}
|
|
39
|
-
catch (e) {
|
|
40
|
-
if (e.code === "ENOENT") {
|
|
41
|
-
return logFilename;
|
|
42
|
-
}
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
throw new Error("Unable to obtain permissions for firebase-debug.log");
|
|
46
|
-
}
|
|
47
|
-
const logFilename = findAvailableLogFile();
|
|
48
23
|
if (!process.env.DEBUG && args.includes("--debug")) {
|
|
49
24
|
process.env.DEBUG = "true";
|
|
50
25
|
}
|
|
51
26
|
process.env.IS_FIREBASE_CLI = "true";
|
|
52
|
-
|
|
53
|
-
level: "debug",
|
|
54
|
-
filename: logFilename,
|
|
55
|
-
format: winston.format.printf((info) => {
|
|
56
|
-
const segments = [info.message, ...(info[triple_beam_1.SPLAT] || [])].map(utils.tryStringify);
|
|
57
|
-
return `[${info.level}] ${(0, node_util_1.stripVTControlCharacters)(segments.join(" "))}`;
|
|
58
|
-
}),
|
|
59
|
-
}));
|
|
27
|
+
const logFilename = (0, logger_1.useFileLogger)();
|
|
60
28
|
logger_1.logger.debug("-".repeat(70));
|
|
61
29
|
logger_1.logger.debug("Command: ", process.argv.join(" "));
|
|
62
30
|
logger_1.logger.debug("CLI Version: ", pkg.version);
|
package/lib/bin/mcp.js
CHANGED
|
@@ -3,10 +3,11 @@
|
|
|
3
3
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
4
|
exports.mcp = void 0;
|
|
5
5
|
const logger_1 = require("../logger");
|
|
6
|
-
(0, logger_1.silenceStdout)();
|
|
7
6
|
const index_1 = require("../mcp/index");
|
|
8
7
|
const util_1 = require("util");
|
|
9
8
|
const types_1 = require("../mcp/types");
|
|
9
|
+
const index_js_1 = require("../mcp/tools/index.js");
|
|
10
|
+
const path_1 = require("path");
|
|
10
11
|
const STARTUP_MESSAGE = `
|
|
11
12
|
This is a running process of the Firebase MCP server. This command should only be executed by an MCP client. An example MCP client configuration might be:
|
|
12
13
|
|
|
@@ -24,13 +25,23 @@ async function mcp() {
|
|
|
24
25
|
options: {
|
|
25
26
|
only: { type: "string", default: "" },
|
|
26
27
|
dir: { type: "string" },
|
|
28
|
+
"generate-tool-list": { type: "boolean", default: false },
|
|
27
29
|
},
|
|
28
30
|
allowPositionals: true,
|
|
29
31
|
});
|
|
32
|
+
if (values["generate-tool-list"]) {
|
|
33
|
+
console.log((0, index_js_1.markdownDocsOfTools)());
|
|
34
|
+
return;
|
|
35
|
+
}
|
|
36
|
+
process.env.IS_FIREBASE_MCP = "true";
|
|
37
|
+
(0, logger_1.useFileLogger)();
|
|
30
38
|
const activeFeatures = (values.only || "")
|
|
31
39
|
.split(",")
|
|
32
40
|
.filter((f) => types_1.SERVER_FEATURES.includes(f));
|
|
33
|
-
const server = new index_1.FirebaseMcpServer({
|
|
41
|
+
const server = new index_1.FirebaseMcpServer({
|
|
42
|
+
activeFeatures,
|
|
43
|
+
projectRoot: values.dir ? (0, path_1.resolve)(values.dir) : undefined,
|
|
44
|
+
});
|
|
34
45
|
await server.start();
|
|
35
46
|
if (process.stdin.isTTY)
|
|
36
47
|
process.stderr.write(STARTUP_MESSAGE);
|
package/lib/command.js
CHANGED
|
@@ -13,6 +13,7 @@ const track_1 = require("./track");
|
|
|
13
13
|
const auth_1 = require("./auth");
|
|
14
14
|
const projects_1 = require("./management/projects");
|
|
15
15
|
const requireAuth_1 = require("./requireAuth");
|
|
16
|
+
const logger_1 = require("./logger");
|
|
16
17
|
class Command {
|
|
17
18
|
constructor(cmd) {
|
|
18
19
|
this.cmd = cmd;
|
|
@@ -163,8 +164,8 @@ class Command {
|
|
|
163
164
|
if ((0, utils_1.getInheritedOption)(options, "json")) {
|
|
164
165
|
options.nonInteractive = true;
|
|
165
166
|
}
|
|
166
|
-
else {
|
|
167
|
-
(0,
|
|
167
|
+
else if (!options.isMCP) {
|
|
168
|
+
(0, logger_1.useConsoleLoggers)();
|
|
168
169
|
}
|
|
169
170
|
if ((0, utils_1.getInheritedOption)(options, "config")) {
|
|
170
171
|
options.configPath = (0, utils_1.getInheritedOption)(options, "config");
|
|
@@ -54,6 +54,6 @@ exports.command = new command_1.Command("apphosting:secrets:grantaccess <secretN
|
|
|
54
54
|
else {
|
|
55
55
|
backend = await apphosting.getBackend(projectId, location, backendId);
|
|
56
56
|
}
|
|
57
|
-
const accounts = secrets.toMulti(secrets.serviceAccountsForBackend(projectNumber, backend));
|
|
57
|
+
const accounts = secrets.toMulti(await secrets.serviceAccountsForBackend(projectNumber, backend));
|
|
58
58
|
await Promise.allSettled(secretList.map((secretName) => secrets.grantSecretAccess(projectId, projectNumber, secretName, accounts)));
|
|
59
59
|
});
|
package/lib/commands/deploy.js
CHANGED
package/lib/commands/init.js
CHANGED
|
@@ -40,7 +40,7 @@ let choices = [
|
|
|
40
40
|
},
|
|
41
41
|
{
|
|
42
42
|
value: "apphosting",
|
|
43
|
-
name: "App Hosting:
|
|
43
|
+
name: "App Hosting: Enable web app deployments with App Hosting",
|
|
44
44
|
checked: false,
|
|
45
45
|
hidden: false,
|
|
46
46
|
},
|
|
@@ -186,12 +186,9 @@ async function initAction(feature, options) {
|
|
|
186
186
|
}
|
|
187
187
|
await (0, init_1.init)(setup, config, options);
|
|
188
188
|
logger_1.logger.info();
|
|
189
|
-
utils.logBullet("Writing configuration info to " + clc.bold("firebase.json") + "...");
|
|
190
189
|
config.writeProjectFile("firebase.json", setup.config);
|
|
191
|
-
utils.logBullet("Writing project information to " + clc.bold(".firebaserc") + "...");
|
|
192
190
|
config.writeProjectFile(".firebaserc", setup.rcfile);
|
|
193
191
|
if (!fsutils.fileExistsSync(config.path(".gitignore"))) {
|
|
194
|
-
utils.logBullet("Writing gitignore file to " + clc.bold(".gitignore") + "...");
|
|
195
192
|
config.writeProjectFile(".gitignore", GITIGNORE_TEMPLATE);
|
|
196
193
|
}
|
|
197
194
|
logger_1.logger.info();
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
|
-
const clc = require("colorette");
|
|
5
4
|
const command_1 = require("../command");
|
|
6
5
|
const utils = require("../utils");
|
|
7
6
|
const auth = require("../auth");
|
|
@@ -9,11 +8,7 @@ const error_1 = require("../error");
|
|
|
9
8
|
exports.command = new command_1.Command("login:use <email>")
|
|
10
9
|
.description("set the default account to use for this project directory or the global default account if not in a Firebase project directory")
|
|
11
10
|
.action((email, options) => {
|
|
12
|
-
|
|
13
|
-
const accountExists = allAccounts.some((a) => a.user.email === email);
|
|
14
|
-
if (!accountExists) {
|
|
15
|
-
throw new error_1.FirebaseError(`Account ${email} does not exist, run "${clc.bold("firebase login:list")}" to see valid accounts`);
|
|
16
|
-
}
|
|
11
|
+
auth.assertAccount(email);
|
|
17
12
|
const projectDir = options.projectRoot;
|
|
18
13
|
if (projectDir) {
|
|
19
14
|
if (options.user.email === email) {
|
|
@@ -27,15 +22,11 @@ exports.command = new command_1.Command("login:use <email>")
|
|
|
27
22
|
if (options.user.email === email) {
|
|
28
23
|
throw new error_1.FirebaseError(`Already using account ${email} for the global default account.`);
|
|
29
24
|
}
|
|
30
|
-
const newDefaultAccount = allAccounts.find((a) => a.user.email === email);
|
|
31
|
-
if (!newDefaultAccount) {
|
|
32
|
-
throw new error_1.FirebaseError(`Account ${email} does not exist, run "${clc.bold("firebase login:list")}" to see valid accounts`);
|
|
33
|
-
}
|
|
34
25
|
const oldDefaultAccount = auth.getGlobalDefaultAccount();
|
|
35
26
|
if (!oldDefaultAccount) {
|
|
36
27
|
throw new error_1.FirebaseError("Could not determine global default account");
|
|
37
28
|
}
|
|
38
|
-
auth.setGlobalDefaultAccount(
|
|
29
|
+
auth.setGlobalDefaultAccount(email);
|
|
39
30
|
auth.addAdditionalAccount(oldDefaultAccount);
|
|
40
31
|
utils.logSuccess(`Set global default account to ${email}.`);
|
|
41
32
|
return email;
|
package/lib/commands/use.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.command = void 0;
|
|
3
|
+
exports.command = exports.setNewActive = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const command_1 = require("../command");
|
|
6
6
|
const projects_1 = require("../management/projects");
|
|
@@ -30,10 +30,10 @@ function listAliases(options) {
|
|
|
30
30
|
function verifyMessage(name) {
|
|
31
31
|
return "please verify project " + clc.bold(name) + " exists and you have access.";
|
|
32
32
|
}
|
|
33
|
-
async function setNewActive(projectOrAlias, aliasOpt,
|
|
33
|
+
async function setNewActive(projectOrAlias, aliasOpt, rc, projectRoot) {
|
|
34
34
|
let project;
|
|
35
|
-
const hasAlias =
|
|
36
|
-
const resolvedProject =
|
|
35
|
+
const hasAlias = rc.hasProjectAlias(projectOrAlias);
|
|
36
|
+
const resolvedProject = rc.resolveAlias(projectOrAlias);
|
|
37
37
|
(0, command_2.validateProjectId)(resolvedProject);
|
|
38
38
|
try {
|
|
39
39
|
project = await (0, projects_1.getProject)(resolvedProject);
|
|
@@ -45,24 +45,25 @@ async function setNewActive(projectOrAlias, aliasOpt, options) {
|
|
|
45
45
|
if (!project) {
|
|
46
46
|
throw new error_1.FirebaseError(`Cannot create alias ${clc.bold(aliasOpt)}, ${verifyMessage(projectOrAlias)}`);
|
|
47
47
|
}
|
|
48
|
-
|
|
48
|
+
rc.addProjectAlias(aliasOpt, projectOrAlias);
|
|
49
49
|
logger_1.logger.info("Created alias", clc.bold(aliasOpt), "for", resolvedProject + ".");
|
|
50
50
|
}
|
|
51
51
|
if (hasAlias) {
|
|
52
52
|
if (!project) {
|
|
53
53
|
throw new error_1.FirebaseError(`Unable to use alias ${clc.bold(projectOrAlias)}, ${verifyMessage(resolvedProject)}`);
|
|
54
54
|
}
|
|
55
|
-
utils.makeActiveProject(
|
|
55
|
+
utils.makeActiveProject(projectRoot, projectOrAlias);
|
|
56
56
|
logger_1.logger.info("Now using alias", clc.bold(projectOrAlias), "(" + resolvedProject + ")");
|
|
57
57
|
}
|
|
58
58
|
else if (project) {
|
|
59
|
-
utils.makeActiveProject(
|
|
59
|
+
utils.makeActiveProject(projectRoot, projectOrAlias);
|
|
60
60
|
logger_1.logger.info("Now using project", clc.bold(projectOrAlias));
|
|
61
61
|
}
|
|
62
62
|
else {
|
|
63
63
|
throw new error_1.FirebaseError(`Invalid project selection, ${verifyMessage(projectOrAlias)}`);
|
|
64
64
|
}
|
|
65
65
|
}
|
|
66
|
+
exports.setNewActive = setNewActive;
|
|
66
67
|
function unalias(alias, options) {
|
|
67
68
|
if (options.rc.hasProjectAlias(alias)) {
|
|
68
69
|
options.rc.removeProjectAlias(alias);
|
|
@@ -150,7 +151,7 @@ exports.command = new command_1.Command("use [alias_or_project_id]")
|
|
|
150
151
|
" to start a project directory in the current folder.");
|
|
151
152
|
}
|
|
152
153
|
if (newActive) {
|
|
153
|
-
return setNewActive(newActive, aliasOpt, options);
|
|
154
|
+
return setNewActive(newActive, aliasOpt, options.rc, options.projectRoot);
|
|
154
155
|
}
|
|
155
156
|
if (options.unalias) {
|
|
156
157
|
return unalias(options.unalias, options);
|