firebase-tools 14.20.0 → 14.21.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/appUtils.js +2 -1
- package/lib/command.js +5 -9
- package/lib/commands/dataconnect-sdk-generate.js +66 -11
- package/lib/commands/firestore-databases-clone.js +99 -0
- package/lib/commands/functions-secrets-set.js +19 -1
- package/lib/commands/index.js +1 -0
- package/lib/commands/init.js +12 -8
- package/lib/commands/internaltesting-functions-discover.js +1 -3
- package/lib/dataconnect/provisionCloudSql.js +3 -2
- package/lib/deploy/extensions/prepare.js +3 -1
- package/lib/deploy/functions/checkIam.js +1 -1
- package/lib/deploy/functions/functionsDeployHelper.js +8 -7
- package/lib/deploy/functions/params.js +17 -3
- package/lib/deploy/functions/prepare.js +9 -6
- package/lib/detectProjectRoot.js +1 -1
- package/lib/emulator/downloadableEmulatorInfo.json +18 -18
- package/lib/emulator/hubExport.js +5 -0
- package/lib/experiments.js +0 -7
- package/lib/firestore/api.js +15 -0
- package/lib/firestore/util.js +22 -1
- package/lib/functions/projectConfig.js +5 -1
- package/lib/functions/secrets.js +14 -1
- package/lib/init/features/dataconnect/index.js +21 -20
- package/lib/init/features/dataconnect/sdk.js +44 -21
- package/lib/init/features/functions/index.js +1 -0
- package/lib/init/index.js +2 -2
- package/lib/mcp/index.js +46 -18
- package/lib/mcp/prompt.js +4 -1
- package/lib/mcp/prompts/core/consult.js +1 -1
- package/lib/mcp/prompts/core/deploy.js +1 -1
- package/lib/mcp/prompts/core/init.js +1 -1
- package/lib/mcp/prompts/crashlytics/connect.js +1 -1
- package/lib/mcp/prompts/dataconnect/schema.js +1 -1
- package/lib/mcp/prompts/index.js +20 -10
- package/lib/mcp/tool.js +17 -2
- package/lib/mcp/tools/apphosting/fetch_logs.js +1 -1
- package/lib/mcp/tools/apphosting/list_backends.js +1 -1
- package/lib/mcp/tools/auth/get_users.js +1 -1
- package/lib/mcp/tools/auth/set_sms_region_policy.js +1 -1
- package/lib/mcp/tools/auth/update_user.js +1 -1
- package/lib/mcp/tools/core/create_android_sha.js +1 -1
- package/lib/mcp/tools/core/create_app.js +1 -1
- package/lib/mcp/tools/core/create_project.js +1 -1
- package/lib/mcp/tools/core/get_environment.js +1 -1
- package/lib/mcp/tools/core/get_project.js +1 -1
- package/lib/mcp/tools/core/get_sdk_config.js +1 -1
- package/lib/mcp/tools/core/get_security_rules.js +1 -1
- package/lib/mcp/tools/core/init.js +3 -2
- package/lib/mcp/tools/core/list_apps.js +1 -1
- package/lib/mcp/tools/core/list_projects.js +1 -1
- package/lib/mcp/tools/core/login.js +1 -1
- package/lib/mcp/tools/core/logout.js +1 -1
- package/lib/mcp/tools/core/read_resources.js +1 -1
- package/lib/mcp/tools/core/update_environment.js +1 -1
- package/lib/mcp/tools/core/validate_security_rules.js +15 -1
- package/lib/mcp/tools/crashlytics/events.js +3 -3
- package/lib/mcp/tools/crashlytics/issues.js +3 -3
- package/lib/mcp/tools/crashlytics/notes.js +4 -4
- package/lib/mcp/tools/crashlytics/reports.js +6 -6
- package/lib/mcp/tools/dataconnect/compile.js +1 -1
- package/lib/mcp/tools/dataconnect/execute.js +1 -1
- package/lib/mcp/tools/dataconnect/generate_operation.js +1 -1
- package/lib/mcp/tools/dataconnect/generate_schema.js +1 -1
- package/lib/mcp/tools/dataconnect/list_services.js +1 -1
- package/lib/mcp/tools/firestore/delete_document.js +1 -1
- package/lib/mcp/tools/firestore/get_documents.js +1 -1
- package/lib/mcp/tools/firestore/list_collections.js +1 -1
- package/lib/mcp/tools/firestore/query_collection.js +1 -1
- package/lib/mcp/tools/functions/get_logs.js +1 -1
- package/lib/mcp/tools/index.js +14 -4
- package/lib/mcp/tools/messaging/send_message.js +1 -1
- package/lib/mcp/tools/realtime_database/get_data.js +1 -1
- package/lib/mcp/tools/realtime_database/set_data.js +1 -1
- package/lib/mcp/tools/remoteconfig/get_template.js +1 -1
- package/lib/mcp/tools/remoteconfig/update_template.js +1 -1
- package/lib/mcp/tools/storage/get_download_url.js +1 -1
- package/lib/mcp/util/availability.js +22 -0
- package/lib/mcp/util/crashlytics/availability.js +81 -0
- package/lib/mcp/util.js +26 -6
- package/package.json +1 -1
- package/schema/firebase-config.json +3 -0
|
@@ -8,7 +8,7 @@ const url = require("node:url");
|
|
|
8
8
|
const apiv2_1 = require("../../../apiv2");
|
|
9
9
|
const consumers_1 = require("node:stream/consumers");
|
|
10
10
|
const node_path_1 = require("node:path");
|
|
11
|
-
exports.get_data = (0, tool_1.tool)({
|
|
11
|
+
exports.get_data = (0, tool_1.tool)("database", {
|
|
12
12
|
name: "get_data",
|
|
13
13
|
description: "Use this to retrieve data from the specified location in a Firebase Realtime Database.",
|
|
14
14
|
inputSchema: zod_1.z.object({
|
|
@@ -9,7 +9,7 @@ const utils_1 = require("../../../utils");
|
|
|
9
9
|
const apiv2_1 = require("../../../apiv2");
|
|
10
10
|
const error_1 = require("../../../error");
|
|
11
11
|
const node_path_1 = require("node:path");
|
|
12
|
-
exports.set_data = (0, tool_1.tool)({
|
|
12
|
+
exports.set_data = (0, tool_1.tool)("database", {
|
|
13
13
|
name: "set_data",
|
|
14
14
|
description: "Use this to write data to the specified location in a Firebase Realtime Database.",
|
|
15
15
|
inputSchema: zod_1.z.object({
|
|
@@ -5,7 +5,7 @@ const zod_1 = require("zod");
|
|
|
5
5
|
const tool_1 = require("../../tool");
|
|
6
6
|
const util_1 = require("../../util");
|
|
7
7
|
const get_1 = require("../../../remoteconfig/get");
|
|
8
|
-
exports.get_template = (0, tool_1.tool)({
|
|
8
|
+
exports.get_template = (0, tool_1.tool)("remoteconfig", {
|
|
9
9
|
name: "get_template",
|
|
10
10
|
description: "Use this to retrieve the specified Firebase Remote Config template from the currently active Firebase Project.",
|
|
11
11
|
inputSchema: zod_1.z.object({
|
|
@@ -6,7 +6,7 @@ const tool_1 = require("../../tool");
|
|
|
6
6
|
const util_1 = require("../../util");
|
|
7
7
|
const publish_1 = require("../../../remoteconfig/publish");
|
|
8
8
|
const rollback_1 = require("../../../remoteconfig/rollback");
|
|
9
|
-
exports.update_template = (0, tool_1.tool)({
|
|
9
|
+
exports.update_template = (0, tool_1.tool)("remoteconfig", {
|
|
10
10
|
name: "update_template",
|
|
11
11
|
description: "Use this to publish a new remote config template or roll back to a specific version for the project",
|
|
12
12
|
inputSchema: zod_1.z
|
|
@@ -6,7 +6,7 @@ const tool_1 = require("../../tool");
|
|
|
6
6
|
const util_1 = require("../../util");
|
|
7
7
|
const storage_1 = require("../../../gcp/storage");
|
|
8
8
|
const types_1 = require("../../../emulator/types");
|
|
9
|
-
exports.get_object_download_url = (0, tool_1.tool)({
|
|
9
|
+
exports.get_object_download_url = (0, tool_1.tool)("storage", {
|
|
10
10
|
name: "get_object_download_url",
|
|
11
11
|
description: "Use this to retrieve the download URL for an object in a Cloud Storage for Firebase bucket.",
|
|
12
12
|
inputSchema: zod_1.z.object({
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.getDefaultFeatureAvailabilityCheck = void 0;
|
|
4
|
+
const util_1 = require("../util");
|
|
5
|
+
const availability_1 = require("./crashlytics/availability");
|
|
6
|
+
const DEFAULT_AVAILABILITY_CHECKS = {
|
|
7
|
+
core: async (ctx) => true,
|
|
8
|
+
firestore: (ctx) => (0, util_1.checkFeatureActive)("firestore", ctx.projectId, { config: ctx.config }),
|
|
9
|
+
storage: (ctx) => (0, util_1.checkFeatureActive)("storage", ctx.projectId, { config: ctx.config }),
|
|
10
|
+
dataconnect: (ctx) => (0, util_1.checkFeatureActive)("dataconnect", ctx.projectId, { config: ctx.config }),
|
|
11
|
+
auth: (ctx) => (0, util_1.checkFeatureActive)("auth", ctx.projectId, { config: ctx.config }),
|
|
12
|
+
messaging: (ctx) => (0, util_1.checkFeatureActive)("messaging", ctx.projectId, { config: ctx.config }),
|
|
13
|
+
functions: (ctx) => (0, util_1.checkFeatureActive)("functions", ctx.projectId, { config: ctx.config }),
|
|
14
|
+
remoteconfig: (ctx) => (0, util_1.checkFeatureActive)("remoteconfig", ctx.projectId, { config: ctx.config }),
|
|
15
|
+
crashlytics: availability_1.isCrashlyticsAvailable,
|
|
16
|
+
apphosting: (ctx) => (0, util_1.checkFeatureActive)("apphosting", ctx.projectId, { config: ctx.config }),
|
|
17
|
+
database: (ctx) => (0, util_1.checkFeatureActive)("database", ctx.projectId, { config: ctx.config }),
|
|
18
|
+
};
|
|
19
|
+
function getDefaultFeatureAvailabilityCheck(feature) {
|
|
20
|
+
return DEFAULT_AVAILABILITY_CHECKS[feature];
|
|
21
|
+
}
|
|
22
|
+
exports.getDefaultFeatureAvailabilityCheck = getDefaultFeatureAvailabilityCheck;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.isCrashlyticsAvailable = void 0;
|
|
4
|
+
const appUtils_1 = require("../../../appUtils");
|
|
5
|
+
const fs = require("fs-extra");
|
|
6
|
+
const path = require("path");
|
|
7
|
+
async function isCrashlyticsAvailable(ctx) {
|
|
8
|
+
ctx.host.log("debug", `Looking for whether crashlytics is installed...`);
|
|
9
|
+
return await isCrashlyticsInstalled(ctx);
|
|
10
|
+
}
|
|
11
|
+
exports.isCrashlyticsAvailable = isCrashlyticsAvailable;
|
|
12
|
+
async function isCrashlyticsInstalled(ctx) {
|
|
13
|
+
const host = ctx.host;
|
|
14
|
+
const projectDir = ctx.config.projectDir;
|
|
15
|
+
const platforms = await (0, appUtils_1.getPlatformsFromFolder)(projectDir);
|
|
16
|
+
if (!platforms.includes(appUtils_1.Platform.FLUTTER) &&
|
|
17
|
+
!platforms.includes(appUtils_1.Platform.ANDROID) &&
|
|
18
|
+
!platforms.includes(appUtils_1.Platform.IOS)) {
|
|
19
|
+
host.log("debug", `Found no supported Crashlytics platforms.`);
|
|
20
|
+
return false;
|
|
21
|
+
}
|
|
22
|
+
if (platforms.includes(appUtils_1.Platform.FLUTTER) && (await flutterAppUsesCrashlytics(projectDir))) {
|
|
23
|
+
host.log("debug", `Found Flutter app using Crashlytics`);
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
if (platforms.includes(appUtils_1.Platform.ANDROID) && (await androidAppUsesCrashlytics(projectDir))) {
|
|
27
|
+
host.log("debug", `Found Android app using Crashlytics`);
|
|
28
|
+
return true;
|
|
29
|
+
}
|
|
30
|
+
if (platforms.includes(appUtils_1.Platform.IOS) && (await iosAppUsesCrashlytics(projectDir))) {
|
|
31
|
+
host.log("debug", `Found iOS app using Crashlytics`);
|
|
32
|
+
return true;
|
|
33
|
+
}
|
|
34
|
+
host.log("debug", `Found supported platforms ${JSON.stringify(platforms)}, but did not find a Crashlytics dependency.`);
|
|
35
|
+
return false;
|
|
36
|
+
}
|
|
37
|
+
async function androidAppUsesCrashlytics(appPath) {
|
|
38
|
+
const buildGradleFiles = await (0, appUtils_1.detectFiles)(appPath, "build.gradle*");
|
|
39
|
+
const crashlyticsPattern = /(firebase-crashlytics|firebase\.crashlytics|com\.google\.firebase\.crashlytics)/;
|
|
40
|
+
for (const file of buildGradleFiles) {
|
|
41
|
+
const content = await fs.readFile(path.join(appPath, file), "utf8");
|
|
42
|
+
if (crashlyticsPattern.test(content)) {
|
|
43
|
+
return true;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
return false;
|
|
47
|
+
}
|
|
48
|
+
async function iosAppUsesCrashlytics(appPath) {
|
|
49
|
+
const podfiles = await (0, appUtils_1.detectFiles)(appPath, "Podfile");
|
|
50
|
+
for (const file of podfiles) {
|
|
51
|
+
const content = await fs.readFile(path.join(appPath, file), "utf8");
|
|
52
|
+
if (content.includes("Crashlytics")) {
|
|
53
|
+
return true;
|
|
54
|
+
}
|
|
55
|
+
}
|
|
56
|
+
const swiftPackageFiles = await (0, appUtils_1.detectFiles)(appPath, "Package.swift");
|
|
57
|
+
for (const file of swiftPackageFiles) {
|
|
58
|
+
const content = await fs.readFile(path.join(appPath, file), "utf8");
|
|
59
|
+
if (content.includes("Crashlytics")) {
|
|
60
|
+
return true;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
const cartFiles = await (0, appUtils_1.detectFiles)(appPath, "Cartfile*");
|
|
64
|
+
for (const file of cartFiles) {
|
|
65
|
+
const content = await fs.readFile(path.join(appPath, file), "utf8");
|
|
66
|
+
if (content.includes("Crashlytics")) {
|
|
67
|
+
return true;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
return false;
|
|
71
|
+
}
|
|
72
|
+
async function flutterAppUsesCrashlytics(appPath) {
|
|
73
|
+
const pubspecFiles = await (0, appUtils_1.detectFiles)(appPath, "pubspec.yaml");
|
|
74
|
+
for (const file of pubspecFiles) {
|
|
75
|
+
const content = await fs.readFile(path.join(appPath, file), "utf8");
|
|
76
|
+
if (content.includes("firebase_crashlytics")) {
|
|
77
|
+
return true;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
return false;
|
|
81
|
+
}
|
package/lib/mcp/util.js
CHANGED
|
@@ -52,17 +52,37 @@ const SERVER_FEATURE_APIS = {
|
|
|
52
52
|
apphosting: (0, api_1.apphostingOrigin)(),
|
|
53
53
|
database: (0, api_1.realtimeOrigin)(),
|
|
54
54
|
};
|
|
55
|
+
const DETECTED_API_FEATURES = {
|
|
56
|
+
core: undefined,
|
|
57
|
+
firestore: undefined,
|
|
58
|
+
storage: undefined,
|
|
59
|
+
dataconnect: undefined,
|
|
60
|
+
auth: undefined,
|
|
61
|
+
messaging: undefined,
|
|
62
|
+
functions: undefined,
|
|
63
|
+
remoteconfig: undefined,
|
|
64
|
+
crashlytics: undefined,
|
|
65
|
+
apphosting: undefined,
|
|
66
|
+
database: undefined,
|
|
67
|
+
};
|
|
55
68
|
async function checkFeatureActive(feature, projectId, options) {
|
|
56
69
|
var _a;
|
|
57
70
|
if (feature in (((_a = options === null || options === void 0 ? void 0 : options.config) === null || _a === void 0 ? void 0 : _a.data) || {}))
|
|
58
71
|
return true;
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
72
|
+
if (DETECTED_API_FEATURES[feature] !== undefined)
|
|
73
|
+
return DETECTED_API_FEATURES[feature];
|
|
74
|
+
if (projectId) {
|
|
75
|
+
try {
|
|
76
|
+
const isActive = await (0, timeout_1.timeoutFallback)((0, ensureApiEnabled_1.check)(projectId, SERVER_FEATURE_APIS[feature], "", true), true, 3000);
|
|
77
|
+
DETECTED_API_FEATURES[feature] = isActive;
|
|
78
|
+
return isActive;
|
|
79
|
+
}
|
|
80
|
+
catch (e) {
|
|
81
|
+
DETECTED_API_FEATURES[feature] = true;
|
|
82
|
+
return true;
|
|
83
|
+
}
|
|
65
84
|
}
|
|
85
|
+
DETECTED_API_FEATURES[feature] = false;
|
|
66
86
|
return false;
|
|
67
87
|
}
|
|
68
88
|
exports.checkFeatureActive = checkFeatureActive;
|
package/package.json
CHANGED