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,14 +1,13 @@
|
|
|
1
1
|
import type { SQL } from 'bun';
|
|
2
2
|
import type { PrimaryKey, RawRow } from '../type/index.js';
|
|
3
|
-
|
|
3
|
+
/** The header a `bun:sql` result carries next to its rows. */
|
|
4
|
+
export type BunSqlHeader = {
|
|
4
5
|
count?: number;
|
|
5
|
-
affectedRows?: number;
|
|
6
|
+
affectedRows?: number | null;
|
|
6
7
|
lastInsertRowid?: PrimaryKey;
|
|
7
8
|
};
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
* adapter, which has no reservation, is given the pool's own handle with an inert `release`.
|
|
11
|
-
*/
|
|
9
|
+
export type BunSqlResult<T = RawRow> = T[] & BunSqlHeader;
|
|
10
|
+
/** The connection a {@link BunSqlQuerier} holds: what a `ReservedSQL` exposes of itself. */
|
|
12
11
|
export type BunSqlConn = Pick<SQL, 'unsafe'> & {
|
|
13
12
|
release(): void;
|
|
14
13
|
};
|
|
@@ -17,24 +16,25 @@ export type BunSqlConn = Pick<SQL, 'unsafe'> & {
|
|
|
17
16
|
* engine uql supports reaches it through a dedicated pool, and keeping this one total means Bun
|
|
18
17
|
* gaining an adapter is a compile error here until the dialect is named.
|
|
19
18
|
*/
|
|
20
|
-
export type BunSqlDialectName = 'postgres' | 'cockroachdb' | 'mysql' | 'mariadb'
|
|
19
|
+
export type BunSqlDialectName = 'postgres' | 'cockroachdb' | 'mysql' | 'mariadb';
|
|
21
20
|
/**
|
|
22
|
-
* Rows a statement read or wrote, from whichever field this adapter fills: Postgres
|
|
23
|
-
*
|
|
24
|
-
*
|
|
21
|
+
* Rows a statement read or wrote, from whichever field this adapter fills: Postgres and CockroachDB
|
|
22
|
+
* report `count` and leave `affectedRows` null, MySQL and MariaDB the other way around - and `count`
|
|
23
|
+
* is 0 on a MySQL write, so the two are read in that order rather than coalesced.
|
|
25
24
|
*
|
|
26
25
|
* `undefined` when the header carries neither, which leaves the returned rows to answer for it -
|
|
27
26
|
* `buildUpdateResult` already falls back to their count, and it is the only one that should.
|
|
28
27
|
*/
|
|
29
28
|
export declare function getAffectedRows(res: BunSqlResult): number | undefined;
|
|
30
29
|
/**
|
|
31
|
-
* Normalizes SQL.Options into
|
|
32
|
-
*
|
|
30
|
+
* Normalizes `SQL.Options` into what Bun's SQL engine expects for a given dialect: the adapter a
|
|
31
|
+
* CockroachDB URL dials, and every BIGINT read as a `bigint` whatever the config asks, for
|
|
32
|
+
* `decodeBigInts` to decode exactly.
|
|
33
33
|
*/
|
|
34
|
-
export declare function normalizeBunOpts(config: SQL.Options, dialectName: BunSqlDialectName): SQL.
|
|
34
|
+
export declare function normalizeBunOpts(config: SQL.Options, dialectName: BunSqlDialectName): SQL.PostgresOrMySQLOptions;
|
|
35
35
|
/**
|
|
36
|
-
* The engine a Bun `SQL.Options` points at: a SQLite file or `:memory
|
|
37
|
-
* the `adapter` Bun itself would read, and Postgres last
|
|
36
|
+
* The engine a Bun `SQL.Options` points at: the URL's scheme - a SQLite file or `:memory:` counting as
|
|
37
|
+
* `sqlite` - then the `adapter` Bun itself would read, and Postgres last, which is Bun's own fallback.
|
|
38
38
|
*/
|
|
39
39
|
export declare function inferDialectName(config: SQL.Options): BunSqlDialectName;
|
|
40
40
|
/** The id a MySQL-family insert reports, by the same wide-integer rule as every other BIGINT. */
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { decodeWideNumber } from '../util/wideNumber.js';
|
|
2
2
|
/**
|
|
3
|
-
* Rows a statement read or wrote, from whichever field this adapter fills: Postgres
|
|
4
|
-
*
|
|
5
|
-
*
|
|
3
|
+
* Rows a statement read or wrote, from whichever field this adapter fills: Postgres and CockroachDB
|
|
4
|
+
* report `count` and leave `affectedRows` null, MySQL and MariaDB the other way around - and `count`
|
|
5
|
+
* is 0 on a MySQL write, so the two are read in that order rather than coalesced.
|
|
6
6
|
*
|
|
7
7
|
* `undefined` when the header carries neither, which leaves the returned rows to answer for it -
|
|
8
8
|
* `buildUpdateResult` already falls back to their count, and it is the only one that should.
|
|
@@ -11,21 +11,13 @@ export function getAffectedRows(res) {
|
|
|
11
11
|
return res.affectedRows || res.count || undefined;
|
|
12
12
|
}
|
|
13
13
|
/**
|
|
14
|
-
* Normalizes SQL.Options into
|
|
15
|
-
*
|
|
14
|
+
* Normalizes `SQL.Options` into what Bun's SQL engine expects for a given dialect: the adapter a
|
|
15
|
+
* CockroachDB URL dials, and every BIGINT read as a `bigint` whatever the config asks, for
|
|
16
|
+
* `decodeBigInts` to decode exactly.
|
|
16
17
|
*/
|
|
17
18
|
export function normalizeBunOpts(config, dialectName) {
|
|
18
|
-
if (dialectName === 'sqlite') {
|
|
19
|
-
const rawFilename = ('filename' in config ? config.filename : null) || ('url' in config ? config.url : null) || ':memory:';
|
|
20
|
-
return {
|
|
21
|
-
...config,
|
|
22
|
-
adapter: 'sqlite',
|
|
23
|
-
filename: rawFilename.toString(),
|
|
24
|
-
};
|
|
25
|
-
}
|
|
26
19
|
const adapter = dialectName === 'cockroachdb' ? 'postgres' : dialectName;
|
|
27
|
-
|
|
28
|
-
const opts = { bigint: true, ...config, adapter };
|
|
20
|
+
const opts = { ...config, adapter, bigint: true };
|
|
29
21
|
if (!opts.url) {
|
|
30
22
|
return opts;
|
|
31
23
|
}
|
|
@@ -41,30 +33,24 @@ export function normalizeBunOpts(config, dialectName) {
|
|
|
41
33
|
return opts;
|
|
42
34
|
}
|
|
43
35
|
/**
|
|
44
|
-
* The engine a Bun `SQL.Options` points at: a SQLite file or `:memory
|
|
45
|
-
* the `adapter` Bun itself would read, and Postgres last
|
|
36
|
+
* The engine a Bun `SQL.Options` points at: the URL's scheme - a SQLite file or `:memory:` counting as
|
|
37
|
+
* `sqlite` - then the `adapter` Bun itself would read, and Postgres last, which is Bun's own fallback.
|
|
46
38
|
*/
|
|
47
39
|
export function inferDialectName(config) {
|
|
48
|
-
if ('filename' in config && config.filename) {
|
|
49
|
-
return 'sqlite';
|
|
50
|
-
}
|
|
51
40
|
const url = 'url' in config ? config.url?.toString() : undefined;
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
const scheme = url.split(':')[0];
|
|
57
|
-
const elsewhere = ELSEWHERE.get(scheme);
|
|
41
|
+
const file = ('filename' in config && !!config.filename) || url === ':memory:' || /\.(db|sqlite)$/.test(url ?? '');
|
|
42
|
+
// Every Bun adapter name is a scheme here too, so the same two tables answer both.
|
|
43
|
+
for (const name of [file ? 'sqlite' : url?.split(':')[0], config.adapter]) {
|
|
44
|
+
const elsewhere = name && ELSEWHERE.get(name);
|
|
58
45
|
if (elsewhere) {
|
|
59
|
-
throw new TypeError(`
|
|
46
|
+
throw new TypeError(`uql-orm/bunSql does not drive ${elsewhere}; use the dedicated uql-orm/${elsewhere} pool`);
|
|
60
47
|
}
|
|
61
|
-
const dialect = SCHEMES.get(
|
|
48
|
+
const dialect = name && SCHEMES.get(name);
|
|
62
49
|
if (dialect) {
|
|
63
50
|
return dialect;
|
|
64
51
|
}
|
|
65
52
|
}
|
|
66
|
-
|
|
67
|
-
return (config.adapter && SCHEMES.get(config.adapter)) || 'postgres';
|
|
53
|
+
return 'postgres';
|
|
68
54
|
}
|
|
69
55
|
/** A `Map` rather than an object literal, whose inherited keys would answer for a `constructor://` URL. */
|
|
70
56
|
const SCHEMES = new Map([
|
|
@@ -73,18 +59,19 @@ const SCHEMES = new Map([
|
|
|
73
59
|
['mysql', 'mysql'],
|
|
74
60
|
['mysql2', 'mysql'],
|
|
75
61
|
['mariadb', 'mariadb'],
|
|
76
|
-
['sqlite', 'sqlite'],
|
|
77
|
-
['sqlite3', 'sqlite'],
|
|
78
62
|
['cockroachdb', 'cockroachdb'],
|
|
79
63
|
]);
|
|
80
64
|
/**
|
|
81
|
-
* Engines uql drives
|
|
82
|
-
*
|
|
83
|
-
*
|
|
65
|
+
* Engines uql drives through another pool. Named rather than left out: Bun's `SQL` falls back to
|
|
66
|
+
* Postgres for any scheme it does not know, so an unlisted `mssql://` would have connected as Postgres
|
|
67
|
+
* and failed on the first statement instead of on the pool. SQLite runs on `Sqlite3QuerierPool`, which
|
|
68
|
+
* uses `bun:sqlite` under Bun.
|
|
84
69
|
*/
|
|
85
70
|
const ELSEWHERE = new Map([
|
|
86
71
|
['mssql', 'mssql'],
|
|
87
72
|
['sqlserver', 'mssql'],
|
|
73
|
+
['sqlite', 'sqlite'],
|
|
74
|
+
['sqlite3', 'sqlite'],
|
|
88
75
|
]);
|
|
89
76
|
/** The id a MySQL-family insert reports, by the same wide-integer rule as every other BIGINT. */
|
|
90
77
|
export function getInsertId(res) {
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
|
|
2
2
|
import { type BunSqlConn } from './bunSql.util.js';
|
|
3
3
|
/**
|
|
4
|
-
* Querier for `bun:sql`, Bun's built-in driver for Postgres, MySQL, MariaDB
|
|
4
|
+
* Querier for `bun:sql`, Bun's built-in driver for Postgres, MySQL, MariaDB and CockroachDB.
|
|
5
5
|
*
|
|
6
6
|
* @remarks Exposes no `SQL` of its own: the pool's would run a statement on any connection, outside
|
|
7
7
|
* the transaction this one's reserved connection holds. Raw access is `pool.sql`.
|
|
@@ -14,7 +14,7 @@ export declare class BunSqlQuerier extends AbstractPoolQuerier<BunSqlConn> {
|
|
|
14
14
|
*
|
|
15
15
|
* Bun's `SQL.Query` is a `Promise` with no cursor or async-iterator API
|
|
16
16
|
* ([oven-sh/bun#17181](https://github.com/oven-sh/bun/issues/17181)), so the rows have to be paged
|
|
17
|
-
* in SQL instead - which the Postgres wire family can do and MySQL
|
|
17
|
+
* in SQL instead - which the Postgres wire family can do and MySQL cannot.
|
|
18
18
|
*/
|
|
19
19
|
protected internalStream<T>(query: string, values?: unknown[]): AsyncGenerator<Awaited<T>, void, any>;
|
|
20
20
|
private execute;
|
|
@@ -3,7 +3,7 @@ import { AbstractPoolQuerier } from '../querier/abstractPoolQuerier.js';
|
|
|
3
3
|
import { decodeBigInts } from '../util/wideNumber.js';
|
|
4
4
|
import { getAffectedRows, getInsertId } from './bunSql.util.js';
|
|
5
5
|
/**
|
|
6
|
-
* Querier for `bun:sql`, Bun's built-in driver for Postgres, MySQL, MariaDB
|
|
6
|
+
* Querier for `bun:sql`, Bun's built-in driver for Postgres, MySQL, MariaDB and CockroachDB.
|
|
7
7
|
*
|
|
8
8
|
* @remarks Exposes no `SQL` of its own: the pool's would run a statement on any connection, outside
|
|
9
9
|
* the transaction this one's reserved connection holds. Raw access is `pool.sql`.
|
|
@@ -18,7 +18,7 @@ export class BunSqlQuerier extends AbstractPoolQuerier {
|
|
|
18
18
|
rows: Array.from(res, decodeBigInts),
|
|
19
19
|
changes: getAffectedRows(res),
|
|
20
20
|
id: getInsertId(res),
|
|
21
|
-
upsertStatus: res.affectedRows,
|
|
21
|
+
upsertStatus: res.affectedRows ?? undefined,
|
|
22
22
|
});
|
|
23
23
|
}
|
|
24
24
|
/**
|
|
@@ -26,7 +26,7 @@ export class BunSqlQuerier extends AbstractPoolQuerier {
|
|
|
26
26
|
*
|
|
27
27
|
* Bun's `SQL.Query` is a `Promise` with no cursor or async-iterator API
|
|
28
28
|
* ([oven-sh/bun#17181](https://github.com/oven-sh/bun/issues/17181)), so the rows have to be paged
|
|
29
|
-
* in SQL instead - which the Postgres wire family can do and MySQL
|
|
29
|
+
* in SQL instead - which the Postgres wire family can do and MySQL cannot.
|
|
30
30
|
*/
|
|
31
31
|
async *internalStream(query, values) {
|
|
32
32
|
if (!this.dialect.features.serverSideCursors) {
|
|
@@ -8,12 +8,7 @@ export declare class BunSqlQuerierPool extends AbstractSqlQuerierPool<BunSqlQuer
|
|
|
8
8
|
readonly config: SQL.Options;
|
|
9
9
|
readonly sql: SQL;
|
|
10
10
|
readonly sqlDialectName: BunSqlDialectName;
|
|
11
|
-
|
|
12
|
-
/**
|
|
13
|
-
* @param config Bun's own `SQL.Options`, from which the engine is inferred. SQLite through here is
|
|
14
|
-
* deprecated: `Sqlite3QuerierPool` (`uql-orm/sqlite`) runs on `bun:sqlite` under Bun, and streams,
|
|
15
|
-
* loads extensions and prepares statements, none of which `bun:sql`'s SQLite adapter can.
|
|
16
|
-
*/
|
|
11
|
+
/** @param config Bun's own `SQL.Options`, from which the engine is inferred. */
|
|
17
12
|
constructor(config: SQL.Options, extra?: ExtraOptions);
|
|
18
13
|
/**
|
|
19
14
|
* Provides a pg-compatible interface for libraries like connect-pg-simple.
|
|
@@ -21,12 +16,5 @@ export declare class BunSqlQuerierPool extends AbstractSqlQuerierPool<BunSqlQuer
|
|
|
21
16
|
*/
|
|
22
17
|
get pool(): SqlPoolCompat;
|
|
23
18
|
getQuerier(): Promise<BunSqlQuerier>;
|
|
24
|
-
/**
|
|
25
|
-
* Bun's SQLite adapter does not support connection reservation (it's unpooled), so the pool hands out
|
|
26
|
-
* its one handle, configured like every other local SQLite connection on the first acquisition, and
|
|
27
|
-
* a `release` that does nothing: the handle is the pool's, and outlives every querier over it.
|
|
28
|
-
*/
|
|
29
|
-
private acquire;
|
|
30
|
-
private configureSqlite;
|
|
31
19
|
end(): Promise<void>;
|
|
32
20
|
}
|
|
@@ -6,8 +6,6 @@ import { MySqlDialect } from '../mysql/mysqlDialect.js';
|
|
|
6
6
|
import { PostgresDialect } from '../postgres/postgresDialect.js';
|
|
7
7
|
import { POSTGRES_WIRE_DRIVER_CAPABILITIES } from '../postgres/postgresWireDriverCapabilities.js';
|
|
8
8
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
9
|
-
import { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
10
|
-
import { SQLITE_PRAGMAS } from '../sqlite/sqlitePragmas.js';
|
|
11
9
|
import { decodeBigInts } from '../util/wideNumber.js';
|
|
12
10
|
import { getAffectedRows, inferDialectName, normalizeBunOpts, } from './bunSql.util.js';
|
|
13
11
|
import { BunSqlQuerier } from './bunSqlQuerier.js';
|
|
@@ -24,30 +22,19 @@ const DialectMap = {
|
|
|
24
22
|
cockroachdb: [CockroachDialect, POSTGRES_WIRE_DRIVER_CAPABILITIES],
|
|
25
23
|
mysql: [MySqlDialect],
|
|
26
24
|
mariadb: [MariaDialect],
|
|
27
|
-
sqlite: [SqliteDialect],
|
|
28
25
|
};
|
|
29
|
-
const SQLITE_DEPRECATION = 'SQLite through uql-orm/bunSql is deprecated; use Sqlite3QuerierPool from uql-orm/sqlite, which runs on bun:sqlite under Bun';
|
|
30
26
|
export class BunSqlQuerierPool extends AbstractSqlQuerierPool {
|
|
31
27
|
config;
|
|
32
28
|
sql;
|
|
33
29
|
sqlDialectName;
|
|
34
|
-
|
|
35
|
-
/**
|
|
36
|
-
* @param config Bun's own `SQL.Options`, from which the engine is inferred. SQLite through here is
|
|
37
|
-
* deprecated: `Sqlite3QuerierPool` (`uql-orm/sqlite`) runs on `bun:sqlite` under Bun, and streams,
|
|
38
|
-
* loads extensions and prepares statements, none of which `bun:sql`'s SQLite adapter can.
|
|
39
|
-
*/
|
|
30
|
+
/** @param config Bun's own `SQL.Options`, from which the engine is inferred. */
|
|
40
31
|
constructor(config, extra) {
|
|
41
32
|
const dialectName = inferDialectName(config);
|
|
42
33
|
const [Dialect, driverCapabilities] = DialectMap[dialectName];
|
|
43
34
|
super(new Dialect({ ...dialectOptionsFrom(extra), driverCapabilities }), extra);
|
|
44
35
|
this.config = config;
|
|
45
36
|
this.sqlDialectName = dialectName;
|
|
46
|
-
|
|
47
|
-
process.emitWarning(SQLITE_DEPRECATION, { type: 'DeprecationWarning', code: 'UQL_BUNSQL_SQLITE' });
|
|
48
|
-
}
|
|
49
|
-
const opts = normalizeBunOpts(config, dialectName);
|
|
50
|
-
this.sql = new SQL(opts);
|
|
37
|
+
this.sql = new SQL(normalizeBunOpts(config, dialectName));
|
|
51
38
|
}
|
|
52
39
|
/**
|
|
53
40
|
* Provides a pg-compatible interface for libraries like connect-pg-simple.
|
|
@@ -65,25 +52,7 @@ export class BunSqlQuerierPool extends AbstractSqlQuerierPool {
|
|
|
65
52
|
};
|
|
66
53
|
}
|
|
67
54
|
async getQuerier() {
|
|
68
|
-
return new BunSqlQuerier(() => this.
|
|
69
|
-
}
|
|
70
|
-
/**
|
|
71
|
-
* Bun's SQLite adapter does not support connection reservation (it's unpooled), so the pool hands out
|
|
72
|
-
* its one handle, configured like every other local SQLite connection on the first acquisition, and
|
|
73
|
-
* a `release` that does nothing: the handle is the pool's, and outlives every querier over it.
|
|
74
|
-
*/
|
|
75
|
-
async acquire() {
|
|
76
|
-
if (this.sqlDialectName !== 'sqlite') {
|
|
77
|
-
return this.sql.reserve();
|
|
78
|
-
}
|
|
79
|
-
this.sqliteConfigured ??= this.configureSqlite();
|
|
80
|
-
await this.sqliteConfigured;
|
|
81
|
-
return { unsafe: this.sql.unsafe.bind(this.sql), release: () => { } };
|
|
82
|
-
}
|
|
83
|
-
async configureSqlite() {
|
|
84
|
-
for (const pragma of SQLITE_PRAGMAS) {
|
|
85
|
-
await this.sql.unsafe(`PRAGMA ${pragma}`);
|
|
86
|
-
}
|
|
55
|
+
return new BunSqlQuerier(() => this.sql.reserve(), this.dialect, this.extra);
|
|
87
56
|
}
|
|
88
57
|
async end() {
|
|
89
58
|
await this.sql.close();
|
package/dist/d1/d1Querier.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { AbstractSqliteQuerier } from '../sqlite/abstractSqliteQuerier.js';
|
|
2
2
|
import type { SqliteDialect } from '../sqlite/sqliteDialect.js';
|
|
3
|
-
import type { ExtraOptions } from '../type/index.js';
|
|
3
|
+
import type { ExtraOptions, RawRow } from '../type/index.js';
|
|
4
4
|
export interface D1Meta {
|
|
5
5
|
duration?: number;
|
|
6
6
|
size_after?: number;
|
|
@@ -25,6 +25,7 @@ export interface D1ExecResult {
|
|
|
25
25
|
export interface D1PreparedStatement {
|
|
26
26
|
bind(...values: unknown[]): D1PreparedStatement;
|
|
27
27
|
first<T = unknown>(colName?: string): Promise<T | null>;
|
|
28
|
+
/** Documented by D1 as an alias of {@link all}: both answer the rows and `meta.changes`. */
|
|
28
29
|
run<T = unknown>(): Promise<D1Result<T>>;
|
|
29
30
|
all<T = unknown>(): Promise<D1Result<T>>;
|
|
30
31
|
raw<T = unknown>(): Promise<T[]>;
|
|
@@ -35,12 +36,19 @@ export interface D1Database {
|
|
|
35
36
|
batch<T = unknown>(statements: D1PreparedStatement[]): Promise<D1Result<T>[]>;
|
|
36
37
|
exec(query: string): Promise<D1ExecResult>;
|
|
37
38
|
}
|
|
38
|
-
/**
|
|
39
|
+
/**
|
|
40
|
+
* The only part of a D1 binding the querier uses: what a {@link D1Database} and a session from
|
|
41
|
+
* `withSession()`, which a read-replicated database is read through, both have.
|
|
42
|
+
*/
|
|
39
43
|
export type D1Preparer = Pick<D1Database, 'prepare'>;
|
|
40
44
|
export declare class D1Querier extends AbstractSqliteQuerier {
|
|
41
45
|
readonly db: D1Preparer;
|
|
42
46
|
readonly extra?: ExtraOptions | undefined;
|
|
43
47
|
constructor(db: D1Preparer, dialect: SqliteDialect, extra?: ExtraOptions | undefined);
|
|
44
|
-
|
|
45
|
-
|
|
48
|
+
protected execute(query: string, values?: unknown[]): Promise<{
|
|
49
|
+
rows: RawRow[];
|
|
50
|
+
changes: number;
|
|
51
|
+
}>;
|
|
52
|
+
/** D1 answers `BEGIN` with `D1_ERROR: not authorized`: a single statement is its only atomic unit. */
|
|
53
|
+
protected internalBegin(): Promise<void>;
|
|
46
54
|
}
|
package/dist/d1/d1Querier.js
CHANGED
|
@@ -7,18 +7,13 @@ export class D1Querier extends AbstractSqliteQuerier {
|
|
|
7
7
|
this.db = db;
|
|
8
8
|
this.extra = extra;
|
|
9
9
|
}
|
|
10
|
-
async
|
|
10
|
+
async execute(query, values) {
|
|
11
11
|
const stmt = this.db.prepare(query);
|
|
12
|
-
const
|
|
13
|
-
|
|
14
|
-
return res.results;
|
|
12
|
+
const { results, meta } = await (values?.length ? stmt.bind(...values) : stmt).all();
|
|
13
|
+
return { rows: results, changes: meta.changes ?? 0 };
|
|
15
14
|
}
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
const res = await bound.run();
|
|
20
|
-
const rows = res.results;
|
|
21
|
-
const changes = rows.length || res.meta?.changes || 0;
|
|
22
|
-
return this.buildUpdateResult({ rows, changes, id: res.meta?.last_row_id });
|
|
15
|
+
/** D1 answers `BEGIN` with `D1_ERROR: not authorized`: a single statement is its only atomic unit. */
|
|
16
|
+
async internalBegin() {
|
|
17
|
+
throw new TypeError('Cloudflare D1 has no transactions: write the changes as one statement, or idempotently');
|
|
23
18
|
}
|
|
24
19
|
}
|
|
@@ -1,10 +1,14 @@
|
|
|
1
1
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
2
2
|
import type { ExtraOptions } from '../type/index.js';
|
|
3
|
-
import { type
|
|
3
|
+
import { type D1Preparer, D1Querier } from './d1Querier.js';
|
|
4
4
|
import { D1SqliteDialect } from './d1SqliteDialect.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pool for Cloudflare D1. It holds nothing: every querier runs on what it was given, `env.DB` or a
|
|
7
|
+
* session from `env.DB.withSession()`, the way a read-replicated database is read consistently.
|
|
8
|
+
*/
|
|
5
9
|
export declare class D1QuerierPool extends AbstractSqlQuerierPool<D1Querier, D1SqliteDialect> {
|
|
6
|
-
readonly db:
|
|
7
|
-
constructor(db:
|
|
10
|
+
readonly db: D1Preparer;
|
|
11
|
+
constructor(db: D1Preparer, extra?: ExtraOptions);
|
|
8
12
|
getQuerier(): Promise<D1Querier>;
|
|
9
13
|
end(): Promise<void>;
|
|
10
14
|
}
|
package/dist/d1/d1QuerierPool.js
CHANGED
|
@@ -2,6 +2,10 @@ import { dialectOptionsFrom } from '../dialect/abstractDialect.js';
|
|
|
2
2
|
import { AbstractSqlQuerierPool } from '../querier/index.js';
|
|
3
3
|
import { D1Querier } from './d1Querier.js';
|
|
4
4
|
import { D1SqliteDialect } from './d1SqliteDialect.js';
|
|
5
|
+
/**
|
|
6
|
+
* Pool for Cloudflare D1. It holds nothing: every querier runs on what it was given, `env.DB` or a
|
|
7
|
+
* session from `env.DB.withSession()`, the way a read-replicated database is read consistently.
|
|
8
|
+
*/
|
|
5
9
|
export class D1QuerierPool extends AbstractSqlQuerierPool {
|
|
6
10
|
db;
|
|
7
11
|
constructor(db, extra) {
|
|
@@ -11,7 +15,5 @@ export class D1QuerierPool extends AbstractSqlQuerierPool {
|
|
|
11
15
|
async getQuerier() {
|
|
12
16
|
return new D1Querier(this.db, this.dialect, this.extra);
|
|
13
17
|
}
|
|
14
|
-
async end() {
|
|
15
|
-
// no-op for D1 bindings
|
|
16
|
-
}
|
|
18
|
+
async end() { }
|
|
17
19
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import type { EntityIndexOptions, EntityOptions,
|
|
1
|
+
import type { EntityIndexColumnInput, EntityIndexOptions, EntityOptions, FilterOptions, RefMap, Type } from '../../type/index.js';
|
|
2
2
|
/**
|
|
3
3
|
* Marks a class as an entity and finalizes its metadata.
|
|
4
4
|
*
|
|
@@ -16,12 +16,8 @@ export declare function Entity<E>(opts?: EntityOptions<E>): (entity: Type<E>, co
|
|
|
16
16
|
*/
|
|
17
17
|
export declare function Filter<E>(name: string, opts: FilterOptions<E>): (entity: Type<E>) => void;
|
|
18
18
|
/**
|
|
19
|
-
* Declares a composite index, its columns read off the
|
|
20
|
-
*
|
|
21
|
-
*
|
|
22
|
-
*
|
|
23
|
-
* @example `@Index((user) => [user.lastName, user.firstName], { name: 'users_fullname_idx' })`
|
|
24
|
-
* @example `@Index((user) => [user.email], { unique: true })`
|
|
25
|
-
* @example `@Index((user) => [user.email], { unique: true, where: { deletedAt: null } })`
|
|
19
|
+
* Declares a composite index, its columns read off the entity's refs, so `@Index((user) => [user.nope])`
|
|
20
|
+
* does not compile and a rename reaches every column. Stacks, so several may sit above one class.
|
|
21
|
+
* @example `@Index((user) => [user.lastName, raw`lower(${user.email})`], { unique: true })`
|
|
26
22
|
*/
|
|
27
|
-
export declare function Index<E>(columns: (
|
|
23
|
+
export declare function Index<E>(columns: (refs: RefMap<E>) => readonly EntityIndexColumnInput<E>[], options?: EntityIndexOptions<E>): (entity: Type<E>) => void;
|
|
@@ -28,13 +28,9 @@ export function Filter(name, opts) {
|
|
|
28
28
|
};
|
|
29
29
|
}
|
|
30
30
|
/**
|
|
31
|
-
* Declares a composite index, its columns read off the
|
|
32
|
-
*
|
|
33
|
-
*
|
|
34
|
-
*
|
|
35
|
-
* @example `@Index((user) => [user.lastName, user.firstName], { name: 'users_fullname_idx' })`
|
|
36
|
-
* @example `@Index((user) => [user.email], { unique: true })`
|
|
37
|
-
* @example `@Index((user) => [user.email], { unique: true, where: { deletedAt: null } })`
|
|
31
|
+
* Declares a composite index, its columns read off the entity's refs, so `@Index((user) => [user.nope])`
|
|
32
|
+
* does not compile and a rename reaches every column. Stacks, so several may sit above one class.
|
|
33
|
+
* @example `@Index((user) => [user.lastName, raw`lower(${user.email})`], { unique: true })`
|
|
38
34
|
*/
|
|
39
35
|
export function Index(columns, options = {}) {
|
|
40
36
|
return (entity) => {
|
|
@@ -11,8 +11,8 @@ export declare function defineRelation<E, T extends object>(entity: Type<E>, key
|
|
|
11
11
|
export declare function relationRegistration<T extends object, O>({ mappedBy, references, ...opts }: RelationOptions<T, O>): RelationRegistration;
|
|
12
12
|
export declare function defineHook<E>(entity: Type<E>, methodName: string, event: HookEvent): EntityMeta<E>;
|
|
13
13
|
/**
|
|
14
|
-
* Declares a composite index, its columns read off the
|
|
15
|
-
* are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
14
|
+
* Declares a composite index, its columns read off the entity's refs. `unique` and the authored column
|
|
15
|
+
* sugar are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
16
16
|
*/
|
|
17
17
|
export declare function defineIndex<E>(entity: Type<E>, index: EntityIndexInput<E>): EntityMeta<E>;
|
|
18
18
|
export declare function defineFilter<E>(entity: Type<E>, name: string, opts: FilterOptions<E>): EntityMeta<E>;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { SOFT_DELETE_FILTER } from '../../type/index.js';
|
|
2
2
|
import { isInlinedExpression } from '../../util/field.util.js';
|
|
3
|
-
import { entityName, entitySql, entityWhere, fieldOptionConflict, getKeys, hasKeys, isToManyRelation, lowerFirst, normalizeIndexColumn, upperFirst, definedEntries, } from '../../util/index.js';
|
|
3
|
+
import { entityName, entitySql, entityWhere, fieldOptionConflict, getKeys, hasKeys, isToManyRelation, lowerFirst, memberRefs, normalizeIndexColumn, upperFirst, definedEntries, } from '../../util/index.js';
|
|
4
4
|
import { ownRegistrations } from '../decorator/bag.js';
|
|
5
5
|
/**
|
|
6
6
|
* A map held on `globalThis` through the global symbol registry, so a single one survives multiple
|
|
@@ -56,8 +56,8 @@ export function defineRelation(entity, key, opts) {
|
|
|
56
56
|
export function relationRegistration({ mappedBy, references, ...opts }) {
|
|
57
57
|
return {
|
|
58
58
|
...opts,
|
|
59
|
-
...(mappedBy
|
|
60
|
-
...(references
|
|
59
|
+
...(mappedBy && { mappedBy: mappedBy(keyMap()) }),
|
|
60
|
+
...(references && { references: [...references(keyMap(), keyMap())] }),
|
|
61
61
|
};
|
|
62
62
|
}
|
|
63
63
|
/** Every entity's key map: a callback only reads one property off it, and that property is its own key. */
|
|
@@ -83,26 +83,22 @@ function addRelation(entity, key, registration) {
|
|
|
83
83
|
}
|
|
84
84
|
export function defineHook(entity, methodName, event) {
|
|
85
85
|
const meta = ensureWritableMeta(entity);
|
|
86
|
-
|
|
87
|
-
meta.hooks = {};
|
|
88
|
-
if (!meta.hooks[event])
|
|
89
|
-
meta.hooks[event] = [];
|
|
90
|
-
meta.hooks[event].push({ methodName });
|
|
86
|
+
((meta.hooks ??= {})[event] ??= []).push({ methodName });
|
|
91
87
|
return meta;
|
|
92
88
|
}
|
|
93
89
|
/**
|
|
94
|
-
* Declares a composite index, its columns read off the
|
|
95
|
-
* are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
90
|
+
* Declares a composite index, its columns read off the entity's refs. `unique` and the authored column
|
|
91
|
+
* sugar are normalized here, which is what lets the dialects render one shape instead of re-parsing it.
|
|
96
92
|
*/
|
|
97
93
|
export function defineIndex(entity, index) {
|
|
98
94
|
const meta = ensureWritableMeta(entity);
|
|
99
|
-
const
|
|
95
|
+
const refs = memberRefs();
|
|
100
96
|
(meta.indexes ??= []).push({
|
|
101
97
|
...index,
|
|
102
98
|
unique: index.unique ?? false,
|
|
103
99
|
where: index.where && entityWhere(index.where),
|
|
104
|
-
columns: index.columns(
|
|
105
|
-
include: index.include?.(
|
|
100
|
+
columns: index.columns(refs).map(normalizeIndexColumn),
|
|
101
|
+
include: index.include?.(refs).map((ref) => ref.key),
|
|
106
102
|
});
|
|
107
103
|
return meta;
|
|
108
104
|
}
|
|
@@ -114,9 +110,7 @@ export function defineFilter(entity, name, opts) {
|
|
|
114
110
|
if (opts.security && opts.onMissing === 'skip') {
|
|
115
111
|
throw TypeError(`'${entity.name}' security filter '${name}' cannot use onMissing: 'skip' (it must fail closed)`);
|
|
116
112
|
}
|
|
117
|
-
|
|
118
|
-
meta.filters = {};
|
|
119
|
-
meta.filters[name] = opts;
|
|
113
|
+
(meta.filters ??= {})[name] = opts;
|
|
120
114
|
return meta;
|
|
121
115
|
}
|
|
122
116
|
/**
|
|
@@ -208,9 +202,7 @@ export function defineEntity(entity, opts = {}) {
|
|
|
208
202
|
}
|
|
209
203
|
if (softDeleteKeys.length) {
|
|
210
204
|
meta.softDelete = softDeleteKeys[0];
|
|
211
|
-
|
|
212
|
-
meta.filters = {};
|
|
213
|
-
meta.filters[SOFT_DELETE_FILTER] = { where: { [meta.softDelete]: null }, default: true };
|
|
205
|
+
(meta.filters ??= {})[SOFT_DELETE_FILTER] = { where: { [meta.softDelete]: null }, default: true };
|
|
214
206
|
}
|
|
215
207
|
const ids = getIdKeys(meta);
|
|
216
208
|
if (!ids.length) {
|
|
@@ -506,10 +498,9 @@ function extendMeta(target, source) {
|
|
|
506
498
|
}
|
|
507
499
|
// Merge hooks from parent entity (parent hooks execute first)
|
|
508
500
|
if (source.hooks) {
|
|
509
|
-
|
|
510
|
-
target.hooks = {};
|
|
501
|
+
const hooks = (target.hooks ??= {});
|
|
511
502
|
for (const [event, sourceList] of definedEntries(source.hooks)) {
|
|
512
|
-
|
|
503
|
+
hooks[event] = [...sourceList, ...(hooks[event] ?? [])];
|
|
513
504
|
}
|
|
514
505
|
}
|
|
515
506
|
}
|
|
@@ -12,7 +12,7 @@ export declare class LibsqlDialect extends SqliteDialect {
|
|
|
12
12
|
* functions this dialect would otherwise inherit are never present.
|
|
13
13
|
*
|
|
14
14
|
* @remarks `inner` and `l1` are left out: `vector_distance_dot` only exists in the newer Rust
|
|
15
|
-
* engine (see `
|
|
15
|
+
* engine (see `TursoLocalDialect`) and no libSQL build has an L1 metric. Both raise the same
|
|
16
16
|
* "does not support vector distance metric" error as any other unsupported metric.
|
|
17
17
|
*/
|
|
18
18
|
readonly vectorMetrics: ReadonlyMap<VectorDistance, VectorMetric>;
|
|
@@ -11,7 +11,7 @@ export class LibsqlDialect extends SqliteDialect {
|
|
|
11
11
|
* functions this dialect would otherwise inherit are never present.
|
|
12
12
|
*
|
|
13
13
|
* @remarks `inner` and `l1` are left out: `vector_distance_dot` only exists in the newer Rust
|
|
14
|
-
* engine (see `
|
|
14
|
+
* engine (see `TursoLocalDialect`) and no libSQL build has an L1 metric. Both raise the same
|
|
15
15
|
* "does not support vector distance metric" error as any other unsupported metric.
|
|
16
16
|
*/
|
|
17
17
|
vectorMetrics = new Map([
|
|
@@ -1,19 +1,28 @@
|
|
|
1
1
|
import type { Config } from '@libsql/client';
|
|
2
|
+
import { AbstractSharedHandleQuerierPool } from '../querier/abstractSharedHandleQuerierPool.js';
|
|
2
3
|
import { type HranaClient, HranaQuerier } from '../sqlite/hranaQuerier.js';
|
|
3
|
-
import { AbstractHranaQuerierPool } from '../sqlite/hranaQuerierPool.js';
|
|
4
4
|
import type { ExtraOptions } from '../type/index.js';
|
|
5
5
|
import { LibsqlDialect } from './libsqlDialect.js';
|
|
6
|
-
/**
|
|
7
|
-
|
|
8
|
-
|
|
6
|
+
/**
|
|
7
|
+
* Pool for libSQL. One client serves every querier, since Hrana keeps no per-connection state: a
|
|
8
|
+
* transaction takes its own session handle. The pool builds that client from `@libsql/client`'s
|
|
9
|
+
* `Config`, or shares one the caller built (`@libsql/client/web`, `@libsql/client-wasm`), which stays
|
|
10
|
+
* theirs to close.
|
|
11
|
+
*/
|
|
12
|
+
export declare class LibsqlQuerierPool extends AbstractSharedHandleQuerierPool<HranaClient, HranaQuerier, LibsqlDialect> {
|
|
9
13
|
private readonly conf;
|
|
10
|
-
constructor(conf: Config, extra?: ExtraOptions);
|
|
11
|
-
protected
|
|
14
|
+
constructor(conf: Config | HranaClient, extra?: ExtraOptions);
|
|
15
|
+
protected openDb(): Promise<HranaClient>;
|
|
16
|
+
protected buildQuerier(client: HranaClient): HranaQuerier;
|
|
17
|
+
end(): Promise<void>;
|
|
12
18
|
/**
|
|
13
|
-
* For embedded
|
|
14
|
-
*
|
|
19
|
+
* For an embedded replica - a `file:` url with a `syncUrl` - a querier on the sync url, so migrations
|
|
20
|
+
* reach sqld, its client closing with it. Anything else migrates like any other querier.
|
|
15
21
|
*/
|
|
16
22
|
getMigrationQuerier(): Promise<HranaQuerier>;
|
|
17
|
-
/**
|
|
23
|
+
/**
|
|
24
|
+
* Imported on use, so `uql-orm/libsql` loads without the optional `@libsql/client` peer installed.
|
|
25
|
+
* Integers read as `bigint` whatever the config asks, so the querier decodes one past 2^53 exactly.
|
|
26
|
+
*/
|
|
18
27
|
private createClient;
|
|
19
28
|
}
|