// spellchecker: words sqlocal kysely insertable updateable import { SQLocalKysely } from "sqlocal/kysely"; import { Generated, Insertable, Kysely, Migration, Migrator } from "kysely"; const tableNames = { mail: { table: "mail", columns: { id: "id", messageId: "message_id", awsMessageId: "aws_message_id", raw: "raw", }, }, } as const; interface MailTable { [tableNames.mail.columns.id]: Generated; [tableNames.mail.columns.messageId]: string; [tableNames.mail.columns.awsMessageId]: string | null; [tableNames.mail.columns.raw]: string; } interface Database { [tableNames.mail.table]: MailTable; } const migrations: Record = { "0001-init": { // deno-lint-ignore no-explicit-any async up(db: Kysely): Promise { const names = tableNames.mail; await db.schema .createTable(names.table) .addColumn( names.columns.id, "integer", (col) => col.primaryKey().autoIncrement(), ) .addColumn( names.columns.messageId, "text", (col) => col.notNull().unique(), ) .addColumn(names.columns.awsMessageId, "text", (col) => col.unique()) .addColumn(names.columns.raw, "text", (col) => col.notNull()) .execute(); for ( const column of [names.columns.messageId, names.columns.awsMessageId] ) { await db.schema .createIndex(`${names.table}_${column}`) .on(names.table) .column(column) .execute(); } }, // deno-lint-ignore no-explicit-any async down(db: Kysely): Promise { await db.schema.dropTable(tableNames.mail.table).execute(); }, }, }; export class DbService { private _sqlocal; private _db; private _migrator; constructor(public readonly path: string) { this._sqlocal = new SQLocalKysely("database.sqlite3"); const db = new Kysely({ dialect: this._sqlocal.dialect }); this._db = db; this._migrator = new Migrator({ db, provider: { getMigrations(): Promise> { return Promise.resolve(migrations); }, }, }); } async migrate(): Promise { await this._migrator.migrateToLatest(); } async addMail(mail: Insertable): Promise { await this._db.insertInto(tableNames.mail.table).values(mail) .executeTakeFirstOrThrow(); } async messageIdToAws(messageId: string): Promise { const row = await this._db.selectFrom(tableNames.mail.table).where( tableNames.mail.columns.messageId, "=", messageId, ).select(tableNames.mail.columns.awsMessageId).executeTakeFirst(); return row?.aws_message_id ?? null; } async messageIdFromAws(awsMessageId: string): Promise { const row = await this._db.selectFrom(tableNames.mail.table).where( tableNames.mail.columns.awsMessageId, "=", awsMessageId, ).select(tableNames.mail.columns.messageId).executeTakeFirst(); return row?.message_id ?? null; } }