react-native-debug-toolkit 0.1.5 → 0.1.7

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.
@@ -12,6 +12,7 @@ class NetworkFeature {
12
12
  this.logs = []
13
13
  this.pendingAxiosRequests = new Map()
14
14
  this.originalFetch = null
15
+ this.blacklist = [] // URL patterns to exclude from logging
15
16
 
16
17
  NetworkFeature.instance = this
17
18
  }
@@ -39,6 +40,39 @@ class NetworkFeature {
39
40
  this.pendingAxiosRequests.clear()
40
41
  }
41
42
 
43
+ // Check if a URL matches any pattern in the blacklist
44
+ isUrlBlacklisted(url) {
45
+ if (!url) return false
46
+
47
+ return this.blacklist.some(pattern => {
48
+ if (pattern instanceof RegExp) {
49
+ return pattern.test(url)
50
+ }
51
+ return url.includes(pattern)
52
+ })
53
+ }
54
+
55
+ // Add a URL pattern to blacklist
56
+ addUrlToBlacklist(pattern) {
57
+ if (!this.blacklist.some(p =>
58
+ (p instanceof RegExp && pattern instanceof RegExp) ?
59
+ p.toString() === pattern.toString() : p === pattern)) {
60
+ this.blacklist.push(pattern)
61
+ }
62
+ }
63
+
64
+ // Remove a URL pattern from blacklist
65
+ removeUrlFromBlacklist(pattern) {
66
+ this.blacklist = this.blacklist.filter(p =>
67
+ (p instanceof RegExp && pattern instanceof RegExp) ?
68
+ p.toString() !== pattern.toString() : p !== pattern)
69
+ }
70
+
71
+ // Clear all patterns from blacklist
72
+ clearBlacklist() {
73
+ this.blacklist = []
74
+ }
75
+
42
76
  setupAxiosInterceptors(axiosInstance) {
43
77
  if (!__DEV__) {
44
78
  return
@@ -94,6 +128,14 @@ class NetworkFeature {
94
128
  return
95
129
  }
96
130
 
131
+ const url = `${response.config.baseURL || ''}${response.config.url}`
132
+
133
+ // Skip logging if URL is blacklisted
134
+ if (this.isUrlBlacklisted(url)) {
135
+ this.pendingAxiosRequests.delete(trackId)
136
+ return
137
+ }
138
+
97
139
  if (this.logs.length >= NetworkFeature.MAX_LOGS) {
98
140
  this.logs.shift()
99
141
  }
@@ -105,7 +147,7 @@ class NetworkFeature {
105
147
  timestamp: pendingRequest.timestamp,
106
148
  duration: Math.round(duration),
107
149
  request: {
108
- url: `${response.config.baseURL || ''}${response.config.url}`,
150
+ url: url,
109
151
  method: response.config.method?.toUpperCase() || 'GET',
110
152
  headers: response.config.headers,
111
153
  body: response.config.data || response.config.params,
@@ -148,6 +190,14 @@ class NetworkFeature {
148
190
  const startTime = pendingRequest
149
191
  ? pendingRequest.startTime
150
192
  : Date.now() - 100
193
+
194
+ const url = `${error.config.baseURL || ''}${error.config.url}`
195
+
196
+ // Skip logging if URL is blacklisted
197
+ if (this.isUrlBlacklisted(url)) {
198
+ this.pendingAxiosRequests.delete(trackId)
199
+ return
200
+ }
151
201
 
152
202
  if (this.logs.length >= NetworkFeature.MAX_LOGS) {
153
203
  this.logs.shift()
@@ -159,7 +209,7 @@ class NetworkFeature {
159
209
  timestamp: pendingRequest ? pendingRequest.timestamp : new Date(),
160
210
  duration: Math.round(duration),
161
211
  request: {
162
- url: `${error.config.baseURL || ''}${error.config.url}`,
212
+ url: url,
163
213
  method: error.config.method?.toUpperCase() || 'GET',
164
214
  headers: error.config.headers,
165
215
  body: error.config.data || error.config.params,
@@ -206,12 +256,18 @@ class NetworkFeature {
206
256
  }
207
257
 
208
258
  _logFetchResponse(request, options, response, startTime) {
259
+ const requestUrl = typeof request === 'string' ? request : request.url
260
+
261
+ // Skip logging if URL is blacklisted
262
+ if (this.isUrlBlacklisted(requestUrl)) {
263
+ return
264
+ }
265
+
209
266
  if (this.logs.length >= NetworkFeature.MAX_LOGS) {
210
267
  this.logs.shift()
211
268
  }
212
269
 
213
270
  const duration = Date.now() - startTime
214
- const requestUrl = typeof request === 'string' ? request : request.url
215
271
 
216
272
  const commonData = {
217
273
  timestamp: new Date(),
@@ -276,6 +332,13 @@ class NetworkFeature {
276
332
  }
277
333
 
278
334
  _logFetchError(request, options, error, startTime) {
335
+ const requestUrl = typeof request === 'string' ? request : request.url
336
+
337
+ // Skip logging if URL is blacklisted
338
+ if (this.isUrlBlacklisted(requestUrl)) {
339
+ return
340
+ }
341
+
279
342
  if (this.logs.length >= NetworkFeature.MAX_LOGS) {
280
343
  this.logs.shift()
281
344
  }
@@ -286,7 +349,7 @@ class NetworkFeature {
286
349
  timestamp: new Date(),
287
350
  duration: Math.round(duration),
288
351
  request: {
289
- url: typeof request === 'string' ? request : request.url,
352
+ url: requestUrl,
290
353
  method: options.method || 'GET',
291
354
  headers: options.headers || {},
292
355
  body: options.body,
@@ -326,5 +389,10 @@ export const createNetworkFeature = () => {
326
389
  cleanup: () => feature.cleanup(),
327
390
  setupAxiosInterceptors: (axiosInstance) =>
328
391
  feature.setupAxiosInterceptors(axiosInstance),
392
+ // Expose blacklist management methods
393
+ addUrlToBlacklist: (pattern) => feature.addUrlToBlacklist(pattern),
394
+ removeUrlFromBlacklist: (pattern) => feature.removeUrlFromBlacklist(pattern),
395
+ clearBlacklist: () => feature.clearBlacklist(),
396
+ getBlacklist: () => feature.blacklist,
329
397
  }
330
398
  }
@@ -1,8 +1,28 @@
1
1
  import React, { useState, useCallback } from 'react'
2
2
  import { View, Text, StyleSheet, Clipboard, Dimensions } from 'react-native'
3
3
  import { ScrollView, Pressable } from 'react-native'
4
-
4
+ import JSONTree from 'react-native-json-tree'
5
5
  const { width: SCREEN_WIDTH } = Dimensions.get('window')
6
+ const theme = {
7
+ scheme: 'monokai',
8
+ author: 'wimer hazenberg (http://www.monokai.nl)',
9
+ base00: '#272822',
10
+ base01: '#383830',
11
+ base02: '#49483e',
12
+ base03: '#75715e',
13
+ base04: '#a59f85',
14
+ base05: '#f8f8f2',
15
+ base06: '#f5f4f1',
16
+ base07: '#f9f8f5',
17
+ base08: '#f92672',
18
+ base09: '#fd971f',
19
+ base0A: '#f4bf75',
20
+ base0B: '#a6e22e',
21
+ base0C: '#a1efe4',
22
+ base0D: '#66d9ef',
23
+ base0E: '#ae81ff',
24
+ base0F: '#cc6633'
25
+ };
6
26
 
7
27
  const CopyButton = ({ text, style }) => {
8
28
  const [copied, setCopied] = useState(false)
@@ -54,8 +74,6 @@ const LongTextContent = ({ text }) => {
54
74
  }
55
75
 
56
76
  const JSONValue = ({ value, path = '', level = 0, maxExpandLevel = 2 }) => {
57
- const [expanded, setExpanded] = useState(level < maxExpandLevel)
58
-
59
77
  if (value === null) {
60
78
  return <Text style={styles.jsonNull}>null</Text>
61
79
  }
@@ -75,9 +93,7 @@ const JSONValue = ({ value, path = '', level = 0, maxExpandLevel = 2 }) => {
75
93
  if (typeof value === 'string') {
76
94
  if (value.length > 150) {
77
95
  return (
78
- <CollapsibleSection
79
- title={`String (${value.length} chars)`}
80
- initiallyExpanded={false}>
96
+ <CollapsibleSection title={`String (${value.length} chars)`} initiallyExpanded={false}>
81
97
  <LongTextContent text={value} />
82
98
  </CollapsibleSection>
83
99
  )
@@ -90,88 +106,16 @@ const JSONValue = ({ value, path = '', level = 0, maxExpandLevel = 2 }) => {
90
106
  )
91
107
  }
92
108
 
93
- if (Array.isArray(value)) {
94
- if (value.length === 0) {
95
- return <Text style={styles.jsonArray}>[]</Text>
96
- }
97
-
98
- return (
99
- <View style={styles.jsonContainer}>
100
- <Pressable
101
- onPress={() => setExpanded(!expanded)}
102
- style={styles.jsonToggle}>
103
- <Text style={styles.jsonBrackets}>
104
- [{!expanded && '...'}
105
- {expanded && value.length > 0 && ''}
106
- </Text>
107
- {!expanded && (
108
- <Text style={styles.jsonCollapsed}> Array({value.length}) </Text>
109
- )}
110
- </Pressable>
111
-
112
- {expanded && (
113
- <View style={styles.jsonChildren}>
114
- {value.map((item, index) => (
115
- <View key={`${path}-${index}`} style={styles.jsonArrayItem}>
116
- <Text style={styles.jsonKey}>{index}: </Text>
117
- <View style={styles.jsonValue}>
118
- <JSONValue
119
- value={item}
120
- path={`${path}[${index}]`}
121
- level={level + 1}
122
- />
123
- </View>
124
- </View>
125
- ))}
126
- </View>
127
- )}
128
-
129
- {expanded && <Text style={styles.jsonBrackets}>]</Text>}
130
- </View>
131
- )
132
- }
133
-
109
+ // For objects and arrays, use JSONTree for improved large data handling
134
110
  if (typeof value === 'object') {
135
- const keys = Object.keys(value)
136
-
137
- if (keys.length === 0) {
138
- return <Text style={styles.jsonObject}>{'{}'}</Text>
139
- }
140
-
141
111
  return (
142
- <View style={styles.jsonContainer}>
143
- <Pressable
144
- onPress={() => setExpanded(!expanded)}
145
- style={styles.jsonToggle}>
146
- <Text style={styles.jsonBrackets}>
147
- {'{'}
148
- {!expanded && '...'}
149
- {expanded && keys.length > 0 && ''}
150
- </Text>
151
- {!expanded && (
152
- <Text style={styles.jsonCollapsed}> Object({keys.length}) </Text>
153
- )}
154
- </Pressable>
155
-
156
- {expanded && (
157
- <View style={styles.jsonChildren}>
158
- {keys.map((key) => (
159
- <View key={`${path}-${key}`} style={styles.jsonProperty}>
160
- <Text style={styles.jsonKey}>{key}: </Text>
161
- <View style={styles.jsonValue}>
162
- <JSONValue
163
- value={value[key]}
164
- path={`${path}.${key}`}
165
- level={level + 1}
166
- />
167
- </View>
168
- </View>
169
- ))}
170
- </View>
171
- )}
172
-
173
- {expanded && <Text style={styles.jsonBrackets}>{'}'}</Text>}
174
- </View>
112
+ <JSONTree
113
+ data={value}
114
+ theme={theme}
115
+ invertTheme={true}
116
+ hideRoot={true}
117
+ shouldExpandNode={(keyPath, nodeData, currentLevel) => currentLevel < maxExpandLevel}
118
+ />
175
119
  )
176
120
  }
177
121
 
@@ -387,7 +331,7 @@ const HttpLogDetails = ({ log }) => {
387
331
  nestedScrollEnabled={true}
388
332
  bounces={false}
389
333
  showsVerticalScrollIndicator={true}>
390
- <JSONValue value={responseData} maxExpandLevel={1} />
334
+ <JSONValue value={responseData} maxExpandLevel={2} />
391
335
  </ScrollView>
392
336
  </View>
393
337
  </View>
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-debug-toolkit",
3
- "version": "0.1.5",
3
+ "version": "0.1.7",
4
4
  "description": "A simple yet powerful debugging toolkit for React Native with a convenient floating UI for development",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -23,7 +23,8 @@
23
23
  "author": "zcj",
24
24
  "license": "MIT",
25
25
  "dependencies": {
26
- "react-native-root-siblings": "^4.0.0"
26
+ "react-native-root-siblings": "^4.0.0",
27
+ "react-native-json-tree": "^1.5.0"
27
28
  },
28
29
  "peerDependencies": {
29
30
  "react": "*",