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.
Files changed (63) hide show
  1. package/lib/command.js +33 -7
  2. package/lib/commands/crashlytics-mappingfile-generateid.js +26 -0
  3. package/lib/commands/crashlytics-mappingfile-upload.js +46 -0
  4. package/lib/commands/crashlytics-symbols-upload.js +18 -87
  5. package/lib/commands/emulators-exec.js +4 -1
  6. package/lib/commands/emulators-export.js +5 -2
  7. package/lib/commands/emulators-start.js +23 -17
  8. package/lib/commands/ext-dev-publish.js +3 -0
  9. package/lib/commands/functions-delete.js +2 -0
  10. package/lib/commands/functions-secrets-get.js +2 -0
  11. package/lib/commands/index.js +3 -0
  12. package/lib/commands/login.js +2 -2
  13. package/lib/crashlytics/buildToolsJarHelper.js +51 -0
  14. package/lib/deploy/functions/backend.js +4 -4
  15. package/lib/deploy/functions/build.js +76 -9
  16. package/lib/deploy/functions/checkIam.js +6 -5
  17. package/lib/deploy/functions/params.js +22 -16
  18. package/lib/deploy/functions/prepare.js +1 -1
  19. package/lib/deploy/functions/release/fabricator.js +22 -5
  20. package/lib/deploy/functions/release/index.js +2 -0
  21. package/lib/deploy/functions/runtimes/discovery/index.js +1 -16
  22. package/lib/deploy/functions/runtimes/discovery/parsing.js +16 -0
  23. package/lib/deploy/functions/runtimes/discovery/v1alpha1.js +59 -131
  24. package/lib/deploy/functions/runtimes/node/parseTriggers.js +1 -1
  25. package/lib/emulator/auth/index.js +7 -2
  26. package/lib/emulator/auth/operations.js +10 -10
  27. package/lib/emulator/commandUtils.js +32 -15
  28. package/lib/emulator/constants.js +14 -6
  29. package/lib/emulator/controller.js +49 -17
  30. package/lib/emulator/downloadableEmulators.js +7 -7
  31. package/lib/emulator/eventarcEmulator.js +148 -0
  32. package/lib/emulator/extensionsEmulator.js +3 -1
  33. package/lib/emulator/functionsEmulator.js +44 -4
  34. package/lib/emulator/functionsEmulatorRuntime.js +12 -23
  35. package/lib/emulator/functionsEmulatorShared.js +6 -1
  36. package/lib/emulator/hub.js +7 -3
  37. package/lib/emulator/hubClient.js +2 -2
  38. package/lib/emulator/hubExport.js +22 -2
  39. package/lib/emulator/registry.js +1 -0
  40. package/lib/emulator/storage/apis/firebase.js +145 -129
  41. package/lib/emulator/storage/apis/gcloud.js +102 -42
  42. package/lib/emulator/storage/files.js +39 -17
  43. package/lib/emulator/storage/metadata.js +76 -55
  44. package/lib/emulator/storage/multipart.js +2 -2
  45. package/lib/emulator/storage/rules/runtime.js +12 -4
  46. package/lib/emulator/storage/server.js +2 -1
  47. package/lib/emulator/storage/upload.js +46 -9
  48. package/lib/emulator/types.js +3 -0
  49. package/lib/emulator/ui.js +7 -2
  50. package/lib/extensions/extensionsApi.js +2 -1
  51. package/lib/extensions/extensionsHelper.js +29 -1
  52. package/lib/functions/constants.js +14 -0
  53. package/lib/functions/env.js +9 -9
  54. package/lib/gcp/cloudfunctions.js +15 -18
  55. package/lib/gcp/cloudfunctionsv2.js +15 -18
  56. package/lib/gcp/cloudscheduler.js +32 -14
  57. package/lib/serve/index.js +15 -0
  58. package/lib/track.js +122 -3
  59. package/lib/utils.js +14 -1
  60. package/npm-shrinkwrap.json +542 -9
  61. package/package.json +5 -4
  62. package/schema/firebase-config.json +12 -0
  63. package/templates/extensions/CHANGELOG.md +1 -7
@@ -1,7 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.backendFromV1Alpha1 = exports.buildFromV1Alpha1 = void 0;
4
- const backend = require("../../backend");
3
+ exports.buildFromV1Alpha1 = void 0;
5
4
  const build = require("../../build");
6
5
  const proto_1 = require("../../../../gcp/proto");
7
6
  const parsing_1 = require("./parsing");
@@ -27,33 +26,13 @@ function buildFromV1Alpha1(yaml, project, region, runtime) {
27
26
  bd.requiredAPIs = parseRequiredAPIs(manifest);
28
27
  for (const id of Object.keys(manifest.endpoints)) {
29
28
  const me = manifest.endpoints[id];
30
- assertManifestEndpoint(me, id);
29
+ assertBuildEndpoint(me, id);
31
30
  const be = parseEndpointForBuild(id, me, project, region, runtime);
32
31
  bd.endpoints[id] = be;
33
32
  }
34
33
  return bd;
35
34
  }
