Drizzle ORM adapter
Installation
- npm
- yarn
- pnpm
npm install @nestjs-cls/transactional-adapter-drizzle-orm
yarn add @nestjs-cls/transactional-adapter-drizzle-orm
pnpm add @nestjs-cls/transactional-adapter-drizzle-orm
Registration
ClsModule.forRoot({
plugins: [
new ClsPluginTransactional({
imports: [
// module in which Drizzle is provided
DrizzleModule
],
adapter: new TransactionalAdapterDrizzleOrm({
// the injection token of the Drizzle client instance
drizzleInstanceToken: DRIZZLE,
}),
}),
],
}),
Typing & usage
In Drizzle, the client type is inferred from the database type depending on the database driver.
For the typing to work properly, you need to provide the client type as the type parameter for the TransactionalAdapterDrizzleOrm
when injecting it.
For example, if you create a client like this:
const drizzleClient = drizzle('<connection string>'{
schema: {
users,
},
});
Then create a custom adapter type based on the client type:
type MyDrizzleAdapter = TransactionAdapterDrizzleOrm<typeof drizzleClient>;
And use it as a type parameter for TransactionHost
when injecting it:
constructor(
private readonly txHost: TransactionHost<MyDrizzleAdapter>,
) {}
Example
This example assumes usage with Postgres together with pg
and drizzle-orm/pg-core
database.ts
const users = pgTable('users', {
id: serial('id').primaryKey(),
name: text().notNull(),
email: text().notNull(),
});
const drizzleClient = drizzle(
new Pool({
connectionString: '<connection string>',
max: 2,
}),
{
schema: {
users,
},
},
);
type DrizzleClient = typeof drizzleClient;
type MyDrizzleAdapter = TransactionAdapterDrizzleOrm<DrizzleClient>;
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<MyDrizzleAdapter>) {}
async getUserById(id: number) {
// txHost.tx is typed as DrizzleClient
return this.tx.query.users.findFirst({
where: eq(users.id, id),
});
}
async createUser(name: string) {
const created = await this.tx
.insert(users)
.values({
name: name,
email: `${name}@email.com`,
})
.returning()
.execute();
return created[0];
}
}