firebase-tools 11.26.0 → 11.28.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/commands/ext-install.js +6 -1
- package/lib/commands/ext-update.js +6 -1
- package/lib/commands/firestore-databases-create.js +45 -0
- package/lib/commands/firestore-databases-delete.js +39 -0
- package/lib/commands/firestore-databases-get.js +25 -0
- package/lib/commands/firestore-databases-list.js +24 -0
- package/lib/commands/firestore-databases-update.js +42 -0
- package/lib/commands/firestore-indexes-list.js +2 -2
- package/lib/commands/firestore-locations.js +24 -0
- package/lib/commands/index.js +7 -0
- package/lib/commands/init.js +5 -0
- package/lib/commands/open.js +10 -0
- package/lib/deploy/firestore/deploy.js +2 -2
- package/lib/deploy/functions/backend.js +1 -5
- package/lib/deploy/functions/build.js +8 -11
- package/lib/deploy/functions/release/fabricator.js +16 -6
- package/lib/experiments.js +1 -6
- package/lib/extensions/extensionsHelper.js +5 -37
- package/lib/extensions/manifest.js +23 -1
- package/lib/firestore/{indexes-sort.js → api-sort.js} +10 -2
- package/lib/firestore/{indexes-api.js → api-types.js} +16 -1
- package/lib/firestore/{indexes.js → api.js} +122 -16
- package/lib/frameworks/astro/index.js +76 -0
- package/lib/frameworks/astro/utils.js +22 -0
- package/lib/frameworks/nuxt/index.js +34 -14
- package/lib/frameworks/nuxt/utils.js +11 -1
- package/lib/frameworks/nuxt2/index.js +3 -9
- package/lib/gcp/cloudfunctions.js +3 -0
- package/lib/gcp/cloudfunctionsv2.js +39 -26
- package/lib/init/features/extensions/index.js +16 -0
- package/lib/init/features/firestore/indexes.js +2 -2
- package/lib/init/features/index.js +3 -1
- package/lib/init/index.js +1 -0
- package/lib/prompt.js +19 -1
- package/npm-shrinkwrap.json +14 -14
- package/package.json +1 -1
- /package/lib/firestore/{indexes-spec.js → api-spec.js} +0 -0
|
@@ -12,9 +12,11 @@ const error_1 = require("../error");
|
|
|
12
12
|
const projectUtils_1 = require("../projectUtils");
|
|
13
13
|
const extensionsApi = require("../extensions/extensionsApi");
|
|
14
14
|
const refs = require("../extensions/refs");
|
|
15
|
+
const secretsUtils = require("../extensions/secretsUtils");
|
|
15
16
|
const warnings_1 = require("../extensions/warnings");
|
|
16
17
|
const paramHelper = require("../extensions/paramHelper");
|
|
17
18
|
const extensionsHelper_1 = require("../extensions/extensionsHelper");
|
|
19
|
+
const prompt_1 = require("../prompt");
|
|
18
20
|
const utils_1 = require("../extensions/utils");
|
|
19
21
|
const requirePermissions_1 = require("../requirePermissions");
|
|
20
22
|
const utils = require("../utils");
|
|
@@ -74,7 +76,7 @@ exports.command = new command_1.Command("ext:install [extensionName]")
|
|
|
74
76
|
extensionVersion,
|
|
75
77
|
});
|
|
76
78
|
}
|
|
77
|
-
if (!(await (0,
|
|
79
|
+
if (!(await (0, prompt_1.confirm)({
|
|
78
80
|
nonInteractive: options.nonInteractive,
|
|
79
81
|
force: options.force,
|
|
80
82
|
default: true,
|
|
@@ -126,6 +128,9 @@ async function installToManifest(options) {
|
|
|
126
128
|
if (!spec) {
|
|
127
129
|
throw new error_1.FirebaseError(`Could not find the extension.yaml for ${extensionName}. Please make sure this is a valid extension and try again.`);
|
|
128
130
|
}
|
|
131
|
+
if (secretsUtils.usesSecrets(spec)) {
|
|
132
|
+
await secretsUtils.ensureSecretManagerApiEnabled(options);
|
|
133
|
+
}
|
|
129
134
|
const config = manifest.loadConfig(options);
|
|
130
135
|
let instanceId = spec.name;
|
|
131
136
|
while (manifest.instanceExists(instanceId, config)) {
|
|
@@ -11,8 +11,10 @@ const extensionsApi = require("../extensions/extensionsApi");
|
|
|
11
11
|
const extensionsHelper_1 = require("../extensions/extensionsHelper");
|
|
12
12
|
const paramHelper = require("../extensions/paramHelper");
|
|
13
13
|
const updateHelper_1 = require("../extensions/updateHelper");
|
|
14
|
+
const secretsUtils = require("../extensions/secretsUtils");
|
|
14
15
|
const refs = require("../extensions/refs");
|
|
15
16
|
const projectUtils_1 = require("../projectUtils");
|
|
17
|
+
const prompt_1 = require("../prompt");
|
|
16
18
|
const requirePermissions_1 = require("../requirePermissions");
|
|
17
19
|
const utils = require("../utils");
|
|
18
20
|
const experiments = require("../experiments");
|
|
@@ -60,7 +62,7 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
60
62
|
return;
|
|
61
63
|
}
|
|
62
64
|
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `Updating ${clc.bold(instanceId)} from version ${clc.bold(oldExtensionVersion.ref)} to version ${clc.bold(newExtensionVersion.ref)}.`);
|
|
63
|
-
if (!(await (0,
|
|
65
|
+
if (!(await (0, prompt_1.confirm)({
|
|
64
66
|
nonInteractive: options.nonInteractive,
|
|
65
67
|
force: options.force,
|
|
66
68
|
default: false,
|
|
@@ -68,6 +70,9 @@ exports.command = new command_1.Command("ext:update <extensionInstanceId> [updat
|
|
|
68
70
|
utils.logLabeledBullet(extensionsHelper_1.logPrefix, "Update aborted.");
|
|
69
71
|
return;
|
|
70
72
|
}
|
|
73
|
+
if (secretsUtils.usesSecrets(newExtensionVersion.spec)) {
|
|
74
|
+
await secretsUtils.ensureSecretManagerApiEnabled(options);
|
|
75
|
+
}
|
|
71
76
|
const oldParamValues = manifest.readInstanceParam({
|
|
72
77
|
instanceId,
|
|
73
78
|
projectDir: config.projectDir,
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const clc = require("colorette");
|
|
6
|
+
const fsi = require("../firestore/api");
|
|
7
|
+
const types = require("../firestore/api-types");
|
|
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
|
+
exports.command = new command_1.Command("firestore:databases:create <database>")
|
|
13
|
+
.description("Create a database in your Firebase project.")
|
|
14
|
+
.option("--location <locationId>", "Region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations. (required)")
|
|
15
|
+
.option("--delete-protection <deleteProtectionState>", "Whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
|
|
16
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.databases.create"])
|
|
17
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
18
|
+
.action(async (database, options) => {
|
|
19
|
+
const api = new fsi.FirestoreApi();
|
|
20
|
+
if (!options.location) {
|
|
21
|
+
logger_1.logger.error("Missing required flag --location. See firebase firestore:databases:create --help for more info.");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const type = types.DatabaseType.FIRESTORE_NATIVE;
|
|
25
|
+
if (options.deleteProtection &&
|
|
26
|
+
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED &&
|
|
27
|
+
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.DISABLED) {
|
|
28
|
+
logger_1.logger.error("Invalid value for flag --delete-protection. See firebase firestore:databases:create --help for more info.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const deleteProtectionState = options.deleteProtection === types.DatabaseDeleteProtectionStateOption.ENABLED
|
|
32
|
+
? types.DatabaseDeleteProtectionState.ENABLED
|
|
33
|
+
: types.DatabaseDeleteProtectionState.DISABLED;
|
|
34
|
+
const databaseResp = await api.createDatabase(options.project, database, options.location, type, deleteProtectionState);
|
|
35
|
+
if (options.json) {
|
|
36
|
+
logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
logger_1.logger.info(clc.bold(`Successfully created ${api.prettyDatabaseString(databaseResp)}`));
|
|
40
|
+
logger_1.logger.info("Please be sure to configure Firebase rules in your Firebase config file for\n" +
|
|
41
|
+
"the new database. By default, created databases will have closed rules that\n" +
|
|
42
|
+
"block any incoming third-party traffic.");
|
|
43
|
+
}
|
|
44
|
+
return databaseResp;
|
|
45
|
+
});
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const clc = require("colorette");
|
|
6
|
+
const fsi = require("../firestore/api");
|
|
7
|
+
const prompt_1 = require("../prompt");
|
|
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:databases:delete <database>")
|
|
14
|
+
.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
|
+
.option("--force", "Attempt to delete database without prompting for confirmation.")
|
|
16
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.databases.delete"])
|
|
17
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
18
|
+
.action(async (database, options) => {
|
|
19
|
+
const api = new fsi.FirestoreApi();
|
|
20
|
+
if (!options.force) {
|
|
21
|
+
const confirmMessage = `You are about to delete projects/${options.project}/databases/${database}. 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 database canceled.");
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
const databaseResp = await api.deleteDatabase(options.project, database);
|
|
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 deleted ${api.prettyDatabaseString(databaseResp)}`));
|
|
37
|
+
}
|
|
38
|
+
return databaseResp;
|
|
39
|
+
});
|
|
@@ -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 fsi = require("../firestore/api");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const requirePermissions_1 = require("../requirePermissions");
|
|
8
|
+
const types_1 = require("../emulator/types");
|
|
9
|
+
const commandUtils_1 = require("../emulator/commandUtils");
|
|
10
|
+
exports.command = new command_1.Command("firestore:databases:get [database]")
|
|
11
|
+
.description("Get database in your Cloud Firestore project.")
|
|
12
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.databases.get"])
|
|
13
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
14
|
+
.action(async (database, options) => {
|
|
15
|
+
const api = new fsi.FirestoreApi();
|
|
16
|
+
const databaseId = database || "(default)";
|
|
17
|
+
const databaseResp = await api.getDatabase(options.project, databaseId);
|
|
18
|
+
if (options.json) {
|
|
19
|
+
logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
|
|
20
|
+
}
|
|
21
|
+
else {
|
|
22
|
+
api.prettyPrintDatabase(databaseResp);
|
|
23
|
+
}
|
|
24
|
+
return databaseResp;
|
|
25
|
+
});
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const fsi = require("../firestore/api");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const requirePermissions_1 = require("../requirePermissions");
|
|
8
|
+
const types_1 = require("../emulator/types");
|
|
9
|
+
const commandUtils_1 = require("../emulator/commandUtils");
|
|
10
|
+
exports.command = new command_1.Command("firestore:databases:list")
|
|
11
|
+
.description("List databases in your Cloud Firestore project.")
|
|
12
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.databases.list"])
|
|
13
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const api = new fsi.FirestoreApi();
|
|
16
|
+
const databases = await api.listDatabases(options.project);
|
|
17
|
+
if (options.json) {
|
|
18
|
+
logger_1.logger.info(JSON.stringify(databases, undefined, 2));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
api.prettyPrintDatabases(databases);
|
|
22
|
+
}
|
|
23
|
+
return databases;
|
|
24
|
+
});
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const clc = require("colorette");
|
|
6
|
+
const fsi = require("../firestore/api");
|
|
7
|
+
const types = require("../firestore/api-types");
|
|
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
|
+
exports.command = new command_1.Command("firestore:databases:update <database>")
|
|
13
|
+
.description("Update a database in your Firebase project. Must specify at least one property to update.")
|
|
14
|
+
.option("--json", "Prints raw json response of the create API call if specified")
|
|
15
|
+
.option("--delete-protection <deleteProtectionState>", "Whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
|
|
16
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.databases.update"])
|
|
17
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
18
|
+
.action(async (database, options) => {
|
|
19
|
+
const api = new fsi.FirestoreApi();
|
|
20
|
+
if (!options.type && !options.deleteProtection) {
|
|
21
|
+
logger_1.logger.error("Missing properties to update. See firebase firestore:databases:update --help for more info.");
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const type = types.DatabaseType.FIRESTORE_NATIVE;
|
|
25
|
+
if (options.deleteProtection &&
|
|
26
|
+
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.ENABLED &&
|
|
27
|
+
options.deleteProtection !== types.DatabaseDeleteProtectionStateOption.DISABLED) {
|
|
28
|
+
logger_1.logger.error("Invalid value for flag --delete-protection. See firebase firestore:databases:update --help for more info.");
|
|
29
|
+
return;
|
|
30
|
+
}
|
|
31
|
+
const deleteProtectionState = options.deleteProtection === types.DatabaseDeleteProtectionStateOption.ENABLED
|
|
32
|
+
? types.DatabaseDeleteProtectionState.ENABLED
|
|
33
|
+
: types.DatabaseDeleteProtectionState.DISABLED;
|
|
34
|
+
const databaseResp = await api.updateDatabase(options.project, database, type, deleteProtectionState);
|
|
35
|
+
if (options.json) {
|
|
36
|
+
logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
|
|
37
|
+
}
|
|
38
|
+
else {
|
|
39
|
+
logger_1.logger.info(clc.bold(`Successfully updated ${api.prettyDatabaseString(databaseResp)}`));
|
|
40
|
+
}
|
|
41
|
+
return databaseResp;
|
|
42
|
+
});
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.command = void 0;
|
|
4
4
|
const command_1 = require("../command");
|
|
5
5
|
const clc = require("colorette");
|
|
6
|
-
const fsi = require("../firestore/
|
|
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");
|
|
@@ -17,7 +17,7 @@ exports.command = new command_1.Command("firestore:indexes")
|
|
|
17
17
|
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
18
18
|
.action(async (options) => {
|
|
19
19
|
var _a;
|
|
20
|
-
const indexApi = new fsi.
|
|
20
|
+
const indexApi = new fsi.FirestoreApi();
|
|
21
21
|
const databaseId = (_a = options.database) !== null && _a !== void 0 ? _a : "(default)";
|
|
22
22
|
const indexes = await indexApi.listIndexes(options.project, databaseId);
|
|
23
23
|
const fieldOverrides = await indexApi.listFieldOverrides(options.project, databaseId);
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.command = void 0;
|
|
4
|
+
const command_1 = require("../command");
|
|
5
|
+
const fsi = require("../firestore/api");
|
|
6
|
+
const logger_1 = require("../logger");
|
|
7
|
+
const requirePermissions_1 = require("../requirePermissions");
|
|
8
|
+
const types_1 = require("../emulator/types");
|
|
9
|
+
const commandUtils_1 = require("../emulator/commandUtils");
|
|
10
|
+
exports.command = new command_1.Command("firestore:locations")
|
|
11
|
+
.description("List possible locations for your Cloud Firestore project.")
|
|
12
|
+
.before(requirePermissions_1.requirePermissions, ["datastore.locations.list"])
|
|
13
|
+
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
14
|
+
.action(async (options) => {
|
|
15
|
+
const api = new fsi.FirestoreApi();
|
|
16
|
+
const locations = await api.locations(options.project);
|
|
17
|
+
if (options.json) {
|
|
18
|
+
logger_1.logger.info(JSON.stringify(locations, undefined, 2));
|
|
19
|
+
}
|
|
20
|
+
else {
|
|
21
|
+
api.prettyPrintLocations(locations);
|
|
22
|
+
}
|
|
23
|
+
return locations;
|
|
24
|
+
});
|
package/lib/commands/index.js
CHANGED
|
@@ -102,6 +102,13 @@ function load(client) {
|
|
|
102
102
|
client.firestore = {};
|
|
103
103
|
client.firestore.delete = loadCommand("firestore-delete");
|
|
104
104
|
client.firestore.indexes = loadCommand("firestore-indexes-list");
|
|
105
|
+
client.firestore.locations = loadCommand("firestore-locations");
|
|
106
|
+
client.firestore.databases = {};
|
|
107
|
+
client.firestore.databases.list = loadCommand("firestore-databases-list");
|
|
108
|
+
client.firestore.databases.get = loadCommand("firestore-databases-get");
|
|
109
|
+
client.firestore.databases.create = loadCommand("firestore-databases-create");
|
|
110
|
+
client.firestore.databases.update = loadCommand("firestore-databases-update");
|
|
111
|
+
client.firestore.databases.delete = loadCommand("firestore-databases-delete");
|
|
105
112
|
client.functions = {};
|
|
106
113
|
client.functions.config = {};
|
|
107
114
|
client.functions.config.clone = loadCommand("functions-config-clone");
|
package/lib/commands/init.js
CHANGED
|
@@ -62,6 +62,11 @@ const choices = [
|
|
|
62
62
|
name: "Remote Config: Configure a template file for Remote Config",
|
|
63
63
|
checked: false,
|
|
64
64
|
},
|
|
65
|
+
{
|
|
66
|
+
value: "extensions",
|
|
67
|
+
name: "Extensions: Set up an empty Extensions manifest",
|
|
68
|
+
checked: false,
|
|
69
|
+
},
|
|
65
70
|
];
|
|
66
71
|
const featureNames = choices.map((choice) => choice.value);
|
|
67
72
|
const DESCRIPTION = `Interactively configure the current directory as a Firebase project or initialize new features in an already configured Firebase project directory.
|
package/lib/commands/open.js
CHANGED
|
@@ -24,6 +24,16 @@ const LINKS = [
|
|
|
24
24
|
{ name: "Firestore: Data", arg: "firestore", consolePath: "/firestore/data" },
|
|
25
25
|
{ name: "Firestore: Rules", arg: "firestore:rules", consolePath: "/firestore/rules" },
|
|
26
26
|
{ name: "Firestore: Indexes", arg: "firestore:indexes", consolePath: "/firestore/indexes" },
|
|
27
|
+
{
|
|
28
|
+
name: "Firestore: Databases List",
|
|
29
|
+
arg: "firestore:databases:list",
|
|
30
|
+
consolePath: "/firestore/databases/list",
|
|
31
|
+
},
|
|
32
|
+
{
|
|
33
|
+
name: "Firestore: Locations",
|
|
34
|
+
arg: "firestore:locations",
|
|
35
|
+
consolePath: "/firestore/locations",
|
|
36
|
+
},
|
|
27
37
|
{ name: "Firestore: Usage", arg: "firestore:usage", consolePath: "/firestore/usage" },
|
|
28
38
|
{ name: "Functions", arg: "functions", consolePath: "/functions/list" },
|
|
29
39
|
{ name: "Functions Log", arg: "functions:log" },
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
const clc = require("colorette");
|
|
4
|
-
const
|
|
4
|
+
const api_1 = require("../../firestore/api");
|
|
5
5
|
const logger_1 = require("../../logger");
|
|
6
6
|
const utils = require("../../utils");
|
|
7
7
|
const rulesDeploy_1 = require("../../rulesDeploy");
|
|
@@ -20,7 +20,7 @@ async function deployIndexes(context, options) {
|
|
|
20
20
|
}
|
|
21
21
|
const indexesContext = (_a = context === null || context === void 0 ? void 0 : context.firestore) === null || _a === void 0 ? void 0 : _a.indexes;
|
|
22
22
|
utils.logBullet(clc.bold(clc.cyan("firestore: ")) + "deploying indexes...");
|
|
23
|
-
const firestoreIndexes = new
|
|
23
|
+
const firestoreIndexes = new api_1.FirestoreApi();
|
|
24
24
|
await Promise.all(indexesContext.map(async (indexContext) => {
|
|
25
25
|
const { databaseId, indexesFileName, indexesRawSpec } = indexContext;
|
|
26
26
|
if (!indexesRawSpec) {
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.compareFunctions = exports.missingEndpoint = exports.hasEndpoint = exports.regionalEndpoints = exports.matchingBackend = exports.findEndpoint = exports.someEndpoint = exports.allEndpoints = exports.checkAvailability = exports.existingBackend = exports.scheduleIdForFunction = exports.functionName = exports.isEmptyBackend = exports.merge = exports.of = exports.empty = exports.isBlockingTriggered = exports.isTaskQueueTriggered = exports.isScheduleTriggered = exports.isEventTriggered = exports.isCallableTriggered = exports.isHttpsTriggered = exports.AllFunctionsPlatforms = exports.secretVersionName = exports.SCHEDULED_FUNCTION_LABEL = exports.MIN_CPU_FOR_CONCURRENCY = exports.DEFAULT_MEMORY = exports.DEFAULT_CONCURRENCY = exports.memoryToGen2Cpu = exports.memoryToGen1Cpu = exports.memoryOptionDisplayName = exports.isValidMemoryOption = exports.AllIngressSettings = exports.AllVpcEgressSettings = exports.endpointTriggerType = void 0;
|
|
4
4
|
const gcf = require("../../gcp/cloudfunctions");
|
|
5
5
|
const gcfV2 = require("../../gcp/cloudfunctionsv2");
|
|
6
|
-
const run = require("../../gcp/run");
|
|
7
6
|
const utils = require("../../utils");
|
|
8
7
|
const error_1 = require("../../error");
|
|
9
8
|
const functional_1 = require("../../functional");
|
|
@@ -195,11 +194,8 @@ async function loadExistingBackend(ctx) {
|
|
|
195
194
|
let gcfV2Results;
|
|
196
195
|
try {
|
|
197
196
|
gcfV2Results = await gcfV2.listAllFunctions(ctx.projectId);
|
|
198
|
-
const
|
|
199
|
-
for (const [apiFunction, runService] of (0, functional_1.zip)(gcfV2Results.functions, runResults)) {
|
|
197
|
+
for (const apiFunction of gcfV2Results.functions) {
|
|
200
198
|
const endpoint = gcfV2.endpointFromFunction(apiFunction);
|
|
201
|
-
endpoint.concurrency = runService.spec.template.spec.containerConcurrency || 1;
|
|
202
|
-
endpoint.cpu = +runService.spec.template.spec.containers[0].resources.limits.cpu;
|
|
203
199
|
ctx.existingBackend.endpoints[endpoint.region] =
|
|
204
200
|
ctx.existingBackend.endpoints[endpoint.region] || {};
|
|
205
201
|
ctx.existingBackend.endpoints[endpoint.region][endpoint.id] = endpoint;
|
|
@@ -5,7 +5,6 @@ const backend = require("./backend");
|
|
|
5
5
|
const proto = require("../../gcp/proto");
|
|
6
6
|
const api = require("../../.../../api");
|
|
7
7
|
const params = require("./params");
|
|
8
|
-
const experiments = require("../../experiments");
|
|
9
8
|
const error_1 = require("../../error");
|
|
10
9
|
const functional_1 = require("../../functional");
|
|
11
10
|
const env_1 = require("../../functions/env");
|
|
@@ -61,18 +60,16 @@ exports.AllIngressSettings = [
|
|
|
61
60
|
];
|
|
62
61
|
async function resolveBackend(build, firebaseConfig, userEnvOpt, userEnvs, nonInteractive) {
|
|
63
62
|
let paramValues = {};
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
toWrite[paramName] = paramValue.toString();
|
|
63
|
+
paramValues = await params.resolveParams(build.params, firebaseConfig, envWithTypes(build.params, userEnvs), nonInteractive);
|
|
64
|
+
const toWrite = {};
|
|
65
|
+
for (const paramName of Object.keys(paramValues)) {
|
|
66
|
+
const paramValue = paramValues[paramName];
|
|
67
|
+
if (Object.prototype.hasOwnProperty.call(userEnvs, paramName) || paramValue.internal) {
|
|
68
|
+
continue;
|
|
73
69
|
}
|
|
74
|
-
|
|
70
|
+
toWrite[paramName] = paramValue.toString();
|
|
75
71
|
}
|
|
72
|
+
(0, env_1.writeUserEnvs)(toWrite, userEnvOpt);
|
|
76
73
|
return { backend: toBackend(build, paramValues), envs: paramValues };
|
|
77
74
|
}
|
|
78
75
|
exports.resolveBackend = resolveBackend;
|
|
@@ -219,7 +219,7 @@ class Fabricator {
|
|
|
219
219
|
}
|
|
220
220
|
}
|
|
221
221
|
async createV2Function(endpoint) {
|
|
222
|
-
var _a, _b, _c;
|
|
222
|
+
var _a, _b, _c, _d, _e;
|
|
223
223
|
const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
224
224
|
if (!storage) {
|
|
225
225
|
logger_1.logger.debug("Precondition failed. Cannot create a GCFv2 function without storage");
|
|
@@ -274,8 +274,13 @@ class Fabricator {
|
|
|
274
274
|
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `create-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
275
275
|
})
|
|
276
276
|
.catch(rethrowAs(endpoint, "create"));
|
|
277
|
-
endpoint.uri = resultFunction.serviceConfig.uri;
|
|
278
|
-
const serviceName = resultFunction.serviceConfig.service;
|
|
277
|
+
endpoint.uri = (_d = resultFunction.serviceConfig) === null || _d === void 0 ? void 0 : _d.uri;
|
|
278
|
+
const serviceName = (_e = resultFunction.serviceConfig) === null || _e === void 0 ? void 0 : _e.service;
|
|
279
|
+
if (!serviceName) {
|
|
280
|
+
logger_1.logger.debug("Result function unexpectedly didn't have a service name.");
|
|
281
|
+
utils.logLabeledWarning("functions", "Updated function is not associated with a service. This deployment is in an unexpected state - please re-deploy your functions.");
|
|
282
|
+
return;
|
|
283
|
+
}
|
|
279
284
|
if (backend.isHttpsTriggered(endpoint)) {
|
|
280
285
|
const invoker = endpoint.httpsTrigger.invoker || ["public"];
|
|
281
286
|
if (!invoker.includes("private")) {
|
|
@@ -346,7 +351,7 @@ class Fabricator {
|
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
async updateV2Function(endpoint) {
|
|
349
|
-
var _a, _b;
|
|
354
|
+
var _a, _b, _c, _d;
|
|
350
355
|
const storage = (_a = this.sources[endpoint.codebase]) === null || _a === void 0 ? void 0 : _a.storage;
|
|
351
356
|
if (!storage) {
|
|
352
357
|
logger_1.logger.debug("Precondition failed. Cannot update a GCFv2 function without storage");
|
|
@@ -362,8 +367,13 @@ class Fabricator {
|
|
|
362
367
|
return await poller.pollOperation(Object.assign(Object.assign({}, gcfV2PollerOptions), { pollerName: `update-${endpoint.codebase}-${endpoint.region}-${endpoint.id}`, operationResourceName: op.name }));
|
|
363
368
|
})
|
|
364
369
|
.catch(rethrowAs(endpoint, "update"));
|
|
365
|
-
endpoint.uri = resultFunction.serviceConfig.uri;
|
|
366
|
-
const serviceName = resultFunction.serviceConfig.service;
|
|
370
|
+
endpoint.uri = (_c = resultFunction.serviceConfig) === null || _c === void 0 ? void 0 : _c.uri;
|
|
371
|
+
const serviceName = (_d = resultFunction.serviceConfig) === null || _d === void 0 ? void 0 : _d.service;
|
|
372
|
+
if (!serviceName) {
|
|
373
|
+
logger_1.logger.debug("Result function unexpectedly didn't have a service name.");
|
|
374
|
+
utils.logLabeledWarning("functions", "Updated function is not associated with a service. This deployment is in an unexpected state - please re-deploy your functions.");
|
|
375
|
+
return;
|
|
376
|
+
}
|
|
367
377
|
let invoker;
|
|
368
378
|
if (backend.isHttpsTriggered(endpoint)) {
|
|
369
379
|
invoker = endpoint.httpsTrigger.invoker === null ? ["public"] : endpoint.httpsTrigger.invoker;
|
package/lib/experiments.js
CHANGED
|
@@ -44,18 +44,13 @@ exports.ALL_EXPERIMENTS = experiments({
|
|
|
44
44
|
"of how that image was created.",
|
|
45
45
|
public: true,
|
|
46
46
|
},
|
|
47
|
-
functionsparams: {
|
|
48
|
-
shortDescription: "Adds support for paramaterizing functions deployments",
|
|
49
|
-
default: true,
|
|
50
|
-
},
|
|
51
47
|
emulatoruisnapshot: {
|
|
52
48
|
shortDescription: "Load pre-release versions of the emulator UI",
|
|
53
49
|
},
|
|
54
50
|
webframeworks: {
|
|
55
51
|
shortDescription: "Native support for popular web frameworks",
|
|
56
52
|
fullDescription: "Adds support for popular web frameworks such as Next.js " +
|
|
57
|
-
"Angular, React, Svelte, and Vite-compatible frameworks.
|
|
58
|
-
"committed to support these platforms long-term, but a manual migration " +
|
|
53
|
+
"Angular, React, Svelte, and Vite-compatible frameworks. A manual migration " +
|
|
59
54
|
"may be required when the non-experimental support for these frameworks " +
|
|
60
55
|
"is released",
|
|
61
56
|
docsUri: "https://firebase.google.com/docs/hosting/frameworks-overview",
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.canonicalizeRefInput = exports.diagnoseAndFixProject = exports.
|
|
3
|
+
exports.canonicalizeRefInput = exports.diagnoseAndFixProject = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.publishExtensionVersionFromLocalSource = exports.publishExtensionVersionFromRemoteRepo = exports.incrementPrereleaseVersion = exports.ensureExtensionsApiEnabled = exports.promptForValidRepoURI = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const ora = require("ora");
|
|
6
6
|
const semver = require("semver");
|
|
@@ -388,23 +388,8 @@ async function publishExtensionVersionFromRemoteRepo(args) {
|
|
|
388
388
|
throw new error_1.FirebaseError("Repo URI is required but not currently set.");
|
|
389
389
|
}
|
|
390
390
|
}
|
|
391
|
-
if (
|
|
392
|
-
|
|
393
|
-
}
|
|
394
|
-
if (!(extension === null || extension === void 0 ? void 0 : extension.repoUri)) {
|
|
395
|
-
logger_1.logger.info(`\n${clc.red("Warning:")} You are about to associate repo URI ${clc.bold(repoUri)} with Extension ${clc.bold(extensionRef)}. This cannot be changed. All future verifiable versions must be published from this repo. ` +
|
|
396
|
-
`You can continue publishing unverifiable versions from local source.`);
|
|
397
|
-
const confirmed = await confirm({
|
|
398
|
-
nonInteractive: args.nonInteractive,
|
|
399
|
-
force: args.force,
|
|
400
|
-
default: false,
|
|
401
|
-
});
|
|
402
|
-
if (!confirmed) {
|
|
403
|
-
return;
|
|
404
|
-
}
|
|
405
|
-
}
|
|
406
|
-
else {
|
|
407
|
-
logger_1.logger.info(`Extension ${clc.bold(extensionRef)} is published from ${clc.bold(extension === null || extension === void 0 ? void 0 : extension.repoUri)}.`);
|
|
391
|
+
if (extension === null || extension === void 0 ? void 0 : extension.repoUri) {
|
|
392
|
+
logger_1.logger.info(`Extension ${clc.bold(extensionRef)} is published from ${clc.bold(extension === null || extension === void 0 ? void 0 : extension.repoUri)}. Use --repo to change this repo.`);
|
|
408
393
|
}
|
|
409
394
|
let extensionRoot = args.extensionRoot;
|
|
410
395
|
let defaultRoot = "/";
|
|
@@ -487,7 +472,7 @@ async function publishExtensionVersionFromRemoteRepo(args) {
|
|
|
487
472
|
});
|
|
488
473
|
const sourceUri = path.join(repoUri, "tree", sourceRef, extensionRoot);
|
|
489
474
|
displayReleaseNotes(extensionRef, extensionSpec.version, notes, sourceUri);
|
|
490
|
-
const confirmed = await confirm({
|
|
475
|
+
const confirmed = await (0, prompt_1.confirm)({
|
|
491
476
|
nonInteractive: args.nonInteractive,
|
|
492
477
|
force: args.force,
|
|
493
478
|
default: false,
|
|
@@ -535,7 +520,7 @@ async function publishExtensionVersionFromLocalSource(args) {
|
|
|
535
520
|
});
|
|
536
521
|
const extensionRef = `${args.publisherId}/${args.extensionId}`;
|
|
537
522
|
displayReleaseNotes(extensionRef, extensionSpec.version, notes);
|
|
538
|
-
const confirmed = await confirm({
|
|
523
|
+
const confirmed = await (0, prompt_1.confirm)({
|
|
539
524
|
nonInteractive: args.nonInteractive,
|
|
540
525
|
force: args.force,
|
|
541
526
|
default: false,
|
|
@@ -725,23 +710,6 @@ function getSourceOrigin(sourceOrVersion) {
|
|
|
725
710
|
throw new error_1.FirebaseError(`Could not find source '${clc.bold(sourceOrVersion)}'. Check to make sure the source is correct, and then please try again.`);
|
|
726
711
|
}
|
|
727
712
|
exports.getSourceOrigin = getSourceOrigin;
|
|
728
|
-
async function confirm(args) {
|
|
729
|
-
if (!args.nonInteractive && !args.force) {
|
|
730
|
-
const message = `Do you wish to continue?`;
|
|
731
|
-
return await (0, prompt_1.promptOnce)({
|
|
732
|
-
type: "confirm",
|
|
733
|
-
message,
|
|
734
|
-
default: args.default,
|
|
735
|
-
});
|
|
736
|
-
}
|
|
737
|
-
else if (args.nonInteractive && !args.force) {
|
|
738
|
-
throw new error_1.FirebaseError("Pass the --force flag to use this command in non-interactive mode");
|
|
739
|
-
}
|
|
740
|
-
else {
|
|
741
|
-
return true;
|
|
742
|
-
}
|
|
743
|
-
}
|
|
744
|
-
exports.confirm = confirm;
|
|
745
713
|
async function diagnoseAndFixProject(options) {
|
|
746
714
|
const projectId = (0, projectUtils_1.getProjectId)(options);
|
|
747
715
|
if (!projectId) {
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.showPostDeprecationNotice = exports.readInstanceParam = exports.getInstanceRef = exports.getInstanceTarget = exports.instanceExists = exports.loadConfig = exports.removeFromManifest = exports.writeLocalSecrets = exports.writeToManifest = exports.ENV_DIRECTORY = void 0;
|
|
3
|
+
exports.showPostDeprecationNotice = exports.readInstanceParam = exports.writeExtensionsToFirebaseJson = exports.getInstanceRef = exports.getInstanceTarget = exports.instanceExists = exports.loadConfig = exports.removeFromManifest = exports.writeLocalSecrets = exports.writeEmptyManifest = exports.writeToManifest = exports.ENV_DIRECTORY = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const path = require("path");
|
|
6
|
+
const fs = require("fs-extra");
|
|
6
7
|
const refs = require("./refs");
|
|
7
8
|
const config_1 = require("../config");
|
|
8
9
|
const planner_1 = require("../deploy/extensions/planner");
|
|
@@ -41,6 +42,26 @@ async function writeToManifest(specs, config, options, allowOverwrite = false) {
|
|
|
41
42
|
await writeLocalSecrets(specs, config, options.force);
|
|
42
43
|
}
|
|
43
44
|
exports.writeToManifest = writeToManifest;
|
|
45
|
+
async function writeEmptyManifest(config, options) {
|
|
46
|
+
if (!fs.existsSync(config.path("extensions"))) {
|
|
47
|
+
fs.mkdirSync(config.path("extensions"));
|
|
48
|
+
}
|
|
49
|
+
if (config.has("extensions") && Object.keys(config.get("extensions")).length) {
|
|
50
|
+
const currentExtensions = Object.entries(config.get("extensions"))
|
|
51
|
+
.map((i) => `${i[0]}: ${i[1]}`)
|
|
52
|
+
.join("\n\t");
|
|
53
|
+
if (!(await (0, prompt_1.confirm)({
|
|
54
|
+
message: `firebase.json already contains extensions:\n${currentExtensions}\nWould you like to overwrite them?`,
|
|
55
|
+
nonInteractive: options.nonInteractive,
|
|
56
|
+
force: options.force,
|
|
57
|
+
default: false,
|
|
58
|
+
}))) {
|
|
59
|
+
return;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
config.set("extensions", {});
|
|
63
|
+
}
|
|
64
|
+
exports.writeEmptyManifest = writeEmptyManifest;
|
|
44
65
|
async function writeLocalSecrets(specs, config, force) {
|
|
45
66
|
for (const spec of specs) {
|
|
46
67
|
const extensionSpec = await (0, planner_1.getExtensionSpec)(spec);
|
|
@@ -133,6 +154,7 @@ function writeExtensionsToFirebaseJson(specs, config) {
|
|
|
133
154
|
config.writeProjectFile("firebase.json", config.src);
|
|
134
155
|
utils.logSuccess("Wrote extensions to " + clc.bold("firebase.json") + "...");
|
|
135
156
|
}
|
|
157
|
+
exports.writeExtensionsToFirebaseJson = writeExtensionsToFirebaseJson;
|
|
136
158
|
async function writeEnvFiles(specs, config, force) {
|
|
137
159
|
for (const spec of specs) {
|
|
138
160
|
const content = Object.entries(spec.params)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.compareFieldOverride = exports.compareApiField = exports.compareApiIndex = exports.compareSpecIndex = void 0;
|
|
4
|
-
const API = require("./
|
|
3
|
+
exports.compareFieldOverride = exports.compareApiField = exports.compareLocation = exports.compareApiDatabase = exports.compareApiIndex = exports.compareSpecIndex = void 0;
|
|
4
|
+
const API = require("./api-types");
|
|
5
5
|
const util = require("./util");
|
|
6
6
|
const QUERY_SCOPE_SEQUENCE = [
|
|
7
7
|
API.QueryScope.COLLECTION_GROUP,
|
|
@@ -34,6 +34,14 @@ function compareApiIndex(a, b) {
|
|
|
34
34
|
return compareArrays(a.fields, b.fields, compareIndexField);
|
|
35
35
|
}
|
|
36
36
|
exports.compareApiIndex = compareApiIndex;
|
|
37
|
+
function compareApiDatabase(a, b) {
|
|
38
|
+
return a.name > b.name ? 1 : -1;
|
|
39
|
+
}
|
|
40
|
+
exports.compareApiDatabase = compareApiDatabase;
|
|
41
|
+
function compareLocation(a, b) {
|
|
42
|
+
return a.locationId > b.locationId ? 1 : -1;
|
|
43
|
+
}
|
|
44
|
+
exports.compareLocation = compareLocation;
|
|
37
45
|
function compareApiField(a, b) {
|
|
38
46
|
const aName = util.parseFieldName(a.name);
|
|
39
47
|
const bName = util.parseFieldName(b.name);
|