firebase-tools 14.13.0 → 14.15.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/apphosting/backend.js +40 -15
- package/lib/auth.js +37 -2
- package/lib/commands/apphosting-backends-create.js +8 -5
- package/lib/commands/dataconnect-sdk-generate.js +3 -5
- package/lib/commands/dataconnect-sql-diff.js +2 -2
- package/lib/commands/dataconnect-sql-grant.js +2 -2
- package/lib/commands/dataconnect-sql-migrate.js +2 -2
- package/lib/commands/dataconnect-sql-setup.js +2 -2
- package/lib/commands/dataconnect-sql-shell.js +2 -2
- package/lib/commands/init.js +3 -0
- package/lib/commands/login.js +12 -7
- package/lib/crashlytics/addNote.js +27 -0
- package/lib/crashlytics/deleteNote.js +23 -0
- package/lib/crashlytics/getIssueDetails.js +5 -20
- package/lib/crashlytics/getSampleCrash.js +6 -20
- package/lib/crashlytics/listNotes.js +29 -0
- package/lib/crashlytics/listTopDevices.js +33 -0
- package/lib/crashlytics/listTopIssues.js +8 -23
- package/lib/crashlytics/listTopOperatingSystems.js +32 -0
- package/lib/crashlytics/listTopVersions.js +32 -0
- package/lib/crashlytics/updateIssue.js +35 -0
- package/lib/crashlytics/utils.js +38 -0
- package/lib/dataconnect/appFinder.js +103 -0
- package/lib/dataconnect/errors.js +7 -1
- package/lib/dataconnect/load.js +105 -6
- package/lib/dataconnect/schemaMigration.js +152 -128
- package/lib/deploy/dataconnect/prepare.js +1 -3
- package/lib/deploy/dataconnect/release.js +33 -27
- package/lib/deploy/functions/prepare.js +2 -0
- package/lib/emulator/controller.js +7 -4
- package/lib/emulator/downloadableEmulatorInfo.json +17 -17
- package/lib/emulator/functionsEmulator.js +2 -0
- package/lib/functions/env.js +19 -15
- package/lib/gcp/cloudsql/connect.js +2 -1
- package/lib/gcp/cloudsql/permissionsSetup.js +10 -1
- package/lib/init/features/dataconnect/create_app.js +48 -0
- package/lib/init/features/dataconnect/index.js +20 -31
- package/lib/init/features/dataconnect/sdk.js +218 -161
- package/lib/init/features/index.js +3 -2
- package/lib/init/index.js +5 -1
- package/lib/management/apps.js +3 -3
- package/lib/mcp/prompts/core/deploy.js +51 -8
- package/lib/mcp/prompts/crashlytics/common.js +10 -0
- package/lib/mcp/prompts/crashlytics/fix_issue.js +89 -0
- package/lib/mcp/prompts/crashlytics/index.js +6 -0
- package/lib/mcp/prompts/crashlytics/prioritize_issues.js +79 -0
- package/lib/mcp/prompts/index.js +3 -2
- package/lib/mcp/tools/core/init.js +5 -1
- package/lib/mcp/tools/crashlytics/add_note.js +32 -0
- package/lib/mcp/tools/crashlytics/constants.js +11 -0
- package/lib/mcp/tools/crashlytics/delete_note.js +35 -0
- package/lib/mcp/tools/crashlytics/get_issue_details.js +2 -4
- package/lib/mcp/tools/crashlytics/get_sample_crash.js +4 -4
- package/lib/mcp/tools/crashlytics/index.js +16 -2
- package/lib/mcp/tools/crashlytics/list_notes.js +37 -0
- package/lib/mcp/tools/crashlytics/list_top_devices.js +33 -0
- package/lib/mcp/tools/crashlytics/list_top_issues.js +5 -7
- package/lib/mcp/tools/crashlytics/list_top_operating_systems.js +33 -0
- package/lib/mcp/tools/crashlytics/list_top_versions.js +33 -0
- package/lib/mcp/tools/crashlytics/update_issue.js +37 -0
- package/lib/mcp/tools/dataconnect/execute_graphql.js +2 -2
- package/lib/mcp/tools/dataconnect/execute_graphql_read.js +2 -2
- package/lib/mcp/tools/dataconnect/execute_mutation.js +2 -2
- package/lib/mcp/tools/dataconnect/execute_query.js +2 -2
- package/lib/mcp/tools/dataconnect/generate_operation.js +2 -2
- package/lib/mcp/tools/dataconnect/get_connector.js +2 -2
- package/lib/mcp/tools/dataconnect/get_schema.js +2 -2
- package/lib/utils.js +11 -1
- package/package.json +1 -1
- package/schema/firebase-config.json +3 -0
- package/templates/init/dataconnect/connector.yaml +0 -16
- package/templates/init/dataconnect/dataconnect.yaml +2 -1
- package/templates/init/dataconnect/mutations.gql +29 -29
- package/templates/init/dataconnect/queries.gql +73 -73
- package/templates/init/dataconnect/schema.gql +48 -48
- package/lib/dataconnect/fileUtils.js +0 -168
|
@@ -54,28 +54,28 @@
|
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "2.
|
|
57
|
+
"version": "2.12.0",
|
|
58
58
|
"expectedSize": 29447008,
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
59
|
+
"expectedChecksum": "73a09e7f54b642c0232ce89e9a4dd14a",
|
|
60
|
+
"expectedChecksumSHA256": "5464803fec776eac553e1431474f3d4fcc7cc2f4fe43a58e8c1ce9d7ede28acd",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.12.0",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.12.0"
|
|
63
63
|
},
|
|
64
64
|
"win32": {
|
|
65
|
-
"version": "2.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
65
|
+
"version": "2.12.0",
|
|
66
|
+
"expectedSize": 29936128,
|
|
67
|
+
"expectedChecksum": "b4077d6d298024c9c454b8eb9ad9bf69",
|
|
68
|
+
"expectedChecksumSHA256": "37be096ab8d4d29fa902ca12df97327997b1dc06d4b5026e11aa11d65f183a71",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.12.0",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.12.0.exe"
|
|
71
71
|
},
|
|
72
72
|
"linux": {
|
|
73
|
-
"version": "2.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
73
|
+
"version": "2.12.0",
|
|
74
|
+
"expectedSize": 29372600,
|
|
75
|
+
"expectedChecksum": "04fb5bc9ef194170a5ba0966247eaa79",
|
|
76
|
+
"expectedChecksumSHA256": "42397dd1b23094944aaf20044bc1ec0a5b400c79b536d15803eb4fa6b2bba025",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.12.0",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.12.0"
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -329,6 +329,7 @@ class FunctionsEmulator {
|
|
|
329
329
|
projectId: this.args.projectId,
|
|
330
330
|
projectAlias: this.args.projectAlias,
|
|
331
331
|
isEmulator: true,
|
|
332
|
+
configDir: emulatableBackend.configDir,
|
|
332
333
|
};
|
|
333
334
|
const userEnvs = functionsEnv.loadUserEnvs(userEnvOpt);
|
|
334
335
|
const discoveredBuild = await runtimeDelegate.discoverBuild(runtimeConfig, environment);
|
|
@@ -879,6 +880,7 @@ class FunctionsEmulator {
|
|
|
879
880
|
getUserEnvs(backend) {
|
|
880
881
|
const projectInfo = {
|
|
881
882
|
functionsSource: backend.functionsDir,
|
|
883
|
+
configDir: backend.configDir,
|
|
882
884
|
projectId: this.args.projectId,
|
|
883
885
|
projectAlias: this.args.projectAlias,
|
|
884
886
|
isEmulator: true,
|
package/lib/functions/env.js
CHANGED
|
@@ -140,7 +140,7 @@ function parseStrict(data) {
|
|
|
140
140
|
return envs;
|
|
141
141
|
}
|
|
142
142
|
exports.parseStrict = parseStrict;
|
|
143
|
-
function findEnvfiles(
|
|
143
|
+
function findEnvfiles(configDir, projectId, projectAlias, isEmulator) {
|
|
144
144
|
const files = [".env"];
|
|
145
145
|
files.push(`.env.${projectId}`);
|
|
146
146
|
if (projectAlias) {
|
|
@@ -150,26 +150,28 @@ function findEnvfiles(functionsSource, projectId, projectAlias, isEmulator) {
|
|
|
150
150
|
files.push(FUNCTIONS_EMULATOR_DOTENV);
|
|
151
151
|
}
|
|
152
152
|
return files
|
|
153
|
-
.map((f) => path.join(
|
|
153
|
+
.map((f) => path.join(configDir, f))
|
|
154
154
|
.filter(fs.existsSync)
|
|
155
155
|
.map((p) => path.basename(p));
|
|
156
156
|
}
|
|
157
|
-
function hasUserEnvs(
|
|
158
|
-
|
|
157
|
+
function hasUserEnvs(opts) {
|
|
158
|
+
const configDir = opts.configDir || opts.functionsSource;
|
|
159
|
+
return findEnvfiles(configDir, opts.projectId, opts.projectAlias, opts.isEmulator).length > 0;
|
|
159
160
|
}
|
|
160
161
|
exports.hasUserEnvs = hasUserEnvs;
|
|
161
162
|
function writeUserEnvs(toWrite, envOpts) {
|
|
162
163
|
if (Object.keys(toWrite).length === 0) {
|
|
163
164
|
return;
|
|
164
165
|
}
|
|
165
|
-
const {
|
|
166
|
-
const
|
|
166
|
+
const { projectId, projectAlias, isEmulator } = envOpts;
|
|
167
|
+
const configDir = envOpts.configDir || envOpts.functionsSource;
|
|
168
|
+
const allEnvFiles = findEnvfiles(configDir, projectId, projectAlias, isEmulator);
|
|
167
169
|
const targetEnvFile = envOpts.isEmulator
|
|
168
170
|
? FUNCTIONS_EMULATOR_DOTENV
|
|
169
171
|
: `.env.${envOpts.projectId}`;
|
|
170
172
|
const targetEnvFileExists = allEnvFiles.includes(targetEnvFile);
|
|
171
173
|
if (!targetEnvFileExists) {
|
|
172
|
-
fs.writeFileSync(path.join(
|
|
174
|
+
fs.writeFileSync(path.join(configDir, targetEnvFile), "", { flag: "wx" });
|
|
173
175
|
(0, utils_1.logBullet)(clc.yellow(clc.bold("functions: ")) +
|
|
174
176
|
`Created new local file ${targetEnvFile} to store param values. We suggest explicitly adding or excluding this file from version control.`);
|
|
175
177
|
}
|
|
@@ -186,7 +188,7 @@ function writeUserEnvs(toWrite, envOpts) {
|
|
|
186
188
|
for (const k of Object.keys(toWrite)) {
|
|
187
189
|
lines += formatUserEnvForWrite(k, toWrite[k]);
|
|
188
190
|
}
|
|
189
|
-
fs.appendFileSync(path.join(
|
|
191
|
+
fs.appendFileSync(path.join(configDir, targetEnvFile), lines);
|
|
190
192
|
}
|
|
191
193
|
exports.writeUserEnvs = writeUserEnvs;
|
|
192
194
|
function checkForDuplicateKeys(isEmulator, keys, fullEnv, envsWithoutLocal) {
|
|
@@ -210,22 +212,24 @@ function formatUserEnvForWrite(key, value) {
|
|
|
210
212
|
}
|
|
211
213
|
return `${key}=${escapedValue}\n`;
|
|
212
214
|
}
|
|
213
|
-
function loadUserEnvs(
|
|
215
|
+
function loadUserEnvs(opts) {
|
|
214
216
|
var _a;
|
|
215
|
-
const
|
|
217
|
+
const configDir = opts.configDir || opts.functionsSource;
|
|
218
|
+
const envFiles = findEnvfiles(configDir, opts.projectId, opts.projectAlias, opts.isEmulator);
|
|
216
219
|
if (envFiles.length === 0) {
|
|
217
220
|
return {};
|
|
218
221
|
}
|
|
219
|
-
if (projectAlias) {
|
|
220
|
-
if (envFiles.includes(`.env.${projectId}`) &&
|
|
221
|
-
|
|
222
|
-
|
|
222
|
+
if (opts.projectAlias) {
|
|
223
|
+
if (envFiles.includes(`.env.${opts.projectId}`) &&
|
|
224
|
+
envFiles.includes(`.env.${opts.projectAlias}`)) {
|
|
225
|
+
throw new error_1.FirebaseError(`Can't have both dotenv files with projectId (env.${opts.projectId}) ` +
|
|
226
|
+
`and projectAlias (.env.${opts.projectAlias}) as extensions.`);
|
|
223
227
|
}
|
|
224
228
|
}
|
|
225
229
|
let envs = {};
|
|
226
230
|
for (const f of envFiles) {
|
|
227
231
|
try {
|
|
228
|
-
const data = fs.readFileSync(path.join(
|
|
232
|
+
const data = fs.readFileSync(path.join(configDir, f), "utf8");
|
|
229
233
|
envs = Object.assign(Object.assign({}, envs), parseStrict(data));
|
|
230
234
|
}
|
|
231
235
|
catch (err) {
|
|
@@ -72,7 +72,7 @@ async function execute(sqlStatements, opts) {
|
|
|
72
72
|
sqlStatements.push("COMMIT;");
|
|
73
73
|
}
|
|
74
74
|
for (const s of sqlStatements) {
|
|
75
|
-
logFn(
|
|
75
|
+
logFn(`> ${s}`);
|
|
76
76
|
try {
|
|
77
77
|
results.push(await conn.query(s));
|
|
78
78
|
}
|
|
@@ -84,6 +84,7 @@ async function execute(sqlStatements, opts) {
|
|
|
84
84
|
}
|
|
85
85
|
}
|
|
86
86
|
await cleanUpFn();
|
|
87
|
+
logFn(``);
|
|
87
88
|
return results;
|
|
88
89
|
}
|
|
89
90
|
exports.execute = execute;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.brownfieldSqlSetup = exports.setupBrownfieldAsGreenfield = exports.getSchemaMetadata = exports.greenFieldSchemaSetup = exports.setupSQLPermissions = exports.checkSQLRoleIsGranted = exports.fdcSqlRoleMap = exports.SchemaSetupStatus = void 0;
|
|
3
|
+
exports.grantRoleTo = exports.brownfieldSqlSetup = exports.setupBrownfieldAsGreenfield = exports.getSchemaMetadata = exports.greenFieldSchemaSetup = exports.setupSQLPermissions = exports.checkSQLRoleIsGranted = exports.fdcSqlRoleMap = exports.SchemaSetupStatus = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const permissions_1 = require("./permissions");
|
|
6
6
|
const cloudsqladmin_1 = require("./cloudsqladmin");
|
|
@@ -12,6 +12,7 @@ const connect_1 = require("./connect");
|
|
|
12
12
|
const lodash_1 = require("lodash");
|
|
13
13
|
const connect_2 = require("./connect");
|
|
14
14
|
const utils = require("../../utils");
|
|
15
|
+
const cloudSqlAdminClient = require("./cloudsqladmin");
|
|
15
16
|
var SchemaSetupStatus;
|
|
16
17
|
(function (SchemaSetupStatus) {
|
|
17
18
|
SchemaSetupStatus["NotSetup"] = "not-setup";
|
|
@@ -220,3 +221,11 @@ async function brownfieldSqlSetup(instanceId, databaseId, schemaInfo, options, s
|
|
|
220
221
|
await (0, connect_1.executeSqlCmdsAsSuperUser)(options, instanceId, databaseId, brownfieldSetupCmds, silent, true);
|
|
221
222
|
}
|
|
222
223
|
exports.brownfieldSqlSetup = brownfieldSqlSetup;
|
|
224
|
+
async function grantRoleTo(options, instanceId, databaseId, role, email) {
|
|
225
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
226
|
+
const { user, mode } = (0, connect_2.toDatabaseUser)(email);
|
|
227
|
+
await cloudSqlAdminClient.createUser(projectId, instanceId, mode, user);
|
|
228
|
+
const fdcSqlRole = exports.fdcSqlRoleMap[role](databaseId);
|
|
229
|
+
await (0, connect_1.executeSqlCmdsAsSuperUser)(options, instanceId, databaseId, [`GRANT "${fdcSqlRole}" TO "${user}"`], false);
|
|
230
|
+
}
|
|
231
|
+
exports.grantRoleTo = grantRoleTo;
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createNextApp = exports.createReactApp = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const clc = require("colorette");
|
|
6
|
+
const utils_1 = require("../../../utils");
|
|
7
|
+
async function createReactApp(webAppId) {
|
|
8
|
+
const args = ["create", "vite@latest", webAppId, "--", "--template", "react"];
|
|
9
|
+
await executeCommand("npm", args);
|
|
10
|
+
}
|
|
11
|
+
exports.createReactApp = createReactApp;
|
|
12
|
+
async function createNextApp(webAppId) {
|
|
13
|
+
const args = [
|
|
14
|
+
"create-next-app@latest",
|
|
15
|
+
webAppId,
|
|
16
|
+
"--ts",
|
|
17
|
+
"--eslint",
|
|
18
|
+
"--tailwind",
|
|
19
|
+
"--src-dir",
|
|
20
|
+
"--app",
|
|
21
|
+
"--turbopack",
|
|
22
|
+
"--import-alias",
|
|
23
|
+
'"@/*"',
|
|
24
|
+
"--skip-install",
|
|
25
|
+
];
|
|
26
|
+
await executeCommand("npx", args);
|
|
27
|
+
}
|
|
28
|
+
exports.createNextApp = createNextApp;
|
|
29
|
+
async function executeCommand(command, args) {
|
|
30
|
+
(0, utils_1.logLabeledBullet)("dataconnect", `Running ${clc.bold(`${command} ${args.join(" ")}`)}`);
|
|
31
|
+
return new Promise((resolve, reject) => {
|
|
32
|
+
const childProcess = (0, child_process_1.spawn)(command, args, {
|
|
33
|
+
stdio: "inherit",
|
|
34
|
+
shell: true,
|
|
35
|
+
});
|
|
36
|
+
childProcess.on("close", (code) => {
|
|
37
|
+
if (code === 0) {
|
|
38
|
+
resolve();
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
reject(new Error(`Command failed with exit code ${code}`));
|
|
42
|
+
}
|
|
43
|
+
});
|
|
44
|
+
childProcess.on("error", (err) => {
|
|
45
|
+
reject(err);
|
|
46
|
+
});
|
|
47
|
+
});
|
|
48
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toDNSCompatibleId = exports.postSetup = exports.actuate = exports.askQuestions = void 0;
|
|
3
|
+
exports.newUniqueId = exports.toDNSCompatibleId = exports.postSetup = exports.actuate = exports.askQuestions = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const clc = require("colorette");
|
|
6
6
|
const fs = require("fs-extra");
|
|
@@ -15,9 +15,9 @@ const names_1 = require("../../../dataconnect/names");
|
|
|
15
15
|
const logger_1 = require("../../../logger");
|
|
16
16
|
const templates_1 = require("../../../templates");
|
|
17
17
|
const utils_1 = require("../../../utils");
|
|
18
|
+
Object.defineProperty(exports, "newUniqueId", { enumerable: true, get: function () { return utils_1.newUniqueId; } });
|
|
18
19
|
const cloudbilling_1 = require("../../../gcp/cloudbilling");
|
|
19
20
|
const sdk = require("./sdk");
|
|
20
|
-
const fileUtils_1 = require("../../../dataconnect/fileUtils");
|
|
21
21
|
const fdcExperience_1 = require("../../../gemini/fdcExperience");
|
|
22
22
|
const configstore_1 = require("../../../configstore");
|
|
23
23
|
const track_1 = require("../../../track");
|
|
@@ -64,7 +64,7 @@ async function askQuestions(setup) {
|
|
|
64
64
|
(0, utils_1.logBullet)("Learn more about Gemini in Firebase and how it uses your data: https://firebase.google.com/docs/gemini-in-firebase#how-gemini-in-firebase-uses-your-data");
|
|
65
65
|
}
|
|
66
66
|
info.appDescription = await (0, prompt_1.input)({
|
|
67
|
-
message: `Describe your app to automatically generate a schema [Enter to skip]:`,
|
|
67
|
+
message: `Describe your app to automatically generate a schema with Gemini [Enter to skip]:`,
|
|
68
68
|
});
|
|
69
69
|
if (info.appDescription) {
|
|
70
70
|
configstore_1.configstore.set("gemini", true);
|
|
@@ -77,6 +77,7 @@ async function askQuestions(setup) {
|
|
|
77
77
|
}
|
|
78
78
|
setup.featureInfo = setup.featureInfo || {};
|
|
79
79
|
setup.featureInfo.dataconnect = info;
|
|
80
|
+
await sdk.askQuestions(setup);
|
|
80
81
|
}
|
|
81
82
|
exports.askQuestions = askQuestions;
|
|
82
83
|
async function actuate(setup, config, options) {
|
|
@@ -94,6 +95,7 @@ async function actuate(setup, config, options) {
|
|
|
94
95
|
info.cloudSqlDatabase = info.cloudSqlDatabase || `fdcdb`;
|
|
95
96
|
try {
|
|
96
97
|
await actuateWithInfo(setup, config, info, options);
|
|
98
|
+
await sdk.actuate(setup, config);
|
|
97
99
|
}
|
|
98
100
|
finally {
|
|
99
101
|
void (0, track_1.trackGA4)("dataconnect_init", {
|
|
@@ -154,7 +156,7 @@ async function actuateWithInfo(setup, config, info, options) {
|
|
|
154
156
|
path: "./example",
|
|
155
157
|
files: [
|
|
156
158
|
{
|
|
157
|
-
path: "queries",
|
|
159
|
+
path: "queries.gql",
|
|
158
160
|
content: operationGql,
|
|
159
161
|
},
|
|
160
162
|
],
|
|
@@ -220,31 +222,27 @@ function schemasDeploySequence(projectId, info, schemaFiles, linkToCloudSql) {
|
|
|
220
222
|
},
|
|
221
223
|
];
|
|
222
224
|
}
|
|
223
|
-
async function postSetup(setup
|
|
225
|
+
async function postSetup(setup) {
|
|
224
226
|
var _a;
|
|
225
227
|
const info = (_a = setup.featureInfo) === null || _a === void 0 ? void 0 : _a.dataconnect;
|
|
226
228
|
if (!info) {
|
|
227
229
|
throw new Error("Data Connect feature RequiredInfo is not provided");
|
|
228
230
|
}
|
|
229
231
|
const instructions = [];
|
|
230
|
-
const cwdPlatformGuess = await (0, fileUtils_1.getPlatformFromFolder)(process.cwd());
|
|
231
|
-
if (cwdPlatformGuess !== types_1.Platform.NONE || (0, utils_1.envOverride)("FDC_CONNECTOR", "")) {
|
|
232
|
-
await sdk.doSetup(setup, config, options);
|
|
233
|
-
}
|
|
234
|
-
else {
|
|
235
|
-
instructions.push(`To add the generated SDK to your app, run ${clc.bold("firebase init dataconnect:sdk")}`);
|
|
236
|
-
}
|
|
237
232
|
if (info.appDescription) {
|
|
238
233
|
instructions.push(`You can visualize the Data Connect Schema in Firebase Console:
|
|
239
234
|
|
|
240
235
|
https://console.firebase.google.com/project/${setup.projectId}/dataconnect/locations/${info.locationId}/services/${info.serviceId}/schema`);
|
|
241
236
|
}
|
|
242
|
-
if (
|
|
243
|
-
instructions.push((0, freeTrial_1.upgradeInstructions)(setup.projectId));
|
|
237
|
+
if (!setup.isBillingEnabled) {
|
|
238
|
+
instructions.push((0, freeTrial_1.upgradeInstructions)(setup.projectId || "your-firebase-project"));
|
|
244
239
|
}
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
(
|
|
240
|
+
instructions.push(`Install the Data Connect VS Code Extensions. You can explore Data Connect Query on local pgLite and Cloud SQL Postgres Instance.`);
|
|
241
|
+
if (instructions.length) {
|
|
242
|
+
logger_1.logger.info(`\n${clc.bold("To get started with Firebase Data Connect:")}`);
|
|
243
|
+
for (const i of instructions) {
|
|
244
|
+
(0, utils_1.logBullet)(i + "\n");
|
|
245
|
+
}
|
|
248
246
|
}
|
|
249
247
|
}
|
|
250
248
|
exports.postSetup = postSetup;
|
|
@@ -271,7 +269,7 @@ async function writeFiles(config, info, serviceGql, options) {
|
|
|
271
269
|
async function writeConnectorFiles(config, connectorInfo, options) {
|
|
272
270
|
const subbedConnectorYaml = subConnectorYamlValues({ connectorId: connectorInfo.id });
|
|
273
271
|
const dir = config.get("dataconnect.source") || "dataconnect";
|
|
274
|
-
await config.askWriteProjectFile((0, path_1.join)(dir, connectorInfo.path, "connector.yaml"), subbedConnectorYaml, !!options.force);
|
|
272
|
+
await config.askWriteProjectFile((0, path_1.join)(dir, connectorInfo.path, "connector.yaml"), subbedConnectorYaml, !!options.force, true);
|
|
275
273
|
for (const f of connectorInfo.files) {
|
|
276
274
|
await config.askWriteProjectFile((0, path_1.join)(dir, connectorInfo.path, f.path), f.content, !!options.force);
|
|
277
275
|
}
|
|
@@ -315,7 +313,7 @@ async function promptForExistingServices(setup, info) {
|
|
|
315
313
|
const choice = await chooseExistingService(existingServicesAndSchemas);
|
|
316
314
|
if (!choice) {
|
|
317
315
|
const existingServiceIds = existingServices.map((s) => s.name.split("/").pop());
|
|
318
|
-
info.serviceId = newUniqueId(defaultServiceId(), existingServiceIds);
|
|
316
|
+
info.serviceId = (0, utils_1.newUniqueId)(defaultServiceId(), existingServiceIds);
|
|
319
317
|
info.analyticsFlow += "_pick_new_service";
|
|
320
318
|
return;
|
|
321
319
|
}
|
|
@@ -346,7 +344,7 @@ async function promptForExistingServices(setup, info) {
|
|
|
346
344
|
const id = c.name.split("/").pop();
|
|
347
345
|
return {
|
|
348
346
|
id,
|
|
349
|
-
path: connectors.length === 1 ? "./
|
|
347
|
+
path: connectors.length === 1 ? "./example" : `./${id}`,
|
|
350
348
|
files: c.source.files || [],
|
|
351
349
|
};
|
|
352
350
|
});
|
|
@@ -419,7 +417,7 @@ async function promptForCloudSQL(setup, info) {
|
|
|
419
417
|
info.analyticsFlow += "_pick_new_csql";
|
|
420
418
|
info.cloudSqlInstanceId = await (0, prompt_1.input)({
|
|
421
419
|
message: `What ID would you like to use for your new CloudSQL instance?`,
|
|
422
|
-
default: newUniqueId(`${defaultServiceId().toLowerCase()}-fdc`, instances.map((i) => i.name)),
|
|
420
|
+
default: (0, utils_1.newUniqueId)(`${defaultServiceId().toLowerCase()}-fdc`, instances.map((i) => i.name)),
|
|
423
421
|
});
|
|
424
422
|
}
|
|
425
423
|
}
|
|
@@ -436,7 +434,7 @@ async function promptForCloudSQL(setup, info) {
|
|
|
436
434
|
try {
|
|
437
435
|
const dbs = await cloudsql.listDatabases(setup.projectId, info.cloudSqlInstanceId);
|
|
438
436
|
const existing = dbs.map((d) => d.name);
|
|
439
|
-
info.cloudSqlDatabase = newUniqueId("fdcdb", existing);
|
|
437
|
+
info.cloudSqlDatabase = (0, utils_1.newUniqueId)("fdcdb", existing);
|
|
440
438
|
}
|
|
441
439
|
catch (err) {
|
|
442
440
|
logger_1.logger.debug(`[dataconnect] Cannot list databases during init: ${err}`);
|
|
@@ -464,15 +462,6 @@ async function locationChoices(setup) {
|
|
|
464
462
|
];
|
|
465
463
|
}
|
|
466
464
|
}
|
|
467
|
-
function newUniqueId(recommended, existingIDs) {
|
|
468
|
-
let id = recommended;
|
|
469
|
-
let i = 1;
|
|
470
|
-
while (existingIDs.includes(id)) {
|
|
471
|
-
id = `${recommended}-${i}`;
|
|
472
|
-
i++;
|
|
473
|
-
}
|
|
474
|
-
return id;
|
|
475
|
-
}
|
|
476
465
|
function defaultServiceId() {
|
|
477
466
|
return toDNSCompatibleId((0, path_1.basename)(process.cwd()));
|
|
478
467
|
}
|