@hot-updater/react-native 1.0.0-rc.15 → 1.0.0-rc.17
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/src/main/java/com/hotupdater/BundleFileStorageService.kt +491 -388
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +5 -11
- package/android/src/main/java/com/hotupdater/FileManagerService.kt +45 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +290 -12
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +35 -19
- 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 +110 -52
- 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/newarch/HotUpdaterModule.kt +74 -69
- package/android/src/oldarch/HotUpdaterModule.kt +63 -59
- package/android/src/oldarch/HotUpdaterSpec.kt +4 -6
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +1 -1
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +446 -61
- package/android/src/test/java/com/hotupdater/HotUpdaterExceptionTest.kt +220 -0
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +19 -27
- package/android/src/test/java/com/hotupdater/InstallIdentityServiceTest.kt +71 -0
- package/android/src/test/java/com/hotupdater/KeyValueStorageServiceTest.kt +106 -0
- package/android/src/test/java/com/hotupdater/NoBackupContext.kt +11 -0
- package/android/src/test/java/com/hotupdater/OkHttpDownloadServiceTest.kt +309 -23
- package/android/src/test/java/com/hotupdater/PreviousProcessExitTest.kt +57 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +238 -157
- package/ios/HotUpdater/Internal/BundleMetadata.swift +3 -53
- package/ios/HotUpdater/Internal/FileManagerService.swift +48 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +8 -18
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +48 -29
- package/ios/HotUpdater/Internal/KeyValueStorageService.swift +71 -0
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +108 -1
- package/ios/HotUpdater/Internal/UpdateFailure.swift +390 -0
- package/lib/commonjs/appReady.js +111 -0
- package/lib/commonjs/appReady.js.map +1 -0
- package/lib/commonjs/appReady.spec.js +360 -0
- package/lib/commonjs/appReady.spec.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
- package/lib/commonjs/appReady.test-utils.js.map +1 -0
- package/lib/commonjs/baseURL.js +16 -0
- package/lib/commonjs/baseURL.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +104 -56
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +337 -74
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/commonjs/clientPlugin.js +49 -0
- package/lib/commonjs/clientPlugin.js.map +1 -0
- package/lib/commonjs/entryImportGraph.spec.js +50 -0
- package/lib/commonjs/entryImportGraph.spec.js.map +1 -0
- package/lib/commonjs/fetchJSON.js +2 -6
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/httpClient.js +15 -67
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/httpClient.spec.js +26 -9
- package/lib/commonjs/httpClient.spec.js.map +1 -1
- package/lib/commonjs/index.js +49 -25
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +126 -40
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +67 -48
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +80 -58
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/pluginHost.js +208 -0
- package/lib/commonjs/pluginHost.js.map +1 -0
- package/lib/commonjs/pluginHost.spec.js +292 -0
- package/lib/commonjs/pluginHost.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/eventId.js +129 -0
- package/lib/commonjs/plugins/insights/eventId.js.map +1 -0
- package/lib/commonjs/plugins/insights/eventId.spec.js +47 -0
- package/lib/commonjs/plugins/insights/eventId.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/index.js +272 -0
- package/lib/commonjs/plugins/insights/index.js.map +1 -0
- package/lib/commonjs/plugins/insights/insights.spec.js +640 -0
- package/lib/commonjs/plugins/insights/insights.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/sender.js +128 -0
- package/lib/commonjs/plugins/insights/sender.js.map +1 -0
- package/lib/commonjs/plugins/insights/sender.spec.js +265 -0
- package/lib/commonjs/plugins/insights/sender.spec.js.map +1 -0
- package/lib/commonjs/plugins/insights/state.js +145 -0
- package/lib/commonjs/plugins/insights/state.js.map +1 -0
- package/lib/commonjs/releaseCatalogCache.js +13 -2
- package/lib/commonjs/releaseCatalogCache.js.map +1 -1
- package/lib/commonjs/releaseCatalogCache.spec.js +18 -0
- package/lib/commonjs/releaseCatalogCache.spec.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/updateError.js +132 -0
- package/lib/commonjs/updateError.js.map +1 -0
- package/lib/commonjs/updateError.spec.js +149 -0
- package/lib/commonjs/updateError.spec.js.map +1 -0
- package/lib/commonjs/wrap.js +43 -25
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.progress.spec.js +195 -0
- package/lib/commonjs/wrap.progress.spec.js.map +1 -0
- package/lib/commonjs/wrap.spec.js +94 -230
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/appReady.js +103 -0
- package/lib/module/appReady.js.map +1 -0
- package/lib/module/appReady.spec.js +359 -0
- package/lib/module/appReady.spec.js.map +1 -0
- package/lib/module/{notifyAppReadyInsights.test-utils.js → appReady.test-utils.js} +4 -3
- package/lib/module/appReady.test-utils.js.map +1 -0
- package/lib/module/baseURL.js +11 -0
- package/lib/module/baseURL.js.map +1 -0
- package/lib/module/checkForUpdate.js +103 -57
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +337 -74
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/module/clientPlugin.js +44 -0
- package/lib/module/clientPlugin.js.map +1 -0
- package/lib/module/entryImportGraph.spec.js +50 -0
- package/lib/module/entryImportGraph.spec.js.map +1 -0
- package/lib/module/fetchJSON.js +2 -6
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/httpClient.js +14 -66
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/httpClient.spec.js +26 -9
- package/lib/module/httpClient.spec.js.map +1 -1
- package/lib/module/index.js +44 -27
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +127 -41
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +63 -44
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +80 -58
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/pluginHost.js +200 -0
- package/lib/module/pluginHost.js.map +1 -0
- package/lib/module/pluginHost.spec.js +291 -0
- package/lib/module/pluginHost.spec.js.map +1 -0
- package/lib/module/plugins/insights/eventId.js +122 -0
- package/lib/module/plugins/insights/eventId.js.map +1 -0
- package/lib/module/plugins/insights/eventId.spec.js +47 -0
- package/lib/module/plugins/insights/eventId.spec.js.map +1 -0
- package/lib/module/plugins/insights/index.js +268 -0
- package/lib/module/plugins/insights/index.js.map +1 -0
- package/lib/module/plugins/insights/insights.spec.js +639 -0
- package/lib/module/plugins/insights/insights.spec.js.map +1 -0
- package/lib/module/plugins/insights/sender.js +123 -0
- package/lib/module/plugins/insights/sender.js.map +1 -0
- package/lib/module/plugins/insights/sender.spec.js +265 -0
- package/lib/module/plugins/insights/sender.spec.js.map +1 -0
- package/lib/module/plugins/insights/state.js +139 -0
- package/lib/module/plugins/insights/state.js.map +1 -0
- package/lib/module/releaseCatalogCache.js +13 -2
- package/lib/module/releaseCatalogCache.js.map +1 -1
- package/lib/module/releaseCatalogCache.spec.js +18 -0
- package/lib/module/releaseCatalogCache.spec.js.map +1 -1
- package/lib/module/sdkVersion.js +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/updateError.js +126 -0
- package/lib/module/updateError.js.map +1 -0
- package/lib/module/updateError.spec.js +149 -0
- package/lib/module/updateError.spec.js.map +1 -0
- package/lib/module/wrap.js +43 -25
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.progress.spec.js +196 -0
- package/lib/module/wrap.progress.spec.js.map +1 -0
- package/lib/module/wrap.spec.js +93 -229
- package/lib/module/wrap.spec.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/appReady.test-utils.d.ts +9 -0
- package/lib/typescript/commonjs/appReady.test-utils.d.ts.map +1 -0
- package/lib/typescript/commonjs/baseURL.d.ts +4 -0
- package/lib/typescript/commonjs/baseURL.d.ts.map +1 -0
- package/lib/typescript/commonjs/checkForUpdate.d.ts +15 -2
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/clientPlugin.d.ts +185 -0
- package/lib/typescript/commonjs/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts +2 -3
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +2 -30
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +3 -6
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +29 -15
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/pluginHost.d.ts +29 -0
- package/lib/typescript/commonjs/pluginHost.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/eventId.d.ts +18 -0
- package/lib/typescript/commonjs/plugins/insights/eventId.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/index.d.ts +40 -0
- package/lib/typescript/commonjs/plugins/insights/index.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/sender.d.ts +74 -0
- package/lib/typescript/commonjs/plugins/insights/sender.d.ts.map +1 -0
- package/lib/typescript/commonjs/plugins/insights/state.d.ts +46 -0
- package/lib/typescript/commonjs/plugins/insights/state.d.ts.map +1 -0
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts +5 -1
- package/lib/typescript/commonjs/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +34 -12
- package/lib/typescript/commonjs/specs/NativeHotUpdater.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 -5
- 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/appReady.test-utils.d.ts +9 -0
- package/lib/typescript/module/appReady.test-utils.d.ts.map +1 -0
- package/lib/typescript/module/baseURL.d.ts +4 -0
- package/lib/typescript/module/baseURL.d.ts.map +1 -0
- package/lib/typescript/module/checkForUpdate.d.ts +15 -2
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/clientPlugin.d.ts +185 -0
- package/lib/typescript/module/clientPlugin.d.ts.map +1 -0
- package/lib/typescript/module/fetchJSON.d.ts +2 -3
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +2 -30
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +3 -6
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +29 -15
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/pluginHost.d.ts +29 -0
- package/lib/typescript/module/pluginHost.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/eventId.d.ts +18 -0
- package/lib/typescript/module/plugins/insights/eventId.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/index.d.ts +40 -0
- package/lib/typescript/module/plugins/insights/index.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/sender.d.ts +74 -0
- package/lib/typescript/module/plugins/insights/sender.d.ts.map +1 -0
- package/lib/typescript/module/plugins/insights/state.d.ts +46 -0
- package/lib/typescript/module/plugins/insights/state.d.ts.map +1 -0
- package/lib/typescript/module/releaseCatalogCache.d.ts +5 -1
- package/lib/typescript/module/releaseCatalogCache.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +34 -12
- package/lib/typescript/module/specs/NativeHotUpdater.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 -5
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +14 -2
- package/plugins/insights/package.json +8 -0
- package/src/appReady.spec.ts +393 -0
- package/src/{notifyAppReadyInsights.test-utils.ts → appReady.test-utils.ts} +7 -7
- package/src/appReady.ts +149 -0
- package/src/baseURL.ts +15 -0
- package/src/checkForUpdate.releaseCatalog.spec.ts +370 -76
- package/src/checkForUpdate.ts +135 -80
- package/src/clientPlugin.ts +231 -0
- package/src/entryImportGraph.spec.ts +65 -0
- package/src/fetchJSON.ts +3 -10
- package/src/httpClient.spec.ts +28 -9
- package/src/httpClient.ts +16 -109
- package/src/index.spec.ts +129 -36
- package/src/index.ts +67 -37
- package/src/native.spec.ts +98 -72
- package/src/native.ts +93 -77
- package/src/pluginHost.spec.ts +297 -0
- package/src/pluginHost.ts +262 -0
- package/src/plugins/insights/eventId.spec.ts +60 -0
- package/src/plugins/insights/eventId.ts +171 -0
- package/src/plugins/insights/index.ts +367 -0
- package/src/plugins/insights/insights.spec.ts +732 -0
- package/src/plugins/insights/sender.spec.ts +287 -0
- package/src/plugins/insights/sender.ts +221 -0
- package/src/plugins/insights/state.ts +184 -0
- package/src/releaseCatalogCache.spec.ts +22 -0
- package/src/releaseCatalogCache.ts +19 -4
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +34 -13
- package/src/updateError.spec.ts +144 -0
- package/src/updateError.ts +153 -0
- package/src/wrap.progress.spec.ts +232 -0
- package/src/wrap.spec.ts +100 -283
- package/src/wrap.tsx +57 -26
- package/src/wrap.types.ts +6 -5
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +0 -225
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.js +0 -188
- package/lib/commonjs/notifyAppReadyInsights.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +0 -378
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +0 -124
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +0 -224
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.js +0 -181
- package/lib/module/notifyAppReadyInsights.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.spec.js +0 -377
- package/lib/module/notifyAppReadyInsights.spec.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +0 -123
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +0 -25
- 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 -25
- 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/notifyAppReadyInsights.boundary.spec.ts +0 -242
- package/src/notifyAppReadyInsights.spec.ts +0 -362
- package/src/notifyAppReadyInsights.transport.spec.ts +0 -138
- package/src/notifyAppReadyInsights.ts +0 -293
package/src/httpClient.ts
CHANGED
|
@@ -6,10 +6,11 @@ import {
|
|
|
6
6
|
} from "@hot-updater/core";
|
|
7
7
|
import { canonicalizeAppVersion } from "@hot-updater/plugin-core";
|
|
8
8
|
|
|
9
|
+
import { resolveBaseURL } from "./baseURL";
|
|
9
10
|
import { fetchJSON, FetchJSONResponseError } from "./fetchJSON";
|
|
10
11
|
import { fetchReleaseCatalogWithCache } from "./releaseCatalogCache";
|
|
11
|
-
import { HOT_UPDATER_SDK_VERSION } from "./sdkVersion";
|
|
12
12
|
import type { HotUpdaterBaseURL } from "./types";
|
|
13
|
+
import { InvalidUpdateResponseError } from "./updateError";
|
|
13
14
|
|
|
14
15
|
export interface ReleaseCatalogRequest {
|
|
15
16
|
readonly platform: "ios" | "android";
|
|
@@ -28,69 +29,31 @@ export interface ArtifactRequest {
|
|
|
28
29
|
readonly requestTimeout?: number;
|
|
29
30
|
}
|
|
30
31
|
|
|
31
|
-
interface InsightsEventCommonParams {
|
|
32
|
-
readonly installId: string;
|
|
33
|
-
readonly userId?: string;
|
|
34
|
-
readonly username?: string;
|
|
35
|
-
readonly platform: "ios" | "android";
|
|
36
|
-
readonly appVersion: string;
|
|
37
|
-
readonly channel: string;
|
|
38
|
-
readonly cohort: string;
|
|
39
|
-
readonly fingerprintHash: string | null;
|
|
40
|
-
readonly fromReleaseId?: string | null;
|
|
41
|
-
readonly toReleaseId?: string | null;
|
|
42
|
-
readonly requestHeaders?: Record<string, string>;
|
|
43
|
-
readonly requestTimeout?: number;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
type InsightsTransitionEventParams = InsightsEventCommonParams & {
|
|
47
|
-
readonly type: "UPDATE_DOWNLOADED" | "UPDATE_APPLIED" | "RECOVERED";
|
|
48
|
-
readonly fromBundleId: string;
|
|
49
|
-
readonly toBundleId: string;
|
|
50
|
-
readonly updateStrategy: "fingerprint" | "appVersion";
|
|
51
|
-
};
|
|
52
|
-
|
|
53
|
-
type InsightsUnchangedEventParams = InsightsEventCommonParams & {
|
|
54
|
-
readonly type: "UNCHANGED";
|
|
55
|
-
readonly fromBundleId: null;
|
|
56
|
-
readonly toBundleId: string;
|
|
57
|
-
readonly updateStrategy: null;
|
|
58
|
-
};
|
|
59
|
-
|
|
60
|
-
export type InsightsEventParams =
|
|
61
|
-
| InsightsTransitionEventParams
|
|
62
|
-
| InsightsUnchangedEventParams;
|
|
63
|
-
|
|
64
32
|
export interface HotUpdaterHttpSession {
|
|
33
|
+
/** Resolves to null when the server says the scope has no catalog, so no update. */
|
|
65
34
|
fetchReleaseCatalog: (
|
|
66
35
|
params: ReleaseCatalogRequest,
|
|
67
|
-
) => Promise<ReleaseCatalog>;
|
|
36
|
+
) => Promise<ReleaseCatalog | null>;
|
|
68
37
|
resolveArtifact: (params: ArtifactRequest) => Promise<ArtifactInfo>;
|
|
69
|
-
sendInsightsEvent: (params: InsightsEventParams) => Promise<void>;
|
|
70
38
|
}
|
|
71
39
|
|
|
72
40
|
export interface HotUpdaterHttpClient {
|
|
73
41
|
createSession: () => Promise<HotUpdaterHttpSession>;
|
|
74
42
|
}
|
|
75
43
|
|
|
76
|
-
const resolveBaseURL = async (baseURL: HotUpdaterBaseURL): Promise<string> => {
|
|
77
|
-
const resolvedBaseURL =
|
|
78
|
-
typeof baseURL === "function" ? await baseURL() : baseURL;
|
|
79
|
-
|
|
80
|
-
if (!resolvedBaseURL) {
|
|
81
|
-
throw new Error("baseURL function must return a non-empty string");
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
return resolvedBaseURL.replace(/\/+$/, "");
|
|
85
|
-
};
|
|
86
|
-
|
|
87
44
|
const resolveArtifactUrl = (baseURL: string, value: string): string => {
|
|
88
45
|
if (/^https?:\/\//i.test(value)) {
|
|
89
|
-
|
|
46
|
+
try {
|
|
47
|
+
new URL(value);
|
|
48
|
+
} catch (error) {
|
|
49
|
+
throw new InvalidUpdateResponseError(`Invalid artifact URL: ${value}`, {
|
|
50
|
+
cause: error,
|
|
51
|
+
});
|
|
52
|
+
}
|
|
90
53
|
return value;
|
|
91
54
|
}
|
|
92
55
|
if (!value.startsWith("/storage/")) {
|
|
93
|
-
throw new
|
|
56
|
+
throw new InvalidUpdateResponseError(
|
|
94
57
|
"Artifact URLs must be absolute HTTP(S) URLs or client-relative storage paths.",
|
|
95
58
|
);
|
|
96
59
|
}
|
|
@@ -136,13 +99,13 @@ const requireArtifactProtocolV1 = (info: ArtifactInfo): ArtifactInfo => {
|
|
|
136
99
|
!info.manifestFileHash ||
|
|
137
100
|
(info.archiveUrl !== undefined && typeof info.archiveUrl !== "string")
|
|
138
101
|
) {
|
|
139
|
-
throw new
|
|
102
|
+
throw new InvalidUpdateResponseError(
|
|
140
103
|
`Server does not support artifact protocol ${ARTIFACT_PROTOCOL_VERSION}.`,
|
|
141
104
|
);
|
|
142
105
|
}
|
|
143
106
|
for (const asset of Object.values(info.assets)) {
|
|
144
107
|
if (!asset.file?.url || !asset.fileHash) {
|
|
145
|
-
throw new
|
|
108
|
+
throw new InvalidUpdateResponseError(
|
|
146
109
|
"Artifact protocol 1 requires an original file for every asset.",
|
|
147
110
|
);
|
|
148
111
|
}
|
|
@@ -150,63 +113,8 @@ const requireArtifactProtocolV1 = (info: ArtifactInfo): ArtifactInfo => {
|
|
|
150
113
|
return info;
|
|
151
114
|
};
|
|
152
115
|
|
|
153
|
-
const sendInsightsEvent = async (
|
|
154
|
-
baseURL: string,
|
|
155
|
-
params: InsightsEventParams,
|
|
156
|
-
): Promise<void> => {
|
|
157
|
-
const controller = new AbortController();
|
|
158
|
-
const timeoutId = setTimeout(() => {
|
|
159
|
-
controller.abort();
|
|
160
|
-
}, params.requestTimeout ?? 5000);
|
|
161
|
-
|
|
162
|
-
try {
|
|
163
|
-
const response = await fetch(`${baseURL}/events`, {
|
|
164
|
-
body: JSON.stringify({
|
|
165
|
-
appVersion: params.appVersion,
|
|
166
|
-
channel: params.channel,
|
|
167
|
-
cohort: params.cohort,
|
|
168
|
-
fingerprintHash: params.fingerprintHash,
|
|
169
|
-
fromBundleId: params.fromBundleId,
|
|
170
|
-
...(params.fromReleaseId === undefined
|
|
171
|
-
? {}
|
|
172
|
-
: { fromReleaseId: params.fromReleaseId }),
|
|
173
|
-
installId: params.installId,
|
|
174
|
-
platform: params.platform,
|
|
175
|
-
sdkVersion: HOT_UPDATER_SDK_VERSION,
|
|
176
|
-
toBundleId: params.toBundleId,
|
|
177
|
-
...(params.toReleaseId === undefined
|
|
178
|
-
? {}
|
|
179
|
-
: { toReleaseId: params.toReleaseId }),
|
|
180
|
-
type: params.type,
|
|
181
|
-
updateStrategy: params.updateStrategy,
|
|
182
|
-
...(params.userId != null ? { userId: params.userId } : {}),
|
|
183
|
-
...(params.username != null ? { username: params.username } : {}),
|
|
184
|
-
}),
|
|
185
|
-
headers: {
|
|
186
|
-
"Content-Type": "application/json",
|
|
187
|
-
...params.requestHeaders,
|
|
188
|
-
},
|
|
189
|
-
method: "POST",
|
|
190
|
-
signal: controller.signal,
|
|
191
|
-
});
|
|
192
|
-
|
|
193
|
-
if (response.status !== 204) {
|
|
194
|
-
throw new Error(
|
|
195
|
-
`Expected HTTP 204 from /events, received ${response.status}`,
|
|
196
|
-
);
|
|
197
|
-
}
|
|
198
|
-
} catch (error: unknown) {
|
|
199
|
-
if (error instanceof Error && error.name === "AbortError") {
|
|
200
|
-
throw new Error("Request timed out");
|
|
201
|
-
}
|
|
202
|
-
throw error;
|
|
203
|
-
} finally {
|
|
204
|
-
clearTimeout(timeoutId);
|
|
205
|
-
}
|
|
206
|
-
};
|
|
207
|
-
|
|
208
116
|
const createSession = (baseURL: string): HotUpdaterHttpSession => ({
|
|
209
|
-
fetchReleaseCatalog: async (params): Promise<ReleaseCatalog> => {
|
|
117
|
+
fetchReleaseCatalog: async (params): Promise<ReleaseCatalog | null> => {
|
|
210
118
|
const channelKey = encodeChannelKey(params.channel);
|
|
211
119
|
let strategyValue: string;
|
|
212
120
|
if (params.updateStrategy === "fingerprint") {
|
|
@@ -255,7 +163,7 @@ const createSession = (baseURL: string): HotUpdaterHttpSession => ({
|
|
|
255
163
|
});
|
|
256
164
|
} catch (error) {
|
|
257
165
|
if (error instanceof FetchJSONResponseError && error.status === 404) {
|
|
258
|
-
throw new
|
|
166
|
+
throw new InvalidUpdateResponseError(
|
|
259
167
|
`Server does not support artifact protocol ${ARTIFACT_PROTOCOL_VERSION}.`,
|
|
260
168
|
{ cause: error },
|
|
261
169
|
);
|
|
@@ -264,7 +172,6 @@ const createSession = (baseURL: string): HotUpdaterHttpSession => ({
|
|
|
264
172
|
}
|
|
265
173
|
return resolveArtifactUrls(baseURL, requireArtifactProtocolV1(info));
|
|
266
174
|
},
|
|
267
|
-
sendInsightsEvent: (params) => sendInsightsEvent(baseURL, params),
|
|
268
175
|
});
|
|
269
176
|
|
|
270
177
|
/** Creates the private HTTP client used by HotUpdater.init and HotUpdater.wrap. */
|
package/src/index.spec.ts
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
1
|
+
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type { HotUpdaterInitOptions, HotUpdaterOptions } from "./wrap";
|
|
4
4
|
|
|
@@ -31,6 +31,9 @@ const mocks = vi.hoisted(() => {
|
|
|
31
31
|
getInstallId: vi.fn(() => "install-id"),
|
|
32
32
|
getManifest: vi.fn(() => null),
|
|
33
33
|
getMinBundleId: vi.fn(() => "min-bundle-id"),
|
|
34
|
+
configurePlugins: vi.fn(),
|
|
35
|
+
emitAfterAppReady: vi.fn(),
|
|
36
|
+
reportUpdateError: vi.fn(),
|
|
34
37
|
init: vi.fn(),
|
|
35
38
|
isChannelSwitched: vi.fn(() => false),
|
|
36
39
|
notifyAppReady: vi.fn(() => ({ status: "UNCHANGED" as const })),
|
|
@@ -38,8 +41,7 @@ const mocks = vi.hoisted(() => {
|
|
|
38
41
|
resetChannel: vi.fn(),
|
|
39
42
|
setCohort: vi.fn(),
|
|
40
43
|
setReloadBehavior: vi.fn(),
|
|
41
|
-
|
|
42
|
-
updateBundle: vi.fn(),
|
|
44
|
+
stageBundle: vi.fn(),
|
|
43
45
|
wrap: vi.fn((Component: unknown) => Component),
|
|
44
46
|
};
|
|
45
47
|
});
|
|
@@ -52,6 +54,15 @@ vi.mock("./httpClient", () => ({
|
|
|
52
54
|
|
|
53
55
|
vi.mock("./checkForUpdate", () => ({
|
|
54
56
|
checkForUpdate: mocks.checkForUpdate,
|
|
57
|
+
reportUpdateError: mocks.reportUpdateError,
|
|
58
|
+
}));
|
|
59
|
+
|
|
60
|
+
vi.mock("./pluginHost", () => ({
|
|
61
|
+
configurePlugins: mocks.configurePlugins,
|
|
62
|
+
}));
|
|
63
|
+
|
|
64
|
+
vi.mock("./appReady", () => ({
|
|
65
|
+
emitAfterAppReady: mocks.emitAfterAppReady,
|
|
55
66
|
}));
|
|
56
67
|
|
|
57
68
|
vi.mock("./native", () => ({
|
|
@@ -77,8 +88,7 @@ vi.mock("./native", () => ({
|
|
|
77
88
|
resetChannel: mocks.resetChannel,
|
|
78
89
|
setCohort: mocks.setCohort,
|
|
79
90
|
setReloadBehavior: mocks.setReloadBehavior,
|
|
80
|
-
|
|
81
|
-
updateBundle: mocks.updateBundle,
|
|
91
|
+
stageBundle: mocks.stageBundle,
|
|
82
92
|
}));
|
|
83
93
|
|
|
84
94
|
vi.mock("./wrap", () => ({
|
|
@@ -99,6 +109,11 @@ describe("HotUpdater client initialization", () => {
|
|
|
99
109
|
mocks.wrap.mockImplementation((Component: unknown) => Component);
|
|
100
110
|
});
|
|
101
111
|
|
|
112
|
+
afterEach(() => {
|
|
113
|
+
vi.unstubAllGlobals();
|
|
114
|
+
vi.restoreAllMocks();
|
|
115
|
+
});
|
|
116
|
+
|
|
102
117
|
it("exposes the console ID through the existing getter only", async () => {
|
|
103
118
|
const HotUpdater = await importHotUpdater();
|
|
104
119
|
|
|
@@ -113,7 +128,6 @@ describe("HotUpdater client initialization", () => {
|
|
|
113
128
|
const HotUpdater = await importHotUpdater();
|
|
114
129
|
|
|
115
130
|
HotUpdater.init({
|
|
116
|
-
insights: true,
|
|
117
131
|
baseURL: "https://updates.example.com",
|
|
118
132
|
requestHeaders: { Authorization: "Bearer token" },
|
|
119
133
|
requestTimeout: 1000,
|
|
@@ -123,7 +137,6 @@ describe("HotUpdater client initialization", () => {
|
|
|
123
137
|
"https://updates.example.com",
|
|
124
138
|
);
|
|
125
139
|
expect(mocks.init).toHaveBeenCalledWith({
|
|
126
|
-
insights: true,
|
|
127
140
|
client,
|
|
128
141
|
requestHeaders: { Authorization: "Bearer token" },
|
|
129
142
|
requestTimeout: 1000,
|
|
@@ -140,42 +153,130 @@ describe("HotUpdater client initialization", () => {
|
|
|
140
153
|
expect(resolveBaseURL).not.toHaveBeenCalled();
|
|
141
154
|
});
|
|
142
155
|
|
|
143
|
-
it("
|
|
156
|
+
it("sets up plugins with the settings they fetch with, before init reads the launch", async () => {
|
|
157
|
+
const plugin = { id: "example", setup: vi.fn() };
|
|
158
|
+
const onError = vi.fn();
|
|
159
|
+
mocks.init.mockImplementationOnce(() => {
|
|
160
|
+
expect(mocks.configurePlugins).toHaveBeenCalledOnce();
|
|
161
|
+
});
|
|
144
162
|
const HotUpdater = await importHotUpdater();
|
|
145
163
|
|
|
146
|
-
HotUpdater.init({
|
|
147
|
-
HotUpdater.wrap({
|
|
164
|
+
HotUpdater.init({
|
|
148
165
|
baseURL: "https://updates.example.com",
|
|
166
|
+
onError,
|
|
167
|
+
plugins: [plugin],
|
|
168
|
+
requestHeaders: { "x-api-key": "client-key" },
|
|
169
|
+
requestTimeout: 1000,
|
|
170
|
+
});
|
|
171
|
+
HotUpdater.wrap({
|
|
172
|
+
baseURL: "https://other.example.com",
|
|
173
|
+
plugins: [plugin],
|
|
149
174
|
updateStrategy: "appVersion",
|
|
150
175
|
});
|
|
151
176
|
|
|
177
|
+
expect(mocks.configurePlugins).toHaveBeenNthCalledWith(1, [plugin], {
|
|
178
|
+
baseURL: "https://updates.example.com",
|
|
179
|
+
onError,
|
|
180
|
+
requestHeaders: { "x-api-key": "client-key" },
|
|
181
|
+
requestTimeout: 1000,
|
|
182
|
+
});
|
|
183
|
+
expect(mocks.configurePlugins).toHaveBeenNthCalledWith(2, [plugin], {
|
|
184
|
+
baseURL: "https://other.example.com",
|
|
185
|
+
onError: undefined,
|
|
186
|
+
requestHeaders: undefined,
|
|
187
|
+
requestTimeout: undefined,
|
|
188
|
+
});
|
|
152
189
|
expect(mocks.init).toHaveBeenCalledWith(
|
|
153
|
-
expect.objectContaining({
|
|
190
|
+
expect.not.objectContaining({ plugins: expect.anything() }),
|
|
154
191
|
);
|
|
155
192
|
expect(mocks.wrap).toHaveBeenCalledWith(
|
|
156
|
-
expect.objectContaining({
|
|
193
|
+
expect.not.objectContaining({ plugins: expect.anything() }),
|
|
157
194
|
);
|
|
158
195
|
});
|
|
159
196
|
|
|
160
|
-
it("
|
|
197
|
+
it("reports a staged manual download to plugins after the launch", async () => {
|
|
198
|
+
mocks.stageBundle.mockResolvedValueOnce({
|
|
199
|
+
delivery: "archive",
|
|
200
|
+
patchFallback: true,
|
|
201
|
+
});
|
|
202
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
203
|
+
activeSelection: {
|
|
204
|
+
bundleId: "next-bundle-id",
|
|
205
|
+
channel: "production",
|
|
206
|
+
kind: "BUNDLE",
|
|
207
|
+
releaseId: "next-release-id",
|
|
208
|
+
scopeKey: "v1:fingerprint:project:ios:cHJvZHVjdGlvbg:hash",
|
|
209
|
+
},
|
|
210
|
+
highestSeenCatalogs: {},
|
|
211
|
+
stableSelection: null,
|
|
212
|
+
verificationPending: true,
|
|
213
|
+
} as never);
|
|
161
214
|
const HotUpdater = await importHotUpdater();
|
|
215
|
+
HotUpdater.init({ baseURL: "https://updates.example.com" });
|
|
162
216
|
|
|
163
|
-
HotUpdater.
|
|
164
|
-
|
|
165
|
-
|
|
217
|
+
await HotUpdater.updateBundle({
|
|
218
|
+
assets: {},
|
|
219
|
+
bundleId: "next-bundle-id",
|
|
220
|
+
manifestFileHash: "manifest-hash",
|
|
221
|
+
manifestUrl: "https://updates.example.com/manifest.json",
|
|
222
|
+
status: "UPDATE",
|
|
166
223
|
});
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
224
|
+
|
|
225
|
+
expect(mocks.emitAfterAppReady).toHaveBeenCalledOnce();
|
|
226
|
+
const [name, createPayload] = mocks.emitAfterAppReady.mock.calls[0] as [
|
|
227
|
+
string,
|
|
228
|
+
() => unknown,
|
|
229
|
+
];
|
|
230
|
+
expect(name).toBe("onBundleDownloaded");
|
|
231
|
+
expect(createPayload()).toEqual({
|
|
232
|
+
channel: "production",
|
|
233
|
+
fromBundleId: "bundle-id",
|
|
234
|
+
fromReleaseId: null,
|
|
235
|
+
toBundleId: "next-bundle-id",
|
|
236
|
+
toReleaseId: "next-release-id",
|
|
237
|
+
updateStrategy: "fingerprint",
|
|
238
|
+
delivery: "archive",
|
|
239
|
+
patchFallback: true,
|
|
171
240
|
});
|
|
241
|
+
});
|
|
172
242
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
243
|
+
it("reports a failed manual download to plugins and rethrows it", async () => {
|
|
244
|
+
const error = Object.assign(new Error("hash mismatch"), {
|
|
245
|
+
code: "SIGNATURE_VERIFICATION_FAILED",
|
|
246
|
+
userInfo: { reason: "hash_mismatch", stage: "download" },
|
|
247
|
+
});
|
|
248
|
+
mocks.stageBundle.mockRejectedValueOnce(error);
|
|
249
|
+
const HotUpdater = await importHotUpdater();
|
|
250
|
+
HotUpdater.init({ baseURL: "https://updates.example.com" });
|
|
251
|
+
|
|
252
|
+
await expect(
|
|
253
|
+
HotUpdater.updateBundle({
|
|
254
|
+
assets: {},
|
|
255
|
+
bundleId: "next-bundle-id",
|
|
256
|
+
channel: "beta",
|
|
257
|
+
manifestFileHash: "manifest-hash",
|
|
258
|
+
manifestUrl: "https://updates.example.com/manifest.json",
|
|
259
|
+
selection: {
|
|
260
|
+
releaseId: "next-release-id",
|
|
261
|
+
scopeKey: "v1:app-version:project:ios:YmV0YQ",
|
|
262
|
+
},
|
|
263
|
+
status: "UPDATE",
|
|
264
|
+
}),
|
|
265
|
+
).rejects.toBe(error);
|
|
266
|
+
|
|
267
|
+
expect(mocks.reportUpdateError).toHaveBeenCalledWith(
|
|
268
|
+
error,
|
|
269
|
+
"download",
|
|
270
|
+
undefined,
|
|
271
|
+
{
|
|
272
|
+
bundleId: "bundle-id",
|
|
273
|
+
channel: "beta",
|
|
274
|
+
targetBundleId: "next-bundle-id",
|
|
275
|
+
targetReleaseId: "next-release-id",
|
|
276
|
+
updateStrategy: "appVersion",
|
|
277
|
+
},
|
|
178
278
|
);
|
|
279
|
+
expect(mocks.emitAfterAppReady).not.toHaveBeenCalled();
|
|
179
280
|
});
|
|
180
281
|
|
|
181
282
|
it("requires baseURL and rejects the removed resolver shape", async () => {
|
|
@@ -219,13 +320,12 @@ describe("HotUpdater client initialization", () => {
|
|
|
219
320
|
expect(wrapOptions.updateStrategy).toBe("appVersion");
|
|
220
321
|
});
|
|
221
322
|
|
|
222
|
-
it("merges settings
|
|
323
|
+
it("merges settings into checks", async () => {
|
|
223
324
|
const client = { createSession: vi.fn() };
|
|
224
325
|
mocks.createHttpClient.mockReturnValue(client as never);
|
|
225
326
|
const checkOnError = vi.fn();
|
|
226
327
|
const HotUpdater = await importHotUpdater();
|
|
227
328
|
HotUpdater.init({
|
|
228
|
-
insights: true,
|
|
229
329
|
baseURL: "https://updates.example.com",
|
|
230
330
|
requestHeaders: { Authorization: "Bearer token" },
|
|
231
331
|
requestTimeout: 1000,
|
|
@@ -238,7 +338,6 @@ describe("HotUpdater client initialization", () => {
|
|
|
238
338
|
});
|
|
239
339
|
|
|
240
340
|
expect(mocks.checkForUpdate).toHaveBeenCalledWith({
|
|
241
|
-
insights: true,
|
|
242
341
|
client,
|
|
243
342
|
onError: checkOnError,
|
|
244
343
|
requestHeaders: {
|
|
@@ -256,13 +355,11 @@ describe("HotUpdater client initialization", () => {
|
|
|
256
355
|
const HotUpdater = await importHotUpdater();
|
|
257
356
|
|
|
258
357
|
HotUpdater.wrap({
|
|
259
|
-
insights: true,
|
|
260
358
|
baseURL: "https://updates.example.com",
|
|
261
359
|
updateStrategy: "appVersion",
|
|
262
360
|
});
|
|
263
361
|
|
|
264
362
|
expect(mocks.wrap).toHaveBeenCalledWith({
|
|
265
|
-
insights: true,
|
|
266
363
|
client,
|
|
267
364
|
updateStrategy: "appVersion",
|
|
268
365
|
});
|
|
@@ -327,15 +424,11 @@ describe("HotUpdater client initialization", () => {
|
|
|
327
424
|
).toThrow("requires HotUpdater.wrap() or HotUpdater.init() to be used");
|
|
328
425
|
});
|
|
329
426
|
|
|
330
|
-
it("
|
|
427
|
+
it("keeps the install id and leaves user identity to the insights plugin", async () => {
|
|
331
428
|
const HotUpdater = await importHotUpdater();
|
|
332
429
|
|
|
333
430
|
expect(HotUpdater.getInstallId()).toBe("install-id");
|
|
334
431
|
expect(HotUpdater.getMinBundleId()).toBe("min-bundle-id");
|
|
335
|
-
HotUpdater.
|
|
336
|
-
expect(mocks.setUser).toHaveBeenCalledWith({
|
|
337
|
-
userId: "user-123",
|
|
338
|
-
username: "alice",
|
|
339
|
-
});
|
|
432
|
+
expect(HotUpdater).not.toHaveProperty("setUser");
|
|
340
433
|
});
|
|
341
434
|
});
|
package/src/index.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
import { emitAfterAppReady } from "./appReady";
|
|
1
2
|
import {
|
|
2
3
|
type CheckForUpdateOptions,
|
|
3
4
|
checkForUpdate,
|
|
4
5
|
type InternalCheckForUpdateOptions,
|
|
6
|
+
reportUpdateError,
|
|
5
7
|
} from "./checkForUpdate";
|
|
6
8
|
import { createHttpClient, type HotUpdaterHttpClient } from "./httpClient";
|
|
7
9
|
import {
|
|
@@ -27,11 +29,10 @@ import {
|
|
|
27
29
|
resetChannel,
|
|
28
30
|
setCohort,
|
|
29
31
|
setReloadBehavior,
|
|
30
|
-
|
|
32
|
+
stageBundle,
|
|
31
33
|
type UpdateParams,
|
|
32
|
-
updateBundle,
|
|
33
34
|
} from "./native";
|
|
34
|
-
import {
|
|
35
|
+
import { configurePlugins } from "./pluginHost";
|
|
35
36
|
import { hotUpdaterStore } from "./store";
|
|
36
37
|
import {
|
|
37
38
|
type AutoUpdateOptions,
|
|
@@ -43,6 +44,21 @@ import {
|
|
|
43
44
|
wrap,
|
|
44
45
|
} from "./wrap";
|
|
45
46
|
|
|
47
|
+
export {
|
|
48
|
+
defineClientPlugin,
|
|
49
|
+
type AppReadyResult,
|
|
50
|
+
type BundleDownloadedInfo,
|
|
51
|
+
type HotUpdaterClientContext,
|
|
52
|
+
type HotUpdaterClientHooks,
|
|
53
|
+
type HotUpdaterClientPlugin,
|
|
54
|
+
type HotUpdaterClientStorage,
|
|
55
|
+
type ReleaseTransitionKind,
|
|
56
|
+
type UpdateCheckResult,
|
|
57
|
+
type UpdateError,
|
|
58
|
+
type UpdateErrorReason,
|
|
59
|
+
type UpdateErrorStage,
|
|
60
|
+
type UpdateStrategy,
|
|
61
|
+
} from "./clientPlugin";
|
|
46
62
|
export type {
|
|
47
63
|
CustomReloadHandler,
|
|
48
64
|
HotUpdaterEvent,
|
|
@@ -54,7 +70,6 @@ export type {
|
|
|
54
70
|
ActiveUpdateState,
|
|
55
71
|
ReloadBehavior,
|
|
56
72
|
ReloadBehaviorSetting,
|
|
57
|
-
SetUserParams,
|
|
58
73
|
} from "./native";
|
|
59
74
|
export * from "./store";
|
|
60
75
|
export {
|
|
@@ -103,13 +118,11 @@ function createHotUpdaterClient() {
|
|
|
103
118
|
|
|
104
119
|
// Global configuration stored from wrap
|
|
105
120
|
const globalConfig: {
|
|
106
|
-
insights: boolean;
|
|
107
121
|
client: HotUpdaterHttpClient | null;
|
|
108
122
|
requestHeaders?: Record<string, string>;
|
|
109
123
|
requestTimeout?: number;
|
|
110
124
|
onError?: (error: unknown) => void;
|
|
111
125
|
} = {
|
|
112
|
-
insights: true,
|
|
113
126
|
client: null,
|
|
114
127
|
};
|
|
115
128
|
|
|
@@ -158,10 +171,9 @@ function createHotUpdaterClient() {
|
|
|
158
171
|
const autoOptions = incoming as AutoUpdateOptions;
|
|
159
172
|
|
|
160
173
|
if (autoOptions.baseURL) {
|
|
161
|
-
const { baseURL, ...rest } = autoOptions;
|
|
174
|
+
const { baseURL, plugins: _plugins, ...rest } = autoOptions;
|
|
162
175
|
return {
|
|
163
176
|
...rest,
|
|
164
|
-
insights: rest.insights ?? true,
|
|
165
177
|
client: createHttpClient(baseURL),
|
|
166
178
|
};
|
|
167
179
|
}
|
|
@@ -178,10 +190,9 @@ function createHotUpdaterClient() {
|
|
|
178
190
|
};
|
|
179
191
|
|
|
180
192
|
if (rest.baseURL) {
|
|
181
|
-
const { baseURL, ...baseURLRest } = rest;
|
|
193
|
+
const { baseURL, plugins: _plugins, ...baseURLRest } = rest;
|
|
182
194
|
return {
|
|
183
195
|
...baseURLRest,
|
|
184
|
-
insights: baseURLRest.insights ?? true,
|
|
185
196
|
client: createHttpClient(baseURL),
|
|
186
197
|
};
|
|
187
198
|
}
|
|
@@ -193,7 +204,13 @@ function createHotUpdaterClient() {
|
|
|
193
204
|
normalizedOptions: InternalInitOptions | InternalWrapOptions,
|
|
194
205
|
options: HotUpdaterOptions | HotUpdaterInitOptions,
|
|
195
206
|
) => {
|
|
196
|
-
|
|
207
|
+
// Plugins are set up before init or wrap reads the launch they observe.
|
|
208
|
+
configurePlugins(options.plugins, {
|
|
209
|
+
baseURL: options.baseURL,
|
|
210
|
+
requestHeaders: options.requestHeaders,
|
|
211
|
+
requestTimeout: options.requestTimeout,
|
|
212
|
+
onError: options.onError,
|
|
213
|
+
});
|
|
197
214
|
globalConfig.client = normalizedOptions.client;
|
|
198
215
|
globalConfig.requestHeaders = options.requestHeaders;
|
|
199
216
|
globalConfig.requestTimeout = options.requestTimeout;
|
|
@@ -451,7 +468,6 @@ function createHotUpdaterClient() {
|
|
|
451
468
|
|
|
452
469
|
const mergedConfig: InternalCheckForUpdateOptions = {
|
|
453
470
|
...config,
|
|
454
|
-
insights: globalConfig.insights,
|
|
455
471
|
client,
|
|
456
472
|
requestHeaders: {
|
|
457
473
|
...globalConfig.requestHeaders,
|
|
@@ -493,33 +509,52 @@ function createHotUpdaterClient() {
|
|
|
493
509
|
* ```
|
|
494
510
|
*/
|
|
495
511
|
updateBundle: async (params: UpdateParams) => {
|
|
496
|
-
|
|
512
|
+
ensureGlobalClient("updateBundle");
|
|
497
513
|
const fromBundleId = getBundleId();
|
|
498
514
|
const state = getActiveUpdateState();
|
|
499
515
|
const active = state.activeSelection;
|
|
500
|
-
const
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
516
|
+
const fromReleaseId =
|
|
517
|
+
active?.bundleId === fromBundleId
|
|
518
|
+
? active.releaseId
|
|
519
|
+
: state.stableSelection?.bundleId === fromBundleId
|
|
520
|
+
? state.stableSelection.releaseId
|
|
521
|
+
: null;
|
|
522
|
+
const channel = params.channel ?? getChannel();
|
|
523
|
+
const strategyOf = (scopeKey: string | null | undefined) =>
|
|
524
|
+
scopeKey?.startsWith("v1:fingerprint:") ? "fingerprint" : "appVersion";
|
|
525
|
+
let delivery: Awaited<ReturnType<typeof stageBundle>>;
|
|
526
|
+
try {
|
|
527
|
+
delivery = await stageBundle(params);
|
|
528
|
+
} catch (error) {
|
|
529
|
+
reportUpdateError(error, "download", undefined, {
|
|
530
|
+
bundleId: fromBundleId,
|
|
531
|
+
channel,
|
|
532
|
+
targetBundleId: params.bundleId,
|
|
533
|
+
targetReleaseId:
|
|
534
|
+
(params.selection as { releaseId?: string | null } | undefined)
|
|
535
|
+
?.releaseId ?? null,
|
|
536
|
+
updateStrategy: strategyOf(
|
|
537
|
+
(params.selection as { scopeKey?: string | null } | undefined)
|
|
538
|
+
?.scopeKey,
|
|
539
|
+
),
|
|
540
|
+
});
|
|
541
|
+
throw error;
|
|
542
|
+
}
|
|
543
|
+
if (delivery !== null && params.bundleId !== fromBundleId) {
|
|
544
|
+
emitAfterAppReady("onBundleDownloaded", () => {
|
|
545
|
+
const selection = getActiveUpdateState().activeSelection;
|
|
546
|
+
return {
|
|
547
|
+
channel,
|
|
506
548
|
fromBundleId,
|
|
507
|
-
fromReleaseId
|
|
508
|
-
active?.bundleId === fromBundleId
|
|
509
|
-
? active.releaseId
|
|
510
|
-
: state.stableSelection?.bundleId === fromBundleId
|
|
511
|
-
? state.stableSelection.releaseId
|
|
512
|
-
: null,
|
|
549
|
+
fromReleaseId,
|
|
513
550
|
toBundleId: params.bundleId,
|
|
514
551
|
toReleaseId: selection?.releaseId ?? null,
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
},
|
|
520
|
-
);
|
|
552
|
+
updateStrategy: strategyOf(selection?.scopeKey),
|
|
553
|
+
...delivery,
|
|
554
|
+
};
|
|
555
|
+
});
|
|
521
556
|
}
|
|
522
|
-
return
|
|
557
|
+
return true;
|
|
523
558
|
},
|
|
524
559
|
|
|
525
560
|
/**
|
|
@@ -558,11 +593,6 @@ function createHotUpdaterClient() {
|
|
|
558
593
|
*/
|
|
559
594
|
getInstallId,
|
|
560
595
|
|
|
561
|
-
/**
|
|
562
|
-
* Persists nullable user identity fields associated with this installation.
|
|
563
|
-
*/
|
|
564
|
-
setUser,
|
|
565
|
-
|
|
566
596
|
/**
|
|
567
597
|
* Reads the native launch report for the current process.
|
|
568
598
|
*/
|