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
@@ -1,8 +1,8 @@
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 prompt_1 = require("../prompt");
8
8
  const logger_1 = require("../logger");
@@ -10,6 +10,7 @@ const requirePermissions_1 = require("../requirePermissions");
10
10
  const types_1 = require("../emulator/types");
11
11
  const commandUtils_1 = require("../emulator/commandUtils");
12
12
  const error_1 = require("../error");
13
+ const pretty_print_1 = require("../firestore/pretty-print");
13
14
  exports.command = new command_1.Command("firestore:databases:delete <database>")
14
15
  .description("Delete a database in your Cloud Firestore project. Database delete protection state must be disabled. To do so, use the update command: firebase firestore:databases:update <database> --delete-protection DISABLED")
15
16
  .option("--force", "Attempt to delete database without prompting for confirmation.")
@@ -17,6 +18,7 @@ exports.command = new command_1.Command("firestore:databases:delete <database>")
17
18
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
18
19
  .action(async (database, options) => {
19
20
  const api = new fsi.FirestoreApi();
21
+ const printer = new pretty_print_1.PrettyPrint();
20
22
  if (!options.force) {
21
23
  const confirmMessage = `You are about to delete projects/${options.project}/databases/${database}. Do you wish to continue?`;
22
24
  const consent = await (0, prompt_1.promptOnce)({
@@ -33,7 +35,7 @@ exports.command = new command_1.Command("firestore:databases:delete <database>")
33
35
  logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
34
36
  }
35
37
  else {
36
- logger_1.logger.info(clc.bold(`Successfully deleted ${api.prettyDatabaseString(databaseResp)}`));
38
+ logger_1.logger.info(clc.bold(`Successfully deleted ${printer.prettyDatabaseString(databaseResp)}`));
37
39
  }
38
40
  return databaseResp;
39
41
  });
@@ -7,19 +7,21 @@ const logger_1 = require("../logger");
7
7
  const requirePermissions_1 = require("../requirePermissions");
8
8
  const types_1 = require("../emulator/types");
9
9
  const commandUtils_1 = require("../emulator/commandUtils");
10
+ const pretty_print_1 = require("../firestore/pretty-print");
10
11
  exports.command = new command_1.Command("firestore:databases:get [database]")
11
12
  .description("Get database in your Cloud Firestore project.")
12
13
  .before(requirePermissions_1.requirePermissions, ["datastore.databases.get"])
13
14
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
14
15
  .action(async (database, options) => {
15
16
  const api = new fsi.FirestoreApi();
17
+ const printer = new pretty_print_1.PrettyPrint();
16
18
  const databaseId = database || "(default)";
17
19
  const databaseResp = await api.getDatabase(options.project, databaseId);
18
20
  if (options.json) {
19
21
  logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
20
22
  }
21
23
  else {
22
- api.prettyPrintDatabase(databaseResp);
24
+ printer.prettyPrintDatabase(databaseResp);
23
25
  }
24
26
  return databaseResp;
25
27
  });
@@ -7,18 +7,20 @@ const logger_1 = require("../logger");
7
7
  const requirePermissions_1 = require("../requirePermissions");
8
8
  const types_1 = require("../emulator/types");
9
9
  const commandUtils_1 = require("../emulator/commandUtils");
10
+ const pretty_print_1 = require("../firestore/pretty-print");
10
11
  exports.command = new command_1.Command("firestore:databases:list")
11
12
  .description("List databases in your Cloud Firestore project.")
12
13
  .before(requirePermissions_1.requirePermissions, ["datastore.databases.list"])
13
14
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
14
15
  .action(async (options) => {
15
16
  const api = new fsi.FirestoreApi();
17
+ const printer = new pretty_print_1.PrettyPrint();
16
18
  const databases = await api.listDatabases(options.project);
17
19
  if (options.json) {
18
20
  logger_1.logger.info(JSON.stringify(databases, undefined, 2));
19
21
  }
20
22
  else {
21
- api.prettyPrintDatabases(databases);
23
+ printer.prettyPrintDatabases(databases);
22
24
  }
23
25
  return databases;
24
26
  });
@@ -0,0 +1,42 @@
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 fsi = require("../firestore/api");
7
+ const logger_1 = require("../logger");
8
+ const requirePermissions_1 = require("../requirePermissions");
9
+ const types_1 = require("../emulator/types");
10
+ const commandUtils_1 = require("../emulator/commandUtils");
11
+ const pretty_print_1 = require("../firestore/pretty-print");
12
+ exports.command = new command_1.Command("firestore:databases:restore")
13
+ .description("Restore a Firestore database in your Firebase project.")
14
+ .option("-d, --database <databaseID>", "ID of the database to restore into")
15
+ .option("-b, --backup <backup>", "Backup from which to restore")
16
+ .before(requirePermissions_1.requirePermissions, ["datastore.backups.restoreDatabase"])
17
+ .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
18
+ .action(async (options) => {
19
+ const api = new fsi.FirestoreApi();
20
+ const printer = new pretty_print_1.PrettyPrint();
21
+ if (!options.database) {
22
+ logger_1.logger.error("Missing required flag --database. See firebase firestore:databases:restore --help for more info");
23
+ return;
24
+ }
25
+ const databaseId = options.database;
26
+ if (!options.backup) {
27
+ logger_1.logger.error("Missing required flag --backup. See firebase firestore:databases:restore --help for more info");
28
+ return;
29
+ }
30
+ const backupName = options.backup;
31
+ const databaseResp = await api.restoreDatabase(options.project, databaseId, backupName);
32
+ if (options.json) {
33
+ logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
34
+ }
35
+ else {
36
+ logger_1.logger.info(clc.bold(`Successfully initiated restore of ${printer.prettyDatabaseString(databaseResp)}`));
37
+ logger_1.logger.info("Please be sure to configure Firebase rules in your Firebase config file for\n" +
38
+ "the new database. By default, created databases will have closed rules that\n" +
39
+ "block any incoming third-party traffic.");
40
+ }
41
+ return databaseResp;
42
+ });
@@ -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:update <database>")
13
14
  .description("Update a database in your Firebase project. Must specify at least one property to update.")
14
15
  .option("--json", "Prints raw json response of the create API call if specified")
@@ -18,6 +19,7 @@ exports.command = new command_1.Command("firestore:databases:update <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.deleteProtection && !options.pointInTimeRecovery) {
22
24
  logger_1.logger.error("Missing properties to update. See firebase firestore:databases:update --help for more info.");
23
25
  return;
@@ -53,7 +55,7 @@ exports.command = new command_1.Command("firestore:databases:update <database>")
53
55
  logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
54
56
  }
55
57
  else {
56
- logger_1.logger.info(clc.bold(`Successfully updated ${api.prettyDatabaseString(databaseResp)}`));
58
+ logger_1.logger.info(clc.bold(`Successfully updated ${printer.prettyDatabaseString(databaseResp)}`));
57
59
  }
58
60
  return databaseResp;
59
61
  });
