@naviedu/nestjs-outbox-inbox
v1.0.3
Published
NestJS module for implementing outbox/inbox pattern with TypeORM and MongoDB support
Downloads
1
Maintainers
Readme
NestJS Outbox/Inbox Module
A NestJS module for implementing the outbox/inbox pattern with support for both TypeORM (MySQL) and MongoDB.
Features
- ✅ Implements the Outbox pattern (guaranteed message publishing)
- ✅ Implements the Inbox pattern (idempotent message consumption)
- ✅ Support for both TypeORM (MySQL) and MongoDB
- ✅ Type-safe event publishing
- ✅ Easy integration with NestJS applications
- ✅ Zero config — works out of the box
Installation
npm install @naviedu/nestjs-outbox-inboxUsage
1. Import and Configure Module
// app.module.ts
import { Module } from '@nestjs/common'
import { OutboxInboxModule } from '@naviedu/nestjs-outbox-inbox'
@Module({
imports: [
// For TypeORM (MySQL) with RabbitMQ (default)
OutboxInboxModule.register({
databaseType: 'typeorm',
typeOrmConfig: {
type: 'mysql',
host: 'localhost',
port: 3306,
username: 'root',
password: 'root',
database: 'outbox_inbox',
synchronize: true,
},
// RabbitMQ is the default message broker
rabbitmqConfig: {
uri: 'amqp://localhost:5672',
// Define exchanges
exchanges: [
{
name: 'outbox_exchange',
type: 'topic',
options: {
durable: true,
},
},
],
// Optional: SSL/TLS configuration
socketOptions: {
cert: 'client-certificate',
key: 'client-key',
ca: ['ca-certificate'],
passphrase: 'passphrase',
},
// Optional: Set prefetch count
prefetchCount: 10,
// Optional: Default queue options
defaultQueueOptions: {
durable: true,
exclusive: false,
},
// Optional: Connection initialization options
connectionInitOptions: {
wait: true,
timeout: 5000,
reject: true,
},
// Optional: Whether to use @golevelup/nestjs-rabbitmq module
// Set to false if you want to use direct amqplib connection only
useNestjsRabbitMQ: true,
},
}),
// OR for MongoDB
OutboxInboxModule.register({
databaseType: 'mongodb',
mongoConfig: {
uri: 'mongodb://localhost:27017/outbox_inbox',
},
}),
// Using Kafka as message broker
OutboxInboxModule.register({
databaseType: 'typeorm',
typeOrmConfig: {
// TypeORM config
},
messageBrokerType: 'kafka',
kafkaConfig: {
clientId: 'outbox-service',
brokers: ['localhost:9092'],
// Optional SSL config
ssl: false,
// Optional SASL authentication
sasl: {
mechanism: 'plain',
username: 'user',
password: 'password',
},
},
}),
// Using Redis as message broker
OutboxInboxModule.register({
databaseType: 'mongodb',
mongoConfig: {
// MongoDB config
},
messageBrokerType: 'redis',
redisConfig: {
host: 'localhost',
port: 6379,
password: 'password',
// Or use URL
// url: 'redis://user:password@localhost:6379/0',
// Optional TLS config
tls: {
ca: 'ca-certificate',
cert: 'client-certificate',
key: 'client-key',
rejectUnauthorized: true,
},
},
}),
// Using multiple message brokers
OutboxInboxModule.register({
databaseType: 'typeorm',
typeOrmConfig: {
// TypeORM config
},
messageBrokerType: 'multiple',
enabledMessageBrokers: ['rabbitmq', 'kafka', 'redis'],
rabbitmqConfig: {
uri: 'amqp://localhost:5672',
exchanges: [
{
name: 'outbox_exchange',
type: 'topic',
},
],
// Other RabbitMQ options as needed
},
kafkaConfig: {
brokers: ['localhost:9092'],
},
redisConfig: {
host: 'localhost',
port: 6379,
},
}),
],
})
export class AppModule {}2. Using the Outbox Service
import { Injectable } from '@nestjs/common'
import { OutboxService } from '@naviedu/nestjs-outbox-inbox'
@Injectable()
export class YourService {
constructor(private readonly outboxService: OutboxService) {}
async createUser(userData: any) {
// Your business logic here
// Publish event to outbox
await this.outboxService.publish({
eventType: 'USER_CREATED',
payload: userData,
})
}
// Process unprocessed events
async processEvents() {
await this.outboxService.processUnprocessedEvents()
}
}3. Event Types
import { IOutboxEvent } from '@naviedu/nestjs-outbox-inbox'
// Define your event types
interface UserCreatedEvent extends IOutboxEvent {
eventType: 'USER_CREATED'
payload: {
userId: number
email: string
// ... other user data
}
}
// Use in your service
await this.outboxService.publish<UserCreatedEvent>({
eventType: 'USER_CREATED',
payload: {
userId: 1,
email: '[email protected]',
},
})Database Schema
TypeORM (MySQL)
CREATE TABLE outbox (
id INT AUTO_INCREMENT PRIMARY KEY,
event_type VARCHAR(255) NOT NULL,
payload JSON NOT NULL,
processed BOOLEAN DEFAULT FALSE,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
CREATE TABLE inbox (
event_id VARCHAR(255) PRIMARY KEY,
event_type VARCHAR(255) NOT NULL,
payload JSON NOT NULL,
received_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);MongoDB
// Outbox Collection
{
_id: ObjectId,
eventType: String,
payload: Object,
processed: Boolean,
createdAt: Date
}
// Inbox Collection
{
_id: String, // eventId
eventType: String,
payload: Object,
receivedAt: Date
}Dependencies
This module requires the following peer dependencies:
{
"@nestjs/common": "^10.0.0",
"@nestjs/core": "^10.0.0",
"@nestjs/typeorm": "^10.0.0",
"@nestjs/mongoose": "^10.0.0",
"@nestjs/microservices": "^10.0.0",
"@nestjs/schedule": "6.0.0",
"@golevelup/nestjs-rabbitmq": "^5.0.0",
"amqplib": "^0.10.0",
"amqp-connection-manager": "^4.1.0",
"mongoose": "^7.0.0",
"reflect-metadata": "^0.1.13",
"rxjs": "^7.0.0",
"typeorm": "^0.3.0",
"kafkajs": "^2.2.4",
"ioredis": "^5.3.2"
}Optional Dependencies
Depending on which message broker you use, you may need the following dependencies:
- For RabbitMQ:
@golevelup/nestjs-rabbitmq,amqplib,amqp-connection-manager - For Kafka:
kafkajs - For Redis:
ioredis
License
MIT
