Skip to content

Commit 51ba4c3

Browse files
committed
feat(builder): reuse transaction and improve type
1 parent 9d8b23f commit 51ba4c3

File tree

2 files changed

+58
-14
lines changed

2 files changed

+58
-14
lines changed

packages/sqlite-builder/src/builder.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
1-
import type { Compilable, CompiledQuery, KyselyPlugin, LogEvent, QueryResult, RawBuilder, Simplify, Sql, Transaction } from 'kysely'
1+
import type { Compilable, CompiledQuery, KyselyPlugin, LogEvent, QueryResult, RawBuilder, Sql, Transaction } from 'kysely'
22
import { Kysely, sql } from 'kysely'
33
import { SqliteSerializePlugin } from 'kysely-plugin-serialize'
4+
import type { SimplifyResult } from 'kysely/dist/cjs/util/type-utils'
45
import { parseTableMap, runCreateTable } from './util'
56
import type { AvailableBuilder, ITable, Logger, SqliteBuilderOption } from './types'
7+
import { Stack } from './stack'
68

79
const enum DBStatus {
810
'needDrop',
@@ -14,6 +16,7 @@ export class SqliteBuilder<DB extends Record<string, any>> {
1416
private status: DBStatus
1517
private tableMap: Map<string, ITable<DB[Extract<keyof DB, string>]>>
1618
private logger?: Logger
19+
private trxs: Stack<Transaction<DB>>
1720
public constructor(option: SqliteBuilderOption<DB>) {
1821
const { dialect, tables, dropTableBeforeInit: truncateBeforeInit, onQuery, plugins: additionalPlugin, logger } = option
1922
this.logger = logger
@@ -32,6 +35,7 @@ export class SqliteBuilder<DB extends Record<string, any>> {
3235
? DBStatus.needDrop
3336
: DBStatus.noNeedDrop
3437
this.tableMap = parseTableMap(tables)
38+
this.trxs = new Stack()
3539
}
3640

3741
public async init(dropTableBeforeInit = false): Promise<SqliteBuilder<DB>> {
@@ -57,63 +61,76 @@ export class SqliteBuilder<DB extends Record<string, any>> {
5761
if (await this.isEmptyTable()) {
5862
return undefined
5963
}
60-
return await this.kysely.transaction().execute(cb)
64+
return await this.kysely.transaction()
65+
.execute((trx) => {
66+
this.trxs.push(trx)
67+
return cb(trx)
68+
})
6169
.catch((err) => {
6270
errorMsg && this.logger?.error(errorMsg, err)
6371
return undefined
6472
})
73+
.finally(() => {
74+
this.trxs.pop()
75+
})
76+
}
77+
78+
private getDB(): Kysely<DB> {
79+
return this.trxs.isEmpty() ? this.kysely : this.trxs.peek()
6580
}
6681

6782
public async exec<T>(
68-
cb: (db: Kysely<DB>) => Promise<T>,
83+
cb: (db: Kysely<DB> | Transaction<DB>) => Promise<T>,
6984
errorMsg?: string,
7085
): Promise<T | undefined> {
7186
if (await this.isEmptyTable()) {
7287
return undefined
7388
}
74-
return cb(this.kysely)
89+
return cb(this.getDB())
7590
.catch((err) => {
7691
errorMsg && this.logger?.error(errorMsg, err)
7792
return undefined
7893
})
7994
}
8095

8196
public async execOne<O>(
82-
cb: (db: Kysely<DB>) => AvailableBuilder<DB, O>,
97+
cb: (db: Kysely<DB> | Transaction<DB>) => AvailableBuilder<DB, O>,
8398
errorMsg?: string,
84-
): Promise<Simplify<O> | undefined> {
99+
): Promise<SimplifyResult<O> | undefined> {
85100
if (await this.isEmptyTable()) {
86101
return undefined
87102
}
88-
return cb(this.kysely).executeTakeFirstOrThrow()
103+
return cb(this.getDB())
104+
.executeTakeFirstOrThrow()
89105
.catch((err) => {
90106
errorMsg && this.logger?.error(errorMsg, err)
91107
return undefined
92-
})
108+
}) as any
93109
}
94110

95111
public async execList<O>(
96-
cb: (db: Kysely<DB>) => AvailableBuilder<DB, O>,
112+
cb: (db: Kysely<DB> | Transaction<DB>) => AvailableBuilder<DB, O>,
97113
errorMsg?: string,
98-
): Promise<Simplify<O>[] | undefined> {
114+
): Promise<SimplifyResult<O>[] | undefined> {
99115
if (await this.isEmptyTable()) {
100116
return undefined
101117
}
102-
return cb(this.kysely).execute()
118+
return cb(this.getDB())
119+
.execute()
103120
.catch((err) => {
104121
errorMsg && this.logger?.error(errorMsg, err)
105122
return undefined
106-
})
123+
}) as any
107124
}
108125

109126
public async toSQL<T extends Compilable>(cb: (db: Kysely<DB>) => T): Promise<CompiledQuery<unknown>> {
110-
return cb(this.kysely).compile()
127+
return cb(this.getDB()).compile()
111128
}
112129

113130
public async raw<T = any>(rawSql: (s: Sql) => RawBuilder<T>): Promise<QueryResult<T> | undefined> {
114131
if (await this.isEmptyTable()) {
115132
return undefined
116133
}
117-
return rawSql(sql).execute(this.kysely)
134+
return rawSql(sql).execute(this.getDB())
118135
}
119136
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
export class Stack<T> {
2+
private items: T[]
3+
4+
constructor() {
5+
this.items = []
6+
}
7+
8+
push(item: T) {
9+
this.items.push(item)
10+
}
11+
12+
pop() {
13+
return this.items.pop()
14+
}
15+
16+
peek() {
17+
return this.items[this.items.length - 1]
18+
}
19+
20+
isEmpty() {
21+
return this.items.length === 0
22+
}
23+
24+
size() {
25+
return this.items.length
26+
}
27+
}

0 commit comments

Comments
 (0)