firebase-tools 14.21.0 → 14.23.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +13 -5
- package/lib/apiv2.js +12 -2
- package/lib/appdistribution/client.js +62 -16
- package/lib/appdistribution/types.js +1 -12
- package/lib/appdistribution/yaml_helper.js +69 -0
- package/lib/commands/appdistribution-groups-list.js +3 -5
- package/lib/commands/appdistribution-testcases-export.js +32 -0
- package/lib/commands/appdistribution-testcases-import.js +34 -0
- package/lib/commands/appdistribution-testers-list.js +3 -5
- package/lib/commands/deploy.js +6 -4
- package/lib/commands/hosting-sites-create.js +4 -3
- package/lib/commands/index.js +8 -5
- package/lib/commands/init.js +5 -7
- package/lib/deploy/functions/params.js +7 -11
- package/lib/emulator/auth/operations.js +7 -1
- package/lib/emulator/downloadableEmulatorInfo.json +25 -25
- package/lib/emulator/functionsEmulatorRuntime.js +8 -0
- package/lib/emulator/taskQueue.js +5 -0
- package/lib/experiments.js +0 -6
- package/lib/firestore/api.js +22 -4
- package/lib/frameworks/angular/index.js +1 -1
- package/lib/frameworks/flutter/index.js +1 -1
- package/lib/frameworks/next/index.js +1 -1
- package/lib/frameworks/nuxt/index.js +1 -1
- package/lib/frameworks/vite/index.js +5 -2
- package/lib/hosting/interactive.js +14 -19
- package/lib/init/features/hosting/github.js +6 -6
- package/lib/init/features/hosting/index.js +89 -86
- package/lib/init/features/index.js +3 -2
- package/lib/init/index.js +5 -1
- package/lib/management/provisioning/errorHandler.js +54 -0
- package/lib/management/provisioning/provision.js +2 -5
- package/lib/mcp/resources/guides/init_backend.js +3 -26
- package/lib/mcp/resources/guides/init_hosting.js +15 -10
- package/lib/mcp/tools/core/init.js +27 -0
- package/lib/mcp/tools/functions/index.js +2 -1
- package/lib/mcp/tools/functions/list_functions.js +48 -0
- package/lib/utils.js +4 -1
- package/package.json +2 -2
- package/schema/firebase-config.json +0 -1
|
@@ -44,38 +44,38 @@
|
|
|
44
44
|
}
|
|
45
45
|
},
|
|
46
46
|
"pubsub": {
|
|
47
|
-
"version": "0.8.
|
|
48
|
-
"expectedSize":
|
|
49
|
-
"expectedChecksum": "
|
|
50
|
-
"expectedChecksumSHA256": "
|
|
51
|
-
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.
|
|
52
|
-
"downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.
|
|
53
|
-
"binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.
|
|
47
|
+
"version": "0.8.17",
|
|
48
|
+
"expectedSize": 65162324,
|
|
49
|
+
"expectedChecksum": "a88ec6424e49af459b5c8a3657d69c06",
|
|
50
|
+
"expectedChecksumSHA256": "72a49d14ee6cd4c1a0fee4a46f520fe4d7465396a155c61abc0103905047edd3",
|
|
51
|
+
"remoteUrl": "https://storage.googleapis.com/firebase-preview-drop/emulator/pubsub-emulator-0.8.17.zip",
|
|
52
|
+
"downloadPathRelativeToCacheDir": "pubsub-emulator-0.8.17.zip",
|
|
53
|
+
"binaryPathRelativeToCacheDir": "pubsub-emulator-0.8.17/pubsub-emulator/bin/cloud-pubsub-emulator"
|
|
54
54
|
},
|
|
55
55
|
"dataconnect": {
|
|
56
56
|
"darwin": {
|
|
57
|
-
"version": "2.
|
|
58
|
-
"expectedSize":
|
|
59
|
-
"expectedChecksum": "
|
|
60
|
-
"expectedChecksumSHA256": "
|
|
61
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-v2.
|
|
62
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
57
|
+
"version": "2.16.0",
|
|
58
|
+
"expectedSize": 29963104,
|
|
59
|
+
"expectedChecksum": "ee4d81abfba3576c7c6c8082313acfd0",
|
|
60
|
+
"expectedChecksumSHA256": "8aed1dc6cc8c35ab23fdf10e519e9cf3d93c8a0ccb0ff7d5af3ddc41a4847e3e",
|
|
61
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-macos-amd64-v2.16.0",
|
|
62
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.16.0"
|
|
63
63
|
},
|
|
64
64
|
"win32": {
|
|
65
|
-
"version": "2.
|
|
66
|
-
"expectedSize":
|
|
67
|
-
"expectedChecksum": "
|
|
68
|
-
"expectedChecksumSHA256": "
|
|
69
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-v2.
|
|
70
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
65
|
+
"version": "2.16.0",
|
|
66
|
+
"expectedSize": 30456320,
|
|
67
|
+
"expectedChecksum": "546019a713be28620a3b43d49fc9d4b0",
|
|
68
|
+
"expectedChecksumSHA256": "ec1de720e173f0a613fbbb51767c0288121aa2f80e45e6bad0f3d2aff12689ec",
|
|
69
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-windows-amd64-v2.16.0",
|
|
70
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.16.0.exe"
|
|
71
71
|
},
|
|
72
72
|
"linux": {
|
|
73
|
-
"version": "2.
|
|
74
|
-
"expectedSize":
|
|
75
|
-
"expectedChecksum": "
|
|
76
|
-
"expectedChecksumSHA256": "
|
|
77
|
-
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-v2.
|
|
78
|
-
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.
|
|
73
|
+
"version": "2.16.0",
|
|
74
|
+
"expectedSize": 29888696,
|
|
75
|
+
"expectedChecksum": "5ab8da956043a48b43199f07b94ac48c",
|
|
76
|
+
"expectedChecksumSHA256": "1a420f3d2672627eae2d9b0b6747b833517cfc08f7e80ae3a79389788691b67a",
|
|
77
|
+
"remoteUrl": "https://storage.googleapis.com/firemat-preview-drop/emulator/dataconnect-emulator-linux-amd64-v2.16.0",
|
|
78
|
+
"downloadPathRelativeToCacheDir": "dataconnect-emulator-2.16.0"
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
}
|
|
@@ -240,6 +240,10 @@ function initializeNetworkFiltering() {
|
|
|
240
240
|
}
|
|
241
241
|
async function initializeFirebaseFunctionsStubs() {
|
|
242
242
|
const firebaseFunctionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
|
|
243
|
+
if ((0, functionsEmulatorUtils_1.compareVersionStrings)(firebaseFunctionsResolution.version, "7.0.0") >= 0) {
|
|
244
|
+
logDebug("Detected firebase-functions v7+, skipping legacy stubs.");
|
|
245
|
+
return;
|
|
246
|
+
}
|
|
243
247
|
const firebaseFunctionsRoot = (0, functionsEmulatorShared_1.findModuleRoot)("firebase-functions", firebaseFunctionsResolution.resolution);
|
|
244
248
|
const httpsProviderResolution = path.join(firebaseFunctionsRoot, "lib/providers/https");
|
|
245
249
|
const httpsProviderV1Resolution = path.join(firebaseFunctionsRoot, "lib/v1/providers/https");
|
|
@@ -451,6 +455,10 @@ function warnAboutStorageProd() {
|
|
|
451
455
|
}
|
|
452
456
|
async function initializeFunctionsConfigHelper() {
|
|
453
457
|
const functionsResolution = await assertResolveDeveloperNodeModule("firebase-functions");
|
|
458
|
+
if ((0, functionsEmulatorUtils_1.compareVersionStrings)(functionsResolution.version, "7.0.0") >= 0) {
|
|
459
|
+
logDebug("Detected firebase-functions v7+, skipping config helper.");
|
|
460
|
+
return;
|
|
461
|
+
}
|
|
454
462
|
const localFunctionsModule = require(functionsResolution.resolution);
|
|
455
463
|
logDebug("Checked functions.config()", {
|
|
456
464
|
config: localFunctionsModule.config(),
|
|
@@ -4,6 +4,7 @@ exports.TaskQueue = exports.TaskStatus = exports.Queue = void 0;
|
|
|
4
4
|
const abort_controller_1 = require("abort-controller");
|
|
5
5
|
const emulatorLogger_1 = require("./emulatorLogger");
|
|
6
6
|
const types_1 = require("./types");
|
|
7
|
+
const error_1 = require("../error");
|
|
7
8
|
const node_fetch_1 = require("node-fetch");
|
|
8
9
|
class Node {
|
|
9
10
|
constructor(data) {
|
|
@@ -198,6 +199,10 @@ class TaskQueue {
|
|
|
198
199
|
}
|
|
199
200
|
const controller = new abort_controller_1.default();
|
|
200
201
|
const signal = controller.signal;
|
|
202
|
+
signal.reason = "";
|
|
203
|
+
signal.throwIfAborted = () => {
|
|
204
|
+
throw new error_1.FirebaseError("Aborted");
|
|
205
|
+
};
|
|
201
206
|
const request = (0, node_fetch_1.default)(emulatedTask.task.httpRequest.url, {
|
|
202
207
|
method: "POST",
|
|
203
208
|
headers: headers,
|
package/lib/experiments.js
CHANGED
|
@@ -118,12 +118,6 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
118
118
|
shortDescription: "Adds experimental App Testing feature",
|
|
119
119
|
public: true,
|
|
120
120
|
},
|
|
121
|
-
ailogic: {
|
|
122
|
-
shortDescription: "Enable Firebase AI Logic feature for existing apps",
|
|
123
|
-
fullDescription: "Enables the AI Logic initialization feature that provisions AI Logic for existing Firebase apps.",
|
|
124
|
-
public: true,
|
|
125
|
-
default: false,
|
|
126
|
-
},
|
|
127
121
|
});
|
|
128
122
|
function isValidExperiment(name) {
|
|
129
123
|
return Object.keys(exports.ALL_EXPERIMENTS).includes(name);
|
package/lib/firestore/api.js
CHANGED
|
@@ -22,16 +22,34 @@ class FirestoreApi {
|
|
|
22
22
|
this.printer = new pretty_print_1.PrettyPrint();
|
|
23
23
|
}
|
|
24
24
|
static processIndex(index) {
|
|
25
|
-
var _a
|
|
26
|
-
|
|
25
|
+
var _a;
|
|
26
|
+
let fields = index.fields;
|
|
27
|
+
const suffixOrder = FirestoreApi.lastIndexFieldOrder(fields);
|
|
28
|
+
const nameSuffix = { fieldPath: "__name__", order: suffixOrder };
|
|
27
29
|
const lastField = (_a = index.fields) === null || _a === void 0 ? void 0 : _a[index.fields.length - 1];
|
|
30
|
+
if (lastField.vectorConfig) {
|
|
31
|
+
const vectorField = lastField;
|
|
32
|
+
fields = fields.slice(0, -1);
|
|
33
|
+
if (fields.length === 0 || (fields === null || fields === void 0 ? void 0 : fields[fields.length - 1].fieldPath) !== "__name__") {
|
|
34
|
+
fields.push(nameSuffix);
|
|
35
|
+
}
|
|
36
|
+
fields.push(vectorField);
|
|
37
|
+
return Object.assign(Object.assign({}, index), { fields });
|
|
38
|
+
}
|
|
28
39
|
if ((lastField === null || lastField === void 0 ? void 0 : lastField.fieldPath) !== "__name__") {
|
|
29
|
-
const defaultDirection = (_c = (_b = index.fields) === null || _b === void 0 ? void 0 : _b[index.fields.length - 1]) === null || _c === void 0 ? void 0 : _c.order;
|
|
30
|
-
const nameSuffix = { fieldPath: "__name__", order: defaultDirection };
|
|
31
40
|
fields.push(nameSuffix);
|
|
32
41
|
}
|
|
33
42
|
return Object.assign(Object.assign({}, index), { fields });
|
|
34
43
|
}
|
|
44
|
+
static lastIndexFieldOrder(fields) {
|
|
45
|
+
let lastIndexFieldOrder = types.Order.ASCENDING;
|
|
46
|
+
for (const field of fields) {
|
|
47
|
+
if (field.order) {
|
|
48
|
+
lastIndexFieldOrder = field.order;
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
return lastIndexFieldOrder;
|
|
52
|
+
}
|
|
35
53
|
async deploy(options, indexes, fieldOverrides, databaseId = "(default)") {
|
|
36
54
|
var _a;
|
|
37
55
|
const spec = this.upgradeOldSpec({
|
|
@@ -26,7 +26,7 @@ async function discover(dir) {
|
|
|
26
26
|
}
|
|
27
27
|
exports.discover = discover;
|
|
28
28
|
function init(setup, config) {
|
|
29
|
-
(0, child_process_1.execSync)(`npx --yes -p @angular/cli@"${exports.supportedRange}" ng new ${setup.projectId} --directory ${setup.hosting.source} --skip-git`, {
|
|
29
|
+
(0, child_process_1.execSync)(`npx --yes -p @angular/cli@"${exports.supportedRange}" ng new ${setup.projectId} --directory ${setup.featureInfo.hosting.source} --skip-git`, {
|
|
30
30
|
stdio: "inherit",
|
|
31
31
|
cwd: config.projectDir,
|
|
32
32
|
});
|
|
@@ -34,7 +34,7 @@ function init(setup, config) {
|
|
|
34
34
|
`--project-name=${projectName}`,
|
|
35
35
|
"--overwrite",
|
|
36
36
|
"--platforms=web",
|
|
37
|
-
setup.hosting.source,
|
|
37
|
+
setup.featureInfo.hosting.source,
|
|
38
38
|
], { stdio: "inherit", cwd: config.projectDir });
|
|
39
39
|
if (result.status !== 0)
|
|
40
40
|
throw new error_1.FirebaseError("We were not able to create your flutter app, create the application yourself https://docs.flutter.dev/get-started/test-drive?tab=terminal before trying again.");
|
|
@@ -214,7 +214,7 @@ async function init(setup, config) {
|
|
|
214
214
|
],
|
|
215
215
|
});
|
|
216
216
|
(0, child_process_1.execSync)(`npx --yes create-next-app@"${exports.supportedRange}" -e hello-world ` +
|
|
217
|
-
`${setup.hosting.source} --use-npm --${language}`, { stdio: "inherit", cwd: config.projectDir });
|
|
217
|
+
`${setup.featureInfo.hosting.source} --use-npm --${language}`, { stdio: "inherit", cwd: config.projectDir });
|
|
218
218
|
}
|
|
219
219
|
exports.init = init;
|
|
220
220
|
async function ɵcodegenPublicDirectory(sourceDir, destDir, _, context) {
|
|
@@ -93,7 +93,7 @@ async function getConfig(cwd) {
|
|
|
93
93
|
}
|
|
94
94
|
exports.getConfig = getConfig;
|
|
95
95
|
function init(setup, config) {
|
|
96
|
-
(0, child_process_1.execSync)(`npx --yes nuxi@"${exports.supportedRange}" init ${setup.hosting.source}`, {
|
|
96
|
+
(0, child_process_1.execSync)(`npx --yes nuxi@"${exports.supportedRange}" init ${setup.featureInfo.hosting.source}`, {
|
|
97
97
|
stdio: "inherit",
|
|
98
98
|
cwd: config.projectDir,
|
|
99
99
|
});
|
|
@@ -25,11 +25,14 @@ async function init(setup, config, baseTemplate = "vanilla") {
|
|
|
25
25
|
{ name: "TypeScript", value: `${baseTemplate}-ts` },
|
|
26
26
|
],
|
|
27
27
|
});
|
|
28
|
-
(0, child_process_1.execSync)(`npm create vite@"${exports.supportedRange}" ${setup.hosting.source} --yes -- --template ${template}`, {
|
|
28
|
+
(0, child_process_1.execSync)(`npm create vite@"${exports.supportedRange}" ${setup.featureInfo.hosting.source} --yes -- --template ${template}`, {
|
|
29
29
|
stdio: "inherit",
|
|
30
30
|
cwd: config.projectDir,
|
|
31
31
|
});
|
|
32
|
-
(0, child_process_1.execSync)(`npm install`, {
|
|
32
|
+
(0, child_process_1.execSync)(`npm install`, {
|
|
33
|
+
stdio: "inherit",
|
|
34
|
+
cwd: (0, path_1.join)(config.projectDir, setup.featureInfo.hosting.source),
|
|
35
|
+
});
|
|
33
36
|
}
|
|
34
37
|
exports.init = init;
|
|
35
38
|
const viteDiscoverWithNpmDependency = (dep) => async (dir) => await discover(dir, undefined, dep);
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.pickHostingSiteName = void 0;
|
|
4
4
|
const error_1 = require("../error");
|
|
5
5
|
const utils_1 = require("../utils");
|
|
6
6
|
const projectUtils_1 = require("../projectUtils");
|
|
@@ -9,11 +9,11 @@ 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}"):';
|
|
12
|
-
async function
|
|
12
|
+
async function pickHostingSiteName(siteId, options) {
|
|
13
13
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
14
14
|
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
15
15
|
let id = siteId;
|
|
16
|
-
let
|
|
16
|
+
let nameConfirmed = false;
|
|
17
17
|
let suggestion;
|
|
18
18
|
if (!id) {
|
|
19
19
|
const attempt = await trySiteID(projectNumber, projectId);
|
|
@@ -24,7 +24,7 @@ async function interactiveCreateHostingSite(siteId, appId, options) {
|
|
|
24
24
|
suggestion = attempt.suggestion;
|
|
25
25
|
}
|
|
26
26
|
}
|
|
27
|
-
while (!
|
|
27
|
+
while (!nameConfirmed) {
|
|
28
28
|
if (!id || suggestion) {
|
|
29
29
|
id = await (0, prompt_1.input)({
|
|
30
30
|
message: prompt,
|
|
@@ -32,24 +32,16 @@ async function interactiveCreateHostingSite(siteId, appId, options) {
|
|
|
32
32
|
default: suggestion,
|
|
33
33
|
});
|
|
34
34
|
}
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
if (!(err instanceof error_1.FirebaseError)) {
|
|
40
|
-
throw err;
|
|
41
|
-
}
|
|
42
|
-
if (options.nonInteractive) {
|
|
43
|
-
throw err;
|
|
44
|
-
}
|
|
35
|
+
const attempt = await trySiteID(projectNumber, id, options.nonInteractive);
|
|
36
|
+
nameConfirmed = attempt.available;
|
|
37
|
+
suggestion = attempt.suggestion;
|
|
38
|
+
if (!nameConfirmed)
|
|
45
39
|
id = "";
|
|
46
|
-
suggestion = getSuggestionFromError(err);
|
|
47
|
-
}
|
|
48
40
|
}
|
|
49
|
-
return
|
|
41
|
+
return id;
|
|
50
42
|
}
|
|
51
|
-
exports.
|
|
52
|
-
async function trySiteID(projectNumber, id) {
|
|
43
|
+
exports.pickHostingSiteName = pickHostingSiteName;
|
|
44
|
+
async function trySiteID(projectNumber, id, nonInteractive = false) {
|
|
53
45
|
try {
|
|
54
46
|
await (0, api_1.createSite)(projectNumber, id, "", true);
|
|
55
47
|
return { available: true };
|
|
@@ -58,6 +50,9 @@ async function trySiteID(projectNumber, id) {
|
|
|
58
50
|
if (!(err instanceof error_1.FirebaseError)) {
|
|
59
51
|
throw err;
|
|
60
52
|
}
|
|
53
|
+
if (nonInteractive) {
|
|
54
|
+
throw err;
|
|
55
|
+
}
|
|
61
56
|
const suggestion = getSuggestionFromError(err);
|
|
62
57
|
return { available: false, suggestion };
|
|
63
58
|
}
|
|
@@ -29,11 +29,11 @@ const HOSTING_GITHUB_ACTION_NAME = "FirebaseExtended/action-hosting-deploy@v0";
|
|
|
29
29
|
const SERVICE_ACCOUNT_MAX_KEY_NUMBER = 10;
|
|
30
30
|
const githubApiClient = new apiv2_1.Client({ urlPrefix: (0, api_1.githubApiOrigin)(), auth: false });
|
|
31
31
|
async function initGitHub(setup) {
|
|
32
|
-
var _a, _b, _c, _d, _e;
|
|
32
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
33
33
|
if (!setup.projectId) {
|
|
34
34
|
return (0, utils_1.reject)("Could not determine Project ID, can't set up GitHub workflow.", { exit: 1 });
|
|
35
35
|
}
|
|
36
|
-
if (!setup.config.hosting) {
|
|
36
|
+
if (!setup.config.hosting && !((_a = setup.featureInfo) === null || _a === void 0 ? void 0 : _a.hosting)) {
|
|
37
37
|
return (0, utils_1.reject)(`Didn't find a Hosting config in firebase.json. Run ${(0, colorette_1.bold)("firebase init hosting")} instead.`);
|
|
38
38
|
}
|
|
39
39
|
logger_1.logger.info();
|
|
@@ -67,10 +67,10 @@ async function initGitHub(setup) {
|
|
|
67
67
|
(0, utils_1.logSuccess)(`Uploaded service account JSON to GitHub as secret ${(0, colorette_1.bold)(githubSecretName)}.`);
|
|
68
68
|
(0, utils_1.logBullet)(`You can manage your secrets at https://github.com/${repo}/settings/secrets.`);
|
|
69
69
|
logger_1.logger.info();
|
|
70
|
-
if (!Array.isArray(setup.config.hosting) && setup.config.hosting.predeploy) {
|
|
70
|
+
if (!Array.isArray(setup.config.hosting) && ((_b = setup.config.hosting) === null || _b === void 0 ? void 0 : _b.predeploy)) {
|
|
71
71
|
(0, utils_1.logBullet)(`You have a predeploy script configured in firebase.json.`);
|
|
72
72
|
}
|
|
73
|
-
const { script } = await promptForBuildScript((
|
|
73
|
+
const { script } = await promptForBuildScript((_c = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _c === void 0 ? void 0 : _c.useWebFrameworks);
|
|
74
74
|
const ymlDeployDoc = loadYMLDeploy();
|
|
75
75
|
let shouldWriteYMLHostingFile = true;
|
|
76
76
|
let shouldWriteYMLDeployFile = false;
|
|
@@ -81,7 +81,7 @@ async function initGitHub(setup) {
|
|
|
81
81
|
shouldWriteYMLHostingFile = overwrite;
|
|
82
82
|
}
|
|
83
83
|
if (shouldWriteYMLHostingFile) {
|
|
84
|
-
writeChannelActionYMLFile(YML_FULL_PATH_PULL_REQUEST, githubSecretName, setup.projectId, script, (
|
|
84
|
+
writeChannelActionYMLFile(YML_FULL_PATH_PULL_REQUEST, githubSecretName, setup.projectId, script, (_d = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _d === void 0 ? void 0 : _d.useWebFrameworks, (_e = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _e === void 0 ? void 0 : _e.source);
|
|
85
85
|
logger_1.logger.info();
|
|
86
86
|
(0, utils_1.logSuccess)(`Created workflow file ${(0, colorette_1.bold)(YML_FULL_PATH_PULL_REQUEST)}`);
|
|
87
87
|
}
|
|
@@ -101,7 +101,7 @@ async function initGitHub(setup) {
|
|
|
101
101
|
shouldWriteYMLDeployFile = true;
|
|
102
102
|
}
|
|
103
103
|
if (shouldWriteYMLDeployFile) {
|
|
104
|
-
writeDeployToProdActionYMLFile(YML_FULL_PATH_MERGE, branch, githubSecretName, setup.projectId, script, (
|
|
104
|
+
writeDeployToProdActionYMLFile(YML_FULL_PATH_MERGE, branch, githubSecretName, setup.projectId, script, (_f = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _f === void 0 ? void 0 : _f.useWebFrameworks, (_g = setup === null || setup === void 0 ? void 0 : setup.hosting) === null || _g === void 0 ? void 0 : _g.source);
|
|
105
105
|
logger_1.logger.info();
|
|
106
106
|
(0, utils_1.logSuccess)(`Created workflow file ${(0, colorette_1.bold)(YML_FULL_PATH_MERGE)}`);
|
|
107
107
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.actuate = exports.askQuestions = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const node_fs_1 = require("node:fs");
|
|
6
6
|
const path_1 = require("path");
|
|
@@ -15,13 +15,16 @@ const getDefaultHostingSite_1 = require("../../../getDefaultHostingSite");
|
|
|
15
15
|
const utils_1 = require("../../../utils");
|
|
16
16
|
const interactive_1 = require("../../../hosting/interactive");
|
|
17
17
|
const templates_1 = require("../../../templates");
|
|
18
|
+
const error_1 = require("../../../error");
|
|
19
|
+
const api_1 = require("../../../hosting/api");
|
|
18
20
|
const INDEX_TEMPLATE = (0, templates_1.readTemplateSync)("init/hosting/index.html");
|
|
19
21
|
const MISSING_TEMPLATE = (0, templates_1.readTemplateSync)("init/hosting/404.html");
|
|
20
22
|
const DEFAULT_IGNORES = ["firebase.json", "**/.*", "**/node_modules/**"];
|
|
21
|
-
async function
|
|
22
|
-
var _a, _b, _c, _d;
|
|
23
|
-
var
|
|
24
|
-
setup.
|
|
23
|
+
async function askQuestions(setup, config, options) {
|
|
24
|
+
var _a, _b, _c, _d, _e, _f;
|
|
25
|
+
var _g, _h, _j, _k, _l;
|
|
26
|
+
setup.featureInfo = setup.featureInfo || {};
|
|
27
|
+
setup.featureInfo.hosting = {};
|
|
25
28
|
if (setup.projectId) {
|
|
26
29
|
let hasHostingSite = true;
|
|
27
30
|
try {
|
|
@@ -33,95 +36,72 @@ async function doSetup(setup, config, options) {
|
|
|
33
36
|
}
|
|
34
37
|
hasHostingSite = false;
|
|
35
38
|
}
|
|
36
|
-
if (!hasHostingSite
|
|
37
|
-
|
|
39
|
+
if (!hasHostingSite &&
|
|
40
|
+
(await (0, prompt_1.confirm)({
|
|
38
41
|
message: "A Firebase Hosting site is required to deploy. Would you like to create one now?",
|
|
39
42
|
default: true,
|
|
40
|
-
})
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
const newSite = await (0, interactive_1.interactiveCreateHostingSite)("", "", createOptions);
|
|
47
|
-
logger_1.logger.info();
|
|
48
|
-
(0, utils_1.logSuccess)(`Firebase Hosting site ${(0, utils_1.last)(newSite.name.split("/"))} created!`);
|
|
49
|
-
logger_1.logger.info();
|
|
50
|
-
}
|
|
43
|
+
}))) {
|
|
44
|
+
const createOptions = {
|
|
45
|
+
projectId: setup.projectId,
|
|
46
|
+
nonInteractive: options.nonInteractive,
|
|
47
|
+
};
|
|
48
|
+
setup.featureInfo.hosting.newSiteId = await (0, interactive_1.pickHostingSiteName)("", createOptions);
|
|
51
49
|
}
|
|
52
50
|
}
|
|
53
51
|
let discoveredFramework = experiments.isEnabled("webframeworks")
|
|
54
52
|
? await (0, frameworks_1.discover)(config.projectDir, false)
|
|
55
53
|
: undefined;
|
|
56
54
|
if (experiments.isEnabled("webframeworks")) {
|
|
57
|
-
if (discoveredFramework
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
message: `Detected an existing ${name} codebase in the current directory, should we use this?`,
|
|
55
|
+
if (discoveredFramework &&
|
|
56
|
+
(await (0, prompt_1.confirm)({
|
|
57
|
+
message: `Detected an existing ${frameworks_1.WebFrameworks[discoveredFramework.framework].name} codebase in the current directory, do you want to use this?`,
|
|
61
58
|
default: true,
|
|
62
|
-
}))
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
setup.hosting.
|
|
66
|
-
setup.hosting.
|
|
59
|
+
}))) {
|
|
60
|
+
setup.featureInfo.hosting.source = ".";
|
|
61
|
+
setup.featureInfo.hosting.useWebFrameworks = true;
|
|
62
|
+
setup.featureInfo.hosting.useDiscoveredFramework = true;
|
|
63
|
+
setup.featureInfo.hosting.webFramework = discoveredFramework.framework;
|
|
67
64
|
}
|
|
68
65
|
else {
|
|
69
|
-
setup.hosting.useWebFrameworks = await (0, prompt_1.confirm)(`Do you want to use a web framework? (${clc.bold("experimental")})`);
|
|
66
|
+
setup.featureInfo.hosting.useWebFrameworks = await (0, prompt_1.confirm)(`Do you want to use a web framework? (${clc.bold("experimental")})`);
|
|
70
67
|
}
|
|
71
68
|
}
|
|
72
|
-
if (setup.hosting.useWebFrameworks) {
|
|
73
|
-
(
|
|
69
|
+
if (setup.featureInfo.hosting.useWebFrameworks) {
|
|
70
|
+
(_a = (_g = setup.featureInfo.hosting).source) !== null && _a !== void 0 ? _a : (_g.source = await (0, prompt_1.input)({
|
|
74
71
|
message: "What folder would you like to use for your web application's root directory?",
|
|
75
72
|
default: "hosting",
|
|
76
73
|
}));
|
|
77
|
-
|
|
78
|
-
delete setup.hosting.useDiscoveredFramework;
|
|
79
|
-
discoveredFramework = await (0, frameworks_1.discover)((0, path_1.join)(config.projectDir, setup.hosting.source));
|
|
74
|
+
discoveredFramework = await (0, frameworks_1.discover)((0, path_1.join)(config.projectDir, setup.featureInfo.hosting.source));
|
|
80
75
|
if (discoveredFramework) {
|
|
81
76
|
const name = frameworks_1.WebFrameworks[discoveredFramework.framework].name;
|
|
82
|
-
(
|
|
83
|
-
message: `Detected an existing ${name} codebase in ${setup.hosting.source}, should we use this?`,
|
|
77
|
+
(_b = (_h = setup.featureInfo.hosting).useDiscoveredFramework) !== null && _b !== void 0 ? _b : (_h.useDiscoveredFramework = await (0, prompt_1.confirm)({
|
|
78
|
+
message: `Detected an existing ${name} codebase in ${setup.featureInfo.hosting.source}, should we use this?`,
|
|
84
79
|
default: true,
|
|
85
80
|
}));
|
|
81
|
+
if (setup.featureInfo.hosting.useDiscoveredFramework)
|
|
82
|
+
setup.featureInfo.hosting.webFramework = discoveredFramework.framework;
|
|
86
83
|
}
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
if (frameworks_1.WebFrameworks[value]) {
|
|
94
|
-
const { name, init } = frameworks_1.WebFrameworks[value];
|
|
95
|
-
if (init)
|
|
96
|
-
choices.push({ name, value });
|
|
97
|
-
}
|
|
84
|
+
const choices = [];
|
|
85
|
+
for (const value in frameworks_1.WebFrameworks) {
|
|
86
|
+
if (frameworks_1.WebFrameworks[value]) {
|
|
87
|
+
const { name, init } = frameworks_1.WebFrameworks[value];
|
|
88
|
+
if (init)
|
|
89
|
+
choices.push({ name, value });
|
|
98
90
|
}
|
|
99
|
-
const defaultChoice = (_d = choices.find(({ value }) => value === (discoveredFramework === null || discoveredFramework === void 0 ? void 0 : discoveredFramework.framework))) === null || _d === void 0 ? void 0 : _d.value;
|
|
100
|
-
setup.hosting.whichFramework =
|
|
101
|
-
setup.hosting.whichFramework ||
|
|
102
|
-
(await (0, prompt_1.select)({
|
|
103
|
-
message: "Please choose the framework:",
|
|
104
|
-
default: defaultChoice,
|
|
105
|
-
choices,
|
|
106
|
-
}));
|
|
107
|
-
if (discoveredFramework)
|
|
108
|
-
(0, node_fs_1.rmSync)(setup.hosting.source, { recursive: true });
|
|
109
|
-
await frameworks_1.WebFrameworks[setup.hosting.whichFramework].init(setup, config);
|
|
110
91
|
}
|
|
111
|
-
|
|
112
|
-
|
|
92
|
+
const defaultChoice = (_c = choices.find(({ value }) => value === (discoveredFramework === null || discoveredFramework === void 0 ? void 0 : discoveredFramework.framework))) === null || _c === void 0 ? void 0 : _c.value;
|
|
93
|
+
(_d = (_j = setup.featureInfo.hosting).webFramework) !== null && _d !== void 0 ? _d : (_j.webFramework = await (0, prompt_1.select)({
|
|
94
|
+
message: "Please choose the framework:",
|
|
95
|
+
default: defaultChoice,
|
|
96
|
+
choices,
|
|
97
|
+
}));
|
|
98
|
+
setup.featureInfo.hosting.region =
|
|
99
|
+
setup.featureInfo.hosting.region ||
|
|
113
100
|
(await (0, prompt_1.select)({
|
|
114
101
|
message: "In which region would you like to host server-side content, if applicable?",
|
|
115
102
|
default: constants_1.DEFAULT_REGION,
|
|
116
103
|
choices: constants_1.ALLOWED_SSR_REGIONS.filter((region) => region.recommended),
|
|
117
104
|
}));
|
|
118
|
-
setup.config.hosting = {
|
|
119
|
-
source: setup.hosting.source,
|
|
120
|
-
ignore: DEFAULT_IGNORES,
|
|
121
|
-
frameworksBackend: {
|
|
122
|
-
region: setup.hosting.region,
|
|
123
|
-
},
|
|
124
|
-
};
|
|
125
105
|
}
|
|
126
106
|
else {
|
|
127
107
|
logger_1.logger.info();
|
|
@@ -129,35 +109,58 @@ async function doSetup(setup, config, options) {
|
|
|
129
109
|
logger_1.logger.info(`will contain Hosting assets to be uploaded with ${clc.bold("firebase deploy")}. If you`);
|
|
130
110
|
logger_1.logger.info("have a build process for your assets, use your build's output directory.");
|
|
131
111
|
logger_1.logger.info();
|
|
132
|
-
setup.hosting.public =
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
112
|
+
(_e = (_k = setup.featureInfo.hosting).public) !== null && _e !== void 0 ? _e : (_k.public = await (0, prompt_1.input)({
|
|
113
|
+
message: "What do you want to use as your public directory?",
|
|
114
|
+
default: "public",
|
|
115
|
+
}));
|
|
116
|
+
(_f = (_l = setup.featureInfo.hosting).spa) !== null && _f !== void 0 ? _f : (_l.spa = await (0, prompt_1.confirm)("Configure as a single-page app (rewrite all urls to /index.html)?"));
|
|
117
|
+
}
|
|
118
|
+
if (await (0, prompt_1.confirm)("Set up automatic builds and deploys with GitHub?")) {
|
|
119
|
+
return (0, github_1.initGitHub)(setup);
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
exports.askQuestions = askQuestions;
|
|
123
|
+
async function actuate(setup, config, options) {
|
|
124
|
+
var _a;
|
|
125
|
+
const hostingInfo = (_a = setup.featureInfo) === null || _a === void 0 ? void 0 : _a.hosting;
|
|
126
|
+
if (!hostingInfo) {
|
|
127
|
+
throw new error_1.FirebaseError("Could not find hosting info in setup.featureInfo.hosting. This should not happen.", { exit: 2 });
|
|
128
|
+
}
|
|
129
|
+
if (hostingInfo.newSiteId && setup.projectId) {
|
|
130
|
+
await (0, api_1.createSite)(setup.projectId, hostingInfo.newSiteId);
|
|
131
|
+
logger_1.logger.info();
|
|
132
|
+
(0, utils_1.logSuccess)(`Firebase Hosting site ${hostingInfo.newSiteId} created!`);
|
|
133
|
+
logger_1.logger.info();
|
|
134
|
+
}
|
|
135
|
+
if (hostingInfo.webFramework) {
|
|
136
|
+
if (!hostingInfo.useDiscoveredFramework) {
|
|
137
|
+
if (hostingInfo.source && (0, node_fs_1.existsSync)(hostingInfo.source)) {
|
|
138
|
+
(0, node_fs_1.rmSync)(hostingInfo.source, { recursive: true });
|
|
139
|
+
}
|
|
140
|
+
await frameworks_1.WebFrameworks[hostingInfo.webFramework].init(setup, config);
|
|
141
|
+
}
|
|
141
142
|
setup.config.hosting = {
|
|
142
|
-
|
|
143
|
+
source: hostingInfo.source,
|
|
143
144
|
ignore: DEFAULT_IGNORES,
|
|
145
|
+
frameworksBackend: {
|
|
146
|
+
region: hostingInfo.region,
|
|
147
|
+
},
|
|
144
148
|
};
|
|
145
149
|
}
|
|
146
|
-
|
|
147
|
-
setup.hosting
|
|
148
|
-
|
|
149
|
-
|
|
150
|
+
else {
|
|
151
|
+
setup.config.hosting = {
|
|
152
|
+
public: hostingInfo.public,
|
|
153
|
+
ignore: DEFAULT_IGNORES,
|
|
154
|
+
};
|
|
155
|
+
if (hostingInfo.spa) {
|
|
150
156
|
setup.config.hosting.rewrites = [{ source: "**", destination: "/index.html" }];
|
|
151
157
|
}
|
|
152
158
|
else {
|
|
153
|
-
await config.askWriteProjectFile(`${
|
|
159
|
+
await config.askWriteProjectFile(`${hostingInfo.public}/404.html`, MISSING_TEMPLATE, !!options.force);
|
|
154
160
|
}
|
|
155
161
|
const c = new apiv2_1.Client({ urlPrefix: "https://www.gstatic.com", auth: false });
|
|
156
162
|
const response = await c.get("/firebasejs/releases.json");
|
|
157
|
-
await config.askWriteProjectFile(`${
|
|
158
|
-
}
|
|
159
|
-
if (setup.hosting.github) {
|
|
160
|
-
return (0, github_1.initGitHub)(setup);
|
|
163
|
+
await config.askWriteProjectFile(`${hostingInfo.public}/index.html`, INDEX_TEMPLATE.replace(/{{VERSION}}/g, response.body.current.version), !!options.force);
|
|
161
164
|
}
|
|
162
165
|
}
|
|
163
|
-
exports.
|
|
166
|
+
exports.actuate = actuate;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.aiLogicActuate = exports.aiLogicAskQuestions = exports.aitools = exports.apptestingAcutate = exports.apptestingAskQuestions = exports.genkit = exports.apphosting = exports.dataconnectSdkActuate = exports.dataconnectSdkAskQuestions = exports.dataconnectActuate = exports.dataconnectAskQuestions = exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storageActuate = exports.storageAskQuestions = exports.
|
|
3
|
+
exports.aiLogicActuate = exports.aiLogicAskQuestions = exports.aitools = exports.apptestingAcutate = exports.apptestingAskQuestions = exports.genkit = exports.apphosting = exports.dataconnectSdkActuate = exports.dataconnectSdkAskQuestions = exports.dataconnectActuate = exports.dataconnectAskQuestions = exports.hostingGithub = exports.remoteconfig = exports.project = exports.extensions = exports.emulators = exports.storageActuate = exports.storageAskQuestions = exports.hostingActuate = exports.hostingAskQuestions = exports.functions = exports.firestoreActuate = exports.firestoreAskQuestions = exports.databaseActuate = exports.databaseAskQuestions = exports.account = void 0;
|
|
4
4
|
var account_1 = require("./account");
|
|
5
5
|
Object.defineProperty(exports, "account", { enumerable: true, get: function () { return account_1.doSetup; } });
|
|
6
6
|
var database_1 = require("./database");
|
|
@@ -12,7 +12,8 @@ Object.defineProperty(exports, "firestoreActuate", { enumerable: true, get: func
|
|
|
12
12
|
var functions_1 = require("./functions");
|
|
13
13
|
Object.defineProperty(exports, "functions", { enumerable: true, get: function () { return functions_1.doSetup; } });
|
|
14
14
|
var hosting_1 = require("./hosting");
|
|
15
|
-
Object.defineProperty(exports, "
|
|
15
|
+
Object.defineProperty(exports, "hostingAskQuestions", { enumerable: true, get: function () { return hosting_1.askQuestions; } });
|
|
16
|
+
Object.defineProperty(exports, "hostingActuate", { enumerable: true, get: function () { return hosting_1.actuate; } });
|
|
16
17
|
var storage_1 = require("./storage");
|
|
17
18
|
Object.defineProperty(exports, "storageAskQuestions", { enumerable: true, get: function () { return storage_1.askQuestions; } });
|
|
18
19
|
Object.defineProperty(exports, "storageActuate", { enumerable: true, get: function () { return storage_1.actuate; } });
|
package/lib/init/index.js
CHANGED
|
@@ -30,7 +30,11 @@ const featuresList = [
|
|
|
30
30
|
actuate: features.dataconnectSdkActuate,
|
|
31
31
|
},
|
|
32
32
|
{ name: "functions", doSetup: features.functions },
|
|
33
|
-
{
|
|
33
|
+
{
|
|
34
|
+
name: "hosting",
|
|
35
|
+
askQuestions: features.hostingAskQuestions,
|
|
36
|
+
actuate: features.hostingActuate,
|
|
37
|
+
},
|
|
34
38
|
{
|
|
35
39
|
name: "storage",
|
|
36
40
|
askQuestions: features.storageAskQuestions,
|