firebase-tools 11.5.0 → 11.6.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 (35) hide show
  1. package/lib/command.js +33 -7
  2. package/lib/commands/emulators-exec.js +4 -1
  3. package/lib/commands/emulators-export.js +5 -2
  4. package/lib/commands/emulators-start.js +23 -17
  5. package/lib/commands/ext-dev-publish.js +3 -0
  6. package/lib/commands/login.js +2 -2
  7. package/lib/emulator/auth/index.js +7 -2
  8. package/lib/emulator/auth/operations.js +10 -10
  9. package/lib/emulator/commandUtils.js +32 -15
  10. package/lib/emulator/constants.js +14 -6
  11. package/lib/emulator/controller.js +54 -17
  12. package/lib/emulator/downloadableEmulators.js +7 -7
  13. package/lib/emulator/eventarcEmulator.js +148 -0
  14. package/lib/emulator/extensionsEmulator.js +3 -1
  15. package/lib/emulator/functionsEmulator.js +44 -4
  16. package/lib/emulator/functionsEmulatorShared.js +6 -1
  17. package/lib/emulator/hub.js +7 -3
  18. package/lib/emulator/hubClient.js +2 -2
  19. package/lib/emulator/hubExport.js +22 -2
  20. package/lib/emulator/registry.js +1 -0
  21. package/lib/emulator/storage/files.js +14 -2
  22. package/lib/emulator/storage/rules/runtime.js +2 -2
  23. package/lib/emulator/storage/server.js +2 -1
  24. package/lib/emulator/storage/upload.js +1 -0
  25. package/lib/emulator/types.js +3 -0
  26. package/lib/emulator/ui.js +7 -2
  27. package/lib/extensions/extensionsApi.js +2 -1
  28. package/lib/extensions/extensionsHelper.js +29 -1
  29. package/lib/serve/index.js +15 -0
  30. package/lib/track.js +119 -3
  31. package/lib/utils.js +14 -1
  32. package/npm-shrinkwrap.json +2 -2
  33. package/package.json +1 -1
  34. package/schema/firebase-config.json +12 -0
  35. package/templates/extensions/CHANGELOG.md +1 -7
@@ -17,6 +17,8 @@ const logger_1 = require("../../logger");
17
17
  const adminSdkConfig_1 = require("../adminSdkConfig");
18
18
  const types_1 = require("./rules/types");
19
19
  const upload_1 = require("./upload");
