- Modified:
    - Renamed the decorator `exportFunctionAsNopeService` -> `exportAsNopeService` and the Interface `IexportFunctionAsNopeServiceParameters` -> `IexportAsNopeServiceParameters`
    - `NopeInstanceManager` and `GenericWrapper`: Now receives a factory to generate the a `NopeEventEmitter`:
      - This affects a lot packages.
    - `NopeModule`:
      - renamed `listFunctions` to `listMethods`
      - renamed `functions` is now called `methods`
      - The Description format is being updated (`functions` is now called `methods`)
  - Fixes:
    - `NopeModule`:
      - Now disposes Emitters as Properties as well
      - `getIdentifierOf` checks event emitters as well now.
    - `GenericWrapper`:
      - Now automatically registers emitters as well.
  - Added:
    -  `NopeModule`: Added the method `listEvents` (to show the available Emitters registered as Properties.)
This commit is contained in:
Martin Karkowski 2022-10-29 07:52:14 +02:00
parent 2f6f71eb8f
commit 881456b2ca
25 changed files with 277 additions and 92 deletions

View File

@ -293,3 +293,24 @@ Inital commit, which is working with the browser
- adapted `NopePubSub`:
- renamed parameter `mqttBasedPatternSubscriptions` to `mqttPatternBasedSubscriptions`
- `helpers/path` -> in `_getLeastCommonPathSegment` we only iterate over the avaible keys.
# 1.4.4
- Modified:
- Renamed the decorator `exportFunctionAsNopeService` -> `exportAsNopeService` and the Interface `IexportFunctionAsNopeServiceParameters` -> `IexportAsNopeServiceParameters`
- `NopeInstanceManager` and `GenericWrapper`: Now receives a factory to generate the a `NopeEventEmitter`:
- This affects a lot packages.
- `NopeModule`:
- renamed `listFunctions` to `listMethods`
- renamed `functions` is now called `methods`
- The Description format is being updated (`functions` is now called `methods`)
- Fixes:
- `NopeModule`:
- Now disposes Emitters as Properties as well
- `getIdentifierOf` checks event emitters as well now.
- `GenericWrapper`:
- Now automatically registers emitters as well.
- Added:
- `NopeModule`: Added the method `listEvents` (to show the available Emitters registered as Properties.)

View File

@ -7,4 +7,4 @@ export const NAME_GENERICMODULE = "NopeGenericModule";
export const NAME_METHOD_DEC = "nopeMethod";
export const NAME_EMITTER_DEC = "nopeEmitter";
export const NAME_PROP_DEC = "nopeProperty";
export const NAME_FUNC_DEC = "exportFunctionAsNopeService";
export const NAME_FUNC_DEC = "exportAsNopeService";

View File

