@honeybadger-io/js 6.16.5 → 6.17.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.
@@ -182,6 +182,17 @@ var stackTraceParser_esm = /*#__PURE__*/Object.freeze({
182
182
  var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
183
183
 
184
184
  (function (exports) {
185
+ var __assign = (commonjsGlobal && commonjsGlobal.__assign) || function () {
186
+ __assign = Object.assign || function(t) {
187
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
188
+ s = arguments[i];
189
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
190
+ t[p] = s[p];
191
+ }
192
+ return t;
193
+ };
194
+ return __assign.apply(this, arguments);
195
+ };
185
196
  var __createBinding = (commonjsGlobal && commonjsGlobal.__createBinding) || (Object.create ? (function(o, m, k, k2) {
186
197
  if (k2 === undefined) k2 = k;
187
198
  var desc = Object.getOwnPropertyDescriptor(m, k);
@@ -242,7 +253,7 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
242
253
  }
243
254
  };
244
255
  Object.defineProperty(exports, "__esModule", { value: true });
245
- exports.logDeprecatedMethod = exports.globalThisOrWindow = exports.isBrowserConfig = exports.clone = exports.formatCGIData = exports.filterUrl = exports.filter = exports.generateStackTrace = exports.endpoint = exports.instrumentConsole = exports.instrument = exports.isErrorObject = exports.makeNotice = exports.logger = exports.sanitize = exports.shallowClone = exports.runAfterNotifyHandlers = exports.shouldSampleEvent = exports.resolveInsights = exports.runBeforeEventHandlers = exports.runBeforeNotifyHandlers = exports.getSourceForBacktrace = exports.getCauses = exports.calculateBacktraceShift = exports.DEFAULT_BACKTRACE_SHIFT = exports.makeBacktrace = exports.objectIsExtensible = exports.objectIsEmpty = exports.mergeNotice = exports.merge = void 0;
256
+ exports.logDeprecatedMethod = exports.globalThisOrWindow = exports.isBrowserConfig = exports.clone = exports.formatCGIData = exports.filterBreadcrumbs = exports.filterUrl = exports.filter = exports.generateStackTrace = exports.endpoint = exports.instrumentConsole = exports.instrument = exports.isErrorObject = exports.makeNotice = exports.logger = exports.sanitize = exports.shallowClone = exports.runAfterNotifyHandlers = exports.shouldSampleEvent = exports.resolveInsights = exports.runBeforeBreadcrumbHandlers = exports.runBeforeEventHandlers = exports.runBeforeNotifyHandlers = exports.getSourceForBacktrace = exports.getCauses = exports.calculateBacktraceShift = exports.DEFAULT_BACKTRACE_SHIFT = exports.makeBacktrace = exports.objectIsExtensible = exports.objectIsEmpty = exports.mergeNotice = exports.merge = void 0;
246
257
  /* eslint-disable prefer-rest-params */
247
258
  var stackTraceParser = __importStar(require$$0$1);
248
259
  function merge(obj1, obj2) {
@@ -455,6 +466,25 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
455
466
  });
456
467
  }
457
468
  exports.runBeforeEventHandlers = runBeforeEventHandlers;
469
+ function runBeforeBreadcrumbHandlers(breadcrumb, handlers, logger) {
470
+ for (var i = 0, len = handlers.length; i < len; i++) {
471
+ var result = void 0;
472
+ try {
473
+ result = handlers[i](breadcrumb);
474
+ }
475
+ catch (err) {
476
+ // Breadcrumbs are recorded inside instrumented fetch/XHR/DOM callbacks,
477
+ // so a buggy handler must not throw into the host app. Log and treat as no-op.
478
+ logger === null || logger === void 0 ? void 0 : logger.error('beforeBreadcrumb handler threw; continuing', err);
479
+ continue;
480
+ }
481
+ if (result === false) {
482
+ return false;
483
+ }
484
+ }
485
+ return true;
486
+ }
487
+ exports.runBeforeBreadcrumbHandlers = runBeforeBreadcrumbHandlers;
458
488
  function resolveInsights(config) {
459
489
  var _a, _b;
460
490
  var insights = config.insights;
@@ -828,6 +858,76 @@ var require$$0$1 = /*@__PURE__*/getAugmentedNamespace(stackTraceParser_esm);
828
858
  return result;
829
859
  }
830
860
  exports.filterUrl = filterUrl;
861
+ /**
862
+ * Breadcrumb metadata keys whose value is a URL, and so may carry a query string.
863
+ *
864
+ * Checked by name rather than by running `filterUrl` over every string value: a `?` is
865
+ * ordinary punctuation in a breadcrumb message or a console argument, and rewriting around
866
+ * it would mangle text that is not a URL at all.
867
+ */
868
+ var URL_METADATA_KEYS = ['url', 'from', 'to', 'href'];
869
+ /**
870
+ * Recursively rewrites the query string of every URL-bearing value.
871
+ *
872
+ * Nested as well as top-level: a breadcrumb may well carry
873
+ * `metadata: { request: { url: '/checkout?token=secret' } }`, and `filter` leaves that URL
874
+ * alone because the key `request` matches no filter.
875
+ *
876
+ * Safe to recurse without a seen-list because `filter` has already run: it replaces a
877
+ * circular reference with a string, so what arrives here is acyclic.
878
+ */
879
+ function filterUrlValues(value, filters) {
880
+ if (is('Array', value)) {
881
+ return value.map(function (entry) { return filterUrlValues(entry, filters); });
882
+ }
883
+ if (!is('Object', value)) {
884
+ return value;
885
+ }
886
+ var result = {};
887
+ var source = value;
888
+ // Own enumerable keys only, assigned with `defineProperty`: a plain `result[key] =` would
889
+ // reassign the prototype rather than create a property for a key named `__proto__`, and
890
+ // breadcrumb metadata is host-supplied.
891
+ Object.keys(source).forEach(function (key) {
892
+ var entry = source[key];
893
+ var filtered = URL_METADATA_KEYS.includes(key.toLowerCase()) && typeof entry === 'string'
894
+ ? filterUrl(entry, filters)
895
+ : filterUrlValues(entry, filters);
896
+ Object.defineProperty(result, key, {
897
+ value: filtered,
898
+ enumerable: true,
899
+ writable: true,
900
+ configurable: true
901
+ });
902
+ });
903
+ return result;
904
+ }
905
+ /**
906
+ * Applies `filters` to a breadcrumb trail.
907
+ *
908
+ * Metadata is filtered by key, exactly as `params` and `session` are, and any value under a
909
+ * URL-bearing key additionally has its query string filtered. Breadcrumb metadata is mostly
910
+ * generated by this library -- the XHR, fetch and navigation integrations all record a full
911
+ * URL -- so a query string lands there without the user ever choosing to put it there.
912
+ */
913
+ function filterBreadcrumbs(trail, filters) {
914
+ if (!is('Array', trail)) {
915
+ return [];
916
+ }
917
+ return trail.map(function (breadcrumb) {
918
+ // Leave a crumb that never carried metadata exactly as it is, so the payload shape does
919
+ // not change for it.
920
+ if (!is('Object', breadcrumb === null || breadcrumb === void 0 ? void 0 : breadcrumb.metadata)) {
921
+ return breadcrumb;
922
+ }
923
+ // `filter` runs first, so a key-matched value is already '[FILTERED]' by the time the
924
+ // URL pass sees it. Passing that through `filterUrl` is harmless: it holds no '?', so
925
+ // it is returned untouched.
926
+ var metadata = filterUrlValues(filter(breadcrumb.metadata, filters), filters);
927
+ return __assign(__assign({}, breadcrumb), { metadata: metadata });
928
+ });
929
+ }
930
+ exports.filterBreadcrumbs = filterBreadcrumbs;
831
931
  function formatCGIData(vars, prefix) {
832
932
  if (prefix === void 0) { prefix = ''; }
833
933
  var formattedVars = {};
@@ -1450,12 +1550,14 @@ var Client = /** @class */ (function () {
1450
1550
  this.__store = null;
1451
1551
  this.__beforeNotifyHandlers = [];
1452
1552
  this.__beforeEventHandlers = [];
1553
+ this.__beforeBreadcrumbHandlers = [];
1554
+ this.__runningBeforeBreadcrumbHandlers = false;
1453
1555
  this.__afterNotifyHandlers = [];
1454
1556
  this.__pendingEvents = new Set();
1455
1557
  this.__notifier = {
1456
1558
  name: '@honeybadger-io/core',
1457
1559
  url: 'https://github.com/honeybadger-io/honeybadger-js/tree/master/packages/core',
1458
- version: '6.16.5'
1560
+ version: '6.17.0'
1459
1561
  };
1460
1562
  this.config = __assign(__assign({}, defaults_1.CONFIG), opts);
1461
1563
  this.__initStore();
@@ -1522,6 +1624,10 @@ var Client = /** @class */ (function () {
1522
1624
  this.__beforeEventHandlers.push(handler);
1523
1625
  return this;
1524
1626
  };
1627
+ Client.prototype.beforeBreadcrumb = function (handler) {
1628
+ this.__beforeBreadcrumbHandlers.push(handler);
1629
+ return this;
1630
+ };
1525
1631
  Client.prototype.afterNotify = function (handler) {
1526
1632
  this.__afterNotifyHandlers.push(handler);
1527
1633
  return this;
@@ -1727,12 +1833,29 @@ var Client = /** @class */ (function () {
1727
1833
  var metadata = (0, util_1.shallowClone)(opts.metadata);
1728
1834
  var category = opts.category || 'custom';
1729
1835
  var timestamp = new Date().toISOString();
1730
- this.__store.addBreadcrumb({
1836
+ var breadcrumb = {
1731
1837
  category: category,
1732
1838
  message: message,
1733
1839
  metadata: metadata,
1734
1840
  timestamp: timestamp
1735
- });
1841
+ };
1842
+ // A handler that logs, or the error we log when a handler throws, goes
1843
+ // through instrumented console methods and lands back here. Skipping the
1844
+ // handlers for those breadcrumbs keeps that from recursing.
1845
+ if (!this.__runningBeforeBreadcrumbHandlers) {
1846
+ this.__runningBeforeBreadcrumbHandlers = true;
1847
+ var keep = void 0;
1848
+ try {
1849
+ keep = (0, util_1.runBeforeBreadcrumbHandlers)(breadcrumb, this.__beforeBreadcrumbHandlers, this.logger);
1850
+ }
1851
+ finally {
1852
+ this.__runningBeforeBreadcrumbHandlers = false;
1853
+ }
1854
+ if (!keep) {
1855
+ return this;
1856
+ }
1857
+ }
1858
+ this.__store.addBreadcrumb(breadcrumb);
1736
1859
  return this;
1737
1860
  };
1738
1861
  /**
@@ -1816,7 +1939,7 @@ var Client = /** @class */ (function () {
1816
1939
  notifier: this.__notifier,
1817
1940
  breadcrumbs: {
1818
1941
  enabled: !!this.config.breadcrumbsEnabled,
1819
- trail: notice.__breadcrumbs || []
1942
+ trail: (0, util_1.filterBreadcrumbs)(notice.__breadcrumbs || [], this.config.filters)
1820
1943
  },
1821
1944
  error: {
1822
1945
  class: notice.name,