Move the secure-random code into this project due to build issues with the module, which is no longer maintained
parent
2c73703d7d
commit
a56cae626a
|
@ -51,7 +51,7 @@ The `metro.config.js` file rewrites a couple of imports. This is partly to work
|
||||||
|
|
||||||
### Cryptography
|
### Cryptography
|
||||||
|
|
||||||
For native builds, we must provide a polyfill of `webcrypto`. We use [react-native-securerandom](https://github.com/robhogan/react-native-securerandom) for the CRNG and [msrcrypto](https://github.com/kevlened/msrCrypto) for the cryptography.
|
For native builds, we must provide a polyfill of `webcrypto`. We use a custom native module AppSecureRandom (based on [react-native-securerandom](https://github.com/robhogan/react-native-securerandom)) for the CRNG and [msrcrypto](https://github.com/kevlened/msrCrypto) for the cryptography.
|
||||||
|
|
||||||
**NOTE** Keys are not currently stored securely.
|
**NOTE** Keys are not currently stored securely.
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,28 @@
|
||||||
|
package xyz.blueskyweb.pubsq;
|
||||||
|
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.bridge.ReactContextBaseJavaModule;
|
||||||
|
import com.facebook.react.bridge.ReactMethod;
|
||||||
|
import com.facebook.react.bridge.Promise;
|
||||||
|
|
||||||
|
import java.security.SecureRandom;
|
||||||
|
import android.util.Base64;
|
||||||
|
|
||||||
|
public class AppSecureRandomModule extends ReactContextBaseJavaModule {
|
||||||
|
public AppSecureRandomModule(ReactApplicationContext context) {
|
||||||
|
super(context);
|
||||||
|
}
|
||||||
|
|
||||||
|
@ReactMethod
|
||||||
|
public void generateSecureRandomAsBase64(int length, Promise promise) {
|
||||||
|
SecureRandom secureRandom = new SecureRandom();
|
||||||
|
byte[] buffer = new byte[length];
|
||||||
|
secureRandom.nextBytes(buffer);
|
||||||
|
promise.resolve(Base64.encodeToString(buffer, Base64.NO_WRAP));
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getName() {
|
||||||
|
return "AppSecureRandomModule";
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,26 @@
|
||||||
|
package xyz.blueskyweb.pubsq;
|
||||||
|
|
||||||
|
import com.facebook.react.ReactPackage;
|
||||||
|
import com.facebook.react.bridge.NativeModule;
|
||||||
|
import com.facebook.react.bridge.ReactApplicationContext;
|
||||||
|
import com.facebook.react.uimanager.ViewManager;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
|
|
||||||
|
public class AppSecureRandomPackage implements ReactPackage {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public List<NativeModule> createNativeModules(ReactApplicationContext reactContext) {
|
||||||
|
List<NativeModule> modules = new ArrayList<>();
|
||||||
|
modules.add(new AppSecureRandomModule(reactContext));
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -28,6 +28,7 @@ public class MainApplication extends Application implements ReactApplication {
|
||||||
List<ReactPackage> packages = new PackageList(this).getPackages();
|
List<ReactPackage> packages = new PackageList(this).getPackages();
|
||||||
// Packages that cannot be autolinked yet can be added manually here, for example:
|
// Packages that cannot be autolinked yet can be added manually here, for example:
|
||||||
// packages.add(new MyReactNativePackage());
|
// packages.add(new MyReactNativePackage());
|
||||||
|
packages.add(new AppSecureRandomPackage());
|
||||||
return packages;
|
return packages;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,5 @@
|
||||||
|
#import <React/RCTBridgeModule.h>
|
||||||
|
|
||||||
|
@interface AppSecureRandomModule : NSObject <RCTBridgeModule>
|
||||||
|
|
||||||
|
@end
|
|
@ -0,0 +1,27 @@
|
||||||
|
#import "AppSecureRandomModule.h"
|
||||||
|
|
||||||
|
@implementation AppSecureRandomModule
|
||||||
|
|
||||||
|
RCT_EXPORT_MODULE();
|
||||||
|
|
||||||
|
+ (BOOL)requiresMainQueueSetup
|
||||||
|
{
|
||||||
|
return NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
RCT_REMAP_METHOD(generateSecureRandomAsBase64,
|
||||||
|
withLength:(int)length
|
||||||
|
resolver:(RCTPromiseResolveBlock)resolve
|
||||||
|
rejecter:(RCTPromiseRejectBlock)reject)
|
||||||
|
{
|
||||||
|
NSMutableData* bytes = [NSMutableData dataWithLength:length];
|
||||||
|
int result = SecRandomCopyBytes(kSecRandomDefault,length, [bytes mutableBytes]);
|
||||||
|
if (result == errSecSuccess) {
|
||||||
|
resolve([bytes base64EncodedStringWithOptions:0]);
|
||||||
|
} else {
|
||||||
|
NSError *error = [NSError errorWithDomain:@"RNSecureRandom" code:result userInfo: nil];
|
||||||
|
reject(@"randombytes_error", @"Error generating random bytes", error);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
|
@ -296,8 +296,6 @@ PODS:
|
||||||
- RNScreens (3.13.1):
|
- RNScreens (3.13.1):
|
||||||
- React-Core
|
- React-Core
|
||||||
- React-RCTImage
|
- React-RCTImage
|
||||||
- RNSecureRandom (1.0.0):
|
|
||||||
- React
|
|
||||||
- Yoga (1.14.0)
|
- Yoga (1.14.0)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
@ -337,7 +335,6 @@ DEPENDENCIES:
|
||||||
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
- "RNCAsyncStorage (from `../node_modules/@react-native-async-storage/async-storage`)"
|
||||||
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
|
- RNInAppBrowser (from `../node_modules/react-native-inappbrowser-reborn`)
|
||||||
- RNScreens (from `../node_modules/react-native-screens`)
|
- RNScreens (from `../node_modules/react-native-screens`)
|
||||||
- RNSecureRandom (from `../node_modules/react-native-securerandom`)
|
|
||||||
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
- Yoga (from `../node_modules/react-native/ReactCommon/yoga`)
|
||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
|
@ -413,8 +410,6 @@ EXTERNAL SOURCES:
|
||||||
:path: "../node_modules/react-native-inappbrowser-reborn"
|
:path: "../node_modules/react-native-inappbrowser-reborn"
|
||||||
RNScreens:
|
RNScreens:
|
||||||
:path: "../node_modules/react-native-screens"
|
:path: "../node_modules/react-native-screens"
|
||||||
RNSecureRandom:
|
|
||||||
:path: "../node_modules/react-native-securerandom"
|
|
||||||
Yoga:
|
Yoga:
|
||||||
:path: "../node_modules/react-native/ReactCommon/yoga"
|
:path: "../node_modules/react-native/ReactCommon/yoga"
|
||||||
|
|
||||||
|
@ -454,7 +449,6 @@ SPEC CHECKSUMS:
|
||||||
RNCAsyncStorage: 466b9df1a14bccda91da86e0b7d9a345d78e1673
|
RNCAsyncStorage: 466b9df1a14bccda91da86e0b7d9a345d78e1673
|
||||||
RNInAppBrowser: 3ff3a3b8f458aaf25aaee879d057352862edf357
|
RNInAppBrowser: 3ff3a3b8f458aaf25aaee879d057352862edf357
|
||||||
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
|
RNScreens: 40a2cb40a02a609938137a1e0acfbf8fc9eebf19
|
||||||
RNSecureRandom: 0dcee021fdb3d50cd5cee5db0ebf583c42f5af0e
|
|
||||||
Yoga: 99652481fcd320aefa4a7ef90095b95acd181952
|
Yoga: 99652481fcd320aefa4a7ef90095b95acd181952
|
||||||
|
|
||||||
PODFILE CHECKSUM: cf94853ebcb0d8e0d027dca9ab7a4ede886a8f20
|
PODFILE CHECKSUM: cf94853ebcb0d8e0d027dca9ab7a4ede886a8f20
|
||||||
|
|
|
@ -13,6 +13,8 @@
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
13B07FC11A68108700A75B9A /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 13B07FB71A68108700A75B9A /* main.m */; };
|
||||||
5CEAE7B7A55582F96F1D5952 /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB672808307A6013805A3FE /* libPods-app.a */; };
|
5CEAE7B7A55582F96F1D5952 /* libPods-app.a in Frameworks */ = {isa = PBXBuildFile; fileRef = FCB672808307A6013805A3FE /* libPods-app.a */; };
|
||||||
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; };
|
||||||
|
E4BD704B285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */; };
|
||||||
|
E4BD704C285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */; };
|
||||||
FEB90D21557517F9279AECA4 /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */; };
|
FEB90D21557517F9279AECA4 /* libPods-app-appTests.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
|
@ -42,6 +44,8 @@
|
||||||
970005155A83960D1D13380F /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
|
970005155A83960D1D13380F /* Pods-app.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.release.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
BAD3BC60FA05CF2D4F6F9BA2 /* libPods-app-appTests.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app-appTests.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
E4437C9E28581FA7006DA9E7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = app.entitlements; path = app/app.entitlements; sourceTree = "<group>"; };
|
E4437C9E28581FA7006DA9E7 /* app.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; name = app.entitlements; path = app/app.entitlements; sourceTree = "<group>"; };
|
||||||
|
E4BD7049285AD54000A8FED9 /* AppSecureRandomModule.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppSecureRandomModule.h; sourceTree = "<group>"; };
|
||||||
|
E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppSecureRandomModule.m; sourceTree = "<group>"; };
|
||||||
ED22CAA45207BC18E75DB44B /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
|
ED22CAA45207BC18E75DB44B /* Pods-app.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-app.debug.xcconfig"; path = "Target Support Files/Pods-app/Pods-app.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; };
|
||||||
FCB672808307A6013805A3FE /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
FCB672808307A6013805A3FE /* libPods-app.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-app.a"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
@ -94,6 +98,8 @@
|
||||||
13B07FB61A68108700A75B9A /* Info.plist */,
|
13B07FB61A68108700A75B9A /* Info.plist */,
|
||||||
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */,
|
||||||
13B07FB71A68108700A75B9A /* main.m */,
|
13B07FB71A68108700A75B9A /* main.m */,
|
||||||
|
E4BD7049285AD54000A8FED9 /* AppSecureRandomModule.h */,
|
||||||
|
E4BD704A285AD57E00A8FED9 /* AppSecureRandomModule.m */,
|
||||||
);
|
);
|
||||||
name = app;
|
name = app;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
|
@ -369,6 +375,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
00E356F31AD99517003FC87E /* appTests.m in Sources */,
|
00E356F31AD99517003FC87E /* appTests.m in Sources */,
|
||||||
|
E4BD704C285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
@ -377,6 +384,7 @@
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
13B07FBC1A68108700A75B9A /* AppDelegate.mm in Sources */,
|
||||||
|
E4BD704B285AD57E00A8FED9 /* AppSecureRandomModule.m in Sources */,
|
||||||
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
13B07FC11A68108700A75B9A /* main.m in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
|
|
@ -44,7 +44,7 @@
|
||||||
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
|
bridge.surfacePresenter = _bridgeAdapter.surfacePresenter;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"app", nil);
|
UIView *rootView = RCTAppSetupDefaultRootView(bridge, @"xyz.blueskyweb.pubsq", nil);
|
||||||
|
|
||||||
if (@available(iOS 13.0, *)) {
|
if (@available(iOS 13.0, *)) {
|
||||||
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
rootView.backgroundColor = [UIColor systemBackgroundColor];
|
||||||
|
|
|
@ -21,6 +21,7 @@
|
||||||
"@react-navigation/native-stack": "^6.6.2",
|
"@react-navigation/native-stack": "^6.6.2",
|
||||||
"@react-navigation/stack": "^6.2.1",
|
"@react-navigation/stack": "^6.2.1",
|
||||||
"@zxing/text-encoding": "^0.9.0",
|
"@zxing/text-encoding": "^0.9.0",
|
||||||
|
"base64-js": "^1.5.1",
|
||||||
"mobx": "^6.6.0",
|
"mobx": "^6.6.0",
|
||||||
"mobx-react-lite": "^3.4.0",
|
"mobx-react-lite": "^3.4.0",
|
||||||
"mobx-state-tree": "^5.1.5",
|
"mobx-state-tree": "^5.1.5",
|
||||||
|
@ -31,7 +32,6 @@
|
||||||
"react-native-inappbrowser-reborn": "^3.6.3",
|
"react-native-inappbrowser-reborn": "^3.6.3",
|
||||||
"react-native-safe-area-context": "^4.3.1",
|
"react-native-safe-area-context": "^4.3.1",
|
||||||
"react-native-screens": "^3.13.1",
|
"react-native-screens": "^3.13.1",
|
||||||
"react-native-securerandom": "^1.0.0",
|
|
||||||
"react-native-web": "^0.17.7",
|
"react-native-web": "^0.17.7",
|
||||||
"ucans": "0.9.1"
|
"ucans": "0.9.1"
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,17 @@
|
||||||
import {generateSecureRandom} from 'react-native-securerandom'
|
// import {generateSecureRandom} from 'react-native-securerandom'
|
||||||
|
import {NativeModules} from 'react-native'
|
||||||
|
const {AppSecureRandomModule} = NativeModules
|
||||||
|
import {toByteArray} from 'base64-js'
|
||||||
import crypto from 'msrcrypto'
|
import crypto from 'msrcrypto'
|
||||||
import '@zxing/text-encoding' // TextEncoder / TextDecoder
|
import '@zxing/text-encoding' // TextEncoder / TextDecoder
|
||||||
|
|
||||||
|
async function generateSecureRandom(bytes: number) {
|
||||||
|
console.log('a')
|
||||||
|
return toByteArray(
|
||||||
|
await AppSecureRandomModule.generateSecureRandomAsBase64(bytes),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
export const whenWebCrypto = new Promise(async (resolve, reject) => {
|
export const whenWebCrypto = new Promise(async (resolve, reject) => {
|
||||||
try {
|
try {
|
||||||
const bytes = await generateSecureRandom(48)
|
const bytes = await generateSecureRandom(48)
|
||||||
|
|
|
@ -3838,7 +3838,7 @@ balanced-match@^1.0.0:
|
||||||
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee"
|
||||||
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==
|
||||||
|
|
||||||
base64-js@*, base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1:
|
base64-js@^1.1.2, base64-js@^1.3.1, base64-js@^1.5.1:
|
||||||
version "1.5.1"
|
version "1.5.1"
|
||||||
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
resolved "https://registry.yarnpkg.com/base64-js/-/base64-js-1.5.1.tgz#1b1b440160a5bf7ad40b650f095963481903930a"
|
||||||
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
integrity sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==
|
||||||
|
@ -11059,13 +11059,6 @@ react-native-screens@^3.13.1:
|
||||||
react-freeze "^1.0.0"
|
react-freeze "^1.0.0"
|
||||||
warn-once "^0.1.0"
|
warn-once "^0.1.0"
|
||||||
|
|
||||||
react-native-securerandom@^1.0.0:
|
|
||||||
version "1.0.0"
|
|
||||||
resolved "https://registry.yarnpkg.com/react-native-securerandom/-/react-native-securerandom-1.0.0.tgz#1cff2f727c90c9ec3318b42dbf825a628b53b49b"
|
|
||||||
integrity sha512-lnhcsWloFzMN/HffyDBlh4VlqdhDH8uxEzUIH3aJPgC1PxV6OKZkvAk409EwsAhcmG/z3yZuVKegKpUr5IM9ug==
|
|
||||||
dependencies:
|
|
||||||
base64-js "*"
|
|
||||||
|
|
||||||
react-native-web@^0.17.7:
|
react-native-web@^0.17.7:
|
||||||
version "0.17.7"
|
version "0.17.7"
|
||||||
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.17.7.tgz#038899dbc94467a0ca0be214b88a30e0c117b176"
|
resolved "https://registry.yarnpkg.com/react-native-web/-/react-native-web-0.17.7.tgz#038899dbc94467a0ca0be214b88a30e0c117b176"
|
||||||
|
|
Loading…
Reference in New Issue