npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@nest-omni/transaction

v1.0.1

Published

Transaction management library for NestJS + TypeORM with AsyncLocalStorage support

Downloads

245

Readme

@nest-omni/transaction

Transaction management library for NestJS + TypeORM with AsyncLocalStorage support.

Installation

npm install @nest-omni/transaction
npm install typeorm reflect-metadata
yarn add @nest-omni/transaction
yarn add typeorm reflect-metadata

Quick Start

1. Register Module

Register TransactionModule in your AppModule. It automatically discovers all TypeORM DataSources:

// app.module.ts
import { Module } from '@nestjs/common';
import { TransactionModule } from '@nest-omni/transaction';

@Module({
  imports: [
    TransactionModule.forRoot(),
    // ... 其他模块
  ],
})
export class AppModule {}

在入口文件导入 reflect-metadata

// main.ts
import 'reflect-metadata';
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
  const app = await NestFactory.create(AppModule);
  await app.listen(3000);
}
bootstrap();

2. Basic Usage

import { Injectable } from '@nestjs/common';
import { Transactional } from '@nest-omni/transaction';
import { User } from './user.entity';
import { DataSource } from 'typeorm';

@Injectable()
export class UserService {
  constructor(
    private readonly dataSource: DataSource,
  ) {}

  @Transactional()
  async createUser(name: string, email: string) {
    // 使用 QueryRunner 自动管理事务
    await this.dataSource.query(
      'INSERT INTO user (name, email) VALUES (?, ?)',
      [name, email]
    );

    // Repository 也在同一事务中
    const user = this.dataSource.getRepository(User).create({ name, email });
    await this.dataSource.getRepository(User).save(user);
  }
}

3. Transaction Propagation

@Injectable()
export class OrderService {
  constructor(
    private readonly userService: UserService,
    private readonly productService: ProductService,
  ) {}

  @Transactional()
  async createOrder(userId: string, productId: string) {
    // REQUIRED: 加入当前事务,如果没有则创建新事务
    await this.userService.updateBalance(userId, -100);

    // REQUIRES_NEW: 总是创建新事务
    await this.productService.recordSale(productId);

    // NESTED: 创建嵌套事务,回滚不影响父事务
    await this.notifyUser(userId);
  }

  @Transactional({ propagation: Propagation.REQUIRES_NEW })
  async recordSale(productId: string) {
    // 独立事务
  }

  @Transactional({ propagation: Propagation.NESTED })
  async notifyUser(userId: string) {
    // 嵌套事务,回滚不会导致 createOrder 回滚
  }
}

Multiple DataSources

@Module({
  imports: [
    TransactionModule.forRoot(),

    TypeOrmModule.forRoot({
      type: 'postgres',
      host: 'localhost',
      port: 5432,
      database: 'main_db',
    }),

    TypeOrmModule.forRoot({
      name: 'log-db',
      type: 'postgres',
      host: 'localhost',
      port: 5433,
      database: 'log_db',
    }),
  ],
})
export class AppModule {}

指定数据源:

@Injectable()
export class LogService {
  @Transactional({ connectionName: 'log-db' })
  async writeLog(message: string) {
    // 使用 log-db 数据源
  }
}

Transaction Hooks

Method 1: Using Listeners

import { Injectable } from '@nestjs/common';
import { TransactionEventListener } from '@nest-omni/transaction';

@Injectable()
export class OrderEventListener implements TransactionEventListener {
  async onCommit(...args: unknown[]) {
    // Execute after transaction commit
    console.log('Order created successfully', args);
  }

  async onRollback(error: Error, ...args: unknown[]) {
    // Execute after transaction rollback
    console.error('Order creation failed', error);
  }
}
@Injectable()
export class OrderService {
  @Transactional()
  @TransactionalEventListeners(OrderEventListener)
  async createOrder(data: OrderDto) {
    // 业务逻辑
  }
}

Method 2: Using Hook Functions

import { runOnTransactionCommit, runOnTransactionRollback } from '@nest-omni/transaction';

@Injectable()
export class OrderService {
  @Transactional()
  async createOrder(data: OrderDto) {
    // 业务逻辑...

    // 提交后执行
    runOnTransactionCommit(async () => {
      await this.emailService.sendConfirmation();
    });

    // 回滚后执行
    runOnTransactionRollback(async (error) => {
      await this.loggingService.logError(error);
    });
  }
}

Transaction Options

@Transactional({
  // DataSource name
  connectionName?: string;

  // Isolation level
  isolationLevel?: IsolationLevel;

  // Propagation behavior
  propagation?: Propagation;
})

Propagation

| Value | Description | |---|---| | REQUIRED | Default. Join existing transaction, or create new if none | | SUPPORTS | Join existing transaction, or execute non-transactional if none | | NESTED | Nested transaction, rollback doesn't affect parent transaction | | REQUIRES_NEW | Always create new transaction, suspend current transaction |

Isolation Level

| Value | Description | |---|---| | READ_UNCOMMITTED | Read uncommitted | | READ_COMMITTED | Read committed (default) | | REPEATABLE_READ | Repeatable read | | SERIALIZABLE | Serializable |

Integration Testing

Use TestTransactionModule for automatic rollback in tests:

import { Test, TestingModule } from '@nestjs/testing';
import { TestTransactionModule, getTestQueryRunnerToken } from '@nest-omni/transaction';
import { DataSource } from 'typeorm';
import { QueryRunner } from 'typeorm';

describe('OrderService', () => {
  let app: INestApplication;
  let testQueryRunner: QueryRunner;

  beforeAll(async () => {
    const module = await Test.createTestingModule({
      imports: [AppModule, TestTransactionModule.forRoot()],
    }).compile();

    app = module.createNestApplication();
    await app.init();

    testQueryRunner = app.get<QueryRunner>(getTestQueryRunnerToken());
  });

  beforeEach(async () => {
    await testQueryRunner.startTransaction();
  });

  afterEach(async () => {
    await testQueryRunner.rollbackTransaction();
  });

  afterAll(async () => {
    await app.close();
  });

  it('should create order', async () => {
    // Test with automatic rollback
  });
});

API

// 装饰器
@Transactional(options?: TransactionOptions)
@TransactionalEventListeners(...listeners: Type<TransactionEventListener>[])

// 函数
runInTransaction(fn, options?)
wrapInTransaction(fn, options?)
runOnTransactionCommit(callback)
runOnTransactionRollback(callback)

// 类/接口
TransactionModule
TestTransactionModule
TransactionalError
NoRegisteredDataSourceError
NotRollBackError
TransactionEventListener

License

MIT