Skip to content

Commit aed727e

Browse files
committed
general cleanup
1 parent 0d598f6 commit aed727e

File tree

8 files changed

+170
-152
lines changed

8 files changed

+170
-152
lines changed

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "kysely",
3-
"version": "0.9.4",
3+
"version": "0.9.5",
44
"description": "Type safe SQL query builder",
55
"repository": {
66
"type": "git",

src/dialect/mysql/mysql-dialect.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -235,6 +235,8 @@ export interface MysqlDialectConfig {
235235

236236
/**
237237
* Called once for each created connection.
238+
*
239+
* This is a Kysely specific feature and does not come from the `pg` module.
238240
*/
239241
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>
240242
}

src/dialect/postgres/postgres-dialect.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ export interface PostgresDialectConfig {
153153

154154
/**
155155
* Called once for each created connection.
156+
*
157+
* This is a Kysely specific feature and does not come from the `pg` module.
156158
*/
157159
onCreateConnection?: (connection: DatabaseConnection) => Promise<void>
158160

src/dialect/postgres/postgres-driver.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,11 +25,11 @@ export class PostgresDriver implements Driver {
2525
// installed. As you can see, there IS an import from `pg` at the
2626
// top level too, but that's only for types. It doesn't get compiled
2727
// into javascript. You can check the built javascript code.
28-
const PoolConstrucor = await importPgPool()
28+
const PoolConstructor = await importPgPool()
2929

3030
// Use the `pg` module's own pool. All drivers should use the
3131
// pool provided by the database library if possible.
32-
this.#pool = new PoolConstrucor(this.#config)
32+
this.#pool = new PoolConstructor(this.#config)
3333
}
3434

3535
async acquireConnection(): Promise<DatabaseConnection> {
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
import { DefaultQueryCompiler } from '../../query-compiler/default-query-compiler.js'
22

3-
// The default query compiler is for postgres dialect.
3+
// The default query compiler is for PostgreSQL.
44
export class PostgresQueryCompiler extends DefaultQueryCompiler {}
Lines changed: 9 additions & 148 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,4 @@
11
import { QueryResult } from '../../driver/database-connection.js'
2-
import { IdentifierNode } from '../../operation-node/identifier-node.js'
3-
import { OperationNodeTransformer } from '../../operation-node/operation-node-transformer.js'
42
import { RootOperationNode } from '../../query-compiler/query-compiler.js'
53
import { isObject } from '../../util/object-utils.js'
64
import { UnknownRow } from '../../util/type-utils.js'
@@ -9,6 +7,12 @@ import {
97
PluginTransformQueryArgs,
108
PluginTransformResultArgs,
119
} from '../kysely-plugin.js'
10+
import { SnakeCaseTransformer } from './camel-case-transformer.js'
11+
import {
12+
createCamelCaseMapper,
13+
createSnakeCaseMapper,
14+
StringMapper,
15+
} from './camel-case.js'
1216

1317
export interface CamelCasePluginOptions {
1418
/**
@@ -108,8 +112,8 @@ export class CamelCasePlugin implements KyselyPlugin {
108112
readonly #snakeCaseTransformer: SnakeCaseTransformer
109113

110114
constructor(opt: CamelCasePluginOptions = {}) {
111-
this.#camelCase = createCamelCase(opt)
112-
this.#snakeCase = createSnakeCase(opt)
115+
this.#camelCase = createCamelCaseMapper(opt)
116+
this.#snakeCase = createSnakeCaseMapper(opt)
113117

114118
this.#snakeCaseTransformer = new SnakeCaseTransformer(
115119
this.snakeCase.bind(this)
@@ -157,149 +161,6 @@ export class CamelCasePlugin implements KyselyPlugin {
157161
}
158162
}
159163

160-
type StringMapper = (str: string) => string
161-
162-
class SnakeCaseTransformer extends OperationNodeTransformer {
163-
readonly #snakeCase: StringMapper
164-
165-
constructor(snakeCase: StringMapper) {
166-
super()
167-
this.#snakeCase = snakeCase
168-
}
169-
170-
protected override transformIdentifier(node: IdentifierNode): IdentifierNode {
171-
node = super.transformIdentifier(node)
172-
173-
return {
174-
...node,
175-
identifier: this.#snakeCase(node.identifier),
176-
}
177-
}
178-
}
179-
180-
function canMap(obj: any): obj is Record<string, any> {
164+
function canMap(obj: unknown): obj is Record<string, unknown> {
181165
return isObject(obj) && !(obj instanceof Date) && !Buffer.isBuffer(obj)
182166
}
183-
184-
function createSnakeCase({
185-
upperCase = false,
186-
underscoreBeforeDigits = false,
187-
underscoreBetweenUppercaseLetters = false,
188-
} = {}): StringMapper {
189-
return memoize((str: string): string => {
190-
if (str.length === 0) {
191-
return str
192-
}
193-
194-
const upper = str.toUpperCase()
195-
const lower = str.toLowerCase()
196-
197-
let out = lower[0]
198-
199-
for (let i = 1, l = str.length; i < l; ++i) {
200-
const char = str[i]
201-
const prevChar = str[i - 1]
202-
203-
const upperChar = upper[i]
204-
const prevUpperChar = upper[i - 1]
205-
206-
const lowerChar = lower[i]
207-
const prevLowerChar = lower[i - 1]
208-
209-
// If underScoreBeforeDigits is true then, well, insert an underscore
210-
// before digits :). Only the first digit gets an underscore if
211-
// there are multiple.
212-
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
213-
out += '_' + char
214-
continue
215-
}
216-
217-
// Test if `char` is an upper-case character and that the character
218-
// actually has different upper and lower case versions.
219-
if (char === upperChar && upperChar !== lowerChar) {
220-
const prevCharacterIsUppercase =
221-
prevChar === prevUpperChar && prevUpperChar !== prevLowerChar
222-
223-
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
224-
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
225-
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
226-
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
227-
out += '_' + lowerChar
228-
} else {
229-
out += lowerChar
230-
}
231-
} else {
232-
out += char
233-
}
234-
}
235-
236-
if (upperCase) {
237-
return out.toUpperCase()
238-
} else {
239-
return out
240-
}
241-
})
242-
}
243-
244-
function createCamelCase({ upperCase = false } = {}): StringMapper {
245-
return memoize((str: string): string => {
246-
if (str.length === 0) {
247-
return str
248-
}
249-
250-
if (upperCase && isAllUpperCaseSnakeCase(str)) {
251-
// Only convert to lower case if the string is all upper
252-
// case snake_case. This allows camelCase strings to go
253-
// through without changing.
254-
str = str.toLowerCase()
255-
}
256-
257-
let out = str[0]
258-
259-
for (let i = 1, l = str.length; i < l; ++i) {
260-
const char = str[i]
261-
const prevChar = str[i - 1]
262-
263-
if (char !== '_') {
264-
if (prevChar === '_') {
265-
out += char.toUpperCase()
266-
} else {
267-
out += char
268-
}
269-
}
270-
}
271-
272-
return out
273-
})
274-
}
275-
276-
function isAllUpperCaseSnakeCase(str: string): boolean {
277-
for (let i = 1, l = str.length; i < l; ++i) {
278-
const char = str[i]
279-
280-
if (char !== '_' && char !== char.toUpperCase()) {
281-
return false
282-
}
283-
}
284-
285-
return true
286-
}
287-
288-
function isDigit(char: string): boolean {
289-
return char >= '0' && char <= '9'
290-
}
291-
292-
function memoize(func: StringMapper): StringMapper {
293-
const cache = new Map<string, string>()
294-
295-
return (str: string) => {
296-
let mapped = cache.get(str)
297-
298-
if (!mapped) {
299-
mapped = func(str)
300-
cache.set(str, mapped)
301-
}
302-
303-
return mapped
304-
}
305-
}
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
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+
5+
export class SnakeCaseTransformer extends OperationNodeTransformer {
6+
readonly #snakeCase: StringMapper
7+
8+
constructor(snakeCase: StringMapper) {
9+
super()
10+
this.#snakeCase = snakeCase
11+
}
12+
13+
protected override transformIdentifier(node: IdentifierNode): IdentifierNode {
14+
node = super.transformIdentifier(node)
15+
16+
return {
17+
...node,
18+
identifier: this.#snakeCase(node.identifier),
19+
}
20+
}
21+
}
Lines changed: 132 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
export type StringMapper = (str: string) => string
2+
3+
/**
4+
* Creates a function that transforms camel case strings to snake case.
5+
*/
6+
export function createSnakeCaseMapper({
7+
upperCase = false,
8+
underscoreBeforeDigits = false,
9+
underscoreBetweenUppercaseLetters = false,
10+
} = {}): StringMapper {
11+
return memoize((str: string): string => {
12+
if (str.length === 0) {
13+
return str
14+
}
15+
16+
const upper = str.toUpperCase()
17+
const lower = str.toLowerCase()
18+
19+
let out = lower[0]
20+
21+
for (let i = 1, l = str.length; i < l; ++i) {
22+
const char = str[i]
23+
const prevChar = str[i - 1]
24+
25+
const upperChar = upper[i]
26+
const prevUpperChar = upper[i - 1]
27+
28+
const lowerChar = lower[i]
29+
const prevLowerChar = lower[i - 1]
30+
31+
// If underScoreBeforeDigits is true then, well, insert an underscore
32+
// before digits :). Only the first digit gets an underscore if
33+
// there are multiple.
34+
if (underscoreBeforeDigits && isDigit(char) && !isDigit(prevChar)) {
35+
out += '_' + char
36+
continue
37+
}
38+
39+
// Test if `char` is an upper-case character and that the character
40+
// actually has different upper and lower case versions.
41+
if (char === upperChar && upperChar !== lowerChar) {
42+
const prevCharacterIsUppercase =
43+
prevChar === prevUpperChar && prevUpperChar !== prevLowerChar
44+
45+
// If underscoreBetweenUppercaseLetters is true, we always place an underscore
46+
// before consecutive uppercase letters (e.g. "fooBAR" becomes "foo_b_a_r").
47+
// Otherwise, we don't (e.g. "fooBAR" becomes "foo_bar").
48+
if (underscoreBetweenUppercaseLetters || !prevCharacterIsUppercase) {
49+
out += '_' + lowerChar
50+
} else {
51+
out += lowerChar
52+
}
53+
} else {
54+
out += char
55+
}
56+
}
57+
58+
if (upperCase) {
59+
return out.toUpperCase()
60+
} else {
61+
return out
62+
}
63+
})
64+
}
65+
66+
/**
67+
* Creates a function that transforms snake case strings to camel case.
68+
*/
69+
export function createCamelCaseMapper({
70+
upperCase = false,
71+
} = {}): StringMapper {
72+
return memoize((str: string): string => {
73+
if (str.length === 0) {
74+
return str
75+
}
76+
77+
if (upperCase && isAllUpperCaseSnakeCase(str)) {
78+
// Only convert to lower case if the string is all upper
79+
// case snake_case. This allows camelCase strings to go
80+
// through without changing.
81+
str = str.toLowerCase()
82+
}
83+
84+
let out = str[0]
85+
86+
for (let i = 1, l = str.length; i < l; ++i) {
87+
const char = str[i]
88+
const prevChar = str[i - 1]
89+
90+
if (char !== '_') {
91+
if (prevChar === '_') {
92+
out += char.toUpperCase()
93+
} else {
94+
out += char
95+
}
96+
}
97+
}
98+
99+
return out
100+
})
101+
}
102+
103+
function isAllUpperCaseSnakeCase(str: string): boolean {
104+
for (let i = 1, l = str.length; i < l; ++i) {
105+
const char = str[i]
106+
107+
if (char !== '_' && char !== char.toUpperCase()) {
108+
return false
109+
}
110+
}
111+
112+
return true
113+
}
114+
115+
function isDigit(char: string): boolean {
116+
return char >= '0' && char <= '9'
117+
}
118+
119+
function memoize(func: StringMapper): StringMapper {
120+
const cache = new Map<string, string>()
121+
122+
return (str: string) => {
123+
let mapped = cache.get(str)
124+
125+
if (!mapped) {
126+
mapped = func(str)
127+
cache.set(str, mapped)
128+
}
129+
130+
return mapped
131+
}
132+
}

0 commit comments

Comments
 (0)