1- import { IBrowserClient , TraceoOptions } from "./types/client" ;
1+ import { IBrowserClient , TraceoBrowserError , TraceoOptions } from "./types/client" ;
22import { Transport } from "./transport" ;
33import { utils } from "./utils" ;
44import { stacktrace } from "./exceptions/stacktrace" ;
55import { Trace } from "./types/stacktrace" ;
66import { BrowserIncidentType } from "./types/transport" ;
7+ import { EventOnErrorType , EventOnUnhandledRejectionType , windowEventHandlers } from "./handlers" ;
8+ import { BrowserInfoType } from "./types/browser" ;
79
810export abstract class BrowserClient implements IBrowserClient {
911 public headers ! : { [ key : string ] : any } ;
1012 public options : TraceoOptions ;
1113 public transport : Transport ;
14+ private browser : BrowserInfoType ;
1215
1316 constructor ( options : TraceoOptions ) {
1417 this . options = options ;
1518 this . transport = new Transport ( this . options ) ;
19+ this . browser = utils . browserDetails ( ) ;
1620
1721 this . initSDK ( ) ;
1822 }
1923
24+ /**
25+ * Method to implement dedicated logic only for a specific type of SDK.
26+ * Implement in dedicated client.
27+ */
2028 public abstract postInitSDK ( ) : void ;
2129
22- public sendError ( error : Error ) : void {
30+ /**
31+ * Method to handle exceptions catched by ErrorBoundary component
32+ * Use this method via IBrowserClient interface implmeneted in dedicated clients
33+ * @param error
34+ */
35+ public handleError ( error : TraceoBrowserError ) : void {
2336 const err = this . constructError ( error ) ;
24- this . transport . send < BrowserIncidentType > ( err , this . headers ) ;
37+ if ( err ) {
38+ this . transport . send < BrowserIncidentType > ( err , this . headers ) ;
39+ }
2540 }
2641
27- private constructError ( error : Error ) : BrowserIncidentType {
28- const browser = utils . browserDetails ( ) ;
42+ /**
43+ * Method to send errors catched by window event handlers like onerror or onunhandledrejection
44+ * @param error
45+ */
46+ private sendError ( error : BrowserIncidentType ) : void {
47+ this . transport . send < BrowserIncidentType > ( error , this . headers ) ;
48+ }
49+
50+ private constructError ( error ?: Error ) : BrowserIncidentType | null {
51+ if ( ! error ) {
52+ console . debug ( "-- : --" ) ;
53+ return null ;
54+ }
2955
30- const type = error . name ;
31- const message = error . message ;
56+ const type = error ? .name || "Error" ;
57+ const message = error ? .message || "(No message)" ;
3258
33- const stack = error . stack || "" ;
59+ const stack = error ? .stack || "" ;
3460
3561 const traces : Trace [ ] = stacktrace . parse ( stack ) ;
3662
@@ -39,13 +65,80 @@ export abstract class BrowserClient implements IBrowserClient {
3965 message,
4066 stack,
4167 traces,
42- browser
68+ browser : this . browser
4369 } ;
4470
4571 return err ;
4672 }
4773
4874 private initSDK ( ) : void {
75+ if ( this . isOffline ) {
76+ return ;
77+ }
78+
79+ if ( window !== undefined ) {
80+ this . initWindowEventHandlers ( ) ;
81+ }
82+
4983 this . postInitSDK ( ) ;
5084 }
85+
86+ private initWindowEventHandlers ( ) {
87+ /**
88+ * Event handlers setup to catch exceptions via native js mechanism
89+ */
90+
91+ windowEventHandlers [ "onerror" ] ( ( data : EventOnErrorType ) => this . handleOnErrorEvent ( data ) ) ;
92+ windowEventHandlers [ "unhandledrejection" ] ( ( data : EventOnUnhandledRejectionType ) =>
93+ this . handleOnUnhandledRejectionEvent ( data )
94+ ) ;
95+ }
96+
97+ private handleOnErrorEvent = ( data : EventOnErrorType ) => {
98+ if ( data . error ) {
99+ const eventError = this . constructError ( data ?. error ) ;
100+ if ( ! eventError ) {
101+ console . debug ( "-- --- --" ) ;
102+ return ;
103+ }
104+
105+ if ( data ?. event ) {
106+ eventError . type = data . event . toString ( ) ;
107+ }
108+
109+ this . sendError ( eventError ) ;
110+ }
111+ } ;
112+
113+ private handleOnUnhandledRejectionEvent = ( data : EventOnUnhandledRejectionType ) => {
114+ // Without reason inside event there is no informations about catched exception
115+ if ( "reason" in data . event ) {
116+ const reason = data . event . reason ;
117+
118+ const type = "Unhandled rejection" ;
119+ const message = reason . message ;
120+
121+ let stack = "" ;
122+ if ( "stack" in reason ) {
123+ stack = reason . stack ;
124+ } else {
125+ stack = reason . toString ( ) ;
126+ }
127+
128+ const traces : Trace [ ] = stacktrace . parse ( stack ) ;
129+ const err : BrowserIncidentType = {
130+ type,
131+ message,
132+ stack,
133+ traces,
134+ browser : this . browser
135+ } ;
136+
137+ this . sendError ( err ) ;
138+ }
139+ } ;
140+
141+ private get isOffline ( ) : boolean | undefined {
142+ return this . options . offline ;
143+ }
51144}
0 commit comments