@probitas/client-sql-sqlite

SQLite client for Probitas scenario testing framework.

This package provides a SQLite client designed for integration testing, with transaction support and in-memory database capabilities.

Features

  • Query Execution: Parameterized queries with type-safe results
  • Transactions: Full transaction support with isolation levels
  • In-Memory Databases: Perfect for isolated test scenarios
  • File-Based Databases: Persist data for stateful testing
  • Resource Management: Implements AsyncDisposable for proper cleanup

Installation

deno add jsr:@probitas/client-sql-sqlite

Quick Start

import { createSqliteClient } from "@probitas/client-sql-sqlite";

// In-memory database for testing
const client = await createSqliteClient({
  path: ":memory:",
});

// Create table
await client.query(`
  CREATE TABLE users (
    id INTEGER PRIMARY KEY,
    name TEXT NOT NULL,
    active INTEGER DEFAULT 1
  )
`);

// Insert and query with parameters (uses ? placeholders)
await client.query("INSERT INTO users (name) VALUES (?)", ["Alice"]);

const result = await client.query<{ id: number; name: string }>(
  "SELECT id, name FROM users WHERE active = ?",
  [1]
);
console.log(result.rows);

await client.close();

Transactions

await client.transaction(async (tx) => {
  await tx.query("INSERT INTO accounts (id, balance) VALUES (?, ?)", [1, 100]);
  await tx.query("INSERT INTO accounts (id, balance) VALUES (?, ?)", [2, 200]);
  // Automatically committed if no error, rolled back on exception
});

Using with using Statement

await using client = await createSqliteClient({ path: ":memory:" });

await client.query("CREATE TABLE test (id INTEGER PRIMARY KEY)");
// Client automatically closed when block exits
Package Description
@probitas/client-sql Common SQL types and utilities
@probitas/client-sql-postgres PostgreSQL client
@probitas/client-sql-mysql MySQL client
@probitas/client-sql-duckdb DuckDB client

Installation

deno add jsr:@probitas/client-sql-sqlite

Classes

class

#BusyError

class BusyError extends SqliteError

Error thrown when the database is busy.

NameDescription
name
sqliteKind
Constructor
new BusyError(message: string, options?: SqliteErrorOptions)
Properties
  • readonlynamestring
  • readonlysqliteKind"busy"
class

#ConstraintError

class ConstraintError extends SqlError
ExtendsSqlError

Error thrown when a constraint violation occurs.

NameDescription
name
kind
constraint
Constructor
new ConstraintError(message: string, constraint: string, options?: SqlErrorOptions)
Properties
  • readonlynamestring
  • readonlykind"constraint"
  • readonlyconstraintstring
class

#DatabaseLockedError

class DatabaseLockedError extends SqliteError

Error thrown when the database is locked.

NameDescription
name
sqliteKind
Constructor
new DatabaseLockedError(message: string, options?: SqliteErrorOptions)
Properties
  • readonlynamestring
  • readonlysqliteKind"database_locked"
class

#DeadlockError

class DeadlockError extends SqlError
ExtendsSqlError

Error thrown when a deadlock is detected.

NameDescription
name
kind
Constructor
new DeadlockError(message: string, options?: SqlErrorOptions)
Properties
  • readonlynamestring
  • readonlykind"deadlock"
class

#QuerySyntaxError

class QuerySyntaxError extends SqlError
ExtendsSqlError

Error thrown when a SQL query has syntax errors.

NameDescription
name
kind
Constructor
new QuerySyntaxError(message: string, options?: SqlErrorOptions)
Properties
  • readonlynamestring
  • readonlykind"query"
class

#ReadonlyDatabaseError

class ReadonlyDatabaseError extends SqliteError

Error thrown when trying to write to a readonly database.

NameDescription
name
sqliteKind
Constructor
new ReadonlyDatabaseError(message: string, options?: SqliteErrorOptions)
Properties
  • readonlynamestring
  • readonlysqliteKind"readonly"
class

#SqlError

class SqlError extends ClientError

Base error class for SQL-specific errors. Extends ClientError with SQL-specific properties.

NameDescription
name
kind
sqlState
Constructor
new SqlError(message: string, kind: SqlErrorKind, options?: SqlErrorOptions)
Properties
  • readonlynamestring
  • readonlykindSqlErrorKind
  • readonlysqlState?string
