@vanikya/ota-react-native 0.1.4 → 0.1.6
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 +50 -4
- package/app.plugin.js +104 -0
- package/ios/OTAUpdate.swift +3 -3
- package/lib/commonjs/hooks/useOTAUpdate.js +25 -8
- package/lib/commonjs/hooks/useOTAUpdate.js.map +1 -1
- package/lib/commonjs/utils/storage.js +81 -6
- package/lib/commonjs/utils/storage.js.map +1 -1
- package/lib/module/hooks/useOTAUpdate.js +26 -9
- package/lib/module/hooks/useOTAUpdate.js.map +1 -1
- package/lib/module/utils/storage.js +81 -6
- package/lib/module/utils/storage.js.map +1 -1
- package/lib/typescript/hooks/useOTAUpdate.d.ts.map +1 -1
- package/lib/typescript/utils/storage.d.ts +19 -0
- package/lib/typescript/utils/storage.d.ts.map +1 -1
- package/package.json +2 -1
- package/src/hooks/useOTAUpdate.ts +28 -10
- package/src/utils/storage.ts +81 -6
package/README.md
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
|
-
# @ota-
|
|
1
|
+
# @vanikya/ota-react-native
|
|
2
|
+
|
|
3
|
+
> **Beta Notice**: This package is currently in beta. Testing is in progress and APIs may change. Use in production at your own discretion. We welcome feedback and bug reports via [GitHub Issues](https://github.com/vanikya/ota-update/issues).
|
|
2
4
|
|
|
3
5
|
React Native SDK for OTA (Over-The-Air) updates. A self-hosted alternative to CodePush and EAS Updates.
|
|
4
6
|
|
|
@@ -10,14 +12,36 @@ Works with both **Expo** and **bare React Native** apps.
|
|
|
10
12
|
npm install @vanikya/ota-react-native
|
|
11
13
|
```
|
|
12
14
|
|
|
13
|
-
### For Expo apps
|
|
15
|
+
### For Expo apps (EAS Build)
|
|
14
16
|
|
|
15
|
-
Install Expo dependencies:
|
|
17
|
+
1. Install Expo dependencies:
|
|
16
18
|
|
|
17
19
|
```bash
|
|
18
20
|
npx expo install expo-file-system expo-crypto
|
|
19
21
|
```
|
|
20
22
|
|
|
23
|
+
2. Add the config plugin to your `app.json` or `app.config.js`:
|
|
24
|
+
|
|
25
|
+
```json
|
|
26
|
+
{
|
|
27
|
+
"expo": {
|
|
28
|
+
"plugins": [
|
|
29
|
+
"@vanikya/ota-react-native"
|
|
30
|
+
]
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
```
|
|
34
|
+
|
|
35
|
+
3. Rebuild your app with EAS Build:
|
|
36
|
+
|
|
37
|
+
```bash
|
|
38
|
+
eas build --platform android
|
|
39
|
+
# or
|
|
40
|
+
eas build --platform ios
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
> **Important**: OTA updates require a native build with EAS Build. They will NOT work in Expo Go because the plugin modifies native code to load custom bundles.
|
|
44
|
+
|
|
21
45
|
### For bare React Native apps
|
|
22
46
|
|
|
23
47
|
Install pods (iOS):
|
|
@@ -32,6 +56,7 @@ cd ios && pod install
|
|
|
32
56
|
|
|
33
57
|
```tsx
|
|
34
58
|
import { OTAProvider } from '@vanikya/ota-react-native';
|
|
59
|
+
import Constants from 'expo-constants';
|
|
35
60
|
|
|
36
61
|
export default function App() {
|
|
37
62
|
return (
|
|
@@ -40,6 +65,7 @@ export default function App() {
|
|
|
40
65
|
serverUrl: 'https://your-server.workers.dev',
|
|
41
66
|
appSlug: 'my-app',
|
|
42
67
|
channel: 'production',
|
|
68
|
+
appVersion: Constants.expoConfig?.version || '1.0.0',
|
|
43
69
|
// Optional: public key for signature verification
|
|
44
70
|
publicKey: 'your-public-key-hex',
|
|
45
71
|
}}
|
|
@@ -97,10 +123,11 @@ function UpdateChecker() {
|
|
|
97
123
|
|------|------|----------|-------------|
|
|
98
124
|
| `config.serverUrl` | string | Yes | Your OTA server URL |
|
|
99
125
|
| `config.appSlug` | string | Yes | Your app's slug |
|
|
126
|
+
| `config.appVersion` | string | Yes | Your native app version (e.g., "1.0.0") |
|
|
100
127
|
| `config.channel` | string | No | Release channel (default: 'production') |
|
|
101
128
|
| `config.publicKey` | string | No | Ed25519 public key for signature verification |
|
|
102
129
|
| `config.checkOnMount` | boolean | No | Auto-check for updates on mount |
|
|
103
|
-
| `config.
|
|
130
|
+
| `config.checkOnForeground` | boolean | No | Auto-check when app comes to foreground |
|
|
104
131
|
|
|
105
132
|
### useOTAUpdate Hook
|
|
106
133
|
|
|
@@ -218,6 +245,25 @@ This SDK requires a backend server. See the [main repository](https://github.com
|
|
|
218
245
|
|
|
219
246
|
Updates are stored locally, so the app works offline after the first download.
|
|
220
247
|
|
|
248
|
+
### How Expo Plugin Works
|
|
249
|
+
|
|
250
|
+
For Expo apps built with EAS Build, the config plugin modifies the native code to enable OTA updates:
|
|
251
|
+
|
|
252
|
+
**Android** (`MainApplication.kt`):
|
|
253
|
+
- Overrides `getJSBundleFile()` to check SharedPreferences for a downloaded bundle path
|
|
254
|
+
- If a valid bundle exists, it loads that instead of the built-in bundle
|
|
255
|
+
|
|
256
|
+
**iOS** (`AppDelegate.swift`):
|
|
257
|
+
- Modifies `bundleURL()` to check UserDefaults for a downloaded bundle path
|
|
258
|
+
- If a valid bundle exists, it returns that URL instead of the built-in bundle
|
|
259
|
+
|
|
260
|
+
When you call `applyUpdate()` or the download completes:
|
|
261
|
+
1. The bundle is saved to the device's document directory
|
|
262
|
+
2. The path is registered with native storage (SharedPreferences/UserDefaults)
|
|
263
|
+
3. On the next app restart, the native code loads the OTA bundle
|
|
264
|
+
|
|
265
|
+
> **Note**: OTA updates only work on EAS Build apps, not Expo Go, because Expo Go doesn't include the native module.
|
|
266
|
+
|
|
221
267
|
## License
|
|
222
268
|
|
|
223
269
|
MIT
|
package/app.plugin.js
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
const { withMainApplication, withAppDelegate, withDangerousMod } = require('@expo/config-plugins');
|
|
2
|
+
const fs = require('fs');
|
|
3
|
+
const path = require('path');
|
|
4
|
+
|
|
5
|
+
function withOTAUpdateAndroid(config) {
|
|
6
|
+
return withMainApplication(config, (config) => {
|
|
7
|
+
let contents = config.modResults.contents;
|
|
8
|
+
|
|
9
|
+
// Check if already modified
|
|
10
|
+
if (contents.includes('getJSBundleFile')) {
|
|
11
|
+
return config;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
// Add imports if not present
|
|
15
|
+
if (!contents.includes('import android.content.SharedPreferences')) {
|
|
16
|
+
contents = contents.replace(
|
|
17
|
+
/^(package .+?\n)/m,
|
|
18
|
+
`$1\nimport android.content.SharedPreferences\nimport java.io.File\n`
|
|
19
|
+
);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
// For Kotlin-based MainApplication (Expo SDK 50+)
|
|
23
|
+
// Find the ReactNativeHost and add getJSBundleFile override
|
|
24
|
+
const kotlinPattern = /override\s+fun\s+getUseDeveloperSupport\(\):\s+Boolean\s*=\s*BuildConfig\.DEBUG/;
|
|
25
|
+
|
|
26
|
+
if (kotlinPattern.test(contents)) {
|
|
27
|
+
contents = contents.replace(
|
|
28
|
+
kotlinPattern,
|
|
29
|
+
`override fun getJSBundleFile(): String? {
|
|
30
|
+
val prefs: SharedPreferences = applicationContext.getSharedPreferences("OTAUpdate", android.content.Context.MODE_PRIVATE)
|
|
31
|
+
val bundlePath = prefs.getString("BundlePath", null)
|
|
32
|
+
if (bundlePath != null && File(bundlePath).exists()) {
|
|
33
|
+
return bundlePath
|
|
34
|
+
}
|
|
35
|
+
return null
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override fun getUseDeveloperSupport(): Boolean = BuildConfig.DEBUG`
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
config.modResults.contents = contents;
|
|
43
|
+
return config;
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
function withOTAUpdateIOS(config) {
|
|
48
|
+
return withAppDelegate(config, (config) => {
|
|
49
|
+
let contents = config.modResults.contents;
|
|
50
|
+
|
|
51
|
+
// Check if already modified
|
|
52
|
+
if (contents.includes('OTAUpdateBundlePath')) {
|
|
53
|
+
return config;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// For Swift AppDelegate
|
|
57
|
+
if (config.modResults.language === 'swift') {
|
|
58
|
+
// Add helper function before the class closing brace
|
|
59
|
+
const helperFunction = `
|
|
60
|
+
// OTA Update: Check for downloaded bundle
|
|
61
|
+
private func getOTABundleURL() -> URL? {
|
|
62
|
+
let defaults = UserDefaults.standard
|
|
63
|
+
if let bundlePath = defaults.string(forKey: "OTAUpdateBundlePath") {
|
|
64
|
+
let fileURL = URL(fileURLWithPath: bundlePath)
|
|
65
|
+
if FileManager.default.fileExists(atPath: bundlePath) {
|
|
66
|
+
return fileURL
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
return nil
|
|
70
|
+
}
|
|
71
|
+
`;
|
|
72
|
+
|
|
73
|
+
// Find bundleURL method and modify it
|
|
74
|
+
const bundleURLPattern = /func\s+bundleURL\(\)\s*->\s*URL\?\s*\{[\s\S]*?\n\s*\}/;
|
|
75
|
+
|
|
76
|
+
if (bundleURLPattern.test(contents)) {
|
|
77
|
+
contents = contents.replace(
|
|
78
|
+
bundleURLPattern,
|
|
79
|
+
`func bundleURL() -> URL? {
|
|
80
|
+
// OTA Update: Check for downloaded bundle first
|
|
81
|
+
if let otaBundle = getOTABundleURL() {
|
|
82
|
+
return otaBundle
|
|
83
|
+
}
|
|
84
|
+
#if DEBUG
|
|
85
|
+
return RCTBundleURLProvider.sharedSettings().jsBundleURL(forBundleRoot: "index")
|
|
86
|
+
#else
|
|
87
|
+
return Bundle.main.url(forResource: "main", withExtension: "jsbundle")
|
|
88
|
+
#endif
|
|
89
|
+
}
|
|
90
|
+
${helperFunction}`
|
|
91
|
+
);
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
config.modResults.contents = contents;
|
|
96
|
+
return config;
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
module.exports = function withOTAUpdate(config) {
|
|
101
|
+
config = withOTAUpdateAndroid(config);
|
|
102
|
+
config = withOTAUpdateIOS(config);
|
|
103
|
+
return config;
|
|
104
|
+
};
|
package/ios/OTAUpdate.swift
CHANGED
|
@@ -135,7 +135,7 @@ class OTAUpdate: NSObject {
|
|
|
135
135
|
@objc
|
|
136
136
|
func applyBundle(_ bundlePath: String, restart: Bool, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
137
137
|
// Store the bundle path for next launch
|
|
138
|
-
UserDefaults.standard.set(bundlePath, forKey: "
|
|
138
|
+
UserDefaults.standard.set(bundlePath, forKey: "OTAUpdateBundlePath")
|
|
139
139
|
UserDefaults.standard.synchronize()
|
|
140
140
|
|
|
141
141
|
if restart {
|
|
@@ -151,13 +151,13 @@ class OTAUpdate: NSObject {
|
|
|
151
151
|
|
|
152
152
|
@objc
|
|
153
153
|
func getPendingBundlePath(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
154
|
-
let path = UserDefaults.standard.string(forKey: "
|
|
154
|
+
let path = UserDefaults.standard.string(forKey: "OTAUpdateBundlePath")
|
|
155
155
|
resolver(path)
|
|
156
156
|
}
|
|
157
157
|
|
|
158
158
|
@objc
|
|
159
159
|
func clearPendingBundle(_ resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
160
|
-
UserDefaults.standard.removeObject(forKey: "
|
|
160
|
+
UserDefaults.standard.removeObject(forKey: "OTAUpdateBundlePath")
|
|
161
161
|
UserDefaults.standard.synchronize()
|
|
162
162
|
resolver(nil)
|
|
163
163
|
}
|
|
@@ -9,7 +9,6 @@ var _reactNative = require("react-native");
|
|
|
9
9
|
var _api = require("../utils/api");
|
|
10
10
|
var _storage = require("../utils/storage");
|
|
11
11
|
var _verification = require("../utils/verification");
|
|
12
|
-
const OTAUpdateNative = _reactNative.NativeModules.OTAUpdate;
|
|
13
12
|
// Generate or get device ID
|
|
14
13
|
async function getDeviceId() {
|
|
15
14
|
// Try to get from native module or AsyncStorage
|
|
@@ -146,6 +145,17 @@ function useOTAUpdate(config) {
|
|
|
146
145
|
bundleHash: release.bundleHash,
|
|
147
146
|
downloadedAt: Date.now()
|
|
148
147
|
});
|
|
148
|
+
|
|
149
|
+
// Register the bundle path with native module (for next app restart)
|
|
150
|
+
// This saves to SharedPreferences (Android) / UserDefaults (iOS)
|
|
151
|
+
const registered = await storage.current.registerBundleWithNative(bundlePath, false);
|
|
152
|
+
if (__DEV__) {
|
|
153
|
+
if (registered) {
|
|
154
|
+
console.log('[OTAUpdate] Bundle registered with native module. Will apply on app restart.');
|
|
155
|
+
} else {
|
|
156
|
+
console.log('[OTAUpdate] Could not register with native module. If using Expo Go, this is expected.');
|
|
157
|
+
}
|
|
158
|
+
}
|
|
149
159
|
setStatus('ready');
|
|
150
160
|
} catch (err) {
|
|
151
161
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -186,14 +196,18 @@ function useOTAUpdate(config) {
|
|
|
186
196
|
deviceInfo: (0, _api.getDeviceInfo)()
|
|
187
197
|
});
|
|
188
198
|
|
|
189
|
-
//
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
//
|
|
194
|
-
// The bundle will be loaded on next app start
|
|
199
|
+
// Register bundle path with native module and optionally restart
|
|
200
|
+
// This ensures the path is saved to SharedPreferences/UserDefaults
|
|
201
|
+
const registered = await storage.current.registerBundleWithNative(metadata.bundlePath, restartApp);
|
|
202
|
+
if (!registered && restartApp) {
|
|
203
|
+
// Native module not available
|
|
195
204
|
if (__DEV__) {
|
|
196
|
-
console.log('[OTAUpdate] Update ready.
|
|
205
|
+
console.log('[OTAUpdate] Update ready. Close and reopen the app to apply the update.');
|
|
206
|
+
console.log('[OTAUpdate] Note: For Expo Go, OTA updates require a native build (EAS Build).');
|
|
207
|
+
}
|
|
208
|
+
} else if (registered && !restartApp) {
|
|
209
|
+
if (__DEV__) {
|
|
210
|
+
console.log('[OTAUpdate] Update registered. Will apply on next app restart.');
|
|
197
211
|
}
|
|
198
212
|
}
|
|
199
213
|
|
|
@@ -232,6 +246,9 @@ function useOTAUpdate(config) {
|
|
|
232
246
|
await storage.current.deleteBundle(metadata.releaseId);
|
|
233
247
|
await storage.current.clearMetadata();
|
|
234
248
|
}
|
|
249
|
+
|
|
250
|
+
// Also clear from native storage (SharedPreferences/UserDefaults)
|
|
251
|
+
await storage.current.clearNativePendingBundle();
|
|
235
252
|
setUpdateInfo(null);
|
|
236
253
|
releaseRef.current = null;
|
|
237
254
|
setStatus('idle');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_react","require","_reactNative","_api","_storage","_verification","
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNative","_api","_storage","_verification","getDeviceId","id","Math","random","toString","substring","useOTAUpdate","config","serverUrl","appSlug","channel","appVersion","publicKey","checkOnMount","checkOnForeground","status","setStatus","useState","updateInfo","setUpdateInfo","downloadProgress","setDownloadProgress","error","setError","currentVersion","setCurrentVersion","apiClient","useRef","OTAApiClient","storage","UpdateStorage","deviceIdRef","releaseRef","useEffect","loadCurrentVersion","metadata","current","getMetadata","version","getDeviceIdCached","useCallback","checkForUpdate","deviceId","currentMetadata","response","checkUpdate","platform","Platform","OS","updateAvailable","release","info","releaseId","bundleSize","isMandatory","releaseNotes","err","Error","String","downloadUpdate","downloadedBytes","totalBytes","percentage","reportEvent","eventType","deviceInfo","getDeviceInfo","bundleData","downloadBundle","bundleUrl","byteLength","verification","verifyBundle","bundleHash","bundleSignature","valid","bundlePath","saveBundle","saveMetadata","downloadedAt","Date","now","registered","registerBundleWithNative","__DEV__","console","log","errorMessage","message","applyUpdate","restartApp","clearPendingUpdate","deleteBundle","clearMetadata","clearNativePendingBundle","handleAppStateChange","nextAppState","subscription","AppState","addEventListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useOTAUpdate.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -8,6 +8,14 @@ exports.getStorageAdapter = getStorageAdapter;
|
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
// Types
|
|
10
10
|
|
|
11
|
+
// Helper to normalize file paths (remove file:// prefix)
|
|
12
|
+
function normalizePath(path) {
|
|
13
|
+
if (path.startsWith('file://')) {
|
|
14
|
+
return path.slice(7);
|
|
15
|
+
}
|
|
16
|
+
return path;
|
|
17
|
+
}
|
|
18
|
+
|
|
11
19
|
// Try to use Expo FileSystem if available
|
|
12
20
|
let ExpoFileSystem = null;
|
|
13
21
|
try {
|
|
@@ -147,7 +155,10 @@ function getStorageAdapter() {
|
|
|
147
155
|
class UpdateStorage {
|
|
148
156
|
constructor() {
|
|
149
157
|
this.storage = getStorageAdapter();
|
|
158
|
+
this.isExpo = !!ExpoFileSystem;
|
|
150
159
|
this.baseDir = `${this.storage.getDocumentDirectory()}ota-update/`;
|
|
160
|
+
// Keep a normalized version for native module calls
|
|
161
|
+
this.baseDirNormalized = normalizePath(this.baseDir);
|
|
151
162
|
}
|
|
152
163
|
async ensureDirectory() {
|
|
153
164
|
const exists = await this.storage.exists(this.baseDir);
|
|
@@ -155,24 +166,40 @@ class UpdateStorage {
|
|
|
155
166
|
await this.storage.makeDirectory(this.baseDir);
|
|
156
167
|
}
|
|
157
168
|
}
|
|
169
|
+
|
|
170
|
+
// Get normalized path (without file:// prefix) for native module compatibility
|
|
171
|
+
getNormalizedPath(path) {
|
|
172
|
+
return normalizePath(path);
|
|
173
|
+
}
|
|
158
174
|
async saveBundle(releaseId, data) {
|
|
159
175
|
await this.ensureDirectory();
|
|
160
176
|
const bundlePath = `${this.baseDir}${releaseId}.bundle`;
|
|
161
177
|
await this.storage.writeFile(bundlePath, data);
|
|
162
|
-
|
|
178
|
+
|
|
179
|
+
// Return normalized path for native module compatibility
|
|
180
|
+
return normalizePath(bundlePath);
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Get the raw bundle path (with file:// for Expo) - for internal storage operations
|
|
184
|
+
getRawBundlePath(releaseId) {
|
|
185
|
+
return `${this.baseDir}${releaseId}.bundle`;
|
|
163
186
|
}
|
|
164
187
|
async getBundlePath(releaseId) {
|
|
165
|
-
const bundlePath =
|
|
188
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
166
189
|
const exists = await this.storage.exists(bundlePath);
|
|
167
|
-
|
|
190
|
+
// Return normalized path for native module compatibility
|
|
191
|
+
return exists ? normalizePath(bundlePath) : null;
|
|
168
192
|
}
|
|
169
193
|
async readBundle(releaseId) {
|
|
170
|
-
const bundlePath =
|
|
171
|
-
|
|
194
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
195
|
+
const exists = await this.storage.exists(bundlePath);
|
|
196
|
+
if (!exists) return null;
|
|
197
|
+
|
|
198
|
+
// Use raw path for storage operations (expo needs file:// prefix)
|
|
172
199
|
return this.storage.readFileAsBuffer(bundlePath);
|
|
173
200
|
}
|
|
174
201
|
async deleteBundle(releaseId) {
|
|
175
|
-
const bundlePath =
|
|
202
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
176
203
|
if (await this.storage.exists(bundlePath)) {
|
|
177
204
|
await this.storage.deleteFile(bundlePath);
|
|
178
205
|
}
|
|
@@ -204,6 +231,54 @@ class UpdateStorage {
|
|
|
204
231
|
// For now, we just keep one bundle at a time
|
|
205
232
|
// In a more advanced implementation, we might keep a few for rollback
|
|
206
233
|
}
|
|
234
|
+
|
|
235
|
+
/**
|
|
236
|
+
* Register the bundle path with the native module.
|
|
237
|
+
* This saves the path to SharedPreferences (Android) or UserDefaults (iOS)
|
|
238
|
+
* so the app can load the OTA bundle on restart.
|
|
239
|
+
*
|
|
240
|
+
* @param bundlePath The normalized path to the bundle file
|
|
241
|
+
* @param restart Whether to restart the app immediately
|
|
242
|
+
* @returns true if successfully registered with native module, false otherwise
|
|
243
|
+
*/
|
|
244
|
+
async registerBundleWithNative(bundlePath, restart = false) {
|
|
245
|
+
try {
|
|
246
|
+
if (OTAUpdateNative?.applyBundle) {
|
|
247
|
+
// Ensure path is normalized before passing to native module
|
|
248
|
+
const normalizedPath = normalizePath(bundlePath);
|
|
249
|
+
await OTAUpdateNative.applyBundle(normalizedPath, restart);
|
|
250
|
+
return true;
|
|
251
|
+
} else {
|
|
252
|
+
// Native module not available - this is expected for Expo Go
|
|
253
|
+
// but should work for EAS Build apps
|
|
254
|
+
if (__DEV__) {
|
|
255
|
+
console.log('[OTAUpdate] Native module not available. Update will apply on next build with native modules.');
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
} catch (error) {
|
|
260
|
+
if (__DEV__) {
|
|
261
|
+
console.error('[OTAUpdate] Failed to register bundle with native module:', error);
|
|
262
|
+
}
|
|
263
|
+
return false;
|
|
264
|
+
}
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
/**
|
|
268
|
+
* Clear the pending bundle from native storage.
|
|
269
|
+
* This removes the bundle path from SharedPreferences (Android) or UserDefaults (iOS).
|
|
270
|
+
*/
|
|
271
|
+
async clearNativePendingBundle() {
|
|
272
|
+
try {
|
|
273
|
+
if (OTAUpdateNative?.clearPendingBundle) {
|
|
274
|
+
await OTAUpdateNative.clearPendingBundle();
|
|
275
|
+
}
|
|
276
|
+
} catch (error) {
|
|
277
|
+
if (__DEV__) {
|
|
278
|
+
console.error('[OTAUpdate] Failed to clear pending bundle:', error);
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
}
|
|
207
282
|
}
|
|
208
283
|
exports.UpdateStorage = UpdateStorage;
|
|
209
284
|
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","ExpoFileSystem","OTAUpdateNative","NativeModules","OTAUpdate","ExpoStorageAdapter","getDocumentDirectory","documentDirectory","writeFile","
|
|
1
|
+
{"version":3,"names":["_reactNative","require","normalizePath","path","startsWith","slice","ExpoFileSystem","OTAUpdateNative","NativeModules","OTAUpdate","ExpoStorageAdapter","getDocumentDirectory","documentDirectory","writeFile","data","ArrayBuffer","bytes","Uint8Array","binary","i","length","String","fromCharCode","base64","btoa","writeAsStringAsync","encoding","EncodingType","Base64","readFile","readAsStringAsync","readFileAsBuffer","atob","charCodeAt","buffer","deleteFile","deleteAsync","idempotent","exists","info","getInfoAsync","makeDirectory","makeDirectoryAsync","intermediates","NativeStorageAdapter","Error","writeFileBase64","readFileBase64","getStorageAdapter","UpdateStorage","constructor","storage","isExpo","baseDir","baseDirNormalized","ensureDirectory","getNormalizedPath","saveBundle","releaseId","bundlePath","getRawBundlePath","getBundlePath","readBundle","deleteBundle","saveMetadata","update","metadataPath","JSON","stringify","getMetadata","content","parse","clearMetadata","cleanOldBundles","keepReleaseId","registerBundleWithNative","restart","applyBundle","normalizedPath","__DEV__","console","log","error","clearNativePendingBundle","clearPendingBundle","exports"],"sourceRoot":"../../../src","sources":["utils/storage.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
2
|
-
import { AppState,
|
|
2
|
+
import { AppState, Platform } from 'react-native';
|
|
3
3
|
import { OTAApiClient, getDeviceInfo } from '../utils/api';
|
|
4
4
|
import { UpdateStorage } from '../utils/storage';
|
|
5
5
|
import { verifyBundle } from '../utils/verification';
|
|
6
|
-
const OTAUpdateNative = NativeModules.OTAUpdate;
|
|
7
6
|
// Generate or get device ID
|
|
8
7
|
async function getDeviceId() {
|
|
9
8
|
// Try to get from native module or AsyncStorage
|
|
@@ -140,6 +139,17 @@ export function useOTAUpdate(config) {
|
|
|
140
139
|
bundleHash: release.bundleHash,
|
|
141
140
|
downloadedAt: Date.now()
|
|
142
141
|
});
|
|
142
|
+
|
|
143
|
+
// Register the bundle path with native module (for next app restart)
|
|
144
|
+
// This saves to SharedPreferences (Android) / UserDefaults (iOS)
|
|
145
|
+
const registered = await storage.current.registerBundleWithNative(bundlePath, false);
|
|
146
|
+
if (__DEV__) {
|
|
147
|
+
if (registered) {
|
|
148
|
+
console.log('[OTAUpdate] Bundle registered with native module. Will apply on app restart.');
|
|
149
|
+
} else {
|
|
150
|
+
console.log('[OTAUpdate] Could not register with native module. If using Expo Go, this is expected.');
|
|
151
|
+
}
|
|
152
|
+
}
|
|
143
153
|
setStatus('ready');
|
|
144
154
|
} catch (err) {
|
|
145
155
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -180,14 +190,18 @@ export function useOTAUpdate(config) {
|
|
|
180
190
|
deviceInfo: getDeviceInfo()
|
|
181
191
|
});
|
|
182
192
|
|
|
183
|
-
//
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
//
|
|
188
|
-
// The bundle will be loaded on next app start
|
|
193
|
+
// Register bundle path with native module and optionally restart
|
|
194
|
+
// This ensures the path is saved to SharedPreferences/UserDefaults
|
|
195
|
+
const registered = await storage.current.registerBundleWithNative(metadata.bundlePath, restartApp);
|
|
196
|
+
if (!registered && restartApp) {
|
|
197
|
+
// Native module not available
|
|
189
198
|
if (__DEV__) {
|
|
190
|
-
console.log('[OTAUpdate] Update ready.
|
|
199
|
+
console.log('[OTAUpdate] Update ready. Close and reopen the app to apply the update.');
|
|
200
|
+
console.log('[OTAUpdate] Note: For Expo Go, OTA updates require a native build (EAS Build).');
|
|
201
|
+
}
|
|
202
|
+
} else if (registered && !restartApp) {
|
|
203
|
+
if (__DEV__) {
|
|
204
|
+
console.log('[OTAUpdate] Update registered. Will apply on next app restart.');
|
|
191
205
|
}
|
|
192
206
|
}
|
|
193
207
|
|
|
@@ -226,6 +240,9 @@ export function useOTAUpdate(config) {
|
|
|
226
240
|
await storage.current.deleteBundle(metadata.releaseId);
|
|
227
241
|
await storage.current.clearMetadata();
|
|
228
242
|
}
|
|
243
|
+
|
|
244
|
+
// Also clear from native storage (SharedPreferences/UserDefaults)
|
|
245
|
+
await storage.current.clearNativePendingBundle();
|
|
229
246
|
setUpdateInfo(null);
|
|
230
247
|
releaseRef.current = null;
|
|
231
248
|
setStatus('idle');
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useState","useCallback","useEffect","useRef","AppState","
|
|
1
|
+
{"version":3,"names":["useState","useCallback","useEffect","useRef","AppState","Platform","OTAApiClient","getDeviceInfo","UpdateStorage","verifyBundle","getDeviceId","id","Math","random","toString","substring","useOTAUpdate","config","serverUrl","appSlug","channel","appVersion","publicKey","checkOnMount","checkOnForeground","status","setStatus","updateInfo","setUpdateInfo","downloadProgress","setDownloadProgress","error","setError","currentVersion","setCurrentVersion","apiClient","storage","deviceIdRef","releaseRef","loadCurrentVersion","metadata","current","getMetadata","version","getDeviceIdCached","checkForUpdate","deviceId","currentMetadata","response","checkUpdate","platform","OS","updateAvailable","release","info","releaseId","bundleSize","isMandatory","releaseNotes","err","Error","String","downloadUpdate","downloadedBytes","totalBytes","percentage","reportEvent","eventType","deviceInfo","bundleData","downloadBundle","bundleUrl","byteLength","verification","bundleHash","bundleSignature","valid","bundlePath","saveBundle","saveMetadata","downloadedAt","Date","now","registered","registerBundleWithNative","__DEV__","console","log","errorMessage","message","applyUpdate","restartApp","clearPendingUpdate","deleteBundle","clearMetadata","clearNativePendingBundle","handleAppStateChange","nextAppState","subscription","addEventListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useOTAUpdate.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -2,6 +2,14 @@ import { NativeModules } from 'react-native';
|
|
|
2
2
|
|
|
3
3
|
// Types
|
|
4
4
|
|
|
5
|
+
// Helper to normalize file paths (remove file:// prefix)
|
|
6
|
+
function normalizePath(path) {
|
|
7
|
+
if (path.startsWith('file://')) {
|
|
8
|
+
return path.slice(7);
|
|
9
|
+
}
|
|
10
|
+
return path;
|
|
11
|
+
}
|
|
12
|
+
|
|
5
13
|
// Try to use Expo FileSystem if available
|
|
6
14
|
let ExpoFileSystem = null;
|
|
7
15
|
try {
|
|
@@ -141,7 +149,10 @@ export function getStorageAdapter() {
|
|
|
141
149
|
export class UpdateStorage {
|
|
142
150
|
constructor() {
|
|
143
151
|
this.storage = getStorageAdapter();
|
|
152
|
+
this.isExpo = !!ExpoFileSystem;
|
|
144
153
|
this.baseDir = `${this.storage.getDocumentDirectory()}ota-update/`;
|
|
154
|
+
// Keep a normalized version for native module calls
|
|
155
|
+
this.baseDirNormalized = normalizePath(this.baseDir);
|
|
145
156
|
}
|
|
146
157
|
async ensureDirectory() {
|
|
147
158
|
const exists = await this.storage.exists(this.baseDir);
|
|
@@ -149,24 +160,40 @@ export class UpdateStorage {
|
|
|
149
160
|
await this.storage.makeDirectory(this.baseDir);
|
|
150
161
|
}
|
|
151
162
|
}
|
|
163
|
+
|
|
164
|
+
// Get normalized path (without file:// prefix) for native module compatibility
|
|
165
|
+
getNormalizedPath(path) {
|
|
166
|
+
return normalizePath(path);
|
|
167
|
+
}
|
|
152
168
|
async saveBundle(releaseId, data) {
|
|
153
169
|
await this.ensureDirectory();
|
|
154
170
|
const bundlePath = `${this.baseDir}${releaseId}.bundle`;
|
|
155
171
|
await this.storage.writeFile(bundlePath, data);
|
|
156
|
-
|
|
172
|
+
|
|
173
|
+
// Return normalized path for native module compatibility
|
|
174
|
+
return normalizePath(bundlePath);
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// Get the raw bundle path (with file:// for Expo) - for internal storage operations
|
|
178
|
+
getRawBundlePath(releaseId) {
|
|
179
|
+
return `${this.baseDir}${releaseId}.bundle`;
|
|
157
180
|
}
|
|
158
181
|
async getBundlePath(releaseId) {
|
|
159
|
-
const bundlePath =
|
|
182
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
160
183
|
const exists = await this.storage.exists(bundlePath);
|
|
161
|
-
|
|
184
|
+
// Return normalized path for native module compatibility
|
|
185
|
+
return exists ? normalizePath(bundlePath) : null;
|
|
162
186
|
}
|
|
163
187
|
async readBundle(releaseId) {
|
|
164
|
-
const bundlePath =
|
|
165
|
-
|
|
188
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
189
|
+
const exists = await this.storage.exists(bundlePath);
|
|
190
|
+
if (!exists) return null;
|
|
191
|
+
|
|
192
|
+
// Use raw path for storage operations (expo needs file:// prefix)
|
|
166
193
|
return this.storage.readFileAsBuffer(bundlePath);
|
|
167
194
|
}
|
|
168
195
|
async deleteBundle(releaseId) {
|
|
169
|
-
const bundlePath =
|
|
196
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
170
197
|
if (await this.storage.exists(bundlePath)) {
|
|
171
198
|
await this.storage.deleteFile(bundlePath);
|
|
172
199
|
}
|
|
@@ -198,5 +225,53 @@ export class UpdateStorage {
|
|
|
198
225
|
// For now, we just keep one bundle at a time
|
|
199
226
|
// In a more advanced implementation, we might keep a few for rollback
|
|
200
227
|
}
|
|
228
|
+
|
|
229
|
+
/**
|
|
230
|
+
* Register the bundle path with the native module.
|
|
231
|
+
* This saves the path to SharedPreferences (Android) or UserDefaults (iOS)
|
|
232
|
+
* so the app can load the OTA bundle on restart.
|
|
233
|
+
*
|
|
234
|
+
* @param bundlePath The normalized path to the bundle file
|
|
235
|
+
* @param restart Whether to restart the app immediately
|
|
236
|
+
* @returns true if successfully registered with native module, false otherwise
|
|
237
|
+
*/
|
|
238
|
+
async registerBundleWithNative(bundlePath, restart = false) {
|
|
239
|
+
try {
|
|
240
|
+
if (OTAUpdateNative?.applyBundle) {
|
|
241
|
+
// Ensure path is normalized before passing to native module
|
|
242
|
+
const normalizedPath = normalizePath(bundlePath);
|
|
243
|
+
await OTAUpdateNative.applyBundle(normalizedPath, restart);
|
|
244
|
+
return true;
|
|
245
|
+
} else {
|
|
246
|
+
// Native module not available - this is expected for Expo Go
|
|
247
|
+
// but should work for EAS Build apps
|
|
248
|
+
if (__DEV__) {
|
|
249
|
+
console.log('[OTAUpdate] Native module not available. Update will apply on next build with native modules.');
|
|
250
|
+
}
|
|
251
|
+
return false;
|
|
252
|
+
}
|
|
253
|
+
} catch (error) {
|
|
254
|
+
if (__DEV__) {
|
|
255
|
+
console.error('[OTAUpdate] Failed to register bundle with native module:', error);
|
|
256
|
+
}
|
|
257
|
+
return false;
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
/**
|
|
262
|
+
* Clear the pending bundle from native storage.
|
|
263
|
+
* This removes the bundle path from SharedPreferences (Android) or UserDefaults (iOS).
|
|
264
|
+
*/
|
|
265
|
+
async clearNativePendingBundle() {
|
|
266
|
+
try {
|
|
267
|
+
if (OTAUpdateNative?.clearPendingBundle) {
|
|
268
|
+
await OTAUpdateNative.clearPendingBundle();
|
|
269
|
+
}
|
|
270
|
+
} catch (error) {
|
|
271
|
+
if (__DEV__) {
|
|
272
|
+
console.error('[OTAUpdate] Failed to clear pending bundle:', error);
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
}
|
|
201
276
|
}
|
|
202
277
|
//# sourceMappingURL=storage.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativeModules","ExpoFileSystem","require","OTAUpdateNative","OTAUpdate","ExpoStorageAdapter","getDocumentDirectory","documentDirectory","writeFile","
|
|
1
|
+
{"version":3,"names":["NativeModules","normalizePath","path","startsWith","slice","ExpoFileSystem","require","OTAUpdateNative","OTAUpdate","ExpoStorageAdapter","getDocumentDirectory","documentDirectory","writeFile","data","ArrayBuffer","bytes","Uint8Array","binary","i","length","String","fromCharCode","base64","btoa","writeAsStringAsync","encoding","EncodingType","Base64","readFile","readAsStringAsync","readFileAsBuffer","atob","charCodeAt","buffer","deleteFile","deleteAsync","idempotent","exists","info","getInfoAsync","makeDirectory","makeDirectoryAsync","intermediates","NativeStorageAdapter","Error","writeFileBase64","readFileBase64","getStorageAdapter","UpdateStorage","constructor","storage","isExpo","baseDir","baseDirNormalized","ensureDirectory","getNormalizedPath","saveBundle","releaseId","bundlePath","getRawBundlePath","getBundlePath","readBundle","deleteBundle","saveMetadata","update","metadataPath","JSON","stringify","getMetadata","content","parse","clearMetadata","cleanOldBundles","keepReleaseId","registerBundleWithNative","restart","applyBundle","normalizedPath","__DEV__","console","log","error","clearNativePendingBundle","clearPendingBundle"],"sourceRoot":"../../../src","sources":["utils/storage.ts"],"mappings":"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","ignoreList":[]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useOTAUpdate.d.ts","sourceRoot":"","sources":["../../../src/hooks/useOTAUpdate.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useOTAUpdate.d.ts","sourceRoot":"","sources":["../../../src/hooks/useOTAUpdate.ts"],"names":[],"mappings":"AAMA,MAAM,WAAW,eAAe;IAC9B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,UAAU,EAAE,MAAM,CAAC;IACnB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,YAAY,CAAC,EAAE,OAAO,CAAC;IACvB,iBAAiB,CAAC,EAAE,OAAO,CAAC;CAC7B;AAED,MAAM,WAAW,UAAU;IACzB,OAAO,EAAE,MAAM,CAAC;IAChB,SAAS,EAAE,MAAM,CAAC;IAClB,UAAU,EAAE,MAAM,CAAC;IACnB,WAAW,EAAE,OAAO,CAAC;IACrB,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;CAC7B;AAED,MAAM,WAAW,gBAAgB;IAC/B,eAAe,EAAE,MAAM,CAAC;IACxB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,MAAM,YAAY,GACpB,MAAM,GACN,UAAU,GACV,WAAW,GACX,aAAa,GACb,WAAW,GACX,OAAO,GACP,UAAU,GACV,OAAO,GACP,YAAY,CAAC;AAEjB,MAAM,WAAW,kBAAkB;IACjC,MAAM,EAAE,YAAY,CAAC;IACrB,UAAU,EAAE,UAAU,GAAG,IAAI,CAAC;IAC9B,gBAAgB,EAAE,gBAAgB,GAAG,IAAI,CAAC;IAC1C,KAAK,EAAE,KAAK,GAAG,IAAI,CAAC;IACpB,cAAc,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,cAAc,EAAE,MAAM,OAAO,CAAC,UAAU,GAAG,IAAI,CAAC,CAAC;IACjD,cAAc,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;IACpC,WAAW,EAAE,CAAC,UAAU,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,IAAI,CAAC,CAAC;IACrD,kBAAkB,EAAE,MAAM,OAAO,CAAC,IAAI,CAAC,CAAC;CACzC;AAWD,wBAAgB,YAAY,CAAC,MAAM,EAAE,eAAe,GAAG,kBAAkB,CA2SxE"}
|
|
@@ -18,9 +18,13 @@ export declare function getStorageAdapter(): StorageAdapter;
|
|
|
18
18
|
export declare class UpdateStorage {
|
|
19
19
|
private storage;
|
|
20
20
|
private baseDir;
|
|
21
|
+
private baseDirNormalized;
|
|
22
|
+
private isExpo;
|
|
21
23
|
constructor();
|
|
22
24
|
private ensureDirectory;
|
|
25
|
+
getNormalizedPath(path: string): string;
|
|
23
26
|
saveBundle(releaseId: string, data: ArrayBuffer): Promise<string>;
|
|
27
|
+
private getRawBundlePath;
|
|
24
28
|
getBundlePath(releaseId: string): Promise<string | null>;
|
|
25
29
|
readBundle(releaseId: string): Promise<ArrayBuffer | null>;
|
|
26
30
|
deleteBundle(releaseId: string): Promise<void>;
|
|
@@ -28,5 +32,20 @@ export declare class UpdateStorage {
|
|
|
28
32
|
getMetadata(): Promise<StoredUpdate | null>;
|
|
29
33
|
clearMetadata(): Promise<void>;
|
|
30
34
|
cleanOldBundles(keepReleaseId: string): Promise<void>;
|
|
35
|
+
/**
|
|
36
|
+
* Register the bundle path with the native module.
|
|
37
|
+
* This saves the path to SharedPreferences (Android) or UserDefaults (iOS)
|
|
38
|
+
* so the app can load the OTA bundle on restart.
|
|
39
|
+
*
|
|
40
|
+
* @param bundlePath The normalized path to the bundle file
|
|
41
|
+
* @param restart Whether to restart the app immediately
|
|
42
|
+
* @returns true if successfully registered with native module, false otherwise
|
|
43
|
+
*/
|
|
44
|
+
registerBundleWithNative(bundlePath: string, restart?: boolean): Promise<boolean>;
|
|
45
|
+
/**
|
|
46
|
+
* Clear the pending bundle from native storage.
|
|
47
|
+
* This removes the bundle path from SharedPreferences (Android) or UserDefaults (iOS).
|
|
48
|
+
*/
|
|
49
|
+
clearNativePendingBundle(): Promise<void>;
|
|
31
50
|
}
|
|
32
51
|
//# sourceMappingURL=storage.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/utils/storage.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,oBAAoB,IAAI,MAAM,CAAC;IAC/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;
|
|
1
|
+
{"version":3,"file":"storage.d.ts","sourceRoot":"","sources":["../../../src/utils/storage.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,YAAY;IAC3B,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,EAAE,MAAM,CAAC;IAChB,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,cAAc;IAC7B,oBAAoB,IAAI,MAAM,CAAC;IAC/B,SAAS,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACnE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC;IACxC,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,CAAC,CAAC;IACrD,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IACxC,MAAM,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IACvC,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC5C;AAgJD,wBAAgB,iBAAiB,IAAI,cAAc,CAYlD;AAGD,qBAAa,aAAa;IACxB,OAAO,CAAC,OAAO,CAAiB;IAChC,OAAO,CAAC,OAAO,CAAS;IACxB,OAAO,CAAC,iBAAiB,CAAS;IAClC,OAAO,CAAC,MAAM,CAAU;;YAUV,eAAe;IAQ7B,iBAAiB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM;IAIjC,UAAU,CAAC,SAAS,EAAE,MAAM,EAAE,IAAI,EAAE,WAAW,GAAG,OAAO,CAAC,MAAM,CAAC;IAWvE,OAAO,CAAC,gBAAgB;IAIlB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAOxD,UAAU,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,WAAW,GAAG,IAAI,CAAC;IAS1D,YAAY,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAO9C,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAOjD,WAAW,IAAI,OAAO,CAAC,YAAY,GAAG,IAAI,CAAC;IAe3C,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC;IAO9B,eAAe,CAAC,aAAa,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAK3D;;;;;;;;OAQG;IACG,wBAAwB,CAAC,UAAU,EAAE,MAAM,EAAE,OAAO,GAAE,OAAe,GAAG,OAAO,CAAC,OAAO,CAAC;IAuB9F;;;OAGG;IACG,wBAAwB,IAAI,OAAO,CAAC,IAAI,CAAC;CAWhD"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@vanikya/ota-react-native",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.6",
|
|
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",
|
|
@@ -14,6 +14,7 @@
|
|
|
14
14
|
"ios",
|
|
15
15
|
"*.podspec",
|
|
16
16
|
"react-native.config.js",
|
|
17
|
+
"app.plugin.js",
|
|
17
18
|
"README.md"
|
|
18
19
|
],
|
|
19
20
|
"scripts": {
|
|
@@ -1,11 +1,9 @@
|
|
|
1
1
|
import { useState, useCallback, useEffect, useRef } from 'react';
|
|
2
|
-
import { AppState, AppStateStatus,
|
|
2
|
+
import { AppState, AppStateStatus, Platform } from 'react-native';
|
|
3
3
|
import { OTAApiClient, ReleaseInfo, getDeviceInfo } from '../utils/api';
|
|
4
4
|
import { UpdateStorage, StoredUpdate } from '../utils/storage';
|
|
5
5
|
import { verifyBundle, VerificationResult } from '../utils/verification';
|
|
6
6
|
|
|
7
|
-
const OTAUpdateNative = NativeModules.OTAUpdate;
|
|
8
|
-
|
|
9
7
|
export interface OTAUpdateConfig {
|
|
10
8
|
serverUrl: string;
|
|
11
9
|
appSlug: string;
|
|
@@ -206,6 +204,18 @@ export function useOTAUpdate(config: OTAUpdateConfig): UseOTAUpdateResult {
|
|
|
206
204
|
downloadedAt: Date.now(),
|
|
207
205
|
});
|
|
208
206
|
|
|
207
|
+
// Register the bundle path with native module (for next app restart)
|
|
208
|
+
// This saves to SharedPreferences (Android) / UserDefaults (iOS)
|
|
209
|
+
const registered = await storage.current.registerBundleWithNative(bundlePath, false);
|
|
210
|
+
|
|
211
|
+
if (__DEV__) {
|
|
212
|
+
if (registered) {
|
|
213
|
+
console.log('[OTAUpdate] Bundle registered with native module. Will apply on app restart.');
|
|
214
|
+
} else {
|
|
215
|
+
console.log('[OTAUpdate] Could not register with native module. If using Expo Go, this is expected.');
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
|
|
209
219
|
setStatus('ready');
|
|
210
220
|
} catch (err) {
|
|
211
221
|
const error = err instanceof Error ? err : new Error(String(err));
|
|
@@ -250,14 +260,19 @@ export function useOTAUpdate(config: OTAUpdateConfig): UseOTAUpdateResult {
|
|
|
250
260
|
deviceInfo: getDeviceInfo(),
|
|
251
261
|
});
|
|
252
262
|
|
|
253
|
-
//
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
//
|
|
263
|
+
// Register bundle path with native module and optionally restart
|
|
264
|
+
// This ensures the path is saved to SharedPreferences/UserDefaults
|
|
265
|
+
const registered = await storage.current.registerBundleWithNative(metadata.bundlePath, restartApp);
|
|
266
|
+
|
|
267
|
+
if (!registered && restartApp) {
|
|
268
|
+
// Native module not available
|
|
269
|
+
if (__DEV__) {
|
|
270
|
+
console.log('[OTAUpdate] Update ready. Close and reopen the app to apply the update.');
|
|
271
|
+
console.log('[OTAUpdate] Note: For Expo Go, OTA updates require a native build (EAS Build).');
|
|
272
|
+
}
|
|
273
|
+
} else if (registered && !restartApp) {
|
|
259
274
|
if (__DEV__) {
|
|
260
|
-
console.log('[OTAUpdate] Update
|
|
275
|
+
console.log('[OTAUpdate] Update registered. Will apply on next app restart.');
|
|
261
276
|
}
|
|
262
277
|
}
|
|
263
278
|
|
|
@@ -301,6 +316,9 @@ export function useOTAUpdate(config: OTAUpdateConfig): UseOTAUpdateResult {
|
|
|
301
316
|
await storage.current.clearMetadata();
|
|
302
317
|
}
|
|
303
318
|
|
|
319
|
+
// Also clear from native storage (SharedPreferences/UserDefaults)
|
|
320
|
+
await storage.current.clearNativePendingBundle();
|
|
321
|
+
|
|
304
322
|
setUpdateInfo(null);
|
|
305
323
|
releaseRef.current = null;
|
|
306
324
|
setStatus('idle');
|
package/src/utils/storage.ts
CHANGED
|
@@ -19,6 +19,14 @@ export interface StorageAdapter {
|
|
|
19
19
|
makeDirectory(path: string): Promise<void>;
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
+
// Helper to normalize file paths (remove file:// prefix)
|
|
23
|
+
function normalizePath(path: string): string {
|
|
24
|
+
if (path.startsWith('file://')) {
|
|
25
|
+
return path.slice(7);
|
|
26
|
+
}
|
|
27
|
+
return path;
|
|
28
|
+
}
|
|
29
|
+
|
|
22
30
|
// Try to use Expo FileSystem if available
|
|
23
31
|
let ExpoFileSystem: any = null;
|
|
24
32
|
try {
|
|
@@ -171,10 +179,15 @@ export function getStorageAdapter(): StorageAdapter {
|
|
|
171
179
|
export class UpdateStorage {
|
|
172
180
|
private storage: StorageAdapter;
|
|
173
181
|
private baseDir: string;
|
|
182
|
+
private baseDirNormalized: string;
|
|
183
|
+
private isExpo: boolean;
|
|
174
184
|
|
|
175
185
|
constructor() {
|
|
176
186
|
this.storage = getStorageAdapter();
|
|
187
|
+
this.isExpo = !!ExpoFileSystem;
|
|
177
188
|
this.baseDir = `${this.storage.getDocumentDirectory()}ota-update/`;
|
|
189
|
+
// Keep a normalized version for native module calls
|
|
190
|
+
this.baseDirNormalized = normalizePath(this.baseDir);
|
|
178
191
|
}
|
|
179
192
|
|
|
180
193
|
private async ensureDirectory(): Promise<void> {
|
|
@@ -184,30 +197,44 @@ export class UpdateStorage {
|
|
|
184
197
|
}
|
|
185
198
|
}
|
|
186
199
|
|
|
200
|
+
// Get normalized path (without file:// prefix) for native module compatibility
|
|
201
|
+
getNormalizedPath(path: string): string {
|
|
202
|
+
return normalizePath(path);
|
|
203
|
+
}
|
|
204
|
+
|
|
187
205
|
async saveBundle(releaseId: string, data: ArrayBuffer): Promise<string> {
|
|
188
206
|
await this.ensureDirectory();
|
|
189
207
|
|
|
190
208
|
const bundlePath = `${this.baseDir}${releaseId}.bundle`;
|
|
191
209
|
await this.storage.writeFile(bundlePath, data);
|
|
192
210
|
|
|
193
|
-
|
|
211
|
+
// Return normalized path for native module compatibility
|
|
212
|
+
return normalizePath(bundlePath);
|
|
213
|
+
}
|
|
214
|
+
|
|
215
|
+
// Get the raw bundle path (with file:// for Expo) - for internal storage operations
|
|
216
|
+
private getRawBundlePath(releaseId: string): string {
|
|
217
|
+
return `${this.baseDir}${releaseId}.bundle`;
|
|
194
218
|
}
|
|
195
219
|
|
|
196
220
|
async getBundlePath(releaseId: string): Promise<string | null> {
|
|
197
|
-
const bundlePath =
|
|
221
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
198
222
|
const exists = await this.storage.exists(bundlePath);
|
|
199
|
-
|
|
223
|
+
// Return normalized path for native module compatibility
|
|
224
|
+
return exists ? normalizePath(bundlePath) : null;
|
|
200
225
|
}
|
|
201
226
|
|
|
202
227
|
async readBundle(releaseId: string): Promise<ArrayBuffer | null> {
|
|
203
|
-
const bundlePath =
|
|
204
|
-
|
|
228
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
229
|
+
const exists = await this.storage.exists(bundlePath);
|
|
230
|
+
if (!exists) return null;
|
|
205
231
|
|
|
232
|
+
// Use raw path for storage operations (expo needs file:// prefix)
|
|
206
233
|
return this.storage.readFileAsBuffer(bundlePath);
|
|
207
234
|
}
|
|
208
235
|
|
|
209
236
|
async deleteBundle(releaseId: string): Promise<void> {
|
|
210
|
-
const bundlePath =
|
|
237
|
+
const bundlePath = this.getRawBundlePath(releaseId);
|
|
211
238
|
if (await this.storage.exists(bundlePath)) {
|
|
212
239
|
await this.storage.deleteFile(bundlePath);
|
|
213
240
|
}
|
|
@@ -246,4 +273,52 @@ export class UpdateStorage {
|
|
|
246
273
|
// For now, we just keep one bundle at a time
|
|
247
274
|
// In a more advanced implementation, we might keep a few for rollback
|
|
248
275
|
}
|
|
276
|
+
|
|
277
|
+
/**
|
|
278
|
+
* Register the bundle path with the native module.
|
|
279
|
+
* This saves the path to SharedPreferences (Android) or UserDefaults (iOS)
|
|
280
|
+
* so the app can load the OTA bundle on restart.
|
|
281
|
+
*
|
|
282
|
+
* @param bundlePath The normalized path to the bundle file
|
|
283
|
+
* @param restart Whether to restart the app immediately
|
|
284
|
+
* @returns true if successfully registered with native module, false otherwise
|
|
285
|
+
*/
|
|
286
|
+
async registerBundleWithNative(bundlePath: string, restart: boolean = false): Promise<boolean> {
|
|
287
|
+
try {
|
|
288
|
+
if (OTAUpdateNative?.applyBundle) {
|
|
289
|
+
// Ensure path is normalized before passing to native module
|
|
290
|
+
const normalizedPath = normalizePath(bundlePath);
|
|
291
|
+
await OTAUpdateNative.applyBundle(normalizedPath, restart);
|
|
292
|
+
return true;
|
|
293
|
+
} else {
|
|
294
|
+
// Native module not available - this is expected for Expo Go
|
|
295
|
+
// but should work for EAS Build apps
|
|
296
|
+
if (__DEV__) {
|
|
297
|
+
console.log('[OTAUpdate] Native module not available. Update will apply on next build with native modules.');
|
|
298
|
+
}
|
|
299
|
+
return false;
|
|
300
|
+
}
|
|
301
|
+
} catch (error) {
|
|
302
|
+
if (__DEV__) {
|
|
303
|
+
console.error('[OTAUpdate] Failed to register bundle with native module:', error);
|
|
304
|
+
}
|
|
305
|
+
return false;
|
|
306
|
+
}
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
/**
|
|
310
|
+
* Clear the pending bundle from native storage.
|
|
311
|
+
* This removes the bundle path from SharedPreferences (Android) or UserDefaults (iOS).
|
|
312
|
+
*/
|
|
313
|
+
async clearNativePendingBundle(): Promise<void> {
|
|
314
|
+
try {
|
|
315
|
+
if (OTAUpdateNative?.clearPendingBundle) {
|
|
316
|
+
await OTAUpdateNative.clearPendingBundle();
|
|
317
|
+
}
|
|
318
|
+
} catch (error) {
|
|
319
|
+
if (__DEV__) {
|
|
320
|
+
console.error('[OTAUpdate] Failed to clear pending bundle:', error);
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
}
|
|
249
324
|
}
|