kysely 0.28.17 → 0.28.18
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/README.md +1 -1
- package/dist/cjs/dialect/mssql/mssql-adapter.d.ts +3 -2
- package/dist/cjs/dialect/mssql/mssql-adapter.js +13 -7
- package/dist/cjs/dialect/mysql/mysql-dialect-config.d.ts +10 -0
- package/dist/cjs/dialect/postgres/postgres-adapter.d.ts +1 -1
- package/dist/cjs/dialect/postgres/postgres-adapter.js +13 -7
- package/dist/cjs/dialect/postgres/postgres-dialect-config.d.ts +10 -0
- package/dist/cjs/dialect/postgres/postgres-driver.js +5 -0
- package/dist/cjs/dialect/postgres/postgres-introspector.js +18 -12
- package/dist/cjs/dialect/sqlite/sqlite-dialect-config.d.ts +10 -0
- package/dist/cjs/helpers/mssql.d.ts +3 -1
- package/dist/cjs/helpers/mssql.js +4 -2
- package/dist/cjs/kysely.d.ts +50 -3
- package/dist/cjs/kysely.js +90 -30
- package/dist/cjs/migration/migrator.js +22 -19
- package/dist/cjs/query-builder/delete-query-builder.d.ts +2 -2
- package/dist/cjs/query-builder/join-builder.d.ts +2 -2
- package/dist/cjs/query-builder/on-conflict-builder.d.ts +5 -2
- package/dist/cjs/query-builder/select-query-builder.d.ts +28 -6
- package/dist/cjs/query-builder/update-query-builder.d.ts +1 -1
- package/dist/cjs/query-compiler/default-query-compiler.js +4 -4
- package/dist/cjs/schema/create-type-builder.d.ts +1 -1
- package/dist/cjs/schema/create-type-builder.js +1 -1
- package/dist/cjs/util/column-type.d.ts +1 -1
- package/dist/esm/dialect/mssql/mssql-adapter.d.ts +3 -2
- package/dist/esm/dialect/mssql/mssql-adapter.js +13 -7
- package/dist/esm/dialect/mysql/mysql-dialect-config.d.ts +10 -0
- package/dist/esm/dialect/postgres/postgres-adapter.d.ts +1 -1
- package/dist/esm/dialect/postgres/postgres-adapter.js +13 -7
- package/dist/esm/dialect/postgres/postgres-dialect-config.d.ts +10 -0
- package/dist/esm/dialect/postgres/postgres-driver.js +5 -0
- package/dist/esm/dialect/postgres/postgres-introspector.js +18 -12
- package/dist/esm/dialect/sqlite/sqlite-dialect-config.d.ts +10 -0
- package/dist/esm/helpers/mssql.d.ts +3 -1
- package/dist/esm/helpers/mssql.js +4 -2
- package/dist/esm/kysely.d.ts +50 -3
- package/dist/esm/kysely.js +90 -30
- package/dist/esm/migration/migrator.js +22 -19
- package/dist/esm/query-builder/delete-query-builder.d.ts +2 -2
- package/dist/esm/query-builder/join-builder.d.ts +2 -2
- package/dist/esm/query-builder/on-conflict-builder.d.ts +5 -2
- package/dist/esm/query-builder/select-query-builder.d.ts +28 -6
- package/dist/esm/query-builder/update-query-builder.d.ts +1 -1
- package/dist/esm/query-compiler/default-query-compiler.js +4 -4
- package/dist/esm/schema/create-type-builder.d.ts +1 -1
- package/dist/esm/schema/create-type-builder.js +1 -1
- package/dist/esm/util/column-type.d.ts +1 -1
- package/package.json +36 -34
package/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
[](https://stand-with-ukraine.pp.ua)
|
|
2
2
|
|
|
3
3
|
[](https://github.com/kysely-org/kysely/releases/latest)
|
|
4
|
-
[](https://socket.dev/npm/package/kysely/overview/0.28.18)
|
|
5
5
|
[](https://github.com/kysely-org/kysely)
|
|
6
6
|
[](https://github.com/kysely-org/kysely/blob/master/LICENSE)
|
|
7
7
|
[](https://github.com/kysely-org/kysely/issues?q=is%3Aissue+is%3Aopen+sort%3Aupdated-desc)
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Kysely } from '../../kysely.js';
|
|
2
2
|
import { DialectAdapterBase } from '../dialect-adapter-base.js';
|
|
3
|
+
import type { MigrationLockOptions } from '../dialect-adapter.js';
|
|
3
4
|
export declare class MssqlAdapter extends DialectAdapterBase {
|
|
4
5
|
/**
|
|
5
6
|
* Whether or not this dialect supports `if not exists` in creation of tables/schemas/views/etc.
|
|
@@ -70,7 +71,7 @@ export declare class MssqlAdapter extends DialectAdapterBase {
|
|
|
70
71
|
* `db` is a single connection (session) that will be used to execute the
|
|
71
72
|
* migrations.
|
|
72
73
|
*/
|
|
73
|
-
acquireMigrationLock(db: Kysely<any
|
|
74
|
+
acquireMigrationLock(db: Kysely<any>, _opt: MigrationLockOptions): Promise<void>;
|
|
74
75
|
/**
|
|
75
76
|
* Releases the migration lock. See {@link acquireMigrationLock}.
|
|
76
77
|
*
|
|
@@ -79,5 +80,5 @@ export declare class MssqlAdapter extends DialectAdapterBase {
|
|
|
79
80
|
* is a single connection (session) that was used to execute the migrations
|
|
80
81
|
* and the `acquireMigrationLock` call.
|
|
81
82
|
*/
|
|
82
|
-
releaseMigrationLock(): Promise<void>;
|
|
83
|
+
releaseMigrationLock(db: Kysely<any>, _opt: MigrationLockOptions): Promise<void>;
|
|
83
84
|
}
|
|
@@ -4,6 +4,7 @@ exports.MssqlAdapter = void 0;
|
|
|
4
4
|
const migrator_js_1 = require("../../migration/migrator.js");
|
|
5
5
|
const sql_js_1 = require("../../raw-builder/sql.js");
|
|
6
6
|
const dialect_adapter_base_js_1 = require("../dialect-adapter-base.js");
|
|
7
|
+
const LOCK_PRINCIPAL = 'dbo';
|
|
7
8
|
class MssqlAdapter extends dialect_adapter_base_js_1.DialectAdapterBase {
|
|
8
9
|
get supportsCreateIfNotExists() {
|
|
9
10
|
return false;
|
|
@@ -14,15 +15,20 @@ class MssqlAdapter extends dialect_adapter_base_js_1.DialectAdapterBase {
|
|
|
14
15
|
get supportsOutput() {
|
|
15
16
|
return true;
|
|
16
17
|
}
|
|
17
|
-
async acquireMigrationLock(db) {
|
|
18
|
-
// Acquire a
|
|
18
|
+
async acquireMigrationLock(db, _opt) {
|
|
19
|
+
// Acquire a session-level exclusive lock on the migrations table. A
|
|
20
|
+
// session-level lock (as opposed to the default transaction-level lock)
|
|
21
|
+
// stays held after the migration transaction commits and until we release
|
|
22
|
+
// it explicitly in `releaseMigrationLock` OR the session ends. This way we
|
|
23
|
+
// know the lock is either released by us after successful or failed
|
|
24
|
+
// migrations OR it's released by SQL Server if the connection dies.
|
|
19
25
|
// https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-getapplock-transact-sql?view=sql-server-ver16
|
|
20
|
-
await (0, sql_js_1.sql) `exec sp_getapplock @DbPrincipal = ${sql_js_1.sql.lit(
|
|
26
|
+
await (0, sql_js_1.sql) `exec sp_getapplock @DbPrincipal = ${sql_js_1.sql.lit(LOCK_PRINCIPAL)}, @Resource = ${sql_js_1.sql.lit(migrator_js_1.DEFAULT_MIGRATION_TABLE)}, @LockMode = ${sql_js_1.sql.lit('Exclusive')}, @LockOwner = ${sql_js_1.sql.lit('Session')}`.execute(db);
|
|
21
27
|
}
|
|
22
|
-
async releaseMigrationLock() {
|
|
23
|
-
//
|
|
24
|
-
//
|
|
25
|
-
|
|
28
|
+
async releaseMigrationLock(db, _opt) {
|
|
29
|
+
// Release the session-level lock acquired in `acquireMigrationLock`.
|
|
30
|
+
// https://learn.microsoft.com/en-us/sql/relational-databases/system-stored-procedures/sp-releaseapplock-transact-sql?view=sql-server-ver16
|
|
31
|
+
await (0, sql_js_1.sql) `exec sp_releaseapplock @DbPrincipal = ${sql_js_1.sql.lit(LOCK_PRINCIPAL)}, @Resource = ${sql_js_1.sql.lit(migrator_js_1.DEFAULT_MIGRATION_TABLE)}, @LockOwner = ${sql_js_1.sql.lit('Session')}`.execute(db);
|
|
26
32
|
}
|
|
27
33
|
}
|
|
28
34
|
exports.MssqlAdapter = MssqlAdapter;
|
|
@@ -10,6 +10,16 @@ export interface MysqlDialectConfig {
|
|
|
10
10
|
*
|
|
11
11
|
* If a function is provided, it's called once when the first query is executed.
|
|
12
12
|
*
|
|
13
|
+
* Once the driver has initialized, {@link Kysely.destroy} calls
|
|
14
|
+
* `pool.end(callback)`, whether the pool is supplied directly or returned by a
|
|
15
|
+
* function. If initialization hasn't started, `db.destroy()` does nothing,
|
|
16
|
+
* even if the supplied pool has been used outside Kysely.
|
|
17
|
+
*
|
|
18
|
+
* If Kysely is not the sole consumer of the pool, or the pool's lifecycle is
|
|
19
|
+
* managed elsewhere, skip `db.destroy()`. Let the application call
|
|
20
|
+
* `pool.end(callback)` once all consumers, including Kysely, have finished. No
|
|
21
|
+
* separate cleanup of the `Kysely` instance is needed.
|
|
22
|
+
*
|
|
13
23
|
* https://github.com/sidorares/node-mysql2#using-connection-pools
|
|
14
24
|
*/
|
|
15
25
|
pool: MysqlPool | (() => Promise<MysqlPool>);
|
|
@@ -76,5 +76,5 @@ export declare class PostgresAdapter extends DialectAdapterBase {
|
|
|
76
76
|
* is a single connection (session) that was used to execute the migrations
|
|
77
77
|
* and the `acquireMigrationLock` call.
|
|
78
78
|
*/
|
|
79
|
-
releaseMigrationLock(
|
|
79
|
+
releaseMigrationLock(db: Kysely<any>, _opt: MigrationLockOptions): Promise<void>;
|
|
80
80
|
}
|
|
@@ -3,8 +3,8 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.PostgresAdapter = void 0;
|
|
4
4
|
const sql_js_1 = require("../../raw-builder/sql.js");
|
|
5
5
|
const dialect_adapter_base_js_1 = require("../dialect-adapter-base.js");
|
|
6
|
-
// Random id for our transaction lock.
|
|
7
6
|
const LOCK_ID = BigInt('3853314791062309107');
|
|
7
|
+
const LOCK_TIMEOUT_MILLISECONDS = 60 * 60 * 1_000;
|
|
8
8
|
class PostgresAdapter extends dialect_adapter_base_js_1.DialectAdapterBase {
|
|
9
9
|
get supportsTransactionalDdl() {
|
|
10
10
|
return true;
|
|
@@ -13,13 +13,19 @@ class PostgresAdapter extends dialect_adapter_base_js_1.DialectAdapterBase {
|
|
|
13
13
|
return true;
|
|
14
14
|
}
|
|
15
15
|
async acquireMigrationLock(db, _opt) {
|
|
16
|
-
//
|
|
17
|
-
|
|
16
|
+
// in 1 RTT, acquire a session-level advisory lock with a timeout.
|
|
17
|
+
//
|
|
18
|
+
// if ever this runs inside a transaction, niche edge case we support - the
|
|
19
|
+
// user is responsible to set a different timeout value or disable (`0` value).
|
|
20
|
+
await (0, sql_js_1.sql) `
|
|
21
|
+
with set_timeout as (
|
|
22
|
+
select set_config('lock_timeout', '${sql_js_1.sql.lit(LOCK_TIMEOUT_MILLISECONDS)}', true) as config_val
|
|
23
|
+
)
|
|
24
|
+
select pg_advisory_lock(${sql_js_1.sql.lit(LOCK_ID)})
|
|
25
|
+
from set_timeout`.execute(db);
|
|
18
26
|
}
|
|
19
|
-
async releaseMigrationLock(
|
|
20
|
-
|
|
21
|
-
// end of the transaction and since `supportsTransactionalDdl` true, we know
|
|
22
|
-
// the `db` instance passed to acquireMigrationLock is actually a transaction.
|
|
27
|
+
async releaseMigrationLock(db, _opt) {
|
|
28
|
+
await (0, sql_js_1.sql) `select pg_advisory_unlock(${sql_js_1.sql.lit(LOCK_ID)})`.execute(db);
|
|
23
29
|
}
|
|
24
30
|
}
|
|
25
31
|
exports.PostgresAdapter = PostgresAdapter;
|
|
@@ -8,6 +8,16 @@ export interface PostgresDialectConfig {
|
|
|
8
8
|
*
|
|
9
9
|
* If a function is provided, it's called once when the first query is executed.
|
|
10
10
|
*
|
|
11
|
+
* Once the driver has initialized, {@link Kysely.destroy} calls `pool.end()`,
|
|
12
|
+
* whether the pool is supplied directly or returned by a function. If
|
|
13
|
+
* initialization hasn't started, `db.destroy()` does nothing, even if the
|
|
14
|
+
* supplied pool has been used outside Kysely.
|
|
15
|
+
*
|
|
16
|
+
* If Kysely is not the sole consumer of the pool, or the pool's lifecycle is
|
|
17
|
+
* managed elsewhere, skip `db.destroy()`. Let the application call `pool.end()`
|
|
18
|
+
* once all consumers, including Kysely, have finished. No separate cleanup of
|
|
19
|
+
* the `Kysely` instance is needed.
|
|
20
|
+
*
|
|
11
21
|
* https://node-postgres.com/apis/pool
|
|
12
22
|
*/
|
|
13
23
|
pool: PostgresPool | (() => Promise<PostgresPool>);
|
|
@@ -21,6 +21,11 @@ class PostgresDriver {
|
|
|
21
21
|
}
|
|
22
22
|
async acquireConnection() {
|
|
23
23
|
const client = await this.#pool.connect();
|
|
24
|
+
// `destroy` was called while the connection was being acquired.
|
|
25
|
+
if (!this.#pool) {
|
|
26
|
+
client.release();
|
|
27
|
+
throw new Error('driver has already been destroyed');
|
|
28
|
+
}
|
|
24
29
|
let connection = this.#connections.get(client);
|
|
25
30
|
if (!connection) {
|
|
26
31
|
connection = new PostgresConnection(client, {
|
|
@@ -73,20 +73,26 @@ class PostgresIntrospector {
|
|
|
73
73
|
};
|
|
74
74
|
}
|
|
75
75
|
#parseTableMetadata(columns) {
|
|
76
|
-
const
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
76
|
+
const tables = [];
|
|
77
|
+
const schemas = new Map();
|
|
78
|
+
for (const column of columns) {
|
|
79
|
+
let schema = schemas.get(column.schema);
|
|
80
|
+
if (!schema) {
|
|
81
|
+
schema = new Map();
|
|
82
|
+
schemas.set(column.schema, schema);
|
|
83
|
+
}
|
|
84
|
+
let table = schema.get(column.table);
|
|
85
|
+
if (!table) {
|
|
86
|
+
table = (0, object_utils_js_1.freeze)({
|
|
83
87
|
columns: [],
|
|
84
88
|
isView: column.table_type === 'v',
|
|
85
|
-
name: table,
|
|
86
|
-
schema,
|
|
87
|
-
})
|
|
89
|
+
name: column.table,
|
|
90
|
+
schema: column.schema,
|
|
91
|
+
});
|
|
92
|
+
schema.set(column.table, table);
|
|
93
|
+
tables.push(table);
|
|
88
94
|
}
|
|
89
|
-
|
|
95
|
+
table.columns.push((0, object_utils_js_1.freeze)({
|
|
90
96
|
comment: column.column_description ?? undefined,
|
|
91
97
|
dataType: column.type,
|
|
92
98
|
dataTypeSchema: column.type_schema,
|
|
@@ -96,7 +102,7 @@ class PostgresIntrospector {
|
|
|
96
102
|
name: column.column,
|
|
97
103
|
}));
|
|
98
104
|
}
|
|
99
|
-
return
|
|
105
|
+
return tables;
|
|
100
106
|
}
|
|
101
107
|
}
|
|
102
108
|
exports.PostgresIntrospector = PostgresIntrospector;
|
|
@@ -8,6 +8,16 @@ export interface SqliteDialectConfig {
|
|
|
8
8
|
*
|
|
9
9
|
* If a function is provided, it's called once when the first query is executed.
|
|
10
10
|
*
|
|
11
|
+
* Once the driver has initialized, {@link Kysely.destroy} calls
|
|
12
|
+
* `database.close()`, whether the database is supplied directly or returned by
|
|
13
|
+
* a function. If initialization hasn't started, `db.destroy()` does nothing,
|
|
14
|
+
* even if the supplied database has been used outside Kysely.
|
|
15
|
+
*
|
|
16
|
+
* If Kysely is not the sole consumer of the database, or the database's
|
|
17
|
+
* lifecycle is managed elsewhere, skip `db.destroy()`. Let the application
|
|
18
|
+
* call `database.close()` once all consumers, including Kysely, have finished.
|
|
19
|
+
* No separate cleanup of the `Kysely` instance is needed.
|
|
20
|
+
*
|
|
11
21
|
* https://github.com/JoshuaWise/better-sqlite3/blob/master/docs/api.md#new-databasepath-options
|
|
12
22
|
*/
|
|
13
23
|
database: SqliteDatabase | (() => Promise<SqliteDatabase>);
|
|
@@ -202,7 +202,9 @@ export declare function jsonObjectFrom<O>(expr: Expression<O>): RawBuilder<Simpl
|
|
|
202
202
|
*
|
|
203
203
|
* ```sql
|
|
204
204
|
* select "id", json_query(
|
|
205
|
-
* '{"
|
|
205
|
+
* '{"'+string_escape(N'first', 'json')+'":"'+string_escape("first_name", 'json')+
|
|
206
|
+
* '","'+string_escape(N'last', 'json')+'":"'+string_escape("last_name", 'json')+
|
|
207
|
+
* '","'+string_escape(N'full', 'json')+'":"'+string_escape(concat("first_name", ' ', "last_name"), 'json')+'"}'
|
|
206
208
|
* ) as "name"
|
|
207
209
|
* from "person"
|
|
208
210
|
* ```
|
|
@@ -209,11 +209,13 @@ function jsonObjectFrom(expr) {
|
|
|
209
209
|
*
|
|
210
210
|
* ```sql
|
|
211
211
|
* select "id", json_query(
|
|
212
|
-
* '{"
|
|
212
|
+
* '{"'+string_escape(N'first', 'json')+'":"'+string_escape("first_name", 'json')+
|
|
213
|
+
* '","'+string_escape(N'last', 'json')+'":"'+string_escape("last_name", 'json')+
|
|
214
|
+
* '","'+string_escape(N'full', 'json')+'":"'+string_escape(concat("first_name", ' ', "last_name"), 'json')+'"}'
|
|
213
215
|
* ) as "name"
|
|
214
216
|
* from "person"
|
|
215
217
|
* ```
|
|
216
218
|
*/
|
|
217
219
|
function jsonBuildObject(obj) {
|
|
218
|
-
return (0, sql_js_1.sql) `json_query('{${sql_js_1.sql.join(Object.keys(obj).map((k) => (0, sql_js_1.sql) `"${sql_js_1.sql.
|
|
220
|
+
return (0, sql_js_1.sql) `json_query('{${sql_js_1.sql.join(Object.keys(obj).map((k) => (0, sql_js_1.sql) `"'+string_escape(N${sql_js_1.sql.lit(k)}, 'json')+'":"'+string_escape(${obj[k]}, 'json')+'"`), (0, sql_js_1.sql) `,`)}}')`;
|
|
219
221
|
}
|
package/dist/cjs/kysely.d.ts
CHANGED
|
@@ -29,7 +29,8 @@ declare global {
|
|
|
29
29
|
* The main Kysely class.
|
|
30
30
|
*
|
|
31
31
|
* You should create one instance of `Kysely` per database using the {@link Kysely}
|
|
32
|
-
* constructor.
|
|
32
|
+
* constructor. The dialect manages database connections and may use a shared
|
|
33
|
+
* pool or database instance.
|
|
33
34
|
*
|
|
34
35
|
* ### Examples
|
|
35
36
|
*
|
|
@@ -384,7 +385,16 @@ export declare class Kysely<DB> extends QueryCreator<DB> implements QueryExecuto
|
|
|
384
385
|
/**
|
|
385
386
|
* Releases all resources and disconnects from the database.
|
|
386
387
|
*
|
|
387
|
-
*
|
|
388
|
+
* Call this when you are done using the `Kysely` instance and Kysely is
|
|
389
|
+
* responsible for closing its connections, pool, or database instance.
|
|
390
|
+
*
|
|
391
|
+
* If the pool or database instance is shared with other consumers or its
|
|
392
|
+
* lifecycle is managed elsewhere, skip this call. Let the application close it
|
|
393
|
+
* once all consumers, including Kysely, have finished. No separate cleanup of
|
|
394
|
+
* the `Kysely` instance is needed.
|
|
395
|
+
*
|
|
396
|
+
* The driver is initialized lazily. If initialization hasn't started, this
|
|
397
|
+
* method does nothing.
|
|
388
398
|
*/
|
|
389
399
|
destroy(): Promise<void>;
|
|
390
400
|
/**
|
|
@@ -511,7 +521,16 @@ export declare class Transaction<DB> extends Kysely<DB> {
|
|
|
511
521
|
/**
|
|
512
522
|
* Releases all resources and disconnects from the database.
|
|
513
523
|
*
|
|
514
|
-
*
|
|
524
|
+
* Call this when you are done using the `Kysely` instance and Kysely is
|
|
525
|
+
* responsible for closing its connections, pool, or database instance.
|
|
526
|
+
*
|
|
527
|
+
* If the pool or database instance is shared with other consumers or its
|
|
528
|
+
* lifecycle is managed elsewhere, skip this call. Let the application close it
|
|
529
|
+
* once all consumers, including Kysely, have finished. No separate cleanup of
|
|
530
|
+
* the `Kysely` instance is needed.
|
|
531
|
+
*
|
|
532
|
+
* The driver is initialized lazily. If initialization hasn't started, this
|
|
533
|
+
* method does nothing.
|
|
515
534
|
*/
|
|
516
535
|
destroy(): Promise<void>;
|
|
517
536
|
/**
|
|
@@ -646,6 +665,10 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
646
665
|
/**
|
|
647
666
|
* Commits the transaction.
|
|
648
667
|
*
|
|
668
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
669
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
670
|
+
* exit the loop before committing.
|
|
671
|
+
*
|
|
649
672
|
* See {@link rollback}.
|
|
650
673
|
*
|
|
651
674
|
* ### Examples
|
|
@@ -671,6 +694,13 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
671
694
|
/**
|
|
672
695
|
* Rolls back the transaction.
|
|
673
696
|
*
|
|
697
|
+
* The connection is released even if the rollback fails, so the transaction
|
|
698
|
+
* cannot be used afterwards in either case.
|
|
699
|
+
*
|
|
700
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
701
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
702
|
+
* exit the loop before rolling back.
|
|
703
|
+
*
|
|
674
704
|
* See {@link commit} and {@link rollbackToSavepoint}.
|
|
675
705
|
*
|
|
676
706
|
* ### Examples
|
|
@@ -696,6 +726,10 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
696
726
|
/**
|
|
697
727
|
* Creates a savepoint with a given name.
|
|
698
728
|
*
|
|
729
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
730
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
731
|
+
* exit the loop before creating a savepoint.
|
|
732
|
+
*
|
|
699
733
|
* See {@link rollbackToSavepoint} and {@link releaseSavepoint}.
|
|
700
734
|
*
|
|
701
735
|
* For a type-safe experience, you should use the returned instance from now on.
|
|
@@ -726,6 +760,10 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
726
760
|
/**
|
|
727
761
|
* Rolls back to a savepoint with a given name.
|
|
728
762
|
*
|
|
763
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
764
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
765
|
+
* exit the loop before rolling back to a savepoint.
|
|
766
|
+
*
|
|
729
767
|
* See {@link savepoint} and {@link releaseSavepoint}.
|
|
730
768
|
*
|
|
731
769
|
* You must use the same instance returned by {@link savepoint}, or
|
|
@@ -757,6 +795,10 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
757
795
|
/**
|
|
758
796
|
* Releases a savepoint with a given name.
|
|
759
797
|
*
|
|
798
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
799
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
800
|
+
* exit the loop before releasing a savepoint.
|
|
801
|
+
*
|
|
760
802
|
* See {@link savepoint} and {@link rollbackToSavepoint}.
|
|
761
803
|
*
|
|
762
804
|
* You must use the same instance returned by {@link savepoint}, or
|
|
@@ -834,8 +876,13 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
834
876
|
*/
|
|
835
877
|
withTables<T extends Record<string, Record<string, any>>>(): ControlledTransaction<DrainOuterGeneric<DB & T>, S>;
|
|
836
878
|
}
|
|
879
|
+
interface ControlledTransctionState {
|
|
880
|
+
isCommitted: boolean;
|
|
881
|
+
isRolledBack: boolean;
|
|
882
|
+
}
|
|
837
883
|
interface ControlledTransactionProps extends KyselyProps {
|
|
838
884
|
readonly connection: ControlledConnection;
|
|
885
|
+
readonly state?: ControlledTransctionState;
|
|
839
886
|
}
|
|
840
887
|
export declare class Command<T> {
|
|
841
888
|
#private;
|
package/dist/cjs/kysely.js
CHANGED
|
@@ -27,7 +27,8 @@ Symbol.asyncDispose ??= Symbol('Symbol.asyncDispose');
|
|
|
27
27
|
* The main Kysely class.
|
|
28
28
|
*
|
|
29
29
|
* You should create one instance of `Kysely` per database using the {@link Kysely}
|
|
30
|
-
* constructor.
|
|
30
|
+
* constructor. The dialect manages database connections and may use a shared
|
|
31
|
+
* pool or database instance.
|
|
31
32
|
*
|
|
32
33
|
* ### Examples
|
|
33
34
|
*
|
|
@@ -436,7 +437,16 @@ class Kysely extends query_creator_js_1.QueryCreator {
|
|
|
436
437
|
/**
|
|
437
438
|
* Releases all resources and disconnects from the database.
|
|
438
439
|
*
|
|
439
|
-
*
|
|
440
|
+
* Call this when you are done using the `Kysely` instance and Kysely is
|
|
441
|
+
* responsible for closing its connections, pool, or database instance.
|
|
442
|
+
*
|
|
443
|
+
* If the pool or database instance is shared with other consumers or its
|
|
444
|
+
* lifecycle is managed elsewhere, skip this call. Let the application close it
|
|
445
|
+
* once all consumers, including Kysely, have finished. No separate cleanup of
|
|
446
|
+
* the `Kysely` instance is needed.
|
|
447
|
+
*
|
|
448
|
+
* The driver is initialized lazily. If initialization hasn't started, this
|
|
449
|
+
* method does nothing.
|
|
440
450
|
*/
|
|
441
451
|
async destroy() {
|
|
442
452
|
await this.#props.driver.destroy();
|
|
@@ -613,10 +623,17 @@ class ControlledTransactionBuilder {
|
|
|
613
623
|
const settings = { isolationLevel, accessMode };
|
|
614
624
|
(0, driver_js_1.validateTransactionSettings)(settings);
|
|
615
625
|
const connection = await (0, provide_controlled_connection_js_1.provideControlledConnection)(this.#props.executor);
|
|
616
|
-
|
|
626
|
+
try {
|
|
627
|
+
await this.#props.driver.beginTransaction(connection.connection, settings);
|
|
628
|
+
}
|
|
629
|
+
catch (error) {
|
|
630
|
+
connection.release();
|
|
631
|
+
throw error;
|
|
632
|
+
}
|
|
617
633
|
return new ControlledTransaction({
|
|
618
634
|
...props,
|
|
619
635
|
connection,
|
|
636
|
+
state: { isCommitted: false, isRolledBack: false },
|
|
620
637
|
executor: this.#props.executor.withConnectionProvider(new single_connection_provider_js_1.SingleConnectionProvider(connection.connection)),
|
|
621
638
|
});
|
|
622
639
|
}
|
|
@@ -625,29 +642,35 @@ exports.ControlledTransactionBuilder = ControlledTransactionBuilder;
|
|
|
625
642
|
class ControlledTransaction extends Transaction {
|
|
626
643
|
#props;
|
|
627
644
|
#compileQuery;
|
|
628
|
-
#state;
|
|
629
645
|
constructor(props) {
|
|
630
|
-
const
|
|
631
|
-
|
|
646
|
+
const transactionState = props.state ?? {
|
|
647
|
+
isCommitted: false,
|
|
648
|
+
isRolledBack: false,
|
|
649
|
+
};
|
|
650
|
+
const controlledProps = {
|
|
632
651
|
...props,
|
|
633
|
-
|
|
652
|
+
state: transactionState,
|
|
653
|
+
executor: new NotCommittedOrRolledBackAssertingExecutor(props.executor, transactionState),
|
|
634
654
|
};
|
|
635
|
-
const { connection, ...transactionProps } =
|
|
655
|
+
const { connection, state, ...transactionProps } = controlledProps;
|
|
636
656
|
super(transactionProps);
|
|
637
|
-
this.#props = (0, object_utils_js_1.freeze)(
|
|
638
|
-
this.#state = state;
|
|
657
|
+
this.#props = (0, object_utils_js_1.freeze)(controlledProps);
|
|
639
658
|
const queryId = (0, query_id_js_1.createQueryId)();
|
|
640
|
-
this.#compileQuery = (node) =>
|
|
659
|
+
this.#compileQuery = (node) => controlledProps.executor.compileQuery(node, queryId);
|
|
641
660
|
}
|
|
642
661
|
get isCommitted() {
|
|
643
|
-
return this.#state.isCommitted;
|
|
662
|
+
return this.#props.state.isCommitted;
|
|
644
663
|
}
|
|
645
664
|
get isRolledBack() {
|
|
646
|
-
return this.#state.isRolledBack;
|
|
665
|
+
return this.#props.state.isRolledBack;
|
|
647
666
|
}
|
|
648
667
|
/**
|
|
649
668
|
* Commits the transaction.
|
|
650
669
|
*
|
|
670
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
671
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
672
|
+
* exit the loop before committing.
|
|
673
|
+
*
|
|
651
674
|
* See {@link rollback}.
|
|
652
675
|
*
|
|
653
676
|
* ### Examples
|
|
@@ -670,16 +693,24 @@ class ControlledTransaction extends Transaction {
|
|
|
670
693
|
* ```
|
|
671
694
|
*/
|
|
672
695
|
commit() {
|
|
673
|
-
assertNotCommittedOrRolledBack(this.#state);
|
|
674
696
|
return new Command(async () => {
|
|
675
|
-
await this.#props.
|
|
676
|
-
|
|
677
|
-
|
|
697
|
+
await this.#props.executor.provideConnection(async (connection) => {
|
|
698
|
+
await this.#props.driver.commitTransaction(connection);
|
|
699
|
+
this.#props.state.isCommitted = true;
|
|
700
|
+
this.#props.connection.release();
|
|
701
|
+
});
|
|
678
702
|
});
|
|
679
703
|
}
|
|
680
704
|
/**
|
|
681
705
|
* Rolls back the transaction.
|
|
682
706
|
*
|
|
707
|
+
* The connection is released even if the rollback fails, so the transaction
|
|
708
|
+
* cannot be used afterwards in either case.
|
|
709
|
+
*
|
|
710
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
711
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
712
|
+
* exit the loop before rolling back.
|
|
713
|
+
*
|
|
683
714
|
* See {@link commit} and {@link rollbackToSavepoint}.
|
|
684
715
|
*
|
|
685
716
|
* ### Examples
|
|
@@ -702,16 +733,26 @@ class ControlledTransaction extends Transaction {
|
|
|
702
733
|
* ```
|
|
703
734
|
*/
|
|
704
735
|
rollback() {
|
|
705
|
-
assertNotCommittedOrRolledBack(this.#state);
|
|
706
736
|
return new Command(async () => {
|
|
707
|
-
await this.#props.
|
|
708
|
-
|
|
709
|
-
|
|
737
|
+
await this.#props.executor.provideConnection(async (connection) => {
|
|
738
|
+
// A failed rollback can't be meaningfully retried (e.g. dead connection).
|
|
739
|
+
try {
|
|
740
|
+
await this.#props.driver.rollbackTransaction(connection);
|
|
741
|
+
}
|
|
742
|
+
finally {
|
|
743
|
+
this.#props.state.isRolledBack = true;
|
|
744
|
+
this.#props.connection.release();
|
|
745
|
+
}
|
|
746
|
+
});
|
|
710
747
|
});
|
|
711
748
|
}
|
|
712
749
|
/**
|
|
713
750
|
* Creates a savepoint with a given name.
|
|
714
751
|
*
|
|
752
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
753
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
754
|
+
* exit the loop before creating a savepoint.
|
|
755
|
+
*
|
|
715
756
|
* See {@link rollbackToSavepoint} and {@link releaseSavepoint}.
|
|
716
757
|
*
|
|
717
758
|
* For a type-safe experience, you should use the returned instance from now on.
|
|
@@ -739,15 +780,20 @@ class ControlledTransaction extends Transaction {
|
|
|
739
780
|
* ```
|
|
740
781
|
*/
|
|
741
782
|
savepoint(savepointName) {
|
|
742
|
-
assertNotCommittedOrRolledBack(this.#state);
|
|
743
783
|
return new Command(async () => {
|
|
744
|
-
await this.#props.
|
|
784
|
+
await this.#props.executor.provideConnection(async (connection) => {
|
|
785
|
+
await this.#props.driver.savepoint?.(connection, savepointName, this.#compileQuery);
|
|
786
|
+
});
|
|
745
787
|
return new ControlledTransaction({ ...this.#props });
|
|
746
788
|
});
|
|
747
789
|
}
|
|
748
790
|
/**
|
|
749
791
|
* Rolls back to a savepoint with a given name.
|
|
750
792
|
*
|
|
793
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
794
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
795
|
+
* exit the loop before rolling back to a savepoint.
|
|
796
|
+
*
|
|
751
797
|
* See {@link savepoint} and {@link releaseSavepoint}.
|
|
752
798
|
*
|
|
753
799
|
* You must use the same instance returned by {@link savepoint}, or
|
|
@@ -776,15 +822,20 @@ class ControlledTransaction extends Transaction {
|
|
|
776
822
|
* ```
|
|
777
823
|
*/
|
|
778
824
|
rollbackToSavepoint(savepointName) {
|
|
779
|
-
assertNotCommittedOrRolledBack(this.#state);
|
|
780
825
|
return new Command(async () => {
|
|
781
|
-
await this.#props.
|
|
826
|
+
await this.#props.executor.provideConnection(async (connection) => {
|
|
827
|
+
await this.#props.driver.rollbackToSavepoint?.(connection, savepointName, this.#compileQuery);
|
|
828
|
+
});
|
|
782
829
|
return new ControlledTransaction({ ...this.#props });
|
|
783
830
|
});
|
|
784
831
|
}
|
|
785
832
|
/**
|
|
786
833
|
* Releases a savepoint with a given name.
|
|
787
834
|
*
|
|
835
|
+
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
836
|
+
* before awaiting this command. When consuming a stream with `for await`,
|
|
837
|
+
* exit the loop before releasing a savepoint.
|
|
838
|
+
*
|
|
788
839
|
* See {@link savepoint} and {@link rollbackToSavepoint}.
|
|
789
840
|
*
|
|
790
841
|
* You must use the same instance returned by {@link savepoint}, or
|
|
@@ -818,9 +869,10 @@ class ControlledTransaction extends Transaction {
|
|
|
818
869
|
* ```
|
|
819
870
|
*/
|
|
820
871
|
releaseSavepoint(savepointName) {
|
|
821
|
-
assertNotCommittedOrRolledBack(this.#state);
|
|
822
872
|
return new Command(async () => {
|
|
823
|
-
await this.#props.
|
|
873
|
+
await this.#props.executor.provideConnection(async (connection) => {
|
|
874
|
+
await this.#props.driver.releaseSavepoint?.(connection, savepointName, this.#compileQuery);
|
|
875
|
+
});
|
|
824
876
|
return new ControlledTransaction({ ...this.#props });
|
|
825
877
|
});
|
|
826
878
|
}
|
|
@@ -899,15 +951,23 @@ class NotCommittedOrRolledBackAssertingExecutor {
|
|
|
899
951
|
return this.#executor.compileQuery(node, queryId);
|
|
900
952
|
}
|
|
901
953
|
provideConnection(consumer) {
|
|
902
|
-
|
|
954
|
+
assertNotCommittedOrRolledBack(this.#state);
|
|
955
|
+
return this.#executor.provideConnection(async (connection) => {
|
|
956
|
+
assertNotCommittedOrRolledBack(this.#state);
|
|
957
|
+
return await consumer(connection);
|
|
958
|
+
});
|
|
903
959
|
}
|
|
904
960
|
executeQuery(compiledQuery) {
|
|
905
961
|
assertNotCommittedOrRolledBack(this.#state);
|
|
906
|
-
return this.#executor
|
|
962
|
+
return this.#executor
|
|
963
|
+
.withConnectionProvider(this)
|
|
964
|
+
.executeQuery(compiledQuery);
|
|
907
965
|
}
|
|
908
966
|
stream(compiledQuery, chunkSize) {
|
|
909
967
|
assertNotCommittedOrRolledBack(this.#state);
|
|
910
|
-
return this.#executor
|
|
968
|
+
return this.#executor
|
|
969
|
+
.withConnectionProvider(this)
|
|
970
|
+
.stream(compiledQuery, chunkSize);
|
|
911
971
|
}
|
|
912
972
|
withConnectionProvider(connectionProvider) {
|
|
913
973
|
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withConnectionProvider(connectionProvider), this.#state);
|