@ -476,7 +476,7 @@ export async function interact(
type: "search-list",
message: "Select the instance",
name: "service",
choices: Object.keys(instanceDescription.functions).sort(),
choices: Object.keys(instanceDescription.methods).sort(),
},
])
).service;
@ -492,8 +492,7 @@ export async function interact(
logger.info("Accessor Generated");
// Now we know, which service we are trying to call.
if (
instanceDescription.functions[service].schema?.inputs?.length ==
0
instanceDescription.methods[service].schema?.inputs?.length == 0
) {
try {
// Now we execute the service

View File

@ -7,7 +7,7 @@
import { getSingleton } from "../helpers/singletonMethod";
import { IFunctionOptions, INopeModule } from "../types";
export type IexportFunctionAsNopeServiceParameters = IFunctionOptions;
export type IexportAsNopeServiceParameters = IFunctionOptions;
/**
* Return the central loger. This logger is a singleton (see {@link getSingleton})
@ -22,7 +22,7 @@ export function getCentralDecoratedContainer(): {
{
uri: string;
callback: (...args) => Promise<any>;
options: IexportFunctionAsNopeServiceParameters;
options: IexportAsNopeServiceParameters;
}
>;
classes: Map<string, INopeModule>;

View File

@ -6,7 +6,7 @@
import {
getCentralDecoratedContainer,
IexportFunctionAsNopeServiceParameters,
IexportAsNopeServiceParameters,
} from "./container";
const CONTAINER = getCentralDecoratedContainer();
@ -23,9 +23,9 @@ export type callable<T> = {
* @param func The Function
* @param options The Options.
*/
export function exportFunctionAsNopeService<T>(
export function exportAsNopeService<T>(
func: T,
options: IexportFunctionAsNopeServiceParameters
options: IexportAsNopeServiceParameters
) {
// Only add the element if it doesnt exists.
if (!CONTAINER.services.has(options.id)) {

View File

@ -5,7 +5,7 @@
export {
getCentralDecoratedContainer,
IexportFunctionAsNopeServiceParameters,
IexportAsNopeServiceParameters,
} from "./container";
export { exportFunctionAsNopeService } from "./functionDecorators";
export { exportAsNopeService } from "./functionDecorators";
export { nopeEmitter, nopeMethod, nopeProperty } from "./moduleDecorators";

View File

@ -196,7 +196,7 @@ describe("NopeConnectivityManager", function () {
// Dispose our Delay.
first.dispose(true);
expect(end - adapted).to.be.equal(0, "There should not be an delta.");
expect(end - adapted < 1).to.be.true("There should not be an delta.");
});
it("master", async () => {

View File

@ -10,6 +10,7 @@ import { expect } from "chai";
import { beforeEach, describe, it } from "mocha";
import "reflect-metadata";
import { getLayer } from "../../communication/getLayer.nodejs";
import { NopeEventEmitter } from "../../eventEmitter";
import { NopeObservable } from "../../observables/nopeObservable";
import { NopeCore } from "./NopeCore";
@ -20,6 +21,7 @@ describe("NopeCore", function () {
communicator: getLayer("event", "", false),
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"first"
);
@ -38,6 +40,7 @@ describe("NopeCore", function () {
communicator: getLayer("event", "", false),
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"first"
);
@ -58,6 +61,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"second"
);
@ -74,6 +78,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"first"
);
@ -83,6 +88,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"second"
);
@ -114,6 +120,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"second"
);
@ -130,6 +137,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"first"
);
@ -139,6 +147,7 @@ describe("NopeCore", function () {
communicator,
logger: false,
},
() => new NopeEventEmitter(),
() => new NopeObservable(),
"second"
);

View File

@ -16,13 +16,17 @@ import {
INopeConnectivityManager,
INopeCore,
INopeDispatcherOptions,
INopeEventEmitter,
INopeInstanceManager,
INopeObservable,
INopeRpcManager,
IPubSubSystem,
} from "../../types/nope";
import { NopeConnectivityManager } from "../ConnectivityManager";
import { NopeInstanceManager } from "../InstanceManager";
import {
generateAssignmentChecker,
NopeInstanceManager,
} from "../InstanceManager";
import { generateSelector, NopeRpcManager } from "../RpcManager";
export class NopeCore implements INopeCore {
@ -39,6 +43,7 @@ export class NopeCore implements INopeCore {
constructor(
public options: INopeDispatcherOptions,
protected generateEmitter: <T>() => INopeEventEmitter<T>,
protected generateObservable: <T>() => INopeObservable<T>,
public readonly id: string = null
) {
@ -85,6 +90,7 @@ export class NopeCore implements INopeCore {
// Create our Instance Manager
this.instanceManager = new NopeInstanceManager(
options,
generateEmitter,
generateObservable,
defaultSelector,
this.id,

View File

@ -24,6 +24,7 @@ import {
INopeConnectivityManager,
INopeCore,
INopeDispatcherOptions,
INopeEventEmitter,
INopeModule,
INopeModuleDescription,
INopeObservable,
@ -161,10 +162,11 @@ export class NopeInstanceManager implements INopeInstanceManager {
*/
constructor(
public options: INopeDispatcherOptions,
protected _generateEmitter: <T>() => INopeEventEmitter<T>,
protected _generateObservable: <T>() => INopeObservable<T>,
protected _defaultSelector: ValidSelectorFunction,
protected readonly _id: string = null,
protected _statusManager: INopeConnectivityManager = null,
protected _connectivityManager: INopeConnectivityManager = null,
protected _rpcManager: INopeRpcManager = null,
protected _core: INopeCore = null
) {
@ -174,9 +176,9 @@ export class NopeInstanceManager implements INopeInstanceManager {
this._id = generateId();
}
if (_statusManager == null) {
if (_connectivityManager == null) {
// Creating a new Status-Manager.
this._statusManager = new NopeConnectivityManager(
this._connectivityManager = new NopeConnectivityManager(
options,
_generateObservable,
this._id
@ -295,7 +297,7 @@ export class NopeInstanceManager implements INopeInstanceManager {
// Wait until the Element is connected.
await this._communicator.connected.waitFor();
await this._statusManager.ready.waitFor();
await this._connectivityManager.ready.waitFor();
await this._rpcManager.ready.waitFor();
this.registerInternalWrapperGenerator(
@ -303,6 +305,7 @@ export class NopeInstanceManager implements INopeInstanceManager {
async (dispather, description) => {
const mod = new NopeGenericWrapper(
dispather,
_this._generateEmitter,
_this._generateObservable
);
await mod.fromDescription(description, "overwrite");
@ -311,7 +314,7 @@ export class NopeInstanceManager implements INopeInstanceManager {
);
// We will use our status-manager to listen to changes.
this._statusManager.dispatchers.onChange.subscribe((changes) => {
this._connectivityManager.dispatchers.onChange.subscribe((changes) => {
if (changes.added.length) {
// If there are dispatchers online,
// We will emit our available services.
@ -591,8 +594,10 @@ export class NopeInstanceManager implements INopeInstanceManager {
},
}
);
// Store the Generator.
this._registeredConstructors.set(identifier, _cb);
// TODO: Send an update.
}
// See interface description
@ -663,7 +668,7 @@ export class NopeInstanceManager implements INopeInstanceManager {
// First we will check if the instance is available internally.
if (this._internalInstances.has(identifier)) {
return this._statusManager.info;
return this._connectivityManager.info;
}
// If that isnt the case, we will check all dispatchers and search the instance.
@ -673,7 +678,7 @@ export class NopeInstanceManager implements INopeInstanceManager {
] of this._mappingOfRemoteDispatchersAndInstances.entries()) {
for (const instance of msg.instances) {
if (instance.identifier == identifier) {
return this._statusManager.getStatus(dispatcher);
return this._connectivityManager.getStatus(dispatcher);
}
}
}

View File

@ -3,6 +3,7 @@
* @email m.karkowski@zema.de
*/
import { NopeEventEmitter } from "../eventEmitter";
import { getSingleton } from "../helpers/singletonMethod";
import { NopeGenericWrapper } from "../module/GenericWrapper";
import { NopeObservable } from "../observables/nopeObservable";
@ -54,6 +55,7 @@ export function getDispatcher(
const create = () => {
const dispatcher = new options.dispatcherConstructorClass(
dispatcherOptions,
() => new NopeEventEmitter(),
() => new NopeObservable()
);
@ -62,7 +64,11 @@ export function getDispatcher(
dispatcher.instanceManager.registerInternalWrapperGenerator(
"*",
async (core, description) => {
const mod = new NopeGenericWrapper(core, () => new NopeObservable());
const mod = new NopeGenericWrapper(
core,
() => new NopeEventEmitter(),
() => new NopeObservable()
);
await mod.fromDescription(description, "overwrite");
// await mod.init();
return mod;

View File

@ -6,7 +6,7 @@
* @desc [description]
*/
import { IexportFunctionAsNopeServiceParameters } from "../decorators/index";
import { IexportAsNopeServiceParameters } from "../decorators/index";
import { getSingleton } from "../helpers/singletonMethod";
import {
INopeDispatcher,
@ -31,7 +31,7 @@ export function getLinkedDispatcher(
{
uri: string;
callback: (...args) => Promise<any>;
options: IexportFunctionAsNopeServiceParameters;
options: IexportAsNopeServiceParameters;
}
>();
});

View File

@ -68,8 +68,8 @@ import * as instanceManager from "./InstanceManager";
import * as rpcManager from "./RpcManager";
export {
exportFunctionAsNopeService,
IexportFunctionAsNopeServiceParameters,
exportAsNopeService,
IexportAsNopeServiceParameters,
nopeEmitter,
nopeMethod,
nopeProperty,

View File

@ -7,7 +7,12 @@
*/
import { inject, injectable } from "inversify";
import { DISPATCHER_OPTIONS, OBSERVABLE_FACTORY } from "../symbols/identifiers";
import {
DISPATCHER_OPTIONS,
EMITTER_FACTORY,
OBSERVABLE_FACTORY,
} from "../symbols/identifiers";
import { INopeEventEmitter } from "../types";
import { INopeDispatcherOptions } from "../types/nope/nopeDispatcher.interface";
import { INopeObservable } from "../types/nope/nopeObservable.interface";
import { NopeDispatcher } from "./nopeDispatcher";
@ -16,9 +21,11 @@ import { NopeDispatcher } from "./nopeDispatcher";
export class InjectableNopeDispatcher extends NopeDispatcher {
constructor(
@inject(DISPATCHER_OPTIONS) public options: INopeDispatcherOptions,
@inject(EMITTER_FACTORY)
protected _generateEmitter: <T>() => INopeEventEmitter<T>,
@inject(OBSERVABLE_FACTORY)
protected _generateObservable: <T>() => INopeObservable<T>
) {
super(options, _generateObservable);
super(options, _generateEmitter, _generateObservable);
}
}

View File

@ -26,7 +26,7 @@ import { NopeCore } from "./Core";
*/
export class NopeDispatcher extends NopeCore implements INopeDispatcher {
public get masterExists(): boolean {
return false;
return this.connectivityManager.master.isMasterForced;
}
// See interface description
@ -108,7 +108,7 @@ export class NopeDispatcher extends NopeCore implements INopeDispatcher {
return Object.assign(this.connectivityManager.info, {
isMaster: this.connectivityManager.isMaster,
instances: this.instanceManager.instances.data.getContent(),
services: [],
services: this.rpcManager.services.data.getContent(),
events: this.eventDistributor.emitters,
properties: this.dataDistributor.emitters,
// Show the data.

View File

@ -7,6 +7,7 @@
import { decorate, injectable } from "inversify";
import { getDispatcher } from "../dispatcher/getDispatcher";
import { NopeDispatcher } from "../dispatcher/nopeDispatcher";
import { InjectableNopeEventEmitter } from "../eventEmitter";
import { NopeBaseModule } from "../module/BaseModule";
import { NopeObservable } from "../observables/nopeObservable";
import { InjectableNopeObservable } from "../observables/nopeObservable.injectable";
@ -14,6 +15,8 @@ import {
COMMUNICATION_LAYER,
DISPATCHER_INSTANCE,
DISPATCHER_OPTIONS,
EMITTER_FACTORY,
EMITTER_INSTANCE,
OBSERVABLE_FACTORY,
OBSERVABLE_INSTANCE,
} from "../symbols/identifiers";
@ -39,7 +42,9 @@ export function generateNopeBasicPackage(
const TYPES = {
dispatcher: DISPATCHER_INSTANCE,
observableFactory: OBSERVABLE_FACTORY,
emitterFactory: EMITTER_FACTORY,
observable: OBSERVABLE_INSTANCE,
emitter: EMITTER_INSTANCE,
communicationLayer: COMMUNICATION_LAYER,
dispatcherOptions: DISPATCHER_OPTIONS,
};
@ -83,6 +88,17 @@ export function generateNopeBasicPackage(
allowInstanceGeneration: false,
},
},
{
description: {
name: "nopeEmitter",
selector: TYPES.emitter,
factorySelector: TYPES.emitterFactory,
type: InjectableNopeEventEmitter,
},
settings: {
allowInstanceGeneration: false,
},
},
{
description: {
name: "nopeObservable",

View File

@ -9,7 +9,7 @@ import { flatten, isArguments } from "lodash";
import "reflect-metadata";
import {
getCentralDecoratedContainer,
IexportFunctionAsNopeServiceParameters,
IexportAsNopeServiceParameters,
} from "../decorators";
import { arraysEqual } from "../helpers/arrayMethods";
import { sleep } from "../helpers/async";
@ -706,14 +706,14 @@ export class NopePackageLoader implements INopePackageLoader {
}
/**
* Function to load all decorated elements with the decorators `exportFunctionAsNopeService`
* Function to load all decorated elements with the decorators `exportAsNopeService`
*
* @param options
*/
async addDecoratedElements(
options: {
addServiceCallback?: (
options: IexportFunctionAsNopeServiceParameters
options: IexportAsNopeServiceParameters
) => Promise<boolean>;
addClassCallback?: (options: INopeModule) => Promise<boolean>;
consider?: Array<"services" | "classes">;

View File

@ -69,10 +69,10 @@ export class NopeBaseModule implements INopeModule {
*/
public version: IVersion;
protected _registeredFunctions: Map<
protected _registeredMethods: Map<
string,
{
func: (...args: any[]) => Promise<any>;
method: (...args: any[]) => Promise<any>;
options: IFunctionOptions;
}
>;
@ -99,10 +99,10 @@ export class NopeBaseModule implements INopeModule {
* @readonly
* @memberof BaseModule
*/
public get functions() {
public get methods() {
const ret: { [index: string]: IFunctionOptions } = {};
for (const [name, funcs] of this._registeredFunctions.entries()) {
for (const [name, funcs] of this._registeredMethods.entries()) {
ret[name] = funcs.options;
}
@ -166,7 +166,7 @@ export class NopeBaseModule implements INopeModule {
this.author = null;
this.version = null;
this.identifier = null;
this._registeredFunctions = new Map();
this._registeredMethods = new Map();
this._registeredProperties = new Map();
this._registeredEvents = new Map();
this.uiLinks = [];
@ -220,7 +220,10 @@ export class NopeBaseModule implements INopeModule {
options.topic.publish
);
}
} else {
throw Error("Topic must be provided in the options");
}
const _observable = await this._core.dataDistributor.register(
observable,
options
@ -251,7 +254,7 @@ export class NopeBaseModule implements INopeModule {
options: IEventOptions
): Promise<void> {
// Unregister the Function
await this.unregisterEvents(name);
await this.unregisterEvent(name);
// Adapt the Topics
if (
@ -295,14 +298,14 @@ export class NopeBaseModule implements INopeModule {
* Function used to register a Method. This Method will be available in the shared network.
*
* @param {string} name Name of the Method, which is used during registration at the dispatcher
* @param {(...args: any[]) => Promise<any>} func The function itself. It must be async.
* @param {(...args: any[]) => Promise<any>} method The function itself. It must be async.
* @param {IFunctionOptions} options The Options, used for registering.
* @return {*} {Promise<void>}
* @memberof NopeBaseModule
*/
public async registerMethod(
name: string,
func: (...args: any[]) => Promise<any>,
method: (...args: any[]) => Promise<any>,
options: IFunctionOptions
): Promise<void> {
// Unregister the Function
@ -317,11 +320,14 @@ export class NopeBaseModule implements INopeModule {
options.id = getMethodPath(this.identifier, name);
}
const _func = await this._core.rpcManager.registerService(func, options);
const _method = await this._core.rpcManager.registerService(
method,
options
);
// Register the new Function.
this._registeredFunctions.set(name, {
func: _func,
this._registeredMethods.set(name, {
method: _method,
options,
});
}
@ -336,21 +342,21 @@ export class NopeBaseModule implements INopeModule {
public async unregisterFunction(name: string): Promise<void> {
// Test if the Method is already registerd,
// If so => unregister it first.
if (this._registeredFunctions.has(name)) {
if (this._registeredMethods.has(name)) {
this._core.rpcManager.unregisterService(
this._registeredFunctions.get(name).func
this._registeredMethods.get(name).method
);
}
}
/**
* Helper Function to unregister an Observable (a Property.)
* Helper Function to unregister an Eventbased Property
*
* @param {string} name Name of the Property, that has been used to register.
* @return {*} {Promise<void>}
* @memberof NopeBaseModule
*/
public async unregisterEvents(name: string): Promise<void> {
public async unregisterEvent(name: string): Promise<void> {
// Test if the Property is already registerd,
// If so => unregister it first.
if (this._registeredEvents.has(name)) {
@ -383,10 +389,10 @@ export class NopeBaseModule implements INopeModule {
* @return {*} {Promise<{ func: (...args: any[]) => Promise<any>; options: IFunctionOptions; }[]>}
* @memberof NopeBaseModule
*/
public async listFunctions(): Promise<
public async listMethods(): Promise<
{ func: (...args: any[]) => Promise<any>; options: IFunctionOptions }[]
> {
return Array.from(this._registeredFunctions.values());
return Array.from(this._registeredMethods.values());
}
/**
@ -401,6 +407,18 @@ export class NopeBaseModule implements INopeModule {
return Array.from(this._registeredProperties.values());
}
/**
* Function used to list all available Properties.
*
* @return {*} {Promise<Array<{ observable: INopeObservable<any>, options: IPropertyOptions }>>}
* @memberof NopeBaseModule
*/
public async listEvents(): Promise<
Array<{ emitter: INopeEventEmitter<any>; options: IEventOptions }>
> {
return Array.from(this._registeredEvents.values());
}
/**
* An init Function. Used to initialize the Element.
*
@ -478,12 +496,12 @@ export class NopeBaseModule implements INopeModule {
*/
public async dispose() {
// Unregister all Methods and Functions
for (const name of this._registeredFunctions.keys()) {
for (const name of this._registeredMethods.keys()) {
await this.unregisterFunction(name);
}
// Remove all known Functions
this._registeredFunctions.clear();
this._registeredMethods.clear();
// Unregister all Properties.
for (const name of this._registeredProperties.keys()) {
@ -492,17 +510,25 @@ export class NopeBaseModule implements INopeModule {
// Remove all known Properties.
this._registeredProperties.clear();
// Unregister all Properties.
for (const name of this._registeredEvents.keys()) {
await this.unregisterEvent(name);
}
// Remove all known Properties.
this._registeredEvents.clear();
}
/**
* Helper Function to extract the used identifiert of Property
*
* @param {(((...args) => Promise<any>) | INopeObservable<any>)} propOrFunc The Property or the Function to receive the Name.
* @param {(((...args) => Promise<any>) | INopeObservable<any>)} prop_event_or_func The Property or the Function to receive the Name.
* @return {*} {string}
* @memberof NopeBaseModule
*/
public getIdentifierOf(
propOrFunc: ((...args) => Promise<any>) | INopeObservable<any>,
prop_event_or_func: ((...args) => Promise<any>) | INopeObservable<any>,
type: "topicToPublish" | "topicToSubscribe" = null
): string {
// To Extract the name of the Property or the Function, we will iterate over
@ -512,7 +538,7 @@ export class NopeBaseModule implements INopeModule {
for (const [name, item] of this._registeredProperties.entries()) {
const { observable, options } = item;
if (observable == propOrFunc) {
if (observable == prop_event_or_func) {
const _subTopic =
typeof options.topic === "string"
? options.topic
@ -543,9 +569,43 @@ export class NopeBaseModule implements INopeModule {
}
}
}
for (const [name, item] of this._registeredFunctions.entries()) {
const { func, options } = item;
if (func == propOrFunc) {
for (const [name, item] of this._registeredEvents.entries()) {
const { emitter, options } = item;
if (emitter == prop_event_or_func) {
const _subTopic =
typeof options.topic === "string"
? options.topic
: options.topic.subscribe || null;
const _pubTopic =
typeof options.topic === "string"
? options.topic
: options.topic.publish || null;
switch (type) {
case "topicToPublish":
if (_pubTopic === null) {
throw Error("No topic for publishing is defined.");
}
return _pubTopic;
case "topicToSubscribe":
if (_subTopic === null) {
throw Error("No topic for subscribing is defined.");
}
return _subTopic;
default:
if (typeof options.topic === "string") {
return options.topic;
}
throw Error(
"Prop uses different name for subscribing and publishing. Please specify using the 'type' identier to select"
);
}
}
}
for (const [name, item] of this._registeredMethods.entries()) {
const { method: func, options } = item;
if (func == prop_event_or_func) {
return options.id;
}
}
@ -563,7 +623,7 @@ export class NopeBaseModule implements INopeModule {
const ret: INopeModuleDescription = {
author: this.author,
description: this.description,
functions: this.functions,
methods: this.methods,
events: this.events,
identifier: this.identifier,
properties: this.properties,

View File

@ -4,9 +4,10 @@
*/
import { inject, injectable } from "inversify";
import { INopeCore } from "../types/nope";
import { INopeCore, INopeEventEmitter } from "../types/nope";
import {
DISPATCHER_INSTANCE,
EMITTER_FACTORY,
OBSERVABLE_FACTORY,
} from "../symbols/identifiers";
import { INopeObservable } from "../types/nope/nopeObservable.interface";
@ -22,8 +23,9 @@ export class InjectableNopeGenericWrapper extends NopeGenericWrapper {
*/
constructor(
@inject(DISPATCHER_INSTANCE) _core: INopeCore,
@inject(OBSERVABLE_FACTORY) _observableFactory: () => INopeObservable<any>
@inject(OBSERVABLE_FACTORY) _observableFactory: () => INopeObservable<any>,
@inject(EMITTER_FACTORY) _emitterFactory: () => INopeEventEmitter<any>
) {
super(_core, _observableFactory);
super(_core, _emitterFactory, _observableFactory);
}
}

View File

@ -5,7 +5,7 @@
import { deepClone } from "../helpers/objectMethods";
import { getNopeLogger } from "../logger/getLogger";
import { ICallOptions, INopeCore } from "../types";
import { ICallOptions, INopeCore, INopeEventEmitter } from "../types";
import {
IEventOptions,
IFunctionOptions,
@ -65,6 +65,10 @@ export class NopeGenericWrapper extends NopeBaseModule {
public dynamicInstanceProperties: {
[index: string]: INopeObservable<any>;
} = {};
public dynamicInstanceEvents: {
[index: string]: INopeEventEmitter<any>;
} = {};
public dynamicInstanceMethodsWithOptions: {
[index: string]: <T>(
options: Partial<ICallOptions>,
@ -116,10 +120,10 @@ export class NopeGenericWrapper extends NopeBaseModule {
);
}
for (const name in description.functions) {
for (const name in description.methods) {
this._logger.debug('Create function interface for "' + name + '"');
const options = description.functions[name];
const options = description.methods[name];
const func = (...args) => {
return _this._core.rpcManager.performCall(options.id, args, options);
};
@ -135,25 +139,23 @@ export class NopeGenericWrapper extends NopeBaseModule {
};
if (this.dynamicInstanceMethods[name]) {
throw Error("Name alread used. Not able to use the method name twice");
throw Error("Name alread used. Not able to use the name twice");
}
(this.dynamicInstanceMethods as any)[name] = func;
if (this.dynamicInstanceMethodsWithOptions[name]) {
throw Error("Name alread used. Not able to use the method name twice");
throw Error("Name alread used. Not able to use the name twice");
}
(this.dynamicInstanceMethodsWithOptions as any)[name] =
funcWithCustomOptions;
// If the Function isnt dynamic, register it on the Object itself.
if (!options.isDynamic) {
if (this[name]) {
throw Error(
"Name alread used. Not able to use the method name twice"
);
throw Error("Name alread used. Not able to use the name twice");
}
this[name] = func;
}
this._registeredFunctions.set(name, {
func,
this._registeredMethods.set(name, {
method: func,
options,
});
}
@ -171,7 +173,7 @@ export class NopeGenericWrapper extends NopeBaseModule {
// let mode = prop.mode;
if (this.dynamicInstanceProperties[name]) {
throw Error("Name alread used. Not able to use the method name twice");
throw Error("Name alread used. Not able to use the name twice");
}
// Make shure it isnt published.
@ -188,9 +190,7 @@ export class NopeGenericWrapper extends NopeBaseModule {
if (!options.isDynamic) {
if (this[name]) {
throw Error(
"Name alread used. Not able to use the method name twice"
);
throw Error("Name alread used. Not able to use the name twice");
}
// Use the Same Element.
this[name] = this.dynamicInstanceProperties[name];
@ -202,6 +202,48 @@ export class NopeGenericWrapper extends NopeBaseModule {
options,
});
}
for (const name in description.events) {
this._logger.debug('Create property interface for "' + name + '"');
const options = description.events[name];
// Add only elements, that are subscribed.
// Properties, which are only publishing
// should throw an error, if data is published
// in a remote. This is done to maintain
// consistency.
// let mode = prop.mode;
if (this.dynamicInstanceEvents[name]) {
throw Error("Name alread used. Not able to use the name twice");
}
// Make shure it isnt published.
// options.preventSendingToRegistery = true;
// Register the Observable:
this.dynamicInstanceEvents[name] = this._core.eventDistributor.register(
// Assign a new Observable.
this._emitterFactory(),
// Use the provided Properties:
_invertMode(options)
);
if (!options.isDynamic) {
if (this[name]) {
throw Error("Name alread used. Not able to use the name twice");
}
// Use the Same Element.
this[name] = this.dynamicInstanceEvents[name];
}
this._logger.debug('Register Property "' + name + '"', options);
this._registeredEvents.set(name, {
emitter: this.dynamicInstanceEvents[name],
options,
});
}
}
/**
@ -212,12 +254,13 @@ export class NopeGenericWrapper extends NopeBaseModule {
*/
constructor(
_core: INopeCore,
protected _emitterFactory: () => INopeEventEmitter<any>,
protected _observableFactory: () => INopeObservable<any>
) {
super(_core);
}
public async listFunctions(): Promise<
public async listMethods(): Promise<
{ func: (...args: any[]) => Promise<any>; options: IFunctionOptions }[]
> {
const _this = this;
@ -270,7 +313,11 @@ export class NopeGenericWrapper extends NopeBaseModule {
delete this[name];
}
this._registeredFunctions.clear();
for (const name in this.dynamicInstanceEvents) {
this.dynamicInstanceEvents[name].dispose();
// Remove Reference
delete this[name];
}
this.dynamicInstanceProperties = {};
@ -280,5 +327,7 @@ export class NopeGenericWrapper extends NopeBaseModule {
}
this._registeredProperties.clear();
this._registeredEvents.clear();
this._registeredMethods.clear();
}
}

View File

@ -9,6 +9,8 @@
export const DISPATCHER_INSTANCE = Symbol.for("nope.dispatcher.instance");
export const DISPATCHER_OPTIONS = Symbol.for("nope.dispatcher.options");
export const OBSERVABLE_FACTORY = Symbol.for("nope.observable.factory");
export const EMITTER_FACTORY = Symbol.for("nope.emitter.factory");
export const OBSERVABLE_INSTANCE = Symbol.for("nope.observable.instance");
export const EMITTER_INSTANCE = Symbol.for("nope.emitter.instance");
export const COMMUNICATION_LAYER = Symbol.for("nope.communication.layer");
export const LOADER = Symbol.for("nope.package.loader");

View File

@ -16,6 +16,7 @@ import { INopeDescriptor } from "./nopeDescriptor.interface";
import {
IEventAdditionalData,
IEventCallback,
INopeEventEmitter,
INopeObserver,
} from "./nopeEventEmitter.interface";
import { INopeModule, INopeModuleDescription } from "./nopeModule.interface";
@ -86,6 +87,7 @@ export interface IHostOverview extends IHost {
export interface IDispatcherConstructor {
new (
options: INopeDispatcherOptions,
_generateEmitter: <T>() => INopeEventEmitter<T>,
_generateObservable: <T>() => INopeObservable<T>
): INopeDispatcher;
}
@ -157,8 +159,8 @@ export interface INopeDispatcher extends INopeCore {
/**
* Helper to pull some data from the system.
* @param path
* @param _default
* @param path The path to the Data.
* @param _default The value to use if no data has been found. If not provided an error is thrown. Defaults to None.
*/
pullData<T = unknown, D = null>(path: string, _default?: D): T;
@ -183,12 +185,13 @@ export interface INopeDispatcher extends INopeCore {
/**
* Receive the "instances" | "services" | "properties" | "events"
* which matches with the given pattern.
* which matches with the given pattern. Therefore the user provides
* the pattern and tyle.
*
* @author M.Karkowski
* @param {string} pattern
* @param {("instances" | "services" | "properties" | "events")} type
* @return {*} {string[]}
* @param {string} pattern Pattern to query the provided type.
* @param {("instances" | "services" | "properties" | "events")} type Type which should be querried
* @return {string[]} List of the matching items.
* @memberof INopeDispatcher
*/
query(

View File

@ -124,7 +124,7 @@ export interface INopeInstanceManager {
* able to create new ones.
*
* @author M.Karkowski
* @param {string} typeIdentifier
* @param {string} typeIdentifier The identifier for the Constructor (Like a service)
* @return {Promise<void>}
* @memberof INopeInstanceManager
*/
@ -208,7 +208,7 @@ export interface INopeInstanceManager {
constructorExists(typeIdentifier: string): boolean;
/**
* Returns the hosting Manager for the given instance.
* Returns the hosting dispatcher for the given instance.
*
* @author M.Karkowski
* @param {string} instanceIdentifier The identifier for instance (its name)
@ -222,7 +222,7 @@ export interface INopeInstanceManager {
* for the "instances"-property.
*
* @author M.Karkowski
* @param {string} instanceIdentifier
* @param {string} instanceIdentifier The identifier for instance (its name)
* @return {(INopeModuleDescription | false)}
* @memberof INopeInstanceManager
*/
@ -236,7 +236,7 @@ export interface INopeInstanceManager {
*
* @author M.Karkowski
* @template I
* @param {I} instance
* @param {I} instance The Instance to consider
* @return {Promise<I>}
* @memberof INopeInstanceManager
*/
@ -250,7 +250,7 @@ export interface INopeInstanceManager {
*
* @author M.Karkowski
* @template I
* @param {(I | string)} instance
* @param {(I | string)} instance The Instance to consider
* @return {Promise<boolean>}
* @memberof INopeInstanceManager
*/

View File

@ -85,7 +85,7 @@ export interface INopeModuleDescription {
* @type {{ [index: string]: IFunctionOptions }}
* @memberof INopeModuleDescription
*/
readonly functions: { [index: string]: IFunctionOptions };
readonly methods: { [index: string]: IFunctionOptions };
readonly events: { [index: string]: IEventOptions };
@ -165,7 +165,7 @@ export interface INopeModule extends INopeModuleDescription {
* @return {Promise<Array<{ name: string, schema: IDescriptor, options: IFunctionOptions }>>}
* @memberof IBaseModule
*/
listFunctions(): Promise<
listMethods(): Promise<
Array<{ func: (...args) => Promise<any>; options: IFunctionOptions }>
>;

View File

@ -1,5 +1,5 @@
import { Container } from "inversify";
import { IexportFunctionAsNopeServiceParameters } from "../../decorators";
import { IexportAsNopeServiceParameters } from "../../decorators";
import { INopeDispatcher } from "./nopeDispatcher.interface";
import { INopeModule } from "./nopeModule.interface";
import {
@ -84,7 +84,7 @@ export interface INopePackageLoader {
*/
addDecoratedElements(options?: {
addServiceCallback?: (
options: IexportFunctionAsNopeServiceParameters
options: IexportAsNopeServiceParameters
) => Promise<boolean>;
addClassCallback?: (options: INopeModule) => Promise<boolean>;
consider?: Array<"services" | "classes">;