Skip to content

Commit

Permalink
Merge pull request #4 from sinuoslabs/chore/breaking-change
Browse files Browse the repository at this point in the history
Chore/breaking change
  • Loading branch information
houssenedao authored Dec 22, 2021
2 parents 62258af + 0bcb4d5 commit 909f9ea
Show file tree
Hide file tree
Showing 15 changed files with 265 additions and 191 deletions.
2 changes: 1 addition & 1 deletion .commitlintrc.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"type-enum": [
2,
"always",
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test"]
["build", "chore", "ci", "docs", "feat", "fix", "perf", "refactor", "style", "test", "revert"]
]
}
}
81 changes: 81 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,87 @@
[![npm version](https://badge.fury.io/js/@sinuos%2Fnestjs-notification.svg)](https://badge.fury.io/js/@sinuos%2Fnestjs-notification)
![license](https://img.shields.io/github/license/sinuoslabs/nestjs-notification)

## Description

NestJs Notifications is a flexible multi-channel notification service inspired by [Laravel Notifications](https://github.com/illuminate/notifications).

Notifications are short, informative messages that inform users of an event that occurred in your application.
For example, if you are writing a billing application, you can send a **"Bill Paid"** notification to your users via email and SMS channels.

This module works with existing channels that you can find here: https://github.com/nestjs-notification-channels. You have the possibility to create your own custom channels.

## Installation

```bash
$ npm i @sinuos/nestjs-notification
```

## Usage

### Declare module

```typescript
import { NestjsNotificationModule } from '@sinuos/nestjs-notify.module';

@Module({
imports: [NestjsNotificationModule.register()],
})
export class AppModule {}
```

### Channel

```typescript
import { Injectable } from '@nestjs/common';
import { INestjsNotifyChannel } from '@sinuos/nestjs-notify.service';

@Injectable()
export class NexmoChannel implements INestjsNotifyChannel {
constructor() {}

send(): Promise<any> {
return Promise.resolve(undefined);
}
}
```

### Notification

```typescript
import { NestJsNotify } from '@sinuos/nestjs-notify.service';

export class InvoicPaidNotification implements NestJsNotify {
public sendToChannels() {
return [NexmoChannel];
}

toNexmo() {
return new NexmoMessage();
}
}
```

### Send notification

```typescript
import { Injectable } from '@nestjs/common';
import { NestjsNotificationService } from '@sinuos/nestjs-notify.service';

@Injectable()
export class AppService {
constructor(private notify: NestjsNotificationService) {}

notify() {
const notification = new InvoicePaidNotification();
this.notify.send(notification);
}
}
```

## Based on

[Nestjs notification](https://github.com/edstevo/nestjs-notifications) by [edstevo](https://github.com/edstevo)

## License

NestJS's notification is [MIT licensed](LICENSE).
2 changes: 1 addition & 1 deletion lib/constants/index.ts
Original file line number Diff line number Diff line change
@@ -1 +1 @@
export * from './nestjs-notify-provider.constant';
export * from './nestjs-notification-provider.constant';
1 change: 1 addition & 0 deletions lib/constants/nestjs-notification-provider.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const NESTJS_NOTIFICATION_OPTIONS = 'NESTJS_NOTIFICATION_OPTIONS';
1 change: 0 additions & 1 deletion lib/constants/nestjs-notify-provider.constant.ts

This file was deleted.

4 changes: 2 additions & 2 deletions lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './interfaces';
export * from './nestjs-notify.module';
export * from './nestjs-notify.service';
export * from './nestjs-notification.module';
export * from './nestjs-notification.service';
6 changes: 3 additions & 3 deletions lib/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './nestjs-notify.interface';
export * from './nestjs-notify-module.interface';
export * from './nestjs-notify-channel.interface';
export * from './nestjs-notification.interface';
export * from './nestjs-notification-module.interface';
export * from './nestjs-notification-channel.interface';
14 changes: 14 additions & 0 deletions lib/interfaces/nestjs-notification-channel.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
import { NestJsNotification } from './nestjs-notification.interface';

/**
* @interface INestjsNotificationChannel
* @property send()
*/
export interface INestjsNotificationChannel {
/**
* Send the given notification
* @param {NestJsNotification} notification
* @return Promise<any>
*/
send(notification: NestJsNotification): Promise<any>;
}
35 changes: 35 additions & 0 deletions lib/interfaces/nestjs-notification-module.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import { ModuleMetadata, Provider, Type } from '@nestjs/common';

/**
* @interface NestjsNotificationModuleOptionsFactory
* @property createNestjsNotificationOptions()
*/
export interface NestjsNotificationModuleOptionsFactory {
createNestjsNotificationOptions():
| Promise<NestjsNotificationModuleOptions>
| NestjsNotificationModuleOptions;
}

/**
* @interface NestjsNotificationModuleAsyncOptions
* @extends {Pick<ModuleMetadata, 'imports'>}
* @property useExisting
* @property useClass
* @property useFactory
* @property inject
* @property extraProviders
*/
export interface NestjsNotificationModuleAsyncOptions extends Pick<ModuleMetadata, 'imports'> {
useExisting?: Type<NestjsNotificationModuleOptionsFactory>;
useClass?: Type<NestjsNotificationModuleOptionsFactory>;
useFactory?: (
...args: any[]
) => Promise<NestjsNotificationModuleOptions> | NestjsNotificationModuleOptions;
inject?: any[];
extraProviders?: Provider[];
}

/**
* @interface NestjsNotificationModuleOptions
*/
export type NestjsNotificationModuleOptions = null;
Original file line number Diff line number Diff line change
@@ -1,17 +1,17 @@
import { Type } from '@nestjs/common';
import { INestjsNotifyChannel } from './nestjs-notify-channel.interface';
import { INestjsNotificationChannel } from './nestjs-notification-channel.interface';

/**
* @interface NestJsNotify
* @interface NestJsNotification
* @property sendToChannels()
* @property toPayload?()
*/
export interface NestJsNotify {
export interface NestJsNotification {
/**
* Get the channels the notification should broadcast on.
* @returns {Type<INestjsNotifyChannel>[]} array
* @returns {Type<INestjsNotificationChannel>[]} array
*/
sendToChannels(): Type<INestjsNotifyChannel>[];
sendToChannels(): Type<INestjsNotificationChannel>[];

/**
* Get the json representation of the notification.
Expand Down
14 changes: 0 additions & 14 deletions lib/interfaces/nestjs-notify-channel.interface.ts

This file was deleted.

34 changes: 0 additions & 34 deletions lib/interfaces/nestjs-notify-module.interface.ts

This file was deleted.

112 changes: 112 additions & 0 deletions lib/nestjs-notification.module.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,112 @@
import { DynamicModule, Module, Provider, ValueProvider } from '@nestjs/common';
import { NestjsNotificationService } from './nestjs-notification.service';
import {
NestjsNotificationModuleAsyncOptions,
NestjsNotificationModuleOptions,
NestjsNotificationModuleOptionsFactory,
} from './interfaces';
import { NESTJS_NOTIFICATION_OPTIONS } from './constants';

@Module({})
export class NestjsNotificationModule {
/**
* Register module
* @static
* @param {NestjsNotificationModuleOptions} options
* @return DynamicModule
*/
static register(options: NestjsNotificationModuleOptions): DynamicModule {
const notifyProvider: ValueProvider = {
provide: NESTJS_NOTIFICATION_OPTIONS,
useValue: options,
};

return {
module: NestjsNotificationModule,
providers: [NestjsNotificationService, notifyProvider],
exports: [NestjsNotificationService, notifyProvider],
};
}

/**
* Register async
* @static
* @param {NestjsNotificationModuleAsyncOptions} options
* @return DynamicModule
*/
static registerAsync(options: NestjsNotificationModuleAsyncOptions): DynamicModule {
const notifyProvider: ValueProvider = {
provide: NESTJS_NOTIFICATION_OPTIONS,
useValue: options,
};

return {
module: NestjsNotificationModule,
imports: options.imports || [],
providers: [NestjsNotificationService, notifyProvider, ...this.createAsyncProviders(options)],
exports: [NestjsNotificationService, notifyProvider],
};
}

/**
* Create async providers
* @private
* @param {NestjsNotificationModuleAsyncOptions} options
* @return Provider[]
*/
private static createAsyncProviders(options: NestjsNotificationModuleAsyncOptions): Provider[] {
if (options.useExisting || options.useFactory) {
return [this.createAsyncConfigProvider(options)];
} else if (!options.useClass) {
return [
{
provide: NESTJS_NOTIFICATION_OPTIONS,
useValue: {},
inject: options.inject || [],
},
];
}

return [
this.createAsyncConfigProvider(options),
{
provide: options.useClass,
useClass: options.useClass,
},
];
}

/**
* Create async config provider
* @private
* @param {NestjsNotificationModuleAsyncOptions} options
* @return Provider<any>
*/
private static createAsyncConfigProvider(
options: NestjsNotificationModuleAsyncOptions,
): Provider<any> {
if (options.useFactory) {
return {
provide: NESTJS_NOTIFICATION_OPTIONS,
useFactory: options.useFactory,
inject: options.inject || [],
};
}

const inject = options.useClass || options.useExisting;

if (!inject) {
throw new Error('Invalid configuration. Must provide useFactory, useClass or useExisting');
}

return {
provide: NESTJS_NOTIFICATION_OPTIONS,
async useFactory(
optionsFactory: NestjsNotificationModuleOptionsFactory,
): Promise<NestjsNotificationModuleOptions> {
return optionsFactory.createNestjsNotificationOptions();
},
inject: [inject],
};
}
}
Loading

0 comments on commit 909f9ea

Please sign in to comment.