Scratch space for learning atproto app development
1import SqliteDb from 'better-sqlite3'
2import {
3 Kysely,
4 Migration,
5 MigrationProvider,
6 Migrator,
7 SqliteDialect,
8} from 'kysely'
9
10import { env } from '#/env'
11
12// Types
13
14export type DatabaseSchema = {
15 status: Status
16 auth_session: AuthSession
17 auth_state: AuthState
18}
19
20export type Status = {
21 uri: string
22 authorDid: string
23 status: string
24 createdAt: string
25 indexedAt: string
26}
27
28export type AuthSession = {
29 key: string
30 session: AuthSessionJson
31}
32
33export type AuthState = {
34 key: string
35 state: AuthStateJson
36}
37
38type AuthStateJson = string
39
40type AuthSessionJson = string
41
42// Migrations
43
44const migrations: Record<string, Migration> = {}
45
46const migrationProvider: MigrationProvider = {
47 async getMigrations() {
48 return migrations
49 },
50}
51
52migrations['001'] = {
53 async up(db: Kysely<unknown>) {
54 await db.schema
55 .createTable('status')
56 .addColumn('uri', 'varchar', (col) => col.primaryKey())
57 .addColumn('authorDid', 'varchar', (col) => col.notNull())
58 .addColumn('status', 'varchar', (col) => col.notNull())
59 .addColumn('createdAt', 'varchar', (col) => col.notNull())
60 .addColumn('indexedAt', 'varchar', (col) => col.notNull())
61 .execute()
62 await db.schema
63 .createTable('auth_session')
64 .addColumn('key', 'varchar', (col) => col.primaryKey())
65 .addColumn('session', 'varchar', (col) => col.notNull())
66 .execute()
67 await db.schema
68 .createTable('auth_state')
69 .addColumn('key', 'varchar', (col) => col.primaryKey())
70 .addColumn('state', 'varchar', (col) => col.notNull())
71 .execute()
72 },
73 async down(db: Kysely<unknown>) {
74 await db.schema.dropTable('auth_state').execute()
75 await db.schema.dropTable('auth_session').execute()
76 await db.schema.dropTable('status').execute()
77 },
78}
79
80// APIs
81
82export async function createDb(options?: {
83 /** @default true */
84 migrate?: boolean
85}): Promise<Database> {
86 const db = new Kysely<DatabaseSchema>({
87 dialect: new SqliteDialect({
88 database: new SqliteDb(env.DB_PATH),
89 }),
90 })
91
92 if (options?.migrate !== false) {
93 const migrator = new Migrator({ db, provider: migrationProvider })
94 const { error } = await migrator.migrateToLatest()
95 if (error) throw error
96 }
97
98 return db
99}
100
101export type Database = Kysely<DatabaseSchema>