@pilcrowjs/db-query
v0.0.2
Published
Add type-safety to your database drivers.
Downloads
585
Readme
Database query
A small library to add type-safety to your database driver.
const rows = db.query("SELECT user.id, user.username, user.email, user.email_verified, user.profile FROM user", []);
for (const row of rows) {
const user: User = {
id: row.number(0),
username: row.string(1),
email: row.string(2),
emailVerified: Boolean(row.number(3)),
profile: row.stringNullable(4)
};
}
const row = db.queryOne(
"SELECT user.id, user.username, user.email, user.email_verified, user.profile FROM user WHERE user.username = ?",
[username]
);
if (row !== null) {
const user: User = {
id: row.number(0),
username: row.string(1),
email: row.string(2),
emailVerified: Boolean(row.number(3)),
profile: row.stringNullable(4)
};
}
Installation
npm install @pilcrowjs/db-query
Example
import sqlite3 from "better-sqlite3";
import { SyncDatabase } from "@pilcrowjs/db-query";
import type { SyncAdapter } from "@pilcrowjs/db-query";
const sqlite = sqlite3("sqlite.db");
const adapter: SyncAdapter<sqlite3.RunResult> = {
query: (statement: string, params: unknown[]): unknown[][] => {
const result = sqlite
.prepare(statement)
.raw()
.all(...params);
return result as unknown[][];
},
execute: (statement: string, params: unknown[]): sqlite3.RunResult => {
const result = sqlite
.prepare(statement)
.raw()
.run(...params);
return result;
}
};
const db = new SyncDatabase(adapter);
APIs for asynchronous drivers are also available.
import { AsyncDatabase } from "@pilcrowjs/db-query";
import type { AsyncAdapter } from "@pilcrowjs/db-query";
const adapter: AsyncAdapter<void> = {
query: async (statement: string, params: unknown[]): Promise<unknown[][]> => {
// ...
},
execute: async (statement: string, params: unknown[]): Promise<void> => {
// ...
}
};
const db = new AsyncDatabase(adapter);
API
Database
function constructor(adapter: Adapter): this;
Database.execute()
AsyncDatabase
will return Promise<any>
. The return type will be the same as Adapter.execute()
.
function execute(statement: string, args: any[]): any;
Database.query()
AsyncDatabase
will return Promise<Rows>
.
function query(statement: string, args: any[]): Rows;
class Rows {
count(): number;
*[Symbol.iterator](): Iterator<Row>;
}
Database.queryOne()
AsyncDatabase
will return Promise<Row | null>
.
function queryOne(statement: string, args: any[]): Row | null;
Database.queryOneOrThrow()
AsyncDatabase
will return Promise<Row>
. Similar to queryOne()
but throws an Error
if there are no rows.
function queryOne(statement: string, args: any[]): Row;
Row
bigintNullable()
and bigint()
will convert integer Numbers to BigInts. All other methods will not do any implicit type conversion (e.g. Number => Boolean). Methods will throw an Error
if the type is invalid.
class Row {
stringNullable(index: number): string | null;
string(index: number): string;
numberNullable(index: number): number | null;
number(index: number): number;
bigintNullable(index: number): bigint | null;
bigint(index: number): bigint;
booleanNullable(index: number): boolean | null;
boolean(index: number): boolean;
bytesNullable(index: number): Uint8Array | null;
bytes(index: number): Uint8Array;
get(index: number): unknown;
}
Adapter
AsyncAdapter
methods should return a promise.
interface Adapter<_ExecuteResult> {
query(statement: string, params: unknown[]): unknown[][];
execute(statement: string, params: unknown[]): _ExecuteResult;
}