@hot-updater/react-native 1.0.0-rc.1 → 1.0.0-rc.15
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/android/proguard-rules.pro +17 -2
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +651 -637
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +10 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterException.kt +0 -13
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +10 -14
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryManager.kt +37 -54
- package/android/src/main/java/com/hotupdater/HotUpdaterRecoveryState.kt +64 -0
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +19 -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 +40 -20
- package/android/src/oldarch/HotUpdater.kt +7 -9
- package/android/src/oldarch/HotUpdaterModule.kt +40 -20
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +1126 -74
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +4 -5
- package/android/src/test/java/com/hotupdater/HotUpdaterRecoveryStateTest.kt +97 -0
- package/android/src/test/java/com/hotupdater/PendingCrashRecoveryTest.kt +44 -0
- package/android/src/test/java/com/hotupdater/TarBrArchiveExtractorTest.kt +206 -0
- package/ios/HotUpdater/Internal/BrotliFileDecompressor.swift +167 -0
- package/ios/HotUpdater/Internal/BuiltInAssetResolver.swift +196 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +773 -1016
- package/ios/HotUpdater/Internal/BundleMetadata.swift +5 -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 +5 -27
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +149 -51
- package/ios/HotUpdater/Internal/NotificationExtension.swift +0 -2
- package/ios/HotUpdater/Internal/TarArchiveExtractor.swift +182 -311
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +13 -72
- 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/checkForUpdate.js +32 -23
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +97 -28
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/commonjs/error.js +4 -13
- package/lib/commonjs/error.js.map +1 -1
- package/lib/commonjs/fetchJSON.js +9 -2
- package/lib/commonjs/fetchJSON.js.map +1 -1
- package/lib/commonjs/httpClient.js +46 -29
- package/lib/commonjs/httpClient.js.map +1 -1
- package/lib/commonjs/httpClient.spec.js +57 -5
- package/lib/commonjs/httpClient.spec.js.map +1 -1
- package/lib/commonjs/index.js +31 -14
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +56 -11
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +15 -14
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +128 -22
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +28 -21
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +1 -0
- package/lib/commonjs/notifyAppReadyInsights.js +188 -0
- package/lib/commonjs/notifyAppReadyInsights.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +161 -29
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
- package/lib/commonjs/notifyAppReadyInsights.test-utils.js.map +1 -0
- package/lib/commonjs/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +14 -7
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +1 -0
- 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/store.notification.spec.js +12 -4
- package/lib/commonjs/store.notification.spec.js.map +1 -1
- package/lib/commonjs/store.spec.js +2 -136
- package/lib/commonjs/store.spec.js.map +1 -1
- package/lib/commonjs/wrap.js +11 -12
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +97 -25
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/checkForUpdate.js +32 -23
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +97 -28
- package/lib/module/checkForUpdate.releaseCatalog.spec.js.map +1 -1
- package/lib/module/error.js +4 -13
- package/lib/module/error.js.map +1 -1
- package/lib/module/fetchJSON.js +7 -1
- package/lib/module/fetchJSON.js.map +1 -1
- package/lib/module/httpClient.js +48 -31
- package/lib/module/httpClient.js.map +1 -1
- package/lib/module/httpClient.spec.js +57 -5
- package/lib/module/httpClient.spec.js.map +1 -1
- package/lib/module/index.js +32 -15
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +56 -11
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +13 -12
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +128 -22
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/{notifyAppReadyAnalytics.boundary.spec.js → notifyAppReadyInsights.boundary.spec.js} +23 -16
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +1 -0
- package/lib/module/notifyAppReadyInsights.js +181 -0
- package/lib/module/notifyAppReadyInsights.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.spec.js → notifyAppReadyInsights.spec.js} +153 -21
- package/lib/module/notifyAppReadyInsights.spec.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.test-utils.js → notifyAppReadyInsights.test-utils.js} +3 -3
- package/lib/module/notifyAppReadyInsights.test-utils.js.map +1 -0
- package/lib/module/{notifyAppReadyAnalytics.transport.spec.js → notifyAppReadyInsights.transport.spec.js} +11 -4
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +1 -0
- 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/store.notification.spec.js +12 -4
- package/lib/module/store.notification.spec.js.map +1 -1
- package/lib/module/store.spec.js +2 -136
- package/lib/module/store.spec.js.map +1 -1
- package/lib/module/wrap.js +11 -12
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +99 -25
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +2 -3
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/error.d.ts +4 -13
- package/lib/typescript/commonjs/error.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchJSON.d.ts +4 -0
- package/lib/typescript/commonjs/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/commonjs/httpClient.d.ts +6 -6
- package/lib/typescript/commonjs/httpClient.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +4 -7
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +5 -9
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +25 -0
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +1 -0
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts +8 -0
- package/lib/typescript/commonjs/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
- 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 +8 -35
- 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/wrap.types.d.ts +5 -8
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +2 -3
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/error.d.ts +4 -13
- package/lib/typescript/module/error.d.ts.map +1 -1
- package/lib/typescript/module/fetchJSON.d.ts +4 -0
- package/lib/typescript/module/fetchJSON.d.ts.map +1 -1
- package/lib/typescript/module/httpClient.d.ts +6 -6
- package/lib/typescript/module/httpClient.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +4 -7
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +5 -9
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +25 -0
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +1 -0
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts +8 -0
- package/lib/typescript/module/notifyAppReadyInsights.test-utils.d.ts.map +1 -0
- 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 +8 -35
- 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/wrap.types.d.ts +5 -8
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/checkForUpdate.releaseCatalog.spec.ts +137 -61
- package/src/checkForUpdate.ts +35 -29
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +12 -1
- package/src/httpClient.spec.ts +70 -5
- package/src/httpClient.ts +78 -64
- package/src/index.spec.ts +59 -11
- package/src/index.ts +41 -17
- package/src/native.spec.ts +133 -22
- package/src/native.ts +21 -32
- package/src/{notifyAppReadyAnalytics.boundary.spec.ts → notifyAppReadyInsights.boundary.spec.ts} +25 -17
- package/src/{notifyAppReadyAnalytics.spec.ts → notifyAppReadyInsights.spec.ts} +141 -22
- package/src/{notifyAppReadyAnalytics.test-utils.ts → notifyAppReadyInsights.test-utils.ts} +4 -4
- package/src/{notifyAppReadyAnalytics.transport.spec.ts → notifyAppReadyInsights.transport.spec.ts} +13 -5
- package/src/notifyAppReadyInsights.ts +293 -0
- package/src/sdkVersion.ts +1 -1
- package/src/specs/NativeHotUpdater.ts +8 -36
- package/src/store.notification.spec.ts +13 -3
- package/src/store.spec.ts +0 -157
- package/src/store.ts +2 -23
- package/src/wrap.spec.ts +109 -31
- package/src/wrap.tsx +11 -11
- package/src/wrap.types.ts +5 -8
- 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/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/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.js +0 -133
- package/lib/commonjs/notifyAppReadyAnalytics.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.spec.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.test-utils.js.map +0 -1
- package/lib/commonjs/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.boundary.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.js +0 -128
- package/lib/module/notifyAppReadyAnalytics.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.spec.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.test-utils.js.map +0 -1
- package/lib/module/notifyAppReadyAnalytics.transport.spec.js.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts +0 -13
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.d.ts.map +0 -1
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
- package/lib/typescript/commonjs/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts +0 -13
- package/lib/typescript/module/notifyAppReadyAnalytics.d.ts.map +0 -1
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts +0 -8
- package/lib/typescript/module/notifyAppReadyAnalytics.test-utils.d.ts.map +0 -1
- package/src/notifyAppReadyAnalytics.ts +0 -194
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,6BAA6B,EAE9B,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/store.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAEV,6BAA6B,EAE9B,MAAM,UAAU,CAAC;AAGlB,MAAM,MAAM,eAAe,GAAG;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC/C,CAAC;AA+KF,eAAO,MAAM,eAAe;;yBApDE,OAAO,CAAC,eAAe,CAAC;0BAwCvB,MAAM,IAAI;CAYa,CAAC;AAEvD,eAAO,MAAM,kBAAkB,GAAI,CAAC,GAAG,eAAe,aAC1C,CAAC,QAAQ,EAAE,eAAe,KAAK,CAAC,MAQ3C,CAAC"}
|
|
@@ -14,8 +14,6 @@ export type UpdateStatus = "CHECK_FOR_UPDATE" | "UPDATING" | "UPDATE_PROCESS_COM
|
|
|
14
14
|
export type HotUpdaterFallbackComponentProps = {
|
|
15
15
|
status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
|
|
16
16
|
progress: number;
|
|
17
|
-
downloadedBytes: HotUpdaterState["downloadedBytes"];
|
|
18
|
-
totalBytes: HotUpdaterState["totalBytes"];
|
|
19
17
|
message: string | null;
|
|
20
18
|
artifactType: HotUpdaterState["artifactType"];
|
|
21
19
|
details: HotUpdaterState["details"];
|
|
@@ -23,9 +21,10 @@ export type HotUpdaterFallbackComponentProps = {
|
|
|
23
21
|
interface CommonHotUpdaterOptions {
|
|
24
22
|
/**
|
|
25
23
|
* Sends app-ready transitions and same-Bundle Release adoptions to the
|
|
26
|
-
* configured server.
|
|
24
|
+
* configured server. Defaults to `true`; set to `false` to disable client
|
|
25
|
+
* reporting.
|
|
27
26
|
*/
|
|
28
|
-
|
|
27
|
+
insights?: boolean;
|
|
29
28
|
/** Base URL of a server exposing the Hot Updater v1 client HTTP protocol. */
|
|
30
29
|
baseURL: HotUpdaterBaseURL;
|
|
31
30
|
requestHeaders?: Record<string, string>;
|
|
@@ -43,7 +42,7 @@ export type AutoUpdateOptions = CommonHotUpdaterOptions & {
|
|
|
43
42
|
export type HotUpdaterInitOptions = CommonHotUpdaterOptions;
|
|
44
43
|
export type HotUpdaterOptions = AutoUpdateOptions;
|
|
45
44
|
type InternalCommonOptions = {
|
|
46
|
-
|
|
45
|
+
insights?: boolean;
|
|
47
46
|
client: HotUpdaterHttpClient;
|
|
48
47
|
requestHeaders?: Record<string, string>;
|
|
49
48
|
requestTimeout?: number;
|
|
@@ -57,9 +56,7 @@ type InternalAutoUpdateOptions = InternalCommonOptions & {
|
|
|
57
56
|
reloadOnForceUpdate?: boolean;
|
|
58
57
|
onUpdateProcessCompleted?: (response: RunUpdateProcessResponse) => void;
|
|
59
58
|
};
|
|
60
|
-
export type InternalInitOptions = InternalCommonOptions
|
|
61
|
-
analytics?: boolean;
|
|
62
|
-
};
|
|
59
|
+
export type InternalInitOptions = InternalCommonOptions;
|
|
63
60
|
export type InternalWrapOptions = InternalAutoUpdateOptions;
|
|
64
61
|
export {};
|
|
65
62
|
//# sourceMappingURL=wrap.types.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.types.d.ts","sourceRoot":"","sources":["../../../src/wrap.types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,cAAc,CAAC;AACzD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AACrD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAC/C,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AAEjD,MAAM,WAAW,wBAAwB;IACvC,MAAM,EAAE,UAAU,GAAG,QAAQ,GAAG,YAAY,CAAC;IAC7C,iBAAiB,EAAE,OAAO,CAAC;IAC3B,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,MAAM,MAAM,YAAY,GACpB,kBAAkB,GAClB,UAAU,GACV,0BAA0B,CAAC;AAE/B,MAAM,MAAM,gCAAgC,GAAG;IAC7C,MAAM,EAAE,OAAO,CAAC,YAAY,EAAE,0BAA0B,CAAC,CAAC;IAC1D,QAAQ,EAAE,MAAM,CAAC;IACjB,
|
|
1
|
+
{"version":3,"file":"wrap.types.d.ts","sourceRoot":"","sources":["../../../src/wrap.types.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/react-native",
|
|
3
|
-
"version": "1.0.0-rc.
|
|
3
|
+
"version": "1.0.0-rc.15",
|
|
4
4
|
"description": "React Native OTA solution for self-hosted",
|
|
5
5
|
"source": "./src/index.ts",
|
|
6
6
|
"main": "./lib/commonjs/index.js",
|
|
@@ -120,8 +120,8 @@
|
|
|
120
120
|
},
|
|
121
121
|
"dependencies": {
|
|
122
122
|
"use-sync-external-store": "1.5.0",
|
|
123
|
-
"@hot-updater/core": "1.0.0-rc.
|
|
124
|
-
"@hot-updater/plugin-core": "1.0.0-rc.
|
|
123
|
+
"@hot-updater/core": "1.0.0-rc.15",
|
|
124
|
+
"@hot-updater/plugin-core": "1.0.0-rc.15"
|
|
125
125
|
},
|
|
126
126
|
"scripts": {
|
|
127
127
|
"build": "node ./scripts/sync-sdk-version.mjs run -- bob build",
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import {
|
|
2
2
|
createReleaseCatalogScopeKey,
|
|
3
3
|
encodeChannelKey,
|
|
4
|
+
type ArtifactInfo,
|
|
4
5
|
type PersistedSelectionReceipt,
|
|
5
6
|
type ReleaseCatalog,
|
|
6
7
|
} from "@hot-updater/core";
|
|
@@ -77,24 +78,29 @@ const createCatalog = (
|
|
|
77
78
|
|
|
78
79
|
const createClient = (catalog = createCatalog()) => {
|
|
79
80
|
const fetchReleaseCatalog = vi.fn(async () => catalog);
|
|
80
|
-
const
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
81
|
+
const artifact: ArtifactInfo = {
|
|
82
|
+
artifactProtocolVersion: 1,
|
|
83
|
+
assets: {},
|
|
84
|
+
manifestFileHash: "manifest-hash",
|
|
85
|
+
manifestUrl: "https://updates.example.com/manifest.json",
|
|
86
|
+
archiveUrl: "https://updates.example.com/bundle.tar.br",
|
|
87
|
+
};
|
|
88
|
+
const resolveArtifact = vi.fn(async () => artifact);
|
|
89
|
+
const sendInsightsEvent = vi.fn(async () => undefined);
|
|
85
90
|
const session = {
|
|
86
91
|
fetchReleaseCatalog,
|
|
87
92
|
resolveArtifact,
|
|
88
|
-
|
|
93
|
+
sendInsightsEvent,
|
|
89
94
|
};
|
|
90
95
|
const client: HotUpdaterHttpClient = {
|
|
91
96
|
createSession: vi.fn(async () => session),
|
|
92
97
|
};
|
|
93
|
-
return { client, fetchReleaseCatalog, resolveArtifact,
|
|
98
|
+
return { client, fetchReleaseCatalog, resolveArtifact, sendInsightsEvent };
|
|
94
99
|
};
|
|
95
100
|
|
|
96
101
|
describe("checkForUpdate Release catalog protocol", () => {
|
|
97
102
|
beforeEach(() => {
|
|
103
|
+
vi.resetModules();
|
|
98
104
|
vi.clearAllMocks();
|
|
99
105
|
vi.stubGlobal("__DEV__", false);
|
|
100
106
|
mocks.acceptReleaseCatalog.mockReturnValue(true);
|
|
@@ -109,6 +115,59 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
109
115
|
mocks.updateBundle.mockResolvedValue(true);
|
|
110
116
|
});
|
|
111
117
|
|
|
118
|
+
it("reports an optional download only after staging, without treating the target as running", async () => {
|
|
119
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
120
|
+
const { client, sendInsightsEvent } = createClient();
|
|
121
|
+
let complete!: (success: boolean) => void;
|
|
122
|
+
mocks.updateBundle.mockImplementationOnce(
|
|
123
|
+
() =>
|
|
124
|
+
new Promise<boolean>((resolve) => {
|
|
125
|
+
complete = resolve;
|
|
126
|
+
}),
|
|
127
|
+
);
|
|
128
|
+
const update = await checkForUpdate({
|
|
129
|
+
client,
|
|
130
|
+
insights: true,
|
|
131
|
+
updateStrategy: "appVersion",
|
|
132
|
+
});
|
|
133
|
+
expect(update?.shouldForceUpdate).toBe(false);
|
|
134
|
+
const pending = update!.updateBundle();
|
|
135
|
+
await vi.waitFor(() => expect(mocks.updateBundle).toHaveBeenCalledOnce());
|
|
136
|
+
expect(sendInsightsEvent).not.toHaveBeenCalled();
|
|
137
|
+
complete(true);
|
|
138
|
+
await expect(pending).resolves.toBe(true);
|
|
139
|
+
expect(sendInsightsEvent).toHaveBeenCalledExactlyOnceWith(
|
|
140
|
+
expect.objectContaining({
|
|
141
|
+
type: "UPDATE_DOWNLOADED",
|
|
142
|
+
fromBundleId: CURRENT_BUNDLE_ID,
|
|
143
|
+
toBundleId: TARGET_BUNDLE_ID,
|
|
144
|
+
fromReleaseId: null,
|
|
145
|
+
toReleaseId: RELEASE_ID,
|
|
146
|
+
updateStrategy: "appVersion",
|
|
147
|
+
}),
|
|
148
|
+
);
|
|
149
|
+
await update!.updateBundle();
|
|
150
|
+
expect(sendInsightsEvent).toHaveBeenCalledOnce();
|
|
151
|
+
});
|
|
152
|
+
|
|
153
|
+
it.each([false, "failure"])(
|
|
154
|
+
"does not report a download when staging returns %s",
|
|
155
|
+
async (result) => {
|
|
156
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
157
|
+
const { client, sendInsightsEvent } = createClient();
|
|
158
|
+
if (result === false) mocks.updateBundle.mockResolvedValueOnce(false);
|
|
159
|
+
else
|
|
160
|
+
mocks.updateBundle.mockRejectedValueOnce(new Error("download failed"));
|
|
161
|
+
const update = await checkForUpdate({
|
|
162
|
+
client,
|
|
163
|
+
insights: true,
|
|
164
|
+
updateStrategy: "appVersion",
|
|
165
|
+
});
|
|
166
|
+
await update!.updateBundle().catch(() => false);
|
|
167
|
+
expect(sendInsightsEvent).not.toHaveBeenCalled();
|
|
168
|
+
},
|
|
169
|
+
);
|
|
170
|
+
|
|
112
171
|
it("selects locally and defers Bundle artifact resolution until install", async () => {
|
|
113
172
|
const { checkForUpdate } = await import("./checkForUpdate");
|
|
114
173
|
const { client, fetchReleaseCatalog, resolveArtifact } = createClient();
|
|
@@ -119,7 +178,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
119
178
|
});
|
|
120
179
|
|
|
121
180
|
expect(result).toMatchObject({
|
|
122
|
-
id:
|
|
181
|
+
id: RELEASE_ID,
|
|
123
182
|
releaseId: RELEASE_ID,
|
|
124
183
|
transitionKind: "INSTALL",
|
|
125
184
|
});
|
|
@@ -145,6 +204,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
145
204
|
expect(mocks.updateBundle).toHaveBeenCalledWith(
|
|
146
205
|
expect.objectContaining({
|
|
147
206
|
bundleId: TARGET_BUNDLE_ID,
|
|
207
|
+
archiveUrl: "https://updates.example.com/bundle.tar.br",
|
|
148
208
|
selection: expect.objectContaining({
|
|
149
209
|
catalogId: CATALOG_ID,
|
|
150
210
|
releaseId: RELEASE_ID,
|
|
@@ -182,7 +242,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
182
242
|
},
|
|
183
243
|
],
|
|
184
244
|
});
|
|
185
|
-
const { client, resolveArtifact,
|
|
245
|
+
const { client, resolveArtifact, sendInsightsEvent } =
|
|
186
246
|
createClient(forceCatalog);
|
|
187
247
|
|
|
188
248
|
const result = await checkForUpdate({
|
|
@@ -191,13 +251,14 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
191
251
|
});
|
|
192
252
|
|
|
193
253
|
expect(result).toMatchObject({
|
|
254
|
+
id: RELEASE_ID,
|
|
194
255
|
shouldForceUpdate: false,
|
|
195
256
|
transitionKind: "ADOPT_RELEASE",
|
|
196
257
|
});
|
|
197
258
|
await expect(result?.updateBundle()).resolves.toBe(true);
|
|
198
259
|
expect(resolveArtifact).not.toHaveBeenCalled();
|
|
199
260
|
expect(mocks.updateBundle).not.toHaveBeenCalled();
|
|
200
|
-
expect(
|
|
261
|
+
expect(sendInsightsEvent).not.toHaveBeenCalled();
|
|
201
262
|
expect(mocks.commitReleaseSelection).toHaveBeenCalledWith({
|
|
202
263
|
guard: expect.objectContaining({ generation: 2, scopeKey: SCOPE_KEY }),
|
|
203
264
|
selection: expect.objectContaining({
|
|
@@ -207,7 +268,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
207
268
|
});
|
|
208
269
|
});
|
|
209
270
|
|
|
210
|
-
it("
|
|
271
|
+
it("reports same-file selection as UNCHANGED with the selected release identity", async () => {
|
|
211
272
|
const active: PersistedSelectionReceipt = {
|
|
212
273
|
catalogId: CATALOG_ID,
|
|
213
274
|
bundleId: TARGET_BUNDLE_ID,
|
|
@@ -227,20 +288,23 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
227
288
|
verificationPending: false,
|
|
228
289
|
});
|
|
229
290
|
const { checkForUpdate } = await import("./checkForUpdate");
|
|
230
|
-
const { client,
|
|
291
|
+
const { client, sendInsightsEvent } = createClient();
|
|
231
292
|
|
|
232
293
|
const result = await checkForUpdate({
|
|
233
|
-
|
|
294
|
+
insights: true,
|
|
234
295
|
client,
|
|
235
296
|
updateStrategy: "appVersion",
|
|
236
297
|
});
|
|
237
298
|
await result?.updateBundle();
|
|
238
299
|
|
|
239
|
-
expect(
|
|
300
|
+
expect(sendInsightsEvent).toHaveBeenCalledWith(
|
|
240
301
|
expect.objectContaining({
|
|
302
|
+
fromBundleId: null,
|
|
303
|
+
updateStrategy: null,
|
|
241
304
|
fromReleaseId: MINIMUM_RELEASE_ID,
|
|
305
|
+
toBundleId: TARGET_BUNDLE_ID,
|
|
242
306
|
toReleaseId: RELEASE_ID,
|
|
243
|
-
type: "
|
|
307
|
+
type: "UNCHANGED",
|
|
244
308
|
}),
|
|
245
309
|
);
|
|
246
310
|
});
|
|
@@ -280,7 +344,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
280
344
|
});
|
|
281
345
|
|
|
282
346
|
expect(result).toMatchObject({
|
|
283
|
-
id:
|
|
347
|
+
id: RELEASE_ID,
|
|
284
348
|
releaseId: RELEASE_ID,
|
|
285
349
|
status: "UPDATE",
|
|
286
350
|
transitionKind: "INSTALL",
|
|
@@ -315,7 +379,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
315
379
|
});
|
|
316
380
|
|
|
317
381
|
expect(result).toMatchObject({
|
|
318
|
-
id:
|
|
382
|
+
id: RELEASE_ID,
|
|
319
383
|
releaseId: RELEASE_ID,
|
|
320
384
|
transitionKind: "ADOPT_RELEASE",
|
|
321
385
|
});
|
|
@@ -395,7 +459,7 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
395
459
|
});
|
|
396
460
|
|
|
397
461
|
expect(result).toMatchObject({
|
|
398
|
-
id:
|
|
462
|
+
id: RELEASE_ID,
|
|
399
463
|
releaseId: RELEASE_ID,
|
|
400
464
|
shouldForceUpdate: true,
|
|
401
465
|
status: "ROLLBACK",
|
|
@@ -448,58 +512,70 @@ describe("checkForUpdate Release catalog protocol", () => {
|
|
|
448
512
|
});
|
|
449
513
|
|
|
450
514
|
expect(result).toMatchObject({
|
|
451
|
-
id:
|
|
515
|
+
id: RELEASE_ID,
|
|
452
516
|
shouldForceUpdate: true,
|
|
453
517
|
status: "ROLLBACK",
|
|
454
518
|
transitionKind: "INSTALL",
|
|
455
519
|
});
|
|
456
520
|
});
|
|
457
521
|
|
|
458
|
-
it("
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
522
|
+
it.each(["EMBEDDED", "BUILTIN"] as const)(
|
|
523
|
+
"returns a forced %s rollback with its console ID or built-in fallback",
|
|
524
|
+
async (kind) => {
|
|
525
|
+
const active: PersistedSelectionReceipt = {
|
|
526
|
+
catalogId: CATALOG_ID,
|
|
527
|
+
bundleId: CURRENT_BUNDLE_ID,
|
|
528
|
+
catalogHash: `sha256:${"b".repeat(64)}`,
|
|
529
|
+
channel: CHANNEL,
|
|
530
|
+
generation: 1,
|
|
531
|
+
kind: "BUNDLE",
|
|
532
|
+
releaseId: MINIMUM_RELEASE_ID,
|
|
533
|
+
scopeKey: SCOPE_KEY,
|
|
534
|
+
selectionContextHash: "old-context",
|
|
535
|
+
};
|
|
536
|
+
mocks.getActiveUpdateState.mockReturnValueOnce({
|
|
537
|
+
activeSelection: active,
|
|
538
|
+
highestSeenCatalogs: {},
|
|
539
|
+
stableSelection: active,
|
|
540
|
+
verificationPending: false,
|
|
541
|
+
});
|
|
542
|
+
const { checkForUpdate } = await import("./checkForUpdate");
|
|
543
|
+
const { client, resolveArtifact } = createClient(
|
|
544
|
+
createCatalog({
|
|
545
|
+
releases:
|
|
546
|
+
kind === "EMBEDDED"
|
|
547
|
+
? [{ ...createCatalog().releases[0]!, kind, bundleId: null }]
|
|
548
|
+
: [],
|
|
549
|
+
rollbackReleases: [],
|
|
550
|
+
}),
|
|
551
|
+
);
|
|
480
552
|
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
553
|
+
const result = await checkForUpdate({
|
|
554
|
+
client,
|
|
555
|
+
updateStrategy: "appVersion",
|
|
556
|
+
});
|
|
485
557
|
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
558
|
+
expect(result).toMatchObject({
|
|
559
|
+
id: kind === "EMBEDDED" ? RELEASE_ID : MINIMUM_RELEASE_ID,
|
|
560
|
+
releaseId: kind === "EMBEDDED" ? RELEASE_ID : null,
|
|
561
|
+
shouldForceUpdate: true,
|
|
562
|
+
status: "ROLLBACK",
|
|
563
|
+
transitionKind: kind === "EMBEDDED" ? "USE_EMBEDDED" : "USE_BUILTIN",
|
|
564
|
+
});
|
|
565
|
+
await expect(result?.updateBundle()).resolves.toBe(true);
|
|
566
|
+
expect(mocks.commitReleaseSelection).toHaveBeenCalledWith(
|
|
567
|
+
expect.objectContaining({
|
|
568
|
+
selection: expect.objectContaining({
|
|
569
|
+
bundleId: MINIMUM_RELEASE_ID,
|
|
570
|
+
kind,
|
|
571
|
+
releaseId: kind === "EMBEDDED" ? RELEASE_ID : null,
|
|
572
|
+
}),
|
|
499
573
|
}),
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
574
|
+
);
|
|
575
|
+
expect(resolveArtifact).not.toHaveBeenCalled();
|
|
576
|
+
expect(mocks.updateBundle).not.toHaveBeenCalled();
|
|
577
|
+
},
|
|
578
|
+
);
|
|
503
579
|
|
|
504
580
|
it("does not surface a rollback when the app already uses built-in bytes", async () => {
|
|
505
581
|
mocks.getBundleId.mockReturnValueOnce(MINIMUM_RELEASE_ID);
|
package/src/checkForUpdate.ts
CHANGED
|
@@ -3,7 +3,6 @@ import {
|
|
|
3
3
|
createReleaseSelectionContextHash,
|
|
4
4
|
encodeChannelKey,
|
|
5
5
|
selectDesiredRelease,
|
|
6
|
-
type ArtifactInfo,
|
|
7
6
|
type PersistedSelectionReceipt,
|
|
8
7
|
type ReleaseCatalog,
|
|
9
8
|
} from "@hot-updater/core";
|
|
@@ -30,6 +29,7 @@ import {
|
|
|
30
29
|
isChannelSwitched,
|
|
31
30
|
updateBundle,
|
|
32
31
|
} from "./native";
|
|
32
|
+
import { reportBundleDownloaded } from "./notifyAppReadyInsights";
|
|
33
33
|
import {
|
|
34
34
|
hasExpectedReleaseCatalogScope,
|
|
35
35
|
type ExpectedReleaseCatalogScope,
|
|
@@ -60,7 +60,7 @@ export interface CheckForUpdateOptions {
|
|
|
60
60
|
requestTimeout?: number;
|
|
61
61
|
}
|
|
62
62
|
|
|
63
|
-
export type CheckForUpdateResult =
|
|
63
|
+
export type CheckForUpdateResult = {
|
|
64
64
|
readonly id: string;
|
|
65
65
|
readonly message: string | null;
|
|
66
66
|
readonly rolloutCohortCount: number;
|
|
@@ -83,7 +83,7 @@ export type ReleaseTransitionKind =
|
|
|
83
83
|
| "USE_BUILTIN";
|
|
84
84
|
|
|
85
85
|
export interface InternalCheckForUpdateOptions extends CheckForUpdateOptions {
|
|
86
|
-
|
|
86
|
+
insights?: boolean;
|
|
87
87
|
client: HotUpdaterHttpClient;
|
|
88
88
|
}
|
|
89
89
|
|
|
@@ -121,14 +121,12 @@ const resetProgress = () => {
|
|
|
121
121
|
hotUpdaterStore.setState({
|
|
122
122
|
artifactType: null,
|
|
123
123
|
details: null,
|
|
124
|
-
downloadedBytes: undefined,
|
|
125
124
|
isUpdateDownloaded: false,
|
|
126
125
|
progress: 0,
|
|
127
|
-
totalBytes: undefined,
|
|
128
126
|
});
|
|
129
127
|
};
|
|
130
128
|
|
|
131
|
-
const
|
|
129
|
+
const notifyUnchangedSelection = async (input: {
|
|
132
130
|
readonly active: PersistedSelectionReceipt | null;
|
|
133
131
|
readonly desired: PersistedSelectionReceipt;
|
|
134
132
|
readonly appVersion: string;
|
|
@@ -138,16 +136,15 @@ const notifyReleaseAdoption = async (input: {
|
|
|
138
136
|
readonly session: HotUpdaterHttpSession;
|
|
139
137
|
readonly requestHeaders?: Record<string, string>;
|
|
140
138
|
readonly requestTimeout?: number;
|
|
141
|
-
readonly updateStrategy: "appVersion" | "fingerprint";
|
|
142
139
|
}): Promise<void> => {
|
|
143
140
|
const { userId, username } = getPersistedUserIdentity();
|
|
144
141
|
try {
|
|
145
|
-
await input.session.
|
|
142
|
+
await input.session.sendInsightsEvent({
|
|
146
143
|
appVersion: input.appVersion,
|
|
147
144
|
channel: input.desired.channel,
|
|
148
145
|
cohort: input.cohort,
|
|
149
146
|
fingerprintHash: input.fingerprintHash,
|
|
150
|
-
fromBundleId:
|
|
147
|
+
fromBundleId: null,
|
|
151
148
|
fromReleaseId: input.active?.releaseId ?? null,
|
|
152
149
|
installId: getInstallId(),
|
|
153
150
|
platform: input.platform,
|
|
@@ -155,13 +152,13 @@ const notifyReleaseAdoption = async (input: {
|
|
|
155
152
|
requestTimeout: input.requestTimeout,
|
|
156
153
|
toBundleId: input.desired.bundleId,
|
|
157
154
|
toReleaseId: input.desired.releaseId,
|
|
158
|
-
type: "
|
|
159
|
-
updateStrategy:
|
|
155
|
+
type: "UNCHANGED",
|
|
156
|
+
updateStrategy: null,
|
|
160
157
|
...(userId === undefined ? {} : { userId }),
|
|
161
158
|
...(username === undefined ? {} : { username }),
|
|
162
159
|
});
|
|
163
160
|
} catch (error) {
|
|
164
|
-
console.warn("[HotUpdater]
|
|
161
|
+
console.warn("[HotUpdater] Unchanged selection insights failed:", error);
|
|
165
162
|
}
|
|
166
163
|
};
|
|
167
164
|
|
|
@@ -218,7 +215,8 @@ async function checkForReleaseCatalogUpdate(input: {
|
|
|
218
215
|
const scopeKey = catalog.scopeKey;
|
|
219
216
|
|
|
220
217
|
const crashedBundleIds = getCrashHistory();
|
|
221
|
-
const
|
|
218
|
+
const activeState = getActiveUpdateState();
|
|
219
|
+
const active = activeState.activeSelection;
|
|
222
220
|
const explicitScopeSwitch =
|
|
223
221
|
input.explicitChannel !== undefined &&
|
|
224
222
|
input.explicitChannel !== input.currentChannel;
|
|
@@ -340,12 +338,8 @@ async function checkForReleaseCatalogUpdate(input: {
|
|
|
340
338
|
guard,
|
|
341
339
|
selection: receipt,
|
|
342
340
|
});
|
|
343
|
-
if (
|
|
344
|
-
|
|
345
|
-
transitionKind === "ADOPT_RELEASE" &&
|
|
346
|
-
options.analytics
|
|
347
|
-
) {
|
|
348
|
-
await notifyReleaseAdoption({
|
|
341
|
+
if (committed && transitionKind === "ADOPT_RELEASE" && options.insights) {
|
|
342
|
+
await notifyUnchangedSelection({
|
|
349
343
|
active,
|
|
350
344
|
appVersion: input.currentAppVersion,
|
|
351
345
|
cohort: input.cohort,
|
|
@@ -355,7 +349,6 @@ async function checkForReleaseCatalogUpdate(input: {
|
|
|
355
349
|
requestHeaders: options.requestHeaders,
|
|
356
350
|
requestTimeout: options.requestTimeout,
|
|
357
351
|
session,
|
|
358
|
-
updateStrategy: options.updateStrategy,
|
|
359
352
|
});
|
|
360
353
|
}
|
|
361
354
|
return committed;
|
|
@@ -370,24 +363,37 @@ async function checkForReleaseCatalogUpdate(input: {
|
|
|
370
363
|
if (!isReleaseSelectionCurrent(guard)) {
|
|
371
364
|
throw new StaleReleaseCatalogError();
|
|
372
365
|
}
|
|
373
|
-
|
|
366
|
+
const downloaded = await updateBundle({
|
|
367
|
+
assets: artifact.assets,
|
|
374
368
|
bundleId: desired.bundleId,
|
|
375
|
-
changedAssets: artifact.changedAssets ?? null,
|
|
376
369
|
channel: input.targetChannel,
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
manifestUrl: artifact.manifestUrl ?? null,
|
|
370
|
+
manifestFileHash: artifact.manifestFileHash,
|
|
371
|
+
manifestUrl: artifact.manifestUrl,
|
|
372
|
+
...(artifact.archiveUrl ? { archiveUrl: artifact.archiveUrl } : {}),
|
|
381
373
|
selection: receipt,
|
|
382
374
|
shouldSkipCurrentBundleIdCheck: true,
|
|
383
375
|
status: desired.status,
|
|
384
376
|
});
|
|
377
|
+
if (downloaded) {
|
|
378
|
+
await reportBundleDownloaded(options, {
|
|
379
|
+
fromBundleId: input.currentBundleId,
|
|
380
|
+
fromReleaseId:
|
|
381
|
+
active?.bundleId === input.currentBundleId
|
|
382
|
+
? active.releaseId
|
|
383
|
+
: activeState.stableSelection?.bundleId === input.currentBundleId
|
|
384
|
+
? activeState.stableSelection.releaseId
|
|
385
|
+
: null,
|
|
386
|
+
toBundleId: desired.bundleId,
|
|
387
|
+
toReleaseId: desired.releaseId,
|
|
388
|
+
channel: input.targetChannel,
|
|
389
|
+
updateStrategy: options.updateStrategy,
|
|
390
|
+
});
|
|
391
|
+
}
|
|
392
|
+
return downloaded;
|
|
385
393
|
};
|
|
386
394
|
|
|
387
395
|
return {
|
|
388
|
-
|
|
389
|
-
fileUrl: null,
|
|
390
|
-
id: desired.bundleId,
|
|
396
|
+
id: desired.releaseId ?? desired.bundleId,
|
|
391
397
|
message: release?.message ?? null,
|
|
392
398
|
releaseId: desired.releaseId,
|
|
393
399
|
rolloutCohortCount: release?.rolloutCohortCount ?? 1000,
|
package/src/error.ts
CHANGED
|
@@ -7,7 +7,7 @@
|
|
|
7
7
|
*
|
|
8
8
|
* Error Classification:
|
|
9
9
|
* - Parameter Validation: Invalid or missing function parameters
|
|
10
|
-
* - Bundle Storage: Errors during download,
|
|
10
|
+
* - Bundle Storage: Errors during download, verification, and storage
|
|
11
11
|
* - Signature Verification: Cryptographic verification failures (collapsed to a single public code)
|
|
12
12
|
* - Internal: Platform-specific or unexpected errors
|
|
13
13
|
*
|
|
@@ -27,8 +27,7 @@ export enum HotUpdaterErrorCode {
|
|
|
27
27
|
MISSING_BUNDLE_ID = "MISSING_BUNDLE_ID",
|
|
28
28
|
|
|
29
29
|
/**
|
|
30
|
-
*
|
|
31
|
-
* Thrown when fileUrl parameter cannot be parsed as a valid URL.
|
|
30
|
+
* Manifest or asset URL is invalid or malformed.
|
|
32
31
|
* @retryable false
|
|
33
32
|
*/
|
|
34
33
|
INVALID_FILE_URL = "INVALID_FILE_URL",
|
|
@@ -58,25 +57,16 @@ export enum HotUpdaterErrorCode {
|
|
|
58
57
|
*/
|
|
59
58
|
INCOMPLETE_DOWNLOAD = "INCOMPLETE_DOWNLOAD",
|
|
60
59
|
|
|
61
|
-
/**
|
|
62
|
-
* Bundle archive format is invalid or corrupted.
|
|
63
|
-
* Thrown when ZIP file has wrong magic bytes, invalid structure, or unsupported format.
|
|
64
|
-
* Also thrown for path traversal attempts during extraction.
|
|
65
|
-
* @retryable false - Indicates corrupted or malicious bundle
|
|
66
|
-
*/
|
|
67
|
-
EXTRACTION_FORMAT_ERROR = "EXTRACTION_FORMAT_ERROR",
|
|
68
|
-
|
|
69
60
|
/**
|
|
70
61
|
* Bundle missing required platform files.
|
|
71
|
-
* Thrown when
|
|
62
|
+
* Thrown when the staged bundle doesn't contain index.android.bundle (Android)
|
|
72
63
|
* or main.jsbundle (iOS).
|
|
73
64
|
* @retryable false - Indicates incorrectly built bundle
|
|
74
65
|
*/
|
|
75
66
|
INVALID_BUNDLE = "INVALID_BUNDLE",
|
|
76
67
|
|
|
77
68
|
/**
|
|
78
|
-
* Insufficient disk space for bundle
|
|
79
|
-
* Thrown when available disk space is less than required (file size * 2).
|
|
69
|
+
* Insufficient disk space for bundle staging.
|
|
80
70
|
* Error message includes required and available bytes.
|
|
81
71
|
* @retryable false - User must free up disk space
|
|
82
72
|
*/
|
package/src/fetchJSON.ts
CHANGED
|
@@ -1,3 +1,14 @@
|
|
|
1
|
+
export class FetchJSONResponseError extends Error {
|
|
2
|
+
constructor(
|
|
3
|
+
readonly status: number,
|
|
4
|
+
statusText: string,
|
|
5
|
+
) {
|
|
6
|
+
super(
|
|
7
|
+
`Request failed with HTTP ${status}${statusText ? ` ${statusText}` : ""}`,
|
|
8
|
+
);
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
|
|
1
12
|
export const fetchJSON = async <T>({
|
|
2
13
|
url,
|
|
3
14
|
requestHeaders,
|
|
@@ -19,7 +30,7 @@ export const fetchJSON = async <T>({
|
|
|
19
30
|
signal: controller.signal,
|
|
20
31
|
});
|
|
21
32
|
if (response.status !== 200) {
|
|
22
|
-
throw new
|
|
33
|
+
throw new FetchJSONResponseError(response.status, response.statusText);
|
|
23
34
|
}
|
|
24
35
|
return (await response.json()) as T;
|
|
25
36
|
} catch (error: unknown) {
|