-- Web CAD Backend – SQLite Schema -- Version 1.0 PRAGMA journal_mode = WAL; PRAGMA foreign_keys = ON; -- ─── Users ────────────────────────────────────────── CREATE TABLE IF NOT EXISTS users ( id TEXT PRIMARY KEY, email TEXT UNIQUE NOT NULL, password_hash TEXT NOT NULL, name TEXT NOT NULL, role TEXT NOT NULL DEFAULT 'planer' CHECK(role IN ('admin','planer','betrachter','gast')), created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); -- ─── Default User (seed) ──────────────────────────── INSERT OR IGNORE INTO users (id, email, password_hash, name, role) VALUES ('user-default', 'default@webcad.local', '', 'Default User', 'admin'); -- ─── Projects ─────────────────────────────────────── CREATE TABLE IF NOT EXISTS projects ( id TEXT PRIMARY KEY, name TEXT NOT NULL, description TEXT, owner_id TEXT NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE ); -- ─── Drawings ─────────────────────────────────────── CREATE TABLE IF NOT EXISTS drawings ( id TEXT PRIMARY KEY, project_id TEXT NOT NULL, name TEXT NOT NULL, data_json TEXT NOT NULL DEFAULT '{}', created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE ); -- ─── Layers ───────────────────────────────────────── CREATE TABLE IF NOT EXISTS layers ( id TEXT PRIMARY KEY, drawing_id TEXT NOT NULL, name TEXT NOT NULL, visible INTEGER NOT NULL DEFAULT 1, locked INTEGER NOT NULL DEFAULT 0, color TEXT NOT NULL DEFAULT '#ffffff', line_type TEXT NOT NULL DEFAULT 'solid', transparency REAL NOT NULL DEFAULT 0, sort_order INTEGER NOT NULL DEFAULT 0, parent_id TEXT, FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE ); -- ─── Elements ─────────────────────────────────────── CREATE TABLE IF NOT EXISTS elements ( id TEXT PRIMARY KEY, drawing_id TEXT NOT NULL, layer_id TEXT NOT NULL, type TEXT NOT NULL, x REAL NOT NULL, y REAL NOT NULL, width REAL NOT NULL, height REAL NOT NULL, properties_json TEXT NOT NULL DEFAULT '{}', created_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE, FOREIGN KEY (layer_id) REFERENCES layers(id) ON DELETE CASCADE ); -- ─── Block Definitions ────────────────────────────── CREATE TABLE IF NOT EXISTS blocks ( id TEXT PRIMARY KEY, drawing_id TEXT NOT NULL, name TEXT NOT NULL, description TEXT, category TEXT NOT NULL DEFAULT 'Allgemein', elements_json TEXT NOT NULL DEFAULT '[]', thumbnail TEXT, FOREIGN KEY (drawing_id) REFERENCES drawings(id) ON DELETE CASCADE ); -- ─── Sessions ────────────────────────────────────── CREATE TABLE IF NOT EXISTS sessions ( token TEXT PRIMARY KEY, user_id TEXT NOT NULL, expires_at INTEGER NOT NULL, created_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); -- ─── Settings ─────────────────────────────────────── CREATE TABLE IF NOT EXISTS settings ( key TEXT PRIMARY KEY, value TEXT NOT NULL, updated_at TEXT NOT NULL DEFAULT (datetime('now')) ); -- ─── Project Folders ─────────────────────────────────── CREATE TABLE IF NOT EXISTS project_folders ( id TEXT PRIMARY KEY, name TEXT NOT NULL, parent_id TEXT, owner_id TEXT NOT NULL, created_at TEXT DEFAULT (datetime('now')), FOREIGN KEY (parent_id) REFERENCES project_folders(id) ON DELETE CASCADE, FOREIGN KEY (owner_id) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_project_folders_parent ON project_folders(parent_id); CREATE INDEX IF NOT EXISTS idx_project_folders_owner ON project_folders(owner_id); -- ─── Projects: add folder_id column ───────────────────── -- NOTE: ALTER TABLE is idempotent-safe via try/catch in adapter; schema.sql -- is only exec'd on fresh databases. For existing DBs, the adapter runs -- the ALTER in init(). -- ─── Indexes ──────────────────────────────────────── CREATE INDEX IF NOT EXISTS idx_drawings_project ON drawings(project_id); CREATE INDEX IF NOT EXISTS idx_layers_drawing ON layers(drawing_id); CREATE INDEX IF NOT EXISTS idx_elements_drawing ON elements(drawing_id); CREATE INDEX IF NOT EXISTS idx_elements_layer ON elements(layer_id); CREATE INDEX IF NOT EXISTS idx_blocks_drawing ON blocks(drawing_id); -- ─── Notifications ─────────────────────────────────── CREATE TABLE IF NOT EXISTS notifications ( id TEXT PRIMARY KEY, user_id TEXT NOT NULL, type TEXT NOT NULL DEFAULT 'info', title TEXT NOT NULL, message TEXT NOT NULL, read INTEGER NOT NULL DEFAULT 0, created_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (user_id) REFERENCES users(id) ON DELETE CASCADE ); -- ─── Project Shares ────────────────────────────────── CREATE TABLE IF NOT EXISTS project_shares ( id TEXT PRIMARY KEY, project_id TEXT NOT NULL, shared_with_email TEXT NOT NULL, shared_by TEXT NOT NULL, permission TEXT NOT NULL DEFAULT 'view' CHECK(permission IN ('view','edit','admin')), share_token TEXT UNIQUE, created_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (project_id) REFERENCES projects(id) ON DELETE CASCADE, FOREIGN KEY (shared_by) REFERENCES users(id) ON DELETE CASCADE ); CREATE INDEX IF NOT EXISTS idx_notifications_user ON notifications(user_id); CREATE INDEX IF NOT EXISTS idx_shares_project ON project_shares(project_id); -- ─── Global Block Folders ───────────────────────────── CREATE TABLE IF NOT EXISTS global_block_folders ( id TEXT PRIMARY KEY, name TEXT NOT NULL, parent_id TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (parent_id) REFERENCES global_block_folders(id) ON DELETE CASCADE ); -- ─── Global Blocks ────────────────────────────────────── CREATE TABLE IF NOT EXISTS global_blocks ( id TEXT PRIMARY KEY, folder_id TEXT, name TEXT NOT NULL, block_data TEXT NOT NULL DEFAULT '{}', svg_data TEXT, created_at TEXT NOT NULL DEFAULT (datetime('now')), updated_at TEXT NOT NULL DEFAULT (datetime('now')), FOREIGN KEY (folder_id) REFERENCES global_block_folders(id) ON DELETE SET NULL ); CREATE INDEX IF NOT EXISTS idx_global_blocks_folder ON global_blocks(folder_id); CREATE INDEX IF NOT EXISTS idx_global_block_folders_parent ON global_block_folders(parent_id);