Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 9 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,24 @@ If you use Expo Development Builds, add the plugin to `app.json`:
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
}
Expand Down
5 changes: 4 additions & 1 deletion android/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,18 @@ android {
defaultConfig {
minSdkVersion getExtOrIntegerDefault("minSdkVersion")
targetSdkVersion getExtOrIntegerDefault("targetSdkVersion")
buildConfigField "boolean", "NETWORK_TOOLS_ENABLED", "true"
}

buildFeatures {
buildConfig true
}

buildTypes {
debug {
buildConfigField "boolean", "NETWORK_TOOLS_ENABLED", "true"
}
release {
buildConfigField "boolean", "NETWORK_TOOLS_ENABLED", "false"
minifyEnabled false
}
}
Expand Down
54 changes: 24 additions & 30 deletions docs/SETUP_GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -53,6 +53,7 @@ If you're using React Native's default networking (fetch), you'll need to custom
import com.facebook.react.ReactApplication
import com.facebook.react.ReactNativeHost
import com.facebook.react.defaults.DefaultReactNativeHost
import com.facebook.react.modules.network.NetworkingModule
import com.networktools.NetworkToolsManager
import okhttp3.OkHttpClient

Expand All @@ -61,59 +62,52 @@ 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
}
}
```

> **Why `BuildConfig.DEBUG`?** The library's own `BuildConfig.NETWORK_TOOLS_ENABLED` is already set to `false` for release builds, so `NetworkToolsManager.addInterceptor()` would be a no-op anyway. The outer `if (BuildConfig.DEBUG)` guard is a second line of defence: it prevents the `setCustomClientBuilder` call itself from running in production and makes the intent explicit to anyone reading the code.

**Java:**

```java
import com.facebook.react.ReactApplication;
import com.facebook.react.ReactNativeHost;
import com.facebook.react.defaults.DefaultReactNativeHost;
import com.facebook.react.modules.network.NetworkingModule;
import com.networktools.NetworkToolsManager;
import okhttp3.OkHttpClient;

public class MainApplication extends Application implements ReactApplication {

private final ReactNativeHost mReactNativeHost =
new DefaultReactNativeHost(this) {
// ... other configurations

@Override
public boolean getUseDeveloperSupport() {
return BuildConfig.DEBUG;
}

@Override
public void onCreate() {
@Override
public void onCreate() {
super.onCreate();

// Use NetworkingModule.setCustomClientBuilder to set the custom builder logic
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() { // 1. Create an anonymous class

// 2. Implement the required 'apply' method
@Override
public void apply(OkHttpClient.Builder builder) {
// 3. Call your static/utility method to add the interceptor
NetworkToolsManager.addInterceptor(builder);
}
if (BuildConfig.DEBUG) {
NetworkingModule.setCustomClientBuilder(
new NetworkingModule.CustomClientBuilder() {
@Override
public void apply(OkHttpClient.Builder builder) {
NetworkToolsManager.addInterceptor(builder);
}
}
);
);
}

// rest of your code
}
};
}
}
```

Expand Down
141 changes: 109 additions & 32 deletions docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -138,38 +138,115 @@ This checklist will help you complete the development and testing of react-nativ
- [ ] Test on iOS
- [ ] Update documentation

### 7. Advanced Features (Optional)

- [ ] Request filtering
- [ ] By URL pattern
- [ ] By method
- [ ] By status code
- [ ] By time range

- [ ] Search functionality
- [ ] Search in URLs
- [ ] Search in request/response bodies
- [ ] Search in headers

- [ ] Export functionality
- [ ] Export to JSON file
- [ ] Share via system share sheet
- [ ] Copy to clipboard

- [ ] UI Components
- [ ] Pre-built NetworkInspector screen
- [ ] Request detail modal
- [ ] Search and filter UI

- [ ] Request replay
- [ ] Replay captured requests
- [ ] Modify and replay
- [ ] Batch replay

- [ ] Mock responses
- [ ] Return mock data for testing
- [ ] Conditional mocking
- [ ] Mock response editor
### 7. Advanced Features

#### Tier 1 — Core Inspector Completeness

- [ ] Session summary dashboard
- [ ] Total requests, success/fail counts, total data transferred
- [ ] Average and peak latency at a glance
- [ ] Shown as a stats panel above the request list

- [ ] Export to CSV / JSON
- [ ] Serialize all captured requests to CSV rows
- [ ] Full JSON dump of session
- [ ] Write to device file system, then trigger share sheet

- [ ] Share individual request
- [ ] Long-press a request to open share options
- [ ] Format choices: plain text summary, JSON, cURL command
- [ ] Use RN `Share` API / `expo-sharing`

- [ ] HAR (HTTP Archive) export
- [ ] Full HAR 1.2 format — importable into Postman, Charles, Proxyman, browser DevTools
- [ ] Include timings, headers, bodies, cookies

- [ ] cURL copy
- [ ] One-tap copy of a request as a ready-to-run `curl` command
- [ ] Include headers, method, body, and URL

#### Tier 2 — Analytics & Statistics

- [ ] Data usage breakdown
- [ ] Bytes sent and received per domain
- [ ] Bytes per endpoint
- [ ] Running total for the session

- [ ] Response time distribution
- [ ] P50 / P95 / P99 latency per domain
- [ ] Simple histogram or spark-line view
- [ ] Time-to-first-byte (TTFB) separate from total duration

- [ ] Per-domain leaderboard
- [ ] Sorted by: slowest average, most calls, most errors
- [ ] Drillable — tap domain to see its requests

- [ ] Slow request alerts
- [ ] Configurable threshold (e.g. > 2 s) via `NetworkMonitorProvider` prop
- [ ] Visual badge / highlight on slow requests in the list

- [ ] Error rate tracking
- [ ] 4xx / 5xx frequency over time within a session
- [ ] Separate counters for client errors vs server errors

#### Tier 3 — Developer Productivity

- [ ] Persistent storage (opt-in)
- [ ] Save requests across restarts to AsyncStorage or MMKV
- [ ] Configurable via `persistRequests` prop on `NetworkMonitorProvider`
- [ ] Clear-on-launch option

- [ ] Pinned / bookmarked requests
- [ ] Mark specific requests to prevent FIFO eviction
- [ ] Separate "Pinned" tab in the monitor UI

- [ ] Regex search and filter
- [ ] Toggle between plain-text and regex mode in the search bar
- [ ] Filter across URL, headers, and body simultaneously
- [ ] Filter by URL pattern, method, status code, time range (migrated from old list)

- [ ] Request diff
- [ ] Select two requests to the same endpoint and compare side-by-side
- [ ] Highlight header / body changes between calls (useful for pagination, mutations)

- [ ] GraphQL-aware display
- [ ] Parse `operationName`, `variables`, and `data` from GraphQL POST bodies
- [ ] Show operation name as the display title instead of the raw URL

- [ ] WebSocket monitoring
- [ ] Capture WebSocket frames via a custom OkHttp `WebSocketListener` wrapper
- [ ] Show open/close events and individual frames in a dedicated tab

#### Tier 4 — Power Features

- [ ] Mock / intercept responses
- [ ] Match requests by URL pattern and return a configured mock response
- [ ] No-server testing directly from the in-app tool
- [ ] Mock editor UI — status code, headers, body
- [ ] Conditional mocking (e.g. only on N-th call)

- [ ] Replay requests
- [ ] Re-fire a captured request with one tap
- [ ] Editable replay — modify headers / body before sending
- [ ] Batch replay of a selected set of requests

- [ ] Network condition simulation
- [ ] Artificial latency injection (configurable ms)
- [ ] Bandwidth throttling (configurable KB/s)
- [ ] Simulate offline / flaky connection

- [ ] Sensitive header redaction
- [ ] Auto-mask `Authorization`, `Cookie`, `X-Api-Key` by default
- [ ] Configurable allowlist / blocklist via `NetworkMonitorProvider` prop
- [ ] Toggle reveal on tap in the detail view

- [ ] Shake-to-open
- [ ] Open the network monitor on device shake — no floating button required
- [ ] Opt-in via `openOnShake` prop

- [ ] Desktop companion / Metro plugin
- [ ] Stream captured requests to a browser panel alongside the Metro bundler
- [ ] WebSocket bridge from the app to a local dev-server listener

### 8. Pre-Release Checklist

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,13 +38,15 @@ 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)
}
}
}
)
)
}

loadReactNative(this)
}
Expand Down
Loading