firebase-tools 13.3.0 → 13.4.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.
Files changed (51) hide show
  1. package/lib/api.js +2 -1
  2. package/lib/commands/apphosting-backends-create.js +6 -3
  3. package/lib/commands/apphosting-backends-delete.js +6 -44
  4. package/lib/commands/apphosting-backends-get.js +4 -35
  5. package/lib/commands/apphosting-backends-list.js +17 -9
  6. package/lib/commands/apphosting-builds-create.js +4 -4
  7. package/lib/commands/apphosting-builds-get.js +2 -2
  8. package/lib/commands/apphosting-rollouts-create.js +3 -3
  9. package/lib/commands/apphosting-rollouts-list.js +2 -2
  10. package/lib/commands/firestore-backups-delete.js +44 -0
  11. package/lib/commands/firestore-backups-get.js +25 -0
  12. package/lib/commands/firestore-backups-list.js +34 -0
  13. package/lib/commands/firestore-backups-schedules-create.js +67 -0
  14. package/lib/commands/firestore-backups-schedules-delete.js +46 -0
  15. package/lib/commands/firestore-backups-schedules-list.js +28 -0
  16. package/lib/commands/firestore-backups-schedules-update.js +33 -0
  17. package/lib/commands/firestore-databases-create.js +4 -2
  18. package/lib/commands/firestore-databases-delete.js +4 -2
  19. package/lib/commands/firestore-databases-get.js +3 -1
  20. package/lib/commands/firestore-databases-list.js +3 -1
  21. package/lib/commands/firestore-databases-restore.js +42 -0
  22. package/lib/commands/firestore-databases-update.js +4 -2
  23. package/lib/commands/firestore-indexes-list.js +5 -3
  24. package/lib/commands/firestore-locations.js +3 -1
  25. package/lib/commands/index.js +10 -0
  26. package/lib/deploy/extensions/v2FunctionHelper.js +2 -1
  27. package/lib/deploy/functions/ensure.js +2 -2
  28. package/lib/deploy/functions/prepare.js +5 -9
  29. package/lib/emulator/downloadableEmulators.js +3 -3
  30. package/lib/ensureApiEnabled.js +8 -6
  31. package/lib/extensions/extensionsHelper.js +2 -2
  32. package/lib/extensions/secretsUtils.js +2 -1
  33. package/lib/firestore/api-sort.js +23 -1
  34. package/lib/firestore/api-types.js +6 -1
  35. package/lib/firestore/api.js +18 -115
  36. package/lib/firestore/backupUtils.js +30 -0
  37. package/lib/firestore/pretty-print.js +184 -0
  38. package/lib/functions/secrets.js +1 -1
  39. package/lib/gcp/apphosting.js +4 -5
  40. package/lib/gcp/auth.js +5 -2
  41. package/lib/gcp/cloudbuild.js +7 -2
  42. package/lib/gcp/firestore.js +75 -1
  43. package/lib/gcp/storage.js +1 -1
  44. package/lib/init/features/apphosting/index.js +139 -78
  45. package/lib/init/features/apphosting/repo.js +83 -35
  46. package/lib/init/features/database.js +2 -1
  47. package/lib/init/features/extensions/index.js +2 -1
  48. package/lib/init/features/functions/index.js +3 -2
  49. package/lib/init/features/hosting/github.js +5 -0
  50. package/lib/prompt.js +1 -0
  51. package/package.json +5 -2
package/lib/api.js CHANGED
@@ -1,7 +1,7 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.githubApiOrigin = exports.githubOrigin = exports.apphostingOrigin = exports.serviceUsageOrigin = exports.cloudRunApiOrigin = exports.hostingApiOrigin = exports.firebaseStorageOrigin = exports.storageOrigin = exports.runtimeconfigOrigin = exports.rulesOrigin = exports.resourceManagerOrigin = exports.remoteConfigApiOrigin = exports.rtdbMetadataOrigin = exports.rtdbManagementOrigin = exports.realtimeOrigin = exports.extensionsTOSOrigin = exports.extensionsPublisherOrigin = exports.extensionsOrigin = exports.iamOrigin = exports.identityOrigin = exports.hostingOrigin = exports.googleOrigin = exports.pubsubOrigin = exports.cloudTasksOrigin = exports.cloudschedulerOrigin = exports.cloudbuildOrigin = exports.functionsDefaultRegion = exports.runOrigin = exports.functionsV2Origin = exports.functionsOrigin = exports.firestoreOrigin = exports.firestoreOriginOrEmulator = exports.firedataOrigin = exports.firebaseExtensionsRegistryOrigin = exports.firebaseApiOrigin = exports.eventarcOrigin = exports.dynamicLinksKey = exports.dynamicLinksOrigin = exports.deployOrigin = exports.consoleOrigin = exports.authOrigin = exports.appDistributionOrigin = exports.artifactRegistryDomain = exports.containerRegistryDomain = exports.cloudMonitoringOrigin = exports.cloudloggingOrigin = exports.cloudbillingOrigin = exports.clientSecret = exports.clientId = exports.authProxyOrigin = void 0;
4
- exports.setScopes = exports.getScopes = exports.githubClientSecret = exports.githubClientId = exports.secretManagerOrigin = void 0;
4
+ exports.setScopes = exports.getScopes = exports.githubClientSecret = exports.githubClientId = exports.computeOrigin = exports.secretManagerOrigin = void 0;
5
5
  const constants_1 = require("./emulator/constants");
