firebase-tools 12.4.0 → 12.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/api/frameworks.js +21 -0
- package/lib/api.js +4 -2
- package/lib/auth.js +3 -3
- package/lib/command.js +15 -4
- package/lib/commands/ext-install.js +10 -4
- package/lib/commands/index.js +2 -0
- package/lib/commands/init.js +8 -0
- package/lib/commands/internaltesting-frameworks-init.js +14 -0
- package/lib/config.js +1 -0
- package/lib/deploy/extensions/prepare.js +1 -0
- package/lib/deploy/extensions/release.js +11 -1
- package/lib/deploy/functions/checkIam.js +4 -1
- package/lib/deploy/functions/prepare.js +2 -1
- package/lib/deploy/functions/runtimes/discovery/index.js +6 -0
- package/lib/deploy/functions/runtimes/node/index.js +12 -4
- package/lib/deploy/functions/runtimes/python/index.js +19 -25
- package/lib/deploy/hosting/deploy.js +0 -6
- package/lib/deploy/hosting/prepare.js +7 -1
- package/lib/deploy/index.js +11 -4
- package/lib/deploy/lifecycleHooks.js +3 -0
- package/lib/detectProjectRoot.js +4 -1
- package/lib/dynamicImport.js +11 -1
- package/lib/emulator/commandUtils.js +4 -4
- package/lib/emulator/controller.js +9 -7
- package/lib/emulator/downloadableEmulators.js +3 -3
- package/lib/emulator/functionsEmulator.js +1 -2
- package/lib/emulator/storage/index.js +6 -0
- package/lib/emulator/storage/rules/manager.js +0 -4
- package/lib/emulator/storage/server.js +52 -0
- package/lib/ensureApiEnabled.js +3 -1
- package/lib/experiments.js +5 -0
- package/lib/extensions/paramHelper.js +0 -5
- package/lib/frameworks/constants.js +2 -15
- package/lib/frameworks/index.js +13 -8
- package/lib/frameworks/utils.js +50 -20
- package/lib/functionsConfig.js +2 -2
- package/lib/gcp/cloudbuild.js +50 -0
- package/lib/init/features/composer/repo.js +121 -0
- package/lib/init/features/frameworks/constants.js +7 -0
- package/lib/init/features/frameworks/index.js +36 -0
- package/lib/init/features/index.js +3 -1
- package/lib/init/index.js +4 -0
- package/lib/management/projects.js +5 -1
- package/lib/monospace/index.js +7 -7
- package/lib/requireAuth.js +1 -1
- package/lib/track.js +91 -52
- package/lib/utils.js +6 -1
- package/package.json +1 -1
- package/schema/extension-yaml.json +432 -0
package/lib/init/index.js
CHANGED
|
@@ -6,6 +6,7 @@ const clc = require("colorette");
|
|
|
6
6
|
const error_1 = require("../error");
|
|
7
7
|
const logger_1 = require("../logger");
|
|
8
8
|
const features = require("./features");
|
|
9
|
+
const experiments_1 = require("../experiments");
|
|
9
10
|
const featureFns = new Map([
|
|
10
11
|
["account", features.account],
|
|
11
12
|
["database", features.database],
|
|
@@ -19,6 +20,9 @@ const featureFns = new Map([
|
|
|
19
20
|
["remoteconfig", features.remoteconfig],
|
|
20
21
|
["hosting:github", features.hostingGithub],
|
|
21
22
|
]);
|
|
23
|
+
if ((0, experiments_1.isEnabled)("frameworks")) {
|
|
24
|
+
featureFns.set("frameworks", features.frameworks);
|
|
25
|
+
}
|
|
22
26
|
async function init(setup, config, options) {
|
|
23
27
|
var _a;
|
|
24
28
|
const nextFeature = (_a = setup.features) === null || _a === void 0 ? void 0 : _a.shift();
|
|
@@ -300,7 +300,11 @@ async function getFirebaseProject(projectId) {
|
|
|
300
300
|
return res.body;
|
|
301
301
|
}
|
|
302
302
|
catch (err) {
|
|
303
|
-
|
|
303
|
+
let message = err.message;
|
|
304
|
+
if (err.original) {
|
|
305
|
+
message += ` (original: ${err.original.message})`;
|
|
306
|
+
}
|
|
307
|
+
logger_1.logger.debug(message);
|
|
304
308
|
throw new error_1.FirebaseError(`Failed to get Firebase project ${projectId}. ` +
|
|
305
309
|
"Please make sure the project exists and your account has permission to access it.", { exit: 2, original: err });
|
|
306
310
|
}
|
package/lib/monospace/index.js
CHANGED
|
@@ -5,7 +5,7 @@ const node_fetch_1 = require("node-fetch");
|
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
7
7
|
const rc_1 = require("../rc");
|
|
8
|
-
const POLL_USER_RESPONSE_MILLIS =
|
|
8
|
+
const POLL_USER_RESPONSE_MILLIS = 2000;
|
|
9
9
|
async function selectProjectInMonospace({ projectRoot, project, isVSCE, }) {
|
|
10
10
|
const initFirebaseResponse = await initFirebase(project);
|
|
11
11
|
if (initFirebaseResponse.success === false) {
|
|
@@ -27,9 +27,7 @@ async function pollAuthorizedProject(rid) {
|
|
|
27
27
|
if (getInitFirebaseRes.userResponse.success) {
|
|
28
28
|
return getInitFirebaseRes.userResponse.projectId;
|
|
29
29
|
}
|
|
30
|
-
|
|
31
|
-
return null;
|
|
32
|
-
}
|
|
30
|
+
return null;
|
|
33
31
|
}
|
|
34
32
|
const { error } = getInitFirebaseRes;
|
|
35
33
|
if (error === "WAITING_FOR_RESPONSE") {
|
|
@@ -39,7 +37,9 @@ async function pollAuthorizedProject(rid) {
|
|
|
39
37
|
if (error === "USER_CANCELED") {
|
|
40
38
|
throw new error_1.FirebaseError("User canceled without authorizing any project");
|
|
41
39
|
}
|
|
42
|
-
throw new error_1.FirebaseError(`Unhandled /get-init-firebase-response error
|
|
40
|
+
throw new error_1.FirebaseError(`Unhandled /get-init-firebase-response error`, {
|
|
41
|
+
original: new Error(error),
|
|
42
|
+
});
|
|
43
43
|
}
|
|
44
44
|
async function initFirebase(project) {
|
|
45
45
|
const port = getMonospaceDaemonPort();
|
|
@@ -73,8 +73,8 @@ function createFirebaseRc(projectDir, authorizedProject) {
|
|
|
73
73
|
firebaseRc.addProjectAlias("default", authorizedProject);
|
|
74
74
|
return firebaseRc.save();
|
|
75
75
|
}
|
|
76
|
-
|
|
77
|
-
return
|
|
76
|
+
function isMonospaceEnv() {
|
|
77
|
+
return getMonospaceDaemonPort() !== undefined;
|
|
78
78
|
}
|
|
79
79
|
exports.isMonospaceEnv = isMonospaceEnv;
|
|
80
80
|
function getMonospaceDaemonPort() {
|
package/lib/requireAuth.js
CHANGED
|
@@ -24,7 +24,7 @@ async function autoAuth(options, authScopes) {
|
|
|
24
24
|
const client = getAuthClient({ scopes: authScopes, projectId: options.project });
|
|
25
25
|
const token = await client.getAccessToken();
|
|
26
26
|
token !== null ? apiv2.setAccessToken(token) : false;
|
|
27
|
-
if (!options.isVSCE && (
|
|
27
|
+
if (!options.isVSCE && (0, monospace_1.isMonospaceEnv)()) {
|
|
28
28
|
await (0, monospace_1.selectProjectInMonospace)({
|
|
29
29
|
projectRoot: options.config.projectDir,
|
|
30
30
|
project: options.project,
|
package/lib/track.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.emulatorSession = exports.trackEmulator = exports.
|
|
3
|
+
exports.track = exports.cliSession = exports.emulatorSession = exports.trackEmulator = exports.trackGA4 = exports.usageEnabled = exports.GA4_PROPERTIES = void 0;
|
|
4
4
|
const node_fetch_1 = require("node-fetch");
|
|
5
5
|
const ua = require("universal-analytics");
|
|
6
6
|
const uuid_1 = require("uuid");
|
|
@@ -8,45 +8,23 @@ const auth_1 = require("./auth");
|
|
|
8
8
|
const configstore_1 = require("./configstore");
|
|
9
9
|
const logger_1 = require("./logger");
|
|
10
10
|
const pkg = require("../package.json");
|
|
11
|
-
exports.
|
|
11
|
+
exports.GA4_PROPERTIES = {
|
|
12
|
+
cli: {
|
|
13
|
+
measurementId: process.env.FIREBASE_CLI_GA4_MEASUREMENT_ID || "G-PDN0QWHQJR",
|
|
14
|
+
apiSecret: process.env.FIREBASE_CLI_GA4_API_SECRET || "LSw5lNxhSFSWeB6aIzJS2w",
|
|
15
|
+
clientIdKey: "analytics-uuid",
|
|
16
|
+
},
|
|
17
|
+
emulator: {
|
|
18
|
+
measurementId: process.env.FIREBASE_EMULATOR_GA4_MEASUREMENT_ID || "G-KYP2JMPFC0",
|
|
19
|
+
apiSecret: process.env.FIREBASE_EMULATOR_GA4_API_SECRET || "2V_zBYc4TdeoppzDaIu0zw",
|
|
20
|
+
clientIdKey: "emulator-analytics-clientId",
|
|
21
|
+
},
|
|
22
|
+
};
|
|
12
23
|
function usageEnabled() {
|
|
13
24
|
return !!process.env.IS_FIREBASE_CLI && !!configstore_1.configstore.get("usage");
|
|
14
25
|
}
|
|
15
26
|
exports.usageEnabled = usageEnabled;
|
|
16
|
-
const
|
|
17
|
-
let visitor;
|
|
18
|
-
function ensureUAVisitor() {
|
|
19
|
-
if (!visitor) {
|
|
20
|
-
let anonId = configstore_1.configstore.get("analytics-uuid");
|
|
21
|
-
if (!anonId) {
|
|
22
|
-
anonId = (0, uuid_1.v4)();
|
|
23
|
-
configstore_1.configstore.set("analytics-uuid", anonId);
|
|
24
|
-
}
|
|
25
|
-
visitor = ua(FIREBASE_ANALYTICS_UA, anonId, {
|
|
26
|
-
strictCidFormat: false,
|
|
27
|
-
https: true,
|
|
28
|
-
});
|
|
29
|
-
visitor.set("cd1", process.platform);
|
|
30
|
-
visitor.set("cd2", process.version);
|
|
31
|
-
visitor.set("cd3", process.env.FIREPIT_VERSION || "none");
|
|
32
|
-
}
|
|
33
|
-
}
|
|
34
|
-
function track(action, label, duration = 0) {
|
|
35
|
-
ensureUAVisitor();
|
|
36
|
-
return new Promise((resolve) => {
|
|
37
|
-
if (usageEnabled() && configstore_1.configstore.get("tokens")) {
|
|
38
|
-
visitor.event("Firebase CLI " + pkg.version, action, label, duration).send(() => {
|
|
39
|
-
resolve();
|
|
40
|
-
});
|
|
41
|
-
}
|
|
42
|
-
else {
|
|
43
|
-
resolve();
|
|
44
|
-
}
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
exports.track = track;
|
|
48
|
-
const EMULATOR_GA4_API_SECRET = process.env.FIREBASE_EMULATOR_GA4_API_SECRET || "2V_zBYc4TdeoppzDaIu0zw";
|
|
49
|
-
const EMULATOR_GA4_USER_PROPS = {
|
|
27
|
+
const GA4_USER_PROPS = {
|
|
50
28
|
node_platform: {
|
|
51
29
|
value: process.platform,
|
|
52
30
|
},
|
|
@@ -60,6 +38,20 @@ const EMULATOR_GA4_USER_PROPS = {
|
|
|
60
38
|
value: process.env.FIREPIT_VERSION || "none",
|
|
61
39
|
},
|
|
62
40
|
};
|
|
41
|
+
async function trackGA4(eventName, params, duration = 1) {
|
|
42
|
+
const session = cliSession();
|
|
43
|
+
if (!session) {
|
|
44
|
+
return;
|
|
45
|
+
}
|
|
46
|
+
return _ga4Track({
|
|
47
|
+
session,
|
|
48
|
+
apiSecret: exports.GA4_PROPERTIES.cli.apiSecret,
|
|
49
|
+
eventName,
|
|
50
|
+
params,
|
|
51
|
+
duration,
|
|
52
|
+
});
|
|
53
|
+
}
|
|
54
|
+
exports.trackGA4 = trackGA4;
|
|
63
55
|
async function trackEmulator(eventName, params) {
|
|
64
56
|
const session = emulatorSession();
|
|
65
57
|
if (!session) {
|
|
@@ -67,29 +59,38 @@ async function trackEmulator(eventName, params) {
|
|
|
67
59
|
}
|
|
68
60
|
const oldTotalEngagementSeconds = session.totalEngagementSeconds;
|
|
69
61
|
session.totalEngagementSeconds = process.uptime();
|
|
62
|
+
const duration = session.totalEngagementSeconds - oldTotalEngagementSeconds;
|
|
63
|
+
return _ga4Track({
|
|
64
|
+
session,
|
|
65
|
+
apiSecret: exports.GA4_PROPERTIES.emulator.apiSecret,
|
|
66
|
+
eventName,
|
|
67
|
+
params,
|
|
68
|
+
duration,
|
|
69
|
+
});
|
|
70
|
+
}
|
|
71
|
+
exports.trackEmulator = trackEmulator;
|
|
72
|
+
async function _ga4Track(args) {
|
|
73
|
+
const { session, apiSecret, eventName, params, duration } = args;
|
|
70
74
|
session.commandName = (params === null || params === void 0 ? void 0 : params.command_name) || session.commandName;
|
|
71
|
-
const search = `?api_secret=${
|
|
75
|
+
const search = `?api_secret=${apiSecret}&measurement_id=${session.measurementId}`;
|
|
72
76
|
const validate = session.validateOnly ? "debug/" : "";
|
|
73
77
|
const url = `https://www.google-analytics.com/${validate}mp/collect${search}`;
|
|
74
78
|
const body = {
|
|
75
79
|
timestamp_micros: `${Date.now()}000`,
|
|
76
80
|
client_id: session.clientId,
|
|
77
|
-
user_properties: Object.assign(Object.assign({},
|
|
81
|
+
user_properties: Object.assign(Object.assign({}, GA4_USER_PROPS), { java_major_version: session.javaMajorVersion
|
|
78
82
|
? { value: session.javaMajorVersion }
|
|
79
83
|
: undefined }),
|
|
80
84
|
validationBehavior: session.validateOnly ? "ENFORCE_RECOMMENDATIONS" : undefined,
|
|
81
85
|
events: [
|
|
82
86
|
{
|
|
83
87
|
name: eventName,
|
|
84
|
-
params: Object.assign({ session_id: session.sessionId, engagement_time_msec: (session.
|
|
85
|
-
.toFixed(3)
|
|
86
|
-
.replace(".", "")
|
|
87
|
-
.replace(/^0+/, ""), debug_mode: session.debugMode ? true : undefined, command_name: session.commandName }, params),
|
|
88
|
+
params: Object.assign({ session_id: session.sessionId, engagement_time_msec: (duration !== null && duration !== void 0 ? duration : 0).toFixed(3).replace(".", "").replace(/^0+/, ""), debug_mode: session.debugMode ? true : undefined, command_name: session.commandName }, params),
|
|
88
89
|
},
|
|
89
90
|
],
|
|
90
91
|
};
|
|
91
92
|
if (session.validateOnly) {
|
|
92
|
-
logger_1.logger.info(`Sending Analytics for event ${eventName}`, params, body);
|
|
93
|
+
logger_1.logger.info(`Sending Analytics for event ${eventName} to property ${session.measurementId}`, params, body);
|
|
93
94
|
}
|
|
94
95
|
try {
|
|
95
96
|
const response = await (0, node_fetch_1.default)(url, {
|
|
@@ -114,8 +115,15 @@ async function trackEmulator(eventName, params) {
|
|
|
114
115
|
return;
|
|
115
116
|
}
|
|
116
117
|
}
|
|
117
|
-
exports.trackEmulator = trackEmulator;
|
|
118
118
|
function emulatorSession() {
|
|
119
|
+
return session("emulator");
|
|
120
|
+
}
|
|
121
|
+
exports.emulatorSession = emulatorSession;
|
|
122
|
+
function cliSession() {
|
|
123
|
+
return session("cli");
|
|
124
|
+
}
|
|
125
|
+
exports.cliSession = cliSession;
|
|
126
|
+
function session(propertyName) {
|
|
119
127
|
const validateOnly = !!process.env.FIREBASE_CLI_MP_VALIDATE;
|
|
120
128
|
if (!usageEnabled()) {
|
|
121
129
|
if (validateOnly) {
|
|
@@ -123,14 +131,15 @@ function emulatorSession() {
|
|
|
123
131
|
}
|
|
124
132
|
return;
|
|
125
133
|
}
|
|
126
|
-
|
|
127
|
-
|
|
134
|
+
const property = exports.GA4_PROPERTIES[propertyName];
|
|
135
|
+
if (!property.currentSession) {
|
|
136
|
+
let clientId = configstore_1.configstore.get(property.clientIdKey);
|
|
128
137
|
if (!clientId) {
|
|
129
138
|
clientId = (0, uuid_1.v4)();
|
|
130
|
-
configstore_1.configstore.set(
|
|
139
|
+
configstore_1.configstore.set(property.clientIdKey, clientId);
|
|
131
140
|
}
|
|
132
|
-
|
|
133
|
-
measurementId:
|
|
141
|
+
property.currentSession = {
|
|
142
|
+
measurementId: property.measurementId,
|
|
134
143
|
clientId,
|
|
135
144
|
sessionId: (Math.random() * Number.MAX_SAFE_INTEGER).toFixed(0),
|
|
136
145
|
totalEngagementSeconds: 0,
|
|
@@ -138,10 +147,8 @@ function emulatorSession() {
|
|
|
138
147
|
validateOnly,
|
|
139
148
|
};
|
|
140
149
|
}
|
|
141
|
-
return
|
|
150
|
+
return property.currentSession;
|
|
142
151
|
}
|
|
143
|
-
exports.emulatorSession = emulatorSession;
|
|
144
|
-
let currentEmulatorSession = undefined;
|
|
145
152
|
function isDebugMode() {
|
|
146
153
|
const account = (0, auth_1.getGlobalDefaultAccount)();
|
|
147
154
|
if (account === null || account === void 0 ? void 0 : account.user.email.endsWith("@google.com")) {
|
|
@@ -155,3 +162,35 @@ function isDebugMode() {
|
|
|
155
162
|
}
|
|
156
163
|
return false;
|
|
157
164
|
}
|
|
165
|
+
const FIREBASE_ANALYTICS_UA = process.env.FIREBASE_ANALYTICS_UA || "UA-29174744-3";
|
|
166
|
+
let visitor;
|
|
167
|
+
function ensureUAVisitor() {
|
|
168
|
+
if (!visitor) {
|
|
169
|
+
let anonId = configstore_1.configstore.get("analytics-uuid");
|
|
170
|
+
if (!anonId) {
|
|
171
|
+
anonId = (0, uuid_1.v4)();
|
|
172
|
+
configstore_1.configstore.set("analytics-uuid", anonId);
|
|
173
|
+
}
|
|
174
|
+
visitor = ua(FIREBASE_ANALYTICS_UA, anonId, {
|
|
175
|
+
strictCidFormat: false,
|
|
176
|
+
https: true,
|
|
177
|
+
});
|
|
178
|
+
visitor.set("cd1", process.platform);
|
|
179
|
+
visitor.set("cd2", process.version);
|
|
180
|
+
visitor.set("cd3", process.env.FIREPIT_VERSION || "none");
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
function track(action, label, duration = 0) {
|
|
184
|
+
ensureUAVisitor();
|
|
185
|
+
return new Promise((resolve) => {
|
|
186
|
+
if (usageEnabled() && configstore_1.configstore.get("tokens")) {
|
|
187
|
+
visitor.event("Firebase CLI " + pkg.version, action, label, duration).send(() => {
|
|
188
|
+
resolve();
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
else {
|
|
192
|
+
resolve();
|
|
193
|
+
}
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
exports.track = track;
|
package/lib/utils.js
CHANGED
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
3
|
+
exports.openInBrowser = exports.connectableHostname = exports.randomInt = exports.debounce = exports.last = exports.cloneDeep = exports.groupBy = exports.assertIsStringOrUndefined = exports.assertIsNumber = exports.assertIsString = exports.assertDefined = exports.thirtyDaysFromNow = exports.isRunningInWSL = exports.isCloudEnvironment = exports.datetimeString = exports.createDestroyer = exports.promiseWithSpinner = exports.setupLoggers = exports.tryParse = exports.tryStringify = exports.promiseProps = exports.withTimeout = exports.promiseWhile = exports.promiseAllSettled = exports.getFunctionsEventProvider = exports.endpoint = exports.makeActiveProject = exports.streamToString = exports.stringToStream = exports.explainStdin = exports.allSettled = exports.reject = exports.logLabeledError = exports.logLabeledWarning = exports.logWarning = exports.logLabeledBullet = exports.logBullet = exports.logLabeledSuccess = exports.logSuccess = exports.addSubdomain = exports.addDatabaseNamespace = exports.getDatabaseViewDataUrl = exports.getDatabaseUrl = exports.envOverride = exports.getInheritedOption = exports.consoleUrl = exports.envOverrides = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const url = require("url");
|
|
6
6
|
const clc = require("colorette");
|
|
7
|
+
const open = require("open");
|
|
7
8
|
const ora = require("ora");
|
|
8
9
|
const process = require("process");
|
|
9
10
|
const stream_1 = require("stream");
|
|
@@ -485,3 +486,7 @@ function connectableHostname(hostname) {
|
|
|
485
486
|
return hostname;
|
|
486
487
|
}
|
|
487
488
|
exports.connectableHostname = connectableHostname;
|
|
489
|
+
async function openInBrowser(url) {
|
|
490
|
+
await open(url);
|
|
491
|
+
}
|
|
492
|
+
exports.openInBrowser = openInBrowser;
|