kysely 0.9.3 → 0.9.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (66) hide show
  1. package/dist/cjs/dialect/mysql/mysql-dialect.d.ts +11 -0
  2. package/dist/cjs/dialect/mysql/mysql-dialect.js +7 -0
  3. package/dist/cjs/dialect/postgres/postgres-dialect.d.ts +13 -1
  4. package/dist/cjs/dialect/postgres/postgres-dialect.js +10 -0
  5. package/dist/cjs/dialect/postgres/postgres-driver.js +2 -2
  6. package/dist/cjs/dialect/postgres/postgres-query-compiler.js +1 -1
  7. package/dist/cjs/driver/runtime-driver.d.ts +3 -2
  8. package/dist/cjs/driver/runtime-driver.js +57 -4
  9. package/dist/cjs/index.d.ts +2 -1
  10. package/dist/cjs/kysely.d.ts +31 -9
  11. package/dist/cjs/kysely.js +25 -9
  12. package/dist/cjs/migration/migration.d.ts +32 -0
  13. package/dist/cjs/operation-node/operator-node.d.ts +1 -1
  14. package/dist/cjs/operation-node/operator-node.js +1 -0
  15. package/dist/cjs/parser/join-parser.d.ts +4 -4
  16. package/dist/cjs/plugin/camel-case/camel-case-plugin.js +5 -116
  17. package/dist/cjs/plugin/camel-case/camel-case-transformer.d.ts +8 -0
  18. package/dist/cjs/plugin/camel-case/camel-case-transformer.js +19 -0
  19. package/dist/cjs/plugin/camel-case/camel-case.d.ts +15 -0
  20. package/dist/cjs/plugin/camel-case/camel-case.js +109 -0
  21. package/dist/cjs/plugin/kysely-plugin.d.ts +1 -1
  22. package/dist/cjs/query-builder/query-builder.d.ts +35 -0
  23. package/dist/cjs/query-builder/query-builder.js +37 -0
  24. package/dist/cjs/query-executor/default-query-executor.d.ts +1 -0
  25. package/dist/cjs/query-executor/default-query-executor.js +6 -0
  26. package/dist/cjs/query-executor/noop-query-executor.d.ts +1 -0
  27. package/dist/cjs/query-executor/noop-query-executor.js +3 -0
  28. package/dist/cjs/query-executor/query-executor.d.ts +9 -4
  29. package/dist/cjs/util/log.d.ts +19 -0
  30. package/dist/cjs/util/log.js +37 -0
  31. package/dist/cjs/util/random-string.js +6 -3
  32. package/dist/cjs/util/type-utils.d.ts +4 -4
  33. package/dist/esm/dialect/mysql/mysql-dialect.d.ts +11 -0
  34. package/dist/esm/dialect/mysql/mysql-dialect.js +7 -0
  35. package/dist/esm/dialect/mysql/mysql-driver.js +1 -1
  36. package/dist/esm/dialect/postgres/postgres-dialect.d.ts +13 -1
  37. package/dist/esm/dialect/postgres/postgres-dialect.js +10 -0
  38. package/dist/esm/dialect/postgres/postgres-driver.js +2 -2
  39. package/dist/esm/dialect/postgres/postgres-query-compiler.js +1 -1
  40. package/dist/esm/driver/runtime-driver.d.ts +3 -2
  41. package/dist/esm/driver/runtime-driver.js +57 -4
  42. package/dist/esm/index.d.ts +2 -1
  43. package/dist/esm/kysely.d.ts +31 -9
  44. package/dist/esm/kysely.js +25 -9
  45. package/dist/esm/migration/migration.d.ts +32 -0
  46. package/dist/esm/operation-node/operator-node.d.ts +1 -1
  47. package/dist/esm/operation-node/operator-node.js +1 -0
  48. package/dist/esm/parser/join-parser.d.ts +4 -4
  49. package/dist/esm/plugin/camel-case/camel-case-plugin.js +4 -115
  50. package/dist/esm/plugin/camel-case/camel-case-transformer.d.ts +8 -0
  51. package/dist/esm/plugin/camel-case/camel-case-transformer.js +15 -0
  52. package/dist/esm/plugin/camel-case/camel-case.d.ts +15 -0
  53. package/dist/esm/plugin/camel-case/camel-case.js +104 -0
  54. package/dist/esm/plugin/kysely-plugin.d.ts +1 -1
  55. package/dist/esm/query-builder/query-builder.d.ts +35 -0
  56. package/dist/esm/query-builder/query-builder.js +37 -0
  57. package/dist/esm/query-executor/default-query-executor.d.ts +1 -0
  58. package/dist/esm/query-executor/default-query-executor.js +6 -0
  59. package/dist/esm/query-executor/noop-query-executor.d.ts +1 -0
  60. package/dist/esm/query-executor/noop-query-executor.js +3 -0
  61. package/dist/esm/query-executor/query-executor.d.ts +9 -4
  62. package/dist/esm/util/log.d.ts +19 -0
  63. package/dist/esm/util/log.js +33 -0
  64. package/dist/esm/util/random-string.js +6 -3
  65. package/dist/esm/util/type-utils.d.ts +4 -4
  66. package/package.json +4 -1
