diff --git a/server.js b/server.js index 9f625c45..f061e391 100644 --- a/server.js +++ b/server.js @@ -977,6 +977,137 @@ app.put('/api/projects/:id', requireAuth, (req, res) => { } }); +// DELETE /api/projects/:id - Soft delete project +app.delete('/api/projects/:id', requireAuth, (req, res) => { + try { + const { id } = req.params; + + // Validate ID + const validatedId = validateProjectId(id); + if (!validatedId) { + return res.status(400).json({ error: 'Invalid project ID' }); + } + + // Check if project exists and is not already deleted + const existing = db.prepare(` + SELECT id FROM projects + WHERE id = ? AND deletedAt IS NULL + `).get(validatedId); + + if (!existing) { + return res.status(404).json({ error: 'Project not found' }); + } + + // Soft delete by setting deletedAt + const now = new Date().toISOString(); + db.prepare(` + UPDATE projects + SET deletedAt = ? + WHERE id = ? + `).run(now, validatedId); + + res.json({ success: true }); + } catch (error) { + console.error('Error soft deleting project:', error); + res.status(500).json({ error: 'Failed to delete project' }); + } +}); + +// POST /api/projects/:id/restore - Restore project from recycle bin +app.post('/api/projects/:id/restore', requireAuth, (req, res) => { + try { + const { id } = req.params; + + // Validate ID + const validatedId = validateProjectId(id); + if (!validatedId) { + return res.status(400).json({ error: 'Invalid project ID' }); + } + + // Check if project exists and is in recycle bin + const existing = db.prepare(` + SELECT id FROM projects + WHERE id = ? AND deletedAt IS NOT NULL + `).get(validatedId); + + if (!existing) { + return res.status(404).json({ error: 'Project not found in recycle bin' }); + } + + // Restore by setting deletedAt to NULL + db.prepare(` + UPDATE projects + SET deletedAt = NULL + WHERE id = ? + `).run(validatedId); + + res.json({ success: true }); + } catch (error) { + console.error('Error restoring project:', error); + res.status(500).json({ error: 'Failed to restore project' }); + } +}); + +// DELETE /api/projects/:id/permanent - Permanently delete project +app.delete('/api/projects/:id/permanent', requireAuth, (req, res) => { + try { + const { id } = req.params; + + // Validate ID + const validatedId = validateProjectId(id); + if (!validatedId) { + return res.status(400).json({ error: 'Invalid project ID' }); + } + + // Check if project exists + const existing = db.prepare(` + SELECT id FROM projects + WHERE id = ? + `).get(validatedId); + + if (!existing) { + return res.status(404).json({ error: 'Project not found' }); + } + + // Permanently delete the project + db.prepare(` + DELETE FROM projects + WHERE id = ? + `).run(validatedId); + + res.json({ success: true }); + } catch (error) { + console.error('Error permanently deleting project:', error); + res.status(500).json({ error: 'Failed to permanently delete project' }); + } +}); + +// GET /api/recycle-bin - List deleted items +app.get('/api/recycle-bin', requireAuth, (req, res) => { + try { + const items = db.prepare(` + SELECT id, name, description, icon, path, deletedAt + FROM projects + WHERE deletedAt IS NOT NULL + ORDER BY deletedAt DESC + `).all(); + + // Add sessionCount (0 for now, will be implemented in Task 4) + const itemsWithSessionCount = items.map(item => ({ + ...item, + sessionCount: 0 + })); + + res.json({ + success: true, + items: itemsWithSessionCount + }); + } catch (error) { + console.error('Error listing recycle bin:', error); + res.status(500).json({ error: 'Failed to list recycle bin' }); + } +}); + // ===== Terminal API Endpoints ===== // Create a new terminal