nope/lib/dispatcher/nopeDispatcherDecorators.ts
2020-09-07 20:12:19 +02:00

137 lines
4.3 KiB
TypeScript

import { getSingleton } from "../helpers/singletonMethod";
// Symbols for the Property Registery:
const _registeredDispatcherMethods_ = Symbol('_registeredDispatcherMethods_');
const _registeredDispatcherParams_ = Symbol('_registeredDispatcherParams_');
// Interfaces for the Class
export interface IExportToDispatcherParameters {
uri?: string,
}
export interface IExportMethodToDispatcherParameters {
uri?: string,
}
export interface IExportFunctionToDispatcherParameters {
uri: string,
}
export interface IExportPropertyToDispatcherParameters {
uri?: string,
readonly?: boolean
}
const container = getSingleton('nopeBackendDispatcher.container', () => {
return {
methods: new Map<string, {
uri: string,
callback: (...args) => Promise<any>,
options: IExportMethodToDispatcherParameters
}>(),
parameters: new Map<string, {
uri: string,
callback: (...args) => Promise<any>,
options: IExportPropertyToDispatcherParameters
}>(),
functions: new Map<string, {
uri: string,
callback: (...args) => Promise<any>,
options: IExportFunctionToDispatcherParameters
}>()
}
});
/**
* Decorator used to export a Class API over openAPI
* @param options
*/
export function exportsElementsToDispatcher(options: IExportToDispatcherParameters) {
return function <T extends { new(...args: any[]): {} }>(Base: T) {
return class extends Base {
constructor(...args: any[]) {
super(...args);
const _this = this as any;
// extract the Registered Methods of the Class.
const registeredMethods = Base.prototype[_registeredDispatcherMethods_] as Map<string, IExportMethodToDispatcherParameters>;
const registeredParams = Base.prototype[_registeredDispatcherParams_] as Map<string, IExportPropertyToDispatcherParameters>;
// Online if they are present, iterate over them
if (registeredMethods) {
registeredMethods.forEach((options, methodName) => {
// Register the Methods
const uri = (options.uri || Base.prototype.name) + (options.uri || methodName);
container.instance.methods.set(uri, {
callback: async (...args) => _this[methodName](...args),
uri,
options
});
});
}
// Online if they are present, iterate over them
if (registeredParams) {
registeredParams.forEach((options, parameterName) => {
// Register the Methods
const uri = (options.uri || Base.prototype.name) + (options.uri || parameterName);
container.instance.parameters.set(uri, {
callback: async (...args) => _this[parameterName](...args),
uri,
options
});
});
}
}
};
}
}
/**
* Decorator, used to export the Method.
* @param options
*/
export function exportMethodToDispatcher(options: IExportMethodToDispatcherParameters) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
target[_registeredDispatcherMethods_] = target[_registeredDispatcherMethods_] || new Map<string, IExportMethodToDispatcherParameters>();
// Here we just add some information that class decorator will use
target[_registeredDispatcherMethods_].set(propertyKey, options);
};
}
/**
* Decorator, will create a POST and GET api for the Parameter.
* @param options
*/
export function exportPropertyToDispatcher(options: IExportPropertyToDispatcherParameters) {
return function (target: any, propertyKey: string, descriptor: PropertyDescriptor) {
target[_registeredDispatcherParams_] = target[_registeredDispatcherParams_] || new Map<string, IExportPropertyToDispatcherParameters>();
// Here we just add some information that class decorator will use
target[_registeredDispatcherParams_].set(propertyKey, options);
};
}
/**
* Defintion of a Functon.
*/
export type callable<T> = {
(...args): T
}
/**
* Decorator, that will export the Function to a Dispatcher
* @param func The Function
* @param options The Options.
*/
export function exportFunctionToDispatcher<T>(func: T, options: IExportFunctionToDispatcherParameters) {
container.instance.functions.set(options.uri, {
callback: async (...args) => await ((func as any)(...args)),
options,
uri: options.uri || (func as any).name
});
return func;
}