import Database from 'better-sqlite3'; import { fileURLToPath } from 'url'; import { dirname, join } from 'path'; const __dirname = dirname(fileURLToPath(import.meta.url)); const DB_PATH = join(__dirname, 'data', 'teamflow.db'); import { mkdirSync } from 'fs'; mkdirSync(join(__dirname, 'data'), { recursive: true }); const db = new Database(DB_PATH); db.pragma('journal_mode = WAL'); db.pragma('foreign_keys = ON'); db.exec(` CREATE TABLE IF NOT EXISTS app_state ( key TEXT PRIMARY KEY, value TEXT NOT NULL ); CREATE TABLE IF NOT EXISTS users ( id INTEGER PRIMARY KEY AUTOINCREMENT, email TEXT UNIQUE NOT NULL, password TEXT NOT NULL, name TEXT NOT NULL, avatar_color TEXT DEFAULT '#6366f1', role TEXT DEFAULT 'member', is_active INTEGER DEFAULT 1, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS boards ( id INTEGER PRIMARY KEY AUTOINCREMENT, title TEXT NOT NULL, description TEXT DEFAULT '', background TEXT DEFAULT 'gradient-blue', is_archived INTEGER DEFAULT 0, created_by INTEGER REFERENCES users(id), created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS board_members ( board_id INTEGER REFERENCES boards(id) ON DELETE CASCADE, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, role TEXT DEFAULT 'member', joined_at TEXT DEFAULT (datetime('now')), PRIMARY KEY (board_id, user_id) ); CREATE TABLE IF NOT EXISTS lists ( id INTEGER PRIMARY KEY AUTOINCREMENT, board_id INTEGER REFERENCES boards(id) ON DELETE CASCADE, title TEXT NOT NULL, position REAL NOT NULL, is_archived INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS cards ( id INTEGER PRIMARY KEY AUTOINCREMENT, list_id INTEGER REFERENCES lists(id) ON DELETE CASCADE, title TEXT NOT NULL, description TEXT DEFAULT '', position REAL NOT NULL, due_date TEXT, priority TEXT DEFAULT 'none', color TEXT DEFAULT '', estimated_hours REAL, time_spent REAL DEFAULT 0, created_by INTEGER REFERENCES users(id), assigned_to INTEGER REFERENCES users(id), created_at TEXT DEFAULT (datetime('now')), updated_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS labels ( id INTEGER PRIMARY KEY AUTOINCREMENT, board_id INTEGER REFERENCES boards(id) ON DELETE CASCADE, name TEXT NOT NULL, color TEXT NOT NULL, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS card_labels ( card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE, label_id INTEGER REFERENCES labels(id) ON DELETE CASCADE, PRIMARY KEY (card_id, label_id) ); CREATE TABLE IF NOT EXISTS card_comments ( id INTEGER PRIMARY KEY AUTOINCREMENT, card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE, user_id INTEGER REFERENCES users(id), content TEXT NOT NULL, is_email_reply INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS card_activity ( id INTEGER PRIMARY KEY AUTOINCREMENT, card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE, user_id INTEGER REFERENCES users(id), action TEXT NOT NULL, details TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS email_config ( id INTEGER PRIMARY KEY CHECK (id = 1), smtp_host TEXT DEFAULT 'smtp.gmail.com', smtp_port INTEGER DEFAULT 587, email TEXT NOT NULL, app_password TEXT NOT NULL, imap_host TEXT DEFAULT 'imap.gmail.com', imap_port INTEGER DEFAULT 993, inbound_enabled INTEGER DEFAULT 0, inbound_folder TEXT DEFAULT 'INBOX', board_email_prefix TEXT DEFAULT 'tf-', configured_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS email_log ( id INTEGER PRIMARY KEY AUTOINCREMENT, from_email TEXT, to_email TEXT, subject TEXT, card_id INTEGER REFERENCES cards(id), direction TEXT, status TEXT, error TEXT DEFAULT '', created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS email_tokens ( id INTEGER PRIMARY KEY AUTOINCREMENT, card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE, user_id INTEGER REFERENCES users(id), token TEXT UNIQUE NOT NULL, purpose TEXT DEFAULT 'reply', expires_at TEXT, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS notifications ( id INTEGER PRIMARY KEY AUTOINCREMENT, user_id INTEGER REFERENCES users(id) ON DELETE CASCADE, type TEXT NOT NULL, title TEXT NOT NULL, message TEXT DEFAULT '', card_id INTEGER, board_id INTEGER, is_read INTEGER DEFAULT 0, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS checklists ( id INTEGER PRIMARY KEY AUTOINCREMENT, card_id INTEGER REFERENCES cards(id) ON DELETE CASCADE, title TEXT NOT NULL DEFAULT 'Checklist', position REAL DEFAULT 0, created_at TEXT DEFAULT (datetime('now')) ); CREATE TABLE IF NOT EXISTS checklist_items ( id INTEGER PRIMARY KEY AUTOINCREMENT, checklist_id INTEGER REFERENCES checklists(id) ON DELETE CASCADE, text TEXT NOT NULL, is_checked INTEGER DEFAULT 0, position REAL DEFAULT 0, created_at TEXT DEFAULT (datetime('now')) ); CREATE INDEX IF NOT EXISTS idx_cards_list ON cards(list_id); CREATE INDEX IF NOT EXISTS idx_card_activity_card ON card_activity(card_id); CREATE INDEX IF NOT EXISTS idx_card_comments_card ON card_comments(card_id); CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id, is_read); CREATE INDEX IF NOT EXISTS idx_lists_board ON lists(board_id); CREATE INDEX IF NOT EXISTS idx_email_tokens_token ON email_tokens(token); `); export default db;