kysely 0.9.4 → 0.9.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.
Files changed (51) hide show
  1. package/dist/cjs/dialect/mysql/mysql-dialect.d.ts +2 -0
  2. package/dist/cjs/dialect/postgres/postgres-dialect.d.ts +2 -0
  3. package/dist/cjs/dialect/postgres/postgres-driver.js +2 -2
  4. package/dist/cjs/dialect/postgres/postgres-query-compiler.js +1 -1
  5. package/dist/cjs/driver/runtime-driver.js +20 -6
  6. package/dist/cjs/index.d.ts +1 -0
  7. package/dist/cjs/kysely.d.ts +8 -3
  8. package/dist/cjs/kysely.js +9 -0
  9. package/dist/cjs/operation-node/operator-node.d.ts +1 -1
  10. package/dist/cjs/operation-node/operator-node.js +6 -0
  11. package/dist/cjs/plugin/camel-case/camel-case-plugin.js +5 -116
  12. package/dist/cjs/plugin/camel-case/camel-case-transformer.d.ts +8 -0
  13. package/dist/cjs/plugin/camel-case/camel-case-transformer.js +19 -0
  14. package/dist/cjs/plugin/camel-case/camel-case.d.ts +15 -0
  15. package/dist/cjs/plugin/camel-case/camel-case.js +109 -0
  16. package/dist/cjs/plugin/kysely-plugin.d.ts +1 -1
  17. package/dist/cjs/query-builder/query-builder.d.ts +1 -1
  18. package/dist/cjs/query-builder/query-builder.js +1 -1
  19. package/dist/cjs/query-executor/default-query-executor.d.ts +1 -0
  20. package/dist/cjs/query-executor/default-query-executor.js +6 -0
  21. package/dist/cjs/query-executor/noop-query-executor.d.ts +1 -0
  22. package/dist/cjs/query-executor/noop-query-executor.js +3 -0
  23. package/dist/cjs/query-executor/query-executor.d.ts +9 -4
  24. package/dist/cjs/util/log.d.ts +13 -2
  25. package/dist/cjs/util/log.js +23 -7
  26. package/dist/esm/dialect/mysql/mysql-dialect.d.ts +2 -0
  27. package/dist/esm/dialect/postgres/postgres-dialect.d.ts +2 -0
  28. package/dist/esm/dialect/postgres/postgres-driver.js +2 -2
  29. package/dist/esm/dialect/postgres/postgres-query-compiler.js +1 -1
  30. package/dist/esm/driver/runtime-driver.js +20 -6
  31. package/dist/esm/index.d.ts +1 -0
  32. package/dist/esm/kysely.d.ts +8 -3
  33. package/dist/esm/kysely.js +9 -0
  34. package/dist/esm/operation-node/operator-node.d.ts +1 -1
  35. package/dist/esm/operation-node/operator-node.js +6 -0
  36. package/dist/esm/plugin/camel-case/camel-case-plugin.js +4 -115
  37. package/dist/esm/plugin/camel-case/camel-case-transformer.d.ts +8 -0
  38. package/dist/esm/plugin/camel-case/camel-case-transformer.js +15 -0
  39. package/dist/esm/plugin/camel-case/camel-case.d.ts +15 -0
  40. package/dist/esm/plugin/camel-case/camel-case.js +104 -0
  41. package/dist/esm/plugin/kysely-plugin.d.ts +1 -1
  42. package/dist/esm/query-builder/query-builder.d.ts +1 -1
  43. package/dist/esm/query-builder/query-builder.js +1 -1
  44. package/dist/esm/query-executor/default-query-executor.d.ts +1 -0
  45. package/dist/esm/query-executor/default-query-executor.js +6 -0
  46. package/dist/esm/query-executor/noop-query-executor.d.ts +1 -0
  47. package/dist/esm/query-executor/noop-query-executor.js +3 -0
  48. package/dist/esm/query-executor/query-executor.d.ts +9 -4
  49. package/dist/esm/util/log.d.ts +13 -2
  50. package/dist/esm/util/log.js +23 -7
  51. package/package.json +4 -1
@@ -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
  }
@@ -75,16 +75,30 @@ class RuntimeConnection {
75
75
  try {
76
76
  return await this.#connection.executeQuery(compiledQuery);
77
77
  }
78
+ catch (error) {
79
+ this.#logError(error);
80
+ throw error;
81
+ }
78
82
  finally {
79
- this.#log.query((log) => {
80
- log(compiledQuery.sql);
81
- log(`duration: ${this.#calculateDurationMillis(startTime)}ms`);
82
- });
83
+ this.#logQuery(compiledQuery, startTime);
83
84
  }
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
+ }
85
99
  #calculateDurationMillis(startTime) {
