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 ADDED
@@ -0,0 +1,15 @@
1
+ {
2
+ "jsc": {
3
+ "loose": true,
4
+ "target": "es2018",
5
+ "parser": {
6
+ "syntax": "typescript",
7
+ "tsx": false,
8
+ "decorators": false,
9
+ "dynamicImport": false
10
+ }
11
+ },
12
+ "module": {
13
+ "type": "commonjs"
14
+ }
15
+ }
@@ -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;
@@ -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;
@@ -0,0 +1,2 @@
1
+ export * from './main';
2
+ export * from './simpleUpdate';
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
@@ -0,0 +1,2 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
@@ -0,0 +1,4 @@
1
+ export declare function promiseAny<T>(promises: Promise<T>[]): Promise<T>;
2
+ export declare function logger(...args: any[]): void;
3
+ export declare function assertRelease(): void;
4
+ export declare const testUrls: (urls?: string[]) => Promise<{} | null>;
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
@@ -24,7 +24,7 @@ export async function updateBackupEndpoints() {
24
24
  logger('fetch remote endpoints:', remoteEndpoints);
25
25
  logger('merged backup endpoints:', backupEndpoints);
26
26
  }
27
- } catch (e) {
27
+ } catch (e: any) {
28
28
  logger('fetch remote endpoints failed');
29
29
  }
30
30
  }
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
  }
@@ -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
- const ret = await promiseAny(urls.map(ping));
69
- if (ret) {
70
- return ret;
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.4",
3
+ "version": "8.5.6",
4
4
  "description": "react-native hot update",
5
- "main": "lib/index.ts",
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": ">=0.57.0"
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
+ }