@float.js/core 2.0.3 β†’ 2.0.5

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.
@@ -593,7 +593,7 @@ function generateDashboardHTML(state) {
593
593
  <div class="logo-icon">\u26A1</div>
594
594
  <div class="logo-text">
595
595
  <span class="logo-title">Float.js</span>
596
- <span class="logo-version">v2.0.1</span>
596
+ <span class="logo-version">v2.0.4</span>
597
597
  </div>
598
598
  </div>
599
599
  </div>
@@ -1 +1 @@
1
- {"version":3,"sources":["../../src/devtools/index.ts"],"sourcesContent":["/**\n * Float.js Dev Dashboard\n * Visual development tools integrated into the framework\n * \n * Next.js doesn't have this! πŸš€\n */\n\nimport { IncomingMessage, ServerResponse } from 'http';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface RouteInfo {\n path: string;\n type: 'page' | 'api' | 'layout' | 'error' | 'loading' | 'not-found';\n file: string;\n methods?: string[];\n params?: string[];\n middleware?: boolean;\n}\n\nexport interface BuildInfo {\n duration: number;\n timestamp: Date;\n success: boolean;\n errors?: string[];\n warnings?: string[];\n}\n\nexport interface RequestLog {\n id: string;\n method: string;\n path: string;\n status: number;\n duration: number;\n timestamp: Date;\n headers?: Record<string, string>;\n body?: unknown;\n response?: unknown;\n}\n\nexport interface PerformanceMetrics {\n requests: number;\n avgResponseTime: number;\n errorRate: number;\n activeConnections: number;\n memoryUsage: NodeJS.MemoryUsage;\n uptime: number;\n}\n\nexport interface DevDashboardOptions {\n enabled?: boolean;\n path?: string;\n maxLogs?: number;\n auth?: {\n username: string;\n password: string;\n };\n}\n\n// ============================================================================\n// DEV DASHBOARD STATE\n// ============================================================================\n\nclass DevDashboardState {\n routes: RouteInfo[] = [];\n builds: BuildInfo[] = [];\n requestLogs: RequestLog[] = [];\n startTime: Date = new Date();\n maxLogs: number = 100;\n \n private requestCount = 0;\n private totalResponseTime = 0;\n private errorCount = 0;\n\n addRoute(route: RouteInfo): void {\n const existing = this.routes.findIndex(r => r.path === route.path);\n if (existing >= 0) {\n this.routes[existing] = route;\n } else {\n this.routes.push(route);\n }\n }\n\n addBuild(build: BuildInfo): void {\n this.builds.unshift(build);\n if (this.builds.length > 20) {\n this.builds.pop();\n }\n }\n\n logRequest(log: RequestLog): void {\n this.requestLogs.unshift(log);\n if (this.requestLogs.length > this.maxLogs) {\n this.requestLogs.pop();\n }\n \n this.requestCount++;\n this.totalResponseTime += log.duration;\n if (log.status >= 400) {\n this.errorCount++;\n }\n }\n\n getMetrics(): PerformanceMetrics {\n return {\n requests: this.requestCount,\n avgResponseTime: this.requestCount > 0 \n ? Math.round(this.totalResponseTime / this.requestCount) \n : 0,\n errorRate: this.requestCount > 0 \n ? Math.round((this.errorCount / this.requestCount) * 100) \n : 0,\n activeConnections: 0, // Updated by server\n memoryUsage: process.memoryUsage(),\n uptime: Date.now() - this.startTime.getTime(),\n };\n }\n\n clear(): void {\n this.requestLogs = [];\n this.requestCount = 0;\n this.totalResponseTime = 0;\n this.errorCount = 0;\n }\n}\n\nexport const dashboardState = new DevDashboardState();\n\n// ============================================================================\n// MIDDLEWARE\n// ============================================================================\n\nexport function createRequestLogger() {\n return (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const startTime = Date.now();\n const id = `req_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n\n // Capture response\n const originalEnd = res.end.bind(res);\n res.end = function(chunk?: any, encoding?: any, callback?: any) {\n const duration = Date.now() - startTime;\n \n dashboardState.logRequest({\n id,\n method: req.method || 'GET',\n path: req.url || '/',\n status: res.statusCode,\n duration,\n timestamp: new Date(),\n });\n\n return originalEnd(chunk, encoding, callback);\n } as typeof res.end;\n\n next();\n };\n}\n\n// ============================================================================\n// DASHBOARD HTML\n// ============================================================================\n\nfunction generateDashboardHTML(state: DevDashboardState): string {\n const metrics = state.getMetrics();\n const memoryMB = Math.round(metrics.memoryUsage.heapUsed / 1024 / 1024);\n const memoryTotal = Math.round(metrics.memoryUsage.heapTotal / 1024 / 1024);\n const uptimeSeconds = Math.round(metrics.uptime / 1000);\n const uptimeFormatted = uptimeSeconds < 60 \n ? `${uptimeSeconds}s` \n : uptimeSeconds < 3600 \n ? `${Math.floor(uptimeSeconds / 60)}m ${uptimeSeconds % 60}s`\n : `${Math.floor(uptimeSeconds / 3600)}h ${Math.floor((uptimeSeconds % 3600) / 60)}m`;\n \n const lastBuild = state.builds.length > 0 ? state.builds[0] : null;\n const lastBuildTime = lastBuild \n ? new Date(lastBuild.timestamp).toLocaleTimeString() \n : 'Never';\n\n return `<!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>Float.js Dev Dashboard</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap\" rel=\"stylesheet\">\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n \n :root {\n --bg-dark: #09090b;\n --bg-card: #18181b;\n --bg-card-hover: #1f1f23;\n --bg-sidebar: #0f0f12;\n --text-primary: #fafafa;\n --text-secondary: #71717a;\n --text-muted: #52525b;\n --accent: #a855f7;\n --accent-glow: rgba(168, 85, 247, 0.15);\n --success: #22c55e;\n --warning: #f59e0b;\n --error: #ef4444;\n --border: #27272a;\n --border-subtle: #1f1f23;\n }\n\n body {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background: var(--bg-dark);\n color: var(--text-primary);\n min-height: 100vh;\n display: flex;\n }\n\n /* Sidebar */\n .sidebar {\n width: 280px;\n background: var(--bg-sidebar);\n border-right: 1px solid var(--border);\n display: flex;\n flex-direction: column;\n position: fixed;\n height: 100vh;\n z-index: 100;\n }\n\n .sidebar-header {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border);\n }\n\n .logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n\n .logo-icon {\n width: 40px;\n height: 40px;\n background: linear-gradient(135deg, #a855f7 0%, #ec4899 50%, #f97316 100%);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 1.25rem;\n box-shadow: 0 0 20px rgba(168, 85, 247, 0.3);\n }\n\n .logo-text {\n display: flex;\n flex-direction: column;\n }\n\n .logo-title {\n font-weight: 700;\n font-size: 1.125rem;\n background: linear-gradient(135deg, #fff 0%, #a1a1aa 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n }\n\n .logo-version {\n font-size: 0.75rem;\n color: var(--text-muted);\n font-family: 'JetBrains Mono', monospace;\n }\n\n /* Status Cards */\n .status-section {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border);\n }\n\n .status-grid {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n }\n\n .status-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--bg-card);\n border-radius: 10px;\n border: 1px solid var(--border-subtle);\n }\n\n .status-label {\n font-size: 0.8rem;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .status-value {\n font-size: 0.875rem;\n font-weight: 600;\n font-family: 'JetBrains Mono', monospace;\n }\n\n .status-value.connected {\n color: var(--success);\n }\n\n .status-value.active {\n color: var(--accent);\n }\n\n .status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n animation: pulse 2s infinite;\n }\n\n .status-dot.green { background: var(--success); box-shadow: 0 0 8px var(--success); }\n .status-dot.purple { background: var(--accent); box-shadow: 0 0 8px var(--accent); }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.7; transform: scale(0.95); }\n }\n\n /* Navigation */\n .nav-section {\n padding: 1rem;\n flex: 1;\n }\n\n .nav-label {\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--text-muted);\n padding: 0.5rem 1rem;\n margin-bottom: 0.5rem;\n }\n\n .nav-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n border-radius: 10px;\n color: var(--text-secondary);\n text-decoration: none;\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.2s;\n cursor: pointer;\n margin-bottom: 0.25rem;\n }\n\n .nav-item:hover {\n background: var(--bg-card);\n color: var(--text-primary);\n }\n\n .nav-item.active {\n background: var(--accent-glow);\n color: var(--accent);\n border: 1px solid rgba(168, 85, 247, 0.2);\n }\n\n .nav-icon {\n font-size: 1.1rem;\n }\n\n .nav-badge {\n margin-left: auto;\n background: var(--bg-card);\n padding: 0.125rem 0.5rem;\n border-radius: 6px;\n font-size: 0.7rem;\n font-family: 'JetBrains Mono', monospace;\n color: var(--text-muted);\n }\n\n /* Sidebar Footer */\n .sidebar-footer {\n padding: 1rem 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .docs-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem;\n background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(236, 72, 153, 0.1));\n border: 1px solid rgba(168, 85, 247, 0.2);\n border-radius: 10px;\n color: var(--accent);\n text-decoration: none;\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.2s;\n }\n\n .docs-link:hover {\n background: linear-gradient(135deg, rgba(168, 85, 247, 0.2), rgba(236, 72, 153, 0.2));\n transform: translateY(-1px);\n }\n\n /* Main Content */\n .main {\n margin-left: 280px;\n flex: 1;\n padding: 2rem;\n min-height: 100vh;\n }\n\n .page-header {\n margin-bottom: 2rem;\n }\n\n .page-title {\n font-size: 1.75rem;\n font-weight: 700;\n margin-bottom: 0.5rem;\n }\n\n .page-subtitle {\n color: var(--text-secondary);\n font-size: 0.9rem;\n }\n\n /* Metrics Grid */\n .metrics-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 1rem;\n margin-bottom: 2rem;\n }\n\n .metric-card {\n background: var(--bg-card);\n border: 1px solid var(--border-subtle);\n border-radius: 16px;\n padding: 1.5rem;\n transition: all 0.3s;\n position: relative;\n overflow: hidden;\n }\n\n .metric-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--accent), #ec4899);\n opacity: 0;\n transition: opacity 0.3s;\n }\n\n .metric-card:hover {\n border-color: var(--accent);\n transform: translateY(-2px);\n box-shadow: 0 8px 32px rgba(168, 85, 247, 0.1);\n }\n\n .metric-card:hover::before {\n opacity: 1;\n }\n\n .metric-icon {\n font-size: 1.5rem;\n margin-bottom: 1rem;\n }\n\n .metric-value {\n font-size: 2rem;\n font-weight: 700;\n font-family: 'JetBrains Mono', monospace;\n margin-bottom: 0.25rem;\n }\n\n .metric-label {\n font-size: 0.8rem;\n color: var(--text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .metric-change {\n position: absolute;\n top: 1rem;\n right: 1rem;\n font-size: 0.75rem;\n padding: 0.25rem 0.5rem;\n border-radius: 6px;\n font-weight: 500;\n }\n\n .metric-change.up { background: rgba(34, 197, 94, 0.1); color: var(--success); }\n .metric-change.down { background: rgba(239, 68, 68, 0.1); color: var(--error); }\n\n /* Sections */\n .content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n }\n\n .section {\n background: var(--bg-card);\n border: 1px solid var(--border-subtle);\n border-radius: 16px;\n overflow: hidden;\n }\n\n .section.full-width {\n grid-column: 1 / -1;\n }\n\n .section-header {\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .section-title {\n font-size: 1rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .section-badge {\n background: var(--bg-dark);\n padding: 0.25rem 0.75rem;\n border-radius: 8px;\n font-size: 0.75rem;\n color: var(--text-muted);\n font-family: 'JetBrains Mono', monospace;\n }\n\n .section-content {\n max-height: 400px;\n overflow-y: auto;\n }\n\n /* Routes List */\n .route-item {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem 1.5rem;\n border-bottom: 1px solid var(--border-subtle);\n transition: background 0.2s;\n }\n\n .route-item:last-child {\n border-bottom: none;\n }\n\n .route-item:hover {\n background: var(--bg-card-hover);\n }\n\n .route-type {\n padding: 0.25rem 0.75rem;\n border-radius: 6px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n min-width: 60px;\n text-align: center;\n }\n\n .route-type.page { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }\n .route-type.api { background: rgba(34, 197, 94, 0.15); color: #4ade80; }\n .route-type.layout { background: rgba(168, 85, 247, 0.15); color: #c084fc; }\n\n .route-path {\n font-family: 'JetBrains Mono', monospace;\n font-size: 0.875rem;\n flex: 1;\n }\n\n .route-file {\n color: var(--text-muted);\n font-size: 0.75rem;\n font-family: 'JetBrains Mono', monospace;\n }\n\n /* Request Logs */\n .log-item {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 0.875rem 1.5rem;\n border-bottom: 1px solid var(--border-subtle);\n font-size: 0.875rem;\n transition: background 0.2s;\n }\n\n .log-item:hover {\n background: var(--bg-card-hover);\n }\n\n .log-method {\n font-weight: 600;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n font-size: 0.7rem;\n min-width: 50px;\n text-align: center;\n font-family: 'JetBrains Mono', monospace;\n }\n\n .log-method.GET { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }\n .log-method.POST { background: rgba(34, 197, 94, 0.15); color: #4ade80; }\n .log-method.PUT { background: rgba(245, 158, 11, 0.15); color: #fbbf24; }\n .log-method.DELETE { background: rgba(239, 68, 68, 0.15); color: #f87171; }\n\n .log-status {\n font-weight: 600;\n font-family: 'JetBrains Mono', monospace;\n font-size: 0.8rem;\n }\n\n .log-status.s2xx { color: var(--success); }\n .log-status.s3xx { color: #60a5fa; }\n .log-status.s4xx { color: var(--warning); }\n .log-status.s5xx { color: var(--error); }\n\n .log-path {\n font-family: 'JetBrains Mono', monospace;\n flex: 1;\n color: var(--text-secondary);\n }\n\n .log-duration {\n font-family: 'JetBrains Mono', monospace;\n color: var(--text-muted);\n font-size: 0.8rem;\n }\n\n .log-time {\n color: var(--text-muted);\n font-size: 0.75rem;\n }\n\n /* Empty State */\n .empty-state {\n text-align: center;\n padding: 3rem;\n color: var(--text-muted);\n }\n\n .empty-icon {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n }\n\n /* Scrollbar */\n ::-webkit-scrollbar { width: 6px; }\n ::-webkit-scrollbar-track { background: transparent; }\n ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }\n ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }\n\n /* Responsive */\n @media (max-width: 1200px) {\n .metrics-grid { grid-template-columns: repeat(2, 1fr); }\n .content-grid { grid-template-columns: 1fr; }\n }\n </style>\n</head>\n<body>\n <!-- Sidebar -->\n <aside class=\"sidebar\">\n <div class=\"sidebar-header\">\n <div class=\"logo\">\n <div class=\"logo-icon\">⚑</div>\n <div class=\"logo-text\">\n <span class=\"logo-title\">Float.js</span>\n <span class=\"logo-version\">v2.0.1</span>\n </div>\n </div>\n </div>\n\n <div class=\"status-section\">\n <div class=\"status-grid\">\n <div class=\"status-item\">\n <span class=\"status-label\">\n <span class=\"status-dot green\"></span>\n Estado\n </span>\n <span class=\"status-value connected\">Conectado</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">\n <span class=\"status-dot purple\"></span>\n HMR\n </span>\n <span class=\"status-value active\">Activo</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">Último build</span>\n <span class=\"status-value\">${lastBuildTime}</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">Uptime</span>\n <span class=\"status-value\">${uptimeFormatted}</span>\n </div>\n </div>\n </div>\n\n <nav class=\"nav-section\">\n <div class=\"nav-label\">Dashboard</div>\n <div class=\"nav-item active\">\n <span class=\"nav-icon\">πŸ“Š</span>\n Overview\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">πŸ›€οΈ</span>\n Routes\n <span class=\"nav-badge\">${state.routes.length}</span>\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">πŸ“</span>\n Logs\n <span class=\"nav-badge\">${state.requestLogs.length}</span>\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">βš™οΈ</span>\n Settings\n </div>\n </nav>\n\n <div class=\"sidebar-footer\">\n <a href=\"https://floatjs.dev/docs\" target=\"_blank\" class=\"docs-link\">\n <span>πŸ“š</span>\n Documentation\n </a>\n </div>\n </aside>\n\n <!-- Main Content -->\n <main class=\"main\">\n <div class=\"page-header\">\n <h1 class=\"page-title\">Dev Dashboard</h1>\n <p class=\"page-subtitle\">Monitor your Float.js application in real-time</p>\n </div>\n\n <!-- Metrics -->\n <div class=\"metrics-grid\">\n <div class=\"metric-card\">\n <div class=\"metric-icon\">πŸ“‘</div>\n <div class=\"metric-value\">${metrics.requests}</div>\n <div class=\"metric-label\">Total Requests</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">⚑</div>\n <div class=\"metric-value\">${metrics.avgResponseTime}ms</div>\n <div class=\"metric-label\">Avg Response</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">πŸ’Ύ</div>\n <div class=\"metric-value\">${memoryMB}/${memoryTotal}</div>\n <div class=\"metric-label\">Memory (MB)</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">${metrics.errorRate > 0 ? '⚠️' : 'βœ…'}</div>\n <div class=\"metric-value\">${metrics.errorRate}%</div>\n <div class=\"metric-label\">Error Rate</div>\n </div>\n </div>\n\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Routes -->\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"section-title\">πŸ›€οΈ Routes</span>\n <span class=\"section-badge\">${state.routes.length} registered</span>\n </div>\n <div class=\"section-content\">\n ${state.routes.length === 0 ? `\n <div class=\"empty-state\">\n <div class=\"empty-icon\">πŸ›€οΈ</div>\n <p>No routes registered</p>\n </div>\n ` : state.routes.map(route => `\n <div class=\"route-item\">\n <span class=\"route-type ${route.type}\">${route.type}</span>\n <span class=\"route-path\">${route.path}</span>\n <span class=\"route-file\">${route.file.split('/').pop()}</span>\n </div>\n `).join('')}\n </div>\n </div>\n\n <!-- Request Logs -->\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"section-title\">πŸ“ Request Logs</span>\n <span class=\"section-badge\">Live</span>\n </div>\n <div class=\"section-content\">\n ${state.requestLogs.length === 0 ? `\n <div class=\"empty-state\">\n <div class=\"empty-icon\">πŸ“</div>\n <p>No requests yet</p>\n </div>\n ` : state.requestLogs.slice(0, 20).map(log => {\n const statusClass = log.status < 300 ? 's2xx' : log.status < 400 ? 's3xx' : log.status < 500 ? 's4xx' : 's5xx';\n return `\n <div class=\"log-item\">\n <span class=\"log-method ${log.method}\">${log.method}</span>\n <span class=\"log-status ${statusClass}\">${log.status}</span>\n <span class=\"log-path\">${log.path}</span>\n <span class=\"log-duration\">${log.duration}ms</span>\n </div>\n `;\n }).join('')}\n </div>\n </div>\n </div>\n </main>\n\n <script>\n // Auto-refresh every 3 seconds\n setTimeout(() => location.reload(), 3000);\n </script>\n</body>\n</html>`;\n}\n\n// ============================================================================\n// DASHBOARD API\n// ============================================================================\n\nfunction generateAPIResponse(state: DevDashboardState): string {\n return JSON.stringify({\n metrics: state.getMetrics(),\n routes: state.routes,\n builds: state.builds.slice(0, 10),\n requestLogs: state.requestLogs.slice(0, 50),\n });\n}\n\n// ============================================================================\n// DASHBOARD HANDLER\n// ============================================================================\n\nexport function createDevDashboard(options: DevDashboardOptions = {}) {\n const {\n enabled = process.env.NODE_ENV !== 'production',\n path = '/__float',\n auth,\n } = options;\n\n if (!enabled) {\n return (_req: IncomingMessage, _res: ServerResponse, next: () => void) => next();\n }\n\n return (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const url = req.url || '';\n \n // Check if this is a dashboard request\n if (!url.startsWith(path)) {\n return next();\n }\n\n // Basic auth if configured\n if (auth) {\n const authHeader = req.headers.authorization;\n if (!authHeader || !authHeader.startsWith('Basic ')) {\n res.setHeader('WWW-Authenticate', 'Basic realm=\"Float.js Dev Dashboard\"');\n res.statusCode = 401;\n res.end('Unauthorized');\n return;\n }\n\n const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();\n const [username, password] = credentials.split(':');\n \n if (username !== auth.username || password !== auth.password) {\n res.statusCode = 401;\n res.end('Invalid credentials');\n return;\n }\n }\n\n // Route dashboard requests\n const subPath = url.slice(path.length);\n\n if (subPath === '' || subPath === '/') {\n // Main dashboard\n res.setHeader('Content-Type', 'text/html');\n res.end(generateDashboardHTML(dashboardState));\n return;\n }\n\n if (subPath === '/api' || subPath === '/api/') {\n // API endpoint\n res.setHeader('Content-Type', 'application/json');\n res.end(generateAPIResponse(dashboardState));\n return;\n }\n\n if (subPath === '/api/routes') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.routes));\n return;\n }\n\n if (subPath === '/api/metrics') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.getMetrics()));\n return;\n }\n\n if (subPath === '/api/logs') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.requestLogs.slice(0, 100)));\n return;\n }\n\n if (subPath === '/api/clear' && req.method === 'POST') {\n dashboardState.clear();\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ success: true }));\n return;\n }\n\n // 404 for unknown dashboard routes\n res.statusCode = 404;\n res.end('Not found');\n };\n}\n\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\nexport const devtools = {\n dashboard: createDevDashboard,\n logger: createRequestLogger,\n state: dashboardState,\n \n // Helpers for manual logging\n logRoute: (route: RouteInfo) => dashboardState.addRoute(route),\n logBuild: (build: BuildInfo) => dashboardState.addBuild(build),\n logRequest: (log: RequestLog) => dashboardState.logRequest(log),\n getMetrics: () => dashboardState.getMetrics(),\n clear: () => dashboardState.clear(),\n};\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":[]}
1
+ {"version":3,"sources":["../../src/devtools/index.ts"],"sourcesContent":["/**\n * Float.js Dev Dashboard\n * Visual development tools integrated into the framework\n * \n * Next.js doesn't have this! πŸš€\n */\n\nimport { IncomingMessage, ServerResponse } from 'http';\n\n// ============================================================================\n// TYPES\n// ============================================================================\n\nexport interface RouteInfo {\n path: string;\n type: 'page' | 'api' | 'layout' | 'error' | 'loading' | 'not-found';\n file: string;\n methods?: string[];\n params?: string[];\n middleware?: boolean;\n}\n\nexport interface BuildInfo {\n duration: number;\n timestamp: Date;\n success: boolean;\n errors?: string[];\n warnings?: string[];\n}\n\nexport interface RequestLog {\n id: string;\n method: string;\n path: string;\n status: number;\n duration: number;\n timestamp: Date;\n headers?: Record<string, string>;\n body?: unknown;\n response?: unknown;\n}\n\nexport interface PerformanceMetrics {\n requests: number;\n avgResponseTime: number;\n errorRate: number;\n activeConnections: number;\n memoryUsage: NodeJS.MemoryUsage;\n uptime: number;\n}\n\nexport interface DevDashboardOptions {\n enabled?: boolean;\n path?: string;\n maxLogs?: number;\n auth?: {\n username: string;\n password: string;\n };\n}\n\n// ============================================================================\n// DEV DASHBOARD STATE\n// ============================================================================\n\nclass DevDashboardState {\n routes: RouteInfo[] = [];\n builds: BuildInfo[] = [];\n requestLogs: RequestLog[] = [];\n startTime: Date = new Date();\n maxLogs: number = 100;\n \n private requestCount = 0;\n private totalResponseTime = 0;\n private errorCount = 0;\n\n addRoute(route: RouteInfo): void {\n const existing = this.routes.findIndex(r => r.path === route.path);\n if (existing >= 0) {\n this.routes[existing] = route;\n } else {\n this.routes.push(route);\n }\n }\n\n addBuild(build: BuildInfo): void {\n this.builds.unshift(build);\n if (this.builds.length > 20) {\n this.builds.pop();\n }\n }\n\n logRequest(log: RequestLog): void {\n this.requestLogs.unshift(log);\n if (this.requestLogs.length > this.maxLogs) {\n this.requestLogs.pop();\n }\n \n this.requestCount++;\n this.totalResponseTime += log.duration;\n if (log.status >= 400) {\n this.errorCount++;\n }\n }\n\n getMetrics(): PerformanceMetrics {\n return {\n requests: this.requestCount,\n avgResponseTime: this.requestCount > 0 \n ? Math.round(this.totalResponseTime / this.requestCount) \n : 0,\n errorRate: this.requestCount > 0 \n ? Math.round((this.errorCount / this.requestCount) * 100) \n : 0,\n activeConnections: 0, // Updated by server\n memoryUsage: process.memoryUsage(),\n uptime: Date.now() - this.startTime.getTime(),\n };\n }\n\n clear(): void {\n this.requestLogs = [];\n this.requestCount = 0;\n this.totalResponseTime = 0;\n this.errorCount = 0;\n }\n}\n\nexport const dashboardState = new DevDashboardState();\n\n// ============================================================================\n// MIDDLEWARE\n// ============================================================================\n\nexport function createRequestLogger() {\n return (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const startTime = Date.now();\n const id = `req_${Date.now()}_${Math.random().toString(36).substring(2, 7)}`;\n\n // Capture response\n const originalEnd = res.end.bind(res);\n res.end = function(chunk?: any, encoding?: any, callback?: any) {\n const duration = Date.now() - startTime;\n \n dashboardState.logRequest({\n id,\n method: req.method || 'GET',\n path: req.url || '/',\n status: res.statusCode,\n duration,\n timestamp: new Date(),\n });\n\n return originalEnd(chunk, encoding, callback);\n } as typeof res.end;\n\n next();\n };\n}\n\n// ============================================================================\n// DASHBOARD HTML\n// ============================================================================\n\nfunction generateDashboardHTML(state: DevDashboardState): string {\n const metrics = state.getMetrics();\n const memoryMB = Math.round(metrics.memoryUsage.heapUsed / 1024 / 1024);\n const memoryTotal = Math.round(metrics.memoryUsage.heapTotal / 1024 / 1024);\n const uptimeSeconds = Math.round(metrics.uptime / 1000);\n const uptimeFormatted = uptimeSeconds < 60 \n ? `${uptimeSeconds}s` \n : uptimeSeconds < 3600 \n ? `${Math.floor(uptimeSeconds / 60)}m ${uptimeSeconds % 60}s`\n : `${Math.floor(uptimeSeconds / 3600)}h ${Math.floor((uptimeSeconds % 3600) / 60)}m`;\n \n const lastBuild = state.builds.length > 0 ? state.builds[0] : null;\n const lastBuildTime = lastBuild \n ? new Date(lastBuild.timestamp).toLocaleTimeString() \n : 'Never';\n\n return `<!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>Float.js Dev Dashboard</title>\n <link rel=\"preconnect\" href=\"https://fonts.googleapis.com\">\n <link rel=\"preconnect\" href=\"https://fonts.gstatic.com\" crossorigin>\n <link href=\"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;600;700&family=JetBrains+Mono:wght@400;500&display=swap\" rel=\"stylesheet\">\n <style>\n * { margin: 0; padding: 0; box-sizing: border-box; }\n \n :root {\n --bg-dark: #09090b;\n --bg-card: #18181b;\n --bg-card-hover: #1f1f23;\n --bg-sidebar: #0f0f12;\n --text-primary: #fafafa;\n --text-secondary: #71717a;\n --text-muted: #52525b;\n --accent: #a855f7;\n --accent-glow: rgba(168, 85, 247, 0.15);\n --success: #22c55e;\n --warning: #f59e0b;\n --error: #ef4444;\n --border: #27272a;\n --border-subtle: #1f1f23;\n }\n\n body {\n font-family: 'Inter', -apple-system, BlinkMacSystemFont, sans-serif;\n background: var(--bg-dark);\n color: var(--text-primary);\n min-height: 100vh;\n display: flex;\n }\n\n /* Sidebar */\n .sidebar {\n width: 280px;\n background: var(--bg-sidebar);\n border-right: 1px solid var(--border);\n display: flex;\n flex-direction: column;\n position: fixed;\n height: 100vh;\n z-index: 100;\n }\n\n .sidebar-header {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border);\n }\n\n .logo {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n }\n\n .logo-icon {\n width: 40px;\n height: 40px;\n background: linear-gradient(135deg, #a855f7 0%, #ec4899 50%, #f97316 100%);\n border-radius: 12px;\n display: flex;\n align-items: center;\n justify-content: center;\n font-weight: 700;\n font-size: 1.25rem;\n box-shadow: 0 0 20px rgba(168, 85, 247, 0.3);\n }\n\n .logo-text {\n display: flex;\n flex-direction: column;\n }\n\n .logo-title {\n font-weight: 700;\n font-size: 1.125rem;\n background: linear-gradient(135deg, #fff 0%, #a1a1aa 100%);\n -webkit-background-clip: text;\n -webkit-text-fill-color: transparent;\n }\n\n .logo-version {\n font-size: 0.75rem;\n color: var(--text-muted);\n font-family: 'JetBrains Mono', monospace;\n }\n\n /* Status Cards */\n .status-section {\n padding: 1.5rem;\n border-bottom: 1px solid var(--border);\n }\n\n .status-grid {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n }\n\n .status-item {\n display: flex;\n align-items: center;\n justify-content: space-between;\n padding: 0.75rem 1rem;\n background: var(--bg-card);\n border-radius: 10px;\n border: 1px solid var(--border-subtle);\n }\n\n .status-label {\n font-size: 0.8rem;\n color: var(--text-secondary);\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .status-value {\n font-size: 0.875rem;\n font-weight: 600;\n font-family: 'JetBrains Mono', monospace;\n }\n\n .status-value.connected {\n color: var(--success);\n }\n\n .status-value.active {\n color: var(--accent);\n }\n\n .status-dot {\n width: 8px;\n height: 8px;\n border-radius: 50%;\n animation: pulse 2s infinite;\n }\n\n .status-dot.green { background: var(--success); box-shadow: 0 0 8px var(--success); }\n .status-dot.purple { background: var(--accent); box-shadow: 0 0 8px var(--accent); }\n\n @keyframes pulse {\n 0%, 100% { opacity: 1; transform: scale(1); }\n 50% { opacity: 0.7; transform: scale(0.95); }\n }\n\n /* Navigation */\n .nav-section {\n padding: 1rem;\n flex: 1;\n }\n\n .nav-label {\n font-size: 0.7rem;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n color: var(--text-muted);\n padding: 0.5rem 1rem;\n margin-bottom: 0.5rem;\n }\n\n .nav-item {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n padding: 0.75rem 1rem;\n border-radius: 10px;\n color: var(--text-secondary);\n text-decoration: none;\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.2s;\n cursor: pointer;\n margin-bottom: 0.25rem;\n }\n\n .nav-item:hover {\n background: var(--bg-card);\n color: var(--text-primary);\n }\n\n .nav-item.active {\n background: var(--accent-glow);\n color: var(--accent);\n border: 1px solid rgba(168, 85, 247, 0.2);\n }\n\n .nav-icon {\n font-size: 1.1rem;\n }\n\n .nav-badge {\n margin-left: auto;\n background: var(--bg-card);\n padding: 0.125rem 0.5rem;\n border-radius: 6px;\n font-size: 0.7rem;\n font-family: 'JetBrains Mono', monospace;\n color: var(--text-muted);\n }\n\n /* Sidebar Footer */\n .sidebar-footer {\n padding: 1rem 1.5rem;\n border-top: 1px solid var(--border);\n }\n\n .docs-link {\n display: flex;\n align-items: center;\n justify-content: center;\n gap: 0.5rem;\n padding: 0.75rem;\n background: linear-gradient(135deg, rgba(168, 85, 247, 0.1), rgba(236, 72, 153, 0.1));\n border: 1px solid rgba(168, 85, 247, 0.2);\n border-radius: 10px;\n color: var(--accent);\n text-decoration: none;\n font-size: 0.875rem;\n font-weight: 500;\n transition: all 0.2s;\n }\n\n .docs-link:hover {\n background: linear-gradient(135deg, rgba(168, 85, 247, 0.2), rgba(236, 72, 153, 0.2));\n transform: translateY(-1px);\n }\n\n /* Main Content */\n .main {\n margin-left: 280px;\n flex: 1;\n padding: 2rem;\n min-height: 100vh;\n }\n\n .page-header {\n margin-bottom: 2rem;\n }\n\n .page-title {\n font-size: 1.75rem;\n font-weight: 700;\n margin-bottom: 0.5rem;\n }\n\n .page-subtitle {\n color: var(--text-secondary);\n font-size: 0.9rem;\n }\n\n /* Metrics Grid */\n .metrics-grid {\n display: grid;\n grid-template-columns: repeat(4, 1fr);\n gap: 1rem;\n margin-bottom: 2rem;\n }\n\n .metric-card {\n background: var(--bg-card);\n border: 1px solid var(--border-subtle);\n border-radius: 16px;\n padding: 1.5rem;\n transition: all 0.3s;\n position: relative;\n overflow: hidden;\n }\n\n .metric-card::before {\n content: '';\n position: absolute;\n top: 0;\n left: 0;\n right: 0;\n height: 2px;\n background: linear-gradient(90deg, var(--accent), #ec4899);\n opacity: 0;\n transition: opacity 0.3s;\n }\n\n .metric-card:hover {\n border-color: var(--accent);\n transform: translateY(-2px);\n box-shadow: 0 8px 32px rgba(168, 85, 247, 0.1);\n }\n\n .metric-card:hover::before {\n opacity: 1;\n }\n\n .metric-icon {\n font-size: 1.5rem;\n margin-bottom: 1rem;\n }\n\n .metric-value {\n font-size: 2rem;\n font-weight: 700;\n font-family: 'JetBrains Mono', monospace;\n margin-bottom: 0.25rem;\n }\n\n .metric-label {\n font-size: 0.8rem;\n color: var(--text-secondary);\n text-transform: uppercase;\n letter-spacing: 0.05em;\n }\n\n .metric-change {\n position: absolute;\n top: 1rem;\n right: 1rem;\n font-size: 0.75rem;\n padding: 0.25rem 0.5rem;\n border-radius: 6px;\n font-weight: 500;\n }\n\n .metric-change.up { background: rgba(34, 197, 94, 0.1); color: var(--success); }\n .metric-change.down { background: rgba(239, 68, 68, 0.1); color: var(--error); }\n\n /* Sections */\n .content-grid {\n display: grid;\n grid-template-columns: 1fr 1fr;\n gap: 1.5rem;\n }\n\n .section {\n background: var(--bg-card);\n border: 1px solid var(--border-subtle);\n border-radius: 16px;\n overflow: hidden;\n }\n\n .section.full-width {\n grid-column: 1 / -1;\n }\n\n .section-header {\n padding: 1.25rem 1.5rem;\n border-bottom: 1px solid var(--border);\n display: flex;\n align-items: center;\n justify-content: space-between;\n }\n\n .section-title {\n font-size: 1rem;\n font-weight: 600;\n display: flex;\n align-items: center;\n gap: 0.5rem;\n }\n\n .section-badge {\n background: var(--bg-dark);\n padding: 0.25rem 0.75rem;\n border-radius: 8px;\n font-size: 0.75rem;\n color: var(--text-muted);\n font-family: 'JetBrains Mono', monospace;\n }\n\n .section-content {\n max-height: 400px;\n overflow-y: auto;\n }\n\n /* Routes List */\n .route-item {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 1rem 1.5rem;\n border-bottom: 1px solid var(--border-subtle);\n transition: background 0.2s;\n }\n\n .route-item:last-child {\n border-bottom: none;\n }\n\n .route-item:hover {\n background: var(--bg-card-hover);\n }\n\n .route-type {\n padding: 0.25rem 0.75rem;\n border-radius: 6px;\n font-size: 0.7rem;\n font-weight: 600;\n text-transform: uppercase;\n letter-spacing: 0.05em;\n min-width: 60px;\n text-align: center;\n }\n\n .route-type.page { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }\n .route-type.api { background: rgba(34, 197, 94, 0.15); color: #4ade80; }\n .route-type.layout { background: rgba(168, 85, 247, 0.15); color: #c084fc; }\n\n .route-path {\n font-family: 'JetBrains Mono', monospace;\n font-size: 0.875rem;\n flex: 1;\n }\n\n .route-file {\n color: var(--text-muted);\n font-size: 0.75rem;\n font-family: 'JetBrains Mono', monospace;\n }\n\n /* Request Logs */\n .log-item {\n display: flex;\n align-items: center;\n gap: 1rem;\n padding: 0.875rem 1.5rem;\n border-bottom: 1px solid var(--border-subtle);\n font-size: 0.875rem;\n transition: background 0.2s;\n }\n\n .log-item:hover {\n background: var(--bg-card-hover);\n }\n\n .log-method {\n font-weight: 600;\n padding: 0.25rem 0.5rem;\n border-radius: 4px;\n font-size: 0.7rem;\n min-width: 50px;\n text-align: center;\n font-family: 'JetBrains Mono', monospace;\n }\n\n .log-method.GET { background: rgba(59, 130, 246, 0.15); color: #60a5fa; }\n .log-method.POST { background: rgba(34, 197, 94, 0.15); color: #4ade80; }\n .log-method.PUT { background: rgba(245, 158, 11, 0.15); color: #fbbf24; }\n .log-method.DELETE { background: rgba(239, 68, 68, 0.15); color: #f87171; }\n\n .log-status {\n font-weight: 600;\n font-family: 'JetBrains Mono', monospace;\n font-size: 0.8rem;\n }\n\n .log-status.s2xx { color: var(--success); }\n .log-status.s3xx { color: #60a5fa; }\n .log-status.s4xx { color: var(--warning); }\n .log-status.s5xx { color: var(--error); }\n\n .log-path {\n font-family: 'JetBrains Mono', monospace;\n flex: 1;\n color: var(--text-secondary);\n }\n\n .log-duration {\n font-family: 'JetBrains Mono', monospace;\n color: var(--text-muted);\n font-size: 0.8rem;\n }\n\n .log-time {\n color: var(--text-muted);\n font-size: 0.75rem;\n }\n\n /* Empty State */\n .empty-state {\n text-align: center;\n padding: 3rem;\n color: var(--text-muted);\n }\n\n .empty-icon {\n font-size: 2.5rem;\n margin-bottom: 1rem;\n opacity: 0.5;\n }\n\n /* Scrollbar */\n ::-webkit-scrollbar { width: 6px; }\n ::-webkit-scrollbar-track { background: transparent; }\n ::-webkit-scrollbar-thumb { background: var(--border); border-radius: 3px; }\n ::-webkit-scrollbar-thumb:hover { background: var(--text-muted); }\n\n /* Responsive */\n @media (max-width: 1200px) {\n .metrics-grid { grid-template-columns: repeat(2, 1fr); }\n .content-grid { grid-template-columns: 1fr; }\n }\n </style>\n</head>\n<body>\n <!-- Sidebar -->\n <aside class=\"sidebar\">\n <div class=\"sidebar-header\">\n <div class=\"logo\">\n <div class=\"logo-icon\">⚑</div>\n <div class=\"logo-text\">\n <span class=\"logo-title\">Float.js</span>\n <span class=\"logo-version\">v2.0.4</span>\n </div>\n </div>\n </div>\n\n <div class=\"status-section\">\n <div class=\"status-grid\">\n <div class=\"status-item\">\n <span class=\"status-label\">\n <span class=\"status-dot green\"></span>\n Estado\n </span>\n <span class=\"status-value connected\">Conectado</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">\n <span class=\"status-dot purple\"></span>\n HMR\n </span>\n <span class=\"status-value active\">Activo</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">Último build</span>\n <span class=\"status-value\">${lastBuildTime}</span>\n </div>\n <div class=\"status-item\">\n <span class=\"status-label\">Uptime</span>\n <span class=\"status-value\">${uptimeFormatted}</span>\n </div>\n </div>\n </div>\n\n <nav class=\"nav-section\">\n <div class=\"nav-label\">Dashboard</div>\n <div class=\"nav-item active\">\n <span class=\"nav-icon\">πŸ“Š</span>\n Overview\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">πŸ›€οΈ</span>\n Routes\n <span class=\"nav-badge\">${state.routes.length}</span>\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">πŸ“</span>\n Logs\n <span class=\"nav-badge\">${state.requestLogs.length}</span>\n </div>\n <div class=\"nav-item\">\n <span class=\"nav-icon\">βš™οΈ</span>\n Settings\n </div>\n </nav>\n\n <div class=\"sidebar-footer\">\n <a href=\"https://floatjs.dev/docs\" target=\"_blank\" class=\"docs-link\">\n <span>πŸ“š</span>\n Documentation\n </a>\n </div>\n </aside>\n\n <!-- Main Content -->\n <main class=\"main\">\n <div class=\"page-header\">\n <h1 class=\"page-title\">Dev Dashboard</h1>\n <p class=\"page-subtitle\">Monitor your Float.js application in real-time</p>\n </div>\n\n <!-- Metrics -->\n <div class=\"metrics-grid\">\n <div class=\"metric-card\">\n <div class=\"metric-icon\">πŸ“‘</div>\n <div class=\"metric-value\">${metrics.requests}</div>\n <div class=\"metric-label\">Total Requests</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">⚑</div>\n <div class=\"metric-value\">${metrics.avgResponseTime}ms</div>\n <div class=\"metric-label\">Avg Response</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">πŸ’Ύ</div>\n <div class=\"metric-value\">${memoryMB}/${memoryTotal}</div>\n <div class=\"metric-label\">Memory (MB)</div>\n </div>\n <div class=\"metric-card\">\n <div class=\"metric-icon\">${metrics.errorRate > 0 ? '⚠️' : 'βœ…'}</div>\n <div class=\"metric-value\">${metrics.errorRate}%</div>\n <div class=\"metric-label\">Error Rate</div>\n </div>\n </div>\n\n <!-- Content Grid -->\n <div class=\"content-grid\">\n <!-- Routes -->\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"section-title\">πŸ›€οΈ Routes</span>\n <span class=\"section-badge\">${state.routes.length} registered</span>\n </div>\n <div class=\"section-content\">\n ${state.routes.length === 0 ? `\n <div class=\"empty-state\">\n <div class=\"empty-icon\">πŸ›€οΈ</div>\n <p>No routes registered</p>\n </div>\n ` : state.routes.map(route => `\n <div class=\"route-item\">\n <span class=\"route-type ${route.type}\">${route.type}</span>\n <span class=\"route-path\">${route.path}</span>\n <span class=\"route-file\">${route.file.split('/').pop()}</span>\n </div>\n `).join('')}\n </div>\n </div>\n\n <!-- Request Logs -->\n <div class=\"section\">\n <div class=\"section-header\">\n <span class=\"section-title\">πŸ“ Request Logs</span>\n <span class=\"section-badge\">Live</span>\n </div>\n <div class=\"section-content\">\n ${state.requestLogs.length === 0 ? `\n <div class=\"empty-state\">\n <div class=\"empty-icon\">πŸ“</div>\n <p>No requests yet</p>\n </div>\n ` : state.requestLogs.slice(0, 20).map(log => {\n const statusClass = log.status < 300 ? 's2xx' : log.status < 400 ? 's3xx' : log.status < 500 ? 's4xx' : 's5xx';\n return `\n <div class=\"log-item\">\n <span class=\"log-method ${log.method}\">${log.method}</span>\n <span class=\"log-status ${statusClass}\">${log.status}</span>\n <span class=\"log-path\">${log.path}</span>\n <span class=\"log-duration\">${log.duration}ms</span>\n </div>\n `;\n }).join('')}\n </div>\n </div>\n </div>\n </main>\n\n <script>\n // Auto-refresh every 3 seconds\n setTimeout(() => location.reload(), 3000);\n </script>\n</body>\n</html>`;\n}\n\n// ============================================================================\n// DASHBOARD API\n// ============================================================================\n\nfunction generateAPIResponse(state: DevDashboardState): string {\n return JSON.stringify({\n metrics: state.getMetrics(),\n routes: state.routes,\n builds: state.builds.slice(0, 10),\n requestLogs: state.requestLogs.slice(0, 50),\n });\n}\n\n// ============================================================================\n// DASHBOARD HANDLER\n// ============================================================================\n\nexport function createDevDashboard(options: DevDashboardOptions = {}) {\n const {\n enabled = process.env.NODE_ENV !== 'production',\n path = '/__float',\n auth,\n } = options;\n\n if (!enabled) {\n return (_req: IncomingMessage, _res: ServerResponse, next: () => void) => next();\n }\n\n return (req: IncomingMessage, res: ServerResponse, next: () => void) => {\n const url = req.url || '';\n \n // Check if this is a dashboard request\n if (!url.startsWith(path)) {\n return next();\n }\n\n // Basic auth if configured\n if (auth) {\n const authHeader = req.headers.authorization;\n if (!authHeader || !authHeader.startsWith('Basic ')) {\n res.setHeader('WWW-Authenticate', 'Basic realm=\"Float.js Dev Dashboard\"');\n res.statusCode = 401;\n res.end('Unauthorized');\n return;\n }\n\n const credentials = Buffer.from(authHeader.slice(6), 'base64').toString();\n const [username, password] = credentials.split(':');\n \n if (username !== auth.username || password !== auth.password) {\n res.statusCode = 401;\n res.end('Invalid credentials');\n return;\n }\n }\n\n // Route dashboard requests\n const subPath = url.slice(path.length);\n\n if (subPath === '' || subPath === '/') {\n // Main dashboard\n res.setHeader('Content-Type', 'text/html');\n res.end(generateDashboardHTML(dashboardState));\n return;\n }\n\n if (subPath === '/api' || subPath === '/api/') {\n // API endpoint\n res.setHeader('Content-Type', 'application/json');\n res.end(generateAPIResponse(dashboardState));\n return;\n }\n\n if (subPath === '/api/routes') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.routes));\n return;\n }\n\n if (subPath === '/api/metrics') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.getMetrics()));\n return;\n }\n\n if (subPath === '/api/logs') {\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify(dashboardState.requestLogs.slice(0, 100)));\n return;\n }\n\n if (subPath === '/api/clear' && req.method === 'POST') {\n dashboardState.clear();\n res.setHeader('Content-Type', 'application/json');\n res.end(JSON.stringify({ success: true }));\n return;\n }\n\n // 404 for unknown dashboard routes\n res.statusCode = 404;\n res.end('Not found');\n };\n}\n\n// ============================================================================\n// EXPORTS\n// ============================================================================\n\nexport const devtools = {\n dashboard: createDevDashboard,\n logger: createRequestLogger,\n state: dashboardState,\n \n // Helpers for manual logging\n logRoute: (route: RouteInfo) => dashboardState.addRoute(route),\n logBuild: (build: BuildInfo) => dashboardState.addBuild(build),\n logRequest: (log: RequestLog) => dashboardState.logRequest(log),\n getMetrics: () => dashboardState.getMetrics(),\n clear: () => dashboardState.clear(),\n};\n"],"mappings":"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A;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAA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","names":[]}
package/dist/index.d.ts CHANGED
@@ -15,7 +15,7 @@ import 'ws';
15
15
  import 'http';
16
16
  import 'events';
17
17
 
18
- declare const VERSION = "2.0.1";
18
+ declare const VERSION = "2.0.4";
19
19
 
20
20
  /**
21
21
  * Float.js Build System
@@ -297,7 +297,7 @@ declare function combineFloatStores<T extends Record<string, FloatStore<any>>>(s
297
297
 
298
298
  /**
299
299
  * Float.js Welcome Page
300
- * Shown when users first install the framework
300
+ * Modern, minimal welcome screen inspired by Next.js
301
301
  */
302
302
  declare function generateWelcomePage(): string;
303
303