81 lines
2.3 KiB
TypeScript
81 lines
2.3 KiB
TypeScript
import { CompiledQuery, Kysely } from 'kysely';
|
|
import { NodeNativeSqliteDialect } from 'kysely-node-native-sqlite';
|
|
|
|
import type { DatabaseTables } from './tables.ts';
|
|
import type { Logger } from '../../utils/logger.ts';
|
|
|
|
/** Options required to open a SQLite database connection. */
|
|
export type DatabaseOptions = {
|
|
|
|
/** Filesystem path to the SQLite database file. */
|
|
path: string;
|
|
|
|
/** Logger extended with a database namespace for diagnostics. */
|
|
debug: Logger;
|
|
};
|
|
|
|
/**
|
|
* Thin wrapper around Kysely and NodeNativeSqliteDialect (which uses node:sqlite).
|
|
*
|
|
* Owns connection setup, pragma configuration, and graceful teardown.
|
|
*/
|
|
export class Database {
|
|
private readonly debug: Logger;
|
|
private readonly dialect: NodeNativeSqliteDialect;
|
|
private readonly kysely: Kysely<DatabaseTables>;
|
|
|
|
/**
|
|
* Open a SQLite database and configure it for concurrent writes.
|
|
*
|
|
* @param options - Database file path and debug logger.
|
|
*/
|
|
constructor(options: DatabaseOptions) {
|
|
// Extend the debug logger to include the database namespace.
|
|
this.debug = options.debug.extend('database');
|
|
|
|
// Create the SQLite database.
|
|
this.dialect = new NodeNativeSqliteDialect(options.path);
|
|
|
|
// Create the Kysely database.
|
|
this.kysely = new Kysely<DatabaseTables>({
|
|
dialect: this.dialect,
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Gets the Kysely database.
|
|
*
|
|
* @returns The typed Kysely query builder for DatabaseTables.
|
|
*/
|
|
get db(): Kysely<DatabaseTables> {
|
|
return this.kysely;
|
|
}
|
|
|
|
async start(): Promise<void> {
|
|
this.debug('starting database connection');
|
|
|
|
// Configure the SQLite pragmas.
|
|
await this.configurePragmas();
|
|
}
|
|
|
|
/**
|
|
* Destroys the database connection.
|
|
*/
|
|
async destroy(): Promise<void> {
|
|
this.debug('destroying database connection');
|
|
await this.kysely.destroy();
|
|
}
|
|
|
|
/**
|
|
* Configures the SQLite pragmas.
|
|
*
|
|
* WAL improves write concurrency; foreign keys enforce referential integrity.
|
|
*/
|
|
private async configurePragmas(): Promise<void> {
|
|
this.debug('configuring SQLite pragmas');
|
|
|
|
await this.kysely.executeQuery(CompiledQuery.raw('PRAGMA journal_mode = WAL'));
|
|
await this.kysely.executeQuery(CompiledQuery.raw('PRAGMA foreign_keys = ON'));
|
|
}
|
|
}
|