Files
bknd/app/src/data/connection/sqlite/GenericSqliteConnection.ts
T
dswbx 36e61cab3f feat: enhance SQLite connection configurations to allow WAL
Updated the Bun and Node SQLite connection implementations to support additional configuration options, including `onCreateConnection`. Introduced tests for connection creation to validate database instance types and ensure proper callback execution. Improved type exports for better integration with existing code.
2025-09-20 10:16:33 +02:00

101 lines
3.0 KiB
TypeScript

import type { KyselyPlugin, QueryResult } from "kysely";
import {
type IGenericSqlite,
type Promisable,
parseBigInt,
buildQueryFn,
GenericSqliteDialect,
} from "kysely-generic-sqlite";
import { SqliteConnection } from "./SqliteConnection";
import type { ConnQuery, ConnQueryResults, Features } from "../Connection";
import type { MaybePromise } from "bknd";
export type { IGenericSqlite };
export type TStatement = { sql: string; parameters?: any[] | readonly any[] };
export interface IGenericCustomSqlite<DB = unknown> extends IGenericSqlite<DB> {
batch?: (stmts: TStatement[]) => Promisable<QueryResult<any>[]>;
}
export type GenericSqliteConnectionConfig<Database = unknown> = {
name?: string;
additionalPlugins?: KyselyPlugin[];
excludeTables?: string[];
onCreateConnection?: (db: Database) => MaybePromise<void>;
supports?: Partial<Features>;
};
export class GenericSqliteConnection<DB = unknown> extends SqliteConnection<DB> {
override name = "generic-sqlite";
#executor: IGenericCustomSqlite<DB> | undefined;
constructor(
public db: DB,
private executor: () => Promisable<IGenericCustomSqlite<DB>>,
config?: GenericSqliteConnectionConfig,
) {
super({
dialect: GenericSqliteDialect,
dialectArgs: [
executor,
config?.onCreateConnection && typeof config.onCreateConnection === "function"
? (c: any) => config.onCreateConnection?.(c.db.db as any)
: undefined,
],
additionalPlugins: config?.additionalPlugins,
excludeTables: config?.excludeTables,
});
this.client = db;
if (config?.name) {
this.name = config.name;
}
if (config?.supports) {
for (const [key, value] of Object.entries(config.supports)) {
if (value !== undefined) {
this.supported[key] = value;
}
}
}
}
private async getExecutor() {
if (!this.#executor) {
this.#executor = await this.executor();
}
return this.#executor;
}
override async executeQueries<O extends ConnQuery[]>(...qbs: O): Promise<ConnQueryResults<O>> {
const executor = await this.getExecutor();
if (!executor.batch) {
return super.executeQueries(...qbs);
}
const compiled = this.getCompiled(...qbs);
const stms: TStatement[] = compiled.map((q) => {
return {
sql: q.sql,
parameters: q.parameters as any[],
};
});
const results = await executor.batch(stms);
return this.withTransformedRows(results) as any;
}
}
export function genericSqlite<DB>(
name: string,
db: DB,
executor: (utils: typeof genericSqliteUtils) => Promisable<IGenericCustomSqlite<DB>>,
config?: GenericSqliteConnectionConfig,
) {
return new GenericSqliteConnection(db, () => executor(genericSqliteUtils), {
name,
...config,
});
}
export const genericSqliteUtils = {
parseBigInt,
buildQueryFn,
};