react-native-network-lens 0.1.0 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +254 -97
- package/lib/module/components/BodyViewer.js +31 -19
- package/lib/module/components/BodyViewer.js.map +1 -1
- package/lib/module/components/JsonTree/JsonTreeView.js +10 -6
- package/lib/module/components/JsonTree/JsonTreeView.js.map +1 -1
- package/lib/module/components/JsonTree/model.js +2 -0
- package/lib/module/components/JsonTree/model.js.map +1 -1
- package/lib/module/components/NetworkLens.js +4 -8
- package/lib/module/components/NetworkLens.js.map +1 -1
- package/lib/module/components/NetworkLensOverlay.js +67 -22
- package/lib/module/components/NetworkLensOverlay.js.map +1 -1
- package/lib/module/components/RawTextView.js +10 -6
- package/lib/module/components/RawTextView.js.map +1 -1
- package/lib/module/components/RequestDetails/RequestDetails.js +44 -21
- package/lib/module/components/RequestDetails/RequestDetails.js.map +1 -1
- package/lib/module/components/RequestList/FilterBar.js +3 -3
- package/lib/module/components/RequestList/FilterBar.js.map +1 -1
- package/lib/module/components/RequestList/RequestList.js +7 -8
- package/lib/module/components/RequestList/RequestList.js.map +1 -1
- package/lib/module/components/ui/Button.js +21 -5
- package/lib/module/components/ui/Button.js.map +1 -1
- package/lib/module/components/ui/Pill.js +13 -6
- package/lib/module/components/ui/Pill.js.map +1 -1
- package/lib/module/settings.js +48 -0
- package/lib/module/settings.js.map +1 -0
- package/lib/module/theme.js +4 -4
- package/lib/typescript/src/components/BodyViewer.d.ts.map +1 -1
- package/lib/typescript/src/components/JsonTree/JsonTreeView.d.ts.map +1 -1
- package/lib/typescript/src/components/JsonTree/model.d.ts.map +1 -1
- package/lib/typescript/src/components/NetworkLens.d.ts +0 -3
- package/lib/typescript/src/components/NetworkLens.d.ts.map +1 -1
- package/lib/typescript/src/components/NetworkLensOverlay.d.ts +1 -1
- package/lib/typescript/src/components/NetworkLensOverlay.d.ts.map +1 -1
- package/lib/typescript/src/components/RawTextView.d.ts.map +1 -1
- package/lib/typescript/src/components/RequestDetails/RequestDetails.d.ts.map +1 -1
- package/lib/typescript/src/components/RequestList/RequestList.d.ts +1 -4
- package/lib/typescript/src/components/RequestList/RequestList.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Button.d.ts +3 -1
- package/lib/typescript/src/components/ui/Button.d.ts.map +1 -1
- package/lib/typescript/src/components/ui/Pill.d.ts +1 -0
- package/lib/typescript/src/components/ui/Pill.d.ts.map +1 -1
- package/lib/typescript/src/settings.d.ts +18 -0
- package/lib/typescript/src/settings.d.ts.map +1 -0
- package/package.json +3 -3
- package/src/components/BodyViewer.tsx +37 -19
- package/src/components/JsonTree/JsonTreeView.tsx +11 -5
- package/src/components/JsonTree/model.ts +2 -0
- package/src/components/NetworkLens.tsx +2 -11
- package/src/components/NetworkLensOverlay.tsx +54 -23
- package/src/components/RawTextView.tsx +11 -6
- package/src/components/RequestDetails/RequestDetails.tsx +31 -19
- package/src/components/RequestList/FilterBar.tsx +2 -2
- package/src/components/RequestList/RequestList.tsx +3 -7
- package/src/components/ui/Button.tsx +23 -7
- package/src/components/ui/Pill.tsx +14 -5
- package/src/settings.ts +55 -0
- package/src/theme.ts +2 -2
package/README.md
CHANGED
|
@@ -1,40 +1,116 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
-
|
|
37
|
-
|
|
1
|
+
<h1 align="center">react-native-network-lens</h1>
|
|
2
|
+
|
|
3
|
+
<p align="center">
|
|
4
|
+
<strong>See every request your React Native app makes, right on the phone.</strong><br />
|
|
5
|
+
Tabbed request details · collapsible JSON tree · search · zero dependencies
|
|
6
|
+
</p>
|
|
7
|
+
|
|
8
|
+
<p align="center">
|
|
9
|
+
<a href="https://www.npmjs.com/package/react-native-network-lens"><img alt="npm version" src="https://img.shields.io/npm/v/react-native-network-lens?color=2563eb" /></a>
|
|
10
|
+
<a href="https://bundlephobia.com/package/react-native-network-lens"><img alt="bundle size" src="https://img.shields.io/bundlephobia/minzip/react-native-network-lens?label=min%2Bgzip" /></a>
|
|
11
|
+
<a href="https://www.npmjs.com/package/react-native-network-lens?activeTab=dependencies"><img alt="dependencies: none" src="https://img.shields.io/badge/dependencies-none-16a34a" /></a>
|
|
12
|
+
<a href="https://github.com/stainsmjohnson/react-native-network-lens/actions/workflows/ci.yml"><img alt="CI" src="https://github.com/stainsmjohnson/react-native-network-lens/actions/workflows/ci.yml/badge.svg" /></a>
|
|
13
|
+
<img alt="TypeScript" src="https://img.shields.io/npm/types/react-native-network-lens" />
|
|
14
|
+
<img alt="platforms" src="https://img.shields.io/badge/platforms-iOS%20%7C%20Android%20%7C%20Expo-5b5b5b" />
|
|
15
|
+
<a href="./LICENSE"><img alt="license" src="https://img.shields.io/npm/l/react-native-network-lens" /></a>
|
|
16
|
+
</p>
|
|
17
|
+
|
|
18
|
+
<p align="center">
|
|
19
|
+
<a href="https://github.com/stainsmjohnson/react-native-network-lens/stargazers"><img alt="GitHub stars" src="https://img.shields.io/github/stars/stainsmjohnson/react-native-network-lens?style=social&label=Star%20this%20project" /></a>
|
|
20
|
+
</p>
|
|
21
|
+
|
|
22
|
+
An in-app HTTP inspector for React Native that is actually usable on a phone
|
|
23
|
+
screen. Drop in one component, fire your requests, tap the floating button and
|
|
24
|
+
read JSON like you would in Chrome DevTools: expand the object you care about,
|
|
25
|
+
collapse the noise, search for a key, scroll sideways instead of fighting
|
|
26
|
+
wrapped text.
|
|
27
|
+
|
|
28
|
+
No native code, no Flipper, no desktop app, no debug build required. It works
|
|
29
|
+
in release builds too, so testers and QA can inspect traffic and share a cURL
|
|
30
|
+
or HAR with you from the device itself.
|
|
31
|
+
|
|
32
|
+
## Screenshots
|
|
33
|
+
|
|
34
|
+
<p align="center">
|
|
35
|
+
<img src="docs/ios-list.png" width="200" alt="Request list on iOS" />
|
|
36
|
+
<img src="docs/ios-tree.png" width="200" alt="Collapsible JSON tree on iOS" />
|
|
37
|
+
<img src="docs/ios-search.png" width="200" alt="Searching inside a response" />
|
|
38
|
+
<img src="docs/ios-raw.png" width="200" alt="Raw view with line numbers" />
|
|
39
|
+
</p>
|
|
40
|
+
<p align="center">
|
|
41
|
+
<img src="docs/android-list.png" width="200" alt="Request list on Android" />
|
|
42
|
+
<img src="docs/android-tree.png" width="200" alt="JSON tree on Android" />
|
|
43
|
+
<img src="docs/ios-list-dark.png" width="200" alt="Dark theme list" />
|
|
44
|
+
<img src="docs/ios-tree-dark.png" width="200" alt="Dark theme JSON tree" />
|
|
45
|
+
</p>
|
|
46
|
+
|
|
47
|
+
## Why another network logger?
|
|
48
|
+
|
|
49
|
+
[`react-native-network-logger`](https://github.com/alexbrazier/react-native-network-logger)
|
|
50
|
+
proved that an in-app, zero-dependency inspector is the right idea. This
|
|
51
|
+
library keeps that idea and rebuilds the UI for small screens.
|
|
52
|
+
|
|
53
|
+
| | react-native-network-lens | react-native-network-logger | Flipper / Reactotron |
|
|
54
|
+
| --- | :---: | :---: | :---: |
|
|
55
|
+
| Works on device, no desktop app | ✅ | ✅ | ❌ |
|
|
56
|
+
| Works in release builds | ✅ | ✅ | ❌ |
|
|
57
|
+
| Zero dependencies, no native code | ✅ | ✅ | ❌ |
|
|
58
|
+
| Separate tabs for headers, request, response | ✅ | ❌ | ✅ |
|
|
59
|
+
| Collapsible JSON tree (console style) | ✅ | ❌ | ✅ |
|
|
60
|
+
| Horizontal scrolling, no wrapped JSON | ✅ | ❌ | ✅ |
|
|
61
|
+
| Search inside a payload with next / previous | ✅ | ❌ | ✅ |
|
|
62
|
+
| Adjustable code font size | ✅ | ❌ | – |
|
|
63
|
+
| Failed / timed-out / aborted states | ✅ | ❌ | ✅ |
|
|
64
|
+
| Filter by method, status group, host | ✅ | partial | ✅ |
|
|
65
|
+
| Feature flag built in (`enabled`) | ✅ | ❌ | – |
|
|
66
|
+
| Floating overlay button | ✅ | ❌ | – |
|
|
67
|
+
| Light / dark / follows system | ✅ | light / dark | – |
|
|
68
|
+
| cURL and HAR export | ✅ | ✅ | ✅ |
|
|
69
|
+
| Supports React Native | 0.69+ | 0.60+ | varies |
|
|
70
|
+
|
|
71
|
+
## Features
|
|
72
|
+
|
|
73
|
+
**Capture**
|
|
74
|
+
|
|
75
|
+
- Intercepts `XMLHttpRequest`, which means `fetch`, axios, Apollo, Relay, RTK
|
|
76
|
+
Query and every other JS networking library are covered.
|
|
77
|
+
- Records request and response headers, bodies, status, timing, size, and
|
|
78
|
+
GraphQL operation names.
|
|
79
|
+
- Distinguishes pending, done, failed, timed out and aborted requests.
|
|
80
|
+
- Ring buffer with a configurable limit, pause/resume, and ignore rules by
|
|
81
|
+
host, exact URL or regex.
|
|
82
|
+
|
|
83
|
+
**Inspect**
|
|
84
|
+
|
|
85
|
+
- Request list with colour-coded method and status, path/host split,
|
|
86
|
+
duration, size and a live counter of requests with errors.
|
|
87
|
+
- Free-text filter plus chips for method, status group (2xx…5xx, pending,
|
|
88
|
+
failed) and host.
|
|
89
|
+
- Details in three tabs: **Overview** (URL, timings, query parameters,
|
|
90
|
+
request and response headers), **Request** body and **Response** body.
|
|
91
|
+
- Bodies render as a collapsible tree like the JavaScript console, or as
|
|
92
|
+
pretty-printed raw text with line numbers. Both scroll horizontally and
|
|
93
|
+
virtualise rows, so multi-megabyte payloads stay smooth.
|
|
94
|
+
- Search inside a body with match count and next / previous; the tree expands
|
|
95
|
+
and scrolls to each hit.
|
|
96
|
+
- "Aa" button cycles the code font size. Long-press any tree node to copy or
|
|
97
|
+
share just that value.
|
|
98
|
+
|
|
99
|
+
**Share**
|
|
100
|
+
|
|
101
|
+
- Share a body, the headers, a cURL command, the full request as JSON, or all
|
|
102
|
+
requests as a HAR file that Chrome, Charles and Proxyman can import.
|
|
103
|
+
- Plug in your clipboard library with one prop to get Copy buttons everywhere.
|
|
104
|
+
|
|
105
|
+
**Integrate**
|
|
106
|
+
|
|
107
|
+
- `<NetworkLensOverlay />` adds a floating badge that opens the inspector in a
|
|
108
|
+
modal. `<NetworkLens />` renders it inline inside your own screen.
|
|
109
|
+
- `enabled` flag on everything: wire it to `__DEV__`, a remote config value or
|
|
110
|
+
a hidden developer setting.
|
|
111
|
+
- Light, dark or follow-the-system themes, fully overridable.
|
|
112
|
+
- Written in TypeScript, works with the New Architecture and the old one,
|
|
113
|
+
survives Fast Refresh.
|
|
38
114
|
|
|
39
115
|
## Installation
|
|
40
116
|
|
|
@@ -44,19 +120,20 @@ yarn add react-native-network-lens
|
|
|
44
120
|
npm install react-native-network-lens
|
|
45
121
|
```
|
|
46
122
|
|
|
47
|
-
No pod install
|
|
123
|
+
No `pod install`, no Gradle changes, no Expo config plugin. Requires React
|
|
124
|
+
Native 0.69+ and React 18+.
|
|
48
125
|
|
|
49
126
|
## Quick start
|
|
50
127
|
|
|
51
128
|
```tsx
|
|
52
|
-
// index.js
|
|
129
|
+
// index.js — as early as possible so nothing is missed
|
|
53
130
|
import { startNetworkLogging } from 'react-native-network-lens';
|
|
54
131
|
|
|
55
132
|
startNetworkLogging({ enabled: __DEV__ });
|
|
56
133
|
```
|
|
57
134
|
|
|
58
135
|
```tsx
|
|
59
|
-
// App.tsx
|
|
136
|
+
// App.tsx
|
|
60
137
|
import { NetworkLensOverlay } from 'react-native-network-lens';
|
|
61
138
|
|
|
62
139
|
export default function App() {
|
|
@@ -69,23 +146,38 @@ export default function App() {
|
|
|
69
146
|
}
|
|
70
147
|
```
|
|
71
148
|
|
|
72
|
-
Tap the floating **NET** button
|
|
73
|
-
|
|
149
|
+
Tap the floating **NET** button. It shows how many requests were captured and
|
|
150
|
+
turns red when something failed.
|
|
74
151
|
|
|
75
|
-
|
|
152
|
+
## Recipes
|
|
153
|
+
|
|
154
|
+
### As a screen in your navigator
|
|
76
155
|
|
|
77
156
|
```tsx
|
|
78
157
|
import { NetworkLens } from 'react-native-network-lens';
|
|
79
158
|
|
|
80
|
-
const NetworkScreen = () => <NetworkLens
|
|
159
|
+
const NetworkScreen = () => <NetworkLens />;
|
|
81
160
|
```
|
|
82
161
|
|
|
83
|
-
`NetworkLens` fills its parent (`flex: 1`)
|
|
84
|
-
|
|
162
|
+
`NetworkLens` fills its parent (`flex: 1`) and handles the Android hardware
|
|
163
|
+
back button for the details view. To make your own header back button step
|
|
164
|
+
out of the details view first:
|
|
165
|
+
|
|
166
|
+
```tsx
|
|
167
|
+
import { NetworkLens, getBackHandler } from 'react-native-network-lens';
|
|
85
168
|
|
|
86
|
-
|
|
169
|
+
const NetworkScreen = ({ navigation }) => {
|
|
170
|
+
const onBack = getBackHandler(navigation.goBack);
|
|
171
|
+
return (
|
|
172
|
+
<>
|
|
173
|
+
<Header onBackPress={onBack} />
|
|
174
|
+
<NetworkLens />
|
|
175
|
+
</>
|
|
176
|
+
);
|
|
177
|
+
};
|
|
178
|
+
```
|
|
87
179
|
|
|
88
|
-
|
|
180
|
+
### Behind a feature flag or hidden gesture
|
|
89
181
|
|
|
90
182
|
```tsx
|
|
91
183
|
const inspectorEnabled = __DEV__ || remoteConfig.getBoolean('network_inspector');
|
|
@@ -95,9 +187,58 @@ startNetworkLogging({ enabled: inspectorEnabled });
|
|
|
95
187
|
<NetworkLensOverlay enabled={inspectorEnabled} />
|
|
96
188
|
```
|
|
97
189
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
190
|
+
Prefer your own trigger (shake gesture, dev menu, tapping the version label
|
|
191
|
+
seven times)? Hide the button and control the sheet yourself:
|
|
192
|
+
|
|
193
|
+
```tsx
|
|
194
|
+
const [open, setOpen] = useState(false);
|
|
195
|
+
|
|
196
|
+
<NetworkLensOverlay hideButton visible={open} onVisibleChange={setOpen} />
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
### Copy buttons
|
|
200
|
+
|
|
201
|
+
The library ships no native code, so clipboard access is opt-in:
|
|
202
|
+
|
|
203
|
+
```tsx
|
|
204
|
+
import Clipboard from '@react-native-clipboard/clipboard';
|
|
205
|
+
|
|
206
|
+
<NetworkLensOverlay copyToClipboard={Clipboard.setString} />
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Expo
|
|
210
|
+
|
|
211
|
+
Works in Expo Go and development builds without a config plugin. Call
|
|
212
|
+
`startNetworkLogging()` at the top of your root layout or `App.tsx`.
|
|
213
|
+
|
|
214
|
+
### Keeping noise out
|
|
215
|
+
|
|
216
|
+
```tsx
|
|
217
|
+
startNetworkLogging({
|
|
218
|
+
ignoredHosts: ['localhost:8081', 'firebaselogging.googleapis.com'],
|
|
219
|
+
ignoredPatterns: [/^HEAD /, /\/analytics\//],
|
|
220
|
+
maxRequests: 300,
|
|
221
|
+
});
|
|
222
|
+
```
|
|
223
|
+
|
|
224
|
+
### Alongside Reactotron, Flipper or Sentry
|
|
225
|
+
|
|
226
|
+
Other tools also patch `XMLHttpRequest`. react-native-network-lens patches on
|
|
227
|
+
top of whatever is already there and restores it on `stopNetworkLogging()`,
|
|
228
|
+
so they can run together.
|
|
229
|
+
|
|
230
|
+
### Using the data yourself
|
|
231
|
+
|
|
232
|
+
```tsx
|
|
233
|
+
import { useNetworkRequests, createHar } from 'react-native-network-lens';
|
|
234
|
+
|
|
235
|
+
const FailedCount = () => {
|
|
236
|
+
const requests = useNetworkRequests();
|
|
237
|
+
return <Text>{requests.filter((r) => r.state === 'failed').length}</Text>;
|
|
238
|
+
};
|
|
239
|
+
|
|
240
|
+
const har = await createHar(getRequests());
|
|
241
|
+
```
|
|
101
242
|
|
|
102
243
|
## API
|
|
103
244
|
|
|
@@ -105,59 +246,48 @@ to turn it off and free the captured data.
|
|
|
105
246
|
|
|
106
247
|
| Option | Type | Default | Description |
|
|
107
248
|
| ----------------- | ---------- | ------- | ----------- |
|
|
108
|
-
| `enabled` | `boolean` | `true` | Master switch. `false` makes the call a no-op
|
|
249
|
+
| `enabled` | `boolean` | `true` | Master switch. `false` makes the call a no-op and stops a running logger. |
|
|
109
250
|
| `maxRequests` | `number` | `500` | Ring-buffer size. |
|
|
110
251
|
| `ignoredHosts` | `string[]` | | Hosts to skip, e.g. `['localhost:8081']`. |
|
|
111
252
|
| `ignoredUrls` | `string[]` | | Exact URLs to skip. |
|
|
112
253
|
| `ignoredPatterns` | `RegExp[]` | | Tested against `"${method} ${url}"`. |
|
|
113
254
|
| `refreshRate` | `number` | `50` | UI update throttle in ms. |
|
|
114
255
|
|
|
115
|
-
|
|
256
|
+
Also exported: `stopNetworkLogging()`, `isNetworkLoggingEnabled()`,
|
|
116
257
|
`getRequests()`, `clearRequests()`, `setNetworkLoggingPaused(bool)`,
|
|
117
|
-
`getBackHandler(fn)
|
|
258
|
+
`getBackHandler(fn)`, `createHar(requests)`.
|
|
118
259
|
|
|
119
260
|
### `<NetworkLens />`
|
|
120
261
|
|
|
121
|
-
| Prop
|
|
122
|
-
|
|
|
123
|
-
| `enabled`
|
|
124
|
-
| `theme`
|
|
125
|
-
| `sort`
|
|
126
|
-
| `compact`
|
|
127
|
-
| `maxRows`
|
|
128
|
-
| `copyToClipboard`
|
|
129
|
-
| `header` | `ReactNode` rendered above the search bar | |
|
|
130
|
-
|
|
131
|
-
A `ref` gives you `goBack(): boolean`, which returns from the details view to
|
|
132
|
-
the list. Use it to wire your own back button or modal `onRequestClose`.
|
|
133
|
-
|
|
134
|
-
The library ships no native code, so there is no clipboard access by default.
|
|
135
|
-
Pass your clipboard function to get **Copy** buttons everywhere:
|
|
262
|
+
| Prop | Type | Default |
|
|
263
|
+
| ----------------- | ------------------------------------------------- | -------- |
|
|
264
|
+
| `enabled` | `boolean` | `true` |
|
|
265
|
+
| `theme` | `'light' \| 'dark' \| 'auto' \| Partial<Theme>` | `'auto'` |
|
|
266
|
+
| `sort` | `'asc' \| 'desc'` | `'desc'` |
|
|
267
|
+
| `compact` | `boolean` | `false` |
|
|
268
|
+
| `maxRows` | `number` | |
|
|
269
|
+
| `copyToClipboard` | `(text: string) => void` | |
|
|
136
270
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
<NetworkLensOverlay copyToClipboard={Clipboard.setString} />
|
|
141
|
-
```
|
|
271
|
+
A `ref` exposes `goBack(): boolean`, which returns from the details view to
|
|
272
|
+
the list (handy for your own back button or a modal's `onRequestClose`).
|
|
142
273
|
|
|
143
274
|
### `<NetworkLensOverlay />`
|
|
144
275
|
|
|
145
276
|
All `NetworkLens` props plus:
|
|
146
277
|
|
|
147
|
-
| Prop
|
|
148
|
-
|
|
|
149
|
-
| `position`
|
|
150
|
-
| `offset`
|
|
151
|
-
| `visible` / `onVisibleChange` | controlled visibility of the
|
|
152
|
-
| `hideButton`
|
|
153
|
-
| `title`
|
|
278
|
+
| Prop | Type | Default |
|
|
279
|
+
| ----------------------------- | -------------------------------------------------------------- | ---------------- |
|
|
280
|
+
| `position` | `'bottom-right' \| 'bottom-left' \| 'top-right' \| 'top-left'` | `'bottom-right'` |
|
|
281
|
+
| `offset` | `{ x?: number; y?: number }` | `{ x: 16, y: 32 }` |
|
|
282
|
+
| `visible` / `onVisibleChange` | controlled visibility of the sheet | |
|
|
283
|
+
| `hideButton` | `boolean` | `false` |
|
|
284
|
+
| `title` | `string` | `'Network'` |
|
|
154
285
|
|
|
155
286
|
### Hooks and building blocks
|
|
156
287
|
|
|
157
|
-
- `useNetworkRequests()` – live array of `NetworkRequest` objects.
|
|
288
|
+
- `useNetworkRequests()` – live array of `NetworkRequest` objects, newest first.
|
|
158
289
|
- `useLoggerEnabled()`, `useLoggerPaused()`.
|
|
159
|
-
- `JsonTreeView`
|
|
160
|
-
elsewhere in your debug tooling.
|
|
290
|
+
- `JsonTreeView` – the collapsible JSON viewer, reusable in your own debug UI.
|
|
161
291
|
|
|
162
292
|
### Theming
|
|
163
293
|
|
|
@@ -165,23 +295,34 @@ All `NetworkLens` props plus:
|
|
|
165
295
|
<NetworkLens theme={{ colors: { primary: '#ff5c8a', jsonKey: '#ffd166' } }} />
|
|
166
296
|
```
|
|
167
297
|
|
|
168
|
-
|
|
169
|
-
|
|
298
|
+
Colours you omit fall back to the light or dark theme depending on the system
|
|
299
|
+
appearance. `theme.sizes.codeFontSize` (default 14) sets the base code size;
|
|
300
|
+
users can still cycle small / medium / large with the **Aa** button. See
|
|
301
|
+
`Theme` in `src/theme.ts` for every token.
|
|
302
|
+
|
|
303
|
+
## Compatibility
|
|
304
|
+
|
|
305
|
+
| | |
|
|
306
|
+
| --- | --- |
|
|
307
|
+
| React Native | 0.69 and newer (CI builds the example on the latest release) |
|
|
308
|
+
| React | 18 and newer |
|
|
309
|
+
| Architecture | New Architecture and legacy, Hermes and JSC |
|
|
310
|
+
| Expo | Expo Go and development builds, no config plugin |
|
|
311
|
+
| Platforms | iOS, Android. Web is untested. |
|
|
170
312
|
|
|
171
313
|
## How it works
|
|
172
314
|
|
|
173
|
-
|
|
174
|
-
`send`)
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
`useSyncExternalStore`. There is no native code, so nothing to link.
|
|
315
|
+
`startNetworkLogging()` patches `XMLHttpRequest.prototype` (`open`,
|
|
316
|
+
`setRequestHeader`, `send`) and `stopNetworkLogging()` restores the originals.
|
|
317
|
+
Every callback is wrapped so a bug in the inspector can never break a request.
|
|
318
|
+
Captured requests live in one store on `globalThis`, which survives Fast
|
|
319
|
+
Refresh, and React reads it through `useSyncExternalStore`.
|
|
179
320
|
|
|
180
321
|
## Security
|
|
181
322
|
|
|
182
323
|
The inspector keeps captured headers and bodies in memory, including
|
|
183
324
|
authorization tokens and cookies, and lets the user share or export them.
|
|
184
|
-
Ship it behind `__DEV__` or an internal flag
|
|
325
|
+
Ship it behind `__DEV__` or an internal flag, and use `ignoredHosts` /
|
|
185
326
|
`ignoredPatterns` for endpoints that must never be captured. See
|
|
186
327
|
[SECURITY.md](SECURITY.md) for details and how to report issues.
|
|
187
328
|
|
|
@@ -192,17 +333,33 @@ The public API is a superset: `startNetworkLogging`, `stopNetworkLogging`,
|
|
|
192
333
|
component keep working. Differences:
|
|
193
334
|
|
|
194
335
|
- `theme` accepts `'auto'` and defaults to it.
|
|
336
|
+
- `forceEnable` is gone; the interceptor coexists with other tools.
|
|
195
337
|
- Requests expose `state` (`pending | done | failed`) and `failureReason`
|
|
196
338
|
(`error | timeout | abort`) instead of staying "pending" forever.
|
|
197
339
|
- Bodies are parsed into `{ kind: 'json' | 'form' | 'text' | 'binary' | 'empty' }`
|
|
198
340
|
via `request.getRequestBody()` / `await request.getResponseBody()`.
|
|
199
341
|
|
|
342
|
+
## FAQ
|
|
343
|
+
|
|
344
|
+
**Nothing shows up.** Call `startNetworkLogging()` before the first request,
|
|
345
|
+
ideally at the top of `index.js`, and make sure `enabled` is not `false`.
|
|
346
|
+
|
|
347
|
+
**Can I ship it to production?** Yes, behind a flag. The library is small and
|
|
348
|
+
inert when `enabled` is `false`. Read the Security section first.
|
|
349
|
+
|
|
350
|
+
**Does it see native networking (Image, video, native SDKs)?** No. Only
|
|
351
|
+
requests that go through JavaScript's `XMLHttpRequest`, which is everything
|
|
352
|
+
your JS code sends.
|
|
353
|
+
|
|
200
354
|
## Contributing
|
|
201
355
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
356
|
+
Issues and pull requests are welcome. See the
|
|
357
|
+
[contributing guide](CONTRIBUTING.md); the example app in `example/` fires a
|
|
358
|
+
variety of requests (large JSON, nested objects, forms, GraphQL-like, errors,
|
|
359
|
+
timeouts, binary) so every screen can be tried in a minute.
|
|
360
|
+
|
|
361
|
+
If this library saves you time, a ⭐ on GitHub helps others find it.
|
|
205
362
|
|
|
206
363
|
## License
|
|
207
364
|
|
|
208
|
-
MIT
|
|
365
|
+
MIT © [Stains M Johnson](https://github.com/stainsmjohnson)
|
|
@@ -7,8 +7,9 @@ import { bodySize, stringifyJson } from "../utils/body.js";
|
|
|
7
7
|
import { formatBytes } from "../utils/format.js";
|
|
8
8
|
import JsonTreeView from "./JsonTree/JsonTreeView.js";
|
|
9
9
|
import RawTextView from "./RawTextView.js";
|
|
10
|
-
import {
|
|
11
|
-
import {
|
|
10
|
+
import { cycleCodeFontScale, useCodeFontScale } from "../settings.js";
|
|
11
|
+
import { ActionSheet, EmptyState, IconButton, SearchInput, SegmentedControl } from "./ui/index.js";
|
|
12
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
12
13
|
const KIND_LABEL = {
|
|
13
14
|
json: 'JSON',
|
|
14
15
|
form: 'Form data',
|
|
@@ -41,6 +42,8 @@ const BodyViewer = ({
|
|
|
41
42
|
const [matchIndex, setMatchIndex] = useState(0);
|
|
42
43
|
const [nodeMenu, setNodeMenu] = useState(null);
|
|
43
44
|
const treeRef = useRef(null);
|
|
45
|
+
const [menuVisible, setMenuVisible] = useState(false);
|
|
46
|
+
const fontScale = useCodeFontScale();
|
|
44
47
|
const effectiveMode = structured ? mode : 'raw';
|
|
45
48
|
useEffect(() => setMatchIndex(0), [query, effectiveMode, body]);
|
|
46
49
|
const onMatchCountChange = useCallback(count => {
|
|
@@ -99,20 +102,14 @@ const BodyViewer = ({
|
|
|
99
102
|
children: meta
|
|
100
103
|
}), /*#__PURE__*/_jsx(View, {
|
|
101
104
|
style: styles.spacer
|
|
102
|
-
}),
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
}), copyToClipboard && body.kind !== 'binary' && /*#__PURE__*/_jsx(TextButton, {
|
|
111
|
-
label: "Copy",
|
|
112
|
-
onPress: () => copyToClipboard(body.text)
|
|
113
|
-
}), /*#__PURE__*/_jsx(TextButton, {
|
|
114
|
-
label: "Share",
|
|
115
|
-
onPress: () => share(body.text)
|
|
105
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
106
|
+
glyph: "Aa",
|
|
107
|
+
accessibilityLabel: `Text size: ${fontScale}. Tap to change`,
|
|
108
|
+
onPress: cycleCodeFontScale
|
|
109
|
+
}), /*#__PURE__*/_jsx(IconButton, {
|
|
110
|
+
glyph: "\u22EE",
|
|
111
|
+
accessibilityLabel: "More options",
|
|
112
|
+
onPress: () => setMenuVisible(true)
|
|
116
113
|
})]
|
|
117
114
|
}), body.kind !== 'binary' && /*#__PURE__*/_jsx(SearchInput, {
|
|
118
115
|
value: query,
|
|
@@ -146,6 +143,22 @@ const BodyViewer = ({
|
|
|
146
143
|
activeMatch: matchIndex,
|
|
147
144
|
onMatchCountChange: onMatchCountChange
|
|
148
145
|
})
|
|
146
|
+
}), /*#__PURE__*/_jsx(ActionSheet, {
|
|
147
|
+
visible: menuVisible,
|
|
148
|
+
onClose: () => setMenuVisible(false),
|
|
149
|
+
actions: [...(effectiveMode === 'tree' ? [{
|
|
150
|
+
label: 'Expand all',
|
|
151
|
+
onPress: () => treeRef.current?.expandAll()
|
|
152
|
+
}, {
|
|
153
|
+
label: 'Collapse all',
|
|
154
|
+
onPress: () => treeRef.current?.collapseAll()
|
|
155
|
+
}] : []), ...(copyToClipboard && body.kind !== 'binary' ? [{
|
|
156
|
+
label: 'Copy',
|
|
157
|
+
onPress: () => copyToClipboard(body.text)
|
|
158
|
+
}] : []), {
|
|
159
|
+
label: 'Share',
|
|
160
|
+
onPress: () => share(body.text)
|
|
161
|
+
}]
|
|
149
162
|
}), /*#__PURE__*/_jsx(ActionSheet, {
|
|
150
163
|
visible: nodeMenu !== null,
|
|
151
164
|
onClose: () => setNodeMenu(null),
|
|
@@ -176,11 +189,10 @@ const styles = StyleSheet.create({
|
|
|
176
189
|
flexDirection: 'row',
|
|
177
190
|
alignItems: 'center',
|
|
178
191
|
paddingHorizontal: 12,
|
|
179
|
-
paddingTop: 10
|
|
180
|
-
gap: 6
|
|
192
|
+
paddingTop: 10
|
|
181
193
|
},
|
|
182
194
|
modeSwitch: {
|
|
183
|
-
width:
|
|
195
|
+
width: 140
|
|
184
196
|
},
|
|
185
197
|
spacer: {
|
|
186
198
|
flex: 1
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","ActivityIndicator","Share","StyleSheet","Text","View","useTheme","bodySize","stringifyJson","formatBytes","JsonTreeView","RawTextView","
|
|
1
|
+
{"version":3,"names":["useCallback","useEffect","useMemo","useRef","useState","ActivityIndicator","Share","StyleSheet","Text","View","useTheme","bodySize","stringifyJson","formatBytes","JsonTreeView","RawTextView","cycleCodeFontScale","useCodeFontScale","ActionSheet","EmptyState","IconButton","SearchInput","SegmentedControl","jsx","_jsx","jsxs","_jsxs","KIND_LABEL","json","form","text","binary","empty","share","message","catch","undefined","valueText","value","BodyViewer","body","loading","emptyTitle","emptySubtitle","copyToClipboard","theme","structured","kind","mode","setMode","query","setQuery","matchCount","setMatchCount","matchIndex","setMatchIndex","nodeMenu","setNodeMenu","treeRef","menuVisible","setMenuVisible","fontScale","effectiveMode","onMatchCountChange","count","index","Math","min","matches","onNext","i","onPrev","meta","parts","mimeType","push","size","split","length","join","style","styles","center","children","color","colors","primary","title","subtitle","container","toolbar","onChange","options","label","modeSwitch","textMuted","numberOfLines","spacer","glyph","accessibilityLabel","onPress","onChangeText","placeholder","search","metaBelow","viewer","borderColor","border","ref","activeMatch","onLongPressNode","visible","onClose","actions","current","expandAll","collapseAll","path","create","flex","alignItems","justifyContent","flexDirection","paddingHorizontal","paddingTop","width","marginHorizontal","marginTop","fontSize","flexShrink","borderTopWidth","hairlineWidth"],"sourceRoot":"../../../src","sources":["components/BodyViewer.tsx"],"mappings":"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","ignoreList":[]}
|