Kysely adapter
Installation
- npm
- yarn
- pnpm
npm install @nestjs-cls/transactional-adapter-kysely
yarn add @nestjs-cls/transactional-adapter-kysely
pnpm add @nestjs-cls/transactional-adapter-kysely
Registration
ClsModule.forRoot({
plugins: [
new ClsPluginTransactional({
imports: [
// module in which Kysely is provided
KyselyModule
],
adapter: new TransactionalAdapterKysely({
// the injection token of the Kysely client instance
kyselyInstanceToken: KYSELY,
}),
}),
],
}),
Typing & usage
The tx
property on the TransactionHost<TransactionalAdapterKysely>
is typed as Kysely<any>
by default. To get the full typing, you need to supply your database type as the type parameter for the TransactionalAdapterKysely
when injecting it:
constructor(
private readonly txHost: TransactionHost<
TransactionalAdapterKysely<Database>
>,
) {}
tip
This may get a bit too verbose, so you you might want to create a type alias for it:
type MyKyselyAdapter = TransactionalAdapterKysely<Database>;
and then inject it with
constructor(
private readonly txHost: TransactionHost<MyKyselyAdapter>,
) {}
Example
database.type.ts
interface Database {
user: User;
}
interface User {
id: Generated<number>;
name: string;
email: string;
}
user.service.ts
@Injectable()
class UserService {
constructor(private readonly userRepository: UserRepository) {}
@Transactional()
async runTransaction() {
// both methods are executed in the same transaction
const user = await this.userRepository.createUser('John');
const foundUser = await this.userRepository.getUserById(user.id);
assert(foundUser.id === user.id);
}
}
user.repository.ts
@Injectable()
class UserRepository {
constructor(
private readonly txHost: TransactionHost<
TransactionalAdapterKysely<Database>
>,
) {}
async getUserById(id: number) {
// txHost.tx is typed as Kysely<Database>
return this.txHost.tx
.selectFrom('user')
.where('id', '=', id)
.selectAll()
.executeTakeFirst();
}
async createUser(name: string) {
return this.txHost.tx
.insertInto('user')
.values({
name: name,
email: `${name}@email.com`,
})
.returningAll()
.executeTakeFirstOrThrow();
}
}