firebase-tools 14.15.2 → 14.16.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.
Files changed (47) hide show
  1. package/lib/commands/firestore-bulkdelete.js +73 -0
  2. package/lib/commands/firestore-operations-cancel.js +44 -0
  3. package/lib/commands/firestore-operations-describe.js +29 -0
  4. package/lib/commands/firestore-operations-list.js +29 -0
  5. package/lib/commands/firestore-utils.js +15 -0
  6. package/lib/commands/functions-config-export.js +5 -2
  7. package/lib/commands/index.js +5 -0
  8. package/lib/config.js +16 -4
  9. package/lib/dataconnect/ensureApis.js +3 -3
  10. package/lib/deploy/functions/deploy.js +4 -3
  11. package/lib/deploy/functions/prepare.js +8 -6
  12. package/lib/emulator/commandUtils.js +7 -1
  13. package/lib/emulator/controller.js +15 -31
  14. package/lib/emulator/downloadableEmulatorInfo.json +18 -18
  15. package/lib/emulator/hub.js +7 -1
  16. package/lib/extensions/runtimes/common.js +3 -2
  17. package/lib/firestore/api.js +45 -0
  18. package/lib/firestore/pretty-print.js +23 -0
  19. package/lib/functions/projectConfig.js +69 -9
  20. package/lib/gcp/cloudfunctions.js +1 -6
  21. package/lib/gcp/cloudfunctionsv2.js +1 -9
  22. package/lib/gcp/cloudsql/cloudsqladmin.js +2 -2
  23. package/lib/init/features/dataconnect/create_app.js +7 -2
  24. package/lib/init/features/dataconnect/index.js +72 -56
  25. package/lib/init/features/dataconnect/sdk.js +23 -10
  26. package/lib/mcp/errors.js +2 -10
  27. package/lib/mcp/index.js +0 -3
  28. package/lib/mcp/prompts/crashlytics/connect.js +114 -0
  29. package/lib/mcp/prompts/crashlytics/index.js +2 -3
  30. package/lib/mcp/tools/auth/disable_user.js +1 -1
  31. package/lib/mcp/tools/auth/get_user.js +9 -2
  32. package/lib/mcp/tools/core/index.js +4 -0
  33. package/lib/mcp/tools/core/init.js +11 -2
  34. package/lib/mcp/tools/core/login.js +46 -0
  35. package/lib/mcp/tools/core/logout.js +62 -0
  36. package/lib/mcp/tools/dataconnect/index.js +2 -2
  37. package/lib/mcp/tools/dataconnect/{info.js → list_services.js} +5 -5
  38. package/lib/mcp/util.js +1 -17
  39. package/lib/serve/functions.js +4 -3
  40. package/lib/unzip.js +13 -0
  41. package/lib/utils.js +17 -1
  42. package/package.json +1 -1
  43. package/schema/firebase-config.json +160 -59
  44. package/lib/mcp/prompts/crashlytics/common.js +0 -10
  45. package/lib/mcp/prompts/crashlytics/fix_issue.js +0 -89
  46. package/lib/mcp/prompts/crashlytics/prioritize_issues.js +0 -79
  47. package/lib/mcp/tools/database/set_rules.js +0 -41
@@ -2,6 +2,18 @@
2
2
  "$schema": "http://json-schema.org/draft-07/schema#",
3
3
  "additionalProperties": false,
4
4
  "definitions": {
5
+ "ActiveRuntime": {
6
+ "enum": [
7
+ "nodejs18",
8
+ "nodejs20",
9
+ "nodejs22",
10
+ "python310",
11
+ "python311",
12
+ "python312",
13
+ "python313"
14
+ ],
15
+ "type": "string"
16
+ },
5
17
  "DataConnectSingle": {
6
18
  "additionalProperties": false,
7
19
  "properties": {
@@ -242,66 +254,14 @@
242
254
  "type": "object"
243
255
  },
244
256
  "FunctionConfig": {
245
- "additionalProperties": false,
246
- "properties": {
247
- "codebase": {
248
- "type": "string"
249
- },
250
- "configDir": {
251
- "type": "string"
252
- },
253
- "ignore": {
254
- "items": {
255
- "type": "string"
256
- },
257
- "type": "array"
258
- },
259
- "postdeploy": {
260
- "anyOf": [
261
- {
262
- "items": {
263
- "type": "string"
264
- },
265
- "type": "array"
266
- },
267
- {
268
- "type": "string"
269
- }
270
- ]
271
- },
272
- "predeploy": {
273
- "anyOf": [
274
- {
275
- "items": {
276
- "type": "string"
277
- },
278
- "type": "array"
279
- },
280
- {
281
- "type": "string"
282
- }
283
- ]
284
- },
285
- "prefix": {
286
- "type": "string"
287
- },
288
- "runtime": {
289
- "enum": [
290
- "nodejs18",
291
- "nodejs20",
292
- "nodejs22",
293
- "python310",
294
- "python311",
295
- "python312",
296
- "python313"
297
- ],
298
- "type": "string"
257
+ "anyOf": [
258
+ {
259
+ "$ref": "#/definitions/LocalFunctionConfig"
299
260
  },
300
- "source": {
301
- "type": "string"
261
+ {
262
+ "$ref": "#/definitions/RemoteFunctionConfig"
302
263
  }
303
- },
304
- "type": "object"
264
+ ]
305
265
  },
306
266
  "HostingHeaders": {
307
267
  "anyOf": [
@@ -903,6 +863,71 @@
903
863
  },
904
864
  "type": "object"
905
865
  },
866
+ "LocalFunctionConfig": {
867
+ "additionalProperties": false,
868
+ "properties": {
869
+ "codebase": {
870
+ "type": "string"
871
+ },
872
+ "configDir": {
873
+ "type": "string"
874
+ },
875
+ "ignore": {
876
+ "items": {
877
+ "type": "string"
878
+ },
879
+ "type": "array"
880
+ },
881
+ "postdeploy": {
882
+ "anyOf": [
883
+ {
884
+ "items": {
885
+ "type": "string"
886
+ },
887
+ "type": "array"
888
+ },
889
+ {
890
+ "type": "string"
891
+ }
892
+ ]
893
+ },
894
+ "predeploy": {
895
+ "anyOf": [
896
+ {
897
+ "items": {
898
+ "type": "string"
899
+ },
900
+ "type": "array"
901
+ },
902
+ {
903
+ "type": "string"
904
+ }
905
+ ]
906
+ },
907
+ "prefix": {
908
+ "type": "string"
909
+ },
910
+ "runtime": {
911
+ "enum": [
912
+ "nodejs18",
913
+ "nodejs20",
914
+ "nodejs22",
915
+ "python310",
916
+ "python311",
917
+ "python312",
918
+ "python313"
919
+ ],
920
+ "type": "string"
921
+ },
922
+ "source": {
923
+ "type": "string"
924
+ }
925
+ },
926
+ "required": [
927
+ "source"
928
+ ],
929
+ "type": "object"
930
+ },
906
931
  "Record<string,string>": {
907
932
  "additionalProperties": false,
908
933
  "type": "object"
@@ -945,6 +970,79 @@
945
970
  ],
946
971
  "type": "object"
947
972
  },
973
+ "RemoteFunctionConfig": {
974
+ "additionalProperties": false,
975
+ "properties": {
976
+ "codebase": {
977
+ "type": "string"
978
+ },
979
+ "configDir": {
980
+ "type": "string"
981
+ },
982
+ "ignore": {
983
+ "items": {
984
+ "type": "string"
985
+ },
986
+ "type": "array"
987
+ },
988
+ "postdeploy": {
989
+ "anyOf": [
990
+ {
991
+ "items": {
992
+ "type": "string"
993
+ },
994
+ "type": "array"
995
+ },
996
+ {
997
+ "type": "string"
998
+ }
999
+ ]
1000
+ },
1001
+ "predeploy": {
1002
+ "anyOf": [
1003
+ {
1004
+ "items": {
1005
+ "type": "string"
1006
+ },
1007
+ "type": "array"
1008
+ },
1009
+ {
1010
+ "type": "string"
1011
+ }
1012
+ ]
1013
+ },
1014
+ "prefix": {
1015
+ "type": "string"
1016
+ },
1017
+ "remoteSource": {
1018
+ "additionalProperties": false,
1019
+ "properties": {
1020
+ "dir": {
1021
+ "type": "string"
1022
+ },
1023
+ "ref": {
1024
+ "type": "string"
1025
+ },
1026
+ "repository": {
1027
+ "type": "string"
1028
+ }
1029
+ },
1030
+ "required": [
1031
+ "ref",
1032
+ "repository"
1033
+ ],
1034
+ "type": "object"
1035
+ },
1036
+ "runtime": {
1037
+ "$ref": "#/definitions/ActiveRuntime"
1038
+ }
1039
+ },
1040
+ "required": [
1041
+ "remoteSource",
1042
+ "runtime"
1043
+ ],
1044
+ "type": "object"
1045
+ },
948
1046
  "StorageSingle": {
949
1047
  "additionalProperties": false,
950
1048
  "properties": {
@@ -1487,7 +1585,10 @@
1487
1585
  "functions": {
1488
1586
  "anyOf": [
1489
1587
  {
1490
- "$ref": "#/definitions/FunctionConfig"
1588
+ "$ref": "#/definitions/LocalFunctionConfig"
1589
+ },
1590
+ {
1591
+ "$ref": "#/definitions/RemoteFunctionConfig"
1491
1592
  },
1492
1593
  {
1493
1594
  "items": {
@@ -1,10 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getAppIdInstruction = exports.ACTIVE_USER_INSTRUCTION = void 0;
4
- exports.ACTIVE_USER_INSTRUCTION = "If the Firbase 'Active user' is set to <NONE>, instruct the user to run `firebase login` before continuing. You will know that the user is not logged in if we have nothing in the 'Active user' field.";
5
- const getAppIdInstruction = (index) => `If there is no active app id, then do the following:
6
- ${index}a. If this is an Android app, read the mobilesdk_app_id value specified in the google-services.json file. If there are multiple files or multiple app ids in single file. Ask the user to disambiguate.
7
- ${index}b. If this is an iOS app, read the GOOGLE_APP_ID from GoogleService-Info.plist file. If there are multiple files or multiple app ids in single file. Ask the user to disambiguate.
8
- ${index}c. If you can't find either of the above, ask the user for the app id.
9
- `;
10
- exports.getAppIdInstruction = getAppIdInstruction;
@@ -1,89 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.fix_issue = void 0;
4
- const prompt_1 = require("../../prompt");
5
- const common_1 = require("./common");
6
- const APP_ID_INSTRUCTION = (0, common_1.getAppIdInstruction)(2);
7
- exports.fix_issue = (0, prompt_1.prompt)({
8
- name: "fix_issue",
9
- omitPrefix: false,
10
- description: "Fix a Crashlytics issue",
11
- arguments: [
12
- {
13
- name: "app_id",
14
- description: "A Firebase app id.",
15
- required: false,
16
- },
17
- {
18
- name: "issue_id",
19
- description: "A Crashlytics issue id.",
20
- required: true,
21
- },
22
- ],
23
- annotations: {
24
- title: "Prioritize Crashlytics Issues",
25
- },
26
- }, async ({ app_id, issue_id }, { accountEmail }) => {
27
- return [
28
- {
29
- role: "user",
30
- content: {
31
- type: "text",
32
- text: `
33
- Your goal is to fix a specific issue from Crashlytics.
34
-
35
- Active user: ${accountEmail || "<NONE>"}
36
- Active app: ${app_id || "<NONE>"}
37
- Issue id: ${issue_id}
38
-
39
- ## Required information
40
-
41
- ## Required information
42
-
43
- Before fetching and prioritizing issues, secure the following information:
44
-
45
- First, and this is INCREDIBLY IMPORTANT, verify the active user. IT IS SO IMPORTANT THAT YOU DO THIS FIRST. NO TOOL CALL WILL WORK WITHOUT IT. ${common_1.ACTIVE_USER_INSTRUCTION}
46
- Then, verify the app id. ${APP_ID_INSTRUCTION}
47
- Finally, verify the issue id is not null or empty.
48
-
49
- All are required to successfully investigate and fix an issue.
50
-
51
- ## Steps
52
-
53
- 1. Make sure you have a good understanding of the code structure and where different functionality exists
54
- 2. Use the 'crashlytics_get_issue_details' tool to get more context on the issue.
55
- 3. Use the 'crashlytics_get_sample_crash_for_issue' tool to get 3 example crashes for this issue.
56
- 4. Read the files that exist in the stack trace of the issue to understand the crash deeply.
57
- 5. Determine the root cause of the crash.
58
- 6. Write out a plan using the following criteria:
59
- 6a. Write out a description of the issue and including
60
- * A brief description of the cause of the issue
61
- * A determination of your level of confidence in the cause of the issue
62
- * A determination of which library is at fault, this codebase or a dependent library
63
- * A determination for how complex the fix will be
64
- 6b. The plan should include relevant files to change
65
- 6c. The plan should include a test plan to verify the fix
66
- 6d. Use the following format for the plan:
67
-
68
- **Cause**
69
- <A description of the cause of the issue>
70
-
71
- **Confidence**: <one of "not at all confident", "somewhat confident", "confident", "very confident">
72
- **Fault**: <a determination of whether this code base is at fault or a dependent library is at fault>
73
- **Complexity**: <one of "simple", "moderately simple", "moderately hard", "hard", "oof, I don't know where to start">
74
-
75
- **Fix**
76
- <A plan for how to fix the issue>
77
-
78
- **Test**
79
- <a plan for how to test that the issue has been fixed an protect against regressions>
80
- 7. Present the plan to the user and get approval before making the change.
81
- 8. Fix the issue.
82
- 8a. Be mindful of API contracts and do not add fields to resources without a clear way to populate those fields
83
- 8b. If there is not enough information in the crash report to find a root cause, describe why you cannot fix the issue instead of making a guess.
84
- 9. Ask the developer if they would like you to test the fix for them.
85
- `.trim(),
86
- },
87
- },
88
- ];
89
- });
@@ -1,79 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.prioritize_issues = void 0;
4
- const prompt_1 = require("../../prompt");
5
- const common_1 = require("./common");
6
- const APP_ID_INSTRUCTION = (0, common_1.getAppIdInstruction)(2);
7
- exports.prioritize_issues = (0, prompt_1.prompt)({
8
- name: "prioritize_issues",
9
- omitPrefix: false,
10
- description: "Fetch and prioritize issues from Crashlytics.",
11
- arguments: [
12
- {
13
- name: "app_id",
14
- description: "AppId for which the issues list should be fetched.",
15
- required: false,
16
- },
17
- {
18
- name: "issue_count",
19
- description: "The number of issues that should be returned in the final list. Defaults to 5.",
20
- required: false,
21
- },
22
- {
23
- name: "prompt",
24
- description: "Any additional instructions you wish to provide about issue prioritization.",
25
- required: false,
26
- },
27
- ],
28
- annotations: {
29
- title: "Prioritize Crashlytics Issues",
30
- },
31
- }, async ({ app_id, prompt, issue_count }, { accountEmail }) => {
32
- return [
33
- {
34
- role: "user",
35
- content: {
36
- type: "text",
37
- text: `
38
- Your goal is to prioritize issues from Crashlytics and return the top ${issue_count || 5} issues based on the criteria below.
39
-
40
- Active user: ${accountEmail || "<NONE>"}
41
- Active app: ${app_id || "<NONE>"}
42
-
43
- ## User Instructions
44
-
45
- ${prompt || "<the user didn't supply specific instructions>"}
46
-
47
- ## Required information
48
-
49
- Before fetching and prioritizing issues, secure the following information:
50
-
51
- First, and this is INCREDIBLY IMPORTANT, verify the active user. IT IS SO IMPORTANT THAT YOU DO THIS FIRST. NO TOOL CALL WILL WORK WITHOUT IT. ${common_1.ACTIVE_USER_INSTRUCTION}
52
- Then, verify the app id. ${APP_ID_INSTRUCTION}
53
-
54
- Both pieces of information are required to successfully prioritize issues.
55
-
56
- ## Steps
57
-
58
- Follow the steps below taking note of any user instructions provided above.
59
-
60
- 1. Use the 'crashlytics_list_top_issues' tool to fetch up to 20 issues.
61
- 2. Use the 'crashlytics_list_top_versions' tool to fetch the top versions for this app.
62
- 3. If the user instructions include statements about prioritization, use those instructions.
63
- 4. If the user instructions do not include statements about prioritization, then prioritize the returned issues using the following criteria:
64
- 4a. The app versions for the issue include the most recent version of the app.
65
- 4b. The number of users experiencing the issue across variants
66
- 4c. The volume of crashes
67
- 5. Return the top ${issue_count || 5} issue ids, with a brief description of the issue in the following format:
68
- * Issue <issue id>
69
- * <the issue title>
70
- * <the issue subtitle>
71
- * Description: <a discription of the issue based on information from the tool response>
72
- * Rationale: <the reason this issue was prioritized in the way it was>
73
-
74
- The point of this command is to surface information only.
75
- `.trim(),
76
- },
77
- },
78
- ];
79
- });
@@ -1,41 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.validate_rules = void 0;
4
- const zod_1 = require("zod");
5
- const apiv2_1 = require("../../../apiv2");
6
- const tool_1 = require("../../tool");
7
- const util_1 = require("../../util");
8
- const rtdb_1 = require("../../../rtdb");
9
- const error_1 = require("../../../error");
10
- exports.validate_rules = (0, tool_1.tool)({
11
- name: "validate_rules",
12
- description: "Validates an RTDB database's rules",
13
- inputSchema: zod_1.z.object({
14
- databaseUrl: zod_1.z
15
- .string()
16
- .optional()
17
- .describe("connect to the database at url. If omitted, use default database instance <project>-default-rtdb.firebaseio.com. Can point to emulator URL (e.g. localhost:6000/<instance>)"),
18
- rules: zod_1.z
19
- .string()
20
- .describe('The rules object, as a string (ex: {".read": false, ".write": false})'),
21
- }),
22
- annotations: {
23
- title: "Validate Realtime Database rules",
24
- idempotentHint: true,
25
- },
26
- _meta: {
27
- requiresAuth: true,
28
- requiresProject: false,
29
- },
30
- }, async ({ databaseUrl, rules }, { projectId, host }) => {
31
- const dbUrl = databaseUrl !== null && databaseUrl !== void 0 ? databaseUrl : `https://${projectId}-default-rtdb.us-central1.firebasedatabase.app`;
32
- const client = new apiv2_1.Client({ urlPrefix: dbUrl });
33
- try {
34
- await (0, rtdb_1.updateRulesWithClient)(client, rules, { dryRun: true });
35
- }
36
- catch (e) {
37
- host.logger.debug(`failed to update rules at url ${dbUrl}`);
38
- return (0, util_1.mcpError)((0, error_1.getErrMsg)(e));
39
- }
40
- return (0, util_1.toContent)("the inputted rules are valid!");
41
- });