class

#SqliteError

class SqliteError extends SqlError
ExtendsSqlError

Base error class for SQLite-specific errors. Extends SqlError with SQLite-specific properties like extendedCode.

NameDescription
name
extendedCode
Constructor
new SqliteError(message: string, options?: SqliteErrorOptions)
Properties
  • readonlynamestring
  • readonlyextendedCode?number
class

#SqliteTransactionImpl

class SqliteTransactionImpl implements SqlTransaction
ImplementsSqlTransaction
NameDescription
begin()Begin a new transaction.
query()
queryOne()
commit()
rollback()
Constructor
new SqliteTransactionImpl(db: Database)
Methods
static begin(): unknown

Begin a new transaction.

query(): unknown
queryOne(): unknown
commit(): unknown
rollback(): unknown
class

#SqlQueryResult

class SqlQueryResult<T = Record<string, any>>

SQL query result with rows, metadata, and transformation methods.

NameDescription
ok
rows
rowCount
duration
metadata
map()Map rows to a new type.
as()Create class instances from rows.
Constructor
new SqlQueryResult(init: SqlQueryResultInit<T>)
Properties
Methods
map(): unknown

Map rows to a new type.

as(): unknown

Create class instances from rows.

class

#SqlRows

class SqlRows<T> extends Array<T>
ExtendsArray<T>

Row array with first/last helper methods. Implements ReadonlyArray by extending Array.

NameDescription
first()Get the first row, or undefined if empty.
firstOrThrow()Get the first row, or throw if empty.
last()Get the last row, or undefined if empty.
lastOrThrow()Get the last row, or throw if empty.
Constructor
new SqlRows(items: readonly T[])
Methods
first(): unknown

Get the first row, or undefined if empty.

firstOrThrow(): unknown

Get the first row, or throw if empty.

last(): unknown

Get the last row, or undefined if empty.

lastOrThrow(): unknown

Get the last row, or throw if empty.

Interfaces

interface

#SqlErrorOptions

interface SqlErrorOptions extends ErrorOptions

Options for SqlError constructor.

NameDescription
sqlStateSQL State code (e.g., "23505" for unique violation)
Properties
  • readonlysqlState?string

    SQL State code (e.g., "23505" for unique violation)

interface

#SqliteClient

interface SqliteClient extends AsyncDisposable

SQLite client interface.

NameDescription
configThe client configuration.
dialectThe SQL dialect identifier.
query()Execute a SQL query.
queryOne()Execute a query and return the first row or undefined.
transaction()Execute a function within a transaction.
backup()Backup the database to a file.
vacuum()Run VACUUM to rebuild the database file, reclaiming unused space.
close()Close the database connection.
Properties
  • readonlyconfigSqliteClientConfig

    The client configuration.

  • readonlydialect"sqlite"

    The SQL dialect identifier.

Methods
query<T = Record<string, any>>(sql: string, params?: unknown[]): Promise<SqlQueryResult<T>>

Execute a SQL query.

Parameters
  • sqlstring
    • SQL query string
  • params?unknown[]
    • Optional query parameters
queryOne<T = Record<string, any>>(sql: string, params?: unknown[]): Promise<T | undefined>

Execute a query and return the first row or undefined.

Parameters
  • sqlstring
    • SQL query string
  • params?unknown[]
    • Optional query parameters
transaction<T>(fn: (tx: SqlTransaction) => unknown, options?: SqlTransactionOptions | SqliteTransactionOptions): Promise<T>

Execute a function within a transaction. Automatically commits on success or rolls back on error.

Parameters
backup(destPath: string): Promise<void>

Backup the database to a file. Uses VACUUM INTO for a consistent backup.

Parameters
  • destPathstring
    • Destination file path for the backup
vacuum(): Promise<void>

Run VACUUM to rebuild the database file, reclaiming unused space.

close(): Promise<void>

Close the database connection.

interface

#SqliteClientConfig

interface SqliteClientConfig extends CommonOptions

Configuration for creating a SQLite client.