@@ -1,13 +1,14 @@
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 logger_1 = require("../logger");
8
8
  const requirePermissions_1 = require("../requirePermissions");
9
9
  const types_1 = require("../emulator/types");
10
10
  const commandUtils_1 = require("../emulator/commandUtils");
11
+ const pretty_print_1 = require("../firestore/pretty-print");
11
12
  exports.command = new command_1.Command("firestore:indexes")
12
13
  .description("List indexes in your project's Cloud Firestore database.")
13
14
  .option("--pretty", "Pretty print. When not specified the indexes are printed in the " +
@@ -18,17 +19,18 @@ exports.command = new command_1.Command("firestore:indexes")
18
19
  .action(async (options) => {
19
20
  var _a;
20
21
  const indexApi = new fsi.FirestoreApi();
22
+ const printer = new pretty_print_1.PrettyPrint();
21
23
  const databaseId = (_a = options.database) !== null && _a !== void 0 ? _a : "(default)";
22
24
  const indexes = await indexApi.listIndexes(options.project, databaseId);
23
25
  const fieldOverrides = await indexApi.listFieldOverrides(options.project, databaseId);
24
26
  const indexSpec = indexApi.makeIndexSpec(indexes, fieldOverrides);
25
27
  if (options.pretty) {
26
28
  logger_1.logger.info(clc.bold(clc.white("Compound Indexes")));
27
- indexApi.prettyPrintIndexes(indexes);
29
+ printer.prettyPrintIndexes(indexes);
28
30
  if (fieldOverrides) {
29
31
  logger_1.logger.info();
30
32
  logger_1.logger.info(clc.bold(clc.white("Field Overrides")));
31
- indexApi.printFieldOverrides(fieldOverrides);
33
+ printer.printFieldOverrides(fieldOverrides);
32
34
  }
33
35
  }
34
36
  else {
@@ -7,18 +7,20 @@ const logger_1 = require("../logger");
7
7
  const requirePermissions_1 = require("../requirePermissions");
8
8
  const types_1 = require("../emulator/types");
9
9
  const commandUtils_1 = require("../emulator/commandUtils");
10
+ const pretty_print_1 = require("../firestore/pretty-print");
10
11
  exports.command = new command_1.Command("firestore:locations")
11
12
  .description("List possible locations for your Cloud Firestore project.")
12
13
  .before(requirePermissions_1.requirePermissions, ["datastore.locations.list"])
13
14
  .before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
14
15
  .action(async (options) => {
15
16
  const api = new fsi.FirestoreApi();
17
+ const printer = new pretty_print_1.PrettyPrint();
16
18
  const locations = await api.locations(options.project);
17
19
  if (options.json) {
18
20
  logger_1.logger.info(JSON.stringify(locations, undefined, 2));
19
21
  }
20
22
  else {
21
- api.prettyPrintLocations(locations);
23
+ printer.prettyPrintLocations(locations);
22
24
  }
23
25
  return locations;
24
26
  });
@@ -101,6 +101,16 @@ function load(client) {
101
101
  client.firestore.databases.create = loadCommand("firestore-databases-create");
102
102
  client.firestore.databases.update = loadCommand("firestore-databases-update");
103
103
  client.firestore.databases.delete = loadCommand("firestore-databases-delete");
104
+ client.firestore.databases.restore = loadCommand("firestore-databases-restore");
105
+ client.firestore.backups = {};
106
+ client.firestore.backups.schedules = {};
107
+ client.firestore.backups.list = loadCommand("firestore-backups-list");
108
+ client.firestore.backups.get = loadCommand("firestore-backups-get");
109
+ client.firestore.backups.delete = loadCommand("firestore-backups-delete");
110
+ client.firestore.backups.schedules.list = loadCommand("firestore-backups-schedules-list");
111
+ client.firestore.backups.schedules.create = loadCommand("firestore-backups-schedules-create");
112
+ client.firestore.backups.schedules.update = loadCommand("firestore-backups-schedules-update");
113
+ client.firestore.backups.schedules.delete = loadCommand("firestore-backups-schedules-delete");
104
114
  client.functions = {};
105
115
  client.functions.config = {};
106
116
  client.functions.config.clone = loadCommand("functions-config-clone");
@@ -8,6 +8,7 @@ const error_1 = require("../../error");
8
8
  const ensureApiEnabled_1 = require("../../ensureApiEnabled");
9
9
  const planner = require("./planner");
10
10
  const projectUtils_1 = require("../../projectUtils");
11
+ const api_1 = require("../../api");
11
12
  const SERVICE_AGENT_ROLE = "roles/eventarc.eventReceiver";
12
13
  async function checkSpecForV2Functions(i) {
13
14
  const extensionSpec = await planner.getExtensionSpec(i);
@@ -16,7 +17,7 @@ async function checkSpecForV2Functions(i) {
16
17
  exports.checkSpecForV2Functions = checkSpecForV2Functions;
17
18
  async function ensureNecessaryV2ApisAndRoles(options) {
18
19
  const projectId = (0, projectUtils_1.needProjectId)(options);
19
- await (0, ensureApiEnabled_1.ensure)(projectId, "compute.googleapis.com", "extensions", options.markdown);
20
+ await (0, ensureApiEnabled_1.ensure)(projectId, api_1.computeOrigin, "extensions", options.markdown);
20
21
  await ensureComputeP4SARole(projectId);
21
22
  }
22
23
  exports.ensureNecessaryV2ApisAndRoles = ensureNecessaryV2ApisAndRoles;
@@ -8,9 +8,9 @@ const utils_1 = require("../../utils");
8
8
  const secretManager_1 = require("../../gcp/secretManager");
9
9
  const projects_1 = require("../../management/projects");
10
10
  const functional_1 = require("../../functional");
11
+ const api_1 = require("../../api");
11
12
  const backend = require("./backend");
12
13
  const FAQ_URL = "https://firebase.google.com/support/faq#functions-runtime";
13
- const CLOUD_BUILD_API = "cloudbuild.googleapis.com";
14
14
  const metadataCallCache = new Map();
15
15
  async function defaultServiceAccount(e) {
16
16
  let metadataCall = metadataCallCache.get(e.project);
@@ -54,7 +54,7 @@ function isPermissionError(e) {
54
54
  }
55
55
  async function cloudBuildEnabled(projectId) {
56
56
  try {
57
- await (0, ensureApiEnabled_1.ensure)(projectId, CLOUD_BUILD_API, "functions");
57
+ await (0, ensureApiEnabled_1.ensure)(projectId, api_1.cloudbuildOrigin, "functions");
58
58
  }
59
59
  catch (e) {
60
60
  if ((0, error_1.isBillingError)(e)) {
@@ -10,6 +10,7 @@ const functionsEnv = require("../../functions/env");
10
10
  const runtimes = require("./runtimes");
11
11
  const validate = require("./validate");
12
12
  const ensure = require("./ensure");
13
+ const api_1 = require("../../api");
13
14
  const functionsDeployHelper_1 = require("./functionsDeployHelper");
14
15
  const utils_1 = require("../../utils");
15
16
  const prepareFunctionsUpload_1 = require("./prepareFunctionsUpload");
@@ -40,10 +41,10 @@ async function prepare(context, options, payload) {
40
41
  (0, utils_1.logLabeledBullet)("functions", `preparing codebase ${clc.bold(codebase)} for deployment`);
41
42
  }
42
43
  const checkAPIsEnabled = await Promise.all([
43
- ensureApiEnabled.ensure(projectId, "cloudfunctions.googleapis.com", "functions"),
44
- ensureApiEnabled.check(projectId, "runtimeconfig.googleapis.com", "runtimeconfig", true),
44
+ ensureApiEnabled.ensure(projectId, api_1.functionsOrigin, "functions"),
45
+ ensureApiEnabled.check(projectId, api_1.runtimeconfigOrigin, "runtimeconfig", true),
45
46
  ensure.cloudBuildEnabled(projectId),
46
- ensureApiEnabled.ensure(projectId, "artifactregistry.googleapis.com", "artifactregistry"),
47
+ ensureApiEnabled.ensure(projectId, api_1.artifactRegistryDomain, "artifactregistry"),
47
48
  ]);
48
49
  const firebaseConfig = await functionsConfig.getFirebaseConfig(options);
49
50
  context.firebaseConfig = firebaseConfig;
@@ -157,12 +158,7 @@ async function prepare(context, options, payload) {
157
158
  return ensureApiEnabled.ensure(projectId, api, "functions", false);
158
159
  }));
159
160
  if (backend.someEndpoint(wantBackend, (e) => e.platform === "gcfv2")) {
160
- const V2_APIS = [
161
- "run.googleapis.com",
162
- "eventarc.googleapis.com",
163
- "pubsub.googleapis.com",
164
- "storage.googleapis.com",
165
- ];
161
+ const V2_APIS = [api_1.cloudRunApiOrigin, api_1.eventarcOrigin, api_1.pubsubOrigin, api_1.storageOrigin];
166
162
  const enablements = V2_APIS.map((api) => {
167
163
  return ensureApiEnabled.ensure(context.projectId, api, "functions");
168
164
  });
@@ -23,9 +23,9 @@ const EMULATOR_UPDATE_DETAILS = {
23
23
  expectedChecksum: "2fd771101c0e1f7898c04c9204f2ce63",
24
24
  },
25
25
  firestore: {
26
- version: "1.18.2",
27
- expectedSize: 63929486,
28
- expectedChecksum: "7b066cd684baf9bcd4a56a258be344a5",
26
+ version: "1.19.1",
27
+ expectedSize: 67187672,
28
+ expectedChecksum: "859b1ac2a6040cccddd993c43586347c",
29
29
  },
30
30
  storage: {
31
31
  version: "1.1.3",
@@ -15,7 +15,8 @@ const apiClient = new apiv2_1.Client({
15
15
  urlPrefix: api_1.serviceUsageOrigin,
16
16
  apiVersion: "v1",
17
17
  });
18
- async function check(projectId, apiName, prefix, silent = false) {
18
+ async function check(projectId, apiUri, prefix, silent = false) {
19
+ const apiName = apiUri.startsWith("http") ? new URL(apiUri).hostname : apiUri;
19
20
  const res = await apiClient.get(`/projects/${projectId}/services/${apiName}`, {
20
21
  headers: { "x-goog-quota-user": `projects/${projectId}` },
21
22
  skipLog: { resBody: true },
@@ -90,18 +91,19 @@ async function enableApiWithRetries(projectId, apiName, prefix, silent, enableme
90
91
  await enable(projectId, apiName);
91
92
  return pollCheckEnabled(projectId, apiName, prefix, silent, enablementRetries);
92
93
  }
93
- async function ensure(projectId, apiName, prefix, silent = false) {
94
+ async function ensure(projectId, apiUri, prefix, silent = false) {
95
+ const hostname = apiUri.startsWith("http") ? new URL(apiUri).hostname : apiUri;
94
96
  if (!silent) {
95
- utils.logLabeledBullet(prefix, `ensuring required API ${(0, colorette_1.bold)(apiName)} is enabled...`);
97
+ utils.logLabeledBullet(prefix, `ensuring required API ${(0, colorette_1.bold)(hostname)} is enabled...`);
96
98
  }
97
- const isEnabled = await check(projectId, apiName, prefix, silent);
99
+ const isEnabled = await check(projectId, hostname, prefix, silent);
98
100
  if (isEnabled) {
99
101
  return;
100
102
  }
101
103
  if (!silent) {
102
- utils.logLabeledWarning(prefix, `missing required API ${(0, colorette_1.bold)(apiName)}. Enabling now...`);
104
+ utils.logLabeledWarning(prefix, `missing required API ${(0, colorette_1.bold)(hostname)}. Enabling now...`);
103
105
  }
104
- return enableApiWithRetries(projectId, apiName, prefix, silent);
106
+ return enableApiWithRetries(projectId, hostname, prefix, silent);
105
107
  }
106
108
  exports.ensure = ensure;
107
109
  function enableApiURI(projectId, apiName) {
@@ -353,7 +353,7 @@ async function ensureExtensionsApiEnabled(options) {
353
353
  if (!projectId) {
354
354
  return;
355
355
  }
356
- return await (0, ensureApiEnabled_1.ensure)(projectId, "firebaseextensions.googleapis.com", "extensions", options.markdown);
356
+ return await (0, ensureApiEnabled_1.ensure)(projectId, api_1.extensionsOrigin, "extensions", options.markdown);
357
357
  }
358
358
  exports.ensureExtensionsApiEnabled = ensureExtensionsApiEnabled;
359
359
  async function ensureExtensionsPublisherApiEnabled(options) {
@@ -361,7 +361,7 @@ async function ensureExtensionsPublisherApiEnabled(options) {
361
361
  if (!projectId) {
362
362
  return;
363
363
  }
364
- return await (0, ensureApiEnabled_1.ensure)(projectId, "firebaseextensionspublisher.googleapis.com", "extensions", options.markdown);
364
+ return await (0, ensureApiEnabled_1.ensure)(projectId, api_1.extensionsPublisherOrigin, "extensions", options.markdown);
365
365
  }
366
366
  exports.ensureExtensionsPublisherApiEnabled = ensureExtensionsPublisherApiEnabled;
367
367
  async function archiveAndUploadSource(extPath, bucketName) {
@@ -8,11 +8,12 @@ const projectUtils_1 = require("../projectUtils");
8
8
  const types_1 = require("./types");
9
9
  const secretManagerApi = require("../gcp/secretManager");
10
10
  const logger_1 = require("../logger");
11
+ const api_1 = require("../api");
11
12
  exports.SECRET_LABEL = "firebase-extensions-managed";
12
13
  exports.SECRET_ROLE = "secretmanager.secretAccessor";
13
14
  async function ensureSecretManagerApiEnabled(options) {
14
15
  const projectId = (0, projectUtils_1.needProjectId)(options);
15
- return await (0, ensureApiEnabled_1.ensure)(projectId, "secretmanager.googleapis.com", "extensions", options.markdown);
16
+ return await (0, ensureApiEnabled_1.ensure)(projectId, api_1.secretManagerOrigin, "extensions", options.markdown);
16
17
  }
17
18
  exports.ensureSecretManagerApiEnabled = ensureSecretManagerApiEnabled;
18
19
  function usesSecrets(spec) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.compareFieldOverride = exports.compareApiField = exports.compareLocation = exports.compareApiDatabase = exports.compareApiIndex = exports.compareSpecIndex = void 0;
3
+ exports.compareFieldOverride = exports.compareApiField = exports.compareApiBackupSchedule = exports.compareApiBackup = exports.compareLocation = exports.compareApiDatabase = exports.compareApiIndex = exports.compareSpecIndex = void 0;
4
4
  const API = require("./api-types");
5
5
  const util = require("./util");
6
6
  const QUERY_SCOPE_SEQUENCE = [
@@ -42,6 +42,28 @@ function compareLocation(a, b) {
42
42
  return a.locationId > b.locationId ? 1 : -1;
43
43
  }
44
44
  exports.compareLocation = compareLocation;
45
+ function compareApiBackup(a, b) {
46
+ const aLocation = a.name.split("/")[3];
47
+ const bLocation = b.name.split("/")[3];
48
+ if (aLocation && bLocation && aLocation !== bLocation) {
49
+ return aLocation > bLocation ? 1 : -1;
50
+ }
51
+ if (a.snapshotTime && b.snapshotTime && a.snapshotTime !== b.snapshotTime) {
52
+ return a.snapshotTime > b.snapshotTime ? -1 : 1;
53
+ }
54
+ return a.name > b.name ? 1 : -1;
55
+ }
56
+ exports.compareApiBackup = compareApiBackup;
57
+ function compareApiBackupSchedule(a, b) {
58
+ if (a.dailyRecurrence && !b.dailyRecurrence) {
59
+ return -1;
60
+ }
61
+ else if (a.weeklyRecurrence && b.dailyRecurrence) {
62
+ return 1;
63
+ }
64
+ return a.name > b.name ? 1 : -1;
65
+ }
66
+ exports.compareApiBackupSchedule = compareApiBackupSchedule;
45
67
  function compareApiField(a, b) {
46
68
  const aName = util.parseFieldName(a.name);
47
69
  const bName = util.parseFieldName(b.name);
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.PointInTimeRecoveryEnablement = exports.PointInTimeRecoveryEnablementOption = exports.DatabaseDeleteProtectionState = exports.DatabaseDeleteProtectionStateOption = exports.DatabaseType = exports.StateTtl = exports.State = exports.ArrayConfig = exports.Order = exports.QueryScope = exports.Mode = void 0;
3
+ exports.RecurrenceType = exports.PointInTimeRecoveryEnablement = exports.PointInTimeRecoveryEnablementOption = exports.DatabaseDeleteProtectionState = exports.DatabaseDeleteProtectionStateOption = exports.DatabaseType = exports.StateTtl = exports.State = exports.ArrayConfig = exports.Order = exports.QueryScope = exports.Mode = void 0;
4
4
  var Mode;
5
5
  (function (Mode) {
6
6
  Mode["ASCENDING"] = "ASCENDING";
@@ -58,3 +58,8 @@ var PointInTimeRecoveryEnablement;
58
58
  PointInTimeRecoveryEnablement["ENABLED"] = "POINT_IN_TIME_RECOVERY_ENABLED";
59
59
  PointInTimeRecoveryEnablement["DISABLED"] = "POINT_IN_TIME_RECOVERY_DISABLED";
60
60
  })(PointInTimeRecoveryEnablement = exports.PointInTimeRecoveryEnablement || (exports.PointInTimeRecoveryEnablement = {}));
61
+ var RecurrenceType;
62
+ (function (RecurrenceType) {
63
+ RecurrenceType["DAILY"] = "DAILY";
64
+ RecurrenceType["WEEKLY"] = "WEEKLY";
65
+ })(RecurrenceType = exports.RecurrenceType || (exports.RecurrenceType = {}));
@@ -12,9 +12,11 @@ const prompt_1 = require("../prompt");
12
12
  const api_1 = require("../api");
13
13
  const error_1 = require("../error");
14
14
  const apiv2_1 = require("../apiv2");
15
+ const pretty_print_1 = require("./pretty-print");
15
16
  class FirestoreApi {
16
17
  constructor() {
17
18
  this.apiClient = new apiv2_1.Client({ urlPrefix: api_1.firestoreOrigin, apiVersion: "v1" });
19
+ this.printer = new pretty_print_1.PrettyPrint();
18
20
  }
19
21
  async deploy(options, indexes, fieldOverrides, databaseId = "(default)") {
20
22
  const spec = this.upgradeOldSpec({
@@ -49,7 +51,7 @@ class FirestoreApi {
49
51
  }
50
52
  else if (!options.force) {
51
53
  const indexesString = indexesToDelete
52
- .map((x) => this.prettyIndexString(x, false))
54
+ .map((x) => this.printer.prettyIndexString(x, false))
53
55
  .join("\n\t");
54
56
  utils.logLabeledBullet("firestore", `The following indexes are defined in your project but are not present in your firestore indexes file:\n\t${indexesString}`);
55
57
  }
@@ -86,7 +88,7 @@ class FirestoreApi {
86
88
  }
87
89
  else if (!options.force) {
88
90
  const indexesString = fieldOverridesToDelete
89
- .map((x) => this.prettyFieldString(x))
91
+ .map((x) => this.printer.prettyFieldString(x))
90
92
  .join("\n\t");
91
93
  utils.logLabeledBullet("firestore", `The following field overrides are defined in your project but are not present in your firestore indexes file:\n\t${indexesString}`);
92
94
  }
@@ -145,7 +147,7 @@ class FirestoreApi {
145
147
  return [];
146
148
  }
147
149
  return fields.filter((field) => {
148
- return field.name.indexOf("__default__") < 0;
150
+ return !field.name.includes("__default__");
149
151
  });
150
152
  }
151
153
  makeIndexSpec(indexes, fields) {
@@ -184,64 +186,6 @@ class FirestoreApi {
184
186
  fieldOverrides: sortedFields,
185
187
  };
186
188
  }
187
- prettyPrintIndexes(indexes) {
188
- if (indexes.length === 0) {
189
- logger_1.logger.info("None");
190
- return;
191
- }
192
- const sortedIndexes = indexes.sort(sort.compareApiIndex);
193
- sortedIndexes.forEach((index) => {
194
- logger_1.logger.info(this.prettyIndexString(index));
195
- });
196
- }
197
- prettyPrintDatabases(databases) {
198
- if (databases.length === 0) {
199
- logger_1.logger.info("No databases found.");
200
- return;
201
- }
202
- const sortedDatabases = databases.sort(sort.compareApiDatabase);
203
- const Table = require("cli-table");
204
- const table = new Table({
205
- head: ["Database Name"],
206
- colWidths: [Math.max(...sortedDatabases.map((database) => database.name.length + 5), 20)],
207
- });
208
- table.push(...sortedDatabases.map((database) => [this.prettyDatabaseString(database)]));
209
- logger_1.logger.info(table.toString());
210
- }
211
- prettyPrintDatabase(database) {
212
- const Table = require("cli-table");
213
- const table = new Table({
214
- head: ["Field", "Value"],
215
- colWidths: [25, Math.max(50, 5 + database.name.length)],
216
- });
217
- table.push(["Name", clc.yellow(database.name)], ["Create Time", clc.yellow(database.createTime)], ["Last Update Time", clc.yellow(database.updateTime)], ["Type", clc.yellow(database.type)], ["Location", clc.yellow(database.locationId)], ["Delete Protection State", clc.yellow(database.deleteProtectionState)], ["Point In Time Recovery", clc.yellow(database.pointInTimeRecoveryEnablement)], ["Earliest Version Time", clc.yellow(database.earliestVersionTime)], ["Version Retention Period", clc.yellow(database.versionRetentionPeriod)]);
218
- logger_1.logger.info(table.toString());
219
- }
220
- prettyPrintLocations(locations) {
221
- if (locations.length === 0) {
222
- logger_1.logger.info("No Locations Available");
223
- return;
224
- }
225
- const Table = require("cli-table");
226
- const table = new Table({
227
- head: ["Display Name", "LocationId"],
228
- colWidths: [20, 30],
229
- });
230
- table.push(...locations
231
- .sort(sort.compareLocation)
232
- .map((location) => [location.displayName, location.locationId]));
233
- logger_1.logger.info(table.toString());
234
- }
235
- printFieldOverrides(fields) {
236
- if (fields.length === 0) {
237
- logger_1.logger.info("None");
238
- return;
239
- }
240
- const sortedFields = fields.sort(sort.compareApiField);
241
- sortedFields.forEach((field) => {
242
- logger_1.logger.info(this.prettyFieldString(field));
243
- });
244
- }
245
189
  validateSpec(spec) {
246
190
  validator.assertHas(spec, "indexes");
247
191
  spec.indexes.forEach((index) => {
@@ -391,7 +335,7 @@ class FirestoreApi {
391
335
  return index.order || index.arrayConfig;
392
336
  });
393
337
  for (const mode of fieldModes) {
394
- if (specModes.indexOf(mode) < 0) {
338
+ if (!specModes.includes(mode)) {
395
339
  return false;
396
340
  }
397
341
  }
@@ -507,60 +451,19 @@ class FirestoreApi {
507
451
  }
508
452
  return database;
509
453
  }
510
- prettyIndexString(index, includeState = true) {
511
- let result = "";
512
- if (index.state && includeState) {
513
- const stateMsg = `[${index.state}] `;
514
- if (index.state === types.State.READY) {
515
- result += clc.green(stateMsg);
516
- }
517
- else if (index.state === types.State.CREATING) {
518
- result += clc.yellow(stateMsg);
519
- }
520
- else {
521
- result += clc.red(stateMsg);
522
- }
523
- }
524
- const nameInfo = util.parseIndexName(index.name);
525
- result += clc.cyan(`(${nameInfo.collectionGroupId})`);
526
- result += " -- ";
527
- index.fields.forEach((field) => {
528
- if (field.fieldPath === "__name__") {
529
- return;
530
- }
531
- const orderOrArrayConfig = field.order ? field.order : field.arrayConfig;
532
- result += `(${field.fieldPath},${orderOrArrayConfig}) `;
533
- });
534
- return result;
535
- }
536
- prettyDatabaseString(database) {
537
- return clc.yellow(database.name);
538
- }
539
- prettyFieldString(field) {
540
- let result = "";
541
- const parsedName = util.parseFieldName(field.name);
542
- result +=
543
- "[" +
544
- clc.cyan(parsedName.collectionGroupId) +
545
- "." +
546
- clc.yellow(parsedName.fieldPath) +
547
- "] --";
548
- const fieldIndexes = field.indexConfig.indexes || [];
549
- if (fieldIndexes.length > 0) {
550
- fieldIndexes.forEach((index) => {
551
- const firstField = index.fields[0];
552
- const mode = firstField.order || firstField.arrayConfig;
553
- result += ` (${mode})`;
554
- });
555
- }
556
- else {
557
- result += " (no indexes)";
558
- }
559
- const fieldTtl = field.ttlConfig;
560
- if (fieldTtl) {
561
- result += ` TTL(${fieldTtl.state})`;
454
+ async restoreDatabase(project, databaseId, backupName) {
455
+ const url = `/projects/${project}/databases:restore`;
456
+ const payload = {
457
+ databaseId,
458
+ backup: backupName,
459
+ };
460
+ const options = { queryParams: { databaseId: databaseId } };
461
+ const res = await this.apiClient.post(url, payload, options);
462
+ const database = res.body.response;
463
+ if (!database) {
464
+ throw new error_1.FirebaseError("Not found");
562
465
  }
563
- return result;
466
+ return database;
564
467
  }
565
468
  }
566
469
  exports.FirestoreApi = FirestoreApi;