firebase-tools 14.2.2 → 14.3.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/api.js +4 -2
- package/lib/apphosting/backend.js +12 -23
- package/lib/apphosting/config.js +9 -20
- package/lib/apphosting/githubConnections.js +52 -80
- package/lib/apphosting/repo.js +22 -36
- package/lib/apphosting/secrets/dialogs.js +2 -3
- package/lib/apphosting/utils.js +1 -3
- package/lib/auth.js +1 -4
- package/lib/commands/apphosting-backends-delete.js +5 -5
- package/lib/commands/apphosting-secrets-set.js +2 -6
- package/lib/commands/apps-create.js +2 -3
- package/lib/commands/apps-sdkconfig.js +2 -7
- package/lib/commands/database-import.js +4 -6
- package/lib/commands/database-remove.js +4 -6
- package/lib/commands/database-set.js +6 -6
- package/lib/commands/database-update.js +5 -5
- package/lib/commands/dataconnect-sql-shell.js +4 -6
- package/lib/commands/ext-dev-deprecate.js +1 -0
- package/lib/commands/ext-dev-init.js +3 -12
- package/lib/commands/ext-dev-register.js +2 -4
- package/lib/commands/ext-dev-undeprecate.js +1 -2
- package/lib/commands/ext-dev-usage.js +1 -3
- package/lib/commands/ext-export.js +1 -2
- package/lib/commands/ext-install.js +1 -0
- package/lib/commands/ext-sdk-install.js +1 -0
- package/lib/commands/ext-update.js +1 -0
- package/lib/commands/firestore-backups-delete.js +1 -2
- package/lib/commands/firestore-backups-schedules-delete.js +1 -2
- package/lib/commands/firestore-databases-delete.js +1 -5
- package/lib/commands/firestore-delete.js +6 -6
- package/lib/commands/functions-artifacts-setpolicy.js +12 -2
- package/lib/commands/functions-config-export.js +5 -9
- package/lib/commands/functions-delete.js +5 -5
- package/lib/commands/functions-deletegcfartifacts.js +4 -4
- package/lib/commands/functions-secrets-destroy.js +8 -10
- package/lib/commands/functions-secrets-prune.js +12 -13
- package/lib/commands/functions-secrets-set.js +11 -15
- package/lib/commands/hosting-channel-create.js +1 -2
- package/lib/commands/hosting-channel-delete.js +4 -4
- package/lib/commands/hosting-channel-open.js +2 -3
- package/lib/commands/hosting-disable.js +5 -5
- package/lib/commands/hosting-sites-delete.js +4 -4
- package/lib/commands/init.js +41 -58
- package/lib/commands/login.js +1 -5
- package/lib/commands/logout.js +2 -3
- package/lib/commands/open.js +1 -2
- package/lib/commands/projects-create.js +1 -2
- package/lib/commands/remoteconfig-rollback.js +5 -5
- package/lib/commands/use.js +110 -110
- package/lib/config.js +1 -2
- package/lib/dataconnect/build.js +2 -4
- package/lib/dataconnect/client.js +20 -1
- package/lib/dataconnect/schemaMigration.js +1 -6
- package/lib/deploy/functions/params.js +10 -17
- package/lib/deploy/functions/prompts.js +6 -28
- package/lib/emulator/commandUtils.js +4 -13
- package/lib/emulator/controller.js +1 -2
- package/lib/emulator/downloadableEmulators.js +12 -12
- package/lib/emulator/initEmulators.js +9 -20
- package/lib/extensions/askUserForEventsConfig.js +6 -15
- package/lib/extensions/askUserForParam.js +23 -52
- package/lib/extensions/checkProjectBilling.js +3 -9
- package/lib/extensions/diagnose.js +3 -6
- package/lib/extensions/extensionsHelper.js +17 -27
- package/lib/extensions/manifest.js +1 -2
- package/lib/extensions/tos.js +10 -2
- package/lib/extensions/utils.js +1 -10
- package/lib/frameworks/index.js +1 -2
- package/lib/frameworks/next/index.js +7 -4
- package/lib/frameworks/vite/index.js +1 -2
- package/lib/functions/secrets.js +14 -15
- package/lib/gcp/auth.js +29 -1
- package/lib/gif/fdcExperience.js +45 -0
- package/lib/hosting/interactive.js +2 -3
- package/lib/init/features/account.js +2 -4
- package/lib/init/features/database.js +11 -20
- package/lib/init/features/dataconnect/index.js +7 -14
- package/lib/init/features/dataconnect/sdk.js +15 -22
- package/lib/init/features/emulators.js +19 -41
- package/lib/init/features/firestore/index.js +2 -6
- package/lib/init/features/firestore/indexes.js +17 -31
- package/lib/init/features/firestore/rules.js +17 -31
- package/lib/init/features/functions/index.js +9 -16
- package/lib/init/features/functions/javascript.js +16 -30
- package/lib/init/features/functions/npm-dependencies.js +4 -8
- package/lib/init/features/functions/python.js +1 -3
- package/lib/init/features/functions/typescript.js +24 -43
- package/lib/init/features/genkit/index.js +23 -38
- package/lib/init/features/hosting/github.js +20 -51
- package/lib/init/features/hosting/index.js +36 -57
- package/lib/init/features/project.js +6 -16
- package/lib/init/features/remoteconfig.js +2 -8
- package/lib/init/features/storage.js +1 -3
- package/lib/management/apps.js +19 -44
- package/lib/management/projects.js +17 -28
- package/lib/mcp/index.js +12 -1
- package/lib/mcp/tools/auth/index.js +7 -1
- package/lib/mcp/tools/auth/set_sms_region_policy.js +36 -0
- package/lib/mcp/tools/core/consult_firebase_assistant.js +27 -0
- package/lib/mcp/tools/core/index.js +6 -1
- package/lib/mcp/tools/dataconnect/converter.js +33 -0
- package/lib/mcp/tools/dataconnect/generate_dataconnect_operation.js +33 -0
- package/lib/mcp/tools/dataconnect/generate_dataconnect_schema.js +25 -0
- package/lib/mcp/tools/dataconnect/get_dataconnect_connector.js +31 -0
- package/lib/mcp/tools/dataconnect/get_dataconnect_schema.js +31 -0
- package/lib/mcp/tools/dataconnect/index.js +11 -1
- package/lib/mcp/tools/firestore/{get_documents.js → get_firestore_documents.js} +5 -5
- package/lib/mcp/tools/firestore/index.js +7 -3
- package/lib/mcp/tools/firestore/{list_collections.js → list_firestore_collections.js} +3 -3
- package/lib/mcp/tools/index.js +2 -1
- package/lib/mcp/tools/storage/get_storage_rules.js +26 -0
- package/lib/mcp/tools/storage/index.js +5 -0
- package/lib/prompt.js +78 -65
- package/lib/requireTosAcceptance.js +4 -0
- package/lib/rulesDeploy.js +10 -15
- package/lib/track.js +1 -34
- package/lib/utils.js +27 -5
- package/package.json +2 -3
package/lib/functions/secrets.js
CHANGED
|
@@ -42,13 +42,13 @@ async function ensureValidKey(key, options) {
|
|
|
42
42
|
throw new error_1.FirebaseError("Secret key must be in UPPER_SNAKE_CASE.");
|
|
43
43
|
}
|
|
44
44
|
(0, utils_1.logWarning)(`By convention, secret key must be in UPPER_SNAKE_CASE.`);
|
|
45
|
-
const
|
|
46
|
-
name: "updateKey",
|
|
47
|
-
type: "confirm",
|
|
45
|
+
const useTransformed = await (0, prompt_1.confirm)({
|
|
48
46
|
default: true,
|
|
49
47
|
message: `Would you like to use ${transformedKey} as key instead?`,
|
|
50
|
-
|
|
51
|
-
|
|
48
|
+
nonInteractive: options.nonInteractive,
|
|
49
|
+
force: options.force,
|
|
50
|
+
});
|
|
51
|
+
if (!useTransformed) {
|
|
52
52
|
throw new error_1.FirebaseError("Secret key must be in UPPER_SNAKE_CASE.");
|
|
53
53
|
}
|
|
54
54
|
}
|
|
@@ -66,12 +66,11 @@ async function ensureSecret(projectId, name, options) {
|
|
|
66
66
|
const secret = await (0, secretManager_1.getSecret)(projectId, name);
|
|
67
67
|
if ((0, secretManager_1.isAppHostingManaged)(secret)) {
|
|
68
68
|
(0, utils_1.logWarning)("Your secret is managed by Firebase App Hosting. Continuing will disable automatic deletion of old versions.");
|
|
69
|
-
const stopTracking = await (0, prompt_1.
|
|
70
|
-
name: "doNotTrack",
|
|
71
|
-
type: "confirm",
|
|
72
|
-
default: false,
|
|
69
|
+
const stopTracking = await (0, prompt_1.confirm)({
|
|
73
70
|
message: "Do you wish to continue?",
|
|
74
|
-
|
|
71
|
+
nonInteractive: options.nonInteractive,
|
|
72
|
+
force: options.force,
|
|
73
|
+
});
|
|
75
74
|
if (stopTracking) {
|
|
76
75
|
delete secret.labels[secretManager_2.FIREBASE_MANAGED];
|
|
77
76
|
await (0, secretManager_1.patchSecret)(secret.projectId, secret.name, secret.labels);
|
|
@@ -84,13 +83,13 @@ async function ensureSecret(projectId, name, options) {
|
|
|
84
83
|
if (!options.force) {
|
|
85
84
|
(0, utils_1.logWarning)("Your secret is not managed by Cloud Functions for Firebase. " +
|
|
86
85
|
"Firebase managed secrets are automatically pruned to reduce your monthly cost for using Secret Manager. ");
|
|
87
|
-
const
|
|
88
|
-
name: "updateLabels",
|
|
89
|
-
type: "confirm",
|
|
86
|
+
const updateLabels = await (0, prompt_1.confirm)({
|
|
90
87
|
default: true,
|
|
91
88
|
message: `Would you like to have your secret ${secret.name} managed by Cloud Functions for Firebase?`,
|
|
92
|
-
|
|
93
|
-
|
|
89
|
+
nonInteractive: options.nonInteractive,
|
|
90
|
+
force: options.force,
|
|
91
|
+
});
|
|
92
|
+
if (updateLabels) {
|
|
94
93
|
return (0, secretManager_1.patchSecret)(projectId, secret.name, Object.assign(Object.assign({}, secret.labels), (0, secretManager_3.labels)()));
|
|
95
94
|
}
|
|
96
95
|
}
|
package/lib/gcp/auth.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setCustomClaim = exports.disableUser = exports.findUser = exports.updateAuthDomains = exports.getAuthDomains = void 0;
|
|
3
|
+
exports.setDenySmsRegionPolicy = exports.setAllowSmsRegionPolicy = exports.setCustomClaim = exports.disableUser = exports.findUser = exports.updateAuthDomains = exports.getAuthDomains = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
6
|
const apiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.identityOrigin)(), auth: true });
|
|
@@ -72,3 +72,31 @@ async function setCustomClaim(project, uid, claim, options) {
|
|
|
72
72
|
return user;
|
|
73
73
|
}
|
|
74
74
|
exports.setCustomClaim = setCustomClaim;
|
|
75
|
+
async function setAllowSmsRegionPolicy(project, countryCodes) {
|
|
76
|
+
const res = await apiClient.patch(`/admin/v2/projects/${project}/config?updateMask=sms_region_config`, {
|
|
77
|
+
sms_region_config: {
|
|
78
|
+
allowlist_only: {
|
|
79
|
+
allowed_regions: countryCodes,
|
|
80
|
+
},
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
if (res.status !== 200) {
|
|
84
|
+
throw new Error("SMS Region Policy failed to be configured");
|
|
85
|
+
}
|
|
86
|
+
return true;
|
|
87
|
+
}
|
|
88
|
+
exports.setAllowSmsRegionPolicy = setAllowSmsRegionPolicy;
|
|
89
|
+
async function setDenySmsRegionPolicy(project, countryCodes) {
|
|
90
|
+
const res = await apiClient.patch(`/admin/v2/projects/${project}/config?updateMask=sms_region_config`, {
|
|
91
|
+
sms_region_config: {
|
|
92
|
+
allow_by_default: {
|
|
93
|
+
disallowed_regions: countryCodes,
|
|
94
|
+
},
|
|
95
|
+
},
|
|
96
|
+
});
|
|
97
|
+
if (res.status !== 200) {
|
|
98
|
+
throw new Error("SMS Region Policy failed to be configured");
|
|
99
|
+
}
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
exports.setDenySmsRegionPolicy = setDenySmsRegionPolicy;
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.generateOperation = exports.chatWithFirebase = exports.generateSchema = void 0;
|
|
4
|
+
const apiv2_1 = require("../apiv2");
|
|
5
|
+
const api_1 = require("../api");
|
|
6
|
+
const apiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.cloudCompanionOrigin)(), auth: true });
|
|
7
|
+
const schemaGeneratorExperience = "/appeco/firebase/fdc-schema-generator";
|
|
8
|
+
const geminiInFirebaseChatExperience = "/appeco/firebase/firebase-chat/free";
|
|
9
|
+
const operationGeneratorExperience = "/appeco/firebase/fdc-query-generator";
|
|
10
|
+
async function generateSchema(prompt, project) {
|
|
11
|
+
const res = await apiClient.post(`/v1beta/projects/${project}/locations/global/instances/default:completeTask`, {
|
|
12
|
+
input: { messages: [{ content: prompt, author: "USER" }] },
|
|
13
|
+
experienceContext: {
|
|
14
|
+
experience: schemaGeneratorExperience,
|
|
15
|
+
},
|
|
16
|
+
});
|
|
17
|
+
return res.body.output.messages[0].content;
|
|
18
|
+
}
|
|
19
|
+
exports.generateSchema = generateSchema;
|
|
20
|
+
async function chatWithFirebase(prompt, project) {
|
|
21
|
+
const res = await apiClient.post(`/v1beta/projects/${project}/locations/global/instances/default:completeTask`, {
|
|
22
|
+
input: { messages: [{ content: prompt, author: "USER" }] },
|
|
23
|
+
experienceContext: {
|
|
24
|
+
experience: geminiInFirebaseChatExperience,
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
return res.body;
|
|
28
|
+
}
|
|
29
|
+
exports.chatWithFirebase = chatWithFirebase;
|
|
30
|
+
async function generateOperation(prompt, service, project) {
|
|
31
|
+
const res = await apiClient.post(`/v1beta/projects/${project}/locations/global/instances/default:completeTask`, {
|
|
32
|
+
input: { messages: [{ content: prompt, author: "USER" }] },
|
|
33
|
+
experienceContext: {
|
|
34
|
+
experience: operationGeneratorExperience,
|
|
35
|
+
},
|
|
36
|
+
clientContext: {
|
|
37
|
+
additionalContext: {
|
|
38
|
+
"@type": "type.googleapis.com/google.cloud.cloudaicompanion.v1main.FirebaseChatRequestContext",
|
|
39
|
+
fdcInfo: { fdcServiceName: service, requiresQuery: true },
|
|
40
|
+
},
|
|
41
|
+
},
|
|
42
|
+
});
|
|
43
|
+
return res.body.output.messages[0].content;
|
|
44
|
+
}
|
|
45
|
+
exports.generateOperation = generateOperation;
|
|
@@ -4,8 +4,8 @@ exports.interactiveCreateHostingSite = void 0;
|
|
|
4
4
|
const error_1 = require("../error");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const projectUtils_1 = require("../projectUtils");
|
|
7
|
-
const prompt_1 = require("../prompt");
|
|
8
7
|
const api_1 = require("./api");
|
|
8
|
+
const prompt_1 = require("../prompt");
|
|
9
9
|
const nameSuggestion = new RegExp("try something like `(.+)`");
|
|
10
10
|
const prompt = "Please provide an unique, URL-friendly id for your site. Your site's URL will be <site-id>.web.app. " +
|
|
11
11
|
'We recommend using letters, numbers, and hyphens (e.g. "{project-id}-{random-hash}"):';
|
|
@@ -26,8 +26,7 @@ async function interactiveCreateHostingSite(siteId, appId, options) {
|
|
|
26
26
|
}
|
|
27
27
|
while (!newSite) {
|
|
28
28
|
if (!id || suggestion) {
|
|
29
|
-
id = await (0, prompt_1.
|
|
30
|
-
type: "input",
|
|
29
|
+
id = await (0, prompt_1.input)({
|
|
31
30
|
message: prompt,
|
|
32
31
|
validate: (s) => s.length > 0,
|
|
33
32
|
default: suggestion,
|
|
@@ -4,8 +4,8 @@ exports.doSetup = void 0;
|
|
|
4
4
|
const logger_1 = require("../../logger");
|
|
5
5
|
const utils = require("../../utils");
|
|
6
6
|
const auth_1 = require("../../auth");
|
|
7
|
-
const prompt_1 = require("../../prompt");
|
|
8
7
|
const error_1 = require("../../error");
|
|
8
|
+
const prompt_1 = require("../../prompt");
|
|
9
9
|
async function promptForAccount() {
|
|
10
10
|
logger_1.logger.info();
|
|
11
11
|
logger_1.logger.info(`Which account do you want to use for this project? Choose an account or add a new one now`);
|
|
@@ -21,9 +21,7 @@ async function promptForAccount() {
|
|
|
21
21
|
name: "(add a new account)",
|
|
22
22
|
value: "__add__",
|
|
23
23
|
});
|
|
24
|
-
const emailChoice = await (0, prompt_1.
|
|
25
|
-
type: "list",
|
|
26
|
-
name: "email",
|
|
24
|
+
const emailChoice = await (0, prompt_1.select)({
|
|
27
25
|
message: "Please select an option:",
|
|
28
26
|
choices,
|
|
29
27
|
});
|
|
@@ -37,8 +37,7 @@ function writeDBRules(rules, logMessagePrefix, filename, config) {
|
|
|
37
37
|
logger_1.logger.info(clc.bold("firebase deploy") + ".");
|
|
38
38
|
}
|
|
39
39
|
async function createDefaultDatabaseInstance(project) {
|
|
40
|
-
const selectedLocation = await (0, prompt_1.
|
|
41
|
-
type: "list",
|
|
40
|
+
const selectedLocation = await (0, prompt_1.select)({
|
|
42
41
|
message: "Please choose the location for your default Realtime Database instance:",
|
|
43
42
|
choices: [
|
|
44
43
|
{ name: "us-central1", value: database_1.DatabaseLocation.US_CENTRAL1 },
|
|
@@ -79,13 +78,11 @@ async function doSetup(setup, config) {
|
|
|
79
78
|
instanceDetails = await (0, database_1.getDatabaseInstanceDetails)(setup.projectId, setup.instance);
|
|
80
79
|
}
|
|
81
80
|
else {
|
|
82
|
-
const
|
|
83
|
-
type: "confirm",
|
|
84
|
-
name: "confirm",
|
|
85
|
-
default: true,
|
|
81
|
+
const createDefault = await (0, prompt_1.confirm)({
|
|
86
82
|
message: "It seems like you haven’t initialized Realtime Database in your project yet. Do you want to set it up?",
|
|
83
|
+
default: true,
|
|
87
84
|
});
|
|
88
|
-
if (
|
|
85
|
+
if (createDefault) {
|
|
89
86
|
instanceDetails = await createDefaultDatabaseInstance(setup.projectId);
|
|
90
87
|
}
|
|
91
88
|
}
|
|
@@ -95,14 +92,12 @@ async function doSetup(setup, config) {
|
|
|
95
92
|
logger_1.logger.info("Firebase Realtime Database Security Rules allow you to define how your data should be");
|
|
96
93
|
logger_1.logger.info("structured and when your data can be read from and written to.");
|
|
97
94
|
logger_1.logger.info();
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
},
|
|
105
|
-
]);
|
|
95
|
+
setup.config.database.rules =
|
|
96
|
+
setup.config.database.rules ||
|
|
97
|
+
(await (0, prompt_1.input)({
|
|
98
|
+
message: "What file should be used for Realtime Database Security Rules?",
|
|
99
|
+
default: "database.rules.json",
|
|
100
|
+
}));
|
|
106
101
|
const filename = setup.config.database.rules;
|
|
107
102
|
if (!filename) {
|
|
108
103
|
throw new error_1.FirebaseError("Must specify location for Realtime Database rules file.");
|
|
@@ -113,11 +108,7 @@ async function doSetup(setup, config) {
|
|
|
113
108
|
? `the Realtime Database Security Rules for ${clc.bold(instanceDetails.name)} from the Firebase console`
|
|
114
109
|
: "default rules";
|
|
115
110
|
const msg = `File ${clc.bold(filename)} already exists. Do you want to overwrite it with ${rulesDescription}?`;
|
|
116
|
-
writeRules = await (0, prompt_1.
|
|
117
|
-
type: "confirm",
|
|
118
|
-
message: msg,
|
|
119
|
-
default: false,
|
|
120
|
-
});
|
|
111
|
+
writeRules = await (0, prompt_1.confirm)(msg);
|
|
121
112
|
}
|
|
122
113
|
if (writeRules) {
|
|
123
114
|
if (instanceDetails) {
|
|
@@ -211,9 +211,8 @@ async function promptForExistingServices(setup, info, isBillingEnabled) {
|
|
|
211
211
|
};
|
|
212
212
|
});
|
|
213
213
|
choices.push({ name: "Create a new service", value: undefined });
|
|
214
|
-
choice = await (0, prompt_1.
|
|
214
|
+
choice = await (0, prompt_1.select)({
|
|
215
215
|
message: "Your project already has existing services. Which would you like to set up local files for?",
|
|
216
|
-
type: "list",
|
|
217
216
|
choices,
|
|
218
217
|
});
|
|
219
218
|
}
|
|
@@ -271,9 +270,8 @@ async function promptForCloudSQL(setup, info) {
|
|
|
271
270
|
else {
|
|
272
271
|
choices.push({ name: "Create a new CloudSQL instance", value: "", location: "" });
|
|
273
272
|
}
|
|
274
|
-
info.cloudSqlInstanceId = await (0, prompt_1.
|
|
273
|
+
info.cloudSqlInstanceId = await (0, prompt_1.select)({
|
|
275
274
|
message: `Which CloudSQL instance would you like to use?`,
|
|
276
|
-
type: "list",
|
|
277
275
|
choices,
|
|
278
276
|
});
|
|
279
277
|
if (info.cloudSqlInstanceId !== "") {
|
|
@@ -283,17 +281,15 @@ async function promptForCloudSQL(setup, info) {
|
|
|
283
281
|
}
|
|
284
282
|
if (info.cloudSqlInstanceId === "") {
|
|
285
283
|
info.isNewInstance = true;
|
|
286
|
-
info.cloudSqlInstanceId = await (0, prompt_1.
|
|
284
|
+
info.cloudSqlInstanceId = await (0, prompt_1.input)({
|
|
287
285
|
message: `What ID would you like to use for your new CloudSQL instance?`,
|
|
288
|
-
type: "input",
|
|
289
286
|
default: `${info.serviceId.toLowerCase() || "app"}-fdc`,
|
|
290
287
|
});
|
|
291
288
|
}
|
|
292
289
|
if (info.locationId === "") {
|
|
293
290
|
const choices = await locationChoices(setup);
|
|
294
|
-
info.locationId = await (0, prompt_1.
|
|
291
|
+
info.locationId = await (0, prompt_1.select)({
|
|
295
292
|
message: "What location would like to use?",
|
|
296
|
-
type: "list",
|
|
297
293
|
choices,
|
|
298
294
|
});
|
|
299
295
|
}
|
|
@@ -305,9 +301,8 @@ async function promptForCloudSQL(setup, info) {
|
|
|
305
301
|
});
|
|
306
302
|
choices.push({ name: "Create a new database", value: "" });
|
|
307
303
|
if (dbs.length) {
|
|
308
|
-
info.cloudSqlDatabase = await (0, prompt_1.
|
|
304
|
+
info.cloudSqlDatabase = await (0, prompt_1.select)({
|
|
309
305
|
message: `Which database in ${info.cloudSqlInstanceId} would you like to use?`,
|
|
310
|
-
type: "list",
|
|
311
306
|
choices,
|
|
312
307
|
});
|
|
313
308
|
}
|
|
@@ -318,9 +313,8 @@ async function promptForCloudSQL(setup, info) {
|
|
|
318
313
|
}
|
|
319
314
|
if (info.cloudSqlDatabase === "") {
|
|
320
315
|
info.isNewDatabase = true;
|
|
321
|
-
info.cloudSqlDatabase = await (0, prompt_1.
|
|
316
|
+
info.cloudSqlDatabase = await (0, prompt_1.input)({
|
|
322
317
|
message: `What ID would you like to use for your new database in ${info.cloudSqlInstanceId}?`,
|
|
323
|
-
type: "input",
|
|
324
318
|
default: `fdcdb`,
|
|
325
319
|
});
|
|
326
320
|
}
|
|
@@ -328,9 +322,8 @@ async function promptForCloudSQL(setup, info) {
|
|
|
328
322
|
}
|
|
329
323
|
async function promptForService(info) {
|
|
330
324
|
if (info.serviceId === "") {
|
|
331
|
-
info.serviceId = await (0, prompt_1.
|
|
325
|
+
info.serviceId = await (0, prompt_1.input)({
|
|
332
326
|
message: "What ID would you like to use for this service?",
|
|
333
|
-
type: "input",
|
|
334
327
|
default: (0, path_1.basename)(process.cwd()),
|
|
335
328
|
});
|
|
336
329
|
}
|
|
@@ -41,7 +41,7 @@ async function askQuestions(setup, config) {
|
|
|
41
41
|
let appDir = process.env[exports.FDC_APP_FOLDER] || process.cwd();
|
|
42
42
|
let targetPlatform = await (0, fileUtils_1.getPlatformFromFolder)(appDir);
|
|
43
43
|
if (targetPlatform === types_1.Platform.NONE && !((_a = process.env[exports.FDC_APP_FOLDER]) === null || _a === void 0 ? void 0 : _a.length)) {
|
|
44
|
-
appDir = await (0,
|
|
44
|
+
appDir = await (0, utils_1.promptForDirectory)({
|
|
45
45
|
config,
|
|
46
46
|
message: "Where is your app directory? Leave blank to set up a generated SDK in your current directory.",
|
|
47
47
|
});
|
|
@@ -60,18 +60,16 @@ async function askQuestions(setup, config) {
|
|
|
60
60
|
{ name: "Android (Kotlin)", value: types_1.Platform.ANDROID },
|
|
61
61
|
{ name: "Flutter (Dart)", value: types_1.Platform.FLUTTER },
|
|
62
62
|
];
|
|
63
|
-
targetPlatform = await (0, prompt_1.
|
|
63
|
+
targetPlatform = await (0, prompt_1.select)({
|
|
64
64
|
message: "Which platform do you want to set up a generated SDK for?",
|
|
65
|
-
type: "list",
|
|
66
65
|
choices: platforms,
|
|
67
66
|
});
|
|
68
67
|
}
|
|
69
68
|
else {
|
|
70
69
|
(0, utils_1.logSuccess)(`Detected ${targetPlatform} app in directory ${appDir}`);
|
|
71
70
|
}
|
|
72
|
-
const connectorInfo = await (0, prompt_1.
|
|
71
|
+
const connectorInfo = await (0, prompt_1.select)({
|
|
73
72
|
message: "Which connector do you want set up a generated SDK for?",
|
|
74
|
-
type: "list",
|
|
75
73
|
choices: connectorChoices,
|
|
76
74
|
});
|
|
77
75
|
const connectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
|
|
@@ -79,23 +77,18 @@ async function askQuestions(setup, config) {
|
|
|
79
77
|
if (targetPlatform === types_1.Platform.WEB) {
|
|
80
78
|
const unusedFrameworks = fileUtils_1.SUPPORTED_FRAMEWORKS.filter((framework) => { var _a; return !((_a = newConnectorYaml.generate) === null || _a === void 0 ? void 0 : _a.javascriptSdk[framework]); });
|
|
81
79
|
if (unusedFrameworks.length > 0) {
|
|
82
|
-
const additionalFrameworks = await (0, prompt_1.
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
});
|
|
95
|
-
}),
|
|
96
|
-
},
|
|
97
|
-
]);
|
|
98
|
-
for (const framework of additionalFrameworks.fdcFrameworks) {
|
|
80
|
+
const additionalFrameworks = await (0, prompt_1.checkbox)({
|
|
81
|
+
message: "Which frameworks would you like to generate SDKs for? " +
|
|
82
|
+
"Press Space to select features, then Enter to confirm your choices.",
|
|
83
|
+
choices: fileUtils_1.SUPPORTED_FRAMEWORKS.map((frameworkStr) => {
|
|
84
|
+
var _a, _b;
|
|
85
|
+
return ({
|
|
86
|
+
value: frameworkStr,
|
|
87
|
+
checked: (_b = (_a = newConnectorYaml === null || newConnectorYaml === void 0 ? void 0 : newConnectorYaml.generate) === null || _a === void 0 ? void 0 : _a.javascriptSdk) === null || _b === void 0 ? void 0 : _b[frameworkStr],
|
|
88
|
+
});
|
|
89
|
+
}),
|
|
90
|
+
});
|
|
91
|
+
for (const framework of additionalFrameworks) {
|
|
99
92
|
newConnectorYaml.generate.javascriptSdk[framework] = true;
|
|
100
93
|
}
|
|
101
94
|
}
|
|
@@ -14,19 +14,15 @@ async function doSetup(setup, config) {
|
|
|
14
14
|
return {
|
|
15
15
|
value: e,
|
|
16
16
|
name: constants_1.Constants.description(e),
|
|
17
|
-
checked: config
|
|
17
|
+
checked: (config === null || config === void 0 ? void 0 : config.has(e)) || (config === null || config === void 0 ? void 0 : config.has(`emulators.${e}`)),
|
|
18
18
|
};
|
|
19
19
|
});
|
|
20
20
|
const selections = {};
|
|
21
|
-
await (0, prompt_1.
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
"Press Space to select emulators, then Enter to confirm your choices.",
|
|
27
|
-
choices: choices,
|
|
28
|
-
},
|
|
29
|
-
]);
|
|
21
|
+
selections.emulators = await (0, prompt_1.checkbox)({
|
|
22
|
+
message: "Which Firebase emulators do you want to set up? " +
|
|
23
|
+
"Press Space to select emulators, then Enter to confirm your choices.",
|
|
24
|
+
choices: choices,
|
|
25
|
+
});
|
|
30
26
|
if (!selections.emulators) {
|
|
31
27
|
return;
|
|
32
28
|
}
|
|
@@ -38,14 +34,10 @@ async function doSetup(setup, config) {
|
|
|
38
34
|
utils.logBullet(`Port for ${selected} already configured: ${clc.cyan(currentPort)}`);
|
|
39
35
|
}
|
|
40
36
|
else {
|
|
41
|
-
await (0, prompt_1.
|
|
42
|
-
{
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
message: `Which port do you want to use for the ${clc.underline(selected)} emulator?`,
|
|
46
|
-
default: constants_1.Constants.getDefaultPort(selected),
|
|
47
|
-
},
|
|
48
|
-
]);
|
|
37
|
+
setup.config.emulators[selected].port = await (0, prompt_1.number)({
|
|
38
|
+
message: `Which port do you want to use for the ${clc.underline(selected)} emulator?`,
|
|
39
|
+
default: constants_1.Constants.getDefaultPort(selected),
|
|
40
|
+
});
|
|
49
41
|
}
|
|
50
42
|
const additionalInitFn = initEmulators_1.AdditionalInitFns[selected];
|
|
51
43
|
if (additionalInitFn) {
|
|
@@ -64,34 +56,20 @@ async function doSetup(setup, config) {
|
|
|
64
56
|
else {
|
|
65
57
|
const ui = setup.config.emulators.ui || {};
|
|
66
58
|
setup.config.emulators.ui = ui;
|
|
67
|
-
await (0, prompt_1.
|
|
68
|
-
{
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
message: `Would you like to enable the ${uiDesc}?`,
|
|
72
|
-
default: true,
|
|
73
|
-
},
|
|
74
|
-
]);
|
|
59
|
+
ui.enalbed = await (0, prompt_1.confirm)({
|
|
60
|
+
message: `Would you like to enable the ${uiDesc}?`,
|
|
61
|
+
default: true,
|
|
62
|
+
});
|
|
75
63
|
if (ui.enabled) {
|
|
76
|
-
await (0, prompt_1.
|
|
77
|
-
{
|
|
78
|
-
type: "input",
|
|
79
|
-
name: "port",
|
|
80
|
-
message: `Which port do you want to use for the ${clc.underline(uiDesc)} (leave empty to use any available port)?`,
|
|
81
|
-
},
|
|
82
|
-
]);
|
|
64
|
+
ui.port = await (0, prompt_1.number)(`Which port do you want to use for the ${clc.underline(uiDesc)} (leave empty to use any available port)?`);
|
|
83
65
|
const portNum = Number.parseInt(ui.port);
|
|
84
66
|
ui.port = isNaN(portNum) ? undefined : portNum;
|
|
85
67
|
}
|
|
86
68
|
}
|
|
87
|
-
await (0, prompt_1.
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
message: "Would you like to download the emulators now?",
|
|
92
|
-
default: true,
|
|
93
|
-
},
|
|
94
|
-
]);
|
|
69
|
+
selections.download = await (0, prompt_1.confirm)({
|
|
70
|
+
message: "Would you like to download the emulators now?",
|
|
71
|
+
default: true,
|
|
72
|
+
});
|
|
95
73
|
}
|
|
96
74
|
if (setup.config.emulators.singleProjectMode === undefined) {
|
|
97
75
|
setup.config.emulators.singleProjectMode = true;
|
|
@@ -37,12 +37,8 @@ async function getDatabaseType(setup) {
|
|
|
37
37
|
return dbType;
|
|
38
38
|
}
|
|
39
39
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
type: "input",
|
|
43
|
-
message: "Please input the name of the Native Firestore database you would like to use:",
|
|
44
|
-
});
|
|
45
|
-
return database;
|
|
40
|
+
function selectDatabaseByPrompting() {
|
|
41
|
+
return (0, prompt_1.input)("Please input the name of the Native Firestore database you would like to use:");
|
|
46
42
|
}
|
|
47
43
|
async function doSetup(setup, config, options) {
|
|
48
44
|
if (setup.projectId) {
|
|
@@ -10,46 +10,32 @@ const logger_1 = require("../../../logger");
|
|
|
10
10
|
const templates_1 = require("../../../templates");
|
|
11
11
|
const indexes = new api.FirestoreApi();
|
|
12
12
|
const INDEXES_TEMPLATE = (0, templates_1.readTemplateSync)("init/firestore/firestore.indexes.json");
|
|
13
|
-
function initIndexes(setup, config) {
|
|
13
|
+
async function initIndexes(setup, config) {
|
|
14
14
|
logger_1.logger.info();
|
|
15
15
|
logger_1.logger.info("Firestore indexes allow you to perform complex queries while");
|
|
16
16
|
logger_1.logger.info("maintaining performance that scales with the size of the result");
|
|
17
17
|
logger_1.logger.info("set. You can keep index definitions in your project directory");
|
|
18
18
|
logger_1.logger.info("and publish them with " + clc.bold("firebase deploy") + ".");
|
|
19
19
|
logger_1.logger.info();
|
|
20
|
-
|
|
21
|
-
{
|
|
22
|
-
type: "input",
|
|
23
|
-
name: "indexes",
|
|
20
|
+
const filename = setup.config.firestore.indexes ||
|
|
21
|
+
(await (0, prompt_1.input)({
|
|
24
22
|
message: "What file should be used for Firestore indexes?",
|
|
25
23
|
default: "firestore.indexes.json",
|
|
26
|
-
}
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
" Do you want to overwrite it with the Firestore Indexes from the Firebase Console?";
|
|
35
|
-
return (0, prompt_1.promptOnce)({
|
|
36
|
-
type: "confirm",
|
|
37
|
-
message: msg,
|
|
38
|
-
default: false,
|
|
39
|
-
});
|
|
24
|
+
}));
|
|
25
|
+
if (fsutils.fileExistsSync(filename)) {
|
|
26
|
+
const msg = "File " +
|
|
27
|
+
clc.bold(filename) +
|
|
28
|
+
" already exists." +
|
|
29
|
+
" Do you want to overwrite it with the Firestore Indexes from the Firebase Console?";
|
|
30
|
+
if (!(await (0, prompt_1.confirm)(msg))) {
|
|
31
|
+
return;
|
|
40
32
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
if (!setup.projectId) {
|
|
48
|
-
return config.writeProjectFile(setup.config.firestore.indexes, INDEXES_TEMPLATE);
|
|
49
|
-
}
|
|
50
|
-
return getIndexesFromConsole(setup.projectId, setup.databaseId).then((contents) => {
|
|
51
|
-
return config.writeProjectFile(setup.config.firestore.indexes, contents);
|
|
52
|
-
});
|
|
33
|
+
}
|
|
34
|
+
if (!setup.projectId) {
|
|
35
|
+
return config.writeProjectFile(setup.config.firestore.indexes, INDEXES_TEMPLATE);
|
|
36
|
+
}
|
|
37
|
+
return getIndexesFromConsole(setup.projectId, setup.databaseId).then((contents) => {
|
|
38
|
+
return config.writeProjectFile(setup.config.firestore.indexes, contents);
|
|
53
39
|
});
|
|
54
40
|
}
|
|
55
41
|
exports.initIndexes = initIndexes;
|
|
@@ -10,45 +10,31 @@ const utils = require("../../../utils");
|
|
|
10
10
|
const templates_1 = require("../../../templates");
|
|
11
11
|
const DEFAULT_RULES_FILE = "firestore.rules";
|
|
12
12
|
const RULES_TEMPLATE = (0, templates_1.readTemplateSync)("init/firestore/firestore.rules");
|
|
13
|
-
function initRules(setup, config) {
|
|
13
|
+
async function initRules(setup, config) {
|
|
14
14
|
logger_1.logger.info();
|
|
15
15
|
logger_1.logger.info("Firestore Security Rules allow you to define how and when to allow");
|
|
16
16
|
logger_1.logger.info("requests. You can keep these rules in your project directory");
|
|
17
17
|
logger_1.logger.info("and publish them with " + clc.bold("firebase deploy") + ".");
|
|
18
18
|
logger_1.logger.info();
|
|
19
|
-
|
|
20
|
-
{
|
|
21
|
-
type: "input",
|
|
22
|
-
name: "rules",
|
|
19
|
+
const filename = setup.config.firestore.rules ||
|
|
20
|
+
(await (0, prompt_1.input)({
|
|
23
21
|
message: "What file should be used for Firestore Rules?",
|
|
24
22
|
default: DEFAULT_RULES_FILE,
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
" Do you want to overwrite it with the Firestore Rules from the Firebase Console?";
|
|
34
|
-
return (0, prompt_1.promptOnce)({
|
|
35
|
-
type: "confirm",
|
|
36
|
-
message: msg,
|
|
37
|
-
default: false,
|
|
38
|
-
});
|
|
23
|
+
}));
|
|
24
|
+
if (fsutils.fileExistsSync(filename)) {
|
|
25
|
+
const msg = "File " +
|
|
26
|
+
clc.bold(filename) +
|
|
27
|
+
" already exists." +
|
|
28
|
+
" Do you want to overwrite it with the Firestore Rules from the Firebase Console?";
|
|
29
|
+
if (!(await (0, prompt_1.confirm)(msg))) {
|
|
30
|
+
return;
|
|
39
31
|
}
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if (!setup.projectId) {
|
|
47
|
-
return config.writeProjectFile(setup.config.firestore.rules, getDefaultRules());
|
|
48
|
-
}
|
|
49
|
-
return getRulesFromConsole(setup.projectId).then((contents) => {
|
|
50
|
-
return config.writeProjectFile(setup.config.firestore.rules, contents);
|
|
51
|
-
});
|
|
32
|
+
}
|
|
33
|
+
if (!setup.projectId) {
|
|
34
|
+
return config.writeProjectFile(setup.config.firestore.rules, getDefaultRules());
|
|
35
|
+
}
|
|
36
|
+
return getRulesFromConsole(setup.projectId).then((contents) => {
|
|
37
|
+
return config.writeProjectFile(setup.config.firestore.rules, contents);
|
|
52
38
|
});
|
|
53
39
|
}
|
|
54
40
|
exports.initRules = initRules;
|