@hot-updater/react-native 0.1.4 → 0.1.5
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 -2
- package/android/build.gradle +16 -3
- package/android/generated/java/com/hotupdater/NativeHotUpdaterSpec.java +54 -0
- package/android/generated/jni/CMakeLists.txt +36 -0
- package/android/generated/jni/HotUpdaterSpec-generated.cpp +56 -0
- package/android/generated/jni/HotUpdaterSpec.h +31 -0
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI-generated.cpp +57 -0
- package/android/generated/jni/react/renderer/components/HotUpdaterSpec/HotUpdaterSpecJSI.h +103 -0
- package/android/react-native-helpers.gradle +42 -0
- package/android/src/main/java/com/hotupdater/HotUpdater.kt +151 -240
- package/android/src/main/java/com/hotupdater/HotUpdaterModule.kt +52 -40
- package/android/src/main/java/com/hotupdater/HotUpdaterPackage.kt +25 -24
- package/android/src/main/java/com/hotupdater/ReactIntegrationManagerBase.kt +34 -0
- package/android/src/newarch/HotUpdaterSpec.kt +3 -2
- package/android/src/newarch/ReactIntegrationManager.kt +46 -0
- package/android/src/oldarch/HotUpdaterSpec.kt +12 -8
- package/android/src/oldarch/ReactIntegrationManager.kt +41 -0
- package/dist/index.d.mts +71 -0
- package/dist/index.d.ts +43 -52
- package/dist/index.js +2366 -139
- package/dist/index.mjs +2411 -0
- package/ios/HotUpdater/HotUpdater.h +8 -4
- package/ios/HotUpdater/HotUpdater.mm +167 -116
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec-generated.mm +67 -0
- package/ios/generated/HotUpdaterSpec/HotUpdaterSpec.h +67 -0
- package/ios/generated/HotUpdaterSpecJSI-generated.cpp +57 -0
- package/ios/generated/HotUpdaterSpecJSI.h +103 -0
- package/package.json +26 -10
- package/react-native.config.js +12 -0
- package/src/const.ts +1 -0
- package/src/ensureBundles.ts +21 -0
- package/src/global.d.ts +3 -0
- package/src/index.ts +27 -5
- package/src/init.tsx +25 -7
- package/src/native.ts +50 -42
- package/src/specs/{NativeHotUpdaterModule.ts → NativeHotUpdater.ts} +6 -7
- package/src/store.ts +48 -0
- package/dist/index.cjs +0 -220
- package/dist/index.d.cts +0 -80
- package/src/checkForUpdate.test.ts +0 -517
- package/src/checkForUpdate.ts +0 -111
- package/src/utils.ts +0 -2
package/dist/index.d.cts
DELETED
|
@@ -1,80 +0,0 @@
|
|
|
1
|
-
import * as _hot_updater_utils from '@hot-updater/utils';
|
|
2
|
-
import { UpdateSourceArg } from '@hot-updater/utils';
|
|
3
|
-
|
|
4
|
-
type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
5
|
-
declare const checkForUpdate: (updateSources: UpdateSourceArg) => Promise<{
|
|
6
|
-
bundleVersion: number;
|
|
7
|
-
forceUpdate: boolean;
|
|
8
|
-
file: null;
|
|
9
|
-
hash: null;
|
|
10
|
-
status: UpdateStatus;
|
|
11
|
-
} | {
|
|
12
|
-
bundleVersion: number;
|
|
13
|
-
forceUpdate: boolean;
|
|
14
|
-
file: string;
|
|
15
|
-
hash: string;
|
|
16
|
-
status: UpdateStatus;
|
|
17
|
-
} | null>;
|
|
18
|
-
|
|
19
|
-
declare class HotUpdaterError extends Error {
|
|
20
|
-
constructor(message: string);
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
type HotUpdaterStatus = "INSTALLING_UPDATE" | "UP_TO_DATE";
|
|
24
|
-
interface HotUpdaterInitConfig {
|
|
25
|
-
source: UpdateSourceArg;
|
|
26
|
-
onSuccess?: (status: HotUpdaterStatus) => void;
|
|
27
|
-
onError?: (error: HotUpdaterError) => void;
|
|
28
|
-
}
|
|
29
|
-
declare const init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
30
|
-
|
|
31
|
-
/**
|
|
32
|
-
* Fetches the current bundle version id.
|
|
33
|
-
*
|
|
34
|
-
* @async
|
|
35
|
-
* @returns {Promise<number>} Resolves with the current version id or null if not available.
|
|
36
|
-
*/
|
|
37
|
-
declare const getBundleVersion: () => Promise<number>;
|
|
38
|
-
/**
|
|
39
|
-
* Downloads files from given URLs.
|
|
40
|
-
*
|
|
41
|
-
* @async
|
|
42
|
-
* @param {string} bundleVersion - identifier for the bundle version.
|
|
43
|
-
* @param {string | null} zipUrl - zip file URL.
|
|
44
|
-
* @returns {Promise<boolean>} Resolves with true if download was successful, otherwise rejects with an error.
|
|
45
|
-
*/
|
|
46
|
-
declare const updateBundle: (bundleVersion: number, zipUrl: string | null) => Promise<boolean>;
|
|
47
|
-
/**
|
|
48
|
-
* Fetches the current app version.
|
|
49
|
-
*/
|
|
50
|
-
declare const getAppVersion: () => Promise<string | null>;
|
|
51
|
-
/**
|
|
52
|
-
* Reloads the app.
|
|
53
|
-
*/
|
|
54
|
-
declare const reload: () => void;
|
|
55
|
-
/**
|
|
56
|
-
* Initializes the HotUpdater.
|
|
57
|
-
*/
|
|
58
|
-
declare const initializeOnAppUpdate: () => void;
|
|
59
|
-
|
|
60
|
-
declare const HotUpdater: {
|
|
61
|
-
init: (config: HotUpdaterInitConfig) => Promise<void>;
|
|
62
|
-
reload: () => void;
|
|
63
|
-
checkForUpdate: (updateSources: _hot_updater_utils.UpdateSourceArg) => Promise<{
|
|
64
|
-
bundleVersion: number;
|
|
65
|
-
forceUpdate: boolean;
|
|
66
|
-
file: null;
|
|
67
|
-
hash: null;
|
|
68
|
-
status: UpdateStatus;
|
|
69
|
-
} | {
|
|
70
|
-
bundleVersion: number;
|
|
71
|
-
forceUpdate: boolean;
|
|
72
|
-
file: string;
|
|
73
|
-
hash: string;
|
|
74
|
-
status: UpdateStatus;
|
|
75
|
-
} | null>;
|
|
76
|
-
getAppVersion: () => Promise<string | null>;
|
|
77
|
-
getBundleVersion: () => Promise<number>;
|
|
78
|
-
};
|
|
79
|
-
|
|
80
|
-
export { HotUpdater, type HotUpdaterInitConfig, type HotUpdaterStatus, type UpdateStatus, checkForUpdate, getAppVersion, getBundleVersion, init, initializeOnAppUpdate, reload, updateBundle };
|
|
@@ -1,517 +0,0 @@
|
|
|
1
|
-
import type { UpdateSource } from "@hot-updater/utils";
|
|
2
|
-
import { beforeAll, describe, expect, it, vi } from "vitest";
|
|
3
|
-
import { checkForUpdate } from "./checkForUpdate";
|
|
4
|
-
import * as natives from "./native";
|
|
5
|
-
|
|
6
|
-
vi.mock("./native", () => ({
|
|
7
|
-
getAppVersion: async () => "1.0",
|
|
8
|
-
getBundleVersion: async () => 1,
|
|
9
|
-
}));
|
|
10
|
-
|
|
11
|
-
vi.mock("react-native", () => ({
|
|
12
|
-
Platform: {
|
|
13
|
-
OS: "ios",
|
|
14
|
-
},
|
|
15
|
-
}));
|
|
16
|
-
|
|
17
|
-
describe("appVersion 1.0, bundleVersion null", async () => {
|
|
18
|
-
beforeAll(() => {
|
|
19
|
-
vi.spyOn(natives, "getAppVersion").mockImplementation(async () => "1.0");
|
|
20
|
-
vi.spyOn(natives, "getBundleVersion").mockImplementation(async () => -1);
|
|
21
|
-
});
|
|
22
|
-
|
|
23
|
-
it("should return null if no update information is available", async () => {
|
|
24
|
-
const updateSources: UpdateSource[] = [];
|
|
25
|
-
|
|
26
|
-
const update = await checkForUpdate(updateSources);
|
|
27
|
-
expect(update).toBeNull();
|
|
28
|
-
});
|
|
29
|
-
|
|
30
|
-
it("should return null if no update is available when the app version is higher", async () => {
|
|
31
|
-
const updateSources: UpdateSource[] = [
|
|
32
|
-
{
|
|
33
|
-
platform: "ios",
|
|
34
|
-
targetVersion: "1.1",
|
|
35
|
-
enabled: true,
|
|
36
|
-
bundleVersion: 1,
|
|
37
|
-
forceUpdate: false,
|
|
38
|
-
file: "http://example.com/bundle.zip",
|
|
39
|
-
hash: "hash",
|
|
40
|
-
},
|
|
41
|
-
];
|
|
42
|
-
|
|
43
|
-
const update = await checkForUpdate(updateSources);
|
|
44
|
-
expect(update).toBeNull();
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
it("should update if a higher bundle with semver version exists", async () => {
|
|
48
|
-
const updateSources: UpdateSource[] = [
|
|
49
|
-
{
|
|
50
|
-
platform: "ios",
|
|
51
|
-
targetVersion: "1.x.x",
|
|
52
|
-
enabled: true,
|
|
53
|
-
bundleVersion: 1,
|
|
54
|
-
forceUpdate: false,
|
|
55
|
-
file: "http://example.com/bundle.zip",
|
|
56
|
-
hash: "hash",
|
|
57
|
-
},
|
|
58
|
-
{
|
|
59
|
-
platform: "ios",
|
|
60
|
-
targetVersion: "1.0",
|
|
61
|
-
enabled: true,
|
|
62
|
-
bundleVersion: 2,
|
|
63
|
-
forceUpdate: false,
|
|
64
|
-
file: "http://example.com/bundle.zip",
|
|
65
|
-
hash: "hash",
|
|
66
|
-
},
|
|
67
|
-
];
|
|
68
|
-
|
|
69
|
-
const update = await checkForUpdate(updateSources);
|
|
70
|
-
expect(update).toStrictEqual({
|
|
71
|
-
bundleVersion: 2,
|
|
72
|
-
forceUpdate: false,
|
|
73
|
-
status: "UPDATE",
|
|
74
|
-
file: "http://example.com/bundle.zip",
|
|
75
|
-
hash: "hash",
|
|
76
|
-
});
|
|
77
|
-
});
|
|
78
|
-
|
|
79
|
-
it("should update if a higher bundle version exists and forceUpdate is set to true", async () => {
|
|
80
|
-
const updateSources: UpdateSource[] = [
|
|
81
|
-
{
|
|
82
|
-
platform: "ios",
|
|
83
|
-
targetVersion: "1.0",
|
|
84
|
-
enabled: true,
|
|
85
|
-
bundleVersion: 1,
|
|
86
|
-
forceUpdate: true,
|
|
87
|
-
file: "http://example.com/bundle.zip",
|
|
88
|
-
hash: "hash",
|
|
89
|
-
},
|
|
90
|
-
];
|
|
91
|
-
const update = await checkForUpdate(updateSources);
|
|
92
|
-
|
|
93
|
-
expect(update).toStrictEqual({
|
|
94
|
-
bundleVersion: 1,
|
|
95
|
-
forceUpdate: true,
|
|
96
|
-
status: "UPDATE",
|
|
97
|
-
file: "http://example.com/bundle.zip",
|
|
98
|
-
hash: "hash",
|
|
99
|
-
});
|
|
100
|
-
});
|
|
101
|
-
|
|
102
|
-
it("should update if a higher bundle version exists and forceUpdate is set to false", async () => {
|
|
103
|
-
const updateSources: UpdateSource[] = [
|
|
104
|
-
{
|
|
105
|
-
platform: "ios",
|
|
106
|
-
targetVersion: "1.0",
|
|
107
|
-
file: "http://example.com/bundle.zip",
|
|
108
|
-
hash: "hash",
|
|
109
|
-
enabled: true,
|
|
110
|
-
bundleVersion: 1,
|
|
111
|
-
forceUpdate: false,
|
|
112
|
-
},
|
|
113
|
-
];
|
|
114
|
-
|
|
115
|
-
const update = await checkForUpdate(updateSources);
|
|
116
|
-
expect(update).toStrictEqual({
|
|
117
|
-
file: "http://example.com/bundle.zip",
|
|
118
|
-
hash: "hash",
|
|
119
|
-
bundleVersion: 1,
|
|
120
|
-
forceUpdate: false,
|
|
121
|
-
status: "UPDATE",
|
|
122
|
-
});
|
|
123
|
-
});
|
|
124
|
-
|
|
125
|
-
it("should update even if the app version is the same and the bundle version is significantly higher", async () => {
|
|
126
|
-
const updateSources: UpdateSource[] = [
|
|
127
|
-
{
|
|
128
|
-
platform: "ios",
|
|
129
|
-
targetVersion: "1.0",
|
|
130
|
-
file: "http://example.com/bundle.zip",
|
|
131
|
-
hash: "hash",
|
|
132
|
-
forceUpdate: false,
|
|
133
|
-
enabled: true,
|
|
134
|
-
bundleVersion: 5,
|
|
135
|
-
},
|
|
136
|
-
];
|
|
137
|
-
|
|
138
|
-
const update = await checkForUpdate(updateSources);
|
|
139
|
-
expect(update).toStrictEqual({
|
|
140
|
-
bundleVersion: 5,
|
|
141
|
-
forceUpdate: false,
|
|
142
|
-
status: "UPDATE",
|
|
143
|
-
file: "http://example.com/bundle.zip",
|
|
144
|
-
hash: "hash",
|
|
145
|
-
});
|
|
146
|
-
});
|
|
147
|
-
|
|
148
|
-
it("should update if the latest version is not available but a previous version is available", async () => {
|
|
149
|
-
const updateSources: UpdateSource[] = [
|
|
150
|
-
{
|
|
151
|
-
platform: "ios",
|
|
152
|
-
targetVersion: "1.0",
|
|
153
|
-
file: "http://example.com/bundle.zip",
|
|
154
|
-
hash: "hash",
|
|
155
|
-
forceUpdate: true,
|
|
156
|
-
enabled: false, // Disabled
|
|
157
|
-
bundleVersion: 2,
|
|
158
|
-
},
|
|
159
|
-
{
|
|
160
|
-
platform: "ios",
|
|
161
|
-
targetVersion: "1.0",
|
|
162
|
-
file: "http://example.com/bundle.zip",
|
|
163
|
-
hash: "hash",
|
|
164
|
-
forceUpdate: false,
|
|
165
|
-
enabled: true,
|
|
166
|
-
bundleVersion: 1,
|
|
167
|
-
},
|
|
168
|
-
];
|
|
169
|
-
|
|
170
|
-
const update = await checkForUpdate(updateSources);
|
|
171
|
-
expect(update).toStrictEqual({
|
|
172
|
-
file: "http://example.com/bundle.zip",
|
|
173
|
-
hash: "hash",
|
|
174
|
-
bundleVersion: 1,
|
|
175
|
-
forceUpdate: false,
|
|
176
|
-
status: "UPDATE",
|
|
177
|
-
});
|
|
178
|
-
});
|
|
179
|
-
|
|
180
|
-
it("should not update if all updates are disabled", async () => {
|
|
181
|
-
const updateSources: UpdateSource[] = [
|
|
182
|
-
{
|
|
183
|
-
platform: "ios",
|
|
184
|
-
targetVersion: "1.0",
|
|
185
|
-
file: "http://example.com/bundle.zip",
|
|
186
|
-
hash: "hash",
|
|
187
|
-
forceUpdate: true,
|
|
188
|
-
enabled: false, // Disabled
|
|
189
|
-
bundleVersion: 2,
|
|
190
|
-
},
|
|
191
|
-
{
|
|
192
|
-
platform: "ios",
|
|
193
|
-
targetVersion: "1.0",
|
|
194
|
-
file: "http://example.com/bundle.zip",
|
|
195
|
-
hash: "hash",
|
|
196
|
-
forceUpdate: false,
|
|
197
|
-
enabled: false, // Disabled
|
|
198
|
-
bundleVersion: 1,
|
|
199
|
-
},
|
|
200
|
-
];
|
|
201
|
-
|
|
202
|
-
const update = await checkForUpdate(updateSources);
|
|
203
|
-
expect(update).toBeNull();
|
|
204
|
-
});
|
|
205
|
-
|
|
206
|
-
it("should rollback to the original bundle when receiving the latest bundle but all updates are disabled", async () => {
|
|
207
|
-
const updateSources: UpdateSource[] = [
|
|
208
|
-
{
|
|
209
|
-
platform: "ios",
|
|
210
|
-
targetVersion: "1.0",
|
|
211
|
-
file: "http://example.com/bundle.zip",
|
|
212
|
-
hash: "hash",
|
|
213
|
-
forceUpdate: true,
|
|
214
|
-
enabled: false, // Disabled
|
|
215
|
-
bundleVersion: 2,
|
|
216
|
-
},
|
|
217
|
-
{
|
|
218
|
-
platform: "ios",
|
|
219
|
-
targetVersion: "1.0",
|
|
220
|
-
file: "http://example.com/bundle.zip",
|
|
221
|
-
hash: "hash",
|
|
222
|
-
forceUpdate: false,
|
|
223
|
-
enabled: false, // Disabled
|
|
224
|
-
bundleVersion: 1,
|
|
225
|
-
},
|
|
226
|
-
];
|
|
227
|
-
|
|
228
|
-
const update = await checkForUpdate(updateSources);
|
|
229
|
-
expect(update).toStrictEqual(null);
|
|
230
|
-
});
|
|
231
|
-
|
|
232
|
-
it("should update if the latest version is available and the app version is the same", async () => {
|
|
233
|
-
const updateSources: UpdateSource[] = [
|
|
234
|
-
{
|
|
235
|
-
forceUpdate: false,
|
|
236
|
-
platform: "ios",
|
|
237
|
-
file: "20240722210327/ios/build.zip",
|
|
238
|
-
hash: "a5cbf59a627759a88d472c502423ff55a4f6cd1aafeed3536f6a5f6e870c2290",
|
|
239
|
-
description: "",
|
|
240
|
-
targetVersion: "1.0",
|
|
241
|
-
bundleVersion: 20240722210327,
|
|
242
|
-
enabled: true,
|
|
243
|
-
},
|
|
244
|
-
];
|
|
245
|
-
|
|
246
|
-
const update = await checkForUpdate(updateSources);
|
|
247
|
-
expect(update).toStrictEqual({
|
|
248
|
-
bundleVersion: 20240722210327,
|
|
249
|
-
forceUpdate: false,
|
|
250
|
-
status: "UPDATE",
|
|
251
|
-
file: "20240722210327/ios/build.zip",
|
|
252
|
-
hash: "a5cbf59a627759a88d472c502423ff55a4f6cd1aafeed3536f6a5f6e870c2290",
|
|
253
|
-
});
|
|
254
|
-
});
|
|
255
|
-
});
|
|
256
|
-
|
|
257
|
-
describe("appVersion 1.0, bundleVersion v2", async () => {
|
|
258
|
-
beforeAll(() => {
|
|
259
|
-
vi.spyOn(natives, "getAppVersion").mockImplementation(async () => "1.0");
|
|
260
|
-
vi.spyOn(natives, "getBundleVersion").mockImplementation(async () => 2);
|
|
261
|
-
});
|
|
262
|
-
|
|
263
|
-
it("should return null if no update information is available", async () => {
|
|
264
|
-
const updateSources: UpdateSource[] = [];
|
|
265
|
-
|
|
266
|
-
const update = await checkForUpdate(updateSources);
|
|
267
|
-
expect(update).toBeNull();
|
|
268
|
-
});
|
|
269
|
-
|
|
270
|
-
it("should return null if no update is available when the app version is higher", async () => {
|
|
271
|
-
const updateSources: UpdateSource[] = [
|
|
272
|
-
{
|
|
273
|
-
platform: "ios",
|
|
274
|
-
targetVersion: "1.0",
|
|
275
|
-
file: "http://example.com/bundle.zip",
|
|
276
|
-
hash: "hash",
|
|
277
|
-
forceUpdate: false,
|
|
278
|
-
enabled: true,
|
|
279
|
-
bundleVersion: 2,
|
|
280
|
-
},
|
|
281
|
-
{
|
|
282
|
-
platform: "ios",
|
|
283
|
-
targetVersion: "1.0",
|
|
284
|
-
file: "http://example.com/bundle.zip",
|
|
285
|
-
hash: "hash",
|
|
286
|
-
forceUpdate: false,
|
|
287
|
-
enabled: true,
|
|
288
|
-
bundleVersion: 1,
|
|
289
|
-
},
|
|
290
|
-
];
|
|
291
|
-
|
|
292
|
-
const update = await checkForUpdate(updateSources);
|
|
293
|
-
expect(update).toBeNull();
|
|
294
|
-
});
|
|
295
|
-
|
|
296
|
-
it("should rollback if the latest bundle is deleted", async () => {
|
|
297
|
-
const updateSources: UpdateSource[] = [
|
|
298
|
-
{
|
|
299
|
-
platform: "ios",
|
|
300
|
-
targetVersion: "1.0",
|
|
301
|
-
file: "http://example.com/bundle.zip",
|
|
302
|
-
hash: "hash",
|
|
303
|
-
forceUpdate: false,
|
|
304
|
-
enabled: true,
|
|
305
|
-
bundleVersion: 1,
|
|
306
|
-
},
|
|
307
|
-
];
|
|
308
|
-
|
|
309
|
-
const update = await checkForUpdate(updateSources);
|
|
310
|
-
expect(update).toStrictEqual({
|
|
311
|
-
file: "http://example.com/bundle.zip",
|
|
312
|
-
hash: "hash",
|
|
313
|
-
bundleVersion: 1,
|
|
314
|
-
forceUpdate: true,
|
|
315
|
-
status: "ROLLBACK",
|
|
316
|
-
});
|
|
317
|
-
});
|
|
318
|
-
|
|
319
|
-
it("should update if a higher bundle version exists and forceUpdate is set to false", async () => {
|
|
320
|
-
const updateSources: UpdateSource[] = [
|
|
321
|
-
{
|
|
322
|
-
platform: "ios",
|
|
323
|
-
targetVersion: "1.0",
|
|
324
|
-
file: "http://example.com/bundle.zip",
|
|
325
|
-
hash: "hash",
|
|
326
|
-
forceUpdate: false,
|
|
327
|
-
enabled: true,
|
|
328
|
-
bundleVersion: 3,
|
|
329
|
-
},
|
|
330
|
-
{
|
|
331
|
-
platform: "ios",
|
|
332
|
-
targetVersion: "1.0",
|
|
333
|
-
file: "http://example.com/bundle.zip",
|
|
334
|
-
hash: "hash",
|
|
335
|
-
forceUpdate: false,
|
|
336
|
-
enabled: true,
|
|
337
|
-
bundleVersion: 2,
|
|
338
|
-
},
|
|
339
|
-
{
|
|
340
|
-
platform: "ios",
|
|
341
|
-
targetVersion: "1.0",
|
|
342
|
-
file: "http://example.com/bundle.zip",
|
|
343
|
-
hash: "hash",
|
|
344
|
-
forceUpdate: false,
|
|
345
|
-
enabled: true,
|
|
346
|
-
bundleVersion: 1,
|
|
347
|
-
},
|
|
348
|
-
];
|
|
349
|
-
|
|
350
|
-
const update = await checkForUpdate(updateSources);
|
|
351
|
-
expect(update).toStrictEqual({
|
|
352
|
-
file: "http://example.com/bundle.zip",
|
|
353
|
-
hash: "hash",
|
|
354
|
-
bundleVersion: 3,
|
|
355
|
-
forceUpdate: false,
|
|
356
|
-
status: "UPDATE",
|
|
357
|
-
});
|
|
358
|
-
});
|
|
359
|
-
|
|
360
|
-
it("should update even if the app version is the same and the bundle version is significantly higher", async () => {
|
|
361
|
-
const updateSources: UpdateSource[] = [
|
|
362
|
-
{
|
|
363
|
-
platform: "ios",
|
|
364
|
-
targetVersion: "1.0",
|
|
365
|
-
file: "http://example.com/bundle.zip",
|
|
366
|
-
hash: "hash",
|
|
367
|
-
forceUpdate: false,
|
|
368
|
-
enabled: true,
|
|
369
|
-
bundleVersion: 5, // Higher than the current version
|
|
370
|
-
},
|
|
371
|
-
{
|
|
372
|
-
platform: "ios",
|
|
373
|
-
targetVersion: "1.0",
|
|
374
|
-
file: "http://example.com/bundle.zip",
|
|
375
|
-
hash: "hash",
|
|
376
|
-
forceUpdate: false,
|
|
377
|
-
enabled: true,
|
|
378
|
-
bundleVersion: 4,
|
|
379
|
-
},
|
|
380
|
-
{
|
|
381
|
-
platform: "ios",
|
|
382
|
-
targetVersion: "1.0",
|
|
383
|
-
file: "http://example.com/bundle.zip",
|
|
384
|
-
hash: "hash",
|
|
385
|
-
forceUpdate: false,
|
|
386
|
-
enabled: true,
|
|
387
|
-
bundleVersion: 3,
|
|
388
|
-
},
|
|
389
|
-
{
|
|
390
|
-
platform: "ios",
|
|
391
|
-
targetVersion: "1.0",
|
|
392
|
-
file: "http://example.com/bundle.zip",
|
|
393
|
-
hash: "hash",
|
|
394
|
-
forceUpdate: false,
|
|
395
|
-
enabled: true,
|
|
396
|
-
bundleVersion: 2,
|
|
397
|
-
},
|
|
398
|
-
{
|
|
399
|
-
platform: "ios",
|
|
400
|
-
targetVersion: "1.0",
|
|
401
|
-
file: "http://example.com/bundle.zip",
|
|
402
|
-
hash: "hash",
|
|
403
|
-
forceUpdate: false,
|
|
404
|
-
enabled: true,
|
|
405
|
-
bundleVersion: 1,
|
|
406
|
-
},
|
|
407
|
-
];
|
|
408
|
-
|
|
409
|
-
const update = await checkForUpdate(updateSources);
|
|
410
|
-
expect(update).toStrictEqual({
|
|
411
|
-
file: "http://example.com/bundle.zip",
|
|
412
|
-
hash: "hash",
|
|
413
|
-
bundleVersion: 5,
|
|
414
|
-
forceUpdate: false,
|
|
415
|
-
status: "UPDATE",
|
|
416
|
-
});
|
|
417
|
-
});
|
|
418
|
-
|
|
419
|
-
it("should not update if the latest version is disabled and matches the current version", async () => {
|
|
420
|
-
const updateSources: UpdateSource[] = [
|
|
421
|
-
{
|
|
422
|
-
platform: "ios",
|
|
423
|
-
targetVersion: "1.0",
|
|
424
|
-
file: "http://example.com/bundle.zip",
|
|
425
|
-
hash: "hash",
|
|
426
|
-
forceUpdate: true,
|
|
427
|
-
enabled: false, // Disabled
|
|
428
|
-
bundleVersion: 3,
|
|
429
|
-
},
|
|
430
|
-
{
|
|
431
|
-
platform: "ios",
|
|
432
|
-
targetVersion: "1.0",
|
|
433
|
-
file: "http://example.com/bundle.zip",
|
|
434
|
-
hash: "hash",
|
|
435
|
-
forceUpdate: true,
|
|
436
|
-
enabled: true,
|
|
437
|
-
bundleVersion: 2,
|
|
438
|
-
},
|
|
439
|
-
{
|
|
440
|
-
platform: "ios",
|
|
441
|
-
targetVersion: "1.0",
|
|
442
|
-
file: "http://example.com/bundle.zip",
|
|
443
|
-
hash: "hash",
|
|
444
|
-
forceUpdate: false,
|
|
445
|
-
enabled: true,
|
|
446
|
-
bundleVersion: 1,
|
|
447
|
-
},
|
|
448
|
-
];
|
|
449
|
-
|
|
450
|
-
const update = await checkForUpdate(updateSources);
|
|
451
|
-
expect(update).toBeNull();
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
it("should rollback to a previous version if the current version is disabled", async () => {
|
|
455
|
-
const updateSources: UpdateSource[] = [
|
|
456
|
-
{
|
|
457
|
-
platform: "ios",
|
|
458
|
-
targetVersion: "1.0",
|
|
459
|
-
file: "http://example.com/bundle.zip",
|
|
460
|
-
hash: "hash",
|
|
461
|
-
forceUpdate: true,
|
|
462
|
-
enabled: false, // Disabled
|
|
463
|
-
bundleVersion: 2,
|
|
464
|
-
},
|
|
465
|
-
{
|
|
466
|
-
platform: "ios",
|
|
467
|
-
targetVersion: "1.0",
|
|
468
|
-
file: "http://example.com/bundle.zip",
|
|
469
|
-
hash: "hash",
|
|
470
|
-
forceUpdate: false,
|
|
471
|
-
enabled: true,
|
|
472
|
-
bundleVersion: 1,
|
|
473
|
-
},
|
|
474
|
-
];
|
|
475
|
-
|
|
476
|
-
const update = await checkForUpdate(updateSources);
|
|
477
|
-
expect(update).toStrictEqual({
|
|
478
|
-
file: "http://example.com/bundle.zip",
|
|
479
|
-
hash: "hash",
|
|
480
|
-
bundleVersion: 1,
|
|
481
|
-
forceUpdate: true, // Cause the app to reload
|
|
482
|
-
status: "ROLLBACK",
|
|
483
|
-
});
|
|
484
|
-
});
|
|
485
|
-
|
|
486
|
-
it("should rollback to the original bundle when receiving the latest bundle but all updates are disabled", async () => {
|
|
487
|
-
const updateSources: UpdateSource[] = [
|
|
488
|
-
{
|
|
489
|
-
platform: "ios",
|
|
490
|
-
targetVersion: "1.0",
|
|
491
|
-
file: "http://example.com/bundle.zip",
|
|
492
|
-
hash: "hash",
|
|
493
|
-
forceUpdate: true,
|
|
494
|
-
enabled: false, // Disabled
|
|
495
|
-
bundleVersion: 2,
|
|
496
|
-
},
|
|
497
|
-
{
|
|
498
|
-
platform: "ios",
|
|
499
|
-
targetVersion: "1.0",
|
|
500
|
-
file: "http://example.com/bundle.zip",
|
|
501
|
-
hash: "hash",
|
|
502
|
-
forceUpdate: false,
|
|
503
|
-
enabled: false, // Disabled
|
|
504
|
-
bundleVersion: 1,
|
|
505
|
-
},
|
|
506
|
-
];
|
|
507
|
-
|
|
508
|
-
const update = await checkForUpdate(updateSources);
|
|
509
|
-
expect(update).toStrictEqual({
|
|
510
|
-
file: null,
|
|
511
|
-
hash: null,
|
|
512
|
-
bundleVersion: 0,
|
|
513
|
-
forceUpdate: true, // Cause the app to reload
|
|
514
|
-
status: "ROLLBACK",
|
|
515
|
-
});
|
|
516
|
-
});
|
|
517
|
-
});
|
package/src/checkForUpdate.ts
DELETED
|
@@ -1,111 +0,0 @@
|
|
|
1
|
-
import type { UpdateSource, UpdateSourceArg } from "@hot-updater/utils";
|
|
2
|
-
import { filterTargetVersion } from "@hot-updater/utils";
|
|
3
|
-
import { Platform } from "react-native";
|
|
4
|
-
import { getAppVersion, getBundleVersion } from "./native";
|
|
5
|
-
import { isNullable } from "./utils";
|
|
6
|
-
export type UpdateStatus = "ROLLBACK" | "UPDATE";
|
|
7
|
-
|
|
8
|
-
const findLatestSources = (sources: UpdateSource[]) => {
|
|
9
|
-
return (
|
|
10
|
-
sources
|
|
11
|
-
?.filter((item) => item.enabled)
|
|
12
|
-
?.sort((a, b) => b.bundleVersion - a.bundleVersion)?.[0] ?? null
|
|
13
|
-
);
|
|
14
|
-
};
|
|
15
|
-
|
|
16
|
-
const checkForRollback = (
|
|
17
|
-
sources: UpdateSource[],
|
|
18
|
-
currentBundleVersion: number,
|
|
19
|
-
) => {
|
|
20
|
-
const enabled = sources?.find(
|
|
21
|
-
(item) => item.bundleVersion === currentBundleVersion,
|
|
22
|
-
)?.enabled;
|
|
23
|
-
const availableOldVersion = sources?.find(
|
|
24
|
-
(item) => item.bundleVersion < currentBundleVersion && item.enabled,
|
|
25
|
-
)?.enabled;
|
|
26
|
-
|
|
27
|
-
if (isNullable(enabled)) {
|
|
28
|
-
return availableOldVersion;
|
|
29
|
-
}
|
|
30
|
-
return !enabled;
|
|
31
|
-
};
|
|
32
|
-
|
|
33
|
-
const ensureUpdateSource = async (updateSource: UpdateSourceArg) => {
|
|
34
|
-
let source: UpdateSource[] | null = null;
|
|
35
|
-
if (typeof updateSource === "string") {
|
|
36
|
-
if (updateSource.startsWith("http")) {
|
|
37
|
-
const response = await fetch(updateSource);
|
|
38
|
-
source = (await response.json()) as UpdateSource[];
|
|
39
|
-
}
|
|
40
|
-
} else if (typeof updateSource === "function") {
|
|
41
|
-
source = await updateSource();
|
|
42
|
-
} else {
|
|
43
|
-
source = updateSource;
|
|
44
|
-
}
|
|
45
|
-
if (!source) {
|
|
46
|
-
throw new Error("Invalid source");
|
|
47
|
-
}
|
|
48
|
-
return source;
|
|
49
|
-
};
|
|
50
|
-
|
|
51
|
-
export const checkForUpdate = async (updateSources: UpdateSourceArg) => {
|
|
52
|
-
const sources = await ensureUpdateSource(updateSources);
|
|
53
|
-
|
|
54
|
-
const currentAppVersion = await getAppVersion();
|
|
55
|
-
const platform = Platform.OS as "ios" | "android";
|
|
56
|
-
|
|
57
|
-
const appVersionSources = currentAppVersion
|
|
58
|
-
? filterTargetVersion(sources, currentAppVersion, platform)
|
|
59
|
-
: [];
|
|
60
|
-
const currentBundleVersion = await getBundleVersion();
|
|
61
|
-
|
|
62
|
-
const isRollback = checkForRollback(appVersionSources, currentBundleVersion);
|
|
63
|
-
const latestSource = await findLatestSources(appVersionSources);
|
|
64
|
-
|
|
65
|
-
if (!latestSource) {
|
|
66
|
-
if (isRollback) {
|
|
67
|
-
return {
|
|
68
|
-
bundleVersion: 0,
|
|
69
|
-
forceUpdate: true,
|
|
70
|
-
file: null,
|
|
71
|
-
hash: null,
|
|
72
|
-
status: "ROLLBACK" as UpdateStatus,
|
|
73
|
-
};
|
|
74
|
-
}
|
|
75
|
-
return null;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
if (latestSource.file)
|
|
79
|
-
if (isRollback) {
|
|
80
|
-
if (latestSource.bundleVersion === currentBundleVersion) {
|
|
81
|
-
return null;
|
|
82
|
-
}
|
|
83
|
-
if (latestSource.bundleVersion > currentBundleVersion) {
|
|
84
|
-
return {
|
|
85
|
-
bundleVersion: latestSource.bundleVersion,
|
|
86
|
-
forceUpdate: latestSource.forceUpdate,
|
|
87
|
-
file: latestSource.file,
|
|
88
|
-
hash: latestSource.hash,
|
|
89
|
-
status: "UPDATE" as UpdateStatus,
|
|
90
|
-
};
|
|
91
|
-
}
|
|
92
|
-
return {
|
|
93
|
-
bundleVersion: latestSource.bundleVersion,
|
|
94
|
-
forceUpdate: true,
|
|
95
|
-
file: latestSource.file,
|
|
96
|
-
hash: latestSource.hash,
|
|
97
|
-
status: "ROLLBACK" as UpdateStatus,
|
|
98
|
-
};
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
if (latestSource.bundleVersion > currentBundleVersion) {
|
|
102
|
-
return {
|
|
103
|
-
bundleVersion: latestSource.bundleVersion,
|
|
104
|
-
forceUpdate: latestSource.forceUpdate,
|
|
105
|
-
file: latestSource.file,
|
|
106
|
-
hash: latestSource.hash,
|
|
107
|
-
status: "UPDATE" as UpdateStatus,
|
|
108
|
-
};
|
|
109
|
-
}
|
|
110
|
-
return null;
|
|
111
|
-
};
|
package/src/utils.ts
DELETED