@hot-updater/react-native 0.30.11 → 0.31.0
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/HotUpdater.podspec +1 -0
- package/android/build.gradle +1 -0
- package/android/src/main/java/com/hotupdater/BsdiffPatch.kt +284 -0
- package/android/src/main/java/com/hotupdater/BundleFileStorageService.kt +885 -5
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +13 -2
- package/android/src/main/java/com/hotupdater/OkHttpDownloadService.kt +37 -8
- package/android/src/main/java/com/hotupdater/ReactNativeValueConverters.kt +48 -12
- package/android/src/main/java/com/hotupdater/SignatureVerifier.kt +60 -22
- package/android/src/newarch/HotUpdater.kt +14 -2
- package/android/src/newarch/HotUpdaterModule.kt +112 -1
- package/android/src/oldarch/HotUpdater.kt +14 -2
- package/android/src/oldarch/HotUpdaterModule.kt +107 -3
- package/android/src/test/java/com/hotupdater/BsdiffPatchTest.kt +46 -0
- package/android/src/test/java/com/hotupdater/BundleFileStorageServiceTest.kt +29 -1
- package/android/src/test/java/com/hotupdater/HotUpdaterImplTest.kt +4 -1
- package/ios/HotUpdater/Internal/BsdiffPatchBridge.h +16 -0
- package/ios/HotUpdater/Internal/BsdiffPatchBridge.mm +343 -0
- package/ios/HotUpdater/Internal/BundleFileStorageService.swift +1093 -47
- package/ios/HotUpdater/Internal/HotUpdater-Bridging-Header.h +2 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +12 -2
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +64 -5
- package/ios/HotUpdater/Internal/NotificationExtension.swift +2 -1
- package/ios/HotUpdater/Internal/SignatureVerifier.swift +28 -5
- package/ios/HotUpdater/Internal/StreamingTarArchiveExtractor.swift +11 -0
- package/ios/HotUpdater/Internal/URLSessionDownloadService.swift +11 -5
- package/lib/commonjs/DefaultResolver.js +18 -4
- package/lib/commonjs/DefaultResolver.js.map +1 -1
- package/lib/commonjs/DefaultResolver.spec.js +136 -0
- package/lib/commonjs/DefaultResolver.spec.js.map +1 -0
- package/lib/commonjs/checkForUpdate.js +6 -0
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/index.js +53 -18
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/index.spec.js +133 -1
- package/lib/commonjs/index.spec.js.map +1 -1
- package/lib/commonjs/native.js +40 -16
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/native.spec.js +119 -3
- package/lib/commonjs/native.spec.js.map +1 -1
- package/lib/commonjs/sdkVersion.js +8 -0
- package/lib/commonjs/sdkVersion.js.map +1 -0
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/commonjs/store.js +72 -5
- package/lib/commonjs/store.js.map +1 -1
- package/lib/commonjs/store.spec.js +265 -8
- package/lib/commonjs/store.spec.js.map +1 -1
- package/lib/commonjs/types.js.map +1 -1
- package/lib/commonjs/wrap.js +19 -5
- package/lib/commonjs/wrap.js.map +1 -1
- package/lib/commonjs/wrap.spec.js +74 -0
- package/lib/commonjs/wrap.spec.js.map +1 -1
- package/lib/module/DefaultResolver.js +18 -4
- package/lib/module/DefaultResolver.js.map +1 -1
- package/lib/module/DefaultResolver.spec.js +135 -0
- package/lib/module/DefaultResolver.spec.js.map +1 -0
- package/lib/module/checkForUpdate.js +6 -0
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/index.js +53 -18
- package/lib/module/index.js.map +1 -1
- package/lib/module/index.spec.js +133 -1
- package/lib/module/index.spec.js.map +1 -1
- package/lib/module/native.js +40 -16
- package/lib/module/native.js.map +1 -1
- package/lib/module/native.spec.js +119 -3
- package/lib/module/native.spec.js.map +1 -1
- package/lib/module/sdkVersion.js +4 -0
- package/lib/module/sdkVersion.js.map +1 -0
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/store.js +72 -5
- package/lib/module/store.js.map +1 -1
- package/lib/module/store.spec.js +265 -8
- package/lib/module/store.spec.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/wrap.js +19 -5
- package/lib/module/wrap.js.map +1 -1
- package/lib/module/wrap.spec.js +74 -0
- package/lib/module/wrap.spec.js.map +1 -1
- package/lib/typescript/commonjs/DefaultResolver.d.ts +4 -3
- package/lib/typescript/commonjs/DefaultResolver.d.ts.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +2 -2
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +37 -9
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +56 -3
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/sdkVersion.d.ts +2 -0
- package/lib/typescript/commonjs/sdkVersion.d.ts.map +1 -0
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +27 -0
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/commonjs/store.d.ts +5 -0
- package/lib/typescript/commonjs/store.d.ts.map +1 -1
- package/lib/typescript/commonjs/types.d.ts +1 -0
- package/lib/typescript/commonjs/types.d.ts.map +1 -1
- package/lib/typescript/commonjs/wrap.d.ts +48 -32
- package/lib/typescript/commonjs/wrap.d.ts.map +1 -1
- package/lib/typescript/module/DefaultResolver.d.ts +4 -3
- package/lib/typescript/module/DefaultResolver.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +2 -2
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +37 -9
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +56 -3
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/sdkVersion.d.ts +2 -0
- package/lib/typescript/module/sdkVersion.d.ts.map +1 -0
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +27 -0
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/store.d.ts +5 -0
- package/lib/typescript/module/store.d.ts.map +1 -1
- package/lib/typescript/module/types.d.ts +1 -0
- package/lib/typescript/module/types.d.ts.map +1 -1
- package/lib/typescript/module/wrap.d.ts +48 -32
- package/lib/typescript/module/wrap.d.ts.map +1 -1
- package/package.json +17 -9
- package/src/DefaultResolver.spec.ts +178 -0
- package/src/DefaultResolver.ts +32 -6
- package/src/checkForUpdate.ts +9 -2
- package/src/index.spec.ts +170 -2
- package/src/index.ts +100 -40
- package/src/native.spec.ts +139 -1
- package/src/native.ts +145 -31
- package/src/sdkVersion.ts +1 -0
- package/src/specs/NativeHotUpdater.ts +28 -0
- package/src/store.spec.ts +324 -9
- package/src/store.ts +133 -7
- package/src/types.ts +2 -0
- package/src/wrap.spec.ts +91 -0
- package/src/wrap.tsx +84 -45
|
@@ -4,6 +4,7 @@ import { type UpdateBundleParams } from "./specs/NativeHotUpdater";
|
|
|
4
4
|
export { HotUpdaterErrorCode, isHotUpdaterError };
|
|
5
5
|
export interface ManifestAsset {
|
|
6
6
|
fileHash: string;
|
|
7
|
+
signature?: string;
|
|
7
8
|
}
|
|
8
9
|
export interface Manifest {
|
|
9
10
|
bundleId: string;
|
|
@@ -31,10 +32,62 @@ export type CustomReloadHandler = () => void | Promise<void>;
|
|
|
31
32
|
* - `custom`: Run a user-provided JS handler on both platforms
|
|
32
33
|
*/
|
|
33
34
|
export type ReloadBehaviorSetting = ReloadBehavior | "custom";
|
|
35
|
+
export type HotUpdaterProgressArtifactType = "archive" | "diff";
|
|
36
|
+
export type HotUpdaterDiffFileStatus = "pending" | "downloading" | "downloaded" | "failed";
|
|
37
|
+
export interface HotUpdaterDiffFileSnapshot {
|
|
38
|
+
/**
|
|
39
|
+
* Manifest asset path for this progress entry.
|
|
40
|
+
*
|
|
41
|
+
* This is the stable identity of the asset in the installed bundle. Use this
|
|
42
|
+
* when matching progress back to the manifest or to the final file location.
|
|
43
|
+
*/
|
|
44
|
+
path: string;
|
|
45
|
+
/**
|
|
46
|
+
* Artifact path currently being transferred for this progress entry.
|
|
47
|
+
*
|
|
48
|
+
* Usually this is the same as `path`. It can differ when the updater
|
|
49
|
+
* downloads an intermediate artifact that will be applied to produce the
|
|
50
|
+
* final asset.
|
|
51
|
+
*/
|
|
52
|
+
downloadPath: string;
|
|
53
|
+
/**
|
|
54
|
+
* Current download state for this asset within the manifest diff update.
|
|
55
|
+
*/
|
|
56
|
+
status: HotUpdaterDiffFileStatus;
|
|
57
|
+
/**
|
|
58
|
+
* Download progress for this file, normalized from 0 to 1.
|
|
59
|
+
*/
|
|
60
|
+
progress: number;
|
|
61
|
+
/**
|
|
62
|
+
* Stable display order among diff files.
|
|
63
|
+
*/
|
|
64
|
+
order: number;
|
|
65
|
+
/**
|
|
66
|
+
* Bytes downloaded for `downloadPath`, when the native downloader reports it.
|
|
67
|
+
*/
|
|
68
|
+
downloadedBytes?: number;
|
|
69
|
+
/**
|
|
70
|
+
* Total expected bytes for `downloadPath`, when known.
|
|
71
|
+
*/
|
|
72
|
+
totalBytes?: number;
|
|
73
|
+
}
|
|
74
|
+
export interface HotUpdaterDiffProgressDetails {
|
|
75
|
+
totalFilesCount: number;
|
|
76
|
+
completedFilesCount: number;
|
|
77
|
+
files: HotUpdaterDiffFileSnapshot[];
|
|
78
|
+
}
|
|
79
|
+
export type HotUpdaterProgressEvent = {
|
|
80
|
+
progress: number;
|
|
81
|
+
artifactType: "archive";
|
|
82
|
+
downloadedBytes?: number;
|
|
83
|
+
totalBytes?: number;
|
|
84
|
+
} | {
|
|
85
|
+
progress: number;
|
|
86
|
+
artifactType: "diff";
|
|
87
|
+
details: HotUpdaterDiffProgressDetails;
|
|
88
|
+
};
|
|
34
89
|
export type HotUpdaterEvent = {
|
|
35
|
-
onProgress:
|
|
36
|
-
progress: number;
|
|
37
|
-
};
|
|
90
|
+
onProgress: HotUpdaterProgressEvent;
|
|
38
91
|
};
|
|
39
92
|
export declare const addListener: <T extends keyof HotUpdaterEvent>(eventName: T, listener: (event: HotUpdaterEvent[T]) => void) => () => void;
|
|
40
93
|
export type UpdateParams = UpdateBundleParams & {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/native.ts"],"names":[],"mappings":"AAAA,OAAO,
|
|
1
|
+
{"version":3,"file":"native.d.ts","sourceRoot":"","sources":["../../../src/native.ts"],"names":[],"mappings":"AAAA,OAAO,EAKL,KAAK,YAAY,EAClB,MAAM,mBAAmB,CAAC;AAG3B,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,SAAS,CAAC;AACjE,OAAyB,EACvB,KAAK,kBAAkB,EACxB,MAAM,0BAA0B,CAAC;AAElC,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,CAAC;AAWlD,MAAM,WAAW,aAAa;IAC5B,QAAQ,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB;AAED,MAAM,WAAW,QAAQ;IACvB,QAAQ,EAAE,MAAM,CAAC;IACjB,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,aAAa,CAAC,CAAC;CACvC;AAUD;;;;;GAKG;AACH,MAAM,MAAM,cAAc,GAAG,QAAQ,GAAG,gBAAgB,CAAC;AAEzD;;;;;GAKG;AACH,MAAM,MAAM,mBAAmB,GAAG,MAAM,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE7D;;;;;;GAMG;AACH,MAAM,MAAM,qBAAqB,GAAG,cAAc,GAAG,QAAQ,CAAC;AAsK9D,MAAM,MAAM,8BAA8B,GAAG,SAAS,GAAG,MAAM,CAAC;AAEhE,MAAM,MAAM,wBAAwB,GAChC,SAAS,GACT,aAAa,GACb,YAAY,GACZ,QAAQ,CAAC;AAEb,MAAM,WAAW,0BAA0B;IACzC;;;;;OAKG;IACH,IAAI,EAAE,MAAM,CAAC;IACb;;;;;;OAMG;IACH,YAAY,EAAE,MAAM,CAAC;IACrB;;OAEG;IACH,MAAM,EAAE,wBAAwB,CAAC;IACjC;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,KAAK,EAAE,MAAM,CAAC;IACd;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB;;OAEG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB;AAED,MAAM,WAAW,6BAA6B;IAC5C,eAAe,EAAE,MAAM,CAAC;IACxB,mBAAmB,EAAE,MAAM,CAAC;IAC5B,KAAK,EAAE,0BAA0B,EAAE,CAAC;CACrC;AAED,MAAM,MAAM,uBAAuB,GAC/B;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,SAAS,CAAC;IACxB,eAAe,CAAC,EAAE,MAAM,CAAC;IACzB,UAAU,CAAC,EAAE,MAAM,CAAC;CACrB,GACD;IACE,QAAQ,EAAE,MAAM,CAAC;IACjB,YAAY,EAAE,MAAM,CAAC;IACrB,OAAO,EAAE,6BAA6B,CAAC;CACxC,CAAC;AAEN,MAAM,MAAM,eAAe,GAAG;IAC5B,UAAU,EAAE,uBAAuB,CAAC;CACrC,CAAC;AAIF,eAAO,MAAM,WAAW,GAAI,CAAC,SAAS,MAAM,eAAe,EACzD,WAAW,CAAC,EACZ,UAAU,CAAC,KAAK,EAAE,eAAe,CAAC,CAAC,CAAC,KAAK,IAAI,eAO9C,CAAC;AAEF,MAAM,MAAM,YAAY,GAAG,kBAAkB,GAAG;IAC9C,MAAM,EAAE,YAAY,CAAC;IACrB,8BAA8B,CAAC,EAAE,OAAO,CAAC;CAC1C,CAAC;AAEF;;;;;;GAMG;AACH,wBAAsB,YAAY,CAAC,MAAM,EAAE,YAAY,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;AAC3E;;GAEG;AACH,wBAAsB,YAAY,CAChC,QAAQ,EAAE,MAAM,EAChB,OAAO,EAAE,MAAM,GAAG,IAAI,GACrB,OAAO,CAAC,OAAO,CAAC,CAAC;AAgGpB;;GAEG;AACH,eAAO,MAAM,aAAa,QAAO,MAAM,GAAG,IAGzC,CAAC;AAEF;;;;;;;;;;;;;GAaG;AACH,eAAO,MAAM,MAAM,qBAqBlB,CAAC;AAEF;;;;;;;;;;;;GAYG;AACH,wBAAgB,iBAAiB,CAC/B,GAAG,IAAI,EACH,CAAC,QAAQ,EAAE,cAAc,CAAC,GAC1B,CAAC,QAAQ,EAAE,QAAQ,EAAE,OAAO,EAAE,mBAAmB,CAAC,GACrD,IAAI,CAuBN;AAED;;;;;GAKG;AACH,eAAO,MAAM,cAAc,QAAO,MAGjC,CAAC;AAEF;;;;;;;;;GASG;AACH,eAAO,MAAM,WAAW,QAAO,MAO9B,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,WAAW,QAAO,QA4B9B,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,UAAU,QAAO,MAE7B,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAO,MAEpC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,kBAAkB,QAAO,MAAM,GAAG,IAG9C,CAAC;AAEF;;GAEG;AACH,MAAM,MAAM,oBAAoB,GAAG;IACjC,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;CAC1B,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,eAAO,MAAM,cAAc,QAAO,oBAWjC,CAAC;AAuFF;;;;;GAKG;AACH,eAAO,MAAM,eAAe,QAAO,MAAM,EAWxC,CAAC;AAEF;;;;;GAKG;AACH,eAAO,MAAM,iBAAiB,QAAO,OAEpC,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,UAAU,QAAO,MAAM,GAAG,IAUtC,CAAC;AAEF;;GAEG;AACH,eAAO,MAAM,YAAY,QAAa,OAAO,CAAC,OAAO,CAMpD,CAAC;AAEF;;;;;;GAMG;AACH,eAAO,MAAM,SAAS,GAAI,QAAQ,MAAM,KAAG,IAI1C,CAAC;AAEF;;;;GAIG;AACH,eAAO,MAAM,SAAS,QAAO,MAS5B,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"sdkVersion.d.ts","sourceRoot":"","sources":["../../../src/sdkVersion.ts"],"names":[],"mappings":"AAAA,eAAO,MAAM,uBAAuB,YAAY,CAAC"}
|
|
@@ -1,5 +1,19 @@
|
|
|
1
1
|
import type { TurboModule } from "react-native";
|
|
2
2
|
import type { UnsafeObject } from "react-native/Libraries/Types/CodegenTypes";
|
|
3
|
+
export interface ChangedAsset {
|
|
4
|
+
file?: {
|
|
5
|
+
compression?: "br" | null;
|
|
6
|
+
url: string;
|
|
7
|
+
} | null;
|
|
8
|
+
fileHash: string;
|
|
9
|
+
patch?: {
|
|
10
|
+
algorithm: "bsdiff";
|
|
11
|
+
baseBundleId: string;
|
|
12
|
+
baseFileHash: string;
|
|
13
|
+
patchFileHash: string;
|
|
14
|
+
patchUrl: string;
|
|
15
|
+
} | null;
|
|
16
|
+
}
|
|
3
17
|
export interface UpdateBundleParams {
|
|
4
18
|
bundleId: string;
|
|
5
19
|
channel?: string;
|
|
@@ -14,6 +28,19 @@ export interface UpdateBundleParams {
|
|
|
14
28
|
* Native determines verification mode by checking for "sig:" prefix.
|
|
15
29
|
*/
|
|
16
30
|
fileHash: string | null;
|
|
31
|
+
/**
|
|
32
|
+
* Optional signed manifest URL for manifest-driven installation.
|
|
33
|
+
*/
|
|
34
|
+
manifestUrl?: string | null;
|
|
35
|
+
/**
|
|
36
|
+
* File hash/signature for the manifest file itself.
|
|
37
|
+
*/
|
|
38
|
+
manifestFileHash?: string | null;
|
|
39
|
+
/**
|
|
40
|
+
* Per-file URLs for assets that must be downloaded instead of reused from
|
|
41
|
+
* the currently active bundle.
|
|
42
|
+
*/
|
|
43
|
+
changedAssets?: UnsafeObject | null;
|
|
17
44
|
}
|
|
18
45
|
export interface Spec extends TurboModule {
|
|
19
46
|
reload(): Promise<void>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativeHotUpdater.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeHotUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"NativeHotUpdater.d.ts","sourceRoot":"","sources":["../../../../src/specs/NativeHotUpdater.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAEhD,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,2CAA2C,CAAC;AAE9E,MAAM,WAAW,YAAY;IAC3B,IAAI,CAAC,EAAE;QACL,WAAW,CAAC,EAAE,IAAI,GAAG,IAAI,CAAC;QAC1B,GAAG,EAAE,MAAM,CAAC;KACb,GAAG,IAAI,CAAC;IACT,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE;QACN,SAAS,EAAE,QAAQ,CAAC;QACpB,YAAY,EAAE,MAAM,CAAC;QACrB,YAAY,EAAE,MAAM,CAAC;QACrB,aAAa,EAAE,MAAM,CAAC;QACtB,QAAQ,EAAE,MAAM,CAAC;KAClB,GAAG,IAAI,CAAC;CACV;AAED,MAAM,WAAW,kBAAkB;IACjC,QAAQ,EAAE,MAAM,CAAC;IACjB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB;;;;;;;;OAQG;IACH,QAAQ,EAAE,MAAM,GAAG,IAAI,CAAC;IACxB;;OAEG;IACH,WAAW,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAC5B;;OAEG;IACH,gBAAgB,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IACjC;;;OAGG;IACH,aAAa,CAAC,EAAE,YAAY,GAAG,IAAI,CAAC;CACrC;AAED,MAAM,WAAW,IAAK,SAAQ,WAAW;IAEvC,MAAM,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IACxB;;;;OAIG;IACH,aAAa,IAAI,OAAO,CAAC,IAAI,CAAC,CAAC;IAC/B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA8BG;IACH,YAAY,CAAC,MAAM,EAAE,kBAAkB,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC;IAE3D;;;;;;;;OAQG;IACH,cAAc,IAAI;QAChB,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;QAC/B,eAAe,CAAC,EAAE,MAAM,CAAC;KAC1B,CAAC;IAEF;;;;;OAKG;IACH,eAAe,IAAI,MAAM,EAAE,CAAC;IAE5B;;;;;OAKG;IACH,iBAAiB,IAAI,OAAO,CAAC;IAE7B;;;;OAIG;IACH,YAAY,IAAI,OAAO,CAAC,OAAO,CAAC,CAAC;IAEjC;;;;;;OAMG;IACH,UAAU,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAEhC;;;;;;OAMG;IACH,WAAW,EAAE,MAAM,MAAM,GAAG,IAAI,CAAC;IAEjC;;;OAGG;IACH,WAAW,EAAE,MAAM,YAAY,CAAC;IAEhC;;;;;;OAMG;IACH,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,IAAI,CAAC;IAEpC;;;;OAIG;IACH,SAAS,EAAE,MAAM,MAAM,CAAC;IAGxB,WAAW,CAAC,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,eAAe,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrC,QAAQ,CAAC,YAAY,EAAE,MAAM;QAC3B,aAAa,EAAE,MAAM,CAAC;QACtB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;QAC3B,OAAO,EAAE,MAAM,CAAC;QAChB,eAAe,EAAE,MAAM,CAAC;QACxB,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;KACjC,CAAC;CACH;;AAED,wBAAoE"}
|
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import type { HotUpdaterDiffProgressDetails } from "./native";
|
|
1
2
|
export type HotUpdaterState = {
|
|
2
3
|
progress: number;
|
|
4
|
+
downloadedBytes: number | undefined;
|
|
5
|
+
totalBytes: number | undefined;
|
|
3
6
|
isUpdateDownloaded: boolean;
|
|
7
|
+
artifactType: "archive" | "diff" | null;
|
|
8
|
+
details: HotUpdaterDiffProgressDetails | null;
|
|
4
9
|
};
|
|
5
10
|
export declare const hotUpdaterStore: {
|
|
6
11
|
getSnapshot: () => HotUpdaterState;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"store.d.ts","sourceRoot":"","sources":["../../../src/store.ts"],"names":[],"mappings":"
|
|
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,eAAe,EAAE,MAAM,GAAG,SAAS,CAAC;IACpC,UAAU,EAAE,MAAM,GAAG,SAAS,CAAC;IAC/B,kBAAkB,EAAE,OAAO,CAAC;IAC5B,YAAY,EAAE,SAAS,GAAG,MAAM,GAAG,IAAI,CAAC;IACxC,OAAO,EAAE,6BAA6B,GAAG,IAAI,CAAC;CAC/C,CAAC;AAqLF,eAAO,MAAM,eAAe;;yBAnEE,OAAO,CAAC,eAAe,CAAC;0BAuDvB,MAAM,IAAI;CAYa,CAAC;AAEvD,eAAO,MAAM,kBAAkB,GAAI,CAAC,GAAG,eAAe,EACpD,WAAU,CAAC,QAAQ,EAAE,eAAe,KAAK,CAA+B,MAQzE,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,cAAc,EAAE,aAAa,GAAG,YAAY,CAAC;IAE7C;;OAEG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAE/B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAAW,CAAC,EAAE,CACZ,MAAM,EAAE,yBAAyB,KAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEnC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CACf,MAAM,EAAE,4BAA4B,KACjC,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;CAChD;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAgBpE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,4BAA4B,CAS9B"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,UAAU,CAAC;AAErD,MAAM,MAAM,iBAAiB,GAAG,MAAM,GAAG,CAAC,MAAM,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC;AAE1E;;GAEG;AACH,MAAM,WAAW,yBAAyB;IACxC;;OAEG;IACH,QAAQ,EAAE,KAAK,GAAG,SAAS,CAAC;IAE5B;;OAEG;IACH,UAAU,EAAE,MAAM,CAAC;IAEnB;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IAEjB;;OAEG;IACH,WAAW,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAEhB;;OAEG;IACH,MAAM,EAAE,MAAM,CAAC;IAEf;;OAEG;IACH,cAAc,EAAE,aAAa,GAAG,YAAY,CAAC;IAE7C;;OAEG;IACH,eAAe,EAAE,MAAM,GAAG,IAAI,CAAC;IAE/B;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;;;OAIG;IACH,MAAM,EAAE,WAAW,GAAG,QAAQ,CAAC;IAE/B;;OAEG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IAExC;;OAEG;IACH,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB;AAED;;GAEG;AACH,MAAM,WAAW,kBAAkB;IACjC;;;;;;;;;;;;;;;;;;;;OAoBG;IACH,WAAW,CAAC,EAAE,CACZ,MAAM,EAAE,yBAAyB,KAC9B,OAAO,CAAC,aAAa,GAAG,IAAI,CAAC,CAAC;IAEnC;;;;;;;;;;;;;;;;;;;OAmBG;IACH,cAAc,CAAC,EAAE,CACf,MAAM,EAAE,4BAA4B,KACjC,OAAO,CAAC,oBAAoB,GAAG,SAAS,CAAC,CAAC;CAChD;AAED;;;;GAIG;AACH,MAAM,WAAW,4BAA4B;IAC3C;;OAEG;IACH,QAAQ,EAAE,MAAM,CAAC;IACjB;;OAEG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;OAEG;IACH,KAAK,EAAE,KAAK,CAAC;CACd;AAED;;;;;;;;GAQG;AACH,wBAAgB,4BAA4B,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,CAgBpE;AAED;;GAEG;AACH,wBAAgB,uBAAuB,CACrC,KAAK,EAAE,OAAO,EACd,QAAQ,EAAE,MAAM,GACf,4BAA4B,CAS9B"}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import type { HotUpdaterError } from "./error";
|
|
3
3
|
import { type NotifyAppReadyResult } from "./native";
|
|
4
|
-
import type
|
|
4
|
+
import { type HotUpdaterState } from "./store";
|
|
5
|
+
import type { HotUpdaterBaseURL, HotUpdaterResolver } from "./types";
|
|
5
6
|
export interface RunUpdateProcessResponse {
|
|
6
7
|
status: "ROLLBACK" | "UPDATE" | "UP_TO_DATE";
|
|
7
8
|
shouldForceUpdate: boolean;
|
|
@@ -9,8 +10,17 @@ export interface RunUpdateProcessResponse {
|
|
|
9
10
|
id: string;
|
|
10
11
|
}
|
|
11
12
|
type UpdateStatus = "CHECK_FOR_UPDATE" | "UPDATING" | "UPDATE_PROCESS_COMPLETED";
|
|
13
|
+
export type HotUpdaterFallbackComponentProps = {
|
|
14
|
+
status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
|
|
15
|
+
progress: number;
|
|
16
|
+
downloadedBytes: HotUpdaterState["downloadedBytes"];
|
|
17
|
+
totalBytes: HotUpdaterState["totalBytes"];
|
|
18
|
+
message: string | null;
|
|
19
|
+
artifactType: HotUpdaterState["artifactType"];
|
|
20
|
+
details: HotUpdaterState["details"];
|
|
21
|
+
};
|
|
12
22
|
/**
|
|
13
|
-
* Common options shared
|
|
23
|
+
* Common options shared by HotUpdater initialization APIs.
|
|
14
24
|
*/
|
|
15
25
|
interface CommonHotUpdaterOptions {
|
|
16
26
|
/**
|
|
@@ -34,28 +44,35 @@ interface CommonHotUpdaterOptions {
|
|
|
34
44
|
*
|
|
35
45
|
* @example
|
|
36
46
|
* ```tsx
|
|
37
|
-
* HotUpdater.
|
|
47
|
+
* HotUpdater.init({
|
|
38
48
|
* baseURL: "https://api.example.com",
|
|
39
|
-
* updateMode: "manual",
|
|
40
49
|
* onNotifyAppReady: ({ status, crashedBundleId }) => {
|
|
41
50
|
* if (status === "RECOVERED") {
|
|
42
51
|
* analytics.track("bundle_rollback", { crashedBundleId });
|
|
43
52
|
* }
|
|
44
|
-
* }
|
|
45
|
-
* })
|
|
53
|
+
* },
|
|
54
|
+
* });
|
|
46
55
|
* ```
|
|
47
56
|
*/
|
|
48
57
|
onNotifyAppReady?: (result: NotifyAppReadyResult) => void;
|
|
58
|
+
/**
|
|
59
|
+
* Default callback invoked when Hot Updater initialization or update checks
|
|
60
|
+
* fail. Per-call `HotUpdater.checkForUpdate({ onError })` handlers override
|
|
61
|
+
* this callback for that check.
|
|
62
|
+
*/
|
|
63
|
+
onError?: (error: HotUpdaterError | Error | unknown) => void;
|
|
49
64
|
}
|
|
50
65
|
/**
|
|
51
66
|
* Configuration with baseURL for standard server-based updates
|
|
52
67
|
*/
|
|
53
68
|
interface BaseURLConfig {
|
|
54
69
|
/**
|
|
55
|
-
* Base URL for update server
|
|
70
|
+
* Base URL for update server. Use a function to resolve it dynamically
|
|
71
|
+
* before each update check.
|
|
56
72
|
* @example "https://update.example.com"
|
|
73
|
+
* @example () => getUpdateServerURL()
|
|
57
74
|
*/
|
|
58
|
-
baseURL:
|
|
75
|
+
baseURL: HotUpdaterBaseURL;
|
|
59
76
|
/**
|
|
60
77
|
* Resolver is not allowed when using baseURL
|
|
61
78
|
*/
|
|
@@ -79,18 +96,16 @@ interface ResolverConfig {
|
|
|
79
96
|
*/
|
|
80
97
|
type NetworkConfig = BaseURLConfig | ResolverConfig;
|
|
81
98
|
export type AutoUpdateOptions = CommonHotUpdaterOptions & NetworkConfig & {
|
|
99
|
+
/**
|
|
100
|
+
* Automatic update mode. This is the default and can be omitted.
|
|
101
|
+
*/
|
|
102
|
+
updateMode?: "auto";
|
|
82
103
|
/**
|
|
83
104
|
* Update strategy
|
|
84
105
|
* - "fingerprint": Use fingerprint hash to check for updates
|
|
85
106
|
* - "appVersion": Use app version to check for updates
|
|
86
107
|
*/
|
|
87
108
|
updateStrategy: "fingerprint" | "appVersion";
|
|
88
|
-
/**
|
|
89
|
-
* Update mode
|
|
90
|
-
* - "auto": Automatically check and download updates
|
|
91
|
-
*/
|
|
92
|
-
updateMode: "auto";
|
|
93
|
-
onError?: (error: HotUpdaterError | Error | unknown) => void;
|
|
94
109
|
/**
|
|
95
110
|
* Component to show while downloading a new bundle update.
|
|
96
111
|
*
|
|
@@ -113,11 +128,7 @@ export type AutoUpdateOptions = CommonHotUpdaterOptions & NetworkConfig & {
|
|
|
113
128
|
*
|
|
114
129
|
* If not defined, the bundle will download in the background without blocking the screen.
|
|
115
130
|
*/
|
|
116
|
-
fallbackComponent?: React.FC<
|
|
117
|
-
status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
|
|
118
|
-
progress: number;
|
|
119
|
-
message: string | null;
|
|
120
|
-
}>;
|
|
131
|
+
fallbackComponent?: React.FC<HotUpdaterFallbackComponentProps>;
|
|
121
132
|
onProgress?: (progress: number) => void;
|
|
122
133
|
/**
|
|
123
134
|
* When a force update exists, the app will automatically reload.
|
|
@@ -135,15 +146,24 @@ export type AutoUpdateOptions = CommonHotUpdaterOptions & NetworkConfig & {
|
|
|
135
146
|
};
|
|
136
147
|
export type ManualUpdateOptions = CommonHotUpdaterOptions & NetworkConfig & {
|
|
137
148
|
/**
|
|
138
|
-
*
|
|
139
|
-
*
|
|
149
|
+
* @deprecated Replace manual `HotUpdater.wrap` with `HotUpdater.init`.
|
|
150
|
+
*
|
|
151
|
+
* ```tsx
|
|
152
|
+
* import { HotUpdater } from "@hot-updater/react-native";
|
|
153
|
+
*
|
|
154
|
+
* HotUpdater.init({
|
|
155
|
+
* baseURL: "<your-update-server-url>",
|
|
156
|
+
* });
|
|
157
|
+
*
|
|
158
|
+
* export default App;
|
|
159
|
+
* ```
|
|
160
|
+
*
|
|
161
|
+
* Then call `HotUpdater.checkForUpdate(...)` from your manual update flow.
|
|
162
|
+
* See https://hot-updater.dev/docs/guides/custom-update
|
|
140
163
|
*/
|
|
141
164
|
updateMode: "manual";
|
|
142
165
|
};
|
|
143
|
-
type
|
|
144
|
-
updateMode: "manual";
|
|
145
|
-
};
|
|
146
|
-
export type HotUpdaterInitOptions = Omit<ManualBaseURLUpdateOptions, "updateMode">;
|
|
166
|
+
export type HotUpdaterInitOptions = CommonHotUpdaterOptions & NetworkConfig;
|
|
147
167
|
export type HotUpdaterOptions = AutoUpdateOptions | ManualUpdateOptions;
|
|
148
168
|
/**
|
|
149
169
|
* Internal options after normalization in index.ts
|
|
@@ -154,16 +174,12 @@ type InternalCommonOptions = {
|
|
|
154
174
|
requestHeaders?: Record<string, string>;
|
|
155
175
|
requestTimeout?: number;
|
|
156
176
|
onNotifyAppReady?: (result: NotifyAppReadyResult) => void;
|
|
177
|
+
onError?: (error: HotUpdaterError | Error | unknown) => void;
|
|
157
178
|
};
|
|
158
179
|
type InternalAutoUpdateOptions = InternalCommonOptions & {
|
|
159
180
|
updateStrategy: "fingerprint" | "appVersion";
|
|
160
181
|
updateMode: "auto";
|
|
161
|
-
|
|
162
|
-
fallbackComponent?: React.FC<{
|
|
163
|
-
status: Exclude<UpdateStatus, "UPDATE_PROCESS_COMPLETED">;
|
|
164
|
-
progress: number;
|
|
165
|
-
message: string | null;
|
|
166
|
-
}>;
|
|
182
|
+
fallbackComponent?: React.FC<HotUpdaterFallbackComponentProps>;
|
|
167
183
|
onProgress?: (progress: number) => void;
|
|
168
184
|
reloadOnForceUpdate?: boolean;
|
|
169
185
|
onUpdateProcessCompleted?: (response: RunUpdateProcessResponse) => void;
|
|
@@ -174,6 +190,6 @@ type InternalManualUpdateOptions = InternalCommonOptions & {
|
|
|
174
190
|
export type InternalInitOptions = InternalCommonOptions;
|
|
175
191
|
export type InternalWrapOptions = InternalAutoUpdateOptions | InternalManualUpdateOptions;
|
|
176
192
|
export declare function init(options: InternalInitOptions): void;
|
|
177
|
-
export declare function wrap
|
|
193
|
+
export declare function wrap(options: InternalWrapOptions): <P extends object>(WrappedComponent: React.ComponentType<P>) => React.ComponentType<P>;
|
|
178
194
|
export {};
|
|
179
195
|
//# sourceMappingURL=wrap.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../../src/wrap.tsx"],"names":[],"mappings":"AAAA,OAAO,KAA8B,MAAM,OAAO,CAAC;AAGnD,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,SAAS,CAAC;AAE/C,OAAO,EAEL,KAAK,oBAAoB,EAG1B,MAAM,UAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"wrap.d.ts","sourceRoot":"","sources":["../../../src/wrap.tsx"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@hot-updater/react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.31.0",
|
|
4
4
|
"description": "React Native OTA solution for self-hosted",
|
|
5
|
-
"
|
|
5
|
+
"source": "./src/index.ts",
|
|
6
|
+
"main": "./lib/commonjs/index.js",
|
|
7
|
+
"module": "./lib/module/index.js",
|
|
6
8
|
"types": "./lib/typescript/commonjs/index.d.ts",
|
|
7
9
|
"exports": {
|
|
8
10
|
".": {
|
|
9
11
|
"source": "./src/index.ts",
|
|
10
|
-
"
|
|
11
|
-
|
|
12
|
+
"import": {
|
|
13
|
+
"types": "./lib/typescript/module/index.d.ts",
|
|
14
|
+
"default": "./lib/module/index.js"
|
|
15
|
+
},
|
|
16
|
+
"require": {
|
|
17
|
+
"types": "./lib/typescript/commonjs/index.d.ts",
|
|
18
|
+
"default": "./lib/commonjs/index.js"
|
|
19
|
+
}
|
|
12
20
|
},
|
|
13
21
|
"./package.json": "./package.json",
|
|
14
22
|
"./app.plugin.js": "./app.plugin.js"
|
|
@@ -113,14 +121,14 @@
|
|
|
113
121
|
"react-native": "0.79.1",
|
|
114
122
|
"react-native-builder-bob": "0.41.0",
|
|
115
123
|
"typescript": "^6.0.2",
|
|
116
|
-
"hot-updater": "0.
|
|
124
|
+
"hot-updater": "0.31.0"
|
|
117
125
|
},
|
|
118
126
|
"dependencies": {
|
|
119
127
|
"use-sync-external-store": "1.5.0",
|
|
120
|
-
"@hot-updater/cli-tools": "0.
|
|
121
|
-
"@hot-updater/
|
|
122
|
-
"@hot-updater/
|
|
123
|
-
"@hot-updater/plugin-core": "0.
|
|
128
|
+
"@hot-updater/cli-tools": "0.31.0",
|
|
129
|
+
"@hot-updater/core": "0.31.0",
|
|
130
|
+
"@hot-updater/js": "0.31.0",
|
|
131
|
+
"@hot-updater/plugin-core": "0.31.0"
|
|
124
132
|
},
|
|
125
133
|
"scripts": {
|
|
126
134
|
"build": "bob build && tsc -p plugin/tsconfig.build.json",
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
import { readFile } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
|
|
4
|
+
import { beforeEach, describe, expect, it, vi } from "vitest";
|
|
5
|
+
|
|
6
|
+
import { createDefaultResolver } from "./DefaultResolver";
|
|
7
|
+
import { HOT_UPDATER_SDK_VERSION } from "./sdkVersion";
|
|
8
|
+
import type { ResolverCheckUpdateParams } from "./types";
|
|
9
|
+
|
|
10
|
+
const mocks = vi.hoisted(() => ({
|
|
11
|
+
fetchUpdateInfo: vi.fn(),
|
|
12
|
+
}));
|
|
13
|
+
|
|
14
|
+
vi.mock("./fetchUpdateInfo", () => ({
|
|
15
|
+
fetchUpdateInfo: mocks.fetchUpdateInfo,
|
|
16
|
+
}));
|
|
17
|
+
|
|
18
|
+
const createParams = (
|
|
19
|
+
params?: Partial<ResolverCheckUpdateParams>,
|
|
20
|
+
): ResolverCheckUpdateParams => ({
|
|
21
|
+
appVersion: "1.0.0",
|
|
22
|
+
bundleId: "bundle-id",
|
|
23
|
+
channel: "production",
|
|
24
|
+
cohort: "cohort",
|
|
25
|
+
fingerprintHash: null,
|
|
26
|
+
minBundleId: "min-bundle-id",
|
|
27
|
+
platform: "ios",
|
|
28
|
+
updateStrategy: "appVersion",
|
|
29
|
+
...params,
|
|
30
|
+
});
|
|
31
|
+
|
|
32
|
+
describe("createDefaultResolver", () => {
|
|
33
|
+
beforeEach(() => {
|
|
34
|
+
mocks.fetchUpdateInfo.mockReset();
|
|
35
|
+
mocks.fetchUpdateInfo.mockResolvedValue(null);
|
|
36
|
+
});
|
|
37
|
+
|
|
38
|
+
it("strips trailing slashes from baseURL for app-version requests", async () => {
|
|
39
|
+
const resolver = createDefaultResolver(
|
|
40
|
+
"http://localhost:3007/hot-updater/",
|
|
41
|
+
);
|
|
42
|
+
|
|
43
|
+
await resolver.checkUpdate?.(
|
|
44
|
+
createParams({
|
|
45
|
+
appVersion: "1.0",
|
|
46
|
+
bundleId: "current-bundle",
|
|
47
|
+
channel: "production",
|
|
48
|
+
cohort: "730",
|
|
49
|
+
minBundleId: "min-bundle",
|
|
50
|
+
platform: "android",
|
|
51
|
+
}),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenCalledWith({
|
|
55
|
+
requestHeaders: {
|
|
56
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
57
|
+
},
|
|
58
|
+
requestTimeout: undefined,
|
|
59
|
+
url: "http://localhost:3007/hot-updater/app-version/android/1.0/production/min-bundle/current-bundle/730",
|
|
60
|
+
});
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
it("strips trailing slashes from baseURL for fingerprint requests", async () => {
|
|
64
|
+
const resolver = createDefaultResolver(
|
|
65
|
+
"http://localhost:3007/hot-updater///",
|
|
66
|
+
);
|
|
67
|
+
|
|
68
|
+
await resolver.checkUpdate?.(
|
|
69
|
+
createParams({
|
|
70
|
+
appVersion: "1.0",
|
|
71
|
+
bundleId: "current-bundle",
|
|
72
|
+
channel: "beta",
|
|
73
|
+
cohort: "qa",
|
|
74
|
+
fingerprintHash: "fingerprint-hash",
|
|
75
|
+
minBundleId: "min-bundle",
|
|
76
|
+
platform: "ios",
|
|
77
|
+
requestHeaders: { authorization: "Bearer token" },
|
|
78
|
+
requestTimeout: 1500,
|
|
79
|
+
updateStrategy: "fingerprint",
|
|
80
|
+
}),
|
|
81
|
+
);
|
|
82
|
+
|
|
83
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenCalledWith({
|
|
84
|
+
requestHeaders: {
|
|
85
|
+
authorization: "Bearer token",
|
|
86
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
87
|
+
},
|
|
88
|
+
requestTimeout: 1500,
|
|
89
|
+
url: "http://localhost:3007/hot-updater/fingerprint/ios/fingerprint-hash/beta/min-bundle/current-bundle/qa",
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
it("keeps the SDK version header aligned with package.json", async () => {
|
|
94
|
+
const [{ HOT_UPDATER_SDK_VERSION }, packageJson] = await Promise.all([
|
|
95
|
+
import("./sdkVersion"),
|
|
96
|
+
readFile(join(__dirname, "../package.json"), "utf-8"),
|
|
97
|
+
]);
|
|
98
|
+
const pkg = JSON.parse(packageJson) as { version: string };
|
|
99
|
+
|
|
100
|
+
expect(HOT_UPDATER_SDK_VERSION).toBe(pkg.version);
|
|
101
|
+
});
|
|
102
|
+
|
|
103
|
+
it("propagates fetchUpdateInfo errors", async () => {
|
|
104
|
+
mocks.fetchUpdateInfo.mockRejectedValueOnce(new Error("Network failed"));
|
|
105
|
+
const resolver = createDefaultResolver("http://localhost:3007/hot-updater");
|
|
106
|
+
|
|
107
|
+
await expect(resolver.checkUpdate?.(createParams())).rejects.toThrow(
|
|
108
|
+
"Network failed",
|
|
109
|
+
);
|
|
110
|
+
});
|
|
111
|
+
|
|
112
|
+
it("resolves dynamic baseURL before checking for updates", async () => {
|
|
113
|
+
const resolveBaseURL = vi.fn(async () => "https://updates.example.com");
|
|
114
|
+
const resolver = createDefaultResolver(resolveBaseURL);
|
|
115
|
+
|
|
116
|
+
await resolver.checkUpdate?.(createParams());
|
|
117
|
+
|
|
118
|
+
expect(resolveBaseURL).toHaveBeenCalledWith();
|
|
119
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenCalledWith({
|
|
120
|
+
requestHeaders: {
|
|
121
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
122
|
+
},
|
|
123
|
+
requestTimeout: undefined,
|
|
124
|
+
url: "https://updates.example.com/app-version/ios/1.0.0/production/min-bundle-id/bundle-id/cohort",
|
|
125
|
+
});
|
|
126
|
+
});
|
|
127
|
+
|
|
128
|
+
it("calls dynamic baseURL for each update check", async () => {
|
|
129
|
+
const resolveBaseURL = vi
|
|
130
|
+
.fn<() => Promise<string>>()
|
|
131
|
+
.mockResolvedValueOnce("https://one.example.com")
|
|
132
|
+
.mockResolvedValueOnce("https://two.example.com");
|
|
133
|
+
const resolver = createDefaultResolver(resolveBaseURL);
|
|
134
|
+
|
|
135
|
+
await resolver.checkUpdate?.(createParams());
|
|
136
|
+
await resolver.checkUpdate?.(createParams());
|
|
137
|
+
|
|
138
|
+
expect(resolveBaseURL).toHaveBeenCalledTimes(2);
|
|
139
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenNthCalledWith(1, {
|
|
140
|
+
requestHeaders: {
|
|
141
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
142
|
+
},
|
|
143
|
+
requestTimeout: undefined,
|
|
144
|
+
url: "https://one.example.com/app-version/ios/1.0.0/production/min-bundle-id/bundle-id/cohort",
|
|
145
|
+
});
|
|
146
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenNthCalledWith(2, {
|
|
147
|
+
requestHeaders: {
|
|
148
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
149
|
+
},
|
|
150
|
+
requestTimeout: undefined,
|
|
151
|
+
url: "https://two.example.com/app-version/ios/1.0.0/production/min-bundle-id/bundle-id/cohort",
|
|
152
|
+
});
|
|
153
|
+
});
|
|
154
|
+
|
|
155
|
+
it("strips trailing slashes from dynamic baseURL results", async () => {
|
|
156
|
+
const resolver = createDefaultResolver(
|
|
157
|
+
() => "https://updates.example.com/",
|
|
158
|
+
);
|
|
159
|
+
|
|
160
|
+
await resolver.checkUpdate?.(createParams());
|
|
161
|
+
|
|
162
|
+
expect(mocks.fetchUpdateInfo).toHaveBeenCalledWith({
|
|
163
|
+
requestHeaders: {
|
|
164
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
165
|
+
},
|
|
166
|
+
requestTimeout: undefined,
|
|
167
|
+
url: "https://updates.example.com/app-version/ios/1.0.0/production/min-bundle-id/bundle-id/cohort",
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
|
|
171
|
+
it("rejects an empty dynamic baseURL", async () => {
|
|
172
|
+
const resolver = createDefaultResolver(() => "");
|
|
173
|
+
|
|
174
|
+
await expect(resolver.checkUpdate?.(createParams())).rejects.toThrow(
|
|
175
|
+
"baseURL resolver must return a non-empty string",
|
|
176
|
+
);
|
|
177
|
+
});
|
|
178
|
+
});
|
package/src/DefaultResolver.ts
CHANGED
|
@@ -1,20 +1,43 @@
|
|
|
1
1
|
import type { AppUpdateInfo } from "@hot-updater/core";
|
|
2
2
|
|
|
3
3
|
import { fetchUpdateInfo } from "./fetchUpdateInfo";
|
|
4
|
-
import
|
|
4
|
+
import { HOT_UPDATER_SDK_VERSION } from "./sdkVersion";
|
|
5
|
+
import type {
|
|
6
|
+
HotUpdaterBaseURL,
|
|
7
|
+
HotUpdaterResolver,
|
|
8
|
+
ResolverCheckUpdateParams,
|
|
9
|
+
} from "./types";
|
|
10
|
+
|
|
11
|
+
const resolveBaseURL = async (baseURL: HotUpdaterBaseURL): Promise<string> => {
|
|
12
|
+
const resolvedBaseURL =
|
|
13
|
+
typeof baseURL === "function" ? await baseURL() : baseURL;
|
|
14
|
+
|
|
15
|
+
if (!resolvedBaseURL) {
|
|
16
|
+
throw new Error("baseURL resolver must return a non-empty string");
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
return resolvedBaseURL;
|
|
20
|
+
};
|
|
5
21
|
|
|
6
22
|
/**
|
|
7
23
|
* Creates a default resolver that uses baseURL for network operations.
|
|
8
24
|
* This encapsulates the existing baseURL logic into a resolver.
|
|
9
25
|
*
|
|
10
|
-
* @param baseURL - The base URL for the update server
|
|
26
|
+
* @param baseURL - The base URL for the update server, or a function that
|
|
27
|
+
* resolves it before each update check.
|
|
11
28
|
* @returns A HotUpdaterResolver that uses the baseURL
|
|
12
29
|
*/
|
|
13
|
-
export function createDefaultResolver(
|
|
30
|
+
export function createDefaultResolver(
|
|
31
|
+
baseURL: HotUpdaterBaseURL,
|
|
32
|
+
): HotUpdaterResolver {
|
|
14
33
|
return {
|
|
15
34
|
checkUpdate: async (
|
|
16
35
|
params: ResolverCheckUpdateParams,
|
|
17
36
|
): Promise<AppUpdateInfo | null> => {
|
|
37
|
+
const resolvedBaseURL = (await resolveBaseURL(baseURL)).replace(
|
|
38
|
+
/\/+$/,
|
|
39
|
+
"",
|
|
40
|
+
);
|
|
18
41
|
let url: string;
|
|
19
42
|
const cohortPath = `/${encodeURIComponent(params.cohort)}`;
|
|
20
43
|
|
|
@@ -22,14 +45,17 @@ export function createDefaultResolver(baseURL: string): HotUpdaterResolver {
|
|
|
22
45
|
if (!params.fingerprintHash) {
|
|
23
46
|
throw new Error("Fingerprint hash is required");
|
|
24
47
|
}
|
|
25
|
-
url = `${
|
|
48
|
+
url = `${resolvedBaseURL}/fingerprint/${params.platform}/${params.fingerprintHash}/${params.channel}/${params.minBundleId}/${params.bundleId}${cohortPath}`;
|
|
26
49
|
} else {
|
|
27
|
-
url = `${
|
|
50
|
+
url = `${resolvedBaseURL}/app-version/${params.platform}/${params.appVersion}/${params.channel}/${params.minBundleId}/${params.bundleId}${cohortPath}`;
|
|
28
51
|
}
|
|
29
52
|
|
|
30
53
|
return fetchUpdateInfo({
|
|
31
54
|
url,
|
|
32
|
-
requestHeaders:
|
|
55
|
+
requestHeaders: {
|
|
56
|
+
...params.requestHeaders,
|
|
57
|
+
"Hot-Updater-SDK-Version": HOT_UPDATER_SDK_VERSION,
|
|
58
|
+
},
|
|
33
59
|
requestTimeout: params.requestTimeout,
|
|
34
60
|
});
|
|
35
61
|
},
|