diff --git a/CHANGELOG.md b/CHANGELOG.md index e5e0736..959072b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -105,4 +105,32 @@ Inital commit, which is working with the browser - Added `internalInstances: INopeObservable` to `InstanceManager`.: - Added dev-depencies for libraries. - Modified: - - Modified `addAllBaseServices` now includes some options, which can be used to determine the specific service to load. \ No newline at end of file + - Modified `addAllBaseServices` now includes some options, which can be used to determine the specific service to load. + +# 1.1.2 +- Added: + - `lib/cli/nope` adding scan for ui service + - `lib/decorators/container`: Main Container, holding all `methods` and `classes`. Use `getCentralDecoratedContainer()` to get this decorator. + - `types/nope/nopePackage.interface` added `IClassDescription` which contains the class description used in the Package Description. + - `logger/nopeLogger`: added methods: `enabledFor`, `enableFor`, `shouldLog` + - `package.json`: installed types of `ace` text editor. + - `ui/helpers.browser`: Created `convertInstanceRenderPage` and `IUiDefinition` + - `ui/helpers.nodejs`: Added a Helper to write the Ui-File (`writeUiFile`) and parse its arguments (`readInwriteUiFileArgs`) + - `ui/index.*`: Crated the corresponding exports. + +- Modified: + - `lib/decorators/*` Adding the main `container` where every function, service method etc is added. All decorators now safe the decorated elements in the container. + - `helpers/json`: Adding `BEGIN_STR` and `END_STR` for parsing functions as constants. + - `logger/eventLogging`: simplify `useEventLogger` + - `logger/index.browser`: Adating exports. + - `loader/loadPackages`: Modifing `IPackageConfig` now extends Partial the `IPackageDescription` + - `types/ui/editor/IEditPage`: adapting Type of `getData` to `T`->`any`. Adapting the return of `getPorts` (The Ports will be generated in the ui then) + - `types/ui/editor/helpers.interface`: Adapting the `w2ui` and added `w2uiHelpers` and added `ace`. Rearanging `IRenderData` element. to compact the data. + - `types/ui/editor/render.callbacks`: Rearange the Generic Type of `TRenderInstancePage` and Renaming `TCreatorPage` to `TInstanceManagerPage`. Adapting the `option` of `TInstanceManagerPage` regarding the `createInstance` and `instances` + - `types/ui/editor/index`: Adapting the Exports. + - `lib/index.browser`: Exporting `ui` elements + - `lib/index.nodejs`: Exporting `ui` elements + - `lib/types/index`: Exporting `ui` elements + +- Fixes: + - `types/nope/nopeInstanceManager.interface`: Fixing Type of createInstance. Now the Type `I` extends `INopeModule` instead of being set to `IGenericNopeModule` diff --git a/contribute/VERSION b/contribute/VERSION index 8cfbc90..867e524 100644 --- a/contribute/VERSION +++ b/contribute/VERSION @@ -1 +1 @@ -1.1.1 \ No newline at end of file +1.2.0 \ No newline at end of file diff --git a/lib/cli/nope.ts b/lib/cli/nope.ts index 8ae5b70..8d7c0d2 100644 --- a/lib/cli/nope.ts +++ b/lib/cli/nope.ts @@ -1,16 +1,14 @@ /** * @author Martin Karkowski * @email m.karkowski@zema.de - * @create date 2021-01-18 17:29:44 - * @modify date 2021-02-09 10:25:07 * @desc [description] */ +import { readInwriteUiFileArgs, writeUiFile } from "../ui/helpers.nodejs"; import { createService } from "./createService"; import { generateDefaultConfig } from "./generateDefaultConfig"; import { generateDefaultPackageConfig } from "./generateDefaultPackageConfig"; import { generateFolderStructure } from "./generateFolderStructure"; -import { NOPELOGO } from "./renderNope"; import { repl } from "./repl"; import run from "./runNopeBackend"; @@ -21,7 +19,15 @@ import run from "./runNopeBackend"; */ export async function main() { const args: { - mode: "run" | "init" | "none" | "scan" | "help" | "service" | "repl"; + mode: + | "run" + | "init" + | "none" + | "conf" + | "help" + | "service" + | "repl" + | "scan-ui"; params: string[]; } = { mode: (process.argv[2] as any) || "none", @@ -44,9 +50,10 @@ Please select the option you want. Therefore add one of the following options: \x1b[4mhelp\x1b[0m Show this help. \x1b[4mrun\x1b[0m Start a NoPE-Backend. \x1b[4minit\x1b[0m Initialize a new project. This project is empty. - \x1b[4mscan\x1b[0m Trys to update the configuration file. + \x1b[4mconf\x1b[0m Trys to update the configuration file. + \x1b[4mscan-ui\x1b[0m Scans and extracts the provided uis. \x1b[4mservice\x1b[0m Generate Helper Files to provide services - \x1b[4mrepl\x1b[0m Opens an interactive console. + \x1b[4mrepl\x1b[0m Opens an interactive console. Have fun using NoPE :) @@ -76,7 +83,7 @@ Have fun using NoPE :) await generateDefaultConfig([additionalArg]); await generateDefaultPackageConfig([additionalArg]); break; - case "scan": + case "conf": additionalArg.help = "Command to generate the Config of the backend"; await generateDefaultPackageConfig([additionalArg]); break; @@ -87,6 +94,11 @@ Have fun using NoPE :) case "repl": await repl([additionalArg]); break; + case "scan-ui": + additionalArg.help = + "Command to readin the UI-Files and store them in a config"; + await writeUiFile(readInwriteUiFileArgs([additionalArg])); + break; } } diff --git a/lib/decorators/container.ts b/lib/decorators/container.ts new file mode 100644 index 0000000..467d921 --- /dev/null +++ b/lib/decorators/container.ts @@ -0,0 +1,38 @@ +/** + * @author Martin Karkowski + * @email m.karkowski@zema.de + * @desc [description] + */ + +import { getSingleton } from "../helpers/singletonMethod"; +import { IFunctionOptions, INopeModule } from "../types"; + +export type IexportFunctionAsNopeServiceParameters = IFunctionOptions; + +/** + * Return the central loger. This logger is a singleton (see {@link getSingleton}) + * + * @author M.Karkowski + * @export + * @return {NopeLogger} A Returns the Logger {@link NopeLogger} + */ +export function getCentralDecoratedContainer(): { + methods: Map< + string, + { + uri: string; + callback: (...args) => Promise; + options: IexportFunctionAsNopeServiceParameters; + } + >; + classes: Map; +} { + const container = getSingleton("nope.decorated.elements", () => { + return { + methods: new Map(), + classes: new Map(), + }; + }); + + return container.instance; +} diff --git a/lib/decorators/functionDecorators.ts b/lib/decorators/functionDecorators.ts index dfb284a..73b8251 100644 --- a/lib/decorators/functionDecorators.ts +++ b/lib/decorators/functionDecorators.ts @@ -1,26 +1,15 @@ /** * @author Martin Karkowski * @email m.karkowski@zema.de - * @create date 2020-11-06 08:52:55 - * @modify date 2020-12-02 08:56:37 * @desc [description] */ -import { getSingleton } from "../helpers/singletonMethod"; -import { IFunctionOptions } from "../types/nope/nopeModule.interface"; +import { + getCentralDecoratedContainer, + IexportFunctionAsNopeServiceParameters, +} from "./container"; -export type IexportFunctionAsNopeServiceParameters = IFunctionOptions; - -const container = getSingleton("nopeBackendDispatcher.container", () => { - return new Map< - string, - { - uri: string; - callback: (...args) => Promise; - options: IexportFunctionAsNopeServiceParameters; - } - >(); -}); +const CONTAINER = getCentralDecoratedContainer(); /** * Defintion of a Functon. @@ -39,8 +28,8 @@ export function exportFunctionAsNopeService( options: IexportFunctionAsNopeServiceParameters ) { // Only add the element if it doesnt exists. - if (!container.instance.has(options.id)) { - container.instance.set(options.id, { + if (!CONTAINER.methods.has(options.id)) { + CONTAINER.methods.set(options.id, { callback: async (...args) => await (func as any)(...args), options, uri: options.id || (func as any).name, diff --git a/lib/decorators/index.ts b/lib/decorators/index.ts index 55b6a14..6d4de1e 100644 --- a/lib/decorators/index.ts +++ b/lib/decorators/index.ts @@ -4,7 +4,8 @@ */ export { - exportFunctionAsNopeService, + getCentralDecoratedContainer, IexportFunctionAsNopeServiceParameters, -} from "./functionDecorators"; +} from "./container"; +export { exportFunctionAsNopeService } from "./functionDecorators"; export { nopeEmitter, nopeMethod, nopeProperty } from "./moduleDecorators"; diff --git a/lib/decorators/moduleDecorators.ts b/lib/decorators/moduleDecorators.ts index 0e8809b..10b600e 100644 --- a/lib/decorators/moduleDecorators.ts +++ b/lib/decorators/moduleDecorators.ts @@ -9,6 +9,9 @@ import { IFunctionOptions, INopeModule, } from "../types/nope/nopeModule.interface"; +import { getCentralDecoratedContainer } from "./container"; + +const CONTAINER = getCentralDecoratedContainer(); /** * Decorator, used to export the Method as Service to Nope.. @@ -26,6 +29,9 @@ export function nopeMethod(options: IFunctionOptions) { methodName: string, descriptor: PropertyDescriptor ) { + // Add the Target to the class. + CONTAINER.classes.set(target.constructor.name, target); + target._markedElements = target._markedElements || []; target._markedElements.push({ accessor: methodName, @@ -46,6 +52,9 @@ export function nopeProperty(options: IEventOptions) { propertyKey: string, descriptor: PropertyDescriptor ) { + // Add the Target to the class. + CONTAINER.classes.set(target.constructor.name, target); + target._markedElements = target._markedElements || []; target._markedElements.push({ accessor: propertyKey, @@ -66,6 +75,9 @@ export function nopeEmitter(options: IEventOptions) { propertyKey: string, descriptor: PropertyDescriptor ) { + // Add the Target to the class. + CONTAINER.classes.set(target.constructor.name, target); + target._markedElements = target._markedElements || []; target._markedElements.push({ accessor: propertyKey, diff --git a/lib/helpers/jsonMethods.ts b/lib/helpers/jsonMethods.ts index a480c46..fa4f388 100644 --- a/lib/helpers/jsonMethods.ts +++ b/lib/helpers/jsonMethods.ts @@ -4,6 +4,9 @@ * @desc [description] */ +const BEGIN_STR = "____Function_beginn/("; +const END_STR = ")/__Function_end"; + /** * Function to stringify an Object. This Function will stringify Functions as well. * @param obj The Object. @@ -31,7 +34,7 @@ export function stringifyWithFunctions(obj, ...args) { str = adaptedFunc; } - return "/Function(" + str + ")/"; + return BEGIN_STR + str + END_STR; } return value; }, @@ -52,10 +55,13 @@ export function parseWithFunctions( return JSON.parse(json, (key, value) => { if ( typeof value === "string" && - value.startsWith("/Function(") && - value.endsWith(")/") + value.startsWith(BEGIN_STR) && + value.endsWith(END_STR) ) { - const _value = value.substring(10, value.length - 2); + const _value = value.substring( + BEGIN_STR.length, + value.length - END_STR.length + ); try { return eval("(" + _value + ")").bind(scope); } catch (e) { diff --git a/lib/index.browser.ts b/lib/index.browser.ts index 9e5d8bb..034ebf3 100644 --- a/lib/index.browser.ts +++ b/lib/index.browser.ts @@ -16,6 +16,7 @@ import * as observables from "./observables/index"; import * as promise from "./promise/index"; import * as pubSub from "./pubSub"; import * as types from "./types/index"; +import * as ui from "./ui/index.browser"; export * from "./communication/index.browser"; export * from "./decorators"; @@ -30,6 +31,7 @@ export * from "./promise/index"; export * from "./pubSub"; export * from "./types/index"; export * from "./types/nope"; +export * from "./ui/index.browser"; export { communcation, decorators, @@ -43,4 +45,5 @@ export { observables, promise, pubSub, + ui, }; diff --git a/lib/index.nodejs.ts b/lib/index.nodejs.ts index 934e94a..68666f9 100644 --- a/lib/index.nodejs.ts +++ b/lib/index.nodejs.ts @@ -33,3 +33,5 @@ export * as pubSub from "./pubSub"; export * as types from "./types"; export * from "./types/index"; export * from "./types/nope"; +export * from "./ui/index.nodejs"; +export * as ui from "./ui/index.nodejs"; diff --git a/lib/loader/loadPackages.ts b/lib/loader/loadPackages.ts index 61ed6d8..66fb2ce 100644 --- a/lib/loader/loadPackages.ts +++ b/lib/loader/loadPackages.ts @@ -11,23 +11,10 @@ import { sleep } from "../helpers/async"; import { createFile, listFiles } from "../helpers/fileMethods"; import { parseWithFunctions, stringifyWithFunctions } from "../index.browser"; import { getNopeLogger } from "../logger/getLogger"; -import { IInstanceCreationMsg } from "../types/nope/nopeCommunication.interface"; import { IPackageDescription } from "../types/nope/nopePackage.interface"; import { INopePackageLoader } from "../types/nope/nopePackageLoader.interface"; -export interface IPackageConfig { - nameOfPackage: string; - defaultInstances: { - options: Partial; - selector: string | symbol; - }[]; - autostart: { - [index: string]: { - service: string; - delay?: number; - params: any[]; - }[]; - }; +export interface IPackageConfig extends Partial> { // File Path of the element. path: string; } @@ -227,6 +214,14 @@ export async function loadPackages( await loader.generateInstances(); } +/** + * Helper to read function provided in the defined configuration. + * + * @author M.Karkowski + * @export + * @param {string} [filename=join(resolve(process.cwd()), "config", "assembly.json")] + * @return {*} + */ export async function loadFunctions( filename: string = join(resolve(process.cwd()), "config", "assembly.json") ) { diff --git a/lib/logger/eventLogging.ts b/lib/logger/eventLogging.ts index d168461..41f4079 100644 --- a/lib/logger/eventLogging.ts +++ b/lib/logger/eventLogging.ts @@ -121,10 +121,7 @@ export function getLogerAsEventEmitter(): LoggerAsEventEmitter { export function useEventLogger(): LoggerAsEventEmitter { const logger = getCentralNopeLogger(); - const res = getSingleton("nope.logger.event", () => { - return new LoggerAsEventEmitter(); - }); - const emitter = res.instance; + const emitter = getLogerAsEventEmitter(); logger.setHandler((msg, context) => { const msgs: string[] = []; diff --git a/lib/logger/index.browser.ts b/lib/logger/index.browser.ts index 1aab35a..83699e8 100644 --- a/lib/logger/index.browser.ts +++ b/lib/logger/index.browser.ts @@ -49,6 +49,7 @@ export const LEVELS = { export { ILogger } from "js-logger"; export { getLogerAsEventEmitter, + LoggerAsEventEmitter, TCallback, TCallbackWithLevel, useEventLogger, @@ -59,5 +60,11 @@ export { getNopeLogger, ValidLoggerDefinition, } from "./getLogger"; -export { LoggerLevel, LoggerLevels } from "./nopeLogger"; +export { + enabledFor, + enableFor, + LoggerLevel, + LoggerLevels, + shouldLog, +} from "./nopeLogger"; export { setGlobalLoggerLevel } from "./setGlobalLoggerLevel"; diff --git a/lib/logger/nopeLogger.ts b/lib/logger/nopeLogger.ts index edbb3da..44d8760 100644 --- a/lib/logger/nopeLogger.ts +++ b/lib/logger/nopeLogger.ts @@ -172,6 +172,47 @@ function _getLogger(level: LoggerLevel, label = ""): ILogger { return logger; } +/** + * Tests if the Logger is enabled for the level, or extracts the level. + * + * @param {ILogger} logger The logger + * @param {LoggerLevel} [lvl] if provided tests if the lvl matches the logger. otherwise returns the current level + * @return {(boolean | LoggerLevel)} + */ +export function enabledFor( + logger: ILogger, + lvl?: LoggerLevel +): boolean | LoggerLevel { + if (lvl) { + return logger.enabledFor(mapping[lvl]); + } + return logger.getLevel().name as LoggerLevel; +} + +/** + * Enables the Logger for the desired Level. + * + * @param {ILogger} logger The logger + * @param {LoggerLevel} lvl The level to use + * @return {void} + */ +export function enableFor(logger: ILogger, lvl: LoggerLevel): void { + return logger.setLevel(mapping[lvl]); +} + +/** + * Helper to test if the message would be logged. + * @param loggerLevel The Level of the logger + * @param messageLevel The Level of the Message + * @returns + */ +export function shouldLog( + loggerLevel: LoggerLevel, + messageLevel: LoggerLevel +): boolean { + return order[messageLevel] >= order[loggerLevel]; +} + /** * The Nope-Logger. It consits o */ diff --git a/lib/types/index.ts b/lib/types/index.ts index 67fa94e..0db9191 100644 --- a/lib/types/index.ts +++ b/lib/types/index.ts @@ -6,6 +6,7 @@ import * as nope from "./nope/index"; import * as ui from "./ui/index"; -export * from "./nope/index"; export * from "./IJSONSchema"; +export * from "./nope/index"; +export * from "./ui/index"; export { nope, ui }; diff --git a/lib/types/nope/nopeInstanceManager.interface.ts b/lib/types/nope/nopeInstanceManager.interface.ts index 3d9b16a..a8faa93 100644 --- a/lib/types/nope/nopeInstanceManager.interface.ts +++ b/lib/types/nope/nopeInstanceManager.interface.ts @@ -137,15 +137,15 @@ export interface INopeInstanceManager { * * @author M.Karkowski * @template I - * @param {Partial} description + * @param {Partial} description Description of the instance to be created * @param {{ * selector?: ValidSelectorFunction; * assignmentValid?: TValidAsssignmentChecker - * }} options + * }} options Options used during creating the instance. * @return {Promise} * @memberof INopeInstanceManager */ - createInstance( + createInstance( description: Partial, options?: { selector?: ValidSelectorFunction; diff --git a/lib/types/nope/nopePackage.interface.ts b/lib/types/nope/nopePackage.interface.ts index db5d00e..7d1dc81 100644 --- a/lib/types/nope/nopePackage.interface.ts +++ b/lib/types/nope/nopePackage.interface.ts @@ -1,5 +1,5 @@ import { interfaces } from "inversify"; -import { TCreatorPage, TRenderInstancePage } from "../ui"; +import { TInstanceManagerPage, TRenderInstancePage } from "../ui"; import { IInstanceCreationMsg } from "./nopeCommunication.interface"; import { IValidPromise } from "./nopeDispatcher.interface"; import { IFunctionOptions, INopeModule } from "./nopeModule.interface"; @@ -57,6 +57,36 @@ export interface IClassDescriptor { name: string; } +export interface IClassDescription { + /** + * Descriptor of the class + */ + description: IClassDescriptor; + /** + * Settings used for the creator. + */ + settings: { + /** + * You can prevent creating instances. + * Defaults to `true` + */ + allowInstanceGeneration?: boolean; + /** + * Max amount, of instances, that are allowed to + * be created by the local dispatcher. (This is only + * used for hosting.) + */ + maxAmountOfInstance?: number; + }; + /** + * UI Related Methods. + */ + ui?: { + creator?: TInstanceManagerPage; + config?: TRenderInstancePage; + }; +} + /** * Element used to define a nopePackages. * A Package can be loaded automatically. @@ -74,17 +104,7 @@ export interface IPackageDescription< * @type {Array} * @memberof IPackageDescription */ - providedClasses: Array<{ - description: IClassDescriptor; - settings: { - allowInstanceGeneration?: boolean; - maxAmountOfInstance?: number; - }; - ui?: { - creator: TCreatorPage; - config: TRenderInstancePage; - }; - }>; + providedClasses: Array; /** * Element containing functions of the module. diff --git a/lib/types/ui/editor/IEditPage.ts b/lib/types/ui/editor/IEditPage.ts index c52a75c..43b1d6e 100644 --- a/lib/types/ui/editor/IEditPage.ts +++ b/lib/types/ui/editor/IEditPage.ts @@ -8,13 +8,13 @@ import { IPort } from "./INodes"; export interface IEditPage extends TRenderFunctionResult { /** - * Function, which must return the current data. + * Function, which must return the current service-data. * * @author M.Karkowski * @return {boolean} * @memberof IEditPage */ - getData(): T; + getData(): any; /** * Function which must return true, if the Entered- @@ -36,7 +36,15 @@ export interface IEditPage extends TRenderFunctionResult { * @param options adapted Edge Options. */ getPorts(): { - inputs: IPort[]; - outputs: IPort[]; + inputs: { + id: string; + label: String; + type: IPort["type"]; + }[]; + outputs: { + id: string; + label: String; + type: IPort["type"]; + }[]; }; } diff --git a/lib/types/ui/editor/INetwork.ts b/lib/types/ui/editor/INetwork.ts index 3514a65..8a19807 100644 --- a/lib/types/ui/editor/INetwork.ts +++ b/lib/types/ui/editor/INetwork.ts @@ -2,4 +2,3 @@ * @author Martin Karkowski * @email m.karkowski@zema.de */ - diff --git a/lib/types/ui/helpers.interface.ts b/lib/types/ui/helpers.interface.ts index ac607e8..139dc12 100644 --- a/lib/types/ui/helpers.interface.ts +++ b/lib/types/ui/helpers.interface.ts @@ -3,16 +3,15 @@ * @email m.karkowski@zema.de */ +import * as go from "gojs"; import { ILogger } from "js-logger"; +import * as plotly from "plotly.js"; import { IJsonSchema } from "../IJSONSchema"; import { INopeDispatcher, INopeObservable } from "../nope/index"; -import * as nope from "../../index.browser"; -import * as plotly from "plotly.js"; -import * as go from "gojs"; import { + IMinProvidedDataSet, IPanel, IPossiblePanels, - IMinProvidedDataSet, IRadioMenuItemDescription, } from "./layout.interface"; @@ -48,9 +47,9 @@ export type TLibraries = { /** * The Nope Library. It contains only the Browser build. * - * @type {typeof nope} + * @type {*} */ - nope: typeof nope; + nope: any; /** * Built on top of d3.js and stack.gl, Plotly.js is a high-level, declarative charting library. plotly.js ships with over 40 chart types, including 3D charts, @@ -66,6 +65,13 @@ export type TLibraries = { * * Contains the original w2ui Library. https://w2ui.com/web/ */ + w2uiHelpers: { + w2popup: (...args) => any; + w2alert: (...args) => any; + w2confirm: (...args) => any; + w2prompt: (...args) => any; + w2utils: any; + }; w2ui: any; /** @@ -93,6 +99,15 @@ export type TLibraries = { * For more details checkout: https://gojs.net/latest/ */ gojs: typeof go; + + /** + * Ace is an embeddable code editor written in JavaScript. It matches the features and performance of native editors such as Sublime, Vim and TextMate. + * It can be easily embedded in any web page and JavaScript application. Ace is maintained as the primary editor for Cloud9 IDE and is the successor of + * the Mozilla Skywriter (Bespin) project. + * + * For more details checkout: https://ace.c9.io/#nav=about + */ + ace: typeof ace; }; export type TcreateLayoutOptions = { @@ -154,6 +169,29 @@ export interface IRenderData { * @memberof IDataInterface */ getData(key: string, defaultValue: T): Promise; + + /** + * Helper to test if the data exists. + * + * @author M.Karkowski + * @param {string} key The key, under which the data is expected. + * @return {Promise} + */ + hasData(key: string): Promise; + + /** + * Register Schema for data. If you try to store or pull data, the schema will be used to verify the data + * @param key The path of the data which should be observed + * @param schema The schema to store + * @returns {boolean} Flag to show the shema is stored or not. + */ + registerSchema(key: string, schema: IJsonSchema): boolean; + + /** + * Helper, to store the configuration. + * @returns success of the operation + */ + store(): Promise; }; connection: { /** @@ -162,7 +200,8 @@ export interface IRenderData { * @type {INopeObservable} * @memberof INoPEConnectService */ - sessionsConnected: INopeObservable; + readonly sessionsConnected: INopeObservable; + /** * Flag, to define, whether a external connection is required to * set the {@link INoPEConnectService.sessionsConnected} to true. @@ -170,7 +209,39 @@ export interface IRenderData { * @type {boolean} * @memberof INoPEConnectService */ - noExternalConnectionRequired: boolean; + readonly noExternalConnectionRequired: boolean; + + /** + * Hostname used in the browser. + * + * @author M.Karkowski + * @type {string} + */ + readonly hostname: string; + /** + * Returns the available layers. + * + * @author M.Karkowski + * @readonly + * @type {(Array)} + * @memberof NoPEService + */ + readonly layers: Array; + + /** + * Adds an communication Layer. + * + * @param {TSession} _session The Parameters for the Session. + * @memberof NoPEService + */ + addCommunicationLayer(_session: TSession): void; + + /** + * Disconnects the Layer. + * @param session The Session Parameters to use. + */ + removeCommunicationLayer(session: TSession): void; + /** * Helper Function to establish a connection to a backend. If called, to url is changed to the `pages/connect` and after a sucessfull connection, the original url is loaded **again**. * @@ -219,31 +290,6 @@ export interface IRenderData { } ) => void; }; - info: { - hostname: string; - /** - * Returns the available layers. - * - * @author M.Karkowski - * @readonly - * @type {(Array)} - * @memberof NoPEService - */ - readonly layers: Array; - /** - * Adds an communication Layer. - * - * @param {TSession} _session The Parameters for the Session. - * @memberof NoPEService - */ - addCommunicationLayer(_session: TSession): void; - - /** - * Disconnects the Layer. - * @param session The Session Parameters to use. - */ - removeCommunicationLayer(session: TSession): void; - }; url: { /** * Helper to get an Object from a schema. The Schema must be from type Object and is only allowed to have @@ -359,35 +405,3 @@ export interface IRenderData { dispatcher: INopeDispatcher; libraries: TLibraries; } - -/** Helper used, to render the instance details */ -// export type TRenderInstancePage = ( -// div: HTMLDivElement, -// options: TRenderData & { -// input: T; -// } -// ) => TRenderFunctionResult; - -// /** Helper to configurate a service */ -// export type TRenderConfigureServicePage = ( -// div: HTMLDivElement, -// options: TRenderData & { -// input: T; -// } -// ) => IEditPage; - -// /** UI to define an instance. */ -// export type TCreatorPage = ( -// div: HTMLDivElement, -// options: TRenderData & { -// createInstance: T; - -// } -// ) => IEditPage; - -// export type TRenderEditPage = ( -// div: HTMLDivElement, -// options: TRenderData & { -// input: T; -// } -// ) => IEditPage; diff --git a/lib/types/ui/index.ts b/lib/types/ui/index.ts index ca1eb09..c7f740d 100644 --- a/lib/types/ui/index.ts +++ b/lib/types/ui/index.ts @@ -7,7 +7,9 @@ import * as editor from "./editor/index"; import * as layout from "./layout.interface"; -export { TCreatorPage, TRenderInstancePage } from "./render.callbacks"; +export * from "./editor/index"; export { TRenderConfigureServicePage } from "./editor/index"; - +export * from "./helpers.interface"; +export * from "./layout.interface"; +export { TInstanceManagerPage, TRenderInstancePage } from "./render.callbacks"; export { editor, layout }; diff --git a/lib/types/ui/render.callbacks.ts b/lib/types/ui/render.callbacks.ts index 119d88e..66d92a8 100644 --- a/lib/types/ui/render.callbacks.ts +++ b/lib/types/ui/render.callbacks.ts @@ -3,25 +3,30 @@ * @email m.karkowski@zema.de */ -import { IGenericNopeModule } from "../nope"; +import { + IGenericNopeModule, + IInstanceCreationMsg, + INopeModule, + INopeModuleDescription, + TValidAsssignmentChecker, + ValidSelectorFunction, +} from "../nope"; import { IRenderData } from "./helpers.interface"; import { TRenderFunctionResult } from "./layout.interface"; /** Helper used, to render the instance details */ -export type TRenderInstancePage< - T extends IGenericNopeModule = IGenericNopeModule -> = ( +export type TRenderInstancePage = ( /** The DIV Element */ div: HTMLDivElement, /** The Provided Options used by the function to create the ui */ options: IRenderData & { /** The Instance to Render. */ - input: T; + input: T & IGenericNopeModule; } ) => TRenderFunctionResult; /** UI to define an instance. */ -export type TCreatorPage = ( +export type TInstanceManagerPage = ( /** The DIV Element */ div: HTMLDivElement, /** The Provided Options used by the function to create the ui */ @@ -29,6 +34,13 @@ export type TCreatorPage = ( /** Name of the Constructor */ ctorName: string; /** The callback to create the instance. */ - createInstance: (...args) => Promise; + createInstance: ( + description: Partial, + options?: { + selector?: ValidSelectorFunction; + assignmentValid?: TValidAsssignmentChecker; + } + ) => Promise; + instances: Array; } ) => void; diff --git a/lib/ui/helpers.browser.ts b/lib/ui/helpers.browser.ts new file mode 100644 index 0000000..e378121 --- /dev/null +++ b/lib/ui/helpers.browser.ts @@ -0,0 +1,43 @@ +import { stringifyWithFunctions } from "../helpers/jsonMethods"; +import { + IClassDescription, + IFunctionOptions, + IGenericNopeModule, + INopeModule, +} from "../types"; +import { TRenderInstancePage } from "../types/ui"; + +/** + * Converts the convertInstanceRenderPage to a string, which could be + * store or something similar. + * + * @export + * @template I The Instance Type + * @param {(TRenderInstancePage)} callback The callback to stringify. + * @return {string} The parsed String. + */ +export function convertInstanceRenderPage( + callback: TRenderInstancePage +): string { + return stringifyWithFunctions(callback); +} + +export interface IUiDefinition { + functions: { + [index: string]: { + ui: IFunctionOptions["ui"]; + id: string; + }; + }; + classes: { + [index: string]: { + ui?: IClassDescription["ui"]; + package: string; + class: string; + path: string; + methods: { + [index: string]: IFunctionOptions["ui"]; + }; + }; + }; +} diff --git a/lib/ui/helpers.nodejs.ts b/lib/ui/helpers.nodejs.ts new file mode 100644 index 0000000..aee9b07 --- /dev/null +++ b/lib/ui/helpers.nodejs.ts @@ -0,0 +1,158 @@ +/** + * @author Martin Karkowski + * @email m.karkowski@zema.de + */ + +import { ArgumentParser } from "argparse"; +import { join, resolve } from "path"; +import "reflect-metadata"; +import { createFile } from "../helpers/fileMethods"; +import { + getCentralDecoratedContainer, + IFunctionOptions, + stringifyWithFunctions, +} from "../index.browser"; +import { listFunctions, listPackages } from "../index.nodejs"; +import { IUiDefinition } from "./helpers.browser"; + +/** + * Helper Function to write a default configuration. + * + * @export + * @param {string} [dir='./modules'] + * @param {string} [filename=join(resolve(process.cwd()), 'config', 'assembly.json')] + */ +export async function writeUiFile( + options: { + dir: string; + filename: string; + } = { + dir: "./modules", + filename: join(resolve(process.cwd()), "config", "ui.json"), + } +) { + const uiFile: IUiDefinition = { + functions: {}, + classes: {}, + }; + + // This call makes shure, that every function is loaded + const functions = await listFunctions(options.dir); + const packages = await listPackages(options.dir); + + const CONTAINER = getCentralDecoratedContainer(); + + // Determine all Packages + for (const item of packages) { + // Iterate over the classes. + for (const cls of item.package.providedClasses) { + const itemToAdd: IUiDefinition["classes"][0] = { + // The Class Name + class: cls.description.name, + // The Package Name + package: item.package.nameOfPackage, + // The Path of he File. + path: item.path, + // The defined UI defintions. + ui: cls.ui, + // Define the Methods elements + methods: {}, + }; + + // The Service + const services = + CONTAINER.classes.get(cls.description.name)?._markedElements || []; + + for (const srv of services) { + if (srv.type === "method" && (srv.options as IFunctionOptions).ui) { + itemToAdd.methods[srv.accessor] = ( + srv.options as IFunctionOptions + ).ui; + } + } + + if ( + itemToAdd.ui || + Object.getOwnPropertyNames(itemToAdd.methods).length > 0 + ) { + // If an ui definition exists, we want + // to export it and store it in our file. + uiFile.classes[itemToAdd.class] = itemToAdd; + } + } + + // Iterate over the functions and provide their uis. + item.package.providedFunctions.map((funcs) => { + if (funcs.options.ui) { + // Store the UI definition in the config file. + uiFile.functions[funcs.options.id] = { + id: funcs.options.id, + ui: funcs.options.ui, + }; + } + }); + } + + for (const [id, data] of CONTAINER.methods.entries()) { + if (data.options.ui) { + uiFile.functions[id] = { + id, + ui: data.options.ui, + }; + } + } + + await createFile(options.filename, stringifyWithFunctions(uiFile, 4)); +} + +/** + * Helper to extract the Arguments for the `writeUiFile` function @see writeUiFile + * + * @author M.Karkowski + * @export + * @param additionalArguments Arguments added by the nope.cli + * @return {*} The Arguments + */ +export function readInwriteUiFileArgs( + additionalArguments: { + help: string; + type: "string" | "number"; + name: string | string; + defaultValue?: any; + }[] = [] +) { + const parser = new ArgumentParser({ + // version: "1.0.0", + add_help: true, + description: "Command Line interface, determines the available Packages.", + }); + + for (const arg of additionalArguments) { + parser.add_argument(arg.name, { + help: arg.help, + default: arg.defaultValue, + type: arg.type, + }); + } + + parser.add_argument("-f", "--file", { + help: "Filename for the configuration.", + default: "./config/ui.json", + type: "str", + dest: "filename", + }); + + parser.add_argument("-d", "--dir", { + help: "Directory to search for the ui definitions", + default: "./modules", + type: "str", + dest: "dir", + }); + + const args: { + dir: string; + filename: string; + } = parser.parse_args(); + + return args; +} diff --git a/lib/ui/helpers.ts b/lib/ui/helpers.ts deleted file mode 100644 index 481e9f1..0000000 --- a/lib/ui/helpers.ts +++ /dev/null @@ -1,23 +0,0 @@ -/** - * @author Martin Karkowski - * @email m.karkowski@zema.de - */ - -import { stringifyWithFunctions } from "../helpers/index.browser"; -import { IGenericNopeModule, INopeModule } from "../module"; -import { TRenderInstancePage } from "../types/ui"; - -/** - * Converts the convertInstanceRenderPage to a string, which could be - * store or something similar. - * - * @export - * @template I The Instance Type - * @param {(TRenderInstancePage)} callback The callback to stringify. - * @return {string} The parsed String. - */ -export function convertInstanceRenderPage( - callback: TRenderInstancePage -): string { - return stringifyWithFunctions(callback); -} diff --git a/lib/ui/index.browser.ts b/lib/ui/index.browser.ts new file mode 100644 index 0000000..379a50a --- /dev/null +++ b/lib/ui/index.browser.ts @@ -0,0 +1 @@ +export * from "./helpers.browser"; diff --git a/lib/ui/index.nodejs.ts b/lib/ui/index.nodejs.ts new file mode 100644 index 0000000..b337182 --- /dev/null +++ b/lib/ui/index.nodejs.ts @@ -0,0 +1,2 @@ +export * from "./helpers.nodejs"; +export * from "./index.browser"; diff --git a/package-lock.json b/package-lock.json index 799e7c9..3cc9946 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "nope", - "version": "1.1.00", + "version": "1.1.1", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "nope", - "version": "1.1.00", + "version": "1.1.1", "license": "MIT", "dependencies": { "argparse": "^2.0.1", @@ -40,6 +40,7 @@ "nope-js": "bin/nope" }, "devDependencies": { + "@types/ace": "^0.0.48", "@types/async": "^3.2.12", "@types/chai": "^4.3.0", "@types/lodash": "^4.14.178", @@ -413,6 +414,12 @@ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" }, + "node_modules/@types/ace": { + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/@types/ace/-/ace-0.0.48.tgz", + "integrity": "sha512-esV6hOWiDOZ6d7w5S11iLu6LQsPGe/9RPzhri7gNNLdrK1LFpO9/m7IZhQL6dat0JHICJ7l51zvHAiCgnPLLHA==", + "dev": true + }, "node_modules/@types/async": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.12.tgz", @@ -18556,6 +18563,12 @@ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.2.tgz", "integrity": "sha512-eZxlbI8GZscaGS7kkc/trHTT5xgrjH3/1n2JDwusC9iahPKWMRvRjJSAN5mCXviuTGQ/lHnhvv8Q1YTpnfz9gA==" }, + "@types/ace": { + "version": "0.0.48", + "resolved": "https://registry.npmjs.org/@types/ace/-/ace-0.0.48.tgz", + "integrity": "sha512-esV6hOWiDOZ6d7w5S11iLu6LQsPGe/9RPzhri7gNNLdrK1LFpO9/m7IZhQL6dat0JHICJ7l51zvHAiCgnPLLHA==", + "dev": true + }, "@types/async": { "version": "3.2.12", "resolved": "https://registry.npmjs.org/@types/async/-/async-3.2.12.tgz", diff --git a/package.json b/package.json index f8bf927..e254c12 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "nope", - "version": "1.1.1", + "version": "1.2.0", "description": "NoPE Runtime for Nodejs. For Browser-Support please use nope-browser", "files": [ "dist-nodejs/**/*", @@ -67,6 +67,7 @@ "websocket-stream": "^5.5.2" }, "devDependencies": { + "@types/ace": "^0.0.48", "@types/async": "^3.2.12", "@types/chai": "^4.3.0", "@types/lodash": "^4.14.178",