react-native-update 8.1.0 → 9.0.0-beta.1
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/.github/workflows/e2e_android.yml +49 -0
- package/.github/workflows/e2e_ios.yml +182 -0
- package/.github/workflows/scripts/adb_all_emulators.sh +10 -0
- package/.github/workflows/scripts/database.rules +13 -0
- package/.github/workflows/scripts/firebase.json +39 -0
- package/.github/workflows/scripts/firestore.indexes.json +72 -0
- package/.github/workflows/scripts/firestore.rules +17 -0
- package/.github/workflows/scripts/functions/package.json +24 -0
- package/.github/workflows/scripts/functions/src/exports.ts +13 -0
- package/.github/workflows/scripts/functions/src/index.ts +12 -0
- package/.github/workflows/scripts/functions/src/sample-data.ts +80 -0
- package/.github/workflows/scripts/functions/src/testFunctionCustomRegion.ts +14 -0
- package/.github/workflows/scripts/functions/src/testFunctionDefaultRegion.ts +70 -0
- package/.github/workflows/scripts/functions/tsconfig.json +16 -0
- package/.github/workflows/scripts/start-firebase-emulator.bat +6 -0
- package/.github/workflows/scripts/start-firebase-emulator.sh +44 -0
- package/.github/workflows/scripts/storage.rules +21 -0
- package/README.md +8 -6
- package/android/build.gradle +22 -0
- package/android/jni/hpatch.c +4 -4
- package/android/jni/hpatch.h +3 -3
- package/android/src/main/java/cn/reactnative/modules/update/DownloadTaskParams.java +0 -2
- package/android/src/main/java/cn/reactnative/modules/update/UpdateModuleImpl.java +265 -0
- package/android/src/main/java/cn/reactnative/modules/update/UpdatePackage.java +31 -20
- package/android/src/newarch/cn/reactnative/modules/update/UpdateModule.java +147 -0
- package/android/src/{main/java → oldarch}/cn/reactnative/modules/update/UpdateModule.java +6 -2
- package/e2e/jest.config.js +12 -0
- package/e2e/starter.test.js +23 -0
- package/ios/RCTPushy/{RCTPushy.m → RCTPushy.mm} +116 -44
- package/ios/pushy_build_time.txt +1 -1
- package/lib/NativeUpdate.js +51 -0
- package/lib/{endpoint.js → endpoint.ts} +22 -12
- package/lib/index.web.js +1 -0
- package/lib/{main.js → main.ts} +122 -71
- package/lib/{simpleUpdate.js → simpleUpdate.tsx} +13 -4
- package/lib/type.ts +70 -0
- package/package.json +37 -3
- package/react-native-update.podspec +20 -2
- package/lib/index.d.ts +0 -94
- /package/ios/RCTPushy/HDiffPatch/{HDiffPatch.m → HDiffPatch.mm} +0 -0
- /package/ios/RCTPushy/{RCTPushyDownloader.m → RCTPushyDownloader.mm} +0 -0
- /package/ios/RCTPushy/{RCTPushyManager.m → RCTPushyManager.mm} +0 -0
- /package/lib/{index.js → index.ts} +0 -0
package/lib/{main.js → main.ts}
RENAMED
|
@@ -2,7 +2,6 @@ import {
|
|
|
2
2
|
tryBackupEndpoints,
|
|
3
3
|
getCheckUrl,
|
|
4
4
|
setCustomEndpoints,
|
|
5
|
-
getReportUrl,
|
|
6
5
|
} from './endpoint';
|
|
7
6
|
import {
|
|
8
7
|
NativeEventEmitter,
|
|
@@ -10,82 +9,114 @@ import {
|
|
|
10
9
|
Platform,
|
|
11
10
|
PermissionsAndroid,
|
|
12
11
|
} from 'react-native';
|
|
12
|
+
import {
|
|
13
|
+
EventType,
|
|
14
|
+
ProgressData,
|
|
15
|
+
UpdateAvailableResult,
|
|
16
|
+
UpdateEventsListener,
|
|
17
|
+
} from './type';
|
|
13
18
|
export { setCustomEndpoints };
|
|
14
19
|
const {
|
|
15
20
|
version: v,
|
|
16
21
|
} = require('react-native/Libraries/Core/ReactNativeVersion');
|
|
17
22
|
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
|
23
|
+
const isTurboModuleEnabled = global.__turboModuleProxy != null;
|
|
18
24
|
|
|
19
|
-
|
|
25
|
+
export const PushyModule = isTurboModuleEnabled
|
|
26
|
+
? require('./NativeUpdate').default
|
|
27
|
+
: NativeModules.Pushy;
|
|
20
28
|
|
|
21
|
-
if (!
|
|
29
|
+
if (!PushyModule) {
|
|
22
30
|
throw new Error('react-native-update模块无法加载,请对照安装文档检查配置。');
|
|
23
31
|
}
|
|
32
|
+
const PushyConstants = isTurboModuleEnabled
|
|
33
|
+
? PushyModule.getConstants()
|
|
34
|
+
: PushyModule;
|
|
24
35
|
|
|
25
|
-
export const downloadRootDir =
|
|
26
|
-
export const packageVersion =
|
|
27
|
-
export const currentVersion =
|
|
28
|
-
export const isFirstTime =
|
|
29
|
-
const rolledBackVersion =
|
|
36
|
+
export const downloadRootDir = PushyConstants.downloadRootDir;
|
|
37
|
+
export const packageVersion = PushyConstants.packageVersion;
|
|
38
|
+
export const currentVersion = PushyConstants.currentVersion;
|
|
39
|
+
export const isFirstTime = PushyConstants.isFirstTime;
|
|
40
|
+
const rolledBackVersion = PushyConstants.rolledBackVersion;
|
|
30
41
|
export const isRolledBack = typeof rolledBackVersion === 'string';
|
|
31
42
|
|
|
32
|
-
export const buildTime =
|
|
33
|
-
let blockUpdate =
|
|
34
|
-
let uuid =
|
|
43
|
+
export const buildTime = PushyConstants.buildTime;
|
|
44
|
+
let blockUpdate = PushyConstants.blockUpdate;
|
|
45
|
+
let uuid = PushyConstants.uuid;
|
|
35
46
|
|
|
36
|
-
if (Platform.OS === 'android' && !
|
|
47
|
+
if (Platform.OS === 'android' && !PushyConstants.isUsingBundleUrl) {
|
|
37
48
|
throw new Error(
|
|
38
49
|
'react-native-update模块无法加载,请对照文档检查Bundle URL的配置',
|
|
39
50
|
);
|
|
40
51
|
}
|
|
41
52
|
|
|
42
|
-
function setLocalHashInfo(hash, info) {
|
|
43
|
-
|
|
53
|
+
function setLocalHashInfo(hash: string, info: Record<string, any>) {
|
|
54
|
+
PushyModule.setLocalHashInfo(hash, JSON.stringify(info));
|
|
44
55
|
}
|
|
45
56
|
|
|
46
|
-
async function getLocalHashInfo(hash) {
|
|
47
|
-
return JSON.parse(await
|
|
57
|
+
async function getLocalHashInfo(hash: string) {
|
|
58
|
+
return JSON.parse(await PushyModule.getLocalHashInfo(hash));
|
|
48
59
|
}
|
|
49
60
|
|
|
50
|
-
export async function getCurrentVersionInfo() {
|
|
61
|
+
export async function getCurrentVersionInfo(): Promise<{
|
|
62
|
+
name?: string;
|
|
63
|
+
description?: string;
|
|
64
|
+
metaInfo?: string;
|
|
65
|
+
}> {
|
|
51
66
|
return currentVersion ? (await getLocalHashInfo(currentVersion)) || {} : {};
|
|
52
67
|
}
|
|
53
68
|
|
|
54
|
-
const eventEmitter = new NativeEventEmitter(
|
|
69
|
+
const eventEmitter = new NativeEventEmitter(PushyModule);
|
|
55
70
|
|
|
56
71
|
if (!uuid) {
|
|
57
72
|
uuid = require('nanoid/non-secure').nanoid();
|
|
58
|
-
|
|
73
|
+
PushyModule.setUuid(uuid);
|
|
59
74
|
}
|
|
60
75
|
|
|
61
|
-
function logger(
|
|
62
|
-
console.log(
|
|
76
|
+
function logger(...args: string[]) {
|
|
77
|
+
console.log('Pushy: ', ...args);
|
|
63
78
|
}
|
|
64
79
|
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
80
|
+
const noop = () => {};
|
|
81
|
+
let reporter: UpdateEventsListener = noop;
|
|
82
|
+
|
|
83
|
+
export function onEvents(customReporter: UpdateEventsListener) {
|
|
84
|
+
reporter = customReporter;
|
|
85
|
+
if (isRolledBack) {
|
|
86
|
+
report({
|
|
87
|
+
type: 'rollback',
|
|
88
|
+
data: {
|
|
89
|
+
rolledBackVersion,
|
|
90
|
+
},
|
|
91
|
+
});
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
function report({
|
|
96
|
+
type,
|
|
97
|
+
message = '',
|
|
98
|
+
data = {},
|
|
99
|
+
}: {
|
|
100
|
+
type: EventType;
|
|
101
|
+
message?: string;
|
|
102
|
+
data?: Record<string, string | number>;
|
|
103
|
+
}) {
|
|
104
|
+
logger(type + ' ' + message);
|
|
105
|
+
reporter({
|
|
106
|
+
type,
|
|
107
|
+
data: {
|
|
108
|
+
currentVersion,
|
|
76
109
|
cInfo,
|
|
77
110
|
packageVersion,
|
|
78
111
|
buildTime,
|
|
79
|
-
|
|
80
|
-
|
|
112
|
+
message,
|
|
113
|
+
...data,
|
|
114
|
+
},
|
|
115
|
+
});
|
|
81
116
|
}
|
|
82
117
|
|
|
83
118
|
logger('uuid: ' + uuid);
|
|
84
119
|
|
|
85
|
-
if (isRolledBack) {
|
|
86
|
-
report(rolledBackVersion, 'rollback');
|
|
87
|
-
}
|
|
88
|
-
|
|
89
120
|
export const cInfo = {
|
|
90
121
|
pushy: require('../package.json').version,
|
|
91
122
|
rn: RNVersion,
|
|
@@ -94,13 +125,14 @@ export const cInfo = {
|
|
|
94
125
|
};
|
|
95
126
|
|
|
96
127
|
function assertRelease() {
|
|
128
|
+
// @ts-expect-error
|
|
97
129
|
if (__DEV__) {
|
|
98
130
|
throw new Error('react-native-update 只能在 RELEASE 版本中运行.');
|
|
99
131
|
}
|
|
100
132
|
}
|
|
101
133
|
|
|
102
134
|
let checkingThrottling = false;
|
|
103
|
-
export async function checkUpdate(APPKEY, isRetry) {
|
|
135
|
+
export async function checkUpdate(APPKEY: string, isRetry?: boolean) {
|
|
104
136
|
assertRelease();
|
|
105
137
|
if (checkingThrottling) {
|
|
106
138
|
logger('repeated checking, ignored');
|
|
@@ -111,16 +143,14 @@ export async function checkUpdate(APPKEY, isRetry) {
|
|
|
111
143
|
checkingThrottling = false;
|
|
112
144
|
}, 3000);
|
|
113
145
|
if (blockUpdate && blockUpdate.until > Date.now() / 1000) {
|
|
114
|
-
|
|
115
|
-
|
|
146
|
+
return report({
|
|
147
|
+
type: 'errorChecking',
|
|
148
|
+
message: `热更新已暂停,原因:${blockUpdate.reason}。请在"${new Date(
|
|
116
149
|
blockUpdate.until * 1000,
|
|
117
150
|
).toLocaleString()}"之后重试。`,
|
|
118
|
-
);
|
|
119
|
-
}
|
|
120
|
-
if (typeof APPKEY !== 'string') {
|
|
121
|
-
throw new Error('未检查到合法的APPKEY,请查看update.json文件是否正确生成');
|
|
151
|
+
});
|
|
122
152
|
}
|
|
123
|
-
|
|
153
|
+
report({ type: 'checking' });
|
|
124
154
|
let resp;
|
|
125
155
|
try {
|
|
126
156
|
resp = await fetch(getCheckUrl(APPKEY), {
|
|
@@ -138,7 +168,10 @@ export async function checkUpdate(APPKEY, isRetry) {
|
|
|
138
168
|
});
|
|
139
169
|
} catch (e) {
|
|
140
170
|
if (isRetry) {
|
|
141
|
-
|
|
171
|
+
return report({
|
|
172
|
+
type: 'errorChecking',
|
|
173
|
+
message: '无法连接更新服务器,请检查网络连接后重试',
|
|
174
|
+
});
|
|
142
175
|
}
|
|
143
176
|
await tryBackupEndpoints();
|
|
144
177
|
return checkUpdate(APPKEY, true);
|
|
@@ -147,13 +180,15 @@ export async function checkUpdate(APPKEY, isRetry) {
|
|
|
147
180
|
checkOperation(result.op);
|
|
148
181
|
|
|
149
182
|
if (resp.status !== 200) {
|
|
150
|
-
|
|
183
|
+
return report({ type: 'errorChecking', message: result.message });
|
|
151
184
|
}
|
|
152
185
|
|
|
153
186
|
return result;
|
|
154
187
|
}
|
|
155
188
|
|
|
156
|
-
function checkOperation(
|
|
189
|
+
function checkOperation(
|
|
190
|
+
op: { type: string; reason: string; duration: number }[],
|
|
191
|
+
) {
|
|
157
192
|
if (!Array.isArray(op)) {
|
|
158
193
|
return;
|
|
159
194
|
}
|
|
@@ -163,14 +198,19 @@ function checkOperation(op) {
|
|
|
163
198
|
reason: action.reason,
|
|
164
199
|
until: Math.round((Date.now() + action.duration) / 1000),
|
|
165
200
|
};
|
|
166
|
-
|
|
201
|
+
PushyModule.setBlockUpdate(blockUpdate);
|
|
167
202
|
}
|
|
168
203
|
});
|
|
169
204
|
}
|
|
170
205
|
|
|
171
206
|
let downloadingThrottling = false;
|
|
172
|
-
let downloadedHash;
|
|
173
|
-
export async function downloadUpdate(
|
|
207
|
+
let downloadedHash: string;
|
|
208
|
+
export async function downloadUpdate(
|
|
209
|
+
options: UpdateAvailableResult,
|
|
210
|
+
eventListeners?: {
|
|
211
|
+
onDownloadProgress?: (data: ProgressData) => void;
|
|
212
|
+
},
|
|
213
|
+
) {
|
|
174
214
|
assertRelease();
|
|
175
215
|
if (!options.update) {
|
|
176
216
|
return;
|
|
@@ -206,10 +246,11 @@ export async function downloadUpdate(options, eventListeners) {
|
|
|
206
246
|
}
|
|
207
247
|
}
|
|
208
248
|
let succeeded = false;
|
|
249
|
+
report({ type: 'downloading' });
|
|
209
250
|
if (options.diffUrl) {
|
|
210
251
|
logger('downloading diff');
|
|
211
252
|
try {
|
|
212
|
-
await
|
|
253
|
+
await PushyModule.downloadPatchFromPpk({
|
|
213
254
|
updateUrl: options.diffUrl,
|
|
214
255
|
hash: options.hash,
|
|
215
256
|
originHash: currentVersion,
|
|
@@ -222,7 +263,7 @@ export async function downloadUpdate(options, eventListeners) {
|
|
|
222
263
|
if (!succeeded && options.pdiffUrl) {
|
|
223
264
|
logger('downloading pdiff');
|
|
224
265
|
try {
|
|
225
|
-
await
|
|
266
|
+
await PushyModule.downloadPatchFromPackage({
|
|
226
267
|
updateUrl: options.pdiffUrl,
|
|
227
268
|
hash: options.hash,
|
|
228
269
|
});
|
|
@@ -234,7 +275,7 @@ export async function downloadUpdate(options, eventListeners) {
|
|
|
234
275
|
if (!succeeded && options.updateUrl) {
|
|
235
276
|
logger('downloading full patch');
|
|
236
277
|
try {
|
|
237
|
-
await
|
|
278
|
+
await PushyModule.downloadFullUpdate({
|
|
238
279
|
updateUrl: options.updateUrl,
|
|
239
280
|
hash: options.hash,
|
|
240
281
|
});
|
|
@@ -245,8 +286,7 @@ export async function downloadUpdate(options, eventListeners) {
|
|
|
245
286
|
}
|
|
246
287
|
progressHandler && progressHandler.remove();
|
|
247
288
|
if (!succeeded) {
|
|
248
|
-
report(options.hash
|
|
249
|
-
throw new Error('all update attempts failed');
|
|
289
|
+
return report({ type: 'errorUpdate', data: { newVersion: options.hash } });
|
|
250
290
|
}
|
|
251
291
|
setLocalHashInfo(options.hash, {
|
|
252
292
|
name: options.name,
|
|
@@ -257,7 +297,7 @@ export async function downloadUpdate(options, eventListeners) {
|
|
|
257
297
|
return options.hash;
|
|
258
298
|
}
|
|
259
299
|
|
|
260
|
-
function assertHash(hash) {
|
|
300
|
+
function assertHash(hash: string) {
|
|
261
301
|
if (!downloadedHash) {
|
|
262
302
|
logger(`no downloaded hash`);
|
|
263
303
|
return;
|
|
@@ -269,19 +309,19 @@ function assertHash(hash) {
|
|
|
269
309
|
return true;
|
|
270
310
|
}
|
|
271
311
|
|
|
272
|
-
export function switchVersion(hash) {
|
|
312
|
+
export function switchVersion(hash: string) {
|
|
273
313
|
assertRelease();
|
|
274
314
|
if (assertHash(hash)) {
|
|
275
315
|
logger('switchVersion: ' + hash);
|
|
276
|
-
|
|
316
|
+
PushyModule.reloadUpdate({ hash });
|
|
277
317
|
}
|
|
278
318
|
}
|
|
279
319
|
|
|
280
|
-
export function switchVersionLater(hash) {
|
|
320
|
+
export function switchVersionLater(hash: string) {
|
|
281
321
|
assertRelease();
|
|
282
322
|
if (assertHash(hash)) {
|
|
283
323
|
logger('switchVersionLater: ' + hash);
|
|
284
|
-
|
|
324
|
+
PushyModule.setNeedUpdate({ hash });
|
|
285
325
|
}
|
|
286
326
|
}
|
|
287
327
|
|
|
@@ -293,22 +333,31 @@ export function markSuccess() {
|
|
|
293
333
|
return;
|
|
294
334
|
}
|
|
295
335
|
marked = true;
|
|
296
|
-
|
|
297
|
-
report(
|
|
336
|
+
PushyModule.markSuccess();
|
|
337
|
+
report({ type: 'markSuccess' });
|
|
298
338
|
}
|
|
299
339
|
|
|
300
|
-
export async function downloadAndInstallApk({
|
|
301
|
-
|
|
302
|
-
|
|
340
|
+
export async function downloadAndInstallApk({
|
|
341
|
+
url,
|
|
342
|
+
onDownloadProgress,
|
|
343
|
+
}: {
|
|
344
|
+
url: string;
|
|
345
|
+
onDownloadProgress?: (data: ProgressData) => void;
|
|
346
|
+
}) {
|
|
347
|
+
if (Platform.OS !== 'android') {
|
|
348
|
+
return;
|
|
349
|
+
}
|
|
350
|
+
report({ type: 'downloadingApk' });
|
|
351
|
+
if (Platform.Version <= 23) {
|
|
303
352
|
try {
|
|
304
353
|
const granted = await PermissionsAndroid.request(
|
|
305
354
|
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
|
|
306
355
|
);
|
|
307
356
|
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
|
308
|
-
return;
|
|
357
|
+
return report({ type: 'rejectStoragePermission' });
|
|
309
358
|
}
|
|
310
359
|
} catch (err) {
|
|
311
|
-
|
|
360
|
+
return report({ type: 'errorStoragePermission' });
|
|
312
361
|
}
|
|
313
362
|
}
|
|
314
363
|
let hash = Date.now().toString();
|
|
@@ -316,17 +365,19 @@ export async function downloadAndInstallApk({ url, onDownloadProgress }) {
|
|
|
316
365
|
if (onDownloadProgress) {
|
|
317
366
|
progressHandler = eventEmitter.addListener(
|
|
318
367
|
'RCTPushyDownloadProgress',
|
|
319
|
-
(progressData) => {
|
|
368
|
+
(progressData: ProgressData) => {
|
|
320
369
|
if (progressData.hash === hash) {
|
|
321
370
|
onDownloadProgress(progressData);
|
|
322
371
|
}
|
|
323
372
|
},
|
|
324
373
|
);
|
|
325
374
|
}
|
|
326
|
-
await
|
|
375
|
+
await PushyModule.downloadAndInstallApk({
|
|
327
376
|
url,
|
|
328
377
|
target: 'update.apk',
|
|
329
378
|
hash,
|
|
379
|
+
}).catch(() => {
|
|
380
|
+
report({ type: 'errowDownloadAndInstallApk' });
|
|
330
381
|
});
|
|
331
382
|
progressHandler && progressHandler.remove();
|
|
332
383
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import React, {
|
|
1
|
+
import React, { PureComponent } from 'react';
|
|
2
2
|
import { Platform, Alert, Linking, AppState } from 'react-native';
|
|
3
3
|
|
|
4
4
|
import {
|
|
@@ -10,16 +10,25 @@ import {
|
|
|
10
10
|
switchVersionLater,
|
|
11
11
|
markSuccess,
|
|
12
12
|
downloadAndInstallApk,
|
|
13
|
+
onEvents,
|
|
13
14
|
} from './main';
|
|
15
|
+
import { UpdateEventsListener } from './type';
|
|
14
16
|
|
|
15
|
-
export function simpleUpdate(
|
|
16
|
-
|
|
17
|
+
export function simpleUpdate(
|
|
18
|
+
WrappedComponent: JSX.Element,
|
|
19
|
+
options: { appKey?: string; onEvents?: UpdateEventsListener } = {},
|
|
20
|
+
) {
|
|
21
|
+
const { appKey, onEvents: eventListeners } = options;
|
|
17
22
|
if (!appKey) {
|
|
18
23
|
throw new Error('appKey is required for simpleUpdate()');
|
|
19
24
|
}
|
|
25
|
+
if (typeof eventListeners === 'function') {
|
|
26
|
+
onEvents(eventListeners);
|
|
27
|
+
}
|
|
28
|
+
// @ts-expect-error
|
|
20
29
|
return __DEV__
|
|
21
30
|
? WrappedComponent
|
|
22
|
-
: class AppUpdate extends
|
|
31
|
+
: class AppUpdate extends PureComponent {
|
|
23
32
|
componentDidMount() {
|
|
24
33
|
if (isRolledBack) {
|
|
25
34
|
Alert.alert('抱歉', '刚刚更新遭遇错误,已为您恢复到更新前版本');
|
package/lib/type.ts
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
export interface ExpiredResult {
|
|
2
|
+
upToDate?: false;
|
|
3
|
+
expired: true;
|
|
4
|
+
downloadUrl: string;
|
|
5
|
+
}
|
|
6
|
+
|
|
7
|
+
export interface UpTodateResult {
|
|
8
|
+
expired?: false;
|
|
9
|
+
upToDate: true;
|
|
10
|
+
paused?: 'app' | 'package';
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
export interface UpdateAvailableResult {
|
|
14
|
+
expired?: false;
|
|
15
|
+
upToDate?: false;
|
|
16
|
+
update: true;
|
|
17
|
+
name: string; // version name
|
|
18
|
+
hash: string;
|
|
19
|
+
description: string;
|
|
20
|
+
metaInfo: string;
|
|
21
|
+
pdiffUrl: string;
|
|
22
|
+
diffUrl?: string;
|
|
23
|
+
updateUrl?: string;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
export type CheckResult =
|
|
27
|
+
| ExpiredResult
|
|
28
|
+
| UpTodateResult
|
|
29
|
+
| UpdateAvailableResult;
|
|
30
|
+
|
|
31
|
+
export interface ProgressData {
|
|
32
|
+
hash: string;
|
|
33
|
+
received: number;
|
|
34
|
+
total: number;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
export type EventType =
|
|
38
|
+
| 'rollback'
|
|
39
|
+
| 'errorChecking'
|
|
40
|
+
| 'checking'
|
|
41
|
+
| 'downloading'
|
|
42
|
+
| 'errorUpdate'
|
|
43
|
+
| 'markSuccess'
|
|
44
|
+
| 'downloadingApk'
|
|
45
|
+
| 'rejectStoragePermission'
|
|
46
|
+
| 'errorStoragePermission'
|
|
47
|
+
| 'errowDownloadAndInstallApk';
|
|
48
|
+
|
|
49
|
+
export interface EventData {
|
|
50
|
+
currentVersion: string;
|
|
51
|
+
cInfo: {
|
|
52
|
+
pushy: string;
|
|
53
|
+
rn: string;
|
|
54
|
+
os: string;
|
|
55
|
+
uuid: string;
|
|
56
|
+
};
|
|
57
|
+
packageVersion: string;
|
|
58
|
+
buildTime: number;
|
|
59
|
+
message?: string;
|
|
60
|
+
rolledBackVersion?: string;
|
|
61
|
+
newVersion?: string;
|
|
62
|
+
[key: string]: any;
|
|
63
|
+
}
|
|
64
|
+
export type UpdateEventsListener = ({
|
|
65
|
+
type,
|
|
66
|
+
data,
|
|
67
|
+
}: {
|
|
68
|
+
type: EventType;
|
|
69
|
+
data: EventData;
|
|
70
|
+
}) => void;
|
package/package.json
CHANGED
|
@@ -1,13 +1,27 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "9.0.0-beta.1",
|
|
4
4
|
"description": "react-native hot update",
|
|
5
|
-
"main": "lib/index.
|
|
5
|
+
"main": "lib/index.ts",
|
|
6
6
|
"scripts": {
|
|
7
7
|
"prepublish": "yarn submodule",
|
|
8
8
|
"submodule": "git submodule update --init --recursive",
|
|
9
9
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
|
-
"build-lib": "yarn submodule && $ANDROID_HOME/ndk/20.1.5948944/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib"
|
|
10
|
+
"build-lib": "yarn submodule && $ANDROID_HOME/ndk/20.1.5948944/ndk-build NDK_PROJECT_PATH=android APP_BUILD_SCRIPT=android/jni/Android.mk NDK_APPLICATION_MK=android/jni/Application.mk NDK_LIBS_OUT=android/lib",
|
|
11
|
+
"build:ios-debug": "cd Example/testHotUpdate && yarn && detox build --configuration ios.sim.debug",
|
|
12
|
+
"build:ios-release": "cd Example/testHotUpdate && yarn && detox build --configuration ios.sim.release",
|
|
13
|
+
"test:ios-debug": "cd Example/testHotUpdate && detox test --configuration ios.sim.debug",
|
|
14
|
+
"test:ios-release": "cd Example/testHotUpdate && yarn detox test --configuration ios.sim.release",
|
|
15
|
+
"build:android-debug": "cd Example/testHotUpdate && yarn && detox build --configuration android.emu.debug",
|
|
16
|
+
"build:android-release": "cd Example/testHotUpdate && yarn && detox build --configuration android.emu.release",
|
|
17
|
+
"test:android-release": "cd Example/testHotUpdate && yarn detox test --configuration android.emu.release --headless --record-logs all",
|
|
18
|
+
"test:android-debug": "cd Example/testHotUpdate && detox test --configuration android.emu.debug --headless --record-logs all",
|
|
19
|
+
"e2e:ios": "npm run build:ios-release && npm run test:ios-release",
|
|
20
|
+
"e2e:android": "npm run build:android-release && npm run test:android-release",
|
|
21
|
+
"tests:emulator:prepare": "cd .github/workflows/scripts/functions && yarn && yarn build",
|
|
22
|
+
"tests:emulator:start-ci": "yarn tests:emulator:prepare && cd ./.github/workflows/scripts && ./start-firebase-emulator.sh",
|
|
23
|
+
"tests:packager:jet-ci": "cd Example/testHotUpdate && cross-env TMPDIR=$HOME/.metro REACT_DEBUGGER=\"echo nope\" node_modules/.bin/react-native start --no-interactive",
|
|
24
|
+
"tests:ios:pod:install": "cd Example/testHotUpdate && yarn && yarn pod-install"
|
|
11
25
|
},
|
|
12
26
|
"repository": {
|
|
13
27
|
"type": "git",
|
|
@@ -30,5 +44,25 @@
|
|
|
30
44
|
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
|
|
31
45
|
"dependencies": {
|
|
32
46
|
"nanoid": "^3.3.3"
|
|
47
|
+
},
|
|
48
|
+
"codegenConfig": {
|
|
49
|
+
"libraries": [
|
|
50
|
+
{
|
|
51
|
+
"name": "RCTPushySpec",
|
|
52
|
+
"type": "modules",
|
|
53
|
+
"jsSrcsDir": "lib"
|
|
54
|
+
}
|
|
55
|
+
]
|
|
56
|
+
},
|
|
57
|
+
"devDependencies": {
|
|
58
|
+
"@types/fs-extra": "^9.0.13",
|
|
59
|
+
"@types/jest": "^29.2.1",
|
|
60
|
+
"detox": "^20.5.0",
|
|
61
|
+
"firebase-tools": "^11.24.1",
|
|
62
|
+
"fs-extra": "^9.1.0",
|
|
63
|
+
"jest": "^29.2.1",
|
|
64
|
+
"pod-install": "^0.1.37",
|
|
65
|
+
"ts-jest": "^29.0.3",
|
|
66
|
+
"typescript": "^4.1.3"
|
|
33
67
|
}
|
|
34
68
|
}
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
require 'json'
|
|
2
2
|
|
|
3
3
|
package = JSON.parse(File.read(File.join(__dir__, 'package.json')))
|
|
4
|
-
|
|
4
|
+
folly_version = '2021.06.28.00-v2'
|
|
5
|
+
folly_compiler_flags = '-DFOLLY_NO_CONFIG -DFOLLY_MOBILE=1 -DFOLLY_USE_LIBCPP=1 -Wno-comma -Wno-shorten-64-to-32'
|
|
5
6
|
Pod::Spec.new do |s|
|
|
6
7
|
s.name = package['name']
|
|
7
8
|
s.version = package['version']
|
|
@@ -13,7 +14,9 @@ Pod::Spec.new do |s|
|
|
|
13
14
|
|
|
14
15
|
s.cocoapods_version = '>= 1.6.0'
|
|
15
16
|
s.platform = :ios, "8.0"
|
|
17
|
+
s.platforms = { :ios => "11.0" }
|
|
16
18
|
s.source = { :git => 'https://github.com/reactnativecn/react-native-pushy.git', :tag => '#{s.version}' }
|
|
19
|
+
s.source_files = "ios/**/*.{h,m,mm,swift}"
|
|
17
20
|
s.libraries = 'bz2', 'z'
|
|
18
21
|
s.vendored_libraries = 'RCTPushy/libRCTPushy.a'
|
|
19
22
|
s.pod_target_xcconfig = { 'USER_HEADER_SEARCH_PATHS' => '"$(SRCROOT)/../node_modules/react-native-update/ios"' }
|
|
@@ -21,10 +24,11 @@ Pod::Spec.new do |s|
|
|
|
21
24
|
s.script_phase = { :name => 'Generate build time', :script => 'set -x;date +%s > ${PODS_ROOT}/../../node_modules/react-native-update/ios/pushy_build_time.txt', :execution_position => :before_compile }
|
|
22
25
|
|
|
23
26
|
s.dependency 'React'
|
|
27
|
+
s.dependency "React-Core"
|
|
24
28
|
s.dependency 'SSZipArchive'
|
|
25
29
|
|
|
26
30
|
s.subspec 'RCTPushy' do |ss|
|
|
27
|
-
ss.source_files = 'ios/RCTPushy/*.{h,m}'
|
|
31
|
+
ss.source_files = 'ios/RCTPushy/*.{h,m,mm,swift}'
|
|
28
32
|
ss.public_header_files = ['ios/RCTPushy/RCTPushy.h']
|
|
29
33
|
end
|
|
30
34
|
|
|
@@ -37,4 +41,18 @@ Pod::Spec.new do |s|
|
|
|
37
41
|
'android/jni/lzma/C/Lzma2Dec.{h,c}']
|
|
38
42
|
ss.private_header_files = 'ios/RCTPushy/HDiffPatch/**/*.h'
|
|
39
43
|
end
|
|
44
|
+
# This guard prevent to install the dependencies when we run `pod install` in the old architecture.
|
|
45
|
+
if ENV['RCT_NEW_ARCH_ENABLED'] == '1' then
|
|
46
|
+
s.compiler_flags = folly_compiler_flags + " -DRCT_NEW_ARCH_ENABLED=1"
|
|
47
|
+
s.pod_target_xcconfig = {
|
|
48
|
+
"HEADER_SEARCH_PATHS" => "\"$(PODS_ROOT)/boost\"",
|
|
49
|
+
"CLANG_CXX_LANGUAGE_STANDARD" => "c++17"
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
s.dependency "React-Codegen"
|
|
53
|
+
s.dependency "RCT-Folly", folly_version
|
|
54
|
+
s.dependency "RCTRequired"
|
|
55
|
+
s.dependency "RCTTypeSafety"
|
|
56
|
+
s.dependency "ReactCommon/turbomodule/core"
|
|
57
|
+
end
|
|
40
58
|
end
|
package/lib/index.d.ts
DELETED
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
export const downloadRootDir: string;
|
|
2
|
-
export const packageVersion: string;
|
|
3
|
-
export const currentVersion: string;
|
|
4
|
-
export const isFirstTime: boolean;
|
|
5
|
-
export const isRolledBack: boolean;
|
|
6
|
-
|
|
7
|
-
export interface ExpiredResult {
|
|
8
|
-
upToDate?: false;
|
|
9
|
-
expired: true;
|
|
10
|
-
downloadUrl: string;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
export interface UpTodateResult {
|
|
14
|
-
expired?: false;
|
|
15
|
-
upToDate: true;
|
|
16
|
-
paused?: 'app' | 'package';
|
|
17
|
-
}
|
|
18
|
-
|
|
19
|
-
export interface UpdateAvailableResult {
|
|
20
|
-
expired?: false;
|
|
21
|
-
upToDate?: false;
|
|
22
|
-
update: true;
|
|
23
|
-
name: string; // version name
|
|
24
|
-
hash: string;
|
|
25
|
-
description: string;
|
|
26
|
-
metaInfo: string;
|
|
27
|
-
pdiffUrl: string;
|
|
28
|
-
diffUrl?: string;
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
export type CheckResult =
|
|
32
|
-
| ExpiredResult
|
|
33
|
-
| UpTodateResult
|
|
34
|
-
| UpdateAvailableResult;
|
|
35
|
-
|
|
36
|
-
export function checkUpdate(appkey: string): Promise<CheckResult>;
|
|
37
|
-
|
|
38
|
-
export function downloadUpdate(
|
|
39
|
-
info: UpdateAvailableResult,
|
|
40
|
-
eventListeners?: {
|
|
41
|
-
onDownloadProgress?: (data: ProgressData) => void;
|
|
42
|
-
},
|
|
43
|
-
): Promise<undefined | string>;
|
|
44
|
-
|
|
45
|
-
export function switchVersion(hash: string): void;
|
|
46
|
-
|
|
47
|
-
export function switchVersionLater(hash: string): void;
|
|
48
|
-
|
|
49
|
-
export function markSuccess(): void;
|
|
50
|
-
|
|
51
|
-
export function downloadAndInstallApk({
|
|
52
|
-
url,
|
|
53
|
-
onDownloadProgress,
|
|
54
|
-
}: {
|
|
55
|
-
url: string;
|
|
56
|
-
onDownloadProgress?: (data: ProgressData) => void;
|
|
57
|
-
}): Promise<void>;
|
|
58
|
-
|
|
59
|
-
/**
|
|
60
|
-
* @param {string} main - The main api endpoint
|
|
61
|
-
* @param {string[]} [backups] - The back up endpoints.
|
|
62
|
-
* @param {string} [backupQueryUrl] - An url that return a json file containing an array of endpoint.
|
|
63
|
-
* like: ["https://backup.api/1", "https://backup.api/2"]
|
|
64
|
-
*/
|
|
65
|
-
export function setCustomEndpoints({
|
|
66
|
-
main,
|
|
67
|
-
backups,
|
|
68
|
-
backupQueryUrl,
|
|
69
|
-
}: {
|
|
70
|
-
main: string;
|
|
71
|
-
backups?: string[];
|
|
72
|
-
backupQueryUrl?: string;
|
|
73
|
-
}): void;
|
|
74
|
-
|
|
75
|
-
export function getCurrentVersionInfo(): Promise<{
|
|
76
|
-
name?: string;
|
|
77
|
-
description?: string;
|
|
78
|
-
metaInfo?: string;
|
|
79
|
-
}>;
|
|
80
|
-
|
|
81
|
-
interface ProgressData {
|
|
82
|
-
hash: string;
|
|
83
|
-
received: number;
|
|
84
|
-
total: number;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
interface SimpleUpdateOptions {
|
|
88
|
-
appKey: string;
|
|
89
|
-
}
|
|
90
|
-
|
|
91
|
-
export function simpleUpdate(
|
|
92
|
-
wrappedComponent: any,
|
|
93
|
-
options: SimpleUpdateOptions,
|
|
94
|
-
): any;
|
|
File without changes
|
|
File without changes
|