What code does is that it wraps Drizzle transaction function into number of helpers to allow you safely extract transaction, while keeping proper error handling.
It uses PostgreSQL types for simplicity, but it can be done with any data source since transaction is part of basic interface.
Transaction parameters are not passed here for example, you can easily add those and pass directly
// 1. Get drizzle
const db = drizzle({ ... });
// 2. Create extractor - you'll need it to commit or rollback session properly
const extractor = new DrizzlePgTransactionExtractor(db);
// 3. Get transaction. If will throw if init failed (e.g. failed to create connection)
const trx = await extractor.extractTransaction();
// Handle commit & rollback operations manyally with any dedgee control you want
try {
await trx.execute(sql`....`)
await trx.commit();
} (err) {
// tryRollback is used because `.commit` error may be raised while doing commit,
// so that we marked state as closed, but then it failed with exception and got
// into try catch
await trx.tryRollback();
}
While original approach is fine, it takes control from you where transaction is created - it always happens in direct DB call. So if you want to add some layers in the middle (logging, monitoring, etc), or you want to have more smart transaction management - that may become cumbersome.
Honestly not happy with Drizzle design choices, since all pieces are there, and it can be implemented so easily in source code - but intention obviously is different. Also rollback with sync error throwing is bruh 😅