Skip to content
Clone

feat(db): add migration 0103 project linear entities

zhenyi committed
parent dc5fbfb commit 95b9ecd Browse files

1 file changed

+110 −0

Added lib/db/migrations/sql/0103_project_linear_entities.sql View lib/db/migrations/sql/0103_project_linear_entities.sql
@@ -0,0 +1,110 @@
1-- 0103_project_linear_entities.sql
2-- Reference DDL for new project entities declared in lib/db/project/:
3-- project_members, project_views, project_documents,
4-- project_links, project_activities, project_favorites.
5-- Documentation only; not run by the migration runner per project policy.
6
7-- ---------------------------------------------------------------------------
8-- project_members
9-- ---------------------------------------------------------------------------
10CREATE TABLE IF NOT EXISTS project_members (
11 id uuid PRIMARY KEY,
12 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
13 user_id uuid NOT NULL REFERENCES users(uid) ON DELETE CASCADE,
14 role smallint NOT NULL DEFAULT 2, -- ProjectMemberRole
15 joined_at timestamptz NOT NULL DEFAULT now(),
16 updated_at timestamptz,
17 UNIQUE (project_id, user_id)
18);
19CREATE INDEX IF NOT EXISTS idx_project_members_user ON project_members (user_id);
20CREATE INDEX IF NOT EXISTS idx_project_members_project ON project_members (project_id);
21
22-- ---------------------------------------------------------------------------
23-- project_views (saved filters / sort / group / layout)
24-- ---------------------------------------------------------------------------
25CREATE TABLE IF NOT EXISTS project_views (
26 id uuid PRIMARY KEY,
27 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
28 creator_id uuid NOT NULL REFERENCES users(uid),
29 name text NOT NULL,
30 description text,
31 filter jsonb NOT NULL DEFAULT '{}'::jsonb,
32 sort_by text NOT NULL DEFAULT 'manual',
33 group_by text,
34 layout text NOT NULL DEFAULT 'list',
35 is_shared boolean NOT NULL DEFAULT false,
36 sort_order integer NOT NULL DEFAULT 0,
37 created_at timestamptz NOT NULL DEFAULT now(),
38 updated_at timestamptz
39);
40CREATE INDEX IF NOT EXISTS idx_project_views_project ON project_views (project_id, sort_order);
41CREATE INDEX IF NOT EXISTS idx_project_views_creator ON project_views (creator_id);
42
43-- ---------------------------------------------------------------------------
44-- project_documents (Linear Documents — Markdown text for now)
45-- ---------------------------------------------------------------------------
46CREATE TABLE IF NOT EXISTS project_documents (
47 id uuid PRIMARY KEY,
48 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
49 parent_id uuid REFERENCES project_documents(id) ON DELETE SET NULL,
50 creator_id uuid NOT NULL REFERENCES users(uid),
51 last_editor_id uuid REFERENCES users(uid),
52 title text NOT NULL,
53 slug text NOT NULL,
54 content text NOT NULL DEFAULT '',
55 icon text,
56 created_at timestamptz NOT NULL DEFAULT now(),
57 updated_at timestamptz,
58 UNIQUE (project_id, slug)
59);
60CREATE INDEX IF NOT EXISTS idx_project_documents_project ON project_documents (project_id);
61CREATE INDEX IF NOT EXISTS idx_project_documents_parent ON project_documents (parent_id);
62
63-- ---------------------------------------------------------------------------
64-- project_links (cross-project relations)
65-- ---------------------------------------------------------------------------
66CREATE TABLE IF NOT EXISTS project_links (
67 id uuid PRIMARY KEY,
68 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
69 related_project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
70 kind smallint NOT NULL, -- ProjectLinkKind
71 created_by uuid NOT NULL REFERENCES users(uid),
72 created_at timestamptz NOT NULL DEFAULT now(),
73 CHECK (project_id <> related_project_id),
74 UNIQUE (project_id, related_project_id, kind)
75);
76CREATE INDEX IF NOT EXISTS idx_project_links_project ON project_links (project_id);
77CREATE INDEX IF NOT EXISTS idx_project_links_related_project ON project_links (related_project_id);
78
79-- ---------------------------------------------------------------------------
80-- project_activities (aggregated activity feed)
81-- ---------------------------------------------------------------------------
82CREATE TABLE IF NOT EXISTS project_activities (
83 id uuid PRIMARY KEY,
84 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
85 actor_id uuid NOT NULL REFERENCES users(uid),
86 verb text NOT NULL,
87 target_kind text NOT NULL,
88 target_id uuid,
89 payload jsonb,
90 created_at timestamptz NOT NULL DEFAULT now()
91);
92CREATE INDEX IF NOT EXISTS idx_project_activities_feed
93 ON project_activities (project_id, created_at DESC);
94CREATE INDEX IF NOT EXISTS idx_project_activities_actor
95 ON project_activities (actor_id, created_at DESC);
96
97-- ---------------------------------------------------------------------------
98-- project_favorites (per-user star / favorites folder)
99-- ---------------------------------------------------------------------------
100CREATE TABLE IF NOT EXISTS project_favorites (
101 id uuid PRIMARY KEY,
102 project_id uuid NOT NULL REFERENCES project(id) ON DELETE CASCADE,
103 user_id uuid NOT NULL REFERENCES users(uid) ON DELETE CASCADE,
104 folder text,
105 created_at timestamptz NOT NULL DEFAULT now()
106);
107CREATE UNIQUE INDEX IF NOT EXISTS idx_project_favorites_unique
108 ON project_favorites (project_id, user_id, COALESCE(folder, ''));
109CREATE INDEX IF NOT EXISTS idx_project_favorites_user
110 ON project_favorites (user_id, created_at DESC);