@@ -0,0 +1,109 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.createCamelCaseMapper = exports.createSnakeCaseMapper = void 0;
4
+ /**
5
+ * Creates a function that transforms camel case strings to snake case.
6
+ */
7
+ function createSnakeCaseMapper({ upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
8
+ return memoize((str) => {
9
+ if (str.length === 0) {
10
+ return str;
11
+ }
12
+ const upper = str.toUpperCase();
13
+ const lower = str.toLowerCase();
14
+ let out = lower[0];
15
+ for (let i = 1, l = str.length; i < l; ++i) {
16
+ const char = str[i];
17
+ const prevChar = str[i - 1];
18
+ const upperChar = upper[i];
19
+ const prevUpperChar = upper[i - 1];
20
+ const lowerChar = lower[i];
21
+ const prevLowerChar = lower[i - 1];
22
+ // If underScoreBeforeDigits is true then, well, insert an underscore
23
+ // before digits :). Only the first digit gets an underscore if
24
+ // there are multiple.
25
+ if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
26
+ out += '_' + char;
27
+ continue;
28
+ }
29
+ // Test if `char` is an upper-case character and that the character
30
+ // actually has different upper and lower case versions.
31
+ if (char === upperChar && upperChar !== lowerChar) {
32
+ const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
33
+ // If underscoreBetweenUppercaseLetters is true, we always place an underscore
34
+ // before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
35
+ // Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
36
+ if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
37
+ out += '_' + lowerChar;
38
+ }
39
+ else {
40
+ out += lowerChar;
41
+ }
42
+ }
43
+ else {
44
+ out += char;
45
+ }
46
+ }
47
+ if (upperCase) {
48
+ return out.toUpperCase();
49
+ }
50
+ else {
51
+ return out;
52
+ }
53
+ });
54
+ }
55
+ exports.createSnakeCaseMapper = createSnakeCaseMapper;
56
+ /**
57
+ * Creates a function that transforms snake case strings to camel case.
58
+ */
59
+ function createCamelCaseMapper({ upperCase = false, } = {}) {
60
+ return memoize((str) => {
61
+ if (str.length === 0) {
62
+ return str;
63
+ }
64
+ if (upperCase && isAllUpperCaseSnakeCase(str)) {
65
+ // Only convert to lower case if the string is all upper
66
+ // case snake_case. This allows camelCase strings to go
67
+ // through without changing.
68
+ str = str.toLowerCase();
69
+ }
70
+ let out = str[0];
71
+ for (let i = 1, l = str.length; i < l; ++i) {
72
+ const char = str[i];
73
+ const prevChar = str[i - 1];
74
+ if (char !== '_') {
75
+ if (prevChar === '_') {
76
+ out += char.toUpperCase();
77
+ }
78
+ else {
79
+ out += char;
80
+ }
81
+ }
82
+ }
83
+ return out;
84
+ });
85
+ }
86
+ exports.createCamelCaseMapper = createCamelCaseMapper;
87
+ function isAllUpperCaseSnakeCase(str) {
88
+ for (let i = 1, l = str.length; i < l; ++i) {
89
+ const char = str[i];
90
+ if (char !== '_' && char !== char.toUpperCase()) {
91
+ return false;
92
+ }
93
+ }
94
+ return true;
95
+ }
96
+ function isDigit(char) {
97
+ return char >= '0' && char <= '9';
98
+ }
99
+ function memoize(func) {
100
+ const cache = new Map();
101
+ return (str) => {
102
+ let mapped = cache.get(str);
103
+ if (!mapped) {
104
+ mapped = func(str);
105
+ cache.set(str, mapped);
106
+ }
107
+ return mapped;
108
+ };
109
+ }
@@ -21,7 +21,7 @@ export interface KyselyPlugin {
21
21
  * return args.node
22
22
  * },
