From a5647705975285fe61034dc5bfb5da000f4abe9e Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2024年7月27日 21:59:25 +0800 Subject: [PATCH 1/9] v9.2.0 --- lib/endpoint.ts | 25 ++++++++++++++-------- lib/main.ts | 57 +++++++++++++++++++++++++++---------------------- lib/type.ts | 3 +++ lib/utils.ts | 23 ++++++++++++++++++++ package.json | 2 +- 5 files changed, 74 insertions(+), 36 deletions(-) diff --git a/lib/endpoint.ts b/lib/endpoint.ts index 98a14c9e..98db2116 100644 --- a/lib/endpoint.ts +++ b/lib/endpoint.ts @@ -1,13 +1,21 @@ import { logger } from './utils'; let currentEndpoint = 'https://update.react-native.cn/api'; -let backupEndpoints: string[] = ['https://update.reactnative.cn/api']; -let backupEndpointsQueryUrl: string | null = null; +let backupEndpoints: string[] = [ + 'https://pushy-koa-qgbgqmcpis.cn-beijing.fcapp.run', + 'https://update.reactnative.cn/api', +]; +let backupEndpointsQueryUrls = [ + 'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json', + 'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json', +]; export async function updateBackupEndpoints() { - if (backupEndpointsQueryUrl) { + if (backupEndpointsQueryUrls) { try { - const resp = await fetch(backupEndpointsQueryUrl); + const resp = await Promise.race( + backupEndpointsQueryUrls.map((queryUrl) => fetch(queryUrl)), + ); const remoteEndpoints = await resp.json(); if (Array.isArray(remoteEndpoints)) { backupEndpoints = Array.from( @@ -36,18 +44,17 @@ export function getCheckUrl(APPKEY, endpoint = currentEndpoint) { export function setCustomEndpoints({ main, backups, - backupQueryUrl, + backupQueryUrls, }: { main: string; backups?: string[]; - backupQueryUrl?: string; + backupQueryUrls?: string[]; }) { currentEndpoint = main; - backupEndpointsQueryUrl = null; if (Array.isArray(backups) && backups.length> 0) { backupEndpoints = backups; } - if (typeof backupQueryUrl === 'string') { - backupEndpointsQueryUrl = backupQueryUrl; + if (Array.isArray(backupQueryUrls) && backupQueryUrls.length> 0) { + backupEndpointsQueryUrls = backupQueryUrls; } } diff --git a/lib/main.ts b/lib/main.ts index b7fa3b74..66cd813c 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -16,7 +16,7 @@ import { UpdateAvailableResult, UpdateEventsListener, } from './type'; -import { assertRelease, logger } from './utils'; +import { assertRelease, logger, testUrls } from './utils'; export { setCustomEndpoints }; const { version: v, @@ -260,11 +260,12 @@ export async function downloadUpdate( } let succeeded = false; report({ type: 'downloading' }); - if (options.diffUrl) { + const diffUrl = (await testUrls(options.diffUrls)) || options.diffUrl; + if (diffUrl) { logger('downloading diff'); try { await PushyModule.downloadPatchFromPpk({ - updateUrl: options.diffUrl, + updateUrl: diffUrl, hash: options.hash, originHash: currentVersion, }); @@ -273,28 +274,34 @@ export async function downloadUpdate( logger(`diff error: ${e.message}, try pdiff`); } } - if (!succeeded && options.pdiffUrl) { - logger('downloading pdiff'); - try { - await PushyModule.downloadPatchFromPackage({ - updateUrl: options.pdiffUrl, - hash: options.hash, - }); - succeeded = true; - } catch (e) { - logger(`pdiff error: ${e.message}, try full patch`); + if (!succeeded) { + const pdiffUrl = (await testUrls(options.pdiffUrls)) || options.pdiffUrl; + if (pdiffUrl) { + logger('downloading pdiff'); + try { + await PushyModule.downloadPatchFromPackage({ + updateUrl: pdiffUrl, + hash: options.hash, + }); + succeeded = true; + } catch (e) { + logger(`pdiff error: ${e.message}, try full patch`); + } } } - if (!succeeded && options.updateUrl) { - logger('downloading full patch'); - try { - await PushyModule.downloadFullUpdate({ - updateUrl: options.updateUrl, - hash: options.hash, - }); - succeeded = true; - } catch (e) { - logger(`full patch error: ${e.message}`); + if (!succeeded) { + const updateUrl = (await testUrls(options.updateUrls)) || options.updateUrl; + if (updateUrl) { + logger('downloading full patch'); + try { + await PushyModule.downloadFullUpdate({ + updateUrl: updateUrl, + hash: options.hash, + }); + succeeded = true; + } catch (e) { + logger(`full patch error: ${e.message}`); + } } } progressHandler && progressHandler.remove(); @@ -322,12 +329,10 @@ function assertHash(hash: string) { return true; } -let applyingUpdate = false; export function switchVersion(hash: string) { assertRelease(); - if (assertHash(hash) && !applyingUpdate) { + if (assertHash(hash)) { logger('switchVersion: ' + hash); - applyingUpdate = true; PushyModule.reloadUpdate({ hash }); } } diff --git a/lib/type.ts b/lib/type.ts index 00ec1978..d8c8ad09 100644 --- a/lib/type.ts +++ b/lib/type.ts @@ -19,8 +19,11 @@ export interface UpdateAvailableResult { description: string; metaInfo: string; pdiffUrl: string; + pdiffUrls?: string[]; diffUrl?: string; + diffUrls?: string[]; updateUrl?: string; + updateUrls?: string[]; } export type CheckResult = diff --git a/lib/utils.ts b/lib/utils.ts index 9b024de4..f7a3c99d 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,3 +1,5 @@ +import { Platform } from "react-native"; + export function logger(...args: any[]) { console.log('Pushy: ', ...args); } @@ -7,3 +9,24 @@ export function assertRelease() { throw new Error('react-native-update 只能在 RELEASE 版本中运行.'); } } + +const ping = + Platform.OS === 'web' + ? Promise.resolve + : async (url: string) => + Promise.race([ + fetch(url, { + method: 'HEAD', + }) + .then(({ status }) => (status === 200 ? url : null)) + .catch(() => null), + new Promise(r => setTimeout(() => r(null), 2000)), + ]); + + +export const testUrls = async (urls?: string[]) => { + if (!urls?.length) { + return null; + } + return Promise.race(urls.map(ping)).catch(() => null); +}; diff --git a/package.json b/package.json index a85c0354..ace53a8e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.1.6", + "version": "9.2.0", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From d7879ac2fe0ad1a043b58efabcc64ca282d55def Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2024年8月21日 20:06:36 +0800 Subject: [PATCH 2/9] v9.2.1 --- ios/RCTPushy/RCTPushy.mm | 3 +-- package.json | 2 +- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/ios/RCTPushy/RCTPushy.mm b/ios/RCTPushy/RCTPushy.mm index 850ef324..f78629b0 100644 --- a/ios/RCTPushy/RCTPushy.mm +++ b/ios/RCTPushy/RCTPushy.mm @@ -349,8 +349,7 @@ - (instancetype)init } } -RCT_EXPORT_METHOD(markSuccess: - resolver:(RCTPromiseResolveBlock)resolve +RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve rejecter:(RCTPromiseRejectBlock)reject) { diff --git a/package.json b/package.json index ace53a8e..0d26da43 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.0", + "version": "9.2.1", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From 1614a21968a326d495b9d6b18d1bcbe7159eb5fc Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2024年11月13日 20:00:06 +0800 Subject: [PATCH 3/9] v9.2.2 --- lib/endpoint.ts | 6 +++--- lib/main.ts | 10 +++++----- lib/utils.ts | 26 ++++++++++++++++++++------ package.json | 5 +++-- 4 files changed, 31 insertions(+), 16 deletions(-) diff --git a/lib/endpoint.ts b/lib/endpoint.ts index 98db2116..9c0bea22 100644 --- a/lib/endpoint.ts +++ b/lib/endpoint.ts @@ -1,4 +1,4 @@ -import { logger } from './utils'; +import { logger, promiseAny } from './utils'; let currentEndpoint = 'https://update.react-native.cn/api'; let backupEndpoints: string[] = [ @@ -13,8 +13,8 @@ let backupEndpointsQueryUrls = [ export async function updateBackupEndpoints() { if (backupEndpointsQueryUrls) { try { - const resp = await Promise.race( - backupEndpointsQueryUrls.map((queryUrl) => fetch(queryUrl)), + const resp = await promiseAny( + backupEndpointsQueryUrls.map(queryUrl => fetch(queryUrl)), ); const remoteEndpoints = await resp.json(); if (Array.isArray(remoteEndpoints)) { diff --git a/lib/main.ts b/lib/main.ts index 66cd813c..bc7d0e12 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -16,7 +16,7 @@ import { UpdateAvailableResult, UpdateEventsListener, } from './type'; -import { assertRelease, logger, testUrls } from './utils'; +import { assertRelease, logger, promiseAny, testUrls } from './utils'; export { setCustomEndpoints }; const { version: v, @@ -167,8 +167,8 @@ export async function checkUpdate(APPKEY: string) { const backupEndpoints = await updateBackupEndpoints(); if (backupEndpoints) { try { - resp = await Promise.race( - backupEndpoints.map((endpoint) => + resp = await promiseAny( + backupEndpoints.map(endpoint => fetch(getCheckUrl(APPKEY, endpoint), fetchPayload), ), ); @@ -205,7 +205,7 @@ function checkOperation( if (!Array.isArray(op)) { return; } - op.forEach((action) => { + op.forEach(action => { if (action.type === 'block') { blockUpdate = { reason: action.reason, @@ -250,7 +250,7 @@ export async function downloadUpdate( const downloadCallback = eventListeners.onDownloadProgress; progressHandler = eventEmitter.addListener( 'RCTPushyDownloadProgress', - (progressData) => { + progressData => { if (progressData.hash === options.hash) { downloadCallback(progressData); } diff --git a/lib/utils.ts b/lib/utils.ts index f7a3c99d..921de601 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -1,9 +1,26 @@ -import { Platform } from "react-native"; +import { Platform } from 'react-native'; export function logger(...args: any[]) { console.log('Pushy: ', ...args); } +export function promiseAny(promises: Promise[]) { + return new Promise((resolve, reject) => { + let count = 0; + + promises.forEach(promise => { + Promise.resolve(promise) + .then(resolve) + .catch(() => { + count++; + if (count === promises.length) { + reject(new Error('All promises were rejected')); + } + }); + }); + }); +} + export function assertRelease() { if (__DEV__) { throw new Error('react-native-update 只能在 RELEASE 版本中运行.'); @@ -17,16 +34,13 @@ const ping = Promise.race([ fetch(url, { method: 'HEAD', - }) - .then(({ status }) => (status === 200 ? url : null)) - .catch(() => null), + }).then(({ status }) => (status === 200 ? url : null)), new Promise(r => setTimeout(() => r(null), 2000)), ]); - export const testUrls = async (urls?: string[]) => { if (!urls?.length) { return null; } - return Promise.race(urls.map(ping)).catch(() => null); + return promiseAny(urls.map(ping)).catch(() => null); }; diff --git a/package.json b/package.json index 0d26da43..60b61cf1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.1", + "version": "9.2.2", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { @@ -67,5 +67,6 @@ "react-native": "^0.72.6", "ts-jest": "^29.0.3", "typescript": "^5.2.2" - } + }, + "packageManager": "yarn@1.22.21+sha1.1959a18351b811cdeedbd484a8f86c3cc3bbaf72" } From d180702ebfce1bd793603ff63ec380623190be7a Mon Sep 17 00:00:00 2001 From: "sunny.luo" Date: 2024年12月13日 18:47:25 +0800 Subject: [PATCH 4/9] v9.2.3 --- lib/utils.ts | 39 +++++++++++++++++++++++++++++++++------ package.json | 2 +- 2 files changed, 34 insertions(+), 7 deletions(-) diff --git a/lib/utils.ts b/lib/utils.ts index 921de601..0aae1579 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -8,7 +8,7 @@ export function promiseAny(promises: Promise[]) { return new Promise((resolve, reject) => { let count = 0; - promises.forEach(promise => { + promises.forEach((promise) => { Promise.resolve(promise) .then(resolve) .catch(() => { @@ -30,17 +30,44 @@ export function assertRelease() { const ping = Platform.OS === 'web' ? Promise.resolve - : async (url: string) => - Promise.race([ + : async (url: string) => { + let pingFinished = false; + return Promise.race([ fetch(url, { method: 'HEAD', - }).then(({ status }) => (status === 200 ? url : null)), - new Promise(r => setTimeout(() => r(null), 2000)), + }) + .then(({ status, statusText }) => { + pingFinished = true; + if (status === 200) { + return url; + } + logger('ping failed', url, status, statusText); + return null; + }) + .catch((e) => { + pingFinished = true; + logger('ping error', url, e); + return null; + }), + new Promise((r) => + setTimeout(() => { + r(null); + if (!pingFinished) { + logger('ping timeout', url); + } + }, 2000), + ), ]); + }; export const testUrls = async (urls?: string[]) => { if (!urls?.length) { return null; } - return promiseAny(urls.map(ping)).catch(() => null); + const ret = await promiseAny(urls.map(ping)); + if (ret) { + return ret; + } + logger('all ping failed, use first url:', urls[0]); + return urls[0]; }; diff --git a/package.json b/package.json index 60b61cf1..53a28ab1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.2", + "version": "9.2.3", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From 0ced603d9797316fa72f731ce48382c4a5e1f086 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: Mon, 7 Apr 2025 15:27:26 +0800 Subject: [PATCH 5/9] fix testurls --- lib/utils.ts | 8 ++++---- package.json | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/lib/utils.ts b/lib/utils.ts index 0aae1579..2954bab0 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -42,16 +42,16 @@ const ping = return url; } logger('ping failed', url, status, statusText); - return null; + throw new Error('Ping failed'); }) .catch((e) => { pingFinished = true; logger('ping error', url, e); - return null; + throw e; }), - new Promise((r) => + new Promise((_, reject) => setTimeout(() => { - r(null); + reject(new Error('Ping timeout')); if (!pingFinished) { logger('ping timeout', url); } diff --git a/package.json b/package.json index 53a28ab1..e262aa7a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.3", + "version": "9.2.4", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From f01df80b5c205b5119440313a653809f284ce112 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2025年4月10日 12:17:15 +0800 Subject: [PATCH 6/9] cleanup --- lib/utils.ts | 10 ++++++---- package.json | 2 +- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/lib/utils.ts b/lib/utils.ts index 2954bab0..e38e8dc8 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -64,10 +64,12 @@ export const testUrls = async (urls?: string[]) => { if (!urls?.length) { return null; } - const ret = await promiseAny(urls.map(ping)); - if (ret) { - return ret; - } + try { + const ret = await promiseAny(urls.map(ping)); + if (ret) { + return ret; + } + } catch {} logger('all ping failed, use first url:', urls[0]); return urls[0]; }; diff --git a/package.json b/package.json index e262aa7a..9e77f73a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.4", + "version": "9.2.5", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From 0d145bf8a0aae7ae237df5571ad9f98ebf1910b9 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2025年8月30日 11:45:47 +0800 Subject: [PATCH 7/9] feat: implement enhancedFetch for improved error handling and fallback support --- .gitignore | 1 + lib/main.ts | 6 +++--- lib/utils.ts | 33 ++++++++++++++++++++++++++++++++- package.json | 2 +- 4 files changed, 37 insertions(+), 5 deletions(-) diff --git a/.gitignore b/.gitignore index 7c639035..80ec3be0 100644 --- a/.gitignore +++ b/.gitignore @@ -46,3 +46,4 @@ Example/**/.pushy Example/testHotUpdate/artifacts yarn-error.log +.cursor/mcp.json diff --git a/lib/main.ts b/lib/main.ts index bc7d0e12..0f3bb6b2 100644 --- a/lib/main.ts +++ b/lib/main.ts @@ -16,7 +16,7 @@ import { UpdateAvailableResult, UpdateEventsListener, } from './type'; -import { assertRelease, logger, promiseAny, testUrls } from './utils'; +import { assertRelease, enhancedFetch, logger, promiseAny, testUrls } from './utils'; export { setCustomEndpoints }; const { version: v, @@ -158,7 +158,7 @@ export async function checkUpdate(APPKEY: string) { }; let resp; try { - resp = await fetch(getCheckUrl(APPKEY), fetchPayload); + resp = await enhancedFetch(getCheckUrl(APPKEY), fetchPayload); } catch (e) { report({ type: 'errorChecking', @@ -169,7 +169,7 @@ export async function checkUpdate(APPKEY: string) { try { resp = await promiseAny( backupEndpoints.map(endpoint => - fetch(getCheckUrl(APPKEY, endpoint), fetchPayload), + enhancedFetch(getCheckUrl(APPKEY, endpoint), fetchPayload), ), ); } catch {} diff --git a/lib/utils.ts b/lib/utils.ts index e38e8dc8..b998c039 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -33,7 +33,7 @@ const ping = : async (url: string) => { let pingFinished = false; return Promise.race([ - fetch(url, { + enhancedFetch(url, { method: 'HEAD', }) .then(({ status, statusText }) => { @@ -73,3 +73,34 @@ export const testUrls = async (urls?: string[]) => { logger('all ping failed, use first url:', urls[0]); return urls[0]; }; + + + +// export const isAndroid70AndBelow = () => { +// // android 7.0 and below devices do not support letsencrypt cert +// // https://letsencrypt.org/2023/07/10/cross-sign-expiration/ +// return Platform.OS === 'android' && Platform.Version <= 24; +// }; + +export const enhancedFetch = async ( + url: string, + params: Parameters[1], + isRetry = false, +) => { + return fetch(url, params) + .then((r) => { + if (r.ok) { + return r; + } + throw new Error(`${r.status} ${r.statusText}`); + }) + .catch((e) => { + logger('fetch error', url, e); + if (isRetry) { + throw e; + } + logger('trying fallback to http'); + return enhancedFetch(url.replace('https', 'http'), params, true); + }); +}; + diff --git a/package.json b/package.json index 9e77f73a..fc6a6135 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.5", + "version": "9.2.6", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From 19f04bcc4cd3b546099cbff22ac1edcf73808d45 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2025年8月30日 11:49:31 +0800 Subject: [PATCH 8/9] chore: bump version to 9.2.7 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index fc6a6135..51616386 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.6", + "version": "9.2.7", "description": "react-native hot update", "main": "lib/index.ts", "scripts": { From 8b4a2b98d05f741fe64e31bceaa00a0e24314d29 Mon Sep 17 00:00:00 2001 From: sunnylqm Date: 2025年11月27日 14:57:52 +0800 Subject: [PATCH 9/9] v9.2.8 --- lib/utils.ts | 6 ------ package.json | 2 +- 2 files changed, 1 insertion(+), 7 deletions(-) diff --git a/lib/utils.ts b/lib/utils.ts index b998c039..06768e65 100644 --- a/lib/utils.ts +++ b/lib/utils.ts @@ -88,12 +88,6 @@ export const enhancedFetch = async ( isRetry = false, ) => { return fetch(url, params) - .then((r) => { - if (r.ok) { - return r; - } - throw new Error(`${r.status} ${r.statusText}`); - }) .catch((e) => { logger('fetch error', url, e); if (isRetry) { diff --git a/package.json b/package.json index 51616386..ffce3e04 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "react-native-update", - "version": "9.2.7", + "version": "9.2.8", "description": "react-native hot update", "main": "lib/index.ts", "scripts": {

AltStyle によって変換されたページ (->オリジナル) /