sqlocal
Version:
SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.
99 lines (83 loc) • 2.79 kB
text/typescript
import {
CompiledQuery,
SqliteAdapter,
SqliteIntrospector,
SqliteQueryCompiler,
} from 'kysely';
import type { DatabaseConnection, Dialect, Driver, QueryResult } from 'kysely';
import { SQLocal } from '../index.js';
import type { Transaction } from '../types.js';
import { convertRowsToObjects } from '../lib/convert-rows-to-objects.js';
import { sqlTag } from '../lib/sql-tag.js';
/**
* A subclass of the `SQLocal` client that provides an additional property
* for using SQLocal as a dialect for the Kysely query builder.
* @see {@link https://sqlocal.dev/kysely/setup}
*/
export class SQLocalKysely extends SQLocal {
/**
* A Kysely dialect that implements the interface needed for
* Kysely to interact with databases through SQLocal.
* @see {@link https://sqlocal.dev/kysely/setup}
*/
dialect: Dialect = {
createAdapter: () => new SqliteAdapter(),
createDriver: () => new SQLocalKyselyDriver(this),
createIntrospector: (db) => new SqliteIntrospector(db),
createQueryCompiler: () => new SqliteQueryCompiler(),
};
}
class SQLocalKyselyDriver implements Driver {
constructor(private client: SQLocalKysely) {}
async init(): Promise<void> {}
async acquireConnection(): Promise<SQLocalKyselyConnection> {
return new SQLocalKyselyConnection(this.client);
}
async releaseConnection(): Promise<void> {}
async beginTransaction(connection: SQLocalKyselyConnection): Promise<void> {
connection.transaction = await this.client.beginTransaction();
}
async commitTransaction(connection: SQLocalKyselyConnection): Promise<void> {
await connection.transaction?.commit();
connection.transaction = null;
}
async rollbackTransaction(
connection: SQLocalKyselyConnection
): Promise<void> {
await connection.transaction?.rollback();
connection.transaction = null;
}
async destroy(): Promise<void> {
await this.client.destroy();
}
}
class SQLocalKyselyConnection implements DatabaseConnection {
transaction: Transaction | null = null;
constructor(private client: SQLocalKysely) {}
async executeQuery<Result>(
query: CompiledQuery
): Promise<QueryResult<Result>> {
let rows;
let affectedRows: bigint | undefined;
if (this.transaction === null) {
const statement = sqlTag(query.sql, query.parameters);
const result = await this.client.exec(
statement.sql,
statement.params,
'all'
);
rows = convertRowsToObjects(result.rows, result.columns);
affectedRows = result.numAffectedRows;
} else {
rows = await this.transaction.query(query);
affectedRows = this.transaction.lastAffectedRows;
}
return {
rows: rows as Result[],
numAffectedRows: affectedRows,
};
}
async *streamQuery(): AsyncGenerator<never, void, unknown> {
throw new Error('SQLite3 does not support streaming.');
}
}