1
0
mirror of https://gitcode.com/gh_mirrors/re/react-native-pushy.git synced 2025-09-17 19:16:10 +08:00
Code Issues Packages Projects Releases Wiki Activity GitHub Gitee

Compare commits

..

28 Commits

Author SHA1 Message Date
sunnylqm
3e02ff6099 v10.13.2 2024-08-26 18:57:13 +08:00
sunnylqm
462a342172 v10.13.1 2024-08-26 18:54:17 +08:00
sunnylqm
94d2e18900 v10.13.0 2024-08-26 18:52:44 +08:00
sunnylqm
d000c40e0f v10.12.0 2024-08-24 15:28:27 +08:00
sunnylqm
5659c79726 v10.11.8 2024-08-21 20:02:47 +08:00
sunnylqm
b20d987473 fix marksuccess 2024-08-21 19:58:28 +08:00
sunnylqm
14c9c0b1f5 v10.11.7 2024-08-16 11:03:25 +08:00
sunnylqm
10178e1e64 chore: Update switchVersion and switchVersionLater to be async functions 2024-08-16 10:49:35 +08:00
sunnylqm
6d980a4c04 v10.11.6 2024-08-06 13:13:05 +08:00
sunnylqm
084fbf35ee fix typo 2024-08-06 13:12:32 +08:00
sunnylqm
d666e8c0f3 v10.11.5 2024-08-01 11:00:39 +08:00
sunnylqm
5e89fb4a25 v10.11.4 2024-07-31 18:06:05 +08:00
sunnylqm
ab01b6010a update example 2024-07-30 09:42:33 +08:00
sunnylqm
92bc830d98 update example 2024-07-29 23:25:33 +08:00
sunnylqm
7531e8ca3a v10.11.3 2024-07-29 22:40:55 +08:00
sunnylqm
b2305cff3f v10.11.2 2024-07-29 00:57:30 +08:00
sunnylqm
c5cdb6031b v10.11.1 2024-07-29 00:45:30 +08:00
sunnylqm
20ebf8979e fix url params 2024-07-29 00:45:10 +08:00
sunnylqm
3929fc2f8e add crunchPngs false 2024-07-28 22:22:21 +08:00
sunnylqm
31ee269717 fix qrcode 2024-07-28 22:20:33 +08:00
sunnylqm
adcd57b6b5 update example 2024-07-28 21:57:33 +08:00
sunnylqm
c595e4e54a v10.11.0 2024-07-28 21:30:26 +08:00
sunnylqm
4f80f96a8d parseTestPayload 2024-07-28 21:26:21 +08:00
Sunny Luo
a77c3c85f3 Update endpoints.json 2024-07-27 22:06:59 +08:00
sunnylqm
2357a0b78d update queryurls 2024-07-27 17:37:54 +08:00
sunnylqm
88bacdfb15 v10.10.3 2024-07-27 17:37:43 +08:00
sunnylqm
90fee03c45 v10.10.2 2024-07-27 16:55:36 +08:00
sunnylqm
7243512d3c v10.10.2 2024-07-27 16:54:24 +08:00
16 changed files with 234 additions and 107 deletions

View File

