1+ import { logger } from '@sentry/utils' ;
12import type { MetroConfig , MixedOutput , Module , ReadOnlyGraph } from 'metro' ;
3+ import * as process from 'process' ;
24import { env } from 'process' ;
35
6+ import { enableLogger } from './enableLogger' ;
7+ import {
8+ canUseSentryBabelTransformer ,
9+ cleanDefaultBabelTransformerPath ,
10+ saveDefaultBabelTransformerPath ,
11+ } from './sentryBabelTransformerUtils' ;
412import { createSentryMetroSerializer , unstable_beforeAssetSerializationPlugin } from './sentryMetroSerializer' ;
513import type { DefaultConfigOptions } from './vendor/expo/expoconfig' ;
614
715export * from './sentryMetroSerializer' ;
816
17+ enableLogger ( ) ;
18+
19+ export interface SentryMetroConfigOptions {
20+ /**
21+ * Annotates React components with Sentry data.
22+ * @default false
23+ */
24+ annotateReactComponents ?: boolean ;
25+ }
26+
27+ export interface SentryExpoConfigOptions {
28+ /**
29+ * Pass a custom `getDefaultConfig` function to override the default Expo configuration getter.
30+ */
31+ getDefaultConfig ?: typeof getSentryExpoConfig
32+ }
33+
934/**
1035 * Adds Sentry to the Metro config.
1136 *
1237 * Adds Debug ID to the output bundle and source maps.
1338 * Collapses Sentry frames from the stack trace view in LogBox.
1439 */
15- export function withSentryConfig ( config : MetroConfig ) : MetroConfig {
40+ export function withSentryConfig (
41+ config : MetroConfig ,
42+ { annotateReactComponents = false } : SentryMetroConfigOptions = { } ,
43+ ) : MetroConfig {
1644 setSentryMetroDevServerEnvFlag ( ) ;
1745
1846 let newConfig = config ;
1947
2048 newConfig = withSentryDebugId ( newConfig ) ;
2149 newConfig = withSentryFramesCollapsed ( newConfig ) ;
50+ if ( annotateReactComponents ) {
51+ newConfig = withSentryBabelTransformer ( newConfig ) ;
52+ }
2253
2354 return newConfig ;
2455}
@@ -28,7 +59,7 @@ export function withSentryConfig(config: MetroConfig): MetroConfig {
2859 */
2960export function getSentryExpoConfig (
3061 projectRoot : string ,
31- options : DefaultConfigOptions & { getDefaultConfig ?: typeof getSentryExpoConfig } = { } ,
62+ options : DefaultConfigOptions & SentryExpoConfigOptions & SentryMetroConfigOptions = { } ,
3263) : MetroConfig {
3364 setSentryMetroDevServerEnvFlag ( ) ;
3465
@@ -41,7 +72,12 @@ export function getSentryExpoConfig(
4172 ] ,
4273 } ) ;
4374
44- return withSentryFramesCollapsed ( config ) ;
75+ let newConfig = withSentryFramesCollapsed ( config ) ;
76+ if ( options . annotateReactComponents ) {
77+ newConfig = withSentryBabelTransformer ( newConfig ) ;
78+ }
79+
80+ return newConfig ;
4581}
4682
4783function loadExpoMetroConfigModule ( ) : {
@@ -64,6 +100,32 @@ function loadExpoMetroConfigModule(): {
64100 }
65101}
66102
103+ function withSentryBabelTransformer ( config : MetroConfig ) : MetroConfig {
104+ const defaultBabelTransformerPath = config . transformer && config . transformer . babelTransformerPath ;
105+ logger . debug ( 'Default Babel transformer path from `config.transformer`:' , defaultBabelTransformerPath ) ;
106+
107+ if ( ! defaultBabelTransformerPath && ! canUseSentryBabelTransformer ( config . projectRoot ) ) {
108+ // eslint-disable-next-line no-console
109+ console . warn ( 'Sentry Babel transformer cannot be used. Not adding it ...' ) ;
110+ return config ;
111+ }
112+
113+ if ( defaultBabelTransformerPath ) {
114+ saveDefaultBabelTransformerPath ( config . projectRoot || '.' , defaultBabelTransformerPath ) ;
115+ process . on ( 'exit' , ( ) => {
116+ cleanDefaultBabelTransformerPath ( config . projectRoot || '.' ) ;
117+ } ) ;
118+ }
119+
120+ return {
121+ ...config ,
122+ transformer : {
123+ ...config . transformer ,
124+ babelTransformerPath : require . resolve ( './sentryBabelTransformer' ) ,
125+ } ,
126+ } ;
127+ }
128+
67129type MetroCustomSerializer = Required < Required < MetroConfig > [ 'serializer' ] > [ 'customSerializer' ] | undefined ;
68130
69131function withSentryDebugId ( config : MetroConfig ) : MetroConfig {
0 commit comments