23
23
  *
24
- * transformResult(args: PluginTransformResultArgs): QueryResult<AnyRow> {
24
+ * transformResult(args: PluginTransformResultArgs): QueryResult<UnknownRow> {
25
25
  * const data = this.data.get(args.queryId)
26
26
  * return args.result
27
27
  * }
@@ -1582,6 +1582,41 @@ export declare class QueryBuilder<DB, TB extends keyof DB, O = {}> implements Op
1582
1582
  * ```
1583
1583
  */
1584
1584
  unionAll(expression: UnionExpression<DB, O>): QueryBuilder<DB, TB, O>;
1585
+ /**
1586
+ * Simply calls the given function passing `this` as the only argument.
1587
+ *
1588
+ * This method can be useful when adding optional method calls:
1589
+ *
1590
+ * @example
1591
+ * ```ts
1592
+ * db.selectFrom('person')
1593
+ * .selectAll()
1594
+ * .call((qb) => {
1595
+ * if (something) {
1596
+ * return qb.where('something', '=', something)
1597
+ * } else {
1598
+ * return qb.where('somethingElse', '=', somethingElse)
1599
+ * }
1600
+ * })
1601
+ * .execute()
1602
+ * ```
1603
+ *
1604
+ * The next example uses a helper funtion `log` to log a query:
1605
+ *
1606
+ * @example
1607
+ * ```ts
1608
+ * function log<T extends AnyQueryBuilder>(qb: T): T {
1609
+ * console.log(qb.compile())
1610
+ * return qb
1611
+ * }
1612
+ *
1613
+ * db.selectFrom('person')
1614
+ * .selectAll()
1615
+ * .call(log)
1616
+ * .execute()
1617
+ * ```
1618
+ */
1619
+ call<T>(func: (qb: this) => T): T;
1585
1620
  /**
1586
1621
  * Gives an alias for the query. This method is only useful for sub queries.
1587
1622
  *
@@ -818,6 +818,43 @@ class QueryBuilder {
818
818
  queryNode: select_query_node_js_1.SelectQueryNode.cloneWithUnion(this.#props.queryNode, (0, union_parser_js_1.parseUnion)(expression, true)),
819
819
  });
820
820
  }
821
+ /**
822
+ * Simply calls the given function passing `this` as the only argument.
823
+ *
824
+ * This method can be useful when adding optional method calls:
825
+ *
826
+ * @example
827
+ * ```ts
828
+ * db.selectFrom('person')
829
+ * .selectAll()
830
+ * .call((qb) => {
831
+ * if (something) {
832
+ * return qb.where('something', '=', something)
833
+ * } else {
834
+ * return qb.where('somethingElse', '=', somethingElse)
835
+ * }
836
+ * })
837
+ * .execute()
838
+ * ```
839
+ *
840
+ * The next example uses a helper funtion `log` to log a query:
841
+ *
842
+ * @example
843
+ * ```ts
844
+ * function log<T extends AnyQueryBuilder>(qb: T): T {
845
+ * console.log(qb.compile())
846
+ * return qb
847
+ * }
848
+ *
849
+ * db.selectFrom('person')
850
+ * .selectAll()
851
+ * .call(log)
852
+ * .execute()
853
+ * ```
854
+ */
855
+ call(func) {
856
+ return func(this);
857
+ }
821
858
  /**
822
859
  * Gives an alias for the query. This method is only useful for sub queries.
823
860
  *
@@ -9,6 +9,7 @@ export declare class DefaultQueryExecutor extends QueryExecutor {
9
9
  constructor(compiler: QueryCompiler, connectionProvider: ConnectionProvider, plugins?: KyselyPlugin[]);
10
10
  compileQuery(node: RootOperationNode): CompiledQuery;
11
11
  protected executeQueryImpl<R>(compiledQuery: CompiledQuery): Promise<QueryResult<R>>;
12
+ withPlugin(plugin: KyselyPlugin): DefaultQueryExecutor;
12
13
  withPluginAtFront(plugin: KyselyPlugin): DefaultQueryExecutor;
13
14
  withConnectionProvider(connectionProvider: ConnectionProvider): QueryExecutor;
14
15
  withoutPlugins(): QueryExecutor;
@@ -18,6 +18,12 @@ class DefaultQueryExecutor extends query_executor_js_1.QueryExecutor {
18
18
  return connection.executeQuery(compiledQuery);
19
19
  });
20
20
  }
21
+ withPlugin(plugin) {
22
+ return new DefaultQueryExecutor(this.#compiler, this.#connectionProvider, [
23
+ ...this.plugins,
24
+ plugin,
25
+ ]);
26
+ }
21
27
  withPluginAtFront(plugin) {
22
28
  return new DefaultQueryExecutor(this.#compiler, this.#connectionProvider, [
23
29
  plugin,
@@ -11,6 +11,7 @@ export declare class NoopQueryExecutor extends QueryExecutor {
11
11
  compileQuery(): CompiledQuery;
12
12
  protected executeQueryImpl<R>(): Promise<QueryResult<R>>;
13
13
  withConnectionProvider(): QueryExecutor;
14
+ withPlugin(plugin: KyselyPlugin): NoopQueryExecutor;
14
15
  withPluginAtFront(plugin: KyselyPlugin): NoopQueryExecutor;
15
16
  withoutPlugins(): QueryExecutor;
16
17
  }
@@ -17,6 +17,9 @@ class NoopQueryExecutor extends query_executor_js_1.QueryExecutor {
17
17
  withConnectionProvider() {
18
18
  throw new Error('this query cannot have a connection provider');
19
19
  }
20
+ withPlugin(plugin) {
21
+ return new NoopQueryExecutor([...this.plugins, plugin]);
22
+ }
20
23
  withPluginAtFront(plugin) {
21
24
  return new NoopQueryExecutor([plugin, ...this.plugins]);
22
25
  }
@@ -35,15 +35,20 @@ export declare abstract class QueryExecutor {
35
35
  * Executes a compiled query.
36
36
  */
37
37
  protected abstract executeQueryImpl<R>(compiledQuery: CompiledQuery, queryId: QueryId): Promise<QueryResult<R>>;
38
+ /**
39
+ * Returns a copy of this executor with a new connection provider.
40
+ */
41
+ abstract withConnectionProvider(connectionProvider: ConnectionProvider): QueryExecutor;
38
42
  /**
39
43
  * Returns a copy of this executor with a plugin added as the
40
- * first plugin.
44
+ * last plugin.
41
45
  */
42
- abstract withPluginAtFront(plugin: KyselyPlugin): QueryExecutor;
46
+ abstract withPlugin(plugin: KyselyPlugin): QueryExecutor;
43
47
  /**
44
- * Returns a copy of this executor with a new connection provider.
48
+ * Returns a copy of this executor with a plugin added as the
49
+ * first plugin.
45
50
  */
46
- abstract withConnectionProvider(connectionProvider: ConnectionProvider): QueryExecutor;
51
+ abstract withPluginAtFront(plugin: KyselyPlugin): QueryExecutor;
47
52
  /**
48
53
  * Returns a copy of this executor without any plugins.
49
54
  */
@@ -0,0 +1,19 @@
1
+ import { ArrayItemType } from './type-utils.js';
2
+ export declare const LOG_LEVELS: readonly ["query", "error"];
3
+ export declare type LogLevel = ArrayItemType<typeof LOG_LEVELS>;
4
+ export declare class Log {
5
+ #private;
6
+ constructor(levels: ReadonlyArray<LogLevel>);
7
+ query(getEvent: () => QueryLogEvent): void;
8
+ error(getEvent: () => ErrorLogEvent): void;
9
+ }
10
+ export declare type LogEvent = QueryLogEvent | ErrorLogEvent;
11
+ export interface QueryLogEvent {
12
+ readonly level: 'query';
13
+ readonly sql: string;
14
+ readonly queryDurationMillis: number;
15
+ }
16
+ export interface ErrorLogEvent {
17
+ readonly level: 'error';
18
+ readonly error: unknown;
19
+ }
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.Log = exports.LOG_LEVELS = void 0;
4
+ const object_utils_js_1 = require("./object-utils.js");
5
+ exports.LOG_LEVELS = ['query', 'error'];
6
+ class Log {
7
+ #levels;
8
+ constructor(levels) {
9
+ this.#levels = (0, object_utils_js_1.freeze)({
10
+ query: levels.includes('query'),
11
+ error: levels.includes('error'),
12
+ });
13
+ }
14
+ query(getEvent) {
15
+ if (this.#levels.query) {
16
+ this.#defaultQuery(getEvent());
17
+ }
18
+ }
19
+ error(getEvent) {
20
+ if (this.#levels.error) {
21
+ this.#defaultError(getEvent());
22
+ }
23
+ }
24
+ #defaultQuery(event) {
25
+ console.log(`kysely:query: ${event.sql}`);
26
+ console.log(`kysely:query: duration: ${event.queryDurationMillis.toFixed(1)}ms`);
27
+ }
28
+ #defaultError(event) {
29
+ if (event.error instanceof Error) {
30
+ console.error(`kysely:error: ${event.error.stack ?? event.error.message}`);
31
+ }
32
+ else {
33
+ console.error(`kysely:error: ${event}`);
34
+ }
35
+ }
36
+ }
37
+ exports.Log = Log;
@@ -3,10 +3,13 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.randomString = void 0;
4
4
  const CHARS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
5
5
  function randomString(length) {
6
- let chars = new Array(length);
6
+ let chars = '';
7
7
  for (let i = 0; i < length; ++i) {
8
- chars[i] = CHARS[Math.floor(Math.random() * CHARS.length)];
8
+ chars += randomChar();
9
9
  }
10
- return chars.join('');
10
+ return chars;
11
11
  }
12
12
  exports.randomString = randomString;
13
+ function randomChar() {
14
+ return CHARS[Math.floor(Math.random() * CHARS.length)];
15
+ }
@@ -136,19 +136,19 @@ export declare type RawBuilderFactory<DB, TB extends keyof DB> = (qb: Expression
136
136
  export declare type AliasedRawBuilderFactory<DB, TB extends keyof DB> = (qb: ExpressionBuilder<DB, TB>) => AnyAliasedRawBuilder;
137
137
  export interface InsertResultTypeTag {
138
138
  /** @internal */
139
- __isInsertResultTypeTag__: true;
139
+ readonly __isInsertResultTypeTag__: true;
140
140
  }
141
141
  export interface DeleteResultTypeTag {
142
142
  /** @internal */
143
- __isDeleteResultTypeTag__: true;
143
+ readonly __isDeleteResultTypeTag__: true;
144
144
  }
145
145
  export interface UpdateResultTypeTag {
146
146
  /** @internal */
147
- __isUpdateResultTypeTag__: true;
147
+ readonly __isUpdateResultTypeTag__: true;
148
148
  }
149
149
  export interface GeneratedPlaceholder {
150
150
  /** @internal */
151
- __isGeneratedPlaceholder__: true;
151
+ readonly __isGeneratedPlaceholder__: true;
152
152
  }
153
153
  export declare type ManyResultRowType<O> = O extends InsertResultTypeTag ? number | undefined : O extends DeleteResultTypeTag ? number : O extends UpdateResultTypeTag ? number : O;
154
154
  export declare type SingleResultRowType<O> = O extends InsertResultTypeTag ? number | undefined : O extends DeleteResultTypeTag ? number : O extends UpdateResultTypeTag ? number : O | undefined;
@@ -5,6 +5,13 @@ import { Dialect } from '../dialect.js';
5
5
  import { DatabaseIntrospector } from '../../introspection/database-introspector.js';
6
6
  import { DialectAdapter } from '../dialect-adapter.js';
7
7
  import { DatabaseConnection } from '../../driver/database-connection.js';
8
+ /**
9
+ * MySQL dialect that uses the [mysql2](https://github.com/sidorares/node-mysql2#readme) library.
10
+ *
11
+ * The {@link MysqlDialectConfig | configuration} passed to the constructor
12
+ * is given as-is to the mysql2 library's [createPool](https://github.com/sidorares/node-mysql2#using-connection-pools)
13
+ * method.
14
+ */
8
15
  export declare class MysqlDialect implements Dialect {
9
16
  #private;
10
17
  constructor(config: MysqlDialectConfig);
@@ -17,6 +24,8 @@ export declare class MysqlDialect implements Dialect {
17
24
  * Config for the mysql dialect.
18
25
  *
19
26
  * This interface is equal to `mysql2` library's pool config.
27
+ *
28
+ * https://github.com/sidorares/node-mysql2#using-connection-pools
20
29
  */
21
30
  export interface MysqlDialectConfig {
22
31
  /**
@@ -176,6 +185,8 @@ export interface MysqlDialectConfig {
176
185
  keepAliveInitialDelay?: number;
177
186
  /**
178
187
  * Called once for each created connection.
188
+ *
189
+ * This is a Kysely specific feature and does not come from the `pg` module.
179
190
  */
180
191
  onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
181
192
  }
@@ -2,6 +2,13 @@ import { MysqlDriver } from './mysql-driver.js';
2
2
  import { MysqlQueryCompiler } from './mysql-query-compiler.js';
3
3
  import { MysqlIntrospector } from './mysql-introspector.js';
4
4
  import { MysqlAdapter } from './mysql-adapter.js';
5
+ /**
6
+ * MySQL dialect that uses the [mysql2](https://github.com/sidorares/node-mysql2#readme) library.
7
+ *
8
+ * The {@link MysqlDialectConfig | configuration} passed to the constructor
9
+ * is given as-is to the mysql2 library's [createPool](https://github.com/sidorares/node-mysql2#using-connection-pools)
10
+ * method.
11
+ */
5
12
  export class MysqlDialect {
6
13
  #config;
7
14
  constructor(config) {
@@ -1,4 +1,4 @@
1
- import { isFunction, isNumber, isObject, } from '../../util/object-utils.js';
1
+ import { isFunction, isNumber, isObject } from '../../util/object-utils.js';
2
2
  const PRIVATE_RELEASE_METHOD = Symbol();
3
3
  export class MysqlDriver {
4
4
  #config;
@@ -8,6 +8,16 @@ import { Dialect } from '../dialect.js';
8
8
  import { DatabaseIntrospector } from '../../introspection/database-introspector.js';
9
9
  import { DialectAdapter } from '../dialect-adapter.js';
10
10
  import { DatabaseConnection } from '../../driver/database-connection.js';
11
+ /**
12
+ * PostgreSQL dialect that uses the [pg](https://node-postgres.com/) library.
13
+ *
14
+ * The {@link PostgresDialectConfig | configuration} passed to the constructor
15
+ * is given as-is to the pg library's [Pool](https://node-postgres.com/api/pool)
16
+ * constructor. See the following two links for more documentation:
17
+ *
18
+ * https://node-postgres.com/api/pool
19
+ * https://node-postgres.com/api/client
20
+ */
11
21
  export declare class PostgresDialect implements Dialect {
12
22
  #private;
13
23
  constructor(config: PostgresDialectConfig);
@@ -19,7 +29,7 @@ export declare class PostgresDialect implements Dialect {
19
29
  /**
20
30
  * Config for the postgres dialect.
21
31
  *
22
- * This interface is equal to `pg` library's pool config:
32
+ * This interface is equal to `pg` library's `Pool` config:
23
33
  *
24
34
  * https://node-postgres.com/api/pool
25
35
  * https://node-postgres.com/api/client
@@ -105,6 +115,8 @@ export interface PostgresDialectConfig {
105
115
  application_name?: string;
106
116
  /**
107
117
  * Called once for each created connection.
118
+ *
119
+ * This is a Kysely specific feature and does not come from the `pg` module.
108
120
  */
109
121
  onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
110
122
  keepAlive?: boolean;
@@ -2,6 +2,16 @@ import { PostgresDriver } from './postgres-driver.js';
2
2
  import { PostgresIntrospector } from './postgres-introspector.js';
3
3
  import { PostgresQueryCompiler } from './postgres-query-compiler.js';
4
4
  import { PostgresAdapter } from './postgres-adapter.js';
5
+ /**
6
+ * PostgreSQL dialect that uses the [pg](https://node-postgres.com/) library.
7
+ *
8
+ * The {@link PostgresDialectConfig | configuration} passed to the constructor
9
+ * is given as-is to the pg library's [Pool](https://node-postgres.com/api/pool)
10
+ * constructor. See the following two links for more documentation:
11
+ *
12
+ * https://node-postgres.com/api/pool
13
+ * https://node-postgres.com/api/client
14
+ */
5
15
  export class PostgresDialect {
6
16
  #config;
7
17
  constructor(config) {
@@ -13,10 +13,10 @@ export class PostgresDriver {
13
13
  // installed. As you can see, there IS an import from `pg` at the
14
14
  // top level too, but that's only for types. It doesn't get compiled
15
15
  // into javascript. You can check the built javascript code.
16
- const PoolConstrucor = await importPgPool();
16
+ const PoolConstructor = await importPgPool();
17
17
  // Use the `pg` module's own pool. All drivers should use the
18
18
  // pool provided by the database library if possible.
19
- this.#pool = new PoolConstrucor(this.#config);
19
+ this.#pool = new PoolConstructor(this.#config);
20
20
  }
21
21
  async acquireConnection() {
22
22
  const client = await this.#pool.connect();
@@ -1,4 +1,4 @@
1
1
  import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js';
2
- // The default query compiler is for postgres dialect.
2
+ // The default query compiler is for PostgreSQL.
3
3
  export class PostgresQueryCompiler extends DefaultQueryCompiler {
4
4
  }
@@ -1,3 +1,4 @@
1
+ import { Log } from '../util/log.js';
1
2
  import { DatabaseConnection } from './database-connection.js';
2
3
  import { Driver, TransactionSettings } from './driver.js';
3
4
  /**
@@ -7,10 +8,10 @@ import { Driver, TransactionSettings } from './driver.js';
7
8
  */
8
9
  export declare class RuntimeDriver implements Driver {
9
10
  #private;
10
- constructor(driver: Driver);
11
+ constructor(driver: Driver, log: Log);
11
12
  init(): Promise<void>;
12
13
  acquireConnection(): Promise<DatabaseConnection>;
13
- releaseConnection(connection: DatabaseConnection): Promise<void>;
14
+ releaseConnection(runtimeConnection: DatabaseConnection): Promise<void>;
14
15
  beginTransaction(connection: DatabaseConnection, settings: TransactionSettings): Promise<void>;
15
16
  commitTransaction(connection: DatabaseConnection): Promise<void>;
16
17
  rollbackTransaction(connection: DatabaseConnection): Promise<void>;
@@ -5,10 +5,13 @@
5
5
  */
6
6
  export class RuntimeDriver {
7
7
  #driver;
8
+ #log;
8
9
  #initPromise;
9
10
  #destroyPromise;
10
- constructor(driver) {
11
+ #connections = new WeakMap();
12
+ constructor(driver, log) {
11
13
  this.#driver = driver;
14
+ this.#log = log;
12
15
  }
13
16
  async init() {
14
17
  if (!this.#initPromise) {
@@ -21,10 +24,18 @@ export class RuntimeDriver {
21
24
  }
22
25
  async acquireConnection() {
23
26
  await this.init();
24
- return this.#driver.acquireConnection();
27
+ const connection = await this.#driver.acquireConnection();
28
+ let runtimeConnection = this.#connections.get(connection);
29
+ if (!runtimeConnection) {
30
+ runtimeConnection = new RuntimeConnection(connection, this.#log);
31
+ this.#connections.set(connection, runtimeConnection);
32
+ }
33
+ return runtimeConnection;
25
34
  }
26
- releaseConnection(connection) {
27
- return this.#driver.releaseConnection(connection);
35
+ async releaseConnection(runtimeConnection) {
36
+ if (runtimeConnection instanceof RuntimeConnection) {
37
+ await this.#driver.releaseConnection(runtimeConnection.connection);
38
+ }
28
39
  }
29
40
  beginTransaction(connection, settings) {
30
41
  return this.#driver.beginTransaction(connection, settings);
@@ -49,3 +60,45 @@ export class RuntimeDriver {
49
60
  await this.#destroyPromise;
50
61
  }
51
62
  }
63
+ class RuntimeConnection {
64
+ #connection;
65
+ #log;
66
+ get connection() {
67
+ return this.#connection;
68
+ }
69
+ constructor(connection, log) {
70
+ this.#connection = connection;
71
+ this.#log = log;
72
+ }
73
+ async executeQuery(compiledQuery) {
74
+ const startTime = process.hrtime.bigint();
75
+ try {
76
+ return await this.#connection.executeQuery(compiledQuery);
77
+ }
78
+ catch (error) {
79
+ this.#logError(error);
80
+ throw error;
81
+ }
82
+ finally {
83
+ this.#logQuery(compiledQuery, startTime);
84
+ }
85
+ }
86
+ #logError(error) {
87
+ this.#log.error(() => ({
88
+ level: 'error',
89
+ error,
90
+ }));
91
+ }
92
+ #logQuery(compiledQuery, startTime) {
93
+ this.#log.query(() => ({
94
+ level: 'query',
95
+ sql: compiledQuery.sql,
96
+ queryDurationMillis: this.#calculateDurationMillis(startTime),
97
+ }));
98
+ }
99
+ #calculateDurationMillis(startTime) {
100
+ const endTime = process.hrtime.bigint();
101
+ const durationNanos = Number(endTime - startTime);
102
+ return durationNanos / 1_000_000;
103
+ }
104
+ }
@@ -110,7 +110,7 @@ export * from './operation-node/operation-node-source.js';
110
110
  export * from './operation-node/order-by-node.js';
111
111
  export * from './introspection/database-introspector.js';
112
112
  export * from './util/compilable.js';
113
- export { AnyColumn, UnknownRow as AnyRow } from './util/type-utils.js';
113
+ export { AnyColumn, UnknownRow, AnyQueryBuilder } from './util/type-utils.js';
114
114
  export { SelectExpression, SelectExpressionOrList, } from './parser/select-parser.js';
115
115
  export { ReferenceExpression, ReferenceExpressionOrList, } from './parser/reference-parser.js';
116
116
  export { ValueExpression, ValueExpressionOrList, } from './parser/value-parser.js';
@@ -120,3 +120,4 @@ export { JoinReferenceExpression, JoinCallbackExpression, } from './parser/join-
120
120
  export { InsertObject } from './parser/insert-values-parser.js';
121
121
  export { MutationObject } from './parser/update-set-parser.js';
122
122
  export { OrderByExpression, OrderByDirectionExpression, } from './parser/order-by-parser.js';
123
+ export { UnionExpression } from './parser/union-parser.js';