@hot-updater/react-native 1.0.0-rc.14 → 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 +2 -2
- package/android/src/main/java/com/hotupdater/BuiltInAssetResolver.kt +286 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +650 -636
- package/android/src/main/java/com/hotupdater/BundleMetadata.kt +3 -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/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/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 +47 -31
- 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/lib/commonjs/checkForUpdate.js +7 -10
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/checkForUpdate.releaseCatalog.spec.js +9 -4
- 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 +44 -27
- 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 +2 -6
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +7 -8
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +21 -16
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js +7 -0
- package/lib/commonjs/notifyAppReadyInsights.boundary.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.js +4 -1
- package/lib/commonjs/notifyAppReadyInsights.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.spec.js +59 -0
- package/lib/commonjs/notifyAppReadyInsights.spec.js.map +1 -1
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js +7 -0
- package/lib/commonjs/notifyAppReadyInsights.transport.spec.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +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 +1 -3
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +7 -0
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/checkForUpdate.js +7 -10
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/checkForUpdate.releaseCatalog.spec.js +9 -4
- 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 +46 -29
- 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 +2 -6
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +7 -8
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +21 -16
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.boundary.spec.js +7 -0
- package/lib/module/notifyAppReadyInsights.boundary.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.js +5 -2
- package/lib/module/notifyAppReadyInsights.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.spec.js +59 -0
- package/lib/module/notifyAppReadyInsights.spec.js.map +1 -1
- package/lib/module/notifyAppReadyInsights.transport.spec.js +7 -0
- package/lib/module/notifyAppReadyInsights.transport.spec.js.map +1 -1
- package/lib/module/sdkVersion.js +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 +1 -3
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +7 -0
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +1 -2
- 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.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +0 -2
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +1 -6
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts +1 -1
- package/lib/typescript/commonjs/notifyAppReadyInsights.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +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.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.types.d.ts +0 -2
- package/lib/typescript/commonjs/wrap.types.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +1 -2
- 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.map +1 -1
- package/lib/typescript/module/index.d.ts +0 -2
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +1 -6
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts +1 -1
- package/lib/typescript/module/notifyAppReadyInsights.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +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.d.ts.map +1 -1
- package/lib/typescript/module/wrap.types.d.ts +0 -2
- package/lib/typescript/module/wrap.types.d.ts.map +1 -1
- package/package.json +3 -3
- package/src/checkForUpdate.releaseCatalog.spec.ts +10 -4
- package/src/checkForUpdate.ts +5 -11
- package/src/error.ts +4 -14
- package/src/fetchJSON.ts +12 -1
- package/src/httpClient.spec.ts +70 -5
- package/src/httpClient.ts +67 -53
- package/src/index.ts +1 -5
- package/src/native.spec.ts +23 -16
- package/src/native.ts +12 -24
- package/src/notifyAppReadyInsights.boundary.spec.ts +8 -0
- package/src/notifyAppReadyInsights.spec.ts +60 -0
- package/src/notifyAppReadyInsights.transport.spec.ts +8 -0
- package/src/notifyAppReadyInsights.ts +13 -1
- 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 +8 -0
- package/src/wrap.tsx +0 -2
- package/src/wrap.types.ts +0 -2
- 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/src/native.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import {
|
|
2
|
-
type
|
|
2
|
+
type ArtifactAsset,
|
|
3
3
|
type CatalogHighWater,
|
|
4
4
|
INVALID_COHORT_ERROR_MESSAGE,
|
|
5
5
|
isValidCohort,
|
|
@@ -234,7 +234,7 @@ const getReloadProcess = (): (() => Promise<void>) | null => {
|
|
|
234
234
|
: null;
|
|
235
235
|
};
|
|
236
236
|
|
|
237
|
-
export type HotUpdaterProgressArtifactType = "
|
|
237
|
+
export type HotUpdaterProgressArtifactType = "diff";
|
|
238
238
|
|
|
239
239
|
export type HotUpdaterDiffFileStatus =
|
|
240
240
|
| "pending"
|
|
@@ -286,18 +286,11 @@ export interface HotUpdaterDiffProgressDetails {
|
|
|
286
286
|
files: HotUpdaterDiffFileSnapshot[];
|
|
287
287
|
}
|
|
288
288
|
|
|
289
|
-
export type HotUpdaterProgressEvent =
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
totalBytes?: number;
|
|
295
|
-
}
|
|
296
|
-
| {
|
|
297
|
-
progress: number;
|
|
298
|
-
artifactType: "diff";
|
|
299
|
-
details: HotUpdaterDiffProgressDetails;
|
|
300
|
-
};
|
|
289
|
+
export type HotUpdaterProgressEvent = {
|
|
290
|
+
progress: number;
|
|
291
|
+
artifactType: "diff";
|
|
292
|
+
details: HotUpdaterDiffProgressDetails;
|
|
293
|
+
};
|
|
301
294
|
|
|
302
295
|
export type HotUpdaterEvent = {
|
|
303
296
|
onProgress: HotUpdaterProgressEvent;
|
|
@@ -434,8 +427,6 @@ export const commitReleaseSelection = async (input: {
|
|
|
434
427
|
export async function updateBundle(params: UpdateParams): Promise<boolean> {
|
|
435
428
|
const updateBundleId = params.bundleId;
|
|
436
429
|
const status = params.status;
|
|
437
|
-
const targetFileUrl = params.fileUrl;
|
|
438
|
-
|
|
439
430
|
const currentBundleId = status === "UPDATE" ? getFreshBundleId() : undefined;
|
|
440
431
|
|
|
441
432
|
// If native is still on the same bundle we installed in this session,
|
|
@@ -467,11 +458,10 @@ export async function updateBundle(params: UpdateParams): Promise<boolean> {
|
|
|
467
458
|
const existing = sessionState.getInflightUpdate(updateBundleId);
|
|
468
459
|
if (existing) return existing;
|
|
469
460
|
|
|
470
|
-
const targetFileHash = params.fileHash;
|
|
471
461
|
const targetChannel = params.channel;
|
|
472
462
|
const targetManifestUrl = params.manifestUrl;
|
|
473
463
|
const targetManifestFileHash = params.manifestFileHash;
|
|
474
|
-
const
|
|
464
|
+
const targetAssets = params.assets;
|
|
475
465
|
|
|
476
466
|
const promise = (async () => {
|
|
477
467
|
try {
|
|
@@ -479,12 +469,10 @@ export async function updateBundle(params: UpdateParams): Promise<boolean> {
|
|
|
479
469
|
const ok = await HotUpdaterNative.updateBundle({
|
|
480
470
|
bundleId: updateBundleId,
|
|
481
471
|
channel: targetChannel,
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
manifestFileHash: targetManifestFileHash ?? null,
|
|
487
|
-
manifestUrl: targetManifestUrl ?? null,
|
|
472
|
+
assets: targetAssets as Record<string, ArtifactAsset>,
|
|
473
|
+
manifestFileHash: targetManifestFileHash,
|
|
474
|
+
manifestUrl: targetManifestUrl,
|
|
475
|
+
...(params.archiveUrl ? { archiveUrl: params.archiveUrl } : {}),
|
|
488
476
|
...(selection === undefined ? {} : { selection }),
|
|
489
477
|
});
|
|
490
478
|
if (ok) {
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
+
ActiveUpdateState,
|
|
4
5
|
NotifyAppReadyInsightsEvent,
|
|
5
6
|
NotifyAppReadyResult,
|
|
6
7
|
} from "./native";
|
|
@@ -42,6 +43,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
42
43
|
getAppVersion: vi.fn<() => string | undefined>(() => "1.0.0"),
|
|
43
44
|
getBundleId: vi.fn<() => string | undefined>(() => "bundle-id"),
|
|
44
45
|
getChannel: vi.fn(() => "production"),
|
|
46
|
+
getActiveUpdateState: vi.fn<() => ActiveUpdateState>(),
|
|
45
47
|
getCohort: vi.fn(() => "123"),
|
|
46
48
|
getFingerprintHash: vi.fn(() => "fingerprint-hash"),
|
|
47
49
|
getInstallId: vi.fn<() => string | undefined>(() => "install-id"),
|
|
@@ -65,6 +67,7 @@ vi.mock("./native", () => ({
|
|
|
65
67
|
getAppVersion: mocks.getAppVersion,
|
|
66
68
|
getBundleId: mocks.getBundleId,
|
|
67
69
|
getChannel: mocks.getChannel,
|
|
70
|
+
getActiveUpdateState: mocks.getActiveUpdateState,
|
|
68
71
|
getCohort: mocks.getCohort,
|
|
69
72
|
getFingerprintHash: mocks.getFingerprintHash,
|
|
70
73
|
getInstallId: mocks.getInstallId,
|
|
@@ -106,6 +109,11 @@ describe("automatic notifyAppReady insights boundaries", () => {
|
|
|
106
109
|
mocks.getAppVersion.mockReturnValue("1.0.0");
|
|
107
110
|
mocks.getBundleId.mockReturnValue("bundle-id");
|
|
108
111
|
mocks.getChannel.mockReturnValue("production");
|
|
112
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
113
|
+
activeSelection: null,
|
|
114
|
+
stableSelection: null,
|
|
115
|
+
verificationPending: false,
|
|
116
|
+
});
|
|
109
117
|
mocks.getCohort.mockReturnValue("123");
|
|
110
118
|
mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
|
|
111
119
|
mocks.getInstallId.mockReturnValue("install-id");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
+
ActiveUpdateState,
|
|
4
5
|
NotifyAppReadyInsightsEvent,
|
|
5
6
|
NotifyAppReadyResult,
|
|
6
7
|
} from "./native";
|
|
@@ -19,6 +20,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
19
20
|
getAppVersion: vi.fn(() => "1.0.0"),
|
|
20
21
|
getBundleId: vi.fn(() => "bundle-id"),
|
|
21
22
|
getChannel: vi.fn(() => "production"),
|
|
23
|
+
getActiveUpdateState: vi.fn<() => ActiveUpdateState>(),
|
|
22
24
|
getCohort: vi.fn(() => "123"),
|
|
23
25
|
getFingerprintHash: vi.fn(() => "fingerprint-hash"),
|
|
24
26
|
getInstallId: vi.fn(() => "install-id"),
|
|
@@ -42,6 +44,7 @@ vi.mock("./native", () => ({
|
|
|
42
44
|
getAppVersion: mocks.getAppVersion,
|
|
43
45
|
getBundleId: mocks.getBundleId,
|
|
44
46
|
getChannel: mocks.getChannel,
|
|
47
|
+
getActiveUpdateState: mocks.getActiveUpdateState,
|
|
45
48
|
getCohort: mocks.getCohort,
|
|
46
49
|
getFingerprintHash: mocks.getFingerprintHash,
|
|
47
50
|
getInstallId: mocks.getInstallId,
|
|
@@ -78,6 +81,11 @@ describe("automatic notifyAppReady insights", () => {
|
|
|
78
81
|
mocks.addListener.mockReturnValue(() => {});
|
|
79
82
|
mocks.getBundleId.mockReturnValue("bundle-id");
|
|
80
83
|
mocks.getChannel.mockReturnValue("production");
|
|
84
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
85
|
+
activeSelection: null,
|
|
86
|
+
stableSelection: null,
|
|
87
|
+
verificationPending: false,
|
|
88
|
+
});
|
|
81
89
|
mocks.getCohort.mockReturnValue("123");
|
|
82
90
|
mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
|
|
83
91
|
mocks.getInstallId.mockReturnValue("install-id");
|
|
@@ -85,6 +93,58 @@ describe("automatic notifyAppReady insights", () => {
|
|
|
85
93
|
mocks.readNotifyAppReady.mockReturnValue(createNotifyReadResult());
|
|
86
94
|
});
|
|
87
95
|
|
|
96
|
+
it.each([
|
|
97
|
+
{
|
|
98
|
+
label: "running selection",
|
|
99
|
+
pending: false,
|
|
100
|
+
channel: "production",
|
|
101
|
+
expected: "release-running",
|
|
102
|
+
},
|
|
103
|
+
{
|
|
104
|
+
label: "staged selection",
|
|
105
|
+
pending: true,
|
|
106
|
+
channel: "production",
|
|
107
|
+
expected: "release-running",
|
|
108
|
+
},
|
|
109
|
+
{
|
|
110
|
+
label: "another channel",
|
|
111
|
+
pending: false,
|
|
112
|
+
channel: "preview",
|
|
113
|
+
expected: null,
|
|
114
|
+
},
|
|
115
|
+
])(
|
|
116
|
+
"attributes an unchanged launch with $label",
|
|
117
|
+
async ({ pending, channel, expected }) => {
|
|
118
|
+
const running = {
|
|
119
|
+
kind: "BUNDLE" as const,
|
|
120
|
+
releaseId: "release-running",
|
|
121
|
+
bundleId: "bundle-id",
|
|
122
|
+
channel,
|
|
123
|
+
};
|
|
124
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
125
|
+
activeSelection: pending
|
|
126
|
+
? {
|
|
127
|
+
...running,
|
|
128
|
+
releaseId: "release-pending",
|
|
129
|
+
bundleId: "bundle-pending",
|
|
130
|
+
}
|
|
131
|
+
: running,
|
|
132
|
+
stableSelection: pending ? running : null,
|
|
133
|
+
verificationPending: pending,
|
|
134
|
+
});
|
|
135
|
+
const { reportNoChange } = await import("./notifyAppReadyInsights");
|
|
136
|
+
const { client, sendInsightsEvent } = createClient();
|
|
137
|
+
await reportNoChange({ client, insights: true });
|
|
138
|
+
expect(sendInsightsEvent).toHaveBeenCalledWith(
|
|
139
|
+
expect.objectContaining({
|
|
140
|
+
type: "UNCHANGED",
|
|
141
|
+
toBundleId: "bundle-id",
|
|
142
|
+
toReleaseId: expected,
|
|
143
|
+
}),
|
|
144
|
+
);
|
|
145
|
+
},
|
|
146
|
+
);
|
|
147
|
+
|
|
88
148
|
it("orders download after in-flight startup reporting and suppresses a later no-change report", async () => {
|
|
89
149
|
const { handleNotifyAppReady, reportBundleDownloaded, reportNoChange } =
|
|
90
150
|
await import("./notifyAppReadyInsights");
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
2
2
|
|
|
3
3
|
import type {
|
|
4
|
+
ActiveUpdateState,
|
|
4
5
|
NotifyAppReadyInsightsEvent,
|
|
5
6
|
NotifyAppReadyResult,
|
|
6
7
|
} from "./native";
|
|
@@ -30,6 +31,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
30
31
|
getAppVersion: vi.fn(() => "1.0.0"),
|
|
31
32
|
getBundleId: vi.fn(() => "bundle-id"),
|
|
32
33
|
getChannel: vi.fn(() => "production"),
|
|
34
|
+
getActiveUpdateState: vi.fn<() => ActiveUpdateState>(),
|
|
33
35
|
getCohort: vi.fn(() => "123"),
|
|
34
36
|
getFingerprintHash: vi.fn(() => "fingerprint-hash"),
|
|
35
37
|
getInstallId: vi.fn(() => "install-id"),
|
|
@@ -53,6 +55,7 @@ vi.mock("./native", () => ({
|
|
|
53
55
|
getAppVersion: mocks.getAppVersion,
|
|
54
56
|
getBundleId: mocks.getBundleId,
|
|
55
57
|
getChannel: mocks.getChannel,
|
|
58
|
+
getActiveUpdateState: mocks.getActiveUpdateState,
|
|
56
59
|
getCohort: mocks.getCohort,
|
|
57
60
|
getFingerprintHash: mocks.getFingerprintHash,
|
|
58
61
|
getInstallId: mocks.getInstallId,
|
|
@@ -75,6 +78,11 @@ describe("automatic notifyAppReady transport failures", () => {
|
|
|
75
78
|
mocks.getAppVersion.mockReturnValue("1.0.0");
|
|
76
79
|
mocks.getBundleId.mockReturnValue("bundle-id");
|
|
77
80
|
mocks.getChannel.mockReturnValue("production");
|
|
81
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
82
|
+
activeSelection: null,
|
|
83
|
+
stableSelection: null,
|
|
84
|
+
verificationPending: false,
|
|
85
|
+
});
|
|
78
86
|
mocks.getCohort.mockReturnValue("123");
|
|
79
87
|
mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
|
|
80
88
|
mocks.getInstallId.mockReturnValue("install-id");
|
|
@@ -3,6 +3,7 @@ import { Platform } from "react-native";
|
|
|
3
3
|
import type { HotUpdaterError } from "./error";
|
|
4
4
|
import type { InsightsEventParams, HotUpdaterHttpClient } from "./httpClient";
|
|
5
5
|
import {
|
|
6
|
+
getActiveUpdateState,
|
|
6
7
|
getAppVersion,
|
|
7
8
|
getBundleId,
|
|
8
9
|
getChannel,
|
|
@@ -101,10 +102,21 @@ const buildNotifyAppReadyInsightsParams = (
|
|
|
101
102
|
);
|
|
102
103
|
}
|
|
103
104
|
|
|
105
|
+
const state = getActiveUpdateState();
|
|
106
|
+
const runningSelection = [
|
|
107
|
+
state.activeSelection,
|
|
108
|
+
state.stableSelection,
|
|
109
|
+
].find(
|
|
110
|
+
(selection) =>
|
|
111
|
+
selection?.bundleId === bundleId &&
|
|
112
|
+
selection.channel === commonParams.channel,
|
|
113
|
+
);
|
|
114
|
+
|
|
104
115
|
return {
|
|
105
116
|
...commonParams,
|
|
106
117
|
fromBundleId: null,
|
|
107
118
|
toBundleId: bundleId,
|
|
119
|
+
toReleaseId: runningSelection?.releaseId ?? null,
|
|
108
120
|
type: "UNCHANGED",
|
|
109
121
|
updateStrategy: null,
|
|
110
122
|
};
|
|
@@ -237,7 +249,7 @@ export const reportNoChange = async (
|
|
|
237
249
|
|
|
238
250
|
let lastDownloadedSelection: string | undefined;
|
|
239
251
|
|
|
240
|
-
/** Report only after the
|
|
252
|
+
/** Report only after the manifest update has been verified and staged successfully. */
|
|
241
253
|
export const reportBundleDownloaded = async (
|
|
242
254
|
options: Pick<
|
|
243
255
|
NotifyAppReadyOptions,
|
package/src/sdkVersion.ts
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
export const HOT_UPDATER_SDK_VERSION = "1.0.0-rc.
|
|
1
|
+
export const HOT_UPDATER_SDK_VERSION = "1.0.0-rc.15";
|
|
@@ -2,48 +2,21 @@ import type { TurboModule } from "react-native";
|
|
|
2
2
|
import { TurboModuleRegistry } from "react-native";
|
|
3
3
|
import type { UnsafeObject } from "react-native/Libraries/Types/CodegenTypes";
|
|
4
4
|
|
|
5
|
-
export interface ChangedAsset {
|
|
6
|
-
file?: {
|
|
7
|
-
compression?: "br" | null;
|
|
8
|
-
url: string;
|
|
9
|
-
} | null;
|
|
10
|
-
fileHash: string;
|
|
11
|
-
patch?: {
|
|
12
|
-
algorithm: "bsdiff";
|
|
13
|
-
baseBundleId: string;
|
|
14
|
-
baseFileHash: string;
|
|
15
|
-
patchFileHash: string;
|
|
16
|
-
patchUrl: string;
|
|
17
|
-
} | null;
|
|
18
|
-
}
|
|
19
|
-
|
|
20
5
|
export interface UpdateBundleParams {
|
|
21
6
|
bundleId: string;
|
|
22
7
|
channel?: string;
|
|
23
|
-
fileUrl: string | null;
|
|
24
|
-
/**
|
|
25
|
-
* File hash for integrity/signature verification.
|
|
26
|
-
*
|
|
27
|
-
* Format depends on signing configuration:
|
|
28
|
-
* - Signed: `sig:<base64_signature>` - Native will verify signature (and implicitly hash)
|
|
29
|
-
* - Unsigned: `<hex_hash>` - Native will verify SHA256 hash only
|
|
30
|
-
*
|
|
31
|
-
* Native determines verification mode by checking for "sig:" prefix.
|
|
32
|
-
*/
|
|
33
|
-
fileHash: string | null;
|
|
34
8
|
/**
|
|
35
|
-
*
|
|
9
|
+
* Signed manifest URL for installation.
|
|
36
10
|
*/
|
|
37
|
-
manifestUrl
|
|
11
|
+
manifestUrl: string;
|
|
38
12
|
/**
|
|
39
13
|
* File hash/signature for the manifest file itself.
|
|
40
14
|
*/
|
|
41
|
-
manifestFileHash
|
|
42
|
-
/**
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
changedAssets?: UnsafeObject | null;
|
|
15
|
+
manifestFileHash: string;
|
|
16
|
+
/** Optional tar.br URL; integrity and sizes come from the verified manifest. */
|
|
17
|
+
archiveUrl?: string | null;
|
|
18
|
+
/** Full protocol v1 target file descriptor map. */
|
|
19
|
+
assets: UnsafeObject;
|
|
47
20
|
/** Full Release Catalog selection receipt committed with the staged Bundle. */
|
|
48
21
|
selection?: UnsafeObject | null;
|
|
49
22
|
}
|
|
@@ -66,13 +39,12 @@ export interface Spec extends TurboModule {
|
|
|
66
39
|
*
|
|
67
40
|
* Parameter validation:
|
|
68
41
|
* - MISSING_BUNDLE_ID: Missing or empty bundleId
|
|
69
|
-
* - INVALID_FILE_URL: Invalid
|
|
42
|
+
* - INVALID_FILE_URL: Invalid manifest or asset URL provided
|
|
70
43
|
*
|
|
71
44
|
* Bundle storage:
|
|
72
45
|
* - DIRECTORY_CREATION_FAILED: Failed to create bundle directory
|
|
73
46
|
* - DOWNLOAD_FAILED: Failed to download bundle
|
|
74
47
|
* - INCOMPLETE_DOWNLOAD: Download incomplete (size mismatch)
|
|
75
|
-
* - EXTRACTION_FORMAT_ERROR: Invalid or corrupted archive format
|
|
76
48
|
* - INVALID_BUNDLE: Bundle missing required platform files
|
|
77
49
|
* - INSUFFICIENT_DISK_SPACE: Insufficient disk space
|
|
78
50
|
* - MOVE_OPERATION_FAILED: Failed to move bundle files
|
|
@@ -61,10 +61,20 @@ describe("hotUpdaterStore notification scheduling", () => {
|
|
|
61
61
|
|
|
62
62
|
const nextProgress = Math.min(1, progress + 0.01);
|
|
63
63
|
emitProgress?.({
|
|
64
|
-
artifactType: "
|
|
65
|
-
|
|
64
|
+
artifactType: "diff",
|
|
65
|
+
details: {
|
|
66
|
+
completedFilesCount: nextProgress === 1 ? 1 : 0,
|
|
67
|
+
files: [
|
|
68
|
+
{
|
|
69
|
+
order: 0,
|
|
70
|
+
path: "index.ios.bundle",
|
|
71
|
+
progress: nextProgress,
|
|
72
|
+
status: nextProgress === 1 ? "downloaded" : "downloading",
|
|
73
|
+
},
|
|
74
|
+
],
|
|
75
|
+
totalFilesCount: 1,
|
|
76
|
+
},
|
|
66
77
|
progress: nextProgress,
|
|
67
|
-
totalBytes: 1_000_000,
|
|
68
78
|
});
|
|
69
79
|
}, [progress]);
|
|
70
80
|
|
package/src/store.spec.ts
CHANGED
|
@@ -41,75 +41,6 @@ describe("hotUpdaterStore", () => {
|
|
|
41
41
|
unsubscribe();
|
|
42
42
|
});
|
|
43
43
|
|
|
44
|
-
it("notifies subscribers only when progress events change the snapshot", async () => {
|
|
45
|
-
const store = await importStore();
|
|
46
|
-
const listener = vi.fn();
|
|
47
|
-
const emitProgress = listeners.get("onProgress");
|
|
48
|
-
|
|
49
|
-
expect(emitProgress).toBeTypeOf("function");
|
|
50
|
-
|
|
51
|
-
const unsubscribe = store.subscribe(listener);
|
|
52
|
-
|
|
53
|
-
emitProgress?.({
|
|
54
|
-
artifactType: "archive",
|
|
55
|
-
progress: 0.5,
|
|
56
|
-
});
|
|
57
|
-
emitProgress?.({
|
|
58
|
-
artifactType: "archive",
|
|
59
|
-
progress: 0.5,
|
|
60
|
-
});
|
|
61
|
-
emitProgress?.({
|
|
62
|
-
artifactType: "archive",
|
|
63
|
-
progress: 1,
|
|
64
|
-
});
|
|
65
|
-
store.setState({ isUpdateDownloaded: true });
|
|
66
|
-
|
|
67
|
-
expect(listener).toHaveBeenCalledTimes(2);
|
|
68
|
-
expect(store.getSnapshot()).toEqual({
|
|
69
|
-
artifactType: "archive",
|
|
70
|
-
details: null,
|
|
71
|
-
downloadedBytes: undefined,
|
|
72
|
-
isUpdateDownloaded: true,
|
|
73
|
-
progress: 1,
|
|
74
|
-
totalBytes: undefined,
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
unsubscribe();
|
|
78
|
-
});
|
|
79
|
-
|
|
80
|
-
it("stores archive byte metadata and notifies when only bytes change", async () => {
|
|
81
|
-
const store = await importStore();
|
|
82
|
-
const listener = vi.fn();
|
|
83
|
-
const emitProgress = listeners.get("onProgress");
|
|
84
|
-
|
|
85
|
-
const unsubscribe = store.subscribe(listener);
|
|
86
|
-
|
|
87
|
-
emitProgress?.({
|
|
88
|
-
artifactType: "archive",
|
|
89
|
-
downloadedBytes: 100.4,
|
|
90
|
-
progress: 0.5,
|
|
91
|
-
totalBytes: 1_000,
|
|
92
|
-
});
|
|
93
|
-
emitProgress?.({
|
|
94
|
-
artifactType: "archive",
|
|
95
|
-
downloadedBytes: 250,
|
|
96
|
-
progress: 0.5,
|
|
97
|
-
totalBytes: 1_000,
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
expect(listener).toHaveBeenCalledTimes(2);
|
|
101
|
-
expect(store.getSnapshot()).toEqual({
|
|
102
|
-
artifactType: "archive",
|
|
103
|
-
details: null,
|
|
104
|
-
downloadedBytes: 250,
|
|
105
|
-
isUpdateDownloaded: false,
|
|
106
|
-
progress: 0.5,
|
|
107
|
-
totalBytes: 1_000,
|
|
108
|
-
});
|
|
109
|
-
|
|
110
|
-
unsubscribe();
|
|
111
|
-
});
|
|
112
|
-
|
|
113
44
|
it("stores manifest progress metadata while keeping overall progress", async () => {
|
|
114
45
|
const store = await importStore();
|
|
115
46
|
const emitProgress = listeners.get("onProgress");
|
|
@@ -163,10 +94,8 @@ describe("hotUpdaterStore", () => {
|
|
|
163
94
|
],
|
|
164
95
|
totalFilesCount: 2,
|
|
165
96
|
},
|
|
166
|
-
downloadedBytes: undefined,
|
|
167
97
|
isUpdateDownloaded: false,
|
|
168
98
|
progress: 0.42,
|
|
169
|
-
totalBytes: undefined,
|
|
170
99
|
});
|
|
171
100
|
});
|
|
172
101
|
|
|
@@ -279,94 +208,8 @@ describe("hotUpdaterStore", () => {
|
|
|
279
208
|
],
|
|
280
209
|
totalFilesCount: 2,
|
|
281
210
|
},
|
|
282
|
-
downloadedBytes: undefined,
|
|
283
211
|
isUpdateDownloaded: false,
|
|
284
212
|
progress: 0.6,
|
|
285
|
-
totalBytes: undefined,
|
|
286
|
-
});
|
|
287
|
-
});
|
|
288
|
-
|
|
289
|
-
it("clears manifest metadata when archive progress events arrive", async () => {
|
|
290
|
-
const store = await importStore();
|
|
291
|
-
const emitProgress = listeners.get("onProgress");
|
|
292
|
-
|
|
293
|
-
emitProgress?.({
|
|
294
|
-
artifactType: "diff",
|
|
295
|
-
details: {
|
|
296
|
-
completedFilesCount: 2,
|
|
297
|
-
files: [
|
|
298
|
-
{
|
|
299
|
-
order: 0,
|
|
300
|
-
path: "index.ios.bundle",
|
|
301
|
-
progress: 1,
|
|
302
|
-
status: "downloaded",
|
|
303
|
-
},
|
|
304
|
-
{
|
|
305
|
-
order: 1,
|
|
306
|
-
path: "assets/logo.png",
|
|
307
|
-
progress: 1,
|
|
308
|
-
status: "downloaded",
|
|
309
|
-
},
|
|
310
|
-
{
|
|
311
|
-
order: 2,
|
|
312
|
-
path: "assets/bg.png",
|
|
313
|
-
progress: 0,
|
|
314
|
-
status: "pending",
|
|
315
|
-
},
|
|
316
|
-
],
|
|
317
|
-
totalFilesCount: 3,
|
|
318
|
-
},
|
|
319
|
-
progress: 0.9,
|
|
320
|
-
});
|
|
321
|
-
|
|
322
|
-
emitProgress?.({
|
|
323
|
-
artifactType: "archive",
|
|
324
|
-
progress: 0.25,
|
|
325
|
-
});
|
|
326
|
-
|
|
327
|
-
expect(store.getSnapshot()).toEqual({
|
|
328
|
-
artifactType: "archive",
|
|
329
|
-
details: null,
|
|
330
|
-
downloadedBytes: undefined,
|
|
331
|
-
isUpdateDownloaded: false,
|
|
332
|
-
progress: 0.25,
|
|
333
|
-
totalBytes: undefined,
|
|
334
|
-
});
|
|
335
|
-
});
|
|
336
|
-
|
|
337
|
-
it("clears stale manifest metadata even when archive events omit optional fields", async () => {
|
|
338
|
-
const store = await importStore();
|
|
339
|
-
const emitProgress = listeners.get("onProgress");
|
|
340
|
-
|
|
341
|
-
emitProgress?.({
|
|
342
|
-
artifactType: "diff",
|
|
343
|
-
details: {
|
|
344
|
-
completedFilesCount: 0,
|
|
345
|
-
files: [
|
|
346
|
-
{
|
|
347
|
-
order: 0,
|
|
348
|
-
path: "manifest.asset.png",
|
|
349
|
-
progress: 0,
|
|
350
|
-
status: "failed",
|
|
351
|
-
},
|
|
352
|
-
],
|
|
353
|
-
totalFilesCount: 1,
|
|
354
|
-
},
|
|
355
|
-
progress: 0.2,
|
|
356
|
-
});
|
|
357
|
-
|
|
358
|
-
emitProgress?.({
|
|
359
|
-
artifactType: "archive",
|
|
360
|
-
progress: 0.4,
|
|
361
|
-
});
|
|
362
|
-
|
|
363
|
-
expect(store.getSnapshot()).toEqual({
|
|
364
|
-
artifactType: "archive",
|
|
365
|
-
details: null,
|
|
366
|
-
downloadedBytes: undefined,
|
|
367
|
-
isUpdateDownloaded: false,
|
|
368
|
-
progress: 0.4,
|
|
369
|
-
totalBytes: undefined,
|
|
370
213
|
});
|
|
371
214
|
});
|
|
372
215
|
});
|
package/src/store.ts
CHANGED
|
@@ -9,10 +9,8 @@ import { addListener } from "./native";
|
|
|
9
9
|
|
|
10
10
|
export type HotUpdaterState = {
|
|
11
11
|
progress: number;
|
|
12
|
-
downloadedBytes: number | undefined;
|
|
13
|
-
totalBytes: number | undefined;
|
|
14
12
|
isUpdateDownloaded: boolean;
|
|
15
|
-
artifactType: "
|
|
13
|
+
artifactType: "diff" | null;
|
|
16
14
|
details: HotUpdaterDiffProgressDetails | null;
|
|
17
15
|
};
|
|
18
16
|
|
|
@@ -56,8 +54,6 @@ const areDiffDetailsEqual = (
|
|
|
56
54
|
const areStatesEqual = (left: HotUpdaterState, right: HotUpdaterState) => {
|
|
57
55
|
return (
|
|
58
56
|
left.progress === right.progress &&
|
|
59
|
-
left.downloadedBytes === right.downloadedBytes &&
|
|
60
|
-
left.totalBytes === right.totalBytes &&
|
|
61
57
|
left.isUpdateDownloaded === right.isUpdateDownloaded &&
|
|
62
58
|
left.artifactType === right.artifactType &&
|
|
63
59
|
areDiffDetailsEqual(left.details, right.details)
|
|
@@ -78,8 +74,6 @@ const normalizeDownloadPath = (value: string | undefined) => {
|
|
|
78
74
|
const createHotUpdaterStore = () => {
|
|
79
75
|
let state: HotUpdaterState = {
|
|
80
76
|
progress: 0,
|
|
81
|
-
downloadedBytes: undefined,
|
|
82
|
-
totalBytes: undefined,
|
|
83
77
|
isUpdateDownloaded: false,
|
|
84
78
|
artifactType: null,
|
|
85
79
|
details: null,
|
|
@@ -165,10 +159,6 @@ const createHotUpdaterStore = () => {
|
|
|
165
159
|
nextState.details = state.details;
|
|
166
160
|
}
|
|
167
161
|
|
|
168
|
-
if (nextState.artifactType !== "diff") {
|
|
169
|
-
nextState.details = null;
|
|
170
|
-
}
|
|
171
|
-
|
|
172
162
|
if (areStatesEqual(state, nextState)) {
|
|
173
163
|
return;
|
|
174
164
|
}
|
|
@@ -180,19 +170,8 @@ const createHotUpdaterStore = () => {
|
|
|
180
170
|
const applyProgressEvent = (event: HotUpdaterProgressEvent) => {
|
|
181
171
|
setState({
|
|
182
172
|
artifactType: event.artifactType,
|
|
183
|
-
details:
|
|
184
|
-
event.artifactType === "diff"
|
|
185
|
-
? normalizeDiffDetails(event.details)
|
|
186
|
-
: null,
|
|
187
|
-
downloadedBytes:
|
|
188
|
-
event.artifactType === "archive"
|
|
189
|
-
? normalizeByteCount(event.downloadedBytes)
|
|
190
|
-
: undefined,
|
|
173
|
+
details: normalizeDiffDetails(event.details),
|
|
191
174
|
progress: event.progress,
|
|
192
|
-
totalBytes:
|
|
193
|
-
event.artifactType === "archive"
|
|
194
|
-
? normalizeByteCount(event.totalBytes)
|
|
195
|
-
: undefined,
|
|
196
175
|
});
|
|
197
176
|
};
|
|
198
177
|
|
package/src/wrap.spec.ts
CHANGED
|
@@ -5,6 +5,7 @@ import { createElement, type ComponentType } from "react";
|
|
|
5
5
|
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
|
|
6
6
|
|
|
7
7
|
import type {
|
|
8
|
+
ActiveUpdateState,
|
|
8
9
|
NotifyAppReadyInsightsEvent,
|
|
9
10
|
NotifyAppReadyResult,
|
|
10
11
|
} from "./native";
|
|
@@ -37,6 +38,7 @@ const mocks = vi.hoisted(() => ({
|
|
|
37
38
|
getBundleId: vi.fn(() => "bundle-id"),
|
|
38
39
|
getUpdateId: vi.fn(() => "release-id"),
|
|
39
40
|
getChannel: vi.fn(() => "production"),
|
|
41
|
+
getActiveUpdateState: vi.fn<() => ActiveUpdateState>(),
|
|
40
42
|
getCohort: vi.fn(() => "123"),
|
|
41
43
|
getFingerprintHash: vi.fn(() => "fingerprint-hash"),
|
|
42
44
|
getInstallId: vi.fn(() => "install-id"),
|
|
@@ -61,6 +63,7 @@ vi.mock("./native", () => ({
|
|
|
61
63
|
getBundleId: mocks.getBundleId,
|
|
62
64
|
getUpdateId: mocks.getUpdateId,
|
|
63
65
|
getChannel: mocks.getChannel,
|
|
66
|
+
getActiveUpdateState: mocks.getActiveUpdateState,
|
|
64
67
|
getCohort: mocks.getCohort,
|
|
65
68
|
getFingerprintHash: mocks.getFingerprintHash,
|
|
66
69
|
getInstallId: mocks.getInstallId,
|
|
@@ -99,6 +102,11 @@ describe("HotUpdater wrap initialization", () => {
|
|
|
99
102
|
mocks.getBundleId.mockReturnValue("bundle-id");
|
|
100
103
|
mocks.getUpdateId.mockReturnValue("release-id");
|
|
101
104
|
mocks.getChannel.mockReturnValue("production");
|
|
105
|
+
mocks.getActiveUpdateState.mockReturnValue({
|
|
106
|
+
activeSelection: null,
|
|
107
|
+
stableSelection: null,
|
|
108
|
+
verificationPending: false,
|
|
109
|
+
});
|
|
102
110
|
mocks.getCohort.mockReturnValue("123");
|
|
103
111
|
mocks.getFingerprintHash.mockReturnValue("fingerprint-hash");
|
|
104
112
|
mocks.getInstallId.mockReturnValue("install-id");
|
package/src/wrap.tsx
CHANGED
|
@@ -136,11 +136,9 @@ export function wrap(
|
|
|
136
136
|
<Fallback
|
|
137
137
|
artifactType={progressState.artifactType}
|
|
138
138
|
details={progressState.details}
|
|
139
|
-
downloadedBytes={progressState.downloadedBytes}
|
|
140
139
|
progress={progress}
|
|
141
140
|
status={updateStatus}
|
|
142
141
|
message={message}
|
|
143
|
-
totalBytes={progressState.totalBytes}
|
|
144
142
|
/>
|
|
145
143
|
);
|
|
146
144
|
}
|
package/src/wrap.types.ts
CHANGED
|
@@ -21,8 +21,6 @@ export type UpdateStatus =
|
|
|
21
21
|
export type HotUpdaterFallbackComponentProps = {
|
|
22
22
|
status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
|
|
23
23
|
progress: number;
|
|
24
|
-
downloadedBytes: HotUpdaterState["downloadedBytes"];
|
|
25
|
-
totalBytes: HotUpdaterState["totalBytes"];
|
|
26
24
|
message: string | null;
|
|
27
25
|
artifactType: HotUpdaterState["artifactType"];
|
|
28
26
|
details: HotUpdaterState["details"];
|