NameDescription
pathDatabase file path.
readonlyOpen the database in read-only mode.
walEnable WAL (Write-Ahead Logging) mode.
Properties
  • readonlypathstring

    Database file path. Use ":memory:" for an in-memory database.

  • readonlyreadonly?boolean

    Open the database in read-only mode.

  • readonlywal?boolean

    Enable WAL (Write-Ahead Logging) mode. WAL mode provides better concurrency and performance.

interface

#SqliteErrorOptions

interface SqliteErrorOptions extends SqlErrorOptions

Options for SqliteError constructor.

NameDescription
extendedCodeSQLite extended error code.
Properties
  • readonlyextendedCode?number

    SQLite extended error code.

interface

#SqliteTransactionOptions

interface SqliteTransactionOptions extends SqlTransactionOptions

SQLite-specific transaction options.

NameDescription
modeTransaction behavior mode.
Properties
interface

#SqlQueryResultExpectation

interface SqlQueryResultExpectation<T>

Expectation interface for SQL query results. All methods return this for chaining.

NameDescription
ok()Verify query succeeded
notOk()Verify query failed
noContent()Verify result has no rows
hasContent()Verify result has rows
rows()Verify exact row count
rowsAtLeast()Verify minimum row count
rowsAtMost()Verify maximum row count
rowCount()Verify exact affected row count
rowCountAtLeast()Verify minimum affected row count
rowCountAtMost()Verify maximum affected row count
rowContains()Verify a row contains the given subset
rowMatch()Custom row validation
mapContains()Verify mapped data contains the given subset
mapMatch()Custom mapped data validation
asContains()Verify instance contains the given subset
asMatch()Custom instance validation
lastInsertId()Verify exact lastInsertId
hasLastInsertId()Verify lastInsertId is present
durationLessThan()Verify query duration is below threshold
Methods
ok(): this

Verify query succeeded

notOk(): this

Verify query failed

noContent(): this

Verify result has no rows

hasContent(): this

Verify result has rows

rows(count: number): this

Verify exact row count

Parameters
  • countnumber
rowsAtLeast(count: number): this

Verify minimum row count

Parameters
  • countnumber
rowsAtMost(count: number): this

Verify maximum row count

Parameters
  • countnumber
rowCount(count: number): this

Verify exact affected row count

Parameters
  • countnumber
rowCountAtLeast(count: number): this

Verify minimum affected row count

Parameters
  • countnumber
rowCountAtMost(count: number): this

Verify maximum affected row count

Parameters
  • countnumber
rowContains(subset: Partial<T>): this

Verify a row contains the given subset

Parameters
  • subsetPartial<T>
rowMatch(matcher: (rows: SqlRows<T>) => unknown): this

Custom row validation

Parameters
  • matcher(rows: SqlRows<T>) => unknown
mapContains<U>(mapper: (row: T) => unknown, subset: Partial<U>): this

Verify mapped data contains the given subset

Parameters
  • mapper(row: T) => unknown
  • subsetPartial<U>
mapMatch<U>(mapper: (row: T) => unknown, matcher: (mapped: U[]) => unknown): this

Custom mapped data validation

Parameters
  • mapper(row: T) => unknown
  • matcher(mapped: U[]) => unknown
asContains<U>(ctor: (row: T) => unknown, subset: Partial<U>): this

Verify instance contains the given subset

Parameters
  • ctor(row: T) => unknown
  • subsetPartial<U>
asMatch<U>(ctor: (row: T) => unknown, matcher: (instances: U[]) => unknown): this

Custom instance validation

Parameters
  • ctor(row: T) => unknown
  • matcher(instances: U[]) => unknown
lastInsertId(expected: bigint | string): this

Verify exact lastInsertId

Parameters
  • expectedbigint | string
hasLastInsertId(): this

Verify lastInsertId is present

durationLessThan(ms: number): this

Verify query duration is below threshold

Parameters
  • msnumber
interface

#SqlQueryResultInit

interface SqlQueryResultInit<T>

Options for creating a SqlQueryResult.

NameDescription
okWhether the query succeeded
rowsThe result rows
rowCountNumber of affected rows (for INSERT/UPDATE/DELETE)
durationQuery execution duration in milliseconds
metadataAdditional metadata
Properties
  • readonlyokboolean

    Whether the query succeeded

  • readonlyrowsreadonly T[]

    The result rows

  • readonlyrowCountnumber

    Number of affected rows (for INSERT/UPDATE/DELETE)

  • readonlydurationnumber

    Query execution duration in milliseconds

  • readonlymetadataSqlQueryResultMetadata

    Additional metadata

interface

#SqlQueryResultMetadata

interface SqlQueryResultMetadata

Metadata for SQL query results.

NameDescription
lastInsertIdLast inserted ID (for INSERT statements)
warningsWarning messages from the database
Properties
  • readonlylastInsertId?bigint | string

    Last inserted ID (for INSERT statements)

  • readonlywarnings?readonly string[]

    Warning messages from the database

interface

#SqlTransaction

interface SqlTransaction

SQL transaction interface. Implementations should provide actual database-specific transaction handling.

NameDescription
query()Execute a query within the transaction.
queryOne()Execute a query and return the first row or undefined.
commit()Commit the transaction.
rollback()Rollback the transaction.
Methods
query<T = Record<string, any>>(sql: string, params?: unknown[]): Promise<SqlQueryResult<T>>

Execute a query within the transaction.

Parameters
  • sqlstring
    • SQL query string
  • params?unknown[]
    • Optional query parameters
queryOne<T = Record<string, any>>(sql: string, params?: unknown[]): Promise<T | undefined>

Execute a query and return the first row or undefined.

Parameters
  • sqlstring
    • SQL query string
  • params?unknown[]
    • Optional query parameters
commit(): Promise<void>

Commit the transaction.

rollback(): Promise<void>

Rollback the transaction.

interface

#SqlTransactionOptions

interface SqlTransactionOptions

Options for starting a transaction.

NameDescription
isolationLevelIsolation level for the transaction
Properties

Functions

function

#convertSqliteError

function convertSqliteError(error: unknown): SqlError

Convert a @db/sqlite error to the appropriate error class.

Note: @db/sqlite throws plain Error objects without SQLite error codes. Error classification is based on message content analysis.

Parameters
  • errorunknown
function

#createSqliteClient

function createSqliteClient(config: SqliteClientConfig): Promise<SqliteClient>

Create a new SQLite client instance.

The client provides parameterized queries, transaction support, WAL mode for better concurrency, and SQLite-specific features like backup and vacuum.

Parameters
Returns

Promise<SqliteClient> — A promise resolving to a new SQLite client instance

Examples

Using file-based database

const client = await createSqliteClient({
  path: "./data.db",
});

const result = await client.query<{ id: number; name: string }>(
  "SELECT * FROM users WHERE id = ?",
  [1],
);
console.log(result.rows.first());

await client.close();

Using in-memory database

const client = await createSqliteClient({
  path: ":memory:",
});

Transaction with auto-commit/rollback

const user = await client.transaction(async (tx) => {
  await tx.query("INSERT INTO users (name) VALUES (?)", ["Alice"]);
  const result = await tx.query("SELECT last_insert_rowid() as id");
  return result.rows.first();
});

Database backup

// Create a backup of the database
await client.backup("./backup.db");

Using await using for automatic cleanup

await using client = await createSqliteClient({ path: "./data.db" });

const result = await client.query("SELECT 1");
// Client automatically closed when scope exits
function

#expectSqlQueryResult

function expectSqlQueryResult<T = Record<string, any>>(result: SqlQueryResult<T>): SqlQueryResultExpectation<T>

Create an expectation for a SQL query result.

Parameters

Type Aliases

type

#SqlErrorKind

type SqlErrorKind = "query" | "constraint" | "deadlock" | "unknown"

SQL-specific error kinds.

type

#SqlIsolationLevel

type SqlIsolationLevel = "read_uncommitted" | "read_committed" | "repeatable_read" | "serializable"

Transaction isolation level.

type

#SqliteErrorKind

type SqliteErrorKind = "database_locked" | "readonly" | "busy"

SQLite-specific error kinds.

type

#SqliteTransactionMode

type SqliteTransactionMode = "deferred" | "immediate" | "exclusive"

SQLite transaction behavior mode.

  • "deferred": Locks are acquired on first read/write (default)
  • "immediate": Acquires RESERVED lock immediately
  • "exclusive": Acquires EXCLUSIVE lock immediately
Search Documentation