@vanikya/ota-react-native 0.1.7 → 0.1.9
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 +82 -7
- package/android/src/main/java/com/otaupdate/OTAUpdateModule.kt +94 -0
- package/ios/OTAUpdate.m +9 -0
- package/ios/OTAUpdate.swift +106 -0
- package/lib/commonjs/hooks/useOTAUpdate.js +42 -11
- package/lib/commonjs/hooks/useOTAUpdate.js.map +1 -1
- package/lib/commonjs/index.js +1 -1
- package/lib/commonjs/utils/api.js +53 -1
- package/lib/commonjs/utils/api.js.map +1 -1
- package/lib/commonjs/utils/storage.js +265 -13
- package/lib/commonjs/utils/storage.js.map +1 -1
- package/lib/commonjs/utils/verification.js +23 -12
- package/lib/commonjs/utils/verification.js.map +1 -1
- package/lib/module/hooks/useOTAUpdate.js +42 -11
- package/lib/module/hooks/useOTAUpdate.js.map +1 -1
- package/lib/module/index.js +1 -1
- package/lib/module/utils/api.js +53 -1
- package/lib/module/utils/api.js.map +1 -1
- package/lib/module/utils/storage.js +265 -13
- package/lib/module/utils/storage.js.map +1 -1
- package/lib/module/utils/verification.js +23 -12
- package/lib/module/utils/verification.js.map +1 -1
- package/lib/typescript/hooks/useOTAUpdate.d.ts +3 -0
- package/lib/typescript/hooks/useOTAUpdate.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +1 -1
- package/lib/typescript/utils/api.d.ts +1 -0
- package/lib/typescript/utils/api.d.ts.map +1 -1
- package/lib/typescript/utils/storage.d.ts +39 -0
- package/lib/typescript/utils/storage.d.ts.map +1 -1
- package/lib/typescript/utils/verification.d.ts.map +1 -1
- package/package.json +2 -2
- package/src/hooks/useOTAUpdate.ts +46 -16
- package/src/index.ts +1 -1
- package/src/utils/api.ts +81 -1
- package/src/utils/storage.ts +317 -13
- package/src/utils/verification.ts +25 -12
package/README.md
CHANGED
|
@@ -2,6 +2,8 @@
|
|
|
2
2
|
|
|
3
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).
|
|
4
4
|
|
|
5
|
+
**[Documentation](https://vanikya.github.io/ota-update/)** | **[GitHub](https://github.com/vanikya/ota-update)** | **[npm](https://www.npmjs.com/package/@vanikya/ota-react-native)**
|
|
6
|
+
|
|
5
7
|
React Native SDK for OTA (Over-The-Air) updates. A self-hosted alternative to CodePush and EAS Updates.
|
|
6
8
|
|
|
7
9
|
Works with both **Expo** and **bare React Native** apps.
|
|
@@ -134,18 +136,22 @@ function UpdateChecker() {
|
|
|
134
136
|
```tsx
|
|
135
137
|
const {
|
|
136
138
|
// State
|
|
139
|
+
status, // UpdateStatus - current status
|
|
137
140
|
isChecking, // boolean - checking for updates
|
|
138
141
|
isDownloading, // boolean - downloading update
|
|
139
142
|
isApplying, // boolean - applying update
|
|
140
|
-
downloadProgress, //
|
|
141
|
-
|
|
143
|
+
downloadProgress, // DownloadProgress | null - download progress
|
|
144
|
+
updateInfo, // UpdateInfo | null - available update info
|
|
142
145
|
error, // Error | null - last error
|
|
146
|
+
isDismissed, // boolean - whether user dismissed the update
|
|
143
147
|
|
|
144
148
|
// Actions
|
|
145
149
|
checkForUpdate, // () => Promise<UpdateInfo | null>
|
|
146
150
|
downloadUpdate, // () => Promise<void>
|
|
147
|
-
applyUpdate, // () => Promise<void>
|
|
148
|
-
|
|
151
|
+
applyUpdate, // (restartApp?: boolean) => Promise<void>
|
|
152
|
+
clearPendingUpdate, // () => Promise<void>
|
|
153
|
+
dismissUpdate, // () => void - dismiss update notification
|
|
154
|
+
resetDismiss, // () => void - reset dismiss state
|
|
149
155
|
} = useOTAUpdate();
|
|
150
156
|
```
|
|
151
157
|
|
|
@@ -198,19 +204,52 @@ Handle mandatory updates that can't be skipped:
|
|
|
198
204
|
|
|
199
205
|
```tsx
|
|
200
206
|
function App() {
|
|
201
|
-
const {
|
|
207
|
+
const { updateInfo, downloadAndApply } = useOTAUpdate();
|
|
202
208
|
|
|
203
209
|
useEffect(() => {
|
|
204
|
-
if (
|
|
210
|
+
if (updateInfo?.isMandatory) {
|
|
205
211
|
// Force update for mandatory releases
|
|
206
212
|
downloadAndApply();
|
|
207
213
|
}
|
|
208
|
-
}, [
|
|
214
|
+
}, [updateInfo]);
|
|
209
215
|
|
|
210
216
|
return <YourApp />;
|
|
211
217
|
}
|
|
212
218
|
```
|
|
213
219
|
|
|
220
|
+
## Dismissable Update Banner
|
|
221
|
+
|
|
222
|
+
Allow users to dismiss optional updates:
|
|
223
|
+
|
|
224
|
+
```tsx
|
|
225
|
+
function UpdateBanner() {
|
|
226
|
+
const { updateInfo, isDismissed, dismissUpdate, downloadAndApply, isDownloading } = useOTAUpdate();
|
|
227
|
+
|
|
228
|
+
// Don't show if no update or user dismissed
|
|
229
|
+
if (!updateInfo || isDismissed) {
|
|
230
|
+
return null;
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
// Force mandatory updates (can't dismiss)
|
|
234
|
+
if (updateInfo.isMandatory) {
|
|
235
|
+
return (
|
|
236
|
+
<View>
|
|
237
|
+
<Text>Required update: v{updateInfo.version}</Text>
|
|
238
|
+
<Button title="Update Now" onPress={downloadAndApply} />
|
|
239
|
+
</View>
|
|
240
|
+
);
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
return (
|
|
244
|
+
<View>
|
|
245
|
+
<Text>Update available: v{updateInfo.version}</Text>
|
|
246
|
+
<Button title="Update" onPress={downloadAndApply} disabled={isDownloading} />
|
|
247
|
+
<Button title="Later" onPress={dismissUpdate} />
|
|
248
|
+
</View>
|
|
249
|
+
);
|
|
250
|
+
}
|
|
251
|
+
```
|
|
252
|
+
|
|
214
253
|
## Error Handling
|
|
215
254
|
|
|
216
255
|
```tsx
|
|
@@ -264,6 +303,42 @@ When you call `applyUpdate()` or the download completes:
|
|
|
264
303
|
|
|
265
304
|
> **Note**: OTA updates only work on EAS Build apps, not Expo Go, because Expo Go doesn't include the native module.
|
|
266
305
|
|
|
306
|
+
## Version Targeting
|
|
307
|
+
|
|
308
|
+
Target specific native app versions when publishing updates using the CLI:
|
|
309
|
+
|
|
310
|
+
```bash
|
|
311
|
+
# Only send updates to app versions >= 2.0.0
|
|
312
|
+
ota release --app my-app --min-app-version 2.0.0
|
|
313
|
+
|
|
314
|
+
# Only send updates to app versions between 2.0.0 and 2.5.0
|
|
315
|
+
ota release --app my-app --min-app-version 2.0.0 --max-app-version 2.5.0
|
|
316
|
+
```
|
|
317
|
+
|
|
318
|
+
This is useful when:
|
|
319
|
+
- You have breaking changes that only work with newer native builds
|
|
320
|
+
- You want to phase out support for older app versions
|
|
321
|
+
- Different native versions have different API requirements
|
|
322
|
+
|
|
323
|
+
## Recovering from Corrupted Updates
|
|
324
|
+
|
|
325
|
+
If an OTA update becomes corrupted (causing app crashes), you can clear it:
|
|
326
|
+
|
|
327
|
+
```tsx
|
|
328
|
+
import { UpdateStorage } from '@vanikya/ota-react-native';
|
|
329
|
+
|
|
330
|
+
// On app startup, check for and clear corrupted bundles
|
|
331
|
+
async function recoverFromCorruptedUpdate() {
|
|
332
|
+
const storage = new UpdateStorage();
|
|
333
|
+
const wasCorrupted = await storage.clearCorruptedBundle();
|
|
334
|
+
if (wasCorrupted) {
|
|
335
|
+
console.log('Cleared corrupted OTA bundle, app will use built-in bundle');
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
```
|
|
339
|
+
|
|
340
|
+
The SDK now validates downloaded bundles to prevent HTML error pages or corrupted files from being saved as bundles.
|
|
341
|
+
|
|
267
342
|
## License
|
|
268
343
|
|
|
269
344
|
MIT
|
|
@@ -5,6 +5,10 @@ import android.content.SharedPreferences
|
|
|
5
5
|
import android.util.Base64
|
|
6
6
|
import com.facebook.react.bridge.*
|
|
7
7
|
import java.io.File
|
|
8
|
+
import java.io.FileOutputStream
|
|
9
|
+
import java.io.InputStream
|
|
10
|
+
import java.net.HttpURLConnection
|
|
11
|
+
import java.net.URL
|
|
8
12
|
import java.security.MessageDigest
|
|
9
13
|
|
|
10
14
|
class OTAUpdateModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaModule(reactContext) {
|
|
@@ -92,6 +96,65 @@ class OTAUpdateModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
|
92
96
|
}
|
|
93
97
|
}
|
|
94
98
|
|
|
99
|
+
// Download file directly to disk - bypasses JS memory entirely
|
|
100
|
+
// This is critical for large bundles (5MB+)
|
|
101
|
+
@ReactMethod
|
|
102
|
+
fun downloadFile(urlString: String, destPath: String, promise: Promise) {
|
|
103
|
+
Thread {
|
|
104
|
+
var connection: HttpURLConnection? = null
|
|
105
|
+
var inputStream: InputStream? = null
|
|
106
|
+
var outputStream: FileOutputStream? = null
|
|
107
|
+
|
|
108
|
+
try {
|
|
109
|
+
val url = URL(urlString)
|
|
110
|
+
connection = url.openConnection() as HttpURLConnection
|
|
111
|
+
connection.connectTimeout = 30000
|
|
112
|
+
connection.readTimeout = 60000
|
|
113
|
+
connection.requestMethod = "GET"
|
|
114
|
+
connection.connect()
|
|
115
|
+
|
|
116
|
+
val responseCode = connection.responseCode
|
|
117
|
+
if (responseCode != HttpURLConnection.HTTP_OK) {
|
|
118
|
+
promise.reject("DOWNLOAD_ERROR", "Download failed with status $responseCode")
|
|
119
|
+
return@Thread
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
// Ensure parent directory exists
|
|
123
|
+
val destFile = File(destPath)
|
|
124
|
+
destFile.parentFile?.mkdirs()
|
|
125
|
+
|
|
126
|
+
inputStream = connection.inputStream
|
|
127
|
+
outputStream = FileOutputStream(destFile)
|
|
128
|
+
|
|
129
|
+
val buffer = ByteArray(8192) // 8KB buffer for efficient streaming
|
|
130
|
+
var bytesRead: Int
|
|
131
|
+
var totalBytesRead: Long = 0
|
|
132
|
+
|
|
133
|
+
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
|
134
|
+
outputStream.write(buffer, 0, bytesRead)
|
|
135
|
+
totalBytesRead += bytesRead
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
outputStream.flush()
|
|
139
|
+
|
|
140
|
+
val result = Arguments.createMap()
|
|
141
|
+
result.putDouble("fileSize", totalBytesRead.toDouble())
|
|
142
|
+
promise.resolve(result)
|
|
143
|
+
|
|
144
|
+
} catch (e: Exception) {
|
|
145
|
+
promise.reject("DOWNLOAD_ERROR", "Failed to download file: ${e.message}", e)
|
|
146
|
+
} finally {
|
|
147
|
+
try {
|
|
148
|
+
inputStream?.close()
|
|
149
|
+
outputStream?.close()
|
|
150
|
+
connection?.disconnect()
|
|
151
|
+
} catch (e: Exception) {
|
|
152
|
+
// Ignore cleanup errors
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
}.start()
|
|
156
|
+
}
|
|
157
|
+
|
|
95
158
|
// Cryptography
|
|
96
159
|
|
|
97
160
|
@ReactMethod
|
|
@@ -107,6 +170,37 @@ class OTAUpdateModule(reactContext: ReactApplicationContext) : ReactContextBaseJ
|
|
|
107
170
|
}
|
|
108
171
|
}
|
|
109
172
|
|
|
173
|
+
// Calculate SHA256 from file path - streams file to avoid memory issues
|
|
174
|
+
// Critical for large bundles (5MB+)
|
|
175
|
+
@ReactMethod
|
|
176
|
+
fun calculateSHA256FromFile(filePath: String, promise: Promise) {
|
|
177
|
+
Thread {
|
|
178
|
+
try {
|
|
179
|
+
val file = File(filePath)
|
|
180
|
+
if (!file.exists()) {
|
|
181
|
+
promise.reject("FILE_ERROR", "File not found: $filePath")
|
|
182
|
+
return@Thread
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
val digest = MessageDigest.getInstance("SHA-256")
|
|
186
|
+
val buffer = ByteArray(8192) // 8KB buffer
|
|
187
|
+
var bytesRead: Int
|
|
188
|
+
|
|
189
|
+
file.inputStream().use { inputStream ->
|
|
190
|
+
while (inputStream.read(buffer).also { bytesRead = it } != -1) {
|
|
191
|
+
digest.update(buffer, 0, bytesRead)
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
val hash = digest.digest()
|
|
196
|
+
val hexString = hash.joinToString("") { "%02x".format(it) }
|
|
197
|
+
promise.resolve(hexString)
|
|
198
|
+
} catch (e: Exception) {
|
|
199
|
+
promise.reject("HASH_ERROR", "Failed to calculate hash: ${e.message}", e)
|
|
200
|
+
}
|
|
201
|
+
}.start()
|
|
202
|
+
}
|
|
203
|
+
|
|
110
204
|
@ReactMethod
|
|
111
205
|
fun verifySignature(base64Content: String, signatureHex: String, publicKeyHex: String, promise: Promise) {
|
|
112
206
|
// Ed25519 signature verification
|
package/ios/OTAUpdate.m
CHANGED
|
@@ -35,11 +35,20 @@ RCT_EXTERN_METHOD(makeDirectory:(NSString *)path
|
|
|
35
35
|
resolver:(RCTPromiseResolveBlock)resolver
|
|
36
36
|
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
37
37
|
|
|
38
|
+
RCT_EXTERN_METHOD(downloadFile:(NSString *)urlString
|
|
39
|
+
destPath:(NSString *)destPath
|
|
40
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
41
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
42
|
+
|
|
38
43
|
// Cryptography
|
|
39
44
|
RCT_EXTERN_METHOD(calculateSHA256:(NSString *)base64Content
|
|
40
45
|
resolver:(RCTPromiseResolveBlock)resolver
|
|
41
46
|
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
42
47
|
|
|
48
|
+
RCT_EXTERN_METHOD(calculateSHA256FromFile:(NSString *)filePath
|
|
49
|
+
resolver:(RCTPromiseResolveBlock)resolver
|
|
50
|
+
rejecter:(RCTPromiseRejectBlock)rejecter)
|
|
51
|
+
|
|
43
52
|
RCT_EXTERN_METHOD(verifySignature:(NSString *)base64Content
|
|
44
53
|
signatureHex:(NSString *)signatureHex
|
|
45
54
|
publicKeyHex:(NSString *)publicKeyHex
|
package/ios/OTAUpdate.swift
CHANGED
|
@@ -85,6 +85,70 @@ class OTAUpdate: NSObject {
|
|
|
85
85
|
}
|
|
86
86
|
}
|
|
87
87
|
|
|
88
|
+
// Download file directly to disk - bypasses JS memory entirely
|
|
89
|
+
// This is critical for large bundles (5MB+)
|
|
90
|
+
@objc
|
|
91
|
+
func downloadFile(_ urlString: String, destPath: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
92
|
+
guard let url = URL(string: urlString) else {
|
|
93
|
+
rejecter("DOWNLOAD_ERROR", "Invalid URL: \(urlString)", nil)
|
|
94
|
+
return
|
|
95
|
+
}
|
|
96
|
+
|
|
97
|
+
let destURL = URL(fileURLWithPath: destPath)
|
|
98
|
+
|
|
99
|
+
// Ensure parent directory exists
|
|
100
|
+
let parentDir = destURL.deletingLastPathComponent()
|
|
101
|
+
do {
|
|
102
|
+
try FileManager.default.createDirectory(at: parentDir, withIntermediateDirectories: true, attributes: nil)
|
|
103
|
+
} catch {
|
|
104
|
+
rejecter("DOWNLOAD_ERROR", "Failed to create directory: \(error.localizedDescription)", error)
|
|
105
|
+
return
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
let task = URLSession.shared.downloadTask(with: url) { tempURL, response, error in
|
|
109
|
+
if let error = error {
|
|
110
|
+
rejecter("DOWNLOAD_ERROR", "Download failed: \(error.localizedDescription)", error)
|
|
111
|
+
return
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
guard let httpResponse = response as? HTTPURLResponse else {
|
|
115
|
+
rejecter("DOWNLOAD_ERROR", "Invalid response", nil)
|
|
116
|
+
return
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
guard httpResponse.statusCode == 200 else {
|
|
120
|
+
rejecter("DOWNLOAD_ERROR", "Download failed with status \(httpResponse.statusCode)", nil)
|
|
121
|
+
return
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
guard let tempURL = tempURL else {
|
|
125
|
+
rejecter("DOWNLOAD_ERROR", "No temporary file created", nil)
|
|
126
|
+
return
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
do {
|
|
130
|
+
// Remove existing file if it exists
|
|
131
|
+
if FileManager.default.fileExists(atPath: destPath) {
|
|
132
|
+
try FileManager.default.removeItem(atPath: destPath)
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
// Move downloaded file to destination
|
|
136
|
+
try FileManager.default.moveItem(at: tempURL, to: destURL)
|
|
137
|
+
|
|
138
|
+
// Get file size
|
|
139
|
+
let attributes = try FileManager.default.attributesOfItem(atPath: destPath)
|
|
140
|
+
let fileSize = attributes[.size] as? Int64 ?? 0
|
|
141
|
+
|
|
142
|
+
let result: [String: Any] = ["fileSize": fileSize]
|
|
143
|
+
resolver(result)
|
|
144
|
+
} catch {
|
|
145
|
+
rejecter("DOWNLOAD_ERROR", "Failed to save file: \(error.localizedDescription)", error)
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
task.resume()
|
|
150
|
+
}
|
|
151
|
+
|
|
88
152
|
// MARK: - Cryptography
|
|
89
153
|
|
|
90
154
|
@objc
|
|
@@ -103,6 +167,48 @@ class OTAUpdate: NSObject {
|
|
|
103
167
|
resolver(hexString)
|
|
104
168
|
}
|
|
105
169
|
|
|
170
|
+
// Calculate SHA256 from file path - streams file to avoid memory issues
|
|
171
|
+
// Critical for large bundles (5MB+)
|
|
172
|
+
@objc
|
|
173
|
+
func calculateSHA256FromFile(_ filePath: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
174
|
+
DispatchQueue.global(qos: .userInitiated).async {
|
|
175
|
+
guard FileManager.default.fileExists(atPath: filePath) else {
|
|
176
|
+
rejecter("FILE_ERROR", "File not found: \(filePath)", nil)
|
|
177
|
+
return
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
guard let inputStream = InputStream(fileAtPath: filePath) else {
|
|
181
|
+
rejecter("FILE_ERROR", "Could not open file: \(filePath)", nil)
|
|
182
|
+
return
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
inputStream.open()
|
|
186
|
+
defer { inputStream.close() }
|
|
187
|
+
|
|
188
|
+
var context = CC_SHA256_CTX()
|
|
189
|
+
CC_SHA256_Init(&context)
|
|
190
|
+
|
|
191
|
+
let bufferSize = 8192 // 8KB buffer
|
|
192
|
+
var buffer = [UInt8](repeating: 0, count: bufferSize)
|
|
193
|
+
|
|
194
|
+
while inputStream.hasBytesAvailable {
|
|
195
|
+
let bytesRead = inputStream.read(&buffer, maxLength: bufferSize)
|
|
196
|
+
if bytesRead > 0 {
|
|
197
|
+
CC_SHA256_Update(&context, buffer, CC_LONG(bytesRead))
|
|
198
|
+
} else if bytesRead < 0 {
|
|
199
|
+
rejecter("READ_ERROR", "Error reading file", inputStream.streamError)
|
|
200
|
+
return
|
|
201
|
+
}
|
|
202
|
+
}
|
|
203
|
+
|
|
204
|
+
var hash = [UInt8](repeating: 0, count: Int(CC_SHA256_DIGEST_LENGTH))
|
|
205
|
+
CC_SHA256_Final(&hash, &context)
|
|
206
|
+
|
|
207
|
+
let hexString = hash.map { String(format: "%02x", $0) }.joined()
|
|
208
|
+
resolver(hexString)
|
|
209
|
+
}
|
|
210
|
+
}
|
|
211
|
+
|
|
106
212
|
@objc
|
|
107
213
|
func verifySignature(_ base64Content: String, signatureHex: String, publicKeyHex: String, resolver: @escaping RCTPromiseResolveBlock, rejecter: @escaping RCTPromiseRejectBlock) {
|
|
108
214
|
// Ed25519 signature verification
|
|
@@ -8,7 +8,6 @@ var _react = require("react");
|
|
|
8
8
|
var _reactNative = require("react-native");
|
|
9
9
|
var _api = require("../utils/api");
|
|
10
10
|
var _storage = require("../utils/storage");
|
|
11
|
-
var _verification = require("../utils/verification");
|
|
12
11
|
// Generate or get device ID
|
|
13
12
|
async function getDeviceId() {
|
|
14
13
|
// Try to get from native module or AsyncStorage
|
|
@@ -32,6 +31,7 @@ function useOTAUpdate(config) {
|
|
|
32
31
|
const [downloadProgress, setDownloadProgress] = (0, _react.useState)(null);
|
|
33
32
|
const [error, setError] = (0, _react.useState)(null);
|
|
34
33
|
const [currentVersion, setCurrentVersion] = (0, _react.useState)(null);
|
|
34
|
+
const [isDismissed, setIsDismissed] = (0, _react.useState)(false);
|
|
35
35
|
const apiClient = (0, _react.useRef)(new _api.OTAApiClient(serverUrl));
|
|
36
36
|
const storage = (0, _react.useRef)(new _storage.UpdateStorage());
|
|
37
37
|
const deviceIdRef = (0, _react.useRef)(null);
|
|
@@ -83,6 +83,11 @@ function useOTAUpdate(config) {
|
|
|
83
83
|
isMandatory: response.release.isMandatory,
|
|
84
84
|
releaseNotes: response.release.releaseNotes
|
|
85
85
|
};
|
|
86
|
+
|
|
87
|
+
// Reset dismiss state if this is a different version than what was previously dismissed
|
|
88
|
+
if (!updateInfo || updateInfo.version !== info.version) {
|
|
89
|
+
setIsDismissed(false);
|
|
90
|
+
}
|
|
86
91
|
setUpdateInfo(info);
|
|
87
92
|
setStatus('available');
|
|
88
93
|
return info;
|
|
@@ -119,23 +124,36 @@ function useOTAUpdate(config) {
|
|
|
119
124
|
deviceInfo: (0, _api.getDeviceInfo)()
|
|
120
125
|
});
|
|
121
126
|
|
|
122
|
-
// Download bundle
|
|
123
|
-
const
|
|
127
|
+
// Download bundle directly to file (bypasses JS memory - critical for large bundles)
|
|
128
|
+
const downloadResult = await storage.current.downloadBundleToFile(release.bundleUrl, release.id);
|
|
124
129
|
setDownloadProgress({
|
|
125
|
-
downloadedBytes:
|
|
130
|
+
downloadedBytes: downloadResult.fileSize,
|
|
126
131
|
totalBytes: release.bundleSize,
|
|
127
132
|
percentage: 100
|
|
128
133
|
});
|
|
129
134
|
|
|
130
|
-
// Verify bundle
|
|
135
|
+
// Verify bundle hash
|
|
131
136
|
setStatus('verifying');
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
137
|
+
|
|
138
|
+
// Calculate hash from file (streaming to avoid memory issues)
|
|
139
|
+
const actualHash = await storage.current.calculateBundleHash(release.id);
|
|
140
|
+
const expectedHashWithoutPrefix = release.bundleHash.replace(/^sha256:/, '');
|
|
141
|
+
if (actualHash !== expectedHashWithoutPrefix) {
|
|
142
|
+
// Delete corrupted bundle
|
|
143
|
+
await storage.current.deleteBundle(release.id);
|
|
144
|
+
throw new Error(`Bundle hash mismatch: expected ${expectedHashWithoutPrefix}, got ${actualHash}`);
|
|
135
145
|
}
|
|
136
146
|
|
|
137
|
-
//
|
|
138
|
-
const
|
|
147
|
+
// Validate bundle content (check it's actually JavaScript, not an error page)
|
|
148
|
+
const isValid = await storage.current.validateBundle(release.id);
|
|
149
|
+
if (!isValid) {
|
|
150
|
+
await storage.current.deleteBundle(release.id);
|
|
151
|
+
throw new Error('Downloaded content is not a valid JavaScript bundle');
|
|
152
|
+
}
|
|
153
|
+
if (__DEV__) {
|
|
154
|
+
console.log('[OTAUpdate] Bundle verified successfully');
|
|
155
|
+
}
|
|
156
|
+
const bundlePath = downloadResult.path;
|
|
139
157
|
|
|
140
158
|
// Save metadata
|
|
141
159
|
await storage.current.saveMetadata({
|
|
@@ -254,6 +272,16 @@ function useOTAUpdate(config) {
|
|
|
254
272
|
setStatus('idle');
|
|
255
273
|
}, []);
|
|
256
274
|
|
|
275
|
+
// Dismiss the update notification (user can hide the banner)
|
|
276
|
+
const dismissUpdate = (0, _react.useCallback)(() => {
|
|
277
|
+
setIsDismissed(true);
|
|
278
|
+
}, []);
|
|
279
|
+
|
|
280
|
+
// Reset dismiss state (useful when a new update is found)
|
|
281
|
+
const resetDismiss = (0, _react.useCallback)(() => {
|
|
282
|
+
setIsDismissed(false);
|
|
283
|
+
}, []);
|
|
284
|
+
|
|
257
285
|
// Check on mount
|
|
258
286
|
(0, _react.useEffect)(() => {
|
|
259
287
|
if (checkOnMount) {
|
|
@@ -280,10 +308,13 @@ function useOTAUpdate(config) {
|
|
|
280
308
|
downloadProgress,
|
|
281
309
|
error,
|
|
282
310
|
currentVersion,
|
|
311
|
+
isDismissed,
|
|
283
312
|
checkForUpdate,
|
|
284
313
|
downloadUpdate,
|
|
285
314
|
applyUpdate,
|
|
286
|
-
clearPendingUpdate
|
|
315
|
+
clearPendingUpdate,
|
|
316
|
+
dismissUpdate,
|
|
317
|
+
resetDismiss
|
|
287
318
|
};
|
|
288
319
|
}
|
|
289
320
|
//# sourceMappingURL=useOTAUpdate.js.map
|
|
@@ -1 +1 @@
|
|
|
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":[]}
|
|
1
|
+
{"version":3,"names":["_react","require","_reactNative","_api","_storage","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","isDismissed","setIsDismissed","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","downloadResult","downloadBundleToFile","bundleUrl","fileSize","actualHash","calculateBundleHash","expectedHashWithoutPrefix","bundleHash","replace","deleteBundle","isValid","validateBundle","__DEV__","console","log","bundlePath","path","saveMetadata","downloadedAt","Date","now","registered","registerBundleWithNative","errorMessage","message","applyUpdate","restartApp","clearPendingUpdate","clearMetadata","clearNativePendingBundle","dismissUpdate","resetDismiss","handleAppStateChange","nextAppState","subscription","AppState","addEventListener","remove"],"sourceRoot":"../../../src","sources":["hooks/useOTAUpdate.ts"],"mappings":"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","ignoreList":[]}
|
package/lib/commonjs/index.js
CHANGED
|
@@ -47,7 +47,59 @@ class OTAApiClient {
|
|
|
47
47
|
if (!response.ok) {
|
|
48
48
|
throw new Error(`Failed to download bundle: HTTP ${response.status}`);
|
|
49
49
|
}
|
|
50
|
-
|
|
50
|
+
|
|
51
|
+
// Validate content type if available
|
|
52
|
+
const contentType = response.headers.get('content-type');
|
|
53
|
+
if (contentType && contentType.includes('text/html')) {
|
|
54
|
+
throw new Error('Server returned HTML instead of JavaScript bundle. Check your server configuration.');
|
|
55
|
+
}
|
|
56
|
+
const data = await response.arrayBuffer();
|
|
57
|
+
|
|
58
|
+
// Basic validation: check if content looks like JavaScript
|
|
59
|
+
// JavaScript bundles typically start with specific patterns
|
|
60
|
+
if (!this.isValidJavaScriptBundle(data)) {
|
|
61
|
+
throw new Error('Downloaded content does not appear to be a valid JavaScript bundle');
|
|
62
|
+
}
|
|
63
|
+
return data;
|
|
64
|
+
}
|
|
65
|
+
isValidJavaScriptBundle(data) {
|
|
66
|
+
// Check minimum size (a valid bundle should be at least a few bytes)
|
|
67
|
+
if (data.byteLength < 10) {
|
|
68
|
+
return false;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
// Read first 1000 bytes as string to check content
|
|
72
|
+
const bytes = new Uint8Array(data, 0, Math.min(1000, data.byteLength));
|
|
73
|
+
let preview = '';
|
|
74
|
+
for (let i = 0; i < bytes.length; i++) {
|
|
75
|
+
preview += String.fromCharCode(bytes[i]);
|
|
76
|
+
}
|
|
77
|
+
const trimmed = preview.trim();
|
|
78
|
+
|
|
79
|
+
// Check for HTML indicators (common error page patterns)
|
|
80
|
+
if (trimmed.startsWith('<!DOCTYPE') || trimmed.startsWith('<!doctype') || trimmed.startsWith('<html') || trimmed.startsWith('<HTML') || trimmed.includes('<head>') || trimmed.includes('<body>')) {
|
|
81
|
+
return false;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
// JavaScript bundles typically start with:
|
|
85
|
+
// - var, let, const (variable declarations)
|
|
86
|
+
// - (function or !function (IIFEs)
|
|
87
|
+
// - "use strict"
|
|
88
|
+
// - Object.defineProperty (common in transpiled code)
|
|
89
|
+
// - __d( (Metro bundler format)
|
|
90
|
+
// - Comments: // or /*
|
|
91
|
+
const jsPatterns = [/^var\s/, /^let\s/, /^const\s/, /^\(function/, /^!function/, /^["']use strict["']/, /^Object\.defineProperty/, /^__d\(/, /^\/[/*]/, /^"use strict"/, /^__BUNDLE_START_TIME__/];
|
|
92
|
+
for (const pattern of jsPatterns) {
|
|
93
|
+
if (pattern.test(trimmed)) {
|
|
94
|
+
return true;
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// Also accept if it contains common JS tokens (for minified bundles)
|
|
99
|
+
if (trimmed.includes('function') || trimmed.includes('exports') || trimmed.includes('require(') || trimmed.includes('__d(')) {
|
|
100
|
+
return true;
|
|
101
|
+
}
|
|
102
|
+
return false;
|
|
51
103
|
}
|
|
52
104
|
}
|
|
53
105
|
exports.OTAApiClient = OTAApiClient;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["_reactNative","require","OTAApiClient","constructor","serverUrl","replace","checkUpdate","request","response","fetch","method","headers","body","JSON","stringify","ok","error","json","catch","Error","status","reportEvent","__DEV__","console","warn","downloadBundle","bundleUrl","arrayBuffer","exports","getDeviceInfo","os","Platform","OS","osVersion","Version","toString"],"sourceRoot":"../../../src","sources":["utils/api.ts"],"mappings":";;;;;;;AAAA,IAAAA,YAAA,GAAAC,OAAA;AAyCO,MAAMC,YAAY,CAAC;EAGxBC,WAAWA,CAACC,SAAiB,EAAE;IAC7B,IAAI,CAACA,SAAS,GAAGA,SAAS,CAACC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,CAAC;EACjD;EAEA,MAAMC,WAAWA,CAACC,OAA2B,EAAgC;IAC3E,MAAMC,QAAQ,GAAG,MAAMC,KAAK,CAAC,GAAG,IAAI,CAACL,SAAS,sBAAsB,EAAE;MACpEM,MAAM,EAAE,MAAM;MACdC,OAAO,EAAE;QACP,cAAc,EAAE;MAClB,CAAC;MACDC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAACP,OAAO;IAC9B,CAAC,CAAC;IAEF,IAAI,CAACC,QAAQ,CAACO,EAAE,EAAE;MAChB,MAAMC,KAAK,GAAG,MAAMR,QAAQ,CAACS,IAAI,CAAC,CAAC,CAACC,KAAK,CAAC,OAAO;QAAEF,KAAK,EAAE;MAAgB,CAAC,CAAC,CAAC;MAC7E,MAAM,IAAIG,KAAK,CAAEH,KAAK,CAAuBA,KAAK,IAAI,QAAQR,QAAQ,CAACY,MAAM,EAAE,CAAC;IAClF;IAEA,OAAOZ,QAAQ,CAACS,IAAI,CAAC,CAAC;EACxB;EAEA,MAAMI,WAAWA,CAACd,OAA2B,EAAiB;IAC5D,IAAI;MACF,MAAME,KAAK,CAAC,GAAG,IAAI,CAACL,SAAS,sBAAsB,EAAE;QACnDM,MAAM,EAAE,MAAM;QACdC,OAAO,EAAE;UACP,cAAc,EAAE;QAClB,CAAC;QACDC,IAAI,EAAEC,IAAI,CAACC,SAAS,CAACP,OAAO;MAC9B,CAAC,CAAC;IACJ,CAAC,CAAC,OAAOS,KAAK,EAAE;MACd;MACA,IAAIM,OAAO,EAAE;QACXC,OAAO,CAACC,IAAI,CAAC,qCAAqC,EAAER,KAAK,CAAC;MAC5D;IACF;EACF;EAEA,MAAMS,cAAcA,CAACC,SAAiB,EAAwB;IAC5D,MAAMlB,QAAQ,GAAG,MAAMC,KAAK,CAACiB,SAAS,CAAC;IAEvC,IAAI,CAAClB,QAAQ,CAACO,EAAE,EAAE;MAChB,MAAM,IAAII,KAAK,CAAC,mCAAmCX,QAAQ,CAACY,MAAM,EAAE,CAAC;IACvE;IAEA,
|
|
1
|
+
{"version":3,"names":["_reactNative","require","OTAApiClient","constructor","serverUrl","replace","checkUpdate","request","response","fetch","method","headers","body","JSON","stringify","ok","error","json","catch","Error","status","reportEvent","__DEV__","console","warn","downloadBundle","bundleUrl","contentType","get","includes","data","arrayBuffer","isValidJavaScriptBundle","byteLength","bytes","Uint8Array","Math","min","preview","i","length","String","fromCharCode","trimmed","trim","startsWith","jsPatterns","pattern","test","exports","getDeviceInfo","os","Platform","OS","osVersion","Version","toString"],"sourceRoot":"../../../src","sources":["utils/api.ts"],"mappings":"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","ignoreList":[]}
|