index.ts
Raw
1import { Database as BunDatabase } from "bun:sqlite";
2import { type Generated, Kysely, type Selectable } from "kysely";
3import { BunSqliteDialect } from "kysely-bun-sqlite";
4
5import { DB_PATH } from "../constants.ts";
6
7interface UserTable {
8 id: Generated<number>;
9 username: string;
10 password_hash: string | null;
11 created_at: string;
12 avatar_version: Generated<number>;
13 git_name: string | null;
14 git_email: string | null;
15}
16
17interface PasskeyTable {
18 id: Generated<number>;
19 user_id: number;
20 credential_id: string;
21 public_key: string;
22 counter: number;
23 created_at: string;
24}
25
26interface SessionTable {
27 id: string;
28 user_id: number;
29 expires_at: string;
30 created_at: string;
31}
32
33interface RepositoryTable {
34 id: Generated<number>;
35 name: string;
36 description: string | null;
37 is_private: number;
38 default_branch: string;
39 created_at: string;
40 issue_seq: Generated<number>;
41 patch_seq: Generated<number>;
42}
43
44interface IssueTable {
45 id: Generated<number>;
46 repo_id: number;
47 author_id: number | null;
48 number: number;
49 title: string;
50 body: string;
51 status: string;
52 created_at: string;
53 updated_at: string;
54 edited_at: string | null;
55}
56
57interface IssueCommentTable {
58 id: Generated<number>;
59 issue_id: number;
60 author_id: number | null;
61 body: string;
62 created_at: string;
63 edited_at: string | null;
64}
65
66interface IssueReactionTable {
67 id: Generated<number>;
68 issue_id: number;
69 comment_id: number | null;
70 user_id: number;
71 emoji: string;
72}
73
74interface PatchTable {
75 id: Generated<number>;
76 repo_id: number;
77 author_id: number | null;
78 number: number;
79 title: string;
80 description: string;
81 patch_content: string;
82 status: string;
83 author_name: string;
84 author_email: string;
85 created_at: string;
86 updated_at: string;
87 edited_at: string | null;
88}
89
90interface PatchCommentTable {
91 id: Generated<number>;
92 patch_id: number;
93 author_id: number | null;
94 body: string;
95 created_at: string;
96 edited_at: string | null;
97}
98
99interface PatchReactionTable {
100 id: Generated<number>;
101 patch_id: number;
102 comment_id: number | null;
103 user_id: number;
104 emoji: string;
105}
106
107interface SshKeyTable {
108 id: Generated<number>;
109 user_id: number;
110 name: string;
111 public_key: string;
112 fingerprint: string;
113 created_at: string;
114}
115
116interface ReleaseTable {
117 id: Generated<number>;
118 repo_id: number;
119 tag_name: string;
120 name: string | null;
121 notes: string | null;
122 commit_hash: string;
123 include_source_code: number;
124 created_at: string;
125}
126
127interface ReleaseAssetTable {
128 id: Generated<number>;
129 release_id: number;
130 filename: string;
131 size: number;
132 content_type: string;
133 created_at: string;
134}
135
136export interface Database {
137 users: UserTable;
138 passkeys: PasskeyTable;
139 sessions: SessionTable;
140 repositories: RepositoryTable;
141 issues: IssueTable;
142 issue_comments: IssueCommentTable;
143 issue_reactions: IssueReactionTable;
144 patches: PatchTable;
145 patch_comments: PatchCommentTable;
146 patch_reactions: PatchReactionTable;
147 ssh_keys: SshKeyTable;
148 releases: ReleaseTable;
149 release_assets: ReleaseAssetTable;
150}
151
152// Selectable row types (id is plain number, as returned by queries)
153export type UserRow = Selectable<UserTable>;
154export type PasskeyRow = Selectable<PasskeyTable>;
155export type SessionRow = Selectable<SessionTable>;
156export type RepositoryRow = Selectable<RepositoryTable>;
157export type IssueRow = Selectable<IssueTable>;
158export type IssueCommentRow = Selectable<IssueCommentTable>;
159export type IssueReactionRow = Selectable<IssueReactionTable>;
160export type PatchRow = Selectable<PatchTable>;
161export type PatchCommentRow = Selectable<PatchCommentTable>;
162export type PatchReactionRow = Selectable<PatchReactionTable>;
163export type SshKeyRow = Selectable<SshKeyTable>;
164export type ReleaseRow = Selectable<ReleaseTable>;
165export type ReleaseAssetRow = Selectable<ReleaseAssetTable>;
166
167const sqlite = new BunDatabase(DB_PATH);
168sqlite.run("PRAGMA journal_mode=WAL");
169sqlite.run("PRAGMA foreign_keys=ON");
170
171export const db = new Kysely<Database>({
172 dialect: new BunSqliteDialect({ database: sqlite }),
173});
174
175export async function getRepo(name: string, isAdmin: boolean) {
176 const repo = await db
177 .selectFrom("repositories")
178 .selectAll()
179 .where("name", "=", name)
180 .executeTakeFirst();
181 if (!repo) return null;
182 if (repo.is_private && !isAdmin) return null;
183 return repo;
184}
185