-- ========================================== -- Migration 009: Folders & Projects -- ========================================== -- Organizational structures for channels. -- Folders are simple containers; projects are -- tagged collections that can span folders. -- ========================================== -- ── Folders ───────────────────────────────── CREATE TABLE IF NOT EXISTS folders ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(200) NOT NULL, parent_id UUID REFERENCES folders(id) ON DELETE CASCADE, sort_order INT DEFAULT 0, created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW(), UNIQUE(user_id, name, parent_id) ); CREATE INDEX idx_folders_user ON folders(user_id); CREATE INDEX idx_folders_parent ON folders(parent_id); CREATE TRIGGER folders_updated_at BEFORE UPDATE ON folders FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Add folder_id to channels (replaces the old text folder column) ALTER TABLE channels ADD COLUMN IF NOT EXISTS folder_id UUID REFERENCES folders(id) ON DELETE SET NULL; CREATE INDEX IF NOT EXISTS idx_channels_folder ON channels(folder_id); -- ── Projects ──────────────────────────────── CREATE TABLE IF NOT EXISTS projects ( id UUID PRIMARY KEY DEFAULT gen_random_uuid(), user_id UUID NOT NULL REFERENCES users(id) ON DELETE CASCADE, name VARCHAR(200) NOT NULL, description TEXT, color VARCHAR(7), -- hex color for UI badge created_at TIMESTAMPTZ DEFAULT NOW(), updated_at TIMESTAMPTZ DEFAULT NOW() ); CREATE INDEX idx_projects_user ON projects(user_id); CREATE TRIGGER projects_updated_at BEFORE UPDATE ON projects FOR EACH ROW EXECUTE FUNCTION update_updated_at(); -- Junction: channels can belong to multiple projects CREATE TABLE IF NOT EXISTS project_channels ( project_id UUID NOT NULL REFERENCES projects(id) ON DELETE CASCADE, channel_id UUID NOT NULL REFERENCES channels(id) ON DELETE CASCADE, added_at TIMESTAMPTZ DEFAULT NOW(), PRIMARY KEY (project_id, channel_id) ); CREATE INDEX idx_project_channels_channel ON project_channels(channel_id);