write/server/db.js
chris 37448be5a8 Add notes panel, font picker, sticky toolbar, and prompt improvements
- Notes: per-story rich-text notes panel (right drawer) with TipTap
  editor, image support, autosave, and full CRUD API
- Font picker: 15 Google Fonts selectable from a floating Aa button,
  persisted to localStorage via --font-body CSS variable
- Sticky toolbar: pulled formatting bar out of overflow:hidden wrapper
  so it sticks below the topbar while scrolling
- Prompts: 100 additional built-in prompts (120 total) in a shuffled
  no-repeat queue; pre-fetch on page load so the AI has time to respond;
  timeout raised to 45s; error logging + /api/prompts/test debug endpoint;
  source badge shows whether prompt came from AI or built-in list

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-24 20:21:26 -04:00

58 lines
2.0 KiB
JavaScript

import Database from 'better-sqlite3'
import { mkdirSync } from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const dataDir = path.join(__dirname, 'data')
mkdirSync(dataDir, { recursive: true })
const db = new Database(path.join(dataDir, 'stories.db'))
db.pragma('journal_mode = WAL')
db.pragma('foreign_keys = ON')
db.exec(`
CREATE TABLE IF NOT EXISTS users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
username TEXT UNIQUE NOT NULL COLLATE NOCASE,
password TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS stories (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title TEXT NOT NULL DEFAULT 'Untitled Story',
content TEXT DEFAULT '{}',
cover_image TEXT,
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS images (
id INTEGER PRIMARY KEY AUTOINCREMENT,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
filename TEXT NOT NULL,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE IF NOT EXISTS notes (
id INTEGER PRIMARY KEY AUTOINCREMENT,
story_id INTEGER NOT NULL REFERENCES stories(id) ON DELETE CASCADE,
user_id INTEGER NOT NULL REFERENCES users(id) ON DELETE CASCADE,
title TEXT NOT NULL DEFAULT 'Untitled Note',
content TEXT DEFAULT '{}',
updated_at DATETIME DEFAULT CURRENT_TIMESTAMP,
created_at DATETIME DEFAULT CURRENT_TIMESTAMP
);
`)
// Migrate: rename email -> username for existing databases
const userCols = db.pragma('table_info(users)').map(c => c.name)
if (userCols.includes('email') && !userCols.includes('username')) {
db.exec('ALTER TABLE users RENAME COLUMN email TO username')
}
export default db