UNPKG

debug-time-machine

Version:
1 lines 51.3 kB
{"version":3,"sources":["../src/useDebugTimeMachine.ts","../src/types.ts"],"sourcesContent":["import { useEffect, useRef, useState, useCallback } from 'react';\nimport {\n IDebugTimeMachineConfig,\n IDebugTimeMachineHookReturn,\n MessageType,\n IStateChangeData,\n IErrorData,\n IConnectionData,\n TConnectionType,\n} from './types';\n\nconst DEFAULT_CONFIG: Required<IDebugTimeMachineConfig> = {\n websocketUrl: 'ws://localhost:4000/ws',\n debugMode: true, // 🔥 기본값을 true로 변경\n captureUserActions: true,\n captureErrors: true,\n captureStateChanges: true,\n maxReconnectAttempts: 5,\n reconnectInterval: 5000,\n developmentOnly: false,\n autoConnect: true,\n enableTimeTravelEngine: true,\n enableMemoryManagement: true,\n enableDOMSnapshots: false,\n enableMetrics: true,\n timeTravelConfig: {},\n memoryConfig: {},\n domSnapshotConfig: {},\n};\n\nconst CONSOLE_STYLES = {\n info: 'color: #2196F3; font-weight: bold;',\n success: 'color: #4CAF50; font-weight: bold;',\n warning: 'color: #FF9800; font-weight: bold;',\n error: 'color: #F44336; font-weight: bold;',\n} as const;\n\ntype TLogType = keyof typeof CONSOLE_STYLES;\n\ndeclare global {\n interface XMLHttpRequest {\n _debugTM?: {\n requestId: string;\n method: string;\n url: string;\n startTime: number;\n shouldCapture: boolean;\n };\n }\n}\n\nexport function useDebugTimeMachine(\n userConfig: IDebugTimeMachineConfig = {}\n): IDebugTimeMachineHookReturn {\n const config = { ...DEFAULT_CONFIG, ...userConfig };\n\n const wsRef = useRef<WebSocket | null>(null);\n const isInitializedRef = useRef(false);\n const isConnectingRef = useRef(false);\n const reconnectAttemptsRef = useRef(0);\n const reconnectTimeoutRef = useRef<number | null>(null);\n\n const [isConnected, setIsConnected] = useState(false);\n const [clientId, setClientId] = useState<string | null>(null);\n const [connectionInfo, setConnectionInfo] = useState({\n connectedAt: null as Date | null,\n reconnectAttempts: 0,\n lastError: null as string | null,\n });\n\n const [performanceMetrics, setPerformanceMetrics] = useState<any>(null);\n const [systemMetrics, setSystemMetrics] = useState<any>(null);\n const [memoryUsage, setMemoryUsage] = useState<any>(null);\n const [networkRequests, setNetworkRequests] = useState<any[]>([]);\n const [networkResponses, setNetworkResponses] = useState<any[]>([]);\n\n const writeLog = useCallback(\n (message: string, type: TLogType = 'info', data?: any) => {\n if (!config.debugMode) return;\n\n const style = CONSOLE_STYLES[type];\n const timestamp = new Date().toISOString();\n\n if (data) {\n console.groupCollapsed(`%c[Debug Time Machine ${timestamp}] ${message}`, style);\n console.log('Data:', data);\n console.groupEnd();\n } else {\n console.log(`%c[Debug Time Machine ${timestamp}] ${message}`, style);\n }\n },\n [config.debugMode]\n );\n\n const sendMessage = useCallback(\n (type: string, data: any): boolean => {\n if (!wsRef.current || wsRef.current.readyState !== WebSocket.OPEN) {\n writeLog(`❌ Cannot send message: WebSocket not ready`, 'warning');\n return false;\n }\n\n const message = {\n type: type,\n payload: data,\n timestamp: Date.now(),\n clientId: clientId || undefined,\n };\n\n try {\n const messageStr = JSON.stringify(message);\n wsRef.current.send(messageStr);\n writeLog(`✅ Message sent successfully: ${type}`, 'success');\n return true;\n } catch (error) {\n writeLog(`❌ Failed to send message: ${type}`, 'error');\n return false;\n }\n },\n [clientId, writeLog]\n );\n\n const captureError = useCallback(\n (error: Error, errorInfo?: any) => {\n writeLog(`🔴 Manual error capture: ${error.message}`, 'error');\n\n // 🔥 수정: WebSocket 상태를 직접 확인\n const isWsConnected = wsRef.current?.readyState === WebSocket.OPEN;\n writeLog(`Debug: isWsConnected=${isWsConnected}, captureErrors=${config.captureErrors}`, 'info');\n \n if (!isWsConnected || !config.captureErrors) {\n writeLog('Cannot capture error: WebSocket not connected or errors disabled', 'warning');\n return;\n }\n\n const errorData: IErrorData = {\n message: error.message || 'Unknown error',\n stack: error.stack || 'No stack trace available',\n timestamp: Date.now(),\n url: window.location.href,\n userAgent: navigator.userAgent,\n };\n\n if (errorInfo) {\n errorData.errorInfo = errorInfo;\n }\n\n const success = sendMessage(MessageType.ERROR, errorData);\n writeLog(`Error message send result: ${success}`, success ? 'success' : 'error');\n },\n [config.captureErrors, sendMessage, writeLog]\n );\n\n const captureStateChange = useCallback(\n (componentName: string, prevState: any, newState: any, props?: any) => {\n const isWsConnected = wsRef.current?.readyState === WebSocket.OPEN;\n \n if (!isWsConnected || !config.captureStateChanges) {\n writeLog('Cannot capture state change: WebSocket not connected or disabled', 'warning');\n return;\n }\n\n const stateChangeData: IStateChangeData = {\n componentName,\n prevState,\n newState,\n props,\n timestamp: Date.now(),\n url: window.location.href,\n };\n\n sendMessage(MessageType.STATE_CHANGE, stateChangeData);\n },\n [config.captureStateChanges, sendMessage, writeLog]\n );\n\n const handleMessage = useCallback(\n (event: MessageEvent) => {\n try {\n const message = JSON.parse(event.data);\n\n if (!message || typeof message !== 'object' || !message.type) {\n return;\n }\n\n const messageData = message.payload || message.data;\n\n switch (message.type) {\n case MessageType.CONNECTION:\n if (messageData && messageData.type === 'welcome' && messageData.clientId) {\n setClientId(messageData.clientId);\n writeLog(`Assigned client ID: ${messageData.clientId}`, 'success');\n }\n break;\n\n case 'ping':\n case 'PING':\n case MessageType.PING:\n sendMessage(MessageType.PONG, {});\n break;\n\n case MessageType.ERROR:\n writeLog('Server error:', 'error', messageData);\n break;\n\n default:\n break;\n }\n } catch (error) {\n writeLog('Failed to parse incoming message', 'error');\n }\n },\n [sendMessage, writeLog]\n );\n\n const connect = useCallback(() => {\n if (isConnectingRef.current || wsRef.current?.readyState === WebSocket.OPEN) {\n return;\n }\n\n try {\n writeLog('Connecting to Time Machine...', 'info');\n isConnectingRef.current = true;\n\n if (wsRef.current) {\n wsRef.current.close();\n wsRef.current = null;\n }\n\n wsRef.current = new WebSocket(config.websocketUrl);\n\n wsRef.current.onopen = () => {\n isConnectingRef.current = false;\n setIsConnected(true);\n reconnectAttemptsRef.current = 0;\n setConnectionInfo(prev => ({\n ...prev,\n connectedAt: new Date(),\n reconnectAttempts: 0,\n lastError: null,\n }));\n\n writeLog('Connected to Debug Time Machine!', 'success');\n\n const connectionData: IConnectionData = {\n type: 'client_ready' as TConnectionType,\n url: window.location.href,\n userAgent: navigator.userAgent,\n timestamp: Date.now(),\n };\n\n setTimeout(() => {\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n try {\n wsRef.current.send(JSON.stringify({\n type: MessageType.CONNECTION,\n payload: connectionData,\n timestamp: Date.now(),\n clientId: clientId || undefined,\n }));\n } catch (sendError) {\n writeLog('Failed to send initial message', 'error');\n }\n }\n }, 300);\n };\n\n wsRef.current.onmessage = handleMessage;\n\n wsRef.current.onclose = event => {\n isConnectingRef.current = false;\n setIsConnected(false);\n setClientId(null);\n\n if (event.code === 1000 || event.code === 1001) {\n return;\n }\n\n if (reconnectAttemptsRef.current < config.maxReconnectAttempts) {\n reconnectAttemptsRef.current++;\n setConnectionInfo(prev => ({\n ...prev,\n reconnectAttempts: reconnectAttemptsRef.current,\n lastError: null,\n }));\n\n reconnectTimeoutRef.current = window.setTimeout(() => {\n connect();\n }, config.reconnectInterval);\n }\n };\n\n wsRef.current.onerror = () => {\n isConnectingRef.current = false;\n setConnectionInfo(prev => ({\n ...prev,\n lastError: 'WebSocket connection error',\n }));\n };\n } catch (error) {\n writeLog('Failed to create WebSocket connection', 'error');\n isConnectingRef.current = false;\n }\n }, [config.websocketUrl, config.maxReconnectAttempts, config.reconnectInterval, handleMessage, writeLog, clientId]);\n\n const reconnect = useCallback(() => {\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current);\n }\n\n if (wsRef.current) {\n wsRef.current.close();\n }\n\n reconnectAttemptsRef.current = 0;\n connect();\n }, [connect]);\n\n const checkDebugServer = useCallback(async (): Promise<boolean> => {\n if (!config.autoConnect) {\n return false;\n }\n\n try {\n const baseUrl = config.websocketUrl.replace('ws://', 'http://').replace('/ws', '');\n \n const controller = new AbortController();\n const timeoutId = setTimeout(() => controller.abort(), 2000);\n \n try {\n const response = await fetch(`${baseUrl}/health`, { \n method: 'GET',\n signal: controller.signal\n });\n \n clearTimeout(timeoutId);\n \n if (response.ok) {\n const data = await response.json();\n writeLog(`🎯 Debug 서버 발견!`, 'success');\n return true;\n }\n } catch (fetchError) {\n clearTimeout(timeoutId);\n throw fetchError;\n }\n } catch (error) {\n if (config.debugMode) {\n writeLog(`Debug 서버 없음`, 'info');\n }\n }\n return false;\n }, [config.websocketUrl, config.autoConnect, config.debugMode, writeLog]);\n\n const setupEnhancedNetworkInterceptor = useCallback(() => {\n if (typeof window === 'undefined') return;\n\n writeLog('🌐 Setting up enhanced network interceptor...', 'info');\n\n const originalFetch = window.fetch;\n const originalXHROpen = XMLHttpRequest.prototype.open;\n const originalXHRSend = XMLHttpRequest.prototype.send;\n\n const generateRequestId = () => `req_${Date.now()}_${Math.random().toString(36).slice(2, 9)}`;\n\n const shouldCaptureUrl = (url: string): boolean => {\n const excludePatterns = [\n /localhost:4000/, /localhost:8080/, /127\\.0\\.0\\.1:4000/, /127\\.0\\.0\\.1:8080/,\n /webpack-hmr/, /hot-update/, /sockjs-node/, /@vite\\/client/, /react-devtools/,\n /chrome-extension:/, /moz-extension:/, /favicon\\.ico/, /manifest\\.json/,\n /\\.(js|css|png|jpg|jpeg|gif|svg|woff|woff2|ttf|eot)(\\?|$)/,\n ];\n\n if (excludePatterns.some(pattern => pattern.test(url))) {\n return false;\n }\n\n const includePatterns = [\n /\\/api\\//, /\\/graphql/, /\\/v\\d+\\//, /jsonplaceholder\\.typicode\\.com/,\n /reqres\\.in/, /httpbin\\.org/, /api\\./,\n ];\n\n return includePatterns.some(pattern => pattern.test(url));\n };\n\n const sanitizeRequestData = (data: any): any => {\n if (!data) return data;\n \n if (typeof data === 'string') {\n try {\n const parsed = JSON.parse(data);\n return sanitizeRequestData(parsed);\n } catch {\n return data\n .replace(/\"password\"\\s*:\\s*\"[^\"]*\"/gi, '\"password\":\"***\"')\n .replace(/\"token\"\\s*:\\s*\"[^\"]*\"/gi, '\"token\":\"***\"')\n .replace(/\"secret\"\\s*:\\s*\"[^\"]*\"/gi, '\"secret\":\"***\"');\n }\n }\n \n if (typeof data === 'object' && data !== null) {\n const sanitized = { ...data };\n Object.keys(sanitized).forEach(key => {\n if (/password|token|secret|auth|key/i.test(key)) {\n sanitized[key] = '***';\n }\n });\n return sanitized;\n }\n \n return data;\n };\n\n window.fetch = async (...args) => {\n const [input, init = {}] = args;\n const url = typeof input === 'string' ? input : (input as Request).url;\n const method = init.method || 'GET';\n const requestId = generateRequestId();\n const startTime = Date.now();\n \n const shouldCapture = shouldCaptureUrl(url) || \n ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method.toUpperCase());\n \n if (!shouldCapture) {\n return originalFetch.apply(window, args);\n }\n\n writeLog(`📤 API Request: ${method} ${url}`, 'info');\n\n const requestData = {\n id: requestId,\n type: 'request',\n method: method.toUpperCase(),\n url,\n timestamp: startTime,\n headers: init.headers ? Object.fromEntries(new Headers(init.headers).entries()) : {},\n body: init.body ? sanitizeRequestData(init.body) : undefined,\n };\n\n setNetworkRequests(prev => [...prev, {\n ...requestData,\n status: 'pending',\n duration: 0,\n }].slice(-100));\n\n try {\n const response = await originalFetch.apply(window, args);\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n const responseHeaders = Object.fromEntries(response.headers.entries());\n \n let responseBody = undefined;\n try {\n const clonedResponse = response.clone();\n const contentType = response.headers.get('content-type') || '';\n \n if (contentType.includes('application/json')) {\n responseBody = await clonedResponse.json();\n } else if (contentType.includes('text/')) {\n const text = await clonedResponse.text();\n responseBody = text.length > 1000 ? text.substring(0, 1000) + '...' : text;\n }\n } catch (bodyError) {\n // Ignore body read errors\n }\n\n const responseData = {\n id: requestId,\n type: 'response',\n method: method.toUpperCase(),\n url,\n status: response.status,\n statusText: response.statusText,\n ok: response.ok,\n duration,\n timestamp: endTime,\n requestTimestamp: startTime,\n headers: responseHeaders,\n body: responseBody,\n size: responseHeaders['content-length'] || 'unknown',\n };\n\n setNetworkRequests(prev => prev.map(req => \n req.id === requestId \n ? { ...req, ...responseData, status: response.status, success: response.ok }\n : req\n ));\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n writeLog(`🔥 Sending NETWORK_REQUEST to server`, 'info');\n const requestSuccess = sendMessage('NETWORK_REQUEST', requestData);\n const responseSuccess = sendMessage('NETWORK_RESPONSE', responseData);\n writeLog(`Network message results: request=${requestSuccess}, response=${responseSuccess}`, 'info');\n } else {\n writeLog(`❌ WebSocket not ready for network data: readyState=${wsRef.current?.readyState}`, 'warning');\n }\n\n if (response.ok) {\n writeLog(`✅ API Success: ${method} ${url} (${response.status}, ${duration}ms)`, 'success');\n } else {\n writeLog(`❌ API Error: ${method} ${url} (${response.status}, ${duration}ms)`, 'error');\n \n captureError(new Error(`HTTP ${response.status}: ${response.statusText}`), {\n type: 'network_error',\n url, method, status: response.status, statusText: response.statusText,\n duration, requestId, responseBody,\n });\n }\n\n return response;\n } catch (error: unknown) {\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n const errorData = {\n id: requestId,\n type: 'error',\n method: method.toUpperCase(),\n url, duration,\n timestamp: endTime,\n requestTimestamp: startTime,\n error: error instanceof Error ? error.message : String(error),\n errorType: error instanceof Error ? error.name : 'Unknown',\n };\n \n setNetworkRequests(prev => prev.map(req => \n req.id === requestId \n ? { ...req, ...errorData, status: 'error', success: false }\n : req\n ));\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n writeLog(`🔥 Sending NETWORK_ERROR to server`, 'error');\n const requestSuccess = sendMessage('NETWORK_REQUEST', requestData);\n const errorSuccess = sendMessage('NETWORK_ERROR', errorData);\n writeLog(`Network error message results: request=${requestSuccess}, error=${errorSuccess}`, 'info');\n } else {\n writeLog(`❌ WebSocket not ready for error data: readyState=${wsRef.current?.readyState}`, 'warning');\n }\n \n captureError(error instanceof Error ? error : new Error(String(error)), {\n type: 'network_error',\n url, method, duration, requestId,\n });\n \n throw error;\n }\n };\n\n XMLHttpRequest.prototype.open = function(method: string, url: string | URL, async?: boolean, username?: string | null, password?: string | null) {\n const urlString = url.toString();\n \n const shouldCapture = shouldCaptureUrl(urlString) || \n ['POST', 'PUT', 'DELETE', 'PATCH'].includes(method.toUpperCase());\n \n if (shouldCapture) {\n const requestId = generateRequestId();\n \n this._debugTM = {\n requestId,\n method: method.toUpperCase(),\n url: urlString,\n startTime: Date.now(),\n shouldCapture: true,\n };\n \n writeLog(`📤 XHR Request: ${method} ${urlString}`, 'info');\n }\n \n return originalXHROpen.call(this, method, url, async || true, username, password);\n };\n \n XMLHttpRequest.prototype.send = function(body?: XMLHttpRequestBodyInit | Document | null) {\n if (this._debugTM && this._debugTM.shouldCapture) {\n const { requestId, method, url, startTime } = this._debugTM;\n \n const requestData = {\n id: requestId,\n type: 'request',\n method, url,\n timestamp: startTime,\n headers: {},\n body: body ? sanitizeRequestData(body) : undefined,\n };\n\n setNetworkRequests(prev => [...prev, {\n ...requestData,\n status: 'pending',\n duration: 0,\n }].slice(-100));\n \n this.addEventListener('loadend', () => {\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n let responseBody = undefined;\n try {\n if (this.responseText && this.getResponseHeader('content-type')?.includes('application/json')) {\n responseBody = JSON.parse(this.responseText);\n } else if (this.responseText) {\n const text = this.responseText;\n responseBody = text.length > 1000 ? text.substring(0, 1000) + '...' : text;\n }\n } catch {\n // Ignore parsing errors\n }\n\n const responseData = {\n id: requestId,\n type: 'response',\n method, url,\n status: this.status,\n statusText: this.statusText,\n ok: this.status >= 200 && this.status < 300,\n duration,\n timestamp: endTime,\n requestTimestamp: startTime,\n headers: {},\n body: responseBody,\n };\n\n setNetworkRequests(prev => prev.map(req => \n req.id === requestId \n ? { ...req, ...responseData, status: this.status, success: this.status >= 200 && this.status < 300 }\n : req\n ));\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n writeLog(`🔥 Sending XHR data to server`, 'info');\n const requestSuccess = sendMessage('NETWORK_REQUEST', requestData);\n \n if (this.status === 0) {\n const errorSuccess = sendMessage('NETWORK_ERROR', {\n id: requestId,\n type: 'error',\n method, url, duration,\n timestamp: endTime,\n requestTimestamp: startTime,\n error: 'Network Error',\n errorType: 'NetworkError',\n });\n writeLog(`XHR error message results: request=${requestSuccess}, error=${errorSuccess}`, 'info');\n } else {\n const responseSuccess = sendMessage('NETWORK_RESPONSE', responseData);\n writeLog(`XHR message results: request=${requestSuccess}, response=${responseSuccess}`, 'info');\n }\n } else {\n writeLog(`❌ WebSocket not ready for XHR data: readyState=${wsRef.current?.readyState}`, 'warning');\n }\n\n if (this.status >= 200 && this.status < 300) {\n writeLog(`✅ XHR Success: ${method} ${url} (${this.status}, ${duration}ms)`, 'success');\n } else {\n writeLog(`❌ XHR Error: ${method} ${url} (${this.status}, ${duration}ms)`, 'error');\n \n if (this.status >= 400) {\n captureError(new Error(`XHR ${this.status}: ${this.statusText}`), {\n type: 'network_error',\n url, method, status: this.status, statusText: this.statusText,\n duration, requestId, responseBody,\n });\n }\n }\n });\n\n this.addEventListener('error', () => {\n const endTime = Date.now();\n const duration = endTime - startTime;\n \n const errorData = {\n id: requestId,\n type: 'error',\n method, url, duration,\n timestamp: endTime,\n requestTimestamp: startTime,\n error: 'Network Error',\n errorType: 'NetworkError',\n };\n\n setNetworkRequests(prev => prev.map(req => \n req.id === requestId \n ? { ...req, ...errorData, status: 'error', success: false }\n : req\n ));\n\n if (wsRef.current?.readyState === WebSocket.OPEN) {\n writeLog(`🔥 Sending XHR error to server`, 'error');\n const requestSuccess = sendMessage('NETWORK_REQUEST', requestData);\n const errorSuccess = sendMessage('NETWORK_ERROR', errorData);\n writeLog(`XHR error message results: request=${requestSuccess}, error=${errorSuccess}`, 'info');\n } else {\n writeLog(`❌ WebSocket not ready for XHR error: readyState=${wsRef.current?.readyState}`, 'warning');\n }\n \n captureError(new Error('XHR Network Error'), {\n type: 'network_error',\n url, method, duration, requestId,\n });\n });\n }\n \n return originalXHRSend.call(this, body);\n };\n\n writeLog('✅ Enhanced network interceptor setup complete', 'success');\n \n return () => {\n window.fetch = originalFetch;\n XMLHttpRequest.prototype.open = originalXHROpen;\n XMLHttpRequest.prototype.send = originalXHRSend;\n writeLog('🧹 Enhanced network interceptor cleaned up', 'info');\n };\n }, [writeLog, sendMessage, captureError, isConnected]);\n\n const autoConnectToServer = useCallback(async (): Promise<(() => void) | null> => {\n if (!config.autoConnect) {\n return null;\n }\n\n writeLog('🔍 Debug Time Machine 서버 검색 중...', 'info');\n \n const serverExists = await checkDebugServer();\n \n if (serverExists) {\n writeLog('✅ Debug Time Machine 서버 발견! 연결을 시작합니다.', 'success');\n connect();\n return null;\n } else {\n writeLog('🤷 Debug Time Machine 서버를 찾을 수 없습니다. 일반 모드로 실행됩니다.', 'info');\n return null;\n }\n }, [config.autoConnect, checkDebugServer, connect, writeLog]);\n\n // Initialize connection and event listeners - 🔥 무한루프 수정\n useEffect(() => {\n if (isInitializedRef.current || wsRef.current) {\n return;\n }\n\n isInitializedRef.current = true;\n writeLog('🚀 Initializing Debug Time Machine client...', 'info');\n\n const cleanupNetworkInterceptor = setupEnhancedNetworkInterceptor();\n\n autoConnectToServer().catch((error) => {\n writeLog('자동 연결 중 오류 발생', 'error', error);\n });\n\n writeLog('✅ Debug Time Machine client initialized!', 'success');\n\n return () => {\n writeLog('🧹 Cleaning up Debug Time Machine client...', 'info');\n isInitializedRef.current = false;\n\n if (cleanupNetworkInterceptor) {\n cleanupNetworkInterceptor();\n }\n\n if (reconnectTimeoutRef.current) {\n clearTimeout(reconnectTimeoutRef.current);\n reconnectTimeoutRef.current = null;\n }\n\n if (wsRef.current) {\n wsRef.current.close(1000, 'Component unmounting');\n wsRef.current = null;\n }\n };\n }, []); // 🔥 핵심: 빈 의존성 배열로 한번만 실행\n\n useEffect(() => {\n return () => {\n if (wsRef.current && wsRef.current.readyState === WebSocket.OPEN) {\n wsRef.current.close();\n }\n };\n }, []);\n\n const createSnapshot = useCallback((state: Record<string, unknown>, actionType: string) => {\n writeLog(`📸 Snapshot created: ${actionType}`, 'success');\n return { id: Date.now().toString(), state, actionType, timestamp: Date.now() };\n }, [writeLog]);\n\n const restoreSnapshot = useCallback((snapshotId: string) => {\n writeLog(`⏮️ Snapshot restored: ${snapshotId}`, 'success');\n return true;\n }, [writeLog]);\n\n const getPerformanceMetrics = useCallback(() => {\n return performanceMetrics;\n }, [performanceMetrics]);\n\n const getSystemMetrics = useCallback(() => {\n return systemMetrics;\n }, [systemMetrics]);\n\n const getMemoryUsage = useCallback(() => {\n return memoryUsage;\n }, [memoryUsage]);\n\n const clearSnapshots = useCallback(() => {\n writeLog('🗑️ All snapshots cleared', 'info');\n }, [writeLog]);\n\n const exportMetrics = useCallback(() => {\n return { exported: true, timestamp: Date.now() };\n }, []);\n\n const getNetworkMetrics = useCallback(() => {\n return {\n totalRequests: networkRequests.length,\n successfulRequests: networkRequests.filter((req: any) => req.success === true).length,\n failedRequests: networkRequests.filter((req: any) => req.success === false).length,\n requests: networkRequests,\n };\n }, [networkRequests]);\n\n const clearNetworkHistory = useCallback(() => {\n setNetworkRequests([]);\n setNetworkResponses([]);\n writeLog('🗑️ Network history cleared', 'info');\n }, [writeLog]);\n\n const exportNetworkData = useCallback(() => {\n return {\n requests: networkRequests,\n responses: networkResponses,\n metrics: getNetworkMetrics(),\n exportedAt: new Date().toISOString(),\n };\n }, [networkRequests, networkResponses, getNetworkMetrics]);\n\n return {\n isConnected,\n clientId,\n reconnect,\n sendMessage,\n captureError,\n captureStateChange,\n connectionInfo,\n shouldCaptureNetworkRequest: () => true,\n shouldCaptureNetworkResponse: () => true,\n createSnapshot,\n restoreSnapshot,\n getPerformanceMetrics,\n getSystemMetrics,\n getMemoryUsage,\n clearSnapshots,\n exportMetrics,\n getNetworkMetrics,\n clearNetworkHistory,\n exportNetworkData,\n timeTravelEngine: null,\n metricsCollector: null,\n domSnapshotOptimizer: null,\n networkInterceptor: null,\n performanceMetrics,\n systemMetrics,\n memoryUsage,\n networkRequests,\n networkResponses,\n } as IDebugTimeMachineHookReturn;\n}","// Debug Time Machine Unified Package Types\n\nexport interface IDebugTimeMachineConfig {\n /**\n * WebSocket URL for the Debug Time Machine server\n * @default \"ws://localhost:4000/ws\"\n */\n websocketUrl?: string;\n \n /**\n * Enable debug mode (console logs)\n * @default true in development, false in production\n */\n debugMode?: boolean;\n \n /**\n * Automatically capture user interactions\n * @default true\n */\n captureUserActions?: boolean;\n \n /**\n * Automatically capture errors\n * @default true\n */\n captureErrors?: boolean;\n \n /**\n * Automatically capture React state changes\n * @default true\n */\n captureStateChanges?: boolean;\n \n /**\n * Maximum number of reconnection attempts\n * @default 5\n */\n maxReconnectAttempts?: number;\n \n /**\n * Reconnection interval in milliseconds\n * @default 5000\n */\n reconnectInterval?: number;\n \n /**\n * Only enable in development environment\n * @default false\n */\n developmentOnly?: boolean;\n\n /**\n * Automatically connect to Debug Time Machine server if available\n * @default true\n */\n autoConnect?: boolean;\n\n // Enhanced options\n /**\n * Enable time travel engine\n * @default true\n */\n enableTimeTravelEngine?: boolean;\n\n /**\n * Enable memory management\n * @default true\n */\n enableMemoryManagement?: boolean;\n\n /**\n * Enable DOM snapshots\n * @default false\n */\n enableDOMSnapshots?: boolean;\n\n /**\n * Enable metrics collection\n * @default true\n */\n enableMetrics?: boolean;\n\n /**\n * Time travel engine configuration\n */\n timeTravelConfig?: any;\n\n /**\n * Memory management configuration\n */\n memoryConfig?: any;\n\n /**\n * DOM snapshot configuration\n */\n domSnapshotConfig?: any;\n}\n\nexport interface IDebugTimeMachineHookReturn {\n /**\n * Whether the client is connected to the server\n */\n isConnected: boolean;\n \n /**\n * Current client ID assigned by the server\n */\n clientId: string | null;\n \n /**\n * Manual reconnection function\n */\n reconnect: () => void;\n \n /**\n * Send a custom message to the server\n */\n sendMessage: (type: string, data: any) => boolean;\n \n /**\n * Manually capture an error\n */\n captureError: (error: Error, errorInfo?: any) => void;\n \n /**\n * Manually capture a state change\n */\n captureStateChange: (componentName: string, prevState: any, newState: any, props?: any) => void;\n \n /**\n * Connection status information\n */\n connectionInfo: IConnectionInfo;\n\n // Enhanced methods\n /**\n * Check if a network request should be captured\n */\n shouldCaptureNetworkRequest: (request: any) => boolean;\n\n /**\n * Check if a network response should be captured\n */\n shouldCaptureNetworkResponse: (response: any) => boolean;\n\n /**\n * Create a snapshot of the current state\n */\n createSnapshot: (state: Record<string, unknown>, actionType: string, description?: string) => any;\n\n /**\n * Restore a snapshot by ID\n */\n restoreSnapshot: (snapshotId: string) => boolean;\n\n /**\n * Get performance metrics\n */\n getPerformanceMetrics: () => any;\n\n /**\n * Get system metrics\n */\n getSystemMetrics: () => any;\n\n /**\n * Get memory usage\n */\n getMemoryUsage: () => any;\n\n /**\n * Clear all snapshots\n */\n clearSnapshots: () => void;\n\n /**\n * Export metrics\n */\n exportMetrics: () => any;\n\n // Network methods\n /**\n * Get network metrics\n */\n getNetworkMetrics: () => any;\n\n /**\n * Clear network history\n */\n clearNetworkHistory: () => void;\n\n /**\n * Export network data\n */\n exportNetworkData: () => void;\n\n // Engine references\n timeTravelEngine: any;\n metricsCollector: any;\n domSnapshotOptimizer: any;\n networkInterceptor: any;\n\n // Enhanced state\n performanceMetrics: any;\n systemMetrics: any;\n memoryUsage: any;\n\n // Network state\n networkRequests: any[];\n networkResponses: any[];\n}\n\nexport interface IConnectionInfo {\n connectedAt: Date | null;\n reconnectAttempts: number;\n lastError: string | null;\n}\n\nexport interface IUserActionData {\n actionType: string;\n element: string;\n coordinates: { x: number; y: number; pageX?: number; pageY?: number };\n target: {\n id: string;\n className: string;\n tagName: string;\n textContent?: string;\n };\n value?: any;\n timestamp: number;\n url: string;\n priority?: 'low' | 'medium' | 'high' | 'critical';\n selector?: string;\n xpath?: string;\n attributes?: { [key: string]: string };\n}\n\nexport interface IStateChangeData {\n componentName: string;\n prevState?: any;\n newState: any;\n props?: any;\n stackTrace?: string[];\n timestamp: number;\n url: string;\n}\n\nexport interface IErrorData {\n message: string;\n stack?: string;\n filename?: string;\n lineno?: number;\n colno?: number;\n timestamp: number;\n url: string;\n userAgent: string;\n errorInfo?: any;\n level?: 'info' | 'warning' | 'error' | 'critical';\n source?: 'javascript' | 'promise' | 'console' | 'react';\n context?: any;\n}\n\nexport interface IConnectionData {\n type: TConnectionType;\n clientId?: string;\n url?: string;\n userAgent?: string;\n message?: string;\n timestamp: number;\n}\n\nexport type TConnectionType = 'welcome' | 'client_ready' | 'debugger_ready' | 'dashboard_ready' | 'disconnect';\n\n// Message types\nexport enum MessageType {\n CONNECTION = 'CONNECTION',\n USER_ACTION = 'USER_ACTION',\n STATE_CHANGE = 'STATE_CHANGE',\n ERROR = 'ERROR',\n PING = 'PING',\n PONG = 'PONG'\n}\n\nexport interface IMessage {\n type: MessageType;\n timestamp: number;\n clientId?: string;\n data: any;\n}\n"],"mappings":"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