@honeybadger-io/js 4.0.0-beta.0 → 4.0.0-beta.3

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.
@@ -4,8 +4,8 @@ var https = require('https');
4
4
  var http = require('http');
5
5
  var url = require('url');
6
6
  var os = require('os');
7
- var fs = require('fs');
8
7
  var domain = require('domain');
8
+ var fs = require('fs');
9
9
 
10
10
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
11
 
@@ -13,8 +13,8 @@ var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
13
13
  var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
14
14
  var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
15
15
  var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
16
- var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
17
16
  var domain__default = /*#__PURE__*/_interopDefaultLegacy(domain);
17
+ var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
18
18
 
19
19
  /*! *****************************************************************************
20
20
  Copyright (c) Microsoft Corporation.
@@ -56,45 +56,7 @@ var __assign = function() {
56
56
  return t;
57
57
  };
58
58
  return __assign.apply(this, arguments);
59
- };
60
-
61
- function __awaiter(thisArg, _arguments, P, generator) {
62
- function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
63
- return new (P || (P = Promise))(function (resolve, reject) {
64
- function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
65
- function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
66
- function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
67
- step((generator = generator.apply(thisArg, _arguments || [])).next());
68
- });
69
- }
70
-
71
- function __generator(thisArg, body) {
72
- var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
73
- return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
74
- function verb(n) { return function (v) { return step([n, v]); }; }
75
- function step(op) {
76
- if (f) throw new TypeError("Generator is already executing.");
77
- while (_) try {
78
- if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
79
- if (y = 0, t) op = [op[0] & 2, t.value];
80
- switch (op[0]) {
81
- case 0: case 1: t = op; break;
82
- case 4: _.label++; return { value: op[1], done: false };
83
- case 5: _.label++; y = op[1]; op = [0]; continue;
84
- case 7: op = _.ops.pop(); _.trys.pop(); continue;
85
- default:
86
- if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
87
- if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
88
- if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
89
- if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
90
- if (t[2]) _.ops.pop();
91
- _.trys.pop(); continue;
92
- }
93
- op = body.call(thisArg, _);
94
- } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
95
- if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
96
- }
97
- }
59
+ };
98
60
 
99
61
  var UNKNOWN_FUNCTION = '<unknown>';
100
62
  /**
@@ -307,7 +269,7 @@ function runBeforeNotifyHandlers(notice, handlers) {
307
269
  }
308
270
  function runAfterNotifyHandlers(notice, handlers, error) {
309
271
  if (notice && notice.afterNotify) {
310
- handlers.unshift(notice.afterNotify);
272
+ notice.afterNotify(error, notice);
311
273
  }
312
274
  for (var i = 0, len = handlers.length; i < len; i++) {
313
275
  handlers[i](error, notice);
@@ -315,7 +277,7 @@ function runAfterNotifyHandlers(notice, handlers, error) {
315
277
  return true;
316
278
  }
317
279
  // Returns a new object with properties from other object.
318
- function newObject(obj) {
280
+ function shallowClone(obj) {
319
281
  if (typeof (obj) !== 'object' || obj === null) {
320
282
  return {};
321
283
  }
@@ -342,8 +304,14 @@ function sanitize(obj, maxDepth) {
342
304
  return false;
343
305
  }
344
306
  function canSerialize(obj) {
345
- // Functions are TMI and Symbols can't convert to strings.
346
- if (/function|symbol/.test(typeof (obj))) {
307
+ var typeOfObj = typeof obj;
308
+ // Functions are TMI
309
+ if (/function/.test(typeOfObj)) {
310
+ // Let special toJSON method pass as it's used by JSON.stringify (#722)
311
+ return obj.name === 'toJSON';
312
+ }
313
+ // Symbols can't convert to strings.
314
+ if (/symbol/.test(typeOfObj)) {
347
315
  return false;
348
316
  }
349
317
  if (obj === null) {
@@ -370,7 +338,7 @@ function sanitize(obj, maxDepth) {
370
338
  }
371
339
  // Serialize inside arrays
372
340
  if (Array.isArray(obj)) {
373
- return obj.map(function (o) { return serialize(o, depth + 1); });
341
+ return obj.map(function (o) { return safeSerialize(o, depth + 1); });
374
342
  }
375
343
  // Serialize inside objects
376
344
  if (typeof (obj) === 'object') {
@@ -378,7 +346,7 @@ function sanitize(obj, maxDepth) {
378
346
  for (var k in obj) {
379
347
  var v = obj[k];
380
348
  if (Object.prototype.hasOwnProperty.call(obj, k) && (k != null) && (v != null)) {
381
- ret[k] = serialize(v, depth + 1);
349
+ ret[k] = safeSerialize(v, depth + 1);
382
350
  }
383
351
  }
384
352
  return ret;
@@ -386,7 +354,16 @@ function sanitize(obj, maxDepth) {
386
354
  // Return everything else untouched
387
355
  return obj;
388
356
  }
389
- return serialize(obj);
357
+ function safeSerialize(obj, depth) {
358
+ if (depth === void 0) { depth = 0; }
359
+ try {
360
+ return serialize(obj, depth);
361
+ }
362
+ catch (e) {
363
+ return "[ERROR] ".concat(e);
364
+ }
365
+ }
366
+ return safeSerialize(obj);
390
367
  }
391
368
  function logger(client) {
392
369
  var log = function (method) {
@@ -425,12 +402,12 @@ function makeNotice(thing) {
425
402
  if (!thing) {
426
403
  notice = {};
427
404
  }
428
- else if (Object.prototype.toString.call(thing) === '[object Error]') {
405
+ else if (thing instanceof Error || Object.prototype.toString.call(thing) === '[object Error]') {
429
406
  var e = thing;
430
407
  notice = merge(thing, { name: e.name, message: e.message, stack: e.stack });
431
408
  }
432
409
  else if (typeof thing === 'object') {
433
- notice = newObject(thing);
410
+ notice = shallowClone(thing);
434
411
  }
435
412
  else {
436
413
  var m = String(thing);
@@ -572,33 +549,44 @@ function getSourceCodeSnippet(fileData, lineNumber, sourceRadius) {
572
549
  return result;
573
550
  }
574
551
 
552
+ var GlobalStore$1 = /** @class */ (function () {
553
+ function GlobalStore(store) {
554
+ this.store = store;
555
+ }
556
+ GlobalStore.prototype.getStore = function () {
557
+ return this.store;
558
+ };
559
+ GlobalStore.prototype.run = function (store, callback) {
560
+ var args = [];
561
+ for (var _i = 2; _i < arguments.length; _i++) {
562
+ args[_i - 2] = arguments[_i];
563
+ }
564
+ this.store = store;
565
+ return callback.apply(void 0, args);
566
+ };
567
+ return GlobalStore;
568
+ }());
569
+
575
570
  var notifier = {
576
571
  name: 'honeybadger-js',
577
572
  url: 'https://github.com/honeybadger-io/honeybadger-js',
578
- version: '4.0.0-beta.0'
573
+ version: '4.0.0-beta.3'
579
574
  };
580
- // Split at commas
581
- var TAG_SEPARATOR = /,/;
582
- // Removes any non-word characters
583
- var TAG_SANITIZER = /[^\w]/g;
584
- // Checks for blank strings
585
- var STRING_EMPTY = '';
575
+ // Split at commas and spaces
576
+ var TAG_SEPARATOR = /,|\s+/;
586
577
  // Checks for non-blank characters
587
578
  var NOT_BLANK = /\S/;
588
579
  var Client = /** @class */ (function () {
589
580
  function Client(opts) {
590
581
  if (opts === void 0) { opts = {}; }
591
- /** @internal */
592
582
  this.__pluginsExecuted = false;
593
- /** @internal */
594
- this.__context = {};
595
- /** @internal */
596
- this.__breadcrumbs = [];
597
- /** @internal */
583
+ this.__store = null;
598
584
  this.__beforeNotifyHandlers = [];
599
- /** @internal */
600
585
  this.__afterNotifyHandlers = [];
601
586
  this.config = __assign({ apiKey: null, endpoint: 'https://api.honeybadger.io', environment: null, hostname: null, projectRoot: null, component: null, action: null, revision: null, reportData: null, breadcrumbsEnabled: true, maxBreadcrumbs: 40, maxObjectDepth: 8, logger: console, developmentEnvironments: ['dev', 'development', 'test'], debug: false, tags: null, enableUncaught: true, enableUnhandledRejection: true, afterUncaught: function () { return true; }, filters: ['creditcard', 'password'], __plugins: [] }, opts);
587
+ // First, we go with the global (shared) store.
588
+ // Webserver middleware can then switch to the AsyncStore for async context tracking.
589
+ this.__store = new GlobalStore$1({ context: {}, breadcrumbs: [] });
602
590
  this.logger = logger(this);
603
591
  }
604
592
  Client.prototype.factory = function (_opts) {
@@ -619,6 +607,10 @@ var Client = /** @class */ (function () {
619
607
  }
620
608
  return this;
621
609
  };
610
+ /** @internal */
611
+ Client.prototype.__setStore = function (store) {
612
+ this.__store = store;
613
+ };
622
614
  Client.prototype.beforeNotify = function (handler) {
623
615
  this.__beforeNotifyHandlers.push(handler);
624
616
  return this;
@@ -629,23 +621,26 @@ var Client = /** @class */ (function () {
629
621
  };
630
622
  Client.prototype.setContext = function (context) {
631
623
  if (typeof context === 'object') {
632
- this.__context = merge(this.__context, context);
624
+ var store = this.__store.getStore();
625
+ store.context = merge(store.context, context);
633
626
  }
634
627
  return this;
635
628
  };
636
629
  Client.prototype.resetContext = function (context) {
637
630
  this.logger.warn('Deprecation warning: `Honeybadger.resetContext()` has been deprecated; please use `Honeybadger.clear()` instead.');
631
+ var store = this.__store.getStore();
638
632
  if (typeof context === 'object' && context !== null) {
639
- this.__context = merge({}, context);
633
+ store.context = context;
640
634
  }
641
635
  else {
642
- this.__context = {};
636
+ store.context = {};
643
637
  }
644
638
  return this;
645
639
  };
646
640
  Client.prototype.clear = function () {
647
- this.__context = {};
648
- this.__breadcrumbs = [];
641
+ var store = this.__store.getStore();
642
+ store.context = {};
643
+ store.breadcrumbs = [];
649
644
  return this;
650
645
  };
651
646
  Client.prototype.notify = function (noticeable, name, extra) {
@@ -687,10 +682,11 @@ var Client = /** @class */ (function () {
687
682
  stack: notice.stack
688
683
  }
689
684
  });
690
- notice.__breadcrumbs = this.config.breadcrumbsEnabled ? this.__breadcrumbs.slice() : [];
685
+ var breadcrumbs = this.__getStoreContentsOrDefault().breadcrumbs;
686
+ notice.__breadcrumbs = this.config.breadcrumbsEnabled ? breadcrumbs.slice() : [];
691
687
  // we need to have the source file data before the beforeNotifyHandlers,
692
688
  // in case they modify them
693
- var sourceCodeData = notice ? notice.backtrace.slice() : null;
689
+ var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
694
690
  getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler, function (sourcePerTrace) {
695
691
  sourcePerTrace.forEach(function (source, index) {
696
692
  notice.backtrace[index].source = source;
@@ -761,15 +757,16 @@ var Client = /** @class */ (function () {
761
757
  if (objectIsEmpty(notice)) {
762
758
  return null;
763
759
  }
760
+ var context = this.__getStoreContentsOrDefault().context;
764
761
  var noticeTags = this.__constructTags(notice.tags);
765
- var contextTags = this.__constructTags(this.__context["tags"]);
762
+ var contextTags = this.__constructTags(context["tags"]);
766
763
  var configTags = this.__constructTags(this.config.tags);
767
764
  // Turning into a Set will remove duplicates
768
765
  var tags = noticeTags.concat(contextTags).concat(configTags);
769
766
  var uniqueTags = tags.filter(function (item, index) { return tags.indexOf(item) === index; });
770
767
  notice = merge(notice, {
771
768
  name: notice.name || 'Error',
772
- context: merge(this.__context, notice.context),
769
+ context: merge(context, notice.context),
773
770
  projectRoot: notice.projectRoot || this.config.projectRoot,
774
771
  environment: notice.environment || this.config.environment,
775
772
  component: notice.component || this.config.component,
@@ -790,33 +787,33 @@ var Client = /** @class */ (function () {
790
787
  return;
791
788
  }
792
789
  opts = opts || {};
793
- var metadata = newObject(opts.metadata);
790
+ var metadata = shallowClone(opts.metadata);
794
791
  var category = opts.category || 'custom';
795
792
  var timestamp = new Date().toISOString();
796
- this.__breadcrumbs.push({
793
+ var store = this.__store.getStore();
794
+ var breadcrumbs = store.breadcrumbs;
795
+ breadcrumbs.push({
797
796
  category: category,
798
797
  message: message,
799
798
  metadata: metadata,
800
799
  timestamp: timestamp
801
800
  });
802
801
  var limit = this.config.maxBreadcrumbs;
803
- if (this.__breadcrumbs.length > limit) {
804
- this.__breadcrumbs = this.__breadcrumbs.slice(this.__breadcrumbs.length - limit);
802
+ if (breadcrumbs.length > limit) {
803
+ breadcrumbs = breadcrumbs.slice(breadcrumbs.length - limit);
805
804
  }
805
+ store.breadcrumbs = breadcrumbs;
806
806
  return this;
807
807
  };
808
- /** @internal */
809
808
  Client.prototype.__developmentMode = function () {
810
809
  if (this.config.reportData === true) {
811
810
  return false;
812
811
  }
813
812
  return (this.config.environment && this.config.developmentEnvironments.includes(this.config.environment));
814
813
  };
815
- /** @internal */
816
814
  Client.prototype.__send = function (_notice) {
817
815
  throw (new Error('Must implement send in subclass'));
818
816
  };
819
- /** @internal */
820
817
  Client.prototype.__buildPayload = function (notice) {
821
818
  var headers = filter(notice.headers, this.config.filters) || {};
822
819
  var cgiData = filter(__assign(__assign({}, notice.cgiData), formatCGIData(headers, 'HTTP_')), this.config.filters);
@@ -852,14 +849,22 @@ var Client = /** @class */ (function () {
852
849
  details: notice.details || {}
853
850
  };
854
851
  };
855
- /** @internal */
856
852
  Client.prototype.__constructTags = function (tags) {
857
853
  if (!tags) {
858
854
  return [];
859
855
  }
860
- return tags.toString().split(TAG_SEPARATOR).map(function (tag) {
861
- return tag.replace(TAG_SANITIZER, STRING_EMPTY);
862
- }).filter(function (tag) { return NOT_BLANK.test(tag); });
856
+ return tags.toString().split(TAG_SEPARATOR).filter(function (tag) { return NOT_BLANK.test(tag); });
857
+ };
858
+ /**
859
+ * For ALS, the store may be uninitialized (if .run()` has not been called).
860
+ * This provides an easy way to read the existing store object or fall back to a default.
861
+ * Returns *a copy* of the store contents.
862
+ * @internal
863
+ */
864
+ Client.prototype.__getStoreContentsOrDefault = function () {
865
+ var existingStoreContents = this.__store.getStore();
866
+ var storeContents = existingStoreContents || {};
867
+ return __assign({ context: {}, breadcrumbs: [] }, storeContents);
863
868
  };
864
869
  return Client;
865
870
  }());
@@ -920,55 +925,63 @@ function getSourceFile(path, cb) {
920
925
  });
921
926
  }
922
927
 
928
+ var Store;
929
+ try {
930
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
931
+ var AsyncLocalStorage = require('async_hooks').AsyncLocalStorage;
932
+ Store = new AsyncLocalStorage();
933
+ }
934
+ catch (e) {
935
+ // eslint-disable-next-line @typescript-eslint/no-var-requires
936
+ var GlobalStore = require('../core/store').GlobalStore;
937
+ Store = new GlobalStore();
938
+ }
939
+ var AsyncStore = Store;
940
+
923
941
  function isHandlerSync(handler) {
924
942
  return handler.length > 2;
925
943
  }
926
- function asyncHandler(handler, hb) {
927
- var _this = this;
928
- return function (event, context) { return __awaiter(_this, void 0, void 0, function () {
929
- var err_1;
930
- return __generator(this, function (_a) {
931
- switch (_a.label) {
932
- case 0:
933
- _a.trys.push([0, 2, , 3]);
934
- return [4 /*yield*/, handler(event, context)];
935
- case 1: return [2 /*return*/, _a.sent()];
936
- case 2:
937
- err_1 = _a.sent();
938
- return [2 /*return*/, new Promise(function (_, reject) {
939
- hb.notify(err_1, {
940
- afterNotify: function () {
941
- hb.clear();
942
- reject(err_1);
943
- }
944
- });
945
- })];
946
- case 3: return [2 /*return*/];
947
- }
948
- });
949
- }); };
944
+ function reportToHoneybadger(hb, err, callback) {
945
+ hb.notify(err, {
946
+ afterNotify: function () {
947
+ hb.clear();
948
+ callback(err);
949
+ }
950
+ });
950
951
  }
951
- function syncHandler(handler, hb) {
952
- return function (event, context, cb) {
953
- var hbHandler = function (err) {
954
- hb.notify(err, {
955
- afterNotify: function () {
956
- hb.clear();
957
- cb(err);
952
+ function asyncHandler(handler, hb) {
953
+ return function wrappedLambdaHandler(event, context) {
954
+ hb.__setStore(AsyncStore);
955
+ return new Promise(function (resolve, reject) {
956
+ AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
957
+ try {
958
+ handler(event, context)
959
+ .then(resolve)
960
+ .catch(function (err) { return reportToHoneybadger(hb, err, reject); });
958
961
  }
959
- });
960
- };
961
- try {
962
- handler(event, context, function (error, result) {
963
- if (error) {
964
- return hbHandler(error);
962
+ catch (err) {
963
+ reportToHoneybadger(hb, err, reject);
965
964
  }
966
- cb(null, result);
967
965
  });
968
- }
969
- catch (err) {
970
- hbHandler(err);
971
- }
966
+ });
967
+ };
968
+ }
969
+ function syncHandler(handler, hb) {
970
+ return function wrappedLambdaHandler(event, context, cb) {
971
+ hb.__setStore(AsyncStore);
972
+ AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
973
+ try {
974
+ handler(event, context, function (error, result) {
975
+ if (error) {
976
+ return reportToHoneybadger(hb, error, cb);
977
+ }
978
+ cb(null, result);
979
+ });
980
+ }
981
+ catch (err) {
982
+ reportToHoneybadger(hb, err, cb);
983
+ }
984
+ });
972
985
  };
973
986
  }
974
987
  function lambdaHandler(handler) {
@@ -1065,10 +1078,7 @@ function fullUrl(req) {
1065
1078
  });
1066
1079
  }
1067
1080
  function requestHandler(req, res, next) {
1068
- this.clear();
1069
- var dom = domain__default["default"].create();
1070
- dom.on('error', next);
1071
- dom.run(next);
1081
+ this.withRequest(req, next, next);
1072
1082
  }
1073
1083
  function errorHandler(err, req, _res, next) {
1074
1084
  this.notify(err, {
@@ -1081,9 +1091,12 @@ function errorHandler(err, req, _res, next) {
1081
1091
  REQUEST_METHOD: req.method
1082
1092
  }
1083
1093
  });
1084
- return next(err);
1094
+ if (next) {
1095
+ return next(err);
1096
+ }
1085
1097
  }
1086
1098
 
1099
+ var kHoneybadgerStore = Symbol.for("kHoneybadgerStore");
1087
1100
  var Honeybadger = /** @class */ (function (_super) {
1088
1101
  __extends(Honeybadger, _super);
1089
1102
  function Honeybadger(opts) {
@@ -1144,7 +1157,7 @@ var Honeybadger = /** @class */ (function (_super) {
1144
1157
  runAfterNotifyHandlers(merge(notice, {
1145
1158
  id: uuid
1146
1159
  }), _this.__afterNotifyHandlers);
1147
- _this.logger.info('Error report sent.', "id=".concat(uuid));
1160
+ _this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
1148
1161
  });
1149
1162
  });
1150
1163
  req.on('error', function (err) {
@@ -1155,13 +1168,41 @@ var Honeybadger = /** @class */ (function (_super) {
1155
1168
  req.end();
1156
1169
  });
1157
1170
  };
1171
+ // This method is intended for web frameworks.
1172
+ // It allows us to track context for individual requests without leaking to other requests
1173
+ // by doing two things:
1174
+ // 1. Using AsyncLocalStorage so the context is tracked across async operations.
1175
+ // 2. Attaching the store contents to the request object,
1176
+ // so, even if the store is destroyed, we can still recover the context for a given request
1177
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1178
+ Honeybadger.prototype.withRequest = function (request, handler, onError) {
1179
+ var _this = this;
1180
+ var storeObject = (request[kHoneybadgerStore] || this.__getStoreContentsOrDefault());
1181
+ this.__setStore(AsyncStore);
1182
+ if (!request[kHoneybadgerStore]) {
1183
+ request[kHoneybadgerStore] = storeObject;
1184
+ }
1185
+ if (onError) {
1186
+ // ALS is fine for context-tracking, but `domain` allows us to catch errors
1187
+ // thrown asynchronously (timers, event emitters)
1188
+ // We can't use unhandledRejection/uncaughtException listeners; they're global and shared across all requests
1189
+ // But the `onError` handler might be request-specific.
1190
+ // Note that this doesn't still handle all cases. `domain` has its own problems:
1191
+ // See https://github.com/honeybadger-io/honeybadger-js/pull/711
1192
+ var dom = domain__default["default"].create();
1193
+ var onErrorWithContext = function (err) { return _this.__store.run(storeObject, function () { return onError(err); }); };
1194
+ dom.on('error', onErrorWithContext);
1195
+ handler = dom.bind(handler);
1196
+ }
1197
+ return this.__store.run(storeObject, handler);
1198
+ };
1158
1199
  return Honeybadger;
1159
1200
  }(Client));
1160
1201
  var server = new Honeybadger({
1161
1202
  __plugins: [
1162
1203
  uncaughtException(),
1163
1204
  unhandledRejection()
1164
- ]
1205
+ ],
1165
1206
  });
1166
1207
 
1167
1208
  module.exports = server;
@@ -1,9 +1,17 @@
1
- import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable } from './types';
1
+ import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord } from './types';
2
2
  export default class Client {
3
+ private __pluginsExecuted;
4
+ protected __store: HoneybadgerStore<{
5
+ context: Record<string, unknown>;
6
+ breadcrumbs: BreadcrumbRecord[];
7
+ }>;
8
+ protected __beforeNotifyHandlers: BeforeNotifyHandler[];
9
+ protected __afterNotifyHandlers: AfterNotifyHandler[];
10
+ protected __getSourceFileHandler: (path: string, cb: (fileContent: string) => void) => void;
3
11
  config: Config;
4
12
  logger: Logger;
5
13
  constructor(opts?: Partial<Config>);
6
- factory(_opts?: Record<string, unknown>): unknown;
14
+ factory(_opts?: Partial<Config>): Client;
7
15
  getVersion(): string;
8
16
  configure(opts?: Partial<Config>): Client;
9
17
  beforeNotify(handler: BeforeNotifyHandler): Client;
@@ -21,4 +29,8 @@ export default class Client {
21
29
  notifyAsync(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Promise<void>;
22
30
  protected makeNotice(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Notice | null;
23
31
  addBreadcrumb(message: string, opts?: Record<string, unknown>): Client;
32
+ protected __developmentMode(): boolean;
33
+ protected __send(_notice: Partial<Notice>): void;
34
+ protected __buildPayload(notice: Notice): Record<string, Record<string, unknown>>;
35
+ protected __constructTags(tags: unknown): Array<string>;
24
36
  }
@@ -0,0 +1,7 @@
1
+ import { HoneybadgerStore } from "./types";
2
+ export declare class GlobalStore<T> implements HoneybadgerStore<T> {
3
+ private store;
4
+ constructor(store: T);
5
+ getStore(): T;
6
+ run<R, TArgs extends never[]>(store: T, callback: (...args: TArgs) => R, ...args: TArgs): R;
7
+ }
@@ -1,4 +1,6 @@
1
+ /// <reference types="node" />
1
2
  import Client from './client';
3
+ import { AsyncLocalStorage } from "async_hooks";
2
4
  export interface Logger {
3
5
  log(...args: unknown[]): unknown;
4
6
  info(...args: unknown[]): unknown;
@@ -88,3 +90,8 @@ export interface CGIData {
88
90
  HTTP_COOKIE: string | undefined;
89
91
  [x: string]: unknown;
90
92
  }
93
+ export declare type HoneybadgerStore<T> = Pick<AsyncLocalStorage<T>, 'getStore' | 'run'>;
94
+ export declare type DefaultStoreContents = {
95
+ context: Record<string, unknown>;
96
+ breadcrumbs: BreadcrumbRecord[];
97
+ };
@@ -8,7 +8,7 @@ export declare function makeBacktrace(stack: string, shift?: number): BacktraceF
8
8
  export declare function getSourceForBacktrace(backtrace: BacktraceFrame[], getSourceFileHandler: (path: string, cb: (fileContent: string) => void) => void, cb: (sourcePerTrace: Record<string, string>[]) => void): void;
9
9
  export declare function runBeforeNotifyHandlers(notice: Notice | null, handlers: BeforeNotifyHandler[]): boolean;
10
10
  export declare function runAfterNotifyHandlers(notice: Notice | null, handlers: AfterNotifyHandler[], error?: Error): boolean;
11
- export declare function newObject<T>(obj: T): T | Record<string, unknown>;
11
+ export declare function shallowClone<T>(obj: T): T | Record<string, unknown>;
12
12
  export declare function sanitize(obj: any, maxDepth?: number): any;
13
13
  export declare function logger(client: Client): Logger;
14
14
  /**
@@ -0,0 +1,5 @@
1
+ import { BreadcrumbRecord, HoneybadgerStore } from "../core/types";
2
+ export declare const AsyncStore: HoneybadgerStore<{
3
+ context: Record<string, unknown>;
4
+ breadcrumbs: BreadcrumbRecord[];
5
+ }>;
@@ -8,6 +8,7 @@ declare class Honeybadger extends Client {
8
8
  lambdaHandler: typeof lambdaHandler;
9
9
  constructor(opts?: Partial<Config>);
10
10
  factory(opts?: Partial<Config>): Honeybadger;
11
+ withRequest<R>(request: Record<symbol, unknown>, handler: (...args: never[]) => R, onError?: (...args: any[]) => any): R | void;
11
12
  }
12
13
  declare const _default: Honeybadger;
13
14
  export default _default;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@honeybadger-io/js",
3
- "version": "4.0.0-beta.0",
3
+ "version": "4.0.0-beta.3",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/honeybadger-io/honeybadger-js",
6
6
  "author": {
@@ -46,11 +46,12 @@
46
46
  },
47
47
  "devDependencies": {
48
48
  "@rollup/plugin-node-resolve": "^13.0.6",
49
- "@rollup/plugin-replace": "^3.0.0",
49
+ "@rollup/plugin-replace": "^4.0.0",
50
50
  "@rollup/plugin-typescript": "^8.3.0",
51
51
  "@types/aws-lambda": "^8.10.89",
52
52
  "@types/express": "^4.17.13",
53
53
  "@types/jest": "^27.0.3",
54
+ "@types/node": "^12.20.46",
54
55
  "@typescript-eslint/eslint-plugin": "^5.6.0",
55
56
  "@typescript-eslint/parser": "^5.6.0",
56
57
  "axios": ">=0.24.0",
@@ -64,11 +65,11 @@
64
65
  "nock": "^13.2.1",
65
66
  "rollup": "^2.61.1",
66
67
  "rollup-plugin-uglify": "^6.0.2",
67
- "shipjs": "0.24.2",
68
+ "shipjs": "0.24.3",
68
69
  "sinon": "^13.0.1",
69
70
  "supertest": "^6.1.6",
70
71
  "ts-jest": "^27.1.1",
71
- "tsd": "^0.19.0",
72
+ "tsd": "^0.20.0",
72
73
  "tslib": "^2.3.1",
73
74
  "typescript": "^4.5.3"
74
75
  },
@@ -1,3 +0,0 @@
1
- export default class NotifyError extends Error {
2
- constructor(message: any);
3
- }
@@ -1,3 +0,0 @@
1
- export default class NotifyError extends Error {
2
- constructor(message: any);
3
- }