@@ -94,7 +94,7 @@ apply from: "../../node_modules/react-native/react.gradle"
* Upload all the APKs to the Play Store and people will download * Upload all the APKs to the Play Store and people will download
* the correct one based on the CPU architecture of their device. * the correct one based on the CPU architecture of their device.
*/ */
def enableSeparateBuildPerCPUArchitecture = false def enableSeparateBuildPerCPUArchitecture = true
/** /**
* Run Proguard to shrink the Java bytecode in release builds. * Run Proguard to shrink the Java bytecode in release builds.
@@ -141,7 +141,7 @@ android {
minSdkVersion rootProject.ext.minSdkVersion minSdkVersion rootProject.ext.minSdkVersion
targetSdkVersion rootProject.ext.targetSdkVersion targetSdkVersion rootProject.ext.targetSdkVersion
versionCode 1 versionCode 1
versionName "1.0" versionName "2.0"
testBuildType System.getProperty('testBuildType', 'debug') testBuildType System.getProperty('testBuildType', 'debug')
testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner' testInstrumentationRunner 'androidx.test.runner.AndroidJUnitRunner'
buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString() buildConfigField "boolean", "IS_NEW_ARCHITECTURE_ENABLED", isNewArchitectureEnabled().toString()
@@ -237,6 +237,7 @@ android {
release { release {
// Caution! In production, you need to generate your own keystore file. // Caution! In production, you need to generate your own keystore file.
// see https://reactnative.dev/docs/signed-apk-android. // see https://reactnative.dev/docs/signed-apk-android.
crunchPngs false
signingConfig signingConfigs.debug signingConfig signingConfigs.debug
minifyEnabled enableProguardInReleaseBuilds minifyEnabled enableProguardInReleaseBuilds
proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro" proguardFiles getDefaultProguardFile("proguard-android.txt"), "proguard-rules.pro"

View File

@@ -21,8 +21,14 @@
android:windowSoftInputMode="adjustResize" android:windowSoftInputMode="adjustResize"
android:exported="true"> android:exported="true">
<intent-filter> <intent-filter>
<action android:name="android.intent.action.MAIN" /> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
<data android:scheme="testhotupdate" />
</intent-filter> </intent-filter>
</activity> </activity>
</application> </application>

View File

@@ -20,7 +20,7 @@
"react-native-camera-kit": "^14.0.0-beta15", "react-native-camera-kit": "^14.0.0-beta15",
"react-native-paper": "^5.12.1", "react-native-paper": "^5.12.1",
"react-native-safe-area-context": "^4.8.2", "react-native-safe-area-context": "^4.8.2",
"react-native-update": "^10.10.0", "react-native-update": "^10.11.3",
"react-native-vector-icons": "^10.0.3" "react-native-vector-icons": "^10.0.3"
}, },
"devDependencies": { "devDependencies": {

View File

@@ -1,6 +1,6 @@
/* eslint-disable react/no-unstable-nested-components */ /* eslint-disable react/no-unstable-nested-components */
/* eslint-disable react-native/no-inline-styles */ /* eslint-disable react-native/no-inline-styles */
import React, {useState} from 'react'; import React, {useRef, useState} from 'react';
import { import {
StyleSheet, StyleSheet,
Platform, Platform,
@@ -37,7 +37,7 @@ function App() {
updateInfo, updateInfo,
packageVersion, packageVersion,
currentHash, currentHash,
parseTestPayload, parseTestQrCode,
progress: {received, total} = {}, progress: {received, total} = {},
} = usePushy(); } = usePushy();
const [useDefaultAlert, setUseDefaultAlert] = useState(true); const [useDefaultAlert, setUseDefaultAlert] = useState(true);
@@ -47,6 +47,7 @@ function App() {
const snackbarVisible = const snackbarVisible =
!useDefaultAlert && showUpdateSnackbar && updateInfo?.update; !useDefaultAlert && showUpdateSnackbar && updateInfo?.update;
const [showCamera, setShowCamera] = useState(false); const [showCamera, setShowCamera] = useState(false);
const lastParsedCode = useRef('');
return ( return (
<View style={styles.container}> <View style={styles.container}>
@@ -73,9 +74,16 @@ function App() {
style={{minHeight: 320}} style={{minHeight: 320}}
scanBarcode={true} scanBarcode={true}
onReadCode={({nativeEvent: {codeStringValue}}) => { onReadCode={({nativeEvent: {codeStringValue}}) => {
console.log(codeStringValue); // 防止重复扫码
parseTestPayload(codeStringValue); if (lastParsedCode.current === codeStringValue) {
return;
}
lastParsedCode.current = codeStringValue;
setTimeout(() => {
lastParsedCode.current = '';
}, 1000);
setShowCamera(false); setShowCamera(false);
parseTestQrCode(codeStringValue);
}} // optional }} // optional
showFrame={true} // (default false) optional, show frame with transparent layer (qr code or barcode will be read on this area ONLY), start animation for scanner, that stops when a code has been found. Frame always at center of the screen showFrame={true} // (default false) optional, show frame with transparent layer (qr code or barcode will be read on this area ONLY), start animation for scanner, that stops when a code has been found. Frame always at center of the screen
laserColor="red" // (default red) optional, color of laser in scanner frame laserColor="red" // (default red) optional, color of laser in scanner frame

View File

@@ -2123,7 +2123,7 @@ buffer-from@^1.0.0:
resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5" resolved "https://registry.yarnpkg.com/buffer-from/-/buffer-from-1.1.2.tgz#2b146a6fd72e80b4f55d255f35ed59a3a9a41bd5"
integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ== integrity sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==
buffer@^5.5.0: buffer@^5.4.3, buffer@^5.5.0:
version "5.7.1" version "5.7.1"
resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" resolved "https://registry.yarnpkg.com/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
@@ -6159,7 +6159,7 @@ pump@^3.0.0:
end-of-stream "^1.1.0" end-of-stream "^1.1.0"
once "^1.3.1" once "^1.3.1"
punycode@^2.1.0: punycode@^2.1.0, punycode@^2.1.1:
version "2.3.1" version "2.3.1"
resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5" resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.1.tgz#027422e2faec0b25e1549c3e1bd8309b9133b6e5"
integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg== integrity sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==
@@ -6236,12 +6236,20 @@ react-native-safe-area-context@^4.8.2:
resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz#e6b3d8acf3c6afcb4b5db03a97f9c37df7668f65" resolved "https://registry.yarnpkg.com/react-native-safe-area-context/-/react-native-safe-area-context-4.8.2.tgz#e6b3d8acf3c6afcb4b5db03a97f9c37df7668f65"
integrity sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ== integrity sha512-ffUOv8BJQ6RqO3nLml5gxJ6ab3EestPiyWekxdzO/1MQ7NF8fW1Mzh1C5QE9yq573Xefnc7FuzGXjtesZGv7cQ==
react-native-update@^10.10.0: react-native-update@^10.11.3:
version "10.10.0" version "10.11.3"
resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.10.0.tgz#5861f0c217d1ed194e1a8aba81fed5430178795c" resolved "https://registry.yarnpkg.com/react-native-update/-/react-native-update-10.11.3.tgz#5fa44fdd12514eb5e7901a5d664f00fd082d6774"
integrity sha512-qZd5kJ9UlNh5Y0zU5vLdIviYwLvTPqdgIynmt4DQ1wEUu2/F6RrI17dICq54em5ValQWB6ua/tdj2lyTVPvADg== integrity sha512-adI3sly0yFt1DfaPqICJ9VwzUoa/XAngv/N7SnICkLxO3jgccBgy0OrXDBxRn43Zeumdq40Z+ADTE5qrY4BWAw==
dependencies: dependencies:
nanoid "^3.3.3" nanoid "^3.3.3"
react-native-url-polyfill "^2.0.0"
react-native-url-polyfill@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==
dependencies:
whatwg-url-without-unicode "8.0.0-3"
react-native-vector-icons@^10.0.3: react-native-vector-icons@^10.0.3:
version "10.0.3" version "10.0.3"
@@ -7490,11 +7498,25 @@ webidl-conversions@^3.0.0:
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
webidl-conversions@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
whatwg-fetch@^3.0.0: whatwg-fetch@^3.0.0:
version "3.6.20" version "3.6.20"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz#580ce6d791facec91d37c72890995a0b48d31c70"
integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg== integrity sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==
whatwg-url-without-unicode@8.0.0-3:
version "8.0.0-3"
resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
dependencies:
buffer "^5.4.3"
punycode "^2.1.1"
webidl-conversions "^5.0.0"
whatwg-url@^5.0.0: whatwg-url@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" resolved "https://registry.yarnpkg.com/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"

View File

@@ -8,7 +8,7 @@
### 优势 ### 优势
1. 基于阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。 1. 对中国用户使用阿里云高速 CDN 分发,对比其他服务器在国外的热更新服务,分发更稳定,更新成功率极高。对国外用户则智能分流至 cloudflare同样享受高速更新服务。
2. 基于 bsdiff/hdiff 算法创建的**超小更新包**,通常版本迭代后在几十 KB 级别(其他全量热更新服务所需流量通常在几十 MB 级别)。 2. 基于 bsdiff/hdiff 算法创建的**超小更新包**,通常版本迭代后在几十 KB 级别(其他全量热更新服务所需流量通常在几十 MB 级别)。
3. 始终跟进 RN 最新正式版本,第一时间提供支持。支持 hermes 字节码格式。支持新架构。 3. 始终跟进 RN 最新正式版本,第一时间提供支持。支持 hermes 字节码格式。支持新架构。
4. 跨越多个版本进行更新时,只需要下载**一个更新包**,不需要逐版本依次更新。 4. 跨越多个版本进行更新时,只需要下载**一个更新包**,不需要逐版本依次更新。
@@ -33,4 +33,3 @@ $ yarn start
本组件由[React Native 中文网](https://reactnative.cn/)独家发布,如有定制需求可以[联系我们](https://reactnative.cn/about.html#content)。 本组件由[React Native 中文网](https://reactnative.cn/)独家发布,如有定制需求可以[联系我们](https://reactnative.cn/about.html#content)。
关于此插件发现任何问题,可以前往[Issues](https://github.com/reactnativecn/react-native-pushy/issues)发帖提问。 关于此插件发现任何问题,可以前往[Issues](https://github.com/reactnativecn/react-native-pushy/issues)发帖提问。

View File

@@ -1 +1 @@
["https://update.react-native.cn/api", "https://update.reactnative.cn/api", "https://p.reactnative.cn/api"] ["https://pushy-koa-qgbgqmcpis.cn-beijing.fcapp.run", "https://p.reactnative.cn/api"]

View File

@@ -75,7 +75,7 @@ RCT_EXPORT_MODULE(RCTPushy);
if (needClearPushyInfo) { if (needClearPushyInfo) {
[defaults setObject:nil forKey:keyPushyInfo]; [defaults setObject:nil forKey:keyPushyInfo];
[defaults setObject:@(YES) forKey:KeyPackageUpdatedMarked]; [defaults setObject:@(YES) forKey:KeyPackageUpdatedMarked];
[defaults synchronize];
// ...need clear files later // ...need clear files later
} }
else { else {
@@ -97,7 +97,7 @@ RCT_EXPORT_MODULE(RCTPushy);
newInfo[paramIsFirstTime] = @(NO); newInfo[paramIsFirstTime] = @(NO);
[defaults setObject:newInfo forKey:keyPushyInfo]; [defaults setObject:newInfo forKey:keyPushyInfo];
[defaults setObject:@(YES) forKey:keyFirstLoadMarked]; [defaults setObject:@(YES) forKey:keyFirstLoadMarked];
[defaults synchronize];
} }
NSString *downloadDir = [RCTPushy downloadDir]; NSString *downloadDir = [RCTPushy downloadDir];
@@ -137,7 +137,7 @@ RCT_EXPORT_MODULE(RCTPushy);
[defaults setObject:nil forKey:keyPushyInfo]; [defaults setObject:nil forKey:keyPushyInfo];
} }
[defaults setObject:curVersion forKey:keyRolledBackMarked]; [defaults setObject:curVersion forKey:keyRolledBackMarked];
[defaults synchronize];
return lastVersion; return lastVersion;
} }
@@ -176,7 +176,7 @@ RCT_EXPORT_MODULE(RCTPushy);
[defaults setObject:nil forKey:KeyPackageUpdatedMarked]; [defaults setObject:nil forKey:KeyPackageUpdatedMarked];
[self clearInvalidFiles]; [self clearInvalidFiles];
} }
[defaults synchronize];
return ret; return ret;
} }
@@ -196,7 +196,7 @@ RCT_EXPORT_METHOD(setUuid:(NSString *)uuid resolver:(RCTPromiseResolveBlock)res
@try { @try {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:uuid forKey:keyUuid]; [defaults setObject:uuid forKey:keyUuid];
[defaults synchronize];
resolve(@true); resolve(@true);
} }
@catch (NSException *exception) { @catch (NSException *exception) {
@@ -214,7 +214,7 @@ RCT_EXPORT_METHOD(setLocalHashInfo:(NSString *)hash
if (object && [object isKindOfClass:[NSDictionary class]]) { if (object && [object isKindOfClass:[NSDictionary class]]) {
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]]; [defaults setObject:value forKey:[keyHashInfo stringByAppendingString:hash]];
[defaults synchronize];
resolve(@true); resolve(@true);
} else { } else {
reject(@"json格式校验报错", nil, nil); reject(@"json格式校验报错", nil, nil);
@@ -295,7 +295,7 @@ RCT_EXPORT_METHOD(setNeedUpdate:(NSDictionary *)options
newInfo[paramPackageVersion] = [RCTPushy packageVersion]; newInfo[paramPackageVersion] = [RCTPushy packageVersion];
[defaults setObject:newInfo forKey:keyPushyInfo]; [defaults setObject:newInfo forKey:keyPushyInfo];
[defaults synchronize];
resolve(@true); resolve(@true);
}else{ }else{
reject(@"执行报错", nil, nil); reject(@"执行报错", nil, nil);
@@ -329,8 +329,7 @@ RCT_EXPORT_METHOD(reloadUpdate:(NSDictionary *)options
} }
} }
RCT_EXPORT_METHOD(markSuccess: RCT_EXPORT_METHOD(markSuccess:(RCTPromiseResolveBlock)resolve
resolver:(RCTPromiseResolveBlock)resolve
rejecter:(RCTPromiseRejectBlock)reject) rejecter:(RCTPromiseRejectBlock)reject)
{ {
@@ -347,7 +346,7 @@ RCT_EXPORT_METHOD(markSuccess:
[pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]]; [pushyInfo removeObjectForKey:[keyHashInfo stringByAppendingString:lastVersion]];
} }
[defaults setObject:pushyInfo forKey:keyPushyInfo]; [defaults setObject:pushyInfo forKey:keyPushyInfo];
[defaults synchronize];
// clear other package dir // clear other package dir
[self clearInvalidFiles]; [self clearInvalidFiles];
@@ -610,7 +609,7 @@ RCT_EXPORT_METHOD(markSuccess:
- (std::shared_ptr<facebook::react::TurboModule>)getTurboModule: - (std::shared_ptr<facebook::react::TurboModule>)getTurboModule:
(const facebook::react::ObjCTurboModule::InitParams &)params (const facebook::react::ObjCTurboModule::InitParams &)params
{ {
return std::make_shared<facebook::react::NativeUpdateSpecJSI>(params); return std::make_shared<facebook::react::NativePushySpecJSI>(params);
} }
#endif #endif

View File

@@ -1,6 +1,6 @@
{ {
"name": "react-native-update", "name": "react-native-update",
"version": "10.10.1", "version": "10.13.2",
"description": "react-native hot update", "description": "react-native hot update",
"main": "src/index", "main": "src/index",
"scripts": { "scripts": {
@@ -45,7 +45,8 @@
}, },
"homepage": "https://github.com/reactnativecn/react-native-pushy#readme", "homepage": "https://github.com/reactnativecn/react-native-pushy#readme",
"dependencies": { "dependencies": {
"nanoid": "^3.3.3" "nanoid": "^3.3.3",
"react-native-url-polyfill": "^2.0.0"
}, },
"codegenConfig": { "codegenConfig": {
"name": "RCTPushySpec", "name": "RCTPushySpec",

View File

@@ -1,5 +1,5 @@
import { CheckResult, PushyOptions, ProgressData, EventType } from './type'; import { CheckResult, PushyOptions, ProgressData, EventType } from './type';
import { log, testUrls } from './utils'; import { joinUrls, log, testUrls } from './utils';
import { EmitterSubscription, Platform } from 'react-native'; import { EmitterSubscription, Platform } from 'react-native';
import { PermissionsAndroid } from './permissions'; import { PermissionsAndroid } from './permissions';
import { import {
@@ -17,8 +17,10 @@ import {
const defaultServer = { const defaultServer = {
main: 'https://update.react-native.cn/api', main: 'https://update.react-native.cn/api',
backups: ['https://update.reactnative.cn/api'], backups: ['https://update.reactnative.cn/api'],
queryUrl: queryUrls: [
'https://gitee.com/sunnylqm/react-native-pushy/raw/master/endpoints.json',
'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json', 'https://cdn.jsdelivr.net/gh/reactnativecn/react-native-pushy@master/endpoints.json',
],
}; };
const empty = {}; const empty = {};
@@ -62,8 +64,7 @@ export class Pushy {
setOptions = (options: Partial<PushyOptions>) => { setOptions = (options: Partial<PushyOptions>) => {
for (const [key, value] of Object.entries(options)) { for (const [key, value] of Object.entries(options)) {
if (value !== undefined) { if (value !== undefined) {
// @ts-expect-error (this.options as any)[key] = value;
this.options[key] = value;
if (key === 'logger') { if (key === 'logger') {
if (isRolledBack) { if (isRolledBack) {
this.report({ this.report({
@@ -124,7 +125,7 @@ export class Pushy {
PushyModule.markSuccess(); PushyModule.markSuccess();
this.report({ type: 'markSuccess' }); this.report({ type: 'markSuccess' });
}; };
switchVersion = (hash: string) => { switchVersion = async (hash: string) => {
if (__DEV__) { if (__DEV__) {
console.warn( console.warn(
'您调用了switchVersion方法但是当前是开发环境不会进行任何操作。', '您调用了switchVersion方法但是当前是开发环境不会进行任何操作。',
@@ -134,11 +135,11 @@ export class Pushy {
if (this.assertHash(hash) && !this.applyingUpdate) { if (this.assertHash(hash) && !this.applyingUpdate) {
log('switchVersion: ' + hash); log('switchVersion: ' + hash);
this.applyingUpdate = true; this.applyingUpdate = true;
PushyModule.reloadUpdate({ hash }); return PushyModule.reloadUpdate({ hash });
} }
}; };
switchVersionLater = (hash: string) => { switchVersionLater = async (hash: string) => {
if (__DEV__) { if (__DEV__) {
console.warn( console.warn(
'您调用了switchVersionLater方法但是当前是开发环境不会进行任何操作。', '您调用了switchVersionLater方法但是当前是开发环境不会进行任何操作。',
@@ -147,7 +148,7 @@ export class Pushy {
} }
if (this.assertHash(hash)) { if (this.assertHash(hash)) {
log('switchVersionLater: ' + hash); log('switchVersionLater: ' + hash);
PushyModule.setNeedUpdate({ hash }); return PushyModule.setNeedUpdate({ hash });
} }
}; };
checkUpdate = async (extra?: Record<string, any>) => { checkUpdate = async (extra?: Record<string, any>) => {
@@ -161,6 +162,13 @@ export class Pushy {
console.warn('web 端不支持热更新检查'); console.warn('web 端不支持热更新检查');
return; return;
} }
if (
this.options.beforeCheckUpdate &&
(await this.options.beforeCheckUpdate()) === false
) {
log('beforeCheckUpdate 返回 false, 忽略检查');
return;
}
const now = Date.now(); const now = Date.now();
if ( if (
this.lastRespJson && this.lastRespJson &&
@@ -170,7 +178,6 @@ export class Pushy {
return await this.lastRespJson; return await this.lastRespJson;
} }
this.lastChecking = now; this.lastChecking = now;
this.report({ type: 'checking' });
const fetchBody = { const fetchBody = {
packageVersion, packageVersion,
hash: currentVersion, hash: currentVersion,
@@ -181,16 +188,21 @@ export class Pushy {
if (__DEV__) { if (__DEV__) {
delete fetchBody.buildTime; delete fetchBody.buildTime;
} }
const body = JSON.stringify(fetchBody);
const fetchPayload = { const fetchPayload = {
method: 'POST', method: 'POST',
headers: { headers: {
Accept: 'application/json', Accept: 'application/json',
'Content-Type': 'application/json', 'Content-Type': 'application/json',
}, },
body: JSON.stringify(fetchBody), body,
}; };
let resp; let resp;
try { try {
this.report({
type: 'checking',
message: this.options.appKey + ': ' + body,
});
resp = await fetch(this.getCheckUrl(), fetchPayload); resp = await fetch(this.getCheckUrl(), fetchPayload);
} catch (e: any) { } catch (e: any) {
this.report({ this.report({
@@ -219,6 +231,8 @@ export class Pushy {
const result: CheckResult = await this.lastRespJson; const result: CheckResult = await this.lastRespJson;
log('checking result:', result);
if (resp.status !== 200) { if (resp.status !== 200) {
this.report({ this.report({
type: 'errorChecking', type: 'errorChecking',
@@ -233,9 +247,11 @@ export class Pushy {
if (!server) { if (!server) {
return []; return [];
} }
if (server.queryUrl) { if (server.queryUrls) {
try { try {
const resp = await fetch(server.queryUrl); const resp = await Promise.race(
server.queryUrls.map(queryUrl => fetch(queryUrl)),
);
const remoteEndpoints = await resp.json(); const remoteEndpoints = await resp.json();
log('fetch endpoints:', remoteEndpoints); log('fetch endpoints:', remoteEndpoints);
if (Array.isArray(remoteEndpoints)) { if (Array.isArray(remoteEndpoints)) {
@@ -244,7 +260,7 @@ export class Pushy {
); );
} }
} catch (e: any) { } catch (e: any) {
log('failed to fetch endpoints from: ', server.queryUrl); log('failed to fetch endpoints from: ', server.queryUrls);
} }
} }
return server.backups; return server.backups;
@@ -255,16 +271,21 @@ export class Pushy {
) => { ) => {
const { const {
hash, hash,
diffUrl: _diffUrl, diff,
diffUrls, pdiff,
pdiffUrl: _pdiffUrl, full,
pdiffUrls, paths = [],
updateUrl: _updateUrl,
updateUrls,
name, name,
description, description = '',
metaInfo, metaInfo = '',
} = info; } = info;
if (
this.options.beforeDownloadUpdate &&
(await this.options.beforeDownloadUpdate(info)) === false
) {
log('beforeDownloadUpdate 返回 false, 忽略下载');
return;
}
if (!info.update || !hash) { if (!info.update || !hash) {
return; return;
} }
@@ -289,10 +310,10 @@ export class Pushy {
}, },
); );
} }
let succeeded = false; let succeeded = '';
this.report({ type: 'downloading' }); this.report({ type: 'downloading' });
let lastError: any; let lastError: any;
const diffUrl = (await testUrls(diffUrls)) || _diffUrl; const diffUrl = await testUrls(joinUrls(paths, diff));
if (diffUrl) { if (diffUrl) {
log('downloading diff'); log('downloading diff');
try { try {
@@ -301,17 +322,17 @@ export class Pushy {
hash, hash,
originHash: currentVersion, originHash: currentVersion,
}); });
succeeded = true; succeeded = 'diff';
} catch (e: any) { } catch (e: any) {
lastError = e; lastError = e;
if (__DEV__) { if (__DEV__) {
succeeded = true; succeeded = 'diff';
} else { } else {
log(`diff error: ${e.message}, try pdiff`); log(`diff error: ${e.message}, try pdiff`);
} }
} }
} }
const pdiffUrl = (await testUrls(pdiffUrls)) || _pdiffUrl; const pdiffUrl = await testUrls(joinUrls(paths, pdiff));
if (!succeeded && pdiffUrl) { if (!succeeded && pdiffUrl) {
log('downloading pdiff'); log('downloading pdiff');
try { try {
@@ -319,29 +340,29 @@ export class Pushy {
updateUrl: pdiffUrl, updateUrl: pdiffUrl,
hash, hash,
}); });
succeeded = true; succeeded = 'pdiff';
} catch (e: any) { } catch (e: any) {
lastError = e; lastError = e;
if (__DEV__) { if (__DEV__) {
succeeded = true; succeeded = 'pdiff';
} else { } else {
log(`pdiff error: ${e.message}, try full patch`); log(`pdiff error: ${e.message}, try full patch`);
} }
} }
} }
const updateUrl = (await testUrls(updateUrls)) || _updateUrl; const fullUrl = await testUrls(joinUrls(paths, full));
if (!succeeded && updateUrl) { if (!succeeded && fullUrl) {
log('downloading full patch'); log('downloading full patch');
try { try {
await PushyModule.downloadFullUpdate({ await PushyModule.downloadFullUpdate({
updateUrl: updateUrl, updateUrl: fullUrl,
hash, hash,
}); });
succeeded = true; succeeded = 'full';
} catch (e: any) { } catch (e: any) {
lastError = e; lastError = e;
if (__DEV__) { if (__DEV__) {
succeeded = true; succeeded = 'full';
} else { } else {
log(`full patch error: ${e.message}`); log(`full patch error: ${e.message}`);
} }
@@ -363,8 +384,13 @@ export class Pushy {
throw lastError; throw lastError;
} }
return; return;
} else {
this.report({
type: 'downloadSuccess',
data: { newVersion: hash, diff: succeeded },
});
} }
log('downloaded hash:', hash); log(`downloaded ${succeeded} hash:`, hash);
setLocalHashInfo(hash, { setLocalHashInfo(hash, {
name, name,
description, description,

View File

@@ -7,22 +7,22 @@ const asyncNoop = () => Promise.resolve();
export const defaultContext = { export const defaultContext = {
checkUpdate: asyncNoop, checkUpdate: asyncNoop,
switchVersion: noop, switchVersion: asyncNoop,
switchVersionLater: noop, switchVersionLater: asyncNoop,
markSuccess: noop, markSuccess: noop,
dismissError: noop, dismissError: noop,
downloadUpdate: asyncNoop, downloadUpdate: asyncNoop,
downloadAndInstallApk: asyncNoop, downloadAndInstallApk: asyncNoop,
getCurrentVersionInfo: () => Promise.resolve({}), getCurrentVersionInfo: () => Promise.resolve({}),
parseTestPayload: () => Promise.resolve(false), parseTestQrCode: () => false,
currentHash: '', currentHash: '',
packageVersion: '', packageVersion: '',
}; };
export const PushyContext = createContext<{ export const PushyContext = createContext<{
checkUpdate: () => Promise<void>; checkUpdate: () => Promise<void>;
switchVersion: () => void; switchVersion: () => Promise<void>;
switchVersionLater: () => void; switchVersionLater: () => Promise<void>;
markSuccess: () => void; markSuccess: () => void;
dismissError: () => void; dismissError: () => void;
downloadUpdate: () => Promise<void>; downloadUpdate: () => Promise<void>;
@@ -32,7 +32,7 @@ export const PushyContext = createContext<{
description?: string; description?: string;
metaInfo?: string; metaInfo?: string;
}>; }>;
parseTestPayload: (code: string) => Promise<boolean>; parseTestQrCode: (code: string) => boolean;
currentHash: string; currentHash: string;
packageVersion: string; packageVersion: string;
client?: Pushy; client?: Pushy;

View File

@@ -4,9 +4,7 @@ const {
version: v, version: v,
} = require('react-native/Libraries/Core/ReactNativeVersion'); } = require('react-native/Libraries/Core/ReactNativeVersion');
const RNVersion = `${v.major}.${v.minor}.${v.patch}`; const RNVersion = `${v.major}.${v.minor}.${v.patch}`;
const isTurboModuleEnabled = const isTurboModuleEnabled = (global as any).__turboModuleProxy != null;
// @ts-expect-error
global.__turboModuleProxy != null;
export const PushyModule = export const PushyModule =
Platform.OS === 'web' Platform.OS === 'web'

View File

@@ -21,6 +21,7 @@ import {
} from './core'; } from './core';
import { CheckResult, ProgressData, PushyTestPayload } from './type'; import { CheckResult, ProgressData, PushyTestPayload } from './type';
import { PushyContext } from './context'; import { PushyContext } from './context';
import { URL } from 'react-native-url-polyfill';
export const PushyProvider = ({ export const PushyProvider = ({
client, client,
@@ -72,18 +73,18 @@ export const PushyProvider = ({
); );
const switchVersion = useCallback( const switchVersion = useCallback(
(info: CheckResult | undefined = updateInfoRef.current) => { async (info: CheckResult | undefined = updateInfoRef.current) => {
if (info && info.hash) { if (info && info.hash) {
client.switchVersion(info.hash); return client.switchVersion(info.hash);
} }
}, },
[client], [client],
); );
const switchVersionLater = useCallback( const switchVersionLater = useCallback(
(info: CheckResult | undefined = updateInfoRef.current) => { async (info: CheckResult | undefined = updateInfoRef.current) => {
if (info && info.hash) { if (info && info.hash) {
client.switchVersionLater(info.hash); return client.switchVersionLater(info.hash);
} }
}, },
[client], [client],
@@ -146,7 +147,7 @@ export const PushyProvider = ({
); );
const checkUpdate = useCallback( const checkUpdate = useCallback(
async (extra?: Record<string, any>) => { async ({ extra }: { extra?: Record<string, any> } | undefined = {}) => {
const now = Date.now(); const now = Date.now();
if (lastChecking.current && now - lastChecking.current < 1000) { if (lastChecking.current && now - lastChecking.current < 1000) {
return; return;
@@ -263,30 +264,65 @@ export const PushyProvider = ({
}, [checkUpdate, options, dismissError, markSuccess]); }, [checkUpdate, options, dismissError, markSuccess]);
const parseTestPayload = useCallback( const parseTestPayload = useCallback(
async (code: string) => { (payload: PushyTestPayload) => {
let payload: PushyTestPayload; if (payload && payload.type && payload.type.startsWith('__rnPushy')) {
try { const logger = options.logger || (() => {});
payload = JSON.parse(code); options.logger = ({ type, data }) => {
} catch { logger({ type, data });
return false; Alert.alert(type, JSON.stringify(data));
} };
if (payload && payload.type) {
if (payload.type === '__rnPushyVersionHash') { if (payload.type === '__rnPushyVersionHash') {
await checkUpdate({ toHash: payload.data }); checkUpdate({ extra: { toHash: payload.data } }).then(() => {
if (updateInfoRef.current && updateInfoRef.current.upToDate) { if (updateInfoRef.current && updateInfoRef.current.upToDate) {
Alert.alert( Alert.alert(
'提示', '提示',
'当前尚未检测到更新版本如果是首次扫码请等待服务器端生成补丁包后再试约10秒', '当前尚未检测到更新版本如果是首次扫码请等待服务器端生成补丁包后再试约10秒',
); );
} }
return true; options.logger = logger;
});
} }
return true;
} }
return false; return false;
}, },
[checkUpdate], [checkUpdate, options],
); );
const parseTestQrCode = useCallback(
(code: string | PushyTestPayload) => {
try {
const payload = typeof code === 'string' ? JSON.parse(code) : code;
return parseTestPayload(payload);
} catch {
return false;
}
},
[parseTestPayload],
);
useEffect(() => {
const parseLinking = (url: string | null) => {
if (!url) {
return;
}
const params = new URL(url).searchParams;
const payload = {
type: params.get('type'),
data: params.get('data'),
};
parseTestPayload(payload);
};
Linking.getInitialURL().then(parseLinking);
const linkingListener = Linking.addEventListener('url', ({ url }) =>
parseLinking(url),
);
return () => {
linkingListener.remove();
};
}, [parseTestPayload]);
return ( return (
<PushyContext.Provider <PushyContext.Provider
value={{ value={{
@@ -304,7 +340,7 @@ export const PushyProvider = ({
progress, progress,
downloadAndInstallApk, downloadAndInstallApk,
getCurrentVersionInfo, getCurrentVersionInfo,
parseTestPayload, parseTestQrCode,
}}> }}>
{children} {children}
</PushyContext.Provider> </PushyContext.Provider>

View File

@@ -7,12 +7,10 @@ export interface CheckResult {
hash?: string; hash?: string;
description?: string; description?: string;
metaInfo?: string; metaInfo?: string;
pdiffUrl?: string; pdiff?: string;
pdiffUrls?: string[]; diff?: string;
diffUrl?: string; full?: string;
diffUrls?: string[]; paths?: string[];
updateUrl?: string;
updateUrls?: string[];
paused?: 'app' | 'package'; paused?: 'app' | 'package';
message?: string; message?: string;
} }
@@ -28,6 +26,7 @@ export type EventType =
| 'errorChecking' | 'errorChecking'
| 'checking' | 'checking'
| 'downloading' | 'downloading'
| 'downloadSuccess'
| 'errorUpdate' | 'errorUpdate'
| 'markSuccess' | 'markSuccess'
| 'downloadingApk' | 'downloadingApk'
@@ -62,7 +61,7 @@ export type UpdateEventsLogger = ({
export interface PushyServerConfig { export interface PushyServerConfig {
main: string; main: string;
backups?: string[]; backups?: string[];
queryUrl?: string; queryUrls?: string[];
} }
export interface PushyOptions { export interface PushyOptions {
@@ -80,9 +79,11 @@ export interface PushyOptions {
dismissErrorAfter?: number; dismissErrorAfter?: number;
debug?: boolean; debug?: boolean;
throwError?: boolean; throwError?: boolean;
beforeCheckUpdate?: () => Promise<boolean>;
beforeDownloadUpdate?: (info: CheckResult) => Promise<boolean>;
} }
export interface PushyTestPayload { export interface PushyTestPayload {
type: '__rnPushyVersionHash'; type: '__rnPushyVersionHash' | string | null;
data: any; data: any;
} }

View File

@@ -31,9 +31,18 @@ const ping =
const canUseGoogle = ping('https://www.google.com'); const canUseGoogle = ping('https://www.google.com');
export function joinUrls(paths: string[], fileName?: string) {
if (fileName) {
return paths.map(path => 'https://' + path + '/' + fileName);
}
}
export const testUrls = async (urls?: string[]) => { export const testUrls = async (urls?: string[]) => {
if (!urls?.length || (await canUseGoogle)) { if (!urls?.length) {
return null; return null;
} }
if (await canUseGoogle) {
return urls[0];
}
return Promise.race(urls.map(ping)).catch(() => null); return Promise.race(urls.map(ping)).catch(() => null);
}; };

View File

@@ -3198,7 +3198,7 @@ buffer-indexof-polyfill@~1.0.0:
resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c" resolved "https://registry.npmjs.org/buffer-indexof-polyfill/-/buffer-indexof-polyfill-1.0.2.tgz#d2732135c5999c64b277fcf9b1abe3498254729c"
integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A== integrity sha512-I7wzHwA3t1/lwXQh+A5PbNvJxgfo5r3xulgpYDB5zckTu/Z9oUK9biouBKQUjEqzaz3HnAT6TYoovmE+GqSf7A==
buffer@^5.5.0: buffer@^5.4.3, buffer@^5.5.0:
version "5.7.1" version "5.7.1"
resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0" resolved "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz#ba62e7c13133053582197160851a8f648e99eed0"
integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ== integrity sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==
@@ -8604,6 +8604,13 @@ react-is@^17.0.1:
resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0" resolved "https://registry.yarnpkg.com/react-is/-/react-is-17.0.2.tgz#e691d4a8e9c789365655539ab372762b0efb54f0"
integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w== integrity sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==
react-native-url-polyfill@^2.0.0:
version "2.0.0"
resolved "https://registry.yarnpkg.com/react-native-url-polyfill/-/react-native-url-polyfill-2.0.0.tgz#db714520a2985cff1d50ab2e66279b9f91ffd589"
integrity sha512-My330Do7/DvKnEvwQc0WdcBnFPploYKp9CYlefDXzIdEaA+PAhDYllkvGeEroEzvc4Kzzj2O4yVdz8v6fjRvhA==
dependencies:
whatwg-url-without-unicode "8.0.0-3"
react-native@0.73: react-native@0.73:
version "0.73.2" version "0.73.2"
resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.2.tgz#74ee163c8189660d41d1da6560411da7ce41a608" resolved "https://registry.yarnpkg.com/react-native/-/react-native-0.73.2.tgz#74ee163c8189660d41d1da6560411da7ce41a608"
@@ -10174,6 +10181,11 @@ webidl-conversions@^3.0.0:
resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz#24534275e2a7bc6be7bc86611cc16ae0a5654871"
integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ== integrity sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==
webidl-conversions@^5.0.0:
version "5.0.0"
resolved "https://registry.yarnpkg.com/webidl-conversions/-/webidl-conversions-5.0.0.tgz#ae59c8a00b121543a2acc65c0434f57b0fc11aff"
integrity sha512-VlZwKPCkYKxQgeSbH5EyngOmRp7Ww7I9rQLERETtf5ofd9pGeswWiOtogpEO850jziPRarreGxn5QIiTqpb2wA==
whatwg-fetch@^3.0.0: whatwg-fetch@^3.0.0:
version "3.6.19" version "3.6.19"
resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973" resolved "https://registry.yarnpkg.com/whatwg-fetch/-/whatwg-fetch-3.6.19.tgz#caefd92ae630b91c07345537e67f8354db470973"
@@ -10184,6 +10196,15 @@ whatwg-fetch@^3.4.1:
resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c" resolved "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz#dced24f37f2624ed0281725d51d0e2e3fe677f8c"
integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA== integrity sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA==
whatwg-url-without-unicode@8.0.0-3:
version "8.0.0-3"
resolved "https://registry.yarnpkg.com/whatwg-url-without-unicode/-/whatwg-url-without-unicode-8.0.0-3.tgz#ab6df4bf6caaa6c85a59f6e82c026151d4bb376b"
integrity sha512-HoKuzZrUlgpz35YO27XgD28uh/WJH4B0+3ttFqRo//lmq+9T/mIOJ6kqmINI9HpUpz1imRC/nR/lxKpJiv0uig==
dependencies:
buffer "^5.4.3"
punycode "^2.1.1"
webidl-conversions "^5.0.0"
whatwg-url@^5.0.0: whatwg-url@^5.0.0:
version "5.0.0" version "5.0.0"
resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d" resolved "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz#966454e8765462e37644d3626f6742ce8b70965d"