network-terminal 1.0.12 → 1.0.13

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/index.js CHANGED
@@ -35,10 +35,10 @@ __export(index_exports, {
35
35
  module.exports = __toCommonJS(index_exports);
36
36
 
37
37
  // src/components/NetworkTerminal.tsx
38
- var import_react3 = require("react");
38
+ var import_react4 = require("react");
39
39
 
40
40
  // src/components/Terminal.tsx
41
- var import_react = require("react");
41
+ var import_react2 = require("react");
42
42
 
43
43
  // src/components/TerminalHeader.tsx
44
44
  var import_jsx_runtime = require("react/jsx-runtime");
@@ -138,6 +138,9 @@ var TerminalHeader = ({
138
138
  ] });
139
139
  };
140
140
 
141
+ // src/components/LogEntry.tsx
142
+ var import_react = require("react");
143
+
141
144
  // src/utils/formatters.ts
142
145
  var formatJson = (data) => {
143
146
  if (!data) return "";
@@ -190,6 +193,17 @@ var getMethodColor = (method) => {
190
193
 
191
194
  // src/components/LogEntry.tsx
192
195
  var import_jsx_runtime2 = require("react/jsx-runtime");
196
+ var decodeSpecialChars = (str) => {
197
+ if (!str) return str;
198
+ try {
199
+ return str.replace(
200
+ /\\u([0-9a-fA-F]{4})/g,
201
+ (_, code) => String.fromCharCode(parseInt(code, 16))
202
+ );
203
+ } catch {
204
+ return str;
205
+ }
206
+ };
193
207
  var styles2 = {
194
208
  container: {
195
209
  marginBottom: "16px",
@@ -260,9 +274,55 @@ var styles2 = {
260
274
  whiteSpace: "pre-wrap",
261
275
  fontFamily: "monospace",
262
276
  margin: 0
277
+ },
278
+ bodyHeader: {
279
+ display: "flex",
280
+ alignItems: "center",
281
+ justifyContent: "space-between",
282
+ marginBottom: "4px"
283
+ },
284
+ copyButton: {
285
+ backgroundColor: "transparent",
286
+ border: "1px solid #4b5563",
287
+ borderRadius: "4px",
288
+ color: "#9ca3af",
289
+ cursor: "pointer",
290
+ fontSize: "11px",
291
+ padding: "2px 8px",
292
+ fontFamily: "monospace",
293
+ transition: "all 0.2s"
294
+ },
295
+ copyButtonHover: {
296
+ backgroundColor: "#374151",
297
+ color: "#fff"
298
+ },
299
+ copyButtonCopied: {
300
+ backgroundColor: "#065f46",
301
+ borderColor: "#10b981",
302
+ color: "#10b981"
263
303
  }
264
304
  };
265
305
  var LogEntry = ({ log, type }) => {
306
+ const [copiedField, setCopiedField] = (0, import_react.useState)(null);
307
+ const [hoveredButton, setHoveredButton] = (0, import_react.useState)(null);
308
+ const handleCopy = async (content, field) => {
309
+ try {
310
+ const text = decodeSpecialChars(formatJson(content));
311
+ await navigator.clipboard.writeText(text);
312
+ setCopiedField(field);
313
+ setTimeout(() => setCopiedField(null), 2e3);
314
+ } catch (err) {
315
+ console.error("Failed to copy:", err);
316
+ }
317
+ };
318
+ const getButtonStyle = (field) => ({
319
+ ...styles2.copyButton,
320
+ ...hoveredButton === field && copiedField !== field ? styles2.copyButtonHover : {},
321
+ ...copiedField === field ? styles2.copyButtonCopied : {}
322
+ });
323
+ const formatContent = (data) => {
324
+ return decodeSpecialChars(formatJson(data));
325
+ };
266
326
  return /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.container, children: [
267
327
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.header, children: [
268
328
  /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("span", { style: styles2.timestamp, children: [
@@ -284,23 +344,59 @@ var LogEntry = ({ log, type }) => {
284
344
  ] }),
285
345
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("div", { style: styles2.url, children: log.url }),
286
346
  type === "request" ? log.requestBody ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyContainer, children: [
287
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyLabel, children: [
288
- "\u25B8",
289
- " Payload:"
347
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyHeader, children: [
348
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyLabel, children: [
349
+ "\u25B8",
350
+ " Payload:"
351
+ ] }),
352
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
353
+ "button",
354
+ {
355
+ style: getButtonStyle("payload"),
356
+ onClick: () => handleCopy(log.requestBody, "payload"),
357
+ onMouseEnter: () => setHoveredButton("payload"),
358
+ onMouseLeave: () => setHoveredButton(null),
359
+ children: copiedField === "payload" ? "Copied!" : "Copy"
360
+ }
361
+ )
290
362
  ] }),
291
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: styles2.pre, children: formatJson(log.requestBody) })
363
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: styles2.pre, children: formatContent(log.requestBody) })
292
364
  ] }) : null : log.error ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyContainer, children: [
293
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...styles2.bodyLabel, color: "#f87171" }, children: [
294
- "\u25B8",
295
- " Error:"
365
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyHeader, children: [
366
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: { ...styles2.bodyLabel, color: "#f87171" }, children: [
367
+ "\u25B8",
368
+ " Error:"
369
+ ] }),
370
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
371
+ "button",
372
+ {
373
+ style: getButtonStyle("error"),
374
+ onClick: () => handleCopy(log.error, "error"),
375
+ onMouseEnter: () => setHoveredButton("error"),
376
+ onMouseLeave: () => setHoveredButton(null),
377
+ children: copiedField === "error" ? "Copied!" : "Copy"
378
+ }
379
+ )
296
380
  ] }),
297
381
  /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: styles2.errorPre, children: log.error })
298
382
  ] }) : log.responseBody ? /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyContainer, children: [
299
- /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyLabel, children: [
300
- "\u25B8",
301
- " Response:"
383
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyHeader, children: [
384
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsxs)("div", { style: styles2.bodyLabel, children: [
385
+ "\u25B8",
386
+ " Response:"
387
+ ] }),
388
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)(
389
+ "button",
390
+ {
391
+ style: getButtonStyle("response"),
392
+ onClick: () => handleCopy(log.responseBody, "response"),
393
+ onMouseEnter: () => setHoveredButton("response"),
394
+ onMouseLeave: () => setHoveredButton(null),
395
+ children: copiedField === "response" ? "Copied!" : "Copy"
396
+ }
397
+ )
302
398
  ] }),
303
- /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: styles2.pre, children: formatJson(log.responseBody) })
399
+ /* @__PURE__ */ (0, import_jsx_runtime2.jsx)("pre", { style: styles2.pre, children: formatContent(log.responseBody) })
304
400
  ] }) : null
305
401
  ] });
306
402
  };
@@ -344,9 +440,9 @@ var Terminal = ({
344
440
  expanded,
345
441
  onToggleExpand
346
442
  }) => {
347
- const terminalRef = (0, import_react.useRef)(null);
348
- const [autoScroll, setAutoScroll] = (0, import_react.useState)(true);
349
- (0, import_react.useEffect)(() => {
443
+ const terminalRef = (0, import_react2.useRef)(null);
444
+ const [autoScroll, setAutoScroll] = (0, import_react2.useState)(true);
445
+ (0, import_react2.useEffect)(() => {
350
446
  if (autoScroll && terminalRef.current) {
351
447
  terminalRef.current.scrollTop = terminalRef.current.scrollHeight;
352
448
  }
@@ -382,19 +478,19 @@ var Terminal = ({
382
478
  };
383
479
 
384
480
  // src/hooks/useNetworkInterceptor.ts
385
- var import_react2 = require("react");
481
+ var import_react3 = require("react");
386
482
  var useNetworkInterceptor = ({
387
483
  enabled,
388
484
  onLogAdd,
389
485
  onLogUpdate
390
486
  }) => {
391
- const originalFetch = (0, import_react2.useRef)(null);
392
- const originalXHROpen = (0, import_react2.useRef)(null);
393
- const originalXHRSend = (0, import_react2.useRef)(null);
394
- const generateId = (0, import_react2.useCallback)((prefix) => {
487
+ const originalFetch = (0, import_react3.useRef)(null);
488
+ const originalXHROpen = (0, import_react3.useRef)(null);
489
+ const originalXHRSend = (0, import_react3.useRef)(null);
490
+ const generateId = (0, import_react3.useCallback)((prefix) => {
395
491
  return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;
396
492
  }, []);
397
- (0, import_react2.useEffect)(() => {
493
+ (0, import_react3.useEffect)(() => {
398
494
  if (!enabled) return;
399
495
  originalFetch.current = window.fetch;
400
496
  window.fetch = async function(input, init) {
@@ -455,7 +551,7 @@ var useNetworkInterceptor = ({
455
551
  }
456
552
  };
457
553
  }, [enabled, onLogAdd, onLogUpdate, generateId]);
458
- (0, import_react2.useEffect)(() => {
554
+ (0, import_react3.useEffect)(() => {
459
555
  if (!enabled) return;
460
556
  originalXHROpen.current = XMLHttpRequest.prototype.open;
461
557
  originalXHRSend.current = XMLHttpRequest.prototype.send;
@@ -637,17 +733,17 @@ var NetworkTerminal = ({
637
733
  height = "450px",
638
734
  zIndex = 9999
639
735
  }) => {
640
- const [logs, setLogs] = (0, import_react3.useState)([]);
641
- const [isVisible, setIsVisible] = (0, import_react3.useState)(defaultVisible);
642
- const [requestExpanded, setRequestExpanded] = (0, import_react3.useState)(true);
643
- const [responseExpanded, setResponseExpanded] = (0, import_react3.useState)(true);
644
- const addLog = (0, import_react3.useCallback)(
736
+ const [logs, setLogs] = (0, import_react4.useState)([]);
737
+ const [isVisible, setIsVisible] = (0, import_react4.useState)(defaultVisible);
738
+ const [requestExpanded, setRequestExpanded] = (0, import_react4.useState)(true);
739
+ const [responseExpanded, setResponseExpanded] = (0, import_react4.useState)(true);
740
+ const addLog = (0, import_react4.useCallback)(
645
741
  (log) => {
646
742
  setLogs((prev) => [...prev.slice(-(maxLogs - 1)), log]);
647
743
  },
648
744
  [maxLogs]
649
745
  );
650
- const updateLog = (0, import_react3.useCallback)((id, updates) => {
746
+ const updateLog = (0, import_react4.useCallback)((id, updates) => {
651
747
  setLogs(
652
748
  (prev) => prev.map((log) => log.id === id ? { ...log, ...updates } : log)
653
749
  );
@@ -657,7 +753,7 @@ var NetworkTerminal = ({
657
753
  onLogAdd: addLog,
658
754
  onLogUpdate: updateLog
659
755
  });
660
- (0, import_react3.useEffect)(() => {
756
+ (0, import_react4.useEffect)(() => {
661
757
  const handleKeyDown = (e) => {
662
758
  if (e.ctrlKey && e.shiftKey && e.key === "N") {
663
759
  e.preventDefault();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/index.ts","../src/components/NetworkTerminal.tsx","../src/components/Terminal.tsx","../src/components/TerminalHeader.tsx","../src/utils/formatters.ts","../src/utils/colors.ts","../src/components/LogEntry.tsx","../src/hooks/useNetworkInterceptor.ts","../src/vite-plugin.ts"],"sourcesContent":["export { NetworkTerminal } from './components/NetworkTerminal';\nexport { Terminal } from './components/Terminal';\nexport { TerminalHeader } from './components/TerminalHeader';\nexport { LogEntry } from './components/LogEntry';\nexport { useNetworkInterceptor } from './hooks/useNetworkInterceptor';\nexport { formatJson, truncate, formatTime } from './utils/formatters';\nexport { getStatusColor, getMethodColor } from './utils/colors';\nexport { networkTerminal } from './vite-plugin';\nexport type {\n NetworkLog,\n NetworkTerminalProps,\n TerminalProps,\n TerminalHeaderProps,\n LogEntryProps,\n UseNetworkInterceptorProps,\n} from './types';\nexport type { NetworkTerminalPluginOptions } from './vite-plugin';\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { NetworkLog, NetworkTerminalProps } from '../types';\nimport { Terminal } from './Terminal';\nimport { useNetworkInterceptor } from '../hooks/useNetworkInterceptor';\n\nconst styles = {\n floatingButton: {\n position: 'fixed' as const,\n bottom: '16px',\n right: '16px',\n zIndex: 9999,\n backgroundColor: '#1f2937',\n color: '#4ade80',\n padding: '8px 16px',\n borderRadius: '8px',\n fontFamily: 'monospace',\n fontSize: '14px',\n boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n border: '1px solid #374151',\n cursor: 'pointer',\n },\n container: {\n position: 'fixed' as const,\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 9999,\n backgroundColor: '#111827',\n borderTop: '2px solid #22c55e',\n boxShadow: '0 -10px 15px -3px rgba(0, 0, 0, 0.1)',\n },\n containerTop: {\n position: 'fixed' as const,\n top: 0,\n left: 0,\n right: 0,\n zIndex: 9999,\n backgroundColor: '#111827',\n borderBottom: '2px solid #22c55e',\n boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n },\n mainHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 16px',\n backgroundColor: '#1f2937',\n borderBottom: '1px solid #374151',\n },\n headerLeft: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n },\n title: {\n color: '#4ade80',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n },\n hint: {\n color: '#6b7280',\n fontFamily: 'monospace',\n fontSize: '12px',\n },\n headerRight: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n clearButton: {\n color: '#9ca3af',\n fontSize: '14px',\n fontFamily: 'monospace',\n padding: '4px 12px',\n borderRadius: '4px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n },\n closeButton: {\n color: '#9ca3af',\n fontSize: '18px',\n fontWeight: 'bold',\n padding: '0 8px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: '4px',\n },\n terminalsContainer: {\n display: 'flex',\n gap: '8px',\n padding: '8px',\n height: '450px',\n },\n terminalWrapper: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column' as const,\n },\n} as const;\n\nexport const NetworkTerminal: React.FC<NetworkTerminalProps> = ({\n maxLogs = 100,\n defaultVisible = false,\n position = 'bottom',\n height = '450px',\n zIndex = 9999,\n}) => {\n const [logs, setLogs] = useState<NetworkLog[]>([]);\n const [isVisible, setIsVisible] = useState(defaultVisible);\n const [requestExpanded, setRequestExpanded] = useState(true);\n const [responseExpanded, setResponseExpanded] = useState(true);\n\n const addLog = useCallback(\n (log: NetworkLog) => {\n setLogs((prev) => [...prev.slice(-(maxLogs - 1)), log]);\n },\n [maxLogs]\n );\n\n const updateLog = useCallback((id: string, updates: Partial<NetworkLog>) => {\n setLogs((prev) =>\n prev.map((log) => (log.id === id ? { ...log, ...updates } : log))\n );\n }, []);\n\n useNetworkInterceptor({\n enabled: isVisible,\n onLogAdd: addLog,\n onLogUpdate: updateLog,\n });\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.ctrlKey && e.shiftKey && e.key === 'N') {\n e.preventDefault();\n setIsVisible((prev) => !prev);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, []);\n\n const clearLogs = () => setLogs([]);\n\n if (!isVisible) {\n return (\n <button\n onClick={() => setIsVisible(true)}\n style={{\n ...styles.floatingButton,\n zIndex,\n }}\n title=\"Open Network Terminal (Ctrl+Shift+N)\"\n >\n {'>'}_ Network\n </button>\n );\n }\n\n const containerStyle =\n position === 'top'\n ? { ...styles.containerTop, zIndex }\n : { ...styles.container, zIndex };\n\n return (\n <div style={containerStyle}>\n <div style={styles.mainHeader}>\n <div style={styles.headerLeft}>\n <span style={styles.title}>{'>'}_ Network Terminal</span>\n <span style={styles.hint}>Press Ctrl+Shift+N to toggle</span>\n </div>\n <div style={styles.headerRight}>\n <button\n onClick={clearLogs}\n style={styles.clearButton}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n Clear All\n </button>\n <button\n onClick={() => setIsVisible(false)}\n style={styles.closeButton}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#f87171')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n {'\\u00D7'}\n </button>\n </div>\n </div>\n\n <div style={{ ...styles.terminalsContainer, height }}>\n <div style={styles.terminalWrapper}>\n <Terminal\n title=\"Requests\"\n logs={logs}\n type=\"request\"\n onClear={clearLogs}\n expanded={requestExpanded}\n onToggleExpand={() => setRequestExpanded(!requestExpanded)}\n />\n </div>\n <div style={styles.terminalWrapper}>\n <Terminal\n title=\"Responses\"\n logs={logs}\n type=\"response\"\n onClear={clearLogs}\n expanded={responseExpanded}\n onToggleExpand={() => setResponseExpanded(!responseExpanded)}\n />\n </div>\n </div>\n </div>\n );\n};\n","import React, { useRef, useState, useEffect } from 'react';\nimport { TerminalProps } from '../types';\nimport { TerminalHeader } from './TerminalHeader';\nimport { LogEntry } from './LogEntry';\n\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n backgroundColor: '#111827',\n borderRadius: '8px',\n border: '1px solid #374151',\n overflow: 'hidden',\n transition: 'all 0.2s',\n flex: 1,\n },\n collapsed: {\n height: '48px',\n flex: 'none' as const,\n },\n body: {\n flex: 1,\n overflow: 'auto',\n padding: '16px',\n fontFamily: 'monospace',\n fontSize: '14px',\n minHeight: '200px',\n maxHeight: '400px',\n },\n empty: {\n color: '#6b7280',\n fontStyle: 'italic',\n },\n} as const;\n\nexport const Terminal: React.FC<TerminalProps> = ({\n title,\n logs,\n type,\n onClear,\n expanded,\n onToggleExpand,\n}) => {\n const terminalRef = useRef<HTMLDivElement>(null);\n const [autoScroll, setAutoScroll] = useState(true);\n\n useEffect(() => {\n if (autoScroll && terminalRef.current) {\n terminalRef.current.scrollTop = terminalRef.current.scrollHeight;\n }\n }, [logs, autoScroll]);\n\n const handleScroll = () => {\n if (terminalRef.current) {\n const { scrollTop, scrollHeight, clientHeight } = terminalRef.current;\n setAutoScroll(scrollHeight - scrollTop - clientHeight < 50);\n }\n };\n\n return (\n <div\n style={{\n ...styles.container,\n ...(expanded ? {} : styles.collapsed),\n }}\n >\n <TerminalHeader\n title={title}\n count={logs.length}\n expanded={expanded}\n onClear={onClear}\n onToggleExpand={onToggleExpand}\n />\n\n {expanded && (\n <div ref={terminalRef} onScroll={handleScroll} style={styles.body}>\n {logs.length === 0 ? (\n <div style={styles.empty}>Waiting for network requests...</div>\n ) : (\n logs.map((log) => <LogEntry key={log.id} log={log} type={type} />)\n )}\n </div>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { TerminalHeaderProps } from '../types';\n\nconst styles = {\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 16px',\n backgroundColor: '#1f2937',\n borderBottom: '1px solid #374151',\n },\n left: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n trafficLights: {\n display: 'flex',\n gap: '6px',\n },\n dot: {\n width: '12px',\n height: '12px',\n borderRadius: '50%',\n },\n title: {\n color: '#d1d5db',\n fontFamily: 'monospace',\n fontSize: '14px',\n marginLeft: '8px',\n },\n count: {\n color: '#6b7280',\n fontFamily: 'monospace',\n fontSize: '12px',\n },\n right: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n button: {\n color: '#9ca3af',\n fontSize: '12px',\n fontFamily: 'monospace',\n padding: '4px 8px',\n borderRadius: '4px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n },\n} as const;\n\nexport const TerminalHeader: React.FC<TerminalHeaderProps> = ({\n title,\n count,\n expanded,\n onClear,\n onToggleExpand,\n}) => {\n return (\n <div style={styles.header}>\n <div style={styles.left}>\n <div style={styles.trafficLights}>\n <div style={{ ...styles.dot, backgroundColor: '#ef4444' }} />\n <div style={{ ...styles.dot, backgroundColor: '#eab308' }} />\n <div style={{ ...styles.dot, backgroundColor: '#22c55e' }} />\n </div>\n <span style={styles.title}>{title}</span>\n <span style={styles.count}>({count} entries)</span>\n </div>\n <div style={styles.right}>\n <button\n onClick={onClear}\n style={styles.button}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n Clear\n </button>\n <button\n onClick={onToggleExpand}\n style={styles.button}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n {expanded ? '\\u25BC' : '\\u25B2'}\n </button>\n </div>\n </div>\n );\n};\n","export const formatJson = (data: unknown): string => {\n if (!data) return '';\n try {\n if (typeof data === 'string') {\n const parsed = JSON.parse(data);\n return JSON.stringify(parsed, null, 2);\n }\n return JSON.stringify(data, null, 2);\n } catch {\n return String(data);\n }\n};\n\nexport const truncate = (str: string, maxLength: number): string => {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength) + '...';\n};\n\nexport const formatTime = (date: Date): string => {\n return date.toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n};\n","export const getStatusColor = (status?: number): string => {\n if (!status) return '#9ca3af'; // gray-400\n if (status >= 200 && status < 300) return '#4ade80'; // green-400\n if (status >= 300 && status < 400) return '#facc15'; // yellow-400\n if (status >= 400 && status < 500) return '#fb923c'; // orange-400\n return '#f87171'; // red-400\n};\n\nexport const getMethodColor = (method: string): string => {\n const colors: Record<string, string> = {\n GET: '#22d3ee', // cyan-400\n POST: '#4ade80', // green-400\n PUT: '#facc15', // yellow-400\n PATCH: '#fb923c', // orange-400\n DELETE: '#f87171', // red-400\n };\n return colors[method.toUpperCase()] || '#9ca3af';\n};\n","import React from 'react';\nimport { LogEntryProps } from '../types';\nimport { formatJson, formatTime } from '../utils/formatters';\nimport { getStatusColor, getMethodColor } from '../utils/colors';\n\nconst styles = {\n container: {\n marginBottom: '16px',\n borderBottom: '1px solid #1f2937',\n paddingBottom: '16px',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '4px',\n flexWrap: 'wrap' as const,\n },\n timestamp: {\n color: '#6b7280',\n fontSize: '12px',\n fontFamily: 'monospace',\n },\n method: {\n fontWeight: 'bold',\n fontFamily: 'monospace',\n },\n status: {\n fontWeight: 'bold',\n fontFamily: 'monospace',\n },\n duration: {\n color: '#6b7280',\n fontSize: '12px',\n fontFamily: 'monospace',\n },\n url: {\n color: '#60a5fa',\n wordBreak: 'break-all' as const,\n marginBottom: '8px',\n fontFamily: 'monospace',\n fontSize: '13px',\n },\n bodyContainer: {\n marginTop: '8px',\n },\n bodyLabel: {\n color: '#a78bfa',\n fontSize: '12px',\n marginBottom: '4px',\n fontFamily: 'monospace',\n },\n pre: {\n backgroundColor: '#1f2937',\n padding: '8px',\n borderRadius: '4px',\n color: '#86efac',\n overflowX: 'auto' as const,\n fontSize: '12px',\n whiteSpace: 'pre-wrap' as const,\n fontFamily: 'monospace',\n maxHeight: '192px',\n overflowY: 'auto' as const,\n margin: 0,\n },\n errorPre: {\n backgroundColor: '#1f2937',\n padding: '8px',\n borderRadius: '4px',\n color: '#fca5a5',\n overflowX: 'auto' as const,\n fontSize: '12px',\n whiteSpace: 'pre-wrap' as const,\n fontFamily: 'monospace',\n margin: 0,\n },\n} as const;\n\nexport const LogEntry: React.FC<LogEntryProps> = ({ log, type }) => {\n return (\n <div style={styles.container}>\n <div style={styles.header}>\n <span style={styles.timestamp}>[{formatTime(log.timestamp)}]</span>\n <span style={{ ...styles.method, color: getMethodColor(log.method) }}>\n {log.method}\n </span>\n {type === 'response' && log.status && (\n <span style={{ ...styles.status, color: getStatusColor(log.status) }}>\n {log.status} {log.statusText}\n </span>\n )}\n {log.duration !== undefined && type === 'response' && (\n <span style={styles.duration}>({log.duration}ms)</span>\n )}\n </div>\n\n <div style={styles.url}>{log.url}</div>\n\n {type === 'request' ? (\n log.requestBody ? (\n <div style={styles.bodyContainer}>\n <div style={styles.bodyLabel}>{'\\u25B8'} Payload:</div>\n <pre style={styles.pre}>{formatJson(log.requestBody)}</pre>\n </div>\n ) : null\n ) : log.error ? (\n <div style={styles.bodyContainer}>\n <div style={{ ...styles.bodyLabel, color: '#f87171' }}>\n {'\\u25B8'} Error:\n </div>\n <pre style={styles.errorPre}>{log.error}</pre>\n </div>\n ) : log.responseBody ? (\n <div style={styles.bodyContainer}>\n <div style={styles.bodyLabel}>{'\\u25B8'} Response:</div>\n <pre style={styles.pre}>{formatJson(log.responseBody)}</pre>\n </div>\n ) : null}\n </div>\n );\n};\n","import { useEffect, useRef, useCallback } from 'react';\nimport { NetworkLog, UseNetworkInterceptorProps } from '../types';\n\nexport const useNetworkInterceptor = ({\n enabled,\n onLogAdd,\n onLogUpdate,\n}: UseNetworkInterceptorProps) => {\n const originalFetch = useRef<typeof fetch | null>(null);\n const originalXHROpen = useRef<typeof XMLHttpRequest.prototype.open | null>(null);\n const originalXHRSend = useRef<typeof XMLHttpRequest.prototype.send | null>(null);\n\n const generateId = useCallback((prefix: string) => {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }, []);\n\n // Intercept Fetch\n useEffect(() => {\n if (!enabled) return;\n\n originalFetch.current = window.fetch;\n\n window.fetch = async function (input, init) {\n const id = generateId('fetch');\n const startTime = performance.now();\n\n const url =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n const method = init?.method || 'GET';\n\n let requestBody: unknown = null;\n if (init?.body) {\n try {\n requestBody =\n typeof init.body === 'string' ? JSON.parse(init.body) : init.body;\n } catch {\n requestBody = init.body;\n }\n }\n\n onLogAdd({\n id,\n timestamp: new Date(),\n method: method.toUpperCase(),\n url,\n requestBody,\n type: 'fetch',\n });\n\n try {\n const response = await originalFetch.current!(input, init);\n const duration = Math.round(performance.now() - startTime);\n\n const clonedResponse = response.clone();\n let responseBody: unknown = null;\n\n try {\n responseBody = await clonedResponse.json();\n } catch {\n try {\n responseBody = await clonedResponse.text();\n } catch {\n responseBody = '[Could not read response body]';\n }\n }\n\n onLogUpdate(id, {\n status: response.status,\n statusText: response.statusText,\n responseBody,\n duration,\n });\n\n return response;\n } catch (error: unknown) {\n const duration = Math.round(performance.now() - startTime);\n const errorMessage =\n error instanceof Error ? error.message : 'Network Error';\n onLogUpdate(id, {\n error: errorMessage,\n duration,\n });\n throw error;\n }\n };\n\n return () => {\n if (originalFetch.current) {\n window.fetch = originalFetch.current;\n }\n };\n }, [enabled, onLogAdd, onLogUpdate, generateId]);\n\n // Intercept XHR\n useEffect(() => {\n if (!enabled) return;\n\n originalXHROpen.current = XMLHttpRequest.prototype.open;\n originalXHRSend.current = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL\n ) {\n (this as XMLHttpRequest & { _networkTerminal: NetworkLog & { startTime: number } })._networkTerminal = {\n id: generateId('xhr'),\n method: method.toUpperCase(),\n url: url.toString(),\n startTime: 0,\n timestamp: new Date(),\n type: 'xhr',\n };\n return originalXHROpen.current!.apply(\n this,\n arguments as unknown as Parameters<typeof XMLHttpRequest.prototype.open>\n );\n };\n\n XMLHttpRequest.prototype.send = function (body?: Document | XMLHttpRequestBodyInit | null) {\n const meta = (this as XMLHttpRequest & { _networkTerminal?: NetworkLog & { startTime: number } })._networkTerminal;\n\n if (meta) {\n meta.startTime = performance.now();\n\n let requestBody: unknown = null;\n if (body) {\n try {\n requestBody = typeof body === 'string' ? JSON.parse(body) : body;\n } catch {\n requestBody = body;\n }\n }\n\n onLogAdd({\n id: meta.id,\n timestamp: new Date(),\n method: meta.method,\n url: meta.url,\n requestBody,\n type: 'xhr',\n });\n\n this.addEventListener('load', function () {\n const duration = Math.round(performance.now() - meta.startTime);\n\n let responseBody: unknown = null;\n try {\n responseBody = JSON.parse(this.responseText);\n } catch {\n responseBody = this.responseText;\n }\n\n onLogUpdate(meta.id, {\n status: this.status,\n statusText: this.statusText,\n responseBody,\n duration,\n });\n });\n\n this.addEventListener('error', function () {\n const duration = Math.round(performance.now() - meta.startTime);\n onLogUpdate(meta.id, {\n error: 'Network Error',\n duration,\n });\n });\n }\n\n return originalXHRSend.current!.apply(\n this,\n arguments as unknown as Parameters<typeof XMLHttpRequest.prototype.send>\n );\n };\n\n return () => {\n if (originalXHROpen.current) {\n XMLHttpRequest.prototype.open = originalXHROpen.current;\n }\n if (originalXHRSend.current) {\n XMLHttpRequest.prototype.send = originalXHRSend.current;\n }\n };\n }, [enabled, onLogAdd, onLogUpdate, generateId]);\n};\n","import type { Plugin, ViteDevServer } from 'vite';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport { exec } from 'child_process';\n\nexport interface NetworkTerminalPluginOptions {\n /** Port for the dashboard (default: 4001) */\n port?: number;\n /** Auto-open dashboard in browser (default: true) */\n open?: boolean;\n}\n\n// Store network logs\nconst networkLogs: any[] = [];\nconst sseClients = new Set<ServerResponse>();\n\nfunction broadcastLog(log: any) {\n const data = JSON.stringify(log);\n sseClients.forEach(client => {\n client.write(`data: ${data}\\n\\n`);\n });\n}\n\nfunction getDashboardHTML(_port: number): string {\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Network Terminal</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n background: #0a0e17;\n color: #e2e8f0;\n height: 100vh;\n overflow: hidden;\n }\n .header {\n background: #0f172a;\n padding: 12px 24px;\n border-bottom: 2px solid #4ade80;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .title { color: #4ade80; font-size: 18px; font-weight: bold; }\n .subtitle { color: #64748b; font-size: 12px; margin-top: 4px; }\n .controls { display: flex; gap: 12px; align-items: center; }\n .btn {\n background: #1e293b;\n border: 1px solid #334155;\n color: #94a3b8;\n padding: 8px 16px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n font-family: inherit;\n }\n .btn:hover { background: #334155; color: #e2e8f0; }\n .container { display: flex; height: calc(100vh - 80px); }\n .panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border-right: 1px solid #1e293b;\n }\n .panel:last-child { border-right: none; }\n .panel-header {\n background: #0f172a;\n padding: 12px 16px;\n border-bottom: 1px solid #1e293b;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .panel-title { font-weight: bold; font-size: 14px; }\n .panel-title.request { color: #3b82f6; }\n .panel-title.response { color: #22c55e; }\n .panel-count {\n background: #1e293b;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n color: #64748b;\n }\n .logs { flex: 1; overflow-y: auto; padding: 8px; }\n .log-entry {\n background: #0f172a;\n border: 1px solid #1e293b;\n border-radius: 8px;\n margin-bottom: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: border-color 0.2s;\n }\n .log-entry:hover { border-color: #334155; }\n .log-entry.selected { border-color: #4ade80; }\n .log-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: #1e293b;\n }\n .method {\n font-weight: bold;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 4px;\n }\n .method.GET { background: #166534; color: #4ade80; }\n .method.POST { background: #1e40af; color: #60a5fa; }\n .method.PUT { background: #a16207; color: #fcd34d; }\n .method.DELETE { background: #991b1b; color: #fca5a5; }\n .method.PATCH { background: #7c3aed; color: #c4b5fd; }\n .status { font-size: 11px; padding: 3px 8px; border-radius: 4px; }\n .status.success { background: #166534; color: #4ade80; }\n .status.error { background: #991b1b; color: #fca5a5; }\n .status.pending { background: #374151; color: #9ca3af; }\n .url {\n flex: 1;\n font-size: 12px;\n color: #94a3b8;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .duration { font-size: 11px; color: #64748b; }\n .timestamp { font-size: 10px; color: #475569; }\n .log-body { padding: 12px; font-size: 11px; max-height: 300px; overflow: auto; }\n .log-body pre {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-all;\n color: #cbd5e1;\n line-height: 1.5;\n }\n .log-body.empty { color: #475569; font-style: italic; }\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #475569;\n text-align: center;\n padding: 20px;\n }\n .empty-state svg { width: 48px; height: 48px; margin-bottom: 16px; opacity: 0.5; }\n .status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #22c55e;\n animation: pulse 2s infinite;\n }\n @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }\n .status-dot.disconnected { background: #ef4444; animation: none; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div>\n <div class=\"title\">>_ Network Terminal</div>\n <div class=\"subtitle\">Vite Plugin - Monitoring fetch/XHR requests</div>\n </div>\n <div class=\"controls\">\n <div class=\"status-dot\" id=\"statusDot\"></div>\n <button class=\"btn\" onclick=\"clearLogs()\">Clear All</button>\n </div>\n </div>\n\n <div class=\"container\">\n <div class=\"panel\">\n <div class=\"panel-header\">\n <span class=\"panel-title request\">⬆ REQUESTS</span>\n <span class=\"panel-count\" id=\"requestCount\">0</span>\n </div>\n <div class=\"logs\" id=\"requestLogs\">\n <div class=\"empty-state\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 19V5M5 12l7-7 7 7\"/>\n </svg>\n <div>Waiting for requests...</div>\n <div style=\"margin-top: 8px; font-size: 11px;\">Make fetch/XHR requests in your app</div>\n </div>\n </div>\n </div>\n\n <div class=\"panel\">\n <div class=\"panel-header\">\n <span class=\"panel-title response\">⬇ RESPONSES</span>\n <span class=\"panel-count\" id=\"responseCount\">0</span>\n </div>\n <div class=\"logs\" id=\"responseLogs\">\n <div class=\"empty-state\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 5v14M5 12l7 7 7-7\"/>\n </svg>\n <div>Waiting for responses...</div>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n const logs = new Map();\n let selectedId = null;\n\n function formatJson(data) {\n if (!data) return null;\n if (typeof data === 'string') {\n try { data = JSON.parse(data); }\n catch (e) { return escapeHtml(data.substring(0, 2000)); }\n }\n return escapeHtml(JSON.stringify(data, null, 2));\n }\n\n function escapeHtml(str) {\n if (typeof str !== 'string') str = String(str);\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n function formatTime(timestamp) {\n const date = new Date(timestamp);\n return date.toLocaleTimeString('en-US', { hour12: false }) + '.' +\n String(date.getMilliseconds()).padStart(3, '0');\n }\n\n function getLogsArray() {\n return Array.from(logs.values()).sort((a, b) =>\n new Date(b.timestamp) - new Date(a.timestamp)\n );\n }\n\n function renderLogs() {\n const logsArray = getLogsArray();\n const requestContainer = document.getElementById('requestLogs');\n const responseContainer = document.getElementById('responseLogs');\n\n document.getElementById('requestCount').textContent = logsArray.length;\n document.getElementById('responseCount').textContent = logsArray.filter(l => l.status).length;\n\n if (logsArray.length === 0) {\n requestContainer.innerHTML = '<div class=\"empty-state\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 19V5M5 12l7-7 7 7\"/></svg><div>Waiting for requests...</div></div>';\n responseContainer.innerHTML = '<div class=\"empty-state\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 5v14M5 12l7 7 7-7\"/></svg><div>Waiting for responses...</div></div>';\n return;\n }\n\n requestContainer.innerHTML = logsArray.map(log => {\n const isSelected = selectedId === log.id;\n const bodyContent = formatJson(log.requestBody);\n return '<div class=\"log-entry '+(isSelected ? 'selected' : '')+'\" onclick=\"selectLog(\\\\''+log.id+'\\\\')\"><div class=\"log-header\"><span class=\"method '+log.method+'\">'+log.method+'</span><span class=\"url\" title=\"'+escapeHtml(log.url)+'\">'+log.url+'</span><span class=\"timestamp\">'+formatTime(log.timestamp)+'</span></div>'+(isSelected ? '<div class=\"log-body '+(bodyContent ? '' : 'empty')+'\">'+(bodyContent ? '<pre>'+bodyContent+'</pre>' : 'No request body')+'</div>' : '')+'</div>';\n }).join('');\n\n responseContainer.innerHTML = logsArray.map(log => {\n const isSelected = selectedId === log.id;\n const statusClass = !log.status ? 'pending' : log.status < 400 ? 'success' : 'error';\n const bodyContent = formatJson(log.responseBody);\n return '<div class=\"log-entry '+(isSelected ? 'selected' : '')+'\" onclick=\"selectLog(\\\\''+log.id+'\\\\')\"><div class=\"log-header\"><span class=\"status '+statusClass+'\">'+(log.status || '...')+'</span><span class=\"url\" title=\"'+escapeHtml(log.url)+'\">'+log.url+'</span><span class=\"duration\">'+(log.duration ? log.duration + 'ms' : '')+'</span></div>'+(isSelected ? '<div class=\"log-body '+(bodyContent ? '' : 'empty')+'\">'+(bodyContent ? '<pre>'+bodyContent+'</pre>' : (log.status ? 'No response body' : 'Pending...'))+'</div>' : '')+'</div>';\n }).join('');\n }\n\n function selectLog(id) {\n selectedId = selectedId === id ? null : id;\n renderLogs();\n }\n\n function clearLogs() {\n logs.clear();\n selectedId = null;\n renderLogs();\n fetch('/clear', { method: 'POST' });\n }\n\n function addLog(log) {\n logs.set(log.id, log);\n if (logs.size > 100) {\n const oldest = getLogsArray().pop();\n if (oldest) logs.delete(oldest.id);\n }\n renderLogs();\n }\n\n function connect() {\n const evtSource = new EventSource('/events');\n evtSource.onopen = () => document.getElementById('statusDot').classList.remove('disconnected');\n evtSource.onmessage = (event) => addLog(JSON.parse(event.data));\n evtSource.onerror = () => {\n document.getElementById('statusDot').classList.add('disconnected');\n evtSource.close();\n setTimeout(connect, 2000);\n };\n }\n\n connect();\n renderLogs();\n </script>\n</body>\n</html>\n`;\n}\n\nfunction getMonitorScript(port: number): string {\n return `\n(function() {\n if (window.__networkTerminalActive) return;\n window.__networkTerminalActive = true;\n\n var DASHBOARD_URL = 'http://localhost:${port}';\n\n function sendLog(log) {\n var xhr = new XMLHttpRequest();\n xhr.open('POST', DASHBOARD_URL + '/log', true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.send(JSON.stringify(log));\n }\n\n function tryParse(data) {\n if (!data) return null;\n if (typeof data === 'object') return data;\n try { return JSON.parse(data); } catch (e) { return data; }\n }\n\n var originalFetch = window.fetch;\n window.fetch = function() {\n var args = arguments;\n var startTime = Date.now();\n var input = args[0];\n var options = args[1] || {};\n var url = typeof input === 'string' ? input : (input.url || input.toString());\n var method = (options.method || 'GET').toUpperCase();\n\n if (url.includes('localhost:${port}')) {\n return originalFetch.apply(this, args);\n }\n\n var log = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n method: method,\n url: url,\n timestamp: new Date().toISOString(),\n requestBody: options.body ? tryParse(options.body) : null,\n status: null,\n responseBody: null,\n duration: null,\n };\n\n sendLog(log);\n\n return originalFetch.apply(this, args).then(function(response) {\n log.status = response.status;\n log.duration = Date.now() - startTime;\n var cloned = response.clone();\n cloned.text().then(function(text) {\n log.responseBody = tryParse(text);\n sendLog(log);\n }).catch(function() { sendLog(log); });\n return response;\n }).catch(function(error) {\n log.status = 0;\n log.duration = Date.now() - startTime;\n log.error = error.message;\n sendLog(log);\n throw error;\n });\n };\n\n var OriginalXHR = window.XMLHttpRequest;\n window.XMLHttpRequest = function() {\n var xhr = new OriginalXHR();\n var method, url, requestBody, startTime;\n\n var originalOpen = xhr.open;\n xhr.open = function(m, u) {\n method = m;\n url = u;\n return originalOpen.apply(this, arguments);\n };\n\n var originalSend = xhr.send;\n xhr.send = function(body) {\n if (url && url.includes('localhost:${port}')) {\n return originalSend.apply(this, arguments);\n }\n\n startTime = Date.now();\n requestBody = body;\n\n var log = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n method: (method || 'GET').toUpperCase(),\n url: url,\n timestamp: new Date().toISOString(),\n requestBody: tryParse(requestBody),\n status: null,\n responseBody: null,\n duration: null,\n };\n\n sendLog(log);\n\n xhr.addEventListener('loadend', function() {\n log.status = xhr.status;\n log.duration = Date.now() - startTime;\n log.responseBody = tryParse(xhr.responseText);\n sendLog(log);\n });\n\n return originalSend.apply(this, arguments);\n };\n\n return xhr;\n };\n\n console.log('[Network Terminal] ✓ Active - Dashboard: http://localhost:${port}');\n})();\n`;\n}\n\nexport function networkTerminal(options: NetworkTerminalPluginOptions = {}): Plugin {\n const { port = 4001, open = true } = options;\n let dashboardServer: ReturnType<typeof createServer> | null = null;\n\n return {\n name: 'vite-plugin-network-terminal',\n apply: 'serve',\n\n configureServer(_server: ViteDevServer) {\n // Start dashboard server\n dashboardServer = createServer((req: IncomingMessage, res: ServerResponse) => {\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.url === '/events') {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n });\n sseClients.add(res);\n networkLogs.forEach(log => {\n res.write(`data: ${JSON.stringify(log)}\\n\\n`);\n });\n req.on('close', () => sseClients.delete(res));\n return;\n }\n\n if (req.url === '/log' && req.method === 'POST') {\n let body = '';\n req.on('data', (chunk: Buffer) => body += chunk);\n req.on('end', () => {\n try {\n const log = JSON.parse(body);\n const existingIndex = networkLogs.findIndex(l => l.id === log.id);\n if (existingIndex >= 0) {\n networkLogs[existingIndex] = log;\n } else {\n networkLogs.unshift(log);\n if (networkLogs.length > 100) networkLogs.pop();\n }\n broadcastLog(log);\n } catch (e) {}\n res.writeHead(200);\n res.end('OK');\n });\n return;\n }\n\n if (req.url === '/clear' && req.method === 'POST') {\n networkLogs.length = 0;\n res.writeHead(200);\n res.end('OK');\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(getDashboardHTML(port));\n });\n\n dashboardServer.listen(port, () => {\n console.log(`\\n \\x1b[32m>_ Network Terminal\\x1b[0m`);\n console.log(` Dashboard: \\x1b[36mhttp://localhost:${port}\\x1b[0m\\n`);\n\n if (open) {\n const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\n exec(`${openCmd} http://localhost:${port}`);\n }\n });\n\n dashboardServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`\\n \\x1b[33m[Network Terminal]\\x1b[0m Port ${port} in use, dashboard disabled\\n`);\n }\n });\n },\n\n transformIndexHtml(html: string) {\n const script = `<script>${getMonitorScript(port)}</script>`;\n if (html.includes('</head>')) {\n return html.replace('</head>', script + '</head>');\n }\n return script + html;\n },\n\n buildEnd() {\n if (dashboardServer) {\n dashboardServer.close();\n }\n },\n };\n}\n\nexport default networkTerminal;\n"],"mappings":"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AA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAwRT;AAEA,SAAS,iBAAiB,MAAsB;AAC9C,SAAO;AAAA;AAAA;AAAA;AAAA;AAAA,0CAKiC,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,kCAwBZ,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,2CAiDK,IAAI;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,gFAiC4B,IAAI;AAAA;AAAA;AAG/E;AAEO,SAAS,gBAAgB,UAAwC,CAAC,GAAW;AAClF,QAAM,EAAE,OAAO,MAAM,OAAO,KAAK,IAAI;AACrC,MAAI,kBAA0D;AAE9D,SAAO;AAAA,IACL,MAAM;AAAA,IACN,OAAO;AAAA,IAEP,gBAAgB,SAAwB;AAEtC,4BAAkB,0BAAa,CAAC,KAAsB,QAAwB;AAC5E,YAAI,UAAU,+BAA+B,GAAG;AAChD,YAAI,UAAU,gCAAgC,oBAAoB;AAClE,YAAI,UAAU,gCAAgC,cAAc;AAE5D,YAAI,IAAI,WAAW,WAAW;AAC5B,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI;AACR;AAAA,QACF;AAEA,YAAI,IAAI,QAAQ,WAAW;AACzB,cAAI,UAAU,KAAK;AAAA,YACjB,gBAAgB;AAAA,YAChB,iBAAiB;AAAA,YACjB,cAAc;AAAA,UAChB,CAAC;AACD,qBAAW,IAAI,GAAG;AAClB,sBAAY,QAAQ,SAAO;AACzB,gBAAI,MAAM,SAAS,KAAK,UAAU,GAAG,CAAC;AAAA;AAAA,CAAM;AAAA,UAC9C,CAAC;AACD,cAAI,GAAG,SAAS,MAAM,WAAW,OAAO,GAAG,CAAC;AAC5C;AAAA,QACF;AAEA,YAAI,IAAI,QAAQ,UAAU,IAAI,WAAW,QAAQ;AAC/C,cAAI,OAAO;AACX,cAAI,GAAG,QAAQ,CAAC,UAAkB,QAAQ,KAAK;AAC/C,cAAI,GAAG,OAAO,MAAM;AAClB,gBAAI;AACF,oBAAM,MAAM,KAAK,MAAM,IAAI;AAC3B,oBAAM,gBAAgB,YAAY,UAAU,OAAK,EAAE,OAAO,IAAI,EAAE;AAChE,kBAAI,iBAAiB,GAAG;AACtB,4BAAY,aAAa,IAAI;AAAA,cAC/B,OAAO;AACL,4BAAY,QAAQ,GAAG;AACvB,oBAAI,YAAY,SAAS,IAAK,aAAY,IAAI;AAAA,cAChD;AACA,2BAAa,GAAG;AAAA,YAClB,SAAS,GAAG;AAAA,YAAC;AACb,gBAAI,UAAU,GAAG;AACjB,gBAAI,IAAI,IAAI;AAAA,UACd,CAAC;AACD;AAAA,QACF;AAEA,YAAI,IAAI,QAAQ,YAAY,IAAI,WAAW,QAAQ;AACjD,sBAAY,SAAS;AACrB,cAAI,UAAU,GAAG;AACjB,cAAI,IAAI,IAAI;AACZ;AAAA,QACF;AAEA,YAAI,UAAU,KAAK,EAAE,gBAAgB,YAAY,CAAC;AAClD,YAAI,IAAI,iBAAiB,IAAI,CAAC;AAAA,MAChC,CAAC;AAED,sBAAgB,OAAO,MAAM,MAAM;AACjC,gBAAQ,IAAI;AAAA,qCAAwC;AACpD,gBAAQ,IAAI,yCAAyC,IAAI;AAAA,CAAW;AAEpE,YAAI,MAAM;AACR,gBAAM,UAAU,QAAQ,aAAa,WAAW,SAAS,QAAQ,aAAa,UAAU,UAAU;AAClG,yCAAK,GAAG,OAAO,qBAAqB,IAAI,EAAE;AAAA,QAC5C;AAAA,MACF,CAAC;AAED,sBAAgB,GAAG,SAAS,CAAC,QAA+B;AAC1D,YAAI,IAAI,SAAS,cAAc;AAC7B,kBAAQ,IAAI;AAAA,2CAA8C,IAAI;AAAA,CAA+B;AAAA,QAC/F;AAAA,MACF,CAAC;AAAA,IACH;AAAA,IAEA,mBAAmB,MAAc;AAC/B,YAAM,SAAS,WAAW,iBAAiB,IAAI,CAAC;AAChD,UAAI,KAAK,SAAS,SAAS,GAAG;AAC5B,eAAO,KAAK,QAAQ,WAAW,SAAS,SAAS;AAAA,MACnD;AACA,aAAO,SAAS;AAAA,IAClB;AAAA,IAEA,WAAW;AACT,UAAI,iBAAiB;AACnB,wBAAgB,MAAM;AAAA,MACxB;AAAA,IACF;AAAA,EACF;AACF;","names":["import_react","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_jsx_runtime","styles"]}
1
+ {"version":3,"sources":["../src/index.ts","../src/components/NetworkTerminal.tsx","../src/components/Terminal.tsx","../src/components/TerminalHeader.tsx","../src/components/LogEntry.tsx","../src/utils/formatters.ts","../src/utils/colors.ts","../src/hooks/useNetworkInterceptor.ts","../src/vite-plugin.ts"],"sourcesContent":["export { NetworkTerminal } from './components/NetworkTerminal';\nexport { Terminal } from './components/Terminal';\nexport { TerminalHeader } from './components/TerminalHeader';\nexport { LogEntry } from './components/LogEntry';\nexport { useNetworkInterceptor } from './hooks/useNetworkInterceptor';\nexport { formatJson, truncate, formatTime } from './utils/formatters';\nexport { getStatusColor, getMethodColor } from './utils/colors';\nexport { networkTerminal } from './vite-plugin';\nexport type {\n NetworkLog,\n NetworkTerminalProps,\n TerminalProps,\n TerminalHeaderProps,\n LogEntryProps,\n UseNetworkInterceptorProps,\n} from './types';\nexport type { NetworkTerminalPluginOptions } from './vite-plugin';\n","import React, { useState, useCallback, useEffect } from 'react';\nimport { NetworkLog, NetworkTerminalProps } from '../types';\nimport { Terminal } from './Terminal';\nimport { useNetworkInterceptor } from '../hooks/useNetworkInterceptor';\n\nconst styles = {\n floatingButton: {\n position: 'fixed' as const,\n bottom: '16px',\n right: '16px',\n zIndex: 9999,\n backgroundColor: '#1f2937',\n color: '#4ade80',\n padding: '8px 16px',\n borderRadius: '8px',\n fontFamily: 'monospace',\n fontSize: '14px',\n boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n border: '1px solid #374151',\n cursor: 'pointer',\n },\n container: {\n position: 'fixed' as const,\n bottom: 0,\n left: 0,\n right: 0,\n zIndex: 9999,\n backgroundColor: '#111827',\n borderTop: '2px solid #22c55e',\n boxShadow: '0 -10px 15px -3px rgba(0, 0, 0, 0.1)',\n },\n containerTop: {\n position: 'fixed' as const,\n top: 0,\n left: 0,\n right: 0,\n zIndex: 9999,\n backgroundColor: '#111827',\n borderBottom: '2px solid #22c55e',\n boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)',\n },\n mainHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 16px',\n backgroundColor: '#1f2937',\n borderBottom: '1px solid #374151',\n },\n headerLeft: {\n display: 'flex',\n alignItems: 'center',\n gap: '12px',\n },\n title: {\n color: '#4ade80',\n fontFamily: 'monospace',\n fontWeight: 'bold',\n },\n hint: {\n color: '#6b7280',\n fontFamily: 'monospace',\n fontSize: '12px',\n },\n headerRight: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n clearButton: {\n color: '#9ca3af',\n fontSize: '14px',\n fontFamily: 'monospace',\n padding: '4px 12px',\n borderRadius: '4px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n },\n closeButton: {\n color: '#9ca3af',\n fontSize: '18px',\n fontWeight: 'bold',\n padding: '0 8px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n borderRadius: '4px',\n },\n terminalsContainer: {\n display: 'flex',\n gap: '8px',\n padding: '8px',\n height: '450px',\n },\n terminalWrapper: {\n flex: 1,\n display: 'flex',\n flexDirection: 'column' as const,\n },\n} as const;\n\nexport const NetworkTerminal: React.FC<NetworkTerminalProps> = ({\n maxLogs = 100,\n defaultVisible = false,\n position = 'bottom',\n height = '450px',\n zIndex = 9999,\n}) => {\n const [logs, setLogs] = useState<NetworkLog[]>([]);\n const [isVisible, setIsVisible] = useState(defaultVisible);\n const [requestExpanded, setRequestExpanded] = useState(true);\n const [responseExpanded, setResponseExpanded] = useState(true);\n\n const addLog = useCallback(\n (log: NetworkLog) => {\n setLogs((prev) => [...prev.slice(-(maxLogs - 1)), log]);\n },\n [maxLogs]\n );\n\n const updateLog = useCallback((id: string, updates: Partial<NetworkLog>) => {\n setLogs((prev) =>\n prev.map((log) => (log.id === id ? { ...log, ...updates } : log))\n );\n }, []);\n\n useNetworkInterceptor({\n enabled: isVisible,\n onLogAdd: addLog,\n onLogUpdate: updateLog,\n });\n\n useEffect(() => {\n const handleKeyDown = (e: KeyboardEvent) => {\n if (e.ctrlKey && e.shiftKey && e.key === 'N') {\n e.preventDefault();\n setIsVisible((prev) => !prev);\n }\n };\n\n window.addEventListener('keydown', handleKeyDown);\n return () => window.removeEventListener('keydown', handleKeyDown);\n }, []);\n\n const clearLogs = () => setLogs([]);\n\n if (!isVisible) {\n return (\n <button\n onClick={() => setIsVisible(true)}\n style={{\n ...styles.floatingButton,\n zIndex,\n }}\n title=\"Open Network Terminal (Ctrl+Shift+N)\"\n >\n {'>'}_ Network\n </button>\n );\n }\n\n const containerStyle =\n position === 'top'\n ? { ...styles.containerTop, zIndex }\n : { ...styles.container, zIndex };\n\n return (\n <div style={containerStyle}>\n <div style={styles.mainHeader}>\n <div style={styles.headerLeft}>\n <span style={styles.title}>{'>'}_ Network Terminal</span>\n <span style={styles.hint}>Press Ctrl+Shift+N to toggle</span>\n </div>\n <div style={styles.headerRight}>\n <button\n onClick={clearLogs}\n style={styles.clearButton}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n Clear All\n </button>\n <button\n onClick={() => setIsVisible(false)}\n style={styles.closeButton}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#f87171')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n {'\\u00D7'}\n </button>\n </div>\n </div>\n\n <div style={{ ...styles.terminalsContainer, height }}>\n <div style={styles.terminalWrapper}>\n <Terminal\n title=\"Requests\"\n logs={logs}\n type=\"request\"\n onClear={clearLogs}\n expanded={requestExpanded}\n onToggleExpand={() => setRequestExpanded(!requestExpanded)}\n />\n </div>\n <div style={styles.terminalWrapper}>\n <Terminal\n title=\"Responses\"\n logs={logs}\n type=\"response\"\n onClear={clearLogs}\n expanded={responseExpanded}\n onToggleExpand={() => setResponseExpanded(!responseExpanded)}\n />\n </div>\n </div>\n </div>\n );\n};\n","import React, { useRef, useState, useEffect } from 'react';\nimport { TerminalProps } from '../types';\nimport { TerminalHeader } from './TerminalHeader';\nimport { LogEntry } from './LogEntry';\n\nconst styles = {\n container: {\n display: 'flex',\n flexDirection: 'column' as const,\n backgroundColor: '#111827',\n borderRadius: '8px',\n border: '1px solid #374151',\n overflow: 'hidden',\n transition: 'all 0.2s',\n flex: 1,\n },\n collapsed: {\n height: '48px',\n flex: 'none' as const,\n },\n body: {\n flex: 1,\n overflow: 'auto',\n padding: '16px',\n fontFamily: 'monospace',\n fontSize: '14px',\n minHeight: '200px',\n maxHeight: '400px',\n },\n empty: {\n color: '#6b7280',\n fontStyle: 'italic',\n },\n} as const;\n\nexport const Terminal: React.FC<TerminalProps> = ({\n title,\n logs,\n type,\n onClear,\n expanded,\n onToggleExpand,\n}) => {\n const terminalRef = useRef<HTMLDivElement>(null);\n const [autoScroll, setAutoScroll] = useState(true);\n\n useEffect(() => {\n if (autoScroll && terminalRef.current) {\n terminalRef.current.scrollTop = terminalRef.current.scrollHeight;\n }\n }, [logs, autoScroll]);\n\n const handleScroll = () => {\n if (terminalRef.current) {\n const { scrollTop, scrollHeight, clientHeight } = terminalRef.current;\n setAutoScroll(scrollHeight - scrollTop - clientHeight < 50);\n }\n };\n\n return (\n <div\n style={{\n ...styles.container,\n ...(expanded ? {} : styles.collapsed),\n }}\n >\n <TerminalHeader\n title={title}\n count={logs.length}\n expanded={expanded}\n onClear={onClear}\n onToggleExpand={onToggleExpand}\n />\n\n {expanded && (\n <div ref={terminalRef} onScroll={handleScroll} style={styles.body}>\n {logs.length === 0 ? (\n <div style={styles.empty}>Waiting for network requests...</div>\n ) : (\n logs.map((log) => <LogEntry key={log.id} log={log} type={type} />)\n )}\n </div>\n )}\n </div>\n );\n};\n","import React from 'react';\nimport { TerminalHeaderProps } from '../types';\n\nconst styles = {\n header: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n padding: '8px 16px',\n backgroundColor: '#1f2937',\n borderBottom: '1px solid #374151',\n },\n left: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n trafficLights: {\n display: 'flex',\n gap: '6px',\n },\n dot: {\n width: '12px',\n height: '12px',\n borderRadius: '50%',\n },\n title: {\n color: '#d1d5db',\n fontFamily: 'monospace',\n fontSize: '14px',\n marginLeft: '8px',\n },\n count: {\n color: '#6b7280',\n fontFamily: 'monospace',\n fontSize: '12px',\n },\n right: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n },\n button: {\n color: '#9ca3af',\n fontSize: '12px',\n fontFamily: 'monospace',\n padding: '4px 8px',\n borderRadius: '4px',\n border: 'none',\n background: 'transparent',\n cursor: 'pointer',\n },\n} as const;\n\nexport const TerminalHeader: React.FC<TerminalHeaderProps> = ({\n title,\n count,\n expanded,\n onClear,\n onToggleExpand,\n}) => {\n return (\n <div style={styles.header}>\n <div style={styles.left}>\n <div style={styles.trafficLights}>\n <div style={{ ...styles.dot, backgroundColor: '#ef4444' }} />\n <div style={{ ...styles.dot, backgroundColor: '#eab308' }} />\n <div style={{ ...styles.dot, backgroundColor: '#22c55e' }} />\n </div>\n <span style={styles.title}>{title}</span>\n <span style={styles.count}>({count} entries)</span>\n </div>\n <div style={styles.right}>\n <button\n onClick={onClear}\n style={styles.button}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n Clear\n </button>\n <button\n onClick={onToggleExpand}\n style={styles.button}\n onMouseEnter={(e) => (e.currentTarget.style.color = '#fff')}\n onMouseLeave={(e) => (e.currentTarget.style.color = '#9ca3af')}\n >\n {expanded ? '\\u25BC' : '\\u25B2'}\n </button>\n </div>\n </div>\n );\n};\n","import React, { useState } from 'react';\nimport { LogEntryProps } from '../types';\nimport { formatJson, formatTime } from '../utils/formatters';\nimport { getStatusColor, getMethodColor } from '../utils/colors';\n\nconst decodeSpecialChars = (str: string): string => {\n if (!str) return str;\n try {\n // Decode Unicode escape sequences like \\u003c to <\n return str.replace(/\\\\u([0-9a-fA-F]{4})/g, (_, code) =>\n String.fromCharCode(parseInt(code, 16))\n );\n } catch {\n return str;\n }\n};\n\nconst styles = {\n container: {\n marginBottom: '16px',\n borderBottom: '1px solid #1f2937',\n paddingBottom: '16px',\n },\n header: {\n display: 'flex',\n alignItems: 'center',\n gap: '8px',\n marginBottom: '4px',\n flexWrap: 'wrap' as const,\n },\n timestamp: {\n color: '#6b7280',\n fontSize: '12px',\n fontFamily: 'monospace',\n },\n method: {\n fontWeight: 'bold',\n fontFamily: 'monospace',\n },\n status: {\n fontWeight: 'bold',\n fontFamily: 'monospace',\n },\n duration: {\n color: '#6b7280',\n fontSize: '12px',\n fontFamily: 'monospace',\n },\n url: {\n color: '#60a5fa',\n wordBreak: 'break-all' as const,\n marginBottom: '8px',\n fontFamily: 'monospace',\n fontSize: '13px',\n },\n bodyContainer: {\n marginTop: '8px',\n },\n bodyLabel: {\n color: '#a78bfa',\n fontSize: '12px',\n marginBottom: '4px',\n fontFamily: 'monospace',\n },\n pre: {\n backgroundColor: '#1f2937',\n padding: '8px',\n borderRadius: '4px',\n color: '#86efac',\n overflowX: 'auto' as const,\n fontSize: '12px',\n whiteSpace: 'pre-wrap' as const,\n fontFamily: 'monospace',\n maxHeight: '192px',\n overflowY: 'auto' as const,\n margin: 0,\n },\n errorPre: {\n backgroundColor: '#1f2937',\n padding: '8px',\n borderRadius: '4px',\n color: '#fca5a5',\n overflowX: 'auto' as const,\n fontSize: '12px',\n whiteSpace: 'pre-wrap' as const,\n fontFamily: 'monospace',\n margin: 0,\n },\n bodyHeader: {\n display: 'flex',\n alignItems: 'center',\n justifyContent: 'space-between',\n marginBottom: '4px',\n },\n copyButton: {\n backgroundColor: 'transparent',\n border: '1px solid #4b5563',\n borderRadius: '4px',\n color: '#9ca3af',\n cursor: 'pointer',\n fontSize: '11px',\n padding: '2px 8px',\n fontFamily: 'monospace',\n transition: 'all 0.2s',\n },\n copyButtonHover: {\n backgroundColor: '#374151',\n color: '#fff',\n },\n copyButtonCopied: {\n backgroundColor: '#065f46',\n borderColor: '#10b981',\n color: '#10b981',\n },\n} as const;\n\nexport const LogEntry: React.FC<LogEntryProps> = ({ log, type }) => {\n const [copiedField, setCopiedField] = useState<string | null>(null);\n const [hoveredButton, setHoveredButton] = useState<string | null>(null);\n\n const handleCopy = async (content: unknown, field: string) => {\n try {\n const text = decodeSpecialChars(formatJson(content));\n await navigator.clipboard.writeText(text);\n setCopiedField(field);\n setTimeout(() => setCopiedField(null), 2000);\n } catch (err) {\n console.error('Failed to copy:', err);\n }\n };\n\n const getButtonStyle = (field: string) => ({\n ...styles.copyButton,\n ...(hoveredButton === field && copiedField !== field ? styles.copyButtonHover : {}),\n ...(copiedField === field ? styles.copyButtonCopied : {}),\n });\n\n const formatContent = (data: unknown): string => {\n return decodeSpecialChars(formatJson(data));\n };\n\n return (\n <div style={styles.container}>\n <div style={styles.header}>\n <span style={styles.timestamp}>[{formatTime(log.timestamp)}]</span>\n <span style={{ ...styles.method, color: getMethodColor(log.method) }}>\n {log.method}\n </span>\n {type === 'response' && log.status && (\n <span style={{ ...styles.status, color: getStatusColor(log.status) }}>\n {log.status} {log.statusText}\n </span>\n )}\n {log.duration !== undefined && type === 'response' && (\n <span style={styles.duration}>({log.duration}ms)</span>\n )}\n </div>\n\n <div style={styles.url}>{log.url}</div>\n\n {type === 'request' ? (\n log.requestBody ? (\n <div style={styles.bodyContainer}>\n <div style={styles.bodyHeader}>\n <div style={styles.bodyLabel}>{'\\u25B8'} Payload:</div>\n <button\n style={getButtonStyle('payload')}\n onClick={() => handleCopy(log.requestBody, 'payload')}\n onMouseEnter={() => setHoveredButton('payload')}\n onMouseLeave={() => setHoveredButton(null)}\n >\n {copiedField === 'payload' ? 'Copied!' : 'Copy'}\n </button>\n </div>\n <pre style={styles.pre}>{formatContent(log.requestBody)}</pre>\n </div>\n ) : null\n ) : log.error ? (\n <div style={styles.bodyContainer}>\n <div style={styles.bodyHeader}>\n <div style={{ ...styles.bodyLabel, color: '#f87171' }}>\n {'\\u25B8'} Error:\n </div>\n <button\n style={getButtonStyle('error')}\n onClick={() => handleCopy(log.error, 'error')}\n onMouseEnter={() => setHoveredButton('error')}\n onMouseLeave={() => setHoveredButton(null)}\n >\n {copiedField === 'error' ? 'Copied!' : 'Copy'}\n </button>\n </div>\n <pre style={styles.errorPre}>{log.error}</pre>\n </div>\n ) : log.responseBody ? (\n <div style={styles.bodyContainer}>\n <div style={styles.bodyHeader}>\n <div style={styles.bodyLabel}>{'\\u25B8'} Response:</div>\n <button\n style={getButtonStyle('response')}\n onClick={() => handleCopy(log.responseBody, 'response')}\n onMouseEnter={() => setHoveredButton('response')}\n onMouseLeave={() => setHoveredButton(null)}\n >\n {copiedField === 'response' ? 'Copied!' : 'Copy'}\n </button>\n </div>\n <pre style={styles.pre}>{formatContent(log.responseBody)}</pre>\n </div>\n ) : null}\n </div>\n );\n};\n","export const formatJson = (data: unknown): string => {\n if (!data) return '';\n try {\n if (typeof data === 'string') {\n const parsed = JSON.parse(data);\n return JSON.stringify(parsed, null, 2);\n }\n return JSON.stringify(data, null, 2);\n } catch {\n return String(data);\n }\n};\n\nexport const truncate = (str: string, maxLength: number): string => {\n if (str.length <= maxLength) return str;\n return str.slice(0, maxLength) + '...';\n};\n\nexport const formatTime = (date: Date): string => {\n return date.toLocaleTimeString('en-US', {\n hour12: false,\n hour: '2-digit',\n minute: '2-digit',\n second: '2-digit',\n });\n};\n","export const getStatusColor = (status?: number): string => {\n if (!status) return '#9ca3af'; // gray-400\n if (status >= 200 && status < 300) return '#4ade80'; // green-400\n if (status >= 300 && status < 400) return '#facc15'; // yellow-400\n if (status >= 400 && status < 500) return '#fb923c'; // orange-400\n return '#f87171'; // red-400\n};\n\nexport const getMethodColor = (method: string): string => {\n const colors: Record<string, string> = {\n GET: '#22d3ee', // cyan-400\n POST: '#4ade80', // green-400\n PUT: '#facc15', // yellow-400\n PATCH: '#fb923c', // orange-400\n DELETE: '#f87171', // red-400\n };\n return colors[method.toUpperCase()] || '#9ca3af';\n};\n","import { useEffect, useRef, useCallback } from 'react';\nimport { NetworkLog, UseNetworkInterceptorProps } from '../types';\n\nexport const useNetworkInterceptor = ({\n enabled,\n onLogAdd,\n onLogUpdate,\n}: UseNetworkInterceptorProps) => {\n const originalFetch = useRef<typeof fetch | null>(null);\n const originalXHROpen = useRef<typeof XMLHttpRequest.prototype.open | null>(null);\n const originalXHRSend = useRef<typeof XMLHttpRequest.prototype.send | null>(null);\n\n const generateId = useCallback((prefix: string) => {\n return `${prefix}-${Date.now()}-${Math.random().toString(36).substr(2, 9)}`;\n }, []);\n\n // Intercept Fetch\n useEffect(() => {\n if (!enabled) return;\n\n originalFetch.current = window.fetch;\n\n window.fetch = async function (input, init) {\n const id = generateId('fetch');\n const startTime = performance.now();\n\n const url =\n typeof input === 'string'\n ? input\n : input instanceof URL\n ? input.href\n : input.url;\n\n const method = init?.method || 'GET';\n\n let requestBody: unknown = null;\n if (init?.body) {\n try {\n requestBody =\n typeof init.body === 'string' ? JSON.parse(init.body) : init.body;\n } catch {\n requestBody = init.body;\n }\n }\n\n onLogAdd({\n id,\n timestamp: new Date(),\n method: method.toUpperCase(),\n url,\n requestBody,\n type: 'fetch',\n });\n\n try {\n const response = await originalFetch.current!(input, init);\n const duration = Math.round(performance.now() - startTime);\n\n const clonedResponse = response.clone();\n let responseBody: unknown = null;\n\n try {\n responseBody = await clonedResponse.json();\n } catch {\n try {\n responseBody = await clonedResponse.text();\n } catch {\n responseBody = '[Could not read response body]';\n }\n }\n\n onLogUpdate(id, {\n status: response.status,\n statusText: response.statusText,\n responseBody,\n duration,\n });\n\n return response;\n } catch (error: unknown) {\n const duration = Math.round(performance.now() - startTime);\n const errorMessage =\n error instanceof Error ? error.message : 'Network Error';\n onLogUpdate(id, {\n error: errorMessage,\n duration,\n });\n throw error;\n }\n };\n\n return () => {\n if (originalFetch.current) {\n window.fetch = originalFetch.current;\n }\n };\n }, [enabled, onLogAdd, onLogUpdate, generateId]);\n\n // Intercept XHR\n useEffect(() => {\n if (!enabled) return;\n\n originalXHROpen.current = XMLHttpRequest.prototype.open;\n originalXHRSend.current = XMLHttpRequest.prototype.send;\n\n XMLHttpRequest.prototype.open = function (\n method: string,\n url: string | URL\n ) {\n (this as XMLHttpRequest & { _networkTerminal: NetworkLog & { startTime: number } })._networkTerminal = {\n id: generateId('xhr'),\n method: method.toUpperCase(),\n url: url.toString(),\n startTime: 0,\n timestamp: new Date(),\n type: 'xhr',\n };\n return originalXHROpen.current!.apply(\n this,\n arguments as unknown as Parameters<typeof XMLHttpRequest.prototype.open>\n );\n };\n\n XMLHttpRequest.prototype.send = function (body?: Document | XMLHttpRequestBodyInit | null) {\n const meta = (this as XMLHttpRequest & { _networkTerminal?: NetworkLog & { startTime: number } })._networkTerminal;\n\n if (meta) {\n meta.startTime = performance.now();\n\n let requestBody: unknown = null;\n if (body) {\n try {\n requestBody = typeof body === 'string' ? JSON.parse(body) : body;\n } catch {\n requestBody = body;\n }\n }\n\n onLogAdd({\n id: meta.id,\n timestamp: new Date(),\n method: meta.method,\n url: meta.url,\n requestBody,\n type: 'xhr',\n });\n\n this.addEventListener('load', function () {\n const duration = Math.round(performance.now() - meta.startTime);\n\n let responseBody: unknown = null;\n try {\n responseBody = JSON.parse(this.responseText);\n } catch {\n responseBody = this.responseText;\n }\n\n onLogUpdate(meta.id, {\n status: this.status,\n statusText: this.statusText,\n responseBody,\n duration,\n });\n });\n\n this.addEventListener('error', function () {\n const duration = Math.round(performance.now() - meta.startTime);\n onLogUpdate(meta.id, {\n error: 'Network Error',\n duration,\n });\n });\n }\n\n return originalXHRSend.current!.apply(\n this,\n arguments as unknown as Parameters<typeof XMLHttpRequest.prototype.send>\n );\n };\n\n return () => {\n if (originalXHROpen.current) {\n XMLHttpRequest.prototype.open = originalXHROpen.current;\n }\n if (originalXHRSend.current) {\n XMLHttpRequest.prototype.send = originalXHRSend.current;\n }\n };\n }, [enabled, onLogAdd, onLogUpdate, generateId]);\n};\n","import type { Plugin, ViteDevServer } from 'vite';\nimport { createServer, IncomingMessage, ServerResponse } from 'http';\nimport { exec } from 'child_process';\n\nexport interface NetworkTerminalPluginOptions {\n /** Port for the dashboard (default: 4001) */\n port?: number;\n /** Auto-open dashboard in browser (default: true) */\n open?: boolean;\n}\n\n// Store network logs\nconst networkLogs: any[] = [];\nconst sseClients = new Set<ServerResponse>();\n\nfunction broadcastLog(log: any) {\n const data = JSON.stringify(log);\n sseClients.forEach(client => {\n client.write(`data: ${data}\\n\\n`);\n });\n}\n\nfunction getDashboardHTML(_port: number): string {\n return `\n<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"UTF-8\">\n <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">\n <title>Network Terminal</title>\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n body {\n font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace;\n background: #0a0e17;\n color: #e2e8f0;\n height: 100vh;\n overflow: hidden;\n }\n .header {\n background: #0f172a;\n padding: 12px 24px;\n border-bottom: 2px solid #4ade80;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .title { color: #4ade80; font-size: 18px; font-weight: bold; }\n .subtitle { color: #64748b; font-size: 12px; margin-top: 4px; }\n .controls { display: flex; gap: 12px; align-items: center; }\n .btn {\n background: #1e293b;\n border: 1px solid #334155;\n color: #94a3b8;\n padding: 8px 16px;\n border-radius: 6px;\n cursor: pointer;\n font-size: 12px;\n font-family: inherit;\n }\n .btn:hover { background: #334155; color: #e2e8f0; }\n .container { display: flex; height: calc(100vh - 80px); }\n .panel {\n flex: 1;\n display: flex;\n flex-direction: column;\n border-right: 1px solid #1e293b;\n }\n .panel:last-child { border-right: none; }\n .panel-header {\n background: #0f172a;\n padding: 12px 16px;\n border-bottom: 1px solid #1e293b;\n display: flex;\n justify-content: space-between;\n align-items: center;\n }\n .panel-title { font-weight: bold; font-size: 14px; }\n .panel-title.request { color: #3b82f6; }\n .panel-title.response { color: #22c55e; }\n .panel-count {\n background: #1e293b;\n padding: 2px 8px;\n border-radius: 10px;\n font-size: 11px;\n color: #64748b;\n }\n .logs { flex: 1; overflow-y: auto; padding: 8px; }\n .log-entry {\n background: #0f172a;\n border: 1px solid #1e293b;\n border-radius: 8px;\n margin-bottom: 8px;\n overflow: hidden;\n cursor: pointer;\n transition: border-color 0.2s;\n }\n .log-entry:hover { border-color: #334155; }\n .log-entry.selected { border-color: #4ade80; }\n .log-header {\n display: flex;\n align-items: center;\n gap: 12px;\n padding: 10px 12px;\n background: #1e293b;\n }\n .method {\n font-weight: bold;\n font-size: 11px;\n padding: 3px 8px;\n border-radius: 4px;\n }\n .method.GET { background: #166534; color: #4ade80; }\n .method.POST { background: #1e40af; color: #60a5fa; }\n .method.PUT { background: #a16207; color: #fcd34d; }\n .method.DELETE { background: #991b1b; color: #fca5a5; }\n .method.PATCH { background: #7c3aed; color: #c4b5fd; }\n .status { font-size: 11px; padding: 3px 8px; border-radius: 4px; }\n .status.success { background: #166534; color: #4ade80; }\n .status.error { background: #991b1b; color: #fca5a5; }\n .status.pending { background: #374151; color: #9ca3af; }\n .url {\n flex: 1;\n font-size: 12px;\n color: #94a3b8;\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n }\n .duration { font-size: 11px; color: #64748b; }\n .timestamp { font-size: 10px; color: #475569; }\n .log-body { padding: 12px; font-size: 11px; max-height: 300px; overflow: auto; }\n .log-body pre {\n margin: 0;\n white-space: pre-wrap;\n word-break: break-all;\n color: #cbd5e1;\n line-height: 1.5;\n }\n .log-body.empty { color: #475569; font-style: italic; }\n .empty-state {\n display: flex;\n flex-direction: column;\n align-items: center;\n justify-content: center;\n height: 100%;\n color: #475569;\n text-align: center;\n padding: 20px;\n }\n .empty-state svg { width: 48px; height: 48px; margin-bottom: 16px; opacity: 0.5; }\n .status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n background: #22c55e;\n animation: pulse 2s infinite;\n }\n @keyframes pulse { 0%, 100% { opacity: 1; } 50% { opacity: 0.5; } }\n .status-dot.disconnected { background: #ef4444; animation: none; }\n </style>\n</head>\n<body>\n <div class=\"header\">\n <div>\n <div class=\"title\">>_ Network Terminal</div>\n <div class=\"subtitle\">Vite Plugin - Monitoring fetch/XHR requests</div>\n </div>\n <div class=\"controls\">\n <div class=\"status-dot\" id=\"statusDot\"></div>\n <button class=\"btn\" onclick=\"clearLogs()\">Clear All</button>\n </div>\n </div>\n\n <div class=\"container\">\n <div class=\"panel\">\n <div class=\"panel-header\">\n <span class=\"panel-title request\">⬆ REQUESTS</span>\n <span class=\"panel-count\" id=\"requestCount\">0</span>\n </div>\n <div class=\"logs\" id=\"requestLogs\">\n <div class=\"empty-state\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 19V5M5 12l7-7 7 7\"/>\n </svg>\n <div>Waiting for requests...</div>\n <div style=\"margin-top: 8px; font-size: 11px;\">Make fetch/XHR requests in your app</div>\n </div>\n </div>\n </div>\n\n <div class=\"panel\">\n <div class=\"panel-header\">\n <span class=\"panel-title response\">⬇ RESPONSES</span>\n <span class=\"panel-count\" id=\"responseCount\">0</span>\n </div>\n <div class=\"logs\" id=\"responseLogs\">\n <div class=\"empty-state\">\n <svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\">\n <path d=\"M12 5v14M5 12l7 7 7-7\"/>\n </svg>\n <div>Waiting for responses...</div>\n </div>\n </div>\n </div>\n </div>\n\n <script>\n const logs = new Map();\n let selectedId = null;\n\n function formatJson(data) {\n if (!data) return null;\n if (typeof data === 'string') {\n try { data = JSON.parse(data); }\n catch (e) { return escapeHtml(data.substring(0, 2000)); }\n }\n return escapeHtml(JSON.stringify(data, null, 2));\n }\n\n function escapeHtml(str) {\n if (typeof str !== 'string') str = String(str);\n return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;');\n }\n\n function formatTime(timestamp) {\n const date = new Date(timestamp);\n return date.toLocaleTimeString('en-US', { hour12: false }) + '.' +\n String(date.getMilliseconds()).padStart(3, '0');\n }\n\n function getLogsArray() {\n return Array.from(logs.values()).sort((a, b) =>\n new Date(b.timestamp) - new Date(a.timestamp)\n );\n }\n\n function renderLogs() {\n const logsArray = getLogsArray();\n const requestContainer = document.getElementById('requestLogs');\n const responseContainer = document.getElementById('responseLogs');\n\n document.getElementById('requestCount').textContent = logsArray.length;\n document.getElementById('responseCount').textContent = logsArray.filter(l => l.status).length;\n\n if (logsArray.length === 0) {\n requestContainer.innerHTML = '<div class=\"empty-state\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 19V5M5 12l7-7 7 7\"/></svg><div>Waiting for requests...</div></div>';\n responseContainer.innerHTML = '<div class=\"empty-state\"><svg viewBox=\"0 0 24 24\" fill=\"none\" stroke=\"currentColor\" stroke-width=\"2\"><path d=\"M12 5v14M5 12l7 7 7-7\"/></svg><div>Waiting for responses...</div></div>';\n return;\n }\n\n requestContainer.innerHTML = logsArray.map(log => {\n const isSelected = selectedId === log.id;\n const bodyContent = formatJson(log.requestBody);\n return '<div class=\"log-entry '+(isSelected ? 'selected' : '')+'\" onclick=\"selectLog(\\\\''+log.id+'\\\\')\"><div class=\"log-header\"><span class=\"method '+log.method+'\">'+log.method+'</span><span class=\"url\" title=\"'+escapeHtml(log.url)+'\">'+log.url+'</span><span class=\"timestamp\">'+formatTime(log.timestamp)+'</span></div>'+(isSelected ? '<div class=\"log-body '+(bodyContent ? '' : 'empty')+'\">'+(bodyContent ? '<pre>'+bodyContent+'</pre>' : 'No request body')+'</div>' : '')+'</div>';\n }).join('');\n\n responseContainer.innerHTML = logsArray.map(log => {\n const isSelected = selectedId === log.id;\n const statusClass = !log.status ? 'pending' : log.status < 400 ? 'success' : 'error';\n const bodyContent = formatJson(log.responseBody);\n return '<div class=\"log-entry '+(isSelected ? 'selected' : '')+'\" onclick=\"selectLog(\\\\''+log.id+'\\\\')\"><div class=\"log-header\"><span class=\"status '+statusClass+'\">'+(log.status || '...')+'</span><span class=\"url\" title=\"'+escapeHtml(log.url)+'\">'+log.url+'</span><span class=\"duration\">'+(log.duration ? log.duration + 'ms' : '')+'</span></div>'+(isSelected ? '<div class=\"log-body '+(bodyContent ? '' : 'empty')+'\">'+(bodyContent ? '<pre>'+bodyContent+'</pre>' : (log.status ? 'No response body' : 'Pending...'))+'</div>' : '')+'</div>';\n }).join('');\n }\n\n function selectLog(id) {\n selectedId = selectedId === id ? null : id;\n renderLogs();\n }\n\n function clearLogs() {\n logs.clear();\n selectedId = null;\n renderLogs();\n fetch('/clear', { method: 'POST' });\n }\n\n function addLog(log) {\n logs.set(log.id, log);\n if (logs.size > 100) {\n const oldest = getLogsArray().pop();\n if (oldest) logs.delete(oldest.id);\n }\n renderLogs();\n }\n\n function connect() {\n const evtSource = new EventSource('/events');\n evtSource.onopen = () => document.getElementById('statusDot').classList.remove('disconnected');\n evtSource.onmessage = (event) => addLog(JSON.parse(event.data));\n evtSource.onerror = () => {\n document.getElementById('statusDot').classList.add('disconnected');\n evtSource.close();\n setTimeout(connect, 2000);\n };\n }\n\n connect();\n renderLogs();\n </script>\n</body>\n</html>\n`;\n}\n\nfunction getMonitorScript(port: number): string {\n return `\n(function() {\n if (window.__networkTerminalActive) return;\n window.__networkTerminalActive = true;\n\n var DASHBOARD_URL = 'http://localhost:${port}';\n\n function sendLog(log) {\n var xhr = new XMLHttpRequest();\n xhr.open('POST', DASHBOARD_URL + '/log', true);\n xhr.setRequestHeader('Content-Type', 'application/json');\n xhr.send(JSON.stringify(log));\n }\n\n function tryParse(data) {\n if (!data) return null;\n if (typeof data === 'object') return data;\n try { return JSON.parse(data); } catch (e) { return data; }\n }\n\n var originalFetch = window.fetch;\n window.fetch = function() {\n var args = arguments;\n var startTime = Date.now();\n var input = args[0];\n var options = args[1] || {};\n var url = typeof input === 'string' ? input : (input.url || input.toString());\n var method = (options.method || 'GET').toUpperCase();\n\n if (url.includes('localhost:${port}')) {\n return originalFetch.apply(this, args);\n }\n\n var log = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n method: method,\n url: url,\n timestamp: new Date().toISOString(),\n requestBody: options.body ? tryParse(options.body) : null,\n status: null,\n responseBody: null,\n duration: null,\n };\n\n sendLog(log);\n\n return originalFetch.apply(this, args).then(function(response) {\n log.status = response.status;\n log.duration = Date.now() - startTime;\n var cloned = response.clone();\n cloned.text().then(function(text) {\n log.responseBody = tryParse(text);\n sendLog(log);\n }).catch(function() { sendLog(log); });\n return response;\n }).catch(function(error) {\n log.status = 0;\n log.duration = Date.now() - startTime;\n log.error = error.message;\n sendLog(log);\n throw error;\n });\n };\n\n var OriginalXHR = window.XMLHttpRequest;\n window.XMLHttpRequest = function() {\n var xhr = new OriginalXHR();\n var method, url, requestBody, startTime;\n\n var originalOpen = xhr.open;\n xhr.open = function(m, u) {\n method = m;\n url = u;\n return originalOpen.apply(this, arguments);\n };\n\n var originalSend = xhr.send;\n xhr.send = function(body) {\n if (url && url.includes('localhost:${port}')) {\n return originalSend.apply(this, arguments);\n }\n\n startTime = Date.now();\n requestBody = body;\n\n var log = {\n id: Date.now().toString() + Math.random().toString(36).substr(2, 9),\n method: (method || 'GET').toUpperCase(),\n url: url,\n timestamp: new Date().toISOString(),\n requestBody: tryParse(requestBody),\n status: null,\n responseBody: null,\n duration: null,\n };\n\n sendLog(log);\n\n xhr.addEventListener('loadend', function() {\n log.status = xhr.status;\n log.duration = Date.now() - startTime;\n log.responseBody = tryParse(xhr.responseText);\n sendLog(log);\n });\n\n return originalSend.apply(this, arguments);\n };\n\n return xhr;\n };\n\n console.log('[Network Terminal] ✓ Active - Dashboard: http://localhost:${port}');\n})();\n`;\n}\n\nexport function networkTerminal(options: NetworkTerminalPluginOptions = {}): Plugin {\n const { port = 4001, open = true } = options;\n let dashboardServer: ReturnType<typeof createServer> | null = null;\n\n return {\n name: 'vite-plugin-network-terminal',\n apply: 'serve',\n\n configureServer(_server: ViteDevServer) {\n // Start dashboard server\n dashboardServer = createServer((req: IncomingMessage, res: ServerResponse) => {\n res.setHeader('Access-Control-Allow-Origin', '*');\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type');\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n if (req.url === '/events') {\n res.writeHead(200, {\n 'Content-Type': 'text/event-stream',\n 'Cache-Control': 'no-cache',\n 'Connection': 'keep-alive',\n });\n sseClients.add(res);\n networkLogs.forEach(log => {\n res.write(`data: ${JSON.stringify(log)}\\n\\n`);\n });\n req.on('close', () => sseClients.delete(res));\n return;\n }\n\n if (req.url === '/log' && req.method === 'POST') {\n let body = '';\n req.on('data', (chunk: Buffer) => body += chunk);\n req.on('end', () => {\n try {\n const log = JSON.parse(body);\n const existingIndex = networkLogs.findIndex(l => l.id === log.id);\n if (existingIndex >= 0) {\n networkLogs[existingIndex] = log;\n } else {\n networkLogs.unshift(log);\n if (networkLogs.length > 100) networkLogs.pop();\n }\n broadcastLog(log);\n } catch (e) {}\n res.writeHead(200);\n res.end('OK');\n });\n return;\n }\n\n if (req.url === '/clear' && req.method === 'POST') {\n networkLogs.length = 0;\n res.writeHead(200);\n res.end('OK');\n return;\n }\n\n res.writeHead(200, { 'Content-Type': 'text/html' });\n res.end(getDashboardHTML(port));\n });\n\n dashboardServer.listen(port, () => {\n console.log(`\\n \\x1b[32m>_ Network Terminal\\x1b[0m`);\n console.log(` Dashboard: \\x1b[36mhttp://localhost:${port}\\x1b[0m\\n`);\n\n if (open) {\n const openCmd = process.platform === 'darwin' ? 'open' : process.platform === 'win32' ? 'start' : 'xdg-open';\n exec(`${openCmd} http://localhost:${port}`);\n }\n });\n\n dashboardServer.on('error', (err: NodeJS.ErrnoException) => {\n if (err.code === 'EADDRINUSE') {\n console.log(`\\n \\x1b[33m[Network Terminal]\\x1b[0m Port ${port} in use, dashboard disabled\\n`);\n }\n });\n },\n\n transformIndexHtml(html: string) {\n const script = `<script>${getMonitorScript(port)}</script>`;\n if (html.includes('</head>')) {\n return html.replace('</head>', script + '</head>');\n }\n return script + html;\n },\n\n buildEnd() {\n if (dashboardServer) {\n dashboardServer.close();\n }\n },\n };\n}\n\nexport default networkTerminal;\n"],"mappings":"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","names":["import_react","import_react","import_jsx_runtime","styles","import_jsx_runtime","styles","import_react","import_jsx_runtime","styles"]}