@hot-updater/react-native 1.0.0-rc.4 → 1.0.0-rc.40
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/build.gradle +13 -2
- package/android/proguard-rules.pro +8 -2
- package/android/src/bridge/BridgeReactInstance.kt +38 -0
- package/android/src/bridgeless/BridgeReactInstance.kt +24 -0
- package/android/src/main/java/com/hotupdater/ActivityStartGate.kt +94 -0
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +1064 -844
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +50 -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 +46 -30
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +75 -192
- 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/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/newarch/JavaScriptExceptionHooks.kt +48 -0
- package/android/src/newarch/ReactIntegrationManager.kt +6 -32
- 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/android/src/oldarch/JavaScriptExceptionHooks.kt +71 -0
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +1032 -1116
- package/ios/HotUpdater/Internal/BundleMetadata.swift +61 -54
- 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 +32 -67
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +229 -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 +102 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +120 -68
- 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 +16 -27
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/fetchUpdateResponse.js +60 -0
- package/lib/commonjs/fetchUpdateResponse.js.map +1 -0
- package/lib/commonjs/httpClient.js +63 -94
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +71 -18
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +74 -60
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/pluginHost.js +45 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +36 -87
- 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 +145 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/wrap.js +43 -26
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/appReady.js +95 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/checkForUpdate.js +113 -63
- 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 +14 -26
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/fetchUpdateResponse.js +55 -0
- package/lib/module/fetchUpdateResponse.js.map +1 -0
- package/lib/module/httpClient.js +62 -93
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +58 -20
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +67 -53
- package/lib/module/native.js.map +1 -1
- package/lib/module/pluginHost.js +36 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +32 -82
- 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 +139 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/wrap.js +43 -26
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +21 -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 +5 -5
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/commonjs/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/commonjs/httpClient.d.ts +4 -33
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -8
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +29 -22
- 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 +8 -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 +35 -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 +21 -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 +5 -5
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/fetchUpdateResponse.d.ts +14 -0
- package/lib/typescript/module/fetchUpdateResponse.d.ts.map +1 -0
- package/lib/typescript/module/httpClient.d.ts +4 -33
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -8
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +29 -22
- 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 +8 -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 +35 -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 +141 -0
- package/src/checkForUpdate.ts +145 -86
- package/src/clientPlugin.ts +18 -0
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +14 -30
- package/src/fetchUpdateResponse.ts +60 -0
- package/src/httpClient.ts +88 -159
- package/src/index.ts +90 -24
- package/src/native.ts +98 -102
- package/src/pluginHost.ts +47 -0
- package/src/releaseCatalogCache.ts +43 -172
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +34 -48
- package/src/store.ts +2 -23
- package/src/types.ts +1 -1
- package/src/updateError.ts +167 -0
- package/src/wrap.tsx +57 -26
- 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 -616
- 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 -302
- 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 -883
- 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 -329
- 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 -615
- 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 -301
- 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 -882
- 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 -330
- 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 -612
- package/src/httpClient.spec.ts +0 -132
- package/src/index.spec.ts +0 -337
- package/src/iosInterop.spec.ts +0 -30
- package/src/native.spec.ts +0 -945
- 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 -406
|
@@ -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 onCatalystInstanceDestroy() {
|
|
30
40
|
super.onCatalystInstanceDestroy()
|
|
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
|
|
@@ -166,90 +178,105 @@ class HotUpdaterModule internal constructor(
|
|
|
166
178
|
try {
|
|
167
179
|
val bundleId = params.getString("bundleId")
|
|
168
180
|
if (bundleId == null || bundleId.isEmpty()) {
|
|
169
|
-
promise.
|
|
181
|
+
promise.rejectUpdateBundle(HotUpdaterException.missingBundleId())
|
|
170
182
|
return@launch
|
|
171
183
|
}
|
|
172
184
|
|
|
173
|
-
val
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
if (
|
|
185
|
+
val manifestUrl = params.getString("manifestUrl")
|
|
186
|
+
val manifestFileHash = params.getString("manifestFileHash")
|
|
187
|
+
val assets = parseAssets(params)
|
|
188
|
+
if (manifestUrl.isNullOrEmpty() || manifestFileHash.isNullOrEmpty() || assets == null) {
|
|
189
|
+
promise.rejectUpdateBundle(HotUpdaterException.invalidManifestParams())
|
|
190
|
+
return@launch
|
|
191
|
+
}
|
|
192
|
+
try {
|
|
193
|
+
java.net.URL(manifestUrl)
|
|
194
|
+
} catch (e: java.net.MalformedURLException) {
|
|
195
|
+
promise.rejectUpdateBundle(
|
|
196
|
+
HotUpdaterException.invalidFileUrl("manifestUrl", manifestUrl, UpdateFailureResource.MANIFEST),
|
|
197
|
+
)
|
|
198
|
+
return@launch
|
|
199
|
+
}
|
|
200
|
+
val channel = params.getString("channel")
|
|
201
|
+
val archiveUrl =
|
|
202
|
+
if (params.hasKey("archiveUrl") && !params.isNull("archiveUrl")) {
|
|
203
|
+
params.getString("archiveUrl")
|
|
204
|
+
} else {
|
|
205
|
+
null
|
|
206
|
+
}
|
|
207
|
+
if (archiveUrl != null) {
|
|
177
208
|
try {
|
|
178
|
-
java.net.URL(
|
|
209
|
+
java.net.URL(archiveUrl)
|
|
179
210
|
} catch (e: java.net.MalformedURLException) {
|
|
180
|
-
promise.
|
|
211
|
+
promise.rejectUpdateBundle(
|
|
212
|
+
HotUpdaterException.invalidFileUrl("archiveUrl", archiveUrl, UpdateFailureResource.ARCHIVE),
|
|
213
|
+
)
|
|
181
214
|
return@launch
|
|
182
215
|
}
|
|
183
216
|
}
|
|
184
|
-
|
|
185
|
-
val fileHash = params.getString("fileHash")
|
|
186
|
-
val manifestUrl = params.getString("manifestUrl")
|
|
187
|
-
val manifestFileHash = params.getString("manifestFileHash")
|
|
188
|
-
val changedAssets = parseChangedAssets(params)
|
|
189
|
-
val channel = params.getString("channel")
|
|
190
217
|
val selection = parseSelection(params)
|
|
191
218
|
|
|
192
219
|
val impl = getInstance()
|
|
193
220
|
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
221
|
+
val result =
|
|
222
|
+
impl.updateBundle(
|
|
223
|
+
bundleId,
|
|
224
|
+
manifestUrl,
|
|
225
|
+
manifestFileHash,
|
|
226
|
+
assets,
|
|
227
|
+
channel,
|
|
228
|
+
selection,
|
|
229
|
+
archiveUrl,
|
|
230
|
+
) { progress ->
|
|
231
|
+
// Post to Main thread for React Native event emission
|
|
232
|
+
Handler(Looper.getMainLooper()).post {
|
|
233
|
+
try {
|
|
234
|
+
val progressParams =
|
|
235
|
+
Arguments.createMap().apply {
|
|
236
|
+
putDouble("progress", progress.progress)
|
|
237
|
+
putString("artifactType", progress.artifactType)
|
|
238
|
+
progress.details?.let { details ->
|
|
239
|
+
val files = Arguments.createArray()
|
|
240
|
+
details.files.forEach { file ->
|
|
241
|
+
files.pushMap(
|
|
242
|
+
Arguments.createMap().apply {
|
|
243
|
+
putString("path", file.path)
|
|
244
|
+
putString("downloadPath", file.downloadPath)
|
|
245
|
+
putString("status", file.status)
|
|
246
|
+
putDouble("progress", file.progress)
|
|
247
|
+
putInt("order", file.order)
|
|
248
|
+
file.downloadedBytes?.let { putDouble("downloadedBytes", it.toDouble()) }
|
|
249
|
+
file.totalBytes?.let { putDouble("totalBytes", it.toDouble()) }
|
|
250
|
+
},
|
|
251
|
+
)
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
putMap(
|
|
255
|
+
"details",
|
|
217
256
|
Arguments.createMap().apply {
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
putDouble("progress", file.progress)
|
|
222
|
-
putInt("order", file.order)
|
|
223
|
-
file.downloadedBytes?.let { putDouble("downloadedBytes", it.toDouble()) }
|
|
224
|
-
file.totalBytes?.let { putDouble("totalBytes", it.toDouble()) }
|
|
257
|
+
putInt("totalFilesCount", details.totalFilesCount)
|
|
258
|
+
putInt("completedFilesCount", details.completedFilesCount)
|
|
259
|
+
putArray("files", files)
|
|
225
260
|
},
|
|
226
261
|
)
|
|
227
262
|
}
|
|
228
|
-
|
|
229
|
-
putMap(
|
|
230
|
-
"details",
|
|
231
|
-
Arguments.createMap().apply {
|
|
232
|
-
putInt("totalFilesCount", details.totalFilesCount)
|
|
233
|
-
putInt("completedFilesCount", details.completedFilesCount)
|
|
234
|
-
putArray("files", files)
|
|
235
|
-
},
|
|
236
|
-
)
|
|
237
263
|
}
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
264
|
+
|
|
265
|
+
this@HotUpdaterModule
|
|
266
|
+
.mReactApplicationContext
|
|
267
|
+
.getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
|
|
268
|
+
?.emit("onProgress", progressParams)
|
|
269
|
+
} catch (e: Exception) {
|
|
270
|
+
Log.w("HotUpdater", "Failed to emit progress (bridge may be unavailable): ${e.message}")
|
|
271
|
+
}
|
|
246
272
|
}
|
|
247
273
|
}
|
|
248
|
-
|
|
249
|
-
promise.resolve(true)
|
|
274
|
+
promise.resolve(result.toWritableMap())
|
|
250
275
|
} catch (e: HotUpdaterException) {
|
|
251
|
-
promise.
|
|
276
|
+
promise.rejectUpdateBundle(e)
|
|
252
277
|
} catch (e: Exception) {
|
|
278
|
+
// Not an update failure (a stale Release selection, for example),
|
|
279
|
+
// so the rejection carries no classification.
|
|
253
280
|
promise.reject("UNKNOWN_ERROR", e.message ?: "An unknown error occurred")
|
|
254
281
|
}
|
|
255
282
|
}
|
|
@@ -414,17 +441,14 @@ class HotUpdaterModule internal constructor(
|
|
|
414
441
|
override fun getInstallId(): String = getInstance().getInstallId()
|
|
415
442
|
|
|
416
443
|
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
417
|
-
override fun
|
|
418
|
-
|
|
419
|
-
@ReactMethod(isBlockingSynchronousMethod = true)
|
|
420
|
-
override fun getUsername(): String? = getInstance().getUsername()
|
|
444
|
+
override fun getStorageItem(key: String): String? = getInstance().getStorageItem(key)
|
|
421
445
|
|
|
422
446
|
@ReactMethod
|
|
423
|
-
override fun
|
|
424
|
-
|
|
425
|
-
|
|
447
|
+
override fun setStorageItem(
|
|
448
|
+
key: String,
|
|
449
|
+
value: String?,
|
|
426
450
|
) {
|
|
427
|
-
getInstance().
|
|
451
|
+
getInstance().setStorageItem(key, value)
|
|
428
452
|
}
|
|
429
453
|
|
|
430
454
|
@ReactMethod
|
|
@@ -62,13 +62,11 @@ abstract class HotUpdaterSpec internal constructor(
|
|
|
62
62
|
|
|
63
63
|
abstract fun getInstallId(): String
|
|
64
64
|
|
|
65
|
-
abstract fun
|
|
65
|
+
abstract fun getStorageItem(key: String): String?
|
|
66
66
|
|
|
67
|
-
abstract fun
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
userId: String?,
|
|
71
|
-
username: String?,
|
|
67
|
+
abstract fun setStorageItem(
|
|
68
|
+
key: String,
|
|
69
|
+
value: String?,
|
|
72
70
|
)
|
|
73
71
|
|
|
74
72
|
abstract fun resetChannel(promise: Promise)
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
package com.hotupdater
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.ReactApplication
|
|
4
|
+
import com.facebook.react.bridge.JSExceptionHandler
|
|
5
|
+
import com.facebook.react.bridge.ReactContext
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Routes JavaScript errors of the running React instance to crash recovery.
|
|
9
|
+
* The old architecture reaches the instance through ReactNativeHost, which only
|
|
10
|
+
* an old architecture build compiles.
|
|
11
|
+
*/
|
|
12
|
+
internal object JavaScriptExceptionHooks {
|
|
13
|
+
private val patchedInstanceManagerIds = mutableSetOf<Int>()
|
|
14
|
+
private val patchedCatalystInstanceIds = mutableSetOf<Int>()
|
|
15
|
+
|
|
16
|
+
fun install(application: ReactApplication) {
|
|
17
|
+
val instanceManager = application.reactNativeHost.reactInstanceManager
|
|
18
|
+
val managerIdentity = System.identityHashCode(instanceManager)
|
|
19
|
+
if (patchedInstanceManagerIds.add(managerIdentity)) {
|
|
20
|
+
val exceptionHandlerField =
|
|
21
|
+
HotUpdaterRecoveryManager.findField(instanceManager.javaClass, "mJSExceptionHandler")
|
|
22
|
+
if (exceptionHandlerField == null) {
|
|
23
|
+
patchedInstanceManagerIds.remove(managerIdentity)
|
|
24
|
+
return
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
exceptionHandlerField.isAccessible = true
|
|
28
|
+
val previousHandler = exceptionHandlerField.get(instanceManager) as? JSExceptionHandler
|
|
29
|
+
exceptionHandlerField.set(
|
|
30
|
+
instanceManager,
|
|
31
|
+
HotUpdaterRecoveryManager.RecoveryJSExceptionHandler(previousHandler),
|
|
32
|
+
)
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
instanceManager.currentReactContext?.let { reactContext ->
|
|
36
|
+
HotUpdaterRecoveryManager.patchReactContextExceptionHandler(reactContext)
|
|
37
|
+
patchCatalystInstanceExceptionHandler(reactContext)
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
private fun patchCatalystInstanceExceptionHandler(reactContext: ReactContext) {
|
|
42
|
+
val catalystInstance =
|
|
43
|
+
try {
|
|
44
|
+
reactContext.catalystInstance
|
|
45
|
+
} catch (_: Exception) {
|
|
46
|
+
null
|
|
47
|
+
} ?: return
|
|
48
|
+
|
|
49
|
+
val catalystIdentity = System.identityHashCode(catalystInstance)
|
|
50
|
+
if (!patchedCatalystInstanceIds.add(catalystIdentity)) {
|
|
51
|
+
return
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
val exceptionHandlerField =
|
|
55
|
+
HotUpdaterRecoveryManager.findField(catalystInstance.javaClass, "mJSExceptionHandler")
|
|
56
|
+
if (exceptionHandlerField == null) {
|
|
57
|
+
patchedCatalystInstanceIds.remove(catalystIdentity)
|
|
58
|
+
return
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
exceptionHandlerField.isAccessible = true
|
|
62
|
+
val previousHandler = exceptionHandlerField.get(catalystInstance) as? JSExceptionHandler
|
|
63
|
+
if (previousHandler is HotUpdaterRecoveryManager.RecoveryJSExceptionHandler) {
|
|
64
|
+
return
|
|
65
|
+
}
|
|
66
|
+
exceptionHandlerField.set(
|
|
67
|
+
catalystInstance,
|
|
68
|
+
HotUpdaterRecoveryManager.RecoveryJSExceptionHandler(previousHandler),
|
|
69
|
+
)
|
|
70
|
+
}
|
|
71
|
+
}
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
import Compression
|
|
2
|
+
import Foundation
|
|
3
|
+
|
|
4
|
+
enum BrotliFileDecompressor {
|
|
5
|
+
private static let bufferSize = 64 * 1024
|
|
6
|
+
|
|
7
|
+
static func decompress(
|
|
8
|
+
from sourcePath: String,
|
|
9
|
+
to outputPath: String,
|
|
10
|
+
expectedOutputByteSize: Int64? = nil
|
|
11
|
+
) throws {
|
|
12
|
+
if let expectedOutputByteSize, expectedOutputByteSize < 0 {
|
|
13
|
+
throw error(6, "Invalid expected Brotli output size")
|
|
14
|
+
}
|
|
15
|
+
let fileManager = FileManager.default
|
|
16
|
+
let parentDirectory = (outputPath as NSString).deletingLastPathComponent
|
|
17
|
+
try fileManager.createDirectory(
|
|
18
|
+
atPath: parentDirectory,
|
|
19
|
+
withIntermediateDirectories: true
|
|
20
|
+
)
|
|
21
|
+
if fileManager.fileExists(atPath: outputPath) {
|
|
22
|
+
try fileManager.removeItem(atPath: outputPath)
|
|
23
|
+
}
|
|
24
|
+
guard fileManager.createFile(atPath: outputPath, contents: nil) else {
|
|
25
|
+
throw error(1, "Failed to create Brotli output file")
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
let input = try FileHandle(forReadingFrom: URL(fileURLWithPath: sourcePath))
|
|
29
|
+
let output = try FileHandle(forWritingTo: URL(fileURLWithPath: outputPath))
|
|
30
|
+
defer {
|
|
31
|
+
try? input.close()
|
|
32
|
+
try? output.close()
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
var stream = compression_stream(
|
|
36
|
+
dst_ptr: UnsafeMutablePointer<UInt8>(bitPattern: 1)!,
|
|
37
|
+
dst_size: 0,
|
|
38
|
+
src_ptr: UnsafePointer<UInt8>(bitPattern: 1)!,
|
|
39
|
+
src_size: 0,
|
|
40
|
+
state: nil
|
|
41
|
+
)
|
|
42
|
+
guard compression_stream_init(
|
|
43
|
+
&stream,
|
|
44
|
+
COMPRESSION_STREAM_DECODE,
|
|
45
|
+
COMPRESSION_BROTLI
|
|
46
|
+
) == COMPRESSION_STATUS_OK else {
|
|
47
|
+
throw error(2, "Failed to initialize Brotli decompression")
|
|
48
|
+
}
|
|
49
|
+
defer { compression_stream_destroy(&stream) }
|
|
50
|
+
|
|
51
|
+
let outputBuffer = UnsafeMutablePointer<UInt8>.allocate(
|
|
52
|
+
capacity: bufferSize
|
|
53
|
+
)
|
|
54
|
+
defer { outputBuffer.deallocate() }
|
|
55
|
+
|
|
56
|
+
var reachedEnd = false
|
|
57
|
+
var totalOutputByteSize: UInt64 = 0
|
|
58
|
+
let maximumOutputByteSize = expectedOutputByteSize.map(UInt64.init)
|
|
59
|
+
while !reachedEnd {
|
|
60
|
+
let chunk = try FileUtilities.readUpToCount(
|
|
61
|
+
from: input,
|
|
62
|
+
count: bufferSize
|
|
63
|
+
) ?? Data()
|
|
64
|
+
let status: compression_status
|
|
65
|
+
if chunk.isEmpty {
|
|
66
|
+
stream.src_ptr = UnsafePointer<UInt8>(bitPattern: 1)!
|
|
67
|
+
stream.src_size = 0
|
|
68
|
+
status = try process(
|
|
69
|
+
&stream,
|
|
70
|
+
output: output,
|
|
71
|
+
outputBuffer: outputBuffer,
|
|
72
|
+
finalize: true,
|
|
73
|
+
totalOutputByteSize: &totalOutputByteSize,
|
|
74
|
+
maximumOutputByteSize: maximumOutputByteSize
|
|
75
|
+
)
|
|
76
|
+
} else {
|
|
77
|
+
status = try chunk.withUnsafeBytes { bytes in
|
|
78
|
+
guard let source = bytes.baseAddress?
|
|
79
|
+
.assumingMemoryBound(to: UInt8.self) else {
|
|
80
|
+
return COMPRESSION_STATUS_OK
|
|
81
|
+
}
|
|
82
|
+
stream.src_ptr = source
|
|
83
|
+
stream.src_size = chunk.count
|
|
84
|
+
return try process(
|
|
85
|
+
&stream,
|
|
86
|
+
output: output,
|
|
87
|
+
outputBuffer: outputBuffer,
|
|
88
|
+
finalize: false,
|
|
89
|
+
totalOutputByteSize: &totalOutputByteSize,
|
|
90
|
+
maximumOutputByteSize: maximumOutputByteSize
|
|
91
|
+
)
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
if status == COMPRESSION_STATUS_END {
|
|
96
|
+
guard stream.src_size == 0 else {
|
|
97
|
+
throw error(7, "Brotli stream contains trailing compressed bytes")
|
|
98
|
+
}
|
|
99
|
+
let trailing = try FileUtilities.readUpToCount(from: input, count: 1)
|
|
100
|
+
guard trailing?.isEmpty != false else {
|
|
101
|
+
throw error(7, "Brotli stream contains trailing compressed bytes")
|
|
102
|
+
}
|
|
103
|
+
reachedEnd = true
|
|
104
|
+
} else if chunk.isEmpty {
|
|
105
|
+
throw error(3, "Brotli input ended before the stream completed")
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
if let maximumOutputByteSize,
|
|
110
|
+
totalOutputByteSize != maximumOutputByteSize {
|
|
111
|
+
throw error(
|
|
112
|
+
8,
|
|
113
|
+
"Brotli output size mismatch: expected \(maximumOutputByteSize), got \(totalOutputByteSize)"
|
|
114
|
+
)
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
|
|
118
|
+
private static func process(
|
|
119
|
+
_ stream: inout compression_stream,
|
|
120
|
+
output: FileHandle,
|
|
121
|
+
outputBuffer: UnsafeMutablePointer<UInt8>,
|
|
122
|
+
finalize: Bool,
|
|
123
|
+
totalOutputByteSize: inout UInt64,
|
|
124
|
+
maximumOutputByteSize: UInt64?
|
|
125
|
+
) throws -> compression_status {
|
|
126
|
+
let flags = finalize ? Int32(COMPRESSION_STREAM_FINALIZE.rawValue) : 0
|
|
127
|
+
var status = COMPRESSION_STATUS_OK
|
|
128
|
+
repeat {
|
|
129
|
+
let previousSourceSize = stream.src_size
|
|
130
|
+
stream.dst_ptr = outputBuffer
|
|
131
|
+
stream.dst_size = bufferSize
|
|
132
|
+
status = compression_stream_process(&stream, flags)
|
|
133
|
+
|
|
134
|
+
guard status == COMPRESSION_STATUS_OK ||
|
|
135
|
+
status == COMPRESSION_STATUS_END else {
|
|
136
|
+
throw error(4, "Brotli decompression failed")
|
|
137
|
+
}
|
|
138
|
+
let produced = bufferSize - stream.dst_size
|
|
139
|
+
if produced > 0 {
|
|
140
|
+
let (nextOutputByteSize, overflowed) = totalOutputByteSize
|
|
141
|
+
.addingReportingOverflow(UInt64(produced))
|
|
142
|
+
guard !overflowed,
|
|
143
|
+
maximumOutputByteSize.map({ nextOutputByteSize <= $0 }) ?? true else {
|
|
144
|
+
throw error(6, "Brotli output exceeds expected size")
|
|
145
|
+
}
|
|
146
|
+
output.write(Data(bytes: outputBuffer, count: produced))
|
|
147
|
+
totalOutputByteSize = nextOutputByteSize
|
|
148
|
+
}
|
|
149
|
+
if finalize,
|
|
150
|
+
status == COMPRESSION_STATUS_OK,
|
|
151
|
+
produced == 0,
|
|
152
|
+
previousSourceSize == stream.src_size {
|
|
153
|
+
throw error(5, "Brotli decompression stalled")
|
|
154
|
+
}
|
|
155
|
+
} while stream.src_size > 0 || stream.dst_size == 0 ||
|
|
156
|
+
(finalize && status == COMPRESSION_STATUS_OK)
|
|
157
|
+
return status
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
private static func error(_ code: Int, _ message: String) -> NSError {
|
|
161
|
+
NSError(
|
|
162
|
+
domain: "BrotliFileDecompressor",
|
|
163
|
+
code: code,
|
|
164
|
+
userInfo: [NSLocalizedDescriptionKey: message]
|
|
165
|
+
)
|
|
166
|
+
}
|
|
167
|
+
}
|