@honeybadger-io/js 4.0.0-beta.1 → 4.0.0-beta.4

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.
@@ -277,7 +277,7 @@ function runAfterNotifyHandlers(notice, handlers, error) {
277
277
  return true;
278
278
  }
279
279
  // Returns a new object with properties from other object.
280
- function newObject(obj) {
280
+ function shallowClone(obj) {
281
281
  if (typeof (obj) !== 'object' || obj === null) {
282
282
  return {};
283
283
  }
@@ -304,8 +304,14 @@ function sanitize(obj, maxDepth) {
304
304
  return false;
305
305
  }
306
306
  function canSerialize(obj) {
307
- // Functions are TMI and Symbols can't convert to strings.
308
- 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)) {
309
315
  return false;
310
316
  }
311
317
  if (obj === null) {
@@ -401,7 +407,7 @@ function makeNotice(thing) {
401
407
  notice = merge(thing, { name: e.name, message: e.message, stack: e.stack });
402
408
  }
403
409
  else if (typeof thing === 'object') {
404
- notice = newObject(thing);
410
+ notice = shallowClone(thing);
405
411
  }
406
412
  else {
407
413
  var m = String(thing);
@@ -564,7 +570,7 @@ var GlobalStore$1 = /** @class */ (function () {
564
570
  var notifier = {
565
571
  name: 'honeybadger-js',
566
572
  url: 'https://github.com/honeybadger-io/honeybadger-js',
567
- version: '4.0.0-beta.1'
573
+ version: '4.0.0-beta.4'
568
574
  };
569
575
  // Split at commas and spaces
570
576
  var TAG_SEPARATOR = /,|\s+/;
@@ -676,11 +682,11 @@ var Client = /** @class */ (function () {
676
682
  stack: notice.stack
677
683
  }
678
684
  });
679
- var breadcrumbs = this.__getStoreOrDefaultObject().breadcrumbs;
685
+ var breadcrumbs = this.__getStoreContentsOrDefault().breadcrumbs;
680
686
  notice.__breadcrumbs = this.config.breadcrumbsEnabled ? breadcrumbs.slice() : [];
681
687
  // we need to have the source file data before the beforeNotifyHandlers,
682
688
  // in case they modify them
683
- var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return newObject(trace); }) : null;
689
+ var sourceCodeData = notice && notice.backtrace ? notice.backtrace.map(function (trace) { return shallowClone(trace); }) : null;
684
690
  getSourceForBacktrace(sourceCodeData, this.__getSourceFileHandler, function (sourcePerTrace) {
685
691
  sourcePerTrace.forEach(function (source, index) {
686
692
  notice.backtrace[index].source = source;
@@ -751,7 +757,7 @@ var Client = /** @class */ (function () {
751
757
  if (objectIsEmpty(notice)) {
752
758
  return null;
753
759
  }
754
- var context = this.__getStoreOrDefaultObject().context;
760
+ var context = this.__getStoreContentsOrDefault().context;
755
761
  var noticeTags = this.__constructTags(notice.tags);
756
762
  var contextTags = this.__constructTags(context["tags"]);
757
763
  var configTags = this.__constructTags(this.config.tags);
@@ -781,7 +787,7 @@ var Client = /** @class */ (function () {
781
787
  return;
782
788
  }
783
789
  opts = opts || {};
784
- var metadata = newObject(opts.metadata);
790
+ var metadata = shallowClone(opts.metadata);
785
791
  var category = opts.category || 'custom';
786
792
  var timestamp = new Date().toISOString();
787
793
  var store = this.__store.getStore();
@@ -852,13 +858,13 @@ var Client = /** @class */ (function () {
852
858
  /**
853
859
  * For ALS, the store may be uninitialized (if .run()` has not been called).
854
860
  * This provides an easy way to read the existing store object or fall back to a default.
855
- * Returns *a copy* of the store.
861
+ * Returns *a copy* of the store contents.
856
862
  * @internal
857
863
  */
858
- Client.prototype.__getStoreOrDefaultObject = function () {
859
- var existingStore = this.__store.getStore();
860
- var store = existingStore || {};
861
- return __assign({ context: {}, breadcrumbs: [] }, store);
864
+ Client.prototype.__getStoreContentsOrDefault = function () {
865
+ var existingStoreContents = this.__store.getStore();
866
+ var storeContents = existingStoreContents || {};
867
+ return __assign({ context: {}, breadcrumbs: [] }, storeContents);
862
868
  };
863
869
  return Client;
864
870
  }());
@@ -1072,7 +1078,7 @@ function fullUrl(req) {
1072
1078
  });
1073
1079
  }
1074
1080
  function requestHandler(req, res, next) {
1075
- this.run(next, next);
1081
+ this.withRequest(req, next, next);
1076
1082
  }
1077
1083
  function errorHandler(err, req, _res, next) {
1078
1084
  this.notify(err, {
@@ -1085,9 +1091,12 @@ function errorHandler(err, req, _res, next) {
1085
1091
  REQUEST_METHOD: req.method
1086
1092
  }
1087
1093
  });
1088
- return next(err);
1094
+ if (next) {
1095
+ return next(err);
1096
+ }
1089
1097
  }
1090
1098
 
1099
+ var kHoneybadgerStore = Symbol.for("kHoneybadgerStore");
1091
1100
  var Honeybadger = /** @class */ (function (_super) {
1092
1101
  __extends(Honeybadger, _super);
1093
1102
  function Honeybadger(opts) {
@@ -1159,11 +1168,20 @@ var Honeybadger = /** @class */ (function (_super) {
1159
1168
  req.end();
1160
1169
  });
1161
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
1162
1177
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
1163
- Honeybadger.prototype.run = function (handler, onError) {
1178
+ Honeybadger.prototype.withRequest = function (request, handler, onError) {
1164
1179
  var _this = this;
1165
- var storeObject = this.__getStoreOrDefaultObject();
1180
+ var storeObject = (request[kHoneybadgerStore] || this.__getStoreContentsOrDefault());
1166
1181
  this.__setStore(AsyncStore);
1182
+ if (!request[kHoneybadgerStore]) {
1183
+ request[kHoneybadgerStore] = storeObject;
1184
+ }
1167
1185
  if (onError) {
1168
1186
  // ALS is fine for context-tracking, but `domain` allows us to catch errors
1169
1187
  // thrown asynchronously (timers, event emitters)
@@ -1,6 +1,6 @@
1
1
  import { Config, Logger, BeforeNotifyHandler, AfterNotifyHandler, Notice, Noticeable, HoneybadgerStore, BreadcrumbRecord } from './types';
2
2
  export default class Client {
3
- private __pluginsExecuted;
3
+ protected __pluginsExecuted: boolean;
4
4
  protected __store: HoneybadgerStore<{
5
5
  context: Record<string, unknown>;
6
6
  breadcrumbs: BreadcrumbRecord[];
@@ -91,3 +91,7 @@ export interface CGIData {
91
91
  [x: string]: unknown;
92
92
  }
93
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
  /**
@@ -8,7 +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
- run<R>(handler: (...args: never[]) => R, onError?: (...args: any[]) => any): R | void;
11
+ withRequest<R>(request: Record<symbol, unknown>, handler: (...args: never[]) => R, onError?: (...args: any[]) => any): R | void;
12
12
  }
13
13
  declare const _default: Honeybadger;
14
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.1",
3
+ "version": "4.0.0-beta.4",
4
4
  "license": "MIT",
5
5
  "homepage": "https://github.com/honeybadger-io/honeybadger-js",
6
6
  "author": {
@@ -29,7 +29,7 @@
29
29
  "url": "https://github.com/honeybadger-io/honeybadger-js/issues"
30
30
  },
31
31
  "scripts": {
32
- "prepare": "npm run build",
32
+ "prepare": "npm run build && husky install",
33
33
  "test": "concurrently \"npm:test:browser\" \"npm:test:server\"",
34
34
  "test:browser": "jest --env=jsdom --testPathPattern=\"test/unit/.*(?<![\\./]server)\\.test\\.(js|ts)\"",
35
35
  "test:server": "jest --env=node --testPathPattern=\"test/unit/.*(?<![\\./]browser)\\.test\\.(js|ts)\"",
@@ -45,6 +45,8 @@
45
45
  "stacktrace-parser": "^0.1.10"
46
46
  },
47
47
  "devDependencies": {
48
+ "@commitlint/cli": "^16.2.3",
49
+ "@commitlint/config-conventional": "^16.2.1",
48
50
  "@rollup/plugin-node-resolve": "^13.0.6",
49
51
  "@rollup/plugin-replace": "^4.0.0",
50
52
  "@rollup/plugin-typescript": "^8.3.0",
@@ -61,6 +63,7 @@
61
63
  "eslint-plugin-jest": "^26.0.0",
62
64
  "eslint-plugin-promise": "^6.0.0",
63
65
  "express": "^4.17.1",
66
+ "husky": "^7.0.4",
64
67
  "jest": "^27.4.4",
65
68
  "nock": "^13.2.1",
66
69
  "rollup": "^2.61.1",
@@ -69,7 +72,7 @@
69
72
  "sinon": "^13.0.1",
70
73
  "supertest": "^6.1.6",
71
74
  "ts-jest": "^27.1.1",
72
- "tsd": "^0.19.0",
75
+ "tsd": "^0.20.0",
73
76
  "tslib": "^2.3.1",
74
77
  "typescript": "^4.5.3"
75
78
  },
@@ -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
- }