@runtimescope/collector 0.6.0

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.
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/server.ts","../src/ring-buffer.ts","../src/store.ts","../src/sqlite-store.ts","../src/rate-limiter.ts","../src/tls.ts","../src/issue-detector.ts","../src/project-manager.ts","../src/auth.ts","../src/redactor.ts","../src/engines/api-discovery.ts","../src/engines/query-monitor.ts","../src/db/connections.ts","../src/db/schema-introspector.ts","../src/db/data-browser.ts","../src/engines/process-monitor.ts","../src/engines/infra-connector.ts","../src/session-manager.ts","../src/session-differ.ts","../src/http-server.ts"],"sourcesContent":["import { createServer as createHttpsServer } from 'node:https';\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport { EventStore } from './store.js';\nimport { ProjectManager } from './project-manager.js';\nimport { SqliteStore } from './sqlite-store.js';\nimport { AuthManager } from './auth.js';\nimport { SessionRateLimiter, type RateLimitConfig } from './rate-limiter.js';\nimport { loadTlsOptions, type TlsConfig } from './tls.js';\nimport type {\n WSMessage,\n HandshakePayload,\n EventBatchPayload,\n CommandResponse,\n SessionInfoExtended,\n} from './types.js';\n\nexport interface CollectorServerOptions {\n port?: number;\n host?: string;\n bufferSize?: number;\n maxRetries?: number;\n retryDelayMs?: number;\n projectManager?: ProjectManager;\n authManager?: AuthManager;\n rateLimits?: RateLimitConfig;\n tls?: TlsConfig;\n}\n\ninterface ClientInfo {\n sessionId: string;\n projectName: string;\n}\n\ninterface PendingCommand {\n resolve: (value: unknown) => void;\n reject: (reason: Error) => void;\n timer: ReturnType<typeof setTimeout>;\n}\n\nexport class CollectorServer {\n private wss: WebSocketServer | null = null;\n private store: EventStore;\n private projectManager: ProjectManager | null;\n private authManager: AuthManager | null = null;\n private rateLimiter: SessionRateLimiter;\n private clients: Map<WebSocket, ClientInfo> = new Map();\n private pendingHandshakes: Set<WebSocket> = new Set();\n private pendingCommands: Map<string, PendingCommand> = new Map();\n private sqliteStores: Map<string, SqliteStore> = new Map();\n private disconnectCallbacks: ((sessionId: string, projectName: string) => void)[] = [];\n private pruneTimer: ReturnType<typeof setInterval> | null = null;\n private tlsConfig: TlsConfig | null = null;\n\n constructor(options: CollectorServerOptions = {}) {\n this.store = new EventStore(options.bufferSize ?? 10_000);\n this.projectManager = options.projectManager ?? null;\n this.authManager = options.authManager ?? null;\n this.rateLimiter = new SessionRateLimiter(options.rateLimits ?? {});\n this.tlsConfig = options.tls ?? null;\n\n if (this.projectManager) {\n this.projectManager.ensureGlobalDir();\n }\n\n // Periodically prune stale rate limiter entries\n if (this.rateLimiter.isEnabled()) {\n this.pruneTimer = setInterval(() => this.rateLimiter.prune(), 60_000);\n }\n }\n\n getStore(): EventStore {\n return this.store;\n }\n\n getPort(): number | null {\n const addr = this.wss?.address();\n return addr && typeof addr === 'object' ? addr.port : null;\n }\n\n getClientCount(): number {\n return this.clients.size;\n }\n\n getProjectManager(): ProjectManager | null {\n return this.projectManager;\n }\n\n getSqliteStore(projectName: string): SqliteStore | undefined {\n return this.sqliteStores.get(projectName);\n }\n\n getSqliteStores(): Map<string, SqliteStore> {\n return this.sqliteStores;\n }\n\n getRateLimiter(): SessionRateLimiter {\n return this.rateLimiter;\n }\n\n onDisconnect(cb: (sessionId: string, projectName: string) => void): void {\n this.disconnectCallbacks.push(cb);\n }\n\n start(options: CollectorServerOptions = {}): Promise<void> {\n const port = options.port ?? 9090;\n const host = options.host ?? '127.0.0.1';\n const maxRetries = options.maxRetries ?? 5;\n const retryDelayMs = options.retryDelayMs ?? 1000;\n const tls = options.tls ?? this.tlsConfig;\n\n return this.tryStart(port, host, maxRetries, retryDelayMs, tls);\n }\n\n private tryStart(\n port: number,\n host: string,\n retriesLeft: number,\n retryDelayMs: number,\n tls?: TlsConfig | null\n ): Promise<void> {\n return new Promise((resolve, reject) => {\n let wss: WebSocketServer;\n\n if (tls) {\n // TLS mode: create HTTPS server, then attach WebSocket to it\n const httpsServer = createHttpsServer(loadTlsOptions(tls));\n wss = new WebSocketServer({ server: httpsServer });\n\n httpsServer.on('listening', () => {\n this.wss = wss;\n this.setupConnectionHandler(wss);\n console.error(`[RuntimeScope] Collector listening on wss://${host}:${port}`);\n resolve();\n });\n\n httpsServer.on('error', (err: NodeJS.ErrnoException) => {\n httpsServer.close();\n this.handleStartError(err, port, host, retriesLeft, retryDelayMs, tls, resolve, reject);\n });\n\n httpsServer.listen(port, host);\n } else {\n // Plain WS mode (default — backward compatible)\n wss = new WebSocketServer({ port, host });\n\n wss.on('listening', () => {\n this.wss = wss;\n this.setupConnectionHandler(wss);\n console.error(`[RuntimeScope] Collector listening on ws://${host}:${port}`);\n resolve();\n });\n\n wss.on('error', (err: NodeJS.ErrnoException) => {\n wss.close();\n this.handleStartError(err, port, host, retriesLeft, retryDelayMs, tls, resolve, reject);\n });\n }\n });\n }\n\n private handleStartError(\n err: NodeJS.ErrnoException,\n port: number,\n host: string,\n retriesLeft: number,\n retryDelayMs: number,\n tls: TlsConfig | null | undefined,\n resolve: () => void,\n reject: (err: Error) => void\n ): void {\n if (err.code === 'EADDRINUSE' && retriesLeft > 0) {\n console.error(\n `[RuntimeScope] Port ${port} in use, retrying in ${retryDelayMs}ms (${retriesLeft} attempts left)...`\n );\n setTimeout(() => {\n this.tryStart(port, host, retriesLeft - 1, retryDelayMs, tls)\n .then(resolve)\n .catch(reject);\n }, retryDelayMs);\n } else {\n console.error('[RuntimeScope] WebSocket server error:', err.message);\n reject(err);\n }\n }\n\n private ensureSqliteStore(projectName: string): SqliteStore | null {\n if (!this.projectManager) return null;\n\n let sqliteStore = this.sqliteStores.get(projectName);\n if (!sqliteStore) {\n try {\n this.projectManager.ensureProjectDir(projectName);\n const dbPath = this.projectManager.getProjectDbPath(projectName);\n sqliteStore = new SqliteStore({ dbPath });\n this.sqliteStores.set(projectName, sqliteStore);\n this.store.setSqliteStore(sqliteStore, projectName);\n console.error(`[RuntimeScope] SQLite store opened for project \"${projectName}\"`);\n } catch (err) {\n console.error(\n `[RuntimeScope] Failed to open SQLite for \"${projectName}\":`,\n (err as Error).message\n );\n return null;\n }\n }\n return sqliteStore;\n }\n\n private setupConnectionHandler(wss: WebSocketServer): void {\n wss.on('connection', (ws) => {\n // If auth is enabled, the connection starts in a pending state.\n // The first message must be a valid handshake with an authToken.\n if (this.authManager?.isEnabled()) {\n this.pendingHandshakes.add(ws);\n\n // Auto-close if no valid handshake within 5 seconds\n const authTimeout = setTimeout(() => {\n if (this.pendingHandshakes.has(ws)) {\n this.pendingHandshakes.delete(ws);\n try {\n ws.send(JSON.stringify({\n type: 'error',\n payload: { code: 'AUTH_TIMEOUT', message: 'Handshake timeout' },\n timestamp: Date.now(),\n }));\n } catch { /* ignore */ }\n ws.close(4001, 'Authentication timeout');\n }\n }, 5000);\n\n ws.on('close', () => {\n clearTimeout(authTimeout);\n this.pendingHandshakes.delete(ws);\n });\n }\n\n ws.on('message', (data) => {\n try {\n const msg: WSMessage = JSON.parse(data.toString());\n this.handleMessage(ws, msg);\n } catch {\n console.error('[RuntimeScope] Malformed WebSocket message, ignoring');\n }\n });\n\n ws.on('close', () => {\n const clientInfo = this.clients.get(ws);\n if (clientInfo) {\n this.store.markDisconnected(clientInfo.sessionId);\n\n // Update SQLite session record\n const sqliteStore = this.sqliteStores.get(clientInfo.projectName);\n if (sqliteStore) {\n sqliteStore.updateSessionDisconnected(clientInfo.sessionId, Date.now());\n }\n\n console.error(`[RuntimeScope] Session ${clientInfo.sessionId} disconnected`);\n\n // Notify disconnect listeners (for session snapshotting)\n for (const cb of this.disconnectCallbacks) {\n try {\n cb(clientInfo.sessionId, clientInfo.projectName);\n } catch {\n // Don't let listener errors break disconnect handling\n }\n }\n }\n this.clients.delete(ws);\n });\n\n ws.on('error', (err) => {\n console.error('[RuntimeScope] WebSocket client error:', err.message);\n });\n });\n }\n\n private handleMessage(ws: WebSocket, msg: WSMessage): void {\n switch (msg.type) {\n case 'handshake': {\n const payload = msg.payload as HandshakePayload;\n\n // Authenticate if auth is enabled\n if (this.authManager?.isEnabled()) {\n if (!this.authManager.isAuthorized(payload.authToken)) {\n try {\n ws.send(JSON.stringify({\n type: 'error',\n payload: { code: 'AUTH_FAILED', message: 'Invalid or missing API key' },\n timestamp: Date.now(),\n }));\n } catch { /* ignore */ }\n ws.close(4001, 'Authentication failed');\n return;\n }\n this.pendingHandshakes.delete(ws);\n }\n\n const projectName = payload.appName;\n\n this.clients.set(ws, {\n sessionId: payload.sessionId,\n projectName,\n });\n\n // Initialize SQLite for this project\n const sqliteStore = this.ensureSqliteStore(projectName);\n\n // Save session info to SQLite\n if (sqliteStore) {\n const sessionInfo: SessionInfoExtended = {\n sessionId: payload.sessionId,\n project: projectName,\n appName: payload.appName,\n connectedAt: msg.timestamp,\n sdkVersion: payload.sdkVersion,\n eventCount: 0,\n isConnected: true,\n };\n sqliteStore.saveSession(sessionInfo);\n }\n\n console.error(\n `[RuntimeScope] Session ${payload.sessionId} connected (${payload.appName} v${payload.sdkVersion})`\n );\n break;\n }\n case 'event': {\n // Reject events from unauthenticated connections\n if (this.pendingHandshakes.has(ws)) return;\n\n const clientInfo = this.clients.get(ws);\n const payload = msg.payload as EventBatchPayload;\n if (Array.isArray(payload.events)) {\n for (const event of payload.events) {\n // Rate limit per session\n if (clientInfo && !this.rateLimiter.allow(clientInfo.sessionId)) {\n break; // drop remaining events in this batch\n }\n this.store.addEvent(event);\n }\n }\n break;\n }\n case 'command_response': {\n const resp = msg as unknown as CommandResponse;\n const pending = this.pendingCommands.get(resp.requestId);\n if (pending) {\n clearTimeout(pending.timer);\n this.pendingCommands.delete(resp.requestId);\n pending.resolve(resp.payload);\n }\n break;\n }\n case 'heartbeat':\n break;\n }\n }\n\n /** Find the WebSocket for a given sessionId */\n private findWsBySessionId(sessionId: string): WebSocket | undefined {\n for (const [ws, info] of this.clients) {\n if (info.sessionId === sessionId) return ws;\n }\n return undefined;\n }\n\n /** Get the first connected session ID (for single-app use) */\n getFirstSessionId(): string | undefined {\n for (const [, info] of this.clients) {\n return info.sessionId;\n }\n return undefined;\n }\n\n /** Get the project name for a session */\n getProjectForSession(sessionId: string): string | undefined {\n for (const [, info] of this.clients) {\n if (info.sessionId === sessionId) return info.projectName;\n }\n return undefined;\n }\n\n /** Send a command to the SDK and await the response */\n sendCommand(\n sessionId: string,\n command: { command: string; requestId: string; params?: Record<string, unknown> },\n timeoutMs = 10_000\n ): Promise<unknown> {\n return new Promise((resolve, reject) => {\n const ws = this.findWsBySessionId(sessionId);\n if (!ws || ws.readyState !== 1 /* OPEN */) {\n reject(new Error(`No active WebSocket for session ${sessionId}`));\n return;\n }\n\n const timer = setTimeout(() => {\n this.pendingCommands.delete(command.requestId);\n reject(new Error(`Command ${command.command} timed out after ${timeoutMs}ms`));\n }, timeoutMs);\n\n this.pendingCommands.set(command.requestId, { resolve, reject, timer });\n\n try {\n ws.send(JSON.stringify({\n type: 'command',\n payload: command,\n timestamp: Date.now(),\n sessionId,\n }));\n } catch (err) {\n clearTimeout(timer);\n this.pendingCommands.delete(command.requestId);\n reject(err);\n }\n });\n }\n\n stop(): void {\n // Stop rate limiter pruning\n if (this.pruneTimer) {\n clearInterval(this.pruneTimer);\n this.pruneTimer = null;\n }\n\n // Close all SQLite stores\n for (const [name, sqliteStore] of this.sqliteStores) {\n try {\n sqliteStore.close();\n console.error(`[RuntimeScope] SQLite store closed for \"${name}\"`);\n } catch {\n // Ignore close errors during shutdown\n }\n }\n this.sqliteStores.clear();\n\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n console.error('[RuntimeScope] Collector stopped');\n }\n }\n}\n","/**\n * Fixed-size circular buffer. When full, new items overwrite the oldest.\n * Optimized for append-heavy workloads with periodic filtered scans.\n */\nexport class RingBuffer<T> {\n private buffer: (T | undefined)[];\n private head: number = 0;\n private _count: number = 0;\n\n constructor(private capacity: number) {\n this.buffer = new Array(capacity);\n }\n\n get count(): number {\n return this._count;\n }\n\n push(item: T): void {\n this.buffer[this.head] = item;\n this.head = (this.head + 1) % this.capacity;\n if (this._count < this.capacity) this._count++;\n }\n\n /** Returns all items from oldest to newest. */\n toArray(): T[] {\n if (this._count === 0) return [];\n const result: T[] = [];\n const start = this._count < this.capacity ? 0 : this.head;\n for (let i = 0; i < this._count; i++) {\n const idx = (start + i) % this.capacity;\n result.push(this.buffer[idx] as T);\n }\n return result;\n }\n\n /** Returns matching items from newest to oldest (most recent first). */\n query(predicate: (item: T) => boolean): T[] {\n if (this._count === 0) return [];\n const result: T[] = [];\n const start = this._count < this.capacity ? 0 : this.head;\n for (let i = this._count - 1; i >= 0; i--) {\n const idx = (start + i) % this.capacity;\n const item = this.buffer[idx] as T;\n if (predicate(item)) result.push(item);\n }\n return result;\n }\n\n clear(): void {\n this.buffer = new Array(this.capacity);\n this.head = 0;\n this._count = 0;\n }\n}\n","import { RingBuffer } from './ring-buffer.js';\nimport type { SqliteStore } from './sqlite-store.js';\nimport type { Redactor } from './redactor.js';\nimport type {\n RuntimeEvent,\n NetworkEvent,\n ConsoleEvent,\n SessionEvent,\n StateEvent,\n RenderEvent,\n PerformanceEvent,\n DatabaseEvent,\n ReconMetadataEvent,\n ReconDesignTokensEvent,\n ReconFontsEvent,\n ReconLayoutTreeEvent,\n ReconAccessibilityEvent,\n ReconComputedStylesEvent,\n ReconElementSnapshotEvent,\n ReconAssetInventoryEvent,\n NetworkFilter,\n ConsoleFilter,\n StateFilter,\n RenderFilter,\n PerformanceFilter,\n DatabaseFilter,\n ReconFilter,\n ReconEventType,\n SessionInfo,\n TimelineFilter,\n EventType,\n} from './types.js';\n\nexport class EventStore {\n private buffer: RingBuffer<RuntimeEvent>;\n private sessions: Map<string, SessionInfo> = new Map();\n private sqliteStore: SqliteStore | null = null;\n private currentProject: string | null = null;\n private onEventCallbacks: ((event: RuntimeEvent) => void)[] = [];\n private redactor: Redactor | null = null;\n\n constructor(capacity = 10_000) {\n this.buffer = new RingBuffer<RuntimeEvent>(capacity);\n }\n\n setRedactor(redactor: Redactor): void {\n this.redactor = redactor;\n }\n\n get eventCount(): number {\n return this.buffer.count;\n }\n\n setSqliteStore(store: SqliteStore, project: string): void {\n this.sqliteStore = store;\n this.currentProject = project;\n }\n\n onEvent(callback: (event: RuntimeEvent) => void): void {\n this.onEventCallbacks.push(callback);\n }\n\n removeEventListener(callback: (event: RuntimeEvent) => void): void {\n const idx = this.onEventCallbacks.indexOf(callback);\n if (idx !== -1) this.onEventCallbacks.splice(idx, 1);\n }\n\n addEvent(event: RuntimeEvent): void {\n // Apply redaction before storing (defense in depth)\n if (this.redactor?.isEnabled()) {\n event = this.redactor.redactEvent(event);\n }\n\n this.buffer.push(event);\n\n if (event.eventType === 'session') {\n const se = event as SessionEvent;\n this.sessions.set(se.sessionId, {\n sessionId: se.sessionId,\n appName: se.appName,\n connectedAt: se.connectedAt,\n sdkVersion: se.sdkVersion,\n eventCount: 0,\n isConnected: true,\n });\n }\n\n const session = this.sessions.get(event.sessionId);\n if (session) session.eventCount++;\n\n // SQLite dual-write\n if (this.sqliteStore && this.currentProject) {\n this.sqliteStore.addEvent(event, this.currentProject);\n }\n\n // Notify listeners\n for (const cb of this.onEventCallbacks) {\n try {\n cb(event);\n } catch {\n // Don't let listener errors break event ingestion\n }\n }\n }\n\n getNetworkRequests(filter: NetworkFilter = {}): NetworkEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'network') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const ne = e as NetworkEvent;\n if (ne.timestamp < since) return false;\n if (filter.urlPattern && !ne.url.includes(filter.urlPattern)) return false;\n if (filter.status !== undefined && ne.status !== filter.status) return false;\n if (filter.method && ne.method.toUpperCase() !== filter.method.toUpperCase())\n return false;\n return true;\n }) as NetworkEvent[];\n }\n\n getConsoleMessages(filter: ConsoleFilter = {}): ConsoleEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'console') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const ce = e as ConsoleEvent;\n if (ce.timestamp < since) return false;\n if (filter.level && ce.level !== filter.level) return false;\n if (filter.search && !ce.message.toLowerCase().includes(filter.search.toLowerCase()))\n return false;\n return true;\n }) as ConsoleEvent[];\n }\n\n getSessionInfo(): SessionInfo[] {\n return Array.from(this.sessions.values());\n }\n\n markDisconnected(sessionId: string): void {\n const s = this.sessions.get(sessionId);\n if (s) s.isConnected = false;\n }\n\n getEventTimeline(filter: TimelineFilter = {}): RuntimeEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n const typeSet = filter.eventTypes\n ? new Set<EventType>(filter.eventTypes)\n : null;\n\n // toArray returns oldest→newest (chronological order)\n return this.buffer.toArray().filter((e) => {\n if (e.timestamp < since) return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n if (typeSet && !typeSet.has(e.eventType)) return false;\n return true;\n });\n }\n\n getAllEvents(sinceSeconds?: number, sessionId?: string): RuntimeEvent[] {\n const since = sinceSeconds ? Date.now() - sinceSeconds * 1000 : 0;\n return this.buffer.toArray().filter((e) => {\n if (e.timestamp < since) return false;\n if (sessionId && e.sessionId !== sessionId) return false;\n return true;\n });\n }\n\n getSessionIdsForProject(appName: string): string[] {\n return Array.from(this.sessions.values())\n .filter((s) => s.appName === appName)\n .map((s) => s.sessionId);\n }\n\n getStateEvents(filter: StateFilter = {}): StateEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'state') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const se = e as StateEvent;\n if (se.timestamp < since) return false;\n if (filter.storeId && se.storeId !== filter.storeId) return false;\n return true;\n }) as StateEvent[];\n }\n\n getRenderEvents(filter: RenderFilter = {}): RenderEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'render') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const re = e as RenderEvent;\n if (re.timestamp < since) return false;\n if (filter.componentName) {\n const hasMatch = re.profiles.some((p) =>\n p.componentName.toLowerCase().includes(filter.componentName!.toLowerCase())\n );\n if (!hasMatch) return false;\n }\n return true;\n }) as RenderEvent[];\n }\n\n getPerformanceMetrics(filter: PerformanceFilter = {}): PerformanceEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'performance') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const pe = e as PerformanceEvent;\n if (pe.timestamp < since) return false;\n if (filter.metricName && pe.metricName !== filter.metricName) return false;\n return true;\n }) as PerformanceEvent[];\n }\n\n getDatabaseEvents(filter: DatabaseFilter = {}): DatabaseEvent[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== 'database') return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n const de = e as DatabaseEvent;\n if (de.timestamp < since) return false;\n if (filter.table) {\n const hasTable = de.tablesAccessed.some(\n (t) => t.toLowerCase() === filter.table!.toLowerCase()\n );\n if (!hasTable) return false;\n }\n if (filter.minDurationMs !== undefined && de.duration < filter.minDurationMs) return false;\n if (filter.search && !de.query.toLowerCase().includes(filter.search.toLowerCase()))\n return false;\n if (filter.operation && de.operation !== filter.operation) return false;\n if (filter.source && de.source !== filter.source) return false;\n return true;\n }) as DatabaseEvent[];\n }\n\n // ============================================================\n // Recon event queries — returns the most recent event of each type\n // ============================================================\n\n private getLatestReconEvent<T extends RuntimeEvent>(\n eventType: ReconEventType,\n filter: ReconFilter = {},\n ): T | null {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n // query() returns newest-first, so the first match is the most recent\n const results = this.buffer.query((e) => {\n if (e.eventType !== eventType) return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n if (e.timestamp < since) return false;\n if (filter.url) {\n const re = e as unknown as { url?: string };\n if (re.url && !re.url.includes(filter.url)) return false;\n }\n return true;\n });\n\n return (results[0] as T) ?? null;\n }\n\n private getReconEvents<T extends RuntimeEvent>(\n eventType: ReconEventType,\n filter: ReconFilter = {},\n ): T[] {\n const since = filter.sinceSeconds\n ? Date.now() - filter.sinceSeconds * 1000\n : 0;\n\n return this.buffer.query((e) => {\n if (e.eventType !== eventType) return false;\n if (filter.sessionId && e.sessionId !== filter.sessionId) return false;\n if (e.timestamp < since) return false;\n if (filter.url) {\n const re = e as unknown as { url?: string };\n if (re.url && !re.url.includes(filter.url)) return false;\n }\n return true;\n }) as T[];\n }\n\n getReconMetadata(filter: ReconFilter = {}): ReconMetadataEvent | null {\n return this.getLatestReconEvent<ReconMetadataEvent>('recon_metadata', filter);\n }\n\n getReconDesignTokens(filter: ReconFilter = {}): ReconDesignTokensEvent | null {\n return this.getLatestReconEvent<ReconDesignTokensEvent>('recon_design_tokens', filter);\n }\n\n getReconFonts(filter: ReconFilter = {}): ReconFontsEvent | null {\n return this.getLatestReconEvent<ReconFontsEvent>('recon_fonts', filter);\n }\n\n getReconLayoutTree(filter: ReconFilter = {}): ReconLayoutTreeEvent | null {\n return this.getLatestReconEvent<ReconLayoutTreeEvent>('recon_layout_tree', filter);\n }\n\n getReconAccessibility(filter: ReconFilter = {}): ReconAccessibilityEvent | null {\n return this.getLatestReconEvent<ReconAccessibilityEvent>('recon_accessibility', filter);\n }\n\n getReconComputedStyles(filter: ReconFilter = {}): ReconComputedStylesEvent[] {\n return this.getReconEvents<ReconComputedStylesEvent>('recon_computed_styles', filter);\n }\n\n getReconElementSnapshots(filter: ReconFilter = {}): ReconElementSnapshotEvent[] {\n return this.getReconEvents<ReconElementSnapshotEvent>('recon_element_snapshot', filter);\n }\n\n getReconAssetInventory(filter: ReconFilter = {}): ReconAssetInventoryEvent | null {\n return this.getLatestReconEvent<ReconAssetInventoryEvent>('recon_asset_inventory', filter);\n }\n\n clear(): { clearedCount: number } {\n const count = this.buffer.count;\n this.buffer.clear();\n this.sessions.clear();\n return { clearedCount: count };\n }\n}\n","import Database from 'better-sqlite3';\nimport type {\n RuntimeEvent,\n HistoricalFilter,\n SessionInfoExtended,\n EventType,\n} from './types.js';\n\n// ============================================================\n// SQLite Persistence Layer\n// Uses write buffering for high-throughput event ingestion\n// ============================================================\n\nexport interface SqliteStoreOptions {\n dbPath: string;\n walMode?: boolean;\n flushIntervalMs?: number;\n batchSize?: number;\n}\n\nexport class SqliteStore {\n private db: InstanceType<typeof Database>;\n private writeBuffer: { event: RuntimeEvent; project: string }[] = [];\n private flushTimer: ReturnType<typeof setInterval> | null = null;\n private readonly batchSize: number;\n\n private insertEventStmt: Database.Statement;\n private insertSessionStmt: Database.Statement;\n private updateSessionDisconnectedStmt: Database.Statement;\n\n constructor(options: SqliteStoreOptions) {\n this.db = new Database(options.dbPath);\n this.batchSize = options.batchSize ?? 50;\n\n if (options.walMode !== false) {\n this.db.pragma('journal_mode = WAL');\n }\n this.db.pragma('synchronous = NORMAL');\n\n this.createSchema();\n\n // Prepare statements\n this.insertEventStmt = this.db.prepare(`\n INSERT INTO events (event_id, session_id, project, event_type, timestamp, data)\n VALUES (?, ?, ?, ?, ?, ?)\n `);\n\n this.insertSessionStmt = this.db.prepare(`\n INSERT OR REPLACE INTO sessions (\n session_id, project, app_name, connected_at, sdk_version,\n event_count, is_connected, build_meta\n ) VALUES (?, ?, ?, ?, ?, ?, ?, ?)\n `);\n\n this.updateSessionDisconnectedStmt = this.db.prepare(`\n UPDATE sessions SET is_connected = 0, disconnected_at = ? WHERE session_id = ?\n `);\n\n // Start flush timer\n const flushInterval = options.flushIntervalMs ?? 100;\n this.flushTimer = setInterval(() => this.flush(), flushInterval);\n }\n\n private createSchema(): void {\n this.db.exec(`\n CREATE TABLE IF NOT EXISTS events (\n id INTEGER PRIMARY KEY AUTOINCREMENT,\n event_id TEXT NOT NULL UNIQUE,\n session_id TEXT NOT NULL,\n project TEXT NOT NULL,\n event_type TEXT NOT NULL,\n timestamp INTEGER NOT NULL,\n data TEXT NOT NULL\n );\n\n CREATE INDEX IF NOT EXISTS idx_events_session ON events(session_id);\n CREATE INDEX IF NOT EXISTS idx_events_type ON events(event_type);\n CREATE INDEX IF NOT EXISTS idx_events_timestamp ON events(timestamp);\n CREATE INDEX IF NOT EXISTS idx_events_type_timestamp ON events(event_type, timestamp);\n CREATE INDEX IF NOT EXISTS idx_events_project ON events(project);\n\n CREATE TABLE IF NOT EXISTS sessions (\n session_id TEXT PRIMARY KEY,\n project TEXT NOT NULL,\n app_name TEXT NOT NULL,\n connected_at INTEGER NOT NULL,\n disconnected_at INTEGER,\n sdk_version TEXT NOT NULL,\n event_count INTEGER DEFAULT 0,\n is_connected INTEGER DEFAULT 1,\n build_meta TEXT\n );\n\n CREATE INDEX IF NOT EXISTS idx_sessions_project ON sessions(project);\n\n CREATE TABLE IF NOT EXISTS session_metrics (\n session_id TEXT PRIMARY KEY,\n project TEXT NOT NULL,\n metrics TEXT NOT NULL,\n created_at INTEGER NOT NULL,\n FOREIGN KEY (session_id) REFERENCES sessions(session_id)\n );\n `);\n }\n\n // --- Write Operations ---\n\n addEvent(event: RuntimeEvent, project: string): void {\n this.writeBuffer.push({ event, project });\n if (this.writeBuffer.length >= this.batchSize) {\n this.flush();\n }\n }\n\n flush(): void {\n if (this.writeBuffer.length === 0) return;\n\n const batch = this.writeBuffer.splice(0);\n const insertMany = this.db.transaction(() => {\n for (const { event, project } of batch) {\n try {\n this.insertEventStmt.run(\n event.eventId,\n event.sessionId,\n project,\n event.eventType,\n event.timestamp,\n JSON.stringify(event)\n );\n } catch {\n // Ignore duplicate event_id (UNIQUE constraint)\n }\n }\n });\n\n try {\n insertMany();\n } catch (err) {\n console.error('[RuntimeScope] SQLite flush error:', (err as Error).message);\n }\n }\n\n saveSession(info: SessionInfoExtended): void {\n this.insertSessionStmt.run(\n info.sessionId,\n info.project,\n info.appName,\n info.connectedAt,\n info.sdkVersion,\n info.eventCount,\n info.isConnected ? 1 : 0,\n info.buildMeta ? JSON.stringify(info.buildMeta) : null\n );\n }\n\n updateSessionDisconnected(sessionId: string, disconnectedAt: number): void {\n this.updateSessionDisconnectedStmt.run(disconnectedAt, sessionId);\n }\n\n saveSessionMetrics(sessionId: string, project: string, metrics: unknown): void {\n this.db.prepare(`\n INSERT OR REPLACE INTO session_metrics (session_id, project, metrics, created_at)\n VALUES (?, ?, ?, ?)\n `).run(sessionId, project, JSON.stringify(metrics), Date.now());\n }\n\n // --- Read Operations ---\n\n getEvents(filter: HistoricalFilter): RuntimeEvent[] {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (filter.project) {\n conditions.push('project = ?');\n params.push(filter.project);\n }\n if (filter.sessionId) {\n conditions.push('session_id = ?');\n params.push(filter.sessionId);\n }\n if (filter.eventTypes && filter.eventTypes.length > 0) {\n const placeholders = filter.eventTypes.map(() => '?').join(', ');\n conditions.push(`event_type IN (${placeholders})`);\n params.push(...filter.eventTypes);\n }\n if (filter.since) {\n conditions.push('timestamp >= ?');\n params.push(filter.since);\n }\n if (filter.until) {\n conditions.push('timestamp <= ?');\n params.push(filter.until);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const limit = filter.limit ? `LIMIT ${filter.limit}` : 'LIMIT 1000';\n const offset = filter.offset ? `OFFSET ${filter.offset}` : '';\n\n const rows = this.db\n .prepare(`SELECT data FROM events ${where} ORDER BY timestamp ASC ${limit} ${offset}`)\n .all(...params) as { data: string }[];\n\n return rows.map((row) => JSON.parse(row.data) as RuntimeEvent);\n }\n\n getEventCount(filter: HistoricalFilter): number {\n const conditions: string[] = [];\n const params: unknown[] = [];\n\n if (filter.project) {\n conditions.push('project = ?');\n params.push(filter.project);\n }\n if (filter.sessionId) {\n conditions.push('session_id = ?');\n params.push(filter.sessionId);\n }\n if (filter.eventTypes && filter.eventTypes.length > 0) {\n const placeholders = filter.eventTypes.map(() => '?').join(', ');\n conditions.push(`event_type IN (${placeholders})`);\n params.push(...filter.eventTypes);\n }\n if (filter.since) {\n conditions.push('timestamp >= ?');\n params.push(filter.since);\n }\n if (filter.until) {\n conditions.push('timestamp <= ?');\n params.push(filter.until);\n }\n\n const where = conditions.length > 0 ? `WHERE ${conditions.join(' AND ')}` : '';\n const row = this.db\n .prepare(`SELECT COUNT(*) as count FROM events ${where}`)\n .get(...params) as { count: number };\n\n return row.count;\n }\n\n getSessions(project: string, limit = 50): SessionInfoExtended[] {\n const rows = this.db\n .prepare(`\n SELECT session_id, project, app_name, connected_at, disconnected_at,\n sdk_version, event_count, is_connected, build_meta\n FROM sessions\n WHERE project = ?\n ORDER BY connected_at DESC\n LIMIT ?\n `)\n .all(project, limit) as {\n session_id: string;\n project: string;\n app_name: string;\n connected_at: number;\n disconnected_at: number | null;\n sdk_version: string;\n event_count: number;\n is_connected: number;\n build_meta: string | null;\n }[];\n\n return rows.map((row) => ({\n sessionId: row.session_id,\n project: row.project,\n appName: row.app_name,\n connectedAt: row.connected_at,\n disconnectedAt: row.disconnected_at ?? undefined,\n sdkVersion: row.sdk_version,\n eventCount: row.event_count,\n isConnected: row.is_connected === 1,\n buildMeta: row.build_meta ? JSON.parse(row.build_meta) : undefined,\n }));\n }\n\n getSessionMetrics(sessionId: string): unknown | null {\n const row = this.db\n .prepare('SELECT metrics FROM session_metrics WHERE session_id = ?')\n .get(sessionId) as { metrics: string } | undefined;\n\n return row ? JSON.parse(row.metrics) : null;\n }\n\n getEventsByType(project: string, eventType: EventType, sinceMs?: number): RuntimeEvent[] {\n const conditions = ['project = ?', 'event_type = ?'];\n const params: unknown[] = [project, eventType];\n\n if (sinceMs) {\n conditions.push('timestamp >= ?');\n params.push(sinceMs);\n }\n\n const where = conditions.join(' AND ');\n const rows = this.db\n .prepare(`SELECT data FROM events WHERE ${where} ORDER BY timestamp ASC LIMIT 1000`)\n .all(...params) as { data: string }[];\n\n return rows.map((row) => JSON.parse(row.data) as RuntimeEvent);\n }\n\n // --- Maintenance ---\n\n deleteOldEvents(beforeTimestamp: number): number {\n const result = this.db\n .prepare('DELETE FROM events WHERE timestamp < ?')\n .run(beforeTimestamp);\n return result.changes;\n }\n\n vacuum(): void {\n this.db.exec('VACUUM');\n }\n\n close(): void {\n if (this.flushTimer) {\n clearInterval(this.flushTimer);\n this.flushTimer = null;\n }\n this.flush(); // Final flush\n this.db.close();\n }\n}\n","// ============================================================\n// Per-Session Rate Limiter\n// Sliding-window counters to prevent any single SDK from\n// flooding the collector with events\n// ============================================================\n\nexport interface RateLimitConfig {\n maxEventsPerSecond?: number;\n maxEventsPerMinute?: number;\n}\n\ninterface SessionWindow {\n secondCount: number;\n secondStart: number;\n minuteCount: number;\n minuteStart: number;\n lastWarning: number;\n}\n\nexport class SessionRateLimiter {\n private windows: Map<string, SessionWindow> = new Map();\n private maxPerSecond: number;\n private maxPerMinute: number;\n private _droppedTotal = 0;\n\n constructor(config: RateLimitConfig = {}) {\n this.maxPerSecond = config.maxEventsPerSecond ?? Infinity;\n this.maxPerMinute = config.maxEventsPerMinute ?? Infinity;\n }\n\n get droppedTotal(): number {\n return this._droppedTotal;\n }\n\n isEnabled(): boolean {\n return this.maxPerSecond !== Infinity || this.maxPerMinute !== Infinity;\n }\n\n /** Returns true if the event should be accepted, false if rate-limited. */\n allow(sessionId: string): boolean {\n if (!this.isEnabled()) return true;\n\n const now = Date.now();\n let w = this.windows.get(sessionId);\n\n if (!w) {\n w = {\n secondCount: 0,\n secondStart: now,\n minuteCount: 0,\n minuteStart: now,\n lastWarning: 0,\n };\n this.windows.set(sessionId, w);\n }\n\n // Reset second window\n if (now - w.secondStart >= 1000) {\n w.secondCount = 0;\n w.secondStart = now;\n }\n\n // Reset minute window\n if (now - w.minuteStart >= 60_000) {\n w.minuteCount = 0;\n w.minuteStart = now;\n }\n\n // Check per-second limit\n if (w.secondCount >= this.maxPerSecond) {\n this._droppedTotal++;\n this.maybeWarn(sessionId, w, now);\n return false;\n }\n\n // Check per-minute limit\n if (w.minuteCount >= this.maxPerMinute) {\n this._droppedTotal++;\n this.maybeWarn(sessionId, w, now);\n return false;\n }\n\n w.secondCount++;\n w.minuteCount++;\n return true;\n }\n\n /** Allow a batch of N events. Returns the number accepted. */\n allowBatch(sessionId: string, count: number): number {\n let accepted = 0;\n for (let i = 0; i < count; i++) {\n if (this.allow(sessionId)) accepted++;\n else break; // once limited, remaining events in batch are also limited\n }\n return accepted;\n }\n\n /** Remove tracking for sessions that haven't been seen in maxAgeMs. */\n prune(maxAgeMs = 300_000): void {\n const cutoff = Date.now() - maxAgeMs;\n for (const [id, w] of this.windows) {\n if (w.minuteStart < cutoff) {\n this.windows.delete(id);\n }\n }\n }\n\n private maybeWarn(sessionId: string, w: SessionWindow, now: number): void {\n // Log at most once per minute per session\n if (now - w.lastWarning >= 60_000) {\n w.lastWarning = now;\n console.error(\n `[RuntimeScope] Rate limiting session ${sessionId.slice(0, 8)}... (dropped ${this._droppedTotal} total)`\n );\n }\n }\n}\n","import { readFileSync } from 'node:fs';\nimport type { SecureContextOptions } from 'node:tls';\n\n// ============================================================\n// TLS Support\n// Loads certificate files for WSS + HTTPS\n// ============================================================\n\nexport interface TlsConfig {\n certPath: string;\n keyPath: string;\n caPath?: string;\n}\n\n/**\n * Load TLS certificate files and return options suitable for\n * https.createServer() or tls.createSecureContext().\n */\nexport function loadTlsOptions(config: TlsConfig): SecureContextOptions {\n return {\n cert: readFileSync(config.certPath, 'utf-8'),\n key: readFileSync(config.keyPath, 'utf-8'),\n ...(config.caPath ? { ca: readFileSync(config.caPath, 'utf-8') } : {}),\n };\n}\n\n/**\n * Resolve TLS config from environment variables.\n * Returns null if TLS is not configured.\n */\nexport function resolveTlsConfig(): TlsConfig | null {\n const certPath = process.env.RUNTIMESCOPE_TLS_CERT;\n const keyPath = process.env.RUNTIMESCOPE_TLS_KEY;\n\n if (!certPath || !keyPath) return null;\n\n return {\n certPath,\n keyPath,\n caPath: process.env.RUNTIMESCOPE_TLS_CA,\n };\n}\n","import type {\n RuntimeEvent,\n NetworkEvent,\n ConsoleEvent,\n RenderEvent,\n StateEvent,\n PerformanceEvent,\n DatabaseEvent,\n DetectedIssue,\n} from './types.js';\n\n/**\n * Runs all pattern detectors against a set of events and returns\n * prioritized issues sorted by severity (high → medium → low).\n */\nexport function detectIssues(events: RuntimeEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const networkEvents = events.filter((e) => e.eventType === 'network') as NetworkEvent[];\n const consoleEvents = events.filter((e) => e.eventType === 'console') as ConsoleEvent[];\n const renderEvents = events.filter((e) => e.eventType === 'render') as RenderEvent[];\n const stateEvents = events.filter((e) => e.eventType === 'state') as StateEvent[];\n const perfEvents = events.filter((e) => e.eventType === 'performance') as PerformanceEvent[];\n const dbEvents = events.filter((e) => e.eventType === 'database') as DatabaseEvent[];\n\n issues.push(...detectFailedRequests(networkEvents));\n issues.push(...detectSlowRequests(networkEvents));\n issues.push(...detectN1Requests(networkEvents));\n issues.push(...detectConsoleErrorSpam(consoleEvents));\n issues.push(...detectHighErrorRate(consoleEvents));\n issues.push(...detectExcessiveRerenders(renderEvents));\n issues.push(...detectLargeStateUpdates(stateEvents));\n issues.push(...detectPoorWebVitals(perfEvents));\n issues.push(...detectSlowDbQueries(dbEvents));\n issues.push(...detectN1DbQueries(dbEvents));\n\n // Sort: high first, then medium, then low\n const order = { high: 0, medium: 1, low: 2 };\n issues.sort((a, b) => order[a.severity] - order[b.severity]);\n\n return issues;\n}\n\n/** HTTP 4xx/5xx responses */\nfunction detectFailedRequests(events: NetworkEvent[]): DetectedIssue[] {\n const failed = events.filter((e) => e.status >= 400);\n if (failed.length === 0) return [];\n\n const grouped = new Map<string, NetworkEvent[]>();\n for (const e of failed) {\n const key = `${e.status} ${e.method} ${e.url}`;\n const arr = grouped.get(key) ?? [];\n arr.push(e);\n grouped.set(key, arr);\n }\n\n return Array.from(grouped.entries()).map(([key, evts]) => ({\n id: `failed-request-${key}`,\n pattern: 'failed_requests',\n severity: evts[0].status >= 500 ? 'high' as const : 'medium' as const,\n title: `Failed request: ${key}`,\n description: `${evts.length} request(s) returned ${evts[0].status}`,\n evidence: evts.slice(0, 3).map(\n (e) => `${e.method} ${e.url} → ${e.status} (${e.duration.toFixed(0)}ms) at ${new Date(e.timestamp).toISOString()}`\n ),\n suggestion: evts[0].status >= 500\n ? 'Server error — check backend logs for this endpoint'\n : 'Client error — verify the request URL, auth headers, and payload',\n }));\n}\n\n/** Requests taking >3 seconds */\nfunction detectSlowRequests(events: NetworkEvent[]): DetectedIssue[] {\n const slow = events.filter((e) => e.duration > 3000);\n if (slow.length === 0) return [];\n\n return [{\n id: 'slow-requests',\n pattern: 'slow_requests',\n severity: 'medium',\n title: `${slow.length} slow network request(s) (>3s)`,\n description: `Slowest: ${slow.sort((a, b) => b.duration - a.duration)[0].url} at ${(slow[0].duration / 1000).toFixed(1)}s`,\n evidence: slow.slice(0, 5).map(\n (e) => `${e.method} ${e.url} → ${(e.duration / 1000).toFixed(1)}s (status ${e.status})`\n ),\n suggestion: 'Consider adding loading states, pagination, or caching for these endpoints',\n }];\n}\n\n/** Same endpoint called >5 times within 2 seconds */\nfunction detectN1Requests(events: NetworkEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n\n // Group by method + URL\n const grouped = new Map<string, NetworkEvent[]>();\n for (const e of events) {\n const key = `${e.method} ${e.url}`;\n const arr = grouped.get(key) ?? [];\n arr.push(e);\n grouped.set(key, arr);\n }\n\n for (const [key, evts] of grouped) {\n if (evts.length <= 5) continue;\n\n // Check if they cluster within 2-second windows\n const sorted = evts.sort((a, b) => a.timestamp - b.timestamp);\n let windowStart = sorted[0].timestamp;\n let windowCount = 1;\n\n for (let i = 1; i < sorted.length; i++) {\n if (sorted[i].timestamp - windowStart <= 2000) {\n windowCount++;\n } else {\n windowStart = sorted[i].timestamp;\n windowCount = 1;\n }\n\n if (windowCount > 5) {\n issues.push({\n id: `n1-${key}`,\n pattern: 'n1_requests',\n severity: 'medium',\n title: `Possible N+1: ${key}`,\n description: `Called ${evts.length} times total, with ${windowCount}+ in a 2s window. This often happens when each list item fetches its own data.`,\n evidence: [\n `Total calls: ${evts.length}`,\n `Time span: ${((sorted[sorted.length - 1].timestamp - sorted[0].timestamp) / 1000).toFixed(1)}s`,\n `First call: ${new Date(sorted[0].timestamp).toISOString()}`,\n ],\n suggestion: 'Lift the data fetch to the parent component, use a batch endpoint, or add a shared cache (e.g. React Query with a shared cache key)',\n });\n break;\n }\n }\n }\n\n return issues;\n}\n\n/** Same error message repeated >5 times in 10 seconds */\nfunction detectConsoleErrorSpam(events: ConsoleEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const errors = events.filter((e) => e.level === 'error');\n\n const grouped = new Map<string, ConsoleEvent[]>();\n for (const e of errors) {\n // Normalize message to group similar errors\n const key = e.message.slice(0, 200);\n const arr = grouped.get(key) ?? [];\n arr.push(e);\n grouped.set(key, arr);\n }\n\n for (const [msg, evts] of grouped) {\n if (evts.length <= 5) continue;\n\n const sorted = evts.sort((a, b) => a.timestamp - b.timestamp);\n const span = sorted[sorted.length - 1].timestamp - sorted[0].timestamp;\n\n if (span <= 10_000) {\n const truncated = msg.length > 80 ? msg.slice(0, 80) + '...' : msg;\n issues.push({\n id: `error-spam-${msg.slice(0, 50)}`,\n pattern: 'console_error_spam',\n severity: 'medium',\n title: `Error spam: \"${truncated}\"`,\n description: `Repeated ${evts.length} times in ${(span / 1000).toFixed(1)}s. This usually indicates a re-render loop or a recurring failed operation.`,\n evidence: [\n `Count: ${evts.length}`,\n `Time span: ${(span / 1000).toFixed(1)}s`,\n ...(evts[0].stackTrace ? [`Stack: ${evts[0].stackTrace.split('\\n')[0]}`] : []),\n ],\n suggestion: 'Check for re-render loops, retry loops without backoff, or error boundaries that keep re-mounting',\n });\n }\n }\n\n return issues;\n}\n\n/** High overall error rate */\nfunction detectHighErrorRate(events: ConsoleEvent[]): DetectedIssue[] {\n if (events.length < 10) return [];\n\n const errors = events.filter((e) => e.level === 'error');\n const errorRate = errors.length / events.length;\n\n if (errorRate > 0.3) {\n return [{\n id: 'high-error-rate',\n pattern: 'high_error_rate',\n severity: 'high',\n title: `High console error rate: ${(errorRate * 100).toFixed(0)}%`,\n description: `${errors.length} of ${events.length} console messages are errors. This suggests a systemic issue.`,\n evidence: [\n `Error count: ${errors.length}`,\n `Total console messages: ${events.length}`,\n `Error rate: ${(errorRate * 100).toFixed(0)}%`,\n ],\n suggestion: 'Check for unhandled promise rejections, missing error boundaries, or misconfigured API endpoints',\n }];\n }\n\n return [];\n}\n\n/** Components re-rendering excessively (velocity > 4/sec) */\nfunction detectExcessiveRerenders(events: RenderEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const seen = new Set<string>();\n\n for (const event of events) {\n for (const profile of event.profiles) {\n if (profile.suspicious && !seen.has(profile.componentName)) {\n seen.add(profile.componentName);\n issues.push({\n id: `excessive-rerenders-${profile.componentName}`,\n pattern: 'excessive_rerenders',\n severity: 'medium',\n title: `Excessive re-renders: <${profile.componentName}>`,\n description: `Rendering at ${profile.renderVelocity.toFixed(1)}/sec (${profile.renderCount} renders in snapshot). Last cause: ${profile.lastRenderCause}.`,\n evidence: [\n `Render velocity: ${profile.renderVelocity.toFixed(1)}/sec`,\n `Render count: ${profile.renderCount}`,\n `Avg duration: ${profile.avgDuration.toFixed(1)}ms`,\n `Last cause: ${profile.lastRenderCause}`,\n ],\n suggestion: profile.lastRenderCause === 'parent'\n ? `Wrap <${profile.componentName}> with React.memo() to prevent unnecessary re-renders from parent`\n : profile.lastRenderCause === 'props'\n ? `Check if props passed to <${profile.componentName}> are stable (useMemo/useCallback for object/function props)`\n : `Audit state updates in <${profile.componentName}> — consider batching or debouncing`,\n });\n }\n }\n }\n\n return issues;\n}\n\n/** State snapshots exceeding 100KB */\nfunction detectLargeStateUpdates(events: StateEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const seen = new Set<string>();\n\n for (const event of events) {\n if (event.phase !== 'update') continue;\n const stateStr = JSON.stringify(event.state);\n const sizeKB = Math.round(stateStr.length / 1024);\n\n if (sizeKB > 100 && !seen.has(event.storeId)) {\n seen.add(event.storeId);\n issues.push({\n id: `large-state-${event.storeId}`,\n pattern: 'large_state_update',\n severity: 'medium',\n title: `Large state update: ${event.storeId} (${sizeKB}KB)`,\n description: `Store \"${event.storeId}\" (${event.library}) has a state snapshot of ${sizeKB}KB. Large state can cause slow serialization and re-renders.`,\n evidence: [\n `Store: ${event.storeId}`,\n `Library: ${event.library}`,\n `State size: ${sizeKB}KB`,\n ...(event.diff ? [`Changed keys: ${Object.keys(event.diff).join(', ')}`] : []),\n ],\n suggestion: 'Consider normalizing or splitting the store, and use selectors to subscribe to specific slices',\n });\n }\n }\n\n return issues;\n}\n\n/** Database queries taking >500ms */\nfunction detectSlowDbQueries(events: DatabaseEvent[]): DetectedIssue[] {\n const slow = events.filter((e) => e.duration > 500);\n if (slow.length === 0) return [];\n\n const sorted = slow.sort((a, b) => b.duration - a.duration);\n return [{\n id: 'slow-db-queries',\n pattern: 'slow_db_queries',\n severity: 'medium',\n title: `${slow.length} slow database quer${slow.length === 1 ? 'y' : 'ies'} (>500ms)`,\n description: `Slowest: ${sorted[0].query.slice(0, 100)} at ${sorted[0].duration.toFixed(0)}ms`,\n evidence: sorted.slice(0, 5).map(\n (e) => `${e.operation} on ${e.tablesAccessed.join(', ') || '?'} → ${e.duration.toFixed(0)}ms (${e.source})`\n ),\n suggestion: 'Add indexes on columns used in WHERE/ORDER BY clauses, or reduce result set size with LIMIT',\n }];\n}\n\n/** Same table queried >5 times within 2 seconds (N+1 pattern) */\nfunction detectN1DbQueries(events: DatabaseEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n\n // Group SELECT queries by primary table\n const grouped = new Map<string, DatabaseEvent[]>();\n for (const e of events) {\n if (e.operation !== 'SELECT') continue;\n const table = e.tablesAccessed[0];\n if (!table) continue;\n const arr = grouped.get(table) ?? [];\n arr.push(e);\n grouped.set(table, arr);\n }\n\n for (const [table, evts] of grouped) {\n if (evts.length <= 5) continue;\n\n const sorted = evts.sort((a, b) => a.timestamp - b.timestamp);\n let windowStart = sorted[0].timestamp;\n let windowCount = 1;\n\n for (let i = 1; i < sorted.length; i++) {\n if (sorted[i].timestamp - windowStart <= 2000) {\n windowCount++;\n } else {\n windowStart = sorted[i].timestamp;\n windowCount = 1;\n }\n\n if (windowCount > 5) {\n issues.push({\n id: `n1-db-${table}`,\n pattern: 'n1_db_queries',\n severity: 'high',\n title: `Possible N+1 DB queries on \"${table}\"`,\n description: `${evts.length} SELECT queries on \"${table}\" total, with ${windowCount}+ in a 2s window. This is a classic N+1 pattern.`,\n evidence: [\n `Table: ${table}`,\n `Total SELECTs: ${evts.length}`,\n `Peak burst: ${windowCount}+ in 2s`,\n `Sources: ${[...new Set(evts.map((e) => e.source))].join(', ')}`,\n ],\n suggestion: 'Use a JOIN, subquery, or batch fetch (e.g. WHERE id IN (...)) instead of querying per item',\n });\n break;\n }\n }\n }\n\n return issues;\n}\n\n/** Web Vitals rated as \"poor\" */\nfunction detectPoorWebVitals(events: PerformanceEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const seen = new Set<string>();\n\n for (const event of events) {\n if (event.rating !== 'poor' || seen.has(event.metricName)) continue;\n seen.add(event.metricName);\n\n const isHighSeverity = event.metricName === 'LCP' || event.metricName === 'CLS';\n\n const suggestions: Record<string, string> = {\n LCP: 'Optimize largest image/text block — preload hero images, use next-gen formats, reduce server response time',\n FCP: 'Reduce render-blocking resources — inline critical CSS, defer non-essential JS',\n CLS: 'Set explicit dimensions on images/videos, avoid injecting content above the fold',\n TTFB: 'Improve server response time — add CDN, optimize database queries, enable caching',\n FID: 'Break up long tasks — use requestIdleCallback, code-split heavy modules',\n INP: 'Optimize event handlers — avoid synchronous layouts, defer non-critical work',\n };\n\n issues.push({\n id: `poor-vital-${event.metricName}`,\n pattern: 'poor_web_vital',\n severity: isHighSeverity ? 'high' : 'medium',\n title: `Poor ${event.metricName}: ${event.value}${event.metricName === 'CLS' ? '' : 'ms'}`,\n description: `${event.metricName} is rated \"poor\" (value: ${event.value}). This directly impacts user experience and SEO.`,\n evidence: [\n `Metric: ${event.metricName}`,\n `Value: ${event.value}${event.metricName === 'CLS' ? '' : 'ms'}`,\n `Rating: ${event.rating}`,\n ...(event.element ? [`Element: ${event.element}`] : []),\n ],\n suggestion: suggestions[event.metricName] ?? 'Review performance best practices at web.dev',\n });\n }\n\n return issues;\n}\n","import { mkdirSync, readFileSync, writeFileSync, existsSync, readdirSync } from 'node:fs';\nimport { join } from 'node:path';\nimport { homedir } from 'node:os';\nimport type { ApiKeyEntry } from './auth.js';\n\n// ============================================================\n// Project Manager — manages ~/.runtimescope/ directory structure\n// ============================================================\n\nexport interface GlobalConfig {\n defaultPort: number;\n bufferSize: number;\n httpPort: number;\n /** Authentication configuration */\n auth?: {\n enabled: boolean;\n apiKeys: ApiKeyEntry[];\n };\n /** TLS certificate paths */\n tls?: {\n certPath: string;\n keyPath: string;\n caPath?: string;\n };\n /** CORS allowed origins (defaults to '*' when not set) */\n corsOrigins?: string[];\n /** Rate limiting configuration */\n rateLimits?: {\n maxEventsPerSecond?: number;\n maxEventsPerMinute?: number;\n };\n /** Payload redaction configuration */\n redaction?: {\n enabled: boolean;\n rules?: { name: string; pattern: string; replacement: string }[];\n };\n}\n\nexport interface ProjectConfig {\n name: string;\n createdAt: string;\n sdkVersion?: string;\n settings: {\n bufferSize?: number;\n retentionDays?: number;\n };\n}\n\nexport interface InfrastructureConfig {\n project?: string;\n databases?: Record<string, {\n type: string;\n connection_string?: string;\n project_ref?: string;\n service_key?: string;\n label?: string;\n }>;\n deployments?: Record<string, {\n platform: string;\n project_id?: string;\n team_id?: string;\n worker_name?: string;\n account_id?: string;\n }>;\n services?: Record<string, string>;\n}\n\nconst DEFAULT_GLOBAL_CONFIG: GlobalConfig = {\n defaultPort: 9090,\n bufferSize: 10_000,\n httpPort: 9091,\n};\n\nexport class ProjectManager {\n private readonly baseDir: string;\n\n constructor(baseDir?: string) {\n this.baseDir = baseDir ?? join(homedir(), '.runtimescope');\n }\n\n get rootDir(): string {\n return this.baseDir;\n }\n\n // --- Directory helpers ---\n\n getProjectDir(projectName: string): string {\n return join(this.baseDir, 'projects', projectName);\n }\n\n getProjectDbPath(projectName: string): string {\n return join(this.getProjectDir(projectName), 'events.db');\n }\n\n getSessionsDir(projectName: string): string {\n return join(this.getProjectDir(projectName), 'sessions');\n }\n\n getSessionSnapshotPath(\n projectName: string,\n sessionId: string,\n timestamp: number\n ): string {\n const date = new Date(timestamp);\n const dateStr = date.toISOString().replace(/[:.]/g, '-').slice(0, 19);\n const shortId = sessionId.slice(0, 8);\n return join(this.getSessionsDir(projectName), `${dateStr}_${shortId}.db`);\n }\n\n // --- Lifecycle (idempotent) ---\n\n ensureGlobalDir(): void {\n this.mkdirp(this.baseDir);\n this.mkdirp(join(this.baseDir, 'projects'));\n\n // Create default global config if it doesn't exist\n const configPath = join(this.baseDir, 'config.json');\n if (!existsSync(configPath)) {\n this.writeJson(configPath, DEFAULT_GLOBAL_CONFIG);\n }\n }\n\n ensureProjectDir(projectName: string): void {\n const projectDir = this.getProjectDir(projectName);\n this.mkdirp(projectDir);\n this.mkdirp(this.getSessionsDir(projectName));\n\n // Create default project config if it doesn't exist\n const configPath = join(projectDir, 'config.json');\n if (!existsSync(configPath)) {\n const config: ProjectConfig = {\n name: projectName,\n createdAt: new Date().toISOString(),\n settings: {\n retentionDays: 30,\n },\n };\n this.writeJson(configPath, config);\n }\n }\n\n // --- Config ---\n\n getGlobalConfig(): GlobalConfig {\n const configPath = join(this.baseDir, 'config.json');\n if (!existsSync(configPath)) return { ...DEFAULT_GLOBAL_CONFIG };\n return { ...DEFAULT_GLOBAL_CONFIG, ...(this.readJson(configPath) as Partial<GlobalConfig>) };\n }\n\n saveGlobalConfig(config: GlobalConfig): void {\n this.writeJson(join(this.baseDir, 'config.json'), config);\n }\n\n getProjectConfig(projectName: string): ProjectConfig | null {\n const configPath = join(this.getProjectDir(projectName), 'config.json');\n if (!existsSync(configPath)) return null;\n return this.readJson(configPath) as ProjectConfig;\n }\n\n saveProjectConfig(projectName: string, config: ProjectConfig): void {\n this.writeJson(join(this.getProjectDir(projectName), 'config.json'), config);\n }\n\n getInfrastructureConfig(projectName: string): InfrastructureConfig | null {\n // Try JSON first, then YAML (if js-yaml is available)\n const jsonPath = join(this.getProjectDir(projectName), 'infrastructure.json');\n if (existsSync(jsonPath)) {\n const config = this.readJson(jsonPath) as InfrastructureConfig;\n return this.resolveConfigEnvVars(config);\n }\n\n // Try YAML (loaded lazily to avoid hard dependency)\n const yamlPath = join(this.getProjectDir(projectName), 'infrastructure.yaml');\n if (existsSync(yamlPath)) {\n try {\n // Dynamic import for optional js-yaml dependency\n const content = readFileSync(yamlPath, 'utf-8');\n // Simple YAML parsing for key: value pairs — full YAML support via js-yaml\n return this.resolveConfigEnvVars(this.parseSimpleYaml(content));\n } catch {\n return null;\n }\n }\n\n return null;\n }\n\n getClaudeInstructions(projectName: string): string | null {\n const filePath = join(this.getProjectDir(projectName), 'claude-instructions.md');\n if (!existsSync(filePath)) return null;\n return readFileSync(filePath, 'utf-8');\n }\n\n // --- Discovery ---\n\n listProjects(): string[] {\n const projectsDir = join(this.baseDir, 'projects');\n if (!existsSync(projectsDir)) return [];\n return readdirSync(projectsDir, { withFileTypes: true })\n .filter((d) => d.isDirectory())\n .map((d) => d.name);\n }\n\n projectExists(projectName: string): boolean {\n return existsSync(this.getProjectDir(projectName));\n }\n\n // --- Environment variable resolution ---\n\n resolveEnvVars(value: string): string {\n return value.replace(/\\$\\{([^}]+)\\}/g, (_match, varName: string) => {\n return process.env[varName] ?? '';\n });\n }\n\n // --- Private helpers ---\n\n private mkdirp(dir: string): void {\n if (!existsSync(dir)) {\n mkdirSync(dir, { recursive: true });\n }\n }\n\n private readJson(path: string): unknown {\n const content = readFileSync(path, 'utf-8');\n return JSON.parse(content);\n }\n\n private writeJson(path: string, data: unknown): void {\n writeFileSync(path, JSON.stringify(data, null, 2) + '\\n', 'utf-8');\n }\n\n private resolveConfigEnvVars(config: unknown): InfrastructureConfig {\n // Deep-resolve ${VAR} patterns in all string values\n const resolve = (obj: unknown): unknown => {\n if (typeof obj === 'string') return this.resolveEnvVars(obj);\n if (Array.isArray(obj)) return obj.map(resolve);\n if (obj && typeof obj === 'object') {\n const result: Record<string, unknown> = {};\n for (const [key, value] of Object.entries(obj)) {\n result[key] = resolve(value);\n }\n return result;\n }\n return obj;\n };\n return resolve(config) as InfrastructureConfig;\n }\n\n /**\n * Minimal YAML parser for simple infrastructure config files.\n * Handles flat key-value pairs and one level of nesting.\n * For full YAML support, install js-yaml.\n */\n private parseSimpleYaml(content: string): InfrastructureConfig {\n try {\n // Try to use js-yaml if available\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n const yaml = require('js-yaml');\n return yaml.load(content) as InfrastructureConfig;\n } catch {\n // Fallback: try JSON.parse in case it's JSON with .yaml extension\n try {\n return JSON.parse(content) as InfrastructureConfig;\n } catch {\n return {};\n }\n }\n }\n}\n","import { randomBytes, timingSafeEqual } from 'node:crypto';\n\n// ============================================================\n// API Key Authentication\n// Validates SDK and HTTP API connections via bearer tokens\n// ============================================================\n\nexport interface ApiKeyEntry {\n key: string;\n label: string;\n project?: string;\n createdAt: number;\n}\n\nexport interface AuthConfig {\n enabled: boolean;\n apiKeys: ApiKeyEntry[];\n}\n\nexport class AuthManager {\n private keys: Map<string, ApiKeyEntry> = new Map();\n private enabled: boolean;\n\n constructor(config: Partial<AuthConfig> = {}) {\n this.enabled = config.enabled ?? false;\n for (const entry of config.apiKeys ?? []) {\n this.keys.set(entry.key, entry);\n }\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /** Validate an API key. Returns the entry if valid, null if invalid. */\n validate(key: string | undefined): ApiKeyEntry | null {\n if (!this.enabled) return null; // auth disabled — everything passes\n if (!key) return null;\n\n for (const [storedKey, entry] of this.keys) {\n if (this.safeCompare(key, storedKey)) {\n return entry;\n }\n }\n return null;\n }\n\n /** Check if request is authorized. Returns true if auth is disabled or key is valid. */\n isAuthorized(key: string | undefined): boolean {\n if (!this.enabled) return true;\n return this.validate(key) !== null;\n }\n\n /** Extract bearer token from Authorization header value. */\n static extractBearer(header: string | undefined): string | undefined {\n if (!header) return undefined;\n const match = header.match(/^Bearer\\s+(\\S+)$/i);\n return match?.[1];\n }\n\n /** Constant-time string comparison to prevent timing attacks. */\n private safeCompare(a: string, b: string): boolean {\n if (a.length !== b.length) return false;\n try {\n return timingSafeEqual(Buffer.from(a, 'utf-8'), Buffer.from(b, 'utf-8'));\n } catch {\n return false;\n }\n }\n}\n\n/** Generate a cryptographically secure API key (64 hex chars = 32 bytes). */\nexport function generateApiKey(label: string, project?: string): ApiKeyEntry {\n return {\n key: randomBytes(32).toString('hex'),\n label,\n project,\n createdAt: Date.now(),\n };\n}\n","import type { RuntimeEvent } from './types.js';\n\n// ============================================================\n// Payload Redaction Engine\n// Defense-in-depth: redacts PII/secrets from events at the\n// collector level (supplements SDK-side beforeSend)\n// ============================================================\n\nexport interface RedactionRule {\n name: string;\n pattern: RegExp;\n replacement: string;\n}\n\nexport interface RedactorConfig {\n enabled?: boolean;\n useBuiltIn?: boolean;\n rules?: RedactionRule[];\n /** Redact JSON object keys matching these patterns (case-insensitive). */\n sensitiveKeys?: string[];\n}\n\n/** Built-in patterns for common secret/PII formats. */\nexport const BUILT_IN_RULES: RedactionRule[] = [\n {\n name: 'jwt',\n pattern: /eyJ[A-Za-z0-9_-]{10,}\\.eyJ[A-Za-z0-9_-]{10,}\\.[A-Za-z0-9_-]+/g,\n replacement: '[REDACTED:jwt]',\n },\n {\n name: 'credit_card',\n pattern: /\\b\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/g,\n replacement: '[REDACTED:cc]',\n },\n {\n name: 'ssn',\n pattern: /\\b\\d{3}-\\d{2}-\\d{4}\\b/g,\n replacement: '[REDACTED:ssn]',\n },\n {\n name: 'email',\n pattern: /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z]{2,}\\b/gi,\n replacement: '[REDACTED:email]',\n },\n {\n name: 'bearer_token',\n pattern: /Bearer\\s+[A-Za-z0-9._~+/=-]+/gi,\n replacement: 'Bearer [REDACTED]',\n },\n {\n name: 'api_key_param',\n pattern: /(?:api[_-]?key|apikey|secret|token|password|passwd|authorization)=[^&\\s\"']+/gi,\n replacement: '[REDACTED:param]',\n },\n];\n\n/** Default sensitive JSON keys — values for these keys get redacted. */\nconst DEFAULT_SENSITIVE_KEYS = [\n 'password', 'passwd', 'secret', 'token', 'accessToken', 'refreshToken',\n 'apiKey', 'api_key', 'authorization', 'credit_card', 'creditCard',\n 'ssn', 'socialSecurity',\n];\n\nexport class Redactor {\n private rules: RedactionRule[];\n private sensitiveKeyPattern: RegExp | null;\n private enabled: boolean;\n\n constructor(config: RedactorConfig = {}) {\n this.enabled = config.enabled ?? true;\n this.rules = [];\n\n if (config.useBuiltIn !== false) {\n this.rules.push(...BUILT_IN_RULES);\n }\n if (config.rules) {\n this.rules.push(...config.rules);\n }\n\n const keys = config.sensitiveKeys ?? DEFAULT_SENSITIVE_KEYS;\n this.sensitiveKeyPattern = keys.length > 0\n ? new RegExp(`^(${keys.join('|')})$`, 'i')\n : null;\n }\n\n isEnabled(): boolean {\n return this.enabled;\n }\n\n /** Apply all redaction rules to a string value. */\n redactString(value: string): string {\n let result = value;\n for (const rule of this.rules) {\n // Reset lastIndex for global regexes\n rule.pattern.lastIndex = 0;\n result = result.replace(rule.pattern, rule.replacement);\n }\n return result;\n }\n\n /**\n * Deep-walk an event and redact all string fields.\n * Returns a new event object (does not mutate the original).\n */\n redactEvent(event: RuntimeEvent): RuntimeEvent {\n if (!this.enabled) return event;\n return this.deepRedact(event) as RuntimeEvent;\n }\n\n private deepRedact(value: unknown, key?: string): unknown {\n if (value === null || value === undefined) return value;\n\n // If this key is a known sensitive field, redact the entire value\n if (key && this.sensitiveKeyPattern?.test(key)) {\n return '[REDACTED]';\n }\n\n if (typeof value === 'string') {\n return this.redactString(value);\n }\n\n if (Array.isArray(value)) {\n return value.map((item) => this.deepRedact(item));\n }\n\n if (typeof value === 'object') {\n const result: Record<string, unknown> = {};\n for (const [k, v] of Object.entries(value)) {\n result[k] = this.deepRedact(v, k);\n }\n return result;\n }\n\n // numbers, booleans — pass through\n return value;\n }\n}\n","import type { EventStore } from '../store.js';\nimport type {\n NetworkEvent,\n ApiEndpoint,\n ApiEndpointHealth,\n ApiContract,\n ApiContractField,\n ServiceInfo,\n ApiChangeRecord,\n AuthInfo,\n GraphQLOperation,\n DetectedIssue,\n} from '../types.js';\n\n// ============================================================\n// API Discovery Engine\n// Auto-discovers and catalogs every API endpoint from network traffic\n// ============================================================\n\n// --- URL Normalization ---\n\nconst UUID_RE = /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/i;\nconst NUMERIC_RE = /^\\d+$/;\nconst MONGO_ID_RE = /^[0-9a-f]{24}$/i;\nconst SHORT_HASH_RE = /^[0-9a-f]{8,}$/i;\nconst LONG_ALPHANUM_RE = /^[a-zA-Z0-9_-]{20,}$/;\nconst BASE64_RE = /^[a-zA-Z0-9+/=_-]{16,}$/;\n\nfunction normalizeSegment(segment: string): string {\n if (UUID_RE.test(segment)) return ':id';\n if (NUMERIC_RE.test(segment)) return ':id';\n if (MONGO_ID_RE.test(segment)) return ':id';\n if (SHORT_HASH_RE.test(segment) && segment.length >= 8) return ':id';\n if (LONG_ALPHANUM_RE.test(segment)) return ':id';\n if (BASE64_RE.test(segment) && segment.length >= 16) return ':token';\n return segment;\n}\n\nfunction normalizeUrl(url: string): { baseUrl: string; normalizedPath: string } {\n try {\n const parsed = new URL(url);\n const baseUrl = parsed.origin;\n const segments = parsed.pathname.split('/').filter(Boolean);\n const normalized = segments.map(normalizeSegment);\n return { baseUrl, normalizedPath: '/' + normalized.join('/') };\n } catch {\n return { baseUrl: 'unknown', normalizedPath: url };\n }\n}\n\n// --- Service Detection ---\n\nconst SERVICE_PATTERNS: [RegExp, string][] = [\n [/\\.supabase\\.co$/, 'Supabase'],\n [/\\.workers\\.dev$/, 'Cloudflare Workers'],\n [/\\.vercel\\.app$/, 'Vercel'],\n [/api\\.stripe\\.com$/, 'Stripe'],\n [/\\.railway\\.app$/, 'Railway'],\n [/\\.netlify\\.app$/, 'Netlify'],\n [/\\.fly\\.dev$/, 'Fly.io'],\n [/\\.render\\.com$/, 'Render'],\n [/api\\.github\\.com$/, 'GitHub API'],\n [/api\\.openai\\.com$/, 'OpenAI'],\n [/api\\.anthropic\\.com$/, 'Anthropic'],\n [/\\.clerk\\.dev$/, 'Clerk'],\n [/\\.auth0\\.com$/, 'Auth0'],\n [/\\.firebase(io|app)\\.com$/, 'Firebase'],\n [/\\.amazonaws\\.com$/, 'AWS'],\n [/\\.googleapis\\.com$/, 'Google APIs'],\n [/^(localhost|127\\.0\\.0\\.1)$/, 'Your API'],\n];\n\nfunction detectService(hostname: string): string {\n for (const [pattern, name] of SERVICE_PATTERNS) {\n if (pattern.test(hostname)) return name;\n }\n // Derive from hostname: api.example.com → example.com\n const parts = hostname.split('.');\n if (parts.length >= 2) {\n return parts.slice(-2).join('.');\n }\n return hostname;\n}\n\n// --- Auth Detection ---\n\nfunction detectAuth(headers: Record<string, string>): AuthInfo {\n const authHeader = headers['authorization'] || headers['Authorization'];\n if (authHeader) {\n if (authHeader.startsWith('Bearer ')) return { type: 'bearer', headerName: 'Authorization' };\n if (authHeader.startsWith('Basic ')) return { type: 'basic', headerName: 'Authorization' };\n return { type: 'api_key', headerName: 'Authorization' };\n }\n\n // Check for common API key headers\n for (const key of Object.keys(headers)) {\n const lower = key.toLowerCase();\n if (lower.includes('api-key') || lower.includes('apikey') || lower === 'x-api-key') {\n return { type: 'api_key', headerName: key };\n }\n }\n\n // Check for cookie-based auth\n if (headers['cookie'] || headers['Cookie']) {\n return { type: 'cookie' };\n }\n\n return { type: 'none' };\n}\n\n// --- Contract Inference ---\n\nfunction inferFieldType(value: unknown): string {\n if (value === null) return 'null';\n if (Array.isArray(value)) return 'array';\n return typeof value;\n}\n\nfunction walkObject(obj: unknown, prefix = ''): ApiContractField[] {\n const fields: ApiContractField[] = [];\n if (obj === null || obj === undefined || typeof obj !== 'object') return fields;\n\n if (Array.isArray(obj)) {\n fields.push({ path: prefix || '[]', type: 'array', nullable: false, example: `[${obj.length} items]` });\n if (obj.length > 0 && typeof obj[0] === 'object' && obj[0] !== null) {\n const itemFields = walkObject(obj[0], prefix ? `${prefix}[]` : '[]');\n fields.push(...itemFields);\n }\n return fields;\n }\n\n for (const [key, value] of Object.entries(obj as Record<string, unknown>)) {\n const path = prefix ? `${prefix}.${key}` : key;\n const type = inferFieldType(value);\n fields.push({\n path,\n type,\n nullable: value === null,\n example: typeof value === 'string' ? value.slice(0, 50) : value,\n });\n if (type === 'object' && value !== null) {\n fields.push(...walkObject(value, path));\n }\n }\n\n return fields;\n}\n\nfunction inferContract(events: NetworkEvent[]): ApiContract | undefined {\n // Sample up to 10 events for contract inference\n const samples = events.slice(-10);\n const responseBodies = samples\n .filter((e) => e.responseBody)\n .map((e) => {\n try {\n return JSON.parse(e.responseBody!);\n } catch {\n return null;\n }\n })\n .filter(Boolean);\n\n if (responseBodies.length === 0) return undefined;\n\n const allFields = new Map<string, { types: Set<string>; nullable: boolean; example?: unknown }>();\n\n for (const body of responseBodies) {\n const fields = walkObject(body);\n for (const field of fields) {\n const existing = allFields.get(field.path);\n if (existing) {\n existing.types.add(field.type);\n if (field.nullable) existing.nullable = true;\n } else {\n allFields.set(field.path, {\n types: new Set([field.type]),\n nullable: field.nullable,\n example: field.example,\n });\n }\n }\n }\n\n const responseFields: ApiContractField[] = [];\n for (const [path, info] of allFields) {\n responseFields.push({\n path,\n type: [...info.types].join(' | '),\n nullable: info.nullable,\n example: info.example,\n });\n }\n\n return { responseFields, sampleCount: responseBodies.length };\n}\n\n// --- Percentile Calculation ---\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0;\n const idx = Math.ceil(sorted.length * (p / 100)) - 1;\n return sorted[Math.max(0, idx)];\n}\n\n// --- Endpoint Key ---\n\nfunction endpointKey(method: string, normalizedPath: string, baseUrl: string): string {\n return `${method.toUpperCase()} ${baseUrl}${normalizedPath}`;\n}\n\n// ============================================================\n// Engine\n// ============================================================\n\ninterface EndpointData {\n normalizedPath: string;\n method: string;\n baseUrl: string;\n service: string;\n events: NetworkEvent[];\n auth: AuthInfo;\n graphqlOperation?: GraphQLOperation;\n}\n\nexport class ApiDiscoveryEngine {\n private endpoints: Map<string, EndpointData> = new Map();\n private store: EventStore;\n\n constructor(store: EventStore) {\n this.store = store;\n }\n\n rebuild(): void {\n this.endpoints.clear();\n const events = this.store.getNetworkRequests();\n for (const event of events) {\n this.ingestEvent(event);\n }\n }\n\n private ingestEvent(event: NetworkEvent): void {\n const { baseUrl, normalizedPath } = normalizeUrl(event.url);\n let hostname: string;\n try {\n hostname = new URL(event.url).hostname;\n } catch {\n hostname = 'unknown';\n }\n\n const key = endpointKey(event.method, normalizedPath, baseUrl);\n const existing = this.endpoints.get(key);\n\n if (existing) {\n existing.events.push(event);\n return;\n }\n\n this.endpoints.set(key, {\n normalizedPath,\n method: event.method.toUpperCase(),\n baseUrl,\n service: detectService(hostname),\n events: [event],\n auth: detectAuth(event.requestHeaders),\n graphqlOperation: event.graphqlOperation,\n });\n }\n\n // --- Refinement pass: parameterize segments with high cardinality ---\n\n private refineEndpoints(): void {\n // Group endpoints by method + baseUrl + segment count\n const groups = new Map<string, EndpointData[]>();\n for (const ep of this.endpoints.values()) {\n const segments = ep.normalizedPath.split('/').filter(Boolean);\n const groupKey = `${ep.method}|${ep.baseUrl}|${segments.length}`;\n const group = groups.get(groupKey) ?? [];\n group.push(ep);\n groups.set(groupKey, group);\n }\n\n // For each group, find segment positions with >5 distinct values\n for (const group of groups.values()) {\n if (group.length <= 5) continue;\n const segmentSets: Map<string, number>[] = [];\n\n for (const ep of group) {\n const segments = ep.normalizedPath.split('/').filter(Boolean);\n for (let i = 0; i < segments.length; i++) {\n if (!segmentSets[i]) segmentSets[i] = new Map();\n segmentSets[i].set(segments[i], (segmentSets[i].get(segments[i]) ?? 0) + 1);\n }\n }\n\n for (let i = 0; i < segmentSets.length; i++) {\n if (segmentSets[i] && segmentSets[i].size > 5) {\n // This position has high cardinality — parameterize it\n for (const ep of group) {\n const segments = ep.normalizedPath.split('/').filter(Boolean);\n if (segments[i] && segments[i] !== ':id' && segments[i] !== ':token') {\n segments[i] = ':id';\n ep.normalizedPath = '/' + segments.join('/');\n }\n }\n }\n }\n }\n\n // Merge duplicates that may have been created by refinement\n const merged = new Map<string, EndpointData>();\n for (const ep of this.endpoints.values()) {\n const key = endpointKey(ep.method, ep.normalizedPath, ep.baseUrl);\n const existing = merged.get(key);\n if (existing) {\n existing.events.push(...ep.events);\n } else {\n merged.set(key, { ...ep });\n }\n }\n this.endpoints = merged;\n }\n\n // --- Public API ---\n\n getCatalog(filter?: { service?: string; minCalls?: number }): ApiEndpoint[] {\n this.rebuild();\n this.refineEndpoints();\n\n const results: ApiEndpoint[] = [];\n for (const ep of this.endpoints.values()) {\n if (filter?.service && ep.service !== filter.service) continue;\n if (filter?.minCalls && ep.events.length < filter.minCalls) continue;\n\n const timestamps = ep.events.map((e) => e.timestamp);\n results.push({\n normalizedPath: ep.normalizedPath,\n method: ep.method,\n baseUrl: ep.baseUrl,\n service: ep.service,\n callCount: ep.events.length,\n firstSeen: Math.min(...timestamps),\n lastSeen: Math.max(...timestamps),\n auth: ep.auth,\n contract: inferContract(ep.events),\n graphqlOperation: ep.graphqlOperation,\n });\n }\n\n return results.sort((a, b) => b.callCount - a.callCount);\n }\n\n getHealth(filter?: { endpoint?: string; sinceSeconds?: number }): ApiEndpointHealth[] {\n this.rebuild();\n this.refineEndpoints();\n\n const since = filter?.sinceSeconds ? Date.now() - filter.sinceSeconds * 1000 : 0;\n const results: ApiEndpointHealth[] = [];\n\n for (const ep of this.endpoints.values()) {\n if (filter?.endpoint) {\n const key = `${ep.method} ${ep.normalizedPath}`;\n if (!key.includes(filter.endpoint)) continue;\n }\n\n const events = ep.events.filter((e) => e.timestamp >= since);\n if (events.length === 0) continue;\n\n const durations = events.map((e) => e.duration).sort((a, b) => a - b);\n const errorCount = events.filter((e) => e.status >= 400).length;\n const errorCodes: Record<number, number> = {};\n for (const e of events) {\n if (e.status >= 400) {\n errorCodes[e.status] = (errorCodes[e.status] ?? 0) + 1;\n }\n }\n\n results.push({\n normalizedPath: ep.normalizedPath,\n method: ep.method,\n service: ep.service,\n callCount: events.length,\n successRate: (events.length - errorCount) / events.length,\n avgLatency: durations.reduce((s, d) => s + d, 0) / durations.length,\n p50Latency: percentile(durations, 50),\n p95Latency: percentile(durations, 95),\n errorRate: errorCount / events.length,\n errorCodes,\n });\n }\n\n return results.sort((a, b) => b.callCount - a.callCount);\n }\n\n getDocumentation(filter?: { service?: string; format?: string }): string {\n const catalog = this.getCatalog(filter ? { service: filter.service } : undefined);\n const health = this.getHealth();\n const healthMap = new Map(health.map((h) => [`${h.method} ${h.normalizedPath}`, h]));\n\n const lines: string[] = ['# API Documentation (Auto-Generated from Traffic)', ''];\n\n // Group by service\n const byService = new Map<string, ApiEndpoint[]>();\n for (const ep of catalog) {\n const list = byService.get(ep.service) ?? [];\n list.push(ep);\n byService.set(ep.service, list);\n }\n\n for (const [service, endpoints] of byService) {\n lines.push(`## ${service}`, '');\n\n for (const ep of endpoints) {\n const h = healthMap.get(`${ep.method} ${ep.normalizedPath}`);\n lines.push(`### ${ep.method} ${ep.normalizedPath}`);\n lines.push(`- Base URL: ${ep.baseUrl}`);\n lines.push(`- Calls: ${ep.callCount}`);\n lines.push(`- Auth: ${ep.auth.type}${ep.auth.headerName ? ` (${ep.auth.headerName})` : ''}`);\n\n if (h) {\n lines.push(`- Avg Latency: ${h.avgLatency.toFixed(0)}ms`);\n lines.push(`- P95 Latency: ${h.p95Latency.toFixed(0)}ms`);\n lines.push(`- Error Rate: ${(h.errorRate * 100).toFixed(1)}%`);\n }\n\n if (ep.graphqlOperation) {\n lines.push(`- GraphQL: ${ep.graphqlOperation.type} ${ep.graphqlOperation.name}`);\n }\n\n if (ep.contract) {\n lines.push('- Response Shape:');\n for (const field of ep.contract.responseFields.slice(0, 20)) {\n lines.push(` - \\`${field.path}\\`: ${field.type}${field.nullable ? ' (nullable)' : ''}`);\n }\n if (ep.contract.responseFields.length > 20) {\n lines.push(` - ... and ${ep.contract.responseFields.length - 20} more fields`);\n }\n }\n\n lines.push('');\n }\n }\n\n return lines.join('\\n');\n }\n\n getServiceMap(): ServiceInfo[] {\n this.rebuild();\n this.refineEndpoints();\n\n const services = new Map<string, {\n baseUrl: string;\n endpoints: Set<string>;\n totalCalls: number;\n totalDuration: number;\n errorCount: number;\n auth: AuthInfo;\n platform?: string;\n }>();\n\n for (const ep of this.endpoints.values()) {\n const existing = services.get(ep.service);\n if (existing) {\n existing.endpoints.add(`${ep.method} ${ep.normalizedPath}`);\n existing.totalCalls += ep.events.length;\n existing.totalDuration += ep.events.reduce((s, e) => s + e.duration, 0);\n existing.errorCount += ep.events.filter((e) => e.status >= 400).length;\n } else {\n let detectedPlatform: string | undefined;\n try {\n const hostname = new URL(ep.baseUrl).hostname;\n for (const [pattern, name] of SERVICE_PATTERNS) {\n if (pattern.test(hostname)) {\n detectedPlatform = name;\n break;\n }\n }\n } catch { /* ignore */ }\n\n services.set(ep.service, {\n baseUrl: ep.baseUrl,\n endpoints: new Set([`${ep.method} ${ep.normalizedPath}`]),\n totalCalls: ep.events.length,\n totalDuration: ep.events.reduce((s, e) => s + e.duration, 0),\n errorCount: ep.events.filter((e) => e.status >= 400).length,\n auth: ep.auth,\n platform: detectedPlatform,\n });\n }\n }\n\n const results: ServiceInfo[] = [];\n for (const [name, data] of services) {\n results.push({\n name,\n baseUrl: data.baseUrl,\n endpointCount: data.endpoints.size,\n totalCalls: data.totalCalls,\n avgLatency: data.totalCalls > 0 ? data.totalDuration / data.totalCalls : 0,\n errorRate: data.totalCalls > 0 ? data.errorCount / data.totalCalls : 0,\n auth: data.auth,\n detectedPlatform: data.platform,\n });\n }\n\n return results.sort((a, b) => b.totalCalls - a.totalCalls);\n }\n\n getApiChanges(sessionA: string, sessionB: string): ApiChangeRecord[] {\n const allEvents = this.store.getNetworkRequests();\n\n const eventsA = allEvents.filter((e) => e.sessionId === sessionA);\n const eventsB = allEvents.filter((e) => e.sessionId === sessionB);\n\n const catalogA = this.buildCatalogFromEvents(eventsA);\n const catalogB = this.buildCatalogFromEvents(eventsB);\n\n const changes: ApiChangeRecord[] = [];\n const allKeys = new Set([...catalogA.keys(), ...catalogB.keys()]);\n\n for (const key of allKeys) {\n const a = catalogA.get(key);\n const b = catalogB.get(key);\n\n if (!a && b) {\n changes.push({\n normalizedPath: b.normalizedPath,\n method: b.method,\n changeType: 'added',\n });\n } else if (a && !b) {\n changes.push({\n normalizedPath: a.normalizedPath,\n method: a.method,\n changeType: 'removed',\n });\n } else if (a && b) {\n // Compare response shapes\n const contractA = inferContract(a.events);\n const contractB = inferContract(b.events);\n if (contractA && contractB) {\n const fieldsA = new Map(contractA.responseFields.map((f) => [f.path, f.type]));\n const fieldsB = new Map(contractB.responseFields.map((f) => [f.path, f.type]));\n const fieldChanges: ApiChangeRecord['fieldChanges'] = [];\n\n for (const [path, type] of fieldsB) {\n if (!fieldsA.has(path)) {\n fieldChanges.push({ path, change: 'added', newType: type });\n } else if (fieldsA.get(path) !== type) {\n fieldChanges.push({ path, change: 'type_changed', oldType: fieldsA.get(path), newType: type });\n }\n }\n for (const [path] of fieldsA) {\n if (!fieldsB.has(path)) {\n fieldChanges.push({ path, change: 'removed', oldType: fieldsA.get(path) });\n }\n }\n\n if (fieldChanges.length > 0) {\n changes.push({\n normalizedPath: a.normalizedPath,\n method: a.method,\n changeType: 'modified',\n fieldChanges,\n });\n }\n }\n }\n }\n\n return changes;\n }\n\n private buildCatalogFromEvents(events: NetworkEvent[]): Map<string, EndpointData> {\n const catalog = new Map<string, EndpointData>();\n for (const event of events) {\n const { baseUrl, normalizedPath } = normalizeUrl(event.url);\n let hostname: string;\n try {\n hostname = new URL(event.url).hostname;\n } catch {\n hostname = 'unknown';\n }\n const key = endpointKey(event.method, normalizedPath, baseUrl);\n const existing = catalog.get(key);\n if (existing) {\n existing.events.push(event);\n } else {\n catalog.set(key, {\n normalizedPath,\n method: event.method.toUpperCase(),\n baseUrl,\n service: detectService(hostname),\n events: [event],\n auth: detectAuth(event.requestHeaders),\n graphqlOperation: event.graphqlOperation,\n });\n }\n }\n return catalog;\n }\n\n detectIssues(): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const health = this.getHealth();\n\n for (const ep of health) {\n // API degradation: >50% error rate\n if (ep.errorRate > 0.5 && ep.callCount >= 3) {\n issues.push({\n id: `api-degradation-${ep.method}-${ep.normalizedPath}`,\n pattern: 'api_degradation',\n severity: 'medium',\n title: `API Degradation: ${ep.method} ${ep.normalizedPath}`,\n description: `Error rate is ${(ep.errorRate * 100).toFixed(0)}% (${Object.entries(ep.errorCodes).map(([k, v]) => `${k}: ${v}`).join(', ')})`,\n evidence: [`${ep.callCount} calls, ${(ep.errorRate * 100).toFixed(0)}% errors`],\n suggestion: 'Check server logs for this endpoint. Verify the backend is healthy.',\n });\n }\n\n // High latency: p95 > 5s\n if (ep.p95Latency > 5000 && ep.callCount >= 3) {\n issues.push({\n id: `high-latency-${ep.method}-${ep.normalizedPath}`,\n pattern: 'high_latency_endpoint',\n severity: 'medium',\n title: `High Latency: ${ep.method} ${ep.normalizedPath}`,\n description: `P95 latency is ${(ep.p95Latency / 1000).toFixed(1)}s`,\n evidence: [`p50: ${ep.p50Latency.toFixed(0)}ms, p95: ${ep.p95Latency.toFixed(0)}ms, avg: ${ep.avgLatency.toFixed(0)}ms`],\n suggestion: 'Consider adding caching, optimizing the query, or paginating the response.',\n });\n }\n }\n\n // Auth inconsistency: same service with mixed auth patterns\n const services = this.getServiceMap();\n const catalog = this.getCatalog();\n for (const service of services) {\n const serviceEndpoints = catalog.filter((ep) => ep.service === service.name);\n const authTypes = new Set(serviceEndpoints.map((ep) => ep.auth.type));\n if (authTypes.size > 1 && !authTypes.has('none')) {\n issues.push({\n id: `auth-inconsistency-${service.name}`,\n pattern: 'auth_inconsistency',\n severity: 'medium',\n title: `Auth Inconsistency: ${service.name}`,\n description: `Mixed auth patterns detected: ${[...authTypes].join(', ')}`,\n evidence: serviceEndpoints.map((ep) => `${ep.method} ${ep.normalizedPath}: ${ep.auth.type}`),\n suggestion: 'Verify that all endpoints for this service use consistent authentication.',\n });\n }\n }\n\n return issues;\n }\n}\n","import type {\n DatabaseEvent,\n NormalizedQueryStats,\n DetectedIssue,\n IndexSuggestion,\n} from '../types.js';\n\n// ============================================================\n// Query Monitor Engine\n// Analyzes captured database queries for performance patterns\n// ============================================================\n\nfunction percentile(sorted: number[], p: number): number {\n if (sorted.length === 0) return 0;\n const idx = Math.ceil(sorted.length * (p / 100)) - 1;\n return sorted[Math.max(0, idx)];\n}\n\nexport function aggregateQueryStats(events: DatabaseEvent[]): NormalizedQueryStats[] {\n const groups = new Map<string, DatabaseEvent[]>();\n for (const e of events) {\n const key = e.normalizedQuery;\n const group = groups.get(key) ?? [];\n group.push(e);\n groups.set(key, group);\n }\n\n const stats: NormalizedQueryStats[] = [];\n for (const [normalizedQuery, groupEvents] of groups) {\n const durations = groupEvents.map((e) => e.duration).sort((a, b) => a - b);\n const totalDuration = durations.reduce((s, d) => s + d, 0);\n const tables = new Set<string>();\n for (const e of groupEvents) {\n for (const t of e.tablesAccessed) tables.add(t);\n }\n\n const rowCounts = groupEvents\n .filter((e) => e.rowsReturned !== undefined)\n .map((e) => e.rowsReturned!);\n\n stats.push({\n normalizedQuery,\n tables: [...tables],\n operation: groupEvents[0].operation,\n callCount: groupEvents.length,\n avgDuration: totalDuration / groupEvents.length,\n maxDuration: Math.max(...durations),\n p95Duration: percentile(durations, 95),\n totalDuration,\n avgRowsReturned: rowCounts.length > 0\n ? rowCounts.reduce((s, r) => s + r, 0) / rowCounts.length\n : 0,\n });\n }\n\n return stats.sort((a, b) => b.totalDuration - a.totalDuration);\n}\n\nexport function detectN1Queries(events: DatabaseEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n\n // Group by table and look for rapid-fire same-table queries within 2s windows\n const tableWindows = new Map<string, { timestamps: number[]; queries: string[] }>();\n\n for (const e of events) {\n if (e.operation !== 'SELECT') continue;\n for (const table of e.tablesAccessed) {\n const entry = tableWindows.get(table) ?? { timestamps: [], queries: [] };\n entry.timestamps.push(e.timestamp);\n entry.queries.push(e.query);\n tableWindows.set(table, entry);\n }\n }\n\n for (const [table, data] of tableWindows) {\n // Sort by timestamp and find windows with >5 queries in 2s\n const sorted = data.timestamps.sort((a, b) => a - b);\n let windowStart = 0;\n\n for (let i = 0; i < sorted.length; i++) {\n while (sorted[i] - sorted[windowStart] > 2000) windowStart++;\n const windowSize = i - windowStart + 1;\n\n if (windowSize > 5) {\n issues.push({\n id: `n1-${table}-${sorted[windowStart]}`,\n pattern: 'n1_db_query',\n severity: 'high',\n title: `N+1 Query Pattern: ${table}`,\n description: `${windowSize} SELECT queries on table \"${table}\" within 2 seconds. This is a classic N+1 query pattern.`,\n evidence: [\n `${windowSize} queries in ${((sorted[i] - sorted[windowStart]) / 1000).toFixed(1)}s`,\n `Sample: ${data.queries[windowStart]?.slice(0, 100)}`,\n ],\n suggestion: `Use a JOIN or batch query (e.g., WHERE id IN (...)) instead of querying \"${table}\" in a loop.`,\n });\n // Skip ahead to avoid duplicate detections for overlapping windows\n windowStart = i + 1;\n }\n }\n }\n\n return issues;\n}\n\nexport function detectSlowQueries(events: DatabaseEvent[], thresholdMs = 500): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const seen = new Set<string>();\n\n for (const e of events) {\n if (e.duration >= thresholdMs && !seen.has(e.normalizedQuery)) {\n seen.add(e.normalizedQuery);\n issues.push({\n id: `slow-query-${e.eventId}`,\n pattern: 'slow_db_query',\n severity: e.duration > 2000 ? 'high' : 'medium',\n title: `Slow Query: ${e.duration.toFixed(0)}ms`,\n description: `Query took ${e.duration.toFixed(0)}ms (threshold: ${thresholdMs}ms). Tables: ${e.tablesAccessed.join(', ') || 'unknown'}.`,\n evidence: [\n `Duration: ${e.duration.toFixed(0)}ms`,\n `Query: ${e.query.slice(0, 150)}`,\n e.rowsReturned !== undefined ? `Rows returned: ${e.rowsReturned}` : '',\n ].filter(Boolean),\n suggestion: 'Consider adding indexes, reducing the result set, or optimizing the query.',\n });\n }\n }\n\n return issues;\n}\n\nexport function suggestIndexes(events: DatabaseEvent[]): IndexSuggestion[] {\n const suggestions: IndexSuggestion[] = [];\n const seen = new Set<string>();\n\n // Parse WHERE and ORDER BY columns from slow queries\n const WHERE_COL_RE = /WHERE\\s+.*?[\"'`]?(\\w+)[\"'`]?\\s*(=|>|<|>=|<=|!=|LIKE|IN|IS)\\s/gi;\n const ORDER_COL_RE = /ORDER\\s+BY\\s+[\"'`]?(\\w+)[\"'`]?/gi;\n\n for (const e of events) {\n if (e.duration < 100) continue; // Only suggest for queries taking >100ms\n\n for (const table of e.tablesAccessed) {\n const columns: string[] = [];\n\n // Extract WHERE columns\n let match: RegExpExecArray | null;\n const whereRe = new RegExp(WHERE_COL_RE.source, WHERE_COL_RE.flags);\n while ((match = whereRe.exec(e.query)) !== null) {\n columns.push(match[1]);\n }\n\n // Extract ORDER BY columns\n const orderRe = new RegExp(ORDER_COL_RE.source, ORDER_COL_RE.flags);\n while ((match = orderRe.exec(e.query)) !== null) {\n columns.push(match[1]);\n }\n\n if (columns.length === 0) continue;\n\n const key = `${table}:${columns.sort().join(',')}`;\n if (seen.has(key)) continue;\n seen.add(key);\n\n suggestions.push({\n table,\n columns,\n reason: `Query taking ${e.duration.toFixed(0)}ms uses these columns in WHERE/ORDER BY`,\n estimatedImpact: e.duration > 1000 ? 'high' : e.duration > 300 ? 'medium' : 'low',\n queryPattern: e.normalizedQuery.slice(0, 150),\n });\n }\n }\n\n return suggestions;\n}\n\nexport function detectOverfetching(events: DatabaseEvent[]): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n const seen = new Set<string>();\n\n for (const e of events) {\n if (e.operation !== 'SELECT') continue;\n if (e.query.match(/SELECT\\s+\\*/i) && e.rowsReturned !== undefined && e.rowsReturned > 100) {\n const key = e.normalizedQuery;\n if (seen.has(key)) continue;\n seen.add(key);\n\n issues.push({\n id: `overfetch-${e.eventId}`,\n pattern: 'overfetching',\n severity: e.rowsReturned > 1000 ? 'high' : 'medium',\n title: `Overfetching: SELECT * returning ${e.rowsReturned} rows`,\n description: `Query uses SELECT * and returns ${e.rowsReturned} rows. Tables: ${e.tablesAccessed.join(', ')}.`,\n evidence: [\n `Query: ${e.query.slice(0, 150)}`,\n `Rows: ${e.rowsReturned}`,\n ],\n suggestion: 'Select only the columns you need and add LIMIT if appropriate.',\n });\n }\n }\n\n return issues;\n}\n","import type { DatabaseConnectionConfig } from '../types.js';\n\n// ============================================================\n// Database Connection Manager\n// Manages connections to local/dev databases for introspection\n// ============================================================\n\nexport interface ManagedConnection {\n config: DatabaseConnectionConfig;\n client: unknown;\n isHealthy: boolean;\n lastChecked: number;\n}\n\nexport class ConnectionManager {\n private connections: Map<string, ManagedConnection> = new Map();\n\n async addConnection(config: DatabaseConnectionConfig): Promise<void> {\n const client = await this.createClient(config);\n this.connections.set(config.id, {\n config,\n client,\n isHealthy: true,\n lastChecked: Date.now(),\n });\n }\n\n getConnection(id: string): ManagedConnection | undefined {\n return this.connections.get(id);\n }\n\n listConnections(): { id: string; type: string; label?: string; isHealthy: boolean }[] {\n return Array.from(this.connections.values()).map((c) => ({\n id: c.config.id,\n type: c.config.type,\n label: c.config.label,\n isHealthy: c.isHealthy,\n }));\n }\n\n async healthCheck(id: string): Promise<boolean> {\n const conn = this.connections.get(id);\n if (!conn) return false;\n\n try {\n if (conn.config.type === 'postgres') {\n const pg = conn.client as { query: (sql: string) => Promise<unknown> };\n await pg.query('SELECT 1');\n } else if (conn.config.type === 'mysql') {\n const mysql = conn.client as { query: (sql: string) => Promise<unknown> };\n await mysql.query('SELECT 1');\n } else if (conn.config.type === 'sqlite') {\n const db = conn.client as { prepare: (sql: string) => { get: () => unknown } };\n db.prepare('SELECT 1').get();\n }\n conn.isHealthy = true;\n } catch {\n conn.isHealthy = false;\n }\n\n conn.lastChecked = Date.now();\n return conn.isHealthy;\n }\n\n async closeConnection(id: string): Promise<void> {\n const conn = this.connections.get(id);\n if (!conn) return;\n\n try {\n if (conn.config.type === 'postgres') {\n await (conn.client as { end: () => Promise<void> }).end();\n } else if (conn.config.type === 'mysql') {\n await (conn.client as { end: () => Promise<void> }).end();\n } else if (conn.config.type === 'sqlite') {\n (conn.client as { close: () => void }).close();\n }\n } catch {\n // Ignore close errors\n }\n\n this.connections.delete(id);\n }\n\n async closeAll(): Promise<void> {\n const ids = [...this.connections.keys()];\n for (const id of ids) {\n await this.closeConnection(id);\n }\n }\n\n // Dynamic require wrapper to avoid TypeScript module resolution at compile time\n // eslint-disable-next-line @typescript-eslint/no-require-imports\n private dynamicRequire(mod: string): unknown {\n try {\n return require(mod);\n } catch {\n throw new Error(`Module '${mod}' not found. Install it: npm install ${mod}`);\n }\n }\n\n private async createClient(config: DatabaseConnectionConfig): Promise<unknown> {\n switch (config.type) {\n case 'postgres': {\n try {\n const pg = this.dynamicRequire('pg') as { Pool: new (opts: unknown) => { query: (sql: string) => Promise<unknown>; end: () => Promise<void> } };\n const pool = new pg.Pool({ connectionString: config.connectionString });\n await pool.query('SELECT 1');\n return pool;\n } catch (err) {\n throw new Error(`Failed to connect to PostgreSQL: ${(err as Error).message}. Ensure 'pg' is installed.`);\n }\n }\n case 'mysql': {\n try {\n const mysql2 = this.dynamicRequire('mysql2/promise') as { createPool: (uri: string) => { query: (sql: string) => Promise<unknown>; end: () => Promise<void> } };\n const pool = mysql2.createPool(config.connectionString!);\n await pool.query('SELECT 1');\n return pool;\n } catch (err) {\n throw new Error(`Failed to connect to MySQL: ${(err as Error).message}. Ensure 'mysql2' is installed.`);\n }\n }\n case 'sqlite': {\n try {\n const BetterSqlite3 = this.dynamicRequire('better-sqlite3') as new (path: string) => unknown;\n return new BetterSqlite3(config.connectionString!);\n } catch (err) {\n throw new Error(`Failed to open SQLite: ${(err as Error).message}. Ensure 'better-sqlite3' is installed.`);\n }\n }\n default:\n throw new Error(`Unsupported database type: ${config.type}`);\n }\n }\n}\n","import type { SchemaTable, SchemaColumn, SchemaForeignKey, SchemaIndex, DatabaseSchema } from '../types.js';\nimport type { ManagedConnection } from './connections.js';\n\n// ============================================================\n// Schema Introspector\n// Reads database schema from PostgreSQL, MySQL, and SQLite\n// ============================================================\n\nexport class SchemaIntrospector {\n async introspect(connection: ManagedConnection, tableName?: string): Promise<DatabaseSchema> {\n switch (connection.config.type) {\n case 'postgres':\n return this.introspectPostgres(connection, tableName);\n case 'mysql':\n return this.introspectMysql(connection, tableName);\n case 'sqlite':\n return this.introspectSqlite(connection, tableName);\n default:\n throw new Error(`Unsupported database type: ${connection.config.type}`);\n }\n }\n\n private async introspectPostgres(conn: ManagedConnection, tableName?: string): Promise<DatabaseSchema> {\n const pg = conn.client as { query: (sql: string, params?: unknown[]) => Promise<{ rows: Record<string, unknown>[] }> };\n\n // Get tables\n const tableFilter = tableName ? `AND table_name = $1` : '';\n const tableParams = tableName ? [tableName] : [];\n const tablesResult = await pg.query(\n `SELECT table_name FROM information_schema.tables WHERE table_schema = 'public' ${tableFilter} ORDER BY table_name`,\n tableParams\n );\n\n const tables: SchemaTable[] = [];\n\n for (const row of tablesResult.rows) {\n const tName = row.table_name as string;\n\n // Columns\n const colsResult = await pg.query(\n `SELECT column_name, data_type, is_nullable, column_default\n FROM information_schema.columns\n WHERE table_schema = 'public' AND table_name = $1\n ORDER BY ordinal_position`,\n [tName]\n );\n\n // Primary keys\n const pkResult = await pg.query(\n `SELECT kcu.column_name\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name\n WHERE tc.table_schema = 'public' AND tc.table_name = $1 AND tc.constraint_type = 'PRIMARY KEY'`,\n [tName]\n );\n const pkColumns = new Set(pkResult.rows.map((r) => r.column_name as string));\n\n const columns: SchemaColumn[] = colsResult.rows.map((r) => ({\n name: r.column_name as string,\n type: r.data_type as string,\n nullable: r.is_nullable === 'YES',\n defaultValue: r.column_default as string | undefined,\n isPrimaryKey: pkColumns.has(r.column_name as string),\n }));\n\n // Foreign keys\n const fkResult = await pg.query(\n `SELECT kcu.column_name, ccu.table_name AS referenced_table, ccu.column_name AS referenced_column\n FROM information_schema.table_constraints tc\n JOIN information_schema.key_column_usage kcu ON tc.constraint_name = kcu.constraint_name\n JOIN information_schema.constraint_column_usage ccu ON tc.constraint_name = ccu.constraint_name\n WHERE tc.table_schema = 'public' AND tc.table_name = $1 AND tc.constraint_type = 'FOREIGN KEY'`,\n [tName]\n );\n\n const foreignKeys: SchemaForeignKey[] = fkResult.rows.map((r) => ({\n column: r.column_name as string,\n referencedTable: r.referenced_table as string,\n referencedColumn: r.referenced_column as string,\n }));\n\n // Indexes\n const idxResult = await pg.query(\n `SELECT indexname, indexdef FROM pg_indexes WHERE tablename = $1 AND schemaname = 'public'`,\n [tName]\n );\n\n const indexes: SchemaIndex[] = idxResult.rows.map((r) => {\n const indexDef = r.indexdef as string;\n const isUnique = indexDef.includes('UNIQUE');\n // Extract column names from index definition\n const colMatch = indexDef.match(/\\(([^)]+)\\)/);\n const idxCols = colMatch ? colMatch[1].split(',').map((c) => c.trim().replace(/\"/g, '')) : [];\n return {\n name: r.indexname as string,\n columns: idxCols,\n unique: isUnique,\n };\n });\n\n // Row count estimate\n const countResult = await pg.query(\n `SELECT reltuples::bigint AS estimate FROM pg_class WHERE relname = $1`,\n [tName]\n );\n const rowCount = countResult.rows[0]?.estimate as number | undefined;\n\n tables.push({ name: tName, columns, foreignKeys, indexes, rowCount: rowCount ?? undefined });\n }\n\n return { connectionId: conn.config.id, tables, fetchedAt: Date.now() };\n }\n\n private async introspectMysql(conn: ManagedConnection, tableName?: string): Promise<DatabaseSchema> {\n const mysql = conn.client as { query: (sql: string, params?: unknown[]) => Promise<[Record<string, unknown>[]]> };\n\n const tableFilter = tableName ? `AND table_name = ?` : '';\n const tableParams = tableName ? [tableName] : [];\n const [tableRows] = await mysql.query(\n `SELECT table_name FROM information_schema.tables WHERE table_schema = DATABASE() ${tableFilter} ORDER BY table_name`,\n tableParams\n );\n\n const tables: SchemaTable[] = [];\n\n for (const row of tableRows) {\n const tName = row.table_name as string;\n\n const [colRows] = await mysql.query(\n `SELECT column_name, data_type, is_nullable, column_default, column_key\n FROM information_schema.columns\n WHERE table_schema = DATABASE() AND table_name = ?\n ORDER BY ordinal_position`,\n [tName]\n );\n\n const columns: SchemaColumn[] = (colRows as Record<string, unknown>[]).map((r) => ({\n name: r.column_name as string,\n type: r.data_type as string,\n nullable: r.is_nullable === 'YES',\n defaultValue: r.column_default as string | undefined,\n isPrimaryKey: r.column_key === 'PRI',\n }));\n\n const [fkRows] = await mysql.query(\n `SELECT column_name, referenced_table_name, referenced_column_name\n FROM information_schema.key_column_usage\n WHERE table_schema = DATABASE() AND table_name = ? AND referenced_table_name IS NOT NULL`,\n [tName]\n );\n\n const foreignKeys: SchemaForeignKey[] = (fkRows as Record<string, unknown>[]).map((r) => ({\n column: r.column_name as string,\n referencedTable: r.referenced_table_name as string,\n referencedColumn: r.referenced_column_name as string,\n }));\n\n const [idxRows] = await mysql.query(`SHOW INDEX FROM \\`${tName}\\``);\n const indexMap = new Map<string, { columns: string[]; unique: boolean }>();\n for (const r of idxRows as Record<string, unknown>[]) {\n const name = r.Key_name as string;\n const existing = indexMap.get(name) ?? { columns: [], unique: (r.Non_unique as number) === 0 };\n existing.columns.push(r.Column_name as string);\n indexMap.set(name, existing);\n }\n\n const indexes: SchemaIndex[] = Array.from(indexMap.entries()).map(([name, data]) => ({\n name,\n columns: data.columns,\n unique: data.unique,\n }));\n\n tables.push({ name: tName, columns, foreignKeys, indexes });\n }\n\n return { connectionId: conn.config.id, tables, fetchedAt: Date.now() };\n }\n\n private async introspectSqlite(conn: ManagedConnection, tableName?: string): Promise<DatabaseSchema> {\n const db = conn.client as {\n prepare: (sql: string) => { all: (...args: unknown[]) => Record<string, unknown>[] };\n };\n\n let tableNames: string[];\n if (tableName) {\n tableNames = [tableName];\n } else {\n const rows = db.prepare(`SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name`).all();\n tableNames = rows.map((r) => r.name as string);\n }\n\n const tables: SchemaTable[] = [];\n\n for (const tName of tableNames) {\n const colRows = db.prepare(`PRAGMA table_info(\"${tName}\")`).all();\n const columns: SchemaColumn[] = colRows.map((r) => ({\n name: r.name as string,\n type: r.type as string,\n nullable: (r.notnull as number) === 0,\n defaultValue: r.dflt_value as string | undefined,\n isPrimaryKey: (r.pk as number) > 0,\n }));\n\n const fkRows = db.prepare(`PRAGMA foreign_key_list(\"${tName}\")`).all();\n const foreignKeys: SchemaForeignKey[] = fkRows.map((r) => ({\n column: r.from as string,\n referencedTable: r.table as string,\n referencedColumn: r.to as string,\n }));\n\n const idxRows = db.prepare(`PRAGMA index_list(\"${tName}\")`).all();\n const indexes: SchemaIndex[] = idxRows.map((r) => {\n const idxInfoRows = db.prepare(`PRAGMA index_info(\"${r.name}\")`).all();\n return {\n name: r.name as string,\n columns: idxInfoRows.map((ir) => ir.name as string),\n unique: (r.unique as number) === 1,\n };\n });\n\n // Row count\n const countRow = db.prepare(`SELECT COUNT(*) as count FROM \"${tName}\"`).all()[0];\n const rowCount = countRow?.count as number | undefined;\n\n tables.push({ name: tName, columns, foreignKeys, indexes, rowCount });\n }\n\n return { connectionId: conn.config.id, tables, fetchedAt: Date.now() };\n }\n}\n","import type { ManagedConnection } from './connections.js';\n\n// ============================================================\n// Data Browser\n// Paginated reads and guarded writes for local dev databases\n// ============================================================\n\nconst MAX_AFFECTED_ROWS = 100;\n\nexport interface ReadOptions {\n table: string;\n limit?: number;\n offset?: number;\n where?: string;\n orderBy?: string;\n}\n\nexport interface ReadResult {\n rows: Record<string, unknown>[];\n total: number;\n limit: number;\n offset: number;\n}\n\nexport interface WriteOptions {\n table: string;\n operation: 'insert' | 'update' | 'delete';\n data?: Record<string, unknown>;\n where?: string;\n}\n\nexport interface WriteResult {\n success: boolean;\n affectedRows: number;\n error?: string;\n}\n\nexport class DataBrowser {\n async read(connection: ManagedConnection, options: ReadOptions): Promise<ReadResult> {\n const limit = Math.min(options.limit ?? 50, 1000);\n const offset = options.offset ?? 0;\n\n switch (connection.config.type) {\n case 'postgres':\n return this.readPostgres(connection, options, limit, offset);\n case 'mysql':\n return this.readMysql(connection, options, limit, offset);\n case 'sqlite':\n return this.readSqlite(connection, options, limit, offset);\n default:\n throw new Error(`Unsupported database type: ${connection.config.type}`);\n }\n }\n\n async write(connection: ManagedConnection, options: WriteOptions): Promise<WriteResult> {\n // Safety guard 1: Only localhost connections\n this.assertLocalhost(connection);\n\n // Safety guard 2: WHERE required for UPDATE/DELETE\n if ((options.operation === 'update' || options.operation === 'delete') && !options.where) {\n return { success: false, affectedRows: 0, error: 'WHERE clause is required for UPDATE and DELETE operations' };\n }\n\n switch (connection.config.type) {\n case 'postgres':\n return this.writePostgres(connection, options);\n case 'mysql':\n return this.writeMysql(connection, options);\n case 'sqlite':\n return this.writeSqlite(connection, options);\n default:\n throw new Error(`Unsupported database type: ${connection.config.type}`);\n }\n }\n\n private assertLocalhost(connection: ManagedConnection): void {\n const connStr = connection.config.connectionString ?? '';\n const isLocal = connStr.includes('localhost') ||\n connStr.includes('127.0.0.1') ||\n connStr.includes('0.0.0.0') ||\n connection.config.type === 'sqlite';\n\n if (!isLocal) {\n throw new Error('Write operations are only allowed on localhost/local database connections. This safety guard prevents accidental modification of production databases.');\n }\n }\n\n // --- PostgreSQL ---\n\n private async readPostgres(conn: ManagedConnection, opts: ReadOptions, limit: number, offset: number): Promise<ReadResult> {\n const pg = conn.client as { query: (sql: string, params?: unknown[]) => Promise<{ rows: Record<string, unknown>[] }> };\n const where = opts.where ? `WHERE ${opts.where}` : '';\n const orderBy = opts.orderBy ? `ORDER BY ${opts.orderBy}` : '';\n\n const countResult = await pg.query(`SELECT COUNT(*) as total FROM \"${opts.table}\" ${where}`);\n const total = parseInt(countResult.rows[0].total as string, 10);\n\n const result = await pg.query(`SELECT * FROM \"${opts.table}\" ${where} ${orderBy} LIMIT ${limit} OFFSET ${offset}`);\n return { rows: result.rows, total, limit, offset };\n }\n\n private async writePostgres(conn: ManagedConnection, opts: WriteOptions): Promise<WriteResult> {\n const pg = conn.client as { query: (sql: string) => Promise<{ rowCount: number }> };\n\n try {\n // Safety guard 3: Check affected rows before executing\n if (opts.operation !== 'insert' && opts.where) {\n const countResult = await (pg as unknown as { query: (sql: string) => Promise<{ rows: Record<string, unknown>[] }> })\n .query(`SELECT COUNT(*) as cnt FROM \"${opts.table}\" WHERE ${opts.where}`);\n const count = parseInt(countResult.rows[0].cnt as string, 10);\n if (count > MAX_AFFECTED_ROWS) {\n return { success: false, affectedRows: 0, error: `Operation would affect ${count} rows (max ${MAX_AFFECTED_ROWS}). Narrow your WHERE clause.` };\n }\n }\n\n await pg.query('BEGIN');\n let result: { rowCount: number };\n\n switch (opts.operation) {\n case 'insert': {\n const cols = Object.keys(opts.data!);\n const vals = Object.values(opts.data!).map((v) => typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v);\n result = await pg.query(`INSERT INTO \"${opts.table}\" (${cols.join(', ')}) VALUES (${vals.join(', ')})`);\n break;\n }\n case 'update': {\n const sets = Object.entries(opts.data!).map(([k, v]) =>\n `${k} = ${typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v}`\n );\n result = await pg.query(`UPDATE \"${opts.table}\" SET ${sets.join(', ')} WHERE ${opts.where}`);\n break;\n }\n case 'delete':\n result = await pg.query(`DELETE FROM \"${opts.table}\" WHERE ${opts.where}`);\n break;\n default:\n throw new Error(`Unknown operation: ${opts.operation}`);\n }\n\n await pg.query('COMMIT');\n return { success: true, affectedRows: result.rowCount };\n } catch (err) {\n await pg.query('ROLLBACK').catch(() => {});\n return { success: false, affectedRows: 0, error: (err as Error).message };\n }\n }\n\n // --- MySQL ---\n\n private async readMysql(conn: ManagedConnection, opts: ReadOptions, limit: number, offset: number): Promise<ReadResult> {\n const mysql = conn.client as { query: (sql: string) => Promise<[Record<string, unknown>[]]> };\n const where = opts.where ? `WHERE ${opts.where}` : '';\n const orderBy = opts.orderBy ? `ORDER BY ${opts.orderBy}` : '';\n\n const [countRows] = await mysql.query(`SELECT COUNT(*) as total FROM \\`${opts.table}\\` ${where}`);\n const total = (countRows[0] as Record<string, unknown>).total as number;\n\n const [rows] = await mysql.query(`SELECT * FROM \\`${opts.table}\\` ${where} ${orderBy} LIMIT ${limit} OFFSET ${offset}`);\n return { rows: rows as Record<string, unknown>[], total, limit, offset };\n }\n\n private async writeMysql(conn: ManagedConnection, opts: WriteOptions): Promise<WriteResult> {\n const mysql = conn.client as { query: (sql: string) => Promise<[{ affectedRows: number }]> };\n\n try {\n if (opts.operation !== 'insert' && opts.where) {\n const [countRows] = await (mysql as unknown as { query: (sql: string) => Promise<[Record<string, unknown>[]]> })\n .query(`SELECT COUNT(*) as cnt FROM \\`${opts.table}\\` WHERE ${opts.where}`);\n const count = (countRows[0] as Record<string, unknown>).cnt as number;\n if (count > MAX_AFFECTED_ROWS) {\n return { success: false, affectedRows: 0, error: `Operation would affect ${count} rows (max ${MAX_AFFECTED_ROWS}).` };\n }\n }\n\n await mysql.query('START TRANSACTION');\n let result: [{ affectedRows: number }];\n\n switch (opts.operation) {\n case 'insert': {\n const cols = Object.keys(opts.data!);\n const vals = Object.values(opts.data!).map((v) => typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v);\n result = await mysql.query(`INSERT INTO \\`${opts.table}\\` (${cols.join(', ')}) VALUES (${vals.join(', ')})`);\n break;\n }\n case 'update': {\n const sets = Object.entries(opts.data!).map(([k, v]) =>\n `\\`${k}\\` = ${typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v}`\n );\n result = await mysql.query(`UPDATE \\`${opts.table}\\` SET ${sets.join(', ')} WHERE ${opts.where}`);\n break;\n }\n case 'delete':\n result = await mysql.query(`DELETE FROM \\`${opts.table}\\` WHERE ${opts.where}`);\n break;\n default:\n throw new Error(`Unknown operation: ${opts.operation}`);\n }\n\n await mysql.query('COMMIT');\n return { success: true, affectedRows: result[0].affectedRows };\n } catch (err) {\n await mysql.query('ROLLBACK').catch(() => {});\n return { success: false, affectedRows: 0, error: (err as Error).message };\n }\n }\n\n // --- SQLite ---\n\n private async readSqlite(conn: ManagedConnection, opts: ReadOptions, limit: number, offset: number): Promise<ReadResult> {\n const db = conn.client as { prepare: (sql: string) => { all: () => Record<string, unknown>[]; get: () => Record<string, unknown> } };\n const where = opts.where ? `WHERE ${opts.where}` : '';\n const orderBy = opts.orderBy ? `ORDER BY ${opts.orderBy}` : '';\n\n const countRow = db.prepare(`SELECT COUNT(*) as total FROM \"${opts.table}\" ${where}`).get();\n const total = countRow.total as number;\n\n const rows = db.prepare(`SELECT * FROM \"${opts.table}\" ${where} ${orderBy} LIMIT ${limit} OFFSET ${offset}`).all();\n return { rows, total, limit, offset };\n }\n\n private async writeSqlite(conn: ManagedConnection, opts: WriteOptions): Promise<WriteResult> {\n const db = conn.client as {\n prepare: (sql: string) => { run: () => { changes: number }; get: () => Record<string, unknown> };\n exec: (sql: string) => void;\n };\n\n try {\n if (opts.operation !== 'insert' && opts.where) {\n const countRow = db.prepare(`SELECT COUNT(*) as cnt FROM \"${opts.table}\" WHERE ${opts.where}`).get();\n const count = countRow.cnt as number;\n if (count > MAX_AFFECTED_ROWS) {\n return { success: false, affectedRows: 0, error: `Operation would affect ${count} rows (max ${MAX_AFFECTED_ROWS}).` };\n }\n }\n\n db.exec('BEGIN');\n let changes: number;\n\n switch (opts.operation) {\n case 'insert': {\n const cols = Object.keys(opts.data!);\n const vals = Object.values(opts.data!).map((v) => typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v);\n const result = db.prepare(`INSERT INTO \"${opts.table}\" (${cols.join(', ')}) VALUES (${vals.join(', ')})`).run();\n changes = result.changes;\n break;\n }\n case 'update': {\n const sets = Object.entries(opts.data!).map(([k, v]) =>\n `\"${k}\" = ${typeof v === 'string' ? `'${v.replace(/'/g, \"''\")}'` : v}`\n );\n const result = db.prepare(`UPDATE \"${opts.table}\" SET ${sets.join(', ')} WHERE ${opts.where}`).run();\n changes = result.changes;\n break;\n }\n case 'delete': {\n const result = db.prepare(`DELETE FROM \"${opts.table}\" WHERE ${opts.where}`).run();\n changes = result.changes;\n break;\n }\n default:\n throw new Error(`Unknown operation: ${opts.operation}`);\n }\n\n db.exec('COMMIT');\n return { success: true, affectedRows: changes };\n } catch (err) {\n try { db.exec('ROLLBACK'); } catch { /* ignore */ }\n return { success: false, affectedRows: 0, error: (err as Error).message };\n }\n }\n}\n","import { execSync } from 'node:child_process';\nimport type { EventStore } from '../store.js';\nimport type { DevProcess, DevProcessType, PortUsage, DetectedIssue } from '../types.js';\n\n// ============================================================\n// Process Monitor Engine\n// Scans for running dev processes (macOS/Linux only)\n// ============================================================\n\nconst PROCESS_PATTERNS: [RegExp, DevProcessType][] = [\n [/next[\\s-]dev|next-server/, 'next'],\n [/vite/, 'vite'],\n [/webpack[\\s-]dev[\\s-]server|webpack serve/, 'webpack'],\n [/wrangler/, 'wrangler'],\n [/prisma\\s+studio|prisma\\s+dev/, 'prisma'],\n [/docker/, 'docker'],\n [/postgres|pg_/, 'postgres'],\n [/mysqld/, 'mysql'],\n [/redis-server/, 'redis'],\n [/\\bbun\\b/, 'bun'],\n [/\\bdeno\\b/, 'deno'],\n [/\\bpython[23]?\\b/, 'python'],\n [/\\bnode\\b/, 'node'],\n];\n\nfunction detectProcessType(command: string): DevProcessType {\n for (const [pattern, type] of PROCESS_PATTERNS) {\n if (pattern.test(command)) return type;\n }\n return 'unknown';\n}\n\nfunction parsePs(): { pid: number; cpu: number; mem: number; command: string }[] {\n try {\n const output = execSync('ps aux', { encoding: 'utf-8', timeout: 5000 });\n const lines = output.split('\\n').slice(1); // Skip header\n const results: { pid: number; cpu: number; mem: number; command: string }[] = [];\n\n for (const line of lines) {\n const parts = line.trim().split(/\\s+/);\n if (parts.length < 11) continue;\n\n const pid = parseInt(parts[1], 10);\n const cpu = parseFloat(parts[2]);\n const mem = parseFloat(parts[3]);\n // VSZ is in KB, convert to MB\n const command = parts.slice(10).join(' ');\n\n if (isNaN(pid)) continue;\n results.push({ pid, cpu, mem, command });\n }\n\n return results;\n } catch {\n return [];\n }\n}\n\nfunction getListenPorts(pid: number): number[] {\n try {\n const output = execSync(`lsof -nP -p ${pid} 2>/dev/null | grep LISTEN`, {\n encoding: 'utf-8',\n timeout: 3000,\n });\n\n const ports: number[] = [];\n for (const line of output.split('\\n')) {\n const match = line.match(/:(\\d+)\\s+\\(LISTEN\\)/);\n if (match) {\n ports.push(parseInt(match[1], 10));\n }\n }\n return [...new Set(ports)];\n } catch {\n return [];\n }\n}\n\nfunction getCwd(pid: number): string | undefined {\n try {\n // macOS: lsof -p PID | grep cwd\n const output = execSync(`lsof -p ${pid} 2>/dev/null | grep cwd`, {\n encoding: 'utf-8',\n timeout: 3000,\n });\n const match = output.match(/cwd\\s+\\w+\\s+\\w+\\s+\\d+\\w?\\s+\\d+\\s+\\d+\\s+\\d+\\s+(.+)/);\n return match?.[1]?.trim();\n } catch {\n return undefined;\n }\n}\n\nfunction getMemoryMB(pid: number): number {\n try {\n const output = execSync(`ps -o rss= -p ${pid}`, { encoding: 'utf-8', timeout: 2000 });\n const rss = parseInt(output.trim(), 10);\n return isNaN(rss) ? 0 : rss / 1024;\n } catch {\n return 0;\n }\n}\n\nexport class ProcessMonitor {\n private store: EventStore;\n private scanInterval: ReturnType<typeof setInterval> | null = null;\n private processes: Map<number, DevProcess> = new Map();\n private lastActivity: Map<number, number> = new Map();\n\n constructor(store: EventStore) {\n this.store = store;\n }\n\n start(intervalMs = 10_000): void {\n this.scan();\n this.scanInterval = setInterval(() => this.scan(), intervalMs);\n }\n\n stop(): void {\n if (this.scanInterval) {\n clearInterval(this.scanInterval);\n this.scanInterval = null;\n }\n }\n\n scan(): void {\n const allProcesses = parsePs();\n const relevantTypes: Set<DevProcessType> = new Set([\n 'next', 'vite', 'webpack', 'wrangler', 'prisma',\n 'docker', 'postgres', 'mysql', 'redis', 'bun', 'deno',\n ]);\n\n const foundPids = new Set<number>();\n\n for (const proc of allProcesses) {\n const type = detectProcessType(proc.command);\n // Only track known dev-related processes, or node processes listening on ports\n if (type === 'unknown' || type === 'python') continue;\n if (type === 'node' && !relevantTypes.has(type)) {\n // For generic node processes, only include if they look like dev servers\n if (!proc.command.includes('server') && !proc.command.includes('dev') && !proc.command.includes('start')) {\n continue;\n }\n }\n\n foundPids.add(proc.pid);\n\n // Only do expensive lsof lookups on first discovery or periodically\n const existing = this.processes.get(proc.pid);\n const ports = existing?.ports ?? getListenPorts(proc.pid);\n const cwd = existing?.cwd ?? getCwd(proc.pid);\n const memoryMB = getMemoryMB(proc.pid);\n\n // Check orphan status: no activity in 30 minutes\n const lastActive = this.lastActivity.get(proc.pid) ?? Date.now();\n const isOrphaned = Date.now() - lastActive > 30 * 60 * 1000;\n\n this.processes.set(proc.pid, {\n pid: proc.pid,\n command: proc.command.slice(0, 200),\n type,\n cpuPercent: proc.cpu,\n memoryMB,\n ports,\n cwd,\n isOrphaned,\n });\n }\n\n // Remove processes that no longer exist\n for (const pid of this.processes.keys()) {\n if (!foundPids.has(pid)) {\n this.processes.delete(pid);\n this.lastActivity.delete(pid);\n }\n }\n }\n\n getProcesses(filter?: { project?: string; type?: DevProcessType }): DevProcess[] {\n const results = Array.from(this.processes.values());\n\n return results.filter((p) => {\n if (filter?.type && p.type !== filter.type) return false;\n if (filter?.project && p.project !== filter.project) return false;\n return true;\n });\n }\n\n killProcess(pid: number, signal: 'SIGTERM' | 'SIGKILL' = 'SIGTERM'): { success: boolean; error?: string } {\n try {\n process.kill(pid, signal);\n this.processes.delete(pid);\n return { success: true };\n } catch (err) {\n return { success: false, error: (err as Error).message };\n }\n }\n\n getPortUsage(port?: number): PortUsage[] {\n const results: PortUsage[] = [];\n\n for (const proc of this.processes.values()) {\n for (const p of proc.ports) {\n if (port !== undefined && p !== port) continue;\n results.push({\n port: p,\n pid: proc.pid,\n process: proc.command.slice(0, 100),\n type: proc.type,\n project: proc.project,\n });\n }\n }\n\n return results.sort((a, b) => a.port - b.port);\n }\n\n detectIssues(): DetectedIssue[] {\n const issues: DetectedIssue[] = [];\n\n for (const proc of this.processes.values()) {\n // Orphaned process\n if (proc.isOrphaned) {\n issues.push({\n id: `orphaned-${proc.pid}`,\n pattern: 'orphaned_process',\n severity: 'low',\n title: `Orphaned Process: ${proc.type} (PID ${proc.pid})`,\n description: `Dev server process has had no activity for 30+ minutes.`,\n evidence: [\n `PID: ${proc.pid}`,\n `Type: ${proc.type}`,\n `Memory: ${proc.memoryMB.toFixed(0)}MB`,\n `Command: ${proc.command.slice(0, 100)}`,\n ],\n suggestion: `Kill with: kill ${proc.pid}`,\n });\n }\n\n // High memory\n if (proc.memoryMB > 1024) {\n issues.push({\n id: `high-memory-${proc.pid}`,\n pattern: 'high_memory_process',\n severity: 'medium',\n title: `High Memory: ${proc.type} using ${proc.memoryMB.toFixed(0)}MB`,\n description: `Process is using ${proc.memoryMB.toFixed(0)}MB of memory (>1GB).`,\n evidence: [\n `PID: ${proc.pid}`,\n `Memory: ${proc.memoryMB.toFixed(0)}MB`,\n `CPU: ${proc.cpuPercent}%`,\n ],\n suggestion: 'Restart the process or investigate memory leaks.',\n });\n }\n }\n\n return issues;\n }\n}\n","import type { EventStore } from '../store.js';\nimport type { ProjectManager } from '../project-manager.js';\nimport type {\n DeployLog,\n RuntimeLog,\n BuildStatus,\n InfraOverview,\n} from '../types.js';\n\n// ============================================================\n// Infrastructure Connector Engine\n// Connects to deployment platform APIs (Vercel, Cloudflare, Railway)\n// ============================================================\n\ninterface PlatformClient {\n name: string;\n getDeployments(opts?: { limit?: number; deployId?: string }): Promise<DeployLog[]>;\n getRuntimeLogs(opts?: { since?: number; level?: string }): Promise<RuntimeLog[]>;\n getBuildStatus(): Promise<BuildStatus | null>;\n}\n\n// --- Vercel Client ---\n\nfunction createVercelClient(projectId: string, token: string): PlatformClient {\n const baseUrl = 'https://api.vercel.com';\n const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' };\n\n return {\n name: 'Vercel',\n async getDeployments(opts) {\n const limit = opts?.limit ?? 10;\n const url = opts?.deployId\n ? `${baseUrl}/v13/deployments/${opts.deployId}`\n : `${baseUrl}/v6/deployments?projectId=${projectId}&limit=${limit}`;\n\n const res = await fetch(url, { headers });\n if (!res.ok) return [];\n\n const data = await res.json() as Record<string, unknown>;\n\n if (opts?.deployId) {\n return [mapVercelDeployment(data, projectId)];\n }\n\n const deployments = (data.deployments ?? []) as Record<string, unknown>[];\n return deployments.map((d) => mapVercelDeployment(d, projectId));\n },\n\n async getRuntimeLogs(opts) {\n // Vercel runtime logs require specific deployment ID — return empty for now\n void opts;\n return [];\n },\n\n async getBuildStatus() {\n const res = await fetch(`${baseUrl}/v6/deployments?projectId=${projectId}&limit=1`, { headers });\n if (!res.ok) return null;\n\n const data = await res.json() as Record<string, unknown>;\n const deployments = (data.deployments ?? []) as Record<string, unknown>[];\n if (deployments.length === 0) return null;\n\n const latest = deployments[0];\n return {\n platform: 'Vercel',\n project: projectId,\n latestDeployId: latest.uid as string,\n status: mapVercelStatus(latest.state as string),\n url: latest.url ? `https://${latest.url}` : undefined,\n lastDeployed: latest.created as number,\n };\n },\n };\n}\n\nfunction mapVercelDeployment(d: Record<string, unknown>, projectId: string): DeployLog {\n return {\n id: d.uid as string,\n platform: 'Vercel',\n project: projectId,\n status: mapVercelStatus(d.state as string ?? d.readyState as string),\n url: d.url ? `https://${d.url}` : undefined,\n branch: (d.meta as Record<string, unknown>)?.githubCommitRef as string | undefined,\n commit: (d.meta as Record<string, unknown>)?.githubCommitSha as string | undefined,\n createdAt: d.created as number ?? d.createdAt as number,\n readyAt: d.ready as number | undefined,\n errorMessage: undefined,\n };\n}\n\nfunction mapVercelStatus(state: string): DeployLog['status'] {\n if (state === 'READY' || state === 'ready') return 'ready';\n if (state === 'ERROR' || state === 'error') return 'error';\n if (state === 'CANCELED' || state === 'canceled') return 'canceled';\n return 'building';\n}\n\n// --- Cloudflare Client ---\n\nfunction createCloudflareClient(accountId: string, workerName: string, token: string): PlatformClient {\n const baseUrl = `https://api.cloudflare.com/client/v4/accounts/${accountId}`;\n const headers = { Authorization: `Bearer ${token}`, 'Content-Type': 'application/json' };\n\n return {\n name: 'Cloudflare Workers',\n async getDeployments(opts) {\n void opts;\n // Cloudflare doesn't have a direct deployments list for workers\n // We can check the worker script upload history\n const res = await fetch(`${baseUrl}/workers/scripts/${workerName}`, { headers });\n if (!res.ok) return [];\n\n const data = await res.json() as Record<string, unknown>;\n const result = data.result as Record<string, unknown> | undefined;\n if (!result) return [];\n\n return [{\n id: result.id as string ?? workerName,\n platform: 'Cloudflare Workers',\n project: workerName,\n status: 'ready' as const,\n createdAt: new Date(result.modified_on as string).getTime(),\n }];\n },\n\n async getRuntimeLogs(opts) {\n void opts;\n // Cloudflare worker logs require WebSocket connection to tail endpoint\n return [];\n },\n\n async getBuildStatus() {\n const res = await fetch(`${baseUrl}/workers/scripts/${workerName}`, { headers });\n if (!res.ok) return null;\n\n const data = await res.json() as Record<string, unknown>;\n const result = data.result as Record<string, unknown> | undefined;\n if (!result) return null;\n\n return {\n platform: 'Cloudflare Workers',\n project: workerName,\n latestDeployId: result.id as string ?? workerName,\n status: 'ready' as const,\n lastDeployed: new Date(result.modified_on as string).getTime(),\n };\n },\n };\n}\n\n// --- Railway Client ---\n\nfunction createRailwayClient(projectId: string, token: string): PlatformClient {\n const graphqlUrl = 'https://backboard.railway.app/graphql/v2';\n\n async function gql(query: string, variables?: Record<string, unknown>): Promise<Record<string, unknown>> {\n const res = await fetch(graphqlUrl, {\n method: 'POST',\n headers: {\n Authorization: `Bearer ${token}`,\n 'Content-Type': 'application/json',\n },\n body: JSON.stringify({ query, variables }),\n });\n if (!res.ok) return {};\n return await res.json() as Record<string, unknown>;\n }\n\n return {\n name: 'Railway',\n async getDeployments(opts) {\n const limit = opts?.limit ?? 10;\n const data = await gql(`\n query($projectId: String!, $first: Int) {\n deployments(input: { projectId: $projectId }, first: $first) {\n edges {\n node {\n id\n status\n createdAt\n url\n meta { branch commitHash }\n }\n }\n }\n }\n `, { projectId, first: limit });\n\n const edges = ((data.data as Record<string, unknown>)?.deployments as Record<string, unknown>)?.edges as { node: Record<string, unknown> }[] ?? [];\n\n return edges.map((edge) => {\n const d = edge.node;\n const meta = d.meta as Record<string, unknown> | undefined;\n return {\n id: d.id as string,\n platform: 'Railway',\n project: projectId,\n status: mapRailwayStatus(d.status as string),\n url: d.url as string | undefined,\n branch: meta?.branch as string | undefined,\n commit: meta?.commitHash as string | undefined,\n createdAt: new Date(d.createdAt as string).getTime(),\n };\n });\n },\n\n async getRuntimeLogs(opts) {\n void opts;\n // Railway logs require specific deployment ID and streaming\n return [];\n },\n\n async getBuildStatus() {\n const data = await gql(`\n query($projectId: String!) {\n deployments(input: { projectId: $projectId }, first: 1) {\n edges {\n node { id status createdAt url }\n }\n }\n }\n `, { projectId });\n\n const edges = ((data.data as Record<string, unknown>)?.deployments as Record<string, unknown>)?.edges as { node: Record<string, unknown> }[] ?? [];\n if (edges.length === 0) return null;\n\n const d = edges[0].node;\n return {\n platform: 'Railway',\n project: projectId,\n latestDeployId: d.id as string,\n status: mapRailwayStatus(d.status as string),\n url: d.url as string | undefined,\n lastDeployed: new Date(d.createdAt as string).getTime(),\n };\n },\n };\n}\n\nfunction mapRailwayStatus(status: string): DeployLog['status'] {\n if (status === 'SUCCESS') return 'ready';\n if (status === 'FAILED') return 'error';\n if (status === 'REMOVED' || status === 'CANCELLED') return 'canceled';\n return 'building';\n}\n\n// ============================================================\n// Main Engine\n// ============================================================\n\nexport class InfraConnector {\n private store: EventStore;\n private clients: Map<string, PlatformClient> = new Map();\n\n constructor(store: EventStore) {\n this.store = store;\n }\n\n loadFromConfig(projectManager: ProjectManager, projectName: string): void {\n const config = projectManager.getInfrastructureConfig(projectName);\n if (!config?.deployments) return;\n\n for (const [key, deployment] of Object.entries(config.deployments)) {\n switch (deployment.platform) {\n case 'vercel': {\n const token = process.env.VERCEL_TOKEN ?? '';\n if (token && deployment.project_id) {\n this.clients.set(key, createVercelClient(deployment.project_id, token));\n }\n break;\n }\n case 'cloudflare': {\n const token = process.env.CLOUDFLARE_API_TOKEN ?? '';\n if (token && deployment.account_id && deployment.worker_name) {\n this.clients.set(key, createCloudflareClient(deployment.account_id, deployment.worker_name, token));\n }\n break;\n }\n case 'railway': {\n const token = process.env.RAILWAY_TOKEN ?? '';\n if (token && deployment.project_id) {\n this.clients.set(key, createRailwayClient(deployment.project_id, token));\n }\n break;\n }\n }\n }\n }\n\n async getDeployLogs(project: string, platform?: string, deployId?: string): Promise<DeployLog[]> {\n const results: DeployLog[] = [];\n\n for (const [key, client] of this.clients) {\n if (platform && client.name.toLowerCase() !== platform.toLowerCase()) continue;\n void key;\n\n try {\n const logs = await client.getDeployments({ deployId, limit: 10 });\n results.push(...logs);\n } catch {\n // Platform API may be unavailable\n }\n }\n\n return results.sort((a, b) => b.createdAt - a.createdAt);\n }\n\n async getRuntimeLogs(project: string, opts?: { platform?: string; since?: number; level?: string }): Promise<RuntimeLog[]> {\n const results: RuntimeLog[] = [];\n\n for (const [, client] of this.clients) {\n if (opts?.platform && client.name.toLowerCase() !== opts.platform.toLowerCase()) continue;\n\n try {\n const logs = await client.getRuntimeLogs(opts);\n results.push(...logs);\n } catch {\n // Platform API may be unavailable\n }\n }\n\n return results.sort((a, b) => b.timestamp - a.timestamp);\n }\n\n async getBuildStatus(project: string): Promise<BuildStatus[]> {\n const results: BuildStatus[] = [];\n\n for (const [, client] of this.clients) {\n try {\n const status = await client.getBuildStatus();\n if (status) results.push(status);\n } catch {\n // Platform API may be unavailable\n }\n }\n\n return results;\n }\n\n getInfraOverview(project?: string): InfraOverview[] {\n // Detect services from network traffic\n const networkEvents = this.store.getNetworkRequests();\n const detectedPlatforms = new Set<string>();\n\n for (const event of networkEvents) {\n try {\n const hostname = new URL(event.url).hostname;\n if (hostname.includes('vercel')) detectedPlatforms.add('Vercel');\n if (hostname.includes('cloudflare') || hostname.includes('workers.dev')) detectedPlatforms.add('Cloudflare');\n if (hostname.includes('railway')) detectedPlatforms.add('Railway');\n if (hostname.includes('supabase')) detectedPlatforms.add('Supabase');\n if (hostname.includes('firebase')) detectedPlatforms.add('Firebase');\n if (hostname.includes('netlify')) detectedPlatforms.add('Netlify');\n } catch { /* ignore */ }\n }\n\n const platforms = Array.from(this.clients.entries()).map(([, client]) => ({\n name: client.name,\n configured: true,\n deployCount: 0,\n status: 'configured',\n }));\n\n return [{\n project: project ?? 'default',\n platforms,\n detectedFromTraffic: [...detectedPlatforms],\n }];\n }\n}\n","import type { ProjectManager } from './project-manager.js';\nimport type { SqliteStore } from './sqlite-store.js';\nimport type { EventStore } from './store.js';\nimport type {\n RuntimeEvent,\n NetworkEvent,\n RenderEvent,\n StateEvent,\n PerformanceEvent,\n DatabaseEvent,\n ConsoleEvent,\n SessionMetrics,\n SessionSnapshot,\n WebVitalRating,\n} from './types.js';\n\n// ============================================================\n// Session Manager\n// Computes session metrics and manages session snapshots\n// ============================================================\n\nexport class SessionManager {\n private projectManager: ProjectManager;\n private sqliteStores: Map<string, SqliteStore>;\n private store: EventStore;\n\n constructor(\n projectManager: ProjectManager,\n sqliteStores: Map<string, SqliteStore>,\n store: EventStore\n ) {\n this.projectManager = projectManager;\n this.sqliteStores = sqliteStores;\n this.store = store;\n }\n\n computeMetrics(sessionId: string, project: string, events: RuntimeEvent[]): SessionMetrics {\n const sessionEvents = events.filter((e) => e.sessionId === sessionId);\n\n const networkEvents = sessionEvents.filter((e) => e.eventType === 'network') as NetworkEvent[];\n const renderEvents = sessionEvents.filter((e) => e.eventType === 'render') as RenderEvent[];\n const stateEvents = sessionEvents.filter((e) => e.eventType === 'state') as StateEvent[];\n const performanceEvents = sessionEvents.filter((e) => e.eventType === 'performance') as PerformanceEvent[];\n const databaseEvents = sessionEvents.filter((e) => e.eventType === 'database') as DatabaseEvent[];\n const consoleEvents = sessionEvents.filter((e) => e.eventType === 'console') as ConsoleEvent[];\n\n // Endpoint metrics\n const endpoints: Record<string, { avgLatency: number; errorRate: number; callCount: number }> = {};\n const endpointGroups = new Map<string, NetworkEvent[]>();\n for (const e of networkEvents) {\n const key = `${e.method} ${e.url}`;\n const group = endpointGroups.get(key) ?? [];\n group.push(e);\n endpointGroups.set(key, group);\n }\n for (const [key, group] of endpointGroups) {\n const avgLatency = group.reduce((s, e) => s + e.duration, 0) / group.length;\n const errorCount = group.filter((e) => e.status >= 400).length;\n endpoints[key] = { avgLatency, errorRate: errorCount / group.length, callCount: group.length };\n }\n\n // Component metrics\n const components: Record<string, { renderCount: number; avgDuration: number }> = {};\n for (const re of renderEvents) {\n for (const p of re.profiles) {\n const existing = components[p.componentName];\n if (existing) {\n existing.renderCount += p.renderCount;\n existing.avgDuration = (existing.avgDuration + p.avgDuration) / 2;\n } else {\n components[p.componentName] = { renderCount: p.renderCount, avgDuration: p.avgDuration };\n }\n }\n }\n\n // Store metrics\n const stores: Record<string, { updateCount: number }> = {};\n for (const se of stateEvents) {\n const existing = stores[se.storeId];\n if (existing) {\n existing.updateCount++;\n } else {\n stores[se.storeId] = { updateCount: 1 };\n }\n }\n\n // Web Vitals (only include events with a rating — i.e., browser Web Vitals, not server metrics)\n const webVitals: Record<string, { value: number; rating: WebVitalRating }> = {};\n for (const pe of performanceEvents) {\n if (pe.rating) {\n webVitals[pe.metricName] = { value: pe.value, rating: pe.rating };\n }\n }\n\n // Query metrics\n const queries: Record<string, { avgDuration: number; callCount: number }> = {};\n const queryGroups = new Map<string, DatabaseEvent[]>();\n for (const de of databaseEvents) {\n const group = queryGroups.get(de.normalizedQuery) ?? [];\n group.push(de);\n queryGroups.set(de.normalizedQuery, group);\n }\n for (const [key, group] of queryGroups) {\n const avgDuration = group.reduce((s, e) => s + e.duration, 0) / group.length;\n queries[key] = { avgDuration, callCount: group.length };\n }\n\n const timestamps = sessionEvents.map((e) => e.timestamp);\n const errorCount = consoleEvents.filter((e) => e.level === 'error').length +\n networkEvents.filter((e) => e.status >= 400).length;\n\n return {\n sessionId,\n project,\n connectedAt: timestamps.length > 0 ? Math.min(...timestamps) : Date.now(),\n disconnectedAt: timestamps.length > 0 ? Math.max(...timestamps) : Date.now(),\n totalEvents: sessionEvents.length,\n errorCount,\n endpoints,\n components,\n stores,\n webVitals,\n queries,\n };\n }\n\n createSnapshot(sessionId: string, project: string): SessionSnapshot {\n const events = this.store.getAllEvents();\n const metrics = this.computeMetrics(sessionId, project, events);\n\n // Save to SQLite\n const sqliteStore = this.sqliteStores.get(project);\n if (sqliteStore) {\n sqliteStore.saveSessionMetrics(sessionId, project, metrics);\n }\n\n return {\n sessionId,\n project,\n metrics,\n createdAt: Date.now(),\n };\n }\n\n getSessionHistory(project: string, limit = 20): SessionSnapshot[] {\n const sqliteStore = this.sqliteStores.get(project);\n if (!sqliteStore) return [];\n\n const sessions = sqliteStore.getSessions(project, limit);\n const snapshots: SessionSnapshot[] = [];\n\n for (const session of sessions) {\n const metricsData = sqliteStore.getSessionMetrics(session.sessionId);\n if (metricsData) {\n snapshots.push({\n sessionId: session.sessionId,\n project,\n metrics: metricsData as SessionMetrics,\n buildMeta: session.buildMeta,\n createdAt: session.disconnectedAt ?? session.connectedAt,\n });\n }\n }\n\n return snapshots;\n }\n}\n","import type { SessionMetrics, MetricDelta, SessionDiffResult } from './types.js';\n\n// ============================================================\n// Session Differ\n// Compares two session metrics across all dimensions\n// ============================================================\n\nconst CHANGE_THRESHOLD = 0.10; // 10% change threshold\n\nfunction classifyDelta(percentChange: number): MetricDelta['classification'] {\n if (percentChange > CHANGE_THRESHOLD) return 'regression';\n if (percentChange < -CHANGE_THRESHOLD) return 'improvement';\n return 'unchanged';\n}\n\nfunction computeDeltas(\n before: Record<string, number>,\n after: Record<string, number>,\n keyPrefix = ''\n): MetricDelta[] {\n const allKeys = new Set([...Object.keys(before), ...Object.keys(after)]);\n const deltas: MetricDelta[] = [];\n\n for (const key of allKeys) {\n const bVal = before[key] ?? 0;\n const aVal = after[key] ?? 0;\n const delta = aVal - bVal;\n const percentChange = bVal !== 0 ? delta / bVal : aVal !== 0 ? 1 : 0;\n\n deltas.push({\n key: keyPrefix ? `${keyPrefix}:${key}` : key,\n before: bVal,\n after: aVal,\n delta,\n percentChange,\n classification: classifyDelta(percentChange),\n });\n }\n\n return deltas.filter((d) => d.classification !== 'unchanged');\n}\n\nexport function compareSessions(\n metricsA: SessionMetrics,\n metricsB: SessionMetrics\n): SessionDiffResult {\n // Endpoint deltas (comparing avg latency)\n const endpointLatencyA: Record<string, number> = {};\n const endpointLatencyB: Record<string, number> = {};\n for (const [key, data] of Object.entries(metricsA.endpoints)) {\n endpointLatencyA[key] = data.avgLatency;\n }\n for (const [key, data] of Object.entries(metricsB.endpoints)) {\n endpointLatencyB[key] = data.avgLatency;\n }\n\n // Component deltas (comparing render counts)\n const componentRendersA: Record<string, number> = {};\n const componentRendersB: Record<string, number> = {};\n for (const [key, data] of Object.entries(metricsA.components)) {\n componentRendersA[key] = data.renderCount;\n }\n for (const [key, data] of Object.entries(metricsB.components)) {\n componentRendersB[key] = data.renderCount;\n }\n\n // Store deltas\n const storeUpdatesA: Record<string, number> = {};\n const storeUpdatesB: Record<string, number> = {};\n for (const [key, data] of Object.entries(metricsA.stores)) {\n storeUpdatesA[key] = data.updateCount;\n }\n for (const [key, data] of Object.entries(metricsB.stores)) {\n storeUpdatesB[key] = data.updateCount;\n }\n\n // Web Vital deltas\n const vitalsA: Record<string, number> = {};\n const vitalsB: Record<string, number> = {};\n for (const [key, data] of Object.entries(metricsA.webVitals)) {\n vitalsA[key] = data.value;\n }\n for (const [key, data] of Object.entries(metricsB.webVitals)) {\n vitalsB[key] = data.value;\n }\n\n // Query deltas\n const queryDurA: Record<string, number> = {};\n const queryDurB: Record<string, number> = {};\n for (const [key, data] of Object.entries(metricsA.queries)) {\n queryDurA[key] = data.avgDuration;\n }\n for (const [key, data] of Object.entries(metricsB.queries)) {\n queryDurB[key] = data.avgDuration;\n }\n\n return {\n sessionA: metricsA.sessionId,\n sessionB: metricsB.sessionId,\n endpointDeltas: computeDeltas(endpointLatencyA, endpointLatencyB, 'endpoint'),\n componentDeltas: computeDeltas(componentRendersA, componentRendersB, 'component'),\n storeDeltas: computeDeltas(storeUpdatesA, storeUpdatesB, 'store'),\n webVitalDeltas: computeDeltas(vitalsA, vitalsB, 'vital'),\n queryDeltas: computeDeltas(queryDurA, queryDurB, 'query'),\n overallDelta: {\n errorCountDelta: metricsB.errorCount - metricsA.errorCount,\n totalEventsDelta: metricsB.totalEvents - metricsA.totalEvents,\n },\n };\n}\n","import { createServer, type IncomingMessage, type ServerResponse, type Server } from 'node:http';\nimport { createServer as createHttpsServer } from 'node:https';\nimport { readFileSync, existsSync } from 'node:fs';\nimport { resolve, dirname } from 'node:path';\nimport { fileURLToPath } from 'node:url';\nimport { WebSocketServer, type WebSocket } from 'ws';\nimport type { EventStore } from './store.js';\nimport type { ProcessMonitor } from './engines/process-monitor.js';\nimport type { RuntimeEvent, DevProcessType } from './types.js';\nimport { AuthManager } from './auth.js';\nimport { loadTlsOptions, type TlsConfig } from './tls.js';\n\n// ============================================================\n// HTTP API Server for Dashboard\n// Lightweight REST API + WebSocket real-time event streaming\n// Uses Node.js built-in http module (no framework deps)\n// ============================================================\n\nexport interface HttpServerOptions {\n port?: number;\n host?: string;\n authManager?: AuthManager;\n allowedOrigins?: string[];\n tls?: TlsConfig;\n}\n\ninterface RouteHandler {\n (req: IncomingMessage, res: ServerResponse, params: URLSearchParams): void | Promise<void>;\n}\n\nexport class HttpServer {\n private server: Server | null = null;\n private wss: WebSocketServer | null = null;\n private store: EventStore;\n private processMonitor: ProcessMonitor | null;\n private authManager: AuthManager | null;\n private allowedOrigins: string[] | null;\n private dashboardClients: Set<WebSocket> = new Set();\n private eventListener: ((event: RuntimeEvent) => void) | null = null;\n private routes: Map<string, RouteHandler> = new Map();\n private sdkBundlePath: string | null = null;\n private activePort = 9091;\n private startedAt = Date.now();\n\n constructor(\n store: EventStore,\n processMonitor?: ProcessMonitor,\n options?: { authManager?: AuthManager; allowedOrigins?: string[] }\n ) {\n this.store = store;\n this.processMonitor = processMonitor ?? null;\n this.authManager = options?.authManager ?? null;\n this.allowedOrigins = options?.allowedOrigins ?? null;\n this.registerRoutes();\n }\n\n private registerRoutes(): void {\n // Health check — always unauthenticated for load balancer probes\n this.routes.set('GET /api/health', (_req, res) => {\n this.json(res, {\n status: 'ok',\n timestamp: Date.now(),\n uptime: Math.floor((Date.now() - this.startedAt) / 1000),\n sessions: this.store.getSessionInfo().filter(s => s.isConnected).length,\n authEnabled: this.authManager?.isEnabled() ?? false,\n });\n });\n\n // Sessions\n this.routes.set('GET /api/sessions', (_req, res) => {\n const sessions = this.store.getSessionInfo();\n this.json(res, { data: sessions, count: sessions.length });\n });\n\n // Projects (sessions grouped by appName)\n this.routes.set('GET /api/projects', (_req, res) => {\n const sessions = this.store.getSessionInfo();\n const projectMap = new Map<string, { appName: string; sessions: string[]; isConnected: boolean; eventCount: number }>();\n\n for (const s of sessions) {\n const existing = projectMap.get(s.appName);\n if (existing) {\n existing.sessions.push(s.sessionId);\n existing.eventCount += s.eventCount;\n if (s.isConnected) existing.isConnected = true;\n } else {\n projectMap.set(s.appName, {\n appName: s.appName,\n sessions: [s.sessionId],\n isConnected: s.isConnected,\n eventCount: s.eventCount,\n });\n }\n }\n\n const projects = Array.from(projectMap.values());\n this.json(res, { data: projects, count: projects.length });\n });\n\n // Processes (served from background scan cache — no blocking lsof calls)\n this.routes.set('GET /api/processes', (_req, res, params) => {\n if (!this.processMonitor) {\n this.json(res, { data: [], count: 0 });\n return;\n }\n const type = params.get('type') as DevProcessType | undefined ?? undefined;\n const project = params.get('project') ?? undefined;\n const processes = this.processMonitor.getProcesses({ type, project });\n this.json(res, { data: processes, count: processes.length });\n });\n\n // Port usage (served from background scan cache)\n this.routes.set('GET /api/ports', (_req, res, params) => {\n if (!this.processMonitor) {\n this.json(res, { data: [], count: 0 });\n return;\n }\n const port = numParam(params, 'port');\n const ports = this.processMonitor.getPortUsage(port);\n this.json(res, { data: ports, count: ports.length });\n });\n\n // Network events\n this.routes.set('GET /api/events/network', (_req, res, params) => {\n const events = this.store.getNetworkRequests({\n sinceSeconds: numParam(params, 'since_seconds'),\n urlPattern: params.get('url_pattern') ?? undefined,\n method: params.get('method') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Console events\n this.routes.set('GET /api/events/console', (_req, res, params) => {\n const events = this.store.getConsoleMessages({\n sinceSeconds: numParam(params, 'since_seconds'),\n level: params.get('level') ?? undefined,\n search: params.get('search') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // State events\n this.routes.set('GET /api/events/state', (_req, res, params) => {\n const events = this.store.getStateEvents({\n sinceSeconds: numParam(params, 'since_seconds'),\n storeId: params.get('store_id') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Render events\n this.routes.set('GET /api/events/renders', (_req, res, params) => {\n const events = this.store.getRenderEvents({\n sinceSeconds: numParam(params, 'since_seconds'),\n componentName: params.get('component') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Performance events\n this.routes.set('GET /api/events/performance', (_req, res, params) => {\n const events = this.store.getPerformanceMetrics({\n sinceSeconds: numParam(params, 'since_seconds'),\n metricName: params.get('metric') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Database events\n this.routes.set('GET /api/events/database', (_req, res, params) => {\n const events = this.store.getDatabaseEvents({\n sinceSeconds: numParam(params, 'since_seconds'),\n table: params.get('table') ?? undefined,\n minDurationMs: numParam(params, 'min_duration_ms'),\n search: params.get('search') ?? undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Timeline\n this.routes.set('GET /api/events/timeline', (_req, res, params) => {\n const eventTypes = params.get('event_types')?.split(',') ?? undefined;\n const events = this.store.getEventTimeline({\n sinceSeconds: numParam(params, 'since_seconds'),\n eventTypes: eventTypes as RuntimeEvent['eventType'][] | undefined,\n sessionId: params.get('session_id') ?? undefined,\n });\n this.json(res, { data: events, count: events.length });\n });\n\n // Clear events\n this.routes.set('DELETE /api/events', (_req, res) => {\n const result = this.store.clear();\n this.json(res, result);\n });\n }\n\n /**\n * Resolve the SDK IIFE bundle path.\n * Tries multiple locations for monorepo and installed-package scenarios.\n */\n private resolveSdkPath(): string | null {\n if (this.sdkBundlePath) return this.sdkBundlePath;\n\n const __dir = dirname(fileURLToPath(import.meta.url));\n const candidates = [\n resolve(__dir, '../../sdk/dist/index.global.js'), // monorepo: packages/collector/dist -> packages/sdk/dist\n resolve(__dir, '../../../node_modules/@runtimescope/sdk/dist/index.global.js'), // npm installed\n ];\n\n for (const p of candidates) {\n if (existsSync(p)) {\n this.sdkBundlePath = p;\n return p;\n }\n }\n return null;\n }\n\n async start(options: HttpServerOptions = {}): Promise<void> {\n const basePort = options.port ?? parseInt(process.env.RUNTIMESCOPE_HTTP_PORT ?? '9091', 10);\n const host = options.host ?? '127.0.0.1';\n const tls = options.tls;\n const maxRetries = 5;\n\n for (let attempt = 0; attempt <= maxRetries; attempt++) {\n const port = basePort + attempt;\n try {\n await this.tryStart(port, host, tls);\n return;\n } catch (err) {\n const isAddrInUse = (err as NodeJS.ErrnoException).code === 'EADDRINUSE';\n if (isAddrInUse && attempt < maxRetries) {\n console.error(`[RuntimeScope] HTTP port ${port} in use, trying ${port + 1}...`);\n continue;\n }\n throw err;\n }\n }\n }\n\n private tryStart(port: number, host: string, tls?: TlsConfig): Promise<void> {\n return new Promise((resolve, reject) => {\n const handler = (req: IncomingMessage, res: ServerResponse) => this.handleRequest(req, res);\n const server = tls\n ? createHttpsServer(loadTlsOptions(tls), handler)\n : createServer(handler);\n\n // Set up WebSocket server for real-time event streaming\n this.wss = new WebSocketServer({ server, path: '/api/ws/events' });\n this.wss.on('connection', (ws) => {\n this.dashboardClients.add(ws);\n ws.on('close', () => this.dashboardClients.delete(ws));\n ws.on('error', () => this.dashboardClients.delete(ws));\n });\n\n // Subscribe to EventStore for real-time broadcasting\n this.eventListener = (event: RuntimeEvent) => this.broadcastEvent(event);\n this.store.onEvent(this.eventListener);\n\n server.on('listening', () => {\n this.server = server;\n this.activePort = port;\n this.startedAt = Date.now();\n const proto = tls ? 'https' : 'http';\n console.error(`[RuntimeScope] HTTP API listening on ${proto}://${host}:${port}`);\n resolve();\n });\n\n server.on('error', (err) => {\n // Clean up the WebSocket server on failure\n this.wss?.close();\n this.wss = null;\n if (this.eventListener) {\n this.store.removeEventListener(this.eventListener);\n this.eventListener = null;\n }\n reject(err);\n });\n\n server.listen(port, host);\n });\n }\n\n async stop(): Promise<void> {\n if (this.eventListener) {\n this.store.removeEventListener(this.eventListener);\n this.eventListener = null;\n }\n\n for (const ws of this.dashboardClients) {\n ws.close();\n }\n this.dashboardClients.clear();\n\n if (this.wss) {\n this.wss.close();\n this.wss = null;\n }\n\n if (this.server) {\n return new Promise((resolve) => {\n this.server!.close(() => {\n this.server = null;\n console.error('[RuntimeScope] HTTP API stopped');\n resolve();\n });\n });\n }\n }\n\n broadcastEvent(event: RuntimeEvent): void {\n if (this.dashboardClients.size === 0) return;\n\n const message = JSON.stringify({ type: 'event', data: event });\n for (const ws of this.dashboardClients) {\n if (ws.readyState === 1 /* OPEN */) {\n try {\n ws.send(message);\n } catch {\n this.dashboardClients.delete(ws);\n }\n }\n }\n }\n\n private handleRequest(req: IncomingMessage, res: ServerResponse): void {\n const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);\n\n // CORS headers — use specific origin when configured, wildcard for dev\n this.setCorsHeaders(req, res);\n\n if (req.method === 'OPTIONS') {\n res.writeHead(204);\n res.end();\n return;\n }\n\n // Auth check — skip for health endpoint and static assets\n const isPublic = url.pathname === '/api/health'\n || url.pathname === '/runtimescope.js'\n || url.pathname === '/snippet';\n\n if (!isPublic && this.authManager?.isEnabled()) {\n const token = AuthManager.extractBearer(req.headers.authorization);\n if (!this.authManager.isAuthorized(token)) {\n this.json(res, { error: 'Unauthorized', code: 'AUTH_FAILED' }, 401);\n return;\n }\n }\n\n // Serve SDK IIFE bundle — works in any HTML page via <script> tag\n if (req.method === 'GET' && url.pathname === '/runtimescope.js') {\n const sdkPath = this.resolveSdkPath();\n if (sdkPath) {\n const bundle = readFileSync(sdkPath, 'utf-8');\n res.writeHead(200, {\n 'Content-Type': 'application/javascript',\n 'Cache-Control': 'no-cache',\n });\n res.end(bundle);\n } else {\n res.writeHead(404, { 'Content-Type': 'text/plain' });\n res.end('SDK bundle not found. Run: npm run build -w packages/sdk');\n }\n return;\n }\n\n // Serve a ready-to-paste snippet for any tech stack\n if (req.method === 'GET' && url.pathname === '/snippet') {\n const appName = url.searchParams.get('app') || 'my-app';\n const wsPort = process.env.RUNTIMESCOPE_PORT ?? '9090';\n const snippet = `<!-- RuntimeScope SDK — paste before </body> -->\n<script src=\"http://localhost:${this.activePort}/runtimescope.js\"></script>\n<script>\n RuntimeScope.init({\n appName: '${appName}',\n endpoint: 'ws://localhost:${wsPort}',\n });\n</script>`;\n res.writeHead(200, {\n 'Content-Type': 'text/plain',\n });\n res.end(snippet);\n return;\n }\n\n const routeKey = `${req.method} ${url.pathname}`;\n const handler = this.routes.get(routeKey);\n\n if (handler) {\n try {\n const result = handler(req, res, url.searchParams);\n if (result instanceof Promise) {\n result.catch((err) => {\n this.json(res, { error: (err as Error).message }, 500);\n });\n }\n } catch (err) {\n this.json(res, { error: (err as Error).message }, 500);\n }\n } else {\n this.json(res, { error: 'Not found', path: url.pathname }, 404);\n }\n }\n\n private setCorsHeaders(req: IncomingMessage, res: ServerResponse): void {\n const origin = req.headers.origin;\n\n if (this.allowedOrigins && this.allowedOrigins.length > 0) {\n // Whitelist mode: only allow configured origins\n if (origin && this.allowedOrigins.includes(origin)) {\n res.setHeader('Access-Control-Allow-Origin', origin);\n res.setHeader('Vary', 'Origin');\n }\n // If origin not in whitelist, omit the header (browser blocks the request)\n } else {\n // Default: wildcard for backward compat in local dev\n res.setHeader('Access-Control-Allow-Origin', '*');\n }\n\n res.setHeader('Access-Control-Allow-Methods', 'GET, POST, DELETE, OPTIONS');\n res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');\n }\n\n private json(res: ServerResponse, data: unknown, status = 200): void {\n res.writeHead(status, { 'Content-Type': 'application/json' });\n res.end(JSON.stringify(data));\n }\n}\n\nfunction numParam(params: URLSearchParams, key: string): number | undefined {\n const val = params.get(key);\n if (!val) return undefined;\n const num = parseInt(val, 10);\n return isNaN(num) ? undefined : num;\n}\n"],"mappings":"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","names":["resolve","readFileSync","resolve","percentile","errorCount","createHttpsServer","readFileSync","existsSync","WebSocketServer","existsSync","resolve","createHttpsServer","WebSocketServer","readFileSync"]}