import { db } from '../db' import { jsonResponse, errorResponse } from '../utils/cors' function parseCanvas(row: any) { return { ...row, is_default: !!row.is_default, is_system: !!row.is_system, show_in_toolbar: !!row.show_in_toolbar, config: row.config ? JSON.parse(row.config) : null, tools: row.tools ? JSON.parse(row.tools) : [] } } export function handleToolbarCanvas() { const rows = db.query('SELECT * FROM project_canvas WHERE show_in_toolbar = 1 ORDER BY toolbar_order ASC, name ASC').all() return jsonResponse((rows as any[]).map(parseCanvas)) } export function handleDefaultCanvas() { const row = db.query('SELECT * FROM project_canvas WHERE is_default = 1 LIMIT 1').get() as any if (!row) { return jsonResponse({ hasDefault: false }) } return jsonResponse({ hasDefault: true, canvas: parseCanvas(row) }) } export async function handleCanvas(req: Request) { if (req.method === 'GET') { const rows = db.query('SELECT * FROM project_canvas ORDER BY is_system DESC, is_default DESC, name ASC').all() return jsonResponse((rows as any[]).map(parseCanvas)) } if (req.method === 'POST') { const body = await req.json() const id = body.id || `canvas-${Date.now()}` const stmt = db.prepare(` INSERT OR REPLACE INTO project_canvas (id, name, description, type, theme_id, config, tools, is_default, is_system, show_in_toolbar, toolbar_icon, toolbar_order, updated_at) VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, CURRENT_TIMESTAMP) `) stmt.run( id, body.name, body.description || '', body.type || 'project', body.theme_id || null, JSON.stringify(body.config || {}), JSON.stringify(body.tools || []), body.is_default ? 1 : 0, body.is_system ? 1 : 0, body.show_in_toolbar ? 1 : 0, body.toolbar_icon || null, body.toolbar_order ?? 99 ) return jsonResponse({ success: true, id }) } return null } export async function handleCanvasById(req: Request, id: string, action?: string) { // POST /api/canvas/:id/clone if (action === 'clone' && req.method === 'POST') { const original = db.query('SELECT * FROM project_canvas WHERE id = ?').get(id) as any if (!original) { return errorResponse('Canvas not found', 404) } const body = await req.json() const newId = `canvas-${Date.now()}` const newName = body.name || `${original.name} (copia)` const stmt = db.prepare(` INSERT INTO project_canvas (id, name, description, type, theme_id, config, tools, is_default, is_system) VALUES (?, ?, ?, 'project', ?, ?, ?, 0, 0) `) stmt.run(newId, newName, original.description, original.theme_id, original.config, original.tools) // Clone canvas components const components = db.query('SELECT * FROM canvas_components WHERE canvas_id = ?').all(id) as any[] if (components.length > 0) { const compStmt = db.prepare(` INSERT INTO canvas_components (canvas_id, component_id, position, props, layout, is_visible) VALUES (?, ?, ?, ?, ?, ?) `) for (const comp of components) { compStmt.run(newId, comp.component_id, comp.position, comp.props, comp.layout, comp.is_visible) } } return jsonResponse({ success: true, id: newId }) } // GET /api/canvas/:id if (req.method === 'GET' && !action) { const row = db.query('SELECT * FROM project_canvas WHERE id = ?').get(id) as any if (!row) { return errorResponse('Canvas not found', 404) } return jsonResponse(parseCanvas(row)) } // PUT /api/canvas/:id if (req.method === 'PUT' && !action) { const canvas = db.query('SELECT * FROM project_canvas WHERE id = ?').get(id) as any if (!canvas) { return errorResponse('Canvas not found', 404) } const body = await req.json() const updates: string[] = [] const values: any[] = [] // System canvas can only modify toolbar settings and is_default if (canvas.is_system) { if (body.is_default !== undefined) { updates.push('is_default = ?'); values.push(body.is_default ? 1 : 0) } if (body.show_in_toolbar !== undefined) { updates.push('show_in_toolbar = ?'); values.push(body.show_in_toolbar ? 1 : 0) } if (body.toolbar_icon !== undefined) { updates.push('toolbar_icon = ?'); values.push(body.toolbar_icon) } if (body.toolbar_order !== undefined) { updates.push('toolbar_order = ?'); values.push(body.toolbar_order) } } else { if (body.name !== undefined) { updates.push('name = ?'); values.push(body.name) } if (body.description !== undefined) { updates.push('description = ?'); values.push(body.description) } if (body.theme_id !== undefined) { updates.push('theme_id = ?'); values.push(body.theme_id) } if (body.config !== undefined) { updates.push('config = ?'); values.push(JSON.stringify(body.config)) } if (body.tools !== undefined) { updates.push('tools = ?'); values.push(JSON.stringify(body.tools)) } if (body.is_default !== undefined) { updates.push('is_default = ?'); values.push(body.is_default ? 1 : 0) } if (body.show_in_toolbar !== undefined) { updates.push('show_in_toolbar = ?'); values.push(body.show_in_toolbar ? 1 : 0) } if (body.toolbar_icon !== undefined) { updates.push('toolbar_icon = ?'); values.push(body.toolbar_icon) } if (body.toolbar_order !== undefined) { updates.push('toolbar_order = ?'); values.push(body.toolbar_order) } } if (updates.length > 0) { updates.push('updated_at = CURRENT_TIMESTAMP') values.push(id) const sql = `UPDATE project_canvas SET ${updates.join(', ')} WHERE id = ?` db.run(sql, values) } return jsonResponse({ success: true, id }) } // DELETE /api/canvas/:id if (req.method === 'DELETE' && !action) { const canvas = db.query('SELECT is_system FROM project_canvas WHERE id = ?').get(id) as { is_system: number } | null if (canvas?.is_system) { return errorResponse('Cannot delete system canvas', 403) } db.run('DELETE FROM project_canvas WHERE id = ?', [id]) return jsonResponse({ success: true }) } return null } // Canvas Components API export async function handleCanvasComponents(req: Request, canvasId: string) { if (req.method === 'GET') { const rows = db.query(` SELECT cc.*, vc.name, vc.template, vc.setup, vc.style, vc.props as component_props, vc.imports FROM canvas_components cc JOIN vue_components vc ON cc.component_id = vc.id WHERE cc.canvas_id = ? ORDER BY cc.position ASC `).all(canvasId) as any[] const components = rows.map(row => ({ id: row.id, canvasId: row.canvas_id, componentId: row.component_id, position: row.position, props: row.props ? JSON.parse(row.props) : {}, layout: row.layout ? JSON.parse(row.layout) : null, isVisible: !!row.is_visible, createdAt: row.created_at, component: { id: row.component_id, name: row.name, template: row.template, setup: row.setup, style: row.style, props: row.component_props ? JSON.parse(row.component_props) : [], imports: row.imports ? JSON.parse(row.imports) : [] } })) return jsonResponse(components) } if (req.method === 'POST') { const body = await req.json() // Verify component exists const component = db.query('SELECT id FROM vue_components WHERE id = ?').get(body.component_id) if (!component) { return errorResponse('Component not found', 404) } // Get next position const maxPos = db.query('SELECT MAX(position) as max FROM canvas_components WHERE canvas_id = ?').get(canvasId) as { max: number | null } const position = body.position ?? ((maxPos?.max ?? -1) + 1) const stmt = db.prepare(` INSERT OR REPLACE INTO canvas_components (canvas_id, component_id, position, props, layout, is_visible) VALUES (?, ?, ?, ?, ?, ?) `) stmt.run( canvasId, body.component_id, position, JSON.stringify(body.props || {}), body.layout ? JSON.stringify(body.layout) : null, body.is_visible !== false ? 1 : 0 ) return jsonResponse({ success: true }) } return null } export async function handleCanvasComponentById(req: Request, canvasId: string, componentId: string) { if (req.method === 'PUT') { const body = await req.json() const updates: string[] = [] const values: any[] = [] if (body.position !== undefined) { updates.push('position = ?'); values.push(body.position) } if (body.props !== undefined) { updates.push('props = ?'); values.push(JSON.stringify(body.props)) } if (body.layout !== undefined) { updates.push('layout = ?'); values.push(JSON.stringify(body.layout)) } if (body.is_visible !== undefined) { updates.push('is_visible = ?'); values.push(body.is_visible ? 1 : 0) } if (updates.length > 0) { values.push(canvasId, componentId) const sql = `UPDATE canvas_components SET ${updates.join(', ')} WHERE canvas_id = ? AND component_id = ?` db.run(sql, values) } return jsonResponse({ success: true }) } if (req.method === 'DELETE') { db.run('DELETE FROM canvas_components WHERE canvas_id = ? AND component_id = ?', [canvasId, componentId]) return jsonResponse({ success: true }) } return null }