firebase-tools 14.23.0 → 14.24.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 +32 -13
- package/lib/commands/dataconnect-sdk-generate.js +3 -2
- package/lib/deploy/functions/services/dataconnect.js +14 -0
- package/lib/deploy/functions/services/index.js +11 -0
- package/lib/emulator/downloadableEmulatorInfo.json +26 -18
- package/lib/emulator/downloadableEmulators.js +59 -47
- package/lib/functions/events/v2.js +2 -1
- package/lib/init/features/dataconnect/sdk.js +18 -0
- package/lib/mcp/tools/crashlytics/events.js +92 -9
- package/package.json +2 -2
- package/schema/connector-yaml.json +30 -0
package/lib/appUtils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.detectFiles = exports.extractAppIdentifiersAndroid = exports.extractAppIdentifierIos = exports.extractAppIdentifiersFlutter = exports.detectApps = exports.getPlatformsFromFolder = exports.appDescription = exports.Framework = exports.Platform = void 0;
|
|
3
|
+
exports.detectFiles = exports.extractAppIdentifiersAndroid = exports.extractAppIdentifierIos = exports.extractAppIdentifiersFlutter = exports.getAllDepsFromPackageJson = exports.detectApps = exports.getPlatformsFromFolder = exports.appDescription = exports.Framework = exports.Platform = void 0;
|
|
4
4
|
const fs = require("fs-extra");
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const glob_1 = require("glob");
|
|
@@ -10,6 +10,7 @@ var Platform;
|
|
|
10
10
|
Platform["WEB"] = "WEB";
|
|
11
11
|
Platform["IOS"] = "IOS";
|
|
12
12
|
Platform["FLUTTER"] = "FLUTTER";
|
|
13
|
+
Platform["ADMIN_NODE"] = "ADMIN_NODE";
|
|
13
14
|
})(Platform = exports.Platform || (exports.Platform = {}));
|
|
14
15
|
var Framework;
|
|
15
16
|
(function (Framework) {
|
|
@@ -30,7 +31,9 @@ async function detectApps(dirPath) {
|
|
|
30
31
|
const pubSpecYamlFiles = await detectFiles(dirPath, "pubspec.yaml");
|
|
31
32
|
const srcMainFolders = await detectFiles(dirPath, "src/main/");
|
|
32
33
|
const xCodeProjects = await detectFiles(dirPath, "*.xcodeproj/");
|
|
33
|
-
const
|
|
34
|
+
const adminAndWebApps = (await Promise.all(packageJsonFiles.map((p) => packageJsonToAdminOrWebApp(dirPath, p)))).flat();
|
|
35
|
+
console.log("packageJsonFiles", packageJsonFiles);
|
|
36
|
+
console.log("adminAndWebApps", adminAndWebApps);
|
|
34
37
|
const flutterAppPromises = await Promise.all(pubSpecYamlFiles.map((f) => processFlutterDir(dirPath, f)));
|
|
35
38
|
const flutterApps = flutterAppPromises.flat();
|
|
36
39
|
const androidAppPromises = await Promise.all(srcMainFolders.map((f) => processAndroidDir(dirPath, f)));
|
|
@@ -41,7 +44,7 @@ async function detectApps(dirPath) {
|
|
|
41
44
|
const iosApps = iosAppPromises
|
|
42
45
|
.flat()
|
|
43
46
|
.filter((a) => !flutterApps.some((f) => isPathInside(f.directory, a.directory)));
|
|
44
|
-
return [...
|
|
47
|
+
return [...flutterApps, ...androidApps, ...iosApps, ...adminAndWebApps];
|
|
45
48
|
}
|
|
46
49
|
exports.detectApps = detectApps;
|
|
47
50
|
async function processIosDir(dirPath, filePath) {
|
|
@@ -108,14 +111,33 @@ function isPathInside(parent, child) {
|
|
|
108
111
|
const relativePath = path.relative(parent, child);
|
|
109
112
|
return !relativePath.startsWith(`..`);
|
|
110
113
|
}
|
|
111
|
-
|
|
114
|
+
function getAllDepsFromPackageJson(packageJson) {
|
|
115
|
+
var _a, _b;
|
|
116
|
+
const devDependencies = Object.keys((_a = packageJson.devDependencies) !== null && _a !== void 0 ? _a : {});
|
|
117
|
+
const dependencies = Object.keys((_b = packageJson.dependencies) !== null && _b !== void 0 ? _b : {});
|
|
118
|
+
const allDeps = Array.from(new Set([...devDependencies, ...dependencies]));
|
|
119
|
+
return allDeps;
|
|
120
|
+
}
|
|
121
|
+
exports.getAllDepsFromPackageJson = getAllDepsFromPackageJson;
|
|
122
|
+
async function packageJsonToAdminOrWebApp(dirPath, packageJsonFile) {
|
|
112
123
|
const fullPath = path.join(dirPath, packageJsonFile);
|
|
113
124
|
const packageJson = JSON.parse((await fs.readFile(fullPath)).toString());
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
125
|
+
const allDeps = getAllDepsFromPackageJson(packageJson);
|
|
126
|
+
const detectedApps = [];
|
|
127
|
+
if (allDeps.includes("firebase-admin") || allDeps.includes("firebase-functions")) {
|
|
128
|
+
detectedApps.push({
|
|
129
|
+
platform: Platform.ADMIN_NODE,
|
|
130
|
+
directory: path.dirname(packageJsonFile),
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
if (allDeps.includes("firebase") || detectedApps.length === 0) {
|
|
134
|
+
detectedApps.push({
|
|
135
|
+
platform: Platform.WEB,
|
|
136
|
+
directory: path.dirname(packageJsonFile),
|
|
137
|
+
frameworks: getFrameworksFromPackageJson(packageJson),
|
|
138
|
+
});
|
|
139
|
+
}
|
|
140
|
+
return detectedApps;
|
|
119
141
|
}
|
|
120
142
|
const WEB_FRAMEWORKS = Object.values(Framework);
|
|
121
143
|
const WEB_FRAMEWORKS_SIGNALS = {
|
|
@@ -148,10 +170,7 @@ async function detectAppIdsForPlatform(dirPath, platform) {
|
|
|
148
170
|
return allAppIds.flat();
|
|
149
171
|
}
|
|
150
172
|
function getFrameworksFromPackageJson(packageJson) {
|
|
151
|
-
|
|
152
|
-
const devDependencies = Object.keys((_a = packageJson.devDependencies) !== null && _a !== void 0 ? _a : {});
|
|
153
|
-
const dependencies = Object.keys((_b = packageJson.dependencies) !== null && _b !== void 0 ? _b : {});
|
|
154
|
-
const allDeps = Array.from(new Set([...devDependencies, ...dependencies]));
|
|
173
|
+
const allDeps = getAllDepsFromPackageJson(packageJson);
|
|
155
174
|
return WEB_FRAMEWORKS.filter((framework) => WEB_FRAMEWORKS_SIGNALS[framework].find((dep) => allDeps.includes(dep)));
|
|
156
175
|
}
|
|
157
176
|
function extractAppIdentifiersFlutter(fileContent) {
|
|
@@ -72,11 +72,12 @@ exports.command = new command_1.Command("dataconnect:sdk:generate")
|
|
|
72
72
|
async function loadAllWithSDKs(projectId, config) {
|
|
73
73
|
const serviceInfos = await (0, load_1.loadAll)(projectId || hub_1.EmulatorHub.MISSING_PROJECT_PLACEHOLDER, config);
|
|
74
74
|
return serviceInfos.filter((serviceInfo) => serviceInfo.connectorInfo.some((c) => {
|
|
75
|
-
var _a, _b, _c, _d;
|
|
75
|
+
var _a, _b, _c, _d, _e;
|
|
76
76
|
return (((_a = c.connectorYaml.generate) === null || _a === void 0 ? void 0 : _a.javascriptSdk) ||
|
|
77
77
|
((_b = c.connectorYaml.generate) === null || _b === void 0 ? void 0 : _b.kotlinSdk) ||
|
|
78
78
|
((_c = c.connectorYaml.generate) === null || _c === void 0 ? void 0 : _c.swiftSdk) ||
|
|
79
|
-
((_d = c.connectorYaml.generate) === null || _d === void 0 ? void 0 : _d.dartSdk)
|
|
79
|
+
((_d = c.connectorYaml.generate) === null || _d === void 0 ? void 0 : _d.dartSdk) ||
|
|
80
|
+
((_e = c.connectorYaml.generate) === null || _e === void 0 ? void 0 : _e.adminNodeSdk));
|
|
80
81
|
}));
|
|
81
82
|
}
|
|
82
83
|
async function generateSDKsInAll(options, serviceInfosWithSDKs, justRanInit) {
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ensureDataConnectTriggerRegion = void 0;
|
|
4
|
+
const error_1 = require("../../../error");
|
|
5
|
+
function ensureDataConnectTriggerRegion(endpoint) {
|
|
6
|
+
if (!endpoint.eventTrigger.region) {
|
|
7
|
+
endpoint.eventTrigger.region = endpoint.region;
|
|
8
|
+
}
|
|
9
|
+
if (endpoint.eventTrigger.region !== endpoint.region) {
|
|
10
|
+
throw new error_1.FirebaseError("The Firebase Data Connect trigger location must match the function region.");
|
|
11
|
+
}
|
|
12
|
+
return Promise.resolve();
|
|
13
|
+
}
|
|
14
|
+
exports.ensureDataConnectTriggerRegion = ensureDataConnectTriggerRegion;
|
|
@@ -9,6 +9,7 @@ const database_1 = require("./database");
|
|
|
9
9
|
const remoteConfig_1 = require("./remoteConfig");
|
|
10
10
|
const testLab_1 = require("./testLab");
|
|
11
11
|
const firestore_1 = require("./firestore");
|
|
12
|
+
const dataconnect_1 = require("./dataconnect");
|
|
12
13
|
const noop = () => Promise.resolve();
|
|
13
14
|
exports.noop = noop;
|
|
14
15
|
const noopProjectBindings = () => Promise.resolve([]);
|
|
@@ -85,6 +86,15 @@ const firestoreService = {
|
|
|
85
86
|
registerTrigger: exports.noop,
|
|
86
87
|
unregisterTrigger: exports.noop,
|
|
87
88
|
};
|
|
89
|
+
const dataconnectService = {
|
|
90
|
+
name: "dataconnect",
|
|
91
|
+
api: "firebasedataconnect.googleapis.com",
|
|
92
|
+
requiredProjectBindings: exports.noopProjectBindings,
|
|
93
|
+
ensureTriggerRegion: dataconnect_1.ensureDataConnectTriggerRegion,
|
|
94
|
+
validateTrigger: exports.noop,
|
|
95
|
+
registerTrigger: exports.noop,
|
|
96
|
+
unregisterTrigger: exports.noop,
|
|
97
|
+
};
|
|
88
98
|
const EVENT_SERVICE_MAPPING = {
|
|
89
99
|
"google.cloud.pubsub.topic.v1.messagePublished": pubSubService,
|
|
90
100
|
"google.cloud.storage.object.v1.finalized": storageService,
|
|
@@ -110,6 +120,7 @@ const EVENT_SERVICE_MAPPING = {
|
|
|
110
120
|
"google.cloud.firestore.document.v1.created.withAuthContext": firestoreService,
|
|
111
121
|
"google.cloud.firestore.document.v1.updated.withAuthContext": firestoreService,
|
|
112
122
|
"google.cloud.firestore.document.v1.deleted.withAuthContext": firestoreService,
|
|
123
|
+
"google.firebase.dataconnect.connector.v1.mutationExecuted": dataconnectService,
|
|
113
124
|
};
|
|
114
125
|
function serviceForEndpoint(endpoint) {
|
|
115
126
|
if (backend.isEventTriggered(endpoint)) {
|
|
@@ -54,28 +54,36 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "2.
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v2.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
57
|
+
"version": "2.17.0",
|
|
58
|
+
"expectedSize": 29983584,
|
|
59
|
+
"expectedChecksum": "d9a3a5bd575dc24185ad473a440c4738",
|
|
60
|
+
"expectedChecksumSHA256": "da5485e68c7adbf86e3fb2f9ca550e4619f55ae75845009837780fcf16dd05cc",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v2.17.0",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
63
|
+
},
|
|
64
|
+
"darwin_arm64": {
|
|
65
|
+
"version": "2.17.0",
|
|
66
|
+
"expectedSize": 29459746,
|
|
67
|
+
"expectedChecksum": "8362a56419a66507b1aead4630b9033c",
|
|
68
|
+
"expectedChecksumSHA256": "cbb8a3030f69c5aba81d1ef2d64d249f18100915f9738f59b815004b27983dab",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-arm64-v2.17.0",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
63
71
|
},
|
|
64
72
|
"win32": {
|
|
65
|
-
"version": "2.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v2.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
73
|
+
"version": "2.17.0",
|
|
74
|
+
"expectedSize": 30477824,
|
|
75
|
+
"expectedChecksum": "7d8434eee4f3d33cc8ec6c99c6056a77",
|
|
76
|
+
"expectedChecksumSHA256": "051c60be0651be4971409da7ab3a15cdfb693400e9293c89010edcb28016d061",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v2.17.0",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0.exe"
|
|
71
79
|
},
|
|
72
80
|
"linux": {
|
|
73
|
-
"version": "2.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v2.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
81
|
+
"version": "2.17.0",
|
|
82
|
+
"expectedSize": 29905080,
|
|
83
|
+
"expectedChecksum": "ca7003aaee41e3c1261f9655c5f9dd8a",
|
|
84
|
+
"expectedChecksumSHA256": "79efd09f1bd685cbfa0157b2d08e0f6eb085ed82d83b48fabb7d102db6636c6c",
|
|
85
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v2.17.0",
|
|
86
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.17.0"
|
|
79
87
|
}
|
|
80
88
|
}
|
|
81
89
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.isIncomaptibleArchError = exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName =
|
|
3
|
+
exports.isIncomaptibleArchError = exports.start = exports.downloadIfNecessary = exports.stop = exports.getPID = exports.get = exports.getDownloadDetails = exports.requiresJava = exports.handleEmulatorProcessError = exports._getCommand = exports.getLogFileName = void 0;
|
|
4
4
|
const lsofi = require("lsofi");
|
|
5
5
|
const types_1 = require("./types");
|
|
6
6
|
const constants_1 = require("./constants");
|
|
@@ -20,51 +20,63 @@ const emulatorUpdateDetails = require("./downloadableEmulatorInfo.json");
|
|
|
20
20
|
const EMULATOR_INSTANCE_KILL_TIMEOUT = 4000;
|
|
21
21
|
const CACHE_DIR = process.env.FIREBASE_EMULATORS_PATH || path.join(os.homedir(), ".cache", "firebase", "emulators");
|
|
22
22
|
const EMULATOR_UPDATE_DETAILS = emulatorUpdateDetails;
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
}
|
|
23
|
+
function generateDownloadDetails(emulator) {
|
|
24
|
+
const emulatorUiDetails = experiments.isEnabled("emulatoruisnapshot")
|
|
25
|
+
? EMULATOR_UPDATE_DETAILS.ui.snapshot
|
|
26
|
+
: EMULATOR_UPDATE_DETAILS.ui.main;
|
|
27
|
+
const dataconnectDetails = process.platform === "darwin"
|
|
28
|
+
? process.arch === "arm64"
|
|
29
|
+
? EMULATOR_UPDATE_DETAILS.dataconnect.darwin_arm64
|
|
30
|
+
: EMULATOR_UPDATE_DETAILS.dataconnect.darwin
|
|
31
|
+
: process.platform === "win32"
|
|
32
|
+
? EMULATOR_UPDATE_DETAILS.dataconnect.win32
|
|
33
|
+
: EMULATOR_UPDATE_DETAILS.dataconnect.linux;
|
|
34
|
+
switch (emulator) {
|
|
35
|
+
case "database":
|
|
36
|
+
return {
|
|
37
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.database.downloadPathRelativeToCacheDir),
|
|
38
|
+
version: EMULATOR_UPDATE_DETAILS.database.version,
|
|
39
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.database), { cacheDir: CACHE_DIR, namePrefix: "firebase-database-emulator" }),
|
|
40
|
+
};
|
|
41
|
+
case "firestore":
|
|
42
|
+
return {
|
|
43
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.firestore.downloadPathRelativeToCacheDir),
|
|
44
|
+
version: EMULATOR_UPDATE_DETAILS.firestore.version,
|
|
45
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.firestore), { cacheDir: CACHE_DIR, namePrefix: "cloud-firestore-emulator" }),
|
|
46
|
+
};
|
|
47
|
+
case "storage":
|
|
48
|
+
return {
|
|
49
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.storage.downloadPathRelativeToCacheDir),
|
|
50
|
+
version: EMULATOR_UPDATE_DETAILS.storage.version,
|
|
51
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.storage), { cacheDir: CACHE_DIR, namePrefix: "cloud-storage-rules-emulator" }),
|
|
52
|
+
};
|
|
53
|
+
case "ui":
|
|
54
|
+
return {
|
|
55
|
+
version: emulatorUiDetails.version,
|
|
56
|
+
downloadPath: path.join(CACHE_DIR, emulatorUiDetails.downloadPathRelativeToCacheDir),
|
|
57
|
+
unzipDir: path.join(CACHE_DIR, `ui-v${emulatorUiDetails.version}`),
|
|
58
|
+
binaryPath: path.join(CACHE_DIR, emulatorUiDetails.binaryPathRelativeToCacheDir),
|
|
59
|
+
opts: Object.assign(Object.assign({}, emulatorUiDetails), { cacheDir: CACHE_DIR, skipCache: experiments.isEnabled("emulatoruisnapshot"), skipChecksumAndSize: experiments.isEnabled("emulatoruisnapshot"), namePrefix: "ui" }),
|
|
60
|
+
};
|
|
61
|
+
case "pubsub":
|
|
62
|
+
return {
|
|
63
|
+
downloadPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.pubsub.downloadPathRelativeToCacheDir),
|
|
64
|
+
version: EMULATOR_UPDATE_DETAILS.pubsub.version,
|
|
65
|
+
unzipDir: path.join(CACHE_DIR, `pubsub-emulator-${EMULATOR_UPDATE_DETAILS.pubsub.version}`),
|
|
66
|
+
binaryPath: path.join(CACHE_DIR, EMULATOR_UPDATE_DETAILS.pubsub.binaryPathRelativeToCacheDir),
|
|
67
|
+
opts: Object.assign(Object.assign({}, EMULATOR_UPDATE_DETAILS.pubsub), { cacheDir: CACHE_DIR, namePrefix: "pubsub-emulator" }),
|
|
68
|
+
};
|
|
69
|
+
case "dataconnect":
|
|
70
|
+
return {
|
|
71
|
+
downloadPath: path.join(CACHE_DIR, dataconnectDetails.downloadPathRelativeToCacheDir),
|
|
72
|
+
version: dataconnectDetails.version,
|
|
73
|
+
binaryPath: path.join(CACHE_DIR, dataconnectDetails.downloadPathRelativeToCacheDir),
|
|
74
|
+
opts: Object.assign(Object.assign({}, dataconnectDetails), { cacheDir: CACHE_DIR, skipChecksumAndSize: false, namePrefix: "dataconnect-emulator", auth: false }),
|
|
75
|
+
};
|
|
76
|
+
default:
|
|
77
|
+
throw new Error(`Invalid downloadable emulator: ${emulator}`);
|
|
78
|
+
}
|
|
79
|
+
}
|
|
68
80
|
const EmulatorDetails = {
|
|
69
81
|
database: {
|
|
70
82
|
name: types_1.Emulators.DATABASE,
|
|
@@ -318,7 +330,7 @@ async function _runBinary(emulator, command, extraEnv) {
|
|
|
318
330
|
});
|
|
319
331
|
}
|
|
320
332
|
function getDownloadDetails(emulator) {
|
|
321
|
-
const details =
|
|
333
|
+
const details = generateDownloadDetails(emulator);
|
|
322
334
|
const pathOverride = process.env[`${emulator.toUpperCase()}_EMULATOR_BINARY_PATH`];
|
|
323
335
|
if (pathOverride) {
|
|
324
336
|
const logger = emulatorLogger_1.EmulatorLogger.forEmulator(emulator);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.CONVERTABLE_EVENTS = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
3
|
+
exports.CONVERTABLE_EVENTS = exports.DATACONNECT_EVENT = exports.FIREALERTS_EVENT = exports.FIRESTORE_EVENTS = exports.TEST_LAB_EVENT = exports.REMOTE_CONFIG_EVENT = exports.DATABASE_EVENTS = exports.FIREBASE_ALERTS_PUBLISH_EVENT = exports.STORAGE_EVENTS = exports.PUBSUB_PUBLISH_EVENT = void 0;
|
|
4
4
|
exports.PUBSUB_PUBLISH_EVENT = "google.cloud.pubsub.topic.v1.messagePublished";
|
|
5
5
|
exports.STORAGE_EVENTS = [
|
|
6
6
|
"google.cloud.storage.object.v1.finalized",
|
|
@@ -28,6 +28,7 @@ exports.FIRESTORE_EVENTS = [
|
|
|
28
28
|
"google.cloud.firestore.document.v1.deleted.withAuthContext",
|
|
29
29
|
];
|
|
30
30
|
exports.FIREALERTS_EVENT = "google.firebase.firebasealerts.alerts.v1.published";
|
|
31
|
+
exports.DATACONNECT_EVENT = "google.firebase.dataconnect.connector.v1.mutationExecuted";
|
|
31
32
|
exports.CONVERTABLE_EVENTS = {
|
|
32
33
|
"google.cloud.firestore.document.v1.created": "google.cloud.firestore.document.v1.created.withAuthContext",
|
|
33
34
|
"google.cloud.firestore.document.v1.updated": "google.cloud.firestore.document.v1.updated.withAuthContext",
|
|
@@ -145,9 +145,13 @@ function initAppCounters(info) {
|
|
|
145
145
|
num_android_apps: 0,
|
|
146
146
|
num_ios_apps: 0,
|
|
147
147
|
num_flutter_apps: 0,
|
|
148
|
+
num_admin_node_apps: 0,
|
|
148
149
|
};
|
|
149
150
|
for (const app of (_a = info.apps) !== null && _a !== void 0 ? _a : []) {
|
|
150
151
|
switch (app.platform) {
|
|
152
|
+
case appUtils_1.Platform.ADMIN_NODE:
|
|
153
|
+
counts.num_admin_node_apps++;
|
|
154
|
+
break;
|
|
151
155
|
case appUtils_1.Platform.WEB:
|
|
152
156
|
counts.num_web_apps++;
|
|
153
157
|
break;
|
|
@@ -246,6 +250,20 @@ function addSdkGenerateToConnectorYaml(connectorInfo, connectorYaml, app) {
|
|
|
246
250
|
}
|
|
247
251
|
const generate = connectorYaml.generate;
|
|
248
252
|
switch (app.platform) {
|
|
253
|
+
case appUtils_1.Platform.ADMIN_NODE: {
|
|
254
|
+
const adminNodeSdk = {
|
|
255
|
+
outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-admin-generated`)),
|
|
256
|
+
package: `@dataconnect/admin-generated`,
|
|
257
|
+
packageJsonDir: path.relative(connectorDir, appDir),
|
|
258
|
+
};
|
|
259
|
+
if (!(0, lodash_1.isArray)(generate === null || generate === void 0 ? void 0 : generate.adminNodeSdk)) {
|
|
260
|
+
generate.adminNodeSdk = generate.adminNodeSdk ? [generate.adminNodeSdk] : [];
|
|
261
|
+
}
|
|
262
|
+
if (!generate.adminNodeSdk.some((s) => s.outputDir === adminNodeSdk.outputDir)) {
|
|
263
|
+
generate.adminNodeSdk.push(adminNodeSdk);
|
|
264
|
+
}
|
|
265
|
+
break;
|
|
266
|
+
}
|
|
249
267
|
case appUtils_1.Platform.WEB: {
|
|
250
268
|
const javascriptSdk = {
|
|
251
269
|
outputDir: path.relative(connectorDir, path.join(appDir, `src/dataconnect-generated`)),
|
|
@@ -3,16 +3,93 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.batch_get_events = exports.list_events = void 0;
|
|
4
4
|
const zod_1 = require("zod");
|
|
5
5
|
const tool_1 = require("../../tool");
|
|
6
|
+
const js_yaml_1 = require("js-yaml");
|
|
6
7
|
const events_1 = require("../../../crashlytics/events");
|
|
7
8
|
const types_1 = require("../../../crashlytics/types");
|
|
8
9
|
const filters_1 = require("../../../crashlytics/filters");
|
|
9
10
|
const util_1 = require("../../util");
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
11
|
+
const DUMP_OPTIONS = { lineWidth: 200 };
|
|
12
|
+
function formatFrames(origFrames, maxFrames = 20) {
|
|
13
|
+
const frames = origFrames || [];
|
|
14
|
+
const shouldTruncate = frames.length > maxFrames;
|
|
15
|
+
const framesToFormat = shouldTruncate ? frames.slice(0, maxFrames - 1) : frames;
|
|
16
|
+
const formatted = framesToFormat.map((frame) => {
|
|
17
|
+
let line = `at`;
|
|
18
|
+
if (frame.symbol) {
|
|
19
|
+
line += ` ${frame.symbol}`;
|
|
20
|
+
}
|
|
21
|
+
if (frame.file) {
|
|
22
|
+
line += ` (${frame.file}`;
|
|
23
|
+
if (frame.line) {
|
|
24
|
+
line += `:${frame.line}`;
|
|
25
|
+
}
|
|
26
|
+
line += ")";
|
|
27
|
+
}
|
|
28
|
+
return line;
|
|
29
|
+
});
|
|
30
|
+
if (shouldTruncate) {
|
|
31
|
+
formatted.push("... frames omitted ...");
|
|
14
32
|
}
|
|
15
|
-
return
|
|
33
|
+
return formatted;
|
|
34
|
+
}
|
|
35
|
+
function toText(event) {
|
|
36
|
+
var _a, _b;
|
|
37
|
+
const result = {};
|
|
38
|
+
for (const [key, value] of Object.entries(event)) {
|
|
39
|
+
if (key === "logs") {
|
|
40
|
+
const logs = value || [];
|
|
41
|
+
const slicedLogs = logs.length > 100 ? logs.slice(logs.length - 100) : logs;
|
|
42
|
+
const logLines = slicedLogs.map((log) => `[${log.logTime}] ${log.message}`);
|
|
43
|
+
result["logs"] = logLines.join("\n");
|
|
44
|
+
}
|
|
45
|
+
else if (key === "breadcrumbs") {
|
|
46
|
+
const breadcrumbs = value || [];
|
|
47
|
+
const slicedBreadcrumbs = breadcrumbs.length > 10 ? breadcrumbs.slice(-10) : breadcrumbs;
|
|
48
|
+
const breadcrumbLines = slicedBreadcrumbs.map((b) => {
|
|
49
|
+
const paramString = Object.entries(b.params)
|
|
50
|
+
.map(([k, v]) => `${k}: ${v}`)
|
|
51
|
+
.join(", ");
|
|
52
|
+
const params = paramString ? ` { ${paramString} }` : "";
|
|
53
|
+
return `[${b.eventTime}] ${b.title}${params}`;
|
|
54
|
+
});
|
|
55
|
+
result["breadcrumbs"] = breadcrumbLines.join("\n");
|
|
56
|
+
}
|
|
57
|
+
else if (key === "threads") {
|
|
58
|
+
let threads = value || [];
|
|
59
|
+
if (((_a = event.issue) === null || _a === void 0 ? void 0 : _a.errorType) === types_1.ErrorType.FATAL || ((_b = event.issue) === null || _b === void 0 ? void 0 : _b.errorType) === types_1.ErrorType.ANR) {
|
|
60
|
+
threads = threads.filter((t) => t.crashed || t.blamed);
|
|
61
|
+
}
|
|
62
|
+
const threadStrings = threads.map((thread) => {
|
|
63
|
+
const header = `Thread: ${thread.name || thread.threadId || ""}${thread.crashed ? " (crashed)" : ""}`;
|
|
64
|
+
const frameStrings = formatFrames(thread.frames || []);
|
|
65
|
+
return [header, ...frameStrings].join("\n");
|
|
66
|
+
});
|
|
67
|
+
result["threads"] = threadStrings.join("\n\n");
|
|
68
|
+
}
|
|
69
|
+
else if (key === "exceptions") {
|
|
70
|
+
const exceptions = value || [];
|
|
71
|
+
const exceptionStrings = exceptions.map((exception) => {
|
|
72
|
+
const header = exception.nested ? "Caused by: " : "";
|
|
73
|
+
const exceptionHeader = `${header}${exception.type || ""}: ${exception.exceptionMessage || ""}`;
|
|
74
|
+
const frameStrings = formatFrames(exception.frames || []);
|
|
75
|
+
return [exceptionHeader, ...frameStrings].join("\n");
|
|
76
|
+
});
|
|
77
|
+
result["exceptions"] = exceptionStrings.join("\n\n");
|
|
78
|
+
}
|
|
79
|
+
else if (key === "errors") {
|
|
80
|
+
const errors = value || [];
|
|
81
|
+
const errorStrings = errors.map((error) => {
|
|
82
|
+
const header = `Error: ${error.title || "error"}`;
|
|
83
|
+
const frameStrings = formatFrames(error.frames || []);
|
|
84
|
+
return [header, ...frameStrings].join("\n");
|
|
85
|
+
});
|
|
86
|
+
result["errors"] = errorStrings.join("\n\n");
|
|
87
|
+
}
|
|
88
|
+
else {
|
|
89
|
+
result[key] = (0, js_yaml_1.dump)(value, DUMP_OPTIONS);
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
return result;
|
|
16
93
|
}
|
|
17
94
|
exports.list_events = (0, tool_1.tool)("crashlytics", {
|
|
18
95
|
name: "list_events",
|
|
@@ -32,13 +109,16 @@ exports.list_events = (0, tool_1.tool)("crashlytics", {
|
|
|
32
109
|
requiresAuth: true,
|
|
33
110
|
},
|
|
34
111
|
}, async ({ appId, filter, pageSize }) => {
|
|
112
|
+
var _a;
|
|
35
113
|
if (!appId)
|
|
36
114
|
return (0, util_1.mcpError)(`Must specify 'appId' parameter.`);
|
|
37
115
|
if (!filter || (!filter.issueId && !filter.issueVariantId))
|
|
38
116
|
return (0, util_1.mcpError)(`Must specify 'filter.issueId' or 'filter.issueVariantId' parameters.`);
|
|
39
117
|
const response = await (0, events_1.listEvents)(appId, filter, pageSize);
|
|
40
|
-
|
|
41
|
-
return
|
|
118
|
+
const eventsContent = ((_a = response.events) === null || _a === void 0 ? void 0 : _a.map((e) => toText(e))) || [];
|
|
119
|
+
return {
|
|
120
|
+
content: [{ type: "text", text: (0, js_yaml_1.dump)(eventsContent, DUMP_OPTIONS) }],
|
|
121
|
+
};
|
|
42
122
|
});
|
|
43
123
|
exports.batch_get_events = (0, tool_1.tool)("crashlytics", {
|
|
44
124
|
name: "batch_get_events",
|
|
@@ -59,11 +139,14 @@ exports.batch_get_events = (0, tool_1.tool)("crashlytics", {
|
|
|
59
139
|
requiresAuth: true,
|
|
60
140
|
},
|
|
61
141
|
}, async ({ appId, names }) => {
|
|
142
|
+
var _a;
|
|
62
143
|
if (!appId)
|
|
63
144
|
return (0, util_1.mcpError)(`Must specify 'appId' parameter.`);
|
|
64
145
|
if (!names || names.length === 0)
|
|
65
146
|
return (0, util_1.mcpError)(`Must provide event resource names in name parameter.`);
|
|
66
147
|
const response = await (0, events_1.batchGetEvents)(appId, names);
|
|
67
|
-
|
|
68
|
-
return
|
|
148
|
+
const eventsContent = ((_a = response.events) === null || _a === void 0 ? void 0 : _a.map((e) => toText(e))) || [];
|
|
149
|
+
return {
|
|
150
|
+
content: [{ type: "text", text: (0, js_yaml_1.dump)(eventsContent, DUMP_OPTIONS) }],
|
|
151
|
+
};
|
|
69
152
|
});
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "14.
|
|
3
|
+
"version": "14.24.0",
|
|
4
4
|
"description": "Command-Line Interface for Firebase",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -66,7 +66,7 @@
|
|
|
66
66
|
"@electric-sql/pglite": "^0.3.3",
|
|
67
67
|
"@electric-sql/pglite-tools": "^0.2.8",
|
|
68
68
|
"@google-cloud/cloud-sql-connector": "^1.3.3",
|
|
69
|
-
"@google-cloud/pubsub": "^
|
|
69
|
+
"@google-cloud/pubsub": "^5.2.0",
|
|
70
70
|
"@inquirer/prompts": "^7.4.0",
|
|
71
71
|
"@modelcontextprotocol/sdk": "^1.10.2",
|
|
72
72
|
"abort-controller": "^3.0.0",
|
|
@@ -2,6 +2,24 @@
|
|
|
2
2
|
"$schema": "http://json-schema.org/draft-07/schema#",
|
|
3
3
|
"additionalProperties": false,
|
|
4
4
|
"definitions": {
|
|
5
|
+
"adminNodeSdk": {
|
|
6
|
+
"additionalProperties": true,
|
|
7
|
+
"type": "object",
|
|
8
|
+
"properties": {
|
|
9
|
+
"outputDir": {
|
|
10
|
+
"type": "string",
|
|
11
|
+
"description": "Path to the directory where generated files should be written to."
|
|
12
|
+
},
|
|
13
|
+
"package": {
|
|
14
|
+
"type": "string",
|
|
15
|
+
"description": "The package name to use for the generated code."
|
|
16
|
+
},
|
|
17
|
+
"packageJSONDir": {
|
|
18
|
+
"type": "string",
|
|
19
|
+
"description": "The directory containing the package.json to install the generated package in."
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
},
|
|
5
23
|
"javascriptSdk": {
|
|
6
24
|
"additionalProperties": true,
|
|
7
25
|
"type": "object",
|
|
@@ -90,6 +108,18 @@
|
|
|
90
108
|
],
|
|
91
109
|
"description": "Configuration for a generated Javascript SDK"
|
|
92
110
|
},
|
|
111
|
+
"adminNodeSdk": {
|
|
112
|
+
"oneOf": [
|
|
113
|
+
{ "$ref": "#/definitions/adminNodeSdk" },
|
|
114
|
+
{
|
|
115
|
+
"type": "array",
|
|
116
|
+
"items": {
|
|
117
|
+
"$ref": "#/definitions/adminNodeSdk"
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
],
|
|
121
|
+
"description": "Configuration for a generated Admin Node SDK"
|
|
122
|
+
},
|
|
93
123
|
"dartSdk": {
|
|
94
124
|
"oneOf": [
|
|
95
125
|
{ "$ref": "#/definitions/dartSdk" },
|