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/commands/init.js
CHANGED
|
@@ -15,6 +15,7 @@ const fsutils = require("../fsutils");
|
|
|
15
15
|
const utils = require("../utils");
|
|
16
16
|
const experiments_1 = require("../experiments");
|
|
17
17
|
const templates_1 = require("../templates");
|
|
18
|
+
const error_1 = require("../error");
|
|
18
19
|
const homeDir = os.homedir();
|
|
19
20
|
const BANNER_TEXT = (0, templates_1.readTemplateSync)("banner.txt");
|
|
20
21
|
const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("_gitignore");
|
|
@@ -112,7 +113,8 @@ exports.command = new command_1.Command("init [feature]")
|
|
|
112
113
|
.help(HELP)
|
|
113
114
|
.before(requireAuth_1.requireAuth)
|
|
114
115
|
.action(initAction);
|
|
115
|
-
function initAction(feature, options) {
|
|
116
|
+
async function initAction(feature, options) {
|
|
117
|
+
var _a;
|
|
116
118
|
if (feature && !featureNames.includes(feature)) {
|
|
117
119
|
return utils.reject(clc.bold(feature) +
|
|
118
120
|
" is not a supported feature; must be one of " +
|
|
@@ -152,66 +154,47 @@ function initAction(feature, options) {
|
|
|
152
154
|
fallback: {},
|
|
153
155
|
}),
|
|
154
156
|
};
|
|
155
|
-
let next;
|
|
156
157
|
if (process.platform === "win32") {
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
158
|
+
if (!(await (0, prompt_1.confirm)("Are you ready to proceed?"))) {
|
|
159
|
+
throw new error_1.FirebaseError("Aborted by user.", { exit: 1 });
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
if (feature) {
|
|
163
|
+
setup.featureArg = true;
|
|
164
|
+
setup.features = [feature];
|
|
161
165
|
}
|
|
162
166
|
else {
|
|
163
|
-
|
|
167
|
+
setup.features = await (0, prompt_1.checkbox)({
|
|
168
|
+
message: "Which Firebase features do you want to set up for this directory? " +
|
|
169
|
+
"Press Space to select features, then Enter to confirm your choices.",
|
|
170
|
+
choices: choices.filter((c) => !c.hidden),
|
|
171
|
+
});
|
|
164
172
|
}
|
|
165
|
-
|
|
166
|
-
.
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
clc.bold("firebase init [feature_name]"));
|
|
192
|
-
}
|
|
193
|
-
setup.features.unshift("project");
|
|
194
|
-
const allAccounts = (0, auth_1.getAllAccounts)();
|
|
195
|
-
if (allAccounts.length > 1) {
|
|
196
|
-
setup.features.unshift("account");
|
|
197
|
-
}
|
|
198
|
-
if (setup.features.includes("hosting") && setup.features.includes("hosting:github")) {
|
|
199
|
-
setup.features = setup.features.filter((f) => f !== "hosting:github");
|
|
200
|
-
}
|
|
201
|
-
return (0, init_1.init)(setup, config, options);
|
|
202
|
-
})
|
|
203
|
-
.then(() => {
|
|
204
|
-
logger_1.logger.info();
|
|
205
|
-
utils.logBullet("Writing configuration info to " + clc.bold("firebase.json") + "...");
|
|
206
|
-
config.writeProjectFile("firebase.json", setup.config);
|
|
207
|
-
utils.logBullet("Writing project information to " + clc.bold(".firebaserc") + "...");
|
|
208
|
-
config.writeProjectFile(".firebaserc", setup.rcfile);
|
|
209
|
-
if (!fsutils.fileExistsSync(config.path(".gitignore"))) {
|
|
210
|
-
utils.logBullet("Writing gitignore file to " + clc.bold(".gitignore") + "...");
|
|
211
|
-
config.writeProjectFile(".gitignore", GITIGNORE_TEMPLATE);
|
|
212
|
-
}
|
|
213
|
-
logger_1.logger.info();
|
|
214
|
-
utils.logSuccess("Firebase initialization complete!");
|
|
215
|
-
});
|
|
173
|
+
if (!setup.features || ((_a = setup.features) === null || _a === void 0 ? void 0 : _a.length) === 0) {
|
|
174
|
+
throw new error_1.FirebaseError("Must select at least one feature. Use " +
|
|
175
|
+
clc.bold(clc.underline("SPACEBAR")) +
|
|
176
|
+
" to select features, or specify a feature by running " +
|
|
177
|
+
clc.bold("firebase init [feature_name]"));
|
|
178
|
+
}
|
|
179
|
+
setup.features.unshift("project");
|
|
180
|
+
const allAccounts = (0, auth_1.getAllAccounts)();
|
|
181
|
+
if (allAccounts.length > 1) {
|
|
182
|
+
setup.features.unshift("account");
|
|
183
|
+
}
|
|
184
|
+
if (setup.features.includes("hosting") && setup.features.includes("hosting:github")) {
|
|
185
|
+
setup.features = setup.features.filter((f) => f !== "hosting:github");
|
|
186
|
+
}
|
|
187
|
+
await (0, init_1.init)(setup, config, options);
|
|
188
|
+
logger_1.logger.info();
|
|
189
|
+
utils.logBullet("Writing configuration info to " + clc.bold("firebase.json") + "...");
|
|
190
|
+
config.writeProjectFile("firebase.json", setup.config);
|
|
191
|
+
utils.logBullet("Writing project information to " + clc.bold(".firebaserc") + "...");
|
|
192
|
+
config.writeProjectFile(".firebaserc", setup.rcfile);
|
|
193
|
+
if (!fsutils.fileExistsSync(config.path(".gitignore"))) {
|
|
194
|
+
utils.logBullet("Writing gitignore file to " + clc.bold(".gitignore") + "...");
|
|
195
|
+
config.writeProjectFile(".gitignore", GITIGNORE_TEMPLATE);
|
|
196
|
+
}
|
|
197
|
+
logger_1.logger.info();
|
|
198
|
+
utils.logSuccess("Firebase initialization complete!");
|
|
216
199
|
}
|
|
217
200
|
exports.initAction = initAction;
|
package/lib/commands/login.js
CHANGED
|
@@ -28,11 +28,7 @@ exports.command = new command_1.Command("login")
|
|
|
28
28
|
}
|
|
29
29
|
if (!options.reauth) {
|
|
30
30
|
utils.logBullet("Firebase optionally collects CLI and Emulator Suite usage and error reporting information to help improve our products. Data is collected in accordance with Google's privacy policy (https://policies.google.com/privacy) and is not used to identify you.\n");
|
|
31
|
-
const collectUsage = await (0, prompt_1.
|
|
32
|
-
type: "confirm",
|
|
33
|
-
name: "collectUsage",
|
|
34
|
-
message: "Allow Firebase to collect CLI and Emulator Suite usage and error reporting information?",
|
|
35
|
-
});
|
|
31
|
+
const collectUsage = await (0, prompt_1.confirm)("Allow Firebase to collect CLI and Emulator Suite usage and error reporting information?");
|
|
36
32
|
configstore_1.configstore.set("usage", collectUsage);
|
|
37
33
|
if (collectUsage) {
|
|
38
34
|
utils.logBullet("To change your data collection preference at any time, run `firebase logout` and log in again.");
|
package/lib/commands/logout.js
CHANGED
|
@@ -5,8 +5,8 @@ const command_1 = require("../command");
|
|
|
5
5
|
const logger_1 = require("../logger");
|
|
6
6
|
const clc = require("colorette");
|
|
7
7
|
const utils = require("../utils");
|
|
8
|
-
const prompt_1 = require("../prompt");
|
|
9
8
|
const auth_1 = require("../auth");
|
|
9
|
+
const prompt_1 = require("../prompt");
|
|
10
10
|
exports.command = new command_1.Command("logout [email]")
|
|
11
11
|
.description("log the CLI out of Firebase")
|
|
12
12
|
.action(logoutAction);
|
|
@@ -38,8 +38,7 @@ async function logoutAction(email, options) {
|
|
|
38
38
|
value: a,
|
|
39
39
|
};
|
|
40
40
|
});
|
|
41
|
-
newDefaultAccount = await (0, prompt_1.
|
|
42
|
-
type: "list",
|
|
41
|
+
newDefaultAccount = await (0, prompt_1.select)({
|
|
43
42
|
message: "You are logging out of your default account, which account should become the new default?",
|
|
44
43
|
choices,
|
|
45
44
|
});
|
package/lib/commands/open.js
CHANGED
|
@@ -67,8 +67,7 @@ exports.command = new command_1.Command("open [link]")
|
|
|
67
67
|
throw new error_1.FirebaseError("Unrecognized link name. Valid links are:\n\n" + LINKS.map((l) => l.arg).join("\n"));
|
|
68
68
|
}
|
|
69
69
|
if (!link) {
|
|
70
|
-
const name = await (0, prompt_1.
|
|
71
|
-
type: "list",
|
|
70
|
+
const name = await (0, prompt_1.select)({
|
|
72
71
|
message: "What link would you like to open?",
|
|
73
72
|
choices: CHOICES,
|
|
74
73
|
});
|
|
@@ -4,7 +4,6 @@ exports.command = void 0;
|
|
|
4
4
|
const command_1 = require("../command");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const projects_1 = require("../management/projects");
|
|
7
|
-
const prompt_1 = require("../prompt");
|
|
8
7
|
const requireAuth_1 = require("../requireAuth");
|
|
9
8
|
exports.command = new command_1.Command("projects:create [projectId]")
|
|
10
9
|
.description("creates a new Google Cloud Platform project, then adds Firebase resources to the project")
|
|
@@ -18,7 +17,7 @@ exports.command = new command_1.Command("projects:create [projectId]")
|
|
|
18
17
|
throw new error_1.FirebaseError("Invalid argument, please provide only one type of project parent (organization or folder)");
|
|
19
18
|
}
|
|
20
19
|
if (!options.nonInteractive) {
|
|
21
|
-
|
|
20
|
+
options = Object.assign(Object.assign({}, options), (await (0, projects_1.promptProjectCreation)()));
|
|
22
21
|
}
|
|
23
22
|
if (!options.projectId) {
|
|
24
23
|
throw new error_1.FirebaseError("Project ID cannot be empty");
|
|
@@ -35,13 +35,13 @@ exports.command = new command_1.Command("remoteconfig:rollback")
|
|
|
35
35
|
`. ` +
|
|
36
36
|
`Invalid Version Number`);
|
|
37
37
|
}
|
|
38
|
-
const
|
|
39
|
-
type: "confirm",
|
|
40
|
-
name: "force",
|
|
38
|
+
const proceed = await (0, prompt_1.confirm)({
|
|
41
39
|
message: "Proceed to rollback template to version " + targetVersion + "?",
|
|
42
40
|
default: false,
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
force: options.force,
|
|
42
|
+
nonInteractive: options.nonInteractive,
|
|
43
|
+
});
|
|
44
|
+
if (!proceed) {
|
|
45
45
|
return;
|
|
46
46
|
}
|
|
47
47
|
return (0, rollback_1.rollbackTemplate)((0, projectUtils_1.needProjectId)(options), targetVersion);
|
package/lib/commands/use.js
CHANGED
|
@@ -9,6 +9,7 @@ const prompt_1 = require("../prompt");
|
|
|
9
9
|
const requireAuth_1 = require("../requireAuth");
|
|
10
10
|
const command_2 = require("../command");
|
|
11
11
|
const utils = require("../utils");
|
|
12
|
+
const error_1 = require("../error");
|
|
12
13
|
function listAliases(options) {
|
|
13
14
|
if (options.rc.hasProjects) {
|
|
14
15
|
logger_1.logger.info("Project aliases for", clc.bold(options.projectRoot || "") + ":");
|
|
@@ -29,6 +30,106 @@ function listAliases(options) {
|
|
|
29
30
|
function verifyMessage(name) {
|
|
30
31
|
return "please verify project " + clc.bold(name) + " exists and you have access.";
|
|
31
32
|
}
|
|
33
|
+
async function setNewActive(projectOrAlias, aliasOpt, options) {
|
|
34
|
+
let project;
|
|
35
|
+
const hasAlias = options.rc.hasProjectAlias(projectOrAlias);
|
|
36
|
+
const resolvedProject = options.rc.resolveAlias(projectOrAlias);
|
|
37
|
+
(0, command_2.validateProjectId)(resolvedProject);
|
|
38
|
+
try {
|
|
39
|
+
project = await (0, projects_1.getProject)(resolvedProject);
|
|
40
|
+
}
|
|
41
|
+
catch (_a) {
|
|
42
|
+
throw new error_1.FirebaseError("Invalid project selection, " + verifyMessage(projectOrAlias));
|
|
43
|
+
}
|
|
44
|
+
if (aliasOpt) {
|
|
45
|
+
if (!project) {
|
|
46
|
+
throw new error_1.FirebaseError(`Cannot create alias ${clc.bold(aliasOpt)}, ${verifyMessage(projectOrAlias)}`);
|
|
47
|
+
}
|
|
48
|
+
options.rc.addProjectAlias(aliasOpt, projectOrAlias);
|
|
49
|
+
logger_1.logger.info("Created alias", clc.bold(aliasOpt), "for", resolvedProject + ".");
|
|
50
|
+
}
|
|
51
|
+
if (hasAlias) {
|
|
52
|
+
if (!project) {
|
|
53
|
+
throw new error_1.FirebaseError(`Unable to use alias ${clc.bold(projectOrAlias)}, ${verifyMessage(resolvedProject)}`);
|
|
54
|
+
}
|
|
55
|
+
utils.makeActiveProject(options.projectRoot, projectOrAlias);
|
|
56
|
+
logger_1.logger.info("Now using alias", clc.bold(projectOrAlias), "(" + resolvedProject + ")");
|
|
57
|
+
}
|
|
58
|
+
else if (project) {
|
|
59
|
+
utils.makeActiveProject(options.projectRoot, projectOrAlias);
|
|
60
|
+
logger_1.logger.info("Now using project", clc.bold(projectOrAlias));
|
|
61
|
+
}
|
|
62
|
+
else {
|
|
63
|
+
throw new error_1.FirebaseError(`Invalid project selection, ${verifyMessage(projectOrAlias)}`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
function unalias(alias, options) {
|
|
67
|
+
if (options.rc.hasProjectAlias(alias)) {
|
|
68
|
+
options.rc.removeProjectAlias(alias);
|
|
69
|
+
logger_1.logger.info("Removed alias", clc.bold(alias));
|
|
70
|
+
logger_1.logger.info();
|
|
71
|
+
listAliases(options);
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
async function addAlias(options) {
|
|
75
|
+
if (options.nonInteractive) {
|
|
76
|
+
return utils.reject("Cannot run " +
|
|
77
|
+
clc.bold("firebase use --add") +
|
|
78
|
+
" in non-interactive mode. Use " +
|
|
79
|
+
clc.bold("firebase use <project_id> --alias <alias>") +
|
|
80
|
+
" instead.");
|
|
81
|
+
}
|
|
82
|
+
const projects = await (0, projects_1.listFirebaseProjects)();
|
|
83
|
+
const results = {};
|
|
84
|
+
const project = await (0, prompt_1.select)({
|
|
85
|
+
message: "Which project do you want to add?",
|
|
86
|
+
choices: projects.map((p) => p.projectId).sort(),
|
|
87
|
+
});
|
|
88
|
+
const alias = await (0, prompt_1.input)({
|
|
89
|
+
message: "What alias do you want to use for this project? (e.g. staging)",
|
|
90
|
+
validate: (input) => {
|
|
91
|
+
return input && input.length > 0;
|
|
92
|
+
},
|
|
93
|
+
});
|
|
94
|
+
options.rc.addProjectAlias(alias, project);
|
|
95
|
+
utils.makeActiveProject(options.projectRoot, results.alias);
|
|
96
|
+
logger_1.logger.info();
|
|
97
|
+
logger_1.logger.info("Created alias", clc.bold(results.alias || ""), "for", results.project + ".");
|
|
98
|
+
logger_1.logger.info("Now using alias", clc.bold(results.alias || "") + " (" + results.project + ")");
|
|
99
|
+
}
|
|
100
|
+
function clearAlias(options) {
|
|
101
|
+
utils.makeActiveProject(options.projectRoot, undefined);
|
|
102
|
+
delete options.projectAlias;
|
|
103
|
+
delete options.project;
|
|
104
|
+
logger_1.logger.info("Cleared active project.");
|
|
105
|
+
logger_1.logger.info();
|
|
106
|
+
listAliases(options);
|
|
107
|
+
}
|
|
108
|
+
async function genericUse(options) {
|
|
109
|
+
if (options.nonInteractive || !process.stdout.isTTY) {
|
|
110
|
+
if (options.project) {
|
|
111
|
+
logger_1.logger.info(options.project);
|
|
112
|
+
return options.project;
|
|
113
|
+
}
|
|
114
|
+
return utils.reject("No active project");
|
|
115
|
+
}
|
|
116
|
+
if (options.projectAlias) {
|
|
117
|
+
logger_1.logger.info("Active Project:", clc.bold(clc.cyan(options.projectAlias + " (" + options.project + ")")));
|
|
118
|
+
}
|
|
119
|
+
else if (options.project) {
|
|
120
|
+
logger_1.logger.info("Active Project:", clc.bold(clc.cyan(options.project)));
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
let msg = "No project is currently active";
|
|
124
|
+
if (options.rc.hasProjects) {
|
|
125
|
+
msg += ", and no aliases have been created.";
|
|
126
|
+
}
|
|
127
|
+
logger_1.logger.info(msg + ".");
|
|
128
|
+
}
|
|
129
|
+
logger_1.logger.info();
|
|
130
|
+
listAliases(options);
|
|
131
|
+
return options.project;
|
|
132
|
+
}
|
|
32
133
|
exports.command = new command_1.Command("use [alias_or_project_id]")
|
|
33
134
|
.description("set an active Firebase project for your working directory")
|
|
34
135
|
.option("--add", "create a new project alias interactively")
|
|
@@ -49,117 +150,16 @@ exports.command = new command_1.Command("use [alias_or_project_id]")
|
|
|
49
150
|
" to start a project directory in the current folder.");
|
|
50
151
|
}
|
|
51
152
|
if (newActive) {
|
|
52
|
-
|
|
53
|
-
const hasAlias = options.rc.hasProjectAlias(newActive);
|
|
54
|
-
const resolvedProject = options.rc.resolveAlias(newActive);
|
|
55
|
-
(0, command_2.validateProjectId)(resolvedProject);
|
|
56
|
-
return (0, projects_1.getProject)(resolvedProject)
|
|
57
|
-
.then((foundProject) => {
|
|
58
|
-
project = foundProject;
|
|
59
|
-
})
|
|
60
|
-
.catch(() => {
|
|
61
|
-
return utils.reject("Invalid project selection, " + verifyMessage(newActive));
|
|
62
|
-
})
|
|
63
|
-
.then(() => {
|
|
64
|
-
if (aliasOpt) {
|
|
65
|
-
if (!project) {
|
|
66
|
-
return utils.reject("Cannot create alias " + clc.bold(aliasOpt) + ", " + verifyMessage(newActive));
|
|
67
|
-
}
|
|
68
|
-
options.rc.addProjectAlias(aliasOpt, newActive);
|
|
69
|
-
logger_1.logger.info("Created alias", clc.bold(aliasOpt), "for", resolvedProject + ".");
|
|
70
|
-
}
|
|
71
|
-
if (hasAlias) {
|
|
72
|
-
if (!project) {
|
|
73
|
-
return utils.reject("Unable to use alias " +
|
|
74
|
-
clc.bold(newActive) +
|
|
75
|
-
", " +
|
|
76
|
-
verifyMessage(resolvedProject));
|
|
77
|
-
}
|
|
78
|
-
utils.makeActiveProject(options.projectRoot, newActive);
|
|
79
|
-
logger_1.logger.info("Now using alias", clc.bold(newActive), "(" + resolvedProject + ")");
|
|
80
|
-
}
|
|
81
|
-
else if (project) {
|
|
82
|
-
utils.makeActiveProject(options.projectRoot, newActive);
|
|
83
|
-
logger_1.logger.info("Now using project", clc.bold(newActive));
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
return utils.reject("Invalid project selection, " + verifyMessage(newActive));
|
|
87
|
-
}
|
|
88
|
-
});
|
|
89
|
-
}
|
|
90
|
-
else if (options.unalias) {
|
|
91
|
-
if (options.rc.hasProjectAlias(options.unalias)) {
|
|
92
|
-
options.rc.removeProjectAlias(options.unalias);
|
|
93
|
-
logger_1.logger.info("Removed alias", clc.bold(options.unalias));
|
|
94
|
-
logger_1.logger.info();
|
|
95
|
-
listAliases(options);
|
|
96
|
-
}
|
|
153
|
+
return setNewActive(newActive, aliasOpt, options);
|
|
97
154
|
}
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
return utils.reject("Cannot run " +
|
|
101
|
-
clc.bold("firebase use --add") +
|
|
102
|
-
" in non-interactive mode. Use " +
|
|
103
|
-
clc.bold("firebase use <project_id> --alias <alias>") +
|
|
104
|
-
" instead.");
|
|
105
|
-
}
|
|
106
|
-
return (0, projects_1.listFirebaseProjects)().then((projects) => {
|
|
107
|
-
const results = {};
|
|
108
|
-
return (0, prompt_1.prompt)(results, [
|
|
109
|
-
{
|
|
110
|
-
type: "list",
|
|
111
|
-
name: "project",
|
|
112
|
-
message: "Which project do you want to add?",
|
|
113
|
-
choices: projects.map((p) => p.projectId).sort(),
|
|
114
|
-
},
|
|
115
|
-
{
|
|
116
|
-
type: "input",
|
|
117
|
-
name: "alias",
|
|
118
|
-
message: "What alias do you want to use for this project? (e.g. staging)",
|
|
119
|
-
validate: (input) => {
|
|
120
|
-
return input && input.length > 0;
|
|
121
|
-
},
|
|
122
|
-
},
|
|
123
|
-
]).then(() => {
|
|
124
|
-
options.rc.addProjectAlias(results.alias, results.project);
|
|
125
|
-
utils.makeActiveProject(options.projectRoot, results.alias);
|
|
126
|
-
logger_1.logger.info();
|
|
127
|
-
logger_1.logger.info("Created alias", clc.bold(results.alias || ""), "for", results.project + ".");
|
|
128
|
-
logger_1.logger.info("Now using alias", clc.bold(results.alias || "") + " (" + results.project + ")");
|
|
129
|
-
});
|
|
130
|
-
});
|
|
131
|
-
}
|
|
132
|
-
else if (options.clear) {
|
|
133
|
-
utils.makeActiveProject(options.projectRoot, undefined);
|
|
134
|
-
options.projectAlias = null;
|
|
135
|
-
options.project = null;
|
|
136
|
-
logger_1.logger.info("Cleared active project.");
|
|
137
|
-
logger_1.logger.info();
|
|
138
|
-
listAliases(options);
|
|
155
|
+
if (options.unalias) {
|
|
156
|
+
return unalias(options.unalias, options);
|
|
139
157
|
}
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
}
|
|
146
|
-
return utils.reject("No active project");
|
|
147
|
-
}
|
|
148
|
-
if (options.projectAlias) {
|
|
149
|
-
logger_1.logger.info("Active Project:", clc.bold(clc.cyan(options.projectAlias + " (" + options.project + ")")));
|
|
150
|
-
}
|
|
151
|
-
else if (options.project) {
|
|
152
|
-
logger_1.logger.info("Active Project:", clc.bold(clc.cyan(options.project)));
|
|
153
|
-
}
|
|
154
|
-
else {
|
|
155
|
-
let msg = "No project is currently active";
|
|
156
|
-
if (options.rc.hasProjects) {
|
|
157
|
-
msg += ", and no aliases have been created.";
|
|
158
|
-
}
|
|
159
|
-
logger_1.logger.info(msg + ".");
|
|
160
|
-
}
|
|
161
|
-
logger_1.logger.info();
|
|
162
|
-
listAliases(options);
|
|
163
|
-
return options.project;
|
|
158
|
+
if (options.add) {
|
|
159
|
+
return addAlias(options);
|
|
160
|
+
}
|
|
161
|
+
if (options.clear) {
|
|
162
|
+
return clearAlias(options);
|
|
164
163
|
}
|
|
164
|
+
return genericUse(options);
|
|
165
165
|
});
|
package/lib/config.js
CHANGED
|
@@ -179,8 +179,7 @@ class Config {
|
|
|
179
179
|
existingContent = fsutils.readFile(writeTo);
|
|
180
180
|
}
|
|
181
181
|
if (existingContent && existingContent !== content && !force) {
|
|
182
|
-
next = await (0, prompt_1.
|
|
183
|
-
type: "confirm",
|
|
182
|
+
next = await (0, prompt_1.confirm)({
|
|
184
183
|
message: "File " + clc.underline(path) + " already exists. Overwrite?",
|
|
185
184
|
default: !!confirmByDefault,
|
|
186
185
|
});
|
package/lib/dataconnect/build.js
CHANGED
|
@@ -44,9 +44,8 @@ async function handleBuildErrors(errors, nonInteractive, force, dryRun) {
|
|
|
44
44
|
throw new error_1.FirebaseError("Explicit acknowledgement required for breaking schema or connector changes and new insecure operations. Rerun this command with --force to deploy these changes.");
|
|
45
45
|
}
|
|
46
46
|
else if (!nonInteractive && !force && !dryRun) {
|
|
47
|
-
const result = await (0, prompt_1.
|
|
47
|
+
const result = await (0, prompt_1.select)({
|
|
48
48
|
message: "Would you like to proceed with these changes?",
|
|
49
|
-
type: "list",
|
|
50
49
|
choices,
|
|
51
50
|
default: "abort",
|
|
52
51
|
});
|
|
@@ -59,9 +58,8 @@ async function handleBuildErrors(errors, nonInteractive, force, dryRun) {
|
|
|
59
58
|
utils.logLabeledWarning("dataconnect", `There are existing insecure operations or changes in your schema or connectors that may cause unexpected behavior in your existing applications:\n` +
|
|
60
59
|
(0, graphqlError_1.prettifyTable)(interactiveAcks));
|
|
61
60
|
if (!nonInteractive && !force && !dryRun) {
|
|
62
|
-
const result = await (0, prompt_1.
|
|
61
|
+
const result = await (0, prompt_1.select)({
|
|
63
62
|
message: "Would you like to proceed with these changes?",
|
|
64
|
-
type: "list",
|
|
65
63
|
choices,
|
|
66
64
|
default: "proceed",
|
|
67
65
|
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.upsertConnector = exports.listConnectors = exports.deleteConnector = exports.getConnector = exports.deleteSchema = exports.upsertSchema = exports.getSchema = exports.deleteService = exports.createService = exports.listAllServices = exports.getService = exports.listLocations = void 0;
|
|
3
|
+
exports.upsertConnector = exports.listConnectors = exports.deleteConnector = exports.getConnector = exports.deleteSchema = exports.upsertSchema = exports.listSchemas = exports.getSchema = exports.deleteService = exports.createService = exports.listAllServices = exports.getService = exports.listLocations = void 0;
|
|
4
4
|
const api_1 = require("../api");
|
|
5
5
|
const apiv2_1 = require("../apiv2");
|
|
6
6
|
const operationPoller = require("../operation-poller");
|
|
@@ -70,6 +70,25 @@ async function getSchema(serviceName) {
|
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
exports.getSchema = getSchema;
|
|
73
|
+
async function listSchemas(serviceName, fields = []) {
|
|
74
|
+
const schemas = [];
|
|
75
|
+
const getNextPage = async (pageToken = "") => {
|
|
76
|
+
const res = await dataconnectClient().get(`${serviceName}/schemas`, {
|
|
77
|
+
queryParams: {
|
|
78
|
+
pageSize: PAGE_SIZE_MAX,
|
|
79
|
+
pageToken,
|
|
80
|
+
fields: fields.join(","),
|
|
81
|
+
},
|
|
82
|
+
});
|
|
83
|
+
schemas.push(...(res.body.schemas || []));
|
|
84
|
+
if (res.body.nextPageToken) {
|
|
85
|
+
await getNextPage(res.body.nextPageToken);
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
await getNextPage();
|
|
89
|
+
return schemas;
|
|
90
|
+
}
|
|
91
|
+
exports.listSchemas = listSchemas;
|
|
73
92
|
async function upsertSchema(schema, validateOnly = false) {
|
|
74
93
|
const op = await dataconnectClient().patch(`${schema.name}`, schema, {
|
|
75
94
|
queryParams: {
|
|
@@ -307,12 +307,7 @@ async function promptForSchemaMigration(options, instanceName, databaseId, err,
|
|
|
307
307
|
{ name: "Abort changes", value: "none" },
|
|
308
308
|
];
|
|
309
309
|
const defaultValue = validationMode === "STRICT_AFTER_COMPATIBLE" ? "none" : "all";
|
|
310
|
-
return await (0, prompt_1.
|
|
311
|
-
message: message,
|
|
312
|
-
type: "list",
|
|
313
|
-
choices,
|
|
314
|
-
default: defaultValue,
|
|
315
|
-
});
|
|
310
|
+
return await (0, prompt_1.select)({ message, choices, default: defaultValue });
|
|
316
311
|
}
|
|
317
312
|
if (!validateOnly) {
|
|
318
313
|
throw new error_1.FirebaseError("Command aborted. Your database schema is incompatible with your Data Connect schema. Run `firebase dataconnect:sql:migrate` to migrate your database schema");
|
|
@@ -219,9 +219,7 @@ function populateDefaultParams(config) {
|
|
|
219
219
|
async function handleSecret(secretParam, projectId) {
|
|
220
220
|
const metadata = await secretManager.getSecretMetadata(projectId, secretParam.name, "latest");
|
|
221
221
|
if (!metadata.secret) {
|
|
222
|
-
const secretValue = await (0, prompt_1.
|
|
223
|
-
name: secretParam.name,
|
|
224
|
-
type: "password",
|
|
222
|
+
const secretValue = await (0, prompt_1.password)({
|
|
225
223
|
message: `This secret will be stored in Cloud Secret Manager (https://cloud.google.com/secret-manager/pricing) as ${secretParam.name}. Enter a value for ${secretParam.label || secretParam.name}:`,
|
|
226
224
|
});
|
|
227
225
|
await secretManager.createSecret(projectId, secretParam.name, (0, secretManager_1.labels)());
|
|
@@ -454,31 +452,28 @@ async function promptResourceStrings(prompt, input, projectId) {
|
|
|
454
452
|
function shouldRetry(obj) {
|
|
455
453
|
return typeof obj === "object" && obj.message !== undefined;
|
|
456
454
|
}
|
|
457
|
-
async function promptText(prompt,
|
|
458
|
-
const res = await (0, prompt_1.
|
|
459
|
-
type: "input",
|
|
455
|
+
async function promptText(prompt, textInput, resolvedDefault, converter) {
|
|
456
|
+
const res = await (0, prompt_1.input)({
|
|
460
457
|
default: resolvedDefault,
|
|
461
458
|
message: prompt,
|
|
462
459
|
});
|
|
463
|
-
if (
|
|
464
|
-
const userRe = new RegExp(
|
|
460
|
+
if (textInput.text.validationRegex) {
|
|
461
|
+
const userRe = new RegExp(textInput.text.validationRegex);
|
|
465
462
|
if (!userRe.test(res)) {
|
|
466
|
-
logger_1.logger.error(
|
|
463
|
+
logger_1.logger.error(textInput.text.validationErrorMessage ||
|
|
467
464
|
`Input did not match provided validator ${userRe.toString()}, retrying...`);
|
|
468
|
-
return promptText(prompt,
|
|
465
|
+
return promptText(prompt, textInput, resolvedDefault, converter);
|
|
469
466
|
}
|
|
470
467
|
}
|
|
471
468
|
const converted = converter(res.toString());
|
|
472
469
|
if (shouldRetry(converted)) {
|
|
473
470
|
logger_1.logger.error(converted.message);
|
|
474
|
-
return promptText(prompt,
|
|
471
|
+
return promptText(prompt, textInput, resolvedDefault, converter);
|
|
475
472
|
}
|
|
476
473
|
return converted;
|
|
477
474
|
}
|
|
478
475
|
async function promptSelect(prompt, input, resolvedDefault, converter) {
|
|
479
|
-
const response = await (0, prompt_1.
|
|
480
|
-
name: "input",
|
|
481
|
-
type: "list",
|
|
476
|
+
const response = await (0, prompt_1.select)({
|
|
482
477
|
default: resolvedDefault,
|
|
483
478
|
message: prompt,
|
|
484
479
|
choices: input.select.options.map((option) => {
|
|
@@ -497,9 +492,7 @@ async function promptSelect(prompt, input, resolvedDefault, converter) {
|
|
|
497
492
|
return converted;
|
|
498
493
|
}
|
|
499
494
|
async function promptSelectMultiple(prompt, input, resolvedDefault, converter) {
|
|
500
|
-
const response = await (0, prompt_1.
|
|
501
|
-
name: "input",
|
|
502
|
-
type: "checkbox",
|
|
495
|
+
const response = await (0, prompt_1.checkbox)({
|
|
503
496
|
default: resolvedDefault,
|
|
504
497
|
message: prompt,
|
|
505
498
|
choices: input.multiSelect.options.map((option) => {
|
|
@@ -39,12 +39,7 @@ async function promptForFailurePolicies(options, want, have) {
|
|
|
39
39
|
exit: 1,
|
|
40
40
|
});
|
|
41
41
|
}
|
|
42
|
-
const proceed = await (0, prompt_1.
|
|
43
|
-
type: "confirm",
|
|
44
|
-
name: "confirm",
|
|
45
|
-
default: false,
|
|
46
|
-
message: "Would you like to proceed with deployment?",
|
|
47
|
-
});
|
|
42
|
+
const proceed = await (0, prompt_1.confirm)("Would you like to proceed with deployment?");
|
|
48
43
|
if (!proceed) {
|
|
49
44
|
throw new error_1.FirebaseError("Deployment canceled.", { exit: 1 });
|
|
50
45
|
}
|
|
@@ -105,10 +100,7 @@ async function promptForUnsafeMigration(fnsToUpdate, options) {
|
|
|
105
100
|
return safeUpdates;
|
|
106
101
|
}
|
|
107
102
|
for (const eu of unsafeUpdates) {
|
|
108
|
-
const shouldUpdate = await (0, prompt_1.
|
|
109
|
-
type: "confirm",
|
|
110
|
-
name: "confirm",
|
|
111
|
-
default: false,
|
|
103
|
+
const shouldUpdate = await (0, prompt_1.confirm)({
|
|
112
104
|
message: `[${(0, functionsDeployHelper_1.getFunctionLabel)(eu.endpoint)}] Would you like to proceed with the unsafe migration?`,
|
|
113
105
|
});
|
|
114
106
|
if (shouldUpdate) {
|
|
@@ -177,12 +169,7 @@ async function promptForMinInstances(options, want, have) {
|
|
|
177
169
|
"\n\n" +
|
|
178
170
|
costLine;
|
|
179
171
|
utils.logLabeledWarning("functions", warnMessage);
|
|
180
|
-
const proceed = await (0, prompt_1.
|
|
181
|
-
type: "confirm",
|
|
182
|
-
name: "confirm",
|
|
183
|
-
default: false,
|
|
184
|
-
message: "Would you like to proceed with deployment?",
|
|
185
|
-
});
|
|
172
|
+
const proceed = await (0, prompt_1.confirm)("Would you like to proceed with deployment?");
|
|
186
173
|
if (!proceed) {
|
|
187
174
|
throw new error_1.FirebaseError("Deployment canceled.", { exit: 1 });
|
|
188
175
|
}
|
|
@@ -200,19 +187,10 @@ async function promptForCleanupPolicyDays(options, locations) {
|
|
|
200
187
|
`Pass the --force option to automatically set up a cleanup policy or ` +
|
|
201
188
|
"run 'firebase functions:artifacts:setpolicy' to manually set up a cleanup policy.");
|
|
202
189
|
}
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
name: "days",
|
|
206
|
-
default: artifacts.DEFAULT_CLEANUP_DAYS.toString(),
|
|
190
|
+
return await (0, prompt_1.number)({
|
|
191
|
+
default: artifacts.DEFAULT_CLEANUP_DAYS,
|
|
207
192
|
message: "How many days do you want to keep container images before they're deleted?",
|
|
208
|
-
validate: (
|
|
209
|
-
const days = parseInt(input);
|
|
210
|
-
if (isNaN(days) || days < 0) {
|
|
211
|
-
return "Please enter a non-negative number";
|
|
212
|
-
}
|
|
213
|
-
return true;
|
|
214
|
-
},
|
|
193
|
+
validate: (days) => !days || isNaN(days) || days < 0 ? "Please enter a non-negative number" : true,
|
|
215
194
|
});
|
|
216
|
-
return parseInt(result);
|
|
217
195
|
}
|
|
218
196
|
exports.promptForCleanupPolicyDays = promptForCleanupPolicyDays;
|