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.
- package/dist/cjs/dialect/mysql/mysql-dialect.d.ts +2 -0
- package/dist/cjs/dialect/postgres/postgres-dialect.d.ts +2 -0
- package/dist/cjs/dialect/postgres/postgres-driver.js +2 -2
- package/dist/cjs/dialect/postgres/postgres-query-compiler.js +1 -1
- package/dist/cjs/driver/runtime-driver.js +20 -6
- package/dist/cjs/index.d.ts +1 -0
- package/dist/cjs/kysely.d.ts +8 -3
- package/dist/cjs/kysely.js +9 -0
- package/dist/cjs/operation-node/operator-node.d.ts +1 -1
- package/dist/cjs/operation-node/operator-node.js +6 -0
- package/dist/cjs/plugin/camel-case/camel-case-plugin.js +5 -116
- package/dist/cjs/plugin/camel-case/camel-case-transformer.d.ts +8 -0
- package/dist/cjs/plugin/camel-case/camel-case-transformer.js +19 -0
- package/dist/cjs/plugin/camel-case/camel-case.d.ts +15 -0
- package/dist/cjs/plugin/camel-case/camel-case.js +109 -0
- package/dist/cjs/plugin/kysely-plugin.d.ts +1 -1
- package/dist/cjs/query-builder/query-builder.d.ts +1 -1
- package/dist/cjs/query-builder/query-builder.js +1 -1
- package/dist/cjs/query-executor/default-query-executor.d.ts +1 -0
- package/dist/cjs/query-executor/default-query-executor.js +6 -0
- package/dist/cjs/query-executor/noop-query-executor.d.ts +1 -0
- package/dist/cjs/query-executor/noop-query-executor.js +3 -0
- package/dist/cjs/query-executor/query-executor.d.ts +9 -4
- package/dist/cjs/util/log.d.ts +13 -2
- package/dist/cjs/util/log.js +23 -7
- package/dist/esm/dialect/mysql/mysql-dialect.d.ts +2 -0
- package/dist/esm/dialect/postgres/postgres-dialect.d.ts +2 -0
- package/dist/esm/dialect/postgres/postgres-driver.js +2 -2
- package/dist/esm/dialect/postgres/postgres-query-compiler.js +1 -1
- package/dist/esm/driver/runtime-driver.js +20 -6
- package/dist/esm/index.d.ts +1 -0
- package/dist/esm/kysely.d.ts +8 -3
- package/dist/esm/kysely.js +9 -0
- package/dist/esm/operation-node/operator-node.d.ts +1 -1
- package/dist/esm/operation-node/operator-node.js +6 -0
- package/dist/esm/plugin/camel-case/camel-case-plugin.js +4 -115
- package/dist/esm/plugin/camel-case/camel-case-transformer.d.ts +8 -0
- package/dist/esm/plugin/camel-case/camel-case-transformer.js +15 -0
- package/dist/esm/plugin/camel-case/camel-case.d.ts +15 -0
- package/dist/esm/plugin/camel-case/camel-case.js +104 -0
- package/dist/esm/plugin/kysely-plugin.d.ts +1 -1
- package/dist/esm/query-builder/query-builder.d.ts +1 -1
- package/dist/esm/query-builder/query-builder.js +1 -1
- package/dist/esm/query-executor/default-query-executor.d.ts +1 -0
- package/dist/esm/query-executor/default-query-executor.js +6 -0
- package/dist/esm/query-executor/noop-query-executor.d.ts +1 -0
- package/dist/esm/query-executor/noop-query-executor.js +3 -0
- package/dist/esm/query-executor/query-executor.d.ts +9 -4
- package/dist/esm/util/log.d.ts +13 -2
- package/dist/esm/util/log.js +23 -7
- package/package.json +4 -1
|
@@ -185,6 +185,8 @@ export interface MysqlDialectConfig {
|
|
|
185
185
|
keepAliveInitialDelay?: number;
|
|
186
186
|
/**
|
|
187
187
|
* Called once for each created connection.
|
|
188
|
+
*
|
|
189
|
+
* This is a Kysely specific feature and does not come from the `pg` module.
|
|
188
190
|
*/
|
|
189
191
|
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
|
|
190
192
|
}
|
|
@@ -115,6 +115,8 @@ export interface PostgresDialectConfig {
|
|
|
115
115
|
application_name?: string;
|
|
116
116
|
/**
|
|
117
117
|
* Called once for each created connection.
|
|
118
|
+
*
|
|
119
|
+
* This is a Kysely specific feature and does not come from the `pg` module.
|
|
118
120
|
*/
|
|
119
121
|
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
|
|
120
122
|
keepAlive?: boolean;
|
|
@@ -16,10 +16,10 @@ class PostgresDriver {
|
|
|
16
16
|
// installed. As you can see, there IS an import from `pg` at the
|
|
17
17
|
// top level too, but that's only for types. It doesn't get compiled
|
|
18
18
|
// into javascript. You can check the built javascript code.
|
|
19
|
-
const
|
|
19
|
+
const PoolConstructor = await importPgPool();
|
|
20
20
|
// Use the `pg` module's own pool. All drivers should use the
|
|
21
21
|
// pool provided by the database library if possible.
|
|
22
|
-
this.#pool = new
|
|
22
|
+
this.#pool = new PoolConstructor(this.#config);
|
|
23
23
|
}
|
|
24
24
|
async acquireConnection() {
|
|
25
25
|
const client = await this.#pool.connect();
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.PostgresQueryCompiler = void 0;
|
|
4
4
|
const default_query_compiler_js_1 = require("../../query-compiler/default-query-compiler.js");
|
|
5
|
-
// The default query compiler is for
|
|
5
|
+
// The default query compiler is for PostgreSQL.
|
|
6
6
|
class PostgresQueryCompiler extends default_query_compiler_js_1.DefaultQueryCompiler {
|
|
7
7
|
}
|
|
8
8
|
exports.PostgresQueryCompiler = PostgresQueryCompiler;
|
|
@@ -79,16 +79,30 @@ class RuntimeConnection {
|
|
|
79
79
|
try {
|
|
80
80
|
return await this.#connection.executeQuery(compiledQuery);
|
|
81
81
|
}
|
|
82
|
+
catch (error) {
|
|
83
|
+
this.#logError(error);
|
|
84
|
+
throw error;
|
|
85
|
+
}
|
|
82
86
|
finally {
|
|
83
|
-
this.#
|
|
84
|
-
log(compiledQuery.sql);
|
|
85
|
-
log(`duration: ${this.#calculateDurationMillis(startTime)}ms`);
|
|
86
|
-
});
|
|
87
|
+
this.#logQuery(compiledQuery, startTime);
|
|
87
88
|
}
|
|
88
89
|
}
|
|
90
|
+
#logError(error) {
|
|
91
|
+
this.#log.error(() => ({
|
|
92
|
+
level: 'error',
|
|
93
|
+
error,
|
|
94
|
+
}));
|
|
95
|
+
}
|
|
96
|
+
#logQuery(compiledQuery, startTime) {
|
|
97
|
+
this.#log.query(() => ({
|
|
98
|
+
level: 'query',
|
|
99
|
+
sql: compiledQuery.sql,
|
|
100
|
+
queryDurationMillis: this.#calculateDurationMillis(startTime),
|
|
101
|
+
}));
|
|
102
|
+
}
|
|
89
103
|
#calculateDurationMillis(startTime) {
|
|
90
104
|
const endTime = process.hrtime.bigint();
|
|
91
|
-
const
|
|
92
|
-
return
|
|
105
|
+
const durationNanos = Number(endTime - startTime);
|
|
106
|
+
return durationNanos / 1_000_000;
|
|
93
107
|
}
|
|
94
108
|
}
|
package/dist/cjs/index.d.ts
CHANGED
|
@@ -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';
|
package/dist/cjs/kysely.d.ts
CHANGED
|
@@ -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
|
|
235
|
-
*
|
|
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
|
}
|
package/dist/cjs/kysely.js
CHANGED
|
@@ -238,6 +238,15 @@ class Kysely extends query_creator_js_1.QueryCreator {
|
|
|
238
238
|
connection() {
|
|
239
239
|
return new ConnectionBuilder({ ...this.#props });
|
|
240
240
|
}
|
|
241
|
+
/**
|
|
242
|
+
* Returns a copy of this Kysely instance with the given plugin installed.
|
|
243
|
+
*/
|
|
244
|
+
withPlugin(plugin) {
|
|
245
|
+
return new Kysely({
|
|
246
|
+
...this.#props,
|
|
247
|
+
executor: this.#props.executor.withPlugin(plugin),
|
|
248
|
+
});
|
|
249
|
+
}
|
|
241
250
|
/**
|
|
242
251
|
* Returns a copy of this Kysely instance without any plugins.
|
|
243
252
|
*/
|
|
@@ -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';
|
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.CamelCasePlugin = void 0;
|
|
4
|
-
const operation_node_transformer_js_1 = require("../../operation-node/operation-node-transformer.js");
|
|
5
4
|
const object_utils_js_1 = require("../../util/object-utils.js");
|
|
5
|
+
const camel_case_transformer_js_1 = require("./camel-case-transformer.js");
|
|
6
|
+
const camel_case_js_1 = require("./camel-case.js");
|
|
6
7
|
/**
|
|
7
8
|
* A plugin that converts snake_case identifiers in the database into
|
|
8
9
|
* camelCase in the javascript side.
|
|
@@ -72,9 +73,9 @@ class CamelCasePlugin {
|
|
|
72
73
|
#snakeCase;
|
|
73
74
|
#snakeCaseTransformer;
|
|
74
75
|
constructor(opt = {}) {
|
|
75
|
-
this.#camelCase =
|
|
76
|
-
this.#snakeCase =
|
|
77
|
-
this.#snakeCaseTransformer = new SnakeCaseTransformer(this.snakeCase.bind(this));
|
|
76
|
+
this.#camelCase = (0, camel_case_js_1.createCamelCaseMapper)(opt);
|
|
77
|
+
this.#snakeCase = (0, camel_case_js_1.createSnakeCaseMapper)(opt);
|
|
78
|
+
this.#snakeCaseTransformer = new camel_case_transformer_js_1.SnakeCaseTransformer(this.snakeCase.bind(this));
|
|
78
79
|
}
|
|
79
80
|
transformQuery(args) {
|
|
80
81
|
return this.#snakeCaseTransformer.transformNode(args.node);
|
|
@@ -109,118 +110,6 @@ class CamelCasePlugin {
|
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
exports.CamelCasePlugin = CamelCasePlugin;
|
|
112
|
-
class SnakeCaseTransformer extends operation_node_transformer_js_1.OperationNodeTransformer {
|
|
113
|
-
#snakeCase;
|
|
114
|
-
constructor(snakeCase) {
|
|
115
|
-
super();
|
|
116
|
-
this.#snakeCase = snakeCase;
|
|
117
|
-
}
|
|
118
|
-
transformIdentifier(node) {
|
|
119
|
-
node = super.transformIdentifier(node);
|
|
120
|
-
return {
|
|
121
|
-
...node,
|
|
122
|
-
identifier: this.#snakeCase(node.identifier),
|
|
123
|
-
};
|
|
124
|
-
}
|
|
125
|
-
}
|
|
126
113
|
function canMap(obj) {
|
|
127
114
|
return (0, object_utils_js_1.isObject)(obj) && !(obj instanceof Date) && !Buffer.isBuffer(obj);
|
|
128
115
|
}
|
|
129
|
-
function createSnakeCase({ upperCase = false, underscoreBeforeDigits = false, underscoreBetweenUppercaseLetters = false, } = {}) {
|
|
130
|
-
return memoize((str) => {
|
|
131
|
-
if (str.length === 0) {
|
|
132
|
-
return str;
|
|
133
|
-
}
|
|
134
|
-
const upper = str.toUpperCase();
|
|
135
|
-
const lower = str.toLowerCase();
|
|
136
|
-
let out = lower[0];
|
|
137
|
-
for (let i = 1, l = str.length; i < l; ++i) {
|
|
138
|
-
const char = str[i];
|
|
139
|
-
const prevChar = str[i - 1];
|
|
140
|
-
const upperChar = upper[i];
|
|
141
|
-
const prevUpperChar = upper[i - 1];
|
|
142
|
-
const lowerChar = lower[i];
|
|
143
|
-
const prevLowerChar = lower[i - 1];
|
|
144
|
-
// If underScoreBeforeDigits is true then, well, insert an underscore
|
|
145
|
-
// before digits :). Only the first digit gets an underscore if
|
|
146
|
-
// there are multiple.
|
|
147
|
-
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
|
|
148
|
-
out += '_' + char;
|
|
149
|
-
continue;
|
|
150
|
-
}
|
|
151
|
-
// Test if `char` is an upper-case character and that the character
|
|
152
|
-
// actually has different upper and lower case versions.
|
|
153
|
-
if (char === upperChar && upperChar !== lowerChar) {
|
|
154
|
-
const prevCharacterIsUppercase = prevChar === prevUpperChar && prevUpperChar !== prevLowerChar;
|
|
155
|
-
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
|
|
156
|
-
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
|
|
157
|
-
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
|
|
158
|
-
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
|
|
159
|
-
out += '_' + lowerChar;
|
|
160
|
-
}
|
|
161
|
-
else {
|
|
162
|
-
out += lowerChar;
|
|
163
|
-
}
|
|
164
|
-
}
|
|
165
|
-
else {
|
|
166
|
-
out += char;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
if (upperCase) {
|
|
170
|
-
return out.toUpperCase();
|
|
171
|
-
}
|
|
172
|
-
else {
|
|
173
|
-
return out;
|
|
174
|
-
}
|
|
175
|
-
});
|
|
176
|
-
}
|
|
177
|
-
function createCamelCase({ upperCase = false } = {}) {
|
|
178
|
-
return memoize((str) => {
|
|
179
|
-
if (str.length === 0) {
|
|
180
|
-
return str;
|
|
181
|
-
}
|
|
182
|
-
if (upperCase && isAllUpperCaseSnakeCase(str)) {
|
|
183
|
-
// Only convert to lower case if the string is all upper
|
|
184
|
-
// case snake_case. This allows camelCase strings to go
|
|
185
|
-
// through without changing.
|
|
186
|
-
str = str.toLowerCase();
|
|
187
|
-
}
|
|
188
|
-
let out = str[0];
|
|
189
|
-
for (let i = 1, l = str.length; i < l; ++i) {
|
|
190
|
-
const char = str[i];
|
|
191
|
-
const prevChar = str[i - 1];
|
|
192
|
-
if (char !== '_') {
|
|
193
|
-
if (prevChar === '_') {
|
|
194
|
-
out += char.toUpperCase();
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
out += char;
|
|
198
|
-
}
|
|
199
|
-
}
|
|
200
|
-
}
|
|
201
|
-
return out;
|
|
202
|
-
});
|
|
203
|
-
}
|
|
204
|
-
function isAllUpperCaseSnakeCase(str) {
|
|
205
|
-
for (let i = 1, l = str.length; i < l; ++i) {
|
|
206
|
-
const char = str[i];
|
|
207
|
-
if (char !== '_' && char !== char.toUpperCase()) {
|
|
208
|
-
return false;
|
|
209
|
-
}
|
|
210
|
-
}
|
|
211
|
-
return true;
|
|
212
|
-
}
|
|
213
|
-
function isDigit(char) {
|
|
214
|
-
return char >= '0' && char <= '9';
|
|
215
|
-
}
|
|
216
|
-
function memoize(func) {
|
|
217
|
-
const cache = new Map();
|
|
218
|
-
return (str) => {
|
|
219
|
-
let mapped = cache.get(str);
|
|
220
|
-
if (!mapped) {
|
|
221
|
-
mapped = func(str);
|
|
222
|
-
cache.set(str, mapped);
|
|
223
|
-
}
|
|
224
|
-
return mapped;
|
|
225
|
-
};
|
|
226
|
-
}
|
|
@@ -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,19 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.SnakeCaseTransformer = void 0;
|
|
4
|
+
const operation_node_transformer_js_1 = require("../../operation-node/operation-node-transformer.js");
|
|
5
|
+
class SnakeCaseTransformer extends operation_node_transformer_js_1.OperationNodeTransformer {
|
|
6
|
+
#snakeCase;
|
|
7
|
+
constructor(snakeCase) {
|
|
8
|
+
super();
|
|
9
|
+
this.#snakeCase = snakeCase;
|
|
10
|
+
}
|
|
11
|
+
transformIdentifier(node) {
|
|
12
|
+
node = super.transformIdentifier(node);
|
|
13
|
+
return {
|
|
14
|
+
...node,
|
|
15
|
+
identifier: this.#snakeCase(node.identifier),
|
|
16
|
+
};
|
|
17
|
+
}
|
|
18
|
+
}
|
|
19
|
+
exports.SnakeCaseTransformer = SnakeCaseTransformer;
|
|
@@ -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,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<
|
|
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
|
|
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
|
*
|
|
@@ -819,7 +819,7 @@ class QueryBuilder {
|
|
|
819
819
|
});
|
|
820
820
|
}
|
|
821
821
|
/**
|
|
822
|
-
* Simply calls the given
|
|
822
|
+
* Simply calls the given function passing `this` as the only argument.
|
|
823
823
|
*
|
|
824
824
|
* This method can be useful when adding optional method calls:
|
|
825
825
|
*
|
|
@@ -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
|
-
*
|
|
44
|
+
* last plugin.
|
|
41
45
|
*/
|
|
42
|
-
abstract
|
|
46
|
+
abstract withPlugin(plugin: KyselyPlugin): QueryExecutor;
|
|
43
47
|
/**
|
|
44
|
-
* Returns a copy of this executor with a
|
|
48
|
+
* Returns a copy of this executor with a plugin added as the
|
|
49
|
+
* first plugin.
|
|
45
50
|
*/
|
|
46
|
-
abstract
|
|
51
|
+
abstract withPluginAtFront(plugin: KyselyPlugin): QueryExecutor;
|
|
47
52
|
/**
|
|
48
53
|
* Returns a copy of this executor without any plugins.
|
|
49
54
|
*/
|
package/dist/cjs/util/log.d.ts
CHANGED
|
@@ -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(
|
|
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
|
}
|
package/dist/cjs/util/log.js
CHANGED
|
@@ -1,21 +1,37 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.Log = exports.LOG_LEVELS = void 0;
|
|
4
|
-
|
|
4
|
+
const object_utils_js_1 = require("./object-utils.js");
|
|
5
|
+
exports.LOG_LEVELS = ['query', 'error'];
|
|
5
6
|
class Log {
|
|
6
7
|
#levels;
|
|
7
8
|
constructor(levels) {
|
|
8
|
-
this.#levels = {
|
|
9
|
+
this.#levels = (0, object_utils_js_1.freeze)({
|
|
9
10
|
query: levels.includes('query'),
|
|
10
|
-
|
|
11
|
+
error: levels.includes('error'),
|
|
12
|
+
});
|
|
11
13
|
}
|
|
12
|
-
query(
|
|
14
|
+
query(getEvent) {
|
|
13
15
|
if (this.#levels.query) {
|
|
14
|
-
|
|
16
|
+
this.#defaultQuery(getEvent());
|
|
15
17
|
}
|
|
16
18
|
}
|
|
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
|
+
}
|
|
19
35
|
}
|
|
20
36
|
}
|
|
21
37
|
exports.Log = Log;
|
|
@@ -185,6 +185,8 @@ export interface MysqlDialectConfig {
|
|
|
185
185
|
keepAliveInitialDelay?: number;
|
|
186
186
|
/**
|
|
187
187
|
* Called once for each created connection.
|
|
188
|
+
*
|
|
189
|
+
* This is a Kysely specific feature and does not come from the `pg` module.
|
|
188
190
|
*/
|
|
189
191
|
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
|
|
190
192
|
}
|
|
@@ -115,6 +115,8 @@ export interface PostgresDialectConfig {
|
|
|
115
115
|
application_name?: string;
|
|
116
116
|
/**
|
|
117
117
|
* Called once for each created connection.
|
|
118
|
+
*
|
|
119
|
+
* This is a Kysely specific feature and does not come from the `pg` module.
|
|
118
120
|
*/
|
|
119
121
|
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>;
|
|
120
122
|
keepAlive?: boolean;
|
|
@@ -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
|
|
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
|
|
19
|
+
this.#pool = new PoolConstructor(this.#config);
|
|
20
20
|
}
|
|
21
21
|
async acquireConnection() {
|
|
22
22
|
const client = await this.#pool.connect();
|