36
35
  exports.buildFromV1Alpha1 = buildFromV1Alpha1;
37
- function backendFromV1Alpha1(yaml, project, region, runtime) {
38
- const manifest = JSON.parse(JSON.stringify(yaml));
39
- const bkend = backend.empty();
40
- bkend.requiredAPIs = parseRequiredAPIs(manifest);
41
- (0, parsing_1.requireKeys)("", manifest, "endpoints");
42
- (0, parsing_1.assertKeyTypes)("", manifest, {
43
- specVersion: "string",
44
- params: "array",
45
- requiredAPIs: "array",
46
- endpoints: "object",
47
- });
48
- for (const id of Object.keys(manifest.endpoints)) {
49
- for (const parsed of parseEndpoints(manifest, id, project, region, runtime)) {
50
- bkend.endpoints[parsed.region] = bkend.endpoints[parsed.region] || {};
51
- bkend.endpoints[parsed.region][parsed.id] = parsed;
52
- }
53
- }
54
- return bkend;
55
- }
56
- exports.backendFromV1Alpha1 = backendFromV1Alpha1;
57
36
  function parseRequiredAPIs(manifest) {
58
37
  const requiredAPIs = manifest.requiredAPIs || [];
59
38
  for (const { api, reason } of requiredAPIs) {
@@ -66,22 +45,22 @@ function parseRequiredAPIs(manifest) {
66
45
  }
67
46
  return requiredAPIs;
68
47
  }
69
- function assertManifestEndpoint(ep, id) {
48
+ function assertBuildEndpoint(ep, id) {
70
49
  const prefix = `endpoints[${id}]`;
71
50
  (0, parsing_1.assertKeyTypes)(prefix, ep, {
72
51
  region: "array",
73
- platform: (platform) => backend.AllFunctionsPlatforms.includes(platform),
52
+ platform: (platform) => build.AllFunctionsPlatforms.includes(platform),
74
53
  entryPoint: "string",
75
- availableMemoryMb: (mem) => mem === null || backend.isValidMemoryOption(mem),
76
- maxInstances: "number?",
77
- minInstances: "number?",
78
- concurrency: "number?",
54
+ availableMemoryMb: (mem) => mem === null || isCEL(mem) || build.isValidMemoryOption(mem),
55
+ maxInstances: "Field<number>?",
56
+ minInstances: "Field<number>?",
57
+ concurrency: "Field<number>?",
79
58
  serviceAccount: "string?",
80
59
  serviceAccountEmail: "string?",
81
- timeoutSeconds: "number?",
60
+ timeoutSeconds: "Field<number>?",
82
61
  vpc: "object?",
83
62
  labels: "object?",
84
- ingressSettings: (setting) => setting === null || backend.AllIngressSettings.includes(setting),
63
+ ingressSettings: (setting) => setting === null || build.AllIngressSettings.includes(setting),
85
64
  environmentVariables: "object?",
86
65
  secretEnvironmentVariables: "array?",
87
66
  httpsTrigger: "object",
@@ -90,12 +69,12 @@ function assertManifestEndpoint(ep, id) {
90
69
  scheduleTrigger: "object",
91
70
  taskQueueTrigger: "object",
92
71
  blockingTrigger: "object",
93
- cpu: (cpu) => cpu === null || typeof cpu === "number" || cpu === "gcf_gen1",
72
+ cpu: (cpu) => cpu === null || isCEL(cpu) || cpu === "gcf_gen1" || typeof cpu === "number",
94
73
  });
95
74
  if (ep.vpc) {
96
75
  (0, parsing_1.assertKeyTypes)(prefix + ".vpc", ep.vpc, {
97
76
  connector: "string",
98
- egressSettings: (setting) => setting === null || backend.AllVpcEgressSettings.includes(setting),
77
+ egressSettings: (setting) => setting === null || build.AllVpcEgressSettings.includes(setting),
99
78
  });
100
79
  (0, parsing_1.requireKeys)(prefix + ".vpc", ep.vpc, "connector");
101
80
  }
@@ -124,44 +103,46 @@ function assertManifestEndpoint(ep, id) {
124
103
  if (triggerCount > 1) {
125
104
  throw new error_1.FirebaseError("Multiple triggers defined for endpoint" + id);
126
105
  }
127
- if (backend.isEventTriggered(ep)) {
106
+ if (build.isEventTriggered(ep)) {
128
107
  (0, parsing_1.requireKeys)(prefix + ".eventTrigger", ep.eventTrigger, "eventType", "eventFilters");
129
108
  (0, parsing_1.assertKeyTypes)(prefix + ".eventTrigger", ep.eventTrigger, {
130
109
  eventFilters: "object",
131
110
  eventFilterPathPatterns: "object",
132
111
  eventType: "string",
133
- retry: "boolean",
134
- region: "string",
112
+ retry: "Field<boolean>",
113
+ region: "Field<string>",
135
114
  serviceAccount: "string?",
136
115
  serviceAccountEmail: "string?",
137
116
  channel: "string",
138
117
  });
139
118
  }
140
- else if (backend.isHttpsTriggered(ep)) {
119
+ else if (build.isHttpsTriggered(ep)) {
141
120
  (0, parsing_1.assertKeyTypes)(prefix + ".httpsTrigger", ep.httpsTrigger, {
142
121
  invoker: "array?",
143
122
  });
144
123
  }
145
- else if (backend.isCallableTriggered(ep)) {
124
+ else if (build.isCallableTriggered(ep)) {
146
125
  }
147
- else if (backend.isScheduleTriggered(ep)) {
126
+ else if (build.isScheduleTriggered(ep)) {
148
127
  (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger", ep.scheduleTrigger, {
149
- schedule: "string",
150
- timeZone: "string?",
128
+ schedule: "Field<string>",
129
+ timeZone: "Field<string>?",
151
130
  retryConfig: "object?",
152
131
  });
153
- (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger.retryConfig", ep.scheduleTrigger.retryConfig || {}, {
154
- retryCount: "number?",
155
- maxDoublings: "number?",
156
- minBackoffSeconds: "number?",
157
- maxBackoffSeconds: "number?",
158
- maxRetrySeconds: "number?",
159
- minBackoffDuration: "string?",
160
- maxBackoffDuration: "string?",
161
- maxRetryDuration: "string?",
162
- });
132
+ if (ep.scheduleTrigger.retryConfig) {
133
+ (0, parsing_1.assertKeyTypes)(prefix + ".scheduleTrigger.retryConfig", ep.scheduleTrigger.retryConfig, {
134
+ retryCount: "Field<number>?",
135
+ maxDoublings: "Field<number>?",
136
+ minBackoffSeconds: "Field<number>?",
137
+ maxBackoffSeconds: "Field<number>?",
138
+ maxRetrySeconds: "Field<number>?",
139
+ maxRetryDuration: "string?",
140
+ minBackoffDuration: "string?",
141
+ maxBackoffDuration: "string?",
142
+ });
143
+ }
163
144
  }
164
- else if (backend.isTaskQueueTriggered(ep)) {
145
+ else if (build.isTaskQueueTriggered(ep)) {
165
146
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger", ep.taskQueueTrigger, {
166
147
  rateLimits: "object?",
167
148
  retryConfig: "object?",
@@ -169,21 +150,21 @@ function assertManifestEndpoint(ep, id) {
169
150
  });
170
151
  if (ep.taskQueueTrigger.rateLimits) {
171
152
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.rateLimits", ep.taskQueueTrigger.rateLimits, {
172
- maxConcurrentDispatches: "number?",
173
- maxDispatchesPerSecond: "number?",
153
+ maxConcurrentDispatches: "Field<number>?",
154
+ maxDispatchesPerSecond: "Field<number>?",
174
155
  });
175
156
  }
176
157
  if (ep.taskQueueTrigger.retryConfig) {
177
158
  (0, parsing_1.assertKeyTypes)(prefix + ".taskQueueTrigger.retryConfig", ep.taskQueueTrigger.retryConfig, {
178
- maxAttempts: "number?",
179
- maxRetrySeconds: "number?",
180
- minBackoffSeconds: "number?",
181
- maxBackoffSeconds: "number?",
182
- maxDoublings: "number?",
159
+ maxAttempts: "Field<number>?",
160
+ maxRetrySeconds: "Field<number>?",
161
+ minBackoffSeconds: "Field<number>?",
162
+ maxBackoffSeconds: "Field<number>?",
163
+ maxDoublings: "Field<number>?",
183
164
  });
184
165
  }
185
166
  }
186
- else if (backend.isBlockingTriggered(ep)) {
167
+ else if (build.isBlockingTriggered(ep)) {
187
168
  (0, parsing_1.requireKeys)(prefix + ".blockingTrigger", ep.blockingTrigger, "eventType");
188
169
  (0, parsing_1.assertKeyTypes)(prefix + ".blockingTrigger", ep.blockingTrigger, {
189
170
  eventType: "string",
@@ -198,12 +179,14 @@ function assertManifestEndpoint(ep, id) {
198
179
  function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
199
180
  var _a;
200
181
  let triggered;
201
- if (backend.isEventTriggered(ep)) {
182
+ if (build.isEventTriggered(ep)) {
202
183
  const eventTrigger = {
203
184
  eventType: ep.eventTrigger.eventType,
204
185
  retry: ep.eventTrigger.retry,
205
186
  };
206
- (0, proto_1.renameIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "serviceAccountEmail");
187
+ if ("serviceAccountEmail" in ep.eventTrigger) {
188
+ eventTrigger.serviceAccount = ep.eventTrigger.serviceAccountEmail;
189
+ }
207
190
  (0, proto_1.copyIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "eventFilterPathPatterns", "region");
208
191
  (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "channel", (c) => resolveChannelName(project, c, defaultRegion));
209
192
  (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "eventFilters", (filters) => {
@@ -215,20 +198,23 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
215
198
  });
216
199
  triggered = { eventTrigger };
217
200
  }
218
- else if (backend.isHttpsTriggered(ep)) {
201
+ else if (build.isHttpsTriggered(ep)) {
219
202
  triggered = { httpsTrigger: {} };
220
203
  (0, proto_1.copyIfPresent)(triggered.httpsTrigger, ep.httpsTrigger, "invoker");
221
204
  }
222
- else if (backend.isCallableTriggered(ep)) {
205
+ else if (build.isCallableTriggered(ep)) {
223
206
  triggered = { callableTrigger: {} };
224
207
  }
225
- else if (backend.isScheduleTriggered(ep)) {
208
+ else if (build.isScheduleTriggered(ep)) {
226
209
  const st = {
227
210
  schedule: ep.scheduleTrigger.schedule || "",
228
211
  timeZone: (_a = ep.scheduleTrigger.timeZone) !== null && _a !== void 0 ? _a : null,
229
212
  };
230
213
  if (ep.scheduleTrigger.retryConfig) {
231
214
  st.retryConfig = {};
215
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "maxBackoffSeconds", "maxBackoffDuration", (duration) => (duration === null ? null : (0, proto_1.secondsFromDuration)(duration)));
216
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "minBackoffSeconds", "minBackoffDuration", (duration) => (duration === null ? null : (0, proto_1.secondsFromDuration)(duration)));
217
+ (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "maxRetrySeconds", "maxRetryDuration", (duration) => (duration === null ? null : (0, proto_1.secondsFromDuration)(duration)));
232
218
  (0, proto_1.copyIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "retryCount", "minBackoffSeconds", "maxBackoffSeconds", "maxRetrySeconds", "maxDoublings");
233
219
  (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "minBackoffSeconds", "minBackoffDuration", (0, functional_1.nullsafeVisitor)(proto_1.secondsFromDuration));
234
220
  (0, proto_1.convertIfPresent)(st.retryConfig, ep.scheduleTrigger.retryConfig, "maxBackoffSeconds", "maxBackoffDuration", (0, functional_1.nullsafeVisitor)(proto_1.secondsFromDuration));
@@ -239,7 +225,7 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
239
225
  }
240
226
  triggered = { scheduleTrigger: st };
241
227
  }
242
- else if (backend.isTaskQueueTriggered(ep)) {
228
+ else if (build.isTaskQueueTriggered(ep)) {
243
229
  const tq = {};
244
230
  if (ep.taskQueueTrigger.invoker) {
245
231
  tq.invoker = ep.taskQueueTrigger.invoker;
@@ -261,7 +247,7 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
261
247
  }
262
248
  triggered = { taskQueueTrigger: tq };
263
249
  }
264
- else if (backend.isBlockingTriggered(ep)) {
250
+ else if (ep.blockingTrigger) {
265
251
  triggered = { blockingTrigger: ep.blockingTrigger };
266
252
  }
267
253
  else {
@@ -270,7 +256,9 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
270
256
  }
271
257
  const parsed = Object.assign({ platform: ep.platform || "gcfv2", region: ep.region || [defaultRegion], project,
272
258
  runtime, entryPoint: ep.entryPoint }, triggered);
273
- (0, proto_1.renameIfPresent)(parsed, ep, "serviceAccount", "serviceAccountEmail");
259
+ if ("serviceAccountEmail" in ep) {
260
+ parsed.serviceAccount = ep.serviceAccountEmail;
261
+ }
274
262
  (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "cpu", "maxInstances", "minInstances", "concurrency", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "serviceAccount");
275
263
  (0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
276
264
  if (!senvs) {
@@ -282,69 +270,6 @@ function parseEndpointForBuild(id, ep, project, defaultRegion, runtime) {
282
270
  });
283
271
  return parsed;
284
272
  }
285
- function parseEndpoints(manifest, id, project, defaultRegion, runtime) {
286
- const allParsed = [];
287
- const prefix = `endpoints[${id}]`;
288
- const ep = manifest.endpoints[id];
289
- assertManifestEndpoint(ep, id);
290
- for (const region of ep.region || [defaultRegion]) {
291
- let triggered;
292
- if (backend.isEventTriggered(ep)) {
293
- const eventTrigger = {
294
- eventType: ep.eventTrigger.eventType,
295
- retry: false,
296
- };
297
- (0, proto_1.renameIfPresent)(eventTrigger, ep.eventTrigger, "serviceAccount", "serviceAccountEmail");
298
- (0, proto_1.copyIfPresent)(eventTrigger, ep.eventTrigger, "eventFilterPathPatterns", "retry", "serviceAccount", "region");
299
- (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "channel", (c) => resolveChannelName(project, c, defaultRegion));
300
- (0, proto_1.convertIfPresent)(eventTrigger, ep.eventTrigger, "eventFilters", (filters) => {
301
- const copy = Object.assign({}, filters);
302
- if (copy["topic"] && !copy["topic"].startsWith("projects/")) {
303
- copy["topic"] = `projects/${project}/topics/${copy["topic"]}`;
304
- }
305
- return copy;
306
- });
307
- triggered = { eventTrigger };
308
- }
309
- else if (backend.isHttpsTriggered(ep)) {
310
- triggered = { httpsTrigger: {} };
311
- (0, proto_1.copyIfPresent)(triggered.httpsTrigger, ep.httpsTrigger, "invoker");
312
- }
313
- else if (backend.isCallableTriggered(ep)) {
314
- triggered = { callableTrigger: {} };
315
- }
316
- else if (backend.isScheduleTriggered(ep)) {
317
- triggered = { scheduleTrigger: ep.scheduleTrigger };
318
- }
319
- else if (backend.isTaskQueueTriggered(ep)) {
320
- triggered = { taskQueueTrigger: ep.taskQueueTrigger };
321
- }
322
- else if (backend.isBlockingTriggered(ep)) {
323
- triggered = { blockingTrigger: ep.blockingTrigger };
324
- }
325
- else {
326
- throw new error_1.FirebaseError(`Do not recognize trigger type for endpoint ${id}. Try upgrading ` +
327
- "firebase-tools with npm install -g firebase-tools@latest");
328
- }
329
- (0, parsing_1.requireKeys)(prefix, ep, "entryPoint");
330
- const parsed = Object.assign({ platform: ep.platform || "gcfv2", id,
331
- region,
332
- project,
333
- runtime, entryPoint: ep.entryPoint }, triggered);
334
- (0, proto_1.renameIfPresent)(parsed, ep, "serviceAccount", "serviceAccountEmail");
335
- (0, proto_1.copyIfPresent)(parsed, ep, "availableMemoryMb", "maxInstances", "minInstances", "concurrency", "serviceAccount", "timeoutSeconds", "vpc", "labels", "ingressSettings", "environmentVariables", "cpu");
336
- (0, proto_1.convertIfPresent)(parsed, ep, "secretEnvironmentVariables", (senvs) => {
337
- if (!senvs) {
338
- return null;
339
- }
340
- return senvs.map(({ key, secret }) => {
341
- return { key, secret: secret || key, projectId: project };
342
- });
343
- });
344
- allParsed.push(parsed);
345
- }
346
- return allParsed;
347
- }
348
273
  function resolveChannelName(projectId, channel, defaultRegion) {
349
274
  if (!channel.includes("/")) {
350
275
  const location = defaultRegion;
@@ -365,3 +290,6 @@ function resolveChannelName(projectId, channel, defaultRegion) {
365
290
  return "projects/" + projectId + "/locations/" + location + "/channels/" + channelId;
366
291
  }
367
292
  }
293
+ function isCEL(expr) {
294
+ return typeof expr === "string" && expr.includes("{{") && expr.includes("}}");
295
+ }
@@ -116,7 +116,7 @@ function addResourcesToBuild(projectId, runtime, annotation, want) {
116
116
  proto.copyIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxAttempts", "maxDoublings");
117
117
  proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "minBackoffSeconds", "minBackoff", toSeconds);
118
118
  proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxBackoffSeconds", "maxBackoff", toSeconds);
119
- proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxRetryDurationSeconds", "maxRetryDuration", toSeconds);
119
+ proto.convertIfPresent(triggered.taskQueueTrigger.retryConfig, annotation.taskQueueTrigger.retryConfig, "maxRetrySeconds", "maxRetryDuration", toSeconds);
120
120
  }
121
121
  }
122
122
  else if (annotation.httpsTrigger) {
@@ -10,6 +10,7 @@ const emulatorLogger_1 = require("../emulatorLogger");
10
10
  const types_1 = require("../types");
11
11
  const server_1 = require("./server");
12
12
  const error_1 = require("../../error");
13
+ const track_1 = require("../../track");
13
14
  class AuthEmulator {
14
15
  constructor(args) {
15
16
  this.args = args;
@@ -37,8 +38,12 @@ class AuthEmulator {
37
38
  getName() {
38
39
  return types_1.Emulators.AUTH;
39
40
  }
40
- async importData(authExportDir, projectId) {
41
- const logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.DATABASE);
41
+ async importData(authExportDir, projectId, options) {
42
+ void (0, track_1.trackEmulator)("emulator_import", {
43
+ initiated_by: options.initiatedBy,
44
+ emulator_name: types_1.Emulators.AUTH,
45
+ });
46
+ const logger = emulatorLogger_1.EmulatorLogger.forEmulator(types_1.Emulators.AUTH);
42
47
  const { host, port } = this.getInfo();
43
48
  const configPath = path.join(authExportDir, "config.json");
44
49
  const configStat = await stat(configPath);
@@ -340,7 +340,7 @@ function batchCreate(state, reqBody) {
340
340
  }
341
341
  fields.emailVerified = !!userInfo.emailVerified;
342
342
  fields.disabled = !!userInfo.disabled;
343
- if (userInfo.mfaInfo) {
343
+ if (userInfo.mfaInfo && userInfo.mfaInfo.length > 0) {
344
344
  fields.mfaInfo = [];
345
345
  (0, errors_1.assert)(fields.email, "Second factor account requires email to be presented.");
346
346
  (0, errors_1.assert)(fields.emailVerified, "Second factor account requires email to be verified.");
@@ -1716,14 +1716,14 @@ function fakeFetchUserInfoFromIdp(providerId, claims, samlResponse) {
1716
1716
  switch (providerId) {
1717
1717
  case "google.com": {
1718
1718
  federatedId = `https://accounts.google.com/${rawId}`;
1719
- let granted_scopes = "openid https://www.googleapis.com/auth/userinfo.profile";
1719
+ let grantedScopes = "openid https://www.googleapis.com/auth/userinfo.profile";
1720
1720
  if (email) {
1721
- granted_scopes += " https://www.googleapis.com/auth/userinfo.email";
1721
+ grantedScopes += " https://www.googleapis.com/auth/userinfo.email";
1722
1722
  }
1723
1723
  response.firstName = claims.given_name;
1724
1724
  response.lastName = claims.family_name;
1725
1725
  response.rawUserInfo = JSON.stringify({
1726
- granted_scopes,
1726
+ granted_scopes: grantedScopes,
1727
1727
  id: rawId,
1728
1728
  name: displayName,
1729
1729
  given_name: claims.given_name,
@@ -2064,7 +2064,7 @@ function generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options
2064
2064
  jwt.tenant_id = state.tenantId;
2065
2065
  jwt.user_record.tenant_id = state.tenantId;
2066
2066
  }
2067
- const provider_data = [];
2067
+ const providerData = [];
2068
2068
  if (user.providerUserInfo) {
2069
2069
  for (const providerUserInfo of user.providerUserInfo) {
2070
2070
  const provider = {
@@ -2075,12 +2075,12 @@ function generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options
2075
2075
  uid: providerUserInfo.rawId,
2076
2076
  phone_number: providerUserInfo.phoneNumber,
2077
2077
  };
2078
- provider_data.push(provider);
2078
+ providerData.push(provider);
2079
2079
  }
2080
2080
  }
2081
- jwt.user_record.provider_data = provider_data;
2081
+ jwt.user_record.provider_data = providerData;
2082
2082
  if (user.mfaInfo) {
2083
- const enrolled_factors = [];
2083
+ const enrolledFactors = [];
2084
2084
  for (const mfaEnrollment of user.mfaInfo) {
2085
2085
  if (!mfaEnrollment.mfaEnrollmentId) {
2086
2086
  continue;
@@ -2092,10 +2092,10 @@ function generateBlockingFunctionJwt(state, event, url, timeoutMs, user, options
2092
2092
  phone_number: mfaEnrollment.phoneInfo,
2093
2093
  factor_id: state_1.PROVIDER_PHONE,
2094
2094
  };
2095
- enrolled_factors.push(enrolledFactor);
2095
+ enrolledFactors.push(enrolledFactor);
2096
2096
  }
2097
2097
  jwt.user_record.multi_factor = {
2098
- enrolled_factors,
2098
+ enrolled_factors: enrolledFactors,
2099
2099
  };
2100
2100
  }
2101
2101
  if (user.lastLoginAt || user.createdAt) {
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.JAVA_DEPRECATION_WARNING = exports.checkJavaSupported = exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
3
+ exports.JAVA_DEPRECATION_WARNING = exports.MIN_SUPPORTED_JAVA_MAJOR_VERSION = exports.checkJavaMajorVersion = exports.emulatorExec = exports.shutdownWhenKilled = exports.setExportOnExitOptions = exports.parseInspectionPort = exports.beforeEmulatorCommand = exports.warnEmulatorNotSupported = exports.printNoticeIfEmulated = exports.DESC_TEST_PARAMS = exports.FLAG_TEST_PARAMS = exports.DESC_TEST_CONFIG = exports.FLAG_TEST_CONFIG = exports.DESC_UI = exports.FLAG_UI = exports.EXPORT_ON_EXIT_CWD_DANGER = exports.EXPORT_ON_EXIT_USAGE_ERROR = exports.DESC_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT = exports.FLAG_EXPORT_ON_EXIT_NAME = exports.DESC_IMPORT = exports.FLAG_IMPORT = exports.DESC_INSPECT_FUNCTIONS = exports.FLAG_INSPECT_FUNCTIONS = exports.DESC_ONLY = exports.FLAG_ONLY = void 0;
4
4
  const clc = require("colorette");
5
5
  const childProcess = require("child_process");
6
6
  const controller = require("../emulator/controller");
@@ -20,6 +20,7 @@ const prompt_1 = require("../prompt");
20
20
  const controller_1 = require("./controller");
21
21
  const fsutils = require("../fsutils");
22
22
  const Table = require("cli-table");
23
+ const track_1 = require("../track");
23
24
  exports.FLAG_ONLY = "--only <emulators>";
24
25
  exports.DESC_ONLY = "only specific emulators. " +
25
26
  "This is a comma separated list of emulator names. " +
@@ -43,7 +44,14 @@ exports.FLAG_TEST_CONFIG = "--test-config <firebase.json file>";
43
44
  exports.DESC_TEST_CONFIG = "A firebase.json style file. Used to configure the Firestore and Realtime Database emulators.";
44
45
  exports.FLAG_TEST_PARAMS = "--test-params <params.env file>";
45
46
  exports.DESC_TEST_PARAMS = "A .env file containing test param values for your emulated extension.";
46
- const DEFAULT_CONFIG = new config_1.Config({ database: {}, firestore: {}, functions: {}, hosting: {}, emulators: { auth: {}, pubsub: {} } }, {});
47
+ const DEFAULT_CONFIG = new config_1.Config({
48
+ eventarc: {},
49
+ database: {},
50
+ firestore: {},
51
+ functions: {},
52
+ hosting: {},
53
+ emulators: { auth: {}, pubsub: {} },
54
+ }, {});
47
55
  function printNoticeIfEmulated(options, emulator) {
48
56
  if (emulator !== types_1.Emulators.DATABASE && emulator !== types_1.Emulators.FIRESTORE) {
49
57
  return;
@@ -201,14 +209,10 @@ function shutdownWhenKilled(options) {
201
209
  ["SIGINT", "SIGTERM", "SIGHUP", "SIGQUIT"].forEach((signal) => {
202
210
  process.on(signal, processKillSignal(signal, res, rej, options));
203
211
  });
204
- })
205
- .then(() => {
206
- process.exit(0);
207
- })
208
- .catch((e) => {
212
+ }).catch((e) => {
209
213
  logger_1.logger.debug(e);
210
214
  utils.logLabeledWarning("emulators", "emulators failed to shut down cleanly, see firebase-debug.log for details.");
211
- process.exit(1);
215
+ throw e;
212
216
  });
213
217
  }
214
218
  exports.shutdownWhenKilled = shutdownWhenKilled;
@@ -247,6 +251,12 @@ async function runScript(script, extraEnv) {
247
251
  const address = registry_1.EmulatorRegistry.getInfoHostString(info);
248
252
  env[constants_1.Constants.FIREBASE_EMULATOR_HUB] = address;
249
253
  }
254
+ const eventarcInstance = registry_1.EmulatorRegistry.get(types_1.Emulators.EVENTARC);
255
+ if (eventarcInstance) {
256
+ const info = eventarcInstance.getInfo();
257
+ const address = registry_1.EmulatorRegistry.getInfoHostString(info);
258
+ env[constants_1.Constants.CLOUD_EVENTARC_EMULATOR_HOST] = address;
259
+ }
250
260
  const proc = childProcess.spawn(script, {
251
261
  stdio: ["inherit", "inherit", "inherit"],
252
262
  shell: true,
@@ -280,12 +290,15 @@ async function runScript(script, extraEnv) {
280
290
  });
281
291
  }
282
292
  async function emulatorExec(script, options) {
283
- shutdownWhenKilled(options);
284
293
  const projectId = (0, projectUtils_1.getProjectId)(options);
285
294
  const extraEnv = {};
286
295
  if (projectId) {
287
296
  extraEnv.GCLOUD_PROJECT = projectId;
288
297
  }
298
+ const session = (0, track_1.emulatorSession)();
299
+ if (session && session.debugMode) {
300
+ extraEnv[constants_1.Constants.FIREBASE_GA_SESSION] = JSON.stringify(session);
301
+ }
289
302
  let exitCode = 0;
290
303
  let deprecationNotices;
291
304
  try {
@@ -308,9 +321,8 @@ async function emulatorExec(script, options) {
308
321
  }
309
322
  exports.emulatorExec = emulatorExec;
310
323
  const JAVA_VERSION_REGEX = /version "([1-9][0-9]*)/;
311
- const MIN_SUPPORTED_JAVA_MAJOR_VERSION = 11;
312
324
  const JAVA_HINT = "Please make sure Java is installed and on your system PATH.";
313
- async function checkJavaSupported() {
325
+ async function checkJavaMajorVersion() {
314
326
  return new Promise((resolve, reject) => {
315
327
  var _a, _b;
316
328
  let child;
@@ -351,25 +363,30 @@ async function checkJavaSupported() {
351
363
  }
352
364
  });
353
365
  }).then((output) => {
366
+ let versionInt = -1;
354
367
  const match = output.match(JAVA_VERSION_REGEX);
355
368
  if (match) {
356
369
  const version = match[1];
357
- const versionInt = parseInt(version, 10);
370
+ versionInt = parseInt(version, 10);
358
371
  if (!versionInt) {
359
372
  utils.logLabeledWarning("emulators", `Failed to parse Java version. Got "${match[0]}".`, "warn");
360
373
  }
361
374
  else {
362
375
  logger_1.logger.debug(`Parsed Java major version: ${versionInt}`);
363
- return versionInt >= MIN_SUPPORTED_JAVA_MAJOR_VERSION;
364
376
  }
365
377
  }
366
378
  else {
367
379
  logger_1.logger.debug("java -version outputs:", output);
368
380
  logger_1.logger.warn(`Failed to parse Java version.`);
369
381
  }
370
- return false;
382
+ const session = (0, track_1.emulatorSession)();
383
+ if (session) {
384
+ session.javaMajorVersion = versionInt;
385
+ }
386
+ return versionInt;
371
387
  });
372
388
  }
373
- exports.checkJavaSupported = checkJavaSupported;
389
+ exports.checkJavaMajorVersion = checkJavaMajorVersion;
390
+ exports.MIN_SUPPORTED_JAVA_MAJOR_VERSION = 11;
374
391
  exports.JAVA_DEPRECATION_WARNING = "firebase-tools no longer supports Java version before 11. " +
375
392
  "Please upgrade to Java version 11 or above to continue using the emulators.";
@@ -1,8 +1,8 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.Constants = exports.EMULATOR_DESCRIPTION = exports.FIND_AVAILBLE_PORT_BY_DEFAULT = void 0;
3
+ exports.Constants = exports.DEFAULT_HOST = exports.EMULATOR_DESCRIPTION = exports.FIND_AVAILBLE_PORT_BY_DEFAULT = exports.DEFAULT_PORTS = void 0;
4
4
  const url = require("url");
5
- const DEFAULT_PORTS = {
5
+ exports.DEFAULT_PORTS = {
6
6
  ui: 4000,
7
7
  hub: 4400,
8
8
  logging: 4500,
@@ -14,6 +14,7 @@ const DEFAULT_PORTS = {
14
14
  database: 9000,
15
15
  auth: 9099,
16
16
  storage: 9199,
17
+ eventarc: 9299,
17
18
  };
18
19
  exports.FIND_AVAILBLE_PORT_BY_DEFAULT = {
19
20
  ui: true,
@@ -27,6 +28,7 @@ exports.FIND_AVAILBLE_PORT_BY_DEFAULT = {
27
28
  auth: false,
28
29
  storage: false,
29
30
  extensions: false,
31
+ eventarc: true,
30
32
  };
31
33
  exports.EMULATOR_DESCRIPTION = {
32
34
  ui: "Emulator UI",
@@ -40,8 +42,9 @@ exports.EMULATOR_DESCRIPTION = {
40
42
  auth: "Authentication Emulator",
41
43
  storage: "Storage Emulator",
42
44
  extensions: "Extensions Emulator",
45
+ eventarc: "Eventarc Emulator",
43
46
  };
44
- const DEFAULT_HOST = "localhost";
47
+ exports.DEFAULT_HOST = "localhost";
45
48
  class Constants {
46
49
  static getServiceName(service) {
47
50
  switch (service) {
@@ -63,15 +66,17 @@ class Constants {
63
66
  return "storage";
64
67
  case this.SERVICE_TEST_LAB:
65
68
  return "test lab";
69
+ case this.SERVICE_EVENTARC:
70
+ return "eventarc";
66
71
  default:
67
72
  return service;
68
73
  }
69
74
  }
70
75
  static getDefaultHost() {
71
- return DEFAULT_HOST;
76
+ return exports.DEFAULT_HOST;
72
77
  }
73
78
  static getDefaultPort(emulator) {
74
- return DEFAULT_PORTS[emulator];
79
+ return exports.DEFAULT_PORTS[emulator];
75
80
  }
76
81
  static description(name) {
77
82
  return exports.EMULATOR_DESCRIPTION[name];
@@ -82,7 +87,7 @@ class Constants {
82
87
  normalized = `http://${normalized}`;
83
88
  }
84
89
  const u = url.parse(normalized);
85
- return u.hostname || DEFAULT_HOST;
90
+ return u.hostname || exports.DEFAULT_HOST;
86
91
  }
87
92
  static isDemoProject(projectId) {
88
93
  return !!projectId && projectId.startsWith(this.FAKE_PROJECT_ID_PREFIX);
@@ -97,10 +102,13 @@ Constants.FIREBASE_DATABASE_EMULATOR_HOST = "FIREBASE_DATABASE_EMULATOR_HOST";
97
102
  Constants.FIREBASE_AUTH_EMULATOR_HOST = "FIREBASE_AUTH_EMULATOR_HOST";
98
103
  Constants.FIREBASE_STORAGE_EMULATOR_HOST = "FIREBASE_STORAGE_EMULATOR_HOST";
99
104
  Constants.CLOUD_STORAGE_EMULATOR_HOST = "STORAGE_EMULATOR_HOST";
105
+ Constants.CLOUD_EVENTARC_EMULATOR_HOST = "CLOUD_EVENTARC_EMULATOR_HOST";
100
106
  Constants.FIREBASE_EMULATOR_HUB = "FIREBASE_EMULATOR_HUB";
107
+ Constants.FIREBASE_GA_SESSION = "FIREBASE_GA_SESSION";
101
108
  Constants.SERVICE_FIRESTORE = "firestore.googleapis.com";
102
109
  Constants.SERVICE_REALTIME_DATABASE = "firebaseio.com";
103
110
  Constants.SERVICE_PUBSUB = "pubsub.googleapis.com";
111
+ Constants.SERVICE_EVENTARC = "eventarc.googleapis.com";
104
112
  Constants.SERVICE_ANALYTICS = "app-measurement.com";
105
113
  Constants.SERVICE_AUTH = "firebaseauth.googleapis.com";
106
114
  Constants.SERVICE_CRASHLYTICS = "fabric.io";