kysely 0.16.5 → 0.16.9
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 +139 -14
- package/dist/cjs/dialect/mysql/mysql-dialect.js +2 -1
- package/dist/cjs/dialect/mysql/mysql-driver.js +1 -1
- package/dist/cjs/dialect/postgres/postgres-dialect.js +2 -1
- package/dist/cjs/dialect/postgres/postgres-driver.js +1 -1
- package/dist/cjs/dialect/sqlite/sqlite-dialect.js +2 -1
- package/dist/cjs/dialect/sqlite/sqlite-driver.js +1 -1
- package/dist/cjs/driver/dummy-driver.d.ts +68 -0
- package/dist/cjs/driver/dummy-driver.js +62 -0
- package/dist/cjs/driver/runtime-driver.d.ts +1 -1
- package/dist/cjs/driver/runtime-driver.js +30 -33
- package/dist/cjs/index-nodeless.d.ts +2 -0
- package/dist/cjs/index-nodeless.js +2 -0
- package/dist/cjs/kysely.d.ts +8 -6
- package/dist/cjs/kysely.js +8 -6
- package/dist/cjs/migration/migrator.d.ts +22 -0
- package/dist/cjs/migration/migrator.js +23 -1
- package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-plugin.d.ts +48 -0
- package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-plugin.js +19 -0
- package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-transformer.d.ts +9 -0
- package/dist/cjs/plugin/deduplicate-joins/deduplicate-joins-transformer.js +42 -0
- package/dist/cjs/plugin/{immediate-value.ts → immediate-value}/immediate-value-plugin.d.ts +0 -0
- package/dist/cjs/plugin/{immediate-value.ts → immediate-value}/immediate-value-plugin.js +0 -0
- package/dist/cjs/plugin/{immediate-value.ts → immediate-value}/immediate-value-transformer.d.ts +0 -0
- package/dist/cjs/plugin/{immediate-value.ts → immediate-value}/immediate-value-transformer.js +0 -0
- package/dist/cjs/query-builder/delete-query-builder.d.ts +51 -9
- package/dist/cjs/query-builder/delete-query-builder.js +56 -8
- package/dist/cjs/query-builder/function-builder.d.ts +29 -5
- package/dist/cjs/query-builder/function-builder.js +31 -7
- package/dist/cjs/query-builder/insert-query-builder.d.ts +53 -11
- package/dist/cjs/query-builder/insert-query-builder.js +58 -10
- package/dist/cjs/query-builder/select-query-builder.d.ts +58 -16
- package/dist/cjs/query-builder/select-query-builder.js +64 -15
- package/dist/cjs/query-builder/update-query-builder.d.ts +52 -9
- package/dist/cjs/query-builder/update-query-builder.js +57 -8
- package/dist/cjs/query-creator.d.ts +2 -2
- package/dist/cjs/query-creator.js +2 -2
- package/dist/cjs/query-executor/query-executor.js +3 -2
- package/dist/cjs/raw-builder/raw-builder.d.ts +2 -2
- package/dist/cjs/raw-builder/raw-builder.js +8 -1
- package/dist/cjs/schema/create-view-builder.js +1 -1
- package/dist/cjs/util/log.d.ts +1 -0
- package/dist/cjs/util/log.js +3 -0
- package/dist/cjs/util/object-utils.d.ts +1 -0
- package/dist/cjs/util/object-utils.js +50 -1
- package/dist/cjs/util/type-utils.d.ts +21 -0
- package/dist/esm/dialect/mysql/mysql-dialect.js +2 -1
- package/dist/esm/dialect/mysql/mysql-driver.js +2 -2
- package/dist/esm/dialect/postgres/postgres-dialect.js +2 -1
- package/dist/esm/dialect/postgres/postgres-driver.js +2 -2
- package/dist/esm/dialect/sqlite/sqlite-dialect.js +2 -1
- package/dist/esm/dialect/sqlite/sqlite-driver.js +2 -2
- package/dist/esm/driver/dummy-driver.d.ts +68 -0
- package/dist/esm/driver/dummy-driver.js +59 -0
- package/dist/esm/driver/runtime-driver.d.ts +1 -1
- package/dist/esm/driver/runtime-driver.js +29 -32
- package/dist/esm/index-nodeless.d.ts +2 -0
- package/dist/esm/index-nodeless.js +2 -0
- package/dist/esm/kysely.d.ts +8 -6
- package/dist/esm/kysely.js +8 -6
- package/dist/esm/migration/migrator.d.ts +22 -0
- package/dist/esm/migration/migrator.js +23 -1
- package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-plugin.d.ts +48 -0
- package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-plugin.js +16 -0
- package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-transformer.d.ts +9 -0
- package/dist/esm/plugin/deduplicate-joins/deduplicate-joins-transformer.js +39 -0
- package/dist/esm/plugin/{immediate-value.ts → immediate-value}/immediate-value-plugin.d.ts +0 -0
- package/dist/esm/plugin/{immediate-value.ts → immediate-value}/immediate-value-plugin.js +0 -0
- package/dist/esm/plugin/{immediate-value.ts → immediate-value}/immediate-value-transformer.d.ts +0 -0
- package/dist/esm/plugin/{immediate-value.ts → immediate-value}/immediate-value-transformer.js +0 -0
- package/dist/esm/query-builder/delete-query-builder.d.ts +51 -9
- package/dist/esm/query-builder/delete-query-builder.js +56 -8
- package/dist/esm/query-builder/function-builder.d.ts +29 -5
- package/dist/esm/query-builder/function-builder.js +31 -7
- package/dist/esm/query-builder/insert-query-builder.d.ts +53 -11
- package/dist/esm/query-builder/insert-query-builder.js +58 -10
- package/dist/esm/query-builder/select-query-builder.d.ts +58 -16
- package/dist/esm/query-builder/select-query-builder.js +64 -15
- package/dist/esm/query-builder/update-query-builder.d.ts +52 -9
- package/dist/esm/query-builder/update-query-builder.js +57 -8
- package/dist/esm/query-creator.d.ts +2 -2
- package/dist/esm/query-creator.js +2 -2
- package/dist/esm/query-executor/query-executor.js +3 -2
- package/dist/esm/raw-builder/raw-builder.d.ts +2 -2
- package/dist/esm/raw-builder/raw-builder.js +8 -1
- package/dist/esm/schema/create-view-builder.js +1 -1
- package/dist/esm/util/log.d.ts +1 -0
- package/dist/esm/util/log.js +3 -0
- package/dist/esm/util/object-utils.d.ts +1 -0
- package/dist/esm/util/object-utils.js +48 -0
- package/dist/esm/util/type-utils.d.ts +21 -0
- package/package.json +11 -5
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.noop = exports.isReadonlyArray = exports.asReadonlyArray = exports.asArray = exports.freeze = exports.getLast = exports.isObject = exports.isFunction = exports.isBuffer = exports.isBigInt = exports.isDate = exports.isNull = exports.isBoolean = exports.isNumber = exports.isString = exports.isEmpty = void 0;
|
|
3
|
+
exports.compare = exports.noop = exports.isReadonlyArray = exports.asReadonlyArray = exports.asArray = exports.freeze = exports.getLast = exports.isObject = exports.isFunction = exports.isBuffer = exports.isBigInt = exports.isDate = exports.isNull = exports.isBoolean = exports.isNumber = exports.isString = exports.isEmpty = void 0;
|
|
4
4
|
function isEmpty(obj) {
|
|
5
5
|
if (Array.isArray(obj) || isString(obj) || isBuffer(obj)) {
|
|
6
6
|
return obj.length === 0;
|
|
@@ -83,3 +83,52 @@ function noop(obj) {
|
|
|
83
83
|
return obj;
|
|
84
84
|
}
|
|
85
85
|
exports.noop = noop;
|
|
86
|
+
function compare(obj1, obj2) {
|
|
87
|
+
if (isReadonlyArray(obj1) && isReadonlyArray(obj2)) {
|
|
88
|
+
return compareArrays(obj1, obj2);
|
|
89
|
+
}
|
|
90
|
+
else if (isObject(obj1) && isObject(obj2)) {
|
|
91
|
+
return compareObjects(obj1, obj2);
|
|
92
|
+
}
|
|
93
|
+
return obj1 === obj2;
|
|
94
|
+
}
|
|
95
|
+
exports.compare = compare;
|
|
96
|
+
function compareArrays(arr1, arr2) {
|
|
97
|
+
if (arr1.length !== arr2.length) {
|
|
98
|
+
return false;
|
|
99
|
+
}
|
|
100
|
+
for (let i = 0; i < arr1.length; ++i) {
|
|
101
|
+
if (!compare(arr1[i], arr2[i])) {
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
return true;
|
|
106
|
+
}
|
|
107
|
+
function compareObjects(obj1, obj2) {
|
|
108
|
+
if (isBuffer(obj1) && isBuffer(obj2)) {
|
|
109
|
+
return compareBuffers(obj1, obj2);
|
|
110
|
+
}
|
|
111
|
+
else if (isDate(obj1) && isDate(obj2)) {
|
|
112
|
+
return compareDates(obj1, obj2);
|
|
113
|
+
}
|
|
114
|
+
return compareGenericObjects(obj1, obj2);
|
|
115
|
+
}
|
|
116
|
+
function compareBuffers(buf1, buf2) {
|
|
117
|
+
return Buffer.compare(buf1, buf2) === 0;
|
|
118
|
+
}
|
|
119
|
+
function compareDates(date1, date2) {
|
|
120
|
+
return date1.getTime() === date2.getTime();
|
|
121
|
+
}
|
|
122
|
+
function compareGenericObjects(obj1, obj2) {
|
|
123
|
+
const keys1 = Object.keys(obj1);
|
|
124
|
+
const keys2 = Object.keys(obj2);
|
|
125
|
+
if (keys1.length !== keys2.length) {
|
|
126
|
+
return false;
|
|
127
|
+
}
|
|
128
|
+
for (const key of keys1) {
|
|
129
|
+
if (!compare(obj1[key], obj2[key])) {
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
return true;
|
|
134
|
+
}
|
|
@@ -111,3 +111,24 @@ export declare type UnknownRow = Record<string, unknown>;
|
|
|
111
111
|
export declare type Nullable<T> = {
|
|
112
112
|
[P in keyof T]: T[P] | null;
|
|
113
113
|
};
|
|
114
|
+
/**
|
|
115
|
+
* Takes all properties from T1 and merges all properties from T2
|
|
116
|
+
* that don't exist in T1 as optional properties.
|
|
117
|
+
*
|
|
118
|
+
* Example:
|
|
119
|
+
*
|
|
120
|
+
* interface Person {
|
|
121
|
+
* name: string
|
|
122
|
+
* age: number
|
|
123
|
+
* }
|
|
124
|
+
*
|
|
125
|
+
* interface Pet {
|
|
126
|
+
* name: string
|
|
127
|
+
* species: 'cat' | 'dog'
|
|
128
|
+
* }
|
|
129
|
+
*
|
|
130
|
+
* type Merged = MergePartial<Person, Pet>
|
|
131
|
+
*
|
|
132
|
+
* // { name: string, age: number, species?: 'cat' | 'dog' }
|
|
133
|
+
*/
|
|
134
|
+
export declare type MergePartial<T1, T2> = T1 & Partial<Omit<T2, keyof T1>>;
|
|
@@ -3,6 +3,7 @@ import { MysqlDriver } from './mysql-driver.js';
|
|
|
3
3
|
import { MysqlQueryCompiler } from './mysql-query-compiler.js';
|
|
4
4
|
import { MysqlIntrospector } from './mysql-introspector.js';
|
|
5
5
|
import { MysqlAdapter } from './mysql-adapter.js';
|
|
6
|
+
import { freeze } from '../../util/object-utils.js';
|
|
6
7
|
/**
|
|
7
8
|
* MySQL dialect that uses the [mysql2](https://github.com/sidorares/node-mysql2#readme) library.
|
|
8
9
|
*
|
|
@@ -13,7 +14,7 @@ import { MysqlAdapter } from './mysql-adapter.js';
|
|
|
13
14
|
export class MysqlDialect {
|
|
14
15
|
#config;
|
|
15
16
|
constructor(config) {
|
|
16
|
-
this.#config = config;
|
|
17
|
+
this.#config = freeze({ ...config });
|
|
17
18
|
}
|
|
18
19
|
createDriver() {
|
|
19
20
|
return new MysqlDriver(this.#config);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="./mysql-driver.d.ts" />
|
|
2
2
|
import { CompiledQuery } from '../../query-compiler/compiled-query.js';
|
|
3
|
-
import { isFunction, isObject } from '../../util/object-utils.js';
|
|
3
|
+
import { isFunction, isObject, freeze } from '../../util/object-utils.js';
|
|
4
4
|
const PRIVATE_RELEASE_METHOD = Symbol();
|
|
5
5
|
export class MysqlDriver {
|
|
6
6
|
#config;
|
|
7
7
|
#connections = new WeakMap();
|
|
8
8
|
#pool;
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.#config = config;
|
|
10
|
+
this.#config = freeze({ ...config });
|
|
11
11
|
}
|
|
12
12
|
async init() {
|
|
13
13
|
// Import the `mysql2` module here instead at the top of the file
|
|
@@ -3,6 +3,7 @@ import { PostgresDriver } from './postgres-driver.js';
|
|
|
3
3
|
import { PostgresIntrospector } from './postgres-introspector.js';
|
|
4
4
|
import { PostgresQueryCompiler } from './postgres-query-compiler.js';
|
|
5
5
|
import { PostgresAdapter } from './postgres-adapter.js';
|
|
6
|
+
import { freeze } from '../../util/object-utils.js';
|
|
6
7
|
/**
|
|
7
8
|
* PostgreSQL dialect that uses the [pg](https://node-postgres.com/) library.
|
|
8
9
|
*
|
|
@@ -16,7 +17,7 @@ import { PostgresAdapter } from './postgres-adapter.js';
|
|
|
16
17
|
export class PostgresDialect {
|
|
17
18
|
#config;
|
|
18
19
|
constructor(config) {
|
|
19
|
-
this.#config = config;
|
|
20
|
+
this.#config = freeze({ ...config });
|
|
20
21
|
}
|
|
21
22
|
createDriver() {
|
|
22
23
|
return new PostgresDriver(this.#config);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="./postgres-driver.d.ts" />
|
|
2
2
|
import { CompiledQuery } from '../../query-compiler/compiled-query.js';
|
|
3
|
-
import { isFunction } from '../../util/object-utils.js';
|
|
3
|
+
import { isFunction, freeze } from '../../util/object-utils.js';
|
|
4
4
|
const PRIVATE_RELEASE_METHOD = Symbol();
|
|
5
5
|
export class PostgresDriver {
|
|
6
6
|
#config;
|
|
7
7
|
#connections = new WeakMap();
|
|
8
8
|
#pool = null;
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.#config = config;
|
|
10
|
+
this.#config = freeze({ ...config });
|
|
11
11
|
}
|
|
12
12
|
async init() {
|
|
13
13
|
// Import the `pg` module here instead at the top of the file
|
|
@@ -3,6 +3,7 @@ import { SqliteDriver } from './sqlite-driver.js';
|
|
|
3
3
|
import { SqliteQueryCompiler } from './sqlite-query-compiler.js';
|
|
4
4
|
import { SqliteIntrospector } from './sqlite-introspector.js';
|
|
5
5
|
import { SqliteAdapter } from './sqlite-adapter.js';
|
|
6
|
+
import { freeze } from '../../util/object-utils.js';
|
|
6
7
|
/**
|
|
7
8
|
* SQLite dialect that uses the [better-sqlite3](https://github.com/JoshuaWise/better-sqlite3) library.
|
|
8
9
|
*
|
|
@@ -13,7 +14,7 @@ import { SqliteAdapter } from './sqlite-adapter.js';
|
|
|
13
14
|
export class SqliteDialect {
|
|
14
15
|
#config;
|
|
15
16
|
constructor(config) {
|
|
16
|
-
this.#config = config;
|
|
17
|
+
this.#config = freeze({ ...config });
|
|
17
18
|
}
|
|
18
19
|
createDriver() {
|
|
19
20
|
return new SqliteDriver(this.#config);
|
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
/// <reference types="./sqlite-driver.d.ts" />
|
|
2
2
|
import { CompiledQuery } from '../../query-compiler/compiled-query.js';
|
|
3
|
-
import { isBoolean, isFunction, isNumber } from '../../util/object-utils.js';
|
|
3
|
+
import { freeze, isBoolean, isFunction, isNumber, } from '../../util/object-utils.js';
|
|
4
4
|
export class SqliteDriver {
|
|
5
5
|
#config;
|
|
6
6
|
#connectionMutex = new ConnectionMutex();
|
|
7
7
|
#db;
|
|
8
8
|
#connection;
|
|
9
9
|
constructor(config) {
|
|
10
|
-
this.#config = config;
|
|
10
|
+
this.#config = freeze({ ...config });
|
|
11
11
|
}
|
|
12
12
|
async init() {
|
|
13
13
|
// Import the `better-sqlite3` module here instead at the top of the file
|
|
@@ -0,0 +1,68 @@
|
|
|
1
|
+
import { DatabaseConnection } from './database-connection.js';
|
|
2
|
+
import { Driver } from './driver.js';
|
|
3
|
+
/**
|
|
4
|
+
* A driver that does absolutely nothing.
|
|
5
|
+
*
|
|
6
|
+
* You can use this to create Kysely instances solely for building queries
|
|
7
|
+
*
|
|
8
|
+
* ### Examples
|
|
9
|
+
*
|
|
10
|
+
* This example creates a Kysely instance for building postgres queries:
|
|
11
|
+
*
|
|
12
|
+
* ```ts
|
|
13
|
+
* const db = new Kysely<Database>({
|
|
14
|
+
* dialect: {
|
|
15
|
+
* createAdapter() {
|
|
16
|
+
* return new PostgresAdapter()
|
|
17
|
+
* },
|
|
18
|
+
* createDriver() {
|
|
19
|
+
* return new DummyDriver()
|
|
20
|
+
* },
|
|
21
|
+
* createIntrospector(db: Kysely<any>) {
|
|
22
|
+
* return new PostgresIntrospector(db)
|
|
23
|
+
* },
|
|
24
|
+
* createQueryCompiler() {
|
|
25
|
+
* return new PostgresQueryCompiler()
|
|
26
|
+
* },
|
|
27
|
+
* },
|
|
28
|
+
* })
|
|
29
|
+
* ```
|
|
30
|
+
*/
|
|
31
|
+
export declare class DummyDriver implements Driver {
|
|
32
|
+
/**
|
|
33
|
+
* Initializes the driver.
|
|
34
|
+
*
|
|
35
|
+
* After calling this method the driver should be usable and `acquireConnection` etc.
|
|
36
|
+
* methods should be callable.
|
|
37
|
+
*
|
|
38
|
+
* IMPORTANT: The underlying database engine driver (like [pg](https://node-postgres.com/))
|
|
39
|
+
* should be imported inside this function, not at the top of the driver file! This is
|
|
40
|
+
* important so that Kysely is usable without installing all database driver libraries
|
|
41
|
+
* it supports.
|
|
42
|
+
*/
|
|
43
|
+
init(): Promise<void>;
|
|
44
|
+
/**
|
|
45
|
+
* Acquires a new connection from the pool.
|
|
46
|
+
*/
|
|
47
|
+
acquireConnection(): Promise<DatabaseConnection>;
|
|
48
|
+
/**
|
|
49
|
+
* Begins a transaction.
|
|
50
|
+
*/
|
|
51
|
+
beginTransaction(): Promise<void>;
|
|
52
|
+
/**
|
|
53
|
+
* Commits a transaction.
|
|
54
|
+
*/
|
|
55
|
+
commitTransaction(): Promise<void>;
|
|
56
|
+
/**
|
|
57
|
+
* Rolls back a transaction.
|
|
58
|
+
*/
|
|
59
|
+
rollbackTransaction(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Releases a connection back to the pool.
|
|
62
|
+
*/
|
|
63
|
+
releaseConnection(): Promise<void>;
|
|
64
|
+
/**
|
|
65
|
+
* Destroys the driver and releases all resources.
|
|
66
|
+
*/
|
|
67
|
+
destroy(): Promise<void>;
|
|
68
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
/// <reference types="./dummy-driver.d.ts" />
|
|
2
|
+
/**
|
|
3
|
+
* A driver that does absolutely nothing.
|
|
4
|
+
*
|
|
5
|
+
* You can use this to create Kysely instances solely for building queries
|
|
6
|
+
*
|
|
7
|
+
* ### Examples
|
|
8
|
+
*
|
|
9
|
+
* This example creates a Kysely instance for building postgres queries:
|
|
10
|
+
*
|
|
11
|
+
* ```ts
|
|
12
|
+
* const db = new Kysely<Database>({
|
|
13
|
+
* dialect: {
|
|
14
|
+
* createAdapter() {
|
|
15
|
+
* return new PostgresAdapter()
|
|
16
|
+
* },
|
|
17
|
+
* createDriver() {
|
|
18
|
+
* return new DummyDriver()
|
|
19
|
+
* },
|
|
20
|
+
* createIntrospector(db: Kysely<any>) {
|
|
21
|
+
* return new PostgresIntrospector(db)
|
|
22
|
+
* },
|
|
23
|
+
* createQueryCompiler() {
|
|
24
|
+
* return new PostgresQueryCompiler()
|
|
25
|
+
* },
|
|
26
|
+
* },
|
|
27
|
+
* })
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
export class DummyDriver {
|
|
31
|
+
async init() {
|
|
32
|
+
// Nothing to do here.
|
|
33
|
+
}
|
|
34
|
+
async acquireConnection() {
|
|
35
|
+
return new DummyConnection();
|
|
36
|
+
}
|
|
37
|
+
async beginTransaction() {
|
|
38
|
+
// Nothing to do here.
|
|
39
|
+
}
|
|
40
|
+
async commitTransaction() {
|
|
41
|
+
// Nothing to do here.
|
|
42
|
+
}
|
|
43
|
+
async rollbackTransaction() {
|
|
44
|
+
// Nothing to do here.
|
|
45
|
+
}
|
|
46
|
+
async releaseConnection() {
|
|
47
|
+
// Nothing to do here.
|
|
48
|
+
}
|
|
49
|
+
async destroy() {
|
|
50
|
+
// Nothing to do here.
|
|
51
|
+
}
|
|
52
|
+
}
|
|
53
|
+
class DummyConnection {
|
|
54
|
+
async executeQuery() {
|
|
55
|
+
return {
|
|
56
|
+
rows: [],
|
|
57
|
+
};
|
|
58
|
+
}
|
|
59
|
+
}
|
|
@@ -28,7 +28,7 @@ export declare class RuntimeDriver implements Driver {
|
|
|
28
28
|
/**
|
|
29
29
|
* Releases a connection back to the pool.
|
|
30
30
|
*/
|
|
31
|
-
releaseConnection(
|
|
31
|
+
releaseConnection(connection: DatabaseConnection): Promise<void>;
|
|
32
32
|
/**
|
|
33
33
|
* Begins a transaction.
|
|
34
34
|
*/
|
|
@@ -10,7 +10,7 @@ export class RuntimeDriver {
|
|
|
10
10
|
#log;
|
|
11
11
|
#initPromise;
|
|
12
12
|
#destroyPromise;
|
|
13
|
-
#connections = new
|
|
13
|
+
#connections = new WeakSet();
|
|
14
14
|
constructor(driver, log) {
|
|
15
15
|
this.#driver = driver;
|
|
16
16
|
this.#log = log;
|
|
@@ -27,17 +27,16 @@ export class RuntimeDriver {
|
|
|
27
27
|
async acquireConnection() {
|
|
28
28
|
await this.init();
|
|
29
29
|
const connection = await this.#driver.acquireConnection();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
30
|
+
if (!this.#connections.has(connection)) {
|
|
31
|
+
if (this.#needsLogging()) {
|
|
32
|
+
this.#addLogging(connection);
|
|
33
|
+
}
|
|
34
|
+
this.#connections.add(connection);
|
|
34
35
|
}
|
|
35
|
-
return
|
|
36
|
+
return connection;
|
|
36
37
|
}
|
|
37
|
-
async releaseConnection(
|
|
38
|
-
|
|
39
|
-
await this.#driver.releaseConnection(runtimeConnection.connection);
|
|
40
|
-
}
|
|
38
|
+
async releaseConnection(connection) {
|
|
39
|
+
await this.#driver.releaseConnection(connection);
|
|
41
40
|
}
|
|
42
41
|
beginTransaction(connection, settings) {
|
|
43
42
|
return this.#driver.beginTransaction(connection, settings);
|
|
@@ -61,29 +60,27 @@ export class RuntimeDriver {
|
|
|
61
60
|
}
|
|
62
61
|
await this.#destroyPromise;
|
|
63
62
|
}
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
#connection;
|
|
67
|
-
#log;
|
|
68
|
-
get connection() {
|
|
69
|
-
return this.#connection;
|
|
70
|
-
}
|
|
71
|
-
constructor(connection, log) {
|
|
72
|
-
this.#connection = connection;
|
|
73
|
-
this.#log = log;
|
|
63
|
+
#needsLogging() {
|
|
64
|
+
return (this.#log.isLevelEnabled('query') || this.#log.isLevelEnabled('error'));
|
|
74
65
|
}
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
66
|
+
// This method monkey patches the database connection's executeQuery method
|
|
67
|
+
// by adding logging code around it. Monkey patching is not pretty, but it's
|
|
68
|
+
// the best option in this case.
|
|
69
|
+
#addLogging(connection) {
|
|
70
|
+
const executeQuery = connection.executeQuery;
|
|
71
|
+
connection.executeQuery = async (compiledQuery) => {
|
|
72
|
+
const startTime = performanceNow();
|
|
73
|
+
try {
|
|
74
|
+
return await executeQuery.call(connection, compiledQuery);
|
|
75
|
+
}
|
|
76
|
+
catch (error) {
|
|
77
|
+
this.#logError(error);
|
|
78
|
+
throw error;
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
this.#logQuery(compiledQuery, startTime);
|
|
82
|
+
}
|
|
83
|
+
};
|
|
87
84
|
}
|
|
88
85
|
#logError(error) {
|
|
89
86
|
this.#log.error(() => ({
|
|
@@ -40,6 +40,7 @@ export * from './driver/database-connection.js';
|
|
|
40
40
|
export * from './driver/connection-provider.js';
|
|
41
41
|
export * from './driver/default-connection-provider.js';
|
|
42
42
|
export * from './driver/single-connection-provider.js';
|
|
43
|
+
export * from './driver/dummy-driver.js';
|
|
43
44
|
export * from './dialect/dialect.js';
|
|
44
45
|
export * from './dialect/dialect-adapter.js';
|
|
45
46
|
export * from './dialect/dialect-adapter-base.js';
|
|
@@ -58,6 +59,7 @@ export * from './query-compiler/query-compiler.js';
|
|
|
58
59
|
export * from './migration/migrator.js';
|
|
59
60
|
export * from './plugin/kysely-plugin.js';
|
|
60
61
|
export * from './plugin/camel-case/camel-case-plugin.js';
|
|
62
|
+
export * from './plugin/deduplicate-joins/deduplicate-joins-plugin.js';
|
|
61
63
|
export * from './operation-node/add-column-node.js';
|
|
62
64
|
export * from './operation-node/add-constraint-node.js';
|
|
63
65
|
export * from './operation-node/alias-node.js';
|
|
@@ -41,6 +41,7 @@ export * from './driver/database-connection.js';
|
|
|
41
41
|
export * from './driver/connection-provider.js';
|
|
42
42
|
export * from './driver/default-connection-provider.js';
|
|
43
43
|
export * from './driver/single-connection-provider.js';
|
|
44
|
+
export * from './driver/dummy-driver.js';
|
|
44
45
|
export * from './dialect/dialect.js';
|
|
45
46
|
export * from './dialect/dialect-adapter.js';
|
|
46
47
|
export * from './dialect/dialect-adapter-base.js';
|
|
@@ -59,6 +60,7 @@ export * from './query-compiler/query-compiler.js';
|
|
|
59
60
|
export * from './migration/migrator.js';
|
|
60
61
|
export * from './plugin/kysely-plugin.js';
|
|
61
62
|
export * from './plugin/camel-case/camel-case-plugin.js';
|
|
63
|
+
export * from './plugin/deduplicate-joins/deduplicate-joins-plugin.js';
|
|
62
64
|
export * from './operation-node/add-column-node.js';
|
|
63
65
|
export * from './operation-node/add-constraint-node.js';
|
|
64
66
|
export * from './operation-node/alias-node.js';
|
package/dist/esm/kysely.d.ts
CHANGED
|
@@ -22,22 +22,24 @@ import { DialectAdapter } from './dialect/dialect-adapter.js';
|
|
|
22
22
|
* This example assumes your database has tables `person` and `pet`:
|
|
23
23
|
*
|
|
24
24
|
* ```ts
|
|
25
|
-
*
|
|
26
|
-
*
|
|
25
|
+
* import { Kysely, Generated, PostgresDialect } from 'kysely'
|
|
26
|
+
*
|
|
27
|
+
* interface PersonTable {
|
|
28
|
+
* id: Generated<number>
|
|
27
29
|
* first_name: string
|
|
28
30
|
* last_name: string
|
|
29
31
|
* }
|
|
30
32
|
*
|
|
31
|
-
* interface
|
|
32
|
-
* id: number
|
|
33
|
+
* interface PetTable {
|
|
34
|
+
* id: Generated<number>
|
|
33
35
|
* owner_id: number
|
|
34
36
|
* name: string
|
|
35
37
|
* species 'cat' | 'dog'
|
|
36
38
|
* }
|
|
37
39
|
*
|
|
38
40
|
* interface Database {
|
|
39
|
-
* person:
|
|
40
|
-
* pet:
|
|
41
|
+
* person: PersonTable,
|
|
42
|
+
* pet: PetTable
|
|
41
43
|
* }
|
|
42
44
|
*
|
|
43
45
|
* const db = new Kysely<Database>({
|
package/dist/esm/kysely.js
CHANGED
|
@@ -24,22 +24,24 @@ import { PRIVATE_ADAPTER } from './util/private-symbols.js';
|
|
|
24
24
|
* This example assumes your database has tables `person` and `pet`:
|
|
25
25
|
*
|
|
26
26
|
* ```ts
|
|
27
|
-
*
|
|
28
|
-
*
|
|
27
|
+
* import { Kysely, Generated, PostgresDialect } from 'kysely'
|
|
28
|
+
*
|
|
29
|
+
* interface PersonTable {
|
|
30
|
+
* id: Generated<number>
|
|
29
31
|
* first_name: string
|
|
30
32
|
* last_name: string
|
|
31
33
|
* }
|
|
32
34
|
*
|
|
33
|
-
* interface
|
|
34
|
-
* id: number
|
|
35
|
+
* interface PetTable {
|
|
36
|
+
* id: Generated<number>
|
|
35
37
|
* owner_id: number
|
|
36
38
|
* name: string
|
|
37
39
|
* species 'cat' | 'dog'
|
|
38
40
|
* }
|
|
39
41
|
*
|
|
40
42
|
* interface Database {
|
|
41
|
-
* person:
|
|
42
|
-
* pet:
|
|
43
|
+
* person: PersonTable,
|
|
44
|
+
* pet: PetTable
|
|
43
45
|
* }
|
|
44
46
|
*
|
|
45
47
|
* const db = new Kysely<Database>({
|
|
@@ -36,6 +36,12 @@ export interface Migration {
|
|
|
36
36
|
export declare class Migrator {
|
|
37
37
|
#private;
|
|
38
38
|
constructor(props: MigratorProps);
|
|
39
|
+
/**
|
|
40
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
41
|
+
*
|
|
42
|
+
* The returned array is sorted by migration name.
|
|
43
|
+
*/
|
|
44
|
+
getMigrations(): Promise<ReadonlyArray<MigrationInfo>>;
|
|
39
45
|
/**
|
|
40
46
|
* Runs all migrations that have not yet been run.
|
|
41
47
|
*
|
|
@@ -219,3 +225,19 @@ export interface MigrationProvider {
|
|
|
219
225
|
export interface NoMigrations {
|
|
220
226
|
readonly __noMigrations__: true;
|
|
221
227
|
}
|
|
228
|
+
export interface MigrationInfo {
|
|
229
|
+
/**
|
|
230
|
+
* Name of the migration.
|
|
231
|
+
*/
|
|
232
|
+
name: string;
|
|
233
|
+
/**
|
|
234
|
+
* The actual migration.
|
|
235
|
+
*/
|
|
236
|
+
migration: Migration;
|
|
237
|
+
/**
|
|
238
|
+
* When was the migration executed.
|
|
239
|
+
*
|
|
240
|
+
* If this is undefined, the migration hasn't been executed yet.
|
|
241
|
+
*/
|
|
242
|
+
executedAt?: Date;
|
|
243
|
+
}
|
|
@@ -30,6 +30,28 @@ export class Migrator {
|
|
|
30
30
|
constructor(props) {
|
|
31
31
|
this.#props = freeze(props);
|
|
32
32
|
}
|
|
33
|
+
/**
|
|
34
|
+
* Returns a {@link MigrationInfo} object for each migration.
|
|
35
|
+
*
|
|
36
|
+
* The returned array is sorted by migration name.
|
|
37
|
+
*/
|
|
38
|
+
async getMigrations() {
|
|
39
|
+
const executedMigrations = (await this.#doesTableExists(MIGRATION_TABLE))
|
|
40
|
+
? await this.#props.db
|
|
41
|
+
.selectFrom(MIGRATION_TABLE)
|
|
42
|
+
.select(['name', 'timestamp'])
|
|
43
|
+
.execute()
|
|
44
|
+
: [];
|
|
45
|
+
const migrations = await this.#resolveMigrations();
|
|
46
|
+
return migrations.map(({ name, ...migration }) => {
|
|
47
|
+
const executed = executedMigrations.find((it) => it.name === name);
|
|
48
|
+
return {
|
|
49
|
+
name,
|
|
50
|
+
migration,
|
|
51
|
+
executedAt: executed ? new Date(executed.timestamp) : undefined,
|
|
52
|
+
};
|
|
53
|
+
});
|
|
54
|
+
}
|
|
33
55
|
/**
|
|
34
56
|
* Runs all migrations that have not yet been run.
|
|
35
57
|
*
|
|
@@ -213,7 +235,7 @@ export class Migrator {
|
|
|
213
235
|
try {
|
|
214
236
|
await this.#props.db
|
|
215
237
|
.insertInto(MIGRATION_LOCK_TABLE)
|
|
216
|
-
.values({ id: MIGRATION_LOCK_ID })
|
|
238
|
+
.values({ id: MIGRATION_LOCK_ID, is_locked: 0 })
|
|
217
239
|
.execute();
|
|
218
240
|
}
|
|
219
241
|
catch (error) {
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { QueryResult } from '../../driver/database-connection.js';
|
|
2
|
+
import { RootOperationNode } from '../../query-compiler/query-compiler.js';
|
|
3
|
+
import { UnknownRow } from '../../util/type-utils.js';
|
|
4
|
+
import { KyselyPlugin, PluginTransformQueryArgs, PluginTransformResultArgs } from '../kysely-plugin.js';
|
|
5
|
+
/**
|
|
6
|
+
* Plugin that removes duplicate joins from queries.
|
|
7
|
+
*
|
|
8
|
+
* See [this recipe](https://github.com/koskimas/kysely/tree/master/recipes/deduplicate-joins.md)
|
|
9
|
+
*/
|
|
10
|
+
export declare class DeduplicateJoinsPlugin implements KyselyPlugin {
|
|
11
|
+
#private;
|
|
12
|
+
/**
|
|
13
|
+
* This is called for each query before it is executed. You can modify the query by
|
|
14
|
+
* transforming its {@link OperationNode} tree provided in {@link PluginTransformQueryArgs.node | args.node}
|
|
15
|
+
* and returning the transformed tree. You'd usually want to use an {@link OperationNodeTransformer}
|
|
16
|
+
* for this.
|
|
17
|
+
*
|
|
18
|
+
* If you need to pass some query-related data between this method and `transformResult` you
|
|
19
|
+
* can use a `WeakMap` with {@link PluginTransformQueryArgs.queryId | args.queryId} as the key:
|
|
20
|
+
*
|
|
21
|
+
* ```ts
|
|
22
|
+
* const plugin = {
|
|
23
|
+
* data: new WeakMap<QueryId, SomeData>(),
|
|
24
|
+
*
|
|
25
|
+
* transformQuery(args: PluginTransformQueryArgs): RootOperationNode {
|
|
26
|
+
* this.data.set(args.queryId, something)
|
|
27
|
+
* return args.node
|
|
28
|
+
* },
|
|
29
|
+
*
|
|
30
|
+
* transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
|
|
31
|
+
* const data = this.data.get(args.queryId)
|
|
32
|
+
* return args.result
|
|
33
|
+
* }
|
|
34
|
+
* }
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* You should use a `WeakMap` instead of a `Map` or some other strong references because `transformQuery`
|
|
38
|
+
* is not always matched by a call to `transformResult` which would leave orphaned items in the map
|
|
39
|
+
* and cause a memory leak.
|
|
40
|
+
*/
|
|
41
|
+
transformQuery(args: PluginTransformQueryArgs): RootOperationNode;
|
|
42
|
+
/**
|
|
43
|
+
* This method is called for each query after it has been executed. The result
|
|
44
|
+
* of the query can be accessed through {@link PluginTransformResultArgs.result | args.result}.
|
|
45
|
+
* You can modify the result and return the modifier result.
|
|
46
|
+
*/
|
|
47
|
+
transformResult(args: PluginTransformResultArgs): Promise<QueryResult<UnknownRow>>;
|
|
48
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
/// <reference types="./deduplicate-joins-plugin.d.ts" />
|
|
2
|
+
import { DeduplicateJoinsTransformer } from './deduplicate-joins-transformer.js';
|
|
3
|
+
/**
|
|
4
|
+
* Plugin that removes duplicate joins from queries.
|
|
5
|
+
*
|
|
6
|
+
* See [this recipe](https://github.com/koskimas/kysely/tree/master/recipes/deduplicate-joins.md)
|
|
7
|
+
*/
|
|
8
|
+
export class DeduplicateJoinsPlugin {
|
|
9
|
+
#transformer = new DeduplicateJoinsTransformer();
|
|
10
|
+
transformQuery(args) {
|
|
11
|
+
return this.#transformer.transformNode(args.node);
|
|
12
|
+
}
|
|
13
|
+
transformResult(args) {
|
|
14
|
+
return Promise.resolve(args.result);
|
|
15
|
+
}
|
|
16
|
+
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { DeleteQueryNode, UpdateQueryNode } from '../../index-nodeless.js';
|
|
2
|
+
import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
|
|
3
|
+
import { SelectQueryNode } from '../../operation-node/select-query-node.js';
|
|
4
|
+
export declare class DeduplicateJoinsTransformer extends OperationNodeTransformer {
|
|
5
|
+
#private;
|
|
6
|
+
protected transformSelectQuery(node: SelectQueryNode): SelectQueryNode;
|
|
7
|
+
protected transformUpdateQuery(node: UpdateQueryNode): UpdateQueryNode;
|
|
8
|
+
protected transformDeleteQuery(node: DeleteQueryNode): DeleteQueryNode;
|
|
9
|
+
}
|