11import { BaseClient , Scope , SDK_VERSION } from '@sentry/core' ;
2- import { SessionFlusher } from '@sentry/hub' ;
3- import { Event , EventHint } from '@sentry/types' ;
4- import { logger } from '@sentry/utils' ;
2+ import { getCurrentHub , SessionFlusher } from '@sentry/hub' ;
3+ import { Event , EventHint , Mechanism , Severity , Transport , TransportOptions } from '@sentry/types' ;
4+ import {
5+ addExceptionMechanism ,
6+ addExceptionTypeValue ,
7+ Dsn ,
8+ extractExceptionKeysForMessage ,
9+ isError ,
10+ isPlainObject ,
11+ logger ,
12+ normalizeToSize ,
13+ SyncPromise ,
14+ } from '@sentry/utils' ;
515
6- import { NodeBackend } from './backend' ;
16+ import { extractStackFromError , parseError , parseStack , prepareFramesForEvent } from './parsers' ;
17+ import { HTTPSTransport , HTTPTransport } from './transports' ;
718import { NodeOptions } from './types' ;
819
920/**
@@ -12,7 +23,7 @@ import { NodeOptions } from './types';
1223 * @see NodeOptions for documentation on configuration options.
1324 * @see SentryClient for usage documentation.
1425 */
15- export class NodeClient extends BaseClient < NodeBackend , NodeOptions > {
26+ export class NodeClient extends BaseClient < NodeOptions > {
1627 protected _sessionFlusher : SessionFlusher | undefined ;
1728
1829 /**
@@ -32,7 +43,7 @@ export class NodeClient extends BaseClient<NodeBackend, NodeOptions> {
3243 version : SDK_VERSION ,
3344 } ;
3445
35- super ( NodeBackend , options ) ;
46+ super ( options ) ;
3647 }
3748
3849 /**
@@ -105,6 +116,115 @@ export class NodeClient extends BaseClient<NodeBackend, NodeOptions> {
105116 }
106117 }
107118
119+ /**
120+ * @inheritDoc
121+ */
122+ // eslint-disable-next-line @typescript-eslint/no-explicit-any, @typescript-eslint/explicit-module-boundary-types
123+ public eventFromException ( exception : any , hint ?: EventHint ) : PromiseLike < Event > {
124+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
125+ let ex : any = exception ;
126+ const providedMechanism : Mechanism | undefined =
127+ hint && hint . data && ( hint . data as { mechanism : Mechanism } ) . mechanism ;
128+ const mechanism : Mechanism = providedMechanism || {
129+ handled : true ,
130+ type : 'generic' ,
131+ } ;
132+
133+ if ( ! isError ( exception ) ) {
134+ if ( isPlainObject ( exception ) ) {
135+ // This will allow us to group events based on top-level keys
136+ // which is much better than creating new group when any key/value change
137+ const message = `Non-Error exception captured with keys: ${ extractExceptionKeysForMessage ( exception ) } ` ;
138+
139+ getCurrentHub ( ) . configureScope ( scope => {
140+ scope . setExtra ( '__serialized__' , normalizeToSize ( exception as Record < string , unknown > ) ) ;
141+ } ) ;
142+
143+ ex = ( hint && hint . syntheticException ) || new Error ( message ) ;
144+ ( ex as Error ) . message = message ;
145+ } else {
146+ // This handles when someone does: `throw "something awesome";`
147+ // We use synthesized Error here so we can extract a (rough) stack trace.
148+ ex = ( hint && hint . syntheticException ) || new Error ( exception as string ) ;
149+ ( ex as Error ) . message = exception ;
150+ }
151+ mechanism . synthetic = true ;
152+ }
153+
154+ return new SyncPromise < Event > ( ( resolve , reject ) =>
155+ parseError ( ex as Error , this . _options )
156+ . then ( event => {
157+ addExceptionTypeValue ( event , undefined , undefined ) ;
158+ addExceptionMechanism ( event , mechanism ) ;
159+
160+ resolve ( {
161+ ...event ,
162+ event_id : hint && hint . event_id ,
163+ } ) ;
164+ } )
165+ . then ( null , reject ) ,
166+ ) ;
167+ }
168+
169+ /**
170+ * @inheritDoc
171+ */
172+ public eventFromMessage ( message : string , level : Severity = Severity . Info , hint ?: EventHint ) : PromiseLike < Event > {
173+ const event : Event = {
174+ event_id : hint && hint . event_id ,
175+ level,
176+ message,
177+ } ;
178+
179+ return new SyncPromise < Event > ( resolve => {
180+ if ( this . _options . attachStacktrace && hint && hint . syntheticException ) {
181+ const stack = hint . syntheticException ? extractStackFromError ( hint . syntheticException ) : [ ] ;
182+ void parseStack ( stack , this . _options )
183+ . then ( frames => {
184+ event . stacktrace = {
185+ frames : prepareFramesForEvent ( frames ) ,
186+ } ;
187+ resolve ( event ) ;
188+ } )
189+ . then ( null , ( ) => {
190+ resolve ( event ) ;
191+ } ) ;
192+ } else {
193+ resolve ( event ) ;
194+ }
195+ } ) ;
196+ }
197+
198+ /**
199+ * @inheritDoc
200+ */
201+ protected _setupTransport ( ) : Transport {
202+ if ( ! this . _options . dsn ) {
203+ // We return the noop transport here in case there is no Dsn.
204+ return super . _setupTransport ( ) ;
205+ }
206+
207+ const dsn = new Dsn ( this . _options . dsn ) ;
208+
209+ const transportOptions : TransportOptions = {
210+ ...this . _options . transportOptions ,
211+ ...( this . _options . httpProxy && { httpProxy : this . _options . httpProxy } ) ,
212+ ...( this . _options . httpsProxy && { httpsProxy : this . _options . httpsProxy } ) ,
213+ ...( this . _options . caCerts && { caCerts : this . _options . caCerts } ) ,
214+ dsn : this . _options . dsn ,
215+ tunnel : this . _options . tunnel ,
216+ _metadata : this . _options . _metadata ,
217+ } ;
218+
219+ if ( this . _options . transport ) {
220+ return new this . _options . transport ( transportOptions ) ;
221+ }
222+ if ( dsn . protocol === 'http' ) {
223+ return new HTTPTransport ( transportOptions ) ;
224+ }
225+ return new HTTPSTransport ( transportOptions ) ;
226+ }
227+
108228 /**
109229 * @inheritDoc
110230 */
0 commit comments