20
+ const track_1 = require("../../track");
21
+ const types_2 = require("../types");
20
22
  class StoredFile {
21
23
  constructor(metadata) {
22
24
  this.metadata = metadata;
@@ -292,7 +294,7 @@ class StorageLayer {
292
294
  get dirPath() {
293
295
  return this._persistence.dirPath;
294
296
  }
295
- async export(storageExportPath) {
297
+ async export(storageExportPath, options) {
296
298
  var e_1, _a;
297
299
  const bucketsList = {
298
300
  buckets: [],
@@ -300,6 +302,11 @@ class StorageLayer {
300
302
  for (const b of await this.listBuckets()) {
301
303
  bucketsList.buckets.push({ id: b.id });
302
304
  }
305
+ void (0, track_1.trackEmulator)("emulator_export", {
306
+ initiated_by: options.initiatedBy,
307
+ emulator_name: types_2.Emulators.STORAGE,
308
+ count: bucketsList.buckets.length,
309
+ });
303
310
  const bucketsFilePath = path.join(storageExportPath, "buckets.json");
304
311
  await fse.writeFile(bucketsFilePath, JSON.stringify(bucketsList, undefined, 2));
305
312
  const blobsDirPath = path.join(storageExportPath, "blobs");
@@ -323,9 +330,14 @@ class StorageLayer {
323
330
  finally { if (e_1) throw e_1.error; }
324
331
  }
325
332
  }
326
- import(storageExportPath) {
333
+ import(storageExportPath, options) {
327
334
  const bucketsFile = path.join(storageExportPath, "buckets.json");
328
335
  const bucketsList = JSON.parse((0, fs_1.readFileSync)(bucketsFile, "utf-8"));
336
+ void (0, track_1.trackEmulator)("emulator_import", {
337
+ initiated_by: options.initiatedBy,
338
+ emulator_name: types_2.Emulators.STORAGE,
339
+ count: bucketsList.buckets.length,
340
+ });
329
341
  for (const b of bucketsList.buckets) {
330
342
  const bucketMetadata = new metadata_1.CloudStorageBucketMetadata(b.id);
331
343
  this._buckets.set(b.id, bucketMetadata);
@@ -65,12 +65,12 @@ class StorageRulesRuntime {
65
65
  get alive() {
66
66
  return this._alive;
67
67
  }
68
- async start(auto_download = true) {
68
+ async start(autoDownload = true) {
69
69
  var _a, _b;
70
70
  const downloadDetails = downloadableEmulators_1.DownloadDetails[types_2.Emulators.STORAGE];
71
71
  const hasEmulator = fs.existsSync(downloadDetails.downloadPath);
72
72
  if (!hasEmulator) {
73
- if (auto_download) {
73
+ if (autoDownload) {
74
74
  if (process.env.CI) {
75
75
  utils.logWarning(`It appears you are running in a CI environment. You can avoid downloading the ${constants_1.Constants.description(types_2.Emulators.STORAGE)} repeatedly by caching the ${downloadDetails.opts.cacheDir} directory.`);
76
76
  }
@@ -36,12 +36,13 @@ function createApp(defaultProjectId, emulator) {
36
36
  type: ["application/json"],
37
37
  }));
38
38
  app.post("/internal/export", async (req, res) => {
39
+ const initiatedBy = req.body.initiatedBy || "unknown";
39
40
  const path = req.body.path;
40
41
  if (!path) {
41
42
  res.status(400).send("Export request body must include 'path'.");
42
43
  return;
43
44
  }
44
- await storageLayer.export(path);
45
+ await storageLayer.export(path, { initiatedBy });
45
46
  res.sendStatus(200);
46
47
  });
47
48
  app.put("/internal/setRules", async (req, res) => {
@@ -65,6 +65,7 @@ class UploadService {
65
65
  };
66
66
  this._uploads.set(upload.id, upload);
67
67
  this._persistence.deleteFile(upload.path, true);
68
+ this._persistence.appendBytes(upload.path, Buffer.alloc(0));
68
69
  return upload;
69
70
  }
70
71
  continueResumableUpload(uploadId, dataRaw) {
@@ -14,6 +14,7 @@ var Emulators;
14
14
  Emulators["LOGGING"] = "logging";
15
15
  Emulators["STORAGE"] = "storage";
16
16
  Emulators["EXTENSIONS"] = "extensions";
17
+ Emulators["EVENTARC"] = "eventarc";
17
18
  })(Emulators = exports.Emulators || (exports.Emulators = {}));
18
19
  exports.DOWNLOADABLE_EMULATORS = [
19
20
  Emulators.FIRESTORE,
@@ -36,12 +37,14 @@ exports.ALL_SERVICE_EMULATORS = [
36
37
  Emulators.HOSTING,
37
38
  Emulators.PUBSUB,
38
39
  Emulators.STORAGE,
40
+ Emulators.EVENTARC,
39
41
  ].filter((v) => v);
40
42
  exports.EMULATORS_SUPPORTED_BY_FUNCTIONS = [
41
43
  Emulators.FIRESTORE,
42
44
  Emulators.DATABASE,
43
45
  Emulators.PUBSUB,
44
46
  Emulators.STORAGE,
47
+ Emulators.EVENTARC,
45
48
  ];
46
49
  exports.EMULATORS_SUPPORTED_BY_UI = [
47
50
  Emulators.AUTH,
@@ -6,6 +6,7 @@ const downloadableEmulators = require("./downloadableEmulators");
6
6
  const registry_1 = require("./registry");
7
7
  const error_1 = require("../error");
8
8
  const constants_1 = require("./constants");
9
+ const track_1 = require("../track");
9
10
  class EmulatorUI {
10
11
  constructor(args) {
11
12
  this.args = args;
@@ -15,14 +16,18 @@ class EmulatorUI {
15
16
  throw new error_1.FirebaseError(`Cannot start ${constants_1.Constants.description(types_1.Emulators.UI)} without ${constants_1.Constants.description(types_1.Emulators.HUB)}!`);
16
17
  }
17
18
  const hubInfo = registry_1.EmulatorRegistry.get(types_1.Emulators.HUB).getInfo();
18
- const { auto_download, host, port, projectId } = this.args;
19
+ const { auto_download: autoDownload, host, port, projectId } = this.args;
19
20
  const env = {
20
21
  HOST: host.toString(),
21
22
  PORT: port.toString(),
22
23
  GCLOUD_PROJECT: projectId,
23
24
  [constants_1.Constants.FIREBASE_EMULATOR_HUB]: registry_1.EmulatorRegistry.getInfoHostString(hubInfo),
24
25
  };
25
- return downloadableEmulators.start(types_1.Emulators.UI, { auto_download }, env);
26
+ const session = (0, track_1.emulatorSession)();
27
+ if (session) {
28
+ env[constants_1.Constants.FIREBASE_GA_SESSION] = JSON.stringify(session);
29
+ }
30
+ return downloadableEmulators.start(types_1.Emulators.UI, { auto_download: autoDownload }, env);
26
31
  }
27
32
  connect() {
28
33
  return Promise.resolve();
@@ -291,13 +291,14 @@ async function listExtensions(publisherId) {
291
291
  return extensions;
292
292
  }
293
293
  exports.listExtensions = listExtensions;
294
- async function listExtensionVersions(ref, filter = "") {
294
+ async function listExtensionVersions(ref, filter = "", showPrereleases = false) {
295
295
  const { publisherId, extensionId } = refs.parse(ref);
296
296
  const extensionVersions = [];
297
297
  const getNextPage = async (pageToken = "") => {
298
298
  const res = await apiClient.get(`/publishers/${publisherId}/extensions/${extensionId}/versions`, {
299
299
  queryParams: {
300
300
  filter,
301
+ showPrereleases: String(showPrereleases),
301
302
  pageSize: PAGE_SIZE_MAX,
302
303
  pageToken,
303
304
  },
@@ -1,6 +1,6 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.canonicalizeRefInput = exports.diagnoseAndFixProject = exports.confirm = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.publishExtensionVersionFromLocalSource = exports.ensureExtensionsApiEnabled = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
3
+ exports.canonicalizeRefInput = exports.diagnoseAndFixProject = exports.confirm = exports.getSourceOrigin = exports.isLocalOrURLPath = exports.isLocalPath = exports.isUrlPath = exports.instanceIdExists = exports.promptForRepeatInstance = exports.promptForOfficialExtension = exports.displayReleaseNotes = exports.getPublisherProjectFromName = exports.createSourceFromLocation = exports.publishExtensionVersionFromLocalSource = exports.incrementPrereleaseVersion = exports.ensureExtensionsApiEnabled = exports.promptForValidInstanceId = exports.validateSpec = exports.validateCommandLineParams = exports.populateDefaultParams = exports.substituteParams = exports.getFirebaseProjectParams = exports.getDBInstanceFromURL = exports.resourceTypeToNiceName = exports.AUTOPOULATED_PARAM_PLACEHOLDERS = exports.EXTENSIONS_BUCKET_NAME = exports.URL_REGEX = exports.logPrefix = exports.SourceOrigin = exports.SpecParamType = void 0;
4
4
  const clc = require("colorette");
5
5
  const ora = require("ora");
6
6
  const semver = require("semver");
@@ -282,6 +282,33 @@ async function archiveAndUploadSource(extPath, bucketName) {
282
282
  const res = await (0, storage_1.uploadObject)(zippedSource, bucketName);
283
283
  return `/${res.bucket}/${res.object}`;
284
284
  }
285
+ async function incrementPrereleaseVersion(ref, extensionVersion, stage) {
286
+ var _a;
287
+ const stageOptions = ["stable", "alpha", "beta", "rc"];
288
+ if (!stageOptions.includes(stage)) {
289
+ throw new error_1.FirebaseError(`--stage flag only supports the following values: ${stageOptions}`);
290
+ }
291
+ if (stage !== "stable") {
292
+ const version = semver.parse(extensionVersion);
293
+ if (version.prerelease.length > 0 || version.build.length > 0) {
294
+ throw new error_1.FirebaseError(`Cannot combine the --stage flag with a version with a prerelease annotation in extension.yaml.`);
295
+ }
296
+ let extensionVersions = [];
297
+ try {
298
+ extensionVersions = await (0, extensionsApi_1.listExtensionVersions)(ref, `id="${version.version}"`, true);
299
+ }
300
+ catch (e) {
301
+ }
302
+ const latestVersion = (_a = extensionVersions
303
+ .map((version) => semver.parse(version.spec.version))
304
+ .filter((version) => version.prerelease.length > 0 && version.prerelease[0] === stage)
305
+ .sort((v1, v2) => semver.compare(v1, v2))
306
+ .pop()) !== null && _a !== void 0 ? _a : `${version}-${stage}`;
307
+ return semver.inc(latestVersion, "prerelease", undefined, stage);
308
+ }
309
+ return extensionVersion;
310
+ }
311
+ exports.incrementPrereleaseVersion = incrementPrereleaseVersion;
285
312
  async function publishExtensionVersionFromLocalSource(args) {
286
313
  const extensionSpec = await (0, localHelper_1.getLocalExtensionSpec)(args.rootDirectory);
287
314
  if (extensionSpec.name !== args.extensionId) {
@@ -290,6 +317,7 @@ async function publishExtensionVersionFromLocalSource(args) {
290
317
  const subbedSpec = JSON.parse(JSON.stringify(extensionSpec));
291
318
  subbedSpec.params = substituteParams(extensionSpec.params || [], exports.AUTOPOULATED_PARAM_PLACEHOLDERS);
292
319
  validateSpec(subbedSpec);
320
+ extensionSpec.version = await incrementPrereleaseVersion(`${args.publisherId}/${args.extensionId}`, extensionSpec.version, args.stage);
293
321
  let extension;
294
322
  try {
295
323
  extension = await (0, extensionsApi_1.getExtension)(`${args.publisherId}/${args.extensionId}`);
@@ -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(process.env.FIREBASE_ANALYTICS_UA || "UA-29174744-3", anonId, {
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") && configstore_1.configstore.get("usage")) {
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,110 @@ 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
+ firepit_version: {
51
+ value: process.env.FIREPIT_VERSION || "none",
52
+ },
53
+ };
54
+ async function trackEmulator(eventName, params) {
55
+ const session = emulatorSession();
56
+ if (!session) {
57
+ return;
58
+ }
59
+ const oldTotalEngagementSeconds = session.totalEngagementSeconds;
60
+ session.totalEngagementSeconds = process.uptime();
61
+ session.commandName = (params === null || params === void 0 ? void 0 : params.command_name) || session.commandName;
62
+ const search = `?api_secret=${EMULATOR_GA4_API_SECRET}&measurement_id=${session.measurementId}`;
63
+ const validate = session.validateOnly ? "debug/" : "";
64
+ const url = `https://www.google-analytics.com/${validate}mp/collect${search}`;
65
+ const body = {
66
+ timestamp_micros: `${Date.now()}000`,
67
+ client_id: session.clientId,
68
+ user_properties: Object.assign(Object.assign({}, EMULATOR_GA4_USER_PROPS), { java_major_version: session.javaMajorVersion
69
+ ? { value: session.javaMajorVersion }
70
+ : undefined }),
71
+ validationBehavior: session.validateOnly ? "ENFORCE_RECOMMENDATIONS" : undefined,
72
+ events: [
73
+ {
74
+ name: eventName,
75
+ params: Object.assign({ session_id: session.sessionId, engagement_time_msec: (session.totalEngagementSeconds - oldTotalEngagementSeconds)
76
+ .toFixed(3)
77
+ .replace(".", "")
78
+ .replace(/^0+/, ""), debug_mode: session.debugMode ? true : undefined, command_name: session.commandName }, params),
79
+ },
80
+ ],
81
+ };
82
+ if (session.validateOnly) {
83
+ logger_1.logger.info(`Sending Analytics for event ${eventName}`, params, body);
84
+ }
85
+ try {
86
+ const response = await (0, node_fetch_1.default)(url, {
87
+ method: "POST",
88
+ headers: {
89
+ "content-type": "application/json;charset=UTF-8",
90
+ },
91
+ body: JSON.stringify(body),
92
+ });
93
+ if (session.validateOnly) {
94
+ if (!response.ok) {
95
+ logger_1.logger.warn(`Analytics validation HTTP error: ${response.status}`);
96
+ }
97
+ const respBody = await response.text();
98
+ logger_1.logger.info(`Analytics validation result: ${respBody}`);
99
+ }
100
+ }
101
+ catch (e) {
102
+ if (session.validateOnly) {
103
+ throw e;
104
+ }
105
+ return;
106
+ }
107
+ }
108
+ exports.trackEmulator = trackEmulator;
109
+ function emulatorSession() {
110
+ const validateOnly = !!process.env.FIREBASE_CLI_MP_VALIDATE;
111
+ if (!usageEnabled()) {
112
+ if (validateOnly) {
113
+ logger_1.logger.warn("Google Analytics is DISABLED. To enable, (re)login and opt in to collection.");
114
+ }
115
+ return;
116
+ }
117
+ if (!currentEmulatorSession) {
118
+ let clientId = configstore_1.configstore.get("emulator-analytics-clientId");
119
+ if (!clientId) {
120
+ clientId = (0, uuid_1.v4)();
121
+ configstore_1.configstore.set("emulator-analytics-clientId", clientId);
122
+ }
123
+ currentEmulatorSession = {
124
+ measurementId: exports.EMULATOR_GA4_MEASUREMENT_ID,
125
+ clientId,
126
+ sessionId: (Math.random() * Number.MAX_SAFE_INTEGER).toFixed(0),
127
+ totalEngagementSeconds: 0,
128
+ debugMode: isDebugMode(),
129
+ validateOnly,
130
+ };
131
+ }
132
+ return currentEmulatorSession;
133
+ }
134
+ exports.emulatorSession = emulatorSession;
135
+ let currentEmulatorSession = undefined;
136
+ function isDebugMode() {
137
+ const account = (0, auth_1.getGlobalDefaultAccount)();
138
+ if (account === null || account === void 0 ? void 0 : account.user.email.endsWith("@google.com")) {
139
+ try {
140
+ require("../tsconfig.json");
141
+ logger_1.logger.info(`Using Google Analytics in DEBUG mode. Emulators (+ UI) events will be shown in GA Debug View only.`);
142
+ return true;
143
+ }
144
+ catch (_a) {
145
+ }
146
+ }
147
+ return false;
148
+ }
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) => {
@@ -1,12 +1,12 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.5.0",
3
+ "version": "11.6.0",
4
4
  "lockfileVersion": 2,
5
5
  "requires": true,
6
6
  "packages": {
7
7
  "": {
8
8
  "name": "firebase-tools",
9
- "version": "11.5.0",
9
+ "version": "11.6.0",
10
10
  "license": "MIT",
11
11
  "dependencies": {
12
12
  "@google-cloud/pubsub": "^3.0.1",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "firebase-tools",
3
- "version": "11.5.0",
3
+ "version": "11.6.0",
4
4
  "description": "Command-Line Interface for Firebase",
5
5
  "main": "./lib/index.js",
6
6
  "bin": {
@@ -174,6 +174,18 @@
174
174
  },
175
175
  "type": "object"
176
176
  },
177
+ "eventarc": {
178
+ "additionalProperties": false,
179
+ "properties": {
180
+ "host": {
181
+ "type": "string"
182
+ },
183
+ "port": {
184
+ "type": "number"
185
+ }
186
+ },
187
+ "type": "object"
188
+ },
177
189
  "extensions": {
178
190
  "properties": {
179
191
  },
@@ -1,7 +1 @@
1
- CHANGELOG.md is how you tell users what has changed in each version of your extension.
2
- When you release a new version, add a new header and release notes for that version.
3
- When users update their instance, they will see the release notes for all versions
4
- between the one they were on and the one they are updating to.
5
-
6
- ## Version 0.0.1
7
- First version
1
+ - Added support for publishing pre-release Extension versions. (#4804)