sqlocal
Version:
SQLocal makes it easy to run SQLite3 in the browser, backed by the origin private file system.
201 lines (177 loc) • 5 kB
text/typescript
import type { Database, Sqlite3Static } from '@sqlite.org/sqlite-wasm';
import type { CompiledQuery as KyselyQuery } from 'kysely';
import type { RunnableQuery as DrizzleQuery } from 'drizzle-orm/runnable-query';
import type { SqliteRemoteResult } from 'drizzle-orm/sqlite-proxy';
import type { sqlTag } from './lib/sql-tag.js';
import type { SQLocalProcessor } from './processor.js';
type IsAny<T> = boolean extends (T extends never ? true : false) ? true : false;
// SQLite
export type Sqlite3 = Sqlite3Static;
export type Sqlite3InitModule = () => Promise<Sqlite3>;
export type Sqlite3Db = Database;
export type Sqlite3Method = 'get' | 'all' | 'run' | 'values';
export type Sqlite3StorageType =
| (string & {})
| 'memory'
| 'opfs'
| 'local'
| 'session';
// Queries
export type Statement = {
sql: string;
params: unknown[];
};
export type ReturningStatement<Result = unknown> =
| Statement
| (IsAny<KyselyQuery<unknown>> extends true ? never : KyselyQuery<Result>)
| (IsAny<DrizzleQuery<unknown, never>> extends true
? never
: DrizzleQuery<
Result extends SqliteRemoteResult<unknown> ? any : Result[],
'sqlite'
>);
export type SqlTag = typeof sqlTag;
export type StatementInput<Result = unknown> =
| ReturningStatement<Result>
| ((sql: SqlTag) => ReturningStatement<Result>);
export type Transaction = {
transactionKey: QueryKey;
lastAffectedRows?: bigint;
query: <Result extends Record<string, any>>(
passStatement: StatementInput<Result>
) => Promise<Result[]>;
sql: <Result extends Record<string, any>>(
queryTemplate: TemplateStringsArray | string,
...params: unknown[]
) => Promise<Result[]>;
batch: <Result extends Record<string, any>>(
passStatements: (sql: SqlTag) => Statement[]
) => Promise<Result[][]>;
commit: () => Promise<void>;
rollback: () => Promise<void>;
};
export type TransactionHandle = Pick<Transaction, 'query' | 'sql' | 'batch'>;
export type ReactiveQuery<Result = unknown> = {
readonly value: Result[];
subscribe: (
onData: (results: Result[]) => void,
onError?: (err: Error) => void
) => {
unsubscribe: () => void;
};
};
export type ReactiveQueryStatus = 'pending' | 'ok' | 'error';
export type RawResultData = {
rows: unknown[] | unknown[][];
columns: string[];
numAffectedRows?: bigint;
};
// Driver
export interface SQLocalDriver {
readonly storageType: Sqlite3StorageType;
init: (config: DriverConfig) => Promise<void>;
exec: (statement: DriverStatement) => Promise<RawResultData>;
execBatch: (
statements: DriverStatement[],
method?: 'transaction' | 'savepoint'
) => Promise<RawResultData[]>;
onWrite: (callback: (change: DataChange) => void) => () => void;
isDatabasePersisted: () => Promise<boolean>;
getDatabaseSizeBytes: () => Promise<number>;
createFunction: (fn: UserFunction) => Promise<void>;
import: (
database:
| ArrayBuffer
| Uint8Array<ArrayBuffer>
| ReadableStream<Uint8Array<ArrayBuffer>>
) => Promise<void>;
export: () => Promise<{
name: string;
data: ArrayBuffer | Uint8Array<ArrayBuffer>;
}>;
clear: () => Promise<void>;
destroy: () => Promise<void>;
}
export type DriverConfig = {
databasePath?: DatabasePath;
reactive?: boolean;
readOnly?: boolean;
verbose?: boolean;
};
export type DriverStatement = {
sql: string;
params?: any[];
method?: Sqlite3Method;
};
// Database status
export type DatabasePath =
| (string & {})
| ':memory:'
| 'local'
| ':localStorage:'
| 'session'
| ':sessionStorage:';
export type QueryKey = string;
export type ConnectReason = 'initial' | 'overwrite' | 'delete';
export type ClientConfig = {
databasePath: DatabasePath;
reactive?: boolean;
readOnly?: boolean;
verbose?: boolean;
onInit?: (sql: SqlTag) => void | Statement[];
onConnect?: (reason: ConnectReason) => void;
processor?: SQLocalProcessor | Worker;
};
export type ProcessorConfig = {
databasePath?: DatabasePath;
reactive?: boolean;
readOnly?: boolean;
verbose?: boolean;
clientKey?: QueryKey;
onInitStatements?: Statement[];
};
export type DatabaseInfo = {
databasePath?: DatabasePath;
databaseSizeBytes?: number;
storageType?: Sqlite3StorageType;
persisted?: boolean;
};
export type DataChange = {
operation: 'insert' | 'update' | 'delete';
table: string;
rowid: BigInt;
};
// User functions
export type UserFunction =
| CallbackUserFunction
| ScalarUserFunction
| AggregateUserFunction
| WindowUserFunction;
export type CallbackUserFunction = {
type: 'callback';
name: string;
func: (...args: any[]) => void;
};
export type ScalarUserFunction = {
type: 'scalar';
name: string;
func: (...args: any[]) => any;
};
export type AggregateUserFunction = {
type: 'aggregate';
name: string;
func: {
step: (...args: any[]) => void;
final: (...args: any[]) => any;
};
};
export type WindowUserFunction = {
type: 'window';
name: string;
func: {
step: (...args: any[]) => void;
value: (...args: any[]) => any;
inverse: (...args: any[]) => void;
final: (...args: any[]) => any;
};
};