import { db } from '../db' import { jsonResponse, errorResponse } from '../utils/cors' export function handleTables() { const tables = db.query(` SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' ORDER BY name `).all() as { name: string }[] const result = tables.map(t => { const countResult = db.query(`SELECT COUNT(*) as count FROM "${t.name}"`).get() as { count: number } return { name: t.name, count: countResult.count } }) return jsonResponse(result) } export async function handleStats() { // Get database file size const file = Bun.file('agent-ui.db') const size = file.size const sizeStr = size < 1024 ? `${size} B` : size < 1024 * 1024 ? `${(size / 1024).toFixed(1)} KB` : `${(size / (1024 * 1024)).toFixed(2)} MB` // Get tables and counts const tables = db.query(` SELECT name FROM sqlite_master WHERE type='table' AND name NOT LIKE 'sqlite_%' `).all() as { name: string }[] let totalRecords = 0 const breakdown = tables.map(t => { const countResult = db.query(`SELECT COUNT(*) as count FROM "${t.name}"`).get() as { count: number } totalRecords += countResult.count return { name: t.name, count: countResult.count } }) return jsonResponse({ size: sizeStr, tables: tables.length, totalRecords, breakdown }) } export function handleTableSchema(tableName: string) { // Verify table exists const tableExists = db.query(` SELECT name FROM sqlite_master WHERE type='table' AND name = ? `).get(tableName) if (!tableExists) { return errorResponse('Table not found', 404) } const schema = db.query(`PRAGMA table_info("${tableName}")`).all() as any[] const result = schema.map(col => ({ name: col.name, type: col.type, notnull: !!col.notnull, pk: !!col.pk })) return jsonResponse(result) } export function handleTableData(tableName: string, url: URL) { // Verify table exists const tableExists = db.query(` SELECT name FROM sqlite_master WHERE type='table' AND name = ? `).get(tableName) if (!tableExists) { return errorResponse('Table not found', 404) } const limit = Math.min(parseInt(url.searchParams.get('limit') || '50'), 500) const offset = parseInt(url.searchParams.get('offset') || '0') const countResult = db.query(`SELECT COUNT(*) as count FROM "${tableName}"`).get() as { count: number } const rows = db.query(`SELECT * FROM "${tableName}" LIMIT ? OFFSET ?`).all(limit, offset) return jsonResponse({ total: countResult.count, limit, offset, rows }) } export async function handleQuery(req: Request) { const body = await req.json() const query = (body.query || '').trim() // Security: Only allow SELECT statements const normalizedQuery = query.toLowerCase() if (!normalizedQuery.startsWith('select')) { return errorResponse('Only SELECT queries are allowed for security reasons', 403) } // Block dangerous keywords const dangerousKeywords = ['drop', 'delete', 'update', 'insert', 'alter', 'create', 'truncate', 'replace'] for (const keyword of dangerousKeywords) { if (normalizedQuery.includes(keyword)) { return errorResponse(`Query contains forbidden keyword: ${keyword.toUpperCase()}`, 403) } } try { const rows = db.query(query).all() return jsonResponse({ rows }) } catch (e: any) { return errorResponse(e.message, 400) } }