6
6
  const logger_1 = require("./logger");
7
7
  const scopes = require("./scopes");
@@ -63,6 +63,7 @@ exports.apphostingOrigin = utils.envOverride("APPHOSTING_URL", "https://firebase
63
63
  exports.githubOrigin = utils.envOverride("GITHUB_URL", "https://github.com");
64
64
  exports.githubApiOrigin = utils.envOverride("GITHUB_API_URL", "https://api.github.com");
65
65
  exports.secretManagerOrigin = utils.envOverride("CLOUD_SECRET_MANAGER_URL", "https://secretmanager.googleapis.com");
66
+ exports.computeOrigin = utils.envOverride("COMPUTE_URL", "https://compute.googleapis.com");
66
67
  exports.githubClientId = utils.envOverride("GITHUB_CLIENT_ID", "89cf50f02ac6aaed3484");
67
68
  exports.githubClientSecret = utils.envOverride("GITHUB_CLIENT_SECRET", "3330d14abc895d9a74d5f17cd7a00711fa2c5bf0");
68
69
  function getScopes() {
@@ -7,11 +7,14 @@ const requireInteractive_1 = require("../requireInteractive");
7
7
  const apphosting_1 = require("../init/features/apphosting");
8
8
  const apphosting_2 = require("../gcp/apphosting");
9
9
  exports.command = new command_1.Command("apphosting:backends:create")
10
- .description("Create a backend in a Firebase project")
11
- .option("-l, --location <location>", "Specify the region of the backend", "")
10
+ .description("create a backend in a Firebase project")
11
+ .option("-l, --location <location>", "specify the region of the backend", "")
12
+ .option("-s, --service-account <serviceAccount>", "specify the service account used to run the server", "")
12
13
  .before(apphosting_2.ensureApiEnabled)
13
14
  .before(requireInteractive_1.default)
14
15
  .action(async (options) => {
15
16
  const projectId = (0, projectUtils_1.needProjectId)(options);
16
- await (0, apphosting_1.doSetup)(options, projectId);
17
+ const location = options.location;
18
+ const serviceAccount = options.serviceAccount;
19
+ await (0, apphosting_1.doSetup)(projectId, location, serviceAccount);
17
20
  });
@@ -5,30 +5,18 @@ const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
6
  const error_1 = require("../error");
7
7
  const prompt_1 = require("../prompt");
8
- const logger_1 = require("../logger");
9
8
  const constants_1 = require("../init/features/apphosting/constants");
10
9
  const utils = require("../utils");
11
10
  const apphosting = require("../gcp/apphosting");
12
- const Table = require("cli-table");
13
- const COLUMN_LENGTH = 20;
14
- const TABLE_HEAD = [
15
- "Backend Id",
16
- "Repository Name",
17
- "Location",
18
- "URL",
19
- "Created Date",
20
- "Updated Date",
21
- ];
22
- exports.command = new command_1.Command("apphosting:backends:delete")
23
- .description("Delete a backend from a Firebase project")
11
+ const apphosting_backends_list_1 = require("./apphosting-backends-list");
12
+ exports.command = new command_1.Command("apphosting:backends:delete <backend>")
13
+ .description("delete a backend from a Firebase project")
24
14
  .option("-l, --location <location>", "App Backend location", "")
25
- .option("-s, --backend <backend>", "Backend Id", "")
26
15
  .withForce()
27
16
  .before(apphosting.ensureApiEnabled)
28
- .action(async (options) => {
17
+ .action(async (backendId, options) => {
29
18
  const projectId = (0, projectUtils_1.needProjectId)(options);
30
19
  let location = options.location;
31
- const backendId = options.backend;
32
20
  if (!backendId) {
33
21
  throw new error_1.FirebaseError("Backend id can't be empty.");
34
22
  }
@@ -42,15 +30,9 @@ exports.command = new command_1.Command("apphosting:backends:delete")
42
30
  choices: allowedLocations,
43
31
  });
44
32
  }
45
- const table = new Table({
46
- head: TABLE_HEAD,
47
- style: { head: ["green"] },
48
- });
49
- table.colWidths = COLUMN_LENGTH;
50
33
  let backend;
51
34
  try {
52
35
  backend = await apphosting.getBackend(projectId, location, backendId);
53
- populateTable(backend, table);
54
36
  }
55
37
  catch (err) {
56
38
  throw new error_1.FirebaseError(`No backends found with given parameters. Command aborted.`, {
@@ -58,7 +40,8 @@ exports.command = new command_1.Command("apphosting:backends:delete")
58
40
  });
59
41
  }
60
42
  utils.logWarning("You are about to permanently delete the backend:");
61
- logger_1.logger.info(table.toString());
43
+ const backends = [backend];
44
+ (0, apphosting_backends_list_1.printBackendsTable)(backends);
62
45
  const confirmDeletion = await (0, prompt_1.promptOnce)({
63
46
  type: "confirm",
64
47
  name: "force",
@@ -77,24 +60,3 @@ exports.command = new command_1.Command("apphosting:backends:delete")
77
60
  }
78
61
  return backend;
79
62
  });
80
- function populateTable(backend, table) {
81
- var _a;
82
- const [location, , backendId] = backend.name.split("/").slice(3, 6);
83
- const entry = [
84
- backendId,
85
- (_a = backend.codebase.repository) === null || _a === void 0 ? void 0 : _a.split("/").pop(),
86
- location,
87
- backend.uri,
88
- backend.createTime,
89
- backend.updateTime,
90
- ];
91
- const newRow = entry.map((name) => {
92
- const maxCellWidth = COLUMN_LENGTH - 2;
93
- const chunks = [];
94
- for (let i = 0; name && i < name.length; i += maxCellWidth) {
95
- chunks.push(name.substring(i, i + maxCellWidth));
96
- }
97
- return chunks.join("\n");
98
- });
99
- table.push(newRow);
100
- }
@@ -4,36 +4,26 @@ exports.command = void 0;
4
4
  const command_1 = require("../command");
5
5
  const projectUtils_1 = require("../projectUtils");
6
6
  const error_1 = require("../error");
7
- const logger_1 = require("../logger");
8
7
  const utils_1 = require("../utils");
9
8
  const apphosting = require("../gcp/apphosting");
10
- const Table = require("cli-table");
11
- const COLUMN_LENGTH = 20;
12
- const TABLE_HEAD = ["Backend Id", "Repository", "Location", "URL", "Created Date", "Updated Date"];
9
+ const apphosting_backends_list_1 = require("./apphosting-backends-list");
13
10
  exports.command = new command_1.Command("apphosting:backends:get <backendId>")
14
- .description("Get backend details of a Firebase project")
15
- .option("-l, --location <location>", "App Backend location", "-")
11
+ .description("get backend details of a Firebase project")
12
+ .option("-l, --location <location>", "app backend location", "-")
16
13
  .before(apphosting.ensureApiEnabled)
17
14
  .action(async (backendId, options) => {
18
15
  const projectId = (0, projectUtils_1.needProjectId)(options);
19
16
  const location = options.location;
20
17
  let backendsList = [];
21
- const table = new Table({
22
- head: TABLE_HEAD,
23
- style: { head: ["green"] },
24
- });
25
- table.colWidths = COLUMN_LENGTH;
26
18
  try {
27
19
  if (location !== "-") {
28
20
  const backendInRegion = await apphosting.getBackend(projectId, location, backendId);
29
21
  backendsList.push(backendInRegion);
30
- populateTable(backendInRegion, table);
31
22
  }
32
23
  else {
33
24
  const resp = await apphosting.listBackends(projectId, "-");
34
25
  const allBackends = resp.backends || [];
35
26
  backendsList = allBackends.filter((bkd) => bkd.name.split("/").pop() === backendId);
36
- backendsList.forEach((bkd) => populateTable(bkd, table));
37
27
  }
38
28
  }
39
29
  catch (err) {
@@ -43,27 +33,6 @@ exports.command = new command_1.Command("apphosting:backends:get <backendId>")
43
33
  (0, utils_1.logWarning)(`Found no backend with id: ${backendId}`);
44
34
  return;
45
35
  }
46
- logger_1.logger.info(table.toString());
36
+ (0, apphosting_backends_list_1.printBackendsTable)(backendsList);
47
37
  return backendsList[0];
48
38
  });
49
- function populateTable(backend, table) {
50
- var _a;
51
- const [location, , backendId] = backend.name.split("/").slice(3, 6);
52
- const entry = [
53
- backendId,
54
- (_a = backend.codebase.repository) === null || _a === void 0 ? void 0 : _a.split("/").pop(),
55
- location,
56
- backend.uri,
57
- backend.createTime,
58
- backend.updateTime,
59
- ];
60
- const newRow = entry.map((name) => {
61
- const maxCellWidth = COLUMN_LENGTH - 2;
62
- const chunks = [];
63
- for (let i = 0; name && i < name.length; i += maxCellWidth) {
64
- chunks.push(name.substring(i, i + maxCellWidth));
65
- }
66
- return chunks.join("\n");
67
- });
68
- table.push(newRow);
69
- }
@@ -1,23 +1,22 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.command = void 0;
4
- const Table = require("cli-table");
3
+ exports.printBackendsTable = exports.command = void 0;
5
4
  const command_1 = require("../command");
6
5
  const utils_1 = require("../utils");
7
6
  const error_1 = require("../error");
8
7
  const logger_1 = require("../logger");
9
8
  const projectUtils_1 = require("../projectUtils");
10
9
  const apphosting = require("../gcp/apphosting");
10
+ const Table = require("cli-table");
11
11
  const TABLE_HEAD = ["Backend ID", "Repository", "Location", "URL", "Created Date", "Updated Date"];
12
12
  exports.command = new command_1.Command("apphosting:backends:list")
13
- .description("List backends of a Firebase project.")
14
- .option("-l, --location <location>", "App Backend location", "-")
13
+ .description("list backends of a Firebase project")
14
+ .option("-l, --location <location>", "app Backend location", "-")
15
15
  .before(apphosting.ensureApiEnabled)
16
16
  .action(async (options) => {
17
- var _a, _b, _c, _d;
17
+ var _a;
18
18
  const projectId = (0, projectUtils_1.needProjectId)(options);
19
19
  const location = options.location;
20
- const table = new Table({ head: TABLE_HEAD, style: { head: ["green"] } });
21
20
  let backendRes;
22
21
  try {
23
22
  backendRes = await apphosting.listBackends(projectId, location);
@@ -26,11 +25,20 @@ exports.command = new command_1.Command("apphosting:backends:list")
26
25
  throw new error_1.FirebaseError(`Unable to list backends present for project: ${projectId}. Please check the parameters you have provided.`, { original: err });
27
26
  }
28
27
  const backends = (_a = backendRes.backends) !== null && _a !== void 0 ? _a : [];
28
+ printBackendsTable(backends);
29
+ return backends;
30
+ });
31
+ function printBackendsTable(backends) {
32
+ var _a, _b, _c;
33
+ const table = new Table({
34
+ head: TABLE_HEAD,
35
+ style: { head: ["green"] },
36
+ });
29
37
  for (const backend of backends) {
30
38
  const [backendLocation, , backendId] = backend.name.split("/").slice(3, 6);
31
39
  table.push([
32
40
  backendId,
33
- (_d = (_c = (_b = backend.codebase) === null || _b === void 0 ? void 0 : _b.repository) === null || _c === void 0 ? void 0 : _c.split("/").pop()) !== null && _d !== void 0 ? _d : "",
41
+ (_c = (_b = (_a = backend.codebase) === null || _a === void 0 ? void 0 : _a.repository) === null || _b === void 0 ? void 0 : _b.split("/").pop()) !== null && _c !== void 0 ? _c : "",
34
42
  backendLocation,
35
43
  backend.uri.startsWith("https:") ? backend.uri : "https://" + backend.uri,
36
44
  (0, utils_1.datetimeString)(new Date(backend.createTime)),
@@ -38,5 +46,5 @@ exports.command = new command_1.Command("apphosting:backends:list")
38
46
  ]);
39
47
  }
40
48
  logger_1.logger.info(table.toString());
41
- return backends;
42
- });
49
+ }
50
+ exports.printBackendsTable = printBackendsTable;
@@ -6,10 +6,10 @@ const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
8
  exports.command = new command_1.Command("apphosting:builds:create <backendId>")
