@vanikya/ota-react-native 0.2.7 → 0.2.8

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/app.plugin.js CHANGED
@@ -1,14 +1,13 @@
1
- const { withMainApplication, withAppDelegate } = require('@expo/config-plugins');
1
+ const { withMainApplication, withAppDelegate, withDangerousMod } = require('@expo/config-plugins');
2
+ const fs = require('fs');
3
+ const path = require('path');
2
4
 
3
5
  /**
4
6
  * OTA Update Expo Config Plugin
5
7
  *
6
8
  * This plugin modifies the native code to enable OTA bundle loading:
7
- * - Android: Overrides getJSBundleFile() or sets jsBundleFilePath in MainApplication.kt
9
+ * - Android: Modifies bundle loading for both old and new architecture
8
10
  * - iOS: Modifies bundleURL() in AppDelegate.swift
9
- *
10
- * Supports both old architecture (getJSBundleFile override) and
11
- * new architecture (jsBundleFilePath parameter in getDefaultReactHost).
12
11
  */
13
12
 
14
13
  function withOTAUpdateAndroid(config) {
@@ -35,74 +34,68 @@ function withOTAUpdateAndroid(config) {
35
34
  let injected = false;
36
35
 
37
36
  // ============================================================
38
- // Strategy 1: React Native 0.82+ NEW ARCHITECTURE
39
- // Look for: getDefaultReactHost(applicationContext, ...) and add jsBundleFilePath parameter
37
+ // Strategy 1: Expo New Architecture with ReactNativeHostWrapper
38
+ // Look for: ReactNativeHostWrapper.createReactHost(applicationContext, reactNativeHost)
39
+ // We need to modify the reactNativeHost to include our bundle override
40
+ // AND add a bundleAssetName override to return null when OTA bundle exists
40
41
  // ============================================================
41
- const newArchPattern = /getDefaultReactHost\s*\(\s*\n?\s*applicationContext\s*,/;
42
- if (newArchPattern.test(contents)) {
43
- console.log('[OTAUpdate] Android: Detected React Native 0.82+ (new architecture)');
44
-
45
- // Find the getDefaultReactHost call and add jsBundleFilePath parameter
46
- // Pattern: getDefaultReactHost(applicationContext, packageList, ...)
47
- const reactHostRegex = /(getDefaultReactHost\s*\(\s*\n?\s*)(applicationContext)(\s*,)/g;
48
-
49
- if (reactHostRegex.test(contents)) {
50
- contents = contents.replace(
51
- /(getDefaultReactHost\s*\(\s*\n?\s*)(applicationContext)(\s*,)/,
52
- '$1$2$3\n jsBundleFilePath = OTAUpdateHelper.getJSBundleFile(applicationContext),'
53
- );
54
- console.log('[OTAUpdate] Android: Injected jsBundleFilePath parameter (new architecture)');
55
- injected = true;
56
- }
57
- }
42
+ const expoNewArchPattern = /ReactNativeHostWrapper\.createReactHost\s*\(\s*applicationContext\s*,\s*reactNativeHost\s*\)/;
43
+ if (expoNewArchPattern.test(contents)) {
44
+ console.log('[OTAUpdate] Android: Detected Expo New Architecture pattern');
58
45
 
59
- // ============================================================
60
- // Strategy 2: Look for reactHost with getDefaultReactHost
61
- // override val reactHost: ReactHost get() = getDefaultReactHost(...)
62
- // ============================================================
63
- if (!injected) {
64
- const reactHostGetPattern = /(override\s+val\s+reactHost\s*:\s*ReactHost\s+get\s*\(\s*\)\s*=\s*getDefaultReactHost\s*\()([^)]*)\)/;
65
- if (reactHostGetPattern.test(contents)) {
66
- console.log('[OTAUpdate] Android: Detected reactHost with getDefaultReactHost');
46
+ // For Expo new arch, we need to add getBundleAssetName override
47
+ // to return null when OTA bundle exists (this forces it to use getJSBundleFile)
48
+ const defaultHostPattern = /(object\s*:\s*DefaultReactNativeHost\s*\([^)]*\)\s*\{)/;
49
+ if (defaultHostPattern.test(contents)) {
50
+ const bundleOverride = `
51
+ override fun getJSBundleFile(): String? {
52
+ return OTAUpdateHelper.getJSBundleFile(applicationContext)
53
+ }
67
54
 
68
- contents = contents.replace(
69
- reactHostGetPattern,
70
- (match, prefix, params) => {
71
- if (params.includes('jsBundleFilePath')) {
72
- return match; // Already has it
73
- }
74
- // Add jsBundleFilePath to the parameters
75
- const newParams = params.trim() + ',\n jsBundleFilePath = OTAUpdateHelper.getJSBundleFile(applicationContext)';
76
- return `${prefix}${newParams})`;
55
+ override fun getBundleAssetName(): String? {
56
+ // Return null if OTA bundle exists to force using getJSBundleFile
57
+ val otaBundle = OTAUpdateHelper.getJSBundleFile(applicationContext)
58
+ if (otaBundle != null) {
59
+ return null
77
60
  }
78
- );
79
- console.log('[OTAUpdate] Android: Injected jsBundleFilePath in reactHost getter');
61
+ return super.getBundleAssetName()
62
+ }
63
+ `;
64
+ contents = contents.replace(defaultHostPattern, `$1${bundleOverride}`);
65
+ console.log('[OTAUpdate] Android: Injected getJSBundleFile and getBundleAssetName overrides');
80
66
  injected = true;
81
67
  }
82
68
  }
83
69
 
84
70
  // ============================================================
85
- // Strategy 3: Old architecture - DefaultReactNativeHost with object block
86
- // Look for: object : DefaultReactNativeHost(this) { ... }
71
+ // Strategy 2: Standard DefaultReactNativeHost pattern
87
72
  // ============================================================
88
73
  if (!injected) {
89
74
  const defaultHostPattern = /(object\s*:\s*DefaultReactNativeHost\s*\([^)]*\)\s*\{)/;
90
75
  if (defaultHostPattern.test(contents)) {
91
- console.log('[OTAUpdate] Android: Detected DefaultReactNativeHost (old architecture)');
76
+ console.log('[OTAUpdate] Android: Detected DefaultReactNativeHost');
92
77
 
93
- const getJSBundleFileOverride = `
78
+ const bundleOverride = `
94
79
  override fun getJSBundleFile(): String? {
95
80
  return OTAUpdateHelper.getJSBundleFile(applicationContext)
96
81
  }
82
+
83
+ override fun getBundleAssetName(): String? {
84
+ val otaBundle = OTAUpdateHelper.getJSBundleFile(applicationContext)
85
+ if (otaBundle != null) {
86
+ return null
87
+ }
88
+ return super.getBundleAssetName()
89
+ }
97
90
  `;
98
- contents = contents.replace(defaultHostPattern, `$1${getJSBundleFileOverride}`);
99
- console.log('[OTAUpdate] Android: Injected getJSBundleFile override');
91
+ contents = contents.replace(defaultHostPattern, `$1${bundleOverride}`);
92
+ console.log('[OTAUpdate] Android: Injected bundle overrides');
100
93
  injected = true;
101
94
  }
102
95
  }
103
96
 
104
97
  // ============================================================
105
- // Strategy 4: Look for override fun getUseDeveloperSupport and insert before it
98
+ // Strategy 3: Look for getUseDeveloperSupport and insert before it
106
99
  // ============================================================
107
100
  if (!injected) {
108
101
  const devSupportPattern = /([ \t]*)(override\s+fun\s+getUseDeveloperSupport\s*\(\s*\))/;
@@ -112,33 +105,22 @@ function withOTAUpdateAndroid(config) {
112
105
  const match = contents.match(devSupportPattern);
113
106
  const indent = match ? match[1] : ' ';
114
107
 
115
- const getJSBundleFileOverride = `${indent}override fun getJSBundleFile(): String? {
108
+ const bundleOverride = `${indent}override fun getJSBundleFile(): String? {
116
109
  ${indent} return OTAUpdateHelper.getJSBundleFile(applicationContext)
117
110
  ${indent}}
118
111
 
119
- ${indent}`;
120
-
121
- contents = contents.replace(devSupportPattern, `${getJSBundleFileOverride}$2`);
122
- console.log('[OTAUpdate] Android: Injected getJSBundleFile before getUseDeveloperSupport');
123
- injected = true;
124
- }
125
- }
112
+ ${indent}override fun getBundleAssetName(): String? {
113
+ ${indent} val otaBundle = OTAUpdateHelper.getJSBundleFile(applicationContext)
114
+ ${indent} if (otaBundle != null) {
115
+ ${indent} return null
116
+ ${indent} }
117
+ ${indent} return super.getBundleAssetName()
118
+ ${indent}}
126
119
 
127
- // ============================================================
128
- // Strategy 5: Look for ReactNativeHost in any form
129
- // ============================================================
130
- if (!injected) {
131
- const anyHostPattern = /(:\s*ReactNativeHost\s*\{)/;
132
- if (anyHostPattern.test(contents)) {
133
- console.log('[OTAUpdate] Android: Found ReactNativeHost block');
120
+ ${indent}`;
134
121
 
135
- const getJSBundleFileOverride = `
136
- override fun getJSBundleFile(): String? {
137
- return OTAUpdateHelper.getJSBundleFile(applicationContext)
138
- }
139
- `;
140
- contents = contents.replace(anyHostPattern, `$1${getJSBundleFileOverride}`);
141
- console.log('[OTAUpdate] Android: Injected getJSBundleFile in ReactNativeHost');
122
+ contents = contents.replace(devSupportPattern, `${bundleOverride}$2`);
123
+ console.log('[OTAUpdate] Android: Injected bundle overrides before getUseDeveloperSupport');
142
124
  injected = true;
143
125
  }
144
126
  }
@@ -146,7 +128,6 @@ ${indent}`;
146
128
  if (!injected) {
147
129
  console.warn('[OTAUpdate] Android: ⚠️ Could not find injection point!');
148
130
  console.warn('[OTAUpdate] Android: Please manually add getJSBundleFile override');
149
- console.warn('[OTAUpdate] Android: See documentation for manual setup');
150
131
 
151
132
  // Log relevant lines for debugging
152
133
  const lines = contents.split('\n');
@@ -204,7 +185,7 @@ function withOTAUpdateIOS(config) {
204
185
  }
205
186
  `;
206
187
 
207
- // Strategy 1: Look for bundleURL() with flexible pattern
188
+ // Strategy 1: Look for bundleURL()
208
189
  const bundleURLPattern1 = /(func\s+bundleURL\s*\(\s*\)\s*->\s*URL\?\s*\{)([\s\S]*?)(\n\s*\})/;
209
190
 
210
191
  if (bundleURLPattern1.test(contents)) {
@@ -227,7 +208,7 @@ ${funcBody}${funcEnd}${helperFunction}`;
227
208
  return config;
228
209
  }
229
210
 
230
- // Strategy 2: Look for sourceURL(for bridge:) pattern
211
+ // Strategy 2: Look for sourceURL(for bridge:)
231
212
  const sourceURLPattern = /(func\s+sourceURL\s*\(\s*for\s+bridge\s*:\s*RCTBridge\s*\)\s*->\s*URL\?\s*\{)([\s\S]*?)(\n\s*\})/;
232
213
 
233
214
  if (sourceURLPattern.test(contents)) {
@@ -103,5 +103,5 @@ var _verification = require("./utils/verification");
103
103
  // Utilities
104
104
 
105
105
  // Version info
106
- const VERSION = exports.VERSION = '0.2.7';
106
+ const VERSION = exports.VERSION = '0.2.8';
107
107
  //# sourceMappingURL=index.js.map
@@ -10,5 +10,5 @@ export { OTAApiClient, getDeviceInfo } from './utils/api';
10
10
  export { UpdateStorage, getStorageAdapter } from './utils/storage';
11
11
  export { calculateHash, verifyBundleHash, verifySignature, verifyBundle } from './utils/verification';
12
12
  // Version info
13
- export const VERSION = '0.2.7';
13
+ export const VERSION = '0.2.8';
14
14
  //# sourceMappingURL=index.js.map
@@ -9,5 +9,5 @@ export { UpdateStorage, getStorageAdapter } from './utils/storage';
9
9
  export type { StoredUpdate, StorageAdapter } from './utils/storage';
10
10
  export { calculateHash, verifyBundleHash, verifySignature, verifyBundle, } from './utils/verification';
11
11
  export type { VerificationResult } from './utils/verification';
12
- export declare const VERSION = "0.2.7";
12
+ export declare const VERSION = "0.2.8";
13
13
  //# sourceMappingURL=index.d.ts.map
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanikya/ota-react-native",
3
- "version": "0.2.7",
3
+ "version": "0.2.8",
4
4
  "description": "OTA Update SDK for React Native apps - self-hosted CodePush/EAS Updates alternative",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",
package/src/index.ts CHANGED
@@ -36,4 +36,4 @@ export {
36
36
  export type { VerificationResult } from './utils/verification';
37
37
 
38
38
  // Version info
39
- export const VERSION = '0.2.7';
39
+ export const VERSION = '0.2.8';