react-native-inapp-inspector 2.3.14 → 2.3.15
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/dist/commonjs/components/AnimatedEntrance.js +3 -3
- package/dist/commonjs/components/ConsoleLogCard.js +174 -100
- package/dist/commonjs/components/Inspector/ConsoleTab.js +25 -16
- package/dist/commonjs/components/Inspector/CrashTab.js +19 -5
- package/dist/commonjs/components/Inspector/DeviceInfoTab.js +198 -98
- package/dist/commonjs/components/Inspector/InspectorHeader.js +2 -2
- package/dist/commonjs/components/Inspector/MainScreen.js +56 -56
- package/dist/commonjs/components/Inspector/NetworkTab.js +1 -335
- package/dist/commonjs/components/Inspector/PerformanceTab.js +32 -6
- package/dist/commonjs/components/Inspector/ReduxTab.js +3 -1
- package/dist/commonjs/components/Inspector/StorageTab.js +23 -5
- package/dist/commonjs/components/JsonViewer.js +14 -2
- package/dist/commonjs/components/LogCard.js +428 -227
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
- package/dist/commonjs/customHooks/consoleLogger.js +34 -2
- package/dist/commonjs/customHooks/crashHandler.js +1 -1
- package/dist/commonjs/customHooks/networkLogger.js +184 -26
- package/dist/commonjs/helpers/searchQueryParser.d.ts +1 -1
- package/dist/commonjs/helpers/searchQueryParser.js +37 -291
- package/dist/commonjs/index.js +141 -27
- package/dist/esm/components/AnimatedEntrance.js +3 -3
- package/dist/esm/components/ConsoleLogCard.js +141 -100
- package/dist/esm/components/Inspector/ConsoleTab.js +25 -16
- package/dist/esm/components/Inspector/CrashTab.js +19 -5
- package/dist/esm/components/Inspector/DeviceInfoTab.js +198 -98
- package/dist/esm/components/Inspector/InspectorHeader.js +3 -3
- package/dist/esm/components/Inspector/MainScreen.js +56 -56
- package/dist/esm/components/Inspector/NetworkTab.js +2 -336
- package/dist/esm/components/Inspector/PerformanceTab.js +32 -6
- package/dist/esm/components/Inspector/ReduxTab.js +3 -1
- package/dist/esm/components/Inspector/StorageTab.js +23 -5
- package/dist/esm/components/JsonViewer.js +14 -2
- package/dist/esm/components/LogCard.js +422 -221
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.js +1 -1
- package/dist/esm/customHooks/consoleLogger.js +34 -2
- package/dist/esm/customHooks/crashHandler.js +1 -1
- package/dist/esm/customHooks/networkLogger.js +184 -26
- package/dist/esm/helpers/searchQueryParser.d.ts +1 -1
- package/dist/esm/helpers/searchQueryParser.js +37 -291
- package/dist/esm/index.js +141 -27
- package/package.json +1 -1
- package/src/components/AnimatedEntrance.tsx +3 -3
- package/src/components/ConsoleLogCard.tsx +154 -103
- package/src/components/Inspector/ConsoleTab.tsx +27 -18
- package/src/components/Inspector/CrashTab.tsx +19 -5
- package/src/components/Inspector/DeviceInfoTab.tsx +224 -102
- package/src/components/Inspector/InspectorHeader.tsx +5 -3
- package/src/components/Inspector/MainScreen.tsx +2 -3
- package/src/components/Inspector/NetworkTab.tsx +1 -402
- package/src/components/Inspector/PerformanceTab.tsx +36 -7
- package/src/components/Inspector/ReduxTab.tsx +9 -1
- package/src/components/Inspector/StorageTab.tsx +27 -7
- package/src/components/JsonViewer.tsx +15 -2
- package/src/components/LogCard.tsx +528 -339
- package/src/constants/version.ts +1 -1
- package/src/customHooks/analyticsLogger.ts +1 -1
- package/src/customHooks/consoleLogger.ts +36 -3
- package/src/customHooks/crashHandler.ts +1 -1
- package/src/customHooks/networkLogger.ts +214 -26
- package/src/helpers/searchQueryParser.ts +40 -285
- package/src/index.tsx +332 -211
|
@@ -7,320 +7,75 @@ export interface SearchQueryOptions {
|
|
|
7
7
|
}
|
|
8
8
|
|
|
9
9
|
/**
|
|
10
|
-
*
|
|
11
|
-
*
|
|
10
|
+
* Universal substring search for NetworkLog.
|
|
11
|
+
* Checks whether a given NetworkLog matches all query keywords across all log fields.
|
|
12
12
|
*/
|
|
13
13
|
export function matchNetworkLogQuery(
|
|
14
14
|
log: NetworkLog,
|
|
15
15
|
searchQuery: string,
|
|
16
16
|
routePath?: string,
|
|
17
|
-
|
|
17
|
+
_options?: SearchQueryOptions,
|
|
18
18
|
): boolean {
|
|
19
19
|
if (!searchQuery || searchQuery.trim().length === 0) return true;
|
|
20
20
|
|
|
21
|
-
|
|
22
|
-
const rawTokens =
|
|
23
|
-
searchQuery.trim().match(/(?:[^\s,"']+|"[^"]*"|'[^']*')+/g) || [];
|
|
24
|
-
|
|
21
|
+
const rawTokens = searchQuery.trim().toLowerCase().split(/\s+/).filter(Boolean);
|
|
25
22
|
if (rawTokens.length === 0) return true;
|
|
26
23
|
|
|
27
|
-
const
|
|
28
|
-
const
|
|
29
|
-
const
|
|
30
|
-
|
|
31
|
-
const methodRaw = log.method || '';
|
|
32
|
-
const urlRaw = log.url || '';
|
|
24
|
+
const methodRaw = (log.method || '').toLowerCase();
|
|
25
|
+
const urlRaw = (log.url || '').toLowerCase();
|
|
26
|
+
const statusStr = log.status != null ? String(log.status).toLowerCase() : 'pending';
|
|
33
27
|
const statusNum =
|
|
34
28
|
typeof log.status === 'number'
|
|
35
29
|
? log.status
|
|
36
30
|
: log.status != null
|
|
37
31
|
? parseInt(String(log.status), 10)
|
|
38
32
|
: null;
|
|
39
|
-
const
|
|
40
|
-
const
|
|
41
|
-
const
|
|
42
|
-
|
|
33
|
+
const clientRaw = (log.client || '').toLowerCase();
|
|
34
|
+
const callerRaw = (log.caller || '').toLowerCase();
|
|
35
|
+
const pathRaw = (routePath || (log as any)?.routeInfo?.path || '').toLowerCase();
|
|
36
|
+
|
|
43
37
|
const reqRaw =
|
|
44
38
|
typeof log.request === 'string'
|
|
45
|
-
? log.request
|
|
39
|
+
? log.request.toLowerCase()
|
|
46
40
|
: log.request != null
|
|
47
|
-
? JSON.stringify(log.request)
|
|
41
|
+
? JSON.stringify(log.request).toLowerCase()
|
|
48
42
|
: '';
|
|
49
43
|
const resRaw =
|
|
50
44
|
typeof log.response === 'string'
|
|
51
|
-
? log.response
|
|
45
|
+
? log.response.toLowerCase()
|
|
52
46
|
: log.response != null
|
|
53
|
-
? JSON.stringify(log.response)
|
|
47
|
+
? JSON.stringify(log.response).toLowerCase()
|
|
54
48
|
: '';
|
|
55
49
|
const reqHeadersRaw = log.requestHeaders
|
|
56
|
-
? JSON.stringify(log.requestHeaders)
|
|
50
|
+
? JSON.stringify(log.requestHeaders).toLowerCase()
|
|
57
51
|
: '';
|
|
58
52
|
const resHeadersRaw = log.responseHeaders
|
|
59
|
-
? JSON.stringify(log.responseHeaders)
|
|
53
|
+
? JSON.stringify(log.responseHeaders).toLowerCase()
|
|
60
54
|
: '';
|
|
61
|
-
const pathRaw = routePath || (log as any)?.routeInfo?.path || '';
|
|
62
|
-
|
|
63
|
-
// Construct search corpus based on active scope
|
|
64
|
-
const getScopedCorpus = (caseSens: boolean): string => {
|
|
65
|
-
let parts: string[] = [];
|
|
66
|
-
if (scope === 'url') {
|
|
67
|
-
parts = [methodRaw, urlRaw, pathRaw, callerRaw];
|
|
68
|
-
} else if (scope === 'reqBody') {
|
|
69
|
-
parts = [reqRaw];
|
|
70
|
-
} else if (scope === 'resBody') {
|
|
71
|
-
parts = [resRaw];
|
|
72
|
-
} else if (scope === 'headers') {
|
|
73
|
-
parts = [reqHeadersRaw, resHeadersRaw];
|
|
74
|
-
} else {
|
|
75
|
-
parts = [
|
|
76
|
-
methodRaw,
|
|
77
|
-
urlRaw,
|
|
78
|
-
statusStr,
|
|
79
|
-
pathRaw,
|
|
80
|
-
callerRaw,
|
|
81
|
-
clientRaw,
|
|
82
|
-
reqRaw,
|
|
83
|
-
resRaw,
|
|
84
|
-
reqHeadersRaw,
|
|
85
|
-
resHeadersRaw,
|
|
86
|
-
];
|
|
87
|
-
}
|
|
88
|
-
const combined = parts.join(' ');
|
|
89
|
-
return caseSens ? combined : combined.toLowerCase();
|
|
90
|
-
};
|
|
91
|
-
|
|
92
|
-
const targetCorpus = getScopedCorpus(isCaseSensitive);
|
|
93
|
-
|
|
94
|
-
const methodStr = methodRaw.toLowerCase();
|
|
95
|
-
const urlStr = urlRaw.toLowerCase();
|
|
96
|
-
const clientStr = clientRaw.toLowerCase();
|
|
97
|
-
const callerStr = callerRaw.toLowerCase();
|
|
98
|
-
const reqStr = reqRaw.toLowerCase();
|
|
99
|
-
const resStr = resRaw.toLowerCase();
|
|
100
|
-
const reqHeadersStr = reqHeadersRaw.toLowerCase();
|
|
101
|
-
const resHeadersStr = resHeadersRaw.toLowerCase();
|
|
102
|
-
const pathStr = pathRaw.toLowerCase();
|
|
103
|
-
|
|
104
|
-
for (const rawToken of rawTokens) {
|
|
105
|
-
const token = rawToken.replace(/^["']|["']$/g, '').trim();
|
|
106
|
-
if (!token) continue;
|
|
107
|
-
|
|
108
|
-
const lowerToken = token.toLowerCase();
|
|
109
|
-
|
|
110
|
-
// 1. method:<VAL> or m:<VAL>
|
|
111
|
-
if (lowerToken.startsWith('method:') || lowerToken.startsWith('m:')) {
|
|
112
|
-
const targetMethod = lowerToken.replace(/^(method:|m:)/, '').trim();
|
|
113
|
-
if (targetMethod.startsWith('!')) {
|
|
114
|
-
if (methodStr === targetMethod.slice(1)) return false;
|
|
115
|
-
} else {
|
|
116
|
-
if (methodStr !== targetMethod) return false;
|
|
117
|
-
}
|
|
118
|
-
continue;
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// 2. status:<VAL> or s:<VAL>
|
|
122
|
-
if (lowerToken.startsWith('status:') || lowerToken.startsWith('s:')) {
|
|
123
|
-
const val = lowerToken.replace(/^(status:|s:)/, '').trim();
|
|
124
|
-
if (val === 'pending' || val === 'loading') {
|
|
125
|
-
if (log.status != null) return false;
|
|
126
|
-
} else if (val.startsWith('>=')) {
|
|
127
|
-
const threshold = parseInt(val.slice(2), 10);
|
|
128
|
-
if (isNaN(threshold) || statusNum === null || statusNum < threshold) return false;
|
|
129
|
-
} else if (val.startsWith('>')) {
|
|
130
|
-
const threshold = parseInt(val.slice(1), 10);
|
|
131
|
-
if (isNaN(threshold) || statusNum === null || statusNum <= threshold) return false;
|
|
132
|
-
} else if (val.startsWith('<=')) {
|
|
133
|
-
const threshold = parseInt(val.slice(2), 10);
|
|
134
|
-
if (isNaN(threshold) || statusNum === null || statusNum > threshold) return false;
|
|
135
|
-
} else if (val.startsWith('<')) {
|
|
136
|
-
const threshold = parseInt(val.slice(1), 10);
|
|
137
|
-
if (isNaN(threshold) || statusNum === null || statusNum >= threshold) return false;
|
|
138
|
-
} else if (val.endsWith('xx') || val.endsWith('x')) {
|
|
139
|
-
const prefix = val.replace(/x/g, '');
|
|
140
|
-
if (!statusStr.startsWith(prefix)) return false;
|
|
141
|
-
} else {
|
|
142
|
-
const targetCode = parseInt(val, 10);
|
|
143
|
-
if (!isNaN(targetCode)) {
|
|
144
|
-
if (statusNum !== targetCode) return false;
|
|
145
|
-
} else if (!statusStr.includes(val)) {
|
|
146
|
-
return false;
|
|
147
|
-
}
|
|
148
|
-
}
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// 3. is:<FLAG>
|
|
153
|
-
if (lowerToken.startsWith('is:')) {
|
|
154
|
-
const flag = lowerToken.slice(3).trim();
|
|
155
|
-
if (
|
|
156
|
-
flag === 'error' ||
|
|
157
|
-
flag === 'failed' ||
|
|
158
|
-
flag === 'err' ||
|
|
159
|
-
flag === 'fail'
|
|
160
|
-
) {
|
|
161
|
-
const isErr =
|
|
162
|
-
log.status === 0 || (statusNum !== null && statusNum >= 400);
|
|
163
|
-
if (!isErr) return false;
|
|
164
|
-
} else if (flag === 'success' || flag === 'ok' || flag === '2xx') {
|
|
165
|
-
const isSuccess = statusNum !== null && statusNum >= 200 && statusNum < 300;
|
|
166
|
-
if (!isSuccess) return false;
|
|
167
|
-
} else if (flag === 'pending' || flag === 'loading') {
|
|
168
|
-
if (log.status != null) return false;
|
|
169
|
-
} else if (flag === 'slow') {
|
|
170
|
-
if (durationNum < 1000) return false;
|
|
171
|
-
} else if (flag === 'fast') {
|
|
172
|
-
if (durationNum >= 200) return false;
|
|
173
|
-
} else if (flag === 'graphql' || flag === 'gql') {
|
|
174
|
-
const isGql =
|
|
175
|
-
urlStr.includes('graphql') ||
|
|
176
|
-
clientStr === 'graphql' ||
|
|
177
|
-
clientStr === 'apollo';
|
|
178
|
-
if (!isGql) return false;
|
|
179
|
-
} else if (flag === 'https') {
|
|
180
|
-
if (!urlStr.startsWith('https')) return false;
|
|
181
|
-
} else if (flag === 'http') {
|
|
182
|
-
if (urlStr.startsWith('https') || !urlStr.startsWith('http'))
|
|
183
|
-
return false;
|
|
184
|
-
} else if (flag === 'json') {
|
|
185
|
-
const isJson =
|
|
186
|
-
reqHeadersStr.includes('application/json') ||
|
|
187
|
-
resHeadersStr.includes('application/json') ||
|
|
188
|
-
urlStr.includes('.json');
|
|
189
|
-
if (!isJson) return false;
|
|
190
|
-
} else if (flag === 'image') {
|
|
191
|
-
const isImg =
|
|
192
|
-
resHeadersStr.includes('image/') ||
|
|
193
|
-
/\.(png|jpe?g|gif|webp|svg)/i.test(urlStr);
|
|
194
|
-
if (!isImg) return false;
|
|
195
|
-
}
|
|
196
|
-
continue;
|
|
197
|
-
}
|
|
198
|
-
|
|
199
|
-
// 4. slow:<DURATION> or dur:<DURATION> or duration:<DURATION>
|
|
200
|
-
if (
|
|
201
|
-
lowerToken.startsWith('slow:') ||
|
|
202
|
-
lowerToken.startsWith('dur:') ||
|
|
203
|
-
lowerToken.startsWith('duration:')
|
|
204
|
-
) {
|
|
205
|
-
const val = lowerToken.replace(/^(slow:|dur:|duration:)/, '').trim();
|
|
206
|
-
let thresholdMs = 0;
|
|
207
|
-
let isGreater = true;
|
|
208
55
|
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
thresholdMs = parseFloat(cleanVal.slice(0, -2));
|
|
228
|
-
} else {
|
|
229
|
-
thresholdMs = parseFloat(cleanVal);
|
|
230
|
-
}
|
|
231
|
-
|
|
232
|
-
if (!isNaN(thresholdMs)) {
|
|
233
|
-
if (isGreater) {
|
|
234
|
-
if (durationNum < thresholdMs) return false;
|
|
235
|
-
} else {
|
|
236
|
-
if (durationNum > thresholdMs) return false;
|
|
237
|
-
}
|
|
238
|
-
}
|
|
239
|
-
continue;
|
|
240
|
-
}
|
|
241
|
-
|
|
242
|
-
// 5. client:<CLIENT> or c:<CLIENT>
|
|
243
|
-
if (lowerToken.startsWith('client:') || lowerToken.startsWith('c:')) {
|
|
244
|
-
const targetClient = lowerToken.replace(/^(client:|c:)/, '').trim();
|
|
245
|
-
if (!clientStr.includes(targetClient)) return false;
|
|
246
|
-
continue;
|
|
247
|
-
}
|
|
248
|
-
|
|
249
|
-
// 6. domain:<DOMAIN> or d:<DOMAIN>
|
|
250
|
-
if (lowerToken.startsWith('domain:') || lowerToken.startsWith('d:')) {
|
|
251
|
-
const targetDomain = lowerToken.replace(/^(domain:|d:)/, '').trim();
|
|
252
|
-
if (!urlStr.includes(targetDomain)) return false;
|
|
253
|
-
continue;
|
|
254
|
-
}
|
|
255
|
-
|
|
256
|
-
// 7. path:<PATH> or p:<PATH> or page:<PAGE>
|
|
257
|
-
if (
|
|
258
|
-
lowerToken.startsWith('path:') ||
|
|
259
|
-
lowerToken.startsWith('p:') ||
|
|
260
|
-
lowerToken.startsWith('page:')
|
|
261
|
-
) {
|
|
262
|
-
const targetPath = lowerToken
|
|
263
|
-
.replace(/^(path:|p:|page:)/, '')
|
|
264
|
-
.trim();
|
|
265
|
-
if (
|
|
266
|
-
!urlStr.includes(targetPath) &&
|
|
267
|
-
!pathStr.includes(targetPath) &&
|
|
268
|
-
!callerStr.includes(targetPath)
|
|
269
|
-
) {
|
|
270
|
-
return false;
|
|
271
|
-
}
|
|
272
|
-
continue;
|
|
56
|
+
const corpus = [
|
|
57
|
+
methodRaw,
|
|
58
|
+
urlRaw,
|
|
59
|
+
statusStr,
|
|
60
|
+
pathRaw,
|
|
61
|
+
callerRaw,
|
|
62
|
+
clientRaw,
|
|
63
|
+
reqRaw,
|
|
64
|
+
resRaw,
|
|
65
|
+
reqHeadersRaw,
|
|
66
|
+
resHeadersRaw,
|
|
67
|
+
].join(' ');
|
|
68
|
+
|
|
69
|
+
return rawTokens.every(token => {
|
|
70
|
+
if (corpus.includes(token)) return true;
|
|
71
|
+
// Error status keywords
|
|
72
|
+
if (token === 'error' || token === 'failed' || token === 'err' || token === 'fail') {
|
|
73
|
+
return log.status === 0 || (statusNum !== null && statusNum >= 400);
|
|
273
74
|
}
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
const target = lowerToken.replace(/^(req:|body:)/, '').trim();
|
|
278
|
-
if (!reqStr.includes(target)) return false;
|
|
279
|
-
continue;
|
|
280
|
-
}
|
|
281
|
-
|
|
282
|
-
// 9. res:<TERM>
|
|
283
|
-
if (lowerToken.startsWith('res:')) {
|
|
284
|
-
const target = lowerToken.slice(4).trim();
|
|
285
|
-
if (!resStr.includes(target)) return false;
|
|
286
|
-
continue;
|
|
287
|
-
}
|
|
288
|
-
|
|
289
|
-
// 10. header:<TERM> or h:<TERM>
|
|
290
|
-
if (lowerToken.startsWith('header:') || lowerToken.startsWith('h:')) {
|
|
291
|
-
const target = lowerToken.replace(/^(header:|h:)/, '').trim();
|
|
292
|
-
if (!reqHeadersStr.includes(target) && !resHeadersStr.includes(target)) {
|
|
293
|
-
return false;
|
|
294
|
-
}
|
|
295
|
-
continue;
|
|
296
|
-
}
|
|
297
|
-
|
|
298
|
-
// 11. Generic Match (handles Regex, Case-sensitivity, and Scoped corpus)
|
|
299
|
-
if (isRegex) {
|
|
300
|
-
try {
|
|
301
|
-
const re = new RegExp(token, isCaseSensitive ? '' : 'i');
|
|
302
|
-
if (!re.test(targetCorpus)) return false;
|
|
303
|
-
} catch {
|
|
304
|
-
const queryTerm = isCaseSensitive ? token : lowerToken;
|
|
305
|
-
if (!targetCorpus.includes(queryTerm)) return false;
|
|
306
|
-
}
|
|
307
|
-
} else {
|
|
308
|
-
const queryTerm = isCaseSensitive ? token : lowerToken;
|
|
309
|
-
if (!targetCorpus.includes(queryTerm)) {
|
|
310
|
-
// Special case: if user typed "error" / "failed", check error status
|
|
311
|
-
if (
|
|
312
|
-
queryTerm === 'error' ||
|
|
313
|
-
queryTerm === 'failed' ||
|
|
314
|
-
queryTerm === 'fail'
|
|
315
|
-
) {
|
|
316
|
-
const isErr =
|
|
317
|
-
log.status === 0 || (statusNum !== null && statusNum >= 400);
|
|
318
|
-
if (isErr) continue;
|
|
319
|
-
}
|
|
320
|
-
return false;
|
|
321
|
-
}
|
|
75
|
+
// Success status keywords
|
|
76
|
+
if (token === 'success' || token === 'ok' || token === '2xx') {
|
|
77
|
+
return statusNum !== null && statusNum >= 200 && statusNum < 300;
|
|
322
78
|
}
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
return true;
|
|
79
|
+
return false;
|
|
80
|
+
});
|
|
326
81
|
}
|