pilcrowOnPaper / db-query

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

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;

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;
}

About

License:MIT License


Languages

Language:TypeScript 92.4%Language:JavaScript 7.6%