firebase-tools 10.5.0 → 10.7.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/command.js +4 -4
- package/lib/commands/deploy.js +1 -1
- package/lib/commands/emulators-start.js +7 -2
- package/lib/commands/ext-configure.js +15 -5
- package/lib/commands/ext-export.js +6 -5
- package/lib/commands/ext-install.js +28 -44
- package/lib/commands/ext-update.js +9 -1
- package/lib/commands/functions-delete.js +7 -3
- package/lib/commands/functions-secrets-destroy.js +23 -3
- package/lib/commands/functions-secrets-prune.js +15 -12
- package/lib/commands/functions-secrets-set.js +51 -4
- package/lib/commands/hosting-channel-deploy.js +2 -2
- package/lib/deploy/database/deploy.js +4 -0
- package/lib/deploy/database/index.js +1 -0
- package/lib/deploy/extensions/deploy.js +4 -4
- package/lib/deploy/extensions/deploymentSummary.js +8 -5
- package/lib/deploy/extensions/planner.js +36 -9
- package/lib/deploy/extensions/prepare.js +1 -1
- package/lib/deploy/extensions/secrets.js +2 -2
- package/lib/deploy/extensions/tasks.js +60 -21
- package/lib/deploy/functions/backend.js +37 -6
- package/lib/deploy/functions/build.js +162 -0
- package/lib/deploy/functions/checkIam.js +10 -6
- package/lib/deploy/functions/deploy.js +49 -28
- package/lib/deploy/functions/ensure.js +4 -4
- package/lib/deploy/functions/functionsDeployHelper.js +99 -24
- package/lib/deploy/functions/prepare.js +130 -62
- package/lib/deploy/functions/prepareFunctionsUpload.js +16 -21
- package/lib/deploy/functions/pricing.js +6 -3
- package/lib/deploy/functions/prompts.js +1 -7
- package/lib/deploy/functions/release/fabricator.js +70 -28
- package/lib/deploy/functions/release/index.js +41 -6
- package/lib/deploy/functions/release/planner.js +19 -12
- package/lib/deploy/functions/release/reporter.js +14 -11
- package/lib/deploy/functions/runtimes/discovery/parsing.js +12 -6
- package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +61 -13
- package/lib/deploy/functions/runtimes/node/index.js +1 -1
- package/lib/deploy/functions/runtimes/node/parseRuntimeAndValidateSDK.js +3 -3
- package/lib/deploy/functions/runtimes/node/parseTriggers.js +29 -24
- package/lib/deploy/functions/runtimes/node/versioning.js +2 -2
- package/lib/deploy/functions/services/auth.js +95 -0
- package/lib/deploy/functions/services/index.js +41 -21
- package/lib/deploy/functions/services/storage.js +1 -6
- package/lib/deploy/functions/validate.js +32 -6
- package/lib/deploy/hosting/args.js +2 -0
- package/lib/deploy/hosting/convertConfig.js +39 -8
- package/lib/deploy/hosting/deploy.js +3 -3
- package/lib/deploy/hosting/prepare.js +2 -2
- package/lib/deploy/hosting/release.js +6 -2
- package/lib/deploy/index.js +82 -93
- package/lib/deploy/remoteconfig/deploy.js +4 -0
- package/lib/deploy/remoteconfig/index.js +3 -1
- package/lib/emulator/auth/operations.js +5 -0
- package/lib/emulator/auth/utils.js +3 -25
- package/lib/emulator/controller.js +17 -14
- package/lib/emulator/downloadableEmulators.js +39 -23
- package/lib/emulator/extensions/postinstall.js +41 -0
- package/lib/emulator/extensions/validation.js +2 -2
- package/lib/emulator/extensionsEmulator.js +85 -21
- package/lib/emulator/functionsEmulator.js +88 -10
- package/lib/emulator/functionsEmulatorShared.js +37 -21
- package/lib/emulator/functionsEmulatorShell.js +2 -3
- package/lib/emulator/pubsubEmulator.js +13 -9
- package/lib/emulator/registry.js +34 -12
- package/lib/emulator/storage/apis/firebase.js +13 -8
- package/lib/emulator/storage/apis/gcloud.js +15 -9
- package/lib/emulator/storage/files.js +14 -3
- package/lib/emulator/storage/index.js +9 -1
- package/lib/emulator/storage/metadata.js +18 -8
- package/lib/emulator/storage/rules/manager.js +7 -17
- package/lib/emulator/storage/server.js +38 -12
- package/lib/ensureApiEnabled.js +8 -4
- package/lib/extensions/askUserForParam.js +14 -11
- package/lib/extensions/changelog.js +1 -1
- package/lib/extensions/emulator/optionsHelper.js +9 -10
- package/lib/extensions/emulator/specHelper.js +7 -1
- package/lib/extensions/emulator/triggerHelper.js +11 -14
- package/lib/extensions/extensionsApi.js +2 -1
- package/lib/extensions/extensionsHelper.js +30 -24
- package/lib/extensions/manifest.js +28 -8
- package/lib/extensions/paramHelper.js +19 -13
- package/lib/extensions/provisioningHelper.js +2 -2
- package/lib/extensions/warnings.js +3 -3
- package/lib/functions/env.js +10 -2
- package/lib/functions/events/index.js +7 -0
- package/lib/functions/events/v1.js +6 -0
- package/lib/functions/projectConfig.js +32 -6
- package/lib/functions/runtimeConfigExport.js +10 -6
- package/lib/functions/secrets.js +99 -6
- package/lib/functionsShellCommandAction.js +1 -1
- package/lib/gcp/cloudfunctions.js +44 -18
- package/lib/gcp/cloudfunctionsv2.js +48 -25
- package/lib/gcp/cloudtasks.js +5 -3
- package/lib/gcp/identityPlatform.js +44 -0
- package/lib/gcp/secretManager.js +2 -2
- package/lib/metaprogramming.js +2 -0
- package/lib/previews.js +1 -1
- package/lib/serve/functions.js +16 -19
- package/lib/serve/hosting.js +25 -12
- package/lib/serve/index.js +6 -0
- package/lib/track.js +15 -21
- package/lib/utils.js +30 -1
- package/npm-shrinkwrap.json +44 -2
- package/package.json +4 -1
- package/schema/firebase-config.json +6 -0
|
@@ -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.API_VERSION = void 0;
|
|
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.BLOCKING_LABEL = exports.CODEBASE_LABEL = exports.API_VERSION = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const error_1 = require("../error");
|
|
6
6
|
const logger_1 = require("../logger");
|
|
@@ -9,10 +9,21 @@ const backend = require("../deploy/functions/backend");
|
|
|
9
9
|
const utils = require("../utils");
|
|
10
10
|
const proto = require("./proto");
|
|
11
11
|
const runtimes = require("../deploy/functions/runtimes");
|
|
12
|
+
const projectConfig = require("../functions/projectConfig");
|
|
12
13
|
const apiv2_1 = require("../apiv2");
|
|
13
14
|
const api_1 = require("../api");
|
|
14
15
|
exports.API_VERSION = "v1";
|
|
16
|
+
exports.CODEBASE_LABEL = "firebase-functions-codebase";
|
|
15
17
|
const client = new apiv2_1.Client({ urlPrefix: api_1.functionsOrigin, apiVersion: exports.API_VERSION });
|
|
18
|
+
exports.BLOCKING_LABEL = "deployment-blocking";
|
|
19
|
+
const BLOCKING_LABEL_KEY_TO_EVENT = {
|
|
20
|
+
"before-create": "providers/cloud.auth/eventTypes/user.beforeCreate",
|
|
21
|
+
"before-sign-in": "providers/cloud.auth/eventTypes/user.beforeSignIn",
|
|
22
|
+
};
|
|
23
|
+
const BLOCKING_EVENT_TO_LABEL_KEY = {
|
|
24
|
+
"providers/cloud.auth/eventTypes/user.beforeCreate": "before-create",
|
|
25
|
+
"providers/cloud.auth/eventTypes/user.beforeSignIn": "before-sign-in",
|
|
26
|
+
};
|
|
16
27
|
function validateFunction(func) {
|
|
17
28
|
proto.assertOneOf("Cloud Function", func, "sourceCode", "sourceArchiveUrl", "sourceRepository", "sourceUploadUrl");
|
|
18
29
|
proto.assertOneOf("Cloud Function", func, "trigger", "httpsTrigger", "eventTrigger");
|
|
@@ -202,7 +213,7 @@ async function listAllFunctions(projectId) {
|
|
|
202
213
|
}
|
|
203
214
|
exports.listAllFunctions = listAllFunctions;
|
|
204
215
|
function endpointFromFunction(gcfFunction) {
|
|
205
|
-
var _a, _b, _c, _d, _e;
|
|
216
|
+
var _a, _b, _c, _d, _e, _f, _g;
|
|
206
217
|
const [, project, , region, , id] = gcfFunction.name.split("/");
|
|
207
218
|
let trigger;
|
|
208
219
|
let uri;
|
|
@@ -223,25 +234,29 @@ function endpointFromFunction(gcfFunction) {
|
|
|
223
234
|
callableTrigger: {},
|
|
224
235
|
};
|
|
225
236
|
}
|
|
237
|
+
else if ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[exports.BLOCKING_LABEL]) {
|
|
238
|
+
trigger = {
|
|
239
|
+
blockingTrigger: {
|
|
240
|
+
eventType: BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[exports.BLOCKING_LABEL]],
|
|
241
|
+
},
|
|
242
|
+
};
|
|
243
|
+
}
|
|
226
244
|
else if (gcfFunction.httpsTrigger) {
|
|
227
245
|
trigger = { httpsTrigger: {} };
|
|
228
|
-
uri = gcfFunction.httpsTrigger.url;
|
|
229
|
-
securityLevel = gcfFunction.httpsTrigger.securityLevel;
|
|
230
246
|
}
|
|
231
247
|
else {
|
|
232
248
|
trigger = {
|
|
233
249
|
eventTrigger: {
|
|
234
250
|
eventType: gcfFunction.eventTrigger.eventType,
|
|
235
|
-
eventFilters:
|
|
236
|
-
|
|
237
|
-
attribute: "resource",
|
|
238
|
-
value: gcfFunction.eventTrigger.resource,
|
|
239
|
-
},
|
|
240
|
-
],
|
|
241
|
-
retry: !!((_e = gcfFunction.eventTrigger.failurePolicy) === null || _e === void 0 ? void 0 : _e.retry),
|
|
251
|
+
eventFilters: { resource: gcfFunction.eventTrigger.resource },
|
|
252
|
+
retry: !!((_f = gcfFunction.eventTrigger.failurePolicy) === null || _f === void 0 ? void 0 : _f.retry),
|
|
242
253
|
},
|
|
243
254
|
};
|
|
244
255
|
}
|
|
256
|
+
if (gcfFunction.httpsTrigger) {
|
|
257
|
+
uri = gcfFunction.httpsTrigger.url;
|
|
258
|
+
securityLevel = gcfFunction.httpsTrigger.securityLevel;
|
|
259
|
+
}
|
|
245
260
|
if (!runtimes.isValidRuntime(gcfFunction.runtime)) {
|
|
246
261
|
logger_1.logger.debug("GCFv1 function has a deprecated runtime:", JSON.stringify(gcfFunction, null, 2));
|
|
247
262
|
}
|
|
@@ -254,15 +269,18 @@ function endpointFromFunction(gcfFunction) {
|
|
|
254
269
|
if (securityLevel) {
|
|
255
270
|
endpoint.securityLevel = securityLevel;
|
|
256
271
|
}
|
|
257
|
-
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "
|
|
272
|
+
proto.copyIfPresent(endpoint, gcfFunction, "serviceAccountEmail", "availableMemoryMb", "minInstances", "maxInstances", "ingressSettings", "labels", "environmentVariables", "secretEnvironmentVariables", "sourceUploadUrl");
|
|
273
|
+
proto.renameIfPresent(endpoint, gcfFunction, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
258
274
|
if (gcfFunction.vpcConnector) {
|
|
259
275
|
endpoint.vpc = { connector: gcfFunction.vpcConnector };
|
|
260
276
|
proto.renameIfPresent(endpoint.vpc, gcfFunction, "egressSettings", "vpcConnectorEgressSettings");
|
|
261
277
|
}
|
|
278
|
+
endpoint.codebase = ((_g = gcfFunction.labels) === null || _g === void 0 ? void 0 : _g[exports.CODEBASE_LABEL]) || projectConfig.DEFAULT_CODEBASE;
|
|
262
279
|
return endpoint;
|
|
263
280
|
}
|
|
264
281
|
exports.endpointFromFunction = endpointFromFunction;
|
|
265
282
|
function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
283
|
+
var _a;
|
|
266
284
|
if (endpoint.platform !== "gcfv1") {
|
|
267
285
|
throw new error_1.FirebaseError("Trying to create a v1 CloudFunction with v2 API. This should never happen");
|
|
268
286
|
}
|
|
@@ -278,13 +296,9 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
278
296
|
};
|
|
279
297
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
280
298
|
if (backend.isEventTriggered(endpoint)) {
|
|
281
|
-
const resourceFilter = backend.findEventFilter(endpoint, "resource");
|
|
282
|
-
if (!resourceFilter) {
|
|
283
|
-
throw new error_1.FirebaseError("Invalid event trigger definition. Expected event filter with 'resource' attribute.");
|
|
284
|
-
}
|
|
285
299
|
gcfFunction.eventTrigger = {
|
|
286
300
|
eventType: endpoint.eventTrigger.eventType,
|
|
287
|
-
resource:
|
|
301
|
+
resource: endpoint.eventTrigger.eventFilters.resource,
|
|
288
302
|
};
|
|
289
303
|
gcfFunction.eventTrigger.failurePolicy = endpoint.eventTrigger.retry
|
|
290
304
|
? { retry: {} }
|
|
@@ -302,6 +316,10 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
302
316
|
gcfFunction.httpsTrigger = {};
|
|
303
317
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-taskqueue": "true" });
|
|
304
318
|
}
|
|
319
|
+
else if (backend.isBlockingTriggered(endpoint)) {
|
|
320
|
+
gcfFunction.httpsTrigger = {};
|
|
321
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [exports.BLOCKING_LABEL]: BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
|
|
322
|
+
}
|
|
305
323
|
else {
|
|
306
324
|
gcfFunction.httpsTrigger = {};
|
|
307
325
|
if (backend.isCallableTriggered(endpoint)) {
|
|
@@ -311,11 +329,19 @@ function functionFromEndpoint(endpoint, sourceUploadUrl) {
|
|
|
311
329
|
gcfFunction.httpsTrigger.securityLevel = endpoint.securityLevel;
|
|
312
330
|
}
|
|
313
331
|
}
|
|
314
|
-
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "
|
|
332
|
+
proto.copyIfPresent(gcfFunction, endpoint, "serviceAccountEmail", "availableMemoryMb", "minInstances", "maxInstances", "ingressSettings", "environmentVariables", "secretEnvironmentVariables");
|
|
333
|
+
proto.renameIfPresent(gcfFunction, endpoint, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
315
334
|
if (endpoint.vpc) {
|
|
316
335
|
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnector", "connector");
|
|
317
336
|
proto.renameIfPresent(gcfFunction, endpoint.vpc, "vpcConnectorEgressSettings", "egressSettings");
|
|
318
337
|
}
|
|
338
|
+
const codebase = endpoint.codebase || projectConfig.DEFAULT_CODEBASE;
|
|
339
|
+
if (codebase !== projectConfig.DEFAULT_CODEBASE) {
|
|
340
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [exports.CODEBASE_LABEL]: codebase });
|
|
341
|
+
}
|
|
342
|
+
else {
|
|
343
|
+
(_a = gcfFunction.labels) === null || _a === void 0 ? true : delete _a[exports.CODEBASE_LABEL];
|
|
344
|
+
}
|
|
319
345
|
return gcfFunction;
|
|
320
346
|
}
|
|
321
347
|
exports.functionFromEndpoint = functionFromEndpoint;
|
|
@@ -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.megabytes = exports.API_VERSION = void 0;
|
|
3
|
+
exports.endpointFromFunction = exports.functionFromEndpoint = exports.deleteFunction = exports.updateFunction = exports.listAllFunctions = exports.listFunctions = exports.getFunction = exports.createFunction = exports.generateUploadUrl = exports.megabytes = exports.BLOCKING_LABEL = exports.CODEBASE_LABEL = exports.API_VERSION = void 0;
|
|
4
4
|
const clc = require("cli-color");
|
|
5
5
|
const apiv2_1 = require("../apiv2");
|
|
6
6
|
const error_1 = require("../error");
|
|
@@ -11,12 +11,23 @@ const backend = require("../deploy/functions/backend");
|
|
|
11
11
|
const runtimes = require("../deploy/functions/runtimes");
|
|
12
12
|
const proto = require("./proto");
|
|
13
13
|
const utils = require("../utils");
|
|
14
|
+
const projectConfig = require("../functions/projectConfig");
|
|
14
15
|
exports.API_VERSION = "v2alpha";
|
|
16
|
+
exports.CODEBASE_LABEL = "firebase-functions-codebase";
|
|
15
17
|
const client = new apiv2_1.Client({
|
|
16
18
|
urlPrefix: api_1.functionsV2Origin,
|
|
17
19
|
auth: true,
|
|
18
20
|
apiVersion: exports.API_VERSION,
|
|
19
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
|
+
};
|
|
20
31
|
const BYTES_PER_UNIT = {
|
|
21
32
|
"": 1,
|
|
22
33
|
k: 1e3,
|
|
@@ -146,6 +157,7 @@ async function deleteFunction(cloudFunction) {
|
|
|
146
157
|
}
|
|
147
158
|
exports.deleteFunction = deleteFunction;
|
|
148
159
|
function functionFromEndpoint(endpoint, source) {
|
|
160
|
+
var _a;
|
|
149
161
|
if (endpoint.platform !== "gcfv2") {
|
|
150
162
|
throw new error_1.FirebaseError("Trying to create a v2 CloudFunction with v1 API. This should never happen");
|
|
151
163
|
}
|
|
@@ -166,9 +178,8 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
166
178
|
serviceConfig: {},
|
|
167
179
|
};
|
|
168
180
|
proto.copyIfPresent(gcfFunction, endpoint, "labels");
|
|
169
|
-
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "serviceAccountEmail", "ingressSettings");
|
|
181
|
+
proto.copyIfPresent(gcfFunction.serviceConfig, endpoint, "environmentVariables", "serviceAccountEmail", "ingressSettings", "timeoutSeconds");
|
|
170
182
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "availableMemory", "availableMemoryMb", (mb) => `${mb}M`);
|
|
171
|
-
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "timeoutSeconds", "timeout", proto.secondsFromDuration);
|
|
172
183
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "minInstanceCount", "minInstances");
|
|
173
184
|
proto.renameIfPresent(gcfFunction.serviceConfig, endpoint, "maxInstanceCount", "maxInstances");
|
|
174
185
|
if (endpoint.vpc) {
|
|
@@ -180,25 +191,22 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
180
191
|
eventType: endpoint.eventTrigger.eventType,
|
|
181
192
|
};
|
|
182
193
|
if (gcfFunction.eventTrigger.eventType === v2_1.PUBSUB_PUBLISH_EVENT) {
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
gcfFunction.eventTrigger.pubsubTopic = pubsubFilter.value;
|
|
188
|
-
for (const filter of endpoint.eventTrigger.eventFilters) {
|
|
189
|
-
if (filter.attribute === "topic") {
|
|
194
|
+
gcfFunction.eventTrigger.pubsubTopic = endpoint.eventTrigger.eventFilters.topic;
|
|
195
|
+
gcfFunction.eventTrigger.eventFilters = [];
|
|
196
|
+
for (const [attribute, value] of Object.entries(endpoint.eventTrigger.eventFilters)) {
|
|
197
|
+
if (attribute === "topic")
|
|
190
198
|
continue;
|
|
191
|
-
}
|
|
192
|
-
if (!gcfFunction.eventTrigger.eventFilters) {
|
|
193
|
-
gcfFunction.eventTrigger.eventFilters = [];
|
|
194
|
-
}
|
|
195
|
-
gcfFunction.eventTrigger.eventFilters.push(filter);
|
|
199
|
+
gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
|
|
196
200
|
}
|
|
197
201
|
}
|
|
198
202
|
else {
|
|
199
|
-
gcfFunction.eventTrigger.eventFilters =
|
|
203
|
+
gcfFunction.eventTrigger.eventFilters = [];
|
|
204
|
+
for (const [attribute, value] of Object.entries(endpoint.eventTrigger.eventFilters)) {
|
|
205
|
+
gcfFunction.eventTrigger.eventFilters.push({ attribute, value });
|
|
206
|
+
}
|
|
200
207
|
}
|
|
201
208
|
proto.renameIfPresent(gcfFunction.eventTrigger, endpoint.eventTrigger, "triggerRegion", "region");
|
|
209
|
+
proto.copyIfPresent(gcfFunction.eventTrigger, endpoint.eventTrigger, "channel");
|
|
202
210
|
if (endpoint.eventTrigger.retry) {
|
|
203
211
|
logger_1.logger.warn("Cannot set a retry policy on Cloud Function", endpoint.id);
|
|
204
212
|
}
|
|
@@ -213,11 +221,21 @@ function functionFromEndpoint(endpoint, source) {
|
|
|
213
221
|
else if (backend.isCallableTriggered(endpoint)) {
|
|
214
222
|
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { "deployment-callable": "true" });
|
|
215
223
|
}
|
|
224
|
+
else if (backend.isBlockingTriggered(endpoint)) {
|
|
225
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [exports.BLOCKING_LABEL]: BLOCKING_EVENT_TO_LABEL_KEY[endpoint.blockingTrigger.eventType] });
|
|
226
|
+
}
|
|
227
|
+
const codebase = endpoint.codebase || projectConfig.DEFAULT_CODEBASE;
|
|
228
|
+
if (codebase !== projectConfig.DEFAULT_CODEBASE) {
|
|
229
|
+
gcfFunction.labels = Object.assign(Object.assign({}, gcfFunction.labels), { [exports.CODEBASE_LABEL]: codebase });
|
|
230
|
+
}
|
|
231
|
+
else {
|
|
232
|
+
(_a = gcfFunction.labels) === null || _a === void 0 ? true : delete _a[exports.CODEBASE_LABEL];
|
|
233
|
+
}
|
|
216
234
|
return gcfFunction;
|
|
217
235
|
}
|
|
218
236
|
exports.functionFromEndpoint = functionFromEndpoint;
|
|
219
237
|
function endpointFromFunction(gcfFunction) {
|
|
220
|
-
var _a, _b, _c;
|
|
238
|
+
var _a, _b, _c, _d, _e;
|
|
221
239
|
const [, project, , region, , id] = gcfFunction.name.split("/");
|
|
222
240
|
let trigger;
|
|
223
241
|
if (((_a = gcfFunction.labels) === null || _a === void 0 ? void 0 : _a["deployment-scheduled"]) === "true") {
|
|
@@ -235,25 +253,30 @@ function endpointFromFunction(gcfFunction) {
|
|
|
235
253
|
callableTrigger: {},
|
|
236
254
|
};
|
|
237
255
|
}
|
|
256
|
+
else if ((_d = gcfFunction.labels) === null || _d === void 0 ? void 0 : _d[exports.BLOCKING_LABEL]) {
|
|
257
|
+
trigger = {
|
|
258
|
+
blockingTrigger: {
|
|
259
|
+
eventType: BLOCKING_LABEL_KEY_TO_EVENT[gcfFunction.labels[exports.BLOCKING_LABEL]],
|
|
260
|
+
},
|
|
261
|
+
};
|
|
262
|
+
}
|
|
238
263
|
else if (gcfFunction.eventTrigger) {
|
|
239
264
|
trigger = {
|
|
240
265
|
eventTrigger: {
|
|
241
266
|
eventType: gcfFunction.eventTrigger.eventType,
|
|
242
|
-
eventFilters:
|
|
267
|
+
eventFilters: {},
|
|
243
268
|
retry: false,
|
|
244
269
|
},
|
|
245
270
|
};
|
|
246
271
|
if (gcfFunction.eventTrigger.pubsubTopic) {
|
|
247
|
-
trigger.eventTrigger.eventFilters.
|
|
248
|
-
attribute: "topic",
|
|
249
|
-
value: gcfFunction.eventTrigger.pubsubTopic,
|
|
250
|
-
});
|
|
272
|
+
trigger.eventTrigger.eventFilters.topic = gcfFunction.eventTrigger.pubsubTopic;
|
|
251
273
|
}
|
|
252
274
|
else {
|
|
253
275
|
for (const { attribute, value } of gcfFunction.eventTrigger.eventFilters || []) {
|
|
254
|
-
trigger.eventTrigger.eventFilters
|
|
276
|
+
trigger.eventTrigger.eventFilters[attribute] = value;
|
|
255
277
|
}
|
|
256
278
|
}
|
|
279
|
+
proto.copyIfPresent(trigger.eventTrigger, gcfFunction.eventTrigger, "channel");
|
|
257
280
|
proto.renameIfPresent(trigger.eventTrigger, gcfFunction.eventTrigger, "region", "triggerRegion");
|
|
258
281
|
}
|
|
259
282
|
else {
|
|
@@ -265,9 +288,8 @@ function endpointFromFunction(gcfFunction) {
|
|
|
265
288
|
const endpoint = Object.assign(Object.assign({ platform: "gcfv2", id,
|
|
266
289
|
project,
|
|
267
290
|
region }, trigger), { entryPoint: gcfFunction.buildConfig.entryPoint, runtime: gcfFunction.buildConfig.runtime, uri: gcfFunction.serviceConfig.uri });
|
|
268
|
-
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "ingressSettings", "environmentVariables");
|
|
291
|
+
proto.copyIfPresent(endpoint, gcfFunction.serviceConfig, "serviceAccountEmail", "ingressSettings", "environmentVariables", "timeoutSeconds");
|
|
269
292
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "availableMemoryMb", "availableMemory", megabytes);
|
|
270
|
-
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "timeout", "timeoutSeconds", proto.durationFromSeconds);
|
|
271
293
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "minInstances", "minInstanceCount");
|
|
272
294
|
proto.renameIfPresent(endpoint, gcfFunction.serviceConfig, "maxInstances", "maxInstanceCount");
|
|
273
295
|
proto.copyIfPresent(endpoint, gcfFunction, "labels");
|
|
@@ -275,6 +297,7 @@ function endpointFromFunction(gcfFunction) {
|
|
|
275
297
|
endpoint.vpc = { connector: gcfFunction.serviceConfig.vpcConnector };
|
|
276
298
|
proto.renameIfPresent(endpoint.vpc, gcfFunction.serviceConfig, "egressSettings", "vpcConnectorEgressSettings");
|
|
277
299
|
}
|
|
300
|
+
endpoint.codebase = ((_e = gcfFunction.labels) === null || _e === void 0 ? void 0 : _e[exports.CODEBASE_LABEL]) || projectConfig.DEFAULT_CODEBASE;
|
|
278
301
|
return endpoint;
|
|
279
302
|
}
|
|
280
303
|
exports.endpointFromFunction = endpointFromFunction;
|
package/lib/gcp/cloudtasks.js
CHANGED
|
@@ -13,7 +13,6 @@ const client = new apiv2_1.Client({
|
|
|
13
13
|
exports.DEFAULT_SETTINGS = {
|
|
14
14
|
rateLimits: {
|
|
15
15
|
maxConcurrentDispatches: 1000,
|
|
16
|
-
maxBurstSize: 100,
|
|
17
16
|
maxDispatchesPerSecond: 500,
|
|
18
17
|
},
|
|
19
18
|
state: "RUNNING",
|
|
@@ -133,10 +132,13 @@ exports.queueNameForEndpoint = queueNameForEndpoint;
|
|
|
133
132
|
function queueFromEndpoint(endpoint) {
|
|
134
133
|
const queue = Object.assign(Object.assign({}, JSON.parse(JSON.stringify(exports.DEFAULT_SETTINGS))), { name: queueNameForEndpoint(endpoint) });
|
|
135
134
|
if (endpoint.taskQueueTrigger.rateLimits) {
|
|
136
|
-
proto.copyIfPresent(queue.rateLimits, endpoint.taskQueueTrigger.rateLimits, "
|
|
135
|
+
proto.copyIfPresent(queue.rateLimits, endpoint.taskQueueTrigger.rateLimits, "maxConcurrentDispatches", "maxDispatchesPerSecond");
|
|
137
136
|
}
|
|
138
137
|
if (endpoint.taskQueueTrigger.retryConfig) {
|
|
139
|
-
proto.copyIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxAttempts", "
|
|
138
|
+
proto.copyIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxAttempts", "maxDoublings");
|
|
139
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxRetryDuration", "maxRetrySeconds", proto.durationFromSeconds);
|
|
140
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "maxBackoff", "maxBackoffSeconds", proto.durationFromSeconds);
|
|
141
|
+
proto.renameIfPresent(queue.retryConfig, endpoint.taskQueueTrigger.retryConfig, "minBackoff", "minBackoffSeconds", proto.durationFromSeconds);
|
|
140
142
|
}
|
|
141
143
|
return queue;
|
|
142
144
|
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.updateConfig = exports.setBlockingFunctionsConfig = exports.getConfig = exports.getBlockingFunctionsConfig = void 0;
|
|
4
|
+
const proto = require("./proto");
|
|
5
|
+
const api_1 = require("../api");
|
|
6
|
+
const apiv2_1 = require("../apiv2");
|
|
7
|
+
const API_VERSION = "v2";
|
|
8
|
+
const adminApiClient = new apiv2_1.Client({
|
|
9
|
+
urlPrefix: api_1.identityOrigin + "/admin",
|
|
10
|
+
apiVersion: API_VERSION,
|
|
11
|
+
});
|
|
12
|
+
async function getBlockingFunctionsConfig(project) {
|
|
13
|
+
const config = (await getConfig(project)) || {};
|
|
14
|
+
if (!config.blockingFunctions) {
|
|
15
|
+
config.blockingFunctions = {};
|
|
16
|
+
}
|
|
17
|
+
return config.blockingFunctions;
|
|
18
|
+
}
|
|
19
|
+
exports.getBlockingFunctionsConfig = getBlockingFunctionsConfig;
|
|
20
|
+
async function getConfig(project) {
|
|
21
|
+
const response = await adminApiClient.get(`projects/${project}/config`);
|
|
22
|
+
return response.body;
|
|
23
|
+
}
|
|
24
|
+
exports.getConfig = getConfig;
|
|
25
|
+
async function setBlockingFunctionsConfig(project, blockingConfig) {
|
|
26
|
+
const config = (await updateConfig(project, { blockingFunctions: blockingConfig }, "blockingFunctions")) || {};
|
|
27
|
+
if (!config.blockingFunctions) {
|
|
28
|
+
config.blockingFunctions = {};
|
|
29
|
+
}
|
|
30
|
+
return config.blockingFunctions;
|
|
31
|
+
}
|
|
32
|
+
exports.setBlockingFunctionsConfig = setBlockingFunctionsConfig;
|
|
33
|
+
async function updateConfig(project, config, updateMask) {
|
|
34
|
+
if (!updateMask) {
|
|
35
|
+
updateMask = proto.fieldMasks(config).join(",");
|
|
36
|
+
}
|
|
37
|
+
const response = await adminApiClient.patch(`projects/${project}/config`, config, {
|
|
38
|
+
queryParams: {
|
|
39
|
+
updateMask,
|
|
40
|
+
},
|
|
41
|
+
});
|
|
42
|
+
return response.body;
|
|
43
|
+
}
|
|
44
|
+
exports.updateConfig = updateConfig;
|
package/lib/gcp/secretManager.js
CHANGED
|
@@ -33,7 +33,7 @@ async function listSecrets(projectId, filter) {
|
|
|
33
33
|
? baseOpts
|
|
34
34
|
: Object.assign(Object.assign({}, baseOpts), { queryParams: Object.assign(Object.assign({}, baseOpts === null || baseOpts === void 0 ? void 0 : baseOpts.queryParams), { pageToken }) });
|
|
35
35
|
const res = await client.get(path, opts);
|
|
36
|
-
for (const s of res.body.secrets) {
|
|
36
|
+
for (const s of res.body.secrets || []) {
|
|
37
37
|
secrets.push(Object.assign(Object.assign({}, parseSecretResourceName(s.name)), { labels: (_a = s.labels) !== null && _a !== void 0 ? _a : {} }));
|
|
38
38
|
}
|
|
39
39
|
if (!res.body.nextPageToken) {
|
|
@@ -133,7 +133,7 @@ async function createSecret(projectId, name, labels) {
|
|
|
133
133
|
},
|
|
134
134
|
labels,
|
|
135
135
|
}, { queryParams: { secretId: name } });
|
|
136
|
-
return parseSecretResourceName(createRes.body.name);
|
|
136
|
+
return Object.assign(Object.assign({}, parseSecretResourceName(createRes.body.name)), { labels });
|
|
137
137
|
}
|
|
138
138
|
exports.createSecret = createSecret;
|
|
139
139
|
async function patchSecret(projectId, name, labels) {
|
package/lib/previews.js
CHANGED
|
@@ -3,7 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.previews = void 0;
|
|
4
4
|
const lodash_1 = require("lodash");
|
|
5
5
|
const configstore_1 = require("./configstore");
|
|
6
|
-
exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, extensionsemulator: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, artifactregistry: false, emulatoruisnapshot: false }, configstore_1.configstore.get("previews"));
|
|
6
|
+
exports.previews = Object.assign({ rtdbrules: false, ext: false, extdev: false, extensionsemulator: false, rtdbmanagement: false, functionsv2: false, golang: false, deletegcfartifacts: false, artifactregistry: false, emulatoruisnapshot: false, frameworkawareness: false }, configstore_1.configstore.get("previews"));
|
|
7
7
|
if (process.env.FIREBASE_CLI_PREVIEWS) {
|
|
8
8
|
process.env.FIREBASE_CLI_PREVIEWS.split(",").forEach((feature) => {
|
|
9
9
|
if ((0, lodash_1.has)(exports.previews, feature)) {
|
package/lib/serve/functions.js
CHANGED
|
@@ -10,28 +10,29 @@ const auth_1 = require("../auth");
|
|
|
10
10
|
const projectConfig = require("../functions/projectConfig");
|
|
11
11
|
const utils = require("../utils");
|
|
12
12
|
class FunctionsServer {
|
|
13
|
-
constructor() {
|
|
14
|
-
this.emulatorServer = undefined;
|
|
15
|
-
this.backend = undefined;
|
|
16
|
-
}
|
|
17
13
|
assertServer() {
|
|
18
|
-
if (!this.emulatorServer || !this.
|
|
14
|
+
if (!this.emulatorServer || !this.backends) {
|
|
19
15
|
throw new Error("Must call start() before calling any other operation!");
|
|
20
16
|
}
|
|
21
17
|
}
|
|
22
18
|
async start(options, partialArgs) {
|
|
23
19
|
const projectId = (0, projectUtils_1.needProjectId)(options);
|
|
24
|
-
const config = projectConfig.normalizeAndValidate(options.config.src.functions)
|
|
25
|
-
const
|
|
20
|
+
const config = projectConfig.normalizeAndValidate(options.config.src.functions);
|
|
21
|
+
const backends = [];
|
|
22
|
+
for (const cfg of config) {
|
|
23
|
+
const functionsDir = path.join(options.config.projectDir, cfg.source);
|
|
24
|
+
const nodeMajorVersion = (0, functionsEmulatorUtils_1.parseRuntimeVersion)(cfg.runtime);
|
|
25
|
+
backends.push({
|
|
26
|
+
functionsDir,
|
|
27
|
+
codebase: cfg.codebase,
|
|
28
|
+
nodeMajorVersion,
|
|
29
|
+
env: {},
|
|
30
|
+
secretEnv: [],
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
this.backends = backends;
|
|
26
34
|
const account = (0, auth_1.getProjectDefaultAccount)(options.config.projectDir);
|
|
27
|
-
const
|
|
28
|
-
this.backend = {
|
|
29
|
-
functionsDir,
|
|
30
|
-
nodeMajorVersion,
|
|
31
|
-
env: {},
|
|
32
|
-
secretEnv: [],
|
|
33
|
-
};
|
|
34
|
-
const args = Object.assign({ projectId, projectDir: options.config.projectDir, emulatableBackends: [this.backend], projectAlias: options.projectAlias, account }, partialArgs);
|
|
35
|
+
const args = Object.assign({ projectId, projectDir: options.config.projectDir, emulatableBackends: this.backends, projectAlias: options.projectAlias, account }, partialArgs);
|
|
35
36
|
if (options.host) {
|
|
36
37
|
utils.assertIsStringOrUndefined(options.host);
|
|
37
38
|
args.host = options.host;
|
|
@@ -59,10 +60,6 @@ class FunctionsServer {
|
|
|
59
60
|
this.assertServer();
|
|
60
61
|
await this.emulatorServer.stop();
|
|
61
62
|
}
|
|
62
|
-
getBackend() {
|
|
63
|
-
this.assertServer();
|
|
64
|
-
return this.backend;
|
|
65
|
-
}
|
|
66
63
|
get() {
|
|
67
64
|
this.assertServer();
|
|
68
65
|
return this.emulatorServer.get();
|
package/lib/serve/hosting.js
CHANGED
|
@@ -15,6 +15,7 @@ const stream_1 = require("stream");
|
|
|
15
15
|
const emulatorLogger_1 = require("../emulator/emulatorLogger");
|
|
16
16
|
const types_1 = require("../emulator/types");
|
|
17
17
|
const utils_1 = require("../utils");
|
|
18
|
+
const child_process_1 = require("child_process");
|
|
18
19
|
const MAX_PORT_ATTEMPTS = 10;
|
|
19
20
|
let attempts = 0;
|
|
20
21
|
let destroyServer = undefined;
|
|
@@ -31,6 +32,29 @@ function startServer(options, config, port, init) {
|
|
|
31
32
|
const morganMiddleware = morgan("combined", {
|
|
32
33
|
stream: morganStream,
|
|
33
34
|
});
|
|
35
|
+
const portInUse = () => {
|
|
36
|
+
const message = "Port " + options.port + " is not available.";
|
|
37
|
+
logger.log("WARN", clc.yellow("hosting: ") + message + " Trying another port...");
|
|
38
|
+
if (attempts < MAX_PORT_ATTEMPTS) {
|
|
39
|
+
attempts++;
|
|
40
|
+
startServer(options, config, port + 5, init);
|
|
41
|
+
}
|
|
42
|
+
else {
|
|
43
|
+
logger.log("WARN", message);
|
|
44
|
+
throw new error_1.FirebaseError("Could not find an open port for hosting development server.", {
|
|
45
|
+
exit: 1,
|
|
46
|
+
});
|
|
47
|
+
}
|
|
48
|
+
};
|
|
49
|
+
if (process.platform === "darwin") {
|
|
50
|
+
try {
|
|
51
|
+
(0, child_process_1.execSync)(`lsof -i :${port}`);
|
|
52
|
+
portInUse();
|
|
53
|
+
return;
|
|
54
|
+
}
|
|
55
|
+
catch (e) {
|
|
56
|
+
}
|
|
57
|
+
}
|
|
34
58
|
const server = superstatic({
|
|
35
59
|
debug: false,
|
|
36
60
|
port: port,
|
|
@@ -60,18 +84,7 @@ function startServer(options, config, port, init) {
|
|
|
60
84
|
destroyServer = (0, utils_1.createDestroyer)(server);
|
|
61
85
|
server.on("error", (err) => {
|
|
62
86
|
if (err.code === "EADDRINUSE") {
|
|
63
|
-
|
|
64
|
-
logger.log("WARN", clc.yellow("hosting: ") + message + " Trying another port...");
|
|
65
|
-
if (attempts < MAX_PORT_ATTEMPTS) {
|
|
66
|
-
attempts++;
|
|
67
|
-
startServer(options, config, port + 5, init);
|
|
68
|
-
}
|
|
69
|
-
else {
|
|
70
|
-
logger.log("WARN", message);
|
|
71
|
-
throw new error_1.FirebaseError("Could not find an open port for hosting development server.", {
|
|
72
|
-
exit: 1,
|
|
73
|
-
});
|
|
74
|
-
}
|
|
87
|
+
portInUse();
|
|
75
88
|
}
|
|
76
89
|
else {
|
|
77
90
|
throw new error_1.FirebaseError("An error occurred while starting the hosting development server:\n\n" + err.toString(), { exit: 1 });
|
package/lib/serve/index.js
CHANGED
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.serve = void 0;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const logger_1 = require("../logger");
|
|
6
|
+
const previews_1 = require("../previews");
|
|
6
7
|
const { FunctionsServer } = require("./functions");
|
|
7
8
|
const TARGETS = {
|
|
8
9
|
hosting: require("./hosting"),
|
|
@@ -11,6 +12,11 @@ const TARGETS = {
|
|
|
11
12
|
async function serve(options) {
|
|
12
13
|
const targetNames = options.targets;
|
|
13
14
|
options.port = parseInt(options.port, 10);
|
|
15
|
+
if (previews_1.previews.frameworkawareness &&
|
|
16
|
+
targetNames.includes("hosting") &&
|
|
17
|
+
[].concat(options.config.get("hosting")).some((it) => it.source)) {
|
|
18
|
+
await require("firebase-frameworks").prepare(targetNames, { project: options.projectId }, options);
|
|
19
|
+
}
|
|
14
20
|
await Promise.all(_.map(targetNames, (targetName) => {
|
|
15
21
|
return TARGETS[targetName].start(options);
|
|
16
22
|
}));
|
package/lib/track.js
CHANGED
|
@@ -1,31 +1,26 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
const
|
|
8
|
-
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.track = void 0;
|
|
4
|
+
const ua = require("universal-analytics");
|
|
5
|
+
const uuid_1 = require("uuid");
|
|
6
|
+
const configstore_1 = require("./configstore");
|
|
7
|
+
const pkg = require("../package.json");
|
|
8
|
+
let anonId = configstore_1.configstore.get("analytics-uuid");
|
|
9
9
|
if (!anonId) {
|
|
10
|
-
anonId =
|
|
11
|
-
configstore.set("analytics-uuid", anonId);
|
|
10
|
+
anonId = (0, uuid_1.v4)();
|
|
11
|
+
configstore_1.configstore.set("analytics-uuid", anonId);
|
|
12
12
|
}
|
|
13
|
-
|
|
13
|
+
const visitor = ua(process.env.FIREBASE_ANALYTICS_UA || "UA-29174744-3", anonId, {
|
|
14
14
|
strictCidFormat: false,
|
|
15
15
|
https: true,
|
|
16
16
|
});
|
|
17
17
|
visitor.set("cd1", process.platform);
|
|
18
18
|
visitor.set("cd2", process.version);
|
|
19
19
|
visitor.set("cd3", process.env.FIREPIT_VERSION || "none");
|
|
20
|
-
function track(action, label, duration) {
|
|
21
|
-
return new Promise(
|
|
22
|
-
if (
|
|
23
|
-
|
|
24
|
-
resolve();
|
|
25
|
-
}
|
|
26
|
-
duration = duration || 0;
|
|
27
|
-
if (configstore.get("tokens") && configstore.get("usage")) {
|
|
28
|
-
visitor.event("Firebase CLI " + pkg.version, action, label, duration).send(function () {
|
|
20
|
+
function track(action, label, duration = 0) {
|
|
21
|
+
return new Promise((resolve) => {
|
|
22
|
+
if (configstore_1.configstore.get("tokens") && configstore_1.configstore.get("usage")) {
|
|
23
|
+
visitor.event("Firebase CLI " + pkg.version, action, label, duration).send(() => {
|
|
29
24
|
resolve();
|
|
30
25
|
});
|
|
31
26
|
}
|
|
@@ -34,5 +29,4 @@ function track(action, label, duration) {
|
|
|
34
29
|
}
|
|
35
30
|
});
|
|
36
31
|
}
|
|
37
|
-
|
|
38
|
-
module.exports = track;
|
|
32
|
+
exports.track = track;
|
package/lib/utils.js
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
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.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;
|
|
4
4
|
const _ = require("lodash");
|
|
5
5
|
const url = require("url");
|
|
6
6
|
const clc = require("cli-color");
|
|
@@ -406,3 +406,32 @@ function groupBy(arr, f) {
|
|
|
406
406
|
}, {});
|
|
407
407
|
}
|
|
408
408
|
exports.groupBy = groupBy;
|
|
409
|
+
function cloneArray(arr) {
|
|
410
|
+
return arr.map((e) => cloneDeep(e));
|
|
411
|
+
}
|
|
412
|
+
function cloneObject(obj) {
|
|
413
|
+
const clone = {};
|
|
414
|
+
for (const [k, v] of Object.entries(obj)) {
|
|
415
|
+
clone[k] = cloneDeep(v);
|
|
416
|
+
}
|
|
417
|
+
return clone;
|
|
418
|
+
}
|
|
419
|
+
function cloneDeep(obj) {
|
|
420
|
+
if (typeof obj !== "object" || !obj) {
|
|
421
|
+
return obj;
|
|
422
|
+
}
|
|
423
|
+
if (obj instanceof RegExp) {
|
|
424
|
+
return RegExp(obj, obj.flags);
|
|
425
|
+
}
|
|
426
|
+
if (obj instanceof Date) {
|
|
427
|
+
return new Date(obj);
|
|
428
|
+
}
|
|
429
|
+
if (Array.isArray(obj)) {
|
|
430
|
+
return cloneArray(obj);
|
|
431
|
+
}
|
|
432
|
+
if (obj instanceof Map) {
|
|
433
|
+
return new Map(obj.entries());
|
|
434
|
+
}
|
|
435
|
+
return cloneObject(obj);
|
|
436
|
+
}
|
|
437
|
+
exports.cloneDeep = cloneDeep;
|