import { getSingleton } from "../helpers/singletonMethod"; import { nopeObservable } from "../observables/nopeObservable"; // 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 { // Different uri (instead of using the name) uri?: string, // Contains Either the Property Name or the idx name. deletableCallbacks?: Array | Array } export interface IExportFunctionToDispatcherParameters { uri?: string, // Contains Either the Property Name or the idx name. deletableCallbacks?: Array | Array } export interface IExportPropertyToDispatcherParameters { uri?: string, readonly?: boolean } const container = getSingleton('nopeBackendDispatcher.container', () => { return { methods: new Map Promise, options: IExportMethodToDispatcherParameters }>(), parameters: new Map, options: IExportPropertyToDispatcherParameters }>(), functions: new Map Promise, options: IExportFunctionToDispatcherParameters }>() } }); /** * Decorator used to export a Class API over openAPI * @param options */ export function exportsElementsToDispatcher(options: IExportToDispatcherParameters) { return function (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; const registeredParams = Base.prototype[_registeredDispatcherParams_] as Map; // 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, { item: _this[parameterName], 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(); // 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(); // Here we just add some information that class decorator will use target[_registeredDispatcherParams_].set(propertyKey, options); }; } /** * Defintion of a Functon. */ export type callable = { (...args): T } /** * Decorator, that will export the Function to a Dispatcher * @param func The Function * @param options The Options. */ export function exportFunctionToDispatcher(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; }