nope/lib/module/BaseModule.ts

199 lines
6.1 KiB
TypeScript
Raw Normal View History

2020-10-12 16:13:10 +00:00
/**
* @author Martin Karkowski
* @email m.karkowski@zema.de
* @create date 2020-10-12 17:54:08
* @modify date 2020-10-12 18:06:41
* @desc [description]
*/
import { IAuthor, IBaseModule, IDescriptor, IFunctionOptions, IPropertyOptions, IVersion } from "./Interface.Module";
import { INopeDispatcher } from "./Interface.nopeDispatcher";
import { INopeObservable } from "./Interface.nopeObservebale";
/**
* Base Implementation of a Module.
*
* @export
* @class BaseModule
* @implements {IBaseModule}
*/
export class BaseModule implements IBaseModule {
/**
* Module Name must be written in lowercase.
*/
private _name = '';
public get name(): string {
return this._name;
}
public set name(value: string) {
const _replacements = [
[' ', ''],
// ['.', ''],
// ['_', ''],
];
let adapted = value;
for (const [search, replace] of _replacements) {
adapted = replaceAll(adapted, search, replace);
}
this._name = adapted.toLowerCase();
}
/**
* A Description of the Module. This is used to Describe roughly
* what the module is capable of
* doing.
*
* @type {string}
* @memberof BaseModule
*/
public description: string;
/**
* A Description of the Author. Use to Mail etc.
*
* @type {IAuthor}
* @memberof BaseModule
*/
public author: IAuthor;
/**
* Description of the provided Version of the Module.
*
* @type {IVersion}
* @memberof BaseModule
*/
public version: IVersion;
protected _registeredFunctions: Map<string, {
func: (...args: any[]) => Promise<any>,
options: IFunctionOptions
}>
protected _registeredProperties: Map<string, {
observable: INopeObservable<any>
options: IPropertyOptions
}>
/**
* Creates an instance of BaseModule.
* @memberof BaseModule
*/
constructor(protected _dispatcher: INopeDispatcher) {
this._name = null;
this.description = null;
this.author = null;
this.version = null;
}
public async registerProperty<T, K = any, S = T, G = T>(name: string, observable: INopeObservable<T, S, G>, options: IPropertyOptions<K>): Promise<void> {
// Unregister the Function
await this.unregisterProperty(name);
// Adapt the Topics
if (typeof options.topic === 'string'){
options.topic = this.name + '.prop.' + name;
} else if (typeof options.topic === 'object'){
if (options.topic.subscribe && !options.topic.subscribe.startsWith(this.name + '.prop.') ){
options.topic.subscribe = this.name + '.prop.' + options.topic.subscribe;
}
if (options.topic.publish && !options.topic.publish.startsWith(this.name + '.prop.')){
options.topic.publish = this.name + '.prop.' + options.topic.publish;
}
}
const _observable = await this._dispatcher.registerObservable(observable, options);
// Register the new Property.
this._registeredProperties.set(name, {
observable: _observable,
options
});
}
public async registerFunction(name: string, func: (...args: any[]) => Promise<any>, options: IFunctionOptions): Promise<void> {
// Unregister the Function
await this.unregisterFunction(name);
// Adapt the Method ID
options.id = this.name + '.' + name;
const _func = await this._dispatcher.registerFunction(func, options);
// Register the new Function.
this._registeredFunctions.set(name, {
func: _func,
options
});
}
public async unregisterFunction(name: string): Promise<void> {
// Test if the Method is already registerd,
// If so => unregister it first.
if (this._registeredFunctions.has(name)) {
this._dispatcher.unregistFunction(this._registeredFunctions.get(name).func, {
preventSendingToRegistery: true
});
}
}
public async unregisterProperty<T, K = any, S = T, G = T>(name: string): Promise<void> {
// Test if the Property is already registerd,
// If so => unregister it first.
if (this._registeredProperties.has(name)) {
this._dispatcher.unregistObservable(this._registeredProperties.get(name).observable, {
preventSendingToRegistery: true
});
}
}
public async listFunctions(): Promise<{ name: string; func: (...args: any[]) => Promise<any>; options: IFunctionOptions; }[]> {
throw new Error("Method not implemented.");
}
public async listProperties(): Promise<{ name: string; schema: IDescriptor; options: IPropertyOptions; }[]> {
throw new Error("Method not implemented.");
}
public async init(): Promise<void> {
// In this base Implementation, check if every requried property is set
// correctly. If not => raise an error.
if (this.name === null){
throw Error('Please Provide a Name for the Module before initializing')
}
if (this.description === null){
throw Error('Please Provide a Description for the Module before initializing')
}
if (this.author === null){
throw Error('Please Provide an Author for the Module before initializing')
}
if (this.version === null){
throw Error('Please Provide a Version for the Module before initializing')
}
}
public async dispose(){
// Unregister all Methods and Functions
for (const name of this._registeredFunctions.keys()){
await this.unregisterFunction(name);
}
// Remove all known Functions
this._registeredFunctions.clear();
// Unregister all Properties.
for (const name of this._registeredProperties.keys()){
await this.unregisterProperty(name);
}
// Remove all known Properties.
this._registeredProperties.clear();
}
}