Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
136 changes: 3 additions & 133 deletions packages/messaging/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,9 @@ message handling pipelines while ensuring flexibility and reliability.

## Documentation

- Official NestJSTools Messaging documentation: https://docs.nestjstools.com/messaging
- NestJSTools website: https://nestjstools.com

---

## Example project based on RaabitMQ example

Repository: https://github.com/nestjstools/messaging-rabbitmq-example
- Documentation: https://docs.nestjstools.com/messaging
- Website: https://nestjstools.com
- Example repository: https://github.com/nestjstools/messaging-rabbitmq-example

---

Expand Down Expand Up @@ -455,128 +450,3 @@ export class AppModule {
| **`avoidErrorsForNotExistedHandlers`** | Avoid errors if no handler is available for the message. | `false` |
| **`normalizer`** | Set your custom normalizer for messages | |

## Creating Your Own Channel and Bus

This process allows you to define and integrate a custom **Channel** and **MessageBus** for your application, giving you
complete flexibility and control over how messages are processed, dispatched, and consumed. Each step provides the
necessary building blocks to create your own transport layer with full integration into the `MessagingModule`.

### 1. Create a `ChannelConfig`

A `ChannelConfig` class holds the configuration required to establish a stable connection to your service (e.g.,
RabbitMQ, Redis, etc.). Your class should implement the `ChannelConfig` interface and define necessary data like the
channel name and middlewares.

```typescript
export class YourChannelConfig implements ChannelConfig {
public readonly name: string;
public readonly middlewares: object[];

constructor({ name, middlewares }: AmqpChannelConfig) {
this.name = name;
this.middlewares = middlewares ?? []; // Default to empty array if no middlewares provided
}
}
```

### 2. Create a `Channel`

Next, create a class that implements the `Channel` interface. This class will serve as your `DataSource` and utilize the
configuration you defined in the `ChannelConfig` class.

```typescript
export class YourChannel extends Channel {
}
```

### 3. Create a `ChannelFactory`

A `ChannelFactory` is responsible for creating instances of your custom `Channel` class. It implements the
`IChannelFactory` interface and ensures proper injection into your app.

```typescript

@Injectable()
@ChannelFactory(YourChannel)
export class YourChannelFactory implements IChannelFactory<YourChannelConfig> {
create(channelConfig: YourChannelConfig): Channel {
return new YourChannel(channelConfig);
}
}
```

### 4. Create a `MessageBus`

The `MessageBus` handles the dispatching of messages in your system. Create a class implementing the `IMessageBus`
interface to send messages to your custom service (e.g., RabbitMQ, Redis, etc.).

```typescript
export class YourMessageBus implements IMessageBus {
constructor(private readonly yourChannel: YourChannel) {
}

async dispatch(message: RoutingMessage): Promise<MessageResponse | void> {
// Write your logic here to dispatch the message to your channel (e.g., RabbitMQ)
}
}
```

### 5. Create a `MessageBusFactory`

The `MessageBusFactory` creates instances of your `MessageBus` and ensures it's properly integrated with your `Channel`.
It implements the `IMessageBusFactory` interface.

```typescript

@Injectable()
@MessageBusFactory(YourChannel)
export class YourMessageBusFactory implements IMessageBusFactory<YourChannel> {
create(channel: YourChannel): IMessageBus {
return new YourMessageBus(channel); // Return a new instance of your message bus
}
}
```

### 6. Create a Consumer `MessageConsumer`

A consumer receives and processes messages. Create a class that implements the `IMessagingConsumer` interface and handle
the message processing within the `consume` method.

```typescript

@Injectable()
@MessageConsumer(YourChannel)
export class YourMessagingConsumer implements IMessagingConsumer<YourChannel> {
async consume(dispatcher: ConsumerMessageDispatcher, channel: YourChannel): Promise<void> {
// Logic to consume a message...
//TODO dispatcher.dispatch(new ConsumerMessage(...));

return Promise.resolve();
}

async onError(errored: ConsumerDispatchedMessageError, channel: YourChannel): Promise<void> {
// Handle error if message processing fails
return Promise.resolve();
}
}
```

### 7. Add Custom `MessageOptions` to Your Bus (Optional)

You can create custom message options for your message.

```typescript
export class YourMessageOptions implements MessageOptions {
constructor(public readonly middlewares: Middleware[] = []) {
}
}
```

Classes with `Injectable()` decorator must be defined as providers in somewhere in application.

---

## Keywords

nestjs messaging library, nestjs message bus, nestjs service bus, <br>nestjs distributed systems,
nestjs microservices messaging, broker independent messaging for nestjs
2 changes: 1 addition & 1 deletion packages/messaging/package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "@nestjstools/messaging",
"version": "4.1.0",
"version": "4.1.1",
"description": "Simplifies asynchronous and synchronous message handling with support for buses, handlers, channels, and consumers. Build scalable, decoupled applications with ease and reliability.",
"author": "Sebastian Iwanczyszyn",
"license": "MIT",
Expand Down
Loading