86
100
  const endTime = process.hrtime.bigint();
87
- const durationTensMillis = Number((endTime - startTime) / 100000n);
88
- return durationTensMillis / 10;
101
+ const durationNanos = Number(endTime - startTime);
102
+ return durationNanos / 1_000_000;
89
103
  }
90
104
  }
@@ -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';
@@ -194,6 +194,10 @@ export declare class Kysely<DB> extends QueryCreator<DB> {
194
194
  * ```
195
195
  */
196
196
  connection(): ConnectionBuilder<DB>;
197
+ /**
198
+ * Returns a copy of this Kysely instance with the given plugin installed.
199
+ */
200
+ withPlugin(plugin: KyselyPlugin): Kysely<DB>;
197
201
  /**
198
202
  * Returns a copy of this Kysely instance without any plugins.
199
203
  */
@@ -231,12 +235,13 @@ export interface KyselyConfig {
231
235
  /**
232
236
  * A list of log levels to log.
233
237
  *
234
- * Currently there's only one level: `query` and it's logged using
235
- * `console.log`. This will be expanded based on user request later.
238
+ * Currently there's only two levels: `query` and `error`.
239
+ * This will be expanded based on user feedback later.
236
240
  *
237
241
  * Log levels:
238
242
  *
239
- * - query: Log each query's SQL and duration.
243
+ * - query: Log each query's SQL and duration using console.log
244
+ * - error: Log all query errors using console.error
240
245
  */
241
246
  readonly log?: ReadonlyArray<LogLevel>;
242
247
  }
@@ -235,6 +235,15 @@ export class Kysely extends QueryCreator {
235
235
  connection() {
236
236
  return new ConnectionBuilder({ ...this.#props });
237
237
  }
238
+ /**
239
+ * Returns a copy of this Kysely instance with the given plugin installed.
240
+ */
241
+ withPlugin(plugin) {
242
+ return new Kysely({
243
+ ...this.#props,
244
+ executor: this.#props.executor.withPlugin(plugin),
245
+ });
246
+ }
238
247
  /**
239
248
  * Returns a copy of this Kysely instance without any plugins.
240
249
  */
@@ -1,6 +1,6 @@
1
1
  import { ArrayItemType } from '../util/type-utils.js';
2
2
  import { OperationNode } from './operation-node.js';
3
- export declare const OPERATORS: readonly ["=", "==", "!=", "<>", ">", ">=", "<", "<=", "in", "not in", "is", "is not", "like", "not like", "ilike", "not ilike", "@>", "<@", "?", "?", "?&", "!<", "!>", "<=>", "!~", "~", "~*", "!~*", "exists", "not exists"];
3
+ export declare const OPERATORS: readonly ["=", "==", "!=", "<>", ">", ">=", "<", "<=", "in", "not in", "is", "is not", "like", "not like", "ilike", "not ilike", "@>", "<@", "?", "?", "?&", "!<", "!>", "<=>", "!~", "~", "~*", "!~*", "exists", "not exists", "&&", "||", "@@", "@@@", "!!", "<->"];
4
4
  export declare type Operator = ArrayItemType<typeof OPERATORS>;
5
5
  export interface OperatorNode extends OperationNode {
6
6
  readonly kind: 'OperatorNode';
@@ -30,6 +30,12 @@ export const OPERATORS = [
30
30
  '!~*',
31
31
  'exists',
32
32
  'not exists',
33
+ '&&',
34
+ '||',
35
+ '@@',
36
+ '@@@',
37
+ '!!',
38
+ '<->',
33
39
  ];
34
40
  /**
35
41
  * @internal
@@ -1,5 +1,6 @@
1
- import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
2
1
  import { isObject } from '../../util/object-utils.js';
2
+ import { SnakeCaseTransformer } from './camel-case-transformer.js';
3
+ import { createCamelCaseMapper, createSnakeCaseMapper, } from './camel-case.js';
3
4
  /**
4
5
  * A plugin that converts snake_case identifiers in the database into
5
6
  * camelCase in the javascript side.
@@ -69,8 +70,8 @@ export class CamelCasePlugin {
69
70
  #snakeCase;
70
71
  #snakeCaseTransformer;
71
72
  constructor(opt = {}) {
72
- this.#camelCase = createCamelCase(opt);
73
- this.#snakeCase = createSnakeCase(opt);
73
+ this.#camelCase = createCamelCaseMapper(opt);
74
+ this.#snakeCase = createSnakeCaseMapper(opt);
74
75
  this.#snakeCaseTransformer = new SnakeCaseTransformer(this.snakeCase.bind(this));
75
76
  }
76
77
  transformQuery(args) {
@@ -105,118 +106,6 @@ export class CamelCasePlugin {
105
106
  return this.#camelCase(str);
106
107
  }
107
108
  }
108
- class SnakeCaseTransformer extends OperationNodeTransformer {
109
- #snakeCase;
110
- constructor(snakeCase) {
111
- super();
112
- this.#snakeCase = snakeCase;
113
- }
114
- transformIdentifier(node) {
115
- node = super.transformIdentifier(node);
116
- return {
117
- ...node,
118
- identifier: this.#snakeCase(node.identifier),
119
- };
120
- }
121
- }
122
109
  function canMap(obj) {
123
110
  return isObject(obj) && !(obj instanceof Date) && !Buffer.isBuffer(obj);
124
111
  }
125
- function createSnakeCase({ upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
126
- return memoize((str) => {
127
- if (str.length === 0) {
128
- return str;
129
- }
130
- const upper = str.toUpperCase();
131
- const lower = str.toLowerCase();
132
- let out = lower[0];
133
- for (let i = 1, l = str.length; i < l; ++i) {
134
- const char = str[i];
135
- const prevChar = str[i - 1];
136
- const upperChar = upper[i];
137
- const prevUpperChar = upper[i - 1];
138
- const lowerChar = lower[i];
139
- const prevLowerChar = lower[i - 1];
140
- // If underScoreBeforeDigits is true then, well, insert an underscore
141
- // before digits :). Only the first digit gets an underscore if
142
- // there are multiple.
143
- if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
144
- out += '_' + char;
145
- continue;
146
- }
147
- // Test if `char` is an upper-case character and that the character
148
- // actually has different upper and lower case versions.
149
- if (char === upperChar && upperChar !== lowerChar) {
150
- const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
151
- // If underscoreBetweenUppercaseLetters is true, we always place an underscore
152
- // before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
153
- // Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
154
- if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
155
- out += '_' + lowerChar;
156
- }
157
- else {
158
- out += lowerChar;
159
- }
160
- }
161
- else {
162
- out += char;
163
- }
164
- }
165
- if (upperCase) {
166
- return out.toUpperCase();
167
- }
168
- else {
169
- return out;
170
- }
171
- });
172
- }
173
- function createCamelCase({ upperCase = false } = {}) {
174
- return memoize((str) => {
175
- if (str.length === 0) {
176
- return str;
177
- }
178
- if (upperCase && isAllUpperCaseSnakeCase(str)) {
179
- // Only convert to lower case if the string is all upper
180
- // case snake_case. This allows camelCase strings to go
181
- // through without changing.
182
- str = str.toLowerCase();
183
- }
184
- let out = str[0];
185
- for (let i = 1, l = str.length; i < l; ++i) {
186
- const char = str[i];
187
- const prevChar = str[i - 1];
188
- if (char !== '_') {
189
- if (prevChar === '_') {
190
- out += char.toUpperCase();
191
- }
192
- else {
193
- out += char;
194
- }
195
- }
196
- }
197
- return out;
198
- });
199
- }
200
- function isAllUpperCaseSnakeCase(str) {
201
- for (let i = 1, l = str.length; i < l; ++i) {
202
- const char = str[i];
203
- if (char !== '_' && char !== char.toUpperCase()) {
204
- return false;
205
- }
206
- }
207
- return true;
208
- }
209
- function isDigit(char) {
210
- return char >= '0' && char <= '9';
211
- }
212
- function memoize(func) {
213
- const cache = new Map();
214
- return (str) => {
215
- let mapped = cache.get(str);
216
- if (!mapped) {
217
- mapped = func(str);
218
- cache.set(str, mapped);
219
- }
220
- return mapped;
221
- };
222
- }
@@ -0,0 +1,8 @@
1
+ import { IdentifierNode } from '../../operation-node/identifier-node.js';
2
+ import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
3
+ import { StringMapper } from './camel-case.js';
4
+ export declare class SnakeCaseTransformer extends OperationNodeTransformer {
5
+ #private;
6
+ constructor(snakeCase: StringMapper);
7
+ protected transformIdentifier(node: IdentifierNode): IdentifierNode;
8
+ }
@@ -0,0 +1,15 @@
1
+ import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js';
2
+ export class SnakeCaseTransformer extends OperationNodeTransformer {
3
+ #snakeCase;
4
+ constructor(snakeCase) {
5
+ super();
6
+ this.#snakeCase = snakeCase;
7
+ }
8
+ transformIdentifier(node) {
9
+ node = super.transformIdentifier(node);
10
+ return {
11
+ ...node,
12
+ identifier: this.#snakeCase(node.identifier),
13
+ };
14
+ }
15
+ }
@@ -0,0 +1,15 @@
1
+ export declare type StringMapper = (str: string) => string;
2
+ /**
3
+ * Creates a function that transforms camel case strings to snake case.
4
+ */
5
+ export declare function createSnakeCaseMapper({ upperCase, underscoreBeforeDigits, underscoreBetweenUppercaseLetters, }?: {
6
+ upperCase?: boolean | undefined;
7
+ underscoreBeforeDigits?: boolean | undefined;
8
+ underscoreBetweenUppercaseLetters?: boolean | undefined;
9
+ }): StringMapper;
10
+ /**
11
+ * Creates a function that transforms snake case strings to camel case.
12
+ */
13
+ export declare function createCamelCaseMapper({ upperCase, }?: {
14
+ upperCase?: boolean | undefined;
15
+ }): StringMapper;
@@ -0,0 +1,104 @@
1
+ /**
2
+ * Creates a function that transforms camel case strings to snake case.
3
+ */
4
+ export function createSnakeCaseMapper({ upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
5
+ return memoize((str) => {
6
+ if (str.length === 0) {
7
+ return str;
8
+ }
9
+ const upper = str.toUpperCase();
10
+ const lower = str.toLowerCase();
11
+ let out = lower[0];
12
+ for (let i = 1, l = str.length; i < l; ++i) {
13
+ const char = str[i];
14
+ const prevChar = str[i - 1];
15
+ const upperChar = upper[i];
16
+ const prevUpperChar = upper[i - 1];
17
+ const lowerChar = lower[i];
18
+ const prevLowerChar = lower[i - 1];
19
+ // If underScoreBeforeDigits is true then, well, insert an underscore
20
+ // before digits :). Only the first digit gets an underscore if
21
+ // there are multiple.
22
+ if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
23
+ out += '_' + char;
24
+ continue;
25
+ }
26
+ // Test if `char` is an upper-case character and that the character
27
+ // actually has different upper and lower case versions.
28
+ if (char === upperChar && upperChar !== lowerChar) {
29
+ const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
30
+ // If underscoreBetweenUppercaseLetters is true, we always place an underscore
31
+ // before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
32
+ // Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
33
+ if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
34
+ out += '_' + lowerChar;
35
+ }
36
+ else {
37
+ out += lowerChar;
38
+ }
39
+ }
40
+ else {
41
+ out += char;
42
+ }
43
+ }
44
+ if (upperCase) {
45
+ return out.toUpperCase();
46
+ }
47
+ else {
48
+ return out;
49
+ }
50
+ });
51
+ }
52
+ /**
53
+ * Creates a function that transforms snake case strings to camel case.
54
+ */
55
+ export function createCamelCaseMapper({ upperCase = false, } = {}) {
56
+ return memoize((str) => {
57
+ if (str.length === 0) {
58
+ return str;
59
+ }
60
+ if (upperCase && isAllUpperCaseSnakeCase(str)) {
61
+ // Only convert to lower case if the string is all upper
62
+ // case snake_case. This allows camelCase strings to go
63
+ // through without changing.
64
+ str = str.toLowerCase();
65
+ }
66
+ let out = str[0];
67
+ for (let i = 1, l = str.length; i < l; ++i) {
68
+ const char = str[i];
69
+ const prevChar = str[i - 1];
70
+ if (char !== '_') {
71
+ if (prevChar === '_') {
72
+ out += char.toUpperCase();
73
+ }
74
+ else {
75
+ out += char;
76
+ }
77
+ }
78
+ }
79
+ return out;
80
+ });
81
+ }
82
+ function isAllUpperCaseSnakeCase(str) {
83
+ for (let i = 1, l = str.length; i < l; ++i) {
84
+ const char = str[i];
85
+ if (char !== '_' && char !== char.toUpperCase()) {
86
+ return false;
87
+ }
88
+ }
89
+ return true;
90
+ }
91
+ function isDigit(char) {
92
+ return char >= '0' && char <= '9';
93
+ }
94
+ function memoize(func) {
95
+ const cache = new Map();
96
+ return (str) => {
97
+ let mapped = cache.get(str);
98
+ if (!mapped) {
99
+ mapped = func(str);
100
+ cache.set(str, mapped);
101
+ }
102
+ return mapped;
103
+ };
104
+ }
@@ -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
  * }
@@ -1583,7 +1583,7 @@ export declare class QueryBuilder<DB, TB extends keyof DB, O = {}> implements Op
1583
1583
  */
1584
1584
  unionAll(expression: UnionExpression<DB, O>): QueryBuilder<DB, TB, O>;
1585
1585
  /**
1586
- * Simply calls the given method passing `this` as the only argument.
1586
+ * Simply calls the given function passing `this` as the only argument.
1587
1587
  *
1588
1588
  * This method can be useful when adding optional method calls:
1589
1589
  *
@@ -816,7 +816,7 @@ export class QueryBuilder {
816
816
  });
817
817
  }
818
818
  /**
819
- * Simply calls the given method passing `this` as the only argument.
819
+ * Simply calls the given function passing `this` as the only argument.
820
820
  *
821
821
  * This method can be useful when adding optional method calls:
822
822
  *
@@ -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;
@@ -15,6 +15,12 @@ export class DefaultQueryExecutor extends QueryExecutor {
15
15
  return connection.executeQuery(compiledQuery);
16
16
  });
17
17
  }
18
+ withPlugin(plugin) {
19
+ return new DefaultQueryExecutor(this.#compiler, this.#connectionProvider, [
20
+ ...this.plugins,
21
+ plugin,
22
+ ]);
23
+ }
18
24
  withPluginAtFront(plugin) {
19
25
  return new DefaultQueryExecutor(this.#compiler, this.#connectionProvider, [
20
26
  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
  }
@@ -14,6 +14,9 @@ export class NoopQueryExecutor extends QueryExecutor {
14
14
  withConnectionProvider() {
15
15
  throw new Error('this query cannot have a connection provider');
16
16
  }
17
+ withPlugin(plugin) {
18
+ return new NoopQueryExecutor([...this.plugins, plugin]);
19
+ }
17
20
  withPluginAtFront(plugin) {
18
21
  return new NoopQueryExecutor([plugin, ...this.plugins]);
19
22
  }
@@ -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
  */
@@ -1,8 +1,19 @@
1
1
  import { ArrayItemType } from './type-utils.js';
2
- export declare const LOG_LEVELS: readonly ["query"];
2
+ export declare const LOG_LEVELS: readonly ["query", "error"];
3
3
  export declare type LogLevel = ArrayItemType<typeof LOG_LEVELS>;
4
4
  export declare class Log {
5
5
  #private;
6
6
  constructor(levels: ReadonlyArray<LogLevel>);
7
- query(callback: (log: (message: string) => void) => void): void;
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;
8
19
  }
@@ -1,17 +1,33 @@
1
- export const LOG_LEVELS = ['query'];
1
+ import { freeze } from './object-utils.js';
2
+ export const LOG_LEVELS = ['query', 'error'];
2
3
  export class Log {
3
4
  #levels;
4
5
  constructor(levels) {
5
- this.#levels = {
6
+ this.#levels = freeze({
6
7
  query: levels.includes('query'),
7
- };
8
+ error: levels.includes('error'),
9
+ });
8
10
  }
9
- query(callback) {
11
+ query(getEvent) {
10
12
  if (this.#levels.query) {
11
- callback(this.#query);
13
+ this.#defaultQuery(getEvent());
12
14
  }
13
15
  }
14
- #query(message) {
15
- console.log(`kysely:query: ${message}`);
16
+ error(getEvent) {
17
+ if (this.#levels.error) {
18
+ this.#defaultError(getEvent());
19
+ }
20
+ }
21
+ #defaultQuery(event) {
22
+ console.log(`kysely:query: ${event.sql}`);
23
+ console.log(`kysely:query: duration: ${event.queryDurationMillis.toFixed(1)}ms`);
24
+ }
25
+ #defaultError(event) {
26
+ if (event.error instanceof Error) {
27
+ console.error(`kysely:error: ${event.error.stack ?? event.error.message}`);
28
+ }
29
+ else {
30
+ console.error(`kysely:error: ${event}`);
31
+ }
16
32
  }
17
33
  }
package/package.json CHANGED
@@ -1,11 +1,14 @@
1
1
  {
2
2
  "name": "kysely",
3
- "version": "0.9.4",
3
+ "version": "0.9.8",
4
4
  "description": "Type safe SQL query builder",
5
5
  "repository": {
6
6
  "type": "git",
7
7
  "url": "git://github.com/koskimas/kysely.git"
8
8
  },
9
+ "engines": {
10
+ "node": ">=16.0.0"
11
+ },
9
12
  "main": "dist/cjs/index.js",
10
13
  "module": "dist/esm/index.js",
11
14
  "exports": {