react-native-update 8.5.4 → 8.5.6
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/.swcrc +15 -0
- package/dist/endpoint.d.ts +13 -0
- package/dist/endpoint.js +62 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +18 -0
- package/dist/main.d.ts +33 -0
- package/dist/main.js +346 -0
- package/dist/simpleUpdate.d.ts +61 -0
- package/dist/simpleUpdate.js +146 -0
- package/dist/type.d.ts +51 -0
- package/dist/type.js +2 -0
- package/dist/utils.d.ts +4 -0
- package/dist/utils.js +83 -0
- package/lib/endpoint.ts +1 -1
- package/lib/main.ts +5 -5
- package/lib/simpleUpdate.tsx +3 -3
- package/lib/utils.ts +8 -7
- package/package.json +7 -4
- package/tsconfig.json +18 -0
package/.swcrc
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
export declare function updateBackupEndpoints(): Promise<string[]>;
|
|
2
|
+
export declare function getCheckUrl(APPKEY: any, endpoint?: string): string;
|
|
3
|
+
/**
|
|
4
|
+
* @param {string} main - The main api endpoint
|
|
5
|
+
* @param {string[]} [backups] - The back up endpoints.
|
|
6
|
+
* @param {string} [backupQueryUrl] - An url that return a json file containing an array of endpoint.
|
|
7
|
+
* like: ["https://backup.api/1", "https://backup.api/2"]
|
|
8
|
+
*/
|
|
9
|
+
export declare function setCustomEndpoints({ main, backups, backupQueryUrls, }: {
|
|
10
|
+
main: string;
|
|
11
|
+
backups?: string[];
|
|
12
|
+
backupQueryUrls?: string[];
|
|
13
|
+
}): void;
|
package/dist/endpoint.js
ADDED
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.setCustomEndpoints = exports.getCheckUrl = exports.updateBackupEndpoints = void 0;
|
|
13
|
+
const utils_1 = require("./utils");
|
|
14
|
+
let currentEndpoint = 'https://update.react-native.cn/api';
|
|
15
|
+
let backupEndpoints = [
|
|
16
|
+
'https://pushy-koa-qgbgqmcpis.cn-beijing.fcapp.run',
|
|
17
|
+
'https://update.reactnative.cn/api',
|
|
18
|
+
];
|
|
19
|
+
let backupEndpointsQueryUrls = [
|
|
20
|
+
'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json',
|
|
21
|
+
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json',
|
|
22
|
+
];
|
|
23
|
+
function updateBackupEndpoints() {
|
|
24
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
25
|
+
if (backupEndpointsQueryUrls) {
|
|
26
|
+
try {
|
|
27
|
+
const resp = yield (0, utils_1.promiseAny)(backupEndpointsQueryUrls.map((queryUrl) => fetch(queryUrl)));
|
|
28
|
+
const remoteEndpoints = yield resp.json();
|
|
29
|
+
if (Array.isArray(remoteEndpoints)) {
|
|
30
|
+
backupEndpoints = Array.from(new Set([...backupEndpoints, ...remoteEndpoints]));
|
|
31
|
+
(0, utils_1.logger)('fetch remote endpoints:', remoteEndpoints);
|
|
32
|
+
(0, utils_1.logger)('merged backup endpoints:', backupEndpoints);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
catch (e) {
|
|
36
|
+
(0, utils_1.logger)('fetch remote endpoints failed');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
return backupEndpoints;
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
exports.updateBackupEndpoints = updateBackupEndpoints;
|
|
43
|
+
function getCheckUrl(APPKEY, endpoint = currentEndpoint) {
|
|
44
|
+
return `${endpoint}/checkUpdate/${APPKEY}`;
|
|
45
|
+
}
|
|
46
|
+
exports.getCheckUrl = getCheckUrl;
|
|
47
|
+
/**
|
|
48
|
+
* @param {string} main - The main api endpoint
|
|
49
|
+
* @param {string[]} [backups] - The back up endpoints.
|
|
50
|
+
* @param {string} [backupQueryUrl] - An url that return a json file containing an array of endpoint.
|
|
51
|
+
* like: ["https://backup.api/1", "https://backup.api/2"]
|
|
52
|
+
*/
|
|
53
|
+
function setCustomEndpoints({ main, backups, backupQueryUrls, }) {
|
|
54
|
+
currentEndpoint = main;
|
|
55
|
+
if (Array.isArray(backups) && backups.length > 0) {
|
|
56
|
+
backupEndpoints = backups;
|
|
57
|
+
}
|
|
58
|
+
if (Array.isArray(backupQueryUrls) && backupQueryUrls.length > 0) {
|
|
59
|
+
backupEndpointsQueryUrls = backupQueryUrls;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
exports.setCustomEndpoints = setCustomEndpoints;
|
package/dist/index.d.ts
ADDED
package/dist/index.js
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./main"), exports);
|
|
18
|
+
__exportStar(require("./simpleUpdate"), exports);
|
package/dist/main.d.ts
ADDED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { setCustomEndpoints } from './endpoint';
|
|
2
|
+
import { CheckResult, ProgressData, UpdateAvailableResult, UpdateEventsListener } from './type';
|
|
3
|
+
export { setCustomEndpoints };
|
|
4
|
+
export declare const PushyModule: any;
|
|
5
|
+
export declare const downloadRootDir: any;
|
|
6
|
+
export declare const packageVersion: any;
|
|
7
|
+
export declare const currentVersion: any;
|
|
8
|
+
export declare const isFirstTime: any;
|
|
9
|
+
export declare const isRolledBack: boolean;
|
|
10
|
+
export declare const buildTime: any;
|
|
11
|
+
export declare function getCurrentVersionInfo(): Promise<{
|
|
12
|
+
name?: string;
|
|
13
|
+
description?: string;
|
|
14
|
+
metaInfo?: string;
|
|
15
|
+
}>;
|
|
16
|
+
export declare function onPushyEvents(customReporter: UpdateEventsListener): void;
|
|
17
|
+
export declare const cInfo: {
|
|
18
|
+
pushy: any;
|
|
19
|
+
rn: string;
|
|
20
|
+
os: string;
|
|
21
|
+
uuid: any;
|
|
22
|
+
};
|
|
23
|
+
export declare function checkUpdate(APPKEY: string): Promise<CheckResult>;
|
|
24
|
+
export declare function downloadUpdate(options: UpdateAvailableResult, eventListeners?: {
|
|
25
|
+
onDownloadProgress?: (data: ProgressData) => void;
|
|
26
|
+
}): Promise<string | void>;
|
|
27
|
+
export declare function switchVersion(hash: string): void;
|
|
28
|
+
export declare function switchVersionLater(hash: string): void;
|
|
29
|
+
export declare function markSuccess(): void;
|
|
30
|
+
export declare function downloadAndInstallApk({ url, onDownloadProgress, }: {
|
|
31
|
+
url: string;
|
|
32
|
+
onDownloadProgress?: (data: ProgressData) => void;
|
|
33
|
+
}): Promise<void>;
|
package/dist/main.js
ADDED
|
@@ -0,0 +1,346 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.downloadAndInstallApk = exports.markSuccess = exports.switchVersionLater = exports.switchVersion = exports.downloadUpdate = exports.checkUpdate = exports.cInfo = exports.onPushyEvents = exports.getCurrentVersionInfo = exports.buildTime = exports.isRolledBack = exports.isFirstTime = exports.currentVersion = exports.packageVersion = exports.downloadRootDir = exports.PushyModule = exports.setCustomEndpoints = void 0;
|
|
13
|
+
const endpoint_1 = require("./endpoint");
|
|
14
|
+
Object.defineProperty(exports, "setCustomEndpoints", { enumerable: true, get: function () { return endpoint_1.setCustomEndpoints; } });
|
|
15
|
+
const react_native_1 = require("react-native");
|
|
16
|
+
const utils_1 = require("./utils");
|
|
17
|
+
const { version: v, } = require('react-native/Libraries/Core/ReactNativeVersion');
|
|
18
|
+
const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
|
|
19
|
+
exports.PushyModule = react_native_1.NativeModules.Pushy;
|
|
20
|
+
if (!exports.PushyModule) {
|
|
21
|
+
throw new Error('react-native-update模块无法加载,请对照安装文档检查配置。');
|
|
22
|
+
}
|
|
23
|
+
const PushyConstants = exports.PushyModule;
|
|
24
|
+
exports.downloadRootDir = PushyConstants.downloadRootDir;
|
|
25
|
+
exports.packageVersion = PushyConstants.packageVersion;
|
|
26
|
+
exports.currentVersion = PushyConstants.currentVersion;
|
|
27
|
+
exports.isFirstTime = PushyConstants.isFirstTime;
|
|
28
|
+
const rolledBackVersion = PushyConstants.rolledBackVersion;
|
|
29
|
+
exports.isRolledBack = typeof rolledBackVersion === 'string';
|
|
30
|
+
exports.buildTime = PushyConstants.buildTime;
|
|
31
|
+
let blockUpdate = PushyConstants.blockUpdate;
|
|
32
|
+
let uuid = PushyConstants.uuid;
|
|
33
|
+
if (react_native_1.Platform.OS === 'android' && !PushyConstants.isUsingBundleUrl) {
|
|
34
|
+
throw new Error('react-native-update模块无法加载,请对照文档检查Bundle URL的配置');
|
|
35
|
+
}
|
|
36
|
+
function setLocalHashInfo(hash, info) {
|
|
37
|
+
exports.PushyModule.setLocalHashInfo(hash, JSON.stringify(info));
|
|
38
|
+
}
|
|
39
|
+
function getLocalHashInfo(hash) {
|
|
40
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
41
|
+
return JSON.parse(yield exports.PushyModule.getLocalHashInfo(hash));
|
|
42
|
+
});
|
|
43
|
+
}
|
|
44
|
+
function getCurrentVersionInfo() {
|
|
45
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
46
|
+
return exports.currentVersion ? (yield getLocalHashInfo(exports.currentVersion)) || {} : {};
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
exports.getCurrentVersionInfo = getCurrentVersionInfo;
|
|
50
|
+
const eventEmitter = new react_native_1.NativeEventEmitter(exports.PushyModule);
|
|
51
|
+
if (!uuid) {
|
|
52
|
+
uuid = require('nanoid/non-secure').nanoid();
|
|
53
|
+
exports.PushyModule.setUuid(uuid);
|
|
54
|
+
}
|
|
55
|
+
const noop = () => { };
|
|
56
|
+
let reporter = noop;
|
|
57
|
+
function onPushyEvents(customReporter) {
|
|
58
|
+
reporter = customReporter;
|
|
59
|
+
if (exports.isRolledBack) {
|
|
60
|
+
report({
|
|
61
|
+
type: 'rollback',
|
|
62
|
+
data: {
|
|
63
|
+
rolledBackVersion,
|
|
64
|
+
},
|
|
65
|
+
});
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
exports.onPushyEvents = onPushyEvents;
|
|
69
|
+
function report({ type, message = '', data = {}, }) {
|
|
70
|
+
(0, utils_1.logger)(type + ' ' + message);
|
|
71
|
+
reporter({
|
|
72
|
+
type,
|
|
73
|
+
data: Object.assign({ currentVersion: exports.currentVersion,
|
|
74
|
+
cInfo: exports.cInfo,
|
|
75
|
+
packageVersion: exports.packageVersion,
|
|
76
|
+
buildTime: exports.buildTime,
|
|
77
|
+
message }, data),
|
|
78
|
+
});
|
|
79
|
+
}
|
|
80
|
+
(0, utils_1.logger)('uuid: ' + uuid);
|
|
81
|
+
exports.cInfo = {
|
|
82
|
+
pushy: require('../package.json').version,
|
|
83
|
+
rn: RNVersion,
|
|
84
|
+
os: react_native_1.Platform.OS + ' ' + react_native_1.Platform.Version,
|
|
85
|
+
uuid,
|
|
86
|
+
};
|
|
87
|
+
let lastChecking;
|
|
88
|
+
const empty = {};
|
|
89
|
+
let lastResult;
|
|
90
|
+
function checkUpdate(APPKEY) {
|
|
91
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
92
|
+
(0, utils_1.assertRelease)();
|
|
93
|
+
const now = Date.now();
|
|
94
|
+
if (lastResult && lastChecking && now - lastChecking < 1000 * 60) {
|
|
95
|
+
// logger('repeated checking, ignored');
|
|
96
|
+
return lastResult;
|
|
97
|
+
}
|
|
98
|
+
lastChecking = now;
|
|
99
|
+
if (blockUpdate && blockUpdate.until > Date.now() / 1000) {
|
|
100
|
+
report({
|
|
101
|
+
type: 'errorChecking',
|
|
102
|
+
message: `热更新已暂停,原因:${blockUpdate.reason}。请在"${new Date(blockUpdate.until * 1000).toLocaleString()}"之后重试。`,
|
|
103
|
+
});
|
|
104
|
+
return lastResult || empty;
|
|
105
|
+
}
|
|
106
|
+
report({ type: 'checking' });
|
|
107
|
+
const fetchPayload = {
|
|
108
|
+
method: 'POST',
|
|
109
|
+
headers: {
|
|
110
|
+
Accept: 'application/json',
|
|
111
|
+
'Content-Type': 'application/json',
|
|
112
|
+
},
|
|
113
|
+
body: JSON.stringify({
|
|
114
|
+
packageVersion: exports.packageVersion,
|
|
115
|
+
hash: exports.currentVersion,
|
|
116
|
+
buildTime: exports.buildTime,
|
|
117
|
+
cInfo: exports.cInfo,
|
|
118
|
+
}),
|
|
119
|
+
};
|
|
120
|
+
let resp;
|
|
121
|
+
try {
|
|
122
|
+
resp = yield fetch((0, endpoint_1.getCheckUrl)(APPKEY), fetchPayload);
|
|
123
|
+
}
|
|
124
|
+
catch (e) {
|
|
125
|
+
report({
|
|
126
|
+
type: 'errorChecking',
|
|
127
|
+
message: '无法连接主更新服务器,尝试备用节点',
|
|
128
|
+
});
|
|
129
|
+
const backupEndpoints = yield (0, endpoint_1.updateBackupEndpoints)();
|
|
130
|
+
if (backupEndpoints) {
|
|
131
|
+
try {
|
|
132
|
+
resp = yield (0, utils_1.promiseAny)(backupEndpoints.map((endpoint) => fetch((0, endpoint_1.getCheckUrl)(APPKEY, endpoint), fetchPayload)));
|
|
133
|
+
}
|
|
134
|
+
catch (_a) { }
|
|
135
|
+
}
|
|
136
|
+
}
|
|
137
|
+
if (!resp) {
|
|
138
|
+
report({
|
|
139
|
+
type: 'errorChecking',
|
|
140
|
+
message: '无法连接更新服务器,请检查网络连接后重试',
|
|
141
|
+
});
|
|
142
|
+
return lastResult || empty;
|
|
143
|
+
}
|
|
144
|
+
const result = yield resp.json();
|
|
145
|
+
lastResult = result;
|
|
146
|
+
// @ts-ignore
|
|
147
|
+
checkOperation(result.op);
|
|
148
|
+
if (resp.status !== 200) {
|
|
149
|
+
report({
|
|
150
|
+
type: 'errorChecking',
|
|
151
|
+
//@ts-ignore
|
|
152
|
+
message: result.message,
|
|
153
|
+
});
|
|
154
|
+
}
|
|
155
|
+
return result;
|
|
156
|
+
});
|
|
157
|
+
}
|
|
158
|
+
exports.checkUpdate = checkUpdate;
|
|
159
|
+
function checkOperation(op) {
|
|
160
|
+
if (!Array.isArray(op)) {
|
|
161
|
+
return;
|
|
162
|
+
}
|
|
163
|
+
op.forEach((action) => {
|
|
164
|
+
if (action.type === 'block') {
|
|
165
|
+
blockUpdate = {
|
|
166
|
+
reason: action.reason,
|
|
167
|
+
until: Math.round((Date.now() + action.duration) / 1000),
|
|
168
|
+
};
|
|
169
|
+
exports.PushyModule.setBlockUpdate(blockUpdate);
|
|
170
|
+
}
|
|
171
|
+
});
|
|
172
|
+
}
|
|
173
|
+
let downloadingThrottling = false;
|
|
174
|
+
let downloadedHash;
|
|
175
|
+
function downloadUpdate(options, eventListeners) {
|
|
176
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
177
|
+
(0, utils_1.assertRelease)();
|
|
178
|
+
if (!options.update) {
|
|
179
|
+
return;
|
|
180
|
+
}
|
|
181
|
+
if (rolledBackVersion === options.hash) {
|
|
182
|
+
(0, utils_1.logger)(`rolledback hash ${rolledBackVersion}, ignored`);
|
|
183
|
+
return;
|
|
184
|
+
}
|
|
185
|
+
if (downloadedHash === options.hash) {
|
|
186
|
+
(0, utils_1.logger)(`duplicated downloaded hash ${downloadedHash}, ignored`);
|
|
187
|
+
return downloadedHash;
|
|
188
|
+
}
|
|
189
|
+
if (downloadingThrottling) {
|
|
190
|
+
(0, utils_1.logger)('repeated downloading, ignored');
|
|
191
|
+
return;
|
|
192
|
+
}
|
|
193
|
+
downloadingThrottling = true;
|
|
194
|
+
setTimeout(() => {
|
|
195
|
+
downloadingThrottling = false;
|
|
196
|
+
}, 3000);
|
|
197
|
+
let progressHandler;
|
|
198
|
+
if (eventListeners) {
|
|
199
|
+
if (eventListeners.onDownloadProgress) {
|
|
200
|
+
const downloadCallback = eventListeners.onDownloadProgress;
|
|
201
|
+
progressHandler = eventEmitter.addListener('RCTPushyDownloadProgress', (progressData) => {
|
|
202
|
+
if (progressData.hash === options.hash) {
|
|
203
|
+
downloadCallback(progressData);
|
|
204
|
+
}
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
let succeeded = false;
|
|
209
|
+
report({ type: 'downloading' });
|
|
210
|
+
const diffUrl = (yield (0, utils_1.testUrls)(options.diffUrls)) || options.diffUrl;
|
|
211
|
+
if (diffUrl) {
|
|
212
|
+
(0, utils_1.logger)('downloading diff');
|
|
213
|
+
try {
|
|
214
|
+
yield exports.PushyModule.downloadPatchFromPpk({
|
|
215
|
+
updateUrl: diffUrl,
|
|
216
|
+
hash: options.hash,
|
|
217
|
+
originHash: exports.currentVersion,
|
|
218
|
+
});
|
|
219
|
+
succeeded = true;
|
|
220
|
+
}
|
|
221
|
+
catch (e) {
|
|
222
|
+
(0, utils_1.logger)(`diff error: ${e.message}, try pdiff`);
|
|
223
|
+
}
|
|
224
|
+
}
|
|
225
|
+
if (!succeeded) {
|
|
226
|
+
const pdiffUrl = (yield (0, utils_1.testUrls)(options.pdiffUrls)) || options.pdiffUrl;
|
|
227
|
+
if (pdiffUrl) {
|
|
228
|
+
(0, utils_1.logger)('downloading pdiff');
|
|
229
|
+
try {
|
|
230
|
+
yield exports.PushyModule.downloadPatchFromPackage({
|
|
231
|
+
updateUrl: pdiffUrl,
|
|
232
|
+
hash: options.hash,
|
|
233
|
+
});
|
|
234
|
+
succeeded = true;
|
|
235
|
+
}
|
|
236
|
+
catch (e) {
|
|
237
|
+
(0, utils_1.logger)(`pdiff error: ${e.message}, try full patch`);
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
if (!succeeded) {
|
|
242
|
+
const updateUrl = (yield (0, utils_1.testUrls)(options.updateUrls)) || options.updateUrl;
|
|
243
|
+
if (updateUrl) {
|
|
244
|
+
(0, utils_1.logger)('downloading full patch');
|
|
245
|
+
try {
|
|
246
|
+
yield exports.PushyModule.downloadFullUpdate({
|
|
247
|
+
updateUrl: updateUrl,
|
|
248
|
+
hash: options.hash,
|
|
249
|
+
});
|
|
250
|
+
succeeded = true;
|
|
251
|
+
}
|
|
252
|
+
catch (e) {
|
|
253
|
+
(0, utils_1.logger)(`full patch error: ${e.message}`);
|
|
254
|
+
}
|
|
255
|
+
}
|
|
256
|
+
}
|
|
257
|
+
progressHandler && progressHandler.remove();
|
|
258
|
+
if (!succeeded) {
|
|
259
|
+
return report({ type: 'errorUpdate', data: { newVersion: options.hash } });
|
|
260
|
+
}
|
|
261
|
+
setLocalHashInfo(options.hash, {
|
|
262
|
+
name: options.name,
|
|
263
|
+
description: options.description,
|
|
264
|
+
metaInfo: options.metaInfo,
|
|
265
|
+
});
|
|
266
|
+
downloadedHash = options.hash;
|
|
267
|
+
return options.hash;
|
|
268
|
+
});
|
|
269
|
+
}
|
|
270
|
+
exports.downloadUpdate = downloadUpdate;
|
|
271
|
+
function assertHash(hash) {
|
|
272
|
+
if (!downloadedHash) {
|
|
273
|
+
(0, utils_1.logger)(`no downloaded hash`);
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
if (hash !== downloadedHash) {
|
|
277
|
+
(0, utils_1.logger)(`use downloaded hash ${downloadedHash} first`);
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
return true;
|
|
281
|
+
}
|
|
282
|
+
function switchVersion(hash) {
|
|
283
|
+
(0, utils_1.assertRelease)();
|
|
284
|
+
if (assertHash(hash)) {
|
|
285
|
+
(0, utils_1.logger)('switchVersion: ' + hash);
|
|
286
|
+
exports.PushyModule.reloadUpdate({ hash });
|
|
287
|
+
}
|
|
288
|
+
}
|
|
289
|
+
exports.switchVersion = switchVersion;
|
|
290
|
+
function switchVersionLater(hash) {
|
|
291
|
+
(0, utils_1.assertRelease)();
|
|
292
|
+
if (assertHash(hash)) {
|
|
293
|
+
(0, utils_1.logger)('switchVersionLater: ' + hash);
|
|
294
|
+
exports.PushyModule.setNeedUpdate({ hash });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
exports.switchVersionLater = switchVersionLater;
|
|
298
|
+
let marked = false;
|
|
299
|
+
function markSuccess() {
|
|
300
|
+
(0, utils_1.assertRelease)();
|
|
301
|
+
if (marked) {
|
|
302
|
+
(0, utils_1.logger)('repeated markSuccess, ignored');
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
marked = true;
|
|
306
|
+
exports.PushyModule.markSuccess();
|
|
307
|
+
report({ type: 'markSuccess' });
|
|
308
|
+
}
|
|
309
|
+
exports.markSuccess = markSuccess;
|
|
310
|
+
function downloadAndInstallApk({ url, onDownloadProgress, }) {
|
|
311
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
312
|
+
if (react_native_1.Platform.OS !== 'android') {
|
|
313
|
+
return;
|
|
314
|
+
}
|
|
315
|
+
report({ type: 'downloadingApk' });
|
|
316
|
+
if (react_native_1.Platform.Version <= 23) {
|
|
317
|
+
try {
|
|
318
|
+
const granted = yield react_native_1.PermissionsAndroid.request(react_native_1.PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
|
|
319
|
+
if (granted !== react_native_1.PermissionsAndroid.RESULTS.GRANTED) {
|
|
320
|
+
return report({ type: 'rejectStoragePermission' });
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
catch (err) {
|
|
324
|
+
return report({ type: 'errorStoragePermission' });
|
|
325
|
+
}
|
|
326
|
+
}
|
|
327
|
+
let hash = Date.now().toString();
|
|
328
|
+
let progressHandler;
|
|
329
|
+
if (onDownloadProgress) {
|
|
330
|
+
progressHandler = eventEmitter.addListener('RCTPushyDownloadProgress', (progressData) => {
|
|
331
|
+
if (progressData.hash === hash) {
|
|
332
|
+
onDownloadProgress(progressData);
|
|
333
|
+
}
|
|
334
|
+
});
|
|
335
|
+
}
|
|
336
|
+
yield exports.PushyModule.downloadAndInstallApk({
|
|
337
|
+
url,
|
|
338
|
+
target: 'update.apk',
|
|
339
|
+
hash,
|
|
340
|
+
}).catch(() => {
|
|
341
|
+
report({ type: 'errowDownloadAndInstallApk' });
|
|
342
|
+
});
|
|
343
|
+
progressHandler && progressHandler.remove();
|
|
344
|
+
});
|
|
345
|
+
}
|
|
346
|
+
exports.downloadAndInstallApk = downloadAndInstallApk;
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
import React, { ComponentType } from 'react';
|
|
2
|
+
import { NativeEventSubscription } from 'react-native';
|
|
3
|
+
import { UpdateEventsListener } from './type';
|
|
4
|
+
export declare function simpleUpdate(WrappedComponent: ComponentType, options?: {
|
|
5
|
+
appKey?: string;
|
|
6
|
+
onPushyEvents?: UpdateEventsListener;
|
|
7
|
+
}): React.ComponentType | {
|
|
8
|
+
new (props: {} | Readonly<{}>): {
|
|
9
|
+
stateListener: NativeEventSubscription | null;
|
|
10
|
+
componentDidMount(): void;
|
|
11
|
+
componentWillUnmount(): void;
|
|
12
|
+
doUpdate: (info: any) => Promise<void>;
|
|
13
|
+
checkUpdate: () => Promise<void>;
|
|
14
|
+
render(): React.JSX.Element;
|
|
15
|
+
context: unknown;
|
|
16
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
|
|
17
|
+
forceUpdate(callback?: (() => void) | undefined): void;
|
|
18
|
+
readonly props: Readonly<{}>;
|
|
19
|
+
state: Readonly<{}>;
|
|
20
|
+
refs: {
|
|
21
|
+
[key: string]: React.ReactInstance;
|
|
22
|
+
};
|
|
23
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
24
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
25
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
26
|
+
componentDidUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>, snapshot?: any): void;
|
|
27
|
+
componentWillMount?(): void;
|
|
28
|
+
UNSAFE_componentWillMount?(): void;
|
|
29
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
30
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
31
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
32
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
33
|
+
};
|
|
34
|
+
new (props: {}, context: any): {
|
|
35
|
+
stateListener: NativeEventSubscription | null;
|
|
36
|
+
componentDidMount(): void;
|
|
37
|
+
componentWillUnmount(): void;
|
|
38
|
+
doUpdate: (info: any) => Promise<void>;
|
|
39
|
+
checkUpdate: () => Promise<void>;
|
|
40
|
+
render(): React.JSX.Element;
|
|
41
|
+
context: unknown;
|
|
42
|
+
setState<K extends never>(state: {} | ((prevState: Readonly<{}>, props: Readonly<{}>) => {} | Pick<{}, K> | null) | Pick<{}, K> | null, callback?: (() => void) | undefined): void;
|
|
43
|
+
forceUpdate(callback?: (() => void) | undefined): void;
|
|
44
|
+
readonly props: Readonly<{}>;
|
|
45
|
+
state: Readonly<{}>;
|
|
46
|
+
refs: {
|
|
47
|
+
[key: string]: React.ReactInstance;
|
|
48
|
+
};
|
|
49
|
+
shouldComponentUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): boolean;
|
|
50
|
+
componentDidCatch?(error: Error, errorInfo: React.ErrorInfo): void;
|
|
51
|
+
getSnapshotBeforeUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>): any;
|
|
52
|
+
componentDidUpdate?(prevProps: Readonly<{}>, prevState: Readonly<{}>, snapshot?: any): void;
|
|
53
|
+
componentWillMount?(): void;
|
|
54
|
+
UNSAFE_componentWillMount?(): void;
|
|
55
|
+
componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
56
|
+
UNSAFE_componentWillReceiveProps?(nextProps: Readonly<{}>, nextContext: any): void;
|
|
57
|
+
componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
58
|
+
UNSAFE_componentWillUpdate?(nextProps: Readonly<{}>, nextState: Readonly<{}>, nextContext: any): void;
|
|
59
|
+
};
|
|
60
|
+
contextType?: React.Context<any> | undefined;
|
|
61
|
+
};
|
|
@@ -0,0 +1,146 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || function (mod) {
|
|
19
|
+
if (mod && mod.__esModule) return mod;
|
|
20
|
+
var result = {};
|
|
21
|
+
if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
|
|
22
|
+
__setModuleDefault(result, mod);
|
|
23
|
+
return result;
|
|
24
|
+
};
|
|
25
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
26
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
27
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
28
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
29
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
30
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
31
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
32
|
+
});
|
|
33
|
+
};
|
|
34
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
35
|
+
exports.simpleUpdate = void 0;
|
|
36
|
+
const react_1 = __importStar(require("react"));
|
|
37
|
+
const react_native_1 = require("react-native");
|
|
38
|
+
const main_1 = require("./main");
|
|
39
|
+
function simpleUpdate(WrappedComponent, options = {}) {
|
|
40
|
+
const { appKey, onPushyEvents: eventListeners } = options;
|
|
41
|
+
if (!appKey) {
|
|
42
|
+
throw new Error('appKey is required for simpleUpdate()');
|
|
43
|
+
}
|
|
44
|
+
if (typeof eventListeners === 'function') {
|
|
45
|
+
(0, main_1.onPushyEvents)(eventListeners);
|
|
46
|
+
}
|
|
47
|
+
return __DEV__
|
|
48
|
+
? WrappedComponent
|
|
49
|
+
: class AppUpdate extends react_1.PureComponent {
|
|
50
|
+
constructor() {
|
|
51
|
+
super(...arguments);
|
|
52
|
+
this.stateListener = null;
|
|
53
|
+
this.doUpdate = (info) => __awaiter(this, void 0, void 0, function* () {
|
|
54
|
+
try {
|
|
55
|
+
const hash = yield (0, main_1.downloadUpdate)(info);
|
|
56
|
+
if (!hash) {
|
|
57
|
+
return;
|
|
58
|
+
}
|
|
59
|
+
this.stateListener && this.stateListener.remove();
|
|
60
|
+
react_native_1.Alert.alert('提示', '下载完毕,是否立即更新?', [
|
|
61
|
+
{
|
|
62
|
+
text: '以后再说',
|
|
63
|
+
style: 'cancel',
|
|
64
|
+
onPress: () => {
|
|
65
|
+
(0, main_1.switchVersionLater)(hash);
|
|
66
|
+
},
|
|
67
|
+
},
|
|
68
|
+
{
|
|
69
|
+
text: '立即更新',
|
|
70
|
+
style: 'default',
|
|
71
|
+
onPress: () => {
|
|
72
|
+
(0, main_1.switchVersion)(hash);
|
|
73
|
+
},
|
|
74
|
+
},
|
|
75
|
+
]);
|
|
76
|
+
}
|
|
77
|
+
catch (err) {
|
|
78
|
+
react_native_1.Alert.alert('更新失败', err.message);
|
|
79
|
+
}
|
|
80
|
+
});
|
|
81
|
+
this.checkUpdate = () => __awaiter(this, void 0, void 0, function* () {
|
|
82
|
+
let info;
|
|
83
|
+
try {
|
|
84
|
+
info = yield (0, main_1.checkUpdate)(appKey);
|
|
85
|
+
}
|
|
86
|
+
catch (err) {
|
|
87
|
+
react_native_1.Alert.alert('更新检查失败', err.message);
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
if (info.expired) {
|
|
91
|
+
react_native_1.Alert.alert('提示', '您的应用版本已更新,点击确定下载安装新版本', [
|
|
92
|
+
{
|
|
93
|
+
text: '确定',
|
|
94
|
+
onPress: () => {
|
|
95
|
+
if (info.downloadUrl) {
|
|
96
|
+
if (react_native_1.Platform.OS === 'android' &&
|
|
97
|
+
info.downloadUrl.endsWith('.apk')) {
|
|
98
|
+
(0, main_1.downloadAndInstallApk)({
|
|
99
|
+
url: info.downloadUrl,
|
|
100
|
+
});
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
react_native_1.Linking.openURL(info.downloadUrl);
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
},
|
|
107
|
+
},
|
|
108
|
+
]);
|
|
109
|
+
}
|
|
110
|
+
else if (info.update) {
|
|
111
|
+
react_native_1.Alert.alert('提示', '检查到新的版本' + info.name + ',是否下载?\n' + info.description, [
|
|
112
|
+
{ text: '否', style: 'cancel' },
|
|
113
|
+
{
|
|
114
|
+
text: '是',
|
|
115
|
+
style: 'default',
|
|
116
|
+
onPress: () => {
|
|
117
|
+
this.doUpdate(info);
|
|
118
|
+
},
|
|
119
|
+
},
|
|
120
|
+
]);
|
|
121
|
+
}
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
componentDidMount() {
|
|
125
|
+
if (main_1.isRolledBack) {
|
|
126
|
+
react_native_1.Alert.alert('抱歉', '刚刚更新遭遇错误,已为您恢复到更新前版本');
|
|
127
|
+
}
|
|
128
|
+
else if (main_1.isFirstTime) {
|
|
129
|
+
(0, main_1.markSuccess)();
|
|
130
|
+
}
|
|
131
|
+
this.stateListener = react_native_1.AppState.addEventListener('change', (nextAppState) => {
|
|
132
|
+
if (nextAppState === 'active') {
|
|
133
|
+
this.checkUpdate();
|
|
134
|
+
}
|
|
135
|
+
});
|
|
136
|
+
this.checkUpdate();
|
|
137
|
+
}
|
|
138
|
+
componentWillUnmount() {
|
|
139
|
+
this.stateListener && this.stateListener.remove();
|
|
140
|
+
}
|
|
141
|
+
render() {
|
|
142
|
+
return <WrappedComponent {...this.props}/>;
|
|
143
|
+
}
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
exports.simpleUpdate = simpleUpdate;
|
package/dist/type.d.ts
ADDED
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
export interface ExpiredResult {
|
|
2
|
+
upToDate?: false;
|
|
3
|
+
expired: true;
|
|
4
|
+
downloadUrl: string;
|
|
5
|
+
}
|
|
6
|
+
export interface UpTodateResult {
|
|
7
|
+
expired?: false;
|
|
8
|
+
upToDate: true;
|
|
9
|
+
paused?: 'app' | 'package';
|
|
10
|
+
}
|
|
11
|
+
export interface UpdateAvailableResult {
|
|
12
|
+
expired?: false;
|
|
13
|
+
upToDate?: false;
|
|
14
|
+
update: true;
|
|
15
|
+
name: string;
|
|
16
|
+
hash: string;
|
|
17
|
+
description: string;
|
|
18
|
+
metaInfo: string;
|
|
19
|
+
pdiffUrl: string;
|
|
20
|
+
pdiffUrls?: string[];
|
|
21
|
+
diffUrl?: string;
|
|
22
|
+
diffUrls?: string[];
|
|
23
|
+
updateUrl?: string;
|
|
24
|
+
updateUrls?: string[];
|
|
25
|
+
}
|
|
26
|
+
export type CheckResult = ExpiredResult | UpTodateResult | UpdateAvailableResult | {};
|
|
27
|
+
export interface ProgressData {
|
|
28
|
+
hash: string;
|
|
29
|
+
received: number;
|
|
30
|
+
total: number;
|
|
31
|
+
}
|
|
32
|
+
export type EventType = 'rollback' | 'errorChecking' | 'checking' | 'downloading' | 'errorUpdate' | 'markSuccess' | 'downloadingApk' | 'rejectStoragePermission' | 'errorStoragePermission' | 'errowDownloadAndInstallApk';
|
|
33
|
+
export interface EventData {
|
|
34
|
+
currentVersion: string;
|
|
35
|
+
cInfo: {
|
|
36
|
+
pushy: string;
|
|
37
|
+
rn: string;
|
|
38
|
+
os: string;
|
|
39
|
+
uuid: string;
|
|
40
|
+
};
|
|
41
|
+
packageVersion: string;
|
|
42
|
+
buildTime: number;
|
|
43
|
+
message?: string;
|
|
44
|
+
rolledBackVersion?: string;
|
|
45
|
+
newVersion?: string;
|
|
46
|
+
[key: string]: any;
|
|
47
|
+
}
|
|
48
|
+
export type UpdateEventsListener = ({ type, data, }: {
|
|
49
|
+
type: EventType;
|
|
50
|
+
data: EventData;
|
|
51
|
+
}) => void;
|
package/dist/type.js
ADDED
package/dist/utils.d.ts
ADDED
package/dist/utils.js
ADDED
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
3
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
4
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
5
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
6
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
7
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
8
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
9
|
+
});
|
|
10
|
+
};
|
|
11
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
+
exports.testUrls = exports.assertRelease = exports.logger = exports.promiseAny = void 0;
|
|
13
|
+
const react_native_1 = require("react-native");
|
|
14
|
+
function promiseAny(promises) {
|
|
15
|
+
return new Promise((resolve, reject) => {
|
|
16
|
+
let count = 0;
|
|
17
|
+
promises.forEach((promise) => {
|
|
18
|
+
Promise.resolve(promise)
|
|
19
|
+
.then(resolve)
|
|
20
|
+
.catch(() => {
|
|
21
|
+
count++;
|
|
22
|
+
if (count === promises.length) {
|
|
23
|
+
reject(new Error('All promises were rejected'));
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
});
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
exports.promiseAny = promiseAny;
|
|
30
|
+
function logger(...args) {
|
|
31
|
+
console.log('Pushy: ', ...args);
|
|
32
|
+
}
|
|
33
|
+
exports.logger = logger;
|
|
34
|
+
function assertRelease() {
|
|
35
|
+
if (__DEV__) {
|
|
36
|
+
throw new Error('react-native-update 只能在 RELEASE 版本中运行.');
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
exports.assertRelease = assertRelease;
|
|
40
|
+
const ping = react_native_1.Platform.OS === 'web'
|
|
41
|
+
? Promise.resolve
|
|
42
|
+
: (url) => __awaiter(void 0, void 0, void 0, function* () {
|
|
43
|
+
let pingFinished = false;
|
|
44
|
+
return Promise.race([
|
|
45
|
+
fetch(url, {
|
|
46
|
+
method: 'HEAD',
|
|
47
|
+
})
|
|
48
|
+
.then(({ status, statusText }) => {
|
|
49
|
+
pingFinished = true;
|
|
50
|
+
if (status === 200) {
|
|
51
|
+
return url;
|
|
52
|
+
}
|
|
53
|
+
logger('ping failed', url, status, statusText);
|
|
54
|
+
throw new Error('Ping failed');
|
|
55
|
+
})
|
|
56
|
+
.catch((e) => {
|
|
57
|
+
pingFinished = true;
|
|
58
|
+
logger('ping error', url, e);
|
|
59
|
+
throw e;
|
|
60
|
+
}),
|
|
61
|
+
new Promise((_, reject) => setTimeout(() => {
|
|
62
|
+
reject(new Error('Ping timeout'));
|
|
63
|
+
if (!pingFinished) {
|
|
64
|
+
logger('ping timeout', url);
|
|
65
|
+
}
|
|
66
|
+
}, 2000)),
|
|
67
|
+
]);
|
|
68
|
+
});
|
|
69
|
+
const testUrls = (urls) => __awaiter(void 0, void 0, void 0, function* () {
|
|
70
|
+
if (!(urls === null || urls === void 0 ? void 0 : urls.length)) {
|
|
71
|
+
return null;
|
|
72
|
+
}
|
|
73
|
+
try {
|
|
74
|
+
const ret = yield promiseAny(urls.map(ping));
|
|
75
|
+
if (ret) {
|
|
76
|
+
return ret;
|
|
77
|
+
}
|
|
78
|
+
}
|
|
79
|
+
catch (_a) { }
|
|
80
|
+
logger('all ping failed, use first url:', urls[0]);
|
|
81
|
+
return urls[0];
|
|
82
|
+
});
|
|
83
|
+
exports.testUrls = testUrls;
|
package/lib/endpoint.ts
CHANGED
package/lib/main.ts
CHANGED
|
@@ -154,7 +154,7 @@ export async function checkUpdate(APPKEY: string) {
|
|
|
154
154
|
let resp;
|
|
155
155
|
try {
|
|
156
156
|
resp = await fetch(getCheckUrl(APPKEY), fetchPayload);
|
|
157
|
-
} catch (e) {
|
|
157
|
+
} catch (e: any) {
|
|
158
158
|
report({
|
|
159
159
|
type: 'errorChecking',
|
|
160
160
|
message: '无法连接主更新服务器,尝试备用节点',
|
|
@@ -265,7 +265,7 @@ export async function downloadUpdate(
|
|
|
265
265
|
originHash: currentVersion,
|
|
266
266
|
});
|
|
267
267
|
succeeded = true;
|
|
268
|
-
} catch (e) {
|
|
268
|
+
} catch (e: any) {
|
|
269
269
|
logger(`diff error: ${e.message}, try pdiff`);
|
|
270
270
|
}
|
|
271
271
|
}
|
|
@@ -279,7 +279,7 @@ export async function downloadUpdate(
|
|
|
279
279
|
hash: options.hash,
|
|
280
280
|
});
|
|
281
281
|
succeeded = true;
|
|
282
|
-
} catch (e) {
|
|
282
|
+
} catch (e: any) {
|
|
283
283
|
logger(`pdiff error: ${e.message}, try full patch`);
|
|
284
284
|
}
|
|
285
285
|
}
|
|
@@ -294,7 +294,7 @@ export async function downloadUpdate(
|
|
|
294
294
|
hash: options.hash,
|
|
295
295
|
});
|
|
296
296
|
succeeded = true;
|
|
297
|
-
} catch (e) {
|
|
297
|
+
} catch (e: any) {
|
|
298
298
|
logger(`full patch error: ${e.message}`);
|
|
299
299
|
}
|
|
300
300
|
}
|
|
@@ -371,7 +371,7 @@ export async function downloadAndInstallApk({
|
|
|
371
371
|
if (granted !== PermissionsAndroid.RESULTS.GRANTED) {
|
|
372
372
|
return report({ type: 'rejectStoragePermission' });
|
|
373
373
|
}
|
|
374
|
-
} catch (err) {
|
|
374
|
+
} catch (err: any) {
|
|
375
375
|
return report({ type: 'errorStoragePermission' });
|
|
376
376
|
}
|
|
377
377
|
}
|
package/lib/simpleUpdate.tsx
CHANGED
|
@@ -34,7 +34,7 @@ export function simpleUpdate(
|
|
|
34
34
|
return __DEV__
|
|
35
35
|
? WrappedComponent
|
|
36
36
|
: class AppUpdate extends PureComponent {
|
|
37
|
-
stateListener: NativeEventSubscription;
|
|
37
|
+
stateListener: NativeEventSubscription | null = null;
|
|
38
38
|
componentDidMount() {
|
|
39
39
|
if (isRolledBack) {
|
|
40
40
|
Alert.alert('抱歉', '刚刚更新遭遇错误,已为您恢复到更新前版本');
|
|
@@ -77,7 +77,7 @@ export function simpleUpdate(
|
|
|
77
77
|
},
|
|
78
78
|
},
|
|
79
79
|
]);
|
|
80
|
-
} catch (err) {
|
|
80
|
+
} catch (err: any) {
|
|
81
81
|
Alert.alert('更新失败', err.message);
|
|
82
82
|
}
|
|
83
83
|
};
|
|
@@ -86,7 +86,7 @@ export function simpleUpdate(
|
|
|
86
86
|
let info;
|
|
87
87
|
try {
|
|
88
88
|
info = await checkUpdate(appKey!);
|
|
89
|
-
} catch (err) {
|
|
89
|
+
} catch (err: any) {
|
|
90
90
|
Alert.alert('更新检查失败', err.message);
|
|
91
91
|
return;
|
|
92
92
|
}
|
package/lib/utils.ts
CHANGED
|
@@ -4,7 +4,7 @@ export function promiseAny<T>(promises: Promise<T>[]) {
|
|
|
4
4
|
return new Promise<T>((resolve, reject) => {
|
|
5
5
|
let count = 0;
|
|
6
6
|
|
|
7
|
-
promises.forEach(promise => {
|
|
7
|
+
promises.forEach((promise) => {
|
|
8
8
|
Promise.resolve(promise)
|
|
9
9
|
.then(resolve)
|
|
10
10
|
.catch(() => {
|
|
@@ -44,7 +44,7 @@ const ping =
|
|
|
44
44
|
logger('ping failed', url, status, statusText);
|
|
45
45
|
throw new Error('Ping failed');
|
|
46
46
|
})
|
|
47
|
-
.catch(e => {
|
|
47
|
+
.catch((e) => {
|
|
48
48
|
pingFinished = true;
|
|
49
49
|
logger('ping error', url, e);
|
|
50
50
|
throw e;
|
|
@@ -60,15 +60,16 @@ const ping =
|
|
|
60
60
|
]);
|
|
61
61
|
};
|
|
62
62
|
|
|
63
|
-
|
|
64
63
|
export const testUrls = async (urls?: string[]) => {
|
|
65
64
|
if (!urls?.length) {
|
|
66
65
|
return null;
|
|
67
66
|
}
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
67
|
+
try {
|
|
68
|
+
const ret = await promiseAny(urls.map(ping));
|
|
69
|
+
if (ret) {
|
|
70
|
+
return ret;
|
|
71
|
+
}
|
|
72
|
+
} catch {}
|
|
72
73
|
logger('all ping failed, use first url:', urls[0]);
|
|
73
74
|
return urls[0];
|
|
74
75
|
};
|
package/package.json
CHANGED
|
@@ -1,10 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-update",
|
|
3
|
-
"version": "8.5.
|
|
3
|
+
"version": "8.5.6",
|
|
4
4
|
"description": "react-native hot update",
|
|
5
|
-
"main": "
|
|
5
|
+
"main": "dist/index.js",
|
|
6
|
+
"types": "dist/index.d.ts",
|
|
6
7
|
"scripts": {
|
|
7
|
-
"prepublish": "yarn submodule",
|
|
8
|
+
"prepublish": "yarn submodule && yarn build",
|
|
9
|
+
"build": "yarn clean && tsc",
|
|
10
|
+
"clean": "rm -rf dist",
|
|
8
11
|
"submodule": "git submodule update --init --recursive",
|
|
9
12
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
10
13
|
"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"
|
|
@@ -25,7 +28,7 @@
|
|
|
25
28
|
"url": "https://github.com/reactnativecn/react-native-pushy/issues"
|
|
26
29
|
},
|
|
27
30
|
"peerDependencies": {
|
|
28
|
-
"react-native": "
|
|
31
|
+
"react-native": "*"
|
|
29
32
|
},
|
|
30
33
|
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
|
|
31
34
|
"dependencies": {
|
package/tsconfig.json
ADDED
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
{
|
|
2
|
+
"compilerOptions": {
|
|
3
|
+
"target": "es2016",
|
|
4
|
+
"module": "commonjs",
|
|
5
|
+
"declaration": true,
|
|
6
|
+
"outDir": "./dist",
|
|
7
|
+
"strict": true,
|
|
8
|
+
"noImplicitAny": false,
|
|
9
|
+
"esModuleInterop": true,
|
|
10
|
+
"skipLibCheck": true,
|
|
11
|
+
"forceConsistentCasingInFileNames": true,
|
|
12
|
+
"jsx": "react-native",
|
|
13
|
+
"lib": ["es2016", "dom"],
|
|
14
|
+
"moduleResolution": "node"
|
|
15
|
+
},
|
|
16
|
+
"include": ["lib/**/*"],
|
|
17
|
+
"exclude": ["node_modules", "dist", "Example"]
|
|
18
|
+
}
|