@bravemobile/react-native-code-push 12.1.0 → 12.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -146,7 +146,28 @@ Then, edit `AppDelegate.swift` like below.
146
146
 
147
147
  #### Edit `MainApplication` Code
148
148
 
149
- **If you have `MainApplication.kt` (>= RN 0.73)**
149
+ **(RN 0.82+) If you have `MainApplication.kt`**
150
+
151
+ ```diff
152
+ + import com.microsoft.codepush.react.CodePush
153
+
154
+ class MainApplication : Application(), ReactApplication {
155
+ override val reactHost: ReactHost by lazy {
156
+ getDefaultReactHost(
157
+ context = applicationContext,
158
+ packageList =
159
+ PackageList(this).packages.apply {
160
+ // Packages that cannot be autolinked yet can be added manually here, for example:
161
+ // add(MyReactNativePackage())
162
+ },
163
+ + jsBundleFilePath = CodePush.getJSBundleFile(),
164
+ )
165
+ }
166
+ // ...
167
+ }
168
+ ```
169
+
170
+ **(RN 0.73+) If you have `MainApplication.kt`**
150
171
 
151
172
  ```diff
152
173
  + import com.microsoft.codepush.react.CodePush
@@ -163,6 +184,7 @@ Then, edit `AppDelegate.swift` like below.
163
184
  }
164
185
  ```
165
186
 
187
+
166
188
  **Or if you have `MainApplication.java`**
167
189
 
168
190
  ```diff
package/app.plugin.js ADDED
@@ -0,0 +1 @@
1
+ module.exports = require("./expo/plugin/withCodePush");
@@ -2,14 +2,62 @@ import path from "path";
2
2
  import fs from "fs";
3
3
  import { EOL } from "os";
4
4
 
5
+ const IMPORT_CODE_PUSH = 'import com.microsoft.codepush.react.CodePush';
6
+ const RN_LEGACY_MARKER = 'object : DefaultReactNativeHost(this)';
7
+ const RN_082_MARKER = ' getDefaultReactHost(';
8
+
5
9
  export function modifyMainApplicationKt(mainApplicationContent: string) {
6
- if (mainApplicationContent.includes('CodePush.getJSBundleFile()')) {
10
+ const hasCodePushImport = mainApplicationContent.includes(IMPORT_CODE_PUSH);
11
+ const hasGetJSBundleFileFn = mainApplicationContent.includes('CodePush.getJSBundleFile()');
12
+
13
+ if (hasCodePushImport && hasGetJSBundleFileFn) {
7
14
  console.log('log: MainApplication.kt already has CodePush initialized.');
8
15
  return mainApplicationContent;
9
16
  }
10
- return mainApplicationContent
11
- .replace('import com.facebook.react.ReactApplication', `import com.facebook.react.ReactApplication${EOL}import com.microsoft.codepush.react.CodePush`)
12
- .replace('override fun getJSMainModuleName(): String = "index"', `override fun getJSMainModuleName(): String = "index"${EOL} override fun getJSBundleFile(): String = CodePush.getJSBundleFile()`)
17
+
18
+ let updatedContent = mainApplicationContent;
19
+
20
+ if (!hasCodePushImport) {
21
+ updatedContent = mainApplicationContent.replace('import com.facebook.react.ReactApplication', `import com.facebook.react.ReactApplication${EOL}${IMPORT_CODE_PUSH}`);
22
+ }
23
+
24
+ const isExtendingDefaultReactNativeHost = mainApplicationContent.includes(RN_LEGACY_MARKER);
25
+
26
+ // RN <0.82
27
+ if (isExtendingDefaultReactNativeHost) {
28
+ if (!hasGetJSBundleFileFn) {
29
+ updatedContent = updatedContent.replace('override fun getJSMainModuleName(): String = "index"', `override fun getJSMainModuleName(): String = "index"${EOL} override fun getJSBundleFile(): String = CodePush.getJSBundleFile()`);
30
+ }
31
+ return updatedContent;
32
+ }
33
+
34
+ // RN 0.82+
35
+ const isUsingGetDefaultReactHost = mainApplicationContent.includes(RN_082_MARKER);
36
+ if (isUsingGetDefaultReactHost) {
37
+ if (!hasGetJSBundleFileFn) {
38
+ return addJsBundleFilePathArgument(updatedContent);
39
+ }
40
+ return updatedContent;
41
+ }
42
+
43
+ throw new Error('Unsupported MainApplication.kt structure.');
44
+ }
45
+
46
+ function addJsBundleFilePathArgument(mainApplicationContent: string) {
47
+ const packageListArgumentPattern = /(packageList\s*=\s*\n\s*PackageList\(this\)[\s\S]+?\},\s*\n)/;
48
+
49
+ if (!packageListArgumentPattern.test(mainApplicationContent)) {
50
+ console.log('log: Could not find packageList argument while updating MainApplication.kt.');
51
+ return mainApplicationContent;
52
+ }
53
+
54
+ return mainApplicationContent.replace(packageListArgumentPattern, (match) => {
55
+ if (match.includes('jsBundleFilePath')) {
56
+ return match;
57
+ }
58
+
59
+ return `${match} jsBundleFilePath = CodePush.getJSBundleFile(),${EOL}`;
60
+ });
13
61
  }
14
62
 
15
63
  export async function initAndroid() {
@@ -47,6 +47,37 @@ class MainApplication : Application(), ReactApplication {
47
47
  }
48
48
  `;
49
49
 
50
+ // https://github.com/react-native-community/template/blob/0.82.1/template/android/app/src/main/java/com/helloworld/MainApplication.kt
51
+ const ktRN82Template = `
52
+ package com.helloworld
53
+
54
+ import android.app.Application
55
+ import com.facebook.react.PackageList
56
+ import com.facebook.react.ReactApplication
57
+ import com.facebook.react.ReactHost
58
+ import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
59
+ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
60
+
61
+ class MainApplication : Application(), ReactApplication {
62
+
63
+ override val reactHost: ReactHost by lazy {
64
+ getDefaultReactHost(
65
+ context = applicationContext,
66
+ packageList =
67
+ PackageList(this).packages.apply {
68
+ // Packages that cannot be autolinked yet can be added manually here, for example:
69
+ // add(MyReactNativePackage())
70
+ },
71
+ )
72
+ }
73
+
74
+ override fun onCreate() {
75
+ super.onCreate()
76
+ loadReactNative(this)
77
+ }
78
+ }
79
+ `;
80
+
50
81
  describe('Android init command', () => {
51
82
  it('should correctly modify Kotlin MainApplication content', () => {
52
83
  const modifiedContent = modifyMainApplicationKt(ktTemplate);
@@ -54,6 +85,17 @@ describe('Android init command', () => {
54
85
  expect(modifiedContent).toContain('override fun getJSBundleFile(): String = CodePush.getJSBundleFile()');
55
86
  });
56
87
 
88
+ it('should insert jsBundleFilePath argument for RN 0.82 style MainApplication', () => {
89
+ const modifiedContent = modifyMainApplicationKt(ktRN82Template);
90
+
91
+ expect(modifiedContent).toContain('import com.microsoft.codepush.react.CodePush');
92
+ expect(modifiedContent).toContain('jsBundleFilePath = CodePush.getJSBundleFile()');
93
+
94
+ const packageListIndex = modifiedContent.indexOf('packageList =');
95
+ const jsBundleIndex = modifiedContent.indexOf('jsBundleFilePath = CodePush.getJSBundleFile()');
96
+ expect(jsBundleIndex).toBeGreaterThan(packageListIndex);
97
+ });
98
+
57
99
  it('should log a message and exit if MainApplication.java is found', async () => {
58
100
  const originalCwd = process.cwd();
59
101
 
@@ -1,14 +1,50 @@
1
1
  import path from "path";
2
2
  import fs from "fs";
3
3
  import { EOL } from "os";
4
+ const IMPORT_CODE_PUSH = 'import com.microsoft.codepush.react.CodePush';
5
+ const RN_LEGACY_MARKER = 'object : DefaultReactNativeHost(this)';
6
+ const RN_082_MARKER = ' getDefaultReactHost(';
4
7
  export function modifyMainApplicationKt(mainApplicationContent) {
5
- if (mainApplicationContent.includes('CodePush.getJSBundleFile()')) {
8
+ const hasCodePushImport = mainApplicationContent.includes(IMPORT_CODE_PUSH);
9
+ const hasGetJSBundleFileFn = mainApplicationContent.includes('CodePush.getJSBundleFile()');
10
+ if (hasCodePushImport && hasGetJSBundleFileFn) {
6
11
  console.log('log: MainApplication.kt already has CodePush initialized.');
7
12
  return mainApplicationContent;
8
13
  }
9
- return mainApplicationContent
10
- .replace('import com.facebook.react.ReactApplication', `import com.facebook.react.ReactApplication${EOL}import com.microsoft.codepush.react.CodePush`)
11
- .replace('override fun getJSMainModuleName(): String = "index"', `override fun getJSMainModuleName(): String = "index"${EOL} override fun getJSBundleFile(): String = CodePush.getJSBundleFile()`);
14
+ let updatedContent = mainApplicationContent;
15
+ if (!hasCodePushImport) {
16
+ updatedContent = mainApplicationContent.replace('import com.facebook.react.ReactApplication', `import com.facebook.react.ReactApplication${EOL}${IMPORT_CODE_PUSH}`);
17
+ }
18
+ const isExtendingDefaultReactNativeHost = mainApplicationContent.includes(RN_LEGACY_MARKER);
19
+ // RN <0.82
20
+ if (isExtendingDefaultReactNativeHost) {
21
+ if (!hasGetJSBundleFileFn) {
22
+ updatedContent = updatedContent.replace('override fun getJSMainModuleName(): String = "index"', `override fun getJSMainModuleName(): String = "index"${EOL} override fun getJSBundleFile(): String = CodePush.getJSBundleFile()`);
23
+ }
24
+ return updatedContent;
25
+ }
26
+ // RN 0.82+
27
+ const isUsingGetDefaultReactHost = mainApplicationContent.includes(RN_082_MARKER);
28
+ if (isUsingGetDefaultReactHost) {
29
+ if (!hasGetJSBundleFileFn) {
30
+ return addJsBundleFilePathArgument(updatedContent);
31
+ }
32
+ return updatedContent;
33
+ }
34
+ throw new Error('Unsupported MainApplication.kt structure.');
35
+ }
36
+ function addJsBundleFilePathArgument(mainApplicationContent) {
37
+ const packageListArgumentPattern = /(packageList\s*=\s*\n\s*PackageList\(this\)[\s\S]+?\},\s*\n)/;
38
+ if (!packageListArgumentPattern.test(mainApplicationContent)) {
39
+ console.log('log: Could not find packageList argument while updating MainApplication.kt.');
40
+ return mainApplicationContent;
41
+ }
42
+ return mainApplicationContent.replace(packageListArgumentPattern, (match) => {
43
+ if (match.includes('jsBundleFilePath')) {
44
+ return match;
45
+ }
46
+ return `${match} jsBundleFilePath = CodePush.getJSBundleFile(),${EOL}`;
47
+ });
12
48
  }
13
49
  export async function initAndroid() {
14
50
  console.log('log: Running Android setup...');
@@ -44,12 +44,50 @@ class MainApplication : Application(), ReactApplication {
44
44
  }
45
45
  }
46
46
  `;
47
+ // https://github.com/react-native-community/template/blob/0.82.1/template/android/app/src/main/java/com/helloworld/MainApplication.kt
48
+ const ktRN82Template = `
49
+ package com.helloworld
50
+
51
+ import android.app.Application
52
+ import com.facebook.react.PackageList
53
+ import com.facebook.react.ReactApplication
54
+ import com.facebook.react.ReactHost
55
+ import com.facebook.react.ReactNativeApplicationEntryPoint.loadReactNative
56
+ import com.facebook.react.defaults.DefaultReactHost.getDefaultReactHost
57
+
58
+ class MainApplication : Application(), ReactApplication {
59
+
60
+ override val reactHost: ReactHost by lazy {
61
+ getDefaultReactHost(
62
+ context = applicationContext,
63
+ packageList =
64
+ PackageList(this).packages.apply {
65
+ // Packages that cannot be autolinked yet can be added manually here, for example:
66
+ // add(MyReactNativePackage())
67
+ },
68
+ )
69
+ }
70
+
71
+ override fun onCreate() {
72
+ super.onCreate()
73
+ loadReactNative(this)
74
+ }
75
+ }
76
+ `;
47
77
  describe('Android init command', () => {
48
78
  it('should correctly modify Kotlin MainApplication content', () => {
49
79
  const modifiedContent = modifyMainApplicationKt(ktTemplate);
50
80
  expect(modifiedContent).toContain('import com.microsoft.codepush.react.CodePush');
51
81
  expect(modifiedContent).toContain('override fun getJSBundleFile(): String = CodePush.getJSBundleFile()');
52
82
  });
83
+ it('should insert jsBundleFilePath argument for RN 0.82 style MainApplication', () => {
84
+ const modifiedContent = modifyMainApplicationKt(ktRN82Template);
85
+ expect(modifiedContent).toContain('import com.microsoft.codepush.react.CodePush');
86
+ expect(modifiedContent).toContain('jsBundleFilePath = CodePush.getJSBundleFile()');
87
+ const packageListIndex = modifiedContent.indexOf('packageList =');
88
+ const jsBundleIndex = modifiedContent.indexOf('jsBundleFilePath = CodePush.getJSBundleFile()');
89
+ expect(jsBundleIndex).toBeGreaterThan(packageListIndex);
90
+ });
53
91
  it('should log a message and exit if MainApplication.java is found', async () => {
54
92
  const originalCwd = process.cwd();
55
93
  fs.mkdirSync(tempDir, { recursive: true });
@@ -1,11 +1,10 @@
1
1
  const { withMainApplication, WarningAggregator } = require('expo/config-plugins');
2
2
 
3
- function androidMainApplicationApplyImplementation(
4
- mainApplication,
5
- find,
6
- add,
7
- reverse = false,
8
- ) {
3
+ const IMPORT_CODE_PUSH = 'import com.microsoft.codepush.react.CodePush';
4
+ const RN_082_MARKER = ' getDefaultReactHost(';
5
+ const JS_BUNDLE_FILE_PATH_ARGUMENT = 'jsBundleFilePath = CodePush.getJSBundleFile()';
6
+
7
+ function androidMainApplicationApplyImplementation(mainApplication, find, add, reverse = false) {
9
8
  if (mainApplication.includes(add)) {
10
9
  return mainApplication;
11
10
  }
@@ -28,20 +27,54 @@ function androidMainApplicationApplyImplementation(
28
27
  return mainApplication;
29
28
  }
30
29
 
30
+ function addJsBundleFilePathArgument(mainApplication) {
31
+ if (mainApplication.includes(JS_BUNDLE_FILE_PATH_ARGUMENT)) {
32
+ return mainApplication;
33
+ }
34
+
35
+ const packageListArgumentPattern = /(packageList\s*=\s*\n\s*PackageList\(this\)[\s\S]+?\},\s*\n)/;
36
+
37
+ if (!packageListArgumentPattern.test(mainApplication)) {
38
+ WarningAggregator.addWarningAndroid(
39
+ 'withCodePushAndroid',
40
+ `
41
+ Failed to detect "packageList = PackageList(this)" block in MainApplication.kt.
42
+ Please add "jsBundleFilePath = CodePush.getJSBundleFile()" inside getDefaultReactHost arguments.
43
+
44
+ Android manual setup: https://github.com/Soomgo-Mobile/react-native-code-push#2-1-manual-setup
45
+ `,
46
+ );
47
+ return mainApplication;
48
+ }
49
+
50
+ return mainApplication.replace(packageListArgumentPattern, (match) => {
51
+ if (match.includes('jsBundleFilePath')) {
52
+ return match;
53
+ }
54
+
55
+ return `${match} ${JS_BUNDLE_FILE_PATH_ARGUMENT},\n`;
56
+ });
57
+ }
58
+
31
59
  const withAndroidMainApplicationDependency = (config) => {
32
60
  return withMainApplication(config, (action) => {
33
61
  action.modResults.contents = androidMainApplicationApplyImplementation(
34
62
  action.modResults.contents,
35
- 'class MainApplication : Application(), ReactApplication {',
36
- 'import com.microsoft.codepush.react.CodePush\n',
37
- true,
63
+ 'import com.facebook.react.ReactApplication',
64
+ IMPORT_CODE_PUSH,
38
65
  );
39
66
 
40
- action.modResults.contents = androidMainApplicationApplyImplementation(
41
- action.modResults.contents,
42
- 'object : DefaultReactNativeHost(this) {',
43
- ' override fun getJSBundleFile(): String = CodePush.getJSBundleFile()\n',
44
- );
67
+ if (!action.modResults.contents.includes('CodePush.getJSBundleFile()')) {
68
+ if (action.modResults.contents.includes(RN_082_MARKER)) {
69
+ action.modResults.contents = addJsBundleFilePathArgument(action.modResults.contents);
70
+ } else {
71
+ action.modResults.contents = androidMainApplicationApplyImplementation(
72
+ action.modResults.contents,
73
+ 'object : DefaultReactNativeHost(this) {',
74
+ ' override fun getJSBundleFile(): String = CodePush.getJSBundleFile()\n');
75
+ }
76
+ }
77
+
45
78
  return action;
46
79
  });
47
80
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bravemobile/react-native-code-push",
3
- "version": "12.1.0",
3
+ "version": "12.1.2",
4
4
  "description": "React Native plugin for the CodePush service",
5
5
  "main": "src/CodePush.js",
6
6
  "react-native": "src/CodePush.js",
@@ -36,8 +36,8 @@
36
36
  "typings",
37
37
  "*.podspec",
38
38
  "react-native.config.js",
39
+ "app.plugin.js",
39
40
  "package.json",
40
- "package-lock.json",
41
41
  "!ios/build",
42
42
  "!android/build",
43
43
  "!android/app/build",