From 9c13598d38fa9e267dc94029cf4479db5cfd5c69 Mon Sep 17 00:00:00 2001 From: sankalpsingh Date: Mon, 25 May 2026 23:58:40 +0530 Subject: [PATCH 1/2] feat(ios): implement URLProtocol-based network interceptor Brings iOS to full parity with Android. Native layer (6 new files): - NetworkToolsInterceptor: NSURLProtocol subclass that intercepts all HTTP/HTTPS traffic through URLSession (the transport React Native uses on iOS). Marks forwarded requests with a property key to prevent infinite recursion. Caps response body capture at 256 KB; skips binary MIME types entirely. - NetworkToolsStorage: thread-safe NSLock-backed singleton, max 100 requests (mirrors NetworkRequestStorage.kt). - NetworkToolsManager: singleton that owns +activate (registers the URLProtocol, #if DEBUG only) and event emission via the module's RCTEventEmitter reference. Module bridge (updated): - NetworkTools now extends RCTEventEmitter so "NetworkTools:onRequest" events flow through the standard DeviceEventEmitter on both old-arch (bridge) and new-arch (JSI/TurboModule). getTurboModule: retained for new arch. - NetworkTools.podspec exposes NetworkToolsManager.h as a public header so Swift AppDelegates can call NetworkToolsManager.activate() after import NetworkTools. Expo plugin (iOS side added): - applySwiftAppDelegatePatch: adds import NetworkTools and inserts a #if DEBUG NetworkToolsManager.activate() #endif block at the top of application(_:didFinishLaunchingWithOptions:). - applyObjcAppDelegatePatch: same for Objective-C AppDelegate.mm. - Android snippets also updated to include the BuildConfig.DEBUG guard. - Plugin tests expanded from 8 to 18; all 41 suite tests pass. Example app: - AppDelegate.swift updated with the #if DEBUG activation block. README: iOS marked as Supported; setup covers both platforms. Closes #13 Co-Authored-By: Claude Sonnet 4.6 --- NetworkTools.podspec | 5 +- README.md | 61 +++++- .../ios/NetworkToolsExample/AppDelegate.swift | 5 + ios/NetworkTools.h | 12 +- ios/NetworkTools.mm | 77 ++++++- ios/NetworkToolsInterceptor.h | 16 ++ ios/NetworkToolsInterceptor.m | 200 ++++++++++++++++++ ios/NetworkToolsManager.h | 39 ++++ ios/NetworkToolsManager.m | 39 ++++ ios/NetworkToolsStorage.h | 21 ++ ios/NetworkToolsStorage.m | 69 ++++++ plugin/src/index.js | 167 +++++++++++++-- plugin/src/index.test.js | 176 +++++++++++++-- 13 files changed, 838 insertions(+), 49 deletions(-) create mode 100644 ios/NetworkToolsInterceptor.h create mode 100644 ios/NetworkToolsInterceptor.m create mode 100644 ios/NetworkToolsManager.h create mode 100644 ios/NetworkToolsManager.m create mode 100644 ios/NetworkToolsStorage.h create mode 100644 ios/NetworkToolsStorage.m diff --git a/NetworkTools.podspec b/NetworkTools.podspec index dc23366..9d98793 100644 --- a/NetworkTools.podspec +++ b/NetworkTools.podspec @@ -14,7 +14,10 @@ Pod::Spec.new do |s| s.source = { :git => "https://github.com/imsankalp/react-native-network-tools.git", :tag => "#{s.version}" } s.source_files = "ios/**/*.{h,m,mm,cpp}" - s.private_header_files = "ios/**/*.h" + + # NetworkToolsManager.h is public so Swift AppDelegates can call + # [NetworkToolsManager activate] after `import NetworkTools`. + s.public_header_files = "ios/NetworkToolsManager.h" install_modules_dependencies(s) diff --git a/README.md b/README.md index 516d2bd..ced8f5f 100644 --- a/README.md +++ b/README.md @@ -33,33 +33,73 @@ If you use Expo Development Builds, add the plugin to `app.json`: ## Quick Start -### 1. Configure OkHttpClient (Android) +### 1a. Configure OkHttpClient (Android) Add the interceptor to your `MainApplication.kt`: ```kotlin +import com.facebook.react.modules.network.NetworkingModule import com.networktools.NetworkToolsManager import okhttp3.OkHttpClient class MainApplication : Application(), ReactApplication { - override fun onCreate() { super.onCreate() - NetworkingModule.setCustomClientBuilder( - object : NetworkingModule.CustomClientBuilder { - override fun apply(builder: OkHttpClient.Builder) { - NetworkToolsManager.addInterceptor(builder) + if (BuildConfig.DEBUG) { + NetworkingModule.setCustomClientBuilder( + object : NetworkingModule.CustomClientBuilder { + override fun apply(builder: OkHttpClient.Builder) { + NetworkToolsManager.addInterceptor(builder) + } } - } - ) + ) + } // rest code } } ``` +### 1b. Register the URLProtocol interceptor (iOS) + +Add the activation call to your `AppDelegate.swift`: + +```swift +import NetworkTools + +func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil +) -> Bool { + #if DEBUG + NetworkToolsManager.activate() + #endif + + // rest of your setup + return true +} +``` + +For Objective-C `AppDelegate.mm`: + +```objc +#import + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ +#if DEBUG + [NetworkToolsManager activate]; +#endif + // rest of your setup + return YES; +} +``` + +If you use **Expo**, the plugin patches both `MainApplication` and `AppDelegate` automatically during `expo prebuild` — no manual steps needed. + ### 2. Wrap Your App with NetworkMonitorProvider ```typescript @@ -163,9 +203,10 @@ For Expo validation, see the [Expo smoke test](docs/EXPO_SMOKE_TEST.md). | --- | --- | --- | | React Native Android (New Architecture) | ✅ Supported | TurboModule path | | React Native Android (Old Architecture) | ✅ Supported | Legacy bridge fallback | -| Expo Development Build + Prebuild (Android) | ✅ Supported | Use config plugin | +| React Native iOS (New Architecture) | ✅ Supported | URLProtocol + TurboModule | +| React Native iOS (Old Architecture) | ✅ Supported | URLProtocol + legacy bridge | +| Expo Development Build + Prebuild (Android + iOS) | ✅ Supported | Config plugin patches both platforms | | Expo Go | ❌ Not supported | Native interception requires a dev build | -| iOS | 🚧 In progress | Not yet implemented end-to-end | ## Contributing diff --git a/example/ios/NetworkToolsExample/AppDelegate.swift b/example/ios/NetworkToolsExample/AppDelegate.swift index cf8b093..7cf2af0 100644 --- a/example/ios/NetworkToolsExample/AppDelegate.swift +++ b/example/ios/NetworkToolsExample/AppDelegate.swift @@ -2,6 +2,7 @@ import UIKit import React import React_RCTAppDelegate import ReactAppDependencyProvider +import NetworkTools @main class AppDelegate: UIResponder, UIApplicationDelegate { @@ -14,6 +15,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate { _ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil ) -> Bool { + #if DEBUG + NetworkToolsManager.activate() + #endif + let delegate = ReactNativeDelegate() let factory = RCTReactNativeFactory(delegate: delegate) delegate.dependencyProvider = RCTAppDependencyProvider() diff --git a/ios/NetworkTools.h b/ios/NetworkTools.h index c14c987..bca5bd2 100644 --- a/ios/NetworkTools.h +++ b/ios/NetworkTools.h @@ -1,5 +1,15 @@ +#import #import -@interface NetworkTools : NSObject +NS_ASSUME_NONNULL_BEGIN + +/** + * React Native TurboModule that bridges NetworkTools storage to JavaScript. + * Extends RCTEventEmitter so "NetworkTools:onRequest" events flow through the + * standard RN DeviceEventEmitter on both old-arch (bridge) and new-arch (JSI). + */ +@interface NetworkTools : RCTEventEmitter @end + +NS_ASSUME_NONNULL_END diff --git a/ios/NetworkTools.mm b/ios/NetworkTools.mm index e89ffd8..a7df931 100644 --- a/ios/NetworkTools.mm +++ b/ios/NetworkTools.mm @@ -1,21 +1,76 @@ #import "NetworkTools.h" +#import "NetworkToolsStorage.h" +#import "NetworkToolsManager.h" -@implementation NetworkTools -- (NSNumber *)multiply:(double)a b:(double)b { - NSNumber *result = @(a * b); +@implementation NetworkTools { + BOOL _hasListeners; +} + +RCT_EXPORT_MODULE(NetworkTools) + +#pragma mark - RCTEventEmitter - return result; +- (NSArray *)supportedEvents { + return @[@"NetworkTools:onRequest"]; } -- (std::shared_ptr)getTurboModule: - (const facebook::react::ObjCTurboModule::InitParams &)params -{ - return std::make_shared(params); +- (void)startObserving { + _hasListeners = YES; +} + +- (void)stopObserving { + _hasListeners = NO; } -+ (NSString *)moduleName -{ - return @"NetworkTools"; +#pragma mark - Module lifecycle + +- (instancetype)init { + if (self = [super init]) { + [[NetworkToolsManager shared] setEmitter:self]; + } + return self; +} + +- (void)invalidate { + [[NetworkToolsManager shared] setEmitter:nil]; + [super invalidate]; +} + +#pragma mark - NativeNetworkToolsSpec + +- (NSString *)getAllRequests { + NSArray *requests = [[NetworkToolsStorage shared] allRequests]; + NSError *err = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:requests options:0 error:&err]; + if (!data) return @"[]"; + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ?: @"[]"; +} + +- (NSString *)getRequestById:(NSString *)requestId { + NSDictionary *request = [[NetworkToolsStorage shared] requestById:requestId]; + if (!request) return @"{}"; + NSError *err = nil; + NSData *data = [NSJSONSerialization dataWithJSONObject:request options:0 error:&err]; + if (!data) return @"{}"; + return [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding] ?: @"{}"; +} + +- (void)clearAllRequests { + [[NetworkToolsStorage shared] clearAll]; +} + +- (double)getRequestCount { + return (double)[[NetworkToolsStorage shared] count]; +} + +// addListener / removeListeners are inherited from RCTEventEmitter and satisfy +// the NativeNetworkToolsSpec protocol — no override needed. + +#pragma mark - TurboModule + +- (std::shared_ptr)getTurboModule: + (const facebook::react::ObjCTurboModule::InitParams &)params { + return std::make_shared(params); } @end diff --git a/ios/NetworkToolsInterceptor.h b/ios/NetworkToolsInterceptor.h new file mode 100644 index 0000000..6c5c63d --- /dev/null +++ b/ios/NetworkToolsInterceptor.h @@ -0,0 +1,16 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * URLProtocol subclass that intercepts all HTTP/HTTPS requests made through + * URLSession, which is the transport layer React Native's fetch/XMLHttpRequest + * uses on iOS. Mirrors Android's NetworkToolsInterceptor.kt. + * + * Registered via +[NetworkToolsManager activate] — only in DEBUG builds. + */ +@interface NetworkToolsInterceptor : NSURLProtocol + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/NetworkToolsInterceptor.m b/ios/NetworkToolsInterceptor.m new file mode 100644 index 0000000..4ddcaff --- /dev/null +++ b/ios/NetworkToolsInterceptor.m @@ -0,0 +1,200 @@ +#import "NetworkToolsInterceptor.h" +#import "NetworkToolsStorage.h" +#import "NetworkToolsManager.h" + +// Property key used to mark requests this interceptor is already handling, +// preventing infinite recursion when the forwarding URLSession is created. +static NSString *const kNTHandledKey = @"NetworkToolsHandled"; + +// Cap body capture at 256 KB to avoid buffering large binary payloads in RAM. +static const NSInteger kNTMaxBodyBytes = 256 * 1024; + +@interface NetworkToolsInterceptor () +@property (nonatomic, strong) NSURLSessionDataTask *dataTask; +@property (nonatomic, strong) NSMutableData *responseData; +@property (nonatomic, strong, nullable) NSHTTPURLResponse *httpResponse; +@property (nonatomic, assign) double requestStartTime; +@property (nonatomic, copy) NSString *requestId; +@property (nonatomic, copy, nullable) NSString *capturedRequestBody; +@end + +@implementation NetworkToolsInterceptor + +#pragma mark - NSURLProtocol registration + ++ (BOOL)canInitWithRequest:(NSURLRequest *)request { + // Skip requests already being handled by us (prevents infinite loop). + if ([NSURLProtocol propertyForKey:kNTHandledKey inRequest:request]) { + return NO; + } + NSString *scheme = request.URL.scheme.lowercaseString; + return [scheme isEqualToString:@"http"] || [scheme isEqualToString:@"https"]; +} + ++ (NSURLRequest *)canonicalRequestForRequest:(NSURLRequest *)request { + return request; +} + +#pragma mark - Request lifecycle + +- (void)startLoading { + self.requestId = [[NSUUID UUID] UUIDString]; + self.requestStartTime = [NSDate date].timeIntervalSince1970 * 1000.0; + self.responseData = [NSMutableData data]; + self.capturedRequestBody = [self readBodyFromRequest:self.request]; + + // Tag the forwarded request so we don't intercept it again. + NSMutableURLRequest *forwarded = [self.request mutableCopy]; + [NSURLProtocol setProperty:@YES forKey:kNTHandledKey inRequest:forwarded]; + + // Use an ephemeral session so cookies / cache don't bleed between the + // interceptor's internal session and the app's session. + NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; + NSURLSession *session = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + self.dataTask = [session dataTaskWithRequest:forwarded]; + [self.dataTask resume]; +} + +- (void)stopLoading { + [self.dataTask cancel]; + self.dataTask = nil; +} + +#pragma mark - NSURLSessionDataDelegate + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask +didReceiveResponse:(NSURLResponse *)response + completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler { + self.httpResponse = [response isKindOfClass:[NSHTTPURLResponse class]] + ? (NSHTTPURLResponse *)response : nil; + [self.client URLProtocol:self + didReceiveResponse:response + cacheStoragePolicy:NSURLCacheStorageNotAllowed]; + completionHandler(NSURLSessionResponseAllow); +} + +- (void)URLSession:(NSURLSession *)session + dataTask:(NSURLSessionDataTask *)dataTask + didReceiveData:(NSData *)data { + [self.responseData appendData:data]; + [self.client URLProtocol:self didLoadData:data]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +didCompleteWithError:(nullable NSError *)error { + if (error) { + [self.client URLProtocol:self didFailWithError:error]; + } else { + [self.client URLProtocolDidFinishLoading:self]; + } + [self recordWithError:error]; +} + +- (void)URLSession:(NSURLSession *)session + task:(NSURLSessionTask *)task +willPerformHTTPRedirection:(NSHTTPURLResponse *)response + newRequest:(NSURLRequest *)newRequest + completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { + // Pass redirects through transparently; the final response is what gets recorded. + [self.client URLProtocol:self wasRedirectedToRequest:newRequest redirectResponse:response]; + completionHandler(newRequest); +} + +#pragma mark - Recording + +- (void)recordWithError:(nullable NSError *)error { + NSURLRequest *request = self.request; + double responseTime = [NSDate date].timeIntervalSince1970 * 1000.0; + double duration = responseTime - self.requestStartTime; + + NSMutableDictionary *entry = [NSMutableDictionary dictionary]; + entry[@"id"] = self.requestId; + entry[@"url"] = request.URL.absoluteString ?: @""; + entry[@"method"] = request.HTTPMethod ?: @"GET"; + entry[@"requestTime"] = @(self.requestStartTime); + entry[@"responseTime"] = @(responseTime); + entry[@"duration"] = @(duration); + + // Request headers + entry[@"requestHeaders"] = request.allHTTPHeaderFields ?: @{}; + + // Request body (already captured in startLoading before the request was sent) + entry[@"requestBody"] = self.capturedRequestBody ?: @""; + + // Response + NSHTTPURLResponse *response = self.httpResponse; + entry[@"responseCode"] = response ? @(response.statusCode) : @0; + entry[@"responseHeaders"] = response ? response.allHeaderFields : @{}; + + // Response body — skip binary content types, cap text bodies + entry[@"responseBody"] = [self responseBodyStringForResponse:response]; + + // Error + entry[@"error"] = error ? (error.localizedDescription ?: @"Unknown error") : @""; + + [[NetworkToolsStorage shared] addRequest:entry]; + [[NetworkToolsManager shared] emitRequest:entry]; +} + +#pragma mark - Helpers + +- (nullable NSString *)readBodyFromRequest:(NSURLRequest *)request { + NSData *bodyData = nil; + + if (request.HTTPBody.length > 0) { + bodyData = request.HTTPBody; + } else if (request.HTTPBodyStream) { + NSInputStream *stream = request.HTTPBodyStream; + [stream open]; + NSMutableData *buffer = [NSMutableData data]; + uint8_t chunk[4096]; + NSInteger bytesRead; + NSInteger totalRead = 0; + while (totalRead < kNTMaxBodyBytes && + (bytesRead = [stream read:chunk maxLength:sizeof(chunk)]) > 0) { + [buffer appendBytes:chunk length:(NSUInteger)bytesRead]; + totalRead += bytesRead; + } + [stream close]; + bodyData = buffer.length > 0 ? buffer : nil; + } + + if (!bodyData) return nil; + + NSData *capped = bodyData.length <= (NSUInteger)kNTMaxBodyBytes + ? bodyData + : [bodyData subdataWithRange:NSMakeRange(0, (NSUInteger)kNTMaxBodyBytes)]; + return [[NSString alloc] initWithData:capped encoding:NSUTF8StringEncoding]; +} + +- (NSString *)responseBodyStringForResponse:(nullable NSHTTPURLResponse *)response { + // Skip binary MIME types entirely. + NSString *mimeType = response.MIMEType.lowercaseString ?: @""; + if ([mimeType hasPrefix:@"image/"] || + [mimeType hasPrefix:@"video/"] || + [mimeType hasPrefix:@"audio/"] || + [mimeType isEqualToString:@"application/octet-stream"] || + [mimeType isEqualToString:@"application/zip"]) { + return @"[binary content — not captured]"; + } + + if (self.responseData.length == 0) return @""; + + NSData *capped = self.responseData.length <= (NSUInteger)kNTMaxBodyBytes + ? self.responseData + : [self.responseData subdataWithRange:NSMakeRange(0, (NSUInteger)kNTMaxBodyBytes)]; + + NSString *body = [[NSString alloc] initWithData:capped encoding:NSUTF8StringEncoding] ?: @""; + + if (self.responseData.length > (NSUInteger)kNTMaxBodyBytes) { + body = [body stringByAppendingFormat:@"\n[... truncated — %lu bytes total]", + (unsigned long)self.responseData.length]; + } + return body; +} + +@end diff --git a/ios/NetworkToolsManager.h b/ios/NetworkToolsManager.h new file mode 100644 index 0000000..187825b --- /dev/null +++ b/ios/NetworkToolsManager.h @@ -0,0 +1,39 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Singleton that owns activation and event emission for NetworkTools on iOS. + * Mirrors Android's NetworkToolsManager.kt. + * + * Call +activate in AppDelegate wrapped in #if DEBUG: + * + * #if DEBUG + * [NetworkToolsManager activate]; + * #endif + */ +@interface NetworkToolsManager : NSObject + +@property (class, nonatomic, readonly) NetworkToolsManager *shared; + +/** + * Registers the URLProtocol interceptor. No-op in release builds — the entire + * method body is compiled out with #if DEBUG. + */ ++ (void)activate; + +/** + * Called by the native module to hand over its RCTEventEmitter reference so + * the interceptor can emit events to JavaScript. + */ +- (void)setEmitter:(nullable id)emitter; + +/** + * Emits a captured request dictionary as a "NetworkTools:onRequest" event. + * No-op if no emitter is registered or in release builds. + */ +- (void)emitRequest:(NSDictionary *)requestDict; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/NetworkToolsManager.m b/ios/NetworkToolsManager.m new file mode 100644 index 0000000..d2e5a3f --- /dev/null +++ b/ios/NetworkToolsManager.m @@ -0,0 +1,39 @@ +#import "NetworkToolsManager.h" +#import "NetworkToolsInterceptor.h" + +static NSString *const kNTEventName = @"NetworkTools:onRequest"; + +@implementation NetworkToolsManager { + __weak id _emitter; +} + ++ (instancetype)shared { + static NetworkToolsManager *instance = nil; + static dispatch_once_t token; + dispatch_once(&token, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + ++ (void)activate { +#if DEBUG + [NSURLProtocol registerClass:[NetworkToolsInterceptor class]]; +#endif +} + +- (void)setEmitter:(nullable id)emitter { + _emitter = emitter; +} + +- (void)emitRequest:(NSDictionary *)requestDict { +#if DEBUG + id emitter = _emitter; + if (emitter == nil) return; + if ([emitter respondsToSelector:@selector(sendEventWithName:body:)]) { + [emitter sendEventWithName:kNTEventName body:requestDict]; + } +#endif +} + +@end diff --git a/ios/NetworkToolsStorage.h b/ios/NetworkToolsStorage.h new file mode 100644 index 0000000..7c87202 --- /dev/null +++ b/ios/NetworkToolsStorage.h @@ -0,0 +1,21 @@ +#import + +NS_ASSUME_NONNULL_BEGIN + +/** + * Thread-safe in-memory store for captured network requests. + * Mirrors Android's NetworkRequestStorage.kt. + */ +@interface NetworkToolsStorage : NSObject + +@property (class, nonatomic, readonly) NetworkToolsStorage *shared; + +- (void)addRequest:(NSDictionary *)request; +- (NSArray *)allRequests; +- (nullable NSDictionary *)requestById:(NSString *)requestId; +- (void)clearAll; +- (NSInteger)count; + +@end + +NS_ASSUME_NONNULL_END diff --git a/ios/NetworkToolsStorage.m b/ios/NetworkToolsStorage.m new file mode 100644 index 0000000..f4df2c2 --- /dev/null +++ b/ios/NetworkToolsStorage.m @@ -0,0 +1,69 @@ +#import "NetworkToolsStorage.h" + +static const NSInteger kNTMaxRequests = 100; + +@implementation NetworkToolsStorage { + NSMutableArray *_requests; + NSLock *_lock; +} + ++ (instancetype)shared { + static NetworkToolsStorage *instance = nil; + static dispatch_once_t token; + dispatch_once(&token, ^{ + instance = [[self alloc] init]; + }); + return instance; +} + +- (instancetype)init { + if (self = [super init]) { + _requests = [NSMutableArray array]; + _lock = [[NSLock alloc] init]; + } + return self; +} + +- (void)addRequest:(NSDictionary *)request { + [_lock lock]; + [_requests addObject:request]; + while ((NSInteger)_requests.count > kNTMaxRequests) { + [_requests removeObjectAtIndex:0]; + } + [_lock unlock]; +} + +- (NSArray *)allRequests { + [_lock lock]; + NSArray *snapshot = [_requests copy]; + [_lock unlock]; + return snapshot; +} + +- (nullable NSDictionary *)requestById:(NSString *)requestId { + [_lock lock]; + NSDictionary *found = nil; + for (NSDictionary *req in _requests) { + if ([req[@"id"] isEqualToString:requestId]) { + found = req; + break; + } + } + [_lock unlock]; + return found; +} + +- (void)clearAll { + [_lock lock]; + [_requests removeAllObjects]; + [_lock unlock]; +} + +- (NSInteger)count { + [_lock lock]; + NSInteger c = (NSInteger)_requests.count; + [_lock unlock]; + return c; +} + +@end diff --git a/plugin/src/index.js b/plugin/src/index.js index c45a750..3403159 100644 --- a/plugin/src/index.js +++ b/plugin/src/index.js @@ -15,10 +15,13 @@ const createRunOncePlugin = return plugin; }); const withMainApplication = configPlugins?.withMainApplication; +const withAppDelegate = configPlugins?.withAppDelegate; const WarningAggregator = configPlugins?.WarningAggregator; const PACKAGE_NAME = 'react-native-network-tools'; +// ─── Android ───────────────────────────────────────────────────────────────── + const KOTLIN_IMPORTS = [ 'import com.facebook.react.modules.network.NetworkingModule', 'import com.networktools.NetworkToolsManager', @@ -31,22 +34,26 @@ const JAVA_IMPORTS = [ 'import okhttp3.OkHttpClient;', ]; -const KOTLIN_SNIPPET = ` NetworkingModule.setCustomClientBuilder( - object : NetworkingModule.CustomClientBuilder { - override fun apply(builder: OkHttpClient.Builder) { - NetworkToolsManager.addInterceptor(builder) +const KOTLIN_SNIPPET = ` if (BuildConfig.DEBUG) { + NetworkingModule.setCustomClientBuilder( + object : NetworkingModule.CustomClientBuilder { + override fun apply(builder: OkHttpClient.Builder) { + NetworkToolsManager.addInterceptor(builder) + } } - } - )`; + ) + }`; -const JAVA_SNIPPET = ` NetworkingModule.setCustomClientBuilder( - new NetworkingModule.CustomClientBuilder() { - @Override - public void apply(OkHttpClient.Builder builder) { - NetworkToolsManager.addInterceptor(builder); +const JAVA_SNIPPET = ` if (BuildConfig.DEBUG) { + NetworkingModule.setCustomClientBuilder( + new NetworkingModule.CustomClientBuilder() { + @Override + public void apply(OkHttpClient.Builder builder) { + NetworkToolsManager.addInterceptor(builder); + } } - } - );`; + ); + }`; function ensureImport(src, importLine) { if (src.includes(importLine)) { @@ -113,6 +120,108 @@ function applyJavaPatch(mainApplicationSrc) { return patched; } +// ─── iOS ────────────────────────────────────────────────────────────────────── + +const SWIFT_IMPORT = 'import NetworkTools'; + +// The snippet is deliberately un-indented; applySwiftAppDelegatePatch reindents +// it to match the surrounding code via the captured indent group. +const SWIFT_SNIPPET = ` #if DEBUG + NetworkToolsManager.activate() + #endif`; + +const OBJC_IMPORT = '#import '; + +const OBJC_SNIPPET = ` #if DEBUG + [NetworkToolsManager activate]; + #endif`; + +function ensureSwiftImport(src) { + if (src.includes(SWIFT_IMPORT)) { + return src; + } + // Insert after the last `import ...` line. + const importMatches = [...src.matchAll(/^import .+$/gm)]; + if (importMatches.length === 0) { + return src; + } + const last = importMatches[importMatches.length - 1]; + const insertAt = last.index + last[0].length; + return `${src.slice(0, insertAt)}\n${SWIFT_IMPORT}${src.slice(insertAt)}`; +} + +function ensureObjcImport(src) { + if (src.includes(OBJC_IMPORT)) { + return src; + } + // Insert after the last #import line. + const importMatches = [...src.matchAll(/^#import .+$/gm)]; + if (importMatches.length === 0) { + return src; + } + const last = importMatches[importMatches.length - 1]; + const insertAt = last.index + last[0].length; + return `${src.slice(0, insertAt)}\n${OBJC_IMPORT}${src.slice(insertAt)}`; +} + +/** + * Patches a Swift AppDelegate by: + * 1. Adding `import NetworkTools` after the last existing import. + * 2. Inserting a `#if DEBUG NetworkToolsManager.activate() #endif` block + * at the start of `application(_:didFinishLaunchingWithOptions:)`. + */ +function applySwiftAppDelegatePatch(src) { + if (src.includes('NetworkToolsManager.activate()')) { + return src; // idempotent + } + + let patched = ensureSwiftImport(src); + + // Match the closing `) -> Bool {` of the function signature, followed by a + // newline and the first line's leading whitespace. + const didFinishRegex = + /(\bdidFinishLaunchingWithOptions\b[\s\S]*?->\s*Bool\s*\{)\s*\n(\s*)/; + if (!didFinishRegex.test(patched)) { + return null; + } + + patched = patched.replace(didFinishRegex, (match, signature, indent) => { + const indented = SWIFT_SNIPPET.split('\n').join(`\n${indent}`); + return `${signature}\n${indent}${indented}\n\n${indent}`; + }); + + return patched; +} + +/** + * Patches an Objective-C AppDelegate (.m / .mm) by: + * 1. Adding `#import ` after the last import. + * 2. Inserting `[NetworkToolsManager activate]` inside + * `application:didFinishLaunchingWithOptions:`. + */ +function applyObjcAppDelegatePatch(src) { + if (src.includes('[NetworkToolsManager activate]')) { + return src; // idempotent + } + + let patched = ensureObjcImport(src); + + const didFinishRegex = + /(-\s*\(BOOL\)\s*application[\s\S]*?didFinishLaunchingWithOptions[\s\S]*?\{)\s*\n(\s*)/; + if (!didFinishRegex.test(patched)) { + return null; + } + + patched = patched.replace(didFinishRegex, (match, signature, indent) => { + const indented = OBJC_SNIPPET.split('\n').join(`\n${indent}`); + return `${signature}\n${indent}${indented}\n\n${indent}`; + }); + + return patched; +} + +// ─── Plugin wiring ──────────────────────────────────────────────────────────── + const withNetworkTools = (config) => { if (!withMainApplication || !WarningAggregator) { throw new Error( @@ -120,7 +229,8 @@ const withNetworkTools = (config) => { ); } - return withMainApplication(config, (mod) => { + // Android — patch MainApplication + let updated = withMainApplication(config, (mod) => { const { language, contents } = mod.modResults; const patchedContents = language === 'kt' ? applyKotlinPatch(contents) : applyJavaPatch(contents); @@ -137,6 +247,33 @@ const withNetworkTools = (config) => { mod.modResults.contents = patchedContents; return mod; }); + + // iOS — patch AppDelegate (Swift or ObjC) + if (withAppDelegate) { + updated = withAppDelegate(updated, (mod) => { + const { language, contents } = mod.modResults; + const patchedContents = + language === 'swift' + ? applySwiftAppDelegatePatch(contents) + : applyObjcAppDelegatePatch(contents); + + if (patchedContents == null) { + WarningAggregator.addWarningIOS( + PACKAGE_NAME, + `Could not automatically patch AppDelegate.${language}. ` + + 'Please add [NetworkToolsManager activate] (ObjC) or ' + + 'NetworkToolsManager.activate() (Swift) manually inside ' + + 'application:didFinishLaunchingWithOptions:, wrapped in #if DEBUG.' + ); + return mod; + } + + mod.modResults.contents = patchedContents; + return mod; + }); + } + + return updated; }; const pkg = require('../../package.json'); @@ -145,3 +282,5 @@ module.exports = createRunOncePlugin(withNetworkTools, pkg.name, pkg.version); module.exports.withNetworkTools = withNetworkTools; module.exports.applyKotlinPatch = applyKotlinPatch; module.exports.applyJavaPatch = applyJavaPatch; +module.exports.applySwiftAppDelegatePatch = applySwiftAppDelegatePatch; +module.exports.applyObjcAppDelegatePatch = applyObjcAppDelegatePatch; diff --git a/plugin/src/index.test.js b/plugin/src/index.test.js index 0453a03..86876c9 100644 --- a/plugin/src/index.test.js +++ b/plugin/src/index.test.js @@ -1,7 +1,14 @@ -const { applyJavaPatch, applyKotlinPatch } = require('./index'); +const { + applyJavaPatch, + applyKotlinPatch, + applySwiftAppDelegatePatch, + applyObjcAppDelegatePatch, +} = require('./index'); -describe('expo config plugin MainApplication patch', () => { - it('applies kotlin patch and is idempotent', () => { +// ─── Android ───────────────────────────────────────────────────────────────── + +describe('Android MainApplication patch', () => { + describe('Kotlin', () => { const source = `package networktools.example import android.app.Application @@ -13,14 +20,35 @@ class MainApplication : Application() { } `; - const once = applyKotlinPatch(source); - expect(once).toContain('NetworkToolsManager.addInterceptor(builder)'); + it('wraps interceptor setup in a BuildConfig.DEBUG guard', () => { + const patched = applyKotlinPatch(source); + expect(patched).toContain('if (BuildConfig.DEBUG)'); + expect(patched).toContain('NetworkToolsManager.addInterceptor(builder)'); + }); + + it('places the addInterceptor call inside the DEBUG guard', () => { + const patched = applyKotlinPatch(source); + const debugGuardIndex = patched.indexOf('if (BuildConfig.DEBUG)'); + const interceptorIndex = patched.indexOf( + 'NetworkToolsManager.addInterceptor(builder)' + ); + expect(debugGuardIndex).toBeGreaterThanOrEqual(0); + expect(interceptorIndex).toBeGreaterThan(debugGuardIndex); + }); - const twice = applyKotlinPatch(once); - expect(twice).toBe(once); + it('is idempotent — applying the patch twice produces the same result', () => { + const once = applyKotlinPatch(source); + const twice = applyKotlinPatch(once); + expect(twice).toBe(once); + }); + + it('returns null when onCreate pattern is not found', () => { + const noOnCreate = `package networktools.example\nclass MainApplication : Application()`; + expect(applyKotlinPatch(noOnCreate)).toBeNull(); + }); }); - it('applies java patch and is idempotent', () => { + describe('Java', () => { const source = `package networktools.example; import android.app.Application; @@ -33,10 +61,134 @@ class MainApplication extends Application { } `; - const once = applyJavaPatch(source); - expect(once).toContain('NetworkToolsManager.addInterceptor(builder);'); + it('wraps interceptor setup in a BuildConfig.DEBUG guard', () => { + const patched = applyJavaPatch(source); + expect(patched).toContain('if (BuildConfig.DEBUG)'); + expect(patched).toContain('NetworkToolsManager.addInterceptor(builder);'); + }); + + it('places the addInterceptor call inside the DEBUG guard', () => { + const patched = applyJavaPatch(source); + const debugGuardIndex = patched.indexOf('if (BuildConfig.DEBUG)'); + const interceptorIndex = patched.indexOf( + 'NetworkToolsManager.addInterceptor(builder);' + ); + expect(debugGuardIndex).toBeGreaterThanOrEqual(0); + expect(interceptorIndex).toBeGreaterThan(debugGuardIndex); + }); + + it('is idempotent — applying the patch twice produces the same result', () => { + const once = applyJavaPatch(source); + const twice = applyJavaPatch(once); + expect(twice).toBe(once); + }); + + it('returns null when onCreate pattern is not found', () => { + const noOnCreate = `package networktools.example;\nclass MainApplication extends Application {}`; + expect(applyJavaPatch(noOnCreate)).toBeNull(); + }); + }); +}); + +// ─── iOS ───────────────────────────────────────────────────────────────────── + +describe('iOS AppDelegate patch', () => { + describe('Swift', () => { + const source = `import UIKit +import React +import React_RCTAppDelegate + +@main +class AppDelegate: UIResponder, UIApplicationDelegate { + func application( + _ application: UIApplication, + didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]? = nil + ) -> Bool { + let delegate = ReactNativeDelegate() + return true + } +} +`; + + it('adds the NetworkTools import', () => { + const patched = applySwiftAppDelegatePatch(source); + expect(patched).toContain('import NetworkTools'); + }); + + it('inserts the #if DEBUG activation block', () => { + const patched = applySwiftAppDelegatePatch(source); + expect(patched).toContain('#if DEBUG'); + expect(patched).toContain('NetworkToolsManager.activate()'); + expect(patched).toContain('#endif'); + }); + + it('places activate() before the first statement in the function body', () => { + const patched = applySwiftAppDelegatePatch(source); + const activateIndex = patched.indexOf('NetworkToolsManager.activate()'); + const delegateIndex = patched.indexOf( + 'let delegate = ReactNativeDelegate()' + ); + expect(activateIndex).toBeGreaterThanOrEqual(0); + expect(activateIndex).toBeLessThan(delegateIndex); + }); + + it('is idempotent — applying the patch twice produces the same result', () => { + const once = applySwiftAppDelegatePatch(source); + const twice = applySwiftAppDelegatePatch(once); + expect(twice).toBe(once); + }); + + it('returns null when didFinishLaunchingWithOptions pattern is not found', () => { + const noDelegate = `import UIKit\nclass AppDelegate: NSObject {}`; + expect(applySwiftAppDelegatePatch(noDelegate)).toBeNull(); + }); + }); + + describe('Objective-C', () => { + const source = `#import "AppDelegate.h" +#import + +@implementation AppDelegate + +- (BOOL)application:(UIApplication *)application + didFinishLaunchingWithOptions:(NSDictionary *)launchOptions +{ + self.moduleName = @"MyApp"; + return [super application:application didFinishLaunchingWithOptions:launchOptions]; +} + +@end +`; + + it('adds the NetworkToolsManager import', () => { + const patched = applyObjcAppDelegatePatch(source); + expect(patched).toContain('#import '); + }); + + it('inserts the #if DEBUG activation block', () => { + const patched = applyObjcAppDelegatePatch(source); + expect(patched).toContain('#if DEBUG'); + expect(patched).toContain('[NetworkToolsManager activate]'); + expect(patched).toContain('#endif'); + }); + + it('places [NetworkToolsManager activate] before the first statement', () => { + const patched = applyObjcAppDelegatePatch(source); + const activateIndex = patched.indexOf('[NetworkToolsManager activate]'); + const moduleNameIndex = patched.indexOf('self.moduleName'); + expect(activateIndex).toBeGreaterThanOrEqual(0); + expect(activateIndex).toBeLessThan(moduleNameIndex); + }); + + it('is idempotent — applying the patch twice produces the same result', () => { + const once = applyObjcAppDelegatePatch(source); + const twice = applyObjcAppDelegatePatch(once); + expect(twice).toBe(once); + }); - const twice = applyJavaPatch(once); - expect(twice).toBe(once); + it('returns null when didFinishLaunchingWithOptions pattern is not found', () => { + const noDelegate = `#import "AppDelegate.h"\n@implementation AppDelegate\n@end`; + expect(applyObjcAppDelegatePatch(noDelegate)).toBeNull(); + }); }); }); From aa7291da3d254b4d30f4be8edfe3af7107468d7b Mon Sep 17 00:00:00 2001 From: sankalpsingh Date: Fri, 29 May 2026 20:49:02 +0530 Subject: [PATCH 2/2] feat: enhance NetworkToolsInterceptor to swizzle NSURLSessionConfiguration - Added swizzling of NSURLSessionConfiguration - Improved request body handling by buffering HTTP body streams and capturing request data. - Updated NetworkToolsManager to use RCTEventEmitter for event emission. - Enhanced UI components to display request and response bodies --- NetworkTools.podspec | 5 + example/Gemfile.lock | 121 + .../project.pbxproj | 69 +- .../contents.xcworkspacedata | 10 + example/ios/NetworkToolsExample/Info.plist | 3 +- example/ios/Podfile.lock | 2994 +++++++++++++++++ ios/NetworkToolsInterceptor.h | 8 + ios/NetworkToolsInterceptor.m | 158 +- ios/NetworkToolsManager.h | 4 +- ios/NetworkToolsManager.m | 13 +- .../floating-network-monitor/index.tsx | 4 +- .../request-detail/NetworkDetails.tsx | 27 +- src/context/types.ts | 4 +- 13 files changed, 3311 insertions(+), 109 deletions(-) create mode 100644 example/Gemfile.lock create mode 100644 example/ios/NetworkToolsExample.xcworkspace/contents.xcworkspacedata create mode 100644 example/ios/Podfile.lock diff --git a/NetworkTools.podspec b/NetworkTools.podspec index 9d98793..0996005 100644 --- a/NetworkTools.podspec +++ b/NetworkTools.podspec @@ -19,6 +19,11 @@ Pod::Spec.new do |s| # [NetworkToolsManager activate] after `import NetworkTools`. s.public_header_files = "ios/NetworkToolsManager.h" + # DEFINES_MODULE = YES tells CocoaPods to generate an umbrella header + + # module map for this pod and inject -fmodule-map-file into every dependent + # target's xcconfig, which is what makes `import NetworkTools` work in Swift + # without use_frameworks!. (Same mechanism used by RNReanimated et al.) + s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES' } install_modules_dependencies(s) end diff --git a/example/Gemfile.lock b/example/Gemfile.lock new file mode 100644 index 0000000..7b209c3 --- /dev/null +++ b/example/Gemfile.lock @@ -0,0 +1,121 @@ +GEM + remote: https://rubygems.org/ + specs: + CFPropertyList (3.0.8) + activesupport (7.2.3.1) + base64 + benchmark (>= 0.3) + bigdecimal + concurrent-ruby (~> 1.0, >= 1.3.1) + connection_pool (>= 2.2.5) + drb + i18n (>= 1.6, < 2) + logger (>= 1.4.2) + minitest (>= 5.1, < 6) + securerandom (>= 0.3) + tzinfo (~> 2.0, >= 2.0.5) + addressable (2.9.0) + public_suffix (>= 2.0.2, < 8.0) + algoliasearch (1.27.5) + httpclient (~> 2.8, >= 2.8.3) + json (>= 1.5.1) + atomos (0.1.3) + base64 (0.3.0) + benchmark (0.5.0) + bigdecimal (4.1.2) + claide (1.1.0) + cocoapods (1.15.2) + addressable (~> 2.8) + claide (>= 1.0.2, < 2.0) + cocoapods-core (= 1.15.2) + cocoapods-deintegrate (>= 1.0.3, < 2.0) + cocoapods-downloader (>= 2.1, < 3.0) + cocoapods-plugins (>= 1.0.0, < 2.0) + cocoapods-search (>= 1.0.0, < 2.0) + cocoapods-trunk (>= 1.6.0, < 2.0) + cocoapods-try (>= 1.1.0, < 2.0) + colored2 (~> 3.1) + escape (~> 0.0.4) + fourflusher (>= 2.3.0, < 3.0) + gh_inspector (~> 1.0) + molinillo (~> 0.8.0) + nap (~> 1.0) + ruby-macho (>= 2.3.0, < 3.0) + xcodeproj (>= 1.23.0, < 2.0) + cocoapods-core (1.15.2) + activesupport (>= 5.0, < 8) + addressable (~> 2.8) + algoliasearch (~> 1.0) + concurrent-ruby (~> 1.1) + fuzzy_match (~> 2.0.4) + nap (~> 1.0) + netrc (~> 0.11) + public_suffix (~> 4.0) + typhoeus (~> 1.0) + cocoapods-deintegrate (1.0.5) + cocoapods-downloader (2.1) + cocoapods-plugins (1.0.0) + nap + cocoapods-search (1.0.1) + cocoapods-trunk (1.6.0) + nap (>= 0.8, < 2.0) + netrc (~> 0.11) + cocoapods-try (1.2.0) + colored2 (3.1.2) + concurrent-ruby (1.3.3) + connection_pool (3.0.2) + drb (2.2.3) + escape (0.0.4) + ethon (0.18.0) + ffi (>= 1.15.0) + logger + ffi (1.17.4) + fourflusher (2.3.1) + fuzzy_match (2.0.4) + gh_inspector (1.1.3) + httpclient (2.9.0) + mutex_m + i18n (1.14.8) + concurrent-ruby (~> 1.0) + json (2.19.5) + logger (1.7.0) + minitest (5.27.0) + molinillo (0.8.0) + mutex_m (0.3.0) + nanaimo (0.3.0) + nap (1.1.0) + netrc (0.11.0) + public_suffix (4.0.7) + rexml (3.4.4) + ruby-macho (2.5.1) + securerandom (0.4.1) + typhoeus (1.6.0) + ethon (>= 0.18.0) + tzinfo (2.0.6) + concurrent-ruby (~> 1.0) + xcodeproj (1.25.1) + CFPropertyList (>= 2.3.3, < 4.0) + atomos (~> 0.1.3) + claide (>= 1.0.2, < 2.0) + colored2 (~> 3.1) + nanaimo (~> 0.3.0) + rexml (>= 3.3.6, < 4.0) + +PLATFORMS + ruby + +DEPENDENCIES + activesupport (>= 6.1.7.5, != 7.1.0) + benchmark + bigdecimal + cocoapods (>= 1.13, != 1.15.1, != 1.15.0) + concurrent-ruby (< 1.3.4) + logger + mutex_m + xcodeproj (< 1.26.0) + +RUBY VERSION + ruby 3.2.0p0 + +BUNDLED WITH + 2.5.11 diff --git a/example/ios/NetworkToolsExample.xcodeproj/project.pbxproj b/example/ios/NetworkToolsExample.xcodeproj/project.pbxproj index 8f8b0a2..161ec42 100644 --- a/example/ios/NetworkToolsExample.xcodeproj/project.pbxproj +++ b/example/ios/NetworkToolsExample.xcodeproj/project.pbxproj @@ -7,22 +7,23 @@ objects = { /* Begin PBXBuildFile section */ - 0C80B921A6F3F58F76C31292 /* libPods-NetworkToolsExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5DCACB8F33CDC322A6C60F78 /* libPods-NetworkToolsExample.a */; }; 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB51A68108700A75B9A /* Images.xcassets */; }; + 5629F01035D80E0CFCEA68B4 /* PrivacyInfo.xcprivacy in Resources */ = {isa = PBXBuildFile; fileRef = 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */; }; 761780ED2CA45674006654EE /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 761780EC2CA45674006654EE /* AppDelegate.swift */; }; 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */; }; + CB1957D31C476AB449C7DD74 /* libPods-NetworkToolsExample.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 0EE1789754AB0B47D7ECAB9F /* libPods-NetworkToolsExample.a */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 0EE1789754AB0B47D7ECAB9F /* libPods-NetworkToolsExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NetworkToolsExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07F961A680F5B00A75B9A /* NetworkToolsExample.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = NetworkToolsExample.app; sourceTree = BUILT_PRODUCTS_DIR; }; 13B07FB51A68108700A75B9A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; name = Images.xcassets; path = NetworkToolsExample/Images.xcassets; sourceTree = ""; }; 13B07FB61A68108700A75B9A /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = Info.plist; path = NetworkToolsExample/Info.plist; sourceTree = ""; }; 13B07FB81A68108700A75B9A /* PrivacyInfo.xcprivacy */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = PrivacyInfo.xcprivacy; path = NetworkToolsExample/PrivacyInfo.xcprivacy; sourceTree = ""; }; - 3B4392A12AC88292D35C810B /* Pods-NetworkToolsExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkToolsExample.debug.xcconfig"; path = "Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample.debug.xcconfig"; sourceTree = ""; }; - 5709B34CF0A7D63546082F79 /* Pods-NetworkToolsExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkToolsExample.release.xcconfig"; path = "Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample.release.xcconfig"; sourceTree = ""; }; - 5DCACB8F33CDC322A6C60F78 /* libPods-NetworkToolsExample.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-NetworkToolsExample.a"; sourceTree = BUILT_PRODUCTS_DIR; }; + 2699EB08EDDA74D4EE02C281 /* Pods-NetworkToolsExample.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkToolsExample.debug.xcconfig"; path = "Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample.debug.xcconfig"; sourceTree = ""; }; 761780EC2CA45674006654EE /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; name = AppDelegate.swift; path = NetworkToolsExample/AppDelegate.swift; sourceTree = ""; }; 81AB9BB72411601600AC10FF /* LaunchScreen.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; name = LaunchScreen.storyboard; path = NetworkToolsExample/LaunchScreen.storyboard; sourceTree = ""; }; + C5FFCCFEE83655390E0F98AB /* Pods-NetworkToolsExample.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NetworkToolsExample.release.xcconfig"; path = "Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample.release.xcconfig"; sourceTree = ""; }; ED297162215061F000B7C4FE /* JavaScriptCore.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = JavaScriptCore.framework; path = System/Library/Frameworks/JavaScriptCore.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ @@ -31,7 +32,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 0C80B921A6F3F58F76C31292 /* libPods-NetworkToolsExample.a in Frameworks */, + CB1957D31C476AB449C7DD74 /* libPods-NetworkToolsExample.a in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -54,7 +55,7 @@ isa = PBXGroup; children = ( ED297162215061F000B7C4FE /* JavaScriptCore.framework */, - 5DCACB8F33CDC322A6C60F78 /* libPods-NetworkToolsExample.a */, + 0EE1789754AB0B47D7ECAB9F /* libPods-NetworkToolsExample.a */, ); name = Frameworks; sourceTree = ""; @@ -91,8 +92,8 @@ BBD78D7AC51CEA395F1C20DB /* Pods */ = { isa = PBXGroup; children = ( - 3B4392A12AC88292D35C810B /* Pods-NetworkToolsExample.debug.xcconfig */, - 5709B34CF0A7D63546082F79 /* Pods-NetworkToolsExample.release.xcconfig */, + 2699EB08EDDA74D4EE02C281 /* Pods-NetworkToolsExample.debug.xcconfig */, + C5FFCCFEE83655390E0F98AB /* Pods-NetworkToolsExample.release.xcconfig */, ); path = Pods; sourceTree = ""; @@ -104,13 +105,13 @@ isa = PBXNativeTarget; buildConfigurationList = 13B07F931A680F5B00A75B9A /* Build configuration list for PBXNativeTarget "NetworkToolsExample" */; buildPhases = ( - C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */, + 67BFCE45756B1AC1E6C56FD9 /* [CP] Check Pods Manifest.lock */, 13B07F871A680F5B00A75B9A /* Sources */, 13B07F8C1A680F5B00A75B9A /* Frameworks */, 13B07F8E1A680F5B00A75B9A /* Resources */, 00DD1BFF1BD5951E006B06BC /* Bundle React Native code and images */, - 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */, - E235C05ADACE081382539298 /* [CP] Copy Pods Resources */, + 203BE0E62F0CC9F15E874532 /* [CP] Embed Pods Frameworks */, + 42F400C8AA3A6B9865E1B84C /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -159,6 +160,7 @@ files = ( 81AB9BB82411601600AC10FF /* LaunchScreen.storyboard in Resources */, 13B07FBF1A68108700A75B9A /* Images.xcassets in Resources */, + 5629F01035D80E0CFCEA68B4 /* PrivacyInfo.xcprivacy in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -181,7 +183,7 @@ shellPath = /bin/sh; shellScript = "set -e\n\nWITH_ENVIRONMENT=\"$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh\"\nREACT_NATIVE_XCODE=\"$REACT_NATIVE_PATH/scripts/react-native-xcode.sh\"\n\n/bin/sh -c \"$WITH_ENVIRONMENT $REACT_NATIVE_XCODE\"\n"; }; - 00EEFC60759A1932668264C0 /* [CP] Embed Pods Frameworks */ = { + 203BE0E62F0CC9F15E874532 /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( @@ -198,43 +200,43 @@ shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; - C38B50BA6285516D6DCD4F65 /* [CP] Check Pods Manifest.lock */ = { + 42F400C8AA3A6B9865E1B84C /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( + "${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources-${CONFIGURATION}-input-files.xcfilelist", ); - inputPaths = ( - "${PODS_PODFILE_DIR_PATH}/Podfile.lock", - "${PODS_ROOT}/Manifest.lock", - ); - name = "[CP] Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputFileListPaths = ( - ); - outputPaths = ( - "$(DERIVED_FILE_DIR)/Pods-NetworkToolsExample-checkManifestLockResult.txt", + "${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources-${CONFIGURATION}-output-files.xcfilelist", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; + shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources.sh\"\n"; showEnvVarsInLog = 0; }; - E235C05ADACE081382539298 /* [CP] Copy Pods Resources */ = { + 67BFCE45756B1AC1E6C56FD9 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources-${CONFIGURATION}-input-files.xcfilelist", ); - name = "[CP] Copy Pods Resources"; + inputPaths = ( + "${PODS_PODFILE_DIR_PATH}/Podfile.lock", + "${PODS_ROOT}/Manifest.lock", + ); + name = "[CP] Check Pods Manifest.lock"; outputFileListPaths = ( - "${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources-${CONFIGURATION}-output-files.xcfilelist", + ); + outputPaths = ( + "$(DERIVED_FILE_DIR)/Pods-NetworkToolsExample-checkManifestLockResult.txt", ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-NetworkToolsExample/Pods-NetworkToolsExample-resources.sh\"\n"; + shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -253,7 +255,7 @@ /* Begin XCBuildConfiguration section */ 13B07F941A680F5B00A75B9A /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 3B4392A12AC88292D35C810B /* Pods-NetworkToolsExample.debug.xcconfig */; + baseConfigurationReference = 2699EB08EDDA74D4EE02C281 /* Pods-NetworkToolsExample.debug.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -271,7 +273,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "networktools.example"; + PRODUCT_BUNDLE_IDENTIFIER = networktools.example; PRODUCT_NAME = NetworkToolsExample; SWIFT_OPTIMIZATION_LEVEL = "-Onone"; SWIFT_VERSION = 5.0; @@ -281,7 +283,7 @@ }; 13B07F951A680F5B00A75B9A /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 5709B34CF0A7D63546082F79 /* Pods-NetworkToolsExample.release.xcconfig */; + baseConfigurationReference = C5FFCCFEE83655390E0F98AB /* Pods-NetworkToolsExample.release.xcconfig */; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; CLANG_ENABLE_MODULES = YES; @@ -298,7 +300,7 @@ "-ObjC", "-lc++", ); - PRODUCT_BUNDLE_IDENTIFIER = "networktools.example"; + PRODUCT_BUNDLE_IDENTIFIER = networktools.example; PRODUCT_NAME = NetworkToolsExample; SWIFT_VERSION = 5.0; VERSIONING_SYSTEM = "apple-generic"; @@ -374,7 +376,10 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + SWIFT_ACTIVE_COMPILATION_CONDITIONS = "$(inherited) DEBUG"; + USE_HERMES = true; }; name = Debug; }; @@ -439,7 +444,9 @@ "-DFOLLY_CFG_NO_COROUTINES=1", "-DFOLLY_HAVE_CLOCK_GETTIME=1", ); + REACT_NATIVE_PATH = "${PODS_ROOT}/../../node_modules/react-native"; SDKROOT = iphoneos; + USE_HERMES = true; VALIDATE_PRODUCT = YES; }; name = Release; diff --git a/example/ios/NetworkToolsExample.xcworkspace/contents.xcworkspacedata b/example/ios/NetworkToolsExample.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..9fa5439 --- /dev/null +++ b/example/ios/NetworkToolsExample.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,10 @@ + + + + + + + diff --git a/example/ios/NetworkToolsExample/Info.plist b/example/ios/NetworkToolsExample/Info.plist index 30c86a2..3a5859f 100644 --- a/example/ios/NetworkToolsExample/Info.plist +++ b/example/ios/NetworkToolsExample/Info.plist @@ -26,7 +26,6 @@ NSAppTransportSecurity - NSAllowsArbitraryLoads NSAllowsLocalNetworking @@ -34,6 +33,8 @@ NSLocationWhenInUseUsageDescription + RCTNewArchEnabled + UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities diff --git a/example/ios/Podfile.lock b/example/ios/Podfile.lock new file mode 100644 index 0000000..6b2215c --- /dev/null +++ b/example/ios/Podfile.lock @@ -0,0 +1,2994 @@ +PODS: + - boost (1.84.0) + - DoubleConversion (1.1.6) + - fast_float (8.0.0) + - FBLazyVector (0.81.1) + - fmt (11.0.2) + - glog (0.3.5) + - hermes-engine (0.81.1): + - hermes-engine/Pre-built (= 0.81.1) + - hermes-engine/Pre-built (0.81.1) + - NetworkTools (0.1.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RCT-Folly (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Default (= 2024.11.18.00) + - RCT-Folly/Default (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCT-Folly/Fabric (2024.11.18.00): + - boost + - DoubleConversion + - fast_float (= 8.0.0) + - fmt (= 11.0.2) + - glog + - RCTDeprecation (0.81.1) + - RCTRequired (0.81.1) + - RCTTypeSafety (0.81.1): + - FBLazyVector (= 0.81.1) + - RCTRequired (= 0.81.1) + - React-Core (= 0.81.1) + - React (0.81.1): + - React-Core (= 0.81.1) + - React-Core/DevSupport (= 0.81.1) + - React-Core/RCTWebSocket (= 0.81.1) + - React-RCTActionSheet (= 0.81.1) + - React-RCTAnimation (= 0.81.1) + - React-RCTBlob (= 0.81.1) + - React-RCTImage (= 0.81.1) + - React-RCTLinking (= 0.81.1) + - React-RCTNetwork (= 0.81.1) + - React-RCTSettings (= 0.81.1) + - React-RCTText (= 0.81.1) + - React-RCTVibration (= 0.81.1) + - React-callinvoker (0.81.1) + - React-Core (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/CoreModulesHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/Default (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/DevSupport (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.1) + - React-Core/RCTWebSocket (= 0.81.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTActionSheetHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTAnimationHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTBlobHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTImageHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTLinkingHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTNetworkHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTSettingsHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTTextHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTVibrationHeaders (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-Core/RCTWebSocket (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTDeprecation + - React-Core/Default (= 0.81.1) + - React-cxxreact + - React-featureflags + - React-hermes + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsinspectorcdp + - React-jsitooling + - React-perflogger + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-CoreModules (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety (= 0.81.1) + - React-Core/CoreModulesHeaders (= 0.81.1) + - React-jsi (= 0.81.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-NativeModulesApple + - React-RCTBlob + - React-RCTFBReactNativeSpec + - React-RCTImage (= 0.81.1) + - React-runtimeexecutor + - ReactCommon + - SocketRocket + - React-cxxreact (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.1) + - React-debug (= 0.81.1) + - React-jsi (= 0.81.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-logger (= 0.81.1) + - React-perflogger (= 0.81.1) + - React-runtimeexecutor + - React-timing (= 0.81.1) + - SocketRocket + - React-debug (0.81.1) + - React-defaultsnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-domnativemodule + - React-featureflagsnativemodule + - React-idlecallbacksnativemodule + - React-jsi + - React-jsiexecutor + - React-microtasksnativemodule + - React-RCTFBReactNativeSpec + - SocketRocket + - React-domnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Fabric + - React-Fabric/bridging + - React-FabricComponents + - React-graphics + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/animations (= 0.81.1) + - React-Fabric/attributedstring (= 0.81.1) + - React-Fabric/bridging (= 0.81.1) + - React-Fabric/componentregistry (= 0.81.1) + - React-Fabric/componentregistrynative (= 0.81.1) + - React-Fabric/components (= 0.81.1) + - React-Fabric/consistency (= 0.81.1) + - React-Fabric/core (= 0.81.1) + - React-Fabric/dom (= 0.81.1) + - React-Fabric/imagemanager (= 0.81.1) + - React-Fabric/leakchecker (= 0.81.1) + - React-Fabric/mounting (= 0.81.1) + - React-Fabric/observers (= 0.81.1) + - React-Fabric/scheduler (= 0.81.1) + - React-Fabric/telemetry (= 0.81.1) + - React-Fabric/templateprocessor (= 0.81.1) + - React-Fabric/uimanager (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/animations (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/attributedstring (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/bridging (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistry (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/componentregistrynative (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/components/legacyviewmanagerinterop (= 0.81.1) + - React-Fabric/components/root (= 0.81.1) + - React-Fabric/components/scrollview (= 0.81.1) + - React-Fabric/components/view (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/legacyviewmanagerinterop (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/root (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/scrollview (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/components/view (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-renderercss + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-Fabric/consistency (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/core (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/dom (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/imagemanager (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/leakchecker (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/mounting (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/observers/events (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/scheduler (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/observers/events + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-performancetimeline + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/telemetry (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/templateprocessor (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric/uimanager/consistency (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-Fabric/uimanager/consistency (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - React-FabricComponents (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components (= 0.81.1) + - React-FabricComponents/textlayoutmanager (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-FabricComponents/components/inputaccessory (= 0.81.1) + - React-FabricComponents/components/iostextinput (= 0.81.1) + - React-FabricComponents/components/modal (= 0.81.1) + - React-FabricComponents/components/rncore (= 0.81.1) + - React-FabricComponents/components/safeareaview (= 0.81.1) + - React-FabricComponents/components/scrollview (= 0.81.1) + - React-FabricComponents/components/switch (= 0.81.1) + - React-FabricComponents/components/text (= 0.81.1) + - React-FabricComponents/components/textinput (= 0.81.1) + - React-FabricComponents/components/unimplementedview (= 0.81.1) + - React-FabricComponents/components/virtualview (= 0.81.1) + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/inputaccessory (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/iostextinput (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/modal (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/rncore (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/safeareaview (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/scrollview (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/switch (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/text (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/textinput (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/unimplementedview (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/components/virtualview (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricComponents/textlayoutmanager (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-cxxreact + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-logger + - React-RCTFBReactNativeSpec + - React-rendererdebug + - React-runtimescheduler + - React-utils + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-FabricImage (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired (= 0.81.1) + - RCTTypeSafety (= 0.81.1) + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsiexecutor (= 0.81.1) + - React-logger + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-featureflags (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-featureflagsnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - React-graphics (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-utils + - SocketRocket + - React-hermes (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.1) + - React-jsi + - React-jsiexecutor (= 0.81.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.1) + - React-runtimeexecutor + - SocketRocket + - React-idlecallbacksnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - React-runtimeexecutor + - React-runtimescheduler + - ReactCommon/turbomodule/core + - SocketRocket + - React-ImageManager (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/Default + - React-debug + - React-Fabric + - React-graphics + - React-rendererdebug + - React-utils + - SocketRocket + - React-jserrorhandler (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - ReactCommon/turbomodule/bridging + - SocketRocket + - React-jsi (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsiexecutor (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.1) + - React-jsi (= 0.81.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-perflogger (= 0.81.1) + - React-runtimeexecutor + - SocketRocket + - React-jsinspector (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-oscompat + - React-perflogger (= 0.81.1) + - React-runtimeexecutor + - SocketRocket + - React-jsinspectorcdp (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-jsinspectornetwork (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectorcdp + - React-performancetimeline + - React-timing + - SocketRocket + - React-jsinspectortracing (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-oscompat + - React-timing + - SocketRocket + - React-jsitooling (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact (= 0.81.1) + - React-jsi (= 0.81.1) + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-runtimeexecutor + - SocketRocket + - React-jsitracing (0.81.1): + - React-jsi + - React-logger (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-Mapbuffer (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-microtasksnativemodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-jsi + - React-jsiexecutor + - React-RCTFBReactNativeSpec + - ReactCommon/turbomodule/core + - SocketRocket + - react-native-safe-area-context (5.7.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - react-native-safe-area-context/common (= 5.7.0) + - react-native-safe-area-context/fabric (= 5.7.0) + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-safe-area-context/common (5.7.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - react-native-safe-area-context/fabric (5.7.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - react-native-safe-area-context/common + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - React-NativeModulesApple (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core + - React-cxxreact + - React-featureflags + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-runtimeexecutor + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - React-oscompat (0.81.1) + - React-perflogger (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - SocketRocket + - React-performancetimeline (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-jsinspectortracing + - React-perflogger + - React-timing + - SocketRocket + - React-RCTActionSheet (0.81.1): + - React-Core/RCTActionSheetHeaders (= 0.81.1) + - React-RCTAnimation (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTAnimationHeaders + - React-featureflags + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTAppDelegate (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-CoreModules + - React-debug + - React-defaultsnativemodule + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-jsitooling + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTNetwork + - React-RCTRuntime + - React-rendererdebug + - React-RuntimeApple + - React-RuntimeCore + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - ReactCommon + - SocketRocket + - React-RCTBlob (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTBlobHeaders + - React-Core/RCTWebSocket + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTFabric (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-debug + - React-Fabric + - React-FabricComponents + - React-FabricImage + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-jsinspectortracing + - React-performancetimeline + - React-RCTAnimation + - React-RCTFBReactNativeSpec + - React-RCTImage + - React-RCTText + - React-rendererconsistency + - React-renderercss + - React-rendererdebug + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - Yoga + - React-RCTFBReactNativeSpec (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec/components (= 0.81.1) + - ReactCommon + - SocketRocket + - React-RCTFBReactNativeSpec/components (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-jsi + - React-NativeModulesApple + - React-rendererdebug + - React-utils + - ReactCommon + - SocketRocket + - Yoga + - React-RCTImage (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTImageHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - React-RCTNetwork + - ReactCommon + - SocketRocket + - React-RCTLinking (0.81.1): + - React-Core/RCTLinkingHeaders (= 0.81.1) + - React-jsi (= 0.81.1) + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - ReactCommon/turbomodule/core (= 0.81.1) + - React-RCTNetwork (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTNetworkHeaders + - React-featureflags + - React-jsi + - React-jsinspectorcdp + - React-jsinspectornetwork + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTRuntime (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-Core + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-RuntimeApple + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - SocketRocket + - React-RCTSettings (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - RCTTypeSafety + - React-Core/RCTSettingsHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-RCTText (0.81.1): + - React-Core/RCTTextHeaders (= 0.81.1) + - Yoga + - React-RCTVibration (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-Core/RCTVibrationHeaders + - React-jsi + - React-NativeModulesApple + - React-RCTFBReactNativeSpec + - ReactCommon + - SocketRocket + - React-rendererconsistency (0.81.1) + - React-renderercss (0.81.1): + - React-debug + - React-utils + - React-rendererdebug (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - SocketRocket + - React-RuntimeApple (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-Core/Default + - React-CoreModules + - React-cxxreact + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-Mapbuffer + - React-NativeModulesApple + - React-RCTFabric + - React-RCTFBReactNativeSpec + - React-RuntimeCore + - React-runtimeexecutor + - React-RuntimeHermes + - React-runtimescheduler + - React-utils + - SocketRocket + - React-RuntimeCore (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-cxxreact + - React-Fabric + - React-featureflags + - React-jserrorhandler + - React-jsi + - React-jsiexecutor + - React-jsinspector + - React-jsitooling + - React-performancetimeline + - React-runtimeexecutor + - React-runtimescheduler + - React-utils + - SocketRocket + - React-runtimeexecutor (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-featureflags + - React-jsi (= 0.81.1) + - React-utils + - SocketRocket + - React-RuntimeHermes (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-featureflags + - React-hermes + - React-jsi + - React-jsinspector + - React-jsinspectorcdp + - React-jsinspectortracing + - React-jsitooling + - React-jsitracing + - React-RuntimeCore + - React-runtimeexecutor + - React-utils + - SocketRocket + - React-runtimescheduler (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker + - React-cxxreact + - React-debug + - React-featureflags + - React-jsi + - React-jsinspectortracing + - React-performancetimeline + - React-rendererconsistency + - React-rendererdebug + - React-runtimeexecutor + - React-timing + - React-utils + - SocketRocket + - React-timing (0.81.1): + - React-debug + - React-utils (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-debug + - React-jsi (= 0.81.1) + - SocketRocket + - ReactAppDependencyProvider (0.81.1): + - ReactCodegen + - ReactCodegen (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-FabricImage + - React-featureflags + - React-graphics + - React-jsi + - React-jsiexecutor + - React-NativeModulesApple + - React-RCTAppDelegate + - React-rendererdebug + - React-utils + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - ReactCommon (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - RCT-Folly + - RCT-Folly/Fabric + - ReactCommon/turbomodule (= 0.81.1) + - SocketRocket + - ReactCommon/turbomodule (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.1) + - React-cxxreact (= 0.81.1) + - React-jsi (= 0.81.1) + - React-logger (= 0.81.1) + - React-perflogger (= 0.81.1) + - ReactCommon/turbomodule/bridging (= 0.81.1) + - ReactCommon/turbomodule/core (= 0.81.1) + - SocketRocket + - ReactCommon/turbomodule/bridging (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.1) + - React-cxxreact (= 0.81.1) + - React-jsi (= 0.81.1) + - React-logger (= 0.81.1) + - React-perflogger (= 0.81.1) + - SocketRocket + - ReactCommon/turbomodule/core (0.81.1): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - React-callinvoker (= 0.81.1) + - React-cxxreact (= 0.81.1) + - React-debug (= 0.81.1) + - React-featureflags (= 0.81.1) + - React-jsi (= 0.81.1) + - React-logger (= 0.81.1) + - React-perflogger (= 0.81.1) + - React-utils (= 0.81.1) + - SocketRocket + - RNCMaskedView (0.3.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNGestureHandler (2.31.2): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNReanimated (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/reanimated (= 3.19.5) + - RNReanimated/worklets (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/reanimated (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/reanimated/apple (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/reanimated/apple (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNReanimated/worklets (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNReanimated/worklets/apple (= 3.19.5) + - SocketRocket + - Yoga + - RNReanimated/worklets/apple (3.19.5): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-hermes + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNScreens (4.25.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - RNScreens/common (= 4.25.0) + - SocketRocket + - Yoga + - RNScreens/common (4.25.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-RCTImage + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - RNVectorIcons (10.3.0): + - boost + - DoubleConversion + - fast_float + - fmt + - glog + - hermes-engine + - RCT-Folly + - RCT-Folly/Fabric + - RCTRequired + - RCTTypeSafety + - React-Core + - React-debug + - React-Fabric + - React-featureflags + - React-graphics + - React-ImageManager + - React-jsi + - React-NativeModulesApple + - React-RCTFabric + - React-renderercss + - React-rendererdebug + - React-utils + - ReactCodegen + - ReactCommon/turbomodule/bridging + - ReactCommon/turbomodule/core + - SocketRocket + - Yoga + - SocketRocket (0.7.1) + - Yoga (0.0.0) + +DEPENDENCIES: + - boost (from `../node_modules/react-native/third-party-podspecs/boost.podspec`) + - DoubleConversion (from `../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec`) + - fast_float (from `../node_modules/react-native/third-party-podspecs/fast_float.podspec`) + - FBLazyVector (from `../node_modules/react-native/Libraries/FBLazyVector`) + - fmt (from `../node_modules/react-native/third-party-podspecs/fmt.podspec`) + - glog (from `../node_modules/react-native/third-party-podspecs/glog.podspec`) + - hermes-engine (from `../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec`) + - NetworkTools (from `../..`) + - RCT-Folly (from `../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec`) + - RCTDeprecation (from `../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation`) + - RCTRequired (from `../node_modules/react-native/Libraries/Required`) + - RCTTypeSafety (from `../node_modules/react-native/Libraries/TypeSafety`) + - React (from `../node_modules/react-native/`) + - React-callinvoker (from `../node_modules/react-native/ReactCommon/callinvoker`) + - React-Core (from `../node_modules/react-native/`) + - React-Core/RCTWebSocket (from `../node_modules/react-native/`) + - React-CoreModules (from `../node_modules/react-native/React/CoreModules`) + - React-cxxreact (from `../node_modules/react-native/ReactCommon/cxxreact`) + - React-debug (from `../node_modules/react-native/ReactCommon/react/debug`) + - React-defaultsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/defaults`) + - React-domnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/dom`) + - React-Fabric (from `../node_modules/react-native/ReactCommon`) + - React-FabricComponents (from `../node_modules/react-native/ReactCommon`) + - React-FabricImage (from `../node_modules/react-native/ReactCommon`) + - React-featureflags (from `../node_modules/react-native/ReactCommon/react/featureflags`) + - React-featureflagsnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/featureflags`) + - React-graphics (from `../node_modules/react-native/ReactCommon/react/renderer/graphics`) + - React-hermes (from `../node_modules/react-native/ReactCommon/hermes`) + - React-idlecallbacksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks`) + - React-ImageManager (from `../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios`) + - React-jserrorhandler (from `../node_modules/react-native/ReactCommon/jserrorhandler`) + - React-jsi (from `../node_modules/react-native/ReactCommon/jsi`) + - React-jsiexecutor (from `../node_modules/react-native/ReactCommon/jsiexecutor`) + - React-jsinspector (from `../node_modules/react-native/ReactCommon/jsinspector-modern`) + - React-jsinspectorcdp (from `../node_modules/react-native/ReactCommon/jsinspector-modern/cdp`) + - React-jsinspectornetwork (from `../node_modules/react-native/ReactCommon/jsinspector-modern/network`) + - React-jsinspectortracing (from `../node_modules/react-native/ReactCommon/jsinspector-modern/tracing`) + - React-jsitooling (from `../node_modules/react-native/ReactCommon/jsitooling`) + - React-jsitracing (from `../node_modules/react-native/ReactCommon/hermes/executor/`) + - React-logger (from `../node_modules/react-native/ReactCommon/logger`) + - React-Mapbuffer (from `../node_modules/react-native/ReactCommon`) + - React-microtasksnativemodule (from `../node_modules/react-native/ReactCommon/react/nativemodule/microtasks`) + - react-native-safe-area-context (from `../node_modules/react-native-safe-area-context`) + - React-NativeModulesApple (from `../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios`) + - React-oscompat (from `../node_modules/react-native/ReactCommon/oscompat`) + - React-perflogger (from `../node_modules/react-native/ReactCommon/reactperflogger`) + - React-performancetimeline (from `../node_modules/react-native/ReactCommon/react/performance/timeline`) + - React-RCTActionSheet (from `../node_modules/react-native/Libraries/ActionSheetIOS`) + - React-RCTAnimation (from `../node_modules/react-native/Libraries/NativeAnimation`) + - React-RCTAppDelegate (from `../node_modules/react-native/Libraries/AppDelegate`) + - React-RCTBlob (from `../node_modules/react-native/Libraries/Blob`) + - React-RCTFabric (from `../node_modules/react-native/React`) + - React-RCTFBReactNativeSpec (from `../node_modules/react-native/React`) + - React-RCTImage (from `../node_modules/react-native/Libraries/Image`) + - React-RCTLinking (from `../node_modules/react-native/Libraries/LinkingIOS`) + - React-RCTNetwork (from `../node_modules/react-native/Libraries/Network`) + - React-RCTRuntime (from `../node_modules/react-native/React/Runtime`) + - React-RCTSettings (from `../node_modules/react-native/Libraries/Settings`) + - React-RCTText (from `../node_modules/react-native/Libraries/Text`) + - React-RCTVibration (from `../node_modules/react-native/Libraries/Vibration`) + - React-rendererconsistency (from `../node_modules/react-native/ReactCommon/react/renderer/consistency`) + - React-renderercss (from `../node_modules/react-native/ReactCommon/react/renderer/css`) + - React-rendererdebug (from `../node_modules/react-native/ReactCommon/react/renderer/debug`) + - React-RuntimeApple (from `../node_modules/react-native/ReactCommon/react/runtime/platform/ios`) + - React-RuntimeCore (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimeexecutor (from `../node_modules/react-native/ReactCommon/runtimeexecutor`) + - React-RuntimeHermes (from `../node_modules/react-native/ReactCommon/react/runtime`) + - React-runtimescheduler (from `../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler`) + - React-timing (from `../node_modules/react-native/ReactCommon/react/timing`) + - React-utils (from `../node_modules/react-native/ReactCommon/react/utils`) + - ReactAppDependencyProvider (from `build/generated/ios`) + - ReactCodegen (from `build/generated/ios`) + - ReactCommon/turbomodule/core (from `../node_modules/react-native/ReactCommon`) + - "RNCMaskedView (from `../node_modules/@react-native-masked-view/masked-view`)" + - RNGestureHandler (from `../node_modules/react-native-gesture-handler`) + - RNReanimated (from `../node_modules/react-native-reanimated`) + - RNScreens (from `../node_modules/react-native-screens`) + - RNVectorIcons (from `../node_modules/react-native-vector-icons`) + - SocketRocket (~> 0.7.1) + - Yoga (from `../node_modules/react-native/ReactCommon/yoga`) + +SPEC REPOS: + trunk: + - SocketRocket + +EXTERNAL SOURCES: + boost: + :podspec: "../node_modules/react-native/third-party-podspecs/boost.podspec" + DoubleConversion: + :podspec: "../node_modules/react-native/third-party-podspecs/DoubleConversion.podspec" + fast_float: + :podspec: "../node_modules/react-native/third-party-podspecs/fast_float.podspec" + FBLazyVector: + :path: "../node_modules/react-native/Libraries/FBLazyVector" + fmt: + :podspec: "../node_modules/react-native/third-party-podspecs/fmt.podspec" + glog: + :podspec: "../node_modules/react-native/third-party-podspecs/glog.podspec" + hermes-engine: + :podspec: "../node_modules/react-native/sdks/hermes-engine/hermes-engine.podspec" + :tag: hermes-2025-07-07-RNv0.81.0-e0fc67142ec0763c6b6153ca2bf96df815539782 + NetworkTools: + :path: "../.." + RCT-Folly: + :podspec: "../node_modules/react-native/third-party-podspecs/RCT-Folly.podspec" + RCTDeprecation: + :path: "../node_modules/react-native/ReactApple/Libraries/RCTFoundation/RCTDeprecation" + RCTRequired: + :path: "../node_modules/react-native/Libraries/Required" + RCTTypeSafety: + :path: "../node_modules/react-native/Libraries/TypeSafety" + React: + :path: "../node_modules/react-native/" + React-callinvoker: + :path: "../node_modules/react-native/ReactCommon/callinvoker" + React-Core: + :path: "../node_modules/react-native/" + React-CoreModules: + :path: "../node_modules/react-native/React/CoreModules" + React-cxxreact: + :path: "../node_modules/react-native/ReactCommon/cxxreact" + React-debug: + :path: "../node_modules/react-native/ReactCommon/react/debug" + React-defaultsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/defaults" + React-domnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/dom" + React-Fabric: + :path: "../node_modules/react-native/ReactCommon" + React-FabricComponents: + :path: "../node_modules/react-native/ReactCommon" + React-FabricImage: + :path: "../node_modules/react-native/ReactCommon" + React-featureflags: + :path: "../node_modules/react-native/ReactCommon/react/featureflags" + React-featureflagsnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/featureflags" + React-graphics: + :path: "../node_modules/react-native/ReactCommon/react/renderer/graphics" + React-hermes: + :path: "../node_modules/react-native/ReactCommon/hermes" + React-idlecallbacksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/idlecallbacks" + React-ImageManager: + :path: "../node_modules/react-native/ReactCommon/react/renderer/imagemanager/platform/ios" + React-jserrorhandler: + :path: "../node_modules/react-native/ReactCommon/jserrorhandler" + React-jsi: + :path: "../node_modules/react-native/ReactCommon/jsi" + React-jsiexecutor: + :path: "../node_modules/react-native/ReactCommon/jsiexecutor" + React-jsinspector: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern" + React-jsinspectorcdp: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/cdp" + React-jsinspectornetwork: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/network" + React-jsinspectortracing: + :path: "../node_modules/react-native/ReactCommon/jsinspector-modern/tracing" + React-jsitooling: + :path: "../node_modules/react-native/ReactCommon/jsitooling" + React-jsitracing: + :path: "../node_modules/react-native/ReactCommon/hermes/executor/" + React-logger: + :path: "../node_modules/react-native/ReactCommon/logger" + React-Mapbuffer: + :path: "../node_modules/react-native/ReactCommon" + React-microtasksnativemodule: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/microtasks" + react-native-safe-area-context: + :path: "../node_modules/react-native-safe-area-context" + React-NativeModulesApple: + :path: "../node_modules/react-native/ReactCommon/react/nativemodule/core/platform/ios" + React-oscompat: + :path: "../node_modules/react-native/ReactCommon/oscompat" + React-perflogger: + :path: "../node_modules/react-native/ReactCommon/reactperflogger" + React-performancetimeline: + :path: "../node_modules/react-native/ReactCommon/react/performance/timeline" + React-RCTActionSheet: + :path: "../node_modules/react-native/Libraries/ActionSheetIOS" + React-RCTAnimation: + :path: "../node_modules/react-native/Libraries/NativeAnimation" + React-RCTAppDelegate: + :path: "../node_modules/react-native/Libraries/AppDelegate" + React-RCTBlob: + :path: "../node_modules/react-native/Libraries/Blob" + React-RCTFabric: + :path: "../node_modules/react-native/React" + React-RCTFBReactNativeSpec: + :path: "../node_modules/react-native/React" + React-RCTImage: + :path: "../node_modules/react-native/Libraries/Image" + React-RCTLinking: + :path: "../node_modules/react-native/Libraries/LinkingIOS" + React-RCTNetwork: + :path: "../node_modules/react-native/Libraries/Network" + React-RCTRuntime: + :path: "../node_modules/react-native/React/Runtime" + React-RCTSettings: + :path: "../node_modules/react-native/Libraries/Settings" + React-RCTText: + :path: "../node_modules/react-native/Libraries/Text" + React-RCTVibration: + :path: "../node_modules/react-native/Libraries/Vibration" + React-rendererconsistency: + :path: "../node_modules/react-native/ReactCommon/react/renderer/consistency" + React-renderercss: + :path: "../node_modules/react-native/ReactCommon/react/renderer/css" + React-rendererdebug: + :path: "../node_modules/react-native/ReactCommon/react/renderer/debug" + React-RuntimeApple: + :path: "../node_modules/react-native/ReactCommon/react/runtime/platform/ios" + React-RuntimeCore: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimeexecutor: + :path: "../node_modules/react-native/ReactCommon/runtimeexecutor" + React-RuntimeHermes: + :path: "../node_modules/react-native/ReactCommon/react/runtime" + React-runtimescheduler: + :path: "../node_modules/react-native/ReactCommon/react/renderer/runtimescheduler" + React-timing: + :path: "../node_modules/react-native/ReactCommon/react/timing" + React-utils: + :path: "../node_modules/react-native/ReactCommon/react/utils" + ReactAppDependencyProvider: + :path: build/generated/ios + ReactCodegen: + :path: build/generated/ios + ReactCommon: + :path: "../node_modules/react-native/ReactCommon" + RNCMaskedView: + :path: "../node_modules/@react-native-masked-view/masked-view" + RNGestureHandler: + :path: "../node_modules/react-native-gesture-handler" + RNReanimated: + :path: "../node_modules/react-native-reanimated" + RNScreens: + :path: "../node_modules/react-native-screens" + RNVectorIcons: + :path: "../node_modules/react-native-vector-icons" + Yoga: + :path: "../node_modules/react-native/ReactCommon/yoga" + +SPEC CHECKSUMS: + boost: 7e761d76ca2ce687f7cc98e698152abd03a18f90 + DoubleConversion: cb417026b2400c8f53ae97020b2be961b59470cb + fast_float: b32c788ed9c6a8c584d114d0047beda9664e7cc6 + FBLazyVector: b8f1312d48447cca7b4abc21ed155db14742bd03 + fmt: a40bb5bd0294ea969aaaba240a927bd33d878cdd + glog: 5683914934d5b6e4240e497e0f4a3b42d1854183 + hermes-engine: 4f8246b1f6d79f625e0d99472d1f3a71da4d28ca + NetworkTools: 106c9082d4e844e4cad6043fdc708f37959a23aa + RCT-Folly: 846fda9475e61ec7bcbf8a3fe81edfcaeb090669 + RCTDeprecation: c4b9e2fd0ab200e3af72b013ed6113187c607077 + RCTRequired: e97dd5dafc1db8094e63bc5031e0371f092ae92a + RCTTypeSafety: 720403058b7c1380c6a3ae5706981d6362962c89 + React: f1486d005993b0af01943af1850d3d4f3b597545 + React-callinvoker: 133f69368c8559e744efa345223625d412f5dfbe + React-Core: 559823921b4f294c2840fa8238ca958a29ddc211 + React-CoreModules: c41e7bbfabbc420783bb926f45837a0d5e53341e + React-cxxreact: 9cb9fa738274a1b36b97ede09c8a6717dec1a20b + React-debug: e01581e1589f329e61c95b332bf7f4969b10564b + React-defaultsnativemodule: bbb39447caa6b6cf9405fa0099f828c083640faa + React-domnativemodule: 03744d12b6d56d098531a933730bf1d4cb79bdfb + React-Fabric: 530b3993a12a96e8a7cdb9f0ef48e605277b572e + React-FabricComponents: 271ec2a9b2c00ac66fd6d1fd24e9e964d907751d + React-FabricImage: d0af66e976dbab7f8b81e36dd369fc70727d2695 + React-featureflags: 269704c8eff86e0485c9d384e286350fcda6eb70 + React-featureflagsnativemodule: db1e5d88a912fb08a5ece33fcf64e1b732da8467 + React-graphics: b19d03a01b0722b4dc82f47acb56dc3ed41937e7 + React-hermes: 811606c0aca5a3f9c6fa8e4994e02ca8f677e68e + React-idlecallbacksnativemodule: 3a3df629cd50046c7e4354f9025aefe8f2c84601 + React-ImageManager: 0d53866c63132791e37bb2373f93044fdef14aa3 + React-jserrorhandler: d5700d6ab7162fd575287502a3c5d601d98e7f09 + React-jsi: ece95417fedbed0e7153a855cb8342b7c72ab75e + React-jsiexecutor: 2b0bb644b533df2f5c0cd6ade9a4560d0bf1dd84 + React-jsinspector: 0c160f8510a8852bdf2dac12f0b1949efc18200b + React-jsinspectorcdp: f4b84409f453f61ddd8614ad45139bc594ec6bb5 + React-jsinspectornetwork: 8f2f0ca8c871ca19b571f426002c0012e7fb2aee + React-jsinspectortracing: 33f6b977eb8a4bc1e3d1a4b948809aca083143f9 + React-jsitooling: 2c61529b589e17229a9f0a4a4fc35aa7ad495850 + React-jsitracing: 838a7b0c013c4aff7d382d7fdc78cf442013ba1d + React-logger: 7aef4d74123e5e3d267e5af1fbf5135b5a0d8381 + React-Mapbuffer: 91e0eab42a6ae7f3e34091a126d70fc53bd3823e + React-microtasksnativemodule: 1ead4fe154df3b1ba34b5a9e35ef3c4bdfa72ccb + react-native-safe-area-context: befb5404eb8a16fdc07fa2bebab3568ecabcbb8a + React-NativeModulesApple: eff2eba56030eb0d107b1642b8f853bc36a833ac + React-oscompat: b12c633e9c00f1f99467b1e0e0b8038895dae436 + React-perflogger: 58d12c4e5df1403030c97b9c621375c312cca454 + React-performancetimeline: 0ee0a3236c77a4ee6d8a6189089e41e4003d292e + React-RCTActionSheet: 3f741a3712653611a6bfc5abceb8260af9d0b218 + React-RCTAnimation: 408ad69ea136e99a463dd33eadecc29e586b3d72 + React-RCTAppDelegate: f03b46e80b8a3dbfa84b35abfe123e02f3ceef83 + React-RCTBlob: bd42e92a00ad22eaab92ffe5c137e7a2f725887a + React-RCTFabric: b99ab638c73cf2d57b886eafdbfb2e4909b0eb9a + React-RCTFBReactNativeSpec: 7ad9aba0e0655e3f29be0a1c3fd4a888fab04dcf + React-RCTImage: 0f1c74f7cd20027f8c34976a211b35d4263a0add + React-RCTLinking: 6d7dfc3a74110df56c3a73cc7626bf4415656542 + React-RCTNetwork: 6a25d8645a80d5b86098675ca39bf8fcf1afa08b + React-RCTRuntime: 38bfe9766565ae3293ca230bc51c9c020a8bc98a + React-RCTSettings: 651d9ae2cdd32f547ad0d225a2c13886d6ad2358 + React-RCTText: 9bc66cd288478e23195e01f5cb45eba79986b2b4 + React-RCTVibration: 371226f5667a00c76d792dcdb5c2e0fcbcde0c3b + React-rendererconsistency: a05f6c37f9389c53213d1e28798e441fa6fbdbcd + React-renderercss: 6e4febfa014b0f53bc171a62b0f713ddbdbb9860 + React-rendererdebug: e94bf27b9d55ef2795caa8e43aa92abc4a373b8b + React-RuntimeApple: 723be5159519eba1cd92449acb29436d21571b82 + React-RuntimeCore: f58eb0f01065c9d27d91de10b2e4ab4c76d83b0e + React-runtimeexecutor: f615ec8742d0b5820170f7c8b4d2c7cb75d93ac9 + React-RuntimeHermes: fddb258e03d330d1132bb19e78fe51ac2f3f41ac + React-runtimescheduler: e92a31460e654ced8587debeec37553315e1b6a5 + React-timing: 97ada2c47b4c5932e7f773c7d239c52b90d6ca68 + React-utils: f0949d247a46b4c09f03e5a3cb1167602d0b729a + ReactAppDependencyProvider: 3eb9096cb139eb433965693bbe541d96eb3d3ec9 + ReactCodegen: 4d203eddf6f977caa324640a20f92e70408d648b + ReactCommon: ce5d4226dfaf9d5dacbef57b4528819e39d3a120 + RNCMaskedView: 5ef8c95cbab95334a32763b72896a7b7d07e6299 + RNGestureHandler: 552c97e0bcb541ff91259759ae49420501d9d5e4 + RNReanimated: 9af1b9f7d221d1cc2f99d935bab08419cae7c1ce + RNScreens: 82303e628dc897156e686705597f2bbcbfa027c3 + RNVectorIcons: 791f13226ec4a3fd13062eda9e892159f0981fae + SocketRocket: d4aabe649be1e368d1318fdf28a022d714d65748 + Yoga: 11c9686a21e2cd82a094a723649d9f4507200fb0 + +PODFILE CHECKSUM: 7c6263b37acc4d9ba197ae38c7f50f6a3a719d8d + +COCOAPODS: 1.16.1 diff --git a/ios/NetworkToolsInterceptor.h b/ios/NetworkToolsInterceptor.h index 6c5c63d..6c6914a 100644 --- a/ios/NetworkToolsInterceptor.h +++ b/ios/NetworkToolsInterceptor.h @@ -11,6 +11,14 @@ NS_ASSUME_NONNULL_BEGIN */ @interface NetworkToolsInterceptor : NSURLProtocol +/** + * Swizzles NSURLSessionConfiguration.protocolClasses so that every session + * created after +activate (including React Native's internal sessions) will + * have NetworkToolsInterceptor injected at the front of the protocol list. + * Called automatically by +[NetworkToolsManager activate]. + */ ++ (void)swizzleSessionConfiguration; + @end NS_ASSUME_NONNULL_END diff --git a/ios/NetworkToolsInterceptor.m b/ios/NetworkToolsInterceptor.m index 4ddcaff..d54b957 100644 --- a/ios/NetworkToolsInterceptor.m +++ b/ios/NetworkToolsInterceptor.m @@ -1,16 +1,33 @@ #import "NetworkToolsInterceptor.h" #import "NetworkToolsStorage.h" #import "NetworkToolsManager.h" +#import -// Property key used to mark requests this interceptor is already handling, -// preventing infinite recursion when the forwarding URLSession is created. static NSString *const kNTHandledKey = @"NetworkToolsHandled"; - -// Cap body capture at 256 KB to avoid buffering large binary payloads in RAM. static const NSInteger kNTMaxBodyBytes = 256 * 1024; +// Original IMP saved during swizzle so we can call through to it. +static IMP gOriginalProtocolClassesIMP = nil; + +// Replacement implementation for -[NSURLSessionConfiguration protocolClasses]. +// Prepends NetworkToolsInterceptor to every session configuration, including +// React Native's internal sessions that are created before +activate is called. +static NSArray *nt_injectedProtocolClasses(NSURLSessionConfiguration *self, SEL _cmd) { + NSArray *original = gOriginalProtocolClassesIMP + ? ((NSArray *(*)(id, SEL))gOriginalProtocolClassesIMP)(self, _cmd) + : @[]; + NSMutableArray *classes = original ? [original mutableCopy] : [NSMutableArray array]; + if (![classes containsObject:[NetworkToolsInterceptor class]]) { + [classes insertObject:[NetworkToolsInterceptor class] atIndex:0]; + } + return [classes copy]; +} + @interface NetworkToolsInterceptor () @property (nonatomic, strong) NSURLSessionDataTask *dataTask; +// Strong reference to the forwarding session — without this the session is +// deallocated immediately, cancelling the data task before it can complete. +@property (nonatomic, strong) NSURLSession *forwardingSession; @property (nonatomic, strong) NSMutableData *responseData; @property (nonatomic, strong, nullable) NSHTTPURLResponse *httpResponse; @property (nonatomic, assign) double requestStartTime; @@ -20,10 +37,22 @@ @interface NetworkToolsInterceptor () @implementation NetworkToolsInterceptor +#pragma mark - Swizzling + ++ (void)swizzleSessionConfiguration { + static dispatch_once_t once; + dispatch_once(&once, ^{ + Method m = class_getInstanceMethod( + [NSURLSessionConfiguration class], + @selector(protocolClasses) + ); + gOriginalProtocolClassesIMP = method_setImplementation(m, (IMP)nt_injectedProtocolClasses); + }); +} + #pragma mark - NSURLProtocol registration + (BOOL)canInitWithRequest:(NSURLRequest *)request { - // Skip requests already being handled by us (prevents infinite loop). if ([NSURLProtocol propertyForKey:kNTHandledKey inRequest:request]) { return NO; } @@ -41,25 +70,55 @@ - (void)startLoading { self.requestId = [[NSUUID UUID] UUIDString]; self.requestStartTime = [NSDate date].timeIntervalSince1970 * 1000.0; self.responseData = [NSMutableData data]; - self.capturedRequestBody = [self readBodyFromRequest:self.request]; - // Tag the forwarded request so we don't intercept it again. + // Buffer the stream BEFORE mutableCopy — once the stream is read it cannot + // be rewound, so copying the request after reading the stream produces a + // forwarded request with an exhausted (empty) body. + NSData *streamData = nil; + if (self.request.HTTPBodyStream) { + streamData = [self drainStream:self.request.HTTPBodyStream]; + } + + // Capture body string for recording. + if (streamData.length > 0) { + self.capturedRequestBody = [self bodyStringFromData:streamData]; + } else if (self.request.HTTPBody.length > 0) { + self.capturedRequestBody = [self bodyStringFromData:self.request.HTTPBody]; + } + NSMutableURLRequest *forwarded = [self.request mutableCopy]; + + // Replace the (now-exhausted) stream with the buffered NSData so the + // forwarded request actually sends the correct body. + if (streamData.length > 0) { + forwarded.HTTPBody = streamData; + forwarded.HTTPBodyStream = nil; + } + + // Mark the forwarded request so canInitWithRequest: skips it. [NSURLProtocol setProperty:@YES forKey:kNTHandledKey inRequest:forwarded]; - // Use an ephemeral session so cookies / cache don't bleed between the - // interceptor's internal session and the app's session. - NSURLSessionConfiguration *config = [NSURLSessionConfiguration ephemeralSessionConfiguration]; - NSURLSession *session = [NSURLSession sessionWithConfiguration:config - delegate:self - delegateQueue:nil]; - self.dataTask = [session dataTaskWithRequest:forwarded]; + // Use defaultSessionConfiguration so cookies and credentials are preserved. + // Remove ourselves from its protocol list to prevent re-interception. + NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; + NSMutableArray *protocols = config.protocolClasses + ? [config.protocolClasses mutableCopy] + : [NSMutableArray array]; + [protocols removeObject:[NetworkToolsInterceptor class]]; + config.protocolClasses = [protocols copy]; + + self.forwardingSession = [NSURLSession sessionWithConfiguration:config + delegate:self + delegateQueue:nil]; + self.dataTask = [self.forwardingSession dataTaskWithRequest:forwarded]; [self.dataTask resume]; } - (void)stopLoading { [self.dataTask cancel]; + [self.forwardingSession invalidateAndCancel]; self.dataTask = nil; + self.forwardingSession = nil; } #pragma mark - NSURLSessionDataDelegate @@ -99,7 +158,6 @@ - (void)URLSession:(NSURLSession *)session willPerformHTTPRedirection:(NSHTTPURLResponse *)response newRequest:(NSURLRequest *)newRequest completionHandler:(void (^)(NSURLRequest *_Nullable))completionHandler { - // Pass redirects through transparently; the final response is what gets recorded. [self.client URLProtocol:self wasRedirectedToRequest:newRequest redirectResponse:response]; completionHandler(newRequest); } @@ -112,29 +170,20 @@ - (void)recordWithError:(nullable NSError *)error { double duration = responseTime - self.requestStartTime; NSMutableDictionary *entry = [NSMutableDictionary dictionary]; - entry[@"id"] = self.requestId; - entry[@"url"] = request.URL.absoluteString ?: @""; - entry[@"method"] = request.HTTPMethod ?: @"GET"; - entry[@"requestTime"] = @(self.requestStartTime); - entry[@"responseTime"] = @(responseTime); - entry[@"duration"] = @(duration); - - // Request headers + entry[@"id"] = self.requestId; + entry[@"url"] = request.URL.absoluteString ?: @""; + entry[@"method"] = request.HTTPMethod ?: @"GET"; + entry[@"requestTime"] = @(self.requestStartTime); + entry[@"responseTime"] = @(responseTime); + entry[@"duration"] = @(duration); entry[@"requestHeaders"] = request.allHTTPHeaderFields ?: @{}; + entry[@"requestBody"] = self.capturedRequestBody ?: @""; - // Request body (already captured in startLoading before the request was sent) - entry[@"requestBody"] = self.capturedRequestBody ?: @""; - - // Response NSHTTPURLResponse *response = self.httpResponse; entry[@"responseCode"] = response ? @(response.statusCode) : @0; entry[@"responseHeaders"] = response ? response.allHeaderFields : @{}; - - // Response body — skip binary content types, cap text bodies - entry[@"responseBody"] = [self responseBodyStringForResponse:response]; - - // Error - entry[@"error"] = error ? (error.localizedDescription ?: @"Unknown error") : @""; + entry[@"responseBody"] = [self responseBodyStringForResponse:response]; + entry[@"error"] = error ? (error.localizedDescription ?: @"Unknown error") : @""; [[NetworkToolsStorage shared] addRequest:entry]; [[NetworkToolsManager shared] emitRequest:entry]; @@ -142,37 +191,30 @@ - (void)recordWithError:(nullable NSError *)error { #pragma mark - Helpers -- (nullable NSString *)readBodyFromRequest:(NSURLRequest *)request { - NSData *bodyData = nil; - - if (request.HTTPBody.length > 0) { - bodyData = request.HTTPBody; - } else if (request.HTTPBodyStream) { - NSInputStream *stream = request.HTTPBodyStream; - [stream open]; - NSMutableData *buffer = [NSMutableData data]; - uint8_t chunk[4096]; - NSInteger bytesRead; - NSInteger totalRead = 0; - while (totalRead < kNTMaxBodyBytes && - (bytesRead = [stream read:chunk maxLength:sizeof(chunk)]) > 0) { - [buffer appendBytes:chunk length:(NSUInteger)bytesRead]; - totalRead += bytesRead; - } - [stream close]; - bodyData = buffer.length > 0 ? buffer : nil; +- (NSData *)drainStream:(NSInputStream *)stream { + NSMutableData *buffer = [NSMutableData data]; + [stream open]; + uint8_t chunk[4096]; + NSInteger bytesRead; + NSInteger totalRead = 0; + while (totalRead < kNTMaxBodyBytes && + (bytesRead = [stream read:chunk maxLength:sizeof(chunk)]) > 0) { + [buffer appendBytes:chunk length:(NSUInteger)bytesRead]; + totalRead += bytesRead; } + [stream close]; + return buffer; +} - if (!bodyData) return nil; - - NSData *capped = bodyData.length <= (NSUInteger)kNTMaxBodyBytes - ? bodyData - : [bodyData subdataWithRange:NSMakeRange(0, (NSUInteger)kNTMaxBodyBytes)]; +- (nullable NSString *)bodyStringFromData:(NSData *)data { + if (data.length == 0) return nil; + NSData *capped = data.length <= (NSUInteger)kNTMaxBodyBytes + ? data + : [data subdataWithRange:NSMakeRange(0, (NSUInteger)kNTMaxBodyBytes)]; return [[NSString alloc] initWithData:capped encoding:NSUTF8StringEncoding]; } - (NSString *)responseBodyStringForResponse:(nullable NSHTTPURLResponse *)response { - // Skip binary MIME types entirely. NSString *mimeType = response.MIMEType.lowercaseString ?: @""; if ([mimeType hasPrefix:@"image/"] || [mimeType hasPrefix:@"video/"] || diff --git a/ios/NetworkToolsManager.h b/ios/NetworkToolsManager.h index 187825b..faa6b4a 100644 --- a/ios/NetworkToolsManager.h +++ b/ios/NetworkToolsManager.h @@ -1,5 +1,7 @@ #import +@class RCTEventEmitter; + NS_ASSUME_NONNULL_BEGIN /** @@ -26,7 +28,7 @@ NS_ASSUME_NONNULL_BEGIN * Called by the native module to hand over its RCTEventEmitter reference so * the interceptor can emit events to JavaScript. */ -- (void)setEmitter:(nullable id)emitter; +- (void)setEmitter:(nullable RCTEventEmitter *)emitter; /** * Emits a captured request dictionary as a "NetworkTools:onRequest" event. diff --git a/ios/NetworkToolsManager.m b/ios/NetworkToolsManager.m index d2e5a3f..563c081 100644 --- a/ios/NetworkToolsManager.m +++ b/ios/NetworkToolsManager.m @@ -1,10 +1,11 @@ #import "NetworkToolsManager.h" #import "NetworkToolsInterceptor.h" +#import static NSString *const kNTEventName = @"NetworkTools:onRequest"; @implementation NetworkToolsManager { - __weak id _emitter; + __weak RCTEventEmitter *_emitter; } + (instancetype)shared { @@ -19,6 +20,10 @@ + (instancetype)shared { + (void)activate { #if DEBUG [NSURLProtocol registerClass:[NetworkToolsInterceptor class]]; + // Swizzle NSURLSessionConfiguration.protocolClasses so that React Native's + // internal sessions (which snapshot the protocol list at session creation + // time) also include NetworkToolsInterceptor. + [NetworkToolsInterceptor swizzleSessionConfiguration]; #endif } @@ -28,11 +33,9 @@ - (void)setEmitter:(nullable id)emitter { - (void)emitRequest:(NSDictionary *)requestDict { #if DEBUG - id emitter = _emitter; + RCTEventEmitter *emitter = _emitter; if (emitter == nil) return; - if ([emitter respondsToSelector:@selector(sendEventWithName:body:)]) { - [emitter sendEventWithName:kNTEventName body:requestDict]; - } + [emitter sendEventWithName:kNTEventName body:requestDict]; #endif } diff --git a/src/components/floating-network-monitor/index.tsx b/src/components/floating-network-monitor/index.tsx index 14d838d..3d37931 100644 --- a/src/components/floating-network-monitor/index.tsx +++ b/src/components/floating-network-monitor/index.tsx @@ -290,9 +290,6 @@ const styles = StyleSheet.create({ container: { backgroundColor: colors.background, paddingHorizontal: 16, - // position: 'absolute', - // justifyContent: 'center', - // alignItems: 'center', elevation: 3, shadowColor: colors.grey5, shadowOffset: { width: 0, height: 2 }, @@ -381,6 +378,7 @@ const styles = StyleSheet.create({ }, footerStyle: { height: spacing.xxl, + paddingBottom: spacing.xl, }, }); diff --git a/src/components/request-detail/NetworkDetails.tsx b/src/components/request-detail/NetworkDetails.tsx index f3477a3..53d7638 100644 --- a/src/components/request-detail/NetworkDetails.tsx +++ b/src/components/request-detail/NetworkDetails.tsx @@ -168,29 +168,32 @@ const OverviewTab: React.FC<{ request: NetworkRequest }> = ({ request }) => { // Request Tab Component const RequestTab: React.FC<{ request: NetworkRequest }> = ({ request }) => { + const requestBody = request.requestBody + ? safeJsonParse(request.requestBody) + : null; + return ( - + ); }; // Response Tab Component const ResponseTab: React.FC<{ request: NetworkRequest }> = ({ request }) => { - const responseData = - typeof request.responseData === 'string' - ? safeJsonParse(request.responseData) - : request.responseData; + const responseBody = request.responseBody + ? safeJsonParse(request.responseBody) + : null; return ( - + {request.customError && ( <> @@ -269,14 +272,21 @@ const DataBox: React.FC<{ data: any; placeholder: string }> = ({ data, placeholder, }) => { - const isEmpty = !data || Object.keys(data).length === 0; + const isEmpty = + data === null || + data === undefined || + data === '' || + (typeof data === 'object' && Object.keys(data).length === 0); + + const display = + typeof data === 'string' ? data : JSON.stringify(data, null, 2); return ( {isEmpty ? ( {placeholder} ) : ( - {JSON.stringify(data, null, 2)} + {display} )} ); @@ -362,6 +372,7 @@ const styles = StyleSheet.create({ content: { flex: 1, backgroundColor: colors.background, + paddingBottom: spacing.lg, }, tabContent: { padding: spacing.md, diff --git a/src/context/types.ts b/src/context/types.ts index eef7ff8..386ab5c 100644 --- a/src/context/types.ts +++ b/src/context/types.ts @@ -28,8 +28,8 @@ export type NetworkRequest = { responseCode: number; requestHeaders: Record; responseHeaders: Record; - requestData?: any; - responseData?: any; + requestBody?: string; + responseBody?: string; duration: number; requestTime: number; responseTime: number;