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
|
@@ -38,8 +38,7 @@ async function doSetup(setup, config, options) {
|
|
|
38
38
|
value: "overwrite",
|
|
39
39
|
},
|
|
40
40
|
];
|
|
41
|
-
const initOpt = await (0, prompt_1.
|
|
42
|
-
type: "list",
|
|
41
|
+
const initOpt = await (0, prompt_1.select)({
|
|
43
42
|
message: "Would you like to initialize a new codebase, or overwrite an existing one?",
|
|
44
43
|
default: "new",
|
|
45
44
|
choices,
|
|
@@ -66,10 +65,7 @@ async function initNewCodebase(setup, config) {
|
|
|
66
65
|
if (attempts++ >= MAX_ATTEMPTS) {
|
|
67
66
|
throw new error_1.FirebaseError("Exceeded max number of attempts to input valid codebase name. Please restart.");
|
|
68
67
|
}
|
|
69
|
-
codebase = await (0, prompt_1.
|
|
70
|
-
type: "input",
|
|
71
|
-
message: "What should be the name of this codebase?",
|
|
72
|
-
});
|
|
68
|
+
codebase = await (0, prompt_1.input)("What should be the name of this codebase?");
|
|
73
69
|
try {
|
|
74
70
|
(0, projectConfig_1.validateCodebase)(codebase);
|
|
75
71
|
(0, projectConfig_1.assertUnique)(setup.config.functions, "codebase", codebase);
|
|
@@ -85,8 +81,7 @@ async function initNewCodebase(setup, config) {
|
|
|
85
81
|
throw new error_1.FirebaseError("Exceeded max number of attempts to input valid source. Please restart.");
|
|
86
82
|
}
|
|
87
83
|
attempts++;
|
|
88
|
-
source = await (0, prompt_1.
|
|
89
|
-
type: "input",
|
|
84
|
+
source = await (0, prompt_1.input)({
|
|
90
85
|
message: `In what sub-directory would you like to initialize your functions for codebase ${clc.bold(codebase)}?`,
|
|
91
86
|
default: codebase,
|
|
92
87
|
});
|
|
@@ -114,8 +109,7 @@ async function overwriteCodebase(setup, config) {
|
|
|
114
109
|
name: cfg["codebase"],
|
|
115
110
|
value: cfg["codebase"],
|
|
116
111
|
}));
|
|
117
|
-
codebase = await (0, prompt_1.
|
|
118
|
-
type: "list",
|
|
112
|
+
codebase = await (0, prompt_1.select)({
|
|
119
113
|
message: "Which codebase would you like to overwrite?",
|
|
120
114
|
choices,
|
|
121
115
|
});
|
|
@@ -142,13 +136,12 @@ async function languageSetup(setup, config) {
|
|
|
142
136
|
name: "TypeScript",
|
|
143
137
|
value: "typescript",
|
|
144
138
|
},
|
|
139
|
+
{
|
|
140
|
+
name: "Python",
|
|
141
|
+
value: "python",
|
|
142
|
+
},
|
|
145
143
|
];
|
|
146
|
-
|
|
147
|
-
name: "Python",
|
|
148
|
-
value: "python",
|
|
149
|
-
});
|
|
150
|
-
const language = await (0, prompt_1.promptOnce)({
|
|
151
|
-
type: "list",
|
|
144
|
+
const language = await (0, prompt_1.select)({
|
|
152
145
|
message: "What language would you like to use to write Cloud Functions?",
|
|
153
146
|
default: "javascript",
|
|
154
147
|
choices,
|
|
@@ -10,35 +10,21 @@ const PACKAGE_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functio
|
|
|
10
10
|
const PACKAGE_NO_LINTING_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/package.nolint.json");
|
|
11
11
|
const ESLINT_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/_eslintrc");
|
|
12
12
|
const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/javascript/_gitignore");
|
|
13
|
-
function setup(setup, config) {
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
config.askWriteProjectFile(`${setup.functions.source}/.eslintrc.js`, ESLINT_TEMPLATE);
|
|
30
|
-
});
|
|
31
|
-
}
|
|
32
|
-
return config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_NO_LINTING_TEMPLATE);
|
|
33
|
-
})
|
|
34
|
-
.then(() => {
|
|
35
|
-
return config.askWriteProjectFile(`${setup.functions.source}/index.js`, INDEX_TEMPLATE);
|
|
36
|
-
})
|
|
37
|
-
.then(() => {
|
|
38
|
-
return config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
|
|
39
|
-
})
|
|
40
|
-
.then(() => {
|
|
41
|
-
return (0, npm_dependencies_1.askInstallDependencies)(setup.functions, config);
|
|
42
|
-
});
|
|
13
|
+
async function setup(setup, config) {
|
|
14
|
+
setup.functions.lint =
|
|
15
|
+
setup.functions.lint ||
|
|
16
|
+
(await (0, prompt_1.confirm)("Do you want to use ESLint to catch probable bugs and enforce style?"));
|
|
17
|
+
if (setup.functions.lint) {
|
|
18
|
+
const cbconfig = (0, projectConfig_1.configForCodebase)(setup.config.functions, setup.functions.codebase);
|
|
19
|
+
cbconfig.predeploy = ['npm --prefix "$RESOURCE_DIR" run lint'];
|
|
20
|
+
await config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_LINTING_TEMPLATE);
|
|
21
|
+
await config.askWriteProjectFile(`${setup.functions.source}/.eslintrc.js`, ESLINT_TEMPLATE);
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
await config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_NO_LINTING_TEMPLATE);
|
|
25
|
+
}
|
|
26
|
+
await config.askWriteProjectFile(`${setup.functions.source}/index.js`, INDEX_TEMPLATE);
|
|
27
|
+
await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
|
|
28
|
+
await (0, npm_dependencies_1.askInstallDependencies)(setup.functions, config);
|
|
43
29
|
}
|
|
44
30
|
exports.setup = setup;
|
|
@@ -5,14 +5,10 @@ const logger_1 = require("../../../logger");
|
|
|
5
5
|
const prompt_1 = require("../../../prompt");
|
|
6
6
|
const spawn_1 = require("../../spawn");
|
|
7
7
|
async function askInstallDependencies(setup, config) {
|
|
8
|
-
await (0, prompt_1.
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
message: "Do you want to install dependencies with npm now?",
|
|
13
|
-
default: true,
|
|
14
|
-
},
|
|
15
|
-
]);
|
|
8
|
+
setup.npm = await (0, prompt_1.confirm)({
|
|
9
|
+
message: "Do you want to install dependencies with npm now?",
|
|
10
|
+
default: true,
|
|
11
|
+
});
|
|
16
12
|
if (setup.npm) {
|
|
17
13
|
try {
|
|
18
14
|
await (0, spawn_1.wrapSpawn)("npm", ["install"], config.projectDir + `/${setup.source}`);
|
|
@@ -25,9 +25,7 @@ async function setup(setup, config) {
|
|
|
25
25
|
venvProcess.on("exit", resolve);
|
|
26
26
|
venvProcess.on("error", reject);
|
|
27
27
|
});
|
|
28
|
-
const install = await (0, prompt_1.
|
|
29
|
-
name: "install",
|
|
30
|
-
type: "confirm",
|
|
28
|
+
const install = await (0, prompt_1.confirm)({
|
|
31
29
|
message: "Do you want to install dependencies now?",
|
|
32
30
|
default: true,
|
|
33
31
|
});
|
|
@@ -12,48 +12,29 @@ const TSCONFIG_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/type
|
|
|
12
12
|
const TSCONFIG_DEV_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/tsconfig.dev.json");
|
|
13
13
|
const INDEX_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/index.ts");
|
|
14
14
|
const GITIGNORE_TEMPLATE = (0, templates_1.readTemplateSync)("init/functions/typescript/_gitignore");
|
|
15
|
-
function setup(setup, config) {
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
]
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
cbconfig.predeploy
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
return config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_NO_LINTING_TEMPLATE);
|
|
40
|
-
})
|
|
41
|
-
.then(() => {
|
|
42
|
-
return config.askWriteProjectFile(`${setup.functions.source}/tsconfig.json`, TSCONFIG_TEMPLATE);
|
|
43
|
-
})
|
|
44
|
-
.then(() => {
|
|
45
|
-
if (setup.functions.lint) {
|
|
46
|
-
return config.askWriteProjectFile(`${setup.functions.source}/tsconfig.dev.json`, TSCONFIG_DEV_TEMPLATE);
|
|
47
|
-
}
|
|
48
|
-
})
|
|
49
|
-
.then(() => {
|
|
50
|
-
return config.askWriteProjectFile(`${setup.functions.source}/src/index.ts`, INDEX_TEMPLATE);
|
|
51
|
-
})
|
|
52
|
-
.then(() => {
|
|
53
|
-
return config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
|
|
54
|
-
})
|
|
55
|
-
.then(() => {
|
|
56
|
-
return (0, npm_dependencies_1.askInstallDependencies)(setup.functions, config);
|
|
57
|
-
});
|
|
15
|
+
async function setup(setup, config) {
|
|
16
|
+
setup.functions.lint =
|
|
17
|
+
setup.functions.lint ||
|
|
18
|
+
(await (0, prompt_1.confirm)({
|
|
19
|
+
message: "Do you want to use ESLint to catch probable bugs and enforce style?",
|
|
20
|
+
default: true,
|
|
21
|
+
}));
|
|
22
|
+
const cbconfig = (0, projectConfig_1.configForCodebase)(setup.config.functions, setup.functions.codebase);
|
|
23
|
+
cbconfig.predeploy = [];
|
|
24
|
+
if (setup.functions.lint) {
|
|
25
|
+
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run lint');
|
|
26
|
+
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run build');
|
|
27
|
+
await config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_LINTING_TEMPLATE);
|
|
28
|
+
await config.askWriteProjectFile(`${setup.functions.source}/.eslintrc.js`, ESLINT_TEMPLATE);
|
|
29
|
+
await config.askWriteProjectFile(`${setup.functions.source}/tsconfig.dev.json`, TSCONFIG_DEV_TEMPLATE);
|
|
30
|
+
}
|
|
31
|
+
else {
|
|
32
|
+
cbconfig.predeploy.push('npm --prefix "$RESOURCE_DIR" run build');
|
|
33
|
+
await config.askWriteProjectFile(`${setup.functions.source}/package.json`, PACKAGE_NO_LINTING_TEMPLATE);
|
|
34
|
+
}
|
|
35
|
+
await config.askWriteProjectFile(`${setup.functions.source}/tsconfig.json`, TSCONFIG_TEMPLATE);
|
|
36
|
+
await config.askWriteProjectFile(`${setup.functions.source}/src/index.ts`, INDEX_TEMPLATE);
|
|
37
|
+
await config.askWriteProjectFile(`${setup.functions.source}/.gitignore`, GITIGNORE_TEMPLATE);
|
|
38
|
+
await (0, npm_dependencies_1.askInstallDependencies)(setup.functions, config);
|
|
58
39
|
}
|
|
59
40
|
exports.setup = setup;
|
|
@@ -2,7 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.promptWriteMode = exports.isPackageJson = exports.isTsConfig = exports.genkitSetup = exports.ensureVertexApiEnabled = exports.doSetup = void 0;
|
|
4
4
|
const fs = require("fs");
|
|
5
|
-
const inquirer = require("inquirer");
|
|
6
5
|
const path = require("path");
|
|
7
6
|
const semver = require("semver");
|
|
8
7
|
const clc = require("colorette");
|
|
@@ -115,17 +114,13 @@ async function doSetup(setup, config, options) {
|
|
|
115
114
|
throw new error_1.FirebaseError("Failed to initialize Genkit prerequisite: Firebase functions");
|
|
116
115
|
}
|
|
117
116
|
const projectDir = `${config.projectDir}/${setup.functions.source}`;
|
|
118
|
-
const installType =
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
{ name: "Just this project", value: "project" },
|
|
126
|
-
],
|
|
127
|
-
},
|
|
128
|
-
])).choice;
|
|
117
|
+
const installType = await (0, prompt_1.select)({
|
|
118
|
+
message: "Install the Genkit CLI globally or locally in this project?",
|
|
119
|
+
choices: [
|
|
120
|
+
{ name: "Globally", value: "globally" },
|
|
121
|
+
{ name: "Just this project", value: "project" },
|
|
122
|
+
],
|
|
123
|
+
});
|
|
129
124
|
try {
|
|
130
125
|
(0, utils_1.logLabeledBullet)("genkit", `Installing Genkit CLI version ${genkitInfo.cliVersion}`);
|
|
131
126
|
if (installType === "globally") {
|
|
@@ -214,18 +209,13 @@ async function genkitSetup(options, genkitInfo, projectDir) {
|
|
|
214
209
|
var _a, _b;
|
|
215
210
|
const modelOptions = getModelOptions(genkitInfo);
|
|
216
211
|
const supportedModels = Object.keys(modelOptions);
|
|
217
|
-
const
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
name:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
value: model,
|
|
225
|
-
})),
|
|
226
|
-
},
|
|
227
|
-
]);
|
|
228
|
-
const model = answer.model;
|
|
212
|
+
const model = await (0, prompt_1.select)({
|
|
213
|
+
message: "Select a model provider:",
|
|
214
|
+
choices: supportedModels.map((model) => ({
|
|
215
|
+
name: modelOptions[model].label,
|
|
216
|
+
value: model,
|
|
217
|
+
})),
|
|
218
|
+
});
|
|
229
219
|
if (model === "vertexai") {
|
|
230
220
|
await ensureVertexApiEnabled(options);
|
|
231
221
|
}
|
|
@@ -419,19 +409,14 @@ function generateImportStatement(imports, name) {
|
|
|
419
409
|
return `import {${imports}} from "${name}";`;
|
|
420
410
|
}
|
|
421
411
|
async function promptWriteMode(message, defaultOption = "merge") {
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
name: "
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
],
|
|
432
|
-
default: defaultOption,
|
|
433
|
-
},
|
|
434
|
-
]);
|
|
435
|
-
return answer.option;
|
|
412
|
+
return (0, prompt_1.select)({
|
|
413
|
+
message,
|
|
414
|
+
choices: [
|
|
415
|
+
{ name: "Set if unset", value: "merge" },
|
|
416
|
+
{ name: "Overwrite", value: "overwrite" },
|
|
417
|
+
{ name: "Keep unchanged", value: "keep" },
|
|
418
|
+
],
|
|
419
|
+
default: defaultOption,
|
|
420
|
+
});
|
|
436
421
|
}
|
|
437
422
|
exports.promptWriteMode = promptWriteMode;
|
|
@@ -75,7 +75,7 @@ async function initGitHub(setup) {
|
|
|
75
75
|
let shouldWriteYMLHostingFile = true;
|
|
76
76
|
let shouldWriteYMLDeployFile = false;
|
|
77
77
|
if (fs.existsSync(YML_FULL_PATH_PULL_REQUEST)) {
|
|
78
|
-
const
|
|
78
|
+
const overwrite = await (0, prompt_1.confirm)({
|
|
79
79
|
message: `GitHub workflow file for PR previews exists. Overwrite? ${YML_PULL_REQUEST_FILENAME}`,
|
|
80
80
|
});
|
|
81
81
|
shouldWriteYMLHostingFile = overwrite;
|
|
@@ -92,10 +92,9 @@ async function initGitHub(setup) {
|
|
|
92
92
|
shouldWriteYMLDeployFile = true;
|
|
93
93
|
}
|
|
94
94
|
else {
|
|
95
|
-
|
|
95
|
+
shouldWriteYMLDeployFile = await (0, prompt_1.confirm)({
|
|
96
96
|
message: `The GitHub workflow file for deploying to the live channel already exists. Overwrite? ${YML_MERGE_FILENAME}`,
|
|
97
97
|
});
|
|
98
|
-
shouldWriteYMLDeployFile = overwrite;
|
|
99
98
|
}
|
|
100
99
|
}
|
|
101
100
|
else {
|
|
@@ -260,10 +259,8 @@ async function uploadSecretToGitHub(repo, ghAccessToken, encryptedServiceAccount
|
|
|
260
259
|
async function promptForRepo(options, ghAccessToken) {
|
|
261
260
|
let key = "";
|
|
262
261
|
let keyId = "";
|
|
263
|
-
const { repo } =
|
|
264
|
-
{
|
|
265
|
-
type: "input",
|
|
266
|
-
name: "repo",
|
|
262
|
+
const { repo } = options.repo ||
|
|
263
|
+
(await (0, prompt_1.input)({
|
|
267
264
|
default: defaultGithubRepo(),
|
|
268
265
|
message: "For which GitHub repository would you like to set up a GitHub workflow? (format: user/repository)",
|
|
269
266
|
validate: async (repo) => {
|
|
@@ -289,64 +286,36 @@ async function promptForRepo(options, ghAccessToken) {
|
|
|
289
286
|
}
|
|
290
287
|
return true;
|
|
291
288
|
},
|
|
292
|
-
}
|
|
293
|
-
]);
|
|
289
|
+
}));
|
|
294
290
|
return { repo, key, keyId };
|
|
295
291
|
}
|
|
296
292
|
async function promptForBuildScript(useWebFrameworks) {
|
|
297
|
-
const
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
name: "shouldSetupScript",
|
|
301
|
-
default: false,
|
|
302
|
-
message: "Set up the workflow to run a build script before every deploy?",
|
|
303
|
-
},
|
|
304
|
-
]);
|
|
293
|
+
const shouldSetupScript = await (0, prompt_1.confirm)({
|
|
294
|
+
message: "Set up the workflow to run a build script before every deploy?",
|
|
295
|
+
});
|
|
305
296
|
if (!shouldSetupScript) {
|
|
306
297
|
return { script: undefined };
|
|
307
298
|
}
|
|
308
|
-
const
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
default: useWebFrameworks ? undefined : "npm ci && npm run build",
|
|
313
|
-
message: "What script should be run before every deploy?",
|
|
314
|
-
},
|
|
315
|
-
]);
|
|
299
|
+
const script = await (0, prompt_1.input)({
|
|
300
|
+
default: useWebFrameworks ? undefined : "npm ci && npm run build",
|
|
301
|
+
message: "What script should be run before every deploy?",
|
|
302
|
+
});
|
|
316
303
|
return { script };
|
|
317
304
|
}
|
|
318
305
|
async function promptToSetupDeploys(defaultBranch) {
|
|
319
|
-
const
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
default: true,
|
|
324
|
-
message: "Set up automatic deployment to your site's live channel when a PR is merged?",
|
|
325
|
-
},
|
|
326
|
-
]);
|
|
306
|
+
const setupDeploys = await (0, prompt_1.confirm)({
|
|
307
|
+
default: true,
|
|
308
|
+
message: "Set up automatic deployment to your site's live channel when a PR is merged?",
|
|
309
|
+
});
|
|
327
310
|
if (!setupDeploys) {
|
|
328
311
|
return { setupDeploys };
|
|
329
312
|
}
|
|
330
|
-
const
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
default: defaultBranch,
|
|
335
|
-
message: "What is the name of the GitHub branch associated with your site's live channel?",
|
|
336
|
-
},
|
|
337
|
-
]);
|
|
313
|
+
const branch = await (0, prompt_1.input)({
|
|
314
|
+
default: defaultBranch,
|
|
315
|
+
message: "What is the name of the GitHub branch associated with your site's live channel?",
|
|
316
|
+
});
|
|
338
317
|
return { branch, setupDeploys };
|
|
339
318
|
}
|
|
340
|
-
async function promptForWriteYMLFile({ message }) {
|
|
341
|
-
return await (0, prompt_1.prompt)({}, [
|
|
342
|
-
{
|
|
343
|
-
type: "confirm",
|
|
344
|
-
name: "overwrite",
|
|
345
|
-
default: false,
|
|
346
|
-
message,
|
|
347
|
-
},
|
|
348
|
-
]);
|
|
349
|
-
}
|
|
350
319
|
async function getGitHubUserDetails(ghAccessToken) {
|
|
351
320
|
const { body: ghUserDetails } = await githubApiClient.get("/user", {
|
|
352
321
|
headers: { Authorization: `token ${ghAccessToken}`, "User-Agent": "Firebase CLI" },
|
|
@@ -33,8 +33,7 @@ async function doSetup(setup, config, options) {
|
|
|
33
33
|
hasHostingSite = false;
|
|
34
34
|
}
|
|
35
35
|
if (!hasHostingSite) {
|
|
36
|
-
const confirmCreate = await (0, prompt_1.
|
|
37
|
-
type: "confirm",
|
|
36
|
+
const confirmCreate = await (0, prompt_1.confirm)({
|
|
38
37
|
message: "A Firebase Hosting site is required to deploy. Would you like to create one now?",
|
|
39
38
|
default: true,
|
|
40
39
|
});
|
|
@@ -56,44 +55,33 @@ async function doSetup(setup, config, options) {
|
|
|
56
55
|
if (experiments.isEnabled("webframeworks")) {
|
|
57
56
|
if (discoveredFramework) {
|
|
58
57
|
const name = frameworks_1.WebFrameworks[discoveredFramework.framework].name;
|
|
59
|
-
await (0, prompt_1.
|
|
60
|
-
name: "useDiscoveredFramework",
|
|
61
|
-
type: "confirm",
|
|
62
|
-
default: true,
|
|
58
|
+
setup.hosting.useDiscoveredFramework = await (0, prompt_1.confirm)({
|
|
63
59
|
message: `Detected an existing ${name} codebase in the current directory, should we use this?`,
|
|
64
|
-
|
|
60
|
+
default: true,
|
|
61
|
+
});
|
|
65
62
|
}
|
|
66
63
|
if (setup.hosting.useDiscoveredFramework) {
|
|
67
64
|
setup.hosting.source = ".";
|
|
68
65
|
setup.hosting.useWebFrameworks = true;
|
|
69
66
|
}
|
|
70
67
|
else {
|
|
71
|
-
await (0, prompt_1.
|
|
72
|
-
name: "useWebFrameworks",
|
|
73
|
-
type: "confirm",
|
|
74
|
-
default: false,
|
|
75
|
-
message: `Do you want to use a web framework? (${clc.bold("experimental")})`,
|
|
76
|
-
}, setup.hosting);
|
|
68
|
+
setup.hosting.useWebFrameworks = await (0, prompt_1.confirm)(`Do you want to use a web framework? (${clc.bold("experimental")})`);
|
|
77
69
|
}
|
|
78
70
|
}
|
|
79
71
|
if (setup.hosting.useWebFrameworks) {
|
|
80
|
-
await (0, prompt_1.
|
|
81
|
-
name: "source",
|
|
82
|
-
type: "input",
|
|
83
|
-
default: "hosting",
|
|
72
|
+
setup.hosting.source = await (0, prompt_1.input)({
|
|
84
73
|
message: "What folder would you like to use for your web application's root directory?",
|
|
85
|
-
|
|
74
|
+
default: "hosting",
|
|
75
|
+
});
|
|
86
76
|
if (setup.hosting.source !== ".")
|
|
87
77
|
delete setup.hosting.useDiscoveredFramework;
|
|
88
78
|
discoveredFramework = await (0, frameworks_1.discover)((0, path_1.join)(config.projectDir, setup.hosting.source));
|
|
89
79
|
if (discoveredFramework) {
|
|
90
80
|
const name = frameworks_1.WebFrameworks[discoveredFramework.framework].name;
|
|
91
|
-
await (0, prompt_1.
|
|
92
|
-
name: "useDiscoveredFramework",
|
|
93
|
-
type: "confirm",
|
|
94
|
-
default: true,
|
|
81
|
+
setup.hosting.useDiscoveredFramework = await (0, prompt_1.confirm)({
|
|
95
82
|
message: `Detected an existing ${name} codebase in ${setup.hosting.source}, should we use this?`,
|
|
96
|
-
|
|
83
|
+
default: true,
|
|
84
|
+
});
|
|
97
85
|
}
|
|
98
86
|
if (setup.hosting.useDiscoveredFramework && discoveredFramework) {
|
|
99
87
|
setup.hosting.webFramework = discoveredFramework.framework;
|
|
@@ -108,24 +96,24 @@ async function doSetup(setup, config, options) {
|
|
|
108
96
|
}
|
|
109
97
|
}
|
|
110
98
|
const defaultChoice = (_a = choices.find(({ value }) => value === (discoveredFramework === null || discoveredFramework === void 0 ? void 0 : discoveredFramework.framework))) === null || _a === void 0 ? void 0 : _a.value;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
99
|
+
setup.hosting.whichFramework =
|
|
100
|
+
setup.hosting.whichFramework ||
|
|
101
|
+
(await (0, prompt_1.select)({
|
|
102
|
+
message: "Please choose the framework:",
|
|
103
|
+
default: defaultChoice,
|
|
104
|
+
choices,
|
|
105
|
+
}));
|
|
118
106
|
if (discoveredFramework)
|
|
119
107
|
(0, node_fs_1.rmSync)(setup.hosting.source, { recursive: true });
|
|
120
108
|
await frameworks_1.WebFrameworks[setup.hosting.whichFramework].init(setup, config);
|
|
121
109
|
}
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
110
|
+
setup.hosting.region =
|
|
111
|
+
setup.hosting.region ||
|
|
112
|
+
(await (0, prompt_1.select)({
|
|
113
|
+
message: "In which region would you like to host server-side content, if applicable?",
|
|
114
|
+
default: constants_1.DEFAULT_REGION,
|
|
115
|
+
choices: constants_1.ALLOWED_SSR_REGIONS.filter((region) => region.recommended),
|
|
116
|
+
}));
|
|
129
117
|
setup.config.hosting = {
|
|
130
118
|
source: setup.hosting.source,
|
|
131
119
|
ignore: DEFAULT_IGNORES,
|
|
@@ -140,31 +128,22 @@ async function doSetup(setup, config, options) {
|
|
|
140
128
|
logger_1.logger.info(`will contain Hosting assets to be uploaded with ${clc.bold("firebase deploy")}. If you`);
|
|
141
129
|
logger_1.logger.info("have a build process for your assets, use your build's output directory.");
|
|
142
130
|
logger_1.logger.info();
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
type: "confirm",
|
|
153
|
-
default: false,
|
|
154
|
-
message: "Configure as a single-page app (rewrite all urls to /index.html)?",
|
|
155
|
-
},
|
|
156
|
-
]);
|
|
131
|
+
setup.hosting.public =
|
|
132
|
+
setup.hosting.public ||
|
|
133
|
+
(await (0, prompt_1.input)({
|
|
134
|
+
message: "What do you want to use as your public directory?",
|
|
135
|
+
default: "public",
|
|
136
|
+
}));
|
|
137
|
+
setup.hosting.spa =
|
|
138
|
+
setup.hosting.spa ||
|
|
139
|
+
(await (0, prompt_1.confirm)("Configure as a single-page app (rewrite all urls to /index.html)?"));
|
|
157
140
|
setup.config.hosting = {
|
|
158
141
|
public: setup.hosting.public,
|
|
159
142
|
ignore: DEFAULT_IGNORES,
|
|
160
143
|
};
|
|
161
144
|
}
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
type: "confirm",
|
|
165
|
-
default: false,
|
|
166
|
-
message: "Set up automatic builds and deploys with GitHub?",
|
|
167
|
-
}, setup.hosting);
|
|
145
|
+
setup.hosting.github =
|
|
146
|
+
setup.hosting.github || (await (0, prompt_1.confirm)("Set up automatic builds and deploys with GitHub?"));
|
|
168
147
|
if (!setup.hosting.useWebFrameworks) {
|
|
169
148
|
if (setup.hosting.spa) {
|
|
170
149
|
setup.config.hosting.rewrites = [{ source: "**", destination: "/index.html" }];
|
|
@@ -6,8 +6,8 @@ const _ = require("lodash");
|
|
|
6
6
|
const error_1 = require("../../error");
|
|
7
7
|
const projects_1 = require("../../management/projects");
|
|
8
8
|
const logger_1 = require("../../logger");
|
|
9
|
-
const prompt_1 = require("../../prompt");
|
|
10
9
|
const utils = require("../../utils");
|
|
10
|
+
const prompt = require("../../prompt");
|
|
11
11
|
const OPTION_NO_PROJECT = "Don't set up a default project";
|
|
12
12
|
const OPTION_USE_PROJECT = "Use an existing project";
|
|
13
13
|
const OPTION_NEW_PROJECT = "Create a new project";
|
|
@@ -24,14 +24,11 @@ function toInitProjectInfo(projectMetaData) {
|
|
|
24
24
|
async function promptAndCreateNewProject() {
|
|
25
25
|
utils.logBullet("If you want to create a project in a Google Cloud organization or folder, please use " +
|
|
26
26
|
`"firebase projects:create" instead, and return to this command when you've created the project.`);
|
|
27
|
-
const
|
|
28
|
-
|
|
29
|
-
if (!promptAnswer.projectId) {
|
|
27
|
+
const { projectId, displayName } = await (0, projects_1.promptProjectCreation)();
|
|
28
|
+
if (!projectId) {
|
|
30
29
|
throw new error_1.FirebaseError("Project ID cannot be empty");
|
|
31
30
|
}
|
|
32
|
-
return await (0, projects_1.createFirebaseProjectAndLog)(
|
|
33
|
-
displayName: promptAnswer.displayName,
|
|
34
|
-
});
|
|
31
|
+
return await (0, projects_1.createFirebaseProjectAndLog)(projectId, { displayName });
|
|
35
32
|
}
|
|
36
33
|
async function promptAndAddFirebaseToCloudProject() {
|
|
37
34
|
const projectId = await (0, projects_1.promptAvailableProjectId)();
|
|
@@ -41,15 +38,8 @@ async function promptAndAddFirebaseToCloudProject() {
|
|
|
41
38
|
return await (0, projects_1.addFirebaseToCloudProjectAndLog)(projectId);
|
|
42
39
|
}
|
|
43
40
|
async function projectChoicePrompt(options) {
|
|
44
|
-
const choices = [
|
|
45
|
-
|
|
46
|
-
{ name: OPTION_NEW_PROJECT, value: OPTION_NEW_PROJECT },
|
|
47
|
-
{ name: OPTION_ADD_FIREBASE, value: OPTION_ADD_FIREBASE },
|
|
48
|
-
{ name: OPTION_NO_PROJECT, value: OPTION_NO_PROJECT },
|
|
49
|
-
];
|
|
50
|
-
const projectSetupOption = await (0, prompt_1.promptOnce)({
|
|
51
|
-
type: "list",
|
|
52
|
-
name: "id",
|
|
41
|
+
const choices = [OPTION_USE_PROJECT, OPTION_NEW_PROJECT, OPTION_ADD_FIREBASE, OPTION_NO_PROJECT];
|
|
42
|
+
const projectSetupOption = await prompt.select({
|
|
53
43
|
message: "Please select an option:",
|
|
54
44
|
choices,
|
|
55
45
|
});
|
|
@@ -6,9 +6,7 @@ const fsutils = require("../../fsutils");
|
|
|
6
6
|
const clc = require("colorette");
|
|
7
7
|
async function doSetup(setup, config) {
|
|
8
8
|
setup.config.remoteconfig = {};
|
|
9
|
-
const jsonFilePath = await (0, prompt_1.
|
|
10
|
-
type: "input",
|
|
11
|
-
name: "template",
|
|
9
|
+
const jsonFilePath = await (0, prompt_1.input)({
|
|
12
10
|
message: "What file should be used for your Remote Config template?",
|
|
13
11
|
default: "remoteconfig.template.json",
|
|
14
12
|
});
|
|
@@ -17,11 +15,7 @@ async function doSetup(setup, config) {
|
|
|
17
15
|
clc.bold(jsonFilePath) +
|
|
18
16
|
" already exists." +
|
|
19
17
|
" Do you want to overwrite the existing Remote Config template?";
|
|
20
|
-
const overwrite = await (0, prompt_1.
|
|
21
|
-
type: "confirm",
|
|
22
|
-
message: msg,
|
|
23
|
-
default: false,
|
|
24
|
-
});
|
|
18
|
+
const overwrite = await (0, prompt_1.confirm)(msg);
|
|
25
19
|
if (!overwrite) {
|
|
26
20
|
return;
|
|
27
21
|
}
|