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.
- package/lib/api.js +2 -1
- package/lib/commands/apphosting-backends-create.js +6 -3
- package/lib/commands/apphosting-backends-delete.js +6 -44
- package/lib/commands/apphosting-backends-get.js +4 -35
- package/lib/commands/apphosting-backends-list.js +17 -9
- package/lib/commands/apphosting-builds-create.js +4 -4
- package/lib/commands/apphosting-builds-get.js +2 -2
- package/lib/commands/apphosting-rollouts-create.js +3 -3
- package/lib/commands/apphosting-rollouts-list.js +2 -2
- package/lib/commands/firestore-backups-delete.js +44 -0
- package/lib/commands/firestore-backups-get.js +25 -0
- package/lib/commands/firestore-backups-list.js +34 -0
- package/lib/commands/firestore-backups-schedules-create.js +67 -0
- package/lib/commands/firestore-backups-schedules-delete.js +46 -0
- package/lib/commands/firestore-backups-schedules-list.js +28 -0
- package/lib/commands/firestore-backups-schedules-update.js +33 -0
- package/lib/commands/firestore-databases-create.js +4 -2
- package/lib/commands/firestore-databases-delete.js +4 -2
- package/lib/commands/firestore-databases-get.js +3 -1
- package/lib/commands/firestore-databases-list.js +3 -1
- package/lib/commands/firestore-databases-restore.js +42 -0
- package/lib/commands/firestore-databases-update.js +4 -2
- package/lib/commands/firestore-indexes-list.js +5 -3
- package/lib/commands/firestore-locations.js +3 -1
- package/lib/commands/index.js +10 -0
- package/lib/deploy/extensions/v2FunctionHelper.js +2 -1
- package/lib/deploy/functions/ensure.js +2 -2
- package/lib/deploy/functions/prepare.js +5 -9
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/ensureApiEnabled.js +8 -6
- package/lib/extensions/extensionsHelper.js +2 -2
- package/lib/extensions/secretsUtils.js +2 -1
- package/lib/firestore/api-sort.js +23 -1
- package/lib/firestore/api-types.js +6 -1
- package/lib/firestore/api.js +18 -115
- package/lib/firestore/backupUtils.js +30 -0
- package/lib/firestore/pretty-print.js +184 -0
- package/lib/functions/secrets.js +1 -1
- package/lib/gcp/apphosting.js +4 -5
- package/lib/gcp/auth.js +5 -2
- package/lib/gcp/cloudbuild.js +7 -2
- package/lib/gcp/firestore.js +75 -1
- package/lib/gcp/storage.js +1 -1
- package/lib/init/features/apphosting/index.js +139 -78
- package/lib/init/features/apphosting/repo.js +83 -35
- package/lib/init/features/database.js +2 -1
- package/lib/init/features/extensions/index.js +2 -1
- package/lib/init/features/functions/index.js +3 -2
- package/lib/init/features/hosting/github.js +5 -0
- package/lib/prompt.js +1 -0
- 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 ${
|
|
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
|
-
|
|
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
|
-
|
|
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 ${
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
23
|
+
printer.prettyPrintLocations(locations);
|
|
22
24
|
}
|
|
23
25
|
return locations;
|
|
24
26
|
});
|
package/lib/commands/index.js
CHANGED
|
@@ -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,
|
|
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,
|
|
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,
|
|
44
|
-
ensureApiEnabled.check(projectId,
|
|
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,
|
|
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.
|
|
27
|
-
expectedSize:
|
|
28
|
-
expectedChecksum: "
|
|
26
|
+
version: "1.19.1",
|
|
27
|
+
expectedSize: 67187672,
|
|
28
|
+
expectedChecksum: "859b1ac2a6040cccddd993c43586347c",
|
|
29
29
|
},
|
|
30
30
|
storage: {
|
|
31
31
|
version: "1.1.3",
|
package/lib/ensureApiEnabled.js
CHANGED
|
@@ -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,
|
|
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,
|
|
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)(
|
|
97
|
+
utils.logLabeledBullet(prefix, `ensuring required API ${(0, colorette_1.bold)(hostname)} is enabled...`);
|
|
96
98
|
}
|
|
97
|
-
const isEnabled = await check(projectId,
|
|
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)(
|
|
104
|
+
utils.logLabeledWarning(prefix, `missing required API ${(0, colorette_1.bold)(hostname)}. Enabling now...`);
|
|
103
105
|
}
|
|
104
|
-
return enableApiWithRetries(projectId,
|
|
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,
|
|
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,
|
|
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,
|
|
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 = {}));
|
package/lib/firestore/api.js
CHANGED
|
@@ -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.
|
|
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.
|
|
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
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
520
|
-
|
|
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
|
|
466
|
+
return database;
|
|
564
467
|
}
|
|
565
468
|
}
|
|
566
469
|
exports.FirestoreApi = FirestoreApi;
|