@vanikya/ota-react-native 0.2.9 → 0.2.10

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.
@@ -36,7 +36,7 @@ android {
36
36
  }
37
37
  }
38
38
 
39
- lintOptions {
39
+ lint {
40
40
  abortOnError false
41
41
  }
42
42
  }
@@ -1,30 +1,11 @@
1
1
  package com.otaupdate
2
2
 
3
- import android.content.Context
4
- import android.util.Log
5
3
  import com.facebook.react.ReactPackage
6
4
  import com.facebook.react.bridge.NativeModule
7
5
  import com.facebook.react.bridge.ReactApplicationContext
8
- import com.facebook.react.bridge.ReactContext
9
6
  import com.facebook.react.uimanager.ViewManager
10
- import expo.modules.core.interfaces.Package
11
- import expo.modules.core.interfaces.ReactNativeHostHandler
12
7
 
13
- /**
14
- * OTAUpdatePackage implements both React Native's ReactPackage and Expo's Package interfaces.
15
- *
16
- * The Expo Package interface is critical for bundle loading with Expo's new architecture.
17
- * It provides ReactNativeHostHandler which allows us to override:
18
- * - getJSBundleFile: Returns path to downloaded OTA bundle
19
- * - getBundleAssetName: Returns null when OTA bundle exists to force using getJSBundleFile
20
- */
21
- class OTAUpdatePackage : ReactPackage, Package {
22
-
23
- companion object {
24
- private const val TAG = "OTAUpdatePackage"
25
- }
26
-
27
- // ReactPackage implementation
8
+ class OTAUpdatePackage : ReactPackage {
28
9
  override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
29
10
  return listOf(OTAUpdateModule(reactContext))
30
11
  }
@@ -32,66 +13,4 @@ class OTAUpdatePackage : ReactPackage, Package {
32
13
  override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
33
14
  return emptyList()
34
15
  }
35
-
36
- // Expo Package implementation - this is the key for Expo new architecture support
37
- override fun createReactNativeHostHandlers(context: Context): List<ReactNativeHostHandler> {
38
- Log.d(TAG, "=== createReactNativeHostHandlers called ===")
39
-
40
- val handler = object : ReactNativeHostHandler {
41
-
42
- override fun getJSBundleFile(useDeveloperSupport: Boolean): String? {
43
- Log.d(TAG, "=== getJSBundleFile called (useDeveloperSupport=$useDeveloperSupport) ===")
44
-
45
- // In development mode, let Metro bundler handle it
46
- if (useDeveloperSupport) {
47
- Log.d(TAG, "Developer support enabled, returning null")
48
- return null
49
- }
50
-
51
- // Get the bundle path from OTAUpdateHelper
52
- val bundlePath = OTAUpdateHelper.getJSBundleFile(context)
53
- Log.d(TAG, "OTAUpdateHelper returned bundle path: $bundlePath")
54
- return bundlePath
55
- }
56
-
57
- override fun getBundleAssetName(useDeveloperSupport: Boolean): String? {
58
- Log.d(TAG, "=== getBundleAssetName called (useDeveloperSupport=$useDeveloperSupport) ===")
59
-
60
- // In development mode, use default behavior
61
- if (useDeveloperSupport) {
62
- Log.d(TAG, "Developer support enabled, returning null (use default)")
63
- return null
64
- }
65
-
66
- // Check if we have an OTA bundle
67
- val bundlePath = OTAUpdateHelper.getJSBundleFile(context)
68
- if (bundlePath != null) {
69
- // Return null to force React Native to use getJSBundleFile instead of bundled assets
70
- Log.d(TAG, "OTA bundle exists at $bundlePath, returning null to force getJSBundleFile")
71
- return null
72
- }
73
-
74
- // No OTA bundle, use default bundled assets
75
- Log.d(TAG, "No OTA bundle, returning null (use default bundled assets)")
76
- return null
77
- }
78
-
79
- override fun onWillCreateReactInstance(useDeveloperSupport: Boolean) {
80
- Log.d(TAG, "=== onWillCreateReactInstance called (useDeveloperSupport=$useDeveloperSupport) ===")
81
- }
82
-
83
- override fun onDidCreateReactInstance(useDeveloperSupport: Boolean, reactContext: ReactContext) {
84
- Log.d(TAG, "=== onDidCreateReactInstance called ===")
85
- }
86
-
87
- override fun onReactInstanceException(useDeveloperSupport: Boolean, exception: Exception) {
88
- Log.e(TAG, "=== onReactInstanceException called ===", exception)
89
- // If there's an exception with OTA bundle, we could clear it here
90
- // For now, just log the exception
91
- }
92
- }
93
-
94
- Log.d(TAG, "Returning ReactNativeHostHandler")
95
- return listOf(handler)
96
- }
97
16
  }
