from __future__ import annotations import sqlite3 from pathlib import Path SCHEMA = """ CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, user_key TEXT NOT NULL, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL ); CREATE TABLE IF NOT EXISTS user_resources ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, app_id TEXT NOT NULL DEFAULT 'default', project_id TEXT NOT NULL DEFAULT 'default', session_id TEXT NOT NULL, original_filename TEXT, mime_type TEXT, content_type TEXT NOT NULL, uri TEXT NOT NULL, uri_public BOOLEAN NOT NULL DEFAULT FALSE, sha256 TEXT, size_bytes INTEGER, title TEXT, description TEXT, status TEXT NOT NULL DEFAULT 'pending', error_message TEXT, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL, deleted_at TIMESTAMP ); CREATE INDEX IF NOT EXISTS idx_user_resources_user_scope ON user_resources (user_id, app_id, project_id, status, deleted_at); CREATE INDEX IF NOT EXISTS idx_user_resources_session_id ON user_resources (session_id); CREATE INDEX IF NOT EXISTS idx_user_resources_user_id ON user_resources (user_id); CREATE TABLE IF NOT EXISTS memory_tombstones ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, memory_id TEXT, session_id TEXT, reason TEXT, created_at TIMESTAMP NOT NULL ); CREATE INDEX IF NOT EXISTS idx_memory_tombstones_user_memory ON memory_tombstones (user_id, memory_id); CREATE INDEX IF NOT EXISTS idx_memory_tombstones_user_session ON memory_tombstones (user_id, session_id); CREATE TABLE IF NOT EXISTS memory_overrides ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, memory_id TEXT, session_id TEXT, override_text TEXT NOT NULL, is_active BOOLEAN NOT NULL DEFAULT TRUE, created_at TIMESTAMP NOT NULL, updated_at TIMESTAMP NOT NULL ); CREATE INDEX IF NOT EXISTS idx_memory_overrides_user_memory_active ON memory_overrides (user_id, memory_id, is_active); """ def connect(db_path: Path) -> sqlite3.Connection: conn = sqlite3.connect(db_path) conn.row_factory = sqlite3.Row conn.execute("PRAGMA journal_mode=WAL") conn.execute("PRAGMA foreign_keys=ON") conn.execute("PRAGMA busy_timeout=5000") return conn def init_db(db_path: Path) -> None: db_path.parent.mkdir(parents=True, exist_ok=True) with connect(db_path) as conn: conn.executescript(SCHEMA)