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.
Files changed (104) hide show
  1. package/dist/bunSql/bunSql.util.d.ts +15 -15
  2. package/dist/bunSql/bunSql.util.js +22 -35
  3. package/dist/bunSql/bunSqlQuerier.d.ts +2 -2
  4. package/dist/bunSql/bunSqlQuerier.js +3 -3
  5. package/dist/bunSql/bunSqlQuerierPool.d.ts +1 -13
  6. package/dist/bunSql/bunSqlQuerierPool.js +3 -34
  7. package/dist/d1/d1Querier.d.ts +12 -4
  8. package/dist/d1/d1Querier.js +6 -11
  9. package/dist/d1/d1QuerierPool.d.ts +7 -3
  10. package/dist/d1/d1QuerierPool.js +5 -3
  11. package/dist/entity/decorator/entity.d.ts +5 -9
  12. package/dist/entity/decorator/entity.js +3 -7
  13. package/dist/entity/metadata/definition.d.ts +2 -2
  14. package/dist/entity/metadata/definition.js +13 -22
  15. package/dist/libsql/libsqlDialect.d.ts +1 -1
  16. package/dist/libsql/libsqlDialect.js +1 -1
  17. package/dist/libsql/libsqlQuerierPool.d.ts +18 -9
  18. package/dist/libsql/libsqlQuerierPool.js +32 -20
  19. package/dist/migrate/builder/expressions.js +1 -15
  20. package/dist/migrate/builder/migrationBuilder.d.ts +6 -28
  21. package/dist/migrate/builder/migrationBuilder.js +9 -83
  22. package/dist/migrate/builder/types.d.ts +14 -24
  23. package/dist/migrate/cli.d.ts +1 -6
  24. package/dist/migrate/cli.js +3 -10
  25. package/dist/migrate/codegen/index.d.ts +1 -1
  26. package/dist/migrate/codegen/index.js +1 -1
  27. package/dist/migrate/codegen/indexDecoratorSource.d.ts +1 -1
  28. package/dist/migrate/codegen/indexDecoratorSource.js +4 -8
  29. package/dist/migrate/codegen/migrationFile.d.ts +9 -5
  30. package/dist/migrate/codegen/migrationFile.js +2 -3
  31. package/dist/migrate/ddl/indexDdl.d.ts +4 -2
  32. package/dist/migrate/ddl/indexDdl.js +16 -15
  33. package/dist/migrate/generator/mongoCommand.d.ts +9 -9
  34. package/dist/migrate/generator/mongoCommand.js +1 -1
  35. package/dist/migrate/generator/mongoSchemaGenerator.d.ts +21 -26
  36. package/dist/migrate/generator/mongoSchemaGenerator.js +103 -80
  37. package/dist/migrate/index.d.ts +1 -1
  38. package/dist/migrate/index.js +1 -1
  39. package/dist/migrate/indexPredicate.d.ts +8 -0
  40. package/dist/migrate/indexPredicate.js +52 -0
  41. package/dist/migrate/migrationTarget.d.ts +23 -0
  42. package/dist/migrate/migrationTarget.js +48 -0
  43. package/dist/migrate/migrator.d.ts +17 -45
  44. package/dist/migrate/migrator.js +80 -179
  45. package/dist/migrate/schemaGenerator.d.ts +12 -13
  46. package/dist/migrate/schemaGenerator.js +43 -9
  47. package/dist/mongo/mongoDialect.d.ts +6 -1
  48. package/dist/querier/abstractSharedHandleQuerierPool.d.ts +5 -5
  49. package/dist/querier/abstractSharedHandleQuerierPool.js +5 -5
  50. package/dist/schema/schemaASTBuilder.d.ts +2 -0
  51. package/dist/schema/schemaASTBuilder.js +9 -22
  52. package/dist/sqlite/abstractSqliteQuerier.d.ts +11 -28
  53. package/dist/sqlite/abstractSqliteQuerier.js +14 -33
  54. package/dist/sqlite/bunSqliteAdapter.bun.d.ts +5 -4
  55. package/dist/sqlite/bunSqliteAdapter.bun.js +1 -1
  56. package/dist/sqlite/hranaQuerier.d.ts +6 -4
  57. package/dist/sqlite/hranaQuerier.js +4 -13
  58. package/dist/sqlite/index.d.ts +0 -1
  59. package/dist/sqlite/index.js +0 -1
  60. package/dist/sqlite/localSqliteQuerierPool.d.ts +14 -5
  61. package/dist/sqlite/nodeSqliteAdapter.d.ts +3 -4
  62. package/dist/sqlite/nodeSqliteAdapter.js +3 -6
  63. package/dist/sqlite/nodeSqliteQuerierPool.d.ts +2 -3
  64. package/dist/sqlite/nodeSqliteQuerierPool.js +3 -1
  65. package/dist/sqlite/sqliteDialect.d.ts +1 -1
  66. package/dist/sqlite/sqliteDialect.js +1 -1
  67. package/dist/sqlite/sqlitePragmas.d.ts +2 -11
  68. package/dist/sqlite/sqlitePragmas.js +1 -1
  69. package/dist/sqlite/sqliteQuerier.d.ts +29 -10
  70. package/dist/sqlite/sqliteQuerier.js +26 -4
  71. package/dist/sqlite/sqliteQuerierPool.d.ts +7 -3
  72. package/dist/sqlite/sqliteQuerierPool.js +12 -8
  73. package/dist/turso/index.d.ts +1 -0
  74. package/dist/turso/index.js +1 -0
  75. package/dist/turso/local.d.ts +1 -1
  76. package/dist/turso/local.js +1 -1
  77. package/dist/turso/tursoDialect.d.ts +4 -9
  78. package/dist/turso/tursoDialect.js +4 -12
  79. package/dist/turso/tursoLocalDialect.d.ts +10 -0
  80. package/dist/turso/tursoLocalDialect.js +13 -0
  81. package/dist/turso/tursoLocalQuerierPool.d.ts +8 -13
  82. package/dist/turso/tursoLocalQuerierPool.js +6 -5
  83. package/dist/turso/tursoQuerierPool.d.ts +15 -30
  84. package/dist/turso/tursoQuerierPool.js +13 -23
  85. package/dist/turso/tursoSessionQuerier.d.ts +57 -0
  86. package/dist/turso/tursoSessionQuerier.js +50 -0
  87. package/dist/type/entity.d.ts +37 -62
  88. package/dist/type/migration.d.ts +11 -40
  89. package/dist/type/queryRaw.d.ts +8 -0
  90. package/dist/type/queryRaw.js +11 -0
  91. package/dist/util/ddlExpression.util.d.ts +5 -3
  92. package/dist/util/ddlExpression.util.js +19 -12
  93. package/dist/util/raw.d.ts +6 -1
  94. package/dist/util/raw.js +11 -8
  95. package/dist/util/sqlLiteral.js +5 -3
  96. package/dist/util/wideNumber.d.ts +2 -2
  97. package/dist/util/wideNumber.js +2 -2
  98. package/package.json +2 -2
  99. package/dist/migrate/schemaGeneratorAsync.d.ts +0 -7
  100. package/dist/migrate/schemaGeneratorAsync.js +0 -12
  101. package/dist/sqlite/hranaQuerierPool.d.ts +0 -20
  102. package/dist/sqlite/hranaQuerierPool.js +0 -26
  103. package/dist/turso/tursoLocalQuerier.d.ts +0 -24
  104. package/dist/turso/tursoLocalQuerier.js +0 -20
@@ -1,12 +1,3 @@
1
- import type { SqlitePreparedStatement } from './abstractSqliteQuerier.js';
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
- export const SQLITE_PRAGMAS = ['journal_mode = WAL', 'foreign_keys = ON'];
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 { PreparedSqliteQuerier, type SqlitePreparedStatement } from './abstractSqliteQuerier.js';
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
- * Structural subset of a synchronous better-sqlite3-compatible driver, declared locally so this
6
- * querier carries no vendor type. A real `better-sqlite3` `Database` satisfies it directly;
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
- export declare class SqliteQuerier extends PreparedSqliteQuerier {
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
- protected prepare(query: string): SqlitePreparedStatement;
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 { PreparedSqliteQuerier } from './abstractSqliteQuerier.js';
2
- export class SqliteQuerier extends PreparedSqliteQuerier {
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
- prepare(query) {
11
- return this.db.prepare(query);
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
- protected createDb(): Promise<SqliteDatabase>;
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 { hasKeys } from '../util/object.util.js';
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: BunDatabase } = await import('bun:sqlite');
20
+ const { Database } = await import('bun:sqlite');
20
21
  const { adaptBunSqlite } = await import('./bunSqliteAdapter.bun.js');
21
- return adaptBunSqlite(new BunDatabase(this.filename, opts));
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, opts);
28
+ return new BetterSqlite3(this.filename, driverOpts).defaultSafeIntegers(true);
25
29
  }
26
30
  }
@@ -1,2 +1,3 @@
1
1
  export * from './tursoDialect.js';
2
2
  export * from './tursoQuerierPool.js';
3
+ export * from './tursoSessionQuerier.js';
@@ -1,2 +1,3 @@
1
1
  export * from './tursoDialect.js';
2
2
  export * from './tursoQuerierPool.js';
3
+ export * from './tursoSessionQuerier.js';
@@ -1,3 +1,3 @@
1
1
  export * from './tursoDialect.js';
2
- export * from './tursoLocalQuerier.js';
2
+ export * from './tursoLocalDialect.js';
3
3
  export * from './tursoLocalQuerierPool.js';
@@ -1,3 +1,3 @@
1
1
  export * from './tursoDialect.js';
2
- export * from './tursoLocalQuerier.js';
2
+ export * from './tursoLocalDialect.js';
3
3
  export * from './tursoLocalQuerierPool.js';
@@ -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 Database.
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 Shared by `TursoQuerierPool` (remote, `@tursodatabase/serverless`) and
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 Database.
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 Shared by `TursoQuerierPool` (remote, `@tursodatabase/serverless`) and
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 { TursoDialect } from './tursoDialect.js';
4
- import { type TursoDatabase, TursoLocalQuerier } from './tursoLocalQuerier.js';
5
- /** Subset of `DatabaseOpts` from `@tursodatabase/database`, declared locally to avoid the coupling. */
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<TursoDatabase, TursoLocalQuerier, TursoDialect> {
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<TursoDatabase>;
25
- protected buildQuerier(db: TursoDatabase): TursoLocalQuerier;
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 { TursoDialect } from './tursoDialect.js';
5
- import { TursoLocalQuerier } from './tursoLocalQuerier.js';
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 TursoDialect(dialectOptionsFrom(extra)), extra);
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 TursoLocalQuerier(db, this.dialect, this.extra);
30
+ return new SqliteQuerier(db, this.dialect, this.extra);
30
31
  }
31
32
  }
@@ -1,37 +1,22 @@
1
- import type { HranaClient } from '../sqlite/hranaQuerier.js';
2
- import { AbstractHranaQuerierPool } from '../sqlite/hranaQuerierPool.js';
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
- * Connection settings for Turso Cloud, mirroring `@tursodatabase/serverless`.
9
+ * Pool for Turso Cloud, over `@tursodatabase/serverless`, which speaks HTTP through `fetch()`.
7
10
  *
8
- * @remarks Declared here rather than imported so this package does not couple its published types
9
- * to a pre-1.0 dependency.
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 type TursoConfig = {
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
- * Accepts either connection settings or an already-built client. The latter covers any driver
33
- * with the same shape: `@libsql/client/web`, `@libsql/client-wasm`, or a test double.
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 { AbstractHranaQuerierPool } from '../sqlite/hranaQuerierPool.js';
2
+ import { AbstractSqlQuerierPool } from '../querier/index.js';
3
3
  import { TursoDialect } from './tursoDialect.js';
4
- function isClient(conf) {
5
- return typeof conf.execute === 'function';
6
- }
4
+ import { TursoSessionQuerier } from './tursoSessionQuerier.js';
7
5
  /**
8
- * Pool for remote Turso Cloud databases, driven by `@tursodatabase/serverless/compat`.
6
+ * Pool for Turso Cloud, over `@tursodatabase/serverless`, which speaks HTTP through `fetch()`.
9
7
  *
10
- * @remarks The compat entry point is required rather than the native one: the native
11
- * `conn.transaction()` takes a callback, which cannot satisfy the explicit
12
- * `beginTransaction`/`commitTransaction` contract, and issuing a bare `BEGIN` is not an option
13
- * because over plain HTTP consecutive requests need not share a connection. Compat's session-backed
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 AbstractHranaQuerierPool {
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 openClient() {
29
- if (isClient(this.conf)) {
30
- return this.conf;
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
+ }