firebase-tools 13.14.1 → 13.15.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/bin/firebase.js +7 -5
- package/lib/commands/deploy.js +7 -1
- package/lib/commands/ext-configure.js +1 -6
- package/lib/commands/ext-dev-init.js +2 -4
- package/lib/commands/ext-dev-upload.js +4 -6
- package/lib/commands/ext-info.js +3 -5
- package/lib/commands/ext-install.js +0 -5
- package/lib/commands/ext-uninstall.js +0 -5
- package/lib/commands/ext-update.js +0 -5
- package/lib/commands/firestore-databases-create.js +19 -1
- package/lib/commands/functions-secrets-set.js +9 -6
- package/lib/commands/hosting-channel-create.js +1 -1
- package/lib/commands/hosting-channel-delete.js +1 -1
- package/lib/commands/hosting-channel-deploy.js +1 -1
- package/lib/commands/hosting-clone.js +1 -2
- package/lib/commands/init.js +14 -12
- package/lib/dataconnect/fileUtils.js +22 -1
- package/lib/dataconnect/types.js +8 -1
- package/lib/emulator/dataconnectEmulator.js +5 -2
- package/lib/emulator/downloadableEmulators.js +11 -12
- package/lib/extensions/askUserForParam.js +1 -1
- package/lib/extensions/change-log.js +2 -4
- package/lib/extensions/displayExtensionInfo.js +0 -5
- package/lib/extensions/extensionsHelper.js +5 -7
- package/lib/extensions/provisioningHelper.js +1 -1
- package/lib/extensions/updateHelper.js +1 -2
- package/lib/extensions/warnings.js +2 -7
- package/lib/firestore/api.js +8 -7
- package/lib/firestore/pretty-print.js +21 -1
- package/lib/firestore/pretty-print.test.js +8 -0
- package/lib/init/features/dataconnect/index.js +19 -8
- package/lib/init/features/dataconnect/sdk.js +46 -37
- package/lib/rulesDeploy.js +14 -12
- package/package.json +3 -3
- package/lib/extensions/billingMigrationHelper.js +0 -61
package/lib/bin/firebase.js
CHANGED
|
@@ -10,12 +10,10 @@ if (!semver.satisfies(nodeVersion, pkg.engines.node)) {
|
|
|
10
10
|
}
|
|
11
11
|
const updateNotifierPkg = require("update-notifier-cjs");
|
|
12
12
|
const clc = require("colorette");
|
|
13
|
-
const
|
|
13
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
14
14
|
const updateNotifier = updateNotifierPkg({ pkg });
|
|
15
15
|
const marked_1 = require("marked");
|
|
16
|
-
marked_1.marked.
|
|
17
|
-
renderer: new TerminalRenderer(),
|
|
18
|
-
});
|
|
16
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
19
17
|
const node_path_1 = require("node:path");
|
|
20
18
|
const triple_beam_1 = require("triple-beam");
|
|
21
19
|
const stripAnsi = require("strip-ansi");
|
|
@@ -105,8 +103,12 @@ process.on("exit", (code) => {
|
|
|
105
103
|
configstore_1.configstore.delete("lastError");
|
|
106
104
|
}
|
|
107
105
|
try {
|
|
106
|
+
const installMethod = !process.env.FIREPIT_VERSION ? "npm" : "automatic script";
|
|
107
|
+
const updateCommand = !process.env.FIREPIT_VERSION
|
|
108
|
+
? "npm install -g firebase-tools"
|
|
109
|
+
: "curl -sL https://firebase.tools | upgrade=true bash";
|
|
108
110
|
const updateMessage = `Update available ${clc.gray("{currentVersion}")} → ${clc.green("{latestVersion}")}\n` +
|
|
109
|
-
`To update to the latest version using
|
|
111
|
+
`To update to the latest version using ${installMethod}, run\n${clc.cyan(updateCommand)}\n` +
|
|
110
112
|
`For other CLI management options, visit the ${(0, marked_1.marked)("[CLI documentation](https://firebase.google.com/docs/cli#update-cli)")}`;
|
|
111
113
|
updateNotifier.notify({ defer: false, isGlobal: true, message: updateMessage });
|
|
112
114
|
}
|
package/lib/commands/deploy.js
CHANGED
|
@@ -107,7 +107,13 @@ exports.command = new command_1.Command("deploy")
|
|
|
107
107
|
await (0, requireHostingSite_1.requireHostingSite)(options);
|
|
108
108
|
}
|
|
109
109
|
catch (err) {
|
|
110
|
-
|
|
110
|
+
const isPermissionError = err instanceof error_1.FirebaseError &&
|
|
111
|
+
err.original instanceof error_1.FirebaseError &&
|
|
112
|
+
err.original.status === 403;
|
|
113
|
+
if (isPermissionError) {
|
|
114
|
+
throw err;
|
|
115
|
+
}
|
|
116
|
+
else if (err === getDefaultHostingSite_1.errNoDefaultSite) {
|
|
111
117
|
createSite = true;
|
|
112
118
|
}
|
|
113
119
|
}
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
|
-
const marked_1 = require("marked");
|
|
5
|
-
const TerminalRenderer = require("marked-terminal");
|
|
6
4
|
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
|
|
7
5
|
const command_1 = require("../command");
|
|
8
6
|
const error_1 = require("../error");
|
|
@@ -19,9 +17,6 @@ const functional_1 = require("../functional");
|
|
|
19
17
|
const paramHelper_1 = require("../extensions/paramHelper");
|
|
20
18
|
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
21
19
|
const tos_1 = require("../extensions/tos");
|
|
22
|
-
marked_1.marked.setOptions({
|
|
23
|
-
renderer: new TerminalRenderer(),
|
|
24
|
-
});
|
|
25
20
|
exports.command = new command_1.Command("ext:configure <extensionInstanceId>")
|
|
26
21
|
.description("configure an existing extension instance")
|
|
27
22
|
.withForce()
|
|
@@ -99,7 +94,7 @@ function infoImmutableParams(immutableParams, paramValues) {
|
|
|
99
94
|
return;
|
|
100
95
|
}
|
|
101
96
|
const plural = immutableParams.length > 1;
|
|
102
|
-
utils.logLabeledWarning(extensionsHelper_1.logPrefix,
|
|
97
|
+
utils.logLabeledWarning(extensionsHelper_1.logPrefix, `The following param${plural ? "s are" : " is"} immutable and won't be changed:`);
|
|
103
98
|
for (const { param } of immutableParams) {
|
|
104
99
|
logger_1.logger.info(`param: ${param}, value: ${paramValues[param]}`);
|
|
105
100
|
}
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
4
|
const marked_1 = require("marked");
|
|
5
|
-
const
|
|
5
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
6
6
|
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
|
|
7
7
|
const command_1 = require("../command");
|
|
8
8
|
const config_1 = require("../config");
|
|
@@ -11,9 +11,7 @@ const prompt_1 = require("../prompt");
|
|
|
11
11
|
const logger_1 = require("../logger");
|
|
12
12
|
const npmDependencies = require("../init/features/functions/npm-dependencies");
|
|
13
13
|
const templates_1 = require("../templates");
|
|
14
|
-
marked_1.marked.
|
|
15
|
-
renderer: new TerminalRenderer(),
|
|
16
|
-
});
|
|
14
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
17
15
|
function readCommonTemplates() {
|
|
18
16
|
return {
|
|
19
17
|
integrationTestFirebaseJsonTemplate: (0, templates_1.readTemplateSync)("extensions/integration-test.json"),
|
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.uploadExtensionAction = exports.command = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const marked_1 = require("marked");
|
|
6
|
-
const
|
|
6
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
7
7
|
const command_1 = require("../command");
|
|
8
8
|
const extensionsHelper_1 = require("../extensions/extensionsHelper");
|
|
9
9
|
const refs = require("../extensions/refs");
|
|
@@ -16,9 +16,7 @@ const utils = require("../utils");
|
|
|
16
16
|
const publisherApi_1 = require("../extensions/publisherApi");
|
|
17
17
|
const extensionsHelper_2 = require("../extensions/extensionsHelper");
|
|
18
18
|
const projects_1 = require("../management/projects");
|
|
19
|
-
marked_1.marked.
|
|
20
|
-
renderer: new TerminalRenderer(),
|
|
21
|
-
});
|
|
19
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
22
20
|
exports.command = new command_1.Command("ext:dev:upload <extensionRef>")
|
|
23
21
|
.description(`upload a new version of an extension`)
|
|
24
22
|
.option(`-s, --stage <stage>`, `release stage (supports "alpha", "beta", "rc", and "stable")`)
|
|
@@ -79,9 +77,9 @@ async function uploadExtensionAction(extensionRef, options) {
|
|
|
79
77
|
});
|
|
80
78
|
}
|
|
81
79
|
if (res) {
|
|
82
|
-
utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
|
|
80
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, await (0, marked_1.marked)(`[Install Link](${(0, publishHelpers_1.consoleInstallLink)(res.ref)})`));
|
|
83
81
|
const version = res.ref.split("@")[1];
|
|
84
|
-
utils.logLabeledBullet(extensionsHelper_1.logPrefix, (0, marked_1.marked)(`[View in Console](${utils.consoleUrl(projectId, `/publisher/extensions/${extensionId}/v/${version}`)})`));
|
|
82
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, await (0, marked_1.marked)(`[View in Console](${utils.consoleUrl(projectId, `/publisher/extensions/${extensionId}/v/${version}`)})`));
|
|
85
83
|
}
|
|
86
84
|
return res;
|
|
87
85
|
}
|
package/lib/commands/ext-info.js
CHANGED
|
@@ -11,7 +11,7 @@ const logger_1 = require("../logger");
|
|
|
11
11
|
const requirePermissions_1 = require("../requirePermissions");
|
|
12
12
|
const utils = require("../utils");
|
|
13
13
|
const marked_1 = require("marked");
|
|
14
|
-
const
|
|
14
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
15
15
|
const FUNCTION_TYPE_REGEX = /\..+\.function/;
|
|
16
16
|
exports.command = new command_1.Command("ext:info <extensionName>")
|
|
17
17
|
.description("display information about an extension by name (extensionName@x.y.z for a specific version)")
|
|
@@ -108,10 +108,8 @@ exports.command = new command_1.Command("ext:info <extensionName>")
|
|
|
108
108
|
logger_1.logger.info(lines.join("\n\n"));
|
|
109
109
|
}
|
|
110
110
|
else {
|
|
111
|
-
marked_1.marked.
|
|
112
|
-
|
|
113
|
-
});
|
|
114
|
-
logger_1.logger.info((0, marked_1.marked)(lines.join("\n")));
|
|
111
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
112
|
+
logger_1.logger.info(await (0, marked_1.marked)(lines.join("\n")));
|
|
115
113
|
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `to install this extension, type ` +
|
|
116
114
|
clc.bold(`firebase ext:install ${extensionName} --project=YOUR_PROJECT`));
|
|
117
115
|
}
|
|
@@ -2,9 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
-
const marked_1 = require("marked");
|
|
6
5
|
const semver = require("semver");
|
|
7
|
-
const TerminalRenderer = require("marked-terminal");
|
|
8
6
|
const displayExtensionInfo_1 = require("../extensions/displayExtensionInfo");
|
|
9
7
|
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
10
8
|
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
|
|
@@ -25,9 +23,6 @@ const track_1 = require("../track");
|
|
|
25
23
|
const prompt_1 = require("../prompt");
|
|
26
24
|
const manifest = require("../extensions/manifest");
|
|
27
25
|
const tos_1 = require("../extensions/tos");
|
|
28
|
-
marked_1.marked.setOptions({
|
|
29
|
-
renderer: new TerminalRenderer(),
|
|
30
|
-
});
|
|
31
26
|
exports.command = new command_1.Command("ext:install [extensionRef]")
|
|
32
27
|
.description("add an uploaded extension to firebase.json if [publisherId/extensionId] is provided;" +
|
|
33
28
|
"or, add a local extension if [localPath] is provided")
|
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
|
-
const marked_1 = require("marked");
|
|
5
|
-
const TerminalRenderer = require("marked-terminal");
|
|
6
4
|
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
|
|
7
5
|
const command_1 = require("../command");
|
|
8
6
|
const extensionsHelper_1 = require("../extensions/extensionsHelper");
|
|
9
7
|
const requirePermissions_1 = require("../requirePermissions");
|
|
10
8
|
const utils_1 = require("../utils");
|
|
11
9
|
const manifest = require("../extensions/manifest");
|
|
12
|
-
marked_1.marked.setOptions({
|
|
13
|
-
renderer: new TerminalRenderer(),
|
|
14
|
-
});
|
|
15
10
|
exports.command = new command_1.Command("ext:uninstall <extensionInstanceId>")
|
|
16
11
|
.description("uninstall an extension that is installed in your Firebase project by instance ID")
|
|
17
12
|
.option("--local", "deprecated")
|
|
@@ -2,8 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.command = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
-
const marked_1 = require("marked");
|
|
6
|
-
const TerminalRenderer = require("marked-terminal");
|
|
7
5
|
const checkMinRequiredVersion_1 = require("../checkMinRequiredVersion");
|
|
8
6
|
const command_1 = require("../command");
|
|
9
7
|
const error_1 = require("../error");
|
|
@@ -20,9 +18,6 @@ const prompt_1 = require("../prompt");
|
|
|
20
18
|
const manifest = require("../extensions/manifest");
|
|
21
19
|
const askUserForEventsConfig = require("../extensions/askUserForEventsConfig");
|
|
22
20
|
const tos_1 = require("../extensions/tos");
|
|
23
|
-
marked_1.marked.setOptions({
|
|
24
|
-
renderer: new TerminalRenderer(),
|
|
25
|
-
});
|
|
26
21
|
exports.command = new command_1.Command("ext:update <extensionInstanceId> [updateSource]")
|
|
27
22
|
.description("update an existing extension instance to the latest version, or to a specific version if provided")
|
|
28
23
|
.before(requirePermissions_1.requirePermissions, [
|
|
@@ -16,6 +16,9 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
|
|
|
16
16
|
.option("--location <locationId>", "Region to create database, for example 'nam5'. Run 'firebase firestore:locations' to get a list of eligible locations. (required)")
|
|
17
17
|
.option("--delete-protection <deleteProtectionState>", "Whether or not to prevent deletion of database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
|
|
18
18
|
.option("--point-in-time-recovery <enablement>", "Whether to enable the PITR feature on this database, for example 'ENABLED' or 'DISABLED'. Default is 'DISABLED'")
|
|
19
|
+
.option("-k, --kms-key-name <kmsKeyName>", "The resource ID of a Cloud KMS key. If set, the database created will be a " +
|
|
20
|
+
"Customer-managed Encryption Key (CMEK) database encrypted with this key. " +
|
|
21
|
+
"This feature is allowlist only in initial launch.")
|
|
19
22
|
.before(requirePermissions_1.requirePermissions, ["datastore.databases.create"])
|
|
20
23
|
.before(commandUtils_1.warnEmulatorNotSupported, types_1.Emulators.FIRESTORE)
|
|
21
24
|
.action(async (database, options) => {
|
|
@@ -42,7 +45,22 @@ exports.command = new command_1.Command("firestore:databases:create <database>")
|
|
|
42
45
|
const pointInTimeRecoveryEnablement = options.pointInTimeRecovery === types.PointInTimeRecoveryEnablementOption.ENABLED
|
|
43
46
|
? types.PointInTimeRecoveryEnablement.ENABLED
|
|
44
47
|
: types.PointInTimeRecoveryEnablement.DISABLED;
|
|
45
|
-
|
|
48
|
+
let cmekConfig;
|
|
49
|
+
if (options.kmsKeyName) {
|
|
50
|
+
cmekConfig = {
|
|
51
|
+
kmsKeyName: options.kmsKeyName,
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
const createDatabaseReq = {
|
|
55
|
+
project: options.project,
|
|
56
|
+
databaseId: database,
|
|
57
|
+
locationId: options.location,
|
|
58
|
+
type,
|
|
59
|
+
deleteProtectionState,
|
|
60
|
+
pointInTimeRecoveryEnablement,
|
|
61
|
+
cmekConfig,
|
|
62
|
+
};
|
|
63
|
+
const databaseResp = await api.createDatabase(createDatabaseReq);
|
|
46
64
|
if (options.json) {
|
|
47
65
|
logger_1.logger.info(JSON.stringify(databaseResp, undefined, 2));
|
|
48
66
|
}
|
|
@@ -54,12 +54,15 @@ exports.command = new command_1.Command("functions:secrets:set <KEY>")
|
|
|
54
54
|
(0, utils_1.logBullet)(`${endpointsToUpdate.length} functions are using stale version of secret ${secret.name}:\n\t` +
|
|
55
55
|
endpointsToUpdate.map((e) => `${e.id}(${e.region})`).join("\n\t"));
|
|
56
56
|
if (!options.force) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
57
|
+
let confirm = false;
|
|
58
|
+
if (!options.nonInteractive) {
|
|
59
|
+
confirm = await (0, prompt_1.promptOnce)({
|
|
60
|
+
name: "redeploy",
|
|
61
|
+
type: "confirm",
|
|
62
|
+
default: true,
|
|
63
|
+
message: `Do you want to re-deploy the functions and destroy the stale version of secret ${secret.name}?`,
|
|
64
|
+
}, options);
|
|
65
|
+
}
|
|
63
66
|
if (!confirm) {
|
|
64
67
|
(0, utils_1.logBullet)("Please deploy your functions for the change to take effect by running:\n\t" +
|
|
65
68
|
clc.bold("firebase deploy --only functions"));
|
|
@@ -65,7 +65,7 @@ exports.command = new command_1.Command("hosting:channel:create [channelId]")
|
|
|
65
65
|
await (0, api_1.addAuthDomains)(projectId, [channel.url]);
|
|
66
66
|
}
|
|
67
67
|
catch (e) {
|
|
68
|
-
(0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
68
|
+
(0, utils_1.logLabeledWarning)(LOG_TAG, await (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
69
69
|
logger_1.logger.debug("[hosting] unable to add auth domain", e);
|
|
70
70
|
}
|
|
71
71
|
logger_1.logger.info();
|
|
@@ -39,7 +39,7 @@ exports.command = new command_1.Command("hosting:channel:delete <channelId>")
|
|
|
39
39
|
await (0, api_1.removeAuthDomain)(projectId, channel.url);
|
|
40
40
|
}
|
|
41
41
|
catch (e) {
|
|
42
|
-
(0, utils_1.logLabeledWarning)("hosting:channel", (0, marked_1.marked)(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
42
|
+
(0, utils_1.logLabeledWarning)("hosting:channel", await (0, marked_1.marked)(`Unable to remove channel domain from Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
43
43
|
logger_1.logger.debug("[hosting] unable to remove auth domain", e);
|
|
44
44
|
}
|
|
45
45
|
}
|
|
@@ -133,7 +133,7 @@ async function syncAuthState(projectId, sites) {
|
|
|
133
133
|
logger_1.logger.debug("[hosting] added auth domain for urls", urlNames);
|
|
134
134
|
}
|
|
135
135
|
catch (e) {
|
|
136
|
-
(0, utils_1.logLabeledWarning)(LOG_TAG, (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
136
|
+
(0, utils_1.logLabeledWarning)(LOG_TAG, await (0, marked_1.marked)(`Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${(0, utils_1.consoleUrl)(projectId, "/authentication/providers")}`));
|
|
137
137
|
logger_1.logger.debug("[hosting] unable to add auth domain", e);
|
|
138
138
|
}
|
|
139
139
|
try {
|
|
@@ -8,7 +8,6 @@ const error_1 = require("../error");
|
|
|
8
8
|
const api_1 = require("../hosting/api");
|
|
9
9
|
const utils = require("../utils");
|
|
10
10
|
const requireAuth_1 = require("../requireAuth");
|
|
11
|
-
const marked_1 = require("marked");
|
|
12
11
|
const logger_1 = require("../logger");
|
|
13
12
|
exports.command = new command_1.Command("hosting:clone <source> <targetChannel>")
|
|
14
13
|
.description("clone a version from one site to another")
|
|
@@ -68,7 +67,7 @@ For example, to copy the content for a site \`my-site\` from a preview channel \
|
|
|
68
67
|
await (0, api_1.addAuthDomains)(tProjectId, [tChannel.url]);
|
|
69
68
|
}
|
|
70
69
|
catch (e) {
|
|
71
|
-
utils.logLabeledWarning("hosting:clone",
|
|
70
|
+
utils.logLabeledWarning("hosting:clone", `Unable to add channel domain to Firebase Auth. Visit the Firebase Console at ${utils.consoleUrl(targetSiteId, "/authentication/providers")}`);
|
|
72
71
|
logger_1.logger.debug("[hosting] unable to add auth domain", e);
|
|
73
72
|
}
|
|
74
73
|
}
|
package/lib/commands/init.js
CHANGED
|
@@ -44,8 +44,9 @@ const choices = [
|
|
|
44
44
|
},
|
|
45
45
|
{
|
|
46
46
|
value: "hosting:github",
|
|
47
|
-
name: "
|
|
47
|
+
name: "Hosting: Set up GitHub Action deploys",
|
|
48
48
|
checked: false,
|
|
49
|
+
hidden: true,
|
|
49
50
|
},
|
|
50
51
|
{
|
|
51
52
|
value: "storage",
|
|
@@ -67,6 +68,17 @@ const choices = [
|
|
|
67
68
|
name: "Extensions: Set up an empty Extensions manifest",
|
|
68
69
|
checked: false,
|
|
69
70
|
},
|
|
71
|
+
{
|
|
72
|
+
value: "dataconnect",
|
|
73
|
+
name: "Data Connect: Set up a Firebase Data Connect service",
|
|
74
|
+
checked: false,
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
value: "dataconnect:sdk",
|
|
78
|
+
name: "Data Connect: Set up a generated SDK for your Firebase Data Connect service",
|
|
79
|
+
checked: false,
|
|
80
|
+
hidden: true,
|
|
81
|
+
},
|
|
70
82
|
];
|
|
71
83
|
if ((0, experiments_1.isEnabled)("genkit")) {
|
|
72
84
|
choices.push({
|
|
@@ -75,16 +87,6 @@ if ((0, experiments_1.isEnabled)("genkit")) {
|
|
|
75
87
|
checked: false,
|
|
76
88
|
});
|
|
77
89
|
}
|
|
78
|
-
choices.push({
|
|
79
|
-
value: "dataconnect",
|
|
80
|
-
name: "Data Connect: Set up a Firebase Data Connect service",
|
|
81
|
-
checked: false,
|
|
82
|
-
});
|
|
83
|
-
choices.push({
|
|
84
|
-
value: "dataconnect:sdk",
|
|
85
|
-
name: " └── Data Connect: Set up a generated SDK for your Firebase Data Connect service",
|
|
86
|
-
checked: false,
|
|
87
|
-
});
|
|
88
90
|
const featureNames = choices.map((choice) => choice.value);
|
|
89
91
|
const DESCRIPTION = `Interactively configure the current directory as a Firebase project or initialize new features in an already configured Firebase project directory.
|
|
90
92
|
|
|
@@ -165,7 +167,7 @@ function initAction(feature, options) {
|
|
|
165
167
|
name: "features",
|
|
166
168
|
message: "Which Firebase features do you want to set up for this directory? " +
|
|
167
169
|
"Press Space to select features, then Enter to confirm your choices.",
|
|
168
|
-
choices: choices,
|
|
170
|
+
choices: choices.filter((c) => !c.hidden),
|
|
169
171
|
},
|
|
170
172
|
]);
|
|
171
173
|
})
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.pickService = exports.readGQLFiles = exports.readConnectorYaml = exports.readDataConnectYaml = exports.readFirebaseJson = void 0;
|
|
3
|
+
exports.getPlatformFromFolder = exports.pickService = exports.readGQLFiles = exports.readConnectorYaml = exports.readDataConnectYaml = exports.readFirebaseJson = void 0;
|
|
4
4
|
const fs = require("fs-extra");
|
|
5
5
|
const path = require("path");
|
|
6
6
|
const error_1 = require("../error");
|
|
7
|
+
const types_1 = require("./types");
|
|
7
8
|
const utils_1 = require("../utils");
|
|
8
9
|
const load_1 = require("./load");
|
|
9
10
|
function readFirebaseJson(config) {
|
|
@@ -92,3 +93,23 @@ async function pickService(projectId, config, serviceId) {
|
|
|
92
93
|
return serviceInfo;
|
|
93
94
|
}
|
|
94
95
|
exports.pickService = pickService;
|
|
96
|
+
const WEB_INDICATORS = ["package.json", "package-lock.json", "node_modules"];
|
|
97
|
+
const IOS_INDICATORS = ["info.plist", "podfile", "package.swift"];
|
|
98
|
+
const ANDROID_INDICATORS = ["androidmanifest.xml", "build.gradle"];
|
|
99
|
+
const IOS_INDICATORS_2 = [".xcworkspace", ".xcodeproj"];
|
|
100
|
+
async function getPlatformFromFolder(dirPath) {
|
|
101
|
+
const fileNames = await fs.readdir(dirPath);
|
|
102
|
+
for (const fileName of fileNames) {
|
|
103
|
+
const cleanedFileName = fileName.toLowerCase();
|
|
104
|
+
if (WEB_INDICATORS.some((indicator) => indicator === cleanedFileName))
|
|
105
|
+
return types_1.Platform.WEB;
|
|
106
|
+
if (ANDROID_INDICATORS.some((indicator) => indicator === cleanedFileName))
|
|
107
|
+
return types_1.Platform.ANDROID;
|
|
108
|
+
if (IOS_INDICATORS.some((indicator) => indicator === cleanedFileName))
|
|
109
|
+
return types_1.Platform.IOS;
|
|
110
|
+
if (IOS_INDICATORS_2.some((indicator) => cleanedFileName.endsWith(indicator)))
|
|
111
|
+
return types_1.Platform.IOS;
|
|
112
|
+
}
|
|
113
|
+
return types_1.Platform.UNDETERMINED;
|
|
114
|
+
}
|
|
115
|
+
exports.getPlatformFromFolder = getPlatformFromFolder;
|
package/lib/dataconnect/types.js
CHANGED
|
@@ -1,12 +1,19 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.toDatasource = exports.requiresVector = exports.SCHEMA_ID = void 0;
|
|
3
|
+
exports.toDatasource = exports.Platform = exports.requiresVector = exports.SCHEMA_ID = void 0;
|
|
4
4
|
exports.SCHEMA_ID = "main";
|
|
5
5
|
function requiresVector(dm) {
|
|
6
6
|
var _a, _b, _c, _d;
|
|
7
7
|
return (_d = (_c = (_b = (_a = dm === null || dm === void 0 ? void 0 : dm.primaryDataSource) === null || _a === void 0 ? void 0 : _a.postgres) === null || _b === void 0 ? void 0 : _b.requiredExtensions) === null || _c === void 0 ? void 0 : _c.includes("vector")) !== null && _d !== void 0 ? _d : false;
|
|
8
8
|
}
|
|
9
9
|
exports.requiresVector = requiresVector;
|
|
10
|
+
var Platform;
|
|
11
|
+
(function (Platform) {
|
|
12
|
+
Platform["ANDROID"] = "ANDROID";
|
|
13
|
+
Platform["WEB"] = "WEB";
|
|
14
|
+
Platform["IOS"] = "IOS";
|
|
15
|
+
Platform["UNDETERMINED"] = "UNDETERMINED";
|
|
16
|
+
})(Platform = exports.Platform || (exports.Platform = {}));
|
|
10
17
|
function toDatasource(projectId, locationId, ds) {
|
|
11
18
|
if (ds.postgresql) {
|
|
12
19
|
return {
|
|
@@ -26,8 +26,9 @@ class DataConnectEmulator {
|
|
|
26
26
|
this.emulatorClient = new DataConnectEmulatorClient();
|
|
27
27
|
}
|
|
28
28
|
async start() {
|
|
29
|
+
let resolvedConfigDir;
|
|
29
30
|
try {
|
|
30
|
-
|
|
31
|
+
resolvedConfigDir = this.args.config.path(this.args.configDir);
|
|
31
32
|
const info = await DataConnectEmulator.build({ configDir: resolvedConfigDir });
|
|
32
33
|
if ((0, types_2.requiresVector)(info.metadata)) {
|
|
33
34
|
if (constants_1.Constants.isDemoProject(this.args.projectId)) {
|
|
@@ -51,7 +52,9 @@ class DataConnectEmulator {
|
|
|
51
52
|
await (0, downloadableEmulators_1.start)(types_1.Emulators.DATACONNECT, {
|
|
52
53
|
auto_download: this.args.auto_download,
|
|
53
54
|
listen: (0, portUtils_1.listenSpecsToString)(this.args.listen),
|
|
54
|
-
config_dir:
|
|
55
|
+
config_dir: resolvedConfigDir,
|
|
56
|
+
enable_output_schema_extensions: true,
|
|
57
|
+
enable_output_generated_sdk: true,
|
|
55
58
|
});
|
|
56
59
|
this.usingExistingEmulator = false;
|
|
57
60
|
}
|
|
@@ -46,20 +46,20 @@ const EMULATOR_UPDATE_DETAILS = {
|
|
|
46
46
|
},
|
|
47
47
|
dataconnect: process.platform === "darwin"
|
|
48
48
|
? {
|
|
49
|
-
version: "1.3.
|
|
50
|
-
expectedSize:
|
|
51
|
-
expectedChecksum: "
|
|
49
|
+
version: "1.3.2",
|
|
50
|
+
expectedSize: 24195840,
|
|
51
|
+
expectedChecksum: "b60f4501c657bec4dc8df3f3ec7ab3fd",
|
|
52
52
|
}
|
|
53
53
|
: process.platform === "win32"
|
|
54
54
|
? {
|
|
55
|
-
version: "1.3.
|
|
56
|
-
expectedSize:
|
|
57
|
-
expectedChecksum: "
|
|
55
|
+
version: "1.3.2",
|
|
56
|
+
expectedSize: 24610304,
|
|
57
|
+
expectedChecksum: "37d5e08f4df5e07b41160b8f2fd90135",
|
|
58
58
|
}
|
|
59
59
|
: {
|
|
60
|
-
version: "1.3.
|
|
61
|
-
expectedSize:
|
|
62
|
-
expectedChecksum: "
|
|
60
|
+
version: "1.3.2",
|
|
61
|
+
expectedSize: 24109208,
|
|
62
|
+
expectedChecksum: "52b09c69bc9a3a84b01a3a7311817229",
|
|
63
63
|
},
|
|
64
64
|
};
|
|
65
65
|
exports.DownloadDetails = {
|
|
@@ -243,9 +243,8 @@ const Commands = {
|
|
|
243
243
|
optionalArgs: [
|
|
244
244
|
"listen",
|
|
245
245
|
"config_dir",
|
|
246
|
-
"
|
|
247
|
-
"
|
|
248
|
-
"rpc_retry_count",
|
|
246
|
+
"enable_output_schema_extensions",
|
|
247
|
+
"enable_output_generated_sdk",
|
|
249
248
|
],
|
|
250
249
|
joinArgs: true,
|
|
251
250
|
shell: false,
|
|
@@ -122,7 +122,7 @@ async function askForParam(args) {
|
|
|
122
122
|
let secretLocations = [];
|
|
123
123
|
const description = paramSpec.description || "";
|
|
124
124
|
const label = paramSpec.label.trim();
|
|
125
|
-
logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(0, marked_1.marked)(description).trim()}`);
|
|
125
|
+
logger_1.logger.info(`\n${clc.bold(label)}${clc.bold(paramSpec.required ? "" : " (Optional)")}: ${(await (0, marked_1.marked)(description)).trim()}`);
|
|
126
126
|
while (!valid) {
|
|
127
127
|
switch (paramSpec.type) {
|
|
128
128
|
case types_1.ParamType.SELECT:
|
|
@@ -5,16 +5,14 @@ const clc = require("colorette");
|
|
|
5
5
|
const marked_1 = require("marked");
|
|
6
6
|
const path = require("path");
|
|
7
7
|
const semver = require("semver");
|
|
8
|
-
const
|
|
8
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
9
9
|
const Table = require("cli-table");
|
|
10
10
|
const extensionsApi_1 = require("./extensionsApi");
|
|
11
11
|
const localHelper_1 = require("./localHelper");
|
|
12
12
|
const logger_1 = require("../logger");
|
|
13
13
|
const refs = require("./refs");
|
|
14
14
|
const utils_1 = require("../utils");
|
|
15
|
-
marked_1.marked.
|
|
16
|
-
renderer: new TerminalRenderer(),
|
|
17
|
-
});
|
|
15
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
18
16
|
const EXTENSIONS_CHANGELOG = "CHANGELOG.md";
|
|
19
17
|
const VERSION_LINE_REGEX = /##.+?(\d+\.\d+\.\d+(?:-((\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*)(?:\.(\d+|\d*[a-zA-Z-][0-9a-zA-Z-]*))*))?).*/;
|
|
20
18
|
async function getReleaseNotesForUpdate(args) {
|
|
@@ -2,18 +2,13 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.retrieveRoleInfo = exports.displayResources = exports.displayEvents = exports.displayExternalServices = exports.displayExtensionVersionInfo = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
-
const marked_1 = require("marked");
|
|
6
5
|
const semver = require("semver");
|
|
7
|
-
const TerminalRenderer = require("marked-terminal");
|
|
8
6
|
const path = require("path");
|
|
9
7
|
const refs = require("../extensions/refs");
|
|
10
8
|
const logger_1 = require("../logger");
|
|
11
9
|
const types_1 = require("./types");
|
|
12
10
|
const iam = require("../gcp/iam");
|
|
13
11
|
const secretsUtils_1 = require("./secretsUtils");
|
|
14
|
-
marked_1.marked.setOptions({
|
|
15
|
-
renderer: new TerminalRenderer(),
|
|
16
|
-
});
|
|
17
12
|
const TASKS_ROLE = "cloudtasks.enqueuer";
|
|
18
13
|
const TASKS_API = "cloudtasks.googleapis.com";
|
|
19
14
|
async function displayExtensionVersionInfo(args) {
|
|
@@ -9,11 +9,9 @@ const fs = require("fs-extra");
|
|
|
9
9
|
const node_fetch_1 = require("node-fetch");
|
|
10
10
|
const path = require("path");
|
|
11
11
|
const marked_1 = require("marked");
|
|
12
|
+
const marked_terminal_1 = require("marked-terminal");
|
|
12
13
|
const unzip_1 = require("./../unzip");
|
|
13
|
-
|
|
14
|
-
marked_1.marked.setOptions({
|
|
15
|
-
renderer: new TerminalRenderer(),
|
|
16
|
-
});
|
|
14
|
+
marked_1.marked.use((0, marked_terminal_1.markedTerminal)());
|
|
17
15
|
const api_1 = require("../api");
|
|
18
16
|
const archiveDirectory_1 = require("../archiveDirectory");
|
|
19
17
|
const utils_1 = require("./utils");
|
|
@@ -417,12 +415,12 @@ function validateReleaseNotes(rootDirectory, newVersion, extension) {
|
|
|
417
415
|
catch (err) {
|
|
418
416
|
throw new error_1.FirebaseError("No CHANGELOG.md file found. " +
|
|
419
417
|
"Please create one and add an entry for this version. " +
|
|
420
|
-
|
|
418
|
+
"See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
|
|
421
419
|
}
|
|
422
420
|
if (!notes && !semver.prerelease(newVersion) && extension) {
|
|
423
421
|
throw new error_1.FirebaseError(`No entry for version ${newVersion} found in CHANGELOG.md. ` +
|
|
424
422
|
"Please add one so users know what has changed in this version. " +
|
|
425
|
-
|
|
423
|
+
"See https://firebase.google.com/docs/extensions/publishers/user-documentation#writing-changelog for more details.");
|
|
426
424
|
}
|
|
427
425
|
return notes;
|
|
428
426
|
}
|
|
@@ -701,7 +699,7 @@ async function uploadExtensionVersionFromLocalSource(args) {
|
|
|
701
699
|
}
|
|
702
700
|
exports.uploadExtensionVersionFromLocalSource = uploadExtensionVersionFromLocalSource;
|
|
703
701
|
function getMissingPublisherError(publisherId) {
|
|
704
|
-
return new error_1.FirebaseError(
|
|
702
|
+
return new error_1.FirebaseError(`Couldn't find publisher ID '${clc.bold(publisherId)}'. Please ensure that you have registered this ID. For step-by-step instructions on getting started as a publisher, see https://firebase.google.com/docs/extensions/publishers/get-started.`);
|
|
705
703
|
}
|
|
706
704
|
exports.getMissingPublisherError = getMissingPublisherError;
|
|
707
705
|
async function createSourceFromLocation(projectId, sourceUri) {
|
|
@@ -64,7 +64,7 @@ async function checkProducts(projectId, usedProducts) {
|
|
|
64
64
|
"without server-side code.\n";
|
|
65
65
|
errorMessage += ` https://console.firebase.google.com/project/${projectId}/authentication/users`;
|
|
66
66
|
}
|
|
67
|
-
throw new error_1.FirebaseError((0, marked_1.marked)(errorMessage), { exit: 2 });
|
|
67
|
+
throw new error_1.FirebaseError(await (0, marked_1.marked)(errorMessage), { exit: 2 });
|
|
68
68
|
}
|
|
69
69
|
}
|
|
70
70
|
function getUsedProducts(spec) {
|
|
@@ -3,7 +3,6 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.inferUpdateSource = exports.updateFromUrlSource = exports.updateFromLocalSource = exports.update = exports.warningUpdateToOtherSource = exports.getExistingSourceOrigin = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const semver = require("semver");
|
|
6
|
-
const marked_1 = require("marked");
|
|
7
6
|
const error_1 = require("../error");
|
|
8
7
|
const logger_1 = require("../logger");
|
|
9
8
|
const extensionsApi = require("./extensionsApi");
|
|
@@ -47,7 +46,7 @@ function warningUpdateToOtherSource(sourceOrigin) {
|
|
|
47
46
|
targetText = "URL";
|
|
48
47
|
}
|
|
49
48
|
const warning = `All the instance's resources and logic will be overwritten to use the source code and files from the ${targetText}.\n`;
|
|
50
|
-
logger_1.logger.info(
|
|
49
|
+
logger_1.logger.info(warning);
|
|
51
50
|
}
|
|
52
51
|
exports.warningUpdateToOtherSource = warningUpdateToOtherSource;
|
|
53
52
|
async function update(updateOptions) {
|
|
@@ -2,11 +2,6 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.outOfBandChangesWarning = exports.displayWarningsForDeploy = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
|
-
const TerminalRenderer = require("marked-terminal");
|
|
6
|
-
const marked_1 = require("marked");
|
|
7
|
-
marked_1.marked.setOptions({
|
|
8
|
-
renderer: new TerminalRenderer(),
|
|
9
|
-
});
|
|
10
5
|
const extensionsHelper_1 = require("./extensionsHelper");
|
|
11
6
|
const deploymentSummary_1 = require("../deploy/extensions/deploymentSummary");
|
|
12
7
|
const planner_1 = require("../deploy/extensions/planner");
|
|
@@ -29,9 +24,9 @@ async function displayWarningsForDeploy(instancesToCreate) {
|
|
|
29
24
|
const unpublishedExtensions = uploadedExtensionInstances.filter((i) => { var _a, _b; return ((_b = (_a = i.extensionVersion) === null || _a === void 0 ? void 0 : _a.listing) === null || _b === void 0 ? void 0 : _b.state) !== "APPROVED"; });
|
|
30
25
|
if (unpublishedExtensions.length) {
|
|
31
26
|
const humanReadableList = unpublishedExtensions.map(toListEntry).join("\n");
|
|
32
|
-
utils.logLabeledBullet(extensionsHelper_1.logPrefix,
|
|
27
|
+
utils.logLabeledBullet(extensionsHelper_1.logPrefix, `The following extension versions have not been published to the Firebase Extensions Hub:\n${humanReadableList}\n.` +
|
|
33
28
|
"Unpublished extensions have not been reviewed by " +
|
|
34
|
-
"Firebase. Please make sure you trust the extension publisher before installing this extension."
|
|
29
|
+
"Firebase. Please make sure you trust the extension publisher before installing this extension.");
|
|
35
30
|
}
|
|
36
31
|
return unpublishedExtensions.length > 0;
|
|
37
32
|
}
|
package/lib/firestore/api.js
CHANGED
|
@@ -420,15 +420,16 @@ class FirestoreApi {
|
|
|
420
420
|
}
|
|
421
421
|
return database;
|
|
422
422
|
}
|
|
423
|
-
async createDatabase(
|
|
424
|
-
const url = `/projects/${project}/databases`;
|
|
423
|
+
async createDatabase(req) {
|
|
424
|
+
const url = `/projects/${req.project}/databases`;
|
|
425
425
|
const payload = {
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
deleteProtectionState,
|
|
429
|
-
pointInTimeRecoveryEnablement,
|
|
426
|
+
locationId: req.locationId,
|
|
427
|
+
type: req.type,
|
|
428
|
+
deleteProtectionState: req.deleteProtectionState,
|
|
429
|
+
pointInTimeRecoveryEnablement: req.pointInTimeRecoveryEnablement,
|
|
430
|
+
cmekConfig: req.cmekConfig,
|
|
430
431
|
};
|
|
431
|
-
const options = { queryParams: { databaseId: databaseId } };
|
|
432
|
+
const options = { queryParams: { databaseId: req.databaseId } };
|
|
432
433
|
const res = await this.apiClient.post(url, payload, options);
|
|
433
434
|
const database = res.body.response;
|
|
434
435
|
if (!database) {
|
|
@@ -33,13 +33,33 @@ class PrettyPrint {
|
|
|
33
33
|
logger_1.logger.info(table.toString());
|
|
34
34
|
}
|
|
35
35
|
prettyPrintDatabase(database) {
|
|
36
|
+
let colValueWidth = Math.max(50, 5 + database.name.length);
|
|
37
|
+
if (database.cmekConfig) {
|
|
38
|
+
colValueWidth = Math.max(140, 20 + database.cmekConfig.kmsKeyName.length);
|
|
39
|
+
}
|
|
36
40
|
const table = new Table({
|
|
37
41
|
head: ["Field", "Value"],
|
|
38
|
-
colWidths: [
|
|
42
|
+
colWidths: [30, colValueWidth],
|
|
39
43
|
});
|
|
40
44
|
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)]);
|
|
45
|
+
if (database.cmekConfig) {
|
|
46
|
+
table.push(["KMS Key Name", clc.yellow(database.cmekConfig.kmsKeyName)]);
|
|
47
|
+
if (database.cmekConfig.activeKeyVersion) {
|
|
48
|
+
table.push([
|
|
49
|
+
"Active Key Versions",
|
|
50
|
+
clc.yellow(this.prettyStringArray(database.cmekConfig.activeKeyVersion)),
|
|
51
|
+
]);
|
|
52
|
+
}
|
|
53
|
+
}
|
|
41
54
|
logger_1.logger.info(table.toString());
|
|
42
55
|
}
|
|
56
|
+
prettyStringArray(stringArray) {
|
|
57
|
+
let result = "";
|
|
58
|
+
stringArray.forEach((str) => {
|
|
59
|
+
result += `${str}\n`;
|
|
60
|
+
});
|
|
61
|
+
return result;
|
|
62
|
+
}
|
|
43
63
|
prettyPrintBackups(backups) {
|
|
44
64
|
if (backups.length === 0) {
|
|
45
65
|
logger_1.logger.info("No backups found.");
|
|
@@ -51,3 +51,11 @@ describe("firebaseConsoleDatabaseUrl", () => {
|
|
|
51
51
|
(0, chai_1.expect)(printer.firebaseConsoleDatabaseUrl("example-project", "(default)")).to.equal("https://console.firebase.google.com/project/example-project/firestore/databases/-default-/data");
|
|
52
52
|
});
|
|
53
53
|
});
|
|
54
|
+
describe("prettyStringArray", () => {
|
|
55
|
+
it("should correctly print an array of strings", () => {
|
|
56
|
+
(0, chai_1.expect)(printer.prettyStringArray(["kms-key-1", "kms-key-2"])).to.equal("kms-key-1\nkms-key-2\n");
|
|
57
|
+
});
|
|
58
|
+
it("should print nothing if the array is empty", () => {
|
|
59
|
+
(0, chai_1.expect)(printer.prettyStringArray([])).to.equal("");
|
|
60
|
+
});
|
|
61
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.doSetup = void 0;
|
|
3
|
+
exports.actuate = exports.doSetup = void 0;
|
|
4
4
|
const path_1 = require("path");
|
|
5
5
|
const clc = require("colorette");
|
|
6
6
|
const prompt_1 = require("../../../prompt");
|
|
@@ -20,7 +20,7 @@ const SCHEMA_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/sche
|
|
|
20
20
|
const QUERIES_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/queries.gql");
|
|
21
21
|
const MUTATIONS_TEMPLATE = (0, templates_1.readTemplateSync)("init/dataconnect/mutations.gql");
|
|
22
22
|
const defaultConnector = {
|
|
23
|
-
id: "default
|
|
23
|
+
id: "default",
|
|
24
24
|
files: [
|
|
25
25
|
{
|
|
26
26
|
path: "queries.gql",
|
|
@@ -33,6 +33,13 @@ const defaultConnector = {
|
|
|
33
33
|
],
|
|
34
34
|
};
|
|
35
35
|
async function doSetup(setup, config) {
|
|
36
|
+
const info = await askQuestions(setup, config);
|
|
37
|
+
await actuate(setup, config, info);
|
|
38
|
+
logger_1.logger.info("");
|
|
39
|
+
(0, utils_1.logSuccess)(`If you'd like to generate an SDK for your new connector, run ${clc.bold("firebase init dataconnect:sdk")}`);
|
|
40
|
+
}
|
|
41
|
+
exports.doSetup = doSetup;
|
|
42
|
+
async function askQuestions(setup, config) {
|
|
36
43
|
var _a, _b, _c;
|
|
37
44
|
let info = {
|
|
38
45
|
serviceId: "",
|
|
@@ -43,6 +50,7 @@ async function doSetup(setup, config) {
|
|
|
43
50
|
isNewDatabase: false,
|
|
44
51
|
connectors: [defaultConnector],
|
|
45
52
|
schemaGql: [],
|
|
53
|
+
shouldProvisionCSQL: false,
|
|
46
54
|
};
|
|
47
55
|
info = await promptForService(setup, info);
|
|
48
56
|
if (info.cloudSqlInstanceId === "") {
|
|
@@ -59,13 +67,17 @@ async function doSetup(setup, config) {
|
|
|
59
67
|
default: defaultConnectionString,
|
|
60
68
|
});
|
|
61
69
|
setup.rcfile.dataconnectEmulatorConfig = { postgres: { localConnectionString } };
|
|
62
|
-
|
|
63
|
-
if (setup.projectId &&
|
|
70
|
+
info.shouldProvisionCSQL = !!(setup.projectId &&
|
|
64
71
|
(info.isNewInstance || info.isNewDatabase) &&
|
|
65
72
|
(await (0, prompt_1.confirm)({
|
|
66
73
|
message: "Would you like to provision your CloudSQL instance and database now? This will take a few minutes.",
|
|
67
74
|
default: true,
|
|
68
|
-
})))
|
|
75
|
+
})));
|
|
76
|
+
return info;
|
|
77
|
+
}
|
|
78
|
+
async function actuate(setup, config, info) {
|
|
79
|
+
await writeFiles(config, info);
|
|
80
|
+
if (setup.projectId && info.shouldProvisionCSQL) {
|
|
69
81
|
await (0, provisionCloudSql_1.provisionCloudSql)({
|
|
70
82
|
projectId: setup.projectId,
|
|
71
83
|
locationId: info.locationId,
|
|
@@ -75,12 +87,11 @@ async function doSetup(setup, config) {
|
|
|
75
87
|
waitForCreation: false,
|
|
76
88
|
});
|
|
77
89
|
}
|
|
78
|
-
logger_1.logger.info("");
|
|
79
|
-
(0, utils_1.logSuccess)(`If you'd like to generate an SDK for your new connector, run ${clc.bold("firebase init dataconnect:sdk")}`);
|
|
80
90
|
}
|
|
81
|
-
exports.
|
|
91
|
+
exports.actuate = actuate;
|
|
82
92
|
async function writeFiles(config, info) {
|
|
83
93
|
const dir = config.get("dataconnect.source") || "dataconnect";
|
|
94
|
+
console.log(dir);
|
|
84
95
|
const subbedDataconnectYaml = subDataconnectYamlValues(Object.assign(Object.assign({}, info), { connectorIds: info.connectors.map((c) => `"./${c.id}"`).join(", ") }));
|
|
85
96
|
config.set("dataconnect", { source: dir });
|
|
86
97
|
await config.askWriteProjectFile((0, path_1.join)(dir, "dataconnect.yaml"), subbedDataconnectYaml);
|
|
@@ -1,18 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.doSetup = void 0;
|
|
3
|
+
exports.actuate = exports.doSetup = void 0;
|
|
4
4
|
const yaml = require("yaml");
|
|
5
|
-
const fs = require("fs
|
|
5
|
+
const fs = require("fs");
|
|
6
6
|
const clc = require("colorette");
|
|
7
7
|
const prompt_1 = require("../../../prompt");
|
|
8
8
|
const fileUtils_1 = require("../../../dataconnect/fileUtils");
|
|
9
9
|
const load_1 = require("../../../dataconnect/load");
|
|
10
10
|
const logger_1 = require("../../../logger");
|
|
11
11
|
const dataconnectEmulator_1 = require("../../../emulator/dataconnectEmulator");
|
|
12
|
+
const error_1 = require("../../../error");
|
|
13
|
+
const lodash_1 = require("lodash");
|
|
12
14
|
const IOS = "ios";
|
|
13
15
|
const WEB = "web";
|
|
14
16
|
const ANDROID = "android";
|
|
15
17
|
async function doSetup(setup, config) {
|
|
18
|
+
const sdkInfo = await askQuestions(setup, config);
|
|
19
|
+
await actuate(sdkInfo, setup.projectId);
|
|
20
|
+
}
|
|
21
|
+
exports.doSetup = doSetup;
|
|
22
|
+
async function askQuestions(setup, config) {
|
|
16
23
|
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
17
24
|
const serviceCfgs = (0, fileUtils_1.readFirebaseJson)(config);
|
|
18
25
|
const serviceInfos = await Promise.all(serviceCfgs.map((c) => (0, load_1.load)(setup.projectId || "", config, c.source)));
|
|
@@ -27,23 +34,28 @@ async function doSetup(setup, config) {
|
|
|
27
34
|
})
|
|
28
35
|
.flat();
|
|
29
36
|
if (!connectorChoices.length) {
|
|
30
|
-
|
|
31
|
-
return;
|
|
37
|
+
throw new error_1.FirebaseError(`Your config has no connectors to set up SDKs for. Run ${clc.bold("firebase init dataconnect")} to set up a service and conenctors.`);
|
|
32
38
|
}
|
|
33
39
|
const connectorInfo = await (0, prompt_1.promptOnce)({
|
|
34
40
|
message: "Which connector do you want set up a generated SDK for?",
|
|
35
41
|
type: "list",
|
|
36
42
|
choices: connectorChoices,
|
|
37
43
|
});
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
let platforms = [];
|
|
45
|
+
while (!platforms.length) {
|
|
46
|
+
platforms = await (0, prompt_1.promptOnce)({
|
|
47
|
+
message: "Which platforms do you want to set up a generated SDK for?",
|
|
48
|
+
type: "checkbox",
|
|
49
|
+
choices: [
|
|
50
|
+
{ name: "iOS (Swift)", value: IOS },
|
|
51
|
+
{ name: "Web (JavaScript)", value: WEB },
|
|
52
|
+
{ name: "Androd (Kotlin)", value: ANDROID },
|
|
53
|
+
],
|
|
54
|
+
});
|
|
55
|
+
if (!platforms.length) {
|
|
56
|
+
logger_1.logger.info("You must pick at least one platform.");
|
|
57
|
+
}
|
|
58
|
+
}
|
|
47
59
|
const newConnectorYaml = JSON.parse(JSON.stringify(connectorInfo.connectorYaml));
|
|
48
60
|
if (!newConnectorYaml.generate) {
|
|
49
61
|
newConnectorYaml.generate = {};
|
|
@@ -53,9 +65,10 @@ async function doSetup(setup, config) {
|
|
|
53
65
|
message: `What directory do you want to write your Swift SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
|
|
54
66
|
type: "input",
|
|
55
67
|
default: ((_a = newConnectorYaml.generate.swiftSdk) === null || _a === void 0 ? void 0 : _a.outputDir) ||
|
|
56
|
-
|
|
68
|
+
`./../gensdk/${newConnectorYaml.connectorId}/swift-sdk`,
|
|
57
69
|
});
|
|
58
|
-
const
|
|
70
|
+
const pkg = (0, lodash_1.camelCase)(newConnectorYaml.connectorId);
|
|
71
|
+
const swiftSdk = { outputDir, package: pkg };
|
|
59
72
|
newConnectorYaml.generate.swiftSdk = swiftSdk;
|
|
60
73
|
}
|
|
61
74
|
if (platforms.includes(WEB)) {
|
|
@@ -63,13 +76,9 @@ async function doSetup(setup, config) {
|
|
|
63
76
|
message: `What directory do you want to write your JavaScript SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
|
|
64
77
|
type: "input",
|
|
65
78
|
default: ((_b = newConnectorYaml.generate.javascriptSdk) === null || _b === void 0 ? void 0 : _b.outputDir) ||
|
|
66
|
-
|
|
67
|
-
});
|
|
68
|
-
const pkg = await (0, prompt_1.promptOnce)({
|
|
69
|
-
message: "What package name do you want to use for your JavaScript SDK?",
|
|
70
|
-
type: "input",
|
|
71
|
-
default: (_d = (_c = newConnectorYaml.generate.javascriptSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`,
|
|
79
|
+
`./../gensdk/${newConnectorYaml.connectorId}/javascript-sdk`,
|
|
72
80
|
});
|
|
81
|
+
const pkg = (_d = (_c = newConnectorYaml.generate.javascriptSdk) === null || _c === void 0 ? void 0 : _c.package) !== null && _d !== void 0 ? _d : `@firebasegen/${connectorInfo.connectorYaml.connectorId}`;
|
|
73
82
|
const packageJSONDir = await (0, prompt_1.promptOnce)({
|
|
74
83
|
message: "Which directory contains the package.json that you would like to add the JavaScript SDK dependency to? (Leave blank to skip)",
|
|
75
84
|
type: "input",
|
|
@@ -89,33 +98,33 @@ async function doSetup(setup, config) {
|
|
|
89
98
|
message: `What directory do you want to write your Kotlin SDK code to? (If not absolute, path will be relative to '${connectorInfo.directory}')`,
|
|
90
99
|
type: "input",
|
|
91
100
|
default: ((_f = newConnectorYaml.generate.kotlinSdk) === null || _f === void 0 ? void 0 : _f.outputDir) ||
|
|
92
|
-
|
|
93
|
-
});
|
|
94
|
-
const pkg = await (0, prompt_1.promptOnce)({
|
|
95
|
-
message: "What package name do you want to use for your Kotlin SDK?",
|
|
96
|
-
type: "input",
|
|
97
|
-
default: (_h = (_g = newConnectorYaml.generate.kotlinSdk) === null || _g === void 0 ? void 0 : _g.package) !== null && _h !== void 0 ? _h : `com.google.firebase.dataconnect.connectors.${connectorInfo.connectorYaml.connectorId}`,
|
|
101
|
+
`./../gensdk/${newConnectorYaml.connectorId}/kotlin-sdk`,
|
|
98
102
|
});
|
|
103
|
+
const pkg = (_h = (_g = newConnectorYaml.generate.kotlinSdk) === null || _g === void 0 ? void 0 : _g.package) !== null && _h !== void 0 ? _h : `connectors.${(0, lodash_1.snakeCase)(connectorInfo.connectorYaml.connectorId)}`;
|
|
99
104
|
const kotlinSdk = {
|
|
100
105
|
outputDir,
|
|
101
106
|
package: pkg,
|
|
102
107
|
};
|
|
103
108
|
newConnectorYaml.generate.kotlinSdk = kotlinSdk;
|
|
104
109
|
}
|
|
105
|
-
const
|
|
106
|
-
const connectorYamlPath = `${connectorInfo.directory}/connector.yaml`;
|
|
107
|
-
fs.writeFileSync(connectorYamlPath, connectorYamlContents, "utf8");
|
|
108
|
-
logger_1.logger.info(`Wrote new config to ${connectorYamlPath}`);
|
|
109
|
-
if (setup.projectId &&
|
|
110
|
+
const shouldGenerate = !!(setup.projectId &&
|
|
110
111
|
(await (0, prompt_1.confirm)({
|
|
111
112
|
message: "Would you like to generate SDK code now?",
|
|
112
113
|
default: true,
|
|
113
|
-
})))
|
|
114
|
+
})));
|
|
115
|
+
const connectorYamlContents = yaml.stringify(newConnectorYaml);
|
|
116
|
+
return { connectorYamlContents, connectorInfo, shouldGenerate };
|
|
117
|
+
}
|
|
118
|
+
async function actuate(sdkInfo, projectId) {
|
|
119
|
+
const connectorYamlPath = `${sdkInfo.connectorInfo.directory}/connector.yaml`;
|
|
120
|
+
fs.writeFileSync(connectorYamlPath, sdkInfo.connectorYamlContents, "utf8");
|
|
121
|
+
logger_1.logger.info(`Wrote new config to ${connectorYamlPath}`);
|
|
122
|
+
if (projectId && sdkInfo.shouldGenerate) {
|
|
114
123
|
await dataconnectEmulator_1.DataConnectEmulator.generate({
|
|
115
|
-
configDir: connectorInfo.directory,
|
|
116
|
-
connectorId: connectorInfo.connectorYaml.connectorId,
|
|
124
|
+
configDir: sdkInfo.connectorInfo.directory,
|
|
125
|
+
connectorId: sdkInfo.connectorInfo.connectorYaml.connectorId,
|
|
117
126
|
});
|
|
118
|
-
logger_1.logger.info(`Generated SDK code for ${connectorInfo.connectorYaml.connectorId}`);
|
|
127
|
+
logger_1.logger.info(`Generated SDK code for ${sdkInfo.connectorInfo.connectorYaml.connectorId}`);
|
|
119
128
|
}
|
|
120
129
|
}
|
|
121
|
-
exports.
|
|
130
|
+
exports.actuate = actuate;
|
package/lib/rulesDeploy.js
CHANGED
|
@@ -71,12 +71,13 @@ class RulesDeploy {
|
|
|
71
71
|
if (await (0, resourceManager_1.serviceAccountHasRoles)(projectNumber, saEmail, [CROSS_SERVICE_RULES_ROLE], true)) {
|
|
72
72
|
return;
|
|
73
73
|
}
|
|
74
|
-
const addRole =
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
74
|
+
const addRole = this.options.force ||
|
|
75
|
+
(await (0, prompt_1.promptOnce)({
|
|
76
|
+
type: "confirm",
|
|
77
|
+
name: "rulesRole",
|
|
78
|
+
message: `Cloud Storage for Firebase needs an IAM Role to use cross-service rules. Grant the new role?`,
|
|
79
|
+
default: true,
|
|
80
|
+
}, this.options));
|
|
80
81
|
if (addRole) {
|
|
81
82
|
await (0, resourceManager_1.addServiceAccountToRoles)(projectNumber, saEmail, [CROSS_SERVICE_RULES_ROLE], true);
|
|
82
83
|
utils.logLabeledBullet(RulesetType[this.type], "updated service account for cross-service rules...");
|
|
@@ -118,12 +119,13 @@ class RulesDeploy {
|
|
|
118
119
|
utils.logLabeledBullet(RulesetType[this.type], "quota exceeded error while uploading rules");
|
|
119
120
|
const history = await gcp.rules.listAllRulesets(this.options.project);
|
|
120
121
|
if (history.length > RULESET_COUNT_LIMIT) {
|
|
121
|
-
const confirm =
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
122
|
+
const confirm = this.options.force ||
|
|
123
|
+
(await (0, prompt_1.promptOnce)({
|
|
124
|
+
type: "confirm",
|
|
125
|
+
name: "force",
|
|
126
|
+
message: `You have ${history.length} rules, do you want to delete the oldest ${RULESETS_TO_GC} to free up space?`,
|
|
127
|
+
default: false,
|
|
128
|
+
}, this.options));
|
|
127
129
|
if (confirm) {
|
|
128
130
|
const releases = await gcp.rules.listAllReleases(this.options.project);
|
|
129
131
|
const unreleased = history.filter((ruleset) => {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "firebase-tools",
|
|
3
|
-
"version": "13.
|
|
3
|
+
"version": "13.15.0",
|
|
4
4
|
"description": "Command-Line Interface for Firebase",
|
|
5
5
|
"main": "./lib/index.js",
|
|
6
6
|
"bin": {
|
|
@@ -94,8 +94,8 @@
|
|
|
94
94
|
"leven": "^3.1.0",
|
|
95
95
|
"libsodium-wrappers": "^0.7.10",
|
|
96
96
|
"lodash": "^4.17.21",
|
|
97
|
-
"marked": "^
|
|
98
|
-
"marked-terminal": "^
|
|
97
|
+
"marked": "^13.0.2",
|
|
98
|
+
"marked-terminal": "^7.0.0",
|
|
99
99
|
"mime": "^2.5.2",
|
|
100
100
|
"minimatch": "^3.0.4",
|
|
101
101
|
"morgan": "^1.10.0",
|
|
@@ -1,61 +0,0 @@
|
|
|
1
|
-
"use strict";
|
|
2
|
-
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.displayNode10CreateBillingNotice = exports.displayNode10UpdateBillingNotice = void 0;
|
|
4
|
-
const marked_1 = require("marked");
|
|
5
|
-
const TerminalRenderer = require("marked-terminal");
|
|
6
|
-
const error_1 = require("../error");
|
|
7
|
-
const extensionsHelper_1 = require("./extensionsHelper");
|
|
8
|
-
const prompt_1 = require("../prompt");
|
|
9
|
-
const utils = require("../utils");
|
|
10
|
-
const utils_1 = require("./utils");
|
|
11
|
-
marked_1.marked.setOptions({
|
|
12
|
-
renderer: new TerminalRenderer(),
|
|
13
|
-
});
|
|
14
|
-
const urlPricingExamples = "https://cloud.google.com/functions/pricing#pricing_examples";
|
|
15
|
-
const urlFAQ = "https://firebase.google.com/support/faq/#extensions-pricing";
|
|
16
|
-
const billingMsgUpdate = "This update includes an upgrade to Node.js 10 from Node.js 8, which is no" +
|
|
17
|
-
" longer maintained. Starting with this update, you will be charged a" +
|
|
18
|
-
" small amount (typically around $0.01/month) for the Firebase resources" +
|
|
19
|
-
" required by this extension (even if it is not used), in addition to any" +
|
|
20
|
-
" charges associated with its usage.\n\n" +
|
|
21
|
-
`See pricing examples: **[${urlPricingExamples}](${urlPricingExamples})**\n` +
|
|
22
|
-
`See the FAQ: **[${urlFAQ}](${urlFAQ})**\n`;
|
|
23
|
-
const billingMsgCreate = "You will be charged around $0.01/month for the Firebase resources" +
|
|
24
|
-
" required by this extension (even if it is not used). Additionally," +
|
|
25
|
-
" using this extension will contribute to your project's overall usage" +
|
|
26
|
-
" level of Firebase services. However, you'll only be charged for usage" +
|
|
27
|
-
" that exceeds Firebase's free tier for those services.\n\n" +
|
|
28
|
-
`See pricing examples: **[${urlPricingExamples}](${urlPricingExamples})**\n` +
|
|
29
|
-
`See the FAQ: **[${urlFAQ}](${urlFAQ})**\n`;
|
|
30
|
-
const defaultSpecVersion = "v1beta";
|
|
31
|
-
const defaultRuntimes = {
|
|
32
|
-
v1beta: "nodejs8",
|
|
33
|
-
};
|
|
34
|
-
function hasRuntime(spec, runtime) {
|
|
35
|
-
const specVersion = spec.specVersion || defaultSpecVersion;
|
|
36
|
-
const defaultRuntime = defaultRuntimes[specVersion];
|
|
37
|
-
const resources = spec.resources || [];
|
|
38
|
-
return resources.some((r) => runtime === ((0, utils_1.getResourceRuntime)(r) || defaultRuntime));
|
|
39
|
-
}
|
|
40
|
-
function displayNode10UpdateBillingNotice(curSpec, newSpec) {
|
|
41
|
-
if (hasRuntime(curSpec, "nodejs8") && hasRuntime(newSpec, "nodejs10")) {
|
|
42
|
-
utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgUpdate));
|
|
43
|
-
}
|
|
44
|
-
}
|
|
45
|
-
exports.displayNode10UpdateBillingNotice = displayNode10UpdateBillingNotice;
|
|
46
|
-
async function displayNode10CreateBillingNotice(spec, prompt) {
|
|
47
|
-
if (hasRuntime(spec, "nodejs10")) {
|
|
48
|
-
utils.logLabeledWarning(extensionsHelper_1.logPrefix, (0, marked_1.marked)(billingMsgCreate));
|
|
49
|
-
if (prompt) {
|
|
50
|
-
const continueUpdate = await (0, prompt_1.promptOnce)({
|
|
51
|
-
type: "confirm",
|
|
52
|
-
message: "Do you wish to continue?",
|
|
53
|
-
default: true,
|
|
54
|
-
});
|
|
55
|
-
if (!continueUpdate) {
|
|
56
|
-
throw new error_1.FirebaseError(`Cancelled.`, { exit: 2 });
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
}
|
|
60
|
-
}
|
|
61
|
-
exports.displayNode10CreateBillingNotice = displayNode10CreateBillingNotice;
|