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