9
- .description("Create a build for an App Hosting backend")
10
- .option("-l, --location <location>", "Specify the region of the backend", "us-central1")
11
- .option("-i, --id <buildId>", "Id of the build. If not present, autogenerate a random id", "")
12
- .option("-b, --branch <branch>", "Repository branch to deploy. Defaults to 'main'", "main")
9
+ .description("create a build for an App Hosting backend")
10
+ .option("-l, --location <location>", "specify the region of the backend", "us-central1")
11
+ .option("-i, --id <buildId>", "id of the build (defaults to autogenerating a random id)", "")
12
+ .option("-b, --branch <branch>", "repository branch to deploy (defaults to 'main')", "main")
13
13
  .before(apphosting.ensureApiEnabled)
14
14
  .action(async (backendId, options) => {
15
15
  var _a;
@@ -6,8 +6,8 @@ const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
8
  exports.command = new command_1.Command("apphosting:builds:get <backendId> <buildId>")
9
- .description("Create a build for an App Hosting backend")
10
- .option("-l, --location <location>", "Specify the region of the backend", "us-central1")
9
+ .description("get a build for an App Hosting backend")
10
+ .option("-l, --location <location>", "specify the region of the backend", "us-central1")
11
11
  .before(apphosting.ensureApiEnabled)
12
12
  .action(async (backendId, buildId, options) => {
13
13
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -6,9 +6,9 @@ const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
8
  exports.command = new command_1.Command("apphosting:rollouts:create <backendId> <buildId>")
9
- .description("Create a build for an App Hosting backend")
10
- .option("-l, --location <location>", "Specify the region of the backend", "us-central1")
11
- .option("-i, --id <rolloutId>", "Id of the rollout. If not present, autogenerate a random id", "")
9
+ .description("create a rollout using a build for an App Hosting backend")
10
+ .option("-l, --location <location>", "specify the region of the backend", "us-central1")
11
+ .option("-i, --id <rolloutId>", "id of the rollout (defaults to autogenerating a random id)", "")
12
12
  .before(apphosting.ensureApiEnabled)
13
13
  .action(async (backendId, buildId, options) => {
14
14
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -6,8 +6,8 @@ const logger_1 = require("../logger");
6
6
  const command_1 = require("../command");
7
7
  const projectUtils_1 = require("../projectUtils");
8
8
  exports.command = new command_1.Command("apphosting:rollouts:list <backendId>")
9
- .description("List rollouts of an App Hosting backend")
10
- .option("-l, --location <location>", "Rgion of the rollouts. Defaults to listing rollouts from all regions", "-")
9
+ .description("list rollouts of an App Hosting backend")
10
+ .option("-l, --location <location>", "region of the rollouts (defaults to listing rollouts from all regions)", "-")
11
11
  .before(apphosting.ensureApiEnabled)
12
12
  .action(async (backendId, options) => {
13
13
  const projectId = (0, projectUtils_1.needProjectId)(options);
@@ -0,0 +1,44 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const firestore_1 = require("../gcp/firestore");
6
+ const prompt_1 = require("../prompt");
7
+ const clc = require("colorette");
8
+ const logger_1 = require("../logger");
9
+ const requirePermissions_1 = require("../requirePermissions");
10
+ const types_1 = require("../emulator/types");
11
+ const commandUtils_1 = require("../emulator/commandUtils");
12
+ const error_1 = require("../error");
13
+ exports.command = new command_1.Command("firestore:backups:delete <backup>")
14
+ .description("Delete a backup under your Cloud Firestore database.")
15
+ .option("--force", "Attempt to delete backup without prompting for confirmation.")
16
+ .before(requirePermissions_1.requirePermissions, ["datastore.backups.delete"])
17
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
18
+ .action(async (backupName, options) => {
19
+ const backup = await (0, firestore_1.getBackup)(backupName);
20
+ if (!options.force) {
21
+ const confirmMessage = `You are about to delete ${backupName}. Do you wish to continue?`;
22
+ const consent = await (0, prompt_1.promptOnce)({
23
+ type: "confirm",
24
+ message: confirmMessage,
25
+ default: false,
26
+ });
27
+ if (!consent) {
28
+ throw new error_1.FirebaseError("Delete backup canceled.");
29
+ }
30
+ }
31
+ try {
32
+ await (0, firestore_1.deleteBackup)(backupName);
33
+ }
34
+ catch (err) {
35
+ throw new error_1.FirebaseError(`Failed to delete the backup ${backupName}`, { original: err });
36
+ }
37
+ if (options.json) {
38
+ logger_1.logger.info(JSON.stringify(backup, undefined, 2));
39
+ }
40
+ else {
41
+ logger_1.logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupName)}`));
42
+ }
43
+ return backup;
44
+ });
@@ -0,0 +1,25 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const logger_1 = require("../logger");
6
+ const requirePermissions_1 = require("../requirePermissions");
7
+ const types_1 = require("../emulator/types");
8
+ const commandUtils_1 = require("../emulator/commandUtils");
9
+ const firestore_1 = require("../gcp/firestore");
10
+ const pretty_print_1 = require("../firestore/pretty-print");
11
+ exports.command = new command_1.Command("firestore:backups:get <backup>")
12
+ .description("Get a Cloud Firestore database backup.")
13
+ .before(requirePermissions_1.requirePermissions, ["datastore.backups.get"])
14
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
15
+ .action(async (backupName, options) => {
16
+ const backup = await (0, firestore_1.getBackup)(backupName);
17
+ const printer = new pretty_print_1.PrettyPrint();
18
+ if (options.json) {
19
+ logger_1.logger.info(JSON.stringify(backup, undefined, 2));
20
+ }
21
+ else {
22
+ printer.prettyPrintBackup(backup);
23
+ }
24
+ return backup;
25
+ });
@@ -0,0 +1,34 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const logger_1 = require("../logger");
6
+ const requirePermissions_1 = require("../requirePermissions");
7
+ const types_1 = require("../emulator/types");
8
+ const commandUtils_1 = require("../emulator/commandUtils");
9
+ const firestore_1 = require("../gcp/firestore");
10
+ const utils_1 = require("../utils");
11
+ const pretty_print_1 = require("../firestore/pretty-print");
12
+ exports.command = new command_1.Command("firestore:backups:list")
13
+ .description("List all Cloud Firestore backups in a given location")
14
+ .option("-l, --location <locationId>", "Location to search for backups, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations. Defaults to all locations.")
15
+ .before(requirePermissions_1.requirePermissions, ["datastore.backups.list"])
16
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
17
+ .action(async (options) => {
18
+ var _a;
19
+ const printer = new pretty_print_1.PrettyPrint();
20
+ const location = (_a = options.location) !== null && _a !== void 0 ? _a : "-";
21
+ const listBackupsResponse = await (0, firestore_1.listBackups)(options.project, location);
22
+ const backups = listBackupsResponse.backups || [];
23
+ if (options.json) {
24
+ logger_1.logger.info(JSON.stringify(listBackupsResponse, undefined, 2));
25
+ }
26
+ else {
27
+ printer.prettyPrintBackups(backups);
28
+ if (listBackupsResponse.unreachable && listBackupsResponse.unreachable.length > 0) {
29
+ (0, utils_1.logWarning)("We were not able to reach the following locations: " +
30
+ listBackupsResponse.unreachable.join(", "));
31
+ }
32
+ }
33
+ return backups;
34
+ });
@@ -0,0 +1,67 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const clc = require("colorette");
5
+ const command_1 = require("../command");
6
+ const backupUtils_1 = require("../firestore/backupUtils");
7
+ const firestore_1 = require("../gcp/firestore");
8
+ const types = require("../firestore/api-types");
9
+ const logger_1 = require("../logger");
10
+ const requirePermissions_1 = require("../requirePermissions");
11
+ const types_1 = require("../emulator/types");
12
+ const commandUtils_1 = require("../emulator/commandUtils");
13
+ const pretty_print_1 = require("../firestore/pretty-print");
14
+ exports.command = new command_1.Command("firestore:backups:schedules:create")
15
+ .description("Create a backup schedule under your Cloud Firestore database.")
16
+ .option("-db, --database <databaseId>", "Database under which you want to create a schedule. Defaults to the (default) database")
17
+ .option("-rt, --retention <duration>", "duration string (e.g. 12h or 30d) for backup retention")
18
+ .option("-rc, --recurrence <recurrence>", "Recurrence settings; either DAILY or WEEKLY")
19
+ .option("-dw, --day-of-week <dayOfWeek>", "On which day of the week to perform backups; one of MONDAY, TUESDAY, WEDNESDAY, THURSDAY, FRIDAY, SATURDAY, or SUNDAY")
20
+ .before(requirePermissions_1.requirePermissions, ["datastore.backupSchedules.create"])
21
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
22
+ .action(async (options) => {
23
+ const printer = new pretty_print_1.PrettyPrint();
24
+ const databaseId = options.database || "(default)";
25
+ if (!options.retention) {
26
+ logger_1.logger.error("Missing required flag --retention. See firebase firestore:backups:schedules:create --help for more info");
27
+ return;
28
+ }
29
+ const retention = (0, backupUtils_1.calculateRetention)(options.retention);
30
+ if (!options.recurrence) {
31
+ logger_1.logger.error("Missing required flag --recurrence. See firebase firestore:backups:schedules:create --help for more info");
32
+ return;
33
+ }
34
+ const recurrenceType = options.recurrence;
35
+ if (recurrenceType !== types.RecurrenceType.DAILY &&
36
+ recurrenceType !== types.RecurrenceType.WEEKLY) {
37
+ logger_1.logger.error("Invalid value for flag --recurrence. See firebase firestore:backups:schedules:create --help for more info");
38
+ return;
39
+ }
40
+ let dailyRecurrence;
41
+ let weeklyRecurrence;
42
+ if (options.recurrence === types.RecurrenceType.DAILY) {
43
+ dailyRecurrence = {};
44
+ if (options.dayOfWeek) {
45
+ logger_1.logger.error("--day-of-week should not be provided if --recurrence is DAILY");
46
+ return;
47
+ }
48
+ }
49
+ else if (options.recurrence === types.RecurrenceType.WEEKLY) {
50
+ if (!options.dayOfWeek) {
51
+ logger_1.logger.error("If --recurrence is WEEKLY, --day-of-week must be provided. See firebase firestore:backups:schedules:create --help for more info");
52
+ return;
53
+ }
54
+ const day = options.dayOfWeek;
55
+ weeklyRecurrence = {
56
+ day,
57
+ };
58
+ }
59
+ const backupSchedule = await (0, firestore_1.createBackupSchedule)(options.project, databaseId, retention, dailyRecurrence, weeklyRecurrence);
60
+ if (options.json) {
61
+ logger_1.logger.info(JSON.stringify(backupSchedule, undefined, 2));
62
+ }
63
+ else {
64
+ logger_1.logger.info(clc.bold(`Successfully created ${printer.prettyBackupScheduleString(backupSchedule)}`));
65
+ }
66
+ return backupSchedule;
67
+ });
@@ -0,0 +1,46 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const firestore_1 = require("../gcp/firestore");
6
+ const prompt_1 = require("../prompt");
7
+ const clc = require("colorette");
8
+ const logger_1 = require("../logger");
9
+ const requirePermissions_1 = require("../requirePermissions");
10
+ const types_1 = require("../emulator/types");
11
+ const commandUtils_1 = require("../emulator/commandUtils");
12
+ const error_1 = require("../error");
13
+ exports.command = new command_1.Command("firestore:backups:schedules:delete <backupSchedule>")
14
+ .description("Delete a backup schedule under your Cloud Firestore database.")
15
+ .option("--force", "Attempt to delete backup schedule without prompting for confirmation.")
16
+ .before(requirePermissions_1.requirePermissions, ["datastore.backupSchedules.delete"])
17
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
18
+ .action(async (backupScheduleName, options) => {
19
+ const backupSchedule = await (0, firestore_1.getBackupSchedule)(backupScheduleName);
20
+ if (!options.force) {
21
+ const confirmMessage = `You are about to delete ${backupScheduleName}. Do you wish to continue?`;
22
+ const consent = await (0, prompt_1.promptOnce)({
23
+ type: "confirm",
24
+ message: confirmMessage,
25
+ default: false,
26
+ });
27
+ if (!consent) {
28
+ throw new error_1.FirebaseError("Delete backup schedule canceled.");
29
+ }
30
+ }
31
+ try {
32
+ await (0, firestore_1.deleteBackupSchedule)(backupScheduleName);
33
+ }
34
+ catch (err) {
35
+ throw new error_1.FirebaseError(`Failed to delete the backup schedule ${backupScheduleName}`, {
36
+ original: err,
37
+ });
38
+ }
39
+ if (options.json) {
40
+ logger_1.logger.info(JSON.stringify(backupSchedule, undefined, 2));
41
+ }
42
+ else {
43
+ logger_1.logger.info(clc.bold(`Successfully deleted ${clc.yellow(backupScheduleName)}`));
44
+ }
45
+ return backupSchedule;
46
+ });
@@ -0,0 +1,28 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const command_1 = require("../command");
5
+ const logger_1 = require("../logger");
6
+ const requirePermissions_1 = require("../requirePermissions");
7
+ const types_1 = require("../emulator/types");
8
+ const commandUtils_1 = require("../emulator/commandUtils");
9
+ const firestore_1 = require("../gcp/firestore");
10
+ const pretty_print_1 = require("../firestore/pretty-print");
11
+ exports.command = new command_1.Command("firestore:backups:schedules:list")
12
+ .description("List backup schedules under your Cloud Firestore database.")
13
+ .option("-db, --database <databaseId>", "Database whose schedules you wish to list. Defaults to the (default) database.")
14
+ .before(requirePermissions_1.requirePermissions, ["datastore.backupSchedules.list"])
15
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
16
+ .action(async (options) => {
17
+ var _a;
18
+ const printer = new pretty_print_1.PrettyPrint();
19
+ const databaseId = (_a = options.database) !== null && _a !== void 0 ? _a : "(default)";
20
+ const backupSchedules = await (0, firestore_1.listBackupSchedules)(options.project, databaseId);
21
+ if (options.json) {
22
+ logger_1.logger.info(JSON.stringify(backupSchedules, undefined, 2));
23
+ }
24
+ else {
25
+ printer.prettyPrintBackupSchedules(backupSchedules, databaseId);
26
+ }
27
+ return backupSchedules;
28
+ });
@@ -0,0 +1,33 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.command = void 0;
4
+ const clc = require("colorette");
5
+ const command_1 = require("../command");
6
+ const backupUtils_1 = require("../firestore/backupUtils");
7
+ const firestore_1 = require("../gcp/firestore");
8
+ const logger_1 = require("../logger");
9
+ const requirePermissions_1 = require("../requirePermissions");
10
+ const types_1 = require("../emulator/types");
11
+ const commandUtils_1 = require("../emulator/commandUtils");
12
+ const pretty_print_1 = require("../firestore/pretty-print");
13
+ exports.command = new command_1.Command("firestore:backups:schedules:update <backupSchedule>")
14
+ .description("Update a backup schedule under your Cloud Firestore database.")
15
+ .option("-rt, --retention <duration>", "duration string (e.g. 12h or 30d) for backup retention")
16
+ .before(requirePermissions_1.requirePermissions, ["datastore.backupSchedules.update"])
17
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
18
+ .action(async (backupScheduleName, options) => {
19
+ const printer = new pretty_print_1.PrettyPrint();
20
+ if (!options.retention) {
21
+ logger_1.logger.error("Missing required flag --retention. See firebase firestore:backups:schedules:update --help for more info");
22
+ return;
23
+ }
24
+ const retention = (0, backupUtils_1.calculateRetention)(options.retention);
25
+ const backupSchedule = await (0, firestore_1.updateBackupSchedule)(backupScheduleName, retention);
26
+ if (options.json) {
27
+ logger_1.logger.info(JSON.stringify(backupSchedule, undefined, 2));
28
+ }
29
+ else {
30
+ logger_1.logger.info(clc.bold(`Successfully updated ${printer.prettyBackupScheduleString(backupSchedule)}`));
31
+ }
32
+ return backupSchedule;
33
+ });
@@ -1,14 +1,15 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.command = void 0;
4
- const command_1 = require("../command");
5
4
  const clc = require("colorette");
5
+ const command_1 = require("../command");
6
6
  const fsi = require("../firestore/api");
7
7
  const types = require("../firestore/api-types");
8
8
  const logger_1 = require("../logger");
9
9
  const requirePermissions_1 = require("../requirePermissions");
10
10
  const types_1 = require("../emulator/types");
11
11
  const commandUtils_1 = require("../emulator/commandUtils");
12
+ const pretty_print_1 = require("../firestore/pretty-print");
12
13
  exports.command = new command_1.Command("firestore:databases:create <database>")
13
14
  .description("Create a database in your Firebase project.")
14
15
  .option("--location <locationId>", "Region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations. (required)")
@@ -18,6 +19,7 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
18
19
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
19
20
  .action(async (database, options) => {
20
21
  const api = new fsi.FirestoreApi();
22
+ const printer = new pretty_print_1.PrettyPrint();
21
23
  if (!options.location) {
22
24
  logger_1.logger.error("Missing required flag --location. See firebase firestore:databases:create --help for more info.");
23
25
  return;
@@ -46,7 +48,7 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
46
48
  logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
47
49
  }
48
50
  else {
49
- logger_1.logger.info(clc.bold(`Successfully created ${api.prettyDatabaseString(databaseResp)}`));
51
+ logger_1.logger.info(clc.bold(`Successfully created ${printer.prettyDatabaseString(databaseResp)}`));
50
52
  logger_1.logger.info("Please be sure to configure Firebase rules in your Firebase config file for\n" +
51
53
  "the new database. By default, created databases will have closed rules that\n" +
52
54
  "block any incoming third-party traffic.");