@hot-updater/react-native 1.0.0-rc.2 → 1.0.0-rc.22
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/android/proguard-rules.pro +17 -2
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +954 -837
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +15 -11
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +287 -22
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +43 -31
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +37 -54
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
- package/android/src/main/java/com/hotupdater/InstallIdentityService.kt +37 -0
- package/android/src/main/java/com/hotupdater/KeyValueStorageService.kt +86 -0
- package/android/src/main/java/com/hotupdater/NetworkState.kt +31 -0
- package/android/src/main/java/com/hotupdater/NoBackupStorage.kt +17 -0
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +127 -50
- package/android/src/main/java/com/hotupdater/PreviousProcessExit.kt +89 -0
- package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +34 -0
- package/android/src/main/java/com/hotupdater/TarArchiveInputStream.kt +214 -375
- package/android/src/main/java/com/hotupdater/TarBrArchiveExtractor.kt +119 -0
- package/android/src/newarch/HotUpdater.kt +7 -9
- package/android/src/newarch/HotUpdaterModule.kt +109 -84
- package/android/src/oldarch/HotUpdater.kt +7 -9
- package/android/src/oldarch/HotUpdaterModule.kt +98 -74
- package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +950 -1112
- package/ios/HotUpdater/Internal/BundleMetadata.swift +8 -53
- package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
- package/ios/HotUpdater/Internal/FileUtilities.swift +64 -0
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +0 -1
- package/ios/HotUpdater/Internal/HotUpdater.mm +13 -45
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +190 -73
- package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
- package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
- package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +119 -71
- package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.h +16 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecovery.mm +83 -0
- package/ios/HotUpdater/Recovery/HotUpdaterRecoveryHooks.mm +49 -0
- package/lib/commonjs/appReady.js +111 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +125 -70
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/clientPlugin.js +13 -0
- package/lib/commonjs/clientPlugin.js.map +1 -0
- package/lib/commonjs/error.js +4 -13
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/fetchJSON.js +5 -2
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/httpClient.js +55 -92
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +68 -20
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +82 -62
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/pluginHost.js +44 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +20 -61
- package/lib/commonjs/releaseCatalogCache.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/sdkVersion.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/store.js +3 -10
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/updateError.js +132 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/wrap.js +44 -27
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/appReady.js +103 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/checkForUpdate.js +118 -65
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/clientPlugin.js +4 -0
- package/lib/module/clientPlugin.js.map +1 -0
- package/lib/module/error.js +4 -13
- package/lib/module/error.js.map +1 -1
- package/lib/module/fetchJSON.js +3 -1
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/httpClient.js +53 -90
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +55 -22
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +74 -54
- package/lib/module/native.js.map +1 -1
- package/lib/module/pluginHost.js +35 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +16 -56
- package/lib/module/releaseCatalogCache.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/sdkVersion.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/store.js +3 -10
- package/lib/module/store.js.map +1 -1
- package/lib/module/updateError.js +126 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/wrap.js +45 -28
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +23 -0
- package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +16 -4
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/clientPlugin.d.ts +2 -0
- package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/commonjs/error.d.ts +4 -13
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +3 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +3 -32
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +7 -12
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +33 -23
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +4 -0
- package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +6 -14
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +42 -47
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +1 -3
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +1 -1
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/updateError.d.ts +26 -0
- package/lib/typescript/commonjs/updateError.d.ts.map +1 -0
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +6 -7
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/appReady.d.ts +23 -0
- package/lib/typescript/module/appReady.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +16 -4
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/clientPlugin.d.ts +2 -0
- package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/module/error.d.ts +4 -13
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +3 -0
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +3 -32
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +7 -12
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +33 -23
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +4 -0
- package/lib/typescript/module/pluginHost.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +6 -14
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +42 -47
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +1 -3
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +1 -1
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/updateError.d.ts +26 -0
- package/lib/typescript/module/updateError.d.ts.map +1 -0
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +6 -7
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +7 -4
- package/src/appReady.ts +149 -0
- package/src/checkForUpdate.ts +152 -89
- package/src/clientPlugin.ts +17 -0
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +5 -1
- package/src/httpClient.ts +78 -157
- package/src/index.ts +87 -29
- package/src/native.ts +109 -104
- package/src/pluginHost.ts +45 -0
- package/src/releaseCatalogCache.ts +26 -140
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +41 -48
- package/src/store.ts +2 -23
- package/src/types.ts +1 -1
- package/src/updateError.ts +153 -0
- package/src/wrap.tsx +59 -28
- package/src/wrap.types.ts +6 -7
- package/android/src/main/java/com/hotupdater/DecompressService.kt +0 -89
- package/android/src/main/java/com/hotupdater/DecompressionStrategy.kt +0 -26
- package/android/src/main/java/com/hotupdater/TarBrDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/TarGzDecompressionStrategy.kt +0 -117
- package/android/src/main/java/com/hotupdater/ZipDecompressionStrategy.kt +0 -192
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +0 -46
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +0 -799
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +0 -273
- package/android/src/test/java/com/hotupdater/NativeConfigUtilsTest.kt +0 -20
- package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +0 -111
- package/android/src/test/java/com/hotupdater/RelativePathResolverTest.kt +0 -41
- package/android/src/test/java/com/hotupdater/ReleaseCatalogCacheServiceTest.kt +0 -118
- package/android/src/test/java/com/hotupdater/TarArchiveInputStreamTest.kt +0 -68
- package/ios/HotUpdater/Internal/ArchiveExtractionUtilities.swift +0 -178
- package/ios/HotUpdater/Internal/DecompressService.swift +0 -112
- package/ios/HotUpdater/Internal/DecompressionStrategy.swift +0 -22
- package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +0 -370
- package/ios/HotUpdater/Internal/TarBrDecompressionStrategy.swift +0 -39
- package/ios/HotUpdater/Internal/TarGzDecompressionStrategy.swift +0 -59
- package/ios/HotUpdater/Internal/ZipArchiveExtractor.swift +0 -482
- package/ios/HotUpdater/Internal/ZipDecompressionStrategy.swift +0 -56
- package/lib/commonjs/catalogCacheNative.spec.js +0 -31
- package/lib/commonjs/catalogCacheNative.spec.js.map +0 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +0 -604
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/commonjs/httpClient.spec.js +0 -102
- package/lib/commonjs/httpClient.spec.js.map +0 -1
- package/lib/commonjs/index.spec.js +0 -298
- package/lib/commonjs/index.spec.js.map +0 -1
- package/lib/commonjs/iosInterop.spec.js +0 -18
- package/lib/commonjs/iosInterop.spec.js.map +0 -1
- package/lib/commonjs/native.spec.js +0 -795
- package/lib/commonjs/native.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -218
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.js +0 -133
- package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -246
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js +0 -24
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -117
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCache.spec.js +0 -195
- package/lib/commonjs/releaseCatalogCache.spec.js.map +0 -1
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/commonjs/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/commonjs/store.notification.spec.js +0 -76
- package/lib/commonjs/store.notification.spec.js.map +0 -1
- package/lib/commonjs/store.spec.js +0 -316
- package/lib/commonjs/store.spec.js.map +0 -1
- package/lib/commonjs/wrap.spec.js +0 -296
- package/lib/commonjs/wrap.spec.js.map +0 -1
- package/lib/module/catalogCacheNative.spec.js +0 -31
- package/lib/module/catalogCacheNative.spec.js.map +0 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +0 -603
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +0 -1
- package/lib/module/httpClient.spec.js +0 -102
- package/lib/module/httpClient.spec.js.map +0 -1
- package/lib/module/index.spec.js +0 -297
- package/lib/module/index.spec.js.map +0 -1
- package/lib/module/iosInterop.spec.js +0 -18
- package/lib/module/iosInterop.spec.js.map +0 -1
- package/lib/module/native.spec.js +0 -794
- package/lib/module/native.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -217
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.js +0 -128
- package/lib/module/notifyAppReadyInsights.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.spec.js +0 -245
- package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.test-utils.js +0 -18
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -116
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/module/releaseCatalogCache.spec.js +0 -195
- package/lib/module/releaseCatalogCache.spec.js.map +0 -1
- package/lib/module/releaseCatalogCacheNativeContract.spec.js +0 -64
- package/lib/module/releaseCatalogCacheNativeContract.spec.js.map +0 -1
- package/lib/module/store.notification.spec.js +0 -77
- package/lib/module/store.notification.spec.js.map +0 -1
- package/lib/module/store.spec.js +0 -315
- package/lib/module/store.spec.js.map +0 -1
- package/lib/module/wrap.spec.js +0 -295
- package/lib/module/wrap.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +0 -13
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +0 -1
- package/src/catalogCacheNative.spec.ts +0 -63
- package/src/checkForUpdate.releaseCatalog.spec.ts +0 -596
- package/src/httpClient.spec.ts +0 -132
- package/src/index.spec.ts +0 -331
- package/src/iosInterop.spec.ts +0 -30
- package/src/native.spec.ts +0 -855
- package/src/notifyAppReadyInsights.boundary.spec.ts +0 -234
- package/src/notifyAppReadyInsights.spec.ts +0 -243
- package/src/notifyAppReadyInsights.test-utils.ts +0 -31
- package/src/notifyAppReadyInsights.transport.spec.ts +0 -130
- package/src/notifyAppReadyInsights.ts +0 -194
- package/src/releaseCatalogCache.spec.ts +0 -282
- package/src/releaseCatalogCacheNativeContract.spec.ts +0 -80
- package/src/store.notification.spec.ts +0 -92
- package/src/store.spec.ts +0 -372
- package/src/wrap.spec.ts +0 -367
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import com.hotupdater.vendor.brotli.dec.BrotliInputStream
|
|
4
|
+
import java.io.File
|
|
5
|
+
import java.io.FileInputStream
|
|
6
|
+
import java.io.IOException
|
|
7
|
+
import java.io.InputStream
|
|
8
|
+
|
|
9
|
+
internal object TarBrArchiveExtractor {
|
|
10
|
+
fun extract(
|
|
11
|
+
archiveFile: File,
|
|
12
|
+
destination: File,
|
|
13
|
+
expectedTarByteSize: Long,
|
|
14
|
+
expectedFiles: Map<String, Long>,
|
|
15
|
+
) {
|
|
16
|
+
require(expectedTarByteSize >= 0) { "Invalid TAR byte size" }
|
|
17
|
+
if (destination.exists() && !destination.deleteRecursively()) {
|
|
18
|
+
throw IOException("Cannot clear archive extraction directory")
|
|
19
|
+
}
|
|
20
|
+
if (!destination.mkdirs()) throw IOException("Cannot create archive extraction directory")
|
|
21
|
+
|
|
22
|
+
try {
|
|
23
|
+
FileInputStream(archiveFile).use { compressedInput ->
|
|
24
|
+
BrotliInputStream(compressedInput).use { brotliInput ->
|
|
25
|
+
val boundedInput = ExactSizeInputStream(brotliInput, expectedTarByteSize)
|
|
26
|
+
TarArchiveInputStream(boundedInput).use { tarInput ->
|
|
27
|
+
val extractedPaths = linkedSetOf<String>()
|
|
28
|
+
var entry = tarInput.getNextEntry()
|
|
29
|
+
while (entry != null) {
|
|
30
|
+
if (!entry.isRegularFile) {
|
|
31
|
+
throw IOException("Unsupported TAR entry type for ${entry.name}")
|
|
32
|
+
}
|
|
33
|
+
val normalizedPath = RelativePathResolver.normalizeRelativePath(entry.name)
|
|
34
|
+
if (normalizedPath == null || normalizedPath != entry.name) {
|
|
35
|
+
throw IOException("Unsafe TAR entry path: ${entry.name}")
|
|
36
|
+
}
|
|
37
|
+
val expectedSize =
|
|
38
|
+
expectedFiles[normalizedPath]
|
|
39
|
+
?: throw IOException("Unexpected TAR entry: $normalizedPath")
|
|
40
|
+
if (!extractedPaths.add(normalizedPath)) {
|
|
41
|
+
throw IOException("Duplicate TAR entry: $normalizedPath")
|
|
42
|
+
}
|
|
43
|
+
if (entry.size != expectedSize) {
|
|
44
|
+
throw IOException("TAR entry size mismatch: $normalizedPath")
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
val outputFile =
|
|
48
|
+
RelativePathResolver.resolveInside(destination, normalizedPath)
|
|
49
|
+
?: throw IOException("Unsafe TAR entry path: $normalizedPath")
|
|
50
|
+
if (outputFile.exists()) throw IOException("TAR output already exists: $normalizedPath")
|
|
51
|
+
val parentDirectory = outputFile.parentFile
|
|
52
|
+
if (parentDirectory != null && !parentDirectory.isDirectory && !parentDirectory.mkdirs()) {
|
|
53
|
+
throw IOException("Cannot create TAR output directory: $normalizedPath")
|
|
54
|
+
}
|
|
55
|
+
outputFile.outputStream().use { output ->
|
|
56
|
+
val buffer = ByteArray(8192)
|
|
57
|
+
var written = 0L
|
|
58
|
+
while (true) {
|
|
59
|
+
val count = tarInput.read(buffer)
|
|
60
|
+
if (count < 0) break
|
|
61
|
+
output.write(buffer, 0, count)
|
|
62
|
+
written += count
|
|
63
|
+
}
|
|
64
|
+
if (written != expectedSize) {
|
|
65
|
+
throw IOException("TAR entry was truncated: $normalizedPath")
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
entry = tarInput.getNextEntry()
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
if (extractedPaths != expectedFiles.keys) {
|
|
72
|
+
throw IOException("TAR file set does not match manifest")
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
boundedInput.requireExactSize()
|
|
76
|
+
}
|
|
77
|
+
}
|
|
78
|
+
} catch (error: Throwable) {
|
|
79
|
+
destination.deleteRecursively()
|
|
80
|
+
throw error
|
|
81
|
+
}
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
private class ExactSizeInputStream(
|
|
85
|
+
private val input: InputStream,
|
|
86
|
+
private val expectedSize: Long,
|
|
87
|
+
) : InputStream() {
|
|
88
|
+
private var byteCount = 0L
|
|
89
|
+
|
|
90
|
+
override fun read(): Int {
|
|
91
|
+
val result = input.read()
|
|
92
|
+
if (result >= 0) recordRead(1)
|
|
93
|
+
return result
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
override fun read(
|
|
97
|
+
buffer: ByteArray,
|
|
98
|
+
offset: Int,
|
|
99
|
+
length: Int,
|
|
100
|
+
): Int {
|
|
101
|
+
val count = input.read(buffer, offset, length)
|
|
102
|
+
if (count > 0) recordRead(count.toLong())
|
|
103
|
+
return count
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
fun requireExactSize() {
|
|
107
|
+
if (byteCount != expectedSize) {
|
|
108
|
+
throw IOException("TAR stream size mismatch: expected $expectedSize, got $byteCount")
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
private fun recordRead(count: Long) {
|
|
113
|
+
if (byteCount > expectedSize - count) {
|
|
114
|
+
throw IOException("TAR stream exceeds declared size")
|
|
115
|
+
}
|
|
116
|
+
byteCount += count
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
}
|
|
@@ -36,7 +36,7 @@ class HotUpdater {
|
|
|
36
36
|
* Updates the bundle using the default singleton instance
|
|
37
37
|
* @param context Application context
|
|
38
38
|
* @param bundleId ID of the bundle to update
|
|
39
|
-
* @param
|
|
39
|
+
* @param params Manifest and asset descriptors for the target bundle
|
|
40
40
|
* @param fileHash Combined hash string for verification (sig:<signature> or <hex_hash>)
|
|
41
41
|
* @param progressCallback Callback for download progress updates
|
|
42
42
|
* @throws HotUpdaterException if the update fails
|
|
@@ -44,22 +44,20 @@ class HotUpdater {
|
|
|
44
44
|
suspend fun updateBundle(
|
|
45
45
|
context: Context,
|
|
46
46
|
bundleId: String,
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
manifestFileHash: String?,
|
|
51
|
-
changedAssets: Map<String, ChangedAssetDescriptor>?,
|
|
47
|
+
manifestUrl: String,
|
|
48
|
+
manifestFileHash: String,
|
|
49
|
+
assets: Map<String, ChangedAssetDescriptor>,
|
|
52
50
|
channel: String?,
|
|
51
|
+
archiveUrl: String? = null,
|
|
53
52
|
progressCallback: (UpdateProgressPayload) -> Unit,
|
|
54
53
|
) {
|
|
55
54
|
getInstance(context).updateBundle(
|
|
56
55
|
bundleId,
|
|
57
|
-
fileUrl,
|
|
58
|
-
fileHash,
|
|
59
56
|
manifestUrl,
|
|
60
57
|
manifestFileHash,
|
|
61
|
-
|
|
58
|
+
assets,
|
|
62
59
|
channel,
|
|
60
|
+
archiveUrl = archiveUrl,
|
|
63
61
|
progressCallback = progressCallback,
|
|
64
62
|
)
|
|
65
63
|
}
|
|
@@ -26,6 +26,16 @@ class HotUpdaterModule internal constructor(
|
|
|
26
26
|
|
|
27
27
|
override fun getName(): String = NAME
|
|
28
28
|
|
|
29
|
+
private fun readSafeInteger(
|
|
30
|
+
map: ReadableMap,
|
|
31
|
+
key: String,
|
|
32
|
+
): Long? {
|
|
33
|
+
if (!map.hasKey(key) || map.isNull(key)) return null
|
|
34
|
+
val value = runCatching { map.getDouble(key) }.getOrNull() ?: return null
|
|
35
|
+
if (!value.isFinite() || value % 1.0 != 0.0) return null
|
|
36
|
+
return value.toLong().takeIf { it in 0..9_007_199_254_740_991L }
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
override fun invalidate() {
|
|
30
40
|
super.invalidate()
|
|
31
41
|
// Cancel all ongoing coroutines when module is destroyed
|
|
@@ -37,12 +47,12 @@ class HotUpdaterModule internal constructor(
|
|
|
37
47
|
*/
|
|
38
48
|
private fun getInstance(): HotUpdaterImpl = HotUpdater.getInstance(mReactApplicationContext)
|
|
39
49
|
|
|
40
|
-
private fun
|
|
41
|
-
if (!params.hasKey("
|
|
50
|
+
private fun parseAssets(params: ReadableMap): Map<String, ChangedAssetDescriptor>? {
|
|
51
|
+
if (!params.hasKey("assets") || params.isNull("assets")) {
|
|
42
52
|
return null
|
|
43
53
|
}
|
|
44
54
|
|
|
45
|
-
val changedAssetsMap = params.getMap("
|
|
55
|
+
val changedAssetsMap = params.getMap("assets") ?: return null
|
|
46
56
|
val parsedAssets = linkedMapOf<String, ChangedAssetDescriptor>()
|
|
47
57
|
val iterator = changedAssetsMap.keySetIterator()
|
|
48
58
|
|
|
@@ -58,6 +68,7 @@ class HotUpdaterModule internal constructor(
|
|
|
58
68
|
val baseFileHash = patchMap.getString("baseFileHash")
|
|
59
69
|
val patchFileHash = patchMap.getString("patchFileHash")
|
|
60
70
|
val patchUrl = patchMap.getString("patchUrl")
|
|
71
|
+
val byteSize = readSafeInteger(patchMap, "byteSize")
|
|
61
72
|
|
|
62
73
|
if (
|
|
63
74
|
algorithm != null &&
|
|
@@ -72,6 +83,7 @@ class HotUpdaterModule internal constructor(
|
|
|
72
83
|
baseFileHash = baseFileHash,
|
|
73
84
|
patchFileHash = patchFileHash,
|
|
74
85
|
patchUrl = patchUrl,
|
|
86
|
+
byteSize = byteSize,
|
|
75
87
|
)
|
|
76
88
|
} else {
|
|
77
89
|
null
|
|
@@ -162,97 +174,112 @@ class HotUpdaterModule internal constructor(
|
|
|
162
174
|
try {
|
|
163
175
|
val bundleId = params.getString("bundleId")
|
|
164
176
|
if (bundleId == null || bundleId.isEmpty()) {
|
|
165
|
-
promise.
|
|
177
|
+
promise.rejectUpdateBundle(HotUpdaterException.missingBundleId())
|
|
166
178
|
return@launch
|
|
167
179
|
}
|
|
168
180
|
|
|
169
|
-
val
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
if (
|
|
181
|
+
val manifestUrl = params.getString("manifestUrl")
|
|
182
|
+
val manifestFileHash = params.getString("manifestFileHash")
|
|
183
|
+
val assets = parseAssets(params)
|
|
184
|
+
if (manifestUrl.isNullOrEmpty() || manifestFileHash.isNullOrEmpty() || assets == null) {
|
|
185
|
+
promise.rejectUpdateBundle(HotUpdaterException.invalidManifestParams())
|
|
186
|
+
return@launch
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
java.net.URL(manifestUrl)
|
|
190
|
+
} catch (e: java.net.MalformedURLException) {
|
|
191
|
+
promise.rejectUpdateBundle(
|
|
192
|
+
HotUpdaterException.invalidFileUrl("manifestUrl", manifestUrl, UpdateFailureResource.MANIFEST),
|
|
193
|
+
)
|
|
194
|
+
return@launch
|
|
195
|
+
}
|
|
196
|
+
val channel = params.getString("channel")
|
|
197
|
+
val archiveUrl =
|
|
198
|
+
if (params.hasKey("archiveUrl") && !params.isNull("archiveUrl")) {
|
|
199
|
+
params.getString("archiveUrl")
|
|
200
|
+
} else {
|
|
201
|
+
null
|
|
202
|
+
}
|
|
203
|
+
if (archiveUrl != null) {
|
|
173
204
|
try {
|
|
174
|
-
java.net.URL(
|
|
205
|
+
java.net.URL(archiveUrl)
|
|
175
206
|
} catch (e: java.net.MalformedURLException) {
|
|
176
|
-
promise.
|
|
207
|
+
promise.rejectUpdateBundle(
|
|
208
|
+
HotUpdaterException.invalidFileUrl("archiveUrl", archiveUrl, UpdateFailureResource.ARCHIVE),
|
|
209
|
+
)
|
|
177
210
|
return@launch
|
|
178
211
|
}
|
|
179
212
|
}
|
|
180
|
-
|
|
181
|
-
val fileHash = params.getString("fileHash")
|
|
182
|
-
val manifestUrl = params.getString("manifestUrl")
|
|
183
|
-
val manifestFileHash = params.getString("manifestFileHash")
|
|
184
|
-
val changedAssets = parseChangedAssets(params)
|
|
185
|
-
val channel = params.getString("channel")
|
|
186
213
|
val selection = parseSelection(params)
|
|
187
214
|
|
|
188
215
|
val impl = getInstance()
|
|
189
216
|
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
)
|
|
231
|
-
}
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
)
|
|
217
|
+
val result =
|
|
218
|
+
impl.updateBundle(
|
|
219
|
+
bundleId,
|
|
220
|
+
manifestUrl,
|
|
221
|
+
manifestFileHash,
|
|
222
|
+
assets,
|
|
223
|
+
channel,
|
|
224
|
+
selection,
|
|
225
|
+
archiveUrl,
|
|
226
|
+
) { progress ->
|
|
227
|
+
// Post to Main thread for React Native event emission
|
|
228
|
+
Handler(Looper.getMainLooper()).post {
|
|
229
|
+
try {
|
|
230
|
+
val progressParams =
|
|
231
|
+
WritableNativeMap().apply {
|
|
232
|
+
putDouble("progress", progress.progress)
|
|
233
|
+
putString("artifactType", progress.artifactType)
|
|
234
|
+
progress.details?.let { details ->
|
|
235
|
+
putMap(
|
|
236
|
+
"details",
|
|
237
|
+
WritableNativeMap().apply {
|
|
238
|
+
putInt("totalFilesCount", details.totalFilesCount)
|
|
239
|
+
putInt("completedFilesCount", details.completedFilesCount)
|
|
240
|
+
putArray(
|
|
241
|
+
"files",
|
|
242
|
+
WritableNativeArray().apply {
|
|
243
|
+
details.files.forEach { file ->
|
|
244
|
+
pushMap(
|
|
245
|
+
WritableNativeMap().apply {
|
|
246
|
+
putString("path", file.path)
|
|
247
|
+
putString("downloadPath", file.downloadPath)
|
|
248
|
+
putString("status", file.status)
|
|
249
|
+
putDouble("progress", file.progress)
|
|
250
|
+
putInt("order", file.order)
|
|
251
|
+
file.downloadedBytes?.let {
|
|
252
|
+
putDouble(
|
|
253
|
+
"downloadedBytes",
|
|
254
|
+
it.toDouble(),
|
|
255
|
+
)
|
|
256
|
+
}
|
|
257
|
+
file.totalBytes?.let { putDouble("totalBytes", it.toDouble()) }
|
|
258
|
+
},
|
|
259
|
+
)
|
|
260
|
+
}
|
|
261
|
+
},
|
|
262
|
+
)
|
|
263
|
+
},
|
|
264
|
+
)
|
|
265
|
+
}
|
|
240
266
|
}
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
267
|
+
|
|
268
|
+
this@HotUpdaterModule
|
|
269
|
+
.mReactApplicationContext
|
|
270
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
271
|
+
?.emit("onProgress", progressParams)
|
|
272
|
+
} catch (e: Exception) {
|
|
273
|
+
Log.w("HotUpdater", "Failed to emit progress (bridge may be unavailable): ${e.message}")
|
|
274
|
+
}
|
|
249
275
|
}
|
|
250
276
|
}
|
|
251
|
-
|
|
252
|
-
promise.resolve(true)
|
|
277
|
+
promise.resolve(result.toWritableMap())
|
|
253
278
|
} catch (e: HotUpdaterException) {
|
|
254
|
-
promise.
|
|
279
|
+
promise.rejectUpdateBundle(e)
|
|
255
280
|
} catch (e: Exception) {
|
|
281
|
+
// Not an update failure (a stale Release selection, for example),
|
|
282
|
+
// so the rejection carries no classification.
|
|
256
283
|
promise.reject("UNKNOWN_ERROR", e.message ?: "An unknown error occurred")
|
|
257
284
|
}
|
|
258
285
|
}
|
|
@@ -389,15 +416,13 @@ class HotUpdaterModule internal constructor(
|
|
|
389
416
|
|
|
390
417
|
override fun getInstallId(): String = getInstance().getInstallId()
|
|
391
418
|
|
|
392
|
-
override fun
|
|
393
|
-
|
|
394
|
-
override fun getUsername(): String? = getInstance().getUsername()
|
|
419
|
+
override fun getStorageItem(key: String): String? = getInstance().getStorageItem(key)
|
|
395
420
|
|
|
396
|
-
override fun
|
|
397
|
-
|
|
398
|
-
|
|
421
|
+
override fun setStorageItem(
|
|
422
|
+
key: String,
|
|
423
|
+
value: String?,
|
|
399
424
|
) {
|
|
400
|
-
getInstance().
|
|
425
|
+
getInstance().setStorageItem(key, value)
|
|
401
426
|
}
|
|
402
427
|
|
|
403
428
|
override fun resetChannel(promise: Promise) {
|
|
@@ -35,7 +35,7 @@ class HotUpdater {
|
|
|
35
35
|
* Updates the bundle using the default singleton instance
|
|
36
36
|
* @param context Application context
|
|
37
37
|
* @param bundleId ID of the bundle to update
|
|
38
|
-
* @param
|
|
38
|
+
* @param params Manifest and asset descriptors for the target bundle
|
|
39
39
|
* @param fileHash Combined hash string for verification (sig:<signature> or <hex_hash>)
|
|
40
40
|
* @param progressCallback Callback for download progress updates
|
|
41
41
|
* @throws HotUpdaterException if the update fails
|
|
@@ -43,22 +43,20 @@ class HotUpdater {
|
|
|
43
43
|
suspend fun updateBundle(
|
|
44
44
|
context: Context,
|
|
45
45
|
bundleId: String,
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
manifestFileHash: String?,
|
|
50
|
-
changedAssets: Map<String, ChangedAssetDescriptor>?,
|
|
46
|
+
manifestUrl: String,
|
|
47
|
+
manifestFileHash: String,
|
|
48
|
+
assets: Map<String, ChangedAssetDescriptor>,
|
|
51
49
|
channel: String?,
|
|
50
|
+
archiveUrl: String? = null,
|
|
52
51
|
progressCallback: (UpdateProgressPayload) -> Unit,
|
|
53
52
|
) {
|
|
54
53
|
getInstance(context).updateBundle(
|
|
55
54
|
bundleId,
|
|
56
|
-
fileUrl,
|
|
57
|
-
fileHash,
|
|
58
55
|
manifestUrl,
|
|
59
56
|
manifestFileHash,
|
|
60
|
-
|
|
57
|
+
assets,
|
|
61
58
|
channel,
|
|
59
|
+
archiveUrl = archiveUrl,
|
|
62
60
|
progressCallback = progressCallback,
|
|
63
61
|
)
|
|
64
62
|
}
|