uql-orm 0.62.0 → 0.64.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/bunSql/bunSql.util.d.ts +15 -15
- package/dist/bunSql/bunSql.util.js +22 -35
- package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
- package/dist/bunSql/bunSqlQuerier.js +3 -3
- package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
- package/dist/bunSql/bunSqlQuerierPool.js +3 -34
- package/dist/d1/d1Querier.d.ts +12 -4
- package/dist/d1/d1Querier.js +6 -11
- package/dist/d1/d1QuerierPool.d.ts +7 -3
- package/dist/d1/d1QuerierPool.js +5 -3
- package/dist/entity/decorator/entity.d.ts +5 -9
- package/dist/entity/decorator/entity.js +3 -7
- package/dist/entity/metadata/definition.d.ts +2 -2
- package/dist/entity/metadata/definition.js +13 -22
- package/dist/libsql/libsqlDialect.d.ts +1 -1
- package/dist/libsql/libsqlDialect.js +1 -1
- package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
- package/dist/libsql/libsqlQuerierPool.js +32 -20
- package/dist/migrate/builder/expressions.js +1 -15
- package/dist/migrate/builder/migrationBuilder.d.ts +6 -28
- package/dist/migrate/builder/migrationBuilder.js +9 -83
- package/dist/migrate/builder/types.d.ts +14 -24
- package/dist/migrate/cli.d.ts +1 -6
- package/dist/migrate/cli.js +3 -10
- package/dist/migrate/codegen/index.d.ts +1 -1
- package/dist/migrate/codegen/index.js +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
- package/dist/migrate/codegen/indexDecoratorSource.js +4 -8
- package/dist/migrate/codegen/migrationFile.d.ts +9 -5
- package/dist/migrate/codegen/migrationFile.js +2 -3
- package/dist/migrate/ddl/indexDdl.d.ts +4 -2
- package/dist/migrate/ddl/indexDdl.js +16 -15
- package/dist/migrate/generator/mongoCommand.d.ts +9 -9
- package/dist/migrate/generator/mongoCommand.js +1 -1
- package/dist/migrate/generator/mongoSchemaGenerator.d.ts +21 -26
- package/dist/migrate/generator/mongoSchemaGenerator.js +103 -80
- package/dist/migrate/index.d.ts +1 -1
- package/dist/migrate/index.js +1 -1
- package/dist/migrate/indexPredicate.d.ts +8 -0
- package/dist/migrate/indexPredicate.js +52 -0
- package/dist/migrate/migrationTarget.d.ts +23 -0
- package/dist/migrate/migrationTarget.js +48 -0
- package/dist/migrate/migrator.d.ts +17 -45
- package/dist/migrate/migrator.js +80 -179
- package/dist/migrate/schemaGenerator.d.ts +12 -13
- package/dist/migrate/schemaGenerator.js +43 -9
- package/dist/mongo/mongoDialect.d.ts +6 -1
- package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
- package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
- package/dist/schema/schemaASTBuilder.d.ts +2 -0
- package/dist/schema/schemaASTBuilder.js +9 -22
- package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
- package/dist/sqlite/abstractSqliteQuerier.js +14 -33
- package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
- package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
- package/dist/sqlite/hranaQuerier.d.ts +6 -4
- package/dist/sqlite/hranaQuerier.js +4 -13
- package/dist/sqlite/index.d.ts +0 -1
- package/dist/sqlite/index.js +0 -1
- package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
- package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
- package/dist/sqlite/nodeSqliteAdapter.js +3 -6
- package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
- package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
- package/dist/sqlite/sqliteDialect.d.ts +1 -1
- package/dist/sqlite/sqliteDialect.js +1 -1
- package/dist/sqlite/sqlitePragmas.d.ts +2 -11
- package/dist/sqlite/sqlitePragmas.js +1 -1
- package/dist/sqlite/sqliteQuerier.d.ts +29 -10
- package/dist/sqlite/sqliteQuerier.js +26 -4
- package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
- package/dist/sqlite/sqliteQuerierPool.js +12 -8
- package/dist/turso/index.d.ts +1 -0
- package/dist/turso/index.js +1 -0
- package/dist/turso/local.d.ts +1 -1
- package/dist/turso/local.js +1 -1
- package/dist/turso/tursoDialect.d.ts +4 -9
- package/dist/turso/tursoDialect.js +4 -12
- package/dist/turso/tursoLocalDialect.d.ts +10 -0
- package/dist/turso/tursoLocalDialect.js +13 -0
- package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
- package/dist/turso/tursoLocalQuerierPool.js +6 -5
- package/dist/turso/tursoQuerierPool.d.ts +15 -30
- package/dist/turso/tursoQuerierPool.js +13 -23
- package/dist/turso/tursoSessionQuerier.d.ts +57 -0
- package/dist/turso/tursoSessionQuerier.js +50 -0
- package/dist/type/entity.d.ts +37 -62
- package/dist/type/migration.d.ts +11 -40
- package/dist/type/queryRaw.d.ts +8 -0
- package/dist/type/queryRaw.js +11 -0
- package/dist/util/ddlExpression.util.d.ts +5 -3
- package/dist/util/ddlExpression.util.js +19 -12
- package/dist/util/raw.d.ts +6 -1
- package/dist/util/raw.js +11 -8
- package/dist/util/sqlLiteral.js +5 -3
- package/dist/util/wideNumber.d.ts +2 -2
- package/dist/util/wideNumber.js +2 -2
- package/package.json +2 -2
- package/dist/migrate/schemaGeneratorAsync.d.ts +0 -7
- package/dist/migrate/schemaGeneratorAsync.js +0 -12
- package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
- package/dist/sqlite/hranaQuerierPool.js +0 -26
- package/dist/turso/tursoLocalQuerier.d.ts +0 -24
- package/dist/turso/tursoLocalQuerier.js +0 -20
|
@@ -1,12 +1,3 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
/**
|
|
3
|
-
* How every local SQLite connection opens. WAL, so a reader does not wait on the writer, and
|
|
4
|
-
* `foreign_keys`, which SQLite ships off per connection for backward compatibility: without it the
|
|
5
|
-
* constraints uql's own DDL declares are decorative - a declared `onDelete: 'CASCADE'` silently does
|
|
6
|
-
* nothing and a dangling reference is accepted.
|
|
7
|
-
*/
|
|
8
|
-
export declare const SQLITE_PRAGMAS: readonly ['journal_mode = WAL', 'foreign_keys = ON'];
|
|
1
|
+
import type { SqliteDatabase } from './sqliteQuerier.js';
|
|
9
2
|
/** Runs {@link SQLITE_PRAGMAS} through a driver's own statements, whether it answers now or later. */
|
|
10
|
-
export declare function applySqlitePragmas(db:
|
|
11
|
-
prepare(sql: string): SqlitePreparedStatement | Promise<SqlitePreparedStatement>;
|
|
12
|
-
}): Promise<void>;
|
|
3
|
+
export declare function applySqlitePragmas(db: Pick<SqliteDatabase, 'prepare'>): Promise<void>;
|
|
@@ -4,7 +4,7 @@
|
|
|
4
4
|
* constraints uql's own DDL declares are decorative - a declared `onDelete: 'CASCADE'` silently does
|
|
5
5
|
* nothing and a dangling reference is accepted.
|
|
6
6
|
*/
|
|
7
|
-
|
|
7
|
+
const SQLITE_PRAGMAS = ['journal_mode = WAL', 'foreign_keys = ON'];
|
|
8
8
|
/** Runs {@link SQLITE_PRAGMAS} through a driver's own statements, whether it answers now or later. */
|
|
9
9
|
export async function applySqlitePragmas(db) {
|
|
10
10
|
for (const pragma of SQLITE_PRAGMAS) {
|
|
@@ -1,20 +1,39 @@
|
|
|
1
|
-
import type { ExtraOptions } from '../type/index.js';
|
|
2
|
-
import {
|
|
1
|
+
import type { ExtraOptions, RawRow } from '../type/index.js';
|
|
2
|
+
import { AbstractSqliteQuerier, type SqliteBindValue } from './abstractSqliteQuerier.js';
|
|
3
3
|
import type { SqliteDialect } from './sqliteDialect.js';
|
|
4
|
+
/** What uql reads of a driver's `run()`: the row count. An inserted id comes back through `RETURNING`. */
|
|
5
|
+
export type SqliteRunResult = {
|
|
6
|
+
changes: number;
|
|
7
|
+
};
|
|
8
|
+
/** A prepared statement with better-sqlite3 semantics, answering at once or with a promise. */
|
|
9
|
+
export type SqlitePreparedStatement = {
|
|
10
|
+
/** True for any statement returning rows, including one with a `RETURNING` clause. */
|
|
11
|
+
readonly reader: boolean;
|
|
12
|
+
all(...values: SqliteBindValue[]): unknown[] | Promise<unknown[]>;
|
|
13
|
+
run(...values: SqliteBindValue[]): SqliteRunResult | Promise<SqliteRunResult>;
|
|
14
|
+
iterate(...values: SqliteBindValue[]): Iterable<unknown> | AsyncIterable<unknown>;
|
|
15
|
+
};
|
|
4
16
|
/**
|
|
5
|
-
*
|
|
6
|
-
*
|
|
7
|
-
* `bun:sqlite` is adapted to it by {@link Sqlite3QuerierPool}.
|
|
17
|
+
* A SQLite driver that prepares statements. `better-sqlite3` and the embedded Turso engine satisfy it
|
|
18
|
+
* as they are, `bun:sqlite` and `node:sqlite` through their adapters.
|
|
8
19
|
*/
|
|
9
20
|
export type SqliteDatabase = {
|
|
10
|
-
prepare(sql: string): SqlitePreparedStatement
|
|
11
|
-
/** Installs a loadable extension (`sqlite-vec`, ...) into this connection. */
|
|
12
|
-
loadExtension(path: string): void;
|
|
21
|
+
prepare(sql: string): SqlitePreparedStatement | Promise<SqlitePreparedStatement>;
|
|
13
22
|
close(): unknown;
|
|
14
23
|
};
|
|
15
|
-
|
|
24
|
+
/**
|
|
25
|
+
* Querier for the SQLite drivers that prepare statements: `better-sqlite3`, `bun:sqlite`, `node:sqlite`
|
|
26
|
+
* and the embedded Turso engine. They differ only in whether preparing and stepping answer at once or
|
|
27
|
+
* with a promise, which `await` and `for await` absorb.
|
|
28
|
+
*/
|
|
29
|
+
export declare class SqliteQuerier extends AbstractSqliteQuerier {
|
|
16
30
|
readonly db: SqliteDatabase;
|
|
17
31
|
readonly extra?: ExtraOptions | undefined;
|
|
18
32
|
constructor(db: SqliteDatabase, dialect: SqliteDialect, extra?: ExtraOptions | undefined);
|
|
19
|
-
|
|
33
|
+
/** `reader` picks the call: `run()` would discard the rows of a statement that reads, RETURNING included. */
|
|
34
|
+
protected execute(query: string, values?: unknown[]): Promise<{
|
|
35
|
+
rows: RawRow[];
|
|
36
|
+
changes: number;
|
|
37
|
+
}>;
|
|
38
|
+
internalStream<T>(query: string, values?: unknown[]): AsyncGenerator<Awaited<T>, void, unknown>;
|
|
20
39
|
}
|
|
@@ -1,5 +1,11 @@
|
|
|
1
|
-
import {
|
|
2
|
-
|
|
1
|
+
import { decodeBigInts } from '../util/wideNumber.js';
|
|
2
|
+
import { AbstractSqliteQuerier } from './abstractSqliteQuerier.js';
|
|
3
|
+
/**
|
|
4
|
+
* Querier for the SQLite drivers that prepare statements: `better-sqlite3`, `bun:sqlite`, `node:sqlite`
|
|
5
|
+
* and the embedded Turso engine. They differ only in whether preparing and stepping answer at once or
|
|
6
|
+
* with a promise, which `await` and `for await` absorb.
|
|
7
|
+
*/
|
|
8
|
+
export class SqliteQuerier extends AbstractSqliteQuerier {
|
|
3
9
|
db;
|
|
4
10
|
extra;
|
|
5
11
|
constructor(db, dialect, extra) {
|
|
@@ -7,7 +13,23 @@ export class SqliteQuerier extends PreparedSqliteQuerier {
|
|
|
7
13
|
this.db = db;
|
|
8
14
|
this.extra = extra;
|
|
9
15
|
}
|
|
10
|
-
|
|
11
|
-
|
|
16
|
+
/** `reader` picks the call: `run()` would discard the rows of a statement that reads, RETURNING included. */
|
|
17
|
+
async execute(query, values) {
|
|
18
|
+
const stmt = await this.db.prepare(query);
|
|
19
|
+
const bound = toBindValues(values);
|
|
20
|
+
if (stmt.reader) {
|
|
21
|
+
return { rows: (await stmt.all(...bound)), changes: 0 };
|
|
22
|
+
}
|
|
23
|
+
return { rows: [], changes: (await stmt.run(...bound)).changes };
|
|
12
24
|
}
|
|
25
|
+
async *internalStream(query, values) {
|
|
26
|
+
const stmt = await this.db.prepare(query);
|
|
27
|
+
for await (const row of stmt.iterate(...toBindValues(values))) {
|
|
28
|
+
yield decodeBigInts(row);
|
|
29
|
+
}
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
/** Bound parameters reach a driver as `unknown[]` from the compiler; every driver types them narrowly. */
|
|
33
|
+
function toBindValues(values) {
|
|
34
|
+
return (values ?? []);
|
|
13
35
|
}
|
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
import type { Options } from 'better-sqlite3';
|
|
2
2
|
import type { ExtraOptions } from '../type/index.js';
|
|
3
|
-
import { AbstractLocalSqliteQuerierPool, type LocalSqlitePoolOptions } from './localSqliteQuerierPool.js';
|
|
4
|
-
import type { SqliteDatabase } from './sqliteQuerier.js';
|
|
3
|
+
import { AbstractLocalSqliteQuerierPool, type LocalSqliteDatabase, type LocalSqlitePoolOptions } from './localSqliteQuerierPool.js';
|
|
5
4
|
/** Driver options, plus the loadable extensions to install on the connection. */
|
|
6
5
|
export type Sqlite3PoolOptions = Options & LocalSqlitePoolOptions;
|
|
7
6
|
/**
|
|
@@ -11,5 +10,10 @@ export type Sqlite3PoolOptions = Options & LocalSqlitePoolOptions;
|
|
|
11
10
|
export declare class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool<Sqlite3PoolOptions> {
|
|
12
11
|
readonly filename: string | Buffer;
|
|
13
12
|
constructor(filename?: string | Buffer, opts?: Sqlite3PoolOptions, extra?: ExtraOptions);
|
|
14
|
-
|
|
13
|
+
/**
|
|
14
|
+
* Both drivers read integers as `bigint`, which the querier decodes exactly past 2^53. `bun:sqlite`
|
|
15
|
+
* rejects option keys it does not know, so `extensions` is stripped out, and opens only a path, so a
|
|
16
|
+
* serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
|
|
17
|
+
*/
|
|
18
|
+
protected createDb(): Promise<LocalSqliteDatabase>;
|
|
15
19
|
}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { AbstractLocalSqliteQuerierPool } from './localSqliteQuerierPool.js';
|
|
1
|
+
import { AbstractLocalSqliteQuerierPool, } from './localSqliteQuerierPool.js';
|
|
3
2
|
/**
|
|
4
3
|
* Pool for `better-sqlite3`, or `bun:sqlite` when running under Bun - the same file, through whichever
|
|
5
4
|
* driver the runtime provides.
|
|
@@ -10,17 +9,22 @@ export class Sqlite3QuerierPool extends AbstractLocalSqliteQuerierPool {
|
|
|
10
9
|
super(opts, extra);
|
|
11
10
|
this.filename = filename;
|
|
12
11
|
}
|
|
12
|
+
/**
|
|
13
|
+
* Both drivers read integers as `bigint`, which the querier decodes exactly past 2^53. `bun:sqlite`
|
|
14
|
+
* rejects option keys it does not know, so `extensions` is stripped out, and opens only a path, so a
|
|
15
|
+
* serialized database - which better-sqlite3 takes as its filename - is deserialized there instead.
|
|
16
|
+
*/
|
|
13
17
|
async createDb() {
|
|
14
|
-
// `bun:sqlite` rejects option keys it does not know, and rejects an options object carrying no
|
|
15
|
-
// open flags, so `extensions` is stripped out and what remains of it collapses back to nothing.
|
|
16
18
|
const { extensions, ...driverOpts } = this.opts ?? {};
|
|
17
|
-
const opts = hasKeys(driverOpts) ? driverOpts : undefined;
|
|
18
19
|
if (typeof Bun !== 'undefined') {
|
|
19
|
-
const { Database
|
|
20
|
+
const { Database } = await import('bun:sqlite');
|
|
20
21
|
const { adaptBunSqlite } = await import('./bunSqliteAdapter.bun.js');
|
|
21
|
-
|
|
22
|
+
const bunOpts = { ...driverOpts, safeIntegers: true };
|
|
23
|
+
return adaptBunSqlite(typeof this.filename === 'string'
|
|
24
|
+
? new Database(this.filename, bunOpts)
|
|
25
|
+
: Database.deserialize(this.filename, bunOpts));
|
|
22
26
|
}
|
|
23
27
|
const { default: BetterSqlite3 } = await import('better-sqlite3');
|
|
24
|
-
return new BetterSqlite3(this.filename,
|
|
28
|
+
return new BetterSqlite3(this.filename, driverOpts).defaultSafeIntegers(true);
|
|
25
29
|
}
|
|
26
30
|
}
|
package/dist/turso/index.d.ts
CHANGED
package/dist/turso/index.js
CHANGED
package/dist/turso/local.d.ts
CHANGED
package/dist/turso/local.js
CHANGED
|
@@ -1,17 +1,12 @@
|
|
|
1
1
|
import { LibsqlDialect } from '../libsql/libsqlDialect.js';
|
|
2
|
-
import type { VectorDistance, VectorMetric } from '../type/index.js';
|
|
3
2
|
/**
|
|
4
|
-
* SQLite Dialect specialization for Turso
|
|
3
|
+
* SQLite Dialect specialization for Turso Cloud: what every Turso Cloud database accepts, since one runs
|
|
4
|
+
* libSQL unless it was created as `tursodb`, which runs the Rust engine. libSQL's vector functions and
|
|
5
|
+
* argument cap hold on both, and so does the Rust engine's missing `ORDER BY` inside an aggregate.
|
|
5
6
|
*
|
|
6
|
-
* @remarks
|
|
7
|
-
* `TursoLocalQuerierPool` (embedded, `@tursodatabase/database`). Built on `LibsqlDialect` because
|
|
8
|
-
* Turso is that engine's successor and keeps its SQL surface, vector functions included. Imports
|
|
9
|
-
* nothing vendor-specific, so the embedded entry point cannot pull native code into an edge bundle
|
|
10
|
-
* through it.
|
|
7
|
+
* @remarks Imports nothing vendor-specific, so no entry point can pull a driver in through it.
|
|
11
8
|
*/
|
|
12
9
|
export declare class TursoDialect extends LibsqlDialect {
|
|
13
|
-
/** The Rust engine adds a dot-product distance to libSQL's cosine and L2. */
|
|
14
|
-
readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
|
|
15
10
|
/** The Rust engine takes no `ORDER BY` inside an aggregate. */
|
|
16
11
|
protected readonly orderedAggregates = false;
|
|
17
12
|
}
|
|
@@ -1,20 +1,12 @@
|
|
|
1
1
|
import { LibsqlDialect } from '../libsql/libsqlDialect.js';
|
|
2
2
|
/**
|
|
3
|
-
* SQLite Dialect specialization for Turso
|
|
3
|
+
* SQLite Dialect specialization for Turso Cloud: what every Turso Cloud database accepts, since one runs
|
|
4
|
+
* libSQL unless it was created as `tursodb`, which runs the Rust engine. libSQL's vector functions and
|
|
5
|
+
* argument cap hold on both, and so does the Rust engine's missing `ORDER BY` inside an aggregate.
|
|
4
6
|
*
|
|
5
|
-
* @remarks
|
|
6
|
-
* `TursoLocalQuerierPool` (embedded, `@tursodatabase/database`). Built on `LibsqlDialect` because
|
|
7
|
-
* Turso is that engine's successor and keeps its SQL surface, vector functions included. Imports
|
|
8
|
-
* nothing vendor-specific, so the embedded entry point cannot pull native code into an edge bundle
|
|
9
|
-
* through it.
|
|
7
|
+
* @remarks Imports nothing vendor-specific, so no entry point can pull a driver in through it.
|
|
10
8
|
*/
|
|
11
9
|
export class TursoDialect extends LibsqlDialect {
|
|
12
|
-
/** The Rust engine adds a dot-product distance to libSQL's cosine and L2. */
|
|
13
|
-
vectorMetrics = new Map([
|
|
14
|
-
['cosine', { fn: 'vector_distance_cos' }],
|
|
15
|
-
['l2', { fn: 'vector_distance_l2' }],
|
|
16
|
-
['inner', { fn: 'vector_distance_dot' }],
|
|
17
|
-
]);
|
|
18
10
|
/** The Rust engine takes no `ORDER BY` inside an aggregate. */
|
|
19
11
|
orderedAggregates = false;
|
|
20
12
|
}
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import type { VectorDistance, VectorMetric } from '../type/index.js';
|
|
2
|
+
import { TursoDialect } from './tursoDialect.js';
|
|
3
|
+
/**
|
|
4
|
+
* SQLite Dialect specialization for the embedded Turso engine, the Rust engine alone: it adds a
|
|
5
|
+
* dot-product distance to libSQL's cosine and L2, and caps no function call.
|
|
6
|
+
*/
|
|
7
|
+
export declare class TursoLocalDialect extends TursoDialect {
|
|
8
|
+
readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
|
|
9
|
+
readonly maxFunctionArgs: number;
|
|
10
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { TursoDialect } from './tursoDialect.js';
|
|
2
|
+
/**
|
|
3
|
+
* SQLite Dialect specialization for the embedded Turso engine, the Rust engine alone: it adds a
|
|
4
|
+
* dot-product distance to libSQL's cosine and L2, and caps no function call.
|
|
5
|
+
*/
|
|
6
|
+
export class TursoLocalDialect extends TursoDialect {
|
|
7
|
+
vectorMetrics = new Map([
|
|
8
|
+
['cosine', { fn: 'vector_distance_cos' }],
|
|
9
|
+
['l2', { fn: 'vector_distance_l2' }],
|
|
10
|
+
['inner', { fn: 'vector_distance_dot' }],
|
|
11
|
+
]);
|
|
12
|
+
maxFunctionArgs = Infinity;
|
|
13
|
+
}
|
|
@@ -1,15 +1,10 @@
|
|
|
1
|
+
import type { connect } from '@tursodatabase/database';
|
|
1
2
|
import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
|
|
3
|
+
import { type SqliteDatabase, SqliteQuerier } from '../sqlite/sqliteQuerier.js';
|
|
2
4
|
import type { ExtraOptions } from '../type/index.js';
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
export type TursoLocalOptions = {
|
|
7
|
-
readonly?: boolean;
|
|
8
|
-
fileMustExist?: boolean;
|
|
9
|
-
timeout?: number;
|
|
10
|
-
defaultQueryTimeout?: number;
|
|
11
|
-
tracing?: 'info' | 'debug' | 'trace';
|
|
12
|
-
};
|
|
5
|
+
import { TursoLocalDialect } from './tursoLocalDialect.js';
|
|
6
|
+
/** The engine's own options: `readonly`, `timeout`, `encryption`, `experimental` and the rest. */
|
|
7
|
+
export type TursoLocalOptions = NonNullable<Parameters<typeof connect>[1]>;
|
|
13
8
|
/**
|
|
14
9
|
* Pool for the embedded Turso engine (`@tursodatabase/database`), the Rust rewrite of SQLite.
|
|
15
10
|
*
|
|
@@ -17,10 +12,10 @@ export type TursoLocalOptions = {
|
|
|
17
12
|
* package ships native binaries that do not resolve on edge runtimes. Separating them guarantees a
|
|
18
13
|
* bundle targeting Workers never reaches the native import.
|
|
19
14
|
*/
|
|
20
|
-
export declare class TursoLocalQuerierPool extends AbstractSharedHandleQuerierPool<
|
|
15
|
+
export declare class TursoLocalQuerierPool extends AbstractSharedHandleQuerierPool<SqliteDatabase, SqliteQuerier, TursoLocalDialect> {
|
|
21
16
|
readonly filename: string;
|
|
22
17
|
readonly opts?: TursoLocalOptions | undefined;
|
|
23
18
|
constructor(filename?: string, opts?: TursoLocalOptions | undefined, extra?: ExtraOptions);
|
|
24
|
-
protected openDb(): Promise<
|
|
25
|
-
protected buildQuerier(db:
|
|
19
|
+
protected openDb(): Promise<SqliteDatabase>;
|
|
20
|
+
protected buildQuerier(db: SqliteDatabase): SqliteQuerier;
|
|
26
21
|
}
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
|
|
2
2
|
import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
|
|
3
3
|
import { applySqlitePragmas } from '../sqlite/sqlitePragmas.js';
|
|
4
|
-
import {
|
|
5
|
-
import {
|
|
4
|
+
import { SqliteQuerier } from '../sqlite/sqliteQuerier.js';
|
|
5
|
+
import { TursoLocalDialect } from './tursoLocalDialect.js';
|
|
6
6
|
/**
|
|
7
7
|
* Pool for the embedded Turso engine (`@tursodatabase/database`), the Rust rewrite of SQLite.
|
|
8
8
|
*
|
|
@@ -14,18 +14,19 @@ export class TursoLocalQuerierPool extends AbstractSharedHandleQuerierPool {
|
|
|
14
14
|
filename;
|
|
15
15
|
opts;
|
|
16
16
|
constructor(filename = ':memory:', opts, extra) {
|
|
17
|
-
super(new
|
|
17
|
+
super(new TursoLocalDialect(dialectOptionsFrom(extra)), extra);
|
|
18
18
|
this.filename = filename;
|
|
19
19
|
this.opts = opts;
|
|
20
20
|
}
|
|
21
21
|
async openDb() {
|
|
22
22
|
const { connect } = await import('@tursodatabase/database');
|
|
23
|
-
// Annotated rather than cast, so the structural contract is checked against the real driver.
|
|
24
23
|
const db = await connect(this.filename, this.opts);
|
|
24
|
+
// Integers as `bigint`, which the querier decodes exactly past 2^53.
|
|
25
|
+
db.defaultSafeIntegers(true);
|
|
25
26
|
await applySqlitePragmas(db);
|
|
26
27
|
return db;
|
|
27
28
|
}
|
|
28
29
|
buildQuerier(db) {
|
|
29
|
-
return new
|
|
30
|
+
return new SqliteQuerier(db, this.dialect, this.extra);
|
|
30
31
|
}
|
|
31
32
|
}
|
|
@@ -1,37 +1,22 @@
|
|
|
1
|
-
import type {
|
|
2
|
-
import {
|
|
1
|
+
import type { Config } from '@tursodatabase/serverless';
|
|
2
|
+
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
3
3
|
import type { ExtraOptions } from '../type/index.js';
|
|
4
4
|
import { TursoDialect } from './tursoDialect.js';
|
|
5
|
+
import { TursoSessionQuerier } from './tursoSessionQuerier.js';
|
|
6
|
+
/** Connection settings for Turso Cloud: `@tursodatabase/serverless`'s own, `requestHeaders` included. */
|
|
7
|
+
export type TursoConfig = Config;
|
|
5
8
|
/**
|
|
6
|
-
*
|
|
9
|
+
* Pool for Turso Cloud, over `@tursodatabase/serverless`, which speaks HTTP through `fetch()`.
|
|
7
10
|
*
|
|
8
|
-
* @remarks
|
|
9
|
-
*
|
|
11
|
+
* @remarks Every querier opens a session of its own, one server stream, so queriers never wait on each
|
|
12
|
+
* other and a transaction spans one stream. The driver is imported on first use, so a pool built at
|
|
13
|
+
* module scope in a Worker loads nothing until a request needs it. A client built with
|
|
14
|
+
* `@libsql/client/web` goes to `LibsqlQuerierPool` instead.
|
|
10
15
|
*/
|
|
11
|
-
export
|
|
12
|
-
/** `libsql://<db>.turso.io` or `https://<db>.turso.io`. */
|
|
13
|
-
url: string;
|
|
14
|
-
authToken?: string;
|
|
15
|
-
remoteEncryptionKey?: string;
|
|
16
|
-
/** Extra HTTP headers attached to every request, e.g. for routing through a gateway. */
|
|
17
|
-
requestHeaders?: Record<string, string>;
|
|
18
|
-
};
|
|
19
|
-
/**
|
|
20
|
-
* Pool for remote Turso Cloud databases, driven by `@tursodatabase/serverless/compat`.
|
|
21
|
-
*
|
|
22
|
-
* @remarks The compat entry point is required rather than the native one: the native
|
|
23
|
-
* `conn.transaction()` takes a callback, which cannot satisfy the explicit
|
|
24
|
-
* `beginTransaction`/`commitTransaction` contract, and issuing a bare `BEGIN` is not an option
|
|
25
|
-
* because over plain HTTP consecutive requests need not share a connection. Compat's session-backed
|
|
26
|
-
* transaction handle is the piece that makes it work.
|
|
27
|
-
*/
|
|
28
|
-
export declare class TursoQuerierPool extends AbstractHranaQuerierPool<TursoDialect> {
|
|
29
|
-
protected readonly ownsClient: boolean;
|
|
16
|
+
export declare class TursoQuerierPool extends AbstractSqlQuerierPool<TursoSessionQuerier, TursoDialect> {
|
|
30
17
|
private readonly conf;
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
constructor(conf: TursoConfig | HranaClient, extra?: ExtraOptions);
|
|
36
|
-
protected openClient(): Promise<HranaClient>;
|
|
18
|
+
constructor(conf: TursoConfig, extra?: ExtraOptions);
|
|
19
|
+
getQuerier(): Promise<TursoSessionQuerier>;
|
|
20
|
+
/** Nothing to close: every querier closes its own session. */
|
|
21
|
+
end(): Promise<void>;
|
|
37
22
|
}
|
|
@@ -1,35 +1,25 @@
|
|
|
1
1
|
import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
|
|
2
|
-
import {
|
|
2
|
+
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
3
3
|
import { TursoDialect } from './tursoDialect.js';
|
|
4
|
-
|
|
5
|
-
return typeof conf.execute === 'function';
|
|
6
|
-
}
|
|
4
|
+
import { TursoSessionQuerier } from './tursoSessionQuerier.js';
|
|
7
5
|
/**
|
|
8
|
-
* Pool for
|
|
6
|
+
* Pool for Turso Cloud, over `@tursodatabase/serverless`, which speaks HTTP through `fetch()`.
|
|
9
7
|
*
|
|
10
|
-
* @remarks
|
|
11
|
-
*
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
* transaction handle is the piece that makes it work.
|
|
8
|
+
* @remarks Every querier opens a session of its own, one server stream, so queriers never wait on each
|
|
9
|
+
* other and a transaction spans one stream. The driver is imported on first use, so a pool built at
|
|
10
|
+
* module scope in a Worker loads nothing until a request needs it. A client built with
|
|
11
|
+
* `@libsql/client/web` goes to `LibsqlQuerierPool` instead.
|
|
15
12
|
*/
|
|
16
|
-
export class TursoQuerierPool extends
|
|
17
|
-
ownsClient;
|
|
13
|
+
export class TursoQuerierPool extends AbstractSqlQuerierPool {
|
|
18
14
|
conf;
|
|
19
|
-
/**
|
|
20
|
-
* Accepts either connection settings or an already-built client. The latter covers any driver
|
|
21
|
-
* with the same shape: `@libsql/client/web`, `@libsql/client-wasm`, or a test double.
|
|
22
|
-
*/
|
|
23
15
|
constructor(conf, extra) {
|
|
24
16
|
super(new TursoDialect(dialectOptionsFrom(extra)), extra);
|
|
25
17
|
this.conf = conf;
|
|
26
|
-
this.ownsClient = !isClient(conf);
|
|
27
18
|
}
|
|
28
|
-
async
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
}
|
|
32
|
-
const { createClient } = await import('@tursodatabase/serverless/compat');
|
|
33
|
-
return createClient(this.conf);
|
|
19
|
+
async getQuerier() {
|
|
20
|
+
const { Session } = await import('@tursodatabase/serverless');
|
|
21
|
+
return new TursoSessionQuerier(new Session(this.conf), this.dialect, this.extra);
|
|
34
22
|
}
|
|
23
|
+
/** Nothing to close: every querier closes its own session. */
|
|
24
|
+
async end() { }
|
|
35
25
|
}
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
import { AbstractSqliteQuerier, type SqliteBindValue } from '../sqlite/abstractSqliteQuerier.js';
|
|
2
|
+
import type { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
3
|
+
import type { ExtraOptions, RawRow } from '../type/index.js';
|
|
4
|
+
/** What a statement comes back with on a session: each row an array of its values, named by `columns`. */
|
|
5
|
+
export type TursoResultSet = {
|
|
6
|
+
columns: string[];
|
|
7
|
+
rows: unknown[][];
|
|
8
|
+
rowsAffected: number;
|
|
9
|
+
};
|
|
10
|
+
/** A value as the server encodes it on a cursor, which the driver's `decodeValue` reads. */
|
|
11
|
+
export type TursoValue = {
|
|
12
|
+
type: 'null' | 'integer' | 'float' | 'text' | 'blob';
|
|
13
|
+
value?: string | number;
|
|
14
|
+
base64?: string;
|
|
15
|
+
};
|
|
16
|
+
/** One entry of a statement's cursor: its columns, a row, the end of a step, or an error. */
|
|
17
|
+
export type TursoCursorEntry = {
|
|
18
|
+
type: 'step_begin' | 'step_end' | 'step_error' | 'row' | 'error';
|
|
19
|
+
cols?: {
|
|
20
|
+
name: string;
|
|
21
|
+
}[];
|
|
22
|
+
row?: TursoValue[];
|
|
23
|
+
error?: {
|
|
24
|
+
message: string;
|
|
25
|
+
code?: string;
|
|
26
|
+
};
|
|
27
|
+
};
|
|
28
|
+
/**
|
|
29
|
+
* The part of a `@tursodatabase/serverless` `Session` the querier uses: one server stream, which every
|
|
30
|
+
* statement on it shares, since each request carries the baton of the response before it.
|
|
31
|
+
*/
|
|
32
|
+
export type TursoSession = {
|
|
33
|
+
execute(sql: string, args: SqliteBindValue[], safeIntegers: boolean): Promise<TursoResultSet>;
|
|
34
|
+
executeRaw(sql: string, args: SqliteBindValue[]): Promise<{
|
|
35
|
+
entries: AsyncIterable<TursoCursorEntry>;
|
|
36
|
+
}>;
|
|
37
|
+
close(): Promise<void>;
|
|
38
|
+
};
|
|
39
|
+
/**
|
|
40
|
+
* Querier for Turso Cloud on a session of its own.
|
|
41
|
+
*
|
|
42
|
+
* @remarks The stream is what makes a transaction plain `BEGIN`/`COMMIT`, left to the base class, and
|
|
43
|
+
* what `release` closes. A row comes back an array carrying its column names as hidden properties, so it
|
|
44
|
+
* is rebuilt as the object every querier answers.
|
|
45
|
+
*/
|
|
46
|
+
export declare class TursoSessionQuerier extends AbstractSqliteQuerier {
|
|
47
|
+
readonly session: TursoSession;
|
|
48
|
+
readonly extra?: ExtraOptions | undefined;
|
|
49
|
+
constructor(session: TursoSession, dialect: SqliteDialect, extra?: ExtraOptions | undefined);
|
|
50
|
+
protected execute(query: string, values?: unknown[]): Promise<{
|
|
51
|
+
rows: RawRow[];
|
|
52
|
+
changes: number;
|
|
53
|
+
}>;
|
|
54
|
+
/** Row by row off the statement's cursor, as the server steps it, each decoded as `execute` decodes one. */
|
|
55
|
+
internalStream<T>(query: string, values?: unknown[]): AsyncGenerator<Awaited<T>, void, unknown>;
|
|
56
|
+
internalRelease(): Promise<void>;
|
|
57
|
+
}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { AbstractSqliteQuerier } from '../sqlite/abstractSqliteQuerier.js';
|
|
2
|
+
import { decodeBigInts } from '../util/wideNumber.js';
|
|
3
|
+
/**
|
|
4
|
+
* Querier for Turso Cloud on a session of its own.
|
|
5
|
+
*
|
|
6
|
+
* @remarks The stream is what makes a transaction plain `BEGIN`/`COMMIT`, left to the base class, and
|
|
7
|
+
* what `release` closes. A row comes back an array carrying its column names as hidden properties, so it
|
|
8
|
+
* is rebuilt as the object every querier answers.
|
|
9
|
+
*/
|
|
10
|
+
export class TursoSessionQuerier extends AbstractSqliteQuerier {
|
|
11
|
+
session;
|
|
12
|
+
extra;
|
|
13
|
+
constructor(session, dialect, extra) {
|
|
14
|
+
super(dialect, extra);
|
|
15
|
+
this.session = session;
|
|
16
|
+
this.extra = extra;
|
|
17
|
+
}
|
|
18
|
+
async execute(query, values) {
|
|
19
|
+
const { columns, rows, rowsAffected } = await this.session.execute(query, toBindValues(values), true);
|
|
20
|
+
return { rows: rows.map((row) => toRow(columns, row)), changes: rowsAffected };
|
|
21
|
+
}
|
|
22
|
+
/** Row by row off the statement's cursor, as the server steps it, each decoded as `execute` decodes one. */
|
|
23
|
+
async *internalStream(query, values) {
|
|
24
|
+
const { DatabaseError, decodeValue } = await import('@tursodatabase/serverless');
|
|
25
|
+
const { entries } = await this.session.executeRaw(query, toBindValues(values));
|
|
26
|
+
let columns = [];
|
|
27
|
+
for await (const entry of entries) {
|
|
28
|
+
if (entry.type === 'step_error' || entry.type === 'error') {
|
|
29
|
+
throw new DatabaseError(entry.error?.message ?? 'SQL execution failed', entry.error?.code);
|
|
30
|
+
}
|
|
31
|
+
if (entry.cols) {
|
|
32
|
+
columns = entry.cols.map(({ name }) => name);
|
|
33
|
+
}
|
|
34
|
+
if (entry.row) {
|
|
35
|
+
yield decodeBigInts(toRow(columns, entry.row.map((value) => decodeValue(value, true))));
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
async internalRelease() {
|
|
40
|
+
await this.session.close();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
/** A row the driver answers as an array of values, named by the statement's columns. */
|
|
44
|
+
function toRow(columns, values) {
|
|
45
|
+
return Object.fromEntries(columns.map((column, at) => [column, values[at]]));
|
|
46
|
+
}
|
|
47
|
+
/** Bound parameters reach a driver as `unknown[]` from the compiler; a session binds them as they are. */
|
|
48
|
+
function toBindValues(values) {
|
|
49
|
+
return (values ?? []);
|
|
50
|
+
}
|