firebase-tools 14.12.1 → 14.14.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/README.md +1 -1
- package/lib/commands/dataconnect-services-list.js +5 -5
- package/lib/commands/dataconnect-sql-grant.js +5 -0
- package/lib/commands/dataconnect-sql-setup.js +1 -3
- package/lib/crashlytics/getIssueDetails.js +41 -0
- package/lib/crashlytics/getSampleCrash.js +48 -0
- package/lib/dataconnect/client.js +23 -15
- package/lib/dataconnect/ensureApis.js +5 -9
- package/lib/dataconnect/errors.js +7 -1
- package/lib/dataconnect/fileUtils.js +5 -6
- package/lib/dataconnect/freeTrial.js +16 -39
- package/lib/dataconnect/provisionCloudSql.js +67 -70
- package/lib/dataconnect/schemaMigration.js +222 -170
- package/lib/deploy/dataconnect/deploy.js +9 -11
- package/lib/deploy/dataconnect/prepare.js +7 -10
- package/lib/deploy/dataconnect/release.js +42 -30
- package/lib/deploy/functions/backend.js +8 -2
- package/lib/deploy/functions/build.js +23 -1
- package/lib/deploy/functions/ensure.js +1 -1
- package/lib/deploy/functions/functionsDeployHelper.js +8 -1
- package/lib/deploy/functions/prepare.js +8 -4
- package/lib/deploy/functions/pricing.js +12 -5
- package/lib/deploy/functions/release/fabricator.js +25 -3
- package/lib/emulator/controller.js +7 -3
- package/lib/emulator/downloadableEmulatorInfo.json +18 -18
- package/lib/emulator/functionsEmulator.js +11 -1
- package/lib/experiments.js +4 -0
- package/lib/extensions/extensionsHelper.js +4 -15
- package/lib/extensions/utils.js +1 -12
- package/lib/firestore/api.js +25 -11
- package/lib/firestore/pretty-print.js +7 -0
- package/lib/functional.js +7 -1
- package/lib/functions/env.js +19 -15
- package/lib/functions/projectConfig.js +25 -2
- package/lib/functions/secrets.js +3 -0
- package/lib/gcp/cloudfunctionsv2.js +3 -31
- package/lib/gcp/cloudscheduler.js +1 -1
- package/lib/gcp/cloudsql/cloudsqladmin.js +2 -14
- package/lib/gcp/cloudsql/connect.js +3 -2
- package/lib/gcp/cloudsql/permissionsSetup.js +23 -16
- package/lib/gcp/k8s.js +32 -0
- package/lib/gcp/runv2.js +178 -0
- package/lib/gemini/fdcExperience.js +5 -3
- package/lib/init/features/dataconnect/index.js +266 -162
- package/lib/init/features/dataconnect/sdk.js +36 -20
- package/lib/init/features/project.js +4 -0
- package/lib/management/studio.js +1 -1
- package/lib/mcp/tools/core/init.js +7 -6
- package/lib/mcp/tools/crashlytics/get_issue_details.js +33 -0
- package/lib/mcp/tools/crashlytics/get_sample_crash.js +43 -0
- package/lib/mcp/tools/crashlytics/index.js +7 -1
- package/lib/mcp/tools/crashlytics/list_top_issues.js +2 -1
- package/lib/rtdb.js +1 -1
- package/package.json +1 -1
- package/schema/firebase-config.json +6 -0
- package/lib/extensions/resolveSource.js +0 -24
package/lib/gcp/runv2.js
ADDED
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serviceFromEndpoint = exports.endpointFromService = exports.FIREBASE_FUNCTION_METADTA_ANNOTATION = exports.FUNCTION_SIGNATURE_TYPE_ENV = exports.FUNCTION_TARGET_ENV = exports.FUNCTION_ID_ANNOTATION = exports.FUNCTION_TARGET_ANNOTATION = exports.TRIGGER_TYPE_ANNOTATION = exports.CLIENT_NAME_LABEL = exports.RUNTIME_LABEL = exports.updateService = exports.submitBuild = exports.API_VERSION = void 0;
|
|
4
|
+
const apiv2_1 = require("../apiv2");
|
|
5
|
+
const error_1 = require("../error");
|
|
6
|
+
const api_1 = require("../api");
|
|
7
|
+
const proto = require("./proto");
|
|
8
|
+
const metaprogramming_1 = require("../metaprogramming");
|
|
9
|
+
const operation_poller_1 = require("../operation-poller");
|
|
10
|
+
const backend = require("../deploy/functions/backend");
|
|
11
|
+
const constants_1 = require("../functions/constants");
|
|
12
|
+
const k8s_1 = require("./k8s");
|
|
13
|
+
const supported_1 = require("../deploy/functions/runtimes/supported");
|
|
14
|
+
const __1 = require("..");
|
|
15
|
+
const functional_1 = require("../functional");
|
|
16
|
+
exports.API_VERSION = "v2";
|
|
17
|
+
const client = new apiv2_1.Client({
|
|
18
|
+
urlPrefix: (0, api_1.runOrigin)(),
|
|
19
|
+
auth: true,
|
|
20
|
+
apiVersion: exports.API_VERSION,
|
|
21
|
+
});
|
|
22
|
+
(0, metaprogramming_1.assertImplements)();
|
|
23
|
+
async function submitBuild(projectId, location, build) {
|
|
24
|
+
const res = await client.post(`/projects/${projectId}/locations/${location}/builds`, build);
|
|
25
|
+
if (res.status !== 200) {
|
|
26
|
+
throw new error_1.FirebaseError(`Failed to submit build: ${res.status} ${res.body}`);
|
|
27
|
+
}
|
|
28
|
+
await (0, operation_poller_1.pollOperation)({
|
|
29
|
+
apiOrigin: (0, api_1.cloudbuildOrigin)(),
|
|
30
|
+
apiVersion: "v1",
|
|
31
|
+
operationResourceName: res.body.buildOperation,
|
|
32
|
+
});
|
|
33
|
+
}
|
|
34
|
+
exports.submitBuild = submitBuild;
|
|
35
|
+
async function updateService(service) {
|
|
36
|
+
const fieldMask = proto.fieldMasks(service, "labels", "annotations", "tags");
|
|
37
|
+
fieldMask.push("template.revision");
|
|
38
|
+
const res = await client.post(service.name, service, {
|
|
39
|
+
queryParams: {
|
|
40
|
+
updateMask: fieldMask.join(","),
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
const svc = await (0, operation_poller_1.pollOperation)({
|
|
44
|
+
apiOrigin: (0, api_1.runOrigin)(),
|
|
45
|
+
apiVersion: exports.API_VERSION,
|
|
46
|
+
operationResourceName: res.body.name,
|
|
47
|
+
});
|
|
48
|
+
return svc;
|
|
49
|
+
}
|
|
50
|
+
exports.updateService = updateService;
|
|
51
|
+
function functionNameToServiceName(id) {
|
|
52
|
+
return id.toLowerCase().replace(/_/g, "-");
|
|
53
|
+
}
|
|
54
|
+
exports.RUNTIME_LABEL = "goog-cloudfunctions-runtime";
|
|
55
|
+
exports.CLIENT_NAME_LABEL = "goog-managed-by";
|
|
56
|
+
exports.TRIGGER_TYPE_ANNOTATION = "cloudfunctions.googleapis.com/trigger-type";
|
|
57
|
+
exports.FUNCTION_TARGET_ANNOTATION = "run.googleapis.com/build-function-target";
|
|
58
|
+
exports.FUNCTION_ID_ANNOTATION = "cloudfunctions.googleapis.com/function-id";
|
|
59
|
+
exports.FUNCTION_TARGET_ENV = "FUNCTION_TARGET";
|
|
60
|
+
exports.FUNCTION_SIGNATURE_TYPE_ENV = "FUNCTION_SIGNATURE_TYPE";
|
|
61
|
+
exports.FIREBASE_FUNCTION_METADTA_ANNOTATION = "firebase-functions-metadata";
|
|
62
|
+
function endpointFromService(service) {
|
|
63
|
+
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
64
|
+
const [, project, , location, , svcId] = service.name.split("/");
|
|
65
|
+
const metadata = JSON.parse(((_a = service.annotations) === null || _a === void 0 ? void 0 : _a[exports.FIREBASE_FUNCTION_METADTA_ANNOTATION]) || "{}");
|
|
66
|
+
const [env, secretEnv] = (0, functional_1.partition)(service.template.containers[0].env || [], (e) => "value" in e);
|
|
67
|
+
const id = metadata.functionId ||
|
|
68
|
+
((_b = service.annotations) === null || _b === void 0 ? void 0 : _b[exports.FUNCTION_ID_ANNOTATION]) ||
|
|
69
|
+
((_c = service.annotations) === null || _c === void 0 ? void 0 : _c[exports.FUNCTION_TARGET_ANNOTATION]) ||
|
|
70
|
+
((_d = env.find((e) => e.name === exports.FUNCTION_TARGET_ENV)) === null || _d === void 0 ? void 0 : _d.value) ||
|
|
71
|
+
svcId;
|
|
72
|
+
const memory = (0, k8s_1.mebibytes)(service.template.containers[0].resources.limits.memory);
|
|
73
|
+
if (!backend.isValidMemoryOption(memory)) {
|
|
74
|
+
__1.logger.debug("Converting a service to an endpoint with an invalid memory option", memory);
|
|
75
|
+
}
|
|
76
|
+
const cpu = Number(service.template.containers[0].resources.limits.cpu);
|
|
77
|
+
const endpoint = {
|
|
78
|
+
platform: ((_e = service.labels) === null || _e === void 0 ? void 0 : _e[exports.CLIENT_NAME_LABEL]) === "cloud-functions" ? "gcfv2" : "run",
|
|
79
|
+
id,
|
|
80
|
+
project,
|
|
81
|
+
labels: service.labels || {},
|
|
82
|
+
region: location,
|
|
83
|
+
runtime: ((_f = service.labels) === null || _f === void 0 ? void 0 : _f[exports.RUNTIME_LABEL]) || (0, supported_1.latest)("nodejs"),
|
|
84
|
+
availableMemoryMb: memory,
|
|
85
|
+
cpu: cpu,
|
|
86
|
+
entryPoint: ((_g = env.find((e) => e.name === exports.FUNCTION_TARGET_ENV)) === null || _g === void 0 ? void 0 : _g.value) ||
|
|
87
|
+
((_h = service.annotations) === null || _h === void 0 ? void 0 : _h[exports.FUNCTION_TARGET_ANNOTATION]) ||
|
|
88
|
+
((_j = service.annotations) === null || _j === void 0 ? void 0 : _j[exports.FUNCTION_ID_ANNOTATION]) ||
|
|
89
|
+
id,
|
|
90
|
+
httpsTrigger: {},
|
|
91
|
+
};
|
|
92
|
+
proto.renameIfPresent(endpoint, service.template, "concurrency", "containerConcurrency");
|
|
93
|
+
proto.renameIfPresent(endpoint, service.labels || {}, "codebase", constants_1.CODEBASE_LABEL);
|
|
94
|
+
proto.renameIfPresent(endpoint, service.scaling || {}, "minInstances", "minInstanceCount");
|
|
95
|
+
proto.renameIfPresent(endpoint, service.scaling || {}, "maxInstances", "maxInstanceCount");
|
|
96
|
+
endpoint.environmentVariables = env.reduce((acc, e) => {
|
|
97
|
+
acc[e.name] = e.value;
|
|
98
|
+
return acc;
|
|
99
|
+
}, {});
|
|
100
|
+
endpoint.secretEnvironmentVariables = secretEnv.map((e) => {
|
|
101
|
+
const [, projectId, , secret] = e.valueSource.secretKeyRef.secret.split("/");
|
|
102
|
+
return {
|
|
103
|
+
key: e.name,
|
|
104
|
+
projectId,
|
|
105
|
+
secret,
|
|
106
|
+
version: e.valueSource.secretKeyRef.version || "latest",
|
|
107
|
+
};
|
|
108
|
+
});
|
|
109
|
+
return endpoint;
|
|
110
|
+
}
|
|
111
|
+
exports.endpointFromService = endpointFromService;
|
|
112
|
+
function serviceFromEndpoint(endpoint, image) {
|
|
113
|
+
const labels = Object.assign(Object.assign({}, endpoint.labels), { [exports.RUNTIME_LABEL]: endpoint.runtime, [exports.CLIENT_NAME_LABEL]: "firebase-functions" });
|
|
114
|
+
delete labels["deployment-tool"];
|
|
115
|
+
if (endpoint.codebase) {
|
|
116
|
+
labels[constants_1.CODEBASE_LABEL] = endpoint.codebase;
|
|
117
|
+
}
|
|
118
|
+
const annotations = {
|
|
119
|
+
[exports.FIREBASE_FUNCTION_METADTA_ANNOTATION]: JSON.stringify({
|
|
120
|
+
functionId: endpoint.id,
|
|
121
|
+
}),
|
|
122
|
+
};
|
|
123
|
+
const template = {
|
|
124
|
+
containers: [
|
|
125
|
+
{
|
|
126
|
+
name: "worker",
|
|
127
|
+
image,
|
|
128
|
+
env: [
|
|
129
|
+
...Object.entries(endpoint.environmentVariables || {}).map(([name, value]) => ({
|
|
130
|
+
name,
|
|
131
|
+
value,
|
|
132
|
+
})),
|
|
133
|
+
...(endpoint.secretEnvironmentVariables || []).map((secret) => ({
|
|
134
|
+
name: secret.key,
|
|
135
|
+
valueSource: {
|
|
136
|
+
secretKeyRef: {
|
|
137
|
+
secret: secret.secret,
|
|
138
|
+
version: secret.version,
|
|
139
|
+
},
|
|
140
|
+
},
|
|
141
|
+
})),
|
|
142
|
+
{
|
|
143
|
+
name: exports.FUNCTION_TARGET_ENV,
|
|
144
|
+
value: endpoint.entryPoint,
|
|
145
|
+
},
|
|
146
|
+
{
|
|
147
|
+
name: exports.FUNCTION_SIGNATURE_TYPE_ENV,
|
|
148
|
+
value: backend.isEventTriggered(endpoint) ? "cloudevent" : "http",
|
|
149
|
+
},
|
|
150
|
+
],
|
|
151
|
+
resources: {
|
|
152
|
+
limits: {
|
|
153
|
+
cpu: String(endpoint.cpu || 1),
|
|
154
|
+
memory: `${endpoint.availableMemoryMb || 256}Mi`,
|
|
155
|
+
},
|
|
156
|
+
cpuIdle: true,
|
|
157
|
+
startupCpuBoost: true,
|
|
158
|
+
},
|
|
159
|
+
},
|
|
160
|
+
],
|
|
161
|
+
containerConcurrency: endpoint.concurrency || backend.DEFAULT_CONCURRENCY,
|
|
162
|
+
};
|
|
163
|
+
proto.renameIfPresent(template, endpoint, "containerConcurrency", "concurrency");
|
|
164
|
+
const service = {
|
|
165
|
+
name: `projects/${endpoint.project}/locations/${endpoint.region}/services/${functionNameToServiceName(endpoint.id)}`,
|
|
166
|
+
labels,
|
|
167
|
+
annotations,
|
|
168
|
+
template,
|
|
169
|
+
client: "cli-firebase",
|
|
170
|
+
};
|
|
171
|
+
if (endpoint.minInstances || endpoint.maxInstances) {
|
|
172
|
+
service.scaling = {};
|
|
173
|
+
proto.renameIfPresent(service.scaling, endpoint, "minInstanceCount", "minInstances");
|
|
174
|
+
proto.renameIfPresent(service.scaling, endpoint, "maxInstanceCount", "maxInstances");
|
|
175
|
+
}
|
|
176
|
+
return service;
|
|
177
|
+
}
|
|
178
|
+
exports.serviceFromEndpoint = serviceFromEndpoint;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.extractCodeBlock = exports.generateOperation = exports.chatWithFirebase = exports.generateSchema = void 0;
|
|
3
|
+
exports.extractCodeBlock = exports.generateOperation = exports.chatWithFirebase = exports.generateSchema = exports.PROMPT_GENERATE_SEED_DATA = exports.PROMPT_GENERATE_CONNECTOR = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
6
|
const error_1 = require("../error");
|
|
@@ -9,6 +9,8 @@ const SCHEMA_GENERATOR_EXPERIENCE = "/appeco/firebase/fdc-schema-generator";
|
|
|
9
9
|
const GEMINI_IN_FIREBASE_EXPERIENCE = "/appeco/firebase/firebase-chat/free";
|
|
10
10
|
const OPERATION_GENERATION_EXPERIENCE = "/appeco/firebase/fdc-query-generator";
|
|
11
11
|
const FIREBASE_CHAT_REQUEST_CONTEXT_TYPE_NAME = "type.googleapis.com/google.cloud.cloudaicompanion.v1main.FirebaseChatRequestContext";
|
|
12
|
+
exports.PROMPT_GENERATE_CONNECTOR = "Create 4 operations for an app using the instance schema with proper authentication.";
|
|
13
|
+
exports.PROMPT_GENERATE_SEED_DATA = "Create a mutation to populate the database with some seed data.";
|
|
12
14
|
async function generateSchema(prompt, project, chatHistory = []) {
|
|
13
15
|
const res = await apiClient.post(`/v1beta/projects/${project}/locations/global/instances/default:completeTask`, {
|
|
14
16
|
input: { messages: [...chatHistory, { content: prompt, author: "USER" }] },
|
|
@@ -16,7 +18,7 @@ async function generateSchema(prompt, project, chatHistory = []) {
|
|
|
16
18
|
experience: SCHEMA_GENERATOR_EXPERIENCE,
|
|
17
19
|
},
|
|
18
20
|
});
|
|
19
|
-
return res.body.output.messages[0].content;
|
|
21
|
+
return extractCodeBlock(res.body.output.messages[0].content);
|
|
20
22
|
}
|
|
21
23
|
exports.generateSchema = generateSchema;
|
|
22
24
|
async function chatWithFirebase(prompt, project, chatHistory = []) {
|
|
@@ -42,7 +44,7 @@ async function generateOperation(prompt, service, project, chatHistory = []) {
|
|
|
42
44
|
},
|
|
43
45
|
},
|
|
44
46
|
});
|
|
45
|
-
return res.body.output.messages[0].content;
|
|
47
|
+
return extractCodeBlock(res.body.output.messages[0].content);
|
|
46
48
|
}
|
|
47
49
|
exports.generateOperation = generateOperation;
|
|
48
50
|
function extractCodeBlock(text) {
|