@hot-updater/react-native 1.0.0-rc.4 → 1.0.0-rc.41
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 +96 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +121 -69
- 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 +5 -14
- 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 +64 -95
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/index.js +355 -324
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/init.types.js +6 -0
- package/lib/commonjs/init.types.js.map +1 -0
- package/lib/commonjs/native.js +77 -63
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/pluginHost.js +41 -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 +46 -38
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/module/appReady.js +90 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/checkForUpdate.js +114 -64
- 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 +5 -14
- 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 +63 -94
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/index.js +335 -327
- package/lib/module/index.js.map +1 -1
- package/lib/module/init.types.js +4 -0
- package/lib/module/init.types.js.map +1 -0
- package/lib/module/native.js +70 -56
- 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 +47 -38
- package/lib/module/wrap.js.map +1 -1
- package/lib/typescript/commonjs/appReady.d.ts +30 -0
- package/lib/typescript/commonjs/appReady.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +20 -6
- 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 +5 -14
- 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 +5 -34
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +124 -116
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/init.types.d.ts +21 -0
- package/lib/typescript/commonjs/init.types.d.ts.map +1 -0
- package/lib/typescript/commonjs/native.d.ts +32 -25
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +8 -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 +2 -3
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +13 -41
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/appReady.d.ts +30 -0
- package/lib/typescript/module/appReady.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +20 -6
- 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 +5 -14
- 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 +5 -34
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +124 -116
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/init.types.d.ts +21 -0
- package/lib/typescript/module/init.types.d.ts.map +1 -0
- package/lib/typescript/module/native.d.ts +32 -25
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +8 -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 +2 -3
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +13 -41
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +8 -4
- package/src/appReady.ts +147 -0
- package/src/checkForUpdate.ts +156 -89
- package/src/clientPlugin.ts +21 -0
- package/src/error.ts +5 -15
- package/src/fetchJSON.ts +14 -30
- package/src/fetchUpdateResponse.ts +60 -0
- package/src/httpClient.ts +89 -160
- package/src/index.ts +413 -425
- package/src/init.types.ts +24 -0
- package/src/native.ts +101 -105
- package/src/pluginHost.ts +52 -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 +60 -43
- package/src/wrap.types.ts +18 -46
- 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
package/src/index.ts
CHANGED
|
@@ -1,12 +1,17 @@
|
|
|
1
|
+
import { createLaunchReporter, type LaunchReporter } from "./appReady";
|
|
1
2
|
import {
|
|
2
3
|
type CheckForUpdateOptions,
|
|
3
4
|
checkForUpdate,
|
|
4
|
-
|
|
5
|
+
reportUpdateError,
|
|
5
6
|
} from "./checkForUpdate";
|
|
7
|
+
import type { ClientPluginApis, HotUpdaterClientPlugin } from "./clientPlugin";
|
|
6
8
|
import { createHttpClient, type HotUpdaterHttpClient } from "./httpClient";
|
|
9
|
+
import type { HotUpdaterInitOptions } from "./init.types";
|
|
7
10
|
import {
|
|
8
11
|
addListener,
|
|
9
12
|
getPublicActiveUpdateState,
|
|
13
|
+
getActiveUpdateState,
|
|
14
|
+
getBundleId,
|
|
10
15
|
clearCrashHistory,
|
|
11
16
|
getAppVersion,
|
|
12
17
|
getBaseURL,
|
|
@@ -25,21 +30,54 @@ import {
|
|
|
25
30
|
resetChannel,
|
|
26
31
|
setCohort,
|
|
27
32
|
setReloadBehavior,
|
|
28
|
-
|
|
33
|
+
stageBundle,
|
|
29
34
|
type UpdateParams,
|
|
30
|
-
updateBundle,
|
|
31
35
|
} from "./native";
|
|
36
|
+
import { createAppPluginHost } from "./pluginHost";
|
|
32
37
|
import { hotUpdaterStore } from "./store";
|
|
33
|
-
import {
|
|
34
|
-
type AutoUpdateOptions,
|
|
35
|
-
type HotUpdaterInitOptions,
|
|
36
|
-
type HotUpdaterOptions,
|
|
37
|
-
init,
|
|
38
|
-
type InternalInitOptions,
|
|
39
|
-
type InternalWrapOptions,
|
|
40
|
-
wrap,
|
|
41
|
-
} from "./wrap";
|
|
38
|
+
import { type HotUpdaterWrapOptions, wrap } from "./wrap";
|
|
42
39
|
|
|
40
|
+
export {
|
|
41
|
+
defineClientPlugin,
|
|
42
|
+
type AppReadyResult,
|
|
43
|
+
type BundleDownloadedInfo,
|
|
44
|
+
type ClientPluginApi,
|
|
45
|
+
type ClientPluginApis,
|
|
46
|
+
type HotUpdaterClientContext,
|
|
47
|
+
type HotUpdaterClientHooks,
|
|
48
|
+
type HotUpdaterClientPlugin,
|
|
49
|
+
type HotUpdaterClientSetup,
|
|
50
|
+
type HotUpdaterClientStorage,
|
|
51
|
+
type ReleaseTransitionKind,
|
|
52
|
+
type UpdateCheckResult,
|
|
53
|
+
type UpdateError,
|
|
54
|
+
type UpdateErrorReason,
|
|
55
|
+
type UpdateErrorStage,
|
|
56
|
+
type UpdateHttpResponse,
|
|
57
|
+
type UpdateStrategy,
|
|
58
|
+
} from "./clientPlugin";
|
|
59
|
+
// The built-in Insights client plugin, for HotUpdater.init({ plugins }).
|
|
60
|
+
export {
|
|
61
|
+
insights,
|
|
62
|
+
type InsightsClient,
|
|
63
|
+
type InsightsOptions,
|
|
64
|
+
type InsightsPlugin,
|
|
65
|
+
type InsightsUser,
|
|
66
|
+
} from "@hot-updater/plugin-insights/client";
|
|
67
|
+
// The built-in Remote Config client plugin, for HotUpdater.init({ plugins }).
|
|
68
|
+
export {
|
|
69
|
+
remoteConfig,
|
|
70
|
+
type RemoteConfigClient,
|
|
71
|
+
type RemoteConfigDefaults,
|
|
72
|
+
type RemoteConfigDefaultValue,
|
|
73
|
+
type RemoteConfigFetchOptions,
|
|
74
|
+
type RemoteConfigFetchStatus,
|
|
75
|
+
type RemoteConfigKey,
|
|
76
|
+
type RemoteConfigOptions,
|
|
77
|
+
type RemoteConfigPlugin,
|
|
78
|
+
type RemoteConfigValue,
|
|
79
|
+
type RemoteConfigValueSource,
|
|
80
|
+
} from "@hot-updater/plugin-remote-config/client";
|
|
43
81
|
export type {
|
|
44
82
|
CustomReloadHandler,
|
|
45
83
|
HotUpdaterEvent,
|
|
@@ -51,7 +89,6 @@ export type {
|
|
|
51
89
|
ActiveUpdateState,
|
|
52
90
|
ReloadBehavior,
|
|
53
91
|
ReloadBehaviorSetting,
|
|
54
|
-
SetUserParams,
|
|
55
92
|
} from "./native";
|
|
56
93
|
export * from "./store";
|
|
57
94
|
export {
|
|
@@ -60,10 +97,10 @@ export {
|
|
|
60
97
|
isSignatureVerificationError,
|
|
61
98
|
type SignatureVerificationFailure,
|
|
62
99
|
} from "./types";
|
|
100
|
+
export type { HotUpdaterInitOptions } from "./init.types";
|
|
63
101
|
export type {
|
|
64
102
|
HotUpdaterFallbackComponentProps,
|
|
65
|
-
|
|
66
|
-
HotUpdaterOptions,
|
|
103
|
+
HotUpdaterWrapOptions,
|
|
67
104
|
RunUpdateProcessResponse,
|
|
68
105
|
} from "./wrap";
|
|
69
106
|
|
|
@@ -85,337 +122,240 @@ const registerGlobalGetBaseURL = () => {
|
|
|
85
122
|
// Call registration immediately on module load
|
|
86
123
|
registerGlobalGetBaseURL();
|
|
87
124
|
|
|
88
|
-
|
|
89
|
-
(
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
/**
|
|
94
|
-
* Creates a HotUpdater client instance with all update management methods.
|
|
95
|
-
* This function is called once on module initialization to create a singleton instance.
|
|
96
|
-
*/
|
|
97
|
-
function createHotUpdaterClient() {
|
|
98
|
-
let configurationAPI: "init" | "wrap" | null = null;
|
|
99
|
-
let mixedConfigurationReported = false;
|
|
100
|
-
|
|
101
|
-
// Global configuration stored from wrap
|
|
102
|
-
const globalConfig: {
|
|
103
|
-
insights: boolean;
|
|
104
|
-
client: HotUpdaterHttpClient | null;
|
|
105
|
-
requestHeaders?: Record<string, string>;
|
|
106
|
-
requestTimeout?: number;
|
|
107
|
-
onError?: (error: unknown) => void;
|
|
108
|
-
} = {
|
|
109
|
-
insights: true,
|
|
110
|
-
client: null,
|
|
111
|
-
};
|
|
112
|
-
|
|
113
|
-
const createMissingNetworkConfigError = (apiName: "init" | "wrap") => {
|
|
114
|
-
if (apiName === "init") {
|
|
115
|
-
return new Error(
|
|
116
|
-
`[HotUpdater] baseURL must be provided.\n\n` +
|
|
117
|
-
`Configure HotUpdater before calling update APIs with the standard baseURL setup:\n\n` +
|
|
118
|
-
` HotUpdater.init({\n` +
|
|
119
|
-
` baseURL: "<your-update-server-url>",\n` +
|
|
120
|
-
` });\n\n` +
|
|
121
|
-
`For manual update flows, visit: https://hot-updater.dev/docs/guides/custom-update`,
|
|
122
|
-
);
|
|
123
|
-
}
|
|
124
|
-
|
|
125
|
-
const baseURLExample =
|
|
126
|
-
` export default HotUpdater.wrap({\n` +
|
|
125
|
+
const createMissingNetworkConfigError = () =>
|
|
126
|
+
new Error(
|
|
127
|
+
`[HotUpdater] baseURL must be provided.\n\n` +
|
|
128
|
+
`Configure HotUpdater with the standard baseURL setup:\n\n` +
|
|
129
|
+
` export const hotUpdater = HotUpdater.init({\n` +
|
|
127
130
|
` baseURL: "<your-update-server-url>",\n` +
|
|
128
|
-
`
|
|
129
|
-
`
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
};
|
|
139
|
-
|
|
140
|
-
const normalizeOptions = (
|
|
141
|
-
options: HotUpdaterOptions,
|
|
142
|
-
): InternalWrapOptions => {
|
|
143
|
-
const incoming = options as HotUpdaterOptions & {
|
|
144
|
-
updateMode?: unknown;
|
|
145
|
-
};
|
|
146
|
-
if (incoming.updateMode === "manual") {
|
|
147
|
-
throw new Error(
|
|
148
|
-
'[HotUpdater] HotUpdater.wrap({ updateMode: "manual" }) was removed. ' +
|
|
149
|
-
"Call HotUpdater.init({ ... }) instead, export your root component " +
|
|
150
|
-
"directly, and use HotUpdater.checkForUpdate(...) for the manual " +
|
|
151
|
-
"update flow. See https://hot-updater.dev/docs/guides/custom-update",
|
|
152
|
-
);
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const autoOptions = incoming as AutoUpdateOptions;
|
|
156
|
-
|
|
157
|
-
if (autoOptions.baseURL) {
|
|
158
|
-
const { baseURL, ...rest } = autoOptions;
|
|
159
|
-
return {
|
|
160
|
-
...rest,
|
|
161
|
-
insights: rest.insights ?? true,
|
|
162
|
-
client: createHttpClient(baseURL),
|
|
163
|
-
};
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
throw createMissingNetworkConfigError("wrap");
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
const normalizeInitOptions = (
|
|
170
|
-
options: HotUpdaterInitOptions,
|
|
171
|
-
): InternalInitOptions => {
|
|
172
|
-
const { updateMode: _updateMode, ...rest } =
|
|
173
|
-
options as HotUpdaterInitOptions & {
|
|
174
|
-
updateMode?: unknown;
|
|
175
|
-
};
|
|
176
|
-
|
|
177
|
-
if (rest.baseURL) {
|
|
178
|
-
const { baseURL, ...baseURLRest } = rest;
|
|
179
|
-
return {
|
|
180
|
-
...baseURLRest,
|
|
181
|
-
insights: baseURLRest.insights ?? true,
|
|
182
|
-
client: createHttpClient(baseURL),
|
|
183
|
-
};
|
|
184
|
-
}
|
|
185
|
-
|
|
186
|
-
throw createMissingNetworkConfigError("init");
|
|
187
|
-
};
|
|
188
|
-
|
|
189
|
-
const configureGlobal = (
|
|
190
|
-
normalizedOptions: InternalInitOptions | InternalWrapOptions,
|
|
191
|
-
options: HotUpdaterOptions | HotUpdaterInitOptions,
|
|
192
|
-
) => {
|
|
193
|
-
globalConfig.insights = normalizedOptions.insights ?? true;
|
|
194
|
-
globalConfig.client = normalizedOptions.client;
|
|
195
|
-
globalConfig.requestHeaders = options.requestHeaders;
|
|
196
|
-
globalConfig.requestTimeout = options.requestTimeout;
|
|
197
|
-
globalConfig.onError = options.onError;
|
|
198
|
-
};
|
|
199
|
-
|
|
200
|
-
const reportMixedConfiguration = (nextAPI: "init" | "wrap") => {
|
|
201
|
-
if (
|
|
202
|
-
configurationAPI !== null &&
|
|
203
|
-
configurationAPI !== nextAPI &&
|
|
204
|
-
!mixedConfigurationReported
|
|
205
|
-
) {
|
|
206
|
-
mixedConfigurationReported = true;
|
|
207
|
-
console.error(
|
|
208
|
-
"[HotUpdater] HotUpdater.init() and HotUpdater.wrap() must not be used together. " +
|
|
209
|
-
"For custom or manual update flows, use HotUpdater.init() with " +
|
|
210
|
-
"HotUpdater.checkForUpdate(). For the automatic HOC flow, use " +
|
|
211
|
-
"HotUpdater.wrap().",
|
|
212
|
-
);
|
|
213
|
-
}
|
|
214
|
-
configurationAPI ??= nextAPI;
|
|
215
|
-
};
|
|
216
|
-
|
|
217
|
-
const ensureGlobalClient = (methodName: string) => {
|
|
218
|
-
if (!globalConfig.client) {
|
|
219
|
-
throw new Error(
|
|
220
|
-
`[HotUpdater] ${methodName} requires HotUpdater.wrap() or HotUpdater.init() to be used.\n\n` +
|
|
221
|
-
`To fix this issue, configure HotUpdater before calling ${methodName}:\n\n` +
|
|
222
|
-
`Option 1: With HotUpdater.wrap()\n` +
|
|
223
|
-
` export default HotUpdater.wrap({\n` +
|
|
224
|
-
` baseURL: "<your-update-server-url>",\n` +
|
|
225
|
-
` updateStrategy: "appVersion"\n` +
|
|
226
|
-
` })(App);\n\n` +
|
|
227
|
-
`Option 2: With HotUpdater.init() for custom runtimes\n` +
|
|
228
|
-
` HotUpdater.init({\n` +
|
|
229
|
-
` baseURL: "<your-update-server-url>",\n` +
|
|
230
|
-
` });\n\n` +
|
|
231
|
-
`For manual update flows, visit: https://hot-updater.dev/docs/guides/custom-update`,
|
|
232
|
-
);
|
|
233
|
-
}
|
|
234
|
-
return globalConfig.client;
|
|
235
|
-
};
|
|
131
|
+
` });\n\n` +
|
|
132
|
+
`See https://hot-updater.dev/docs/react-native-api/init`,
|
|
133
|
+
);
|
|
134
|
+
|
|
135
|
+
/** The methods that read or change native state, the same on every instance. */
|
|
136
|
+
const nativeMethods = {
|
|
137
|
+
/**
|
|
138
|
+
* Reloads the app.
|
|
139
|
+
*/
|
|
140
|
+
reload,
|
|
236
141
|
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
* @returns {Function} Higher-order component that wraps the app component
|
|
249
|
-
*
|
|
250
|
-
* @example
|
|
251
|
-
* ```tsx
|
|
252
|
-
* export default HotUpdater.wrap({
|
|
253
|
-
* baseURL: "<your-update-server-url>",
|
|
254
|
-
* updateStrategy: "appVersion",
|
|
255
|
-
* requestHeaders: {
|
|
256
|
-
* "x-api-key": "<your-api-key>",
|
|
257
|
-
* },
|
|
258
|
-
* })(App);
|
|
259
|
-
* ```
|
|
260
|
-
*/
|
|
261
|
-
wrap: (options: HotUpdaterOptions) => {
|
|
262
|
-
const normalizedOptions = normalizeOptions(options);
|
|
263
|
-
reportMixedConfiguration("wrap");
|
|
264
|
-
configureGlobal(normalizedOptions, options);
|
|
142
|
+
/**
|
|
143
|
+
* Configures how `hotUpdater.reload()` behaves.
|
|
144
|
+
*
|
|
145
|
+
* This can be called unconditionally on both platforms.
|
|
146
|
+
* The default is `processRestart`.
|
|
147
|
+
*
|
|
148
|
+
* - `reload`: built-in React Native reload on both platforms
|
|
149
|
+
* - `processRestart`: Android process restart, iOS behaves like normal reload
|
|
150
|
+
* - `custom`: run a custom JS handler on both platforms
|
|
151
|
+
*/
|
|
152
|
+
setReloadBehavior,
|
|
265
153
|
|
|
266
|
-
|
|
267
|
-
|
|
154
|
+
/**
|
|
155
|
+
* Returns whether an update has finished downloading in this app session.
|
|
156
|
+
*
|
|
157
|
+
* When it returns true, calling `hotUpdater.reload()` (or restarting the app)
|
|
158
|
+
* will apply the downloaded update bundle.
|
|
159
|
+
*
|
|
160
|
+
* - Derived from `progress` reaching 1.0
|
|
161
|
+
* - Resets to false when a new download starts (progress < 1)
|
|
162
|
+
*
|
|
163
|
+
* @returns {boolean} True if a downloaded update is ready to apply
|
|
164
|
+
* @example
|
|
165
|
+
* ```ts
|
|
166
|
+
* if (hotUpdater.isUpdateDownloaded()) {
|
|
167
|
+
* await hotUpdater.reload();
|
|
168
|
+
* }
|
|
169
|
+
* ```
|
|
170
|
+
*/
|
|
171
|
+
isUpdateDownloaded: () => hotUpdaterStore.getSnapshot().isUpdateDownloaded,
|
|
172
|
+
|
|
173
|
+
/**
|
|
174
|
+
* Fetches the current app version.
|
|
175
|
+
*/
|
|
176
|
+
getAppVersion,
|
|
268
177
|
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
*
|
|
272
|
-
* Use this for manual update flows in runtimes where a root component HOC
|
|
273
|
-
* is not convenient. Use this instead of wrapping the root component.
|
|
274
|
-
*
|
|
275
|
-
* @example
|
|
276
|
-
* ```tsx
|
|
277
|
-
* HotUpdater.init({
|
|
278
|
-
* baseURL: "<your-update-server-url>",
|
|
279
|
-
* });
|
|
280
|
-
*
|
|
281
|
-
* export default App;
|
|
282
|
-
* ```
|
|
283
|
-
*/
|
|
284
|
-
init: (options: HotUpdaterInitOptions): void => {
|
|
285
|
-
const normalizedOptions = normalizeInitOptions(options);
|
|
178
|
+
/** Reads the active and stable Release/Bundle state. */
|
|
179
|
+
getActiveUpdateState: async () => getPublicActiveUpdateState(),
|
|
286
180
|
|
|
287
|
-
|
|
288
|
-
|
|
181
|
+
/**
|
|
182
|
+
* Returns the selected update ID, matching the ID shown in the console.
|
|
183
|
+
* A staged update can change this ID before the app reloads.
|
|
184
|
+
*/
|
|
185
|
+
getBundleId: getUpdateId,
|
|
289
186
|
|
|
290
|
-
|
|
291
|
-
|
|
187
|
+
/** Returns the minimum bundle ID based on the native app build time. */
|
|
188
|
+
getMinBundleId,
|
|
292
189
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
190
|
+
/**
|
|
191
|
+
* Fetches the current manifest for the active bundle.
|
|
192
|
+
*/
|
|
193
|
+
getManifest,
|
|
297
194
|
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
195
|
+
/**
|
|
196
|
+
* Fetches the current channel of the app.
|
|
197
|
+
*
|
|
198
|
+
* If no channel is specified, the app is assigned to the 'production' channel.
|
|
199
|
+
*
|
|
200
|
+
* @returns {string} The current release channel of the app
|
|
201
|
+
* @default "production"
|
|
202
|
+
* @example
|
|
203
|
+
* ```ts
|
|
204
|
+
* const channel = hotUpdater.getChannel();
|
|
205
|
+
* console.log(`Current channel: ${channel}`);
|
|
206
|
+
* ```
|
|
207
|
+
*/
|
|
208
|
+
getChannel,
|
|
309
209
|
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
* await HotUpdater.reload();
|
|
324
|
-
* }
|
|
325
|
-
* ```
|
|
326
|
-
*/
|
|
327
|
-
isUpdateDownloaded: () => hotUpdaterStore.getSnapshot().isUpdateDownloaded,
|
|
210
|
+
/**
|
|
211
|
+
* Fetches the build-time default channel of the app.
|
|
212
|
+
*
|
|
213
|
+
* This value does not change when a runtime channel override is active.
|
|
214
|
+
*
|
|
215
|
+
* @returns {string} The default release channel embedded in the app
|
|
216
|
+
* @example
|
|
217
|
+
* ```ts
|
|
218
|
+
* const defaultChannel = hotUpdater.getDefaultChannel();
|
|
219
|
+
* console.log(`Default channel: ${defaultChannel}`);
|
|
220
|
+
* ```
|
|
221
|
+
*/
|
|
222
|
+
getDefaultChannel,
|
|
328
223
|
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
224
|
+
/**
|
|
225
|
+
* Returns whether the app is currently using a runtime channel override.
|
|
226
|
+
*
|
|
227
|
+
* @returns {boolean} true when a non-default channel has been applied
|
|
228
|
+
*/
|
|
229
|
+
isChannelSwitched,
|
|
333
230
|
|
|
334
|
-
|
|
335
|
-
|
|
231
|
+
/**
|
|
232
|
+
* Sets the persisted cohort used for rollout calculations.
|
|
233
|
+
* Call `getCohort()` first if you need to restore the initial value later.
|
|
234
|
+
*/
|
|
235
|
+
setCohort,
|
|
336
236
|
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
getBundleId: getUpdateId,
|
|
237
|
+
/**
|
|
238
|
+
* Gets the persisted cohort used for rollout calculations.
|
|
239
|
+
*/
|
|
240
|
+
getCohort,
|
|
342
241
|
|
|
343
|
-
|
|
344
|
-
|
|
242
|
+
/**
|
|
243
|
+
* Adds a listener to HotUpdater events.
|
|
244
|
+
*
|
|
245
|
+
* @param {keyof HotUpdaterEvent} eventName - The name of the event to listen for
|
|
246
|
+
* @param {(event: HotUpdaterEvent[T]) => void} listener - The callback function to handle the event
|
|
247
|
+
* @returns {() => void} A cleanup function that removes the event listener
|
|
248
|
+
*
|
|
249
|
+
* @example
|
|
250
|
+
* ```ts
|
|
251
|
+
* const unsubscribe = hotUpdater.addListener("onProgress", ({ progress }) => {
|
|
252
|
+
* console.log(`Update progress: ${progress * 100}%`);
|
|
253
|
+
* });
|
|
254
|
+
*
|
|
255
|
+
* // Unsubscribe when no longer needed
|
|
256
|
+
* unsubscribe();
|
|
257
|
+
* ```
|
|
258
|
+
*/
|
|
259
|
+
addListener,
|
|
345
260
|
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
261
|
+
/**
|
|
262
|
+
* Clears the runtime channel override and restores the original bundle.
|
|
263
|
+
*
|
|
264
|
+
* @returns {Promise<boolean>} Resolves with true if reset was successful
|
|
265
|
+
*/
|
|
266
|
+
resetChannel: async () => {
|
|
267
|
+
const ok = await resetChannel();
|
|
268
|
+
if (ok) {
|
|
269
|
+
hotUpdaterStore.setState({
|
|
270
|
+
artifactType: null,
|
|
271
|
+
details: null,
|
|
272
|
+
isUpdateDownloaded: false,
|
|
273
|
+
progress: 0,
|
|
274
|
+
});
|
|
275
|
+
}
|
|
276
|
+
return ok;
|
|
277
|
+
},
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Fetches the fingerprint of the app.
|
|
281
|
+
*
|
|
282
|
+
* @returns {string} The fingerprint of the app
|
|
283
|
+
*
|
|
284
|
+
* @example
|
|
285
|
+
* ```ts
|
|
286
|
+
* const fingerprint = hotUpdater.getFingerprintHash();
|
|
287
|
+
* console.log(`Fingerprint: ${fingerprint}`);
|
|
288
|
+
* ```
|
|
289
|
+
*/
|
|
290
|
+
getFingerprintHash,
|
|
350
291
|
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
*
|
|
356
|
-
* @returns {string} The current release channel of the app
|
|
357
|
-
* @default "production"
|
|
358
|
-
* @example
|
|
359
|
-
* ```ts
|
|
360
|
-
* const channel = HotUpdater.getChannel();
|
|
361
|
-
* console.log(`Current channel: ${channel}`);
|
|
362
|
-
* ```
|
|
363
|
-
*/
|
|
364
|
-
getChannel,
|
|
292
|
+
/**
|
|
293
|
+
* Fetches the persisted install id for this app installation.
|
|
294
|
+
*/
|
|
295
|
+
getInstallId,
|
|
365
296
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
*
|
|
371
|
-
* @returns {string} The default release channel embedded in the app
|
|
372
|
-
* @example
|
|
373
|
-
* ```ts
|
|
374
|
-
* const defaultChannel = HotUpdater.getDefaultChannel();
|
|
375
|
-
* console.log(`Default channel: ${defaultChannel}`);
|
|
376
|
-
* ```
|
|
377
|
-
*/
|
|
378
|
-
getDefaultChannel,
|
|
297
|
+
/**
|
|
298
|
+
* Reads the native launch report for the current process.
|
|
299
|
+
*/
|
|
300
|
+
notifyAppReady,
|
|
379
301
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
302
|
+
/**
|
|
303
|
+
* Gets the list of bundle IDs that have been marked as crashed.
|
|
304
|
+
* These bundles will be rejected if attempted to install again.
|
|
305
|
+
*
|
|
306
|
+
* @returns {string[]} Array of crashed bundle IDs
|
|
307
|
+
*
|
|
308
|
+
* @example
|
|
309
|
+
* ```ts
|
|
310
|
+
* const crashedBundles = hotUpdater.getCrashHistory();
|
|
311
|
+
* console.log("Crashed bundles:", crashedBundles);
|
|
312
|
+
* ```
|
|
313
|
+
*/
|
|
314
|
+
getCrashHistory,
|
|
386
315
|
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
316
|
+
/**
|
|
317
|
+
* Clears the crashed bundle history, allowing previously crashed bundles
|
|
318
|
+
* to be installed again.
|
|
319
|
+
*
|
|
320
|
+
* @returns {boolean} true if clearing was successful
|
|
321
|
+
*
|
|
322
|
+
* @example
|
|
323
|
+
* ```ts
|
|
324
|
+
* // Clear crash history to allow retrying a previously failed bundle
|
|
325
|
+
* hotUpdater.clearCrashHistory();
|
|
326
|
+
* ```
|
|
327
|
+
*/
|
|
328
|
+
clearCrashHistory,
|
|
329
|
+
};
|
|
392
330
|
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
331
|
+
/** What an instance's own methods use: its server, settings, and launch. */
|
|
332
|
+
interface InstanceConfig {
|
|
333
|
+
readonly client: HotUpdaterHttpClient;
|
|
334
|
+
readonly requestHeaders?: Record<string, string>;
|
|
335
|
+
readonly requestTimeout?: number;
|
|
336
|
+
readonly onError?: (error: unknown) => void;
|
|
337
|
+
readonly launch: LaunchReporter;
|
|
338
|
+
}
|
|
397
339
|
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
* unsubscribe();
|
|
413
|
-
* ```
|
|
414
|
-
*/
|
|
415
|
-
addListener,
|
|
340
|
+
/** The methods that use the instance's own configuration and plugins. */
|
|
341
|
+
const createConfiguredMethods = (config: InstanceConfig) => {
|
|
342
|
+
const check = (options: CheckForUpdateOptions) =>
|
|
343
|
+
checkForUpdate({
|
|
344
|
+
...options,
|
|
345
|
+
client: config.client,
|
|
346
|
+
emit: config.launch.emit,
|
|
347
|
+
requestHeaders: {
|
|
348
|
+
...config.requestHeaders,
|
|
349
|
+
...options.requestHeaders,
|
|
350
|
+
},
|
|
351
|
+
requestTimeout: options.requestTimeout ?? config.requestTimeout,
|
|
352
|
+
onError: options.onError ?? config.onError,
|
|
353
|
+
});
|
|
416
354
|
|
|
355
|
+
return {
|
|
417
356
|
/**
|
|
418
|
-
*
|
|
357
|
+
* Checks for an update, with this instance's server and request
|
|
358
|
+
* settings.
|
|
419
359
|
*
|
|
420
360
|
* @param {Object} config - Update check configuration
|
|
421
361
|
* @param {string} [config.channel] - Optional channel override for this update check
|
|
@@ -425,7 +365,7 @@ function createHotUpdaterClient() {
|
|
|
425
365
|
*
|
|
426
366
|
* @example
|
|
427
367
|
* ```ts
|
|
428
|
-
* const updateInfo = await
|
|
368
|
+
* const updateInfo = await hotUpdater.checkForUpdate({
|
|
429
369
|
* updateStrategy: "appVersion",
|
|
430
370
|
* requestHeaders: {
|
|
431
371
|
* "x-api-key": "<your-api-key>",
|
|
@@ -439,40 +379,22 @@ function createHotUpdaterClient() {
|
|
|
439
379
|
*
|
|
440
380
|
* await updateInfo.updateBundle();
|
|
441
381
|
* if (updateInfo.shouldForceUpdate) {
|
|
442
|
-
* await
|
|
382
|
+
* await hotUpdater.reload();
|
|
443
383
|
* }
|
|
444
384
|
* ```
|
|
445
385
|
*/
|
|
446
|
-
checkForUpdate:
|
|
447
|
-
const client = ensureGlobalClient("checkForUpdate");
|
|
448
|
-
|
|
449
|
-
const mergedConfig: InternalCheckForUpdateOptions = {
|
|
450
|
-
...config,
|
|
451
|
-
insights: globalConfig.insights,
|
|
452
|
-
client,
|
|
453
|
-
requestHeaders: {
|
|
454
|
-
...globalConfig.requestHeaders,
|
|
455
|
-
...config.requestHeaders,
|
|
456
|
-
},
|
|
457
|
-
requestTimeout: config.requestTimeout ?? globalConfig.requestTimeout,
|
|
458
|
-
onError: config.onError ?? globalConfig.onError,
|
|
459
|
-
};
|
|
460
|
-
|
|
461
|
-
return checkForUpdate(mergedConfig);
|
|
462
|
-
},
|
|
386
|
+
checkForUpdate: check,
|
|
463
387
|
|
|
464
388
|
/**
|
|
465
389
|
* Updates the bundle of the app.
|
|
466
390
|
*
|
|
467
391
|
* @param {UpdateBundleParams} params - Parameters object required for bundle update
|
|
468
392
|
* @param {string} params.bundleId - The bundle ID of the app
|
|
469
|
-
* @param {string|null} params.fileUrl - The URL of the zip file
|
|
470
|
-
*
|
|
471
393
|
* @returns {Promise<boolean>} Whether the update was successful
|
|
472
394
|
*
|
|
473
395
|
* @example
|
|
474
396
|
* ```ts
|
|
475
|
-
* const updateInfo = await
|
|
397
|
+
* const updateInfo = await hotUpdater.checkForUpdate({
|
|
476
398
|
* updateStrategy: "appVersion",
|
|
477
399
|
* requestHeaders: {
|
|
478
400
|
* "x-api-key": "<your-api-key>",
|
|
@@ -487,98 +409,164 @@ function createHotUpdaterClient() {
|
|
|
487
409
|
*
|
|
488
410
|
* await updateInfo.updateBundle();
|
|
489
411
|
* if (updateInfo.shouldForceUpdate) {
|
|
490
|
-
* await
|
|
412
|
+
* await hotUpdater.reload();
|
|
491
413
|
* }
|
|
492
414
|
* ```
|
|
493
415
|
*/
|
|
494
|
-
updateBundle: (params: UpdateParams) => {
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
const
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
416
|
+
updateBundle: async (params: UpdateParams) => {
|
|
417
|
+
const fromBundleId = getBundleId();
|
|
418
|
+
const state = getActiveUpdateState();
|
|
419
|
+
const active = state.activeSelection;
|
|
420
|
+
const fromReleaseId =
|
|
421
|
+
active?.bundleId === fromBundleId
|
|
422
|
+
? active.releaseId
|
|
423
|
+
: state.stableSelection?.bundleId === fromBundleId
|
|
424
|
+
? state.stableSelection.releaseId
|
|
425
|
+
: null;
|
|
426
|
+
const channel = params.channel ?? getChannel();
|
|
427
|
+
const strategyOf = (scopeKey: string | null | undefined) =>
|
|
428
|
+
scopeKey?.startsWith("v1:fingerprint:") ? "fingerprint" : "appVersion";
|
|
429
|
+
let delivery: Awaited<ReturnType<typeof stageBundle>>;
|
|
430
|
+
try {
|
|
431
|
+
delivery = await stageBundle(params);
|
|
432
|
+
} catch (error) {
|
|
433
|
+
reportUpdateError(config.launch.emit, error, "download", undefined, {
|
|
434
|
+
bundleId: fromBundleId,
|
|
435
|
+
channel,
|
|
436
|
+
targetBundleId: params.bundleId,
|
|
437
|
+
targetReleaseId:
|
|
438
|
+
(params.selection as { releaseId?: string | null } | undefined)
|
|
439
|
+
?.releaseId ?? null,
|
|
440
|
+
updateStrategy: strategyOf(
|
|
441
|
+
(params.selection as { scopeKey?: string | null } | undefined)
|
|
442
|
+
?.scopeKey,
|
|
443
|
+
),
|
|
444
|
+
});
|
|
445
|
+
throw error;
|
|
446
|
+
}
|
|
447
|
+
if (delivery !== null && params.bundleId !== fromBundleId) {
|
|
448
|
+
config.launch.emit("onBundleDownloaded", () => {
|
|
449
|
+
const selection = getActiveUpdateState().activeSelection;
|
|
450
|
+
return {
|
|
451
|
+
channel,
|
|
452
|
+
fromBundleId,
|
|
453
|
+
fromReleaseId,
|
|
454
|
+
toBundleId: params.bundleId,
|
|
455
|
+
toReleaseId: selection?.releaseId ?? null,
|
|
456
|
+
updateStrategy: strategyOf(selection?.scopeKey),
|
|
457
|
+
...delivery,
|
|
458
|
+
};
|
|
514
459
|
});
|
|
515
460
|
}
|
|
516
|
-
return
|
|
461
|
+
return true;
|
|
517
462
|
},
|
|
518
463
|
|
|
519
464
|
/**
|
|
520
|
-
*
|
|
521
|
-
*
|
|
522
|
-
*
|
|
465
|
+
* Wraps the app's root: when it mounts, it checks for an update with
|
|
466
|
+
* this instance's configuration, downloads one, and reloads for a
|
|
467
|
+
* forced update. A `fallbackComponent` replaces the root until the
|
|
468
|
+
* check and a forced update finish.
|
|
523
469
|
*
|
|
524
470
|
* @example
|
|
525
|
-
* ```
|
|
526
|
-
*
|
|
527
|
-
*
|
|
471
|
+
* ```tsx
|
|
472
|
+
* export default hotUpdater.wrap({
|
|
473
|
+
* updateStrategy: "appVersion",
|
|
474
|
+
* fallbackComponent: ({ progress }) => <Splash progress={progress} />,
|
|
475
|
+
* })(App);
|
|
528
476
|
* ```
|
|
529
477
|
*/
|
|
530
|
-
|
|
531
|
-
|
|
532
|
-
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
*/
|
|
540
|
-
setUser,
|
|
541
|
-
|
|
542
|
-
/**
|
|
543
|
-
* Reads the native launch report for the current process.
|
|
544
|
-
*/
|
|
545
|
-
notifyAppReady,
|
|
478
|
+
wrap: (options: HotUpdaterWrapOptions) =>
|
|
479
|
+
wrap({
|
|
480
|
+
...options,
|
|
481
|
+
checkForUpdate: check,
|
|
482
|
+
appReady: () => config.launch.appReady,
|
|
483
|
+
onError: (error) => config.onError?.(error),
|
|
484
|
+
}),
|
|
485
|
+
};
|
|
486
|
+
};
|
|
546
487
|
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
*
|
|
551
|
-
* @returns {string[]} Array of crashed bundle IDs
|
|
552
|
-
*
|
|
553
|
-
* @example
|
|
554
|
-
* ```ts
|
|
555
|
-
* const crashedBundles = HotUpdater.getCrashHistory();
|
|
556
|
-
* console.log("Crashed bundles:", crashedBundles);
|
|
557
|
-
* ```
|
|
558
|
-
*/
|
|
559
|
-
getCrashHistory,
|
|
488
|
+
/** The methods of every instance `HotUpdater.init` returns. */
|
|
489
|
+
export type HotUpdaterCore = typeof nativeMethods &
|
|
490
|
+
ReturnType<typeof createConfiguredMethods>;
|
|
560
491
|
|
|
561
|
-
|
|
562
|
-
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
|
|
566
|
-
|
|
567
|
-
|
|
568
|
-
|
|
569
|
-
|
|
570
|
-
|
|
571
|
-
|
|
572
|
-
|
|
573
|
-
|
|
574
|
-
|
|
575
|
-
|
|
492
|
+
/**
|
|
493
|
+
* The instance `HotUpdater.init` returns: HotUpdater's methods, and each
|
|
494
|
+
* plugin's API under the plugin's id.
|
|
495
|
+
*/
|
|
496
|
+
export type HotUpdaterInstance<
|
|
497
|
+
TPlugins extends readonly HotUpdaterClientPlugin[] = readonly [],
|
|
498
|
+
> = Readonly<HotUpdaterCore> & ClientPluginApis<TPlugins>;
|
|
499
|
+
|
|
500
|
+
export const HotUpdater = {
|
|
501
|
+
/**
|
|
502
|
+
* Creates the app's HotUpdater instance: the update server, its request
|
|
503
|
+
* settings, and the client plugins. Each call returns an independent
|
|
504
|
+
* instance with its own configuration and plugins, so create one, at the
|
|
505
|
+
* top level of a module, and export it.
|
|
506
|
+
*
|
|
507
|
+
* The instance has every HotUpdater method, such as `wrap`,
|
|
508
|
+
* `checkForUpdate`, and `reload`, and each plugin's API under the
|
|
509
|
+
* plugin's id, such as `hotUpdater.remoteConfig` for `remoteConfig()`.
|
|
510
|
+
*
|
|
511
|
+
* @example
|
|
512
|
+
* ```tsx
|
|
513
|
+
* export const hotUpdater = HotUpdater.init({
|
|
514
|
+
* baseURL: "<your-update-server-url>",
|
|
515
|
+
* plugins: [remoteConfig({ defaults: { welcome_message: "Hi" } })],
|
|
516
|
+
* });
|
|
517
|
+
*
|
|
518
|
+
* hotUpdater.remoteConfig.getString("welcome_message");
|
|
519
|
+
* ```
|
|
520
|
+
*/
|
|
521
|
+
init: <
|
|
522
|
+
const TPlugins extends readonly HotUpdaterClientPlugin[] = readonly [],
|
|
523
|
+
>(
|
|
524
|
+
options: HotUpdaterInitOptions<TPlugins>,
|
|
525
|
+
): HotUpdaterInstance<TPlugins> => {
|
|
526
|
+
const {
|
|
527
|
+
baseURL,
|
|
528
|
+
plugins,
|
|
529
|
+
requestHeaders,
|
|
530
|
+
requestTimeout,
|
|
531
|
+
onError,
|
|
532
|
+
onNotifyAppReady,
|
|
533
|
+
} = options;
|
|
534
|
+
if (!baseURL) throw createMissingNetworkConfigError();
|
|
535
|
+
|
|
536
|
+
const host = createAppPluginHost();
|
|
537
|
+
const launch = createLaunchReporter(host);
|
|
538
|
+
const instance = {
|
|
539
|
+
...nativeMethods,
|
|
540
|
+
...createConfiguredMethods({
|
|
541
|
+
client: createHttpClient(baseURL, (response) => {
|
|
542
|
+
launch.emit("onHttpResponse", () => response);
|
|
543
|
+
}),
|
|
544
|
+
requestHeaders,
|
|
545
|
+
requestTimeout,
|
|
546
|
+
onError,
|
|
547
|
+
launch,
|
|
548
|
+
}),
|
|
549
|
+
};
|
|
550
|
+
const reservedIds = new Set([...Object.keys(instance), "init"]);
|
|
551
|
+
for (const plugin of plugins ?? []) {
|
|
552
|
+
if (reservedIds.has(plugin.id)) {
|
|
553
|
+
throw new Error(
|
|
554
|
+
`[HotUpdater] A plugin cannot use the id "${plugin.id}": the HotUpdater instance has its own "${plugin.id}".`,
|
|
555
|
+
);
|
|
556
|
+
}
|
|
557
|
+
}
|
|
576
558
|
|
|
577
|
-
|
|
578
|
-
|
|
579
|
-
|
|
580
|
-
|
|
581
|
-
|
|
559
|
+
// Plugins are set up before the instance reads the launch they observe.
|
|
560
|
+
const apis = host.configurePlugins(plugins, {
|
|
561
|
+
baseURL,
|
|
562
|
+
requestHeaders,
|
|
563
|
+
requestTimeout,
|
|
564
|
+
onError,
|
|
565
|
+
});
|
|
566
|
+
void launch.read({ onNotifyAppReady, onError });
|
|
567
|
+
return Object.freeze({
|
|
568
|
+
...instance,
|
|
569
|
+
...apis,
|
|
570
|
+
}) as HotUpdaterInstance<TPlugins>;
|
|
571
|
+
},
|
|
582
572
|
};
|
|
583
|
-
|
|
584
|
-
export const HotUpdater: HotUpdaterClient = createHotUpdaterClient();
|