Skip to content

Commit

Permalink
feat(): create exception and change dependances requirement
Browse files Browse the repository at this point in the history
  • Loading branch information
houssenedao committed Dec 23, 2021
1 parent e07935f commit c723335
Show file tree
Hide file tree
Showing 11 changed files with 245 additions and 9 deletions.
3 changes: 1 addition & 2 deletions lib/bootstrap/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,2 @@
export * from './webhook.channel';
export * from './webhook.interface';
export * from './webhook.message';
export * from './webhook-channel.message';
91 changes: 91 additions & 0 deletions lib/bootstrap/webhook-channel.message.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
import { WebhookChannelException } from '../exceptions';

/**
* Webhook message
* @class WebhookChannelMessage
*/
export class WebhookChannelMessage {
/**
* @public
* @property {string} channelId
*/
private url: string;

/**
* @public
* @property {any} header
*/
private header: any;

/**
* @public
* @property {any} body
*/
private body: any;

/**
* @constructor
* @param {string} body
*/
constructor(body: any) {
this.body = body;
}

/**
* Get url.
*/
get getUrl() {
return this.url;
}

/**
* Set the message url.
* @param {string} url
* @return this
*/
setUrl(url: string): WebhookChannelMessage {
if (!url) {
throw new WebhookChannelException('URL is not empty');
}

this.url = url;

return this;
}

/**
* Get header
*/
get getHeader() {
return this.header;
}

/**
* Set the message header.
* @param {any} header
* @return this
*/
setHeader(header: any): WebhookChannelMessage {
this.header = header;

return this;
}

/**
* Get body
*/
get getBody() {
return this.body;
}

/**
* Set the message body.
* @param {any} body
* @return this
*/
setBody(body: any): WebhookChannelMessage {
this.body = body;

return this;
}
}
65 changes: 59 additions & 6 deletions lib/bootstrap/webhook.channel.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,34 @@
import { Injectable, InternalServerErrorException } from '@nestjs/common';
import { Inject, Injectable, Optional } from '@nestjs/common';
import { HttpService } from '@nestjs/axios';
import { INestjsNotificationChannel } from '@sinuos/nestjs-notification';
import { AxiosResponse } from 'axios';
import { IWebhookChannel } from './webhook.interface';
import { IWebhookChannel, WebhookChannelModuleOptions } from '../interfaces';
import { WebhookChannelException } from '../exceptions';
import { WEBHOOK_CHANNEL_OPTIONS } from '../constants';

@Injectable()
export class WebhookChannel implements INestjsNotificationChannel {
/**
* @readonly
* @private
*/
private readonly url: string;

/**
* @constructor
* @param options
* @param {HttpService} http
*/
constructor(private readonly http: HttpService) {}
constructor(
private readonly http: HttpService,
@Optional()
@Inject(WEBHOOK_CHANNEL_OPTIONS)
options: WebhookChannelModuleOptions,
) {
if (options?.url) {
this.url = options.url;
}
}

/**
* Send notify
Expand All @@ -21,28 +39,63 @@ export class WebhookChannel implements INestjsNotificationChannel {
public async send(
notification: IWebhookChannel,
): Promise<AxiosResponse<any>> {
// validator
this.validator(notification);

// get message content
const message = WebhookChannel.getData(notification);

// url
const url = message.getUrl;

// make http request.
const response = await this.http.request({
method: 'POST',
url: message.getUrl,
url,
data: message.getBody,
headers: message.getHeader,
});

// return response
return response.toPromise();
}

/**
* Validator.
* @method
* @param {IWebhookChannel} notification
* @private
*/
private validator(notification: IWebhookChannel) {
const message = WebhookChannel.getData(notification);

/** Account sid is empty */
if (!this.url && !message.getUrl) {
throw new WebhookChannelException('URL is required');
}
}

/**
* Get data.
* @method
* @param {IWebhookChannel} notification
* @private
*/
private static getData(notification: IWebhookChannel) {
return WebhookChannel.getChannelData(notification);
}

/**
* Get the data for the notification.
* @param notification
*/
private static getData(notification: IWebhookChannel) {
private static getChannelData(notification: IWebhookChannel) {
if (typeof notification.toWebhook === 'function') {
return notification.toWebhook();
}

throw new InternalServerErrorException(
// throw exception
throw new WebhookChannelException(
'Notification is missing toWebhook method.',
);
}
Expand Down
1 change: 1 addition & 0 deletions lib/constants/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './webhook-channel.constant';
2 changes: 2 additions & 0 deletions lib/constants/webhook-channel.constant.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export const WEBHOOK_CHANNEL_HTTP = 'WEBHOOK_CHANNEL_HTTP';
export const WEBHOOK_CHANNEL_OPTIONS = 'WEBHOOK_CHANNEL_OPTIONS';
1 change: 1 addition & 0 deletions lib/exceptions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export * from './webhook-channel.exception';
15 changes: 15 additions & 0 deletions lib/exceptions/webhook-channel.exception.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
/**
* @class WebhookChannelException
* @extends Error
*/
export class WebhookChannelException extends Error {
/**
* @constructor
* @param message
*/
constructor(message: string) {
super(message);

this.name = 'WebhookChannelException';
}
}
2 changes: 1 addition & 1 deletion lib/index.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
export * from './bootstrap';
export * from './webhook-channel.service';
export * from './interfaces';
export * from './webhook-channel.module';
2 changes: 2 additions & 0 deletions lib/interfaces/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
export * from './webhook-channel.interface';
export * from './webhook-channel-module.interface';
57 changes: 57 additions & 0 deletions lib/interfaces/webhook-channel-module.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import { ModuleMetadata, Provider, Type } from '@nestjs/common';

/**
* @interface WebhookChannelModuleOptionsFactory
* @property createWebhookChannelOptions()
*/
export interface WebhookChannelModuleOptionsFactory {
createWebhookChannelOptions():
| Promise<WebhookChannelModuleOptions>
| WebhookChannelModuleOptions;
}

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

/**
* HTTP client.
* @interface WebhookHttpClient
*/
export interface WebhookHttpClient {
maxRedirects?: number;
timeout?: number;
}

/**
* @interface WebhookChannelConfig
*/
export interface WebhookChannelConfig {
url?: string;
}

/**
* @interface WebhookChannelModuleOptions
* @property {string} twilioAccountSid
* @property {string} twilioAuthToken
* @property {string} endpoint
*/
export interface WebhookChannelModuleOptions
extends WebhookHttpClient,
WebhookChannelConfig {}
15 changes: 15 additions & 0 deletions lib/interfaces/webhook-channel.interface.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import { NestJsNotification } from '@sinuos/nestjs-notification';

/**
* Webhook channel model
* @interface IWebhookChannel
* @extends NestJsNotification
*/
export interface IWebhookChannel extends NestJsNotification {
/**
* Get the Http representation of the notification.
* @property
* @returns {any} http payload data
*/
toWebhook?(): any;
}

0 comments on commit c723335

Please sign in to comment.