@honeybadger-io/js 4.0.0-beta.5 → 4.0.2

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.
@@ -1,20 +1,21 @@
1
1
  'use strict';
2
2
 
3
- var https = require('https');
4
- var http = require('http');
5
- var url = require('url');
6
3
  var os = require('os');
7
4
  var domain = require('domain');
8
5
  var fs = require('fs');
6
+ var util = require('util');
7
+ var url = require('url');
8
+ var http = require('http');
9
+ var https = require('https');
9
10
 
10
11
  function _interopDefaultLegacy (e) { return e && typeof e === 'object' && 'default' in e ? e : { 'default': e }; }
11
12
 
12
- var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
13
- var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
14
- var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
15
13
  var os__default = /*#__PURE__*/_interopDefaultLegacy(os);
16
14
  var domain__default = /*#__PURE__*/_interopDefaultLegacy(domain);
17
15
  var fs__default = /*#__PURE__*/_interopDefaultLegacy(fs);
16
+ var url__default = /*#__PURE__*/_interopDefaultLegacy(url);
17
+ var http__default = /*#__PURE__*/_interopDefaultLegacy(http);
18
+ var https__default = /*#__PURE__*/_interopDefaultLegacy(https);
18
19
 
19
20
  /*! *****************************************************************************
20
21
  Copyright (c) Microsoft Corporation.
@@ -56,7 +57,45 @@ var __assign = function() {
56
57
  return t;
57
58
  };
58
59
  return __assign.apply(this, arguments);
59
- };
60
+ };
61
+
62
+ function __awaiter(thisArg, _arguments, P, generator) {
63
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
64
+ return new (P || (P = Promise))(function (resolve, reject) {
65
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
66
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
67
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
68
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
69
+ });
70
+ }
71
+
72
+ function __generator(thisArg, body) {
73
+ var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
74
+ return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
75
+ function verb(n) { return function (v) { return step([n, v]); }; }
76
+ function step(op) {
77
+ if (f) throw new TypeError("Generator is already executing.");
78
+ while (_) try {
79
+ 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;
80
+ if (y = 0, t) op = [op[0] & 2, t.value];
81
+ switch (op[0]) {
82
+ case 0: case 1: t = op; break;
83
+ case 4: _.label++; return { value: op[1], done: false };
84
+ case 5: _.label++; y = op[1]; op = [0]; continue;
85
+ case 7: op = _.ops.pop(); _.trys.pop(); continue;
86
+ default:
87
+ if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
88
+ if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
89
+ if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
90
+ if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
91
+ if (t[2]) _.ops.pop();
92
+ _.trys.pop(); continue;
93
+ }
94
+ op = body.call(thisArg, _);
95
+ } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
96
+ if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
97
+ }
98
+ }
60
99
 
61
100
  var UNKNOWN_FUNCTION = '<unknown>';
62
101
  /**
@@ -238,24 +277,31 @@ function makeBacktrace(stack, shift) {
238
277
  return [];
239
278
  }
240
279
  }
241
- function getSourceForBacktrace(backtrace, getSourceFileHandler, cb) {
242
- if (!getSourceFileHandler || !backtrace || !backtrace.length) {
243
- cb([]);
244
- return;
245
- }
246
- var result = [];
247
- var getSourceFromFile = function (index) {
248
- if (index === void 0) { index = 0; }
249
- if (!backtrace.length) {
250
- return cb(result);
251
- }
252
- var trace = backtrace.splice(0)[index];
253
- getSourceFileHandler(trace.file, (function (fileContent) {
254
- result[index] = getSourceCodeSnippet(fileContent, trace.number);
255
- getSourceFromFile(index + 1);
256
- }));
257
- };
258
- getSourceFromFile();
280
+ function getSourceForBacktrace(backtrace, getSourceFileHandler) {
281
+ return __awaiter(this, void 0, void 0, function () {
282
+ var result, index, trace, fileContent;
283
+ return __generator(this, function (_a) {
284
+ switch (_a.label) {
285
+ case 0:
286
+ result = [];
287
+ if (!getSourceFileHandler || !backtrace || !backtrace.length) {
288
+ return [2 /*return*/, result];
289
+ }
290
+ index = 0;
291
+ _a.label = 1;
292
+ case 1:
293
+ if (!backtrace.length) return [3 /*break*/, 3];
294
+ trace = backtrace.splice(0)[index];
295
+ return [4 /*yield*/, getSourceFileHandler(trace.file)];
296
+ case 2:
297
+ fileContent = _a.sent();
298
+ result[index] = getSourceCodeSnippet(fileContent, trace.number);
299
+ index++;
300
+ return [3 /*break*/, 1];
301
+ case 3: return [2 /*return*/, result];
302
+ }
303
+ });
304
+ });
259
305
  }
260
306
  function runBeforeNotifyHandlers(notice, handlers) {
261
307
  var result = true;
@@ -415,8 +461,8 @@ function makeNotice(thing) {
415
461
  }
416
462
  return notice;
417
463
  }
418
- function endpoint(config, path) {
419
- var endpoint = config.endpoint.trim().replace(/\/$/, '');
464
+ function endpoint(base, path) {
465
+ var endpoint = base.trim().replace(/\/$/, '');
420
466
  path = path.trim().replace(/(^\/|\/$)/g, '');
421
467
  return "".concat(endpoint, "/").concat(path);
422
468
  }
@@ -548,6 +594,9 @@ function getSourceCodeSnippet(fileData, lineNumber, sourceRadius) {
548
594
  }
549
595
  return result;
550
596
  }
597
+ function isBrowserConfig(config) {
598
+ return config.async !== undefined;
599
+ }
551
600
 
552
601
  var GlobalStore$1 = /** @class */ (function () {
553
602
  function GlobalStore(store) {
@@ -570,14 +619,14 @@ var GlobalStore$1 = /** @class */ (function () {
570
619
  var notifier = {
571
620
  name: 'honeybadger-js',
572
621
  url: 'https://github.com/honeybadger-io/honeybadger-js',
573
- version: '4.0.0-beta.5'
622
+ version: '4.0.2'
574
623
  };
575
624
  // Split at commas and spaces
576
625
  var TAG_SEPARATOR = /,|\s+/;
577
626
  // Checks for non-blank characters
578
627
  var NOT_BLANK = /\S/;
579
628
  var Client = /** @class */ (function () {
580
- function Client(opts) {
629
+ function Client(opts, transport) {
581
630
  if (opts === void 0) { opts = {}; }
582
631
  this.__pluginsExecuted = false;
583
632
  this.__store = null;
@@ -587,11 +636,9 @@ var Client = /** @class */ (function () {
587
636
  // First, we go with the global (shared) store.
588
637
  // Webserver middleware can then switch to the AsyncStore for async context tracking.
589
638
  this.__store = new GlobalStore$1({ context: {}, breadcrumbs: [] });
639
+ this.__transport = transport;
590
640
  this.logger = logger(this);
591
641
  }
592
- Client.prototype.factory = function (_opts) {
593
- throw (new Error('Must implement __factory in subclass'));
594
- };
595
642
  Client.prototype.getVersion = function () {
596
643
  return notifier.version;
597
644
  };
@@ -665,6 +712,9 @@ var Client = /** @class */ (function () {
665
712
  this.logger.warn('could not send error report: no API key has been configured', notice);
666
713
  preConditionError = new Error('missing API key');
667
714
  }
715
+ // we need to have the source file data before the beforeNotifyHandlers,
716
+ // in case they modify them
717
+ var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
668
718
  var beforeNotifyResult = runBeforeNotifyHandlers(notice, this.__beforeNotifyHandlers);
669
719
  if (!preConditionError && !beforeNotifyResult) {
670
720
  this.logger.debug('skipping error report: beforeNotify handlers returned false', notice);
@@ -684,14 +734,41 @@ var Client = /** @class */ (function () {
684
734
  });
685
735
  var breadcrumbs = this.__getStoreContentsOrDefault().breadcrumbs;
686
736
  notice.__breadcrumbs = this.config.breadcrumbsEnabled ? breadcrumbs.slice() : [];
687
- // we need to have the source file data before the beforeNotifyHandlers,
688
- // in case they modify them
689
- var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
690
- getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler, function (sourcePerTrace) {
737
+ getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler)
738
+ .then(function (sourcePerTrace) {
691
739
  sourcePerTrace.forEach(function (source, index) {
692
740
  notice.backtrace[index].source = source;
693
741
  });
694
- _this.__send(notice);
742
+ var payload = _this.__buildPayload(notice);
743
+ _this.__transport
744
+ .send({
745
+ headers: {
746
+ 'X-API-Key': _this.config.apiKey,
747
+ 'Content-Type': 'application/json',
748
+ 'Accept': 'text/json, application/json'
749
+ },
750
+ method: 'POST',
751
+ endpoint: endpoint(_this.config.endpoint, '/v1/notices/js'),
752
+ maxObjectDepth: _this.config.maxObjectDepth,
753
+ logger: _this.logger,
754
+ async: isBrowserConfig(_this.config) ? _this.config.async : undefined,
755
+ }, payload)
756
+ .then(function (res) {
757
+ if (res.statusCode !== 201) {
758
+ runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, new Error("Bad HTTP response: ".concat(res.statusCode)));
759
+ _this.logger.warn("Error report failed: unknown response from server. code=".concat(res.statusCode));
760
+ return;
761
+ }
762
+ var uuid = JSON.parse(res.body).id;
763
+ runAfterNotifyHandlers(merge(notice, {
764
+ id: uuid
765
+ }), _this.__afterNotifyHandlers);
766
+ _this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
767
+ })
768
+ .catch(function (err) {
769
+ _this.logger.error('Error report failed: an unknown error occurred.', "message=".concat(err.message));
770
+ runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, err);
771
+ });
695
772
  });
696
773
  return true;
697
774
  };
@@ -759,7 +836,7 @@ var Client = /** @class */ (function () {
759
836
  }
760
837
  var context = this.__getStoreContentsOrDefault().context;
761
838
  var noticeTags = this.__constructTags(notice.tags);
762
- var contextTags = this.__constructTags(context["tags"]);
839
+ var contextTags = this.__constructTags(context['tags']);
763
840
  var configTags = this.__constructTags(this.config.tags);
764
841
  // Turning into a Set will remove duplicates
765
842
  var tags = noticeTags.concat(contextTags).concat(configTags);
@@ -811,9 +888,6 @@ var Client = /** @class */ (function () {
811
888
  }
812
889
  return (this.config.environment && this.config.developmentEnvironments.includes(this.config.environment));
813
890
  };
814
- Client.prototype.__send = function (_notice) {
815
- throw (new Error('Must implement send in subclass'));
816
- };
817
891
  Client.prototype.__buildPayload = function (notice) {
818
892
  var headers = filter(notice.headers, this.config.filters) || {};
819
893
  var cgiData = filter(__assign(__assign({}, notice.cgiData), formatCGIData(headers, 'HTTP_')), this.config.filters);
@@ -869,59 +943,86 @@ var Client = /** @class */ (function () {
869
943
  return Client;
870
944
  }());
871
945
 
946
+ var readFile = util.promisify(fs__default["default"].readFile);
872
947
  function fatallyLogAndExit(err) {
873
948
  console.error('[Honeybadger] Exiting process due to uncaught exception');
874
949
  console.error(err.stack || err);
875
950
  process.exit(1);
876
951
  }
877
- function getStats(cb) {
878
- var load = os__default["default"].loadavg(), stats = {
879
- load: {
880
- one: load[0],
881
- five: load[1],
882
- fifteen: load[2]
883
- },
884
- mem: {}
885
- };
886
- if (fs__default["default"].existsSync('/proc/meminfo')) {
887
- return fs__default["default"].readFile('/proc/meminfo', 'utf8', parseStats);
888
- }
889
- fallback();
890
- function parseStats(err, memData) {
891
- if (err)
892
- return fallback();
893
- // The first four lines, in order, are Total, Free, Buffers, Cached.
894
- // @TODO: Figure out if there's a way to only read these lines
895
- var data = memData.split('\n').slice(0, 4);
896
- var results = data.map(function (i) {
897
- return parseInt(/\s+(\d+)\skB/i.exec(i)[1], 10) / 1024.0;
952
+ function getStats() {
953
+ return __awaiter(this, void 0, void 0, function () {
954
+ var load, stats, fallback, memData, data, results;
955
+ return __generator(this, function (_a) {
956
+ switch (_a.label) {
957
+ case 0:
958
+ load = os__default["default"].loadavg();
959
+ stats = {
960
+ load: {
961
+ one: load[0],
962
+ five: load[1],
963
+ fifteen: load[2]
964
+ },
965
+ mem: {}
966
+ };
967
+ fallback = function () {
968
+ stats.mem = {
969
+ free: os__default["default"].freemem(),
970
+ total: os__default["default"].totalmem()
971
+ };
972
+ };
973
+ if (!fs__default["default"].existsSync('/proc/meminfo')) {
974
+ fallback();
975
+ return [2 /*return*/, stats];
976
+ }
977
+ _a.label = 1;
978
+ case 1:
979
+ _a.trys.push([1, 3, , 4]);
980
+ return [4 /*yield*/, readFile('/proc/meminfo', 'utf8')
981
+ // The first four lines, in order, are Total, Free, Buffers, Cached.
982
+ // @TODO: Figure out if there's a way to only read these lines
983
+ ];
984
+ case 2:
985
+ memData = _a.sent();
986
+ data = memData.split('\n').slice(0, 4);
987
+ results = data.map(function (i) {
988
+ return parseInt(/\s+(\d+)\skB/i.exec(i)[1], 10) / 1024.0;
989
+ });
990
+ stats.mem = {
991
+ total: results[0],
992
+ free: results[1],
993
+ buffers: results[2],
994
+ cached: results[3],
995
+ free_total: results[1] + results[2] + results[3]
996
+ };
997
+ return [3 /*break*/, 4];
998
+ case 3:
999
+ _a.sent();
1000
+ fallback();
1001
+ return [3 /*break*/, 4];
1002
+ case 4: return [2 /*return*/, stats];
1003
+ }
898
1004
  });
899
- stats.mem = {
900
- total: results[0],
901
- free: results[1],
902
- buffers: results[2],
903
- cached: results[3],
904
- free_total: results[1] + results[2] + results[3]
905
- };
906
- return cb(stats);
907
- }
908
- function fallback() {
909
- stats.mem = {
910
- free: os__default["default"].freemem(),
911
- total: os__default["default"].totalmem()
912
- };
913
- return cb(stats);
914
- }
1005
+ });
915
1006
  }
916
1007
  /**
917
1008
  * Get source file if possible, used to build `notice.backtrace.source`
918
1009
  *
919
1010
  * @param path to source code
920
- * @param cb callback with fileContent
921
1011
  */
922
- function getSourceFile(path, cb) {
923
- fs__default["default"].readFile(path, 'utf-8', function (err, data) {
924
- cb(err ? null : data);
1012
+ function getSourceFile(path) {
1013
+ return __awaiter(this, void 0, void 0, function () {
1014
+ return __generator(this, function (_a) {
1015
+ switch (_a.label) {
1016
+ case 0:
1017
+ _a.trys.push([0, 2, , 3]);
1018
+ return [4 /*yield*/, readFile(path, 'utf-8')];
1019
+ case 1: return [2 /*return*/, _a.sent()];
1020
+ case 2:
1021
+ _a.sent();
1022
+ return [2 /*return*/, null];
1023
+ case 3: return [2 /*return*/];
1024
+ }
1025
+ });
925
1026
  });
926
1027
  }
927
1028
 
@@ -954,12 +1055,15 @@ function asyncHandler(handler, hb) {
954
1055
  hb.__setStore(AsyncStore);
955
1056
  return new Promise(function (resolve, reject) {
956
1057
  AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
1058
+ var timeoutHandler = setupTimeoutWarning(hb, context);
957
1059
  try {
958
1060
  handler(event, context)
959
1061
  .then(resolve)
960
- .catch(function (err) { return reportToHoneybadger(hb, err, reject); });
1062
+ .catch(function (err) { return reportToHoneybadger(hb, err, reject); })
1063
+ .finally(function () { return clearTimeout(timeoutHandler); });
961
1064
  }
962
1065
  catch (err) {
1066
+ clearTimeout(timeoutHandler);
963
1067
  reportToHoneybadger(hb, err, reject);
964
1068
  }
965
1069
  });
@@ -970,8 +1074,10 @@ function syncHandler(handler, hb) {
970
1074
  return function wrappedLambdaHandler(event, context, cb) {
971
1075
  hb.__setStore(AsyncStore);
972
1076
  AsyncStore.run({ context: {}, breadcrumbs: [] }, function () {
1077
+ var timeoutHandler = setupTimeoutWarning(hb, context);
973
1078
  try {
974
1079
  handler(event, context, function (error, result) {
1080
+ clearTimeout(timeoutHandler);
975
1081
  if (error) {
976
1082
  return reportToHoneybadger(hb, error, cb);
977
1083
  }
@@ -979,11 +1085,24 @@ function syncHandler(handler, hb) {
979
1085
  });
980
1086
  }
981
1087
  catch (err) {
1088
+ clearTimeout(timeoutHandler);
982
1089
  reportToHoneybadger(hb, err, cb);
983
1090
  }
984
1091
  });
985
1092
  };
986
1093
  }
1094
+ function shouldReportTimeoutWarning(hb, context) {
1095
+ return typeof context.getRemainingTimeInMillis === 'function' && !!(hb.config.reportTimeoutWarning);
1096
+ }
1097
+ function setupTimeoutWarning(hb, context) {
1098
+ if (!shouldReportTimeoutWarning(hb, context)) {
1099
+ return;
1100
+ }
1101
+ var delay = context.getRemainingTimeInMillis() - (hb.config.timeoutWarningThresholdMs);
1102
+ return setTimeout(function () {
1103
+ hb.notify("".concat(context.functionName, "[").concat(context.functionVersion, "] may have timed out"));
1104
+ }, delay > 0 ? delay : 0);
1105
+ }
987
1106
  function lambdaHandler(handler) {
988
1107
  // eslint-disable-next-line @typescript-eslint/no-this-alias
989
1108
  var hb = this;
@@ -1096,12 +1215,69 @@ function errorHandler(err, req, _res, next) {
1096
1215
  }
1097
1216
  }
1098
1217
 
1099
- var kHoneybadgerStore = Symbol.for("kHoneybadgerStore");
1218
+ var ServerTransport = /** @class */ (function () {
1219
+ function ServerTransport() {
1220
+ }
1221
+ ServerTransport.prototype.send = function (options, payload) {
1222
+ var _this = this;
1223
+ var protocol = new url.URL(options.endpoint).protocol;
1224
+ var transport = (protocol === 'http:' ? http__default["default"] : https__default["default"]);
1225
+ return new Promise(function (resolve, reject) {
1226
+ var promise;
1227
+ // this should not be here. it should be done before reaching the transport layer
1228
+ // it could be inside a beforeNotifyHandler, but is not possible at the moment because those handlers are synchronous
1229
+ if (_this.isNoticePayload(payload)) {
1230
+ promise = _this.appendMetadata(payload);
1231
+ }
1232
+ else {
1233
+ promise = Promise.resolve();
1234
+ }
1235
+ promise.then(function () {
1236
+ var httpOptions = {
1237
+ method: options.method,
1238
+ headers: options.headers,
1239
+ };
1240
+ var data = undefined;
1241
+ if (payload) {
1242
+ data = Buffer.from(JSON.stringify(sanitize(payload, options.maxObjectDepth)), 'utf8');
1243
+ httpOptions.headers['Content-Length'] = data.length;
1244
+ }
1245
+ var req = transport.request(options.endpoint, httpOptions, function (res) {
1246
+ options.logger.debug("statusCode: ".concat(res.statusCode));
1247
+ var body = '';
1248
+ res.on('data', function (chunk) {
1249
+ body += chunk;
1250
+ });
1251
+ res.on('end', function () { return resolve({ statusCode: res.statusCode, body: body }); });
1252
+ });
1253
+ req.on('error', function (err) { return reject(err); });
1254
+ if (data) {
1255
+ req.write(data);
1256
+ }
1257
+ req.end();
1258
+ });
1259
+ });
1260
+ };
1261
+ ServerTransport.prototype.isNoticePayload = function (payload) {
1262
+ return payload && payload.error !== undefined;
1263
+ };
1264
+ ServerTransport.prototype.appendMetadata = function (payload) {
1265
+ payload.server.pid = process.pid;
1266
+ return getStats()
1267
+ .then(function (stats) {
1268
+ payload.server.stats = stats;
1269
+ });
1270
+ };
1271
+ return ServerTransport;
1272
+ }());
1273
+
1274
+ var kHoneybadgerStore = Symbol.for('kHoneybadgerStore');
1100
1275
  var Honeybadger = /** @class */ (function (_super) {
1101
1276
  __extends(Honeybadger, _super);
1102
1277
  function Honeybadger(opts) {
1103
1278
  if (opts === void 0) { opts = {}; }
1104
- var _this = _super.call(this, __assign({ afterUncaught: fatallyLogAndExit, projectRoot: process.cwd(), hostname: os__default["default"].hostname() }, opts)) || this;
1279
+ var _a;
1280
+ var _this = _super.call(this, __assign({ afterUncaught: fatallyLogAndExit, projectRoot: process.cwd(), hostname: os__default["default"].hostname() }, opts), new ServerTransport()) || this;
1105
1281
  /** @internal */
1106
1282
  _this.__beforeNotifyHandlers = [
1107
1283
  function (notice) {
@@ -1114,6 +1290,10 @@ var Honeybadger = /** @class */ (function (_super) {
1114
1290
  });
1115
1291
  }
1116
1292
  ];
1293
+ // serverless defaults
1294
+ var config = _this.config;
1295
+ config.reportTimeoutWarning = (_a = config.reportTimeoutWarning) !== null && _a !== void 0 ? _a : true;
1296
+ config.timeoutWarningThresholdMs = config.timeoutWarningThresholdMs || 50;
1117
1297
  _this.__getSourceFileHandler = getSourceFile.bind(_this);
1118
1298
  _this.errorHandler = errorHandler.bind(_this);
1119
1299
  _this.requestHandler = requestHandler.bind(_this);
@@ -1121,51 +1301,27 @@ var Honeybadger = /** @class */ (function (_super) {
1121
1301
  return _this;
1122
1302
  }
1123
1303
  Honeybadger.prototype.factory = function (opts) {
1304
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
1124
1305
  return new Honeybadger(opts);
1125
1306
  };
1126
- /** @internal */
1127
- Honeybadger.prototype.__send = function (notice) {
1307
+ Honeybadger.prototype.configure = function (opts) {
1308
+ if (opts === void 0) { opts = {}; }
1309
+ return _super.prototype.configure.call(this, opts);
1310
+ };
1311
+ Honeybadger.prototype.checkIn = function (id) {
1128
1312
  var _this = this;
1129
- var protocol = new url.URL(this.config.endpoint).protocol;
1130
- var transport = (protocol === "http:" ? http__default["default"] : https__default["default"]);
1131
- var payload = this.__buildPayload(notice);
1132
- payload.server.pid = process.pid;
1133
- getStats(function (stats) {
1134
- payload.server.stats = stats;
1135
- var data = Buffer.from(JSON.stringify(sanitize(payload, _this.config.maxObjectDepth)), 'utf8');
1136
- var options = {
1137
- method: 'POST',
1138
- headers: {
1139
- 'Content-Type': 'application/json',
1140
- 'Content-Length': data.length,
1141
- 'X-API-Key': _this.config.apiKey
1142
- }
1143
- };
1144
- var req = transport.request(endpoint(_this.config, '/v1/notices/js'), options, function (res) {
1145
- _this.logger.debug("statusCode: ".concat(res.statusCode));
1146
- var body = '';
1147
- res.on('data', function (chunk) {
1148
- body += chunk;
1149
- });
1150
- res.on('end', function () {
1151
- if (res.statusCode !== 201) {
1152
- runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, new Error("Bad HTTP response: ".concat(res.statusCode)));
1153
- _this.logger.warn("Error report failed: unknown response from server. code=".concat(res.statusCode));
1154
- return;
1155
- }
1156
- var uuid = JSON.parse(body).id;
1157
- runAfterNotifyHandlers(merge(notice, {
1158
- id: uuid
1159
- }), _this.__afterNotifyHandlers);
1160
- _this.logger.info("Error report sent \u26A1 https://app.honeybadger.io/notice/".concat(uuid));
1161
- });
1162
- });
1163
- req.on('error', function (err) {
1164
- _this.logger.error('Error report failed: an unknown error occurred.', "message=".concat(err.message));
1165
- runAfterNotifyHandlers(notice, _this.__afterNotifyHandlers, err);
1166
- });
1167
- req.write(data);
1168
- req.end();
1313
+ return this.__transport
1314
+ .send({
1315
+ method: 'GET',
1316
+ endpoint: endpoint(this.config.endpoint, "v1/check_in/".concat(id)),
1317
+ logger: this.logger,
1318
+ })
1319
+ .then(function () {
1320
+ _this.logger.info('CheckIn sent');
1321
+ return Promise.resolve();
1322
+ })
1323
+ .catch(function (err) {
1324
+ _this.logger.error('CheckIn failed: an unknown error occurred.', "message=".concat(err.message));
1169
1325
  });
1170
1326
  };
1171
1327
  // This method is intended for web frameworks.
@@ -0,0 +1,7 @@
1
+ import { Transport, TransportOptions, NoticeTransportPayload } from '../core/types';
2
+ export declare class BrowserTransport implements Transport {
3
+ send(options: TransportOptions, payload?: NoticeTransportPayload | undefined): Promise<{
4
+ statusCode: number;
5
+ body: string;
6
+ }>;
7
+ }
@@ -1,15 +1,12 @@
1
1
  import Client from './core/client';
2
- import { Config } from './core/types';
3
- interface BrowserConfig extends Config {
4
- async: boolean;
5
- maxErrors: number;
6
- }
2
+ import { BrowserConfig } from './core/types';
7
3
  declare class Honeybadger extends Client {
8
4
  config: BrowserConfig;
9
5
  constructor(opts?: Partial<BrowserConfig>);
10
- configure(opts?: Partial<BrowserConfig>): Client;
6
+ configure(opts?: Partial<BrowserConfig>): this;
11
7
  resetMaxErrors(): number;
12
- factory(opts?: Partial<BrowserConfig>): Honeybadger;
8
+ factory(opts?: Partial<BrowserConfig>): this;
9
+ checkIn(_id: string): Promise<void>;
13
10
  }
14
11
  declare const _default: Honeybadger;
15
12
  export default _default;
@@ -1,5 +1,5 @@
1
- import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord } from './types';
2
- export default class Client {
1
+ import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord, Transport, NoticeTransportPayload } from './types';
2
+ export default abstract class Client {
3
3
  protected __pluginsExecuted: boolean;
4
4
  protected __store: HoneybadgerStore<{
5
5
  context: Record<string, unknown>;
@@ -7,13 +7,15 @@ export default class Client {
7
7
  }>;
8
8
  protected __beforeNotifyHandlers: BeforeNotifyHandler[];
9
9
  protected __afterNotifyHandlers: AfterNotifyHandler[];
10
- protected __getSourceFileHandler: (path: string, cb: (fileContent: string) => void) => void;
10
+ protected __getSourceFileHandler: (path: string) => Promise<string>;
11
+ protected readonly __transport: Transport;
11
12
  config: Config;
12
13
  logger: Logger;
13
- constructor(opts?: Partial<Config>);
14
- factory(_opts?: Partial<Config>): Client;
14
+ protected constructor(opts: Partial<Config>, transport: Transport);
15
+ protected abstract factory(opts: Partial<Config>): this;
16
+ protected abstract checkIn(id: string): Promise<void>;
15
17
  getVersion(): string;
16
- configure(opts?: Partial<Config>): Client;
18
+ configure(opts?: Partial<Config>): this;
17
19
  beforeNotify(handler: BeforeNotifyHandler): Client;
18
20
  afterNotify(handler: AfterNotifyHandler): Client;
19
21
  setContext(context: Record<string, unknown>): Client;
@@ -30,7 +32,6 @@ export default class Client {
30
32
  protected makeNotice(noticeable: Noticeable, name?: string | Partial<Notice>, extra?: Partial<Notice>): Notice | null;
31
33
  addBreadcrumb(message: string, opts?: Record<string, unknown>): Client;
32
34
  protected __developmentMode(): boolean;
33
- protected __send(_notice: Partial<Notice>): void;
34
- protected __buildPayload(notice: Notice): Record<string, Record<string, unknown>>;
35
+ protected __buildPayload(notice: Notice): NoticeTransportPayload;
35
36
  protected __constructTags(tags: unknown): Array<string>;
36
37
  }
@@ -1,4 +1,4 @@
1
- import { HoneybadgerStore } from "./types";
1
+ import { HoneybadgerStore } from './types';
2
2
  export declare class GlobalStore<T> implements HoneybadgerStore<T> {
3
3
  private store;
4
4
  constructor(store: T);