11/*
22The script serves to generate CodePushified React Native app to reproduce issues or for testing purposes.
33
4+ NOTE: Use CodePushDemoApp and CodePushDemoAppCpp as reference how to implement CodePush in your app. For creating a working demo app
5+ follow steps bellow.
6+
47Requirements:
58 1. npm i -g react-native-cli
69 2. npm i -g appcenter-cli
@@ -34,13 +37,6 @@ if (fs.existsSync(appName)) {
3437 process . exit ( ) ;
3538}
3639
37- // Checking if yarn is installed
38- try {
39- execCommand ( 'yarn bin' ) ;
40- } catch ( err ) {
41- console . error ( `You must install 'yarn' to use this script!` ) ;
42- process . exit ( ) ;
43- }
4440
4541const appNameAndroid = `${ appName } -android` ;
4642const appNameIOS = `${ appName } -ios` ;
@@ -49,6 +45,7 @@ const reactNativeVersion = args[1] || `react-native@${execCommand('npm view reac
4945const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan ( 49 ) ;
5046const reactNativeCodePushVersion = args [ 2 ] || `react-native-code-push@${ execCommand ( 'npm view react-native-code-push version' ) } ` . trim ( ) ;
5147
48+ const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan ( 73 )
5249if ( ! isReactNativeVersionLowerThan ( 60 ) && process . platform === "darwin" ) {
5350 try {
5451 console . log ( "Verify that CocoaPods installed" ) ;
@@ -89,8 +86,8 @@ function createCodePushApp(name, os) {
8986 const app = JSON . parse ( appResult ) ;
9087 owner = app . owner . name ;
9188 console . log ( `App "${ name } " has been created \n` ) ;
92- } catch ( e ) {
93- console . error ( `Error: Unable to create CodePush app. Please check that you haven't application with "${ name } " name on portal.` , ) ;
89+ } catch ( e ) {
90+ console . error ( `Error: Unable to create CodePush app. Please check that you haven't application with "${ name } " name on portal.` , ) ;
9491 console . error ( "Error: " , e . toString ( ) ) ;
9592 }
9693 execCommand ( `appcenter codepush deployment add -a ${ owner } /${ name } Staging` ) ;
@@ -128,7 +125,7 @@ function generatePlainReactNativeApp(appName, reactNativeVersion) {
128125
129126function installCodePush ( reactNativeCodePushVersion ) {
130127 console . log ( `Installing React Native Module for CodePush...` ) ;
131- execCommand ( `yarn add ${ reactNativeCodePushVersion } ` ) ;
128+ execCommand ( `npm i ${ reactNativeCodePushVersion } ` ) ;
132129 console . log ( `React Native Module for CodePush has been installed \n` ) ;
133130}
134131
@@ -213,8 +210,8 @@ function optimizeToTestInDebugMode() {
213210 const rnXcodeShPath = `node_modules/react-native/${ rnXcodeShLocationFolder } /react-native-xcode.sh` ;
214211 // Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling
215212 execCommand ( `sed -ie 's/if \\[\\[ "\$PLATFORM_NAME" == \\*simulator \\]\\]; then/if false; then/' ${ rnXcodeShPath } ` ) ;
216- execCommand ( `perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${ appName } /AppDelegate.m ` ) ;
217- execCommand ( `sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle` ) ;
213+ execCommand ( `perl -i -p0e 's/#ifdef DEBUG.*?#endif/jsCodeLocation = [CodePush bundleURL];/s' ios/${ appName } /${ getAppDelegateName ( ) } ` ) ;
214+ reactNativeVersionIsLowerThanV073 && execCommand ( `sed -ie 's/targetName.toLowerCase().contains("release")/true/' node_modules/react-native/react.gradle` ) ;
218215}
219216
220217function grantAccess ( folderPath ) {
@@ -250,7 +247,8 @@ function isReactNativeVersionLowerThan(version) {
250247function androidSetup ( ) {
251248 const buildGradlePath = path . join ( 'android' , 'app' , 'build.gradle' ) ;
252249 const settingsGradlePath = path . join ( 'android' , 'settings.gradle' ) ;
253- const mainApplicationPath = path . join ( 'android' , 'app' , 'src' , 'main' , 'java' , 'com' , appName , 'MainApplication.java' ) ;
250+ const mainApplicationType = reactNativeVersionIsLowerThanV073 ? 'java' : 'kt' ;
251+ const mainApplicationPath = path . join ( 'android' , 'app' , 'src' , 'main' , 'java' , 'com' , appName , `MainApplication.${ mainApplicationType } ` ) ;
254252 const stringsResourcesPath = path . join ( 'android' , 'app' , 'src' , 'main' , 'res' , 'values' , 'strings.xml' ) ;
255253
256254 let stringsResourcesContent = fs . readFileSync ( stringsResourcesPath , "utf8" ) ;
@@ -260,47 +258,78 @@ function androidSetup() {
260258 fs . writeFileSync ( stringsResourcesPath , stringsResourcesContent ) ;
261259
262260 let buildGradleContents = fs . readFileSync ( buildGradlePath , "utf8" ) ;
263- const reactGradleLink = buildGradleContents . match ( / \n a p p l y f r o m : [ " ' ] .* ?r e a c t \. g r a d l e [ " ' ] / ) [ 0 ] ;
261+ const reactGradleLink = buildGradleContents . match ( / \n a p p l y f r o m : [ " ' ] .* ?r e a c t \. g r a d l e [ " ' ] / ) ;
264262 const codePushGradleLink = `\napply from: "../../node_modules/react-native-code-push/android/codepush.gradle"` ;
265- buildGradleContents = buildGradleContents . replace ( reactGradleLink ,
266- `${ reactGradleLink } ${ codePushGradleLink } ` ) ;
267- fs . writeFileSync ( buildGradlePath , buildGradleContents ) ;
263+ if ( reactGradleLink != null ) {
264+ buildGradleContents = buildGradleContents . replace ( reactGradleLink [ 0 ] ,
265+ `${ reactGradleLink [ 0 ] } ${ codePushGradleLink } ` ) ;
266+ fs . writeFileSync ( buildGradlePath , buildGradleContents ) ;
267+ }
268+ // react.gradle script removed from 0.71 thus this workaround
269+ else {
270+ const appPluginLastLine = buildGradleContents . match ( / a p p l y p l u g i n : " c o m .f a c e b o o k .r e a c t " / ) [ 0 ] ;
271+ buildGradleContents = buildGradleContents . replace ( appPluginLastLine , `${ appPluginLastLine } ${ codePushGradleLink } ` )
272+ fs . writeFileSync ( buildGradlePath , buildGradleContents ) ;
273+ }
268274
269275 let settingsGradleContents = fs . readFileSync ( settingsGradlePath , "utf8" ) ;
270276 const settingsGradleInclude = "include \':app\'" ;
271- const codePushProjectImport = `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')` ;
277+ const codePushProjectImport = `':react-native-code-push'\nproject(':react-native-code-push').projectDir = new File(rootProject.projectDir, '../node_modules/react-native-code-push/android/app')` ;
272278 settingsGradleContents = settingsGradleContents . replace ( settingsGradleInclude ,
273279 `${ settingsGradleInclude } , ${ codePushProjectImport } ` ) ;
274280 fs . writeFileSync ( settingsGradlePath , settingsGradleContents ) ;
275281
276- const getJSBundleFileOverride = `
277- @Override
278- protected String getJSBundleFile(){
279- return CodePush.getJSBundleFile();
280- }
281- ` ;
282+ let importCodePush = `\nimport com.microsoft.codepush.react.CodePush;` ;
283+ let reactNativeHostInstantiationImport = "import android.app.Application;" ;
282284 let mainApplicationContents = fs . readFileSync ( mainApplicationPath , "utf8" ) ;
283- const reactNativeHostInstantiation = "new ReactNativeHost(this) {" ;
285+ let getJSBundleFileOverride = "" ;
286+ let reactNativeHostInstantiation = "" ;
287+
288+ // handle react-native version with java
289+ if ( reactNativeVersionIsLowerThanV073 ) {
290+ reactNativeHostInstantiation = "new ReactNativeHost(this) {" ;
291+
292+ getJSBundleFileOverride = `
293+ @Override
294+ protected String getJSBundleFile(){
295+ return CodePush.getJSBundleFile();
296+ }
297+ ` ;
298+ }
299+ // handle react-native version with kotlin
300+ else {
301+ reactNativeHostInstantiation = "object : DefaultReactNativeHost(this) {"
302+ getJSBundleFileOverride = `
303+ override fun getJSBundleFile(): String {
304+ return CodePush.getJSBundleFile()
305+ }
306+ ` ;
307+ importCodePush = importCodePush . replace ( ';' , '' ) ;
308+ reactNativeHostInstantiationImport = reactNativeHostInstantiationImport . replace ( ';' , '' ) ;
309+ }
284310 mainApplicationContents = mainApplicationContents . replace ( reactNativeHostInstantiation ,
285311 `${ reactNativeHostInstantiation } ${ getJSBundleFileOverride } ` ) ;
286312
287- const importCodePush = `\nimport com.microsoft.codepush.react.CodePush;` ;
288- const reactNativeHostInstantiationImport = "import android.app.Application;" ;
289313 mainApplicationContents = mainApplicationContents . replace ( reactNativeHostInstantiationImport ,
290314 `${ reactNativeHostInstantiationImport } ${ importCodePush } ` ) ;
291315 fs . writeFileSync ( mainApplicationPath , mainApplicationContents ) ;
292316}
293317
318+ function getAppDelegateName ( ) { return fs . readdirSync ( path . join ( 'ios' , appName ) ) . find ( file => file === ( 'AppDelegate.mm' ) || file === 'AppDelegate.m' ) } ;
319+
294320// Configuring ios applications for react-native version higher than 0.60
295321function iosSetup ( ) {
296322 const plistPath = path . join ( 'ios' , appName , 'Info.plist' ) ;
297- const appDelegatePath = path . join ( 'ios' , appName , 'AppDelegate.m' ) ;
323+
324+ const appDelegatePath = path . join ( 'ios' , appName , getAppDelegateName ( ) ) ;
298325
299326 let plistContents = fs . readFileSync ( plistPath , "utf8" ) ;
300- const falseInfoPlist = `<false/>` ;
327+
328+ const dictPlistTag = `</dict>\n</plist>` ;
329+
301330 const codePushDeploymentKey = iosStagingDeploymentKey || 'deployment-key-here' ;
302- plistContents = plistContents . replace ( falseInfoPlist ,
303- `${ falseInfoPlist } \n\ t<key>CodePushDeploymentKey</key>\n\t<string>${ codePushDeploymentKey } </string>` ) ;
331+ plistContents = plistContents . replace ( dictPlistTag ,
332+ `\ t<key>CodePushDeploymentKey</key>\n\t<string>${ codePushDeploymentKey } </string>${ dictPlistTag } ` ) ;
304333 fs . writeFileSync ( plistPath , plistContents ) ;
305334
306335 let appDelegateContents = fs . readFileSync ( appDelegatePath , "utf8" ) ;
0 commit comments