firebase-tools 12.8.0 → 12.9.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/commands/deploy.js +23 -2
- package/lib/commands/firestore-databases-update.js +16 -9
- package/lib/commands/{frameworks-stacks-create.js → frameworks-backends-create.js} +2 -2
- package/lib/commands/{frameworks-stacks-delete.js → frameworks-backends-delete.js} +10 -10
- package/lib/commands/frameworks-backends-get.js +41 -0
- package/lib/commands/frameworks-backends-list.js +41 -0
- package/lib/commands/hosting-channel-create.js +12 -1
- package/lib/commands/hosting-sites-create.js +9 -28
- package/lib/commands/index.js +5 -5
- package/lib/emulator/controller.js +1 -0
- package/lib/emulator/functionsEmulator.js +2 -2
- package/lib/firestore/api.js +1 -2
- package/lib/functions/env.js +0 -1
- package/lib/functionsShellCommandAction.js +1 -1
- package/lib/gcp/frameworks.js +14 -14
- package/lib/getDefaultHostingSite.js +18 -4
- package/lib/hosting/api.js +13 -3
- package/lib/hosting/interactive.js +75 -0
- package/lib/init/features/frameworks/index.js +28 -28
- package/lib/init/features/hosting/index.js +28 -2
- package/package.json +1 -1
- package/lib/commands/frameworks-stacks-get.js +0 -29
- package/lib/commands/frameworks-stacks-list.js +0 -24
package/lib/commands/deploy.js
CHANGED
|
@@ -10,6 +10,11 @@ const deploy_1 = require("../deploy");
|
|
|
10
10
|
const requireConfig_1 = require("../requireConfig");
|
|
11
11
|
const filterTargets_1 = require("../filterTargets");
|
|
12
12
|
const requireHostingSite_1 = require("../requireHostingSite");
|
|
13
|
+
const getDefaultHostingSite_1 = require("../getDefaultHostingSite");
|
|
14
|
+
const error_1 = require("../error");
|
|
15
|
+
const colorette_1 = require("colorette");
|
|
16
|
+
const interactive_1 = require("../hosting/interactive");
|
|
17
|
+
const utils_1 = require("../utils");
|
|
13
18
|
exports.VALID_DEPLOY_TARGETS = [
|
|
14
19
|
"database",
|
|
15
20
|
"storage",
|
|
@@ -45,7 +50,7 @@ exports.TARGET_PERMISSIONS = {
|
|
|
45
50
|
};
|
|
46
51
|
exports.command = new command_1.Command("deploy")
|
|
47
52
|
.description("deploy code and assets to your Firebase project")
|
|
48
|
-
.withForce("delete Cloud Functions missing from the current working directory
|
|
53
|
+
.withForce("delete Cloud Functions missing from the current working directory and bypass interactive prompts")
|
|
49
54
|
.option("-p, --public <path>", "override the Hosting public directory specified in firebase.json")
|
|
50
55
|
.option("-m, --message <message>", "an optional message describing this deploy")
|
|
51
56
|
.option("--only <targets>", 'only deploy to specified, comma-separated targets (e.g. "hosting,storage"). For functions, ' +
|
|
@@ -71,7 +76,23 @@ exports.command = new command_1.Command("deploy")
|
|
|
71
76
|
await (0, requireDatabaseInstance_1.requireDatabaseInstance)(options);
|
|
72
77
|
}
|
|
73
78
|
if (options.filteredTargets.includes("hosting")) {
|
|
74
|
-
|
|
79
|
+
let createSite = false;
|
|
80
|
+
try {
|
|
81
|
+
await (0, requireHostingSite_1.requireHostingSite)(options);
|
|
82
|
+
}
|
|
83
|
+
catch (err) {
|
|
84
|
+
if (err === getDefaultHostingSite_1.errNoDefaultSite) {
|
|
85
|
+
createSite = true;
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
if (!createSite) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (options.nonInteractive) {
|
|
92
|
+
throw new error_1.FirebaseError(`Unable to deploy to Hosting as there is no Hosting site. Use ${(0, colorette_1.bold)("firebase hosting:sites:create")} to create a site.`);
|
|
93
|
+
}
|
|
94
|
+
(0, utils_1.logBullet)("No Hosting site detected.");
|
|
95
|
+
await (0, interactive_1.interactiveCreateHostingSite)("", "", options);
|
|
75
96
|
}
|
|
76
97
|
})
|
|
77
98
|
.before(checkValidTargetFilters_1.checkValidTargetFilters)
|
|
@@ -18,30 +18,37 @@ exports.command = new command_1.Command("firestore:databases:update <database>")
|
|
|
18
18
|
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
19
19
|
.action(async (database, options) => {
|
|
20
20
|
const api = new fsi.FirestoreApi();
|
|
21
|
-
if (!options.
|
|
21
|
+
if (!options.deleteProtection && !options.pointInTimeRecovery) {
|
|
22
22
|
logger_1.logger.error("Missing properties to update. See firebase firestore:databases:update --help for more info.");
|
|
23
23
|
return;
|
|
24
24
|
}
|
|
25
|
-
const type = types.DatabaseType.FIRESTORE_NATIVE;
|
|
26
25
|
if (options.deleteProtection &&
|
|
27
26
|
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED &&
|
|
28
27
|
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.DISABLED) {
|
|
29
28
|
logger_1.logger.error("Invalid value for flag --delete-protection. See firebase firestore:databases:update --help for more info.");
|
|
30
29
|
return;
|
|
31
30
|
}
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
31
|
+
let deleteProtectionState;
|
|
32
|
+
if (options.deleteProtection === types.DatabaseDeleteProtectionStateOption.ENABLED) {
|
|
33
|
+
deleteProtectionState = types.DatabaseDeleteProtectionState.ENABLED;
|
|
34
|
+
}
|
|
35
|
+
else if (options.deleteProtection === types.DatabaseDeleteProtectionStateOption.DISABLED) {
|
|
36
|
+
deleteProtectionState = types.DatabaseDeleteProtectionState.DISABLED;
|
|
37
|
+
}
|
|
35
38
|
if (options.pointInTimeRecovery &&
|
|
36
39
|
options.pointInTimeRecovery !== types.PointInTimeRecoveryEnablementOption.ENABLED &&
|
|
37
40
|
options.pointInTimeRecovery !== types.PointInTimeRecoveryEnablementOption.DISABLED) {
|
|
38
41
|
logger_1.logger.error("Invalid value for flag --point-in-time-recovery. See firebase firestore:databases:update --help for more info.");
|
|
39
42
|
return;
|
|
40
43
|
}
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
44
|
+
let pointInTimeRecoveryEnablement;
|
|
45
|
+
if (options.pointInTimeRecovery === types.PointInTimeRecoveryEnablementOption.ENABLED) {
|
|
46
|
+
pointInTimeRecoveryEnablement = types.PointInTimeRecoveryEnablement.ENABLED;
|
|
47
|
+
}
|
|
48
|
+
else if (options.pointInTimeRecovery === types.PointInTimeRecoveryEnablementOption.DISABLED) {
|
|
49
|
+
pointInTimeRecoveryEnablement = types.PointInTimeRecoveryEnablement.DISABLED;
|
|
50
|
+
}
|
|
51
|
+
const databaseResp = await api.updateDatabase(options.project, database, deleteProtectionState, pointInTimeRecoveryEnablement);
|
|
45
52
|
if (options.json) {
|
|
46
53
|
logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
|
|
47
54
|
}
|
|
@@ -5,8 +5,8 @@ const command_1 = require("../command");
|
|
|
5
5
|
const projectUtils_1 = require("../projectUtils");
|
|
6
6
|
const requireInteractive_1 = require("../requireInteractive");
|
|
7
7
|
const frameworks_1 = require("../init/features/frameworks");
|
|
8
|
-
exports.command = new command_1.Command("
|
|
9
|
-
.description("Create a
|
|
8
|
+
exports.command = new command_1.Command("backends:create")
|
|
9
|
+
.description("Create a backend in a Firebase project")
|
|
10
10
|
.before(requireInteractive_1.default)
|
|
11
11
|
.action(async (options) => {
|
|
12
12
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
@@ -7,32 +7,32 @@ const error_1 = require("../error");
|
|
|
7
7
|
const gcp = require("../gcp/frameworks");
|
|
8
8
|
const prompt_1 = require("../prompt");
|
|
9
9
|
const utils = require("../utils");
|
|
10
|
-
exports.command = new command_1.Command("
|
|
11
|
-
.description("Delete a
|
|
10
|
+
exports.command = new command_1.Command("backends:delete")
|
|
11
|
+
.description("Delete a backend from a Firebase project")
|
|
12
12
|
.option("-l, --location <location>", "App Backend location", "us-central1")
|
|
13
|
-
.option("-s, --
|
|
13
|
+
.option("-s, --backendId <backendId>", "Backend Id", "")
|
|
14
14
|
.withForce()
|
|
15
15
|
.action(async (options) => {
|
|
16
16
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
17
17
|
const location = options.location;
|
|
18
|
-
const
|
|
19
|
-
if (!
|
|
20
|
-
throw new error_1.FirebaseError("
|
|
18
|
+
const backendId = options.backendId;
|
|
19
|
+
if (!backendId) {
|
|
20
|
+
throw new error_1.FirebaseError("Backend id can't be empty.");
|
|
21
21
|
}
|
|
22
22
|
const confirmDeletion = await (0, prompt_1.promptOnce)({
|
|
23
23
|
type: "confirm",
|
|
24
24
|
name: "force",
|
|
25
25
|
default: false,
|
|
26
|
-
message: "You are about to delete the
|
|
26
|
+
message: "You are about to delete the backend with id: " + backendId + "\n Are you sure?",
|
|
27
27
|
}, options);
|
|
28
28
|
if (!confirmDeletion) {
|
|
29
29
|
throw new error_1.FirebaseError("Deletion aborted.");
|
|
30
30
|
}
|
|
31
31
|
try {
|
|
32
|
-
await gcp.
|
|
33
|
-
utils.logSuccess(`Successfully deleted the
|
|
32
|
+
await gcp.deleteBackend(projectId, location, backendId);
|
|
33
|
+
utils.logSuccess(`Successfully deleted the backend: ${backendId}`);
|
|
34
34
|
}
|
|
35
35
|
catch (err) {
|
|
36
|
-
throw new error_1.FirebaseError(`Failed to delete
|
|
36
|
+
throw new error_1.FirebaseError(`Failed to delete backend: ${backendId}. Please check the parameters you have provided.`, { original: err });
|
|
37
37
|
}
|
|
38
38
|
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const projectUtils_1 = require("../projectUtils");
|
|
6
|
+
const gcp = require("../gcp/frameworks");
|
|
7
|
+
const error_1 = require("../error");
|
|
8
|
+
const logger_1 = require("../logger");
|
|
9
|
+
const Table = require("cli-table");
|
|
10
|
+
exports.command = new command_1.Command("backends:get")
|
|
11
|
+
.description("Get backend details of a Firebase project")
|
|
12
|
+
.option("-l, --location <location>", "App Backend location", "us-central1")
|
|
13
|
+
.option("--s, --backendId <backendId>", "Backend Id", "")
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
16
|
+
const location = options.location;
|
|
17
|
+
const backendId = options.backendId;
|
|
18
|
+
if (!backendId) {
|
|
19
|
+
throw new error_1.FirebaseError("Backend id can't be empty.");
|
|
20
|
+
}
|
|
21
|
+
let backend;
|
|
22
|
+
try {
|
|
23
|
+
backend = await gcp.getBackend(projectId, location, backendId);
|
|
24
|
+
const table = new Table({
|
|
25
|
+
head: ["Backend Id", "Repository Name", "URL", "Location", "Created Date", "Updated Date"],
|
|
26
|
+
style: { head: ["green"] },
|
|
27
|
+
});
|
|
28
|
+
table.push([
|
|
29
|
+
backend.name,
|
|
30
|
+
backend.codebase.repository,
|
|
31
|
+
backend.uri,
|
|
32
|
+
backend.createTime,
|
|
33
|
+
backend.updateTime,
|
|
34
|
+
]);
|
|
35
|
+
logger_1.logger.info(table.toString());
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new error_1.FirebaseError(`Failed to get backend: ${backendId}. Please check the parameters you have provided.`, { original: err });
|
|
39
|
+
}
|
|
40
|
+
return backend;
|
|
41
|
+
});
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const projectUtils_1 = require("../projectUtils");
|
|
6
|
+
const gcp = require("../gcp/frameworks");
|
|
7
|
+
const error_1 = require("../error");
|
|
8
|
+
const logger_1 = require("../logger");
|
|
9
|
+
const colorette_1 = require("colorette");
|
|
10
|
+
const Table = require("cli-table");
|
|
11
|
+
exports.command = new command_1.Command("backends:list")
|
|
12
|
+
.description("List backends of a Firebase project.")
|
|
13
|
+
.option("-l, --location <location>", "App Backend location", "us-central1")
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
16
|
+
const location = options.location;
|
|
17
|
+
const table = new Table({
|
|
18
|
+
head: ["Backend Id", "Repository Name", "URL", "Location", "Created Date", "Updated Date"],
|
|
19
|
+
style: { head: ["green"] },
|
|
20
|
+
});
|
|
21
|
+
let backendsList;
|
|
22
|
+
try {
|
|
23
|
+
backendsList = await gcp.listBackends(projectId, location);
|
|
24
|
+
for (const backend of backendsList.backends) {
|
|
25
|
+
const entry = [
|
|
26
|
+
backend.name,
|
|
27
|
+
backend.codebase.repository,
|
|
28
|
+
backend.uri,
|
|
29
|
+
backend.createTime,
|
|
30
|
+
backend.updateTime,
|
|
31
|
+
];
|
|
32
|
+
table.push(entry);
|
|
33
|
+
}
|
|
34
|
+
logger_1.logger.info(`Backends for project ${(0, colorette_1.bold)(projectId)}`);
|
|
35
|
+
logger_1.logger.info(table.toString());
|
|
36
|
+
}
|
|
37
|
+
catch (err) {
|
|
38
|
+
throw new error_1.FirebaseError(`Unable to list backends present in project: ${projectId}. Please check the parameters you have provided.`, { original: err });
|
|
39
|
+
}
|
|
40
|
+
return backendsList;
|
|
41
|
+
});
|
|
@@ -14,6 +14,7 @@ const logger_1 = require("../logger");
|
|
|
14
14
|
const requireConfig_1 = require("../requireConfig");
|
|
15
15
|
const marked_1 = require("marked");
|
|
16
16
|
const requireHostingSite_1 = require("../requireHostingSite");
|
|
17
|
+
const getDefaultHostingSite_1 = require("../getDefaultHostingSite");
|
|
17
18
|
const LOG_TAG = "hosting:channel";
|
|
18
19
|
exports.command = new command_1.Command("hosting:channel:create [channelId]")
|
|
19
20
|
.description("create a Firebase Hosting channel")
|
|
@@ -21,7 +22,17 @@ exports.command = new command_1.Command("hosting:channel:create [channelId]")
|
|
|
21
22
|
.option("--site <siteId>", "site for which to create the channel")
|
|
22
23
|
.before(requireConfig_1.requireConfig)
|
|
23
24
|
.before(requirePermissions_1.requirePermissions, ["firebasehosting.sites.update"])
|
|
24
|
-
.before(
|
|
25
|
+
.before(async (options) => {
|
|
26
|
+
try {
|
|
27
|
+
await (0, requireHostingSite_1.requireHostingSite)(options);
|
|
28
|
+
}
|
|
29
|
+
catch (err) {
|
|
30
|
+
if (err === getDefaultHostingSite_1.errNoDefaultSite) {
|
|
31
|
+
throw new error_1.FirebaseError(`Unable to deploy to Hosting as there is no Hosting site. Use ${(0, colorette_1.bold)("firebase hosting:sites:create")} to create a site.`);
|
|
32
|
+
}
|
|
33
|
+
throw err;
|
|
34
|
+
}
|
|
35
|
+
})
|
|
25
36
|
.action(async (channelId, options) => {
|
|
26
37
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
27
38
|
const site = options.site;
|
|
@@ -2,14 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
4
|
const colorette_1 = require("colorette");
|
|
5
|
-
const utils_1 = require("../utils");
|
|
6
5
|
const command_1 = require("../command");
|
|
7
|
-
const
|
|
8
|
-
const
|
|
9
|
-
const error_1 = require("../error");
|
|
10
|
-
const requirePermissions_1 = require("../requirePermissions");
|
|
11
|
-
const projectUtils_1 = require("../projectUtils");
|
|
6
|
+
const interactive_1 = require("../hosting/interactive");
|
|
7
|
+
const utils_1 = require("../utils");
|
|
12
8
|
const logger_1 = require("../logger");
|
|
9
|
+
const projectUtils_1 = require("../projectUtils");
|
|
10
|
+
const requirePermissions_1 = require("../requirePermissions");
|
|
11
|
+
const error_1 = require("../error");
|
|
13
12
|
const LOG_TAG = "hosting:sites";
|
|
14
13
|
exports.command = new command_1.Command("hosting:sites:create [siteId]")
|
|
15
14
|
.description("create a Firebase Hosting site")
|
|
@@ -18,29 +17,11 @@ exports.command = new command_1.Command("hosting:sites:create [siteId]")
|
|
|
18
17
|
.action(async (siteId, options) => {
|
|
19
18
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
20
19
|
const appId = options.app;
|
|
21
|
-
if (!siteId) {
|
|
22
|
-
|
|
23
|
-
throw new error_1.FirebaseError(`"siteId" argument must be provided in a non-interactive environment`);
|
|
24
|
-
}
|
|
25
|
-
siteId = await (0, prompt_1.promptOnce)({
|
|
26
|
-
type: "input",
|
|
27
|
-
message: "Please provide an unique, URL-friendly id for the site (<id>.web.app):",
|
|
28
|
-
validate: (s) => s.length > 0,
|
|
29
|
-
});
|
|
30
|
-
}
|
|
31
|
-
if (!siteId) {
|
|
32
|
-
throw new error_1.FirebaseError(`"siteId" must not be empty`);
|
|
33
|
-
}
|
|
34
|
-
let site;
|
|
35
|
-
try {
|
|
36
|
-
site = await (0, api_1.createSite)(projectId, siteId, appId);
|
|
37
|
-
}
|
|
38
|
-
catch (e) {
|
|
39
|
-
if (e.status === 409) {
|
|
40
|
-
throw new error_1.FirebaseError(`Site ${(0, colorette_1.bold)(siteId)} already exists in project ${(0, colorette_1.bold)(projectId)}.`, { original: e });
|
|
41
|
-
}
|
|
42
|
-
throw e;
|
|
20
|
+
if (options.nonInteractive && !siteId) {
|
|
21
|
+
throw new error_1.FirebaseError(`${(0, colorette_1.bold)(siteId)} is required in a non-interactive environment`);
|
|
43
22
|
}
|
|
23
|
+
const site = await (0, interactive_1.interactiveCreateHostingSite)(siteId, appId, options);
|
|
24
|
+
siteId = (0, utils_1.last)(site.name.split("/"));
|
|
44
25
|
logger_1.logger.info();
|
|
45
26
|
(0, utils_1.logLabeledSuccess)(LOG_TAG, `Site ${(0, colorette_1.bold)(siteId)} has been created in project ${(0, colorette_1.bold)(projectId)}.`);
|
|
46
27
|
if (appId) {
|
package/lib/commands/index.js
CHANGED
|
@@ -147,11 +147,11 @@ function load(client) {
|
|
|
147
147
|
}
|
|
148
148
|
if (experiments.isEnabled("internalframeworks")) {
|
|
149
149
|
client.frameworks = {};
|
|
150
|
-
client.frameworks.
|
|
151
|
-
client.frameworks.
|
|
152
|
-
client.frameworks.
|
|
153
|
-
client.frameworks.
|
|
154
|
-
client.frameworks.
|
|
150
|
+
client.frameworks.backends = {};
|
|
151
|
+
client.frameworks.backends.list = loadCommand("frameworks-backends-list");
|
|
152
|
+
client.frameworks.backends.create = loadCommand("frameworks-backends-create");
|
|
153
|
+
client.frameworks.backends.get = loadCommand("frameworks-backends-get");
|
|
154
|
+
client.frameworks.backends.delete = loadCommand("frameworks-backends-delete");
|
|
155
155
|
}
|
|
156
156
|
client.login = loadCommand("login");
|
|
157
157
|
client.login.add = loadCommand("login-add");
|
|
@@ -352,6 +352,7 @@ async function startAll(options, showUI = true, runningTestScript = false) {
|
|
|
352
352
|
host: functionsAddr.host,
|
|
353
353
|
port: functionsAddr.port,
|
|
354
354
|
debugPort: inspectFunctions,
|
|
355
|
+
verbosity: options.logVerbosity,
|
|
355
356
|
projectAlias: options.projectAlias,
|
|
356
357
|
});
|
|
357
358
|
await startEmulator(functionsEmulator);
|
|
@@ -82,7 +82,7 @@ class FunctionsEmulator {
|
|
|
82
82
|
this.multicastTriggers = {};
|
|
83
83
|
this.blockingFunctionsConfig = {};
|
|
84
84
|
this.debugMode = false;
|
|
85
|
-
emulatorLogger_1.EmulatorLogger.setVerbosity(this.args.
|
|
85
|
+
emulatorLogger_1.EmulatorLogger.setVerbosity(this.args.verbosity ? emulatorLogger_1.Verbosity[this.args.verbosity] : emulatorLogger_1.Verbosity["DEBUG"]);
|
|
86
86
|
if (this.args.debugPort) {
|
|
87
87
|
this.args.disabledRuntimeFeatures = this.args.disabledRuntimeFeatures || {};
|
|
88
88
|
this.args.disabledRuntimeFeatures.timeout = true;
|
|
@@ -337,7 +337,6 @@ class FunctionsEmulator {
|
|
|
337
337
|
else {
|
|
338
338
|
this.workerPools[emulatableBackend.codebase].refresh();
|
|
339
339
|
}
|
|
340
|
-
this.blockingFunctionsConfig = {};
|
|
341
340
|
const toSetup = triggerDefinitions.filter((definition) => {
|
|
342
341
|
if (force) {
|
|
343
342
|
return true;
|
|
@@ -923,6 +922,7 @@ class FunctionsEmulator {
|
|
|
923
922
|
}
|
|
924
923
|
async reloadTriggers() {
|
|
925
924
|
this.triggerGeneration++;
|
|
925
|
+
this.blockingFunctionsConfig = {};
|
|
926
926
|
for (const backend of this.args.emulatableBackends) {
|
|
927
927
|
await this.loadTriggers(backend);
|
|
928
928
|
}
|
package/lib/firestore/api.js
CHANGED
|
@@ -485,10 +485,9 @@ class FirestoreApi {
|
|
|
485
485
|
}
|
|
486
486
|
return database;
|
|
487
487
|
}
|
|
488
|
-
async updateDatabase(project, databaseId,
|
|
488
|
+
async updateDatabase(project, databaseId, deleteProtectionState, pointInTimeRecoveryEnablement) {
|
|
489
489
|
const url = `/projects/${project}/databases/${databaseId}`;
|
|
490
490
|
const payload = {
|
|
491
|
-
type,
|
|
492
491
|
deleteProtectionState,
|
|
493
492
|
pointInTimeRecoveryEnablement,
|
|
494
493
|
};
|
package/lib/functions/env.js
CHANGED
package/lib/gcp/frameworks.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.createBuild = exports.
|
|
3
|
+
exports.createBuild = exports.deleteBackend = exports.listBackends = exports.getBackend = exports.createBackend = exports.API_VERSION = void 0;
|
|
4
4
|
const apiv2_1 = require("../apiv2");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
6
|
exports.API_VERSION = "v1alpha";
|
|
@@ -9,32 +9,32 @@ const client = new apiv2_1.Client({
|
|
|
9
9
|
auth: true,
|
|
10
10
|
apiVersion: exports.API_VERSION,
|
|
11
11
|
});
|
|
12
|
-
async function
|
|
13
|
-
const res = await client.post(`projects/${projectId}/locations/${location}/backends`,
|
|
12
|
+
async function createBackend(projectId, location, backendReqBoby, backendId) {
|
|
13
|
+
const res = await client.post(`projects/${projectId}/locations/${location}/backends`, backendReqBoby, { queryParams: { backendId } });
|
|
14
14
|
return res.body;
|
|
15
15
|
}
|
|
16
|
-
exports.
|
|
17
|
-
async function
|
|
18
|
-
const name = `projects/${projectId}/locations/${location}/backends/${
|
|
16
|
+
exports.createBackend = createBackend;
|
|
17
|
+
async function getBackend(projectId, location, backendId) {
|
|
18
|
+
const name = `projects/${projectId}/locations/${location}/backends/${backendId}`;
|
|
19
19
|
const res = await client.get(name);
|
|
20
20
|
return res.body;
|
|
21
21
|
}
|
|
22
|
-
exports.
|
|
23
|
-
async function
|
|
22
|
+
exports.getBackend = getBackend;
|
|
23
|
+
async function listBackends(projectId, location) {
|
|
24
24
|
const name = `projects/${projectId}/locations/${location}/backends`;
|
|
25
25
|
const res = await client.get(name);
|
|
26
26
|
return res.body;
|
|
27
27
|
}
|
|
28
|
-
exports.
|
|
29
|
-
async function
|
|
30
|
-
const name = `projects/${projectId}/locations/${location}/backends/${
|
|
28
|
+
exports.listBackends = listBackends;
|
|
29
|
+
async function deleteBackend(projectId, location, backendId) {
|
|
30
|
+
const name = `projects/${projectId}/locations/${location}/backends/${backendId}`;
|
|
31
31
|
const res = await client.delete(name);
|
|
32
32
|
return res.body;
|
|
33
33
|
}
|
|
34
|
-
exports.
|
|
35
|
-
async function createBuild(projectId, location,
|
|
34
|
+
exports.deleteBackend = deleteBackend;
|
|
35
|
+
async function createBuild(projectId, location, backendId, buildInput) {
|
|
36
36
|
const buildId = buildInput.name;
|
|
37
|
-
const res = await client.post(`projects/${projectId}/locations/${location}/backends/${
|
|
37
|
+
const res = await client.post(`projects/${projectId}/locations/${location}/backends/${backendId}/builds`, buildInput, { queryParams: { buildId } });
|
|
38
38
|
return res.body;
|
|
39
39
|
}
|
|
40
40
|
exports.createBuild = createBuild;
|
|
@@ -1,17 +1,31 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getDefaultHostingSite = void 0;
|
|
3
|
+
exports.getDefaultHostingSite = exports.errNoDefaultSite = void 0;
|
|
4
|
+
const error_1 = require("./error");
|
|
5
|
+
const api_1 = require("./hosting/api");
|
|
4
6
|
const logger_1 = require("./logger");
|
|
5
7
|
const projects_1 = require("./management/projects");
|
|
6
8
|
const projectUtils_1 = require("./projectUtils");
|
|
9
|
+
const utils_1 = require("./utils");
|
|
10
|
+
exports.errNoDefaultSite = new error_1.FirebaseError("Could not determine the default site for the project.");
|
|
7
11
|
async function getDefaultHostingSite(options) {
|
|
8
12
|
var _a;
|
|
9
13
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
10
14
|
const project = await (0, projects_1.getFirebaseProject)(projectId);
|
|
11
|
-
|
|
15
|
+
let site = (_a = project.resources) === null || _a === void 0 ? void 0 : _a.hostingSite;
|
|
12
16
|
if (!site) {
|
|
13
|
-
logger_1.logger.debug(`
|
|
14
|
-
|
|
17
|
+
logger_1.logger.debug(`the default site does not exist on the Firebase project; asking Hosting.`);
|
|
18
|
+
const sites = await (0, api_1.listSites)(projectId);
|
|
19
|
+
for (const s of sites) {
|
|
20
|
+
if (s.type === api_1.SiteType.DEFAULT_SITE) {
|
|
21
|
+
site = (0, utils_1.last)(s.name.split("/"));
|
|
22
|
+
break;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!site) {
|
|
26
|
+
throw exports.errNoDefaultSite;
|
|
27
|
+
}
|
|
28
|
+
return site;
|
|
15
29
|
}
|
|
16
30
|
return site;
|
|
17
31
|
}
|
package/lib/hosting/api.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.getAllSiteDomains = exports.getSiteDomains = exports.cleanAuthState = exports.getCleanDomains = exports.removeAuthDomain = exports.addAuthDomains = exports.deleteSite = exports.updateSite = exports.createSite = exports.getSite = exports.listSites = exports.createRelease = exports.cloneVersion = exports.listVersions = exports.updateVersion = exports.createVersion = exports.deleteChannel = exports.updateChannelTtl = exports.createChannel = exports.listChannels = exports.getChannel = exports.normalizeName = void 0;
|
|
3
|
+
exports.getAllSiteDomains = exports.getSiteDomains = exports.cleanAuthState = exports.getCleanDomains = exports.removeAuthDomain = exports.addAuthDomains = exports.deleteSite = exports.updateSite = exports.createSite = exports.getSite = exports.listSites = exports.createRelease = exports.cloneVersion = exports.listVersions = exports.updateVersion = exports.createVersion = exports.deleteChannel = exports.updateChannelTtl = exports.createChannel = exports.listChannels = exports.getChannel = exports.normalizeName = exports.SiteType = void 0;
|
|
4
4
|
const error_1 = require("../error");
|
|
5
5
|
const api_1 = require("../api");
|
|
6
6
|
const apiv2_1 = require("../apiv2");
|
|
@@ -16,6 +16,12 @@ var ReleaseType;
|
|
|
16
16
|
ReleaseType["ROLLBACK"] = "ROLLBACK";
|
|
17
17
|
ReleaseType["SITE_DISABLE"] = "SITE_DISABLE";
|
|
18
18
|
})(ReleaseType || (ReleaseType = {}));
|
|
19
|
+
var SiteType;
|
|
20
|
+
(function (SiteType) {
|
|
21
|
+
SiteType["TYPE_UNSPECIFIED"] = "TYPE_UNSPECIFIED";
|
|
22
|
+
SiteType["DEFAULT_SITE"] = "DEFAULT_SITE";
|
|
23
|
+
SiteType["USER_SITE"] = "USER_SITE";
|
|
24
|
+
})(SiteType = exports.SiteType || (exports.SiteType = {}));
|
|
19
25
|
function normalizeName(s) {
|
|
20
26
|
return s.replace(/[/:_#]/g, "-");
|
|
21
27
|
}
|
|
@@ -170,8 +176,12 @@ async function getSite(project, site) {
|
|
|
170
176
|
}
|
|
171
177
|
}
|
|
172
178
|
exports.getSite = getSite;
|
|
173
|
-
async function createSite(project, site, appId = "") {
|
|
174
|
-
const
|
|
179
|
+
async function createSite(project, site, appId = "", validateOnly = false) {
|
|
180
|
+
const queryParams = { siteId: site };
|
|
181
|
+
if (validateOnly) {
|
|
182
|
+
queryParams.validateOnly = "true";
|
|
183
|
+
}
|
|
184
|
+
const res = await apiClient.post(`/projects/${project}/sites`, { appId: appId }, { queryParams });
|
|
175
185
|
return res.body;
|
|
176
186
|
}
|
|
177
187
|
exports.createSite = createSite;
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.interactiveCreateHostingSite = void 0;
|
|
4
|
+
const error_1 = require("../error");
|
|
5
|
+
const utils_1 = require("../utils");
|
|
6
|
+
const projectUtils_1 = require("../projectUtils");
|
|
7
|
+
const prompt_1 = require("../prompt");
|
|
8
|
+
const api_1 = require("./api");
|
|
9
|
+
const nameSuggestion = new RegExp("try something like `(.+)`");
|
|
10
|
+
const prompt = "Please provide an unique, URL-friendly id for your site. Your site's URL will be <site-id>.web.app. " +
|
|
11
|
+
'We recommend using letters, numbers, and hyphens (e.g. "{project-id}-{random-hash}"):';
|
|
12
|
+
async function interactiveCreateHostingSite(siteId, appId, options) {
|
|
13
|
+
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
14
|
+
const projectNumber = await (0, projectUtils_1.needProjectNumber)(options);
|
|
15
|
+
let id = siteId;
|
|
16
|
+
let newSite;
|
|
17
|
+
let suggestion;
|
|
18
|
+
if (!id) {
|
|
19
|
+
const attempt = await trySiteID(projectNumber, projectId);
|
|
20
|
+
if (attempt.available) {
|
|
21
|
+
suggestion = projectId;
|
|
22
|
+
}
|
|
23
|
+
else {
|
|
24
|
+
suggestion = attempt.suggestion;
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
while (!newSite) {
|
|
28
|
+
if (!id || suggestion) {
|
|
29
|
+
id = await (0, prompt_1.promptOnce)({
|
|
30
|
+
type: "input",
|
|
31
|
+
message: prompt,
|
|
32
|
+
validate: (s) => s.length > 0,
|
|
33
|
+
default: suggestion,
|
|
34
|
+
});
|
|
35
|
+
}
|
|
36
|
+
try {
|
|
37
|
+
newSite = await (0, api_1.createSite)(projectNumber, id, appId);
|
|
38
|
+
}
|
|
39
|
+
catch (err) {
|
|
40
|
+
if (!(err instanceof error_1.FirebaseError)) {
|
|
41
|
+
throw err;
|
|
42
|
+
}
|
|
43
|
+
if (options.nonInteractive) {
|
|
44
|
+
throw err;
|
|
45
|
+
}
|
|
46
|
+
suggestion = getSuggestionFromError(err);
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
return newSite;
|
|
50
|
+
}
|
|
51
|
+
exports.interactiveCreateHostingSite = interactiveCreateHostingSite;
|
|
52
|
+
async function trySiteID(projectNumber, id) {
|
|
53
|
+
try {
|
|
54
|
+
await (0, api_1.createSite)(projectNumber, id, "", true);
|
|
55
|
+
return { available: true };
|
|
56
|
+
}
|
|
57
|
+
catch (err) {
|
|
58
|
+
if (!(err instanceof error_1.FirebaseError)) {
|
|
59
|
+
throw err;
|
|
60
|
+
}
|
|
61
|
+
const suggestion = getSuggestionFromError(err);
|
|
62
|
+
return { available: false, suggestion };
|
|
63
|
+
}
|
|
64
|
+
}
|
|
65
|
+
function getSuggestionFromError(err) {
|
|
66
|
+
if (err.status === 400 && err.message.includes("Invalid name:")) {
|
|
67
|
+
const i = err.message.indexOf("Invalid name:");
|
|
68
|
+
(0, utils_1.logWarning)(err.message.substring(i));
|
|
69
|
+
const match = nameSuggestion.exec(err.message);
|
|
70
|
+
if (match) {
|
|
71
|
+
return match[1];
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.
|
|
3
|
+
exports.createBackend = exports.getOrCreateBackend = exports.doSetup = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const utils = require("../../../utils");
|
|
6
6
|
const logger_1 = require("../../../logger");
|
|
@@ -44,13 +44,13 @@ async function doSetup(setup, projectId) {
|
|
|
44
44
|
message: "How do you want to deploy",
|
|
45
45
|
choices: constants_1.ALLOWED_DEPLOY_METHODS,
|
|
46
46
|
}, setup.frameworks);
|
|
47
|
-
const
|
|
48
|
-
if (
|
|
49
|
-
utils.logSuccess(`Successfully created a
|
|
47
|
+
const backend = await getOrCreateBackend(projectId, setup);
|
|
48
|
+
if (backend) {
|
|
49
|
+
utils.logSuccess(`Successfully created a backend: ${backend.name}`);
|
|
50
50
|
}
|
|
51
51
|
}
|
|
52
52
|
exports.doSetup = doSetup;
|
|
53
|
-
function
|
|
53
|
+
function toBackend(cloudBuildConnRepo) {
|
|
54
54
|
return {
|
|
55
55
|
codebase: {
|
|
56
56
|
repository: `${cloudBuildConnRepo.name}`,
|
|
@@ -59,41 +59,41 @@ function toStack(cloudBuildConnRepo) {
|
|
|
59
59
|
labels: {},
|
|
60
60
|
};
|
|
61
61
|
}
|
|
62
|
-
async function
|
|
62
|
+
async function getOrCreateBackend(projectId, setup) {
|
|
63
63
|
const location = setup.frameworks.region;
|
|
64
64
|
const deployMethod = setup.frameworks.deployMethod;
|
|
65
65
|
try {
|
|
66
|
-
return await
|
|
66
|
+
return await getExistingBackend(projectId, setup, location);
|
|
67
67
|
}
|
|
68
68
|
catch (err) {
|
|
69
69
|
if (err.status === 404) {
|
|
70
|
-
logger_1.logger.info("Creating new
|
|
70
|
+
logger_1.logger.info("Creating new backend.");
|
|
71
71
|
if (deployMethod === "github") {
|
|
72
72
|
const cloudBuildConnRepo = await repo.linkGitHubRepository(projectId, location);
|
|
73
|
-
const
|
|
74
|
-
return await
|
|
73
|
+
const backendDetails = toBackend(cloudBuildConnRepo);
|
|
74
|
+
return await createBackend(projectId, location, backendDetails, setup.frameworks.serviceName);
|
|
75
75
|
}
|
|
76
76
|
}
|
|
77
77
|
else {
|
|
78
|
-
throw new error_1.FirebaseError(`Failed to get or create a
|
|
78
|
+
throw new error_1.FirebaseError(`Failed to get or create a backend using the given initialization details: ${err}`);
|
|
79
79
|
}
|
|
80
80
|
}
|
|
81
81
|
return undefined;
|
|
82
82
|
}
|
|
83
|
-
exports.
|
|
84
|
-
async function
|
|
85
|
-
let
|
|
86
|
-
while (
|
|
83
|
+
exports.getOrCreateBackend = getOrCreateBackend;
|
|
84
|
+
async function getExistingBackend(projectId, setup, location) {
|
|
85
|
+
let backend = await gcp.getBackend(projectId, location, setup.frameworks.serviceName);
|
|
86
|
+
while (backend) {
|
|
87
87
|
setup.frameworks.serviceName = undefined;
|
|
88
88
|
await (0, prompt_1.promptOnce)({
|
|
89
|
-
name: "
|
|
89
|
+
name: "existingBackend",
|
|
90
90
|
type: "confirm",
|
|
91
91
|
default: true,
|
|
92
|
-
message: "A
|
|
92
|
+
message: "A backend already exists for the given serviceName, do you want to use existing backend? (yes/no)",
|
|
93
93
|
}, setup.frameworks);
|
|
94
|
-
if (setup.frameworks.
|
|
95
|
-
logger_1.logger.info("Using the existing
|
|
96
|
-
return
|
|
94
|
+
if (setup.frameworks.existingBackend) {
|
|
95
|
+
logger_1.logger.info("Using the existing backend.");
|
|
96
|
+
return backend;
|
|
97
97
|
}
|
|
98
98
|
await (0, prompt_1.promptOnce)({
|
|
99
99
|
name: "serviceName",
|
|
@@ -101,14 +101,14 @@ async function getExistingStack(projectId, setup, location) {
|
|
|
101
101
|
default: "acme-inc-web",
|
|
102
102
|
message: "Please enter a new service name [1-30 characters]",
|
|
103
103
|
}, setup.frameworks);
|
|
104
|
-
|
|
105
|
-
setup.frameworks.
|
|
104
|
+
backend = await gcp.getBackend(projectId, location, setup.frameworks.serviceName);
|
|
105
|
+
setup.frameworks.existingBackend = undefined;
|
|
106
106
|
}
|
|
107
|
-
return
|
|
107
|
+
return backend;
|
|
108
108
|
}
|
|
109
|
-
async function
|
|
110
|
-
const op = await gcp.
|
|
111
|
-
const
|
|
112
|
-
return
|
|
109
|
+
async function createBackend(projectId, location, backendReqBoby, backendId) {
|
|
110
|
+
const op = await gcp.createBackend(projectId, location, backendReqBoby, backendId);
|
|
111
|
+
const backend = await poller.pollOperation(Object.assign(Object.assign({}, frameworksPollerOptions), { pollerName: `create-${projectId}-${location}-${backendId}`, operationResourceName: op.name }));
|
|
112
|
+
return backend;
|
|
113
113
|
}
|
|
114
|
-
exports.
|
|
114
|
+
exports.createBackend = createBackend;
|
|
@@ -4,6 +4,7 @@ exports.doSetup = void 0;
|
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const fs = require("fs");
|
|
6
6
|
const rimraf_1 = require("rimraf");
|
|
7
|
+
const path_1 = require("path");
|
|
7
8
|
const apiv2_1 = require("../../../apiv2");
|
|
8
9
|
const github_1 = require("./github");
|
|
9
10
|
const prompt_1 = require("../../../prompt");
|
|
@@ -11,13 +12,38 @@ const logger_1 = require("../../../logger");
|
|
|
11
12
|
const frameworks_1 = require("../../../frameworks");
|
|
12
13
|
const constants_1 = require("../../../frameworks/constants");
|
|
13
14
|
const experiments = require("../../../experiments");
|
|
14
|
-
const
|
|
15
|
+
const getDefaultHostingSite_1 = require("../../../getDefaultHostingSite");
|
|
16
|
+
const utils_1 = require("../../../utils");
|
|
17
|
+
const interactive_1 = require("../../../hosting/interactive");
|
|
15
18
|
const INDEX_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/index.html", "utf8");
|
|
16
19
|
const MISSING_TEMPLATE = fs.readFileSync(__dirname + "/../../../../templates/init/hosting/404.html", "utf8");
|
|
17
20
|
const DEFAULT_IGNORES = ["firebase.json", "**/.*", "**/node_modules/**"];
|
|
18
|
-
async function doSetup(setup, config) {
|
|
21
|
+
async function doSetup(setup, config, options) {
|
|
19
22
|
var _a;
|
|
20
23
|
setup.hosting = {};
|
|
24
|
+
let hasHostingSite = true;
|
|
25
|
+
try {
|
|
26
|
+
await (0, getDefaultHostingSite_1.getDefaultHostingSite)(options);
|
|
27
|
+
}
|
|
28
|
+
catch (err) {
|
|
29
|
+
if (err !== getDefaultHostingSite_1.errNoDefaultSite) {
|
|
30
|
+
throw err;
|
|
31
|
+
}
|
|
32
|
+
hasHostingSite = false;
|
|
33
|
+
}
|
|
34
|
+
if (!hasHostingSite) {
|
|
35
|
+
const confirmCreate = await (0, prompt_1.promptOnce)({
|
|
36
|
+
type: "confirm",
|
|
37
|
+
message: "A Firebase Hosting site is required to deploy. Would you like to create one now?",
|
|
38
|
+
default: true,
|
|
39
|
+
});
|
|
40
|
+
if (confirmCreate) {
|
|
41
|
+
const newSite = await (0, interactive_1.interactiveCreateHostingSite)("", "", options);
|
|
42
|
+
logger_1.logger.info();
|
|
43
|
+
(0, utils_1.logSuccess)(`Firebase Hosting site ${(0, utils_1.last)(newSite.name.split("/"))} created!`);
|
|
44
|
+
logger_1.logger.info();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
21
47
|
let discoveredFramework = experiments.isEnabled("webframeworks")
|
|
22
48
|
? await (0, frameworks_1.discover)(config.projectDir, false)
|
|
23
49
|
: undefined;
|
package/package.json
CHANGED
|
@@ -1,29 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.command = void 0;
|
|
4
|
-
const command_1 = require("../command");
|
|
5
|
-
const projectUtils_1 = require("../projectUtils");
|
|
6
|
-
const gcp = require("../gcp/frameworks");
|
|
7
|
-
const error_1 = require("../error");
|
|
8
|
-
const logger_1 = require("../logger");
|
|
9
|
-
exports.command = new command_1.Command("stacks:get")
|
|
10
|
-
.description("Get stack details of a Firebase project")
|
|
11
|
-
.option("-l, --location <location>", "App Backend location", "us-central1")
|
|
12
|
-
.option("--s, --stackId <stackId>", "Stack Id", "")
|
|
13
|
-
.action(async (options) => {
|
|
14
|
-
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
15
|
-
const location = options.location;
|
|
16
|
-
const stackId = options.stackId;
|
|
17
|
-
if (!stackId) {
|
|
18
|
-
throw new error_1.FirebaseError("Stack id can't be empty.");
|
|
19
|
-
}
|
|
20
|
-
let stack;
|
|
21
|
-
try {
|
|
22
|
-
stack = await gcp.getStack(projectId, location, stackId);
|
|
23
|
-
logger_1.logger.info(stack);
|
|
24
|
-
}
|
|
25
|
-
catch (err) {
|
|
26
|
-
throw new error_1.FirebaseError(`Failed to get stack: ${stackId}. Please check the parameters you have provided.`, { original: err });
|
|
27
|
-
}
|
|
28
|
-
return stack;
|
|
29
|
-
});
|
|
@@ -1,24 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.command = void 0;
|
|
4
|
-
const command_1 = require("../command");
|
|
5
|
-
const projectUtils_1 = require("../projectUtils");
|
|
6
|
-
const gcp = require("../gcp/frameworks");
|
|
7
|
-
const error_1 = require("../error");
|
|
8
|
-
const logger_1 = require("../logger");
|
|
9
|
-
exports.command = new command_1.Command("stacks:list")
|
|
10
|
-
.description("List stacks of a Firebase project.")
|
|
11
|
-
.option("-l, --location <location>", "App Backend location", "us-central1")
|
|
12
|
-
.action(async (options) => {
|
|
13
|
-
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
14
|
-
const location = options.location;
|
|
15
|
-
let stacks;
|
|
16
|
-
try {
|
|
17
|
-
stacks = await gcp.listStack(projectId, location);
|
|
18
|
-
logger_1.logger.info(stacks);
|
|
19
|
-
}
|
|
20
|
-
catch (err) {
|
|
21
|
-
throw new error_1.FirebaseError(`Unable to list stacks present in project: ${projectId}. Please check the parameters you have provided.`, { original: err });
|
|
22
|
-
}
|
|
23
|
-
return stacks;
|
|
24
|
-
});
|