feat: Add dynamic Vue 3 components system
- Add dynamicComponents.ts service (~300 lines) - CSS scoping with high specificity - Async setup support with Suspense - Event bus for inter-component communication - Shared Pinia store with main app - No app overhead (uses render + createVNode) - Add MCP tools for Vue components - render_vue_component - save_vue_component - load_vue_component - list_vue_components - delete_vue_component - Add SQLite table for component persistence - Add TypeScript declarations for webmcp - Configure Vite for runtime template compilation - Add comprehensive README with documentation Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
This commit is contained in:
@@ -22,6 +22,21 @@ db.run(`
|
||||
)
|
||||
`)
|
||||
|
||||
// Tabla para componentes Vue dinámicos
|
||||
db.run(`
|
||||
CREATE TABLE IF NOT EXISTS vue_components (
|
||||
id TEXT PRIMARY KEY,
|
||||
name TEXT NOT NULL,
|
||||
template TEXT NOT NULL,
|
||||
setup TEXT,
|
||||
style TEXT,
|
||||
props TEXT,
|
||||
imports TEXT,
|
||||
created_at TEXT DEFAULT CURRENT_TIMESTAMP,
|
||||
updated_at TEXT DEFAULT CURRENT_TIMESTAMP
|
||||
)
|
||||
`)
|
||||
|
||||
console.log('[DB] SQLite inicializado: agent-ui.db')
|
||||
|
||||
// API HTTP solamente - WebSocket lo maneja webmcp
|
||||
@@ -85,6 +100,57 @@ Bun.serve({
|
||||
return Response.json({ status: 'ok', timestamp: new Date().toISOString() }, { headers: corsHeaders })
|
||||
}
|
||||
|
||||
// API de Componentes Vue
|
||||
if (url.pathname === '/api/components') {
|
||||
if (req.method === 'GET') {
|
||||
const rows = db.query('SELECT * FROM vue_components ORDER BY updated_at DESC').all()
|
||||
return Response.json(rows, { headers: corsHeaders })
|
||||
}
|
||||
|
||||
if (req.method === 'POST') {
|
||||
const body = await req.json()
|
||||
const id = body.id || `comp-${Date.now()}`
|
||||
const stmt = db.prepare(`
|
||||
INSERT OR REPLACE INTO vue_components
|
||||
(id, name, template, setup, style, props, imports, updated_at)
|
||||
VALUES (?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP)
|
||||
`)
|
||||
stmt.run(
|
||||
id,
|
||||
body.name,
|
||||
body.template,
|
||||
body.setup || '',
|
||||
body.style || '',
|
||||
JSON.stringify(body.props || []),
|
||||
JSON.stringify(body.imports || [])
|
||||
)
|
||||
return Response.json({ success: true, id }, { headers: corsHeaders })
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
db.run('DELETE FROM vue_components')
|
||||
return Response.json({ success: true }, { headers: corsHeaders })
|
||||
}
|
||||
}
|
||||
|
||||
// Obtener componente por ID
|
||||
if (url.pathname.startsWith('/api/components/')) {
|
||||
const id = url.pathname.split('/').pop()
|
||||
|
||||
if (req.method === 'GET') {
|
||||
const row = db.query('SELECT * FROM vue_components WHERE id = ?').get(id)
|
||||
if (!row) {
|
||||
return Response.json({ error: 'Component not found' }, { status: 404, headers: corsHeaders })
|
||||
}
|
||||
return Response.json(row, { headers: corsHeaders })
|
||||
}
|
||||
|
||||
if (req.method === 'DELETE') {
|
||||
db.run('DELETE FROM vue_components WHERE id = ?', [id])
|
||||
return Response.json({ success: true }, { headers: corsHeaders })
|
||||
}
|
||||
}
|
||||
|
||||
return new Response('Not Found', { status: 404, headers: corsHeaders })
|
||||
}
|
||||
})
|
||||
|
||||
Reference in New Issue
Block a user