package/app.plugin.js CHANGED
@@ -1,23 +1,116 @@
1
- const { withAppDelegate } = require('@expo/config-plugins');
1
+ const { withMainApplication, withAppDelegate } = require('@expo/config-plugins');
2
2
 
3
3
  /**
4
4
  * OTA Update Expo Config Plugin
5
5
  *
6
6
  * This plugin modifies the native code to enable OTA bundle loading:
7
- * - Android: Uses Expo's Package interface (ReactNativeHostHandler) - no modification needed
7
+ * - Android: Modifies MainApplication.kt to override getJSBundleFile and getBundleAssetName
8
8
  * - iOS: Modifies bundleURL() in AppDelegate.swift
9
- *
10
- * For Android, the OTAUpdatePackage implements expo.modules.core.interfaces.Package
11
- * which provides ReactNativeHostHandler to hook into bundle loading.
12
- * This is registered via expo-module.config.json.
13
9
  */
14
10
 
15
11
  function withOTAUpdateAndroid(config) {
16
- // Android bundle loading is handled by OTAUpdatePackage implementing
17
- // expo.modules.core.interfaces.Package with ReactNativeHostHandler.
18
- // No MainApplication.kt modification is needed for Expo apps.
19
- console.log('[OTAUpdate] Android: Using Expo Package interface for bundle loading');
20
- return config;
12
+ return withMainApplication(config, (config) => {
13
+ let contents = config.modResults.contents;
14
+
15
+ // Check if already modified
16
+ if (contents.includes('OTAUpdateHelper')) {
17
+ console.log('[OTAUpdate] Android: OTAUpdateHelper already present, skipping');
18
+ return config;
19
+ }
20
+
21
+ console.log('[OTAUpdate] Android: Analyzing MainApplication.kt structure...');
22
+
23
+ // Add import for OTAUpdateHelper at the top
24
+ const packageMatch = contents.match(/^package\s+[\w.]+\s*\n/m);
25
+ if (packageMatch) {
26
+ const insertPos = packageMatch.index + packageMatch[0].length;
27
+ const importStatement = `\nimport com.otaupdate.OTAUpdateHelper\n`;
28
+ contents = contents.slice(0, insertPos) + importStatement + contents.slice(insertPos);
29
+ console.log('[OTAUpdate] Android: Added import for OTAUpdateHelper');
30
+ }
31
+
32
+ let injected = false;
33
+
34
+ // ============================================================
35
+ // Strategy 1: Look for DefaultReactNativeHost and add overrides
36
+ // This works for both old and new architecture Expo apps
37
+ // ============================================================
38
+ const defaultHostPattern = /(object\s*:\s*DefaultReactNativeHost\s*\([^)]*\)\s*\{)/;
39
+ if (defaultHostPattern.test(contents)) {
40
+ console.log('[OTAUpdate] Android: Detected DefaultReactNativeHost');
41
+
42
+ const bundleOverride = `
43
+ override fun getJSBundleFile(): String? {
44
+ return OTAUpdateHelper.getJSBundleFile(applicationContext)
45
+ }
46
+
47
+ override fun getBundleAssetName(): String? {
48
+ // Return null if OTA bundle exists to force using getJSBundleFile
49
+ val otaBundle = OTAUpdateHelper.getJSBundleFile(applicationContext)
50
+ if (otaBundle != null) {
51
+ return null
52
+ }
53
+ return super.getBundleAssetName()
54
+ }
55
+ `;
56
+ contents = contents.replace(defaultHostPattern, `$1${bundleOverride}`);
57
+ console.log('[OTAUpdate] Android: Injected getJSBundleFile and getBundleAssetName overrides');
58
+ injected = true;
59
+ }
60
+
61
+ // ============================================================
62
+ // Strategy 2: Look for getUseDeveloperSupport and insert before it
63
+ // ============================================================
64
+ if (!injected) {
65
+ const devSupportPattern = /([ \t]*)(override\s+fun\s+getUseDeveloperSupport\s*\(\s*\))/;
66
+ if (devSupportPattern.test(contents)) {
67
+ console.log('[OTAUpdate] Android: Found getUseDeveloperSupport, inserting before it');
68
+
69
+ const match = contents.match(devSupportPattern);
70
+ const indent = match ? match[1] : ' ';
71
+
72
+ const bundleOverride = `${indent}override fun getJSBundleFile(): String? {
73
+ ${indent} return OTAUpdateHelper.getJSBundleFile(applicationContext)
74
+ ${indent}}
75
+
76
+ ${indent}override fun getBundleAssetName(): String? {
77
+ ${indent} val otaBundle = OTAUpdateHelper.getJSBundleFile(applicationContext)
78
+ ${indent} if (otaBundle != null) {
79
+ ${indent} return null
80
+ ${indent} }
81
+ ${indent} return super.getBundleAssetName()
82
+ ${indent}}
83
+
84
+ ${indent}`;
85
+
86
+ contents = contents.replace(devSupportPattern, `${bundleOverride}$2`);
87
+ console.log('[OTAUpdate] Android: Injected bundle overrides before getUseDeveloperSupport');
88
+ injected = true;
89
+ }
90
+ }
91
+
92
+ if (!injected) {
93
+ console.warn('[OTAUpdate] Android: ⚠️ Could not find injection point!');
94
+ console.warn('[OTAUpdate] Android: Please manually add getJSBundleFile override');
95
+
96
+ // Log relevant lines for debugging
97
+ const lines = contents.split('\n');
98
+ console.log('[OTAUpdate] Android: Relevant lines in MainApplication.kt:');
99
+ lines.forEach((line, i) => {
100
+ if (line.includes('ReactNativeHost') ||
101
+ line.includes('DefaultReactNativeHost') ||
102
+ line.includes('getDefaultReactHost') ||
103
+ line.includes('reactHost') ||
104
+ line.includes('getJSBundleFile') ||
105
+ line.includes('jsBundleFilePath')) {
106
+ console.log(` ${i + 1}: ${line.trim()}`);
107
+ }
108
+ });
109
+ }
110
+
111
+ config.modResults.contents = contents;
112
+ return config;
113
+ });
21
114
  }
22
115
 
23
116
  function withOTAUpdateIOS(config) {
@@ -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.9';
106
+ const VERSION = exports.VERSION = '0.2.10';
107
107
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["_OTAProvider","require","_OTADebugPanel","_useOTAUpdate","_api","_storage","_verification","VERSION","exports"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAIA,IAAAC,cAAA,GAAAD,OAAA;AAGA,IAAAE,aAAA,GAAAF,OAAA;AAUA,IAAAG,IAAA,GAAAH,OAAA;AAQA,IAAAI,QAAA,GAAAJ,OAAA;AAGA,IAAAK,aAAA,GAAAL,OAAA;AA7BA;;AAIA;;AAGA;;AAUA;;AAoBA;AACO,MAAMM,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["_OTAProvider","require","_OTADebugPanel","_useOTAUpdate","_api","_storage","_verification","VERSION","exports"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AACA,IAAAA,YAAA,GAAAC,OAAA;AAIA,IAAAC,cAAA,GAAAD,OAAA;AAGA,IAAAE,aAAA,GAAAF,OAAA;AAUA,IAAAG,IAAA,GAAAH,OAAA;AAQA,IAAAI,QAAA,GAAAJ,OAAA;AAGA,IAAAK,aAAA,GAAAL,OAAA;AA7BA;;AAIA;;AAGA;;AAUA;;AAoBA;AACO,MAAMM,OAAO,GAAAC,OAAA,CAAAD,OAAA,GAAG,QAAQ","ignoreList":[]}
@@ -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.9';
13
+ export const VERSION = '0.2.10';
14
14
  //# sourceMappingURL=index.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["OTAProvider","useOTA","withOTA","UpdateBanner","OTADebugPanel","useOTAUpdate","OTAApiClient","getDeviceInfo","UpdateStorage","getStorageAdapter","calculateHash","verifyBundleHash","verifySignature","verifyBundle","VERSION"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA;AACA,SAASA,WAAW,EAAEC,MAAM,EAAEC,OAAO,EAAEC,YAAY,QAAQ,eAAe;AAG1E;AACA,SAASC,aAAa,QAAQ,4BAA4B;;AAE1D;AACA,SAASC,YAAY,QAAQ,sBAAsB;AASnD;AACA,SAASC,YAAY,EAAEC,aAAa,QAAQ,aAAa;AAQzD,SAASC,aAAa,EAAEC,iBAAiB,QAAQ,iBAAiB;AAGlE,SACEC,aAAa,EACbC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,QACP,sBAAsB;AAG7B;AACA,OAAO,MAAMC,OAAO,GAAG,OAAO","ignoreList":[]}
1
+ {"version":3,"names":["OTAProvider","useOTA","withOTA","UpdateBanner","OTADebugPanel","useOTAUpdate","OTAApiClient","getDeviceInfo","UpdateStorage","getStorageAdapter","calculateHash","verifyBundleHash","verifySignature","verifyBundle","VERSION"],"sourceRoot":"../../src","sources":["index.ts"],"mappings":"AAAA;AACA,SAASA,WAAW,EAAEC,MAAM,EAAEC,OAAO,EAAEC,YAAY,QAAQ,eAAe;AAG1E;AACA,SAASC,aAAa,QAAQ,4BAA4B;;AAE1D;AACA,SAASC,YAAY,QAAQ,sBAAsB;AASnD;AACA,SAASC,YAAY,EAAEC,aAAa,QAAQ,aAAa;AAQzD,SAASC,aAAa,EAAEC,iBAAiB,QAAQ,iBAAiB;AAGlE,SACEC,aAAa,EACbC,gBAAgB,EAChBC,eAAe,EACfC,YAAY,QACP,sBAAsB;AAG7B;AACA,OAAO,MAAMC,OAAO,GAAG,QAAQ","ignoreList":[]}
@@ -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.9";
12
+ export declare const VERSION = "0.2.10";
13
13
  //# sourceMappingURL=index.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EACV,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,eAAO,MAAM,OAAO,UAAU,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,eAAe,CAAC;AAC3E,YAAY,EAAE,gBAAgB,EAAE,iBAAiB,EAAE,MAAM,eAAe,CAAC;AAGzE,OAAO,EAAE,aAAa,EAAE,MAAM,4BAA4B,CAAC;AAG3D,OAAO,EAAE,YAAY,EAAE,MAAM,sBAAsB,CAAC;AACpD,YAAY,EACV,eAAe,EACf,UAAU,EACV,gBAAgB,EAChB,YAAY,EACZ,kBAAkB,GACnB,MAAM,sBAAsB,CAAC;AAG9B,OAAO,EAAE,YAAY,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAC1D,YAAY,EACV,kBAAkB,EAClB,mBAAmB,EACnB,WAAW,EACX,kBAAkB,GACnB,MAAM,aAAa,CAAC;AAErB,OAAO,EAAE,aAAa,EAAE,iBAAiB,EAAE,MAAM,iBAAiB,CAAC;AACnE,YAAY,EAAE,YAAY,EAAE,cAAc,EAAE,MAAM,iBAAiB,CAAC;AAEpE,OAAO,EACL,aAAa,EACb,gBAAgB,EAChB,eAAe,EACf,YAAY,GACb,MAAM,sBAAsB,CAAC;AAC9B,YAAY,EAAE,kBAAkB,EAAE,MAAM,sBAAsB,CAAC;AAG/D,eAAO,MAAM,OAAO,WAAW,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@vanikya/ota-react-native",
3
- "version": "0.2.9",
3
+ "version": "0.2.10",
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",
@@ -15,7 +15,6 @@
15
15
  "*.podspec",
16
16
  "react-native.config.js",
17
17
  "app.plugin.js",
18
- "expo-module.config.json",
19
18
  "README.md"
20
19
  ],
21
20
  "scripts": {
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.9';
39
+ export const VERSION = '0.2.10';
@@ -1,8 +0,0 @@
1
- {
2
- "platforms": ["android", "ios"],
3
- "android": {
4
- "modules": [],
5
- "package": "com.otaupdate.OTAUpdatePackage"
6
- },
7
- "ios": {}
8
- }