@hot-updater/react-native 0.18.5 → 0.19.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/android/src/main/java/com/hotupdater/HotUpdater.kt +7 -0
- package/android/src/main/java/com/hotupdater/HotUpdaterImpl.kt +13 -0
- package/android/src/newarch/HotUpdaterModule.kt +1 -0
- package/android/src/oldarch/HotUpdaterModule.kt +1 -0
- package/ios/HotUpdater/Internal/HotUpdater.mm +2 -1
- package/ios/HotUpdater/Internal/HotUpdaterImpl.swift +8 -2
- package/lib/commonjs/checkForUpdate.js +27 -20
- package/lib/commonjs/checkForUpdate.js.map +1 -1
- package/lib/commonjs/fetchUpdateInfo.js +53 -48
- package/lib/commonjs/fetchUpdateInfo.js.map +1 -1
- package/lib/commonjs/index.js +0 -12
- package/lib/commonjs/index.js.map +1 -1
- package/lib/commonjs/native.js +5 -19
- package/lib/commonjs/native.js.map +1 -1
- package/lib/commonjs/specs/NativeHotUpdater.js.map +1 -1
- package/lib/module/checkForUpdate.js +28 -21
- package/lib/module/checkForUpdate.js.map +1 -1
- package/lib/module/fetchUpdateInfo.js +53 -48
- package/lib/module/fetchUpdateInfo.js.map +1 -1
- package/lib/module/index.js +1 -13
- package/lib/module/index.js.map +1 -1
- package/lib/module/native.js +4 -17
- package/lib/module/native.js.map +1 -1
- package/lib/module/specs/NativeHotUpdater.js.map +1 -1
- package/lib/typescript/commonjs/checkForUpdate.d.ts +11 -2
- package/lib/typescript/commonjs/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts +9 -3
- package/lib/typescript/commonjs/fetchUpdateInfo.d.ts.map +1 -1
- package/lib/typescript/commonjs/index.d.ts +0 -12
- package/lib/typescript/commonjs/index.d.ts.map +1 -1
- package/lib/typescript/commonjs/native.d.ts +1 -5
- package/lib/typescript/commonjs/native.d.ts.map +1 -1
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts +1 -0
- package/lib/typescript/commonjs/specs/NativeHotUpdater.d.ts.map +1 -1
- package/lib/typescript/module/checkForUpdate.d.ts +11 -2
- package/lib/typescript/module/checkForUpdate.d.ts.map +1 -1
- package/lib/typescript/module/fetchUpdateInfo.d.ts +9 -3
- package/lib/typescript/module/fetchUpdateInfo.d.ts.map +1 -1
- package/lib/typescript/module/index.d.ts +0 -12
- package/lib/typescript/module/index.d.ts.map +1 -1
- package/lib/typescript/module/native.d.ts +1 -5
- package/lib/typescript/module/native.d.ts.map +1 -1
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts +1 -0
- package/lib/typescript/module/specs/NativeHotUpdater.d.ts.map +1 -1
- package/package.json +10 -5
- package/plugin/build/withHotUpdater.js +138 -7
- package/src/checkForUpdate.ts +44 -35
- package/src/fetchUpdateInfo.ts +65 -51
- package/src/index.ts +0 -13
- package/src/native.ts +4 -22
- package/src/specs/NativeHotUpdater.ts +1 -0
package/src/checkForUpdate.ts
CHANGED
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
import type { AppUpdateInfo,
|
|
1
|
+
import type { AppUpdateInfo, UpdateBundleParams } from "@hot-updater/core";
|
|
2
2
|
import { Platform } from "react-native";
|
|
3
3
|
import { HotUpdaterError } from "./error";
|
|
4
4
|
import { type UpdateSource, fetchUpdateInfo } from "./fetchUpdateInfo";
|
|
5
5
|
import {
|
|
6
|
-
HotUpdaterConstants,
|
|
7
6
|
getAppVersion,
|
|
8
7
|
getBundleId,
|
|
9
8
|
getChannel,
|
|
9
|
+
getFingerprintHash,
|
|
10
10
|
getMinBundleId,
|
|
11
11
|
updateBundle,
|
|
12
12
|
} from "./native";
|
|
@@ -55,30 +55,22 @@ export async function checkForUpdate(
|
|
|
55
55
|
return null;
|
|
56
56
|
}
|
|
57
57
|
|
|
58
|
-
const
|
|
59
|
-
bundleId: currentBundleId,
|
|
60
|
-
platform,
|
|
61
|
-
minBundleId,
|
|
62
|
-
channel: channel ?? undefined,
|
|
63
|
-
};
|
|
58
|
+
const fingerprintHash = getFingerprintHash();
|
|
64
59
|
|
|
65
|
-
return fetchUpdateInfo(
|
|
66
|
-
options.source,
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
options.onError,
|
|
80
|
-
options.requestTimeout,
|
|
81
|
-
).then((updateInfo) => {
|
|
60
|
+
return fetchUpdateInfo({
|
|
61
|
+
source: options.source,
|
|
62
|
+
params: {
|
|
63
|
+
bundleId: currentBundleId,
|
|
64
|
+
appVersion: currentAppVersion,
|
|
65
|
+
platform,
|
|
66
|
+
minBundleId,
|
|
67
|
+
channel,
|
|
68
|
+
fingerprintHash,
|
|
69
|
+
},
|
|
70
|
+
requestHeaders: options.requestHeaders,
|
|
71
|
+
onError: options.onError,
|
|
72
|
+
requestTimeout: options.requestTimeout,
|
|
73
|
+
}).then((updateInfo) => {
|
|
82
74
|
if (!updateInfo) {
|
|
83
75
|
return null;
|
|
84
76
|
}
|
|
@@ -96,13 +88,30 @@ export async function checkForUpdate(
|
|
|
96
88
|
});
|
|
97
89
|
}
|
|
98
90
|
|
|
99
|
-
export
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
91
|
+
export interface GetUpdateSourceOptions {
|
|
92
|
+
/**
|
|
93
|
+
* The update strategy to use.
|
|
94
|
+
* @description
|
|
95
|
+
* - "fingerprint": Use the fingerprint hash to check for updates.
|
|
96
|
+
* - "appVersion": Use the target app version to check for updates.
|
|
97
|
+
*/
|
|
98
|
+
updateStrategy: "appVersion" | "fingerprint";
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
export const getUpdateSource =
|
|
102
|
+
(baseUrl: string, options: GetUpdateSourceOptions) =>
|
|
103
|
+
(params: UpdateBundleParams) => {
|
|
104
|
+
switch (options.updateStrategy) {
|
|
105
|
+
case "fingerprint": {
|
|
106
|
+
if (!params.fingerprintHash) {
|
|
107
|
+
throw new HotUpdaterError("Fingerprint hash is required");
|
|
108
|
+
}
|
|
109
|
+
return `${baseUrl}/fingerprint/${params.platform}/${params.fingerprintHash}/${params.channel}/${params.minBundleId}/${params.bundleId}`;
|
|
110
|
+
}
|
|
111
|
+
case "appVersion": {
|
|
112
|
+
return `${baseUrl}/app-version/${params.platform}/${params.appVersion}/${params.channel}/${params.minBundleId}/${params.bundleId}`;
|
|
113
|
+
}
|
|
114
|
+
default:
|
|
115
|
+
return baseUrl;
|
|
116
|
+
}
|
|
117
|
+
};
|
package/src/fetchUpdateInfo.ts
CHANGED
|
@@ -1,65 +1,79 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
AppUpdateInfo,
|
|
3
|
+
UpdateBundleParams,
|
|
4
|
+
UpdateStrategy,
|
|
5
|
+
} from "@hot-updater/core";
|
|
2
6
|
|
|
3
7
|
export type UpdateSource =
|
|
4
8
|
| string
|
|
5
|
-
| ((
|
|
6
|
-
| ((
|
|
9
|
+
| ((params: UpdateBundleParams) => Promise<AppUpdateInfo | null>)
|
|
10
|
+
| ((params: UpdateBundleParams) => string);
|
|
7
11
|
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
args: GetBundlesArgs,
|
|
12
|
+
function buildRequestHeaders(
|
|
13
|
+
params: UpdateBundleParams,
|
|
11
14
|
requestHeaders?: Record<string, string>,
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
const url = source(args);
|
|
17
|
-
if (typeof url !== "string") {
|
|
18
|
-
return null;
|
|
19
|
-
}
|
|
20
|
-
source = url;
|
|
21
|
-
}
|
|
15
|
+
): Record<string, string> {
|
|
16
|
+
const updateStrategy: UpdateStrategy = params.fingerprintHash
|
|
17
|
+
? "fingerprint"
|
|
18
|
+
: "appVersion";
|
|
22
19
|
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
20
|
+
return {
|
|
21
|
+
"Content-Type": "application/json",
|
|
22
|
+
"x-app-platform": params.platform,
|
|
23
|
+
"x-bundle-id": params.bundleId,
|
|
24
|
+
...(updateStrategy === "fingerprint"
|
|
25
|
+
? { "x-fingerprint-hash": params.fingerprintHash! }
|
|
26
|
+
: { "x-app-version": params.appVersion }),
|
|
27
|
+
...(params.minBundleId && { "x-min-bundle-id": params.minBundleId }),
|
|
28
|
+
...(params.channel && { "x-channel": params.channel }),
|
|
29
|
+
...(requestHeaders ?? {}),
|
|
30
|
+
};
|
|
31
|
+
}
|
|
27
32
|
|
|
28
|
-
|
|
29
|
-
|
|
33
|
+
async function resolveSource(
|
|
34
|
+
source: UpdateSource,
|
|
35
|
+
params: UpdateBundleParams,
|
|
36
|
+
): Promise<{ url: string } | { info: AppUpdateInfo | null }> {
|
|
37
|
+
if (typeof source !== "function") {
|
|
38
|
+
return { url: source };
|
|
39
|
+
}
|
|
40
|
+
const result = source(params);
|
|
41
|
+
if (typeof result === "string") {
|
|
42
|
+
return { url: result };
|
|
43
|
+
}
|
|
44
|
+
return { info: await result };
|
|
45
|
+
}
|
|
30
46
|
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
"x-app-version": args.appVersion,
|
|
49
|
-
...(args.minBundleId ? { "x-min-bundle-id": args.minBundleId } : {}),
|
|
50
|
-
...(args.channel ? { "x-channel": args.channel } : {}),
|
|
51
|
-
...requestHeaders,
|
|
52
|
-
};
|
|
53
|
-
break;
|
|
54
|
-
default:
|
|
55
|
-
throw new Error("Invalid update strategy");
|
|
47
|
+
export const fetchUpdateInfo = async ({
|
|
48
|
+
source,
|
|
49
|
+
params,
|
|
50
|
+
requestHeaders,
|
|
51
|
+
onError,
|
|
52
|
+
requestTimeout = 5000,
|
|
53
|
+
}: {
|
|
54
|
+
source: UpdateSource;
|
|
55
|
+
params: UpdateBundleParams;
|
|
56
|
+
requestHeaders?: Record<string, string>;
|
|
57
|
+
onError?: (error: Error) => void;
|
|
58
|
+
requestTimeout?: number;
|
|
59
|
+
}): Promise<AppUpdateInfo | null> => {
|
|
60
|
+
try {
|
|
61
|
+
const resolvedSource = await resolveSource(source, params);
|
|
62
|
+
if ("info" in resolvedSource) {
|
|
63
|
+
return resolvedSource.info;
|
|
56
64
|
}
|
|
57
65
|
|
|
58
|
-
const
|
|
66
|
+
const controller = new AbortController();
|
|
67
|
+
const timeoutId = setTimeout(() => {
|
|
68
|
+
controller.abort();
|
|
69
|
+
}, requestTimeout);
|
|
70
|
+
|
|
71
|
+
const headers = buildRequestHeaders(params, requestHeaders);
|
|
72
|
+
|
|
73
|
+
const response = await fetch(resolvedSource.url, {
|
|
59
74
|
signal: controller.signal,
|
|
60
75
|
headers,
|
|
61
76
|
});
|
|
62
|
-
|
|
63
77
|
clearTimeout(timeoutId);
|
|
64
78
|
|
|
65
79
|
if (response.status !== 200) {
|
|
@@ -69,9 +83,9 @@ export const fetchUpdateInfo = async (
|
|
|
69
83
|
} catch (error: any) {
|
|
70
84
|
if (error.name === "AbortError") {
|
|
71
85
|
onError?.(new Error("Request timed out"));
|
|
72
|
-
|
|
86
|
+
} else {
|
|
87
|
+
onError?.(error as Error);
|
|
73
88
|
}
|
|
74
|
-
onError?.(error as Error);
|
|
75
89
|
return null;
|
|
76
90
|
}
|
|
77
91
|
};
|
package/src/index.ts
CHANGED
|
@@ -6,7 +6,6 @@ import {
|
|
|
6
6
|
getChannel,
|
|
7
7
|
getFingerprintHash,
|
|
8
8
|
getMinBundleId,
|
|
9
|
-
getReleaseChannel,
|
|
10
9
|
reload,
|
|
11
10
|
updateBundle,
|
|
12
11
|
} from "./native";
|
|
@@ -79,18 +78,6 @@ export const HotUpdater = {
|
|
|
79
78
|
* ```
|
|
80
79
|
*/
|
|
81
80
|
getChannel,
|
|
82
|
-
/**
|
|
83
|
-
* The initial channel of the native app.
|
|
84
|
-
*
|
|
85
|
-
* @returns {string} The current release channel of the app
|
|
86
|
-
* @default "production"
|
|
87
|
-
* @example
|
|
88
|
-
* ```ts
|
|
89
|
-
* const channel = HotUpdater.getReleaseChannel();
|
|
90
|
-
* console.log(`Current release channel: ${channel}`);
|
|
91
|
-
* ```
|
|
92
|
-
*/
|
|
93
|
-
getReleaseChannel,
|
|
94
81
|
/**
|
|
95
82
|
* Adds a listener to HotUpdater events.
|
|
96
83
|
*
|
package/src/native.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import type { UpdateStatus
|
|
2
|
-
import { NativeEventEmitter
|
|
1
|
+
import type { UpdateStatus } from "@hot-updater/core";
|
|
2
|
+
import { NativeEventEmitter } from "react-native";
|
|
3
3
|
import HotUpdaterNative, {
|
|
4
4
|
type UpdateBundleParams,
|
|
5
5
|
} from "./specs/NativeHotUpdater";
|
|
@@ -7,20 +7,9 @@ import HotUpdaterNative, {
|
|
|
7
7
|
const NIL_UUID = "00000000-0000-0000-0000-000000000000";
|
|
8
8
|
|
|
9
9
|
declare const __HOT_UPDATER_BUNDLE_ID: string | undefined;
|
|
10
|
-
declare const __HOT_UPDATER_FINGERPRINT_HASH_IOS: string | null;
|
|
11
|
-
declare const __HOT_UPDATER_FINGERPRINT_HASH_ANDROID: string | null;
|
|
12
|
-
declare const __HOT_UPDATER_UPDATE_STRATEGY: UpdateStrategy;
|
|
13
|
-
declare const __HOT_UPDATER_CHANNEL: string | null;
|
|
14
10
|
|
|
15
11
|
export const HotUpdaterConstants = {
|
|
16
|
-
OVER_THE_AIR_CHANNEL: __HOT_UPDATER_CHANNEL,
|
|
17
12
|
HOT_UPDATER_BUNDLE_ID: __HOT_UPDATER_BUNDLE_ID || NIL_UUID,
|
|
18
|
-
FINGERPRINT_HASH: Platform.select({
|
|
19
|
-
ios: __HOT_UPDATER_FINGERPRINT_HASH_IOS,
|
|
20
|
-
android: __HOT_UPDATER_FINGERPRINT_HASH_ANDROID,
|
|
21
|
-
default: null,
|
|
22
|
-
}),
|
|
23
|
-
UPDATE_STRATEGY: __HOT_UPDATER_UPDATE_STRATEGY,
|
|
24
13
|
};
|
|
25
14
|
|
|
26
15
|
export type HotUpdaterEvent = {
|
|
@@ -141,14 +130,6 @@ export const getBundleId = (): string => {
|
|
|
141
130
|
* @returns {string} Resolves with the channel or null if not available.
|
|
142
131
|
*/
|
|
143
132
|
export const getChannel = (): string => {
|
|
144
|
-
if (HotUpdaterConstants.OVER_THE_AIR_CHANNEL) {
|
|
145
|
-
return HotUpdaterConstants.OVER_THE_AIR_CHANNEL;
|
|
146
|
-
}
|
|
147
|
-
const constants = HotUpdaterNative.getConstants();
|
|
148
|
-
return constants.CHANNEL;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
export const getReleaseChannel = (): string => {
|
|
152
133
|
const constants = HotUpdaterNative.getConstants();
|
|
153
134
|
return constants.CHANNEL;
|
|
154
135
|
};
|
|
@@ -159,5 +140,6 @@ export const getReleaseChannel = (): string => {
|
|
|
159
140
|
* @returns {string | null} Resolves with the fingerprint hash
|
|
160
141
|
*/
|
|
161
142
|
export const getFingerprintHash = (): string | null => {
|
|
162
|
-
|
|
143
|
+
const constants = HotUpdaterNative.getConstants();
|
|
144
|
+
return constants.FINGERPRINT_HASH;
|
|
163
145
|
};
|