1+ import  type  {  ExpoConfig  }  from  '@expo/config-types' ; 
12/* eslint-disable @typescript-eslint/no-unsafe-member-access */ 
23import  type  {  ConfigPlugin ,  XcodeProject  }  from  'expo/config-plugins' ; 
3- import  {  withDangerousMod ,  withXcodeProject  }  from  'expo/config-plugins' ; 
4+ import  {  withAppDelegate ,   withDangerousMod ,  withXcodeProject  }  from  'expo/config-plugins' ; 
45import  *  as  path  from  'path' ; 
56
67import  {  warnOnce ,  writeSentryPropertiesTo  }  from  './utils' ; 
@@ -12,8 +13,11 @@ const SENTRY_REACT_NATIVE_XCODE_PATH =
1213const  SENTRY_REACT_NATIVE_XCODE_DEBUG_FILES_PATH  = 
1314  "`${NODE_BINARY:-node} --print \"require('path').dirname(require.resolve('@sentry/react-native/package.json')) + '/scripts/sentry-xcode-debug-files.sh'\"`" ; 
1415
15- export  const  withSentryIOS : ConfigPlugin < string >  =  ( config ,  sentryProperties : string )  =>  { 
16-   const  cfg  =  withXcodeProject ( config ,  config  =>  { 
16+ export  const  withSentryIOS : ConfigPlugin < {  sentryProperties : string ;  useNativeInit : boolean  |  undefined  } >  =  ( 
17+   config , 
18+   {  sentryProperties,  useNativeInit =  false  } , 
19+ )  =>  { 
20+   const  xcodeProjectCfg  =  withXcodeProject ( config ,  config  =>  { 
1721    const  xcodeProject : XcodeProject  =  config . modResults ; 
1822
1923    const  sentryBuildPhase  =  xcodeProject . pbxItemByComment ( 
@@ -36,7 +40,9 @@ export const withSentryIOS: ConfigPlugin<string> = (config, sentryProperties: st
3640    return  config ; 
3741  } ) ; 
3842
39-   return  withDangerousMod ( cfg ,  [ 
43+   const  appDelegateCfc  =  useNativeInit  ? modifyAppDelegate ( xcodeProjectCfg )  : xcodeProjectCfg ; 
44+ 
45+   return  withDangerousMod ( appDelegateCfc ,  [ 
4046    'ios' , 
4147    config  =>  { 
4248      writeSentryPropertiesTo ( path . resolve ( config . modRequest . projectRoot ,  'ios' ) ,  sentryProperties ) ; 
@@ -79,3 +85,58 @@ export function addSentryWithBundledScriptsToBundleShellScript(script: string):
7985    ( match : string )  =>  `/bin/sh ${ SENTRY_REACT_NATIVE_XCODE_PATH }   ${ match }  ` , 
8086  ) ; 
8187} 
88+ 
89+ export  function  modifyAppDelegate ( config : ExpoConfig ) : ExpoConfig  { 
90+   return  withAppDelegate ( config ,  async  config  =>  { 
91+     if  ( ! config . modResults  ||  ! config . modResults . path )  { 
92+       warnOnce ( 'Skipping AppDelegate modification because the file does not exist.' ) ; 
93+       return  config ; 
94+     } 
95+ 
96+     const  fileName  =  config . modResults . path . split ( '/' ) . pop ( ) ; 
97+ 
98+     if  ( config . modResults . language  ===  'swift' )  { 
99+       if  ( config . modResults . contents . includes ( 'RNSentrySDK.start()' ) )  { 
100+         warnOnce ( `Your '${ fileName }  ' already contains 'RNSentrySDK.start()'.` ) ; 
101+         return  config ; 
102+       } 
103+       if  ( ! config . modResults . contents . includes ( 'import RNSentry' ) )  { 
104+         // Insert import statement after UIKit import 
105+         config . modResults . contents  =  config . modResults . contents . replace ( / ( i m p o r t   U I K i t \n ) / ,  `$1import RNSentry\n` ) ; 
106+       } 
107+       // Add RNSentrySDK.start() at the beginning of application method 
108+       const  originalContents  =  config . modResults . contents ; 
109+       config . modResults . contents  =  config . modResults . contents . replace ( 
110+         / ( f u n c   a p p l i c a t i o n \( [ ^ ) ] * \)   - >   B o o l   \{ ) / s, 
111+         `$1\n    RNSentrySDK.start()` , 
112+       ) ; 
113+       if  ( config . modResults . contents  ===  originalContents )  { 
114+         warnOnce ( `Failed to insert 'RNSentrySDK.start()'.` ) ; 
115+       } 
116+     }  else  { 
117+       // Objective-C 
118+       if  ( config . modResults . contents . includes ( '[RNSentrySDK start]' ) )  { 
119+         warnOnce ( `Your '${ fileName }  ' already contains '[RNSentrySDK start]'.` ) ; 
120+         return  config ; 
121+       } 
122+       if  ( ! config . modResults . contents . includes ( '#import <RNSentry/RNSentry.h>' ) )  { 
123+         // Add import after AppDelegate.h 
124+         config . modResults . contents  =  config . modResults . contents . replace ( 
125+           / ( # i m p o r t   " A p p D e l e g a t e .h " \n ) / , 
126+           `$1#import <RNSentry/RNSentry.h>\n` , 
127+         ) ; 
128+       } 
129+       // Add [RNSentrySDK start] at the beginning of application:didFinishLaunchingWithOptions method 
130+       const  originalContents  =  config . modResults . contents ; 
131+       config . modResults . contents  =  config . modResults . contents . replace ( 
132+         / ( -   \( B O O L \) a p p l i c a t i o n : [ \s \S ] * ?d i d F i n i s h L a u n c h i n g W i t h O p t i o n s : [ \s \S ] * ?\{ \n ) ( \s * ) / s, 
133+         `$1$2[RNSentrySDK start];\n$2` , 
134+       ) ; 
135+       if  ( config . modResults . contents  ===  originalContents )  { 
136+         warnOnce ( `Failed to insert '[RNSentrySDK start]'.` ) ; 
137+       } 
138+     } 
139+ 
140+     return  config ; 
141+   } ) ; 
142+ } 
0 commit comments