core/src/types/staged-handler.ts

95 lines
2.2 KiB
TypeScript

import { IMessage } from './message';
/**
* Message data object for staged handling
* Response value is always mandatory.
*/
export interface IMessageData {
text?: string;
data?: any;
compose?: any[];
value: any;
}
export type IMessageHandler = (data: IMessageData | string, reject: (error: Error) => void, next: IMessageHandler) => void;
/**
* Staged messaging handler
*/
export class MessageResolver {
private handlers: IMessageHandler[] = [];
public static textFormatter(text: string | undefined, value: any): string {
let stri = text || '';
if (Array.isArray(value) || typeof value === 'object') {
stri = stri.replace(/%([a-z]+)?(\d+)?/ig, (substr: string, word?: string, nr?: number): string => {
if (nr && typeof nr === 'string') {
nr = parseInt(nr as 'string', 10);
}
if (Array.isArray(value) && nr != null) {
return value[nr];
}
if (!word) {
return substr;
}
const val = value[word];
if (Array.isArray(val) && nr) {
return val[nr];
}
return val;
});
} else if (value === 'string') {
if (!text) {
stri = value;
} else {
text += ' ' + value;
}
}
return stri;
}
constructor(public msg: IMessage) {}
/**
* Inject a middleware message handler
* @param fn Message handler function
*/
use(fn: IMessageHandler): void {
this.handlers.push(fn);
}
/**
* Resolve the message. Call this only from the last plugin in the chain.
* @param data Message response data
*/
resolve(data: IMessageData | string, ...rest: any[]): void {
const ist = this.handlers.pop();
if (!this.handlers.length || !ist) {
if (typeof data === 'string') {
this.msg.resolve(data, ...rest);
return;
}
if (data.compose && Array.isArray(data.compose)) {
this.msg.resolve(data.compose);
return;
}
this.msg.resolve(MessageResolver.textFormatter(data.text, data.value));
return;
}
ist.call(this, data, this.msg.reject, this.resolve);
}
/**
* Reject the message. You can call this from anywhere.
* @param error Error
*/
reject(error: Error): void {
this.msg.reject(error);
}
}