1
1
/*
2
2
The script serves to generate CodePushified React Native app to reproduce issues or for testing purposes.
3
3
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
+
4
7
Requirements:
5
8
1. npm i -g react-native-cli
6
9
2. npm i -g appcenter-cli
@@ -34,13 +37,6 @@ if (fs.existsSync(appName)) {
34
37
process . exit ( ) ;
35
38
}
36
39
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
- }
44
40
45
41
const appNameAndroid = `${ appName } -android` ;
46
42
const appNameIOS = `${ appName } -ios` ;
@@ -49,6 +45,7 @@ const reactNativeVersion = args[1] || `react-native@${execCommand('npm view reac
49
45
const reactNativeVersionIsLowerThanV049 = isReactNativeVersionLowerThan ( 49 ) ;
50
46
const reactNativeCodePushVersion = args [ 2 ] || `react-native-code-push@${ execCommand ( 'npm view react-native-code-push version' ) } ` . trim ( ) ;
51
47
48
+ const reactNativeVersionIsLowerThanV073 = isReactNativeVersionLowerThan ( 73 )
52
49
if ( ! isReactNativeVersionLowerThan ( 60 ) && process . platform === "darwin" ) {
53
50
try {
54
51
console . log ( "Verify that CocoaPods installed" ) ;
@@ -89,8 +86,8 @@ function createCodePushApp(name, os) {
89
86
const app = JSON . parse ( appResult ) ;
90
87
owner = app . owner . name ;
91
88
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.` , ) ;
94
91
console . error ( "Error: " , e . toString ( ) ) ;
95
92
}
96
93
execCommand ( `appcenter codepush deployment add -a ${ owner } /${ name } Staging` ) ;
@@ -128,7 +125,7 @@ function generatePlainReactNativeApp(appName, reactNativeVersion) {
128
125
129
126
function installCodePush ( reactNativeCodePushVersion ) {
130
127
console . log ( `Installing React Native Module for CodePush...` ) ;
131
- execCommand ( `yarn add ${ reactNativeCodePushVersion } ` ) ;
128
+ execCommand ( `npm i ${ reactNativeCodePushVersion } ` ) ;
132
129
console . log ( `React Native Module for CodePush has been installed \n` ) ;
133
130
}
134
131
@@ -213,8 +210,8 @@ function optimizeToTestInDebugMode() {
213
210
const rnXcodeShPath = `node_modules/react-native/${ rnXcodeShLocationFolder } /react-native-xcode.sh` ;
214
211
// Replace "if [[ "$PLATFORM_NAME" == *simulator ]]; then" with "if false; then" to force bundling
215
212
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` ) ;
218
215
}
219
216
220
217
function grantAccess ( folderPath ) {
@@ -250,7 +247,8 @@ function isReactNativeVersionLowerThan(version) {
250
247
function androidSetup ( ) {
251
248
const buildGradlePath = path . join ( 'android' , 'app' , 'build.gradle' ) ;
252
249
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 } ` ) ;
254
252
const stringsResourcesPath = path . join ( 'android' , 'app' , 'src' , 'main' , 'res' , 'values' , 'strings.xml' ) ;
255
253
256
254
let stringsResourcesContent = fs . readFileSync ( stringsResourcesPath , "utf8" ) ;
@@ -260,47 +258,78 @@ function androidSetup() {
260
258
fs . writeFileSync ( stringsResourcesPath , stringsResourcesContent ) ;
261
259
262
260
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 [ " ' ] / ) ;
264
262
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
+ }
268
274
269
275
let settingsGradleContents = fs . readFileSync ( settingsGradlePath , "utf8" ) ;
270
276
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')` ;
272
278
settingsGradleContents = settingsGradleContents . replace ( settingsGradleInclude ,
273
279
`${ settingsGradleInclude } , ${ codePushProjectImport } ` ) ;
274
280
fs . writeFileSync ( settingsGradlePath , settingsGradleContents ) ;
275
281
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;" ;
282
284
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
+ }
284
310
mainApplicationContents = mainApplicationContents . replace ( reactNativeHostInstantiation ,
285
311
`${ reactNativeHostInstantiation } ${ getJSBundleFileOverride } ` ) ;
286
312
287
- const importCodePush = `\nimport com.microsoft.codepush.react.CodePush;` ;
288
- const reactNativeHostInstantiationImport = "import android.app.Application;" ;
289
313
mainApplicationContents = mainApplicationContents . replace ( reactNativeHostInstantiationImport ,
290
314
`${ reactNativeHostInstantiationImport } ${ importCodePush } ` ) ;
291
315
fs . writeFileSync ( mainApplicationPath , mainApplicationContents ) ;
292
316
}
293
317
318
+ function getAppDelegateName ( ) { return fs . readdirSync ( path . join ( 'ios' , appName ) ) . find ( file => file === ( 'AppDelegate.mm' ) || file === 'AppDelegate.m' ) } ;
319
+
294
320
// Configuring ios applications for react-native version higher than 0.60
295
321
function iosSetup ( ) {
296
322
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 ( ) ) ;
298
325
299
326
let plistContents = fs . readFileSync ( plistPath , "utf8" ) ;
300
- const falseInfoPlist = `<false/>` ;
327
+
328
+ const dictPlistTag = `</dict>\n</plist>` ;
329
+
301
330
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 } ` ) ;
304
333
fs . writeFileSync ( plistPath , plistContents ) ;
305
334
306
335
let appDelegateContents = fs . readFileSync ( appDelegatePath , "utf8" ) ;
0 commit comments