kysely 0.29.7 → 0.29.8
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/dialect/mssql/mssql-driver.d.ts +3 -0
- package/dist/dialect/mysql/mysql-driver.d.ts +3 -0
- package/dist/dialect/pglite/pglite-driver.d.ts +3 -0
- package/dist/dialect/postgres/postgres-dialect-config.d.ts +2 -2
- package/dist/dialect/postgres/postgres-driver.d.ts +6 -1
- package/dist/dialect/postgres/postgres-driver.js +31 -3
- package/dist/dialect/sqlite/sqlite-driver.d.ts +3 -0
- package/dist/driver/aborted-transaction-error.d.ts +11 -0
- package/dist/driver/aborted-transaction-error.js +16 -0
- package/dist/driver/driver.d.ts +3 -0
- package/dist/driver/dummy-driver.d.ts +3 -0
- package/dist/driver/runtime-driver.d.ts +3 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +1 -0
- package/dist/kysely.d.ts +9 -4
- package/dist/kysely.js +53 -28
- package/package.json +6 -6
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.29.8)
|
|
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)
|
|
@@ -25,6 +25,9 @@ export declare class MssqlDriver implements Driver {
|
|
|
25
25
|
beginTransaction(connection: MssqlConnection, settings: TransactionSettings): Promise<void>;
|
|
26
26
|
/**
|
|
27
27
|
* Commits a transaction.
|
|
28
|
+
*
|
|
29
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
30
|
+
* the transaction was rolled back instead of committed.
|
|
28
31
|
*/
|
|
29
32
|
commitTransaction(connection: MssqlConnection): Promise<void>;
|
|
30
33
|
/**
|
|
@@ -25,6 +25,9 @@ export declare class MysqlDriver implements Driver {
|
|
|
25
25
|
beginTransaction(connection: DatabaseConnection, settings: TransactionSettings): Promise<void>;
|
|
26
26
|
/**
|
|
27
27
|
* Commits a transaction.
|
|
28
|
+
*
|
|
29
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
30
|
+
* the transaction was rolled back instead of committed.
|
|
28
31
|
*/
|
|
29
32
|
commitTransaction(connection: DatabaseConnection): Promise<void>;
|
|
30
33
|
/**
|
|
@@ -20,6 +20,9 @@ export declare class PGliteDriver implements Driver {
|
|
|
20
20
|
beginTransaction(connection: PGliteConnection): Promise<void>;
|
|
21
21
|
/**
|
|
22
22
|
* Commits a transaction.
|
|
23
|
+
*
|
|
24
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
25
|
+
* the transaction was rolled back instead of committed.
|
|
23
26
|
*/
|
|
24
27
|
commitTransaction(connection: PGliteConnection): Promise<void>;
|
|
25
28
|
/**
|
|
@@ -95,7 +95,7 @@ export type PostgresClientConstructor = new (options: any) => PostgresClient;
|
|
|
95
95
|
* https://node-postgres.com/apis/pool#releasing-clients
|
|
96
96
|
*/
|
|
97
97
|
export interface PostgresPoolClient extends Omit<PostgresClient, 'connect' | 'end'> {
|
|
98
|
-
release(): void;
|
|
98
|
+
release(destroy?: boolean): void;
|
|
99
99
|
}
|
|
100
100
|
/**
|
|
101
101
|
* This interface is pg driver's `Cursor` class that kysely needs.
|
|
@@ -124,7 +124,7 @@ export type PostgresCursorConstructor = new <T>(sql: string, parameters: unknown
|
|
|
124
124
|
* https://node-postgres.com/apis/result
|
|
125
125
|
*/
|
|
126
126
|
export interface PostgresQueryResult<R> {
|
|
127
|
-
command: 'UPDATE' | 'DELETE' | 'INSERT' | 'SELECT' | 'MERGE';
|
|
127
|
+
command: 'UPDATE' | 'DELETE' | 'INSERT' | 'SELECT' | 'MERGE' | 'COMMIT' | 'ROLLBACK';
|
|
128
128
|
rowCount: number;
|
|
129
129
|
rows: R[];
|
|
130
130
|
}
|
|
@@ -5,6 +5,7 @@ import type { QueryCompiler } from '../../query-compiler/query-compiler.js';
|
|
|
5
5
|
import type { AbortableOperationOptions } from '../../util/abort.js';
|
|
6
6
|
import type { PostgresClientConstructor, PostgresCursorConstructor, PostgresDialectConfig, PostgresPoolClient } from './postgres-dialect-config.js';
|
|
7
7
|
declare const PRIVATE_RELEASE_METHOD: unique symbol;
|
|
8
|
+
declare const PRIVATE_MARK_FOR_DISCARD_METHOD: unique symbol;
|
|
8
9
|
export declare class PostgresDriver implements Driver {
|
|
9
10
|
#private;
|
|
10
11
|
constructor(config: PostgresDialectConfig);
|
|
@@ -25,12 +26,15 @@ export declare class PostgresDriver implements Driver {
|
|
|
25
26
|
beginTransaction(connection: DatabaseConnection, settings: TransactionSettings): Promise<void>;
|
|
26
27
|
/**
|
|
27
28
|
* Commits a transaction.
|
|
29
|
+
*
|
|
30
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
31
|
+
* the transaction was rolled back instead of committed.
|
|
28
32
|
*/
|
|
29
33
|
commitTransaction(connection: DatabaseConnection): Promise<void>;
|
|
30
34
|
/**
|
|
31
35
|
* Rolls back a transaction.
|
|
32
36
|
*/
|
|
33
|
-
rollbackTransaction(connection:
|
|
37
|
+
rollbackTransaction(connection: PostgresConnection): Promise<void>;
|
|
34
38
|
savepoint(connection: DatabaseConnection, savepointName: string, compileQuery: QueryCompiler['compileQuery']): Promise<void>;
|
|
35
39
|
rollbackToSavepoint(connection: DatabaseConnection, savepointName: string, compileQuery: QueryCompiler['compileQuery']): Promise<void>;
|
|
36
40
|
releaseSavepoint(connection: DatabaseConnection, savepointName: string, compileQuery: QueryCompiler['compileQuery']): Promise<void>;
|
|
@@ -57,5 +61,6 @@ declare class PostgresConnection implements DatabaseConnection {
|
|
|
57
61
|
killSession(controlConnectionProvider: ControlConnectionProvider): Promise<void>;
|
|
58
62
|
streamQuery<O>(compiledQuery: CompiledQuery, chunkSize: number): AsyncIterableIterator<QueryResult<O>>;
|
|
59
63
|
[PRIVATE_RELEASE_METHOD](): void;
|
|
64
|
+
[PRIVATE_MARK_FOR_DISCARD_METHOD](): void;
|
|
60
65
|
}
|
|
61
66
|
export {};
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
/// <reference types="./postgres-driver.d.ts" />
|
|
2
|
+
import { AbortedTransactionError } from '../../driver/aborted-transaction-error.js';
|
|
2
3
|
import { parseSavepointCommand } from '../../parser/savepoint-parser.js';
|
|
3
4
|
import { CompiledQuery } from '../../query-compiler/compiled-query.js';
|
|
4
5
|
import { isFunction, freeze } from '../../util/object-utils.js';
|
|
5
6
|
import { createQueryId } from '../../util/query-id.js';
|
|
6
7
|
import { extendStackTrace } from '../../util/stack-trace-utils.js';
|
|
7
8
|
const PRIVATE_RELEASE_METHOD = Symbol();
|
|
9
|
+
const PRIVATE_MARK_FOR_DISCARD_METHOD = Symbol();
|
|
8
10
|
export class PostgresDriver {
|
|
9
11
|
#config;
|
|
10
12
|
#connections = new WeakMap();
|
|
@@ -58,10 +60,21 @@ export class PostgresDriver {
|
|
|
58
60
|
await connection.executeQuery(CompiledQuery.raw(sql));
|
|
59
61
|
}
|
|
60
62
|
async commitTransaction(connection) {
|
|
61
|
-
await connection.executeQuery(CompiledQuery.raw('commit'));
|
|
63
|
+
const { rows } = await connection.executeQuery(CompiledQuery.raw('commit'));
|
|
64
|
+
// PostgreSQL completes COMMIT with a ROLLBACK tag if an earlier
|
|
65
|
+
// statement error left the transaction aborted.
|
|
66
|
+
if (rows[0]?.command === 'ROLLBACK') {
|
|
67
|
+
throw new AbortedTransactionError();
|
|
68
|
+
}
|
|
62
69
|
}
|
|
63
70
|
async rollbackTransaction(connection) {
|
|
64
|
-
|
|
71
|
+
try {
|
|
72
|
+
await connection.executeQuery(CompiledQuery.raw('rollback'));
|
|
73
|
+
}
|
|
74
|
+
catch (err) {
|
|
75
|
+
connection[PRIVATE_MARK_FOR_DISCARD_METHOD]();
|
|
76
|
+
throw err;
|
|
77
|
+
}
|
|
65
78
|
}
|
|
66
79
|
async savepoint(connection, savepointName, compileQuery) {
|
|
67
80
|
await connection.executeQuery(compileQuery(parseSavepointCommand('savepoint', savepointName), createQueryId()));
|
|
@@ -88,6 +101,7 @@ class PostgresConnection {
|
|
|
88
101
|
#options;
|
|
89
102
|
#queryId;
|
|
90
103
|
#pid;
|
|
104
|
+
#discarded;
|
|
91
105
|
constructor(client, options) {
|
|
92
106
|
this.#client = client;
|
|
93
107
|
this.#options = options;
|
|
@@ -107,16 +121,21 @@ class PostgresConnection {
|
|
|
107
121
|
this.#pid = processID;
|
|
108
122
|
}
|
|
109
123
|
else {
|
|
124
|
+
this.#assertNotDiscarded();
|
|
110
125
|
const { rows: [{ pid }], } = await this.#client.query('select pg_backend_pid() as pid', []);
|
|
111
126
|
this.#pid = Number(pid);
|
|
112
127
|
}
|
|
113
128
|
}
|
|
114
129
|
async executeQuery(compiledQuery) {
|
|
130
|
+
this.#assertNotDiscarded();
|
|
115
131
|
try {
|
|
116
132
|
// this helps ensure we don't cancel the wrong query when aborted.
|
|
117
133
|
this.#queryId = compiledQuery.queryId;
|
|
118
134
|
const result = await this.#client.query(compiledQuery.sql, compiledQuery.parameters);
|
|
119
135
|
const { command, rowCount, rows } = result;
|
|
136
|
+
if (command === 'ROLLBACK' || command === 'COMMIT') {
|
|
137
|
+
return { rows: [{ command }] };
|
|
138
|
+
}
|
|
120
139
|
return {
|
|
121
140
|
numAffectedRows: command === 'INSERT' ||
|
|
122
141
|
command === 'UPDATE' ||
|
|
@@ -142,6 +161,7 @@ class PostgresConnection {
|
|
|
142
161
|
if (!this.#options.cursor) {
|
|
143
162
|
throw new Error("`cursor` is not present in your postgres dialect config. It's required to make streaming work in postgres.");
|
|
144
163
|
}
|
|
164
|
+
this.#assertNotDiscarded();
|
|
145
165
|
// this helps ensure we don't cancel the wrong query when aborted.
|
|
146
166
|
this.#queryId = compiledQuery.queryId;
|
|
147
167
|
const cursor = this.#client.query(new this.#options.cursor(compiledQuery.sql, compiledQuery.parameters.slice()));
|
|
@@ -163,7 +183,15 @@ class PostgresConnection {
|
|
|
163
183
|
}
|
|
164
184
|
}
|
|
165
185
|
[PRIVATE_RELEASE_METHOD]() {
|
|
166
|
-
this.#client.release();
|
|
186
|
+
this.#client.release(Boolean(this.#discarded));
|
|
187
|
+
}
|
|
188
|
+
[PRIVATE_MARK_FOR_DISCARD_METHOD]() {
|
|
189
|
+
this.#discarded = true;
|
|
190
|
+
}
|
|
191
|
+
#assertNotDiscarded() {
|
|
192
|
+
if (this.#discarded) {
|
|
193
|
+
throw new Error('Postgres connection has been discarded');
|
|
194
|
+
}
|
|
167
195
|
}
|
|
168
196
|
async #executeControlQuery(query, controlConnectionProvider) {
|
|
169
197
|
if (!this.#queryId) {
|
|
@@ -23,6 +23,9 @@ export declare class SqliteDriver implements Driver {
|
|
|
23
23
|
beginTransaction(connection: DatabaseConnection): Promise<void>;
|
|
24
24
|
/**
|
|
25
25
|
* Commits a transaction.
|
|
26
|
+
*
|
|
27
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
28
|
+
* the transaction was rolled back instead of committed.
|
|
26
29
|
*/
|
|
27
30
|
commitTransaction(connection: DatabaseConnection): Promise<void>;
|
|
28
31
|
/**
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
declare const ABORTED_TRANSACTION_ERROR: unique symbol;
|
|
2
|
+
/**
|
|
3
|
+
* Thrown when the database rolls back a transaction instead of committing it.
|
|
4
|
+
*/
|
|
5
|
+
export declare class AbortedTransactionError extends Error {
|
|
6
|
+
name: string;
|
|
7
|
+
readonly [ABORTED_TRANSACTION_ERROR] = true;
|
|
8
|
+
constructor();
|
|
9
|
+
}
|
|
10
|
+
export declare function isAbortedTransactionError(error: unknown): error is AbortedTransactionError;
|
|
11
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="./aborted-transaction-error.d.ts" />
|
|
2
|
+
import { isObject } from '../util/object-utils.js';
|
|
3
|
+
const ABORTED_TRANSACTION_ERROR = Symbol.for('kysely.AbortedTransactionError');
|
|
4
|
+
/**
|
|
5
|
+
* Thrown when the database rolls back a transaction instead of committing it.
|
|
6
|
+
*/
|
|
7
|
+
export class AbortedTransactionError extends Error {
|
|
8
|
+
name = 'AbortedTransactionError';
|
|
9
|
+
[ABORTED_TRANSACTION_ERROR] = true;
|
|
10
|
+
constructor() {
|
|
11
|
+
super('Transaction was rolled back instead of committed');
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
export function isAbortedTransactionError(error) {
|
|
15
|
+
return isObject(error) && ABORTED_TRANSACTION_ERROR in error;
|
|
16
|
+
}
|
package/dist/driver/driver.d.ts
CHANGED
|
@@ -24,6 +24,9 @@ export interface Driver {
|
|
|
24
24
|
beginTransaction(connection: DatabaseConnection, settings: TransactionSettings): Promise<void>;
|
|
25
25
|
/**
|
|
26
26
|
* Commits a transaction.
|
|
27
|
+
*
|
|
28
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
29
|
+
* the transaction was rolled back instead of committed.
|
|
27
30
|
*/
|
|
28
31
|
commitTransaction(connection: DatabaseConnection): Promise<void>;
|
|
29
32
|
/**
|
|
@@ -55,6 +55,9 @@ export declare class DummyDriver implements Driver {
|
|
|
55
55
|
beginTransaction(): Promise<void>;
|
|
56
56
|
/**
|
|
57
57
|
* Commits a transaction.
|
|
58
|
+
*
|
|
59
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
60
|
+
* the transaction was rolled back instead of committed.
|
|
58
61
|
*/
|
|
59
62
|
commitTransaction(): Promise<void>;
|
|
60
63
|
/**
|
|
@@ -33,6 +33,9 @@ export declare class RuntimeDriver implements Driver {
|
|
|
33
33
|
beginTransaction(connection: DatabaseConnection, settings: TransactionSettings): Promise<void>;
|
|
34
34
|
/**
|
|
35
35
|
* Commits a transaction.
|
|
36
|
+
*
|
|
37
|
+
* Throws {@link AbortedTransactionError} if the database confirms that
|
|
38
|
+
* the transaction was rolled back instead of committed.
|
|
36
39
|
*/
|
|
37
40
|
commitTransaction(connection: DatabaseConnection): Promise<void>;
|
|
38
41
|
/**
|
package/dist/index.d.ts
CHANGED
|
@@ -60,6 +60,7 @@ export * from './dynamic/dynamic.js';
|
|
|
60
60
|
export * from './dynamic/dynamic-reference-builder.js';
|
|
61
61
|
export * from './dynamic/dynamic-table-builder.js';
|
|
62
62
|
export * from './driver/driver.js';
|
|
63
|
+
export * from './driver/aborted-transaction-error.js';
|
|
63
64
|
export type * from './driver/database-connection.js';
|
|
64
65
|
export type * from './driver/connection-provider.js';
|
|
65
66
|
export * from './driver/default-connection-provider.js';
|
package/dist/index.js
CHANGED
|
@@ -53,6 +53,7 @@ export * from './dynamic/dynamic.js';
|
|
|
53
53
|
export * from './dynamic/dynamic-reference-builder.js';
|
|
54
54
|
export * from './dynamic/dynamic-table-builder.js';
|
|
55
55
|
export * from './driver/driver.js';
|
|
56
|
+
export * from './driver/aborted-transaction-error.js';
|
|
56
57
|
export * from './driver/default-connection-provider.js';
|
|
57
58
|
export * from './driver/single-connection-provider.js';
|
|
58
59
|
export * from './driver/dummy-driver.js';
|
package/dist/kysely.d.ts
CHANGED
|
@@ -626,6 +626,9 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
626
626
|
/**
|
|
627
627
|
* Commits the transaction.
|
|
628
628
|
*
|
|
629
|
+
* If the database rolls back instead of committing, marks the transaction
|
|
630
|
+
* as rolled back, releases the connection and throws {@link AbortedTransactionError}.
|
|
631
|
+
*
|
|
629
632
|
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
630
633
|
* before awaiting this command. When consuming a stream with `for await`,
|
|
631
634
|
* exit the loop before committing.
|
|
@@ -655,6 +658,9 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
655
658
|
/**
|
|
656
659
|
* Rolls back the transaction.
|
|
657
660
|
*
|
|
661
|
+
* If a commit already reported that the database rolled back the transaction,
|
|
662
|
+
* succeeds without sending another rollback command.
|
|
663
|
+
*
|
|
658
664
|
* The connection is released even if the rollback fails, so the transaction
|
|
659
665
|
* cannot be used afterwards in either case.
|
|
660
666
|
*
|
|
@@ -815,13 +821,12 @@ export declare class ControlledTransaction<DB, S extends string[] = []> extends
|
|
|
815
821
|
$omitTables<T extends keyof DB>(): ControlledTransaction<DB extends object ? Omit<DB, T> : DB, S>;
|
|
816
822
|
$pickTables<T extends keyof DB>(): ControlledTransaction<DB extends object ? Pick<DB, T> : DB, S>;
|
|
817
823
|
}
|
|
818
|
-
interface
|
|
819
|
-
|
|
820
|
-
isRolledBack: boolean;
|
|
824
|
+
interface ControlledTransactionState {
|
|
825
|
+
status: 'active' | 'committed' | 'rolled back' | 'aborted';
|
|
821
826
|
}
|
|
822
827
|
interface ControlledTransactionProps extends KyselyProps {
|
|
823
828
|
readonly connection: ControlledConnection;
|
|
824
|
-
readonly
|
|
829
|
+
readonly transactionState: ControlledTransactionState;
|
|
825
830
|
}
|
|
826
831
|
export declare class Command<T> {
|
|
827
832
|
#private;
|
package/dist/kysely.js
CHANGED
|
@@ -6,6 +6,7 @@ import { QueryCreator } from './query-creator.js';
|
|
|
6
6
|
import { DefaultQueryExecutor } from './query-executor/default-query-executor.js';
|
|
7
7
|
import { freeze, isObject, isUndefined } from './util/object-utils.js';
|
|
8
8
|
import { RuntimeDriver } from './driver/runtime-driver.js';
|
|
9
|
+
import { isAbortedTransactionError, } from './driver/aborted-transaction-error.js';
|
|
9
10
|
import { SingleConnectionProvider } from './driver/single-connection-provider.js';
|
|
10
11
|
import { validateTransactionSettings, } from './driver/driver.js';
|
|
11
12
|
import { createFunctionModule, } from './query-builder/function-module.js';
|
|
@@ -680,8 +681,10 @@ export class TransactionBuilder {
|
|
|
680
681
|
const settings = { isolationLevel, accessMode };
|
|
681
682
|
validateTransactionSettings(settings);
|
|
682
683
|
return this.#props.executor.provideConnection(async (connection) => {
|
|
683
|
-
const
|
|
684
|
-
|
|
684
|
+
const transactionState = {
|
|
685
|
+
status: 'active',
|
|
686
|
+
};
|
|
687
|
+
const executor = new NotCommittedOrRolledBackAssertingExecutor(this.#props.executor.withConnectionProvider(new SingleConnectionProvider(connection)), transactionState);
|
|
685
688
|
const transaction = new Transaction({ ...kyselyProps, executor });
|
|
686
689
|
let transactionBegun = false;
|
|
687
690
|
try {
|
|
@@ -689,13 +692,16 @@ export class TransactionBuilder {
|
|
|
689
692
|
transactionBegun = true;
|
|
690
693
|
const result = await callback(transaction);
|
|
691
694
|
await this.#props.driver.commitTransaction(connection);
|
|
692
|
-
|
|
695
|
+
transactionState.status = 'committed';
|
|
693
696
|
return result;
|
|
694
697
|
}
|
|
695
698
|
catch (error) {
|
|
696
|
-
if (
|
|
699
|
+
if (isAbortedTransactionError(error)) {
|
|
700
|
+
transactionState.status = 'aborted';
|
|
701
|
+
}
|
|
702
|
+
else if (transactionBegun) {
|
|
697
703
|
await this.#props.driver.rollbackTransaction(connection);
|
|
698
|
-
|
|
704
|
+
transactionState.status = 'rolled back';
|
|
699
705
|
}
|
|
700
706
|
throw error;
|
|
701
707
|
}
|
|
@@ -734,7 +740,7 @@ export class ControlledTransactionBuilder {
|
|
|
734
740
|
return new ControlledTransaction({
|
|
735
741
|
...props,
|
|
736
742
|
connection,
|
|
737
|
-
|
|
743
|
+
transactionState: { status: 'active' },
|
|
738
744
|
executor: this.#props.executor.withConnectionProvider(new SingleConnectionProvider(connection.connection)),
|
|
739
745
|
});
|
|
740
746
|
}
|
|
@@ -745,23 +751,27 @@ export class ControlledTransaction extends Transaction {
|
|
|
745
751
|
constructor(props) {
|
|
746
752
|
props = {
|
|
747
753
|
...props,
|
|
748
|
-
executor: new NotCommittedOrRolledBackAssertingExecutor(props.executor, props.
|
|
754
|
+
executor: new NotCommittedOrRolledBackAssertingExecutor(props.executor, props.transactionState),
|
|
749
755
|
};
|
|
750
|
-
const { connection,
|
|
756
|
+
const { connection, transactionState, ...transactionProps } = props;
|
|
751
757
|
super(transactionProps);
|
|
752
758
|
this.#props = freeze(props);
|
|
753
759
|
const queryId = createQueryId();
|
|
754
760
|
this.#compileQuery = (node) => props.executor.compileQuery(node, queryId);
|
|
755
761
|
}
|
|
756
762
|
get isCommitted() {
|
|
757
|
-
return this.#props.
|
|
763
|
+
return this.#props.transactionState.status === 'committed';
|
|
758
764
|
}
|
|
759
765
|
get isRolledBack() {
|
|
760
|
-
return this.#props.
|
|
766
|
+
return (this.#props.transactionState.status === 'rolled back' ||
|
|
767
|
+
this.#props.transactionState.status === 'aborted');
|
|
761
768
|
}
|
|
762
769
|
/**
|
|
763
770
|
* Commits the transaction.
|
|
764
771
|
*
|
|
772
|
+
* If the database rolls back instead of committing, marks the transaction
|
|
773
|
+
* as rolled back, releases the connection and throws {@link AbortedTransactionError}.
|
|
774
|
+
*
|
|
765
775
|
* Waits for ongoing queries to finish. Streams must be exhausted or closed
|
|
766
776
|
* before awaiting this command. When consuming a stream with `for await`,
|
|
767
777
|
* exit the loop before committing.
|
|
@@ -790,8 +800,17 @@ export class ControlledTransaction extends Transaction {
|
|
|
790
800
|
commit() {
|
|
791
801
|
return new Command(async () => {
|
|
792
802
|
await this.#props.executor.provideConnection(async (connection) => {
|
|
793
|
-
|
|
794
|
-
|
|
803
|
+
try {
|
|
804
|
+
await this.#props.driver.commitTransaction(connection);
|
|
805
|
+
}
|
|
806
|
+
catch (error) {
|
|
807
|
+
if (isAbortedTransactionError(error)) {
|
|
808
|
+
this.#props.transactionState.status = 'aborted';
|
|
809
|
+
this.#props.connection.release();
|
|
810
|
+
}
|
|
811
|
+
throw error;
|
|
812
|
+
}
|
|
813
|
+
this.#props.transactionState.status = 'committed';
|
|
795
814
|
this.#props.connection.release();
|
|
796
815
|
});
|
|
797
816
|
});
|
|
@@ -799,6 +818,9 @@ export class ControlledTransaction extends Transaction {
|
|
|
799
818
|
/**
|
|
800
819
|
* Rolls back the transaction.
|
|
801
820
|
*
|
|
821
|
+
* If a commit already reported that the database rolled back the transaction,
|
|
822
|
+
* succeeds without sending another rollback command.
|
|
823
|
+
*
|
|
802
824
|
* The connection is released even if the rollback fails, so the transaction
|
|
803
825
|
* cannot be used afterwards in either case.
|
|
804
826
|
*
|
|
@@ -829,13 +851,16 @@ export class ControlledTransaction extends Transaction {
|
|
|
829
851
|
*/
|
|
830
852
|
rollback() {
|
|
831
853
|
return new Command(async () => {
|
|
854
|
+
if (this.#props.transactionState.status === 'aborted') {
|
|
855
|
+
return;
|
|
856
|
+
}
|
|
832
857
|
await this.#props.executor.provideConnection(async (connection) => {
|
|
833
858
|
// A failed rollback can't be meaningfully retried (e.g. dead connection).
|
|
834
859
|
try {
|
|
835
860
|
await this.#props.driver.rollbackTransaction(connection);
|
|
836
861
|
}
|
|
837
862
|
finally {
|
|
838
|
-
this.#props.
|
|
863
|
+
this.#props.transactionState.status = 'rolled back';
|
|
839
864
|
this.#props.connection.release();
|
|
840
865
|
}
|
|
841
866
|
});
|
|
@@ -1014,11 +1039,11 @@ export class Command {
|
|
|
1014
1039
|
return await this.#cb();
|
|
1015
1040
|
}
|
|
1016
1041
|
}
|
|
1017
|
-
function assertNotCommittedOrRolledBack(
|
|
1018
|
-
if (
|
|
1042
|
+
function assertNotCommittedOrRolledBack(transactionState) {
|
|
1043
|
+
if (transactionState.status === 'committed') {
|
|
1019
1044
|
throw new Error('Transaction is already committed');
|
|
1020
1045
|
}
|
|
1021
|
-
if (
|
|
1046
|
+
if (transactionState.status !== 'active') {
|
|
1022
1047
|
throw new Error('Transaction is already rolled back');
|
|
1023
1048
|
}
|
|
1024
1049
|
}
|
|
@@ -1030,13 +1055,13 @@ function assertNotCommittedOrRolledBack(state) {
|
|
|
1030
1055
|
*/
|
|
1031
1056
|
class NotCommittedOrRolledBackAssertingExecutor {
|
|
1032
1057
|
#executor;
|
|
1033
|
-
#
|
|
1034
|
-
constructor(executor,
|
|
1058
|
+
#transactionState;
|
|
1059
|
+
constructor(executor, transactionState) {
|
|
1035
1060
|
this.#executor =
|
|
1036
1061
|
executor instanceof NotCommittedOrRolledBackAssertingExecutor
|
|
1037
1062
|
? executor.#executor
|
|
1038
1063
|
: executor;
|
|
1039
|
-
this.#
|
|
1064
|
+
this.#transactionState = transactionState;
|
|
1040
1065
|
}
|
|
1041
1066
|
get adapter() {
|
|
1042
1067
|
return this.#executor.adapter;
|
|
@@ -1051,37 +1076,37 @@ class NotCommittedOrRolledBackAssertingExecutor {
|
|
|
1051
1076
|
return this.#executor.compileQuery(node, queryId);
|
|
1052
1077
|
}
|
|
1053
1078
|
provideConnection(consumer, options) {
|
|
1054
|
-
assertNotCommittedOrRolledBack(this.#
|
|
1079
|
+
assertNotCommittedOrRolledBack(this.#transactionState);
|
|
1055
1080
|
return this.#executor.provideConnection(async (connection) => {
|
|
1056
|
-
assertNotCommittedOrRolledBack(this.#
|
|
1081
|
+
assertNotCommittedOrRolledBack(this.#transactionState);
|
|
1057
1082
|
return await consumer(connection);
|
|
1058
1083
|
}, options);
|
|
1059
1084
|
}
|
|
1060
1085
|
executeQuery(compiledQuery, options) {
|
|
1061
|
-
assertNotCommittedOrRolledBack(this.#
|
|
1086
|
+
assertNotCommittedOrRolledBack(this.#transactionState);
|
|
1062
1087
|
return this.#executor
|
|
1063
1088
|
.withConnectionProvider(this)
|
|
1064
1089
|
.executeQuery(compiledQuery, options);
|
|
1065
1090
|
}
|
|
1066
1091
|
stream(compiledQuery, chunkSize, options) {
|
|
1067
|
-
assertNotCommittedOrRolledBack(this.#
|
|
1092
|
+
assertNotCommittedOrRolledBack(this.#transactionState);
|
|
1068
1093
|
return this.#executor
|
|
1069
1094
|
.withConnectionProvider(this)
|
|
1070
1095
|
.stream(compiledQuery, chunkSize, options);
|
|
1071
1096
|
}
|
|
1072
1097
|
withConnectionProvider(connectionProvider) {
|
|
1073
|
-
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withConnectionProvider(connectionProvider), this.#
|
|
1098
|
+
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withConnectionProvider(connectionProvider), this.#transactionState);
|
|
1074
1099
|
}
|
|
1075
1100
|
withPlugin(plugin) {
|
|
1076
|
-
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPlugin(plugin), this.#
|
|
1101
|
+
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPlugin(plugin), this.#transactionState);
|
|
1077
1102
|
}
|
|
1078
1103
|
withPlugins(plugins) {
|
|
1079
|
-
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPlugins(plugins), this.#
|
|
1104
|
+
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPlugins(plugins), this.#transactionState);
|
|
1080
1105
|
}
|
|
1081
1106
|
withPluginAtFront(plugin) {
|
|
1082
|
-
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPluginAtFront(plugin), this.#
|
|
1107
|
+
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withPluginAtFront(plugin), this.#transactionState);
|
|
1083
1108
|
}
|
|
1084
1109
|
withoutPlugins() {
|
|
1085
|
-
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withoutPlugins(), this.#
|
|
1110
|
+
return new NotCommittedOrRolledBackAssertingExecutor(this.#executor.withoutPlugins(), this.#transactionState);
|
|
1086
1111
|
}
|
|
1087
1112
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "kysely",
|
|
3
|
-
"version": "0.29.
|
|
3
|
+
"version": "0.29.8",
|
|
4
4
|
"description": "Type safe SQL query builder",
|
|
5
5
|
"repository": {
|
|
6
6
|
"type": "git",
|
|
@@ -62,17 +62,17 @@
|
|
|
62
62
|
],
|
|
63
63
|
"devDependencies": {
|
|
64
64
|
"@arethetypeswrong/cli": "0.18.5",
|
|
65
|
-
"@electric-sql/pglite": "0.5.
|
|
65
|
+
"@electric-sql/pglite": "0.5.13",
|
|
66
66
|
"@types/better-sqlite3": "9.6.0",
|
|
67
67
|
"@types/chai": "5.2.3",
|
|
68
68
|
"@types/chai-as-promised": "8.0.2",
|
|
69
69
|
"@types/mocha": "10.0.10",
|
|
70
|
-
"@types/node": "26.6.
|
|
70
|
+
"@types/node": "26.6.6",
|
|
71
71
|
"@types/pg": "8.23.1",
|
|
72
72
|
"@types/pg-cursor": "2.7.2",
|
|
73
73
|
"@types/prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:@types/lodash.merge@4.6.1",
|
|
74
74
|
"@types/semver": "7.8.0",
|
|
75
|
-
"@types/sinon": "22.0.
|
|
75
|
+
"@types/sinon": "22.0.2",
|
|
76
76
|
"better-sqlite3": "13.0.3",
|
|
77
77
|
"chai": "6.3.0",
|
|
78
78
|
"chai-as-promised": "8.0.2",
|
|
@@ -86,11 +86,11 @@
|
|
|
86
86
|
"playwright": "1.64.1",
|
|
87
87
|
"prettier": "3.9.10",
|
|
88
88
|
"prototype-pollution-vulnerable-lodash.merge-dont-upgrade": "npm:lodash.merge@4.6.1",
|
|
89
|
-
"remeda": "2.
|
|
89
|
+
"remeda": "2.57.0",
|
|
90
90
|
"semver": "7.8.5",
|
|
91
91
|
"sinon": "22.1.0",
|
|
92
92
|
"tarn": "3.1.2",
|
|
93
|
-
"tedious": "20.3.
|
|
93
|
+
"tedious": "20.3.8",
|
|
94
94
|
"tsd": "0.33.0",
|
|
95
95
|
"tsx": "4.23.15",
|
|
96
96
|
"typescript": "7.0.2",
|