@buoy-gg/network 1.7.2
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 +381 -0
- package/lib/commonjs/index.js +34 -0
- package/lib/commonjs/network/components/NetworkCopySettingsView.js +867 -0
- package/lib/commonjs/network/components/NetworkEventDetailView.js +837 -0
- package/lib/commonjs/network/components/NetworkEventItemCompact.js +323 -0
- package/lib/commonjs/network/components/NetworkFilterViewV3.js +297 -0
- package/lib/commonjs/network/components/NetworkModal.js +937 -0
- package/lib/commonjs/network/hooks/useNetworkEvents.js +320 -0
- package/lib/commonjs/network/hooks/useTickEveryMinute.js +34 -0
- package/lib/commonjs/network/index.js +102 -0
- package/lib/commonjs/network/types/index.js +1 -0
- package/lib/commonjs/network/utils/extractOperationName.js +80 -0
- package/lib/commonjs/network/utils/formatGraphQLVariables.js +219 -0
- package/lib/commonjs/network/utils/formatting.js +30 -0
- package/lib/commonjs/network/utils/networkEventStore.js +269 -0
- package/lib/commonjs/network/utils/networkListener.js +801 -0
- package/lib/commonjs/package.json +1 -0
- package/lib/commonjs/preset.js +83 -0
- package/lib/module/index.js +7 -0
- package/lib/module/network/components/NetworkCopySettingsView.js +862 -0
- package/lib/module/network/components/NetworkEventDetailView.js +834 -0
- package/lib/module/network/components/NetworkEventItemCompact.js +320 -0
- package/lib/module/network/components/NetworkFilterViewV3.js +293 -0
- package/lib/module/network/components/NetworkModal.js +933 -0
- package/lib/module/network/hooks/useNetworkEvents.js +316 -0
- package/lib/module/network/hooks/useTickEveryMinute.js +29 -0
- package/lib/module/network/index.js +20 -0
- package/lib/module/network/types/index.js +1 -0
- package/lib/module/network/utils/extractOperationName.js +76 -0
- package/lib/module/network/utils/formatGraphQLVariables.js +213 -0
- package/lib/module/network/utils/formatting.js +9 -0
- package/lib/module/network/utils/networkEventStore.js +265 -0
- package/lib/module/network/utils/networkListener.js +791 -0
- package/lib/module/preset.js +79 -0
- package/lib/typescript/index.d.ts +3 -0
- package/lib/typescript/index.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.d.ts +26 -0
- package/lib/typescript/network/components/NetworkCopySettingsView.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts +13 -0
- package/lib/typescript/network/components/NetworkEventDetailView.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.d.ts +12 -0
- package/lib/typescript/network/components/NetworkEventItemCompact.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.d.ts +22 -0
- package/lib/typescript/network/components/NetworkFilterViewV3.d.ts.map +1 -0
- package/lib/typescript/network/components/NetworkModal.d.ts +14 -0
- package/lib/typescript/network/components/NetworkModal.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useNetworkEvents.d.ts +72 -0
- package/lib/typescript/network/hooks/useNetworkEvents.d.ts.map +1 -0
- package/lib/typescript/network/hooks/useTickEveryMinute.d.ts +9 -0
- package/lib/typescript/network/hooks/useTickEveryMinute.d.ts.map +1 -0
- package/lib/typescript/network/index.d.ts +12 -0
- package/lib/typescript/network/index.d.ts.map +1 -0
- package/lib/typescript/network/types/index.d.ts +88 -0
- package/lib/typescript/network/types/index.d.ts.map +1 -0
- package/lib/typescript/network/utils/extractOperationName.d.ts +41 -0
- package/lib/typescript/network/utils/extractOperationName.d.ts.map +1 -0
- package/lib/typescript/network/utils/formatGraphQLVariables.d.ts +79 -0
- package/lib/typescript/network/utils/formatGraphQLVariables.d.ts.map +1 -0
- package/lib/typescript/network/utils/formatting.d.ts +6 -0
- package/lib/typescript/network/utils/formatting.d.ts.map +1 -0
- package/lib/typescript/network/utils/networkEventStore.d.ts +81 -0
- package/lib/typescript/network/utils/networkEventStore.d.ts.map +1 -0
- package/lib/typescript/network/utils/networkListener.d.ts +191 -0
- package/lib/typescript/network/utils/networkListener.d.ts.map +1 -0
- package/lib/typescript/preset.d.ts +76 -0
- package/lib/typescript/preset.d.ts.map +1 -0
- package/package.json +69 -0
|
@@ -0,0 +1,320 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.FREE_TIER_REQUEST_LIMIT = void 0;
|
|
7
|
+
exports.useNetworkEvents = useNetworkEvents;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _networkEventStore = require("../utils/networkEventStore");
|
|
10
|
+
var _networkListener = require("../utils/networkListener");
|
|
11
|
+
var _formatGraphQLVariables = require("../utils/formatGraphQLVariables");
|
|
12
|
+
/**
|
|
13
|
+
* Hook for accessing network events and controls
|
|
14
|
+
* Uses Reactotron-style listener pattern
|
|
15
|
+
*/
|
|
16
|
+
|
|
17
|
+
/** Free tier limit for network requests */
|
|
18
|
+
const FREE_TIER_REQUEST_LIMIT = exports.FREE_TIER_REQUEST_LIMIT = 25;
|
|
19
|
+
|
|
20
|
+
/**
|
|
21
|
+
* Custom hook for accessing network events and controls
|
|
22
|
+
*
|
|
23
|
+
* This hook provides a complete interface for network monitoring, including
|
|
24
|
+
* event filtering, statistics calculation, and interception control. It uses
|
|
25
|
+
* the Reactotron-style listener pattern for network event handling.
|
|
26
|
+
*
|
|
27
|
+
* @returns Object containing filtered events, statistics, controls, and utilities
|
|
28
|
+
*
|
|
29
|
+
* @example
|
|
30
|
+
* ```typescript
|
|
31
|
+
* function NetworkMonitor() {
|
|
32
|
+
* const {
|
|
33
|
+
* events,
|
|
34
|
+
* stats,
|
|
35
|
+
* filter,
|
|
36
|
+
* setFilter,
|
|
37
|
+
* clearEvents,
|
|
38
|
+
* toggleInterception,
|
|
39
|
+
* isEnabled
|
|
40
|
+
* } = useNetworkEvents();
|
|
41
|
+
*
|
|
42
|
+
* return (
|
|
43
|
+
* <div>
|
|
44
|
+
* <p>Total requests: {stats.totalRequests}</p>
|
|
45
|
+
* <p>Success rate: {stats.successfulRequests}/{stats.totalRequests}</p>
|
|
46
|
+
* <button onClick={toggleInterception}>
|
|
47
|
+
* {isEnabled ? 'Stop' : 'Start'} Monitoring
|
|
48
|
+
* </button>
|
|
49
|
+
* </div>
|
|
50
|
+
* );
|
|
51
|
+
* }
|
|
52
|
+
* ```
|
|
53
|
+
*
|
|
54
|
+
* @performance Uses memoization for expensive filtering and statistics calculations
|
|
55
|
+
* @performance Optimizes string operations and array processing for large datasets
|
|
56
|
+
* @performance Includes Set-based lookups for O(1) filter matching
|
|
57
|
+
*
|
|
58
|
+
* @param options.isPro - Whether user has Pro access (unlimited events). Defaults to false (limited to FREE_TIER_REQUEST_LIMIT)
|
|
59
|
+
*/
|
|
60
|
+
function useNetworkEvents(options = {}) {
|
|
61
|
+
const {
|
|
62
|
+
isPro = false
|
|
63
|
+
} = options;
|
|
64
|
+
const [events, setEvents] = (0, _react.useState)([]);
|
|
65
|
+
const [filter, setFilter] = (0, _react.useState)({});
|
|
66
|
+
const [isEnabled, setIsEnabled] = (0, _react.useState)(false);
|
|
67
|
+
|
|
68
|
+
// Subscribe to event store changes
|
|
69
|
+
(0, _react.useEffect)(() => {
|
|
70
|
+
// Subscribe to store changes
|
|
71
|
+
const unsubscribeStore = _networkEventStore.networkEventStore.subscribe(setEvents);
|
|
72
|
+
|
|
73
|
+
// Add listener to network events
|
|
74
|
+
const unsubscribeListener = (0, _networkListener.addNetworkListener)(event => {
|
|
75
|
+
// Only log in development and for non-ignored URLs
|
|
76
|
+
if (__DEV__ && !event.request.url.includes("symbolicate") && !event.request.url.includes(":8081")) {
|
|
77
|
+
// Network event processed: [event.type] [method] [url] - available for debugging if needed
|
|
78
|
+
}
|
|
79
|
+
_networkEventStore.networkEventStore.processNetworkEvent(event);
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
// Check if already listening
|
|
83
|
+
setIsEnabled((0, _networkListener.networkListener)().isActive);
|
|
84
|
+
|
|
85
|
+
// Start listening if not already
|
|
86
|
+
if (!(0, _networkListener.networkListener)().isActive) {
|
|
87
|
+
(0, _networkListener.startNetworkListener)();
|
|
88
|
+
setIsEnabled(true);
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
// Load initial events
|
|
92
|
+
setEvents(_networkEventStore.networkEventStore.getEvents());
|
|
93
|
+
return () => {
|
|
94
|
+
unsubscribeStore();
|
|
95
|
+
unsubscribeListener();
|
|
96
|
+
};
|
|
97
|
+
}, []);
|
|
98
|
+
|
|
99
|
+
// Clear all events
|
|
100
|
+
const clearEvents = (0, _react.useCallback)(() => {
|
|
101
|
+
_networkEventStore.networkEventStore.clearEvents();
|
|
102
|
+
}, []);
|
|
103
|
+
|
|
104
|
+
// Toggle interception
|
|
105
|
+
const toggleInterception = (0, _react.useCallback)(() => {
|
|
106
|
+
if (isEnabled) {
|
|
107
|
+
(0, _networkListener.stopNetworkListener)();
|
|
108
|
+
setIsEnabled(false);
|
|
109
|
+
} else {
|
|
110
|
+
(0, _networkListener.startNetworkListener)();
|
|
111
|
+
setIsEnabled(true);
|
|
112
|
+
}
|
|
113
|
+
}, [isEnabled]);
|
|
114
|
+
|
|
115
|
+
// Memoize search text processing to avoid repeated toLowerCase calls
|
|
116
|
+
// Performance: Expensive string operations repeated for every event on every filter
|
|
117
|
+
const searchLower = (0, _react.useMemo)(() => {
|
|
118
|
+
return filter.searchText ? filter.searchText.toLowerCase() : null;
|
|
119
|
+
}, [filter.searchText]);
|
|
120
|
+
|
|
121
|
+
// Memoize method filter Set for O(1) lookup instead of Array.includes
|
|
122
|
+
// Performance: Converting array.includes to Set.has for faster lookups with large method lists
|
|
123
|
+
const methodSet = (0, _react.useMemo)(() => {
|
|
124
|
+
return filter.method && filter.method.length > 0 ? new Set(filter.method) : null;
|
|
125
|
+
}, [filter.method]);
|
|
126
|
+
|
|
127
|
+
// Memoize content type Set for O(1) lookup
|
|
128
|
+
// Performance: Converting array.some to Set.has for faster content type matching
|
|
129
|
+
const contentTypeSet = (0, _react.useMemo)(() => {
|
|
130
|
+
return filter.contentType && filter.contentType.length > 0 ? new Set(filter.contentType) : null;
|
|
131
|
+
}, [filter.contentType]);
|
|
132
|
+
|
|
133
|
+
// Filter events with optimized string operations and Set lookups
|
|
134
|
+
// Performance: Complex multi-stage filtering with string operations and content type matching
|
|
135
|
+
const filteredEvents = (0, _react.useMemo)(() => {
|
|
136
|
+
let filtered = [...events];
|
|
137
|
+
if (methodSet) {
|
|
138
|
+
filtered = filtered.filter(e => methodSet.has(e.method));
|
|
139
|
+
}
|
|
140
|
+
if (filter.status && filter.status !== "all") {
|
|
141
|
+
switch (filter.status) {
|
|
142
|
+
case "success":
|
|
143
|
+
filtered = filtered.filter(e => e.status && e.status >= 200 && e.status < 300);
|
|
144
|
+
break;
|
|
145
|
+
case "error":
|
|
146
|
+
filtered = filtered.filter(e => e.error || e.status && e.status >= 400);
|
|
147
|
+
break;
|
|
148
|
+
case "pending":
|
|
149
|
+
filtered = filtered.filter(e => !e.status && !e.error);
|
|
150
|
+
break;
|
|
151
|
+
}
|
|
152
|
+
}
|
|
153
|
+
if (searchLower) {
|
|
154
|
+
filtered = filtered.filter(e => e.url.toLowerCase().includes(searchLower) || e.method.toLowerCase().includes(searchLower) || e.path?.toLowerCase().includes(searchLower) || e.host?.toLowerCase().includes(searchLower) || e.error && e.error.toLowerCase().includes(searchLower) ||
|
|
155
|
+
// Search by GraphQL operation name (e.g., "GetUser", "CreatePost")
|
|
156
|
+
e.operationName && e.operationName.toLowerCase().includes(searchLower) ||
|
|
157
|
+
// Search by GraphQL variable values (e.g., "Sandshrew", "123", "true")
|
|
158
|
+
// This enables finding specific requests like "GetPokemon › Sandshrew" by typing "Sandshrew"
|
|
159
|
+
(0, _formatGraphQLVariables.searchGraphQLVariables)(e.graphqlVariables, searchLower));
|
|
160
|
+
}
|
|
161
|
+
if (filter.host) {
|
|
162
|
+
filtered = filtered.filter(e => e.host === filter.host);
|
|
163
|
+
}
|
|
164
|
+
if (contentTypeSet) {
|
|
165
|
+
filtered = filtered.filter(e => {
|
|
166
|
+
const headers = e.responseHeaders || e.requestHeaders;
|
|
167
|
+
const contentType = headers?.["content-type"] || headers?.["Content-Type"] || "";
|
|
168
|
+
for (const type of contentTypeSet) {
|
|
169
|
+
switch (type) {
|
|
170
|
+
case "JSON":
|
|
171
|
+
if (contentType.includes("json")) return true;
|
|
172
|
+
break;
|
|
173
|
+
case "XML":
|
|
174
|
+
if (contentType.includes("xml")) return true;
|
|
175
|
+
break;
|
|
176
|
+
case "HTML":
|
|
177
|
+
if (contentType.includes("html")) return true;
|
|
178
|
+
break;
|
|
179
|
+
case "TEXT":
|
|
180
|
+
if (contentType.includes("text")) return true;
|
|
181
|
+
break;
|
|
182
|
+
case "IMAGE":
|
|
183
|
+
if (contentType.includes("image")) return true;
|
|
184
|
+
break;
|
|
185
|
+
case "VIDEO":
|
|
186
|
+
if (contentType.includes("video")) return true;
|
|
187
|
+
break;
|
|
188
|
+
case "AUDIO":
|
|
189
|
+
if (contentType.includes("audio")) return true;
|
|
190
|
+
break;
|
|
191
|
+
case "FORM":
|
|
192
|
+
if (contentType.includes("form")) return true;
|
|
193
|
+
break;
|
|
194
|
+
case "OTHER":
|
|
195
|
+
if (!contentType || !contentType.includes("json") && !contentType.includes("xml") && !contentType.includes("html") && !contentType.includes("text") && !contentType.includes("image") && !contentType.includes("video") && !contentType.includes("audio") && !contentType.includes("form")) {
|
|
196
|
+
return true;
|
|
197
|
+
}
|
|
198
|
+
break;
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return false;
|
|
202
|
+
});
|
|
203
|
+
}
|
|
204
|
+
return filtered;
|
|
205
|
+
}, [events, filter, searchLower, methodSet, contentTypeSet]);
|
|
206
|
+
|
|
207
|
+
// For free users, determine which events are "locked" (beyond the limit)
|
|
208
|
+
// Based on original event order, not filtered results - so locked events stay locked even when searching
|
|
209
|
+
const lockedEventIds = (0, _react.useMemo)(() => {
|
|
210
|
+
if (isPro) {
|
|
211
|
+
return new Set();
|
|
212
|
+
}
|
|
213
|
+
// Events beyond the limit in the ORIGINAL events array are locked
|
|
214
|
+
const lockedIds = new Set();
|
|
215
|
+
events.slice(FREE_TIER_REQUEST_LIMIT).forEach(event => {
|
|
216
|
+
lockedIds.add(event.id);
|
|
217
|
+
});
|
|
218
|
+
return lockedIds;
|
|
219
|
+
}, [events, isPro]);
|
|
220
|
+
|
|
221
|
+
// Check if there are locked events in the current filtered results
|
|
222
|
+
const lockedEventsInFilter = (0, _react.useMemo)(() => {
|
|
223
|
+
return filteredEvents.filter(event => lockedEventIds.has(event.id));
|
|
224
|
+
}, [filteredEvents, lockedEventIds]);
|
|
225
|
+
const hasLockedEvents = lockedEventsInFilter.length > 0;
|
|
226
|
+
const lockedEventCount = lockedEventsInFilter.length;
|
|
227
|
+
|
|
228
|
+
// Helper to check if a specific event is locked
|
|
229
|
+
const isEventLocked = (0, _react.useCallback)(eventId => {
|
|
230
|
+
return lockedEventIds.has(eventId);
|
|
231
|
+
}, [lockedEventIds]);
|
|
232
|
+
|
|
233
|
+
// Memoize expensive statistics calculation by categorizing events in single pass
|
|
234
|
+
// Performance: Multiple array.filter operations replaced with single loop for better performance
|
|
235
|
+
const stats = (0, _react.useMemo)(() => {
|
|
236
|
+
let successful = 0;
|
|
237
|
+
let failed = 0;
|
|
238
|
+
let pending = 0;
|
|
239
|
+
let totalSent = 0;
|
|
240
|
+
let totalReceived = 0;
|
|
241
|
+
let durationSum = 0;
|
|
242
|
+
let durationCount = 0;
|
|
243
|
+
|
|
244
|
+
// Single pass through events for all statistics
|
|
245
|
+
for (const event of events) {
|
|
246
|
+
// Categorize status
|
|
247
|
+
if (event.status && event.status >= 200 && event.status < 300) {
|
|
248
|
+
successful++;
|
|
249
|
+
} else if (event.error || event.status && event.status >= 400) {
|
|
250
|
+
failed++;
|
|
251
|
+
} else if (!event.status && !event.error) {
|
|
252
|
+
pending++;
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
// Accumulate data sizes
|
|
256
|
+
totalSent += event.requestSize || 0;
|
|
257
|
+
totalReceived += event.responseSize || 0;
|
|
258
|
+
|
|
259
|
+
// Accumulate durations
|
|
260
|
+
if (event.duration) {
|
|
261
|
+
durationSum += event.duration;
|
|
262
|
+
durationCount++;
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
const avgDuration = durationCount > 0 ? durationSum / durationCount : 0;
|
|
266
|
+
return {
|
|
267
|
+
totalRequests: events.length,
|
|
268
|
+
successfulRequests: successful,
|
|
269
|
+
failedRequests: failed,
|
|
270
|
+
pendingRequests: pending,
|
|
271
|
+
totalDataSent: totalSent,
|
|
272
|
+
totalDataReceived: totalReceived,
|
|
273
|
+
averageDuration: Math.round(avgDuration)
|
|
274
|
+
};
|
|
275
|
+
}, [events]);
|
|
276
|
+
|
|
277
|
+
// Memoize unique hosts extraction with single pass instead of map + filter + Set
|
|
278
|
+
// Performance: Avoiding array.map().filter() chain, using single loop with Set for deduplication
|
|
279
|
+
const hosts = (0, _react.useMemo)(() => {
|
|
280
|
+
const hostSet = new Set();
|
|
281
|
+
for (const event of events) {
|
|
282
|
+
if (event.host) {
|
|
283
|
+
hostSet.add(event.host);
|
|
284
|
+
}
|
|
285
|
+
}
|
|
286
|
+
return Array.from(hostSet);
|
|
287
|
+
}, [events]);
|
|
288
|
+
|
|
289
|
+
// Memoize unique methods extraction with single pass
|
|
290
|
+
// Performance: Avoiding array.map() + Set constructor, using single loop for better performance
|
|
291
|
+
const methods = (0, _react.useMemo)(() => {
|
|
292
|
+
const methodSet = new Set();
|
|
293
|
+
for (const event of events) {
|
|
294
|
+
methodSet.add(event.method);
|
|
295
|
+
}
|
|
296
|
+
return Array.from(methodSet);
|
|
297
|
+
}, [events]);
|
|
298
|
+
return {
|
|
299
|
+
/** Filtered events (all shown, but some may be locked for free users) */
|
|
300
|
+
events: filteredEvents,
|
|
301
|
+
/** All events before filtering (for stats) */
|
|
302
|
+
allEvents: events,
|
|
303
|
+
stats,
|
|
304
|
+
filter,
|
|
305
|
+
setFilter,
|
|
306
|
+
clearEvents,
|
|
307
|
+
isEnabled,
|
|
308
|
+
toggleInterception,
|
|
309
|
+
hosts,
|
|
310
|
+
methods,
|
|
311
|
+
/** Whether there are locked events due to free tier limit */
|
|
312
|
+
hasLockedEvents,
|
|
313
|
+
/** Number of events locked due to free tier limit */
|
|
314
|
+
lockedEventCount,
|
|
315
|
+
/** Check if a specific event is locked (by ID) */
|
|
316
|
+
isEventLocked,
|
|
317
|
+
/** Free tier request limit */
|
|
318
|
+
requestLimit: FREE_TIER_REQUEST_LIMIT
|
|
319
|
+
};
|
|
320
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.TickProvider = TickProvider;
|
|
7
|
+
exports.useTickEveryMinute = useTickEveryMinute;
|
|
8
|
+
var _react = require("react");
|
|
9
|
+
var _jsxRuntime = require("react/jsx-runtime");
|
|
10
|
+
const TickContext = /*#__PURE__*/(0, _react.createContext)(Date.now());
|
|
11
|
+
function TickProvider({
|
|
12
|
+
children,
|
|
13
|
+
intervalMs = 60_000
|
|
14
|
+
}) {
|
|
15
|
+
const [tick, setTick] = (0, _react.useState)(() => Date.now());
|
|
16
|
+
(0, _react.useEffect)(() => {
|
|
17
|
+
const id = setInterval(() => {
|
|
18
|
+
setTick(Date.now());
|
|
19
|
+
}, intervalMs);
|
|
20
|
+
return () => {
|
|
21
|
+
clearInterval(id);
|
|
22
|
+
};
|
|
23
|
+
}, [intervalMs]);
|
|
24
|
+
return /*#__PURE__*/(0, _jsxRuntime.jsx)(TickContext.Provider, {
|
|
25
|
+
value: tick,
|
|
26
|
+
children: children
|
|
27
|
+
});
|
|
28
|
+
}
|
|
29
|
+
function useTickEveryMinute() {
|
|
30
|
+
const tick = (0, _react.useContext)(TickContext);
|
|
31
|
+
|
|
32
|
+
// Expose stable object so consumers can memoize on value changes
|
|
33
|
+
return (0, _react.useMemo)(() => tick, [tick]);
|
|
34
|
+
}
|
|
@@ -0,0 +1,102 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
Object.defineProperty(exports, "NetworkEventDetailView", {
|
|
7
|
+
enumerable: true,
|
|
8
|
+
get: function () {
|
|
9
|
+
return _NetworkEventDetailView.NetworkEventDetailView;
|
|
10
|
+
}
|
|
11
|
+
});
|
|
12
|
+
Object.defineProperty(exports, "NetworkEventItemCompact", {
|
|
13
|
+
enumerable: true,
|
|
14
|
+
get: function () {
|
|
15
|
+
return _NetworkEventItemCompact.NetworkEventItemCompact;
|
|
16
|
+
}
|
|
17
|
+
});
|
|
18
|
+
Object.defineProperty(exports, "NetworkModal", {
|
|
19
|
+
enumerable: true,
|
|
20
|
+
get: function () {
|
|
21
|
+
return _NetworkModal.NetworkModal;
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
Object.defineProperty(exports, "addNetworkListener", {
|
|
25
|
+
enumerable: true,
|
|
26
|
+
get: function () {
|
|
27
|
+
return _networkListener.addNetworkListener;
|
|
28
|
+
}
|
|
29
|
+
});
|
|
30
|
+
Object.defineProperty(exports, "formatBytes", {
|
|
31
|
+
enumerable: true,
|
|
32
|
+
get: function () {
|
|
33
|
+
return _formatting.formatBytes;
|
|
34
|
+
}
|
|
35
|
+
});
|
|
36
|
+
Object.defineProperty(exports, "formatDuration", {
|
|
37
|
+
enumerable: true,
|
|
38
|
+
get: function () {
|
|
39
|
+
return _formatting.formatDuration;
|
|
40
|
+
}
|
|
41
|
+
});
|
|
42
|
+
Object.defineProperty(exports, "formatHttpStatus", {
|
|
43
|
+
enumerable: true,
|
|
44
|
+
get: function () {
|
|
45
|
+
return _formatting.formatHttpStatus;
|
|
46
|
+
}
|
|
47
|
+
});
|
|
48
|
+
Object.defineProperty(exports, "getNetworkListenerCount", {
|
|
49
|
+
enumerable: true,
|
|
50
|
+
get: function () {
|
|
51
|
+
return _networkListener.getNetworkListenerCount;
|
|
52
|
+
}
|
|
53
|
+
});
|
|
54
|
+
Object.defineProperty(exports, "isNetworkListening", {
|
|
55
|
+
enumerable: true,
|
|
56
|
+
get: function () {
|
|
57
|
+
return _networkListener.isNetworkListening;
|
|
58
|
+
}
|
|
59
|
+
});
|
|
60
|
+
Object.defineProperty(exports, "networkEventStore", {
|
|
61
|
+
enumerable: true,
|
|
62
|
+
get: function () {
|
|
63
|
+
return _networkEventStore.networkEventStore;
|
|
64
|
+
}
|
|
65
|
+
});
|
|
66
|
+
Object.defineProperty(exports, "networkListener", {
|
|
67
|
+
enumerable: true,
|
|
68
|
+
get: function () {
|
|
69
|
+
return _networkListener.networkListener;
|
|
70
|
+
}
|
|
71
|
+
});
|
|
72
|
+
Object.defineProperty(exports, "removeAllNetworkListeners", {
|
|
73
|
+
enumerable: true,
|
|
74
|
+
get: function () {
|
|
75
|
+
return _networkListener.removeAllNetworkListeners;
|
|
76
|
+
}
|
|
77
|
+
});
|
|
78
|
+
Object.defineProperty(exports, "startNetworkListener", {
|
|
79
|
+
enumerable: true,
|
|
80
|
+
get: function () {
|
|
81
|
+
return _networkListener.startNetworkListener;
|
|
82
|
+
}
|
|
83
|
+
});
|
|
84
|
+
Object.defineProperty(exports, "stopNetworkListener", {
|
|
85
|
+
enumerable: true,
|
|
86
|
+
get: function () {
|
|
87
|
+
return _networkListener.stopNetworkListener;
|
|
88
|
+
}
|
|
89
|
+
});
|
|
90
|
+
Object.defineProperty(exports, "useNetworkEvents", {
|
|
91
|
+
enumerable: true,
|
|
92
|
+
get: function () {
|
|
93
|
+
return _useNetworkEvents.useNetworkEvents;
|
|
94
|
+
}
|
|
95
|
+
});
|
|
96
|
+
var _NetworkModal = require("./components/NetworkModal");
|
|
97
|
+
var _NetworkEventDetailView = require("./components/NetworkEventDetailView");
|
|
98
|
+
var _NetworkEventItemCompact = require("./components/NetworkEventItemCompact");
|
|
99
|
+
var _useNetworkEvents = require("./hooks/useNetworkEvents");
|
|
100
|
+
var _networkListener = require("./utils/networkListener");
|
|
101
|
+
var _networkEventStore = require("./utils/networkEventStore");
|
|
102
|
+
var _formatting = require("./utils/formatting");
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
Object.defineProperty(exports, "__esModule", {
|
|
4
|
+
value: true
|
|
5
|
+
});
|
|
6
|
+
exports.extractOperationName = extractOperationName;
|
|
7
|
+
/**
|
|
8
|
+
* Extract GraphQL operation name from request data
|
|
9
|
+
*
|
|
10
|
+
* This utility extracts the operation name from GraphQL requests to enable
|
|
11
|
+
* searching and filtering by operation name rather than just URL paths.
|
|
12
|
+
*
|
|
13
|
+
* For GraphQL, all requests typically go to the same endpoint (e.g., /graphql),
|
|
14
|
+
* making URL-based search ineffective. This function extracts the actual
|
|
15
|
+
* operation name (e.g., "GetUser", "CreatePost") from the request payload.
|
|
16
|
+
*
|
|
17
|
+
* Extraction Methods (tried in order):
|
|
18
|
+
* 1. Direct operationName field in request data
|
|
19
|
+
* 2. Parse from query string using regex pattern
|
|
20
|
+
*
|
|
21
|
+
* @param requestData - The request data object (typically GraphQL query payload)
|
|
22
|
+
* @returns Operation name string or null if not found
|
|
23
|
+
*
|
|
24
|
+
* @example
|
|
25
|
+
* // Method 1: Explicit operationName field
|
|
26
|
+
* const data1 = {
|
|
27
|
+
* operationName: "GetUser",
|
|
28
|
+
* query: "query GetUser { user { id name } }"
|
|
29
|
+
* };
|
|
30
|
+
* extractOperationName(data1); // Returns "GetUser"
|
|
31
|
+
*
|
|
32
|
+
* @example
|
|
33
|
+
* // Method 2: Parse from query string
|
|
34
|
+
* const data2 = {
|
|
35
|
+
* query: "mutation CreatePost { createPost(title: \"Hello\") { id } }"
|
|
36
|
+
* };
|
|
37
|
+
* extractOperationName(data2); // Returns "CreatePost"
|
|
38
|
+
*
|
|
39
|
+
* @example
|
|
40
|
+
* // No operation name (anonymous query)
|
|
41
|
+
* const data3 = {
|
|
42
|
+
* query: "{ user { id name } }"
|
|
43
|
+
* };
|
|
44
|
+
* extractOperationName(data3); // Returns null
|
|
45
|
+
*/
|
|
46
|
+
function extractOperationName(requestData) {
|
|
47
|
+
// Validate input is an object
|
|
48
|
+
if (!requestData || typeof requestData !== 'object') {
|
|
49
|
+
return null;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
// Method 1: Check for explicit operationName field
|
|
53
|
+
// This is the standard GraphQL request format
|
|
54
|
+
if ('operationName' in requestData && requestData.operationName) {
|
|
55
|
+
const opName = requestData.operationName;
|
|
56
|
+
// Ensure it's a string and not empty
|
|
57
|
+
if (typeof opName === 'string' && opName.trim().length > 0) {
|
|
58
|
+
return opName.trim();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// Method 2: Parse from query string
|
|
63
|
+
// Handles cases where operationName field is missing or null
|
|
64
|
+
if ('query' in requestData && typeof requestData.query === 'string') {
|
|
65
|
+
const query = requestData.query;
|
|
66
|
+
|
|
67
|
+
// Match: query OperationName or mutation OperationName or subscription OperationName
|
|
68
|
+
// Pattern explanation:
|
|
69
|
+
// - (?:query|mutation|subscription) - Match operation type (non-capturing group)
|
|
70
|
+
// - \s+ - One or more whitespace characters
|
|
71
|
+
// - (\w+) - Capture operation name (letters, numbers, underscore)
|
|
72
|
+
const match = query.match(/(?:query|mutation|subscription)\s+(\w+)/);
|
|
73
|
+
if (match && match[1]) {
|
|
74
|
+
return match[1];
|
|
75
|
+
}
|
|
76
|
+
}
|
|
77
|
+
|
|
78
|
+
// No operation name found
|
|
79
|
+
return null;
|
|
80
|
+
}
|