swadhinbiswas feat: push-mirror, webhook queue, auth-cache, gists/discussions · 8/28/2026
96005fc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
/**
* Discussions Schema - Drizzle ORM
* GitHub-style repository discussions and threaded comments
*/
import {
boolean,
index,
integer,
pgTable,
text,
timestamp,
} from "drizzle-orm/pg-core";
import { repositories } from "./repositories";
import { users } from "./users";
export const DISCUSSION_CATEGORIES = [
"General",
"Ideas",
"Q&A",
"Show and tell",
] as const;
export type DiscussionCategory = (typeof DISCUSSION_CATEGORIES)[number];
export const discussions = pgTable(
"discussions",
{
id: text("id").primaryKey(),
repositoryId: text("repository_id")
.notNull()
.references(() => repositories.id, { onDelete: "cascade" }),
authorId: text("author_id")
.notNull()
.references(() => users.id),
title: text("title").notNull(),
body: text("body").notNull(),
category: text("category").notNull().default("General"),
pinned: boolean("pinned").default(false),
closed: boolean("closed").default(false),
commentCount: integer("comment_count").default(0),
lastActivityAt: timestamp("last_activity_at"),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
},
(t) => ({
repoClosedIdx: index("discussions_repo_closed_idx").on(
t.repositoryId,
t.closed,
),
repoActivityIdx: index("discussions_repo_activity_idx").on(
t.repositoryId,
t.lastActivityAt,
),
authorIdx: index("discussions_author_idx").on(t.authorId),
}),
);
export const discussionComments = pgTable(
"discussion_comments",
{
id: text("id").primaryKey(),
discussionId: text("discussion_id")
.notNull()
.references(() => discussions.id, { onDelete: "cascade" }),
// Self-reference for one-level threading; stored but treated flat in UI v1.
// Plain text column (no FK) mirrors the issues.parent_id convention to avoid
// circular type references in Drizzle.
parentId: text("parent_id"),
authorId: text("author_id")
.notNull()
.references(() => users.id),
body: text("body").notNull(),
createdAt: timestamp("created_at").notNull().defaultNow(),
updatedAt: timestamp("updated_at").notNull().defaultNow(),
},
(t) => ({
discussionIdx: index("discussion_comments_discussion_idx").on(
t.discussionId,
),
parentIdx: index("discussion_comments_parent_idx").on(t.parentId),
}),
);
// Types
export type Discussion = typeof discussions.$inferSelect;
export type NewDiscussion = typeof discussions.$inferInsert;
export type DiscussionComment = typeof discussionComments.$inferSelect;
export type NewDiscussionComment = typeof discussionComments.$inferInsert;