firebase-tools 11.5.0 → 11.8.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/command.js +33 -7
- package/lib/commands/crashlytics-mappingfile-generateid.js +26 -0
- package/lib/commands/crashlytics-mappingfile-upload.js +46 -0
- package/lib/commands/crashlytics-symbols-upload.js +18 -87
- package/lib/commands/emulators-exec.js +4 -1
- package/lib/commands/emulators-export.js +5 -2
- package/lib/commands/emulators-start.js +23 -17
- package/lib/commands/ext-dev-publish.js +3 -0
- package/lib/commands/functions-delete.js +2 -0
- package/lib/commands/functions-secrets-get.js +2 -0
- package/lib/commands/index.js +3 -0
- package/lib/commands/login.js +2 -2
- package/lib/crashlytics/buildToolsJarHelper.js +51 -0
- package/lib/deploy/functions/backend.js +4 -4
- package/lib/deploy/functions/build.js +76 -9
- package/lib/deploy/functions/checkIam.js +6 -5
- package/lib/deploy/functions/params.js +22 -16
- package/lib/deploy/functions/prepare.js +1 -1
- package/lib/deploy/functions/release/fabricator.js +22 -5
- package/lib/deploy/functions/release/index.js +2 -0
- package/lib/deploy/functions/runtimes/discovery/index.js +1 -16
- package/lib/deploy/functions/runtimes/discovery/parsing.js +16 -0
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +59 -131
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +1 -1
- package/lib/emulator/auth/index.js +7 -2
- package/lib/emulator/auth/operations.js +10 -10
- package/lib/emulator/commandUtils.js +32 -15
- package/lib/emulator/constants.js +14 -6
- package/lib/emulator/controller.js +49 -17
- package/lib/emulator/downloadableEmulators.js +7 -7
- package/lib/emulator/eventarcEmulator.js +148 -0
- package/lib/emulator/extensionsEmulator.js +3 -1
- package/lib/emulator/functionsEmulator.js +44 -4
- package/lib/emulator/functionsEmulatorRuntime.js +12 -23
- package/lib/emulator/functionsEmulatorShared.js +6 -1
- package/lib/emulator/hub.js +7 -3
- package/lib/emulator/hubClient.js +2 -2
- package/lib/emulator/hubExport.js +22 -2
- package/lib/emulator/registry.js +1 -0
- package/lib/emulator/storage/apis/firebase.js +145 -129
- package/lib/emulator/storage/apis/gcloud.js +102 -42
- package/lib/emulator/storage/files.js +39 -17
- package/lib/emulator/storage/metadata.js +76 -55
- package/lib/emulator/storage/multipart.js +2 -2
- package/lib/emulator/storage/rules/runtime.js +12 -4
- package/lib/emulator/storage/server.js +2 -1
- package/lib/emulator/storage/upload.js +46 -9
- package/lib/emulator/types.js +3 -0
- package/lib/emulator/ui.js +7 -2
- package/lib/extensions/extensionsApi.js +2 -1
- package/lib/extensions/extensionsHelper.js +29 -1
- package/lib/functions/constants.js +14 -0
- package/lib/functions/env.js +9 -9
- package/lib/gcp/cloudfunctions.js +15 -18
- package/lib/gcp/cloudfunctionsv2.js +15 -18
- package/lib/gcp/cloudscheduler.js +32 -14
- package/lib/serve/index.js +15 -0
- package/lib/track.js +122 -3
- package/lib/utils.js +14 -1
- package/npm-shrinkwrap.json +542 -9
- package/package.json +5 -4
- package/schema/firebase-config.json +12 -0
- package/templates/extensions/CHANGELOG.md +1 -7
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.functionFromEndpoint = exports.endpointFromFunction = exports.listAllFunctions = exports.listFunctions = exports.deleteFunction = exports.updateFunction = exports.setInvokerUpdate = exports.setInvokerCreate = exports.getIamPolicy = exports.setIamPolicy = exports.createFunction = exports.generateUploadUrl = exports.
|
|
3
|
+
exports.functionFromEndpoint = exports.endpointFromFunction = exports.listAllFunctions = exports.listFunctions = exports.deleteFunction = exports.updateFunction = exports.setInvokerUpdate = exports.setInvokerCreate = exports.getIamPolicy = exports.setIamPolicy = exports.createFunction = exports.generateUploadUrl = exports.API_VERSION = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
@@ -11,18 +11,9 @@ const runtimes = require("../deploy/functions/runtimes");
|
|
|
11
11
|
const projectConfig = require("../functions/projectConfig");
|
|
12
12
|
const apiv2_1 = require("../apiv2");
|
|
13
13
|
const api_1 = require("../api");
|
|
14
|
+
const constants_1 = require("../functions/constants");
|
|
14
15
|
exports.API_VERSION = "v1";
|
|
15
|
-
exports.CODEBASE_LABEL = "firebase-functions-codebase";
|
|
16
16
|
const client = new apiv2_1.Client({ urlPrefix: api_1.functionsOrigin, apiVersion: exports.API_VERSION });
|
|
17
|
-
exports.BLOCKING_LABEL = "deployment-blocking";
|
|
18
|
-
const BLOCKING_LABEL_KEY_TO_EVENT = {
|
|
19
|
-
"before-create": "providers/cloud.auth/eventTypes/user.beforeCreate",
|
|
20
|
-
"before-sign-in": "providers/cloud.auth/eventTypes/user.beforeSignIn",
|
|
21
|
-
};
|
|
22
|
-
const BLOCKING_EVENT_TO_LABEL_KEY = {
|
|
23
|
-
"providers/cloud.auth/eventTypes/user.beforeCreate": "before-create",
|
|
24
|
-
"providers/cloud.auth/eventTypes/user.beforeSignIn": "before-sign-in",
|
|
25
|
-
};
|
|
26
17
|
function functionsOpLogReject(funcName, type, err) {
|
|
27
18
|
var _a, _b;
|
|
28
19
|
if (((_b = (_a = err === null || err === void 0 ? void 0 : err.context) === null || _a === void 0 ? void 0 : _a.response) === null || _b === void 0 ? void 0 : _b.statusCode) === 429) {
|
|
@@ -199,7 +190,7 @@ async function listAllFunctions(projectId) {
|
|
|
199
190
|
}
|
|
200
191
|
exports.listAllFunctions = listAllFunctions;
|
|
201
192
|
function endpointFromFunction(gcfFunction) {
|
|
202
|
-
var _a, _b, _c, _d, _e, _f, _g;
|
|
193
|
+
var _a, _b, _c, _d, _e, _f, _g, _h;
|
|
203
194
|
const [, project, , region, , id] = gcfFunction.name.split("/");
|
|
204
195
|
let trigger;
|
|
205
196
|
let uri;
|
|
@@ -220,10 +211,10 @@ function endpointFromFunction(gcfFunction) {
|
|
|
220
211
|
callableTrigger: {},
|
|
221
212
|
};
|
|
222
213
|
}
|
|
223
|
-
else if ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[
|
|
214
|
+
else if ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[constants_1.BLOCKING_LABEL]) {
|
|
224
215
|
trigger = {
|
|
225
216
|
blockingTrigger: {
|
|
226
|
-
eventType: BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[
|
|
217
|
+
eventType: constants_1.BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[constants_1.BLOCKING_LABEL]],
|
|
227
218
|
},
|
|
228
219
|
};
|
|
229
220
|
}
|
|
@@ -263,7 +254,10 @@ function endpointFromFunction(gcfFunction) {
|
|
|
263
254
|
endpoint.vpc = { connector: gcfFunction.vpcConnector };
|
|
264
255
|
proto.convertIfPresent(endpoint.vpc, gcfFunction, "egressSettings", "vpcConnectorEgressSettings", (raw) => raw);
|
|
265
256
|
}
|
|
266
|
-
endpoint.codebase = ((_g = gcfFunction.labels) === null || _g === void 0 ? void 0 : _g[
|
|
257
|
+
endpoint.codebase = ((_g = gcfFunction.labels) === null || _g === void 0 ? void 0 : _g[constants_1.CODEBASE_LABEL]) || projectConfig.DEFAULT_CODEBASE;
|
|
258
|
+
if ((_h = gcfFunction.labels) === null || _h === void 0 ? void 0 : _h[constants_1.HASH_LABEL]) {
|
|
259
|
+
endpoint.hash = gcfFunction.labels[constants_1.HASH_LABEL];
|
|
260
|
+
}
|
|
267
261
|
return endpoint;
|
|
268
262
|
}
|
|
269
263
|
exports.endpointFromFunction = endpointFromFunction;
|
|
@@ -312,7 +306,7 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
312
306
|
}
|
|
313
307
|
else if (backend.isBlockingTriggered(endpoint)) {
|
|
314
308
|
gcfFunction.httpsTrigger = {};
|
|
315
|
-
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [
|
|
309
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.BLOCKING_LABEL]: constants_1.BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
|
|
316
310
|
}
|
|
317
311
|
else {
|
|
318
312
|
gcfFunction.httpsTrigger = {};
|
|
@@ -337,10 +331,13 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
337
331
|
}
|
|
338
332
|
const codebase = endpoint.codebase || projectConfig.DEFAULT_CODEBASE;
|
|
339
333
|
if (codebase !== projectConfig.DEFAULT_CODEBASE) {
|
|
340
|
-
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [
|
|
334
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.CODEBASE_LABEL]: codebase });
|
|
341
335
|
}
|
|
342
336
|
else {
|
|
343
|
-
(_b = gcfFunction.labels) === null || _b === void 0 ? true : delete _b[
|
|
337
|
+
(_b = gcfFunction.labels) === null || _b === void 0 ? true : delete _b[constants_1.CODEBASE_LABEL];
|
|
338
|
+
}
|
|
339
|
+
if (endpoint.hash) {
|
|
340
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.HASH_LABEL]: endpoint.hash });
|
|
344
341
|
}
|
|
345
342
|
return gcfFunction;
|
|
346
343
|
}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.mebibytes = exports.
|
|
3
|
+
exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.mebibytes = exports.API_VERSION = void 0;
|
|
4
4
|
const clc = require("colorette");
|
|
5
5
|
const apiv2_1 = require("../apiv2");
|
|
6
6
|
const error_1 = require("../error");
|
|
@@ -12,22 +12,13 @@ const runtimes = require("../deploy/functions/runtimes");
|
|
|
12
12
|
const proto = require("./proto");
|
|
13
13
|
const utils = require("../utils");
|
|
14
14
|
const projectConfig = require("../functions/projectConfig");
|
|
15
|
+
const constants_1 = require("../functions/constants");
|
|
15
16
|
exports.API_VERSION = "v2alpha";
|
|
16
|
-
exports.CODEBASE_LABEL = "firebase-functions-codebase";
|
|
17
17
|
const client = new apiv2_1.Client({
|
|
18
18
|
urlPrefix: api_1.functionsV2Origin,
|
|
19
19
|
auth: true,
|
|
20
20
|
apiVersion: exports.API_VERSION,
|
|
21
21
|
});
|
|
22
|
-
exports.BLOCKING_LABEL = "deployment-blocking";
|
|
23
|
-
const BLOCKING_LABEL_KEY_TO_EVENT = {
|
|
24
|
-
"before-create": "providers/cloud.auth/eventTypes/user.beforeCreate",
|
|
25
|
-
"before-sign-in": "providers/cloud.auth/eventTypes/user.beforeSignIn",
|
|
26
|
-
};
|
|
27
|
-
const BLOCKING_EVENT_TO_LABEL_KEY = {
|
|
28
|
-
"providers/cloud.auth/eventTypes/user.beforeCreate": "before-create",
|
|
29
|
-
"providers/cloud.auth/eventTypes/user.beforeSignIn": "before-sign-in",
|
|
30
|
-
};
|
|
31
22
|
const BYTES_PER_UNIT = {
|
|
32
23
|
"": 1,
|
|
33
24
|
k: 1e3,
|
|
@@ -243,20 +234,23 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
243
234
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callable": "true" });
|
|
244
235
|
}
|
|
245
236
|
else if (backend.isBlockingTriggered(endpoint)) {
|
|
246
|
-
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [
|
|
237
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.BLOCKING_LABEL]: constants_1.BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
|
|
247
238
|
}
|
|
248
239
|
const codebase = endpoint.codebase || projectConfig.DEFAULT_CODEBASE;
|
|
249
240
|
if (codebase !== projectConfig.DEFAULT_CODEBASE) {
|
|
250
|
-
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [
|
|
241
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.CODEBASE_LABEL]: codebase });
|
|
251
242
|
}
|
|
252
243
|
else {
|
|
253
|
-
(_b = gcfFunction.labels) === null || _b === void 0 ? true : delete _b[
|
|
244
|
+
(_b = gcfFunction.labels) === null || _b === void 0 ? true : delete _b[constants_1.CODEBASE_LABEL];
|
|
245
|
+
}
|
|
246
|
+
if (endpoint.hash) {
|
|
247
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [constants_1.HASH_LABEL]: endpoint.hash });
|
|
254
248
|
}
|
|
255
249
|
return gcfFunction;
|
|
256
250
|
}
|
|
257
251
|
exports.functionFromEndpoint = functionFromEndpoint;
|
|
258
252
|
function endpointFromFunction(gcfFunction) {
|
|
259
|
-
var _a, _b, _c, _d, _e;
|
|
253
|
+
var _a, _b, _c, _d, _e, _f;
|
|
260
254
|
const [, project, , region, , id] = gcfFunction.name.split("/");
|
|
261
255
|
let trigger;
|
|
262
256
|
if (((_a = gcfFunction.labels) === null || _a === void 0 ? void 0 : _a["deployment-scheduled"]) === "true") {
|
|
@@ -274,10 +268,10 @@ function endpointFromFunction(gcfFunction) {
|
|
|
274
268
|
callableTrigger: {},
|
|
275
269
|
};
|
|
276
270
|
}
|
|
277
|
-
else if ((_d = gcfFunction.labels) === null || _d === void 0 ? void 0 : _d[
|
|
271
|
+
else if ((_d = gcfFunction.labels) === null || _d === void 0 ? void 0 : _d[constants_1.BLOCKING_LABEL]) {
|
|
278
272
|
trigger = {
|
|
279
273
|
blockingTrigger: {
|
|
280
|
-
eventType: BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[
|
|
274
|
+
eventType: constants_1.BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[constants_1.BLOCKING_LABEL]],
|
|
281
275
|
},
|
|
282
276
|
};
|
|
283
277
|
}
|
|
@@ -341,7 +335,10 @@ function endpointFromFunction(gcfFunction) {
|
|
|
341
335
|
endpoint.vpc = { connector: gcfFunction.serviceConfig.vpcConnector };
|
|
342
336
|
proto.renameIfPresent(endpoint.vpc, gcfFunction.serviceConfig, "egressSettings", "vpcConnectorEgressSettings");
|
|
343
337
|
}
|
|
344
|
-
endpoint.codebase = ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[
|
|
338
|
+
endpoint.codebase = ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[constants_1.CODEBASE_LABEL]) || projectConfig.DEFAULT_CODEBASE;
|
|
339
|
+
if ((_f = gcfFunction.labels) === null || _f === void 0 ? void 0 : _f[constants_1.HASH_LABEL]) {
|
|
340
|
+
endpoint.hash = gcfFunction.labels[constants_1.HASH_LABEL];
|
|
341
|
+
}
|
|
345
342
|
return endpoint;
|
|
346
343
|
}
|
|
347
344
|
exports.endpointFromFunction = endpointFromFunction;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.jobFromEndpoint = exports.topicNameForEndpoint = exports.jobNameForEndpoint = exports.createOrReplaceJob = exports.
|
|
3
|
+
exports.jobFromEndpoint = exports.topicNameForEndpoint = exports.jobNameForEndpoint = exports.createOrReplaceJob = exports.getJob = exports.deleteJob = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
@@ -8,15 +8,18 @@ const api_1 = require("../api");
|
|
|
8
8
|
const apiv2_1 = require("../apiv2");
|
|
9
9
|
const backend = require("../deploy/functions/backend");
|
|
10
10
|
const proto = require("./proto");
|
|
11
|
+
const checkIam_1 = require("../deploy/functions/checkIam");
|
|
11
12
|
const functional_1 = require("../functional");
|
|
12
13
|
const VERSION = "v1";
|
|
13
|
-
const
|
|
14
|
+
const DEFAULT_TIME_ZONE_V1 = "America/Los_Angeles";
|
|
15
|
+
const DEFAULT_TIME_ZONE_V2 = "UTC";
|
|
14
16
|
const apiClient = new apiv2_1.Client({ urlPrefix: api_1.cloudschedulerOrigin, apiVersion: VERSION });
|
|
15
17
|
function createJob(job) {
|
|
16
18
|
const strippedName = job.name.substring(0, job.name.lastIndexOf("/"));
|
|
17
|
-
|
|
19
|
+
const json = job.pubsubTarget
|
|
20
|
+
? Object.assign({ timeZone: DEFAULT_TIME_ZONE_V1 }, job) : Object.assign({ timeZone: DEFAULT_TIME_ZONE_V2 }, job);
|
|
21
|
+
return apiClient.post(`/${strippedName}`, json);
|
|
18
22
|
}
|
|
19
|
-
exports.createJob = createJob;
|
|
20
23
|
function deleteJob(name) {
|
|
21
24
|
return apiClient.delete(`/${name}`);
|
|
22
25
|
}
|
|
@@ -28,14 +31,22 @@ function getJob(name) {
|
|
|
28
31
|
}
|
|
29
32
|
exports.getJob = getJob;
|
|
30
33
|
function updateJob(job) {
|
|
31
|
-
|
|
32
|
-
|
|
34
|
+
let fieldMasks;
|
|
35
|
+
let json;
|
|
36
|
+
if (job.pubsubTarget) {
|
|
37
|
+
fieldMasks = proto.fieldMasks(job, "pubsubTarget");
|
|
38
|
+
json = Object.assign({ timeZone: DEFAULT_TIME_ZONE_V1 }, job);
|
|
39
|
+
}
|
|
40
|
+
else {
|
|
41
|
+
fieldMasks = proto.fieldMasks(job, "httpTarget");
|
|
42
|
+
json = Object.assign({ timeZone: DEFAULT_TIME_ZONE_V2 }, job);
|
|
43
|
+
}
|
|
44
|
+
return apiClient.patch(`/${job.name}`, json, {
|
|
33
45
|
queryParams: {
|
|
34
46
|
updateMask: fieldMasks.join(","),
|
|
35
47
|
},
|
|
36
48
|
});
|
|
37
49
|
}
|
|
38
|
-
exports.updateJob = updateJob;
|
|
39
50
|
async function createOrReplaceJob(job) {
|
|
40
51
|
var _a, _b;
|
|
41
52
|
const jobName = job.name.split("/").pop();
|
|
@@ -56,7 +67,7 @@ async function createOrReplaceJob(job) {
|
|
|
56
67
|
return newJob;
|
|
57
68
|
}
|
|
58
69
|
if (!job.timeZone) {
|
|
59
|
-
job.timeZone =
|
|
70
|
+
job.timeZone = job.pubsubTarget ? DEFAULT_TIME_ZONE_V1 : DEFAULT_TIME_ZONE_V2;
|
|
60
71
|
}
|
|
61
72
|
if (!needUpdate(existingJob.body, job)) {
|
|
62
73
|
logger_1.logger.debug(`scheduler job ${jobName} is up to date, no changes required`);
|
|
@@ -90,9 +101,9 @@ function needUpdate(existingJob, newJob) {
|
|
|
90
101
|
}
|
|
91
102
|
return false;
|
|
92
103
|
}
|
|
93
|
-
function jobNameForEndpoint(endpoint,
|
|
104
|
+
function jobNameForEndpoint(endpoint, location) {
|
|
94
105
|
const id = backend.scheduleIdForFunction(endpoint);
|
|
95
|
-
return `projects/${endpoint.project}/locations/${
|
|
106
|
+
return `projects/${endpoint.project}/locations/${location}/jobs/${id}`;
|
|
96
107
|
}
|
|
97
108
|
exports.jobNameForEndpoint = jobNameForEndpoint;
|
|
98
109
|
function topicNameForEndpoint(endpoint) {
|
|
@@ -100,10 +111,11 @@ function topicNameForEndpoint(endpoint) {
|
|
|
100
111
|
return `projects/${endpoint.project}/topics/${id}`;
|
|
101
112
|
}
|
|
102
113
|
exports.topicNameForEndpoint = topicNameForEndpoint;
|
|
103
|
-
function jobFromEndpoint(endpoint,
|
|
114
|
+
function jobFromEndpoint(endpoint, location, projectNumber) {
|
|
104
115
|
const job = {};
|
|
116
|
+
job.name = jobNameForEndpoint(endpoint, location);
|
|
105
117
|
if (endpoint.platform === "gcfv1") {
|
|
106
|
-
job.
|
|
118
|
+
job.timeZone = endpoint.scheduleTrigger.timeZone || DEFAULT_TIME_ZONE_V1;
|
|
107
119
|
job.pubsubTarget = {
|
|
108
120
|
topicName: topicNameForEndpoint(endpoint),
|
|
109
121
|
attributes: {
|
|
@@ -112,7 +124,14 @@ function jobFromEndpoint(endpoint, appEngineLocation) {
|
|
|
112
124
|
};
|
|
113
125
|
}
|
|
114
126
|
else if (endpoint.platform === "gcfv2") {
|
|
115
|
-
|
|
127
|
+
job.timeZone = endpoint.scheduleTrigger.timeZone || DEFAULT_TIME_ZONE_V2;
|
|
128
|
+
job.httpTarget = {
|
|
129
|
+
uri: endpoint.uri,
|
|
130
|
+
httpMethod: "POST",
|
|
131
|
+
oidcToken: {
|
|
132
|
+
serviceAccountEmail: (0, checkIam_1.getDefaultComputeServiceAgent)(projectNumber),
|
|
133
|
+
},
|
|
134
|
+
};
|
|
116
135
|
}
|
|
117
136
|
else {
|
|
118
137
|
(0, functional_1.assertExhaustive)(endpoint.platform);
|
|
@@ -121,7 +140,6 @@ function jobFromEndpoint(endpoint, appEngineLocation) {
|
|
|
121
140
|
throw new error_1.FirebaseError("Cannot create a scheduler job without a schedule:" + JSON.stringify(endpoint));
|
|
122
141
|
}
|
|
123
142
|
job.schedule = endpoint.scheduleTrigger.schedule;
|
|
124
|
-
job.timeZone = endpoint.scheduleTrigger.timeZone || DEFAULT_TIME_ZONE;
|
|
125
143
|
if (endpoint.scheduleTrigger.retryConfig) {
|
|
126
144
|
job.retryConfig = {};
|
|
127
145
|
proto.copyIfPresent(job.retryConfig, endpoint.scheduleTrigger.retryConfig, "maxDoublings", "retryCount");
|
package/lib/serve/index.js
CHANGED
|
@@ -4,6 +4,9 @@ exports.serve = void 0;
|
|
|
4
4
|
const logger_1 = require("../logger");
|
|
5
5
|
const frameworks_1 = require("../frameworks");
|
|
6
6
|
const previews_1 = require("../previews");
|
|
7
|
+
const track_1 = require("../track");
|
|
8
|
+
const projectUtils_1 = require("../projectUtils");
|
|
9
|
+
const constants_1 = require("../emulator/constants");
|
|
7
10
|
const { FunctionsServer } = require("./functions");
|
|
8
11
|
const TARGETS = {
|
|
9
12
|
hosting: require("./hosting"),
|
|
@@ -17,12 +20,24 @@ async function serve(options) {
|
|
|
17
20
|
[].concat(options.config.get("hosting")).some((it) => it.source)) {
|
|
18
21
|
await (0, frameworks_1.prepareFrameworks)(targetNames, options, options);
|
|
19
22
|
}
|
|
23
|
+
const isDemoProject = constants_1.Constants.isDemoProject((0, projectUtils_1.getProjectId)(options) || "");
|
|
24
|
+
targetNames.forEach((targetName) => {
|
|
25
|
+
void (0, track_1.trackEmulator)("emulator_run", {
|
|
26
|
+
emulator_name: targetName,
|
|
27
|
+
is_demo_project: String(isDemoProject),
|
|
28
|
+
});
|
|
29
|
+
});
|
|
20
30
|
await Promise.all(targetNames.map((targetName) => {
|
|
21
31
|
return TARGETS[targetName].start(options);
|
|
22
32
|
}));
|
|
23
33
|
await Promise.all(targetNames.map((targetName) => {
|
|
24
34
|
return TARGETS[targetName].connect();
|
|
25
35
|
}));
|
|
36
|
+
void (0, track_1.trackEmulator)("emulators_started", {
|
|
37
|
+
count: targetNames.length,
|
|
38
|
+
count_all: targetNames.length,
|
|
39
|
+
is_demo_project: String(isDemoProject),
|
|
40
|
+
});
|
|
26
41
|
await new Promise((resolve) => {
|
|
27
42
|
process.on("SIGINT", () => {
|
|
28
43
|
logger_1.logger.info("Shutting down...");
|
package/lib/track.js
CHANGED
|
@@ -1,16 +1,25 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.track = void 0;
|
|
3
|
+
exports.emulatorSession = exports.trackEmulator = exports.track = exports.usageEnabled = exports.EMULATOR_GA4_MEASUREMENT_ID = void 0;
|
|
4
|
+
const node_fetch_1 = require("node-fetch");
|
|
4
5
|
const ua = require("universal-analytics");
|
|
5
6
|
const uuid_1 = require("uuid");
|
|
7
|
+
const auth_1 = require("./auth");
|
|
6
8
|
const configstore_1 = require("./configstore");
|
|
9
|
+
const logger_1 = require("./logger");
|
|
7
10
|
const pkg = require("../package.json");
|
|
11
|
+
exports.EMULATOR_GA4_MEASUREMENT_ID = process.env.FIREBASE_EMULATOR_GA4_MEASUREMENT_ID || "G-KYP2JMPFC0";
|
|
12
|
+
function usageEnabled() {
|
|
13
|
+
return !!configstore_1.configstore.get("usage");
|
|
14
|
+
}
|
|
15
|
+
exports.usageEnabled = usageEnabled;
|
|
16
|
+
const FIREBASE_ANALYTICS_UA = process.env.FIREBASE_ANALYTICS_UA || "UA-29174744-3";
|
|
8
17
|
let anonId = configstore_1.configstore.get("analytics-uuid");
|
|
9
18
|
if (!anonId) {
|
|
10
19
|
anonId = (0, uuid_1.v4)();
|
|
11
20
|
configstore_1.configstore.set("analytics-uuid", anonId);
|
|
12
21
|
}
|
|
13
|
-
const visitor = ua(
|
|
22
|
+
const visitor = ua(FIREBASE_ANALYTICS_UA, anonId, {
|
|
14
23
|
strictCidFormat: false,
|
|
15
24
|
https: true,
|
|
16
25
|
});
|
|
@@ -19,7 +28,7 @@ visitor.set("cd2", process.version);
|
|
|
19
28
|
visitor.set("cd3", process.env.FIREPIT_VERSION || "none");
|
|
20
29
|
function track(action, label, duration = 0) {
|
|
21
30
|
return new Promise((resolve) => {
|
|
22
|
-
if (configstore_1.configstore.get("tokens") &&
|
|
31
|
+
if (configstore_1.configstore.get("tokens") && usageEnabled()) {
|
|
23
32
|
visitor.event("Firebase CLI " + pkg.version, action, label, duration).send(() => {
|
|
24
33
|
resolve();
|
|
25
34
|
});
|
|
@@ -30,3 +39,113 @@ function track(action, label, duration = 0) {
|
|
|
30
39
|
});
|
|
31
40
|
}
|
|
32
41
|
exports.track = track;
|
|
42
|
+
const EMULATOR_GA4_API_SECRET = process.env.FIREBASE_EMULATOR_GA4_API_SECRET || "2V_zBYc4TdeoppzDaIu0zw";
|
|
43
|
+
const EMULATOR_GA4_USER_PROPS = {
|
|
44
|
+
node_platform: {
|
|
45
|
+
value: process.platform,
|
|
46
|
+
},
|
|
47
|
+
node_version: {
|
|
48
|
+
value: process.version,
|
|
49
|
+
},
|
|
50
|
+
cli_version: {
|
|
51
|
+
value: pkg.version,
|
|
52
|
+
},
|
|
53
|
+
firepit_version: {
|
|
54
|
+
value: process.env.FIREPIT_VERSION || "none",
|
|
55
|
+
},
|
|
56
|
+
};
|
|
57
|
+
async function trackEmulator(eventName, params) {
|
|
58
|
+
const session = emulatorSession();
|
|
59
|
+
if (!session) {
|
|
60
|
+
return;
|
|
61
|
+
}
|
|
62
|
+
const oldTotalEngagementSeconds = session.totalEngagementSeconds;
|
|
63
|
+
session.totalEngagementSeconds = process.uptime();
|
|
64
|
+
session.commandName = (params === null || params === void 0 ? void 0 : params.command_name) || session.commandName;
|
|
65
|
+
const search = `?api_secret=${EMULATOR_GA4_API_SECRET}&measurement_id=${session.measurementId}`;
|
|
66
|
+
const validate = session.validateOnly ? "debug/" : "";
|
|
67
|
+
const url = `https://www.google-analytics.com/${validate}mp/collect${search}`;
|
|
68
|
+
const body = {
|
|
69
|
+
timestamp_micros: `${Date.now()}000`,
|
|
70
|
+
client_id: session.clientId,
|
|
71
|
+
user_properties: Object.assign(Object.assign({}, EMULATOR_GA4_USER_PROPS), { java_major_version: session.javaMajorVersion
|
|
72
|
+
? { value: session.javaMajorVersion }
|
|
73
|
+
: undefined }),
|
|
74
|
+
validationBehavior: session.validateOnly ? "ENFORCE_RECOMMENDATIONS" : undefined,
|
|
75
|
+
events: [
|
|
76
|
+
{
|
|
77
|
+
name: eventName,
|
|
78
|
+
params: Object.assign({ session_id: session.sessionId, engagement_time_msec: (session.totalEngagementSeconds - oldTotalEngagementSeconds)
|
|
79
|
+
.toFixed(3)
|
|
80
|
+
.replace(".", "")
|
|
81
|
+
.replace(/^0+/, ""), debug_mode: session.debugMode ? true : undefined, command_name: session.commandName }, params),
|
|
82
|
+
},
|
|
83
|
+
],
|
|
84
|
+
};
|
|
85
|
+
if (session.validateOnly) {
|
|
86
|
+
logger_1.logger.info(`Sending Analytics for event ${eventName}`, params, body);
|
|
87
|
+
}
|
|
88
|
+
try {
|
|
89
|
+
const response = await (0, node_fetch_1.default)(url, {
|
|
90
|
+
method: "POST",
|
|
91
|
+
headers: {
|
|
92
|
+
"content-type": "application/json;charset=UTF-8",
|
|
93
|
+
},
|
|
94
|
+
body: JSON.stringify(body),
|
|
95
|
+
});
|
|
96
|
+
if (session.validateOnly) {
|
|
97
|
+
if (!response.ok) {
|
|
98
|
+
logger_1.logger.warn(`Analytics validation HTTP error: ${response.status}`);
|
|
99
|
+
}
|
|
100
|
+
const respBody = await response.text();
|
|
101
|
+
logger_1.logger.info(`Analytics validation result: ${respBody}`);
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
catch (e) {
|
|
105
|
+
if (session.validateOnly) {
|
|
106
|
+
throw e;
|
|
107
|
+
}
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
exports.trackEmulator = trackEmulator;
|
|
112
|
+
function emulatorSession() {
|
|
113
|
+
const validateOnly = !!process.env.FIREBASE_CLI_MP_VALIDATE;
|
|
114
|
+
if (!usageEnabled()) {
|
|
115
|
+
if (validateOnly) {
|
|
116
|
+
logger_1.logger.warn("Google Analytics is DISABLED. To enable, (re)login and opt in to collection.");
|
|
117
|
+
}
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
if (!currentEmulatorSession) {
|
|
121
|
+
let clientId = configstore_1.configstore.get("emulator-analytics-clientId");
|
|
122
|
+
if (!clientId) {
|
|
123
|
+
clientId = (0, uuid_1.v4)();
|
|
124
|
+
configstore_1.configstore.set("emulator-analytics-clientId", clientId);
|
|
125
|
+
}
|
|
126
|
+
currentEmulatorSession = {
|
|
127
|
+
measurementId: exports.EMULATOR_GA4_MEASUREMENT_ID,
|
|
128
|
+
clientId,
|
|
129
|
+
sessionId: (Math.random() * Number.MAX_SAFE_INTEGER).toFixed(0),
|
|
130
|
+
totalEngagementSeconds: 0,
|
|
131
|
+
debugMode: isDebugMode(),
|
|
132
|
+
validateOnly,
|
|
133
|
+
};
|
|
134
|
+
}
|
|
135
|
+
return currentEmulatorSession;
|
|
136
|
+
}
|
|
137
|
+
exports.emulatorSession = emulatorSession;
|
|
138
|
+
let currentEmulatorSession = undefined;
|
|
139
|
+
function isDebugMode() {
|
|
140
|
+
const account = (0, auth_1.getGlobalDefaultAccount)();
|
|
141
|
+
if (account === null || account === void 0 ? void 0 : account.user.email.endsWith("@google.com")) {
|
|
142
|
+
try {
|
|
143
|
+
require("../tsconfig.json");
|
|
144
|
+
logger_1.logger.info(`Using Google Analytics in DEBUG mode. Emulators (+ UI) events will be shown in GA Debug View only.`);
|
|
145
|
+
return true;
|
|
146
|
+
}
|
|
147
|
+
catch (_a) {
|
|
148
|
+
}
|
|
149
|
+
}
|
|
150
|
+
return false;
|
|
151
|
+
}
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.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.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");
|
|
@@ -248,6 +248,19 @@ async function promiseWhile(action, check, interval = 2500) {
|
|
|
248
248
|
});
|
|
249
249
|
}
|
|
250
250
|
exports.promiseWhile = promiseWhile;
|
|
251
|
+
function withTimeout(timeoutMs, promise) {
|
|
252
|
+
return new Promise((resolve, reject) => {
|
|
253
|
+
const timeout = setTimeout(() => reject(new Error("Timed out.")), timeoutMs);
|
|
254
|
+
promise.then((value) => {
|
|
255
|
+
clearTimeout(timeout);
|
|
256
|
+
resolve(value);
|
|
257
|
+
}, (err) => {
|
|
258
|
+
clearTimeout(timeout);
|
|
259
|
+
reject(err);
|
|
260
|
+
});
|
|
261
|
+
});
|
|
262
|
+
}
|
|
263
|
+
exports.withTimeout = withTimeout;
|
|
251
264
|
async function promiseProps(obj) {
|
|
252
265
|
const resultObj = {};
|
|
253
266
|
const promises = Object.keys(obj).map(async (key) => {
|