import { Router } from 'express' import db from '../db.js' import { auth } from '../middleware/auth.js' import { generateEpub } from '../lib/epub.js' import { generateOdt } from '../lib/odt.js' const router = Router() router.use(auth) const parse = s => { try { return JSON.parse(s || '{}') } catch { return {} } } const safe = s => JSON.stringify(s ?? {}) router.get('/', (req, res) => { const rows = db.prepare( 'SELECT id, title, content, cover_image, updated_at, created_at FROM stories WHERE user_id = ? ORDER BY updated_at DESC' ).all(req.user.id) res.json(rows.map(r => ({ ...r, content: parse(r.content) }))) }) router.get('/:id', (req, res) => { const story = db.prepare( 'SELECT id, title, content, cover_image, updated_at, created_at FROM stories WHERE id = ? AND user_id = ?' ).get(req.params.id, req.user.id) if (!story) return res.status(404).json({ error: 'Not found' }) res.json({ ...story, content: parse(story.content) }) }) router.post('/', (req, res) => { const { title = 'Untitled Story', content = {} } = req.body || {} const { lastInsertRowid } = db.prepare( 'INSERT INTO stories (user_id, title, content) VALUES (?, ?, ?)' ).run(req.user.id, title, safe(content)) const story = db.prepare('SELECT * FROM stories WHERE id = ?').get(lastInsertRowid) res.json({ ...story, content: parse(story.content) }) }) router.put('/:id', (req, res) => { const story = db.prepare('SELECT * FROM stories WHERE id = ? AND user_id = ?').get(req.params.id, req.user.id) if (!story) return res.status(404).json({ error: 'Not found' }) const { title, content, cover_image } = req.body || {} db.prepare( 'UPDATE stories SET title = ?, content = ?, cover_image = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?' ).run( title ?? story.title, content !== undefined ? safe(content) : story.content, cover_image !== undefined ? cover_image : story.cover_image, req.params.id ) const updated = db.prepare('SELECT * FROM stories WHERE id = ?').get(req.params.id) res.json({ ...updated, content: parse(updated.content) }) }) router.delete('/:id', (req, res) => { const story = db.prepare('SELECT * FROM stories WHERE id = ? AND user_id = ?').get(req.params.id, req.user.id) if (!story) return res.status(404).json({ error: 'Not found' }) db.prepare('DELETE FROM stories WHERE id = ?').run(req.params.id) res.json({ ok: true }) }) // ── Exports ────────────────────────────────────────────── router.get('/:id/export/epub', async (req, res) => { const story = db.prepare('SELECT * FROM stories WHERE id = ? AND user_id = ?').get(req.params.id, req.user.id) if (!story) return res.status(404).json({ error: 'Not found' }) try { const buf = await generateEpub({ ...story, content: parse(story.content) }) const fname = (story.title || 'story').replace(/[^\w\s-]/g, '').trim().replace(/\s+/g, '_') + '.epub' res.set({ 'Content-Type': 'application/epub+zip', 'Content-Disposition': `attachment; filename="${fname}"` }) res.send(buf) } catch (err) { console.error('EPUB error:', err) res.status(500).json({ error: 'Export failed' }) } }) router.get('/:id/export/odt', async (req, res) => { const story = db.prepare('SELECT * FROM stories WHERE id = ? AND user_id = ?').get(req.params.id, req.user.id) if (!story) return res.status(404).json({ error: 'Not found' }) try { const buf = await generateOdt({ ...story, content: parse(story.content) }) const fname = (story.title || 'story').replace(/[^\w\s-]/g, '').trim().replace(/\s+/g, '_') + '.odt' res.set({ 'Content-Type': 'application/vnd.oasis.opendocument.text', 'Content-Disposition': `attachment; filename="${fname}"` }) res.send(buf) } catch (err) { console.error('ODT error:', err) res.status(500).json({ error: 'Export failed' }) } }) export default router