firebase-tools 14.3.0 → 14.4.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 +72 -18
- package/lib/apphosting/githubConnections.js +13 -19
- 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 +12 -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 -1
- package/lib/commands/login-use.js +2 -11
- package/lib/commands/use.js +9 -8
- package/lib/config.js +1 -0
- package/lib/crashlytics/listTopIssues.js +44 -0
- package/lib/dataconnect/cloudAICompanionClient.js +67 -0
- package/lib/dataconnect/dataplaneClient.js +16 -1
- package/lib/dataconnect/types.js +5 -1
- package/lib/deploy/apphosting/args.js +2 -0
- package/lib/deploy/apphosting/deploy.js +74 -0
- package/lib/deploy/apphosting/index.js +9 -0
- package/lib/deploy/apphosting/prepare.js +141 -0
- package/lib/deploy/apphosting/release.js +53 -0
- package/lib/deploy/apphosting/util.js +65 -0
- package/lib/deploy/extensions/v2FunctionHelper.js +2 -1
- 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 +60 -0
- package/lib/emulator/downloadableEmulators.js +25 -61
- package/lib/ensureApiEnabled.js +11 -1
- package/lib/experiments.js +1 -1
- package/lib/extensions/manifest.js +2 -2
- package/lib/fsAsync.js +9 -2
- 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/storage.js +43 -1
- package/lib/index.js +1 -2
- package/lib/init/features/apphosting.js +84 -6
- package/lib/init/features/database.js +64 -45
- package/lib/init/features/dataconnect/index.js +51 -53
- package/lib/init/features/emulators.js +9 -5
- package/lib/init/features/firestore/index.js +54 -23
- package/lib/init/features/firestore/indexes.js +23 -23
- package/lib/init/features/firestore/rules.js +35 -40
- 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 +2 -1
- package/lib/init/features/hosting/github.js +3 -2
- package/lib/init/features/index.js +8 -4
- package/lib/init/features/remoteconfig.js +3 -2
- package/lib/init/index.js +76 -24
- package/lib/logger.js +71 -7
- package/lib/management/projects.js +25 -2
- package/lib/mcp/errors.js +1 -1
- package/lib/mcp/index.js +134 -51
- package/lib/mcp/tools/auth/{disable_auth_user.js → disable_user.js} +3 -3
- package/lib/mcp/tools/auth/get_user.js +38 -0
- package/lib/mcp/tools/auth/index.js +8 -6
- package/lib/mcp/tools/auth/list_users.js +47 -0
- package/lib/mcp/tools/auth/set_claims.js +43 -0
- package/lib/mcp/tools/auth/set_sms_region_policy.js +1 -1
- package/lib/mcp/tools/core/{consult_firebase_assistant.js → consult_assistant.js} +4 -4
- 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/{project → core}/get_sdk_config.js +6 -3
- package/lib/mcp/tools/core/index.js +20 -6
- package/lib/mcp/tools/core/init.js +129 -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 +30 -1
- package/lib/mcp/tools/dataconnect/emulator.js +32 -0
- package/lib/mcp/tools/dataconnect/execute_graphql.js +48 -0
- package/lib/mcp/tools/dataconnect/execute_graphql_read.js +48 -0
- package/lib/mcp/tools/dataconnect/execute_mutation.js +62 -0
- package/lib/mcp/tools/dataconnect/execute_query.js +62 -0
- package/lib/mcp/tools/dataconnect/{generate_dataconnect_operation.js → generate_operation.js} +9 -9
- package/lib/mcp/tools/dataconnect/{generate_dataconnect_schema.js → generate_schema.js} +4 -4
- package/lib/mcp/tools/dataconnect/{get_dataconnect_connector.js → get_connector.js} +9 -9
- package/lib/mcp/tools/dataconnect/{get_dataconnect_schema.js → get_schema.js} +10 -10
- package/lib/mcp/tools/dataconnect/index.js +14 -10
- package/lib/mcp/tools/dataconnect/{list_dataconnect_services.js → list_services.js} +5 -5
- package/lib/mcp/tools/firestore/converter.js +47 -1
- package/lib/mcp/tools/firestore/delete_document.js +37 -0
- package/lib/mcp/tools/firestore/{get_firestore_documents.js → get_documents.js} +3 -3
- package/lib/mcp/tools/firestore/index.js +12 -6
- package/lib/mcp/tools/firestore/{list_firestore_collections.js → list_collections.js} +4 -9
- package/lib/mcp/tools/firestore/query_collection.js +116 -0
- package/lib/mcp/tools/index.js +44 -8
- 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 +34 -0
- package/lib/mcp/tools/storage/{get_storage_rules.js → get_rules.js} +6 -6
- package/lib/mcp/tools/storage/index.js +8 -2
- package/lib/mcp/types.js +9 -1
- package/lib/mcp/util.js +29 -2
- package/lib/messaging/interfaces.js +2 -0
- package/lib/messaging/sendMessage.js +48 -0
- package/lib/remoteconfig/publish.js +39 -0
- package/lib/requireAuth.js +2 -2
- package/lib/utils.js +2 -37
- package/package.json +2 -1
- package/schema/firebase-config.json +62 -10
- 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 +1 -1
- package/templates/init/functions/typescript/package.nolint.json +2 -2
- package/lib/mcp/tools/auth/get_auth_user.js +0 -29
- package/lib/mcp/tools/auth/set_auth_claims.js +0 -34
- package/lib/mcp/tools/core/get_firebase_directory.js +0 -20
- package/lib/mcp/tools/core/set_firebase_directory.js +0 -33
- package/lib/mcp/tools/firestore/get_firestore_rules.js +0 -26
- package/lib/mcp/tools/project/index.js +0 -7
- /package/lib/mcp/tools/{project → core}/get_project.js +0 -0
- /package/lib/mcp/tools/{project → core}/list_apps.js +0 -0
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,32 @@ 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 webApp = await app_1.webApps.getOrCreateWebApp(projectId, null, backendId);
|
|
112
|
+
if (!webApp) {
|
|
113
|
+
(0, utils_1.logWarning)(`Firebase web app not set`);
|
|
114
|
+
}
|
|
115
|
+
const createBackendSpinner = ora("Creating your new backend...").start();
|
|
116
|
+
const backend = await createBackend(projectId, location, backendId, null, undefined, webApp === null || webApp === void 0 ? void 0 : webApp.id);
|
|
117
|
+
createBackendSpinner.succeed(`Successfully created backend!\n\t${backend.name}\n`);
|
|
118
|
+
return {
|
|
119
|
+
backend,
|
|
120
|
+
location,
|
|
121
|
+
};
|
|
122
|
+
}
|
|
123
|
+
exports.doSetupSourceDeploy = doSetupSourceDeploy;
|
|
124
|
+
async function ensureRequiredApisEnabled(projectId) {
|
|
125
|
+
await Promise.all([
|
|
126
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.developerConnectOrigin)(), "apphosting", true),
|
|
127
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudbuildOrigin)(), "apphosting", true),
|
|
128
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.secretManagerOrigin)(), "apphosting", true),
|
|
129
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.cloudRunApiOrigin)(), "apphosting", true),
|
|
130
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.artifactRegistryDomain)(), "apphosting", true),
|
|
131
|
+
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.iamOrigin)(), "apphosting", true),
|
|
132
|
+
]);
|
|
133
|
+
}
|
|
134
|
+
exports.ensureRequiredApisEnabled = ensureRequiredApisEnabled;
|
|
115
135
|
async function createGitRepoLink(projectId, location, connectionId) {
|
|
116
136
|
await Promise.all([
|
|
117
137
|
(0, ensureApiEnabled_1.ensure)(projectId, (0, api_1.developerConnectOrigin)(), "apphosting", true),
|
|
@@ -130,7 +150,7 @@ async function createGitRepoLink(projectId, location, connectionId) {
|
|
|
130
150
|
await githubConnections.linkGitHubRepository(projectId, location, connectionId);
|
|
131
151
|
}
|
|
132
152
|
exports.createGitRepoLink = createGitRepoLink;
|
|
133
|
-
async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount) {
|
|
153
|
+
async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount, deployFromSource = false) {
|
|
134
154
|
const sa = serviceAccount || defaultComputeServiceAccountEmail(projectId);
|
|
135
155
|
const name = `projects/${projectId}/serviceAccounts/${sa}`;
|
|
136
156
|
try {
|
|
@@ -147,6 +167,14 @@ async function ensureAppHostingComputeServiceAccount(projectId, serviceAccount)
|
|
|
147
167
|
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
168
|
}
|
|
149
169
|
}
|
|
170
|
+
if (deployFromSource) {
|
|
171
|
+
const policy = await (0, resourceManager_1.getIamPolicy)(projectId);
|
|
172
|
+
const objectViewerBinding = policy.bindings.find((binding) => binding.role === "roles/storage.objectViewer");
|
|
173
|
+
if (!objectViewerBinding ||
|
|
174
|
+
!objectViewerBinding.members.includes(`serviceAccount:${defaultComputeServiceAccountEmail(projectId)}`)) {
|
|
175
|
+
await (0, resourceManager_1.addServiceAccountToRoles)(projectId, defaultComputeServiceAccountEmail(projectId), ["roles/storage.objectViewer"], true);
|
|
176
|
+
}
|
|
177
|
+
}
|
|
150
178
|
}
|
|
151
179
|
exports.ensureAppHostingComputeServiceAccount = ensureAppHostingComputeServiceAccount;
|
|
152
180
|
async function promptNewBackendId(projectId, location) {
|
|
@@ -168,17 +196,20 @@ async function promptNewBackendId(projectId, location) {
|
|
|
168
196
|
(0, utils_1.logWarning)(`Backend with id ${backendId} already exists in ${location}`);
|
|
169
197
|
}
|
|
170
198
|
}
|
|
199
|
+
exports.promptNewBackendId = promptNewBackendId;
|
|
171
200
|
function defaultComputeServiceAccountEmail(projectId) {
|
|
172
201
|
return `${DEFAULT_COMPUTE_SERVICE_ACCOUNT_NAME}@${projectId}.iam.gserviceaccount.com`;
|
|
173
202
|
}
|
|
174
|
-
async function createBackend(projectId, location, backendId,
|
|
203
|
+
async function createBackend(projectId, location, backendId, serviceAccount, repository, webAppId, rootDir = "/") {
|
|
175
204
|
const defaultServiceAccount = defaultComputeServiceAccountEmail(projectId);
|
|
176
205
|
const backendReqBody = {
|
|
177
206
|
servingLocality: "GLOBAL_ACCESS",
|
|
178
|
-
codebase:
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
207
|
+
codebase: repository
|
|
208
|
+
? {
|
|
209
|
+
repository: `${repository.name}`,
|
|
210
|
+
rootDirectory: rootDir,
|
|
211
|
+
}
|
|
212
|
+
: undefined,
|
|
182
213
|
labels: deploymentTool.labels(),
|
|
183
214
|
serviceAccount: serviceAccount || defaultServiceAccount,
|
|
184
215
|
appId: webAppId,
|
|
@@ -203,6 +234,7 @@ async function provisionDefaultComputeServiceAccount(projectId) {
|
|
|
203
234
|
"roles/firebaseapphosting.computeRunner",
|
|
204
235
|
"roles/firebase.sdkAdminServiceAgent",
|
|
205
236
|
"roles/developerconnect.readTokenAccessor",
|
|
237
|
+
"roles/storage.objectViewer",
|
|
206
238
|
], true);
|
|
207
239
|
}
|
|
208
240
|
async function setDefaultTrafficPolicy(projectId, location, backendId, codebaseBranch) {
|
|
@@ -225,11 +257,11 @@ async function promptLocation(projectId, prompt = "Please select a location:") {
|
|
|
225
257
|
if (allowedLocations.length === 1) {
|
|
226
258
|
return allowedLocations[0];
|
|
227
259
|
}
|
|
228
|
-
const location =
|
|
260
|
+
const location = await (0, prompt_1.select)({
|
|
229
261
|
default: constants_1.DEFAULT_LOCATION,
|
|
230
262
|
message: prompt,
|
|
231
263
|
choices: allowedLocations,
|
|
232
|
-
})
|
|
264
|
+
});
|
|
233
265
|
(0, utils_1.logSuccess)(`Location set to ${location}.\n`);
|
|
234
266
|
return location;
|
|
235
267
|
}
|
|
@@ -245,6 +277,28 @@ async function getBackendForLocation(projectId, location, backendId) {
|
|
|
245
277
|
}
|
|
246
278
|
}
|
|
247
279
|
exports.getBackendForLocation = getBackendForLocation;
|
|
280
|
+
async function promptExistingBackend(projectId, promptMessage) {
|
|
281
|
+
const { backends } = await apphosting.listBackends(projectId, "-");
|
|
282
|
+
const backendId = await (0, prompt_1.search)({
|
|
283
|
+
message: promptMessage,
|
|
284
|
+
source: (input = "") => {
|
|
285
|
+
return new Promise((resolve) => resolve([
|
|
286
|
+
...fuzzy
|
|
287
|
+
.filter(input, backends, {
|
|
288
|
+
extract: (backend) => apphosting.parseBackendName(backend.name).id,
|
|
289
|
+
})
|
|
290
|
+
.map((result) => {
|
|
291
|
+
return {
|
|
292
|
+
name: apphosting.parseBackendName(result.original.name).id,
|
|
293
|
+
value: apphosting.parseBackendName(result.original.name).id,
|
|
294
|
+
};
|
|
295
|
+
}),
|
|
296
|
+
]));
|
|
297
|
+
},
|
|
298
|
+
});
|
|
299
|
+
return backendId;
|
|
300
|
+
}
|
|
301
|
+
exports.promptExistingBackend = promptExistingBackend;
|
|
248
302
|
async function chooseBackends(projectId, backendId, chooseBackendPrompt, force) {
|
|
249
303
|
let { unreachable, backends } = await apphosting.listBackends(projectId, "-");
|
|
250
304
|
if (unreachable && unreachable.length !== 0) {
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getGitHubCommit = exports.getGitHubBranch = exports.fetchRepositoryCloneUris = exports.listAppHostingConnections = exports.getOrCreateRepository = exports.getOrCreateConnection = exports.createConnection = exports.ensureSecretManagerAdminGrant = exports.promptGitHubBranch = exports.getOrCreateOauthConnection = exports.listValidInstallations = exports.promptGitHubInstallation = exports.getConnectionForInstallation = exports.linkGitHubRepository = exports.
|
|
3
|
+
exports.getGitHubCommit = exports.getGitHubBranch = exports.fetchRepositoryCloneUris = exports.listAppHostingConnections = exports.getOrCreateRepository = exports.getOrCreateConnection = exports.createConnection = exports.ensureSecretManagerAdminGrant = exports.promptGitHubBranch = exports.getOrCreateOauthConnection = exports.listValidInstallations = exports.promptGitHubInstallation = exports.getConnectionForInstallation = exports.linkGitHubRepository = exports.getOrCreateFullyInstalledGithubConnection = exports.generateConnectionId = exports.generateRepositoryId = exports.extractRepoSlugFromUri = exports.parseConnectionName = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const devConnect = require("../gcp/devConnect");
|
|
6
6
|
const rm = require("../gcp/resourceManager");
|
|
@@ -14,7 +14,6 @@ const fuzzy = require("fuzzy");
|
|
|
14
14
|
const apiv2_1 = require("../apiv2");
|
|
15
15
|
const githubApiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.githubApiOrigin)(), auth: false });
|
|
16
16
|
const APPHOSTING_CONN_PATTERN = /.+\/apphosting-github-conn-.+$/;
|
|
17
|
-
const APPHOSTING_OAUTH_CONN_NAME = "firebase-app-hosting-github-oauth";
|
|
18
17
|
const CONNECTION_NAME_REGEX = /^projects\/(?<projectId>[^\/]+)\/locations\/(?<location>[^\/]+)\/connections\/(?<id>[^\/]+)$/;
|
|
19
18
|
function parseConnectionName(name) {
|
|
20
19
|
const match = CONNECTION_NAME_REGEX.exec(name);
|
|
@@ -48,13 +47,14 @@ function generateRepositoryId(remoteUri) {
|
|
|
48
47
|
return (_a = extractRepoSlugFromUri(remoteUri)) === null || _a === void 0 ? void 0 : _a.replaceAll("/", "-");
|
|
49
48
|
}
|
|
50
49
|
exports.generateRepositoryId = generateRepositoryId;
|
|
51
|
-
|
|
50
|
+
const generateConnectionId = () => {
|
|
52
51
|
const randomHash = Math.random().toString(36).slice(6);
|
|
53
52
|
return `apphosting-github-conn-${randomHash}`;
|
|
54
|
-
}
|
|
53
|
+
};
|
|
54
|
+
exports.generateConnectionId = generateConnectionId;
|
|
55
55
|
const ADD_ACCOUNT_CHOICE = "@ADD_ACCOUNT";
|
|
56
56
|
const MANAGE_INSTALLATION_CHOICE = "@MANAGE_INSTALLATION";
|
|
57
|
-
async function
|
|
57
|
+
async function getOrCreateFullyInstalledGithubConnection(projectId, location, createConnectionId) {
|
|
58
58
|
utils.logBullet(clc.bold(`${clc.yellow("===")} Import a GitHub repository`));
|
|
59
59
|
if (createConnectionId) {
|
|
60
60
|
try {
|
|
@@ -87,15 +87,15 @@ async function getOrCreateGithubConnectionWithSentinel(projectId, location, crea
|
|
|
87
87
|
}
|
|
88
88
|
}
|
|
89
89
|
if (!createConnectionId) {
|
|
90
|
-
createConnectionId = generateConnectionId();
|
|
90
|
+
createConnectionId = (0, exports.generateConnectionId)();
|
|
91
91
|
}
|
|
92
92
|
const connection = await createFullyInstalledConnection(projectId, location, createConnectionId, oauthConn, installationId);
|
|
93
93
|
return connection;
|
|
94
94
|
}
|
|
95
|
-
exports.
|
|
95
|
+
exports.getOrCreateFullyInstalledGithubConnection = getOrCreateFullyInstalledGithubConnection;
|
|
96
96
|
async function linkGitHubRepository(projectId, location, createConnectionId) {
|
|
97
97
|
var _a, _b;
|
|
98
|
-
const connection = await
|
|
98
|
+
const connection = await getOrCreateFullyInstalledGithubConnection(projectId, location, createConnectionId);
|
|
99
99
|
let repoCloneUri;
|
|
100
100
|
do {
|
|
101
101
|
if (repoCloneUri === MANAGE_INSTALLATION_CHOICE) {
|
|
@@ -192,18 +192,12 @@ async function listValidInstallations(projectId, location, connection) {
|
|
|
192
192
|
exports.listValidInstallations = listValidInstallations;
|
|
193
193
|
async function getOrCreateOauthConnection(projectId, location) {
|
|
194
194
|
let conn;
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
catch (err) {
|
|
199
|
-
if (err.status === 404) {
|
|
200
|
-
await ensureSecretManagerAdminGrant(projectId);
|
|
201
|
-
conn = await createConnection(projectId, location, APPHOSTING_OAUTH_CONN_NAME);
|
|
202
|
-
}
|
|
203
|
-
else {
|
|
204
|
-
throw err;
|
|
205
|
-
}
|
|
195
|
+
const completedConnections = await listAppHostingConnections(projectId, location);
|
|
196
|
+
if (completedConnections.length > 0) {
|
|
197
|
+
return completedConnections[0];
|
|
206
198
|
}
|
|
199
|
+
await ensureSecretManagerAdminGrant(projectId);
|
|
200
|
+
conn = await createConnection(projectId, location, (0, exports.generateConnectionId)());
|
|
207
201
|
while (conn.installationState.stage === "PENDING_USER_OAUTH") {
|
|
208
202
|
utils.logBullet("Please authorize the Firebase GitHub app by visiting this url:");
|
|
209
203
|
const { url, cleanup } = await utils.openInBrowserPopup(conn.installationState.actionUri, "Authorize the GitHub app");
|
|
@@ -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,22 @@ 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
|
+
(0, logger_1.useFileLogger)();
|
|
30
37
|
const activeFeatures = (values.only || "")
|
|
31
38
|
.split(",")
|
|
32
39
|
.filter((f) => types_1.SERVER_FEATURES.includes(f));
|
|
33
|
-
const server = new index_1.FirebaseMcpServer({
|
|
40
|
+
const server = new index_1.FirebaseMcpServer({
|
|
41
|
+
activeFeatures,
|
|
42
|
+
projectRoot: values.dir ? (0, path_1.resolve)(values.dir) : undefined,
|
|
43
|
+
});
|
|
34
44
|
await server.start();
|
|
35
45
|
if (process.stdin.isTTY)
|
|
36
46
|
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
|
@@ -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;
|