From 819a0b1a7273467e48f2032f37e09728100a55ae Mon Sep 17 00:00:00 2001 From: Daniel Kluge Date: Thu, 2 Nov 2023 18:29:04 +0100 Subject: [PATCH] Documentation should be done --- example/package-lock.json | 129 +++++++++++++++++++++ example/package.json | 4 + example/src/index.ts | 14 +++ example/src/modules/httpInterfaceServer.ts | 24 +++- example/src/modules/mqttConnector.ts | 52 ++++++++- example/tsconfig.json | 2 +- example/typedoc.json | 9 ++ lib/package-lock.json | 57 +++++++++ lib/package.json | 3 + lib/src/AIMCMapper.ts | 19 ++- lib/src/helper/fileImporter.ts | 4 + lib/src/helper/traverser.ts | 10 ++ lib/src/index.ts | 16 ++- lib/src/interfaceConnectionObject.ts | 50 +++++++- lib/src/multimessageBroker.ts | 13 +++ lib/src/parser/AIDParser.ts | 59 ++++++++++ lib/src/parser/AIMCParser.ts | 30 ++++- lib/src/server.ts | 19 ++- lib/src/types/aidConf.ts | 4 +- lib/src/types/requests.ts | 73 +++++++++++- lib/typedoc.json | 9 ++ 21 files changed, 571 insertions(+), 29 deletions(-) create mode 100644 example/typedoc.json create mode 100644 lib/typedoc.json diff --git a/example/package-lock.json b/example/package-lock.json index f8be6f3..846e8d1 100644 --- a/example/package-lock.json +++ b/example/package-lock.json @@ -15,6 +15,9 @@ }, "devDependencies": { "@types/express": "^4.17.20", + "typedoc": "^0.25.3", + "typedoc-plugin-extras": "^3.0.0", + "typedoc-plugin-rename-defaults": "^0.7.0", "typescript": "^5.2.2" } }, @@ -29,6 +32,9 @@ "devDependencies": { "@types/node": "^20.8.2", "@types/uuid": "^9.0.6", + "typedoc": "^0.25.3", + "typedoc-plugin-extras": "^3.0.0", + "typedoc-plugin-rename-defaults": "^0.7.0", "typescript": "^5.2.2" } }, @@ -172,6 +178,12 @@ "node": ">= 0.6" } }, + "node_modules/ansi-sequence-parser": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ansi-sequence-parser/-/ansi-sequence-parser-1.1.1.tgz", + "integrity": "sha512-vJXt3yiaUL4UU546s3rPXlsry/RnM730G1+HkpKE012AN0sx1eOrxSu95oKDIonskeLTijMgqWZ3uDEe3NFvyg==", + "dev": true + }, "node_modules/array-flatten": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", @@ -317,6 +329,18 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "dev": true, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/commist": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/commist/-/commist-3.2.0.tgz", @@ -837,6 +861,12 @@ "url": "https://opencollective.com/js-sdsl" } }, + "node_modules/jsonc-parser": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", + "integrity": "sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w==", + "dev": true + }, "node_modules/lru-cache": { "version": "7.18.3", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-7.18.3.tgz", @@ -845,6 +875,24 @@ "node": ">=12" } }, + "node_modules/lunr": { + "version": "2.3.9", + "resolved": "https://registry.npmjs.org/lunr/-/lunr-2.3.9.tgz", + "integrity": "sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow==", + "dev": true + }, + "node_modules/marked": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-4.3.0.tgz", + "integrity": "sha512-PRsaiG84bK+AMvxziE/lCFss8juXjNaWzVbN5tXAm4XjeaS9NAHhop+PjQxz2A9h8Q4M/xGmzP8vqNwy6JeK0A==", + "dev": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 12" + } + }, "node_modules/media-typer": { "version": "0.3.0", "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", @@ -1188,6 +1236,18 @@ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==" }, + "node_modules/shiki": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/shiki/-/shiki-0.14.5.tgz", + "integrity": "sha512-1gCAYOcmCFONmErGTrS1fjzJLA7MGZmKzrBNX7apqSwhyITJg2O102uFzXUeBxNnEkDA9vHIKLyeKq0V083vIw==", + "dev": true, + "dependencies": { + "ansi-sequence-parser": "^1.1.0", + "jsonc-parser": "^3.2.0", + "vscode-oniguruma": "^1.7.0", + "vscode-textmate": "^8.0.0" + } + }, "node_modules/side-channel": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz", @@ -1274,6 +1334,63 @@ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==" }, + "node_modules/typedoc": { + "version": "0.25.3", + "resolved": "https://registry.npmjs.org/typedoc/-/typedoc-0.25.3.tgz", + "integrity": "sha512-Ow8Bo7uY1Lwy7GTmphRIMEo6IOZ+yYUyrc8n5KXIZg1svpqhZSWgni2ZrDhe+wLosFS8yswowUzljTAV/3jmWw==", + "dev": true, + "dependencies": { + "lunr": "^2.3.9", + "marked": "^4.3.0", + "minimatch": "^9.0.3", + "shiki": "^0.14.1" + }, + "bin": { + "typedoc": "bin/typedoc" + }, + "engines": { + "node": ">= 16" + }, + "peerDependencies": { + "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" + } + }, + "node_modules/typedoc-plugin-extras": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-extras/-/typedoc-plugin-extras-3.0.0.tgz", + "integrity": "sha512-eiAe3qtm2WbV5owdncpt0zHZPqsNZH2mzNGILPd4zqrvEZie3Et9es4cpGZ+8lHO/SI0pVKwsAj7IuMxPNOdYg==", + "dev": true, + "peerDependencies": { + "typedoc": "0.25.x" + } + }, + "node_modules/typedoc-plugin-rename-defaults": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.0.tgz", + "integrity": "sha512-NudSQ1o/XLHNF9c4y7LzIZxfE9ltz09yCDklBPJpP5VMRvuBpYGIbQ0ZgmPz+EIV8vPx9Z/OyKwzp4HT2vDtfg==", + "dev": true, + "dependencies": { + "camelcase": "^8.0.0" + }, + "peerDependencies": { + "typedoc": "0.22.x || 0.23.x || 0.24.x || 0.25.x" + } + }, + "node_modules/typedoc/node_modules/minimatch": { + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", + "dev": true, + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -1321,6 +1438,18 @@ "node": ">= 0.8" } }, + "node_modules/vscode-oniguruma": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/vscode-oniguruma/-/vscode-oniguruma-1.7.0.tgz", + "integrity": "sha512-L9WMGRfrjOhgHSdOYgCt/yRMsXzLDJSL7BPrOZt73gU0iWO4mpqzqQzOz5srxqTvMBaR0XZTSrVWo4j55Rc6cA==", + "dev": true + }, + "node_modules/vscode-textmate": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/vscode-textmate/-/vscode-textmate-8.0.0.tgz", + "integrity": "sha512-AFbieoL7a5LMqcnOF04ji+rpXadgOXnZsxQr//r83kLPr7biP7am3g9zbaZIaBGwBRWeSvoMD4mgPdX3e4NWBg==", + "dev": true + }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", diff --git a/example/package.json b/example/package.json index 113fb71..5564a40 100644 --- a/example/package.json +++ b/example/package.json @@ -5,6 +5,7 @@ "main": "dist/index.js", "scripts": { "build": "npx tsc", + "docs": "npx typedoc", "start": "node dist/index.js", "test": "echo \"Error: no test specified\" && exit 1" }, @@ -31,6 +32,9 @@ "license": "ISC", "devDependencies": { "@types/express": "^4.17.20", + "typedoc": "^0.25.3", + "typedoc-plugin-extras": "^3.0.0", + "typedoc-plugin-rename-defaults": "^0.7.0", "typescript": "^5.2.2" }, "dependencies": { diff --git a/example/src/index.ts b/example/src/index.ts index e073fd9..0547cf6 100644 --- a/example/src/index.ts +++ b/example/src/index.ts @@ -3,6 +3,20 @@ import { MultiMessageBroker, FileImporter } from "aas-multimessagebroker"; import HTTPInterfaceServer from "./modules/httpInterfaceServer"; import MQTTConnector from "./modules/mqttConnector"; +/** + * This is an example of how to use the MultiMessageBroker. + * It creates a sample interface and connector and registers them to the broker, then starts it. + * + * @remarks + * In this package a {@link HTTPInterfaceServer} is used to serve the Asset Administration Shell API interface. + * To connect to the asset a {@link MQTTConnector} was created. + * The asset is a Python script located outside of this repository which sends the current timestamp as two parameters. + * The AAS-Package is defined in the file ../owntest.json. + * It was created using the {@link https://github.com/admin-shell-io/aasx-package-explorer|aasx-package-explorer}. + * + * @packageDocumentation + */ + // First we need to import the AAS Package // It was created using the aasx-package-explorer (https://github.com/admin-shell-io/aasx-package-explorer) const aas = FileImporter.readAASByPath("../owntest.json"); diff --git a/example/src/modules/httpInterfaceServer.ts b/example/src/modules/httpInterfaceServer.ts index 4c0d968..3fa2fec 100644 --- a/example/src/modules/httpInterfaceServer.ts +++ b/example/src/modules/httpInterfaceServer.ts @@ -18,8 +18,20 @@ export type Config = { * @see {@link aas-multimessagebroker#AbstractInterfaceServer|AbstractInterfaceServer} */ export default class HTTPInterfaceServer extends AbstractInterfaceServer { - public static serverInterfaceName: string = "HTTPInterfaceServer"; - public static supportsSubscriptions: boolean = false; // TODO, longpolling? + /** + * Server name + * @override + * @readonly + * @alpha + */ + public static readonly serverInterfaceName: string = "HTTPInterfaceServer"; + /** + * Whether the server supports subscriptions + * @override + * @readonly + * @alpha + */ + public static readonly supportsSubscriptions: boolean = false; // TODO, longpolling? /** * This is the {@link express#Express|express app}. @@ -39,6 +51,8 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer * * @remarks * This is called before the server is started. + * @override + * @public */ public prepare(): void { this.app.use(express.json()); @@ -47,6 +61,8 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer /** * This should start the server. + * @override + * @public */ public run(): void { this.server = this.app.listen(this.config.bindPort, this.config.bindAddress, () => { @@ -56,6 +72,8 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer /** * This should stop the server. + * @override + * @public */ public stop(): void { if (this.server && this.server.close) this.server.close(); @@ -63,6 +81,8 @@ export default class HTTPInterfaceServer extends AbstractInterfaceServer /** * This should call notify all observers + * @override + * @public */ public notify(event: any): void { this.observers.forEach(observer => { diff --git a/example/src/modules/mqttConnector.ts b/example/src/modules/mqttConnector.ts index 825c8b4..6b14d9c 100644 --- a/example/src/modules/mqttConnector.ts +++ b/example/src/modules/mqttConnector.ts @@ -11,9 +11,35 @@ import type { AASCoreTypes } from "aas-multimessagebroker"; * @see {@link aas-multimessagebroker#AbstractConnectionObject|AbstractConnectionObject} */ export default class MQTTConnector extends AbstractConnectionObject { + /** + * A name for your connector. Not used yet. + * @override + * @public + * @readonly + * @alpha + */ public static readonly connectorName: string = "MQTT Connector"; + /** + * The protocol(s) your connector supports. Absolutely critical so the broker knows which connector to use. + * @override + * @public + */ public static readonly uriProtocol: string[] = ["mqtt", "mqtts"]; + /** + * The type of connection your connector uses. Either "ON_DEMAND" or "PERMANENT". + * @override + * @public + * @readonly + * @alpha + */ public static readonly connectionType: "ON_DEMAND" | "PERMANENT" = "PERMANENT"; + /** + * Whether your connector supports subscriptions. + * @override + * @public + * @readonly + * @alpha + */ public static readonly supportsSubscriptions: boolean = true; /** @@ -26,13 +52,15 @@ export default class MQTTConnector extends AbstractConnectionObject = {}; - /** * This should connect the Connector to the asset. * - * @remarks For async connections like HTTP you can just return true and do the connection on demand. + * @remarks + * For async connections like HTTP you can just return true and do the connection on demand. * * @returns Whether the connection was successful. + * @override + * @public */ public connect(): boolean { if (!this.client) this.client = mqtt.connect(this.endpointMetadata.base, this.connectionParameter); @@ -51,6 +79,8 @@ export default class MQTTConnector extends AbstractConnectionObject void): boolean { const cc = this.mapper.get(prop); @@ -130,6 +166,9 @@ export default class MQTTConnector extends AbstractConnectionObject): any { // TODO @@ -144,6 +183,9 @@ export default class MQTTConnector extends AbstractConnectionObject): string | null { // TODO @@ -157,6 +199,9 @@ export default class MQTTConnector extends AbstractConnectionObject void): boolean { // TODO @@ -168,6 +213,9 @@ export default class MQTTConnector extends AbstractConnectionObject=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -129,6 +143,27 @@ "typescript": "4.6.x || 4.7.x || 4.8.x || 4.9.x || 5.0.x || 5.1.x || 5.2.x" } }, + "node_modules/typedoc-plugin-extras": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-extras/-/typedoc-plugin-extras-3.0.0.tgz", + "integrity": "sha512-eiAe3qtm2WbV5owdncpt0zHZPqsNZH2mzNGILPd4zqrvEZie3Et9es4cpGZ+8lHO/SI0pVKwsAj7IuMxPNOdYg==", + "dev": true, + "peerDependencies": { + "typedoc": "0.25.x" + } + }, + "node_modules/typedoc-plugin-rename-defaults": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.0.tgz", + "integrity": "sha512-NudSQ1o/XLHNF9c4y7LzIZxfE9ltz09yCDklBPJpP5VMRvuBpYGIbQ0ZgmPz+EIV8vPx9Z/OyKwzp4HT2vDtfg==", + "dev": true, + "dependencies": { + "camelcase": "^8.0.0" + }, + "peerDependencies": { + "typedoc": "0.22.x || 0.23.x || 0.24.x || 0.25.x" + } + }, "node_modules/typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", @@ -206,6 +241,12 @@ "balanced-match": "^1.0.0" } }, + "camelcase": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-8.0.0.tgz", + "integrity": "sha512-8WB3Jcas3swSvjIeA2yvCJ+Miyz5l1ZmB6HFb9R1317dt9LCQoswg/BGrmAmkWVEszSrrg4RwmO46qIm2OEnSA==", + "dev": true + }, "jsonc-parser": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/jsonc-parser/-/jsonc-parser-3.2.0.tgz", @@ -257,6 +298,22 @@ "shiki": "^0.14.1" } }, + "typedoc-plugin-extras": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-extras/-/typedoc-plugin-extras-3.0.0.tgz", + "integrity": "sha512-eiAe3qtm2WbV5owdncpt0zHZPqsNZH2mzNGILPd4zqrvEZie3Et9es4cpGZ+8lHO/SI0pVKwsAj7IuMxPNOdYg==", + "dev": true, + "requires": {} + }, + "typedoc-plugin-rename-defaults": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/typedoc-plugin-rename-defaults/-/typedoc-plugin-rename-defaults-0.7.0.tgz", + "integrity": "sha512-NudSQ1o/XLHNF9c4y7LzIZxfE9ltz09yCDklBPJpP5VMRvuBpYGIbQ0ZgmPz+EIV8vPx9Z/OyKwzp4HT2vDtfg==", + "dev": true, + "requires": { + "camelcase": "^8.0.0" + } + }, "typescript": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.2.2.tgz", diff --git a/lib/package.json b/lib/package.json index 32a9fbe..7a33670 100644 --- a/lib/package.json +++ b/lib/package.json @@ -5,6 +5,7 @@ "main": "dist/index.js", "scripts": { "build": "npx tsc", + "docs": "npx typedoc", "test": "echo \"Error: no test specified\" && exit 1" }, "keywords": [ @@ -33,6 +34,8 @@ "@types/node": "^20.8.2", "@types/uuid": "^9.0.6", "typedoc": "^0.25.3", + "typedoc-plugin-extras": "^3.0.0", + "typedoc-plugin-rename-defaults": "^0.7.0", "typescript": "^5.2.2" }, "dependencies": { diff --git a/lib/src/AIMCMapper.ts b/lib/src/AIMCMapper.ts index 62e572c..3c9430d 100644 --- a/lib/src/AIMCMapper.ts +++ b/lib/src/AIMCMapper.ts @@ -1,25 +1,27 @@ -import { types } from "@aas-core-works/aas-core3.0-typescript"; -import { ConnectionConfiguration, AIMCMap } from "./types/aimcConf"; +import type { types } from "@aas-core-works/aas-core3.0-typescript"; +import type { ConnectionConfiguration, AIMCMap } from "./types/aimcConf"; import AIMCParser from "./parser/AIMCParser"; import Traverser from "./helper/traverser"; import AIDParser from "./parser/AIDParser"; -import { SubmodelElementCollection } from "@aas-core-works/aas-core3.0-typescript/dist/types/types"; /** * The AIMC Mapper. * @remarks - * This class is used to map properties t endpoints. + * This class is used to map properties to endpoints. + * @public */ export default class AIMCMapper { /** * The map. + * @private */ private map: AIMCMap = new Map(); /** * Creates the mapper. * @param env The AAS Environment + * @public */ public constructor(private readonly env: types.Environment) { this.generate(); @@ -27,6 +29,7 @@ export default class AIMCMapper { /** * Generates the map from the AAS Environment. + * @private */ private generate(): void { const aimc = AIMCParser.parse(this.env); @@ -48,11 +51,11 @@ export default class AIMCMapper { let {first, second} = resolved; - let parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as SubmodelElementCollection); + let parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as types.SubmodelElementCollection); if (parsedPropConf === null) { // maybe the property is in the first element [first, second] = [second, first]; - parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as SubmodelElementCollection); + parsedPropConf = AIDParser.parseInterfaceMetadataProperty(first as types.SubmodelElementCollection); } if (parsedPropConf === null) continue; @@ -69,6 +72,7 @@ export default class AIMCMapper { /** * * @returns The complete map + * @public */ public getMap(): AIMCMap { return this.map; @@ -78,6 +82,7 @@ export default class AIMCMapper { * Get endpoint for a specific Element * @param element Element * @returns Endpoint description or undefined if not found + * @public */ public get(element: types.Class): ConnectionConfiguration | undefined { return this.map.get(element); @@ -88,6 +93,7 @@ export default class AIMCMapper { * Can return multiple as idShorts are not necessarily unique * @param idShort idShort of the element * @returns Endpoints descriptions of elements with that idShort + * @public */ public getByIdShort(idShort: string): ConnectionConfiguration[] { const result = []; @@ -101,6 +107,7 @@ export default class AIMCMapper { * Get an element by its endpoint * @param path Absolute endpoint path * @returns Elements that use that path + * @public */ public reverseGet(path: string): types.Class[] { const result = []; diff --git a/lib/src/helper/fileImporter.ts b/lib/src/helper/fileImporter.ts index 1727cfb..25b10a1 100644 --- a/lib/src/helper/fileImporter.ts +++ b/lib/src/helper/fileImporter.ts @@ -4,6 +4,7 @@ import { types, jsonization } from "@aas-core-works/aas-core3.0-typescript"; /** * Helper class to import AAS-Environments from files. + * @public */ export default class FileImporter { @@ -13,6 +14,7 @@ export default class FileImporter { * @returns Environment * @throws Error if file is not a JSON file * @throws Any IO error on file read operation + * @public */ public static readAASByPath(path: string): types.Environment { if (!path.endsWith(".json")) throw new Error("File must be a JSON file"); @@ -30,6 +32,7 @@ export default class FileImporter { * Import all AAS-Environments from a directory. * @param path Directory path * @returns Environments + * @public */ public static readAllAASFromPath(path: string): types.Environment[] { @@ -47,6 +50,7 @@ export default class FileImporter { * Get all JSON files from a directory. * @param aasPath Directory path * @returns Paths of the JSON files + * @private */ private static getAllAASFilePaths(aasPath: string): string[] { const files = readdirSync(aasPath); diff --git a/lib/src/helper/traverser.ts b/lib/src/helper/traverser.ts index 0ffbf6f..3f9c403 100644 --- a/lib/src/helper/traverser.ts +++ b/lib/src/helper/traverser.ts @@ -10,6 +10,7 @@ const GLOBALLY_IDENTIFIABLES = [types.KeyTypes.GlobalReference, types.KeyTypes.A /** * Helper to traverse the AAS-Environment. + * @public */ export default class Traverser { @@ -18,6 +19,7 @@ export default class Traverser { * @param environment Environment to search in * @param id ID * @returns AAS or null if not found + * @public */ public static findAASById(environment: types.Environment, id: string): types.AssetAdministrationShell | null { if (environment.assetAdministrationShells === null) return null; @@ -30,6 +32,7 @@ export default class Traverser { * @param environment Environment to search in * @param id ID * @returns Submodel or null if not found + * @public */ public static findSMById(environment: types.Environment, id: string): types.Submodel | null { if (environment.submodels === null) return null; @@ -42,6 +45,7 @@ export default class Traverser { * @param environment Environment to search in * @param id idShort * @returns Submodel or null if not found + * @public */ public static findSMByIdShort(environment: types.Environment, id: string): types.Submodel | null { if (environment.submodels === null) return null; @@ -54,6 +58,7 @@ export default class Traverser { * @param env Environment to search in * @param ref Reference * @returns Element or null if not found + * @public */ public static resolveReference(env: types.Environment, ref: types.Reference): types.Class | null { if (ref.type === types.ReferenceTypes.ExternalReference) return null; // Not implemented @@ -77,6 +82,7 @@ export default class Traverser { * @param env Environment to search in * @param relationship Relationship element * @returns Resolved relationship element or null if not found + * @public */ public static resolveRelationship(env: types.Environment, relationship: RelationshipElement): ResolvedRelationshipElement | null { const first = Traverser.resolveReference(env, relationship.first); @@ -91,6 +97,7 @@ export default class Traverser { * @param start Start element * @param idShorts Array of idShorts to traverse by * @returns Target element at the end of the path or null if not found + * @public */ public static traverseByShortIds(start: types.Class, idShorts: string[]): types.Class | null { let current: types.Class | null = start; @@ -109,6 +116,7 @@ export default class Traverser { * @param submodelOrIdShort Submodel element or Submodel idShort * @param idShorts idShorts to traverse by * @returns Target element at the end of the path or null if not found + * @public */ public static getElementByIdPath(env: types.Environment, submodelOrIdShort: string | types.Submodel, idShorts: string[]): types.Class | null { const sm = typeof submodelOrIdShort === "string" ? Traverser.findSMByIdShort(env, submodelOrIdShort) : submodelOrIdShort; @@ -121,6 +129,7 @@ export default class Traverser { * @param start Start element * @param checkFunction Function to find the element. First element which evaluates to true using this function will be returned. * @returns Element or null if not found + * @public */ public static findElement(start: types.Class, checkFunction: (element: types.Class) => boolean): types.Class | null { for (const element of start.descend()) { @@ -135,6 +144,7 @@ export default class Traverser { * @param start Start element * @param idShort idShort to search for * @returns Child element or null if not found + * @public */ public static findChildByIdShort(start: types.Class, idShort: string): types.Class | null { for (const child of start.descendOnce()) { diff --git a/lib/src/index.ts b/lib/src/index.ts index 4195b46..57cf9b2 100644 --- a/lib/src/index.ts +++ b/lib/src/index.ts @@ -7,4 +7,18 @@ export * as Types from "./types"; export { Traverser, FileImporter } from "./helper"; export { AIDParser, AIMCParser } from "./parser"; -export { jsonization as AASCoreJsonization, types as AASCoreTypes } from "@aas-core-works/aas-core3.0-typescript"; \ No newline at end of file +export { jsonization as AASCoreJsonization, types as AASCoreTypes } from "@aas-core-works/aas-core3.0-typescript"; + +/** + * A modular library for a Multimessagebroker for Industry 4.0 Applications. + * It can be used to create your own modules and run the broker. + * + * @remarks + * This is the library which defines {@link MultiMessageBroker|the logic} used to create {@link AbstractInterfaceServer|server interfaces} to the user (north-bound) following + * the Asset Administration Shell API specification and {@link AbstractConnectionObject|interface connectors} to the asset (south-bound) which + * can be arbitrary but defined in the AssetInterfacesDescription Submodel of the AAS. + * Mappings from the AssetInterfacesMappingConfiguration Submodel of the AAS are used to map specific elements of the AAS + * to dynamic data (using endpoints) of the asset. + * + * @packageDocumentation + */ \ No newline at end of file diff --git a/lib/src/interfaceConnectionObject.ts b/lib/src/interfaceConnectionObject.ts index fb880cb..435f7b6 100644 --- a/lib/src/interfaceConnectionObject.ts +++ b/lib/src/interfaceConnectionObject.ts @@ -10,42 +10,55 @@ export type OnEventCallback = (response: any) => void /** * Abstract class for an connector to an asset. * This should be used as base class for your own connectors. + * @public */ export default abstract class InterfaceConnectionObject { /** * A name for your connector. - * @remarks - * Currently not used. + * @public + * @virtual + * @readonly + * @alpha */ public static readonly connectorName: string; /** * Which protocols are supported by your connector. * This is really important later so the AAS can decide which connector to use! + * @public + * @virtual + * @readonly */ public static readonly uriProtocol: string[]|string; /** * The type of connection your connector uses. - * @remarks - * Currently not used. + * @public + * @virtual + * @readonly + * @alpha */ public static readonly connectionType: ConnectionType; /** * Whether your connector supports subscriptions. - * @remarks - * Currently not used. + * @public + * @virtual + * @readonly + * @alpha */ public static readonly supportsSubscriptions: boolean; /** * A store for all observers and their callbacks. + * @sealed */ protected readonly observerStore: Record void)[]> = {}; /** * A store for all event subscriptions and their callbacks. + * @sealed */ protected readonly eventSubStore: Record void)[]> = {}; /** * A store for all async action handles and their results. + * @sealed */ protected readonly asyncActionStateStore: Record = {}; @@ -55,6 +68,8 @@ export default abstract class InterfaceConnectionObject { * @param endpointMetadata {@link EndpointMetadata} * @param mapper {@link AIMCMapper} * @param onConnectorEvent Callback when an event is received. + * @public + * @sealed */ public constructor( protected readonly connectionParameter: ConfigInterface, @@ -65,11 +80,15 @@ export default abstract class InterfaceConnectionObject { /** * This should connect the Connector to the asset. * @returns Whether the connection was successful. + * @public + * @virtual */ public abstract connect(): boolean; /** * This should disconnect the Connector from the asset (if it even is connected). + * @public + * @virtual */ public abstract disconnect(): void; @@ -77,6 +96,8 @@ export default abstract class InterfaceConnectionObject { * Read a property value from the asset. * @param prop Property * @returns Value of property casted to the type it says it should be. + * @public + * @virtual */ public abstract readProperty(prop: types.Property): void; @@ -84,6 +105,8 @@ export default abstract class InterfaceConnectionObject { * Write a property value to the asset. * @param prop Property * @param value Value to write. + * @public + * @virtual */ public abstract writeProperty(prop: types.Property, value: any): void; @@ -92,6 +115,8 @@ export default abstract class InterfaceConnectionObject { * @param prop Property * @param callback Callback to call when the property changes. * @returns Whether the creation of an observer was successful. + * @public + * @virtual */ public abstract observeProperty(prop: types.Property, callback: (value: any) => void): boolean; @@ -100,6 +125,8 @@ export default abstract class InterfaceConnectionObject { * @param action Action * @param args Arguments * @returns Return value of the action. + * @public + * @virtual */ public abstract callActionSync(action: types.Operation, args: Record): any; @@ -108,6 +135,8 @@ export default abstract class InterfaceConnectionObject { * @param action Action * @param args Arguments * @returns Handle for the async action. + * @public + * @virtual */ public abstract callActionAsync(action: types.Operation, args: Record): string | null; @@ -115,6 +144,8 @@ export default abstract class InterfaceConnectionObject { * Read the state of an async action. * @param handle Handle of the async action. * @returns Whether the async action is finished. + * @public + * @virtual */ public readAsyncActionState(handle: string): boolean { return this.asyncActionStateStore[handle].finished; @@ -124,6 +155,8 @@ export default abstract class InterfaceConnectionObject { * Read the result of an async action. * @param handle Handle of the async action. * @returns Result of the async action. + * @public + * @virtual */ public readAsyncActionResponse(handle: string): any { return this.asyncActionStateStore[handle].result; @@ -134,18 +167,23 @@ export default abstract class InterfaceConnectionObject { * @param event Event * @param callback Callback to call when the event occurs. * @returns Whether the subscription was successful. + * @public + * @virtual */ public abstract subscribeEvent(event: types.BasicEventElement, callback: (event: types.BasicEventElement) => void): boolean; /** * Unsubscribe from an event. * @param event Event + * @public + * @virtual */ public abstract unsubscribeEvent(event: types.BasicEventElement): void; /** * Generate a handle for an async action. * @returns Handle + * @sealed */ protected generateAsyncHandle() { const handle = v4(); diff --git a/lib/src/multimessageBroker.ts b/lib/src/multimessageBroker.ts index 98327e2..7f30540 100644 --- a/lib/src/multimessageBroker.ts +++ b/lib/src/multimessageBroker.ts @@ -32,28 +32,40 @@ type InterfaceConnectionEntry = { * @remarks * Here are all Interface Servers and Connectors are created and managed. * Also every request is handled here. + * @public */ export default class MultiMessageBroker { + /** + * MMB singleton instance + * @private + */ private static instance: MultiMessageBroker|null = null; /** * Whether the broker is prepared. + * @private */ private prepared: boolean = false; /** * All registered AASs. + * @private */ private aasRegistrations: AASRegistrationPrepared[] = []; /** * All registered Interface Connectors. + * @private */ private interfaceConnections: InterfaceConnectionEntry[] = []; + /** + * @private + */ private constructor() {} /** * Get the singleton instance of the broker. + * @public */ public static getInstance(): MultiMessageBroker { if (this.instance === null) this.instance = new MultiMessageBroker(); @@ -215,6 +227,7 @@ export default class MultiMessageBroker { /** * Callback on a connector event. * @param response + * @alpha */ private onConnectorEvent(response: any) { for (const aas of this.aasRegistrations) { diff --git a/lib/src/parser/AIDParser.ts b/lib/src/parser/AIDParser.ts index 5b8a991..0a5d525 100644 --- a/lib/src/parser/AIDParser.ts +++ b/lib/src/parser/AIDParser.ts @@ -3,8 +3,18 @@ import type { AssetInterfacesDescription, EndpointMetadata, InterfaceDescription import { AvailableEndpoint, endpointAvailable } from "../types/common"; import Traverser from "../helper/traverser"; +/** + * Class for static methods to parse the AssetInterfacesDescription Submodel + * @public + */ export default class AIDParser { + /** + * Full parsing of the AID Submodel. + * @param env AAS Environment + * @returns Parsed AID or null if it's not parsable + * @public + */ public static parse(env: aasCore.types.Environment): AssetInterfacesDescription | null { const sm = Traverser.findSMByIdShort(env, "AssetInterfacesDescription"); if (sm === null || sm.submodelElements === null) return null; @@ -27,6 +37,12 @@ export default class AIDParser { return parsed; } + /** + * Parses one entry of an SubmodelElementList in die AID, containing one endpoint. + * @param entry AID entry for one endpoint + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Description for one interface or null if not parsable + */ private static parseAIDEntry(entry: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceDescription | null { const title = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "title"); const titleString = title !== null && aasCore.types.isProperty(title) && title.value ? title.value : ""; @@ -47,6 +63,12 @@ export default class AIDParser { } + /** + * Parse EndpointMetaData + * @param endpoint EndpointMetaData SubmodelElementCollection + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed EndpointMetaData or null if not parsable + */ public static parseEndpointMetaData(endpoint: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): EndpointMetadata | null { if (!endpoint.value || endpoint.idShort?.toLocaleLowerCase() !== "endpointmetadata") return null; @@ -64,6 +86,16 @@ export default class AIDParser { return parsed; } + /** + * Parse an InterfaceMetaData SubmodelElementCollection + * + * @remarks + * Parses all properties, actions and events. + * + * @param interfaceMeta Interface MetaData SubmodelElementCollection + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed InterfaceMetaData or null if not parsable + */ public static parseInterfaceMetaData(interfaceMeta: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceMetadata | null { if (!interfaceMeta.value || interfaceMeta.idShort?.toLocaleLowerCase() !== "interfacemetadata") return null; @@ -94,6 +126,13 @@ export default class AIDParser { return parsed as InterfaceMetadata; } + /** + * Parse a single Property InterfaceMetadata + * @param prop SubmodelElementCollection of one Property + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed Property InterfaceMetadata or null if not parsable + * @beta + */ public static parseInterfaceMetadataProperty(prop: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceProperty | null { if (!aasCore.types.isSubmodelElementCollection(prop) || !prop.value) return null; @@ -115,6 +154,12 @@ export default class AIDParser { return { ...parsed, forms: parsedForm } as InterfaceProperty; } + /** + * Parse the forms of a single Property InterfaceMetadata + * @param form Form SubmodelElementCollection of one Property + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed Form or null if not parsable + */ private static parseInterfaceMetadataPropertyForm(form: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfacePropertyForm | null { if (!form.value) return null; @@ -132,11 +177,25 @@ export default class AIDParser { return parsed as InterfacePropertyForm; } + /** + * Parse a single Action InterfaceMetadata + * @param prop SubmodelElementCollection of one Action + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed Action InterfaceMetadata or null if not parsable + * @alpha + */ public static parseInterfaceMetadataAction(action: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceAction | null { // TODO return null; } + /** + * Parse a single Event InterfaceMetadata + * @param prop SubmodelElementCollection of one Event + * @param endpointProtocol Protocol used in the endpoint, so additional properties can be parsed + * @returns Parsed Event InterfaceMetadata or null if not parsable + * @alpha + */ public static parseInterfaceMetadataEvent(event: aasCore.types.SubmodelElementCollection, endpointProtocol?: AvailableEndpoint): InterfaceEvent | null { // TODO return null; diff --git a/lib/src/parser/AIMCParser.ts b/lib/src/parser/AIMCParser.ts index fd9066a..76e7c2a 100644 --- a/lib/src/parser/AIMCParser.ts +++ b/lib/src/parser/AIMCParser.ts @@ -3,8 +3,18 @@ import Traverser from "../helper/traverser"; import { AssetInterfacesMappingConfiguration, MappingConfEntry, MappingConfiguration } from "../types/aimcConf"; import { endpointAvailable, ResolvedRelationshipElement } from "../types/common"; +/** + * Class for static methods to parse the AssetInterfacesMappingConfiguration Submodel + * @public + */ export default class AIMCParser { + /** + * Parse the complete AIMC Submodel + * @param env Environment + * @returns Parsed AIMC or null if not parsable + * @public + */ public static parse(env: aasCore.types.Environment): AssetInterfacesMappingConfiguration | null { const sm = Traverser.findSMByIdShort(env, "AssetInterfacesMappingConfiguration"); if (sm === null || sm.submodelElements === null) return null; @@ -27,6 +37,14 @@ export default class AIMCParser { return parsed; } + /** + * Parse one entry of the AIMC Submodel + * @remarks + * The Environment is necessary so references can be resolved further down the line. + * @param entry Parse one entry of the AIMC Submodel + * @param environment The complete environment + * @returns Parsed Endpoint and MappingConfiguration or null if not parsable + */ public static parseAIMCEntry(entry: aasCore.types.SubmodelElementCollection, environment: aasCore.types.Environment): MappingConfEntry | null { const ep = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "endpointmetadatareference"); const mc = Traverser.findElement(entry, element => (element as any).idShort?.toLocaleLowerCase() === "mappingconfiguration"); @@ -49,6 +67,14 @@ export default class AIMCParser { }; } + /** + * Parse MappingConfiguration SubmodelElementCollection + * @remarks + * The Environment is necessary so references can be resolved further down the line. + * @param conf MappingConfiguration SubmodelElementCollection + * @param env Environment + * @returns Parsed MappingConfiguration or null if not parsable + */ public static parseMappingConfiguration(conf: aasCore.types.SubmodelElementCollection, env: aasCore.types.Environment): MappingConfiguration | null { if (!conf.value) return null; @@ -68,10 +94,6 @@ export default class AIMCParser { for (const ssm of sourceSinkMappings.overValueOrEmpty()) { if (!aasCore.types.isRelationshipElement(ssm)) continue; - // No resolve, to allow for mapping - //const resolved = Traverser.resolveRelationship(env, ssm); - //if (resolved === null) continue; - parsed.SourceSinkMappings.push(ssm as ResolvedRelationshipElement); } diff --git a/lib/src/server.ts b/lib/src/server.ts index 63466d6..17d4c45 100644 --- a/lib/src/server.ts +++ b/lib/src/server.ts @@ -6,18 +6,25 @@ import type { OnRequestCallback } from "./types/requests"; * This should be used as base class for your own interface servers! * * @typeParam ConfigInterface - The config interface for your interface server. + * @public */ export default abstract class AASInterfaceServer { /** * A name for your interface server. * @remarks * Currently unused + * @public + * @readonly + * @virtual */ public static readonly serverInterfaceName: string; /** * Whether your interface server supports subscriptions. * @remarks * Currently unused + * @public + * @readonly + * @virtual */ public static readonly supportsSubscriptions: boolean; @@ -26,8 +33,10 @@ export default abstract class AASInterfaceServer { * @param config Interface server config * @param aas AAS Environment for the server * @param onRequestCallback Callback when a request is received and parsed + * @public + * @sealed */ - constructor( + public constructor( protected readonly config: ConfigInterface, protected readonly aas: types.Environment, protected readonly onRequestCallback: OnRequestCallback) {} @@ -36,19 +45,27 @@ export default abstract class AASInterfaceServer { * Prepare the interface server. * @remarks * Here you can create routes, listeners, callbacks,... + * @virtual + * @public */ public abstract prepare(): void; /** * Run the interface server. + * @public + * @virtual */ public abstract run(): void; /** * Stop the interface server. + * @public + * @virtual */ public abstract stop(): void; /** * Notify observers/subscribers about an event. * @param event Event to notify the interface server about + * @public + * @virtual */ public abstract notify(event: any): void; diff --git a/lib/src/types/aidConf.ts b/lib/src/types/aidConf.ts index dd38a0b..e5309c5 100644 --- a/lib/src/types/aidConf.ts +++ b/lib/src/types/aidConf.ts @@ -1,4 +1,4 @@ -import { AvailableEndpoint } from "./common"; +import type { AvailableEndpoint } from "./common"; export type AssetInterfacesDescription = { [key in AvailableEndpoint]?: InterfaceDescription[]; @@ -77,10 +77,12 @@ type InterfacePropertyFormMQTT = InterfacePropertyFormBase & { qos?: 0 | 1 | 2; } +/** @alpha */ export type InterfaceAction = { // TODO } +/** @alpha */ export type InterfaceEvent = { // TODO } \ No newline at end of file diff --git a/lib/src/types/requests.ts b/lib/src/types/requests.ts index 0110ad5..e32137a 100644 --- a/lib/src/types/requests.ts +++ b/lib/src/types/requests.ts @@ -1,16 +1,21 @@ import type { types } from "@aas-core-works/aas-core3.0-typescript"; -export type Request = GetRequest | WriteRequest | ObserveRequest | CallRequest | CallAsyncRequest | AsyncStateRequest | AsyncResultRequest | SubscribeRequest | UnsubscribeRequest; - -export type OnRequestCallback = (request: Request) => any & GetRequestCallback & WriteRequestCallback & ObserveRequestCallback & CallRequestCallback & CallAsyncRequestCallback & AsyncStateRequestCallback & AsyncResultRequestCallback & SubscribeRequestCallback & UnsubscribeRequestCallback; - +/** + * Read Property Request + */ type GetRequest = { type: "READ"; target: types.Property; } +/** + * Read Property Request Callback + */ type GetRequestCallback = (request: GetRequest) => any; +/** + * Write Property Request + */ type WriteRequest = { type: "WRITE"; target: types.Property; @@ -19,8 +24,14 @@ type WriteRequest = { } } +/** + * Wrote Property Request Callback + */ type WriteRequestCallback = (request: WriteRequest) => void; +/** + * Observe Property Request + */ type ObserveRequest = { type: "OBSERVE"; target: types.Property; @@ -29,8 +40,14 @@ type ObserveRequest = { } } +/** + * Observe Property Request Callback + */ type ObserveRequestCallback = (request: ObserveRequest) => boolean; +/** + * Subscribe Event Request + */ type SubscribeRequest = { type: "SUBSCRIBE"; target: types.BasicEventElement; @@ -39,15 +56,27 @@ type SubscribeRequest = { } } +/** + * Subscribe Event Request Callback + */ type SubscribeRequestCallback = (request: SubscribeRequest) => boolean; +/** + * Unsubscribe Event Request + */ type UnsubscribeRequest = { type: "UNSUBSCRIBE"; target: types.BasicEventElement; } +/** + * Unsubscribe Event Request Callback + */ type UnsubscribeRequestCallback = (request: UnsubscribeRequest) => void; +/** + * Call Operation Request + */ type CallRequest = { type: "CALL"; target: types.Operation; @@ -56,8 +85,14 @@ type CallRequest = { } } +/** + * Call Operation Request Callback + */ type CallRequestCallback = (request: CallRequest) => any; +/** + * Call Async Operation Request + */ type CallAsyncRequest = { type: "CALL-ASYNC"; target: types.Operation; @@ -66,20 +101,48 @@ type CallAsyncRequest = { } } +/** + * Call Async Operation Request Callback + */ type CallAsyncRequestCallback = (request: CallAsyncRequest) => string | null; +/** + * Get Async Operation State Request + */ type AsyncStateRequest = { type: "GET-OP-STATE"; target: string; } +/** + * Get Async Operation State Request Callback + */ type AsyncStateRequestCallback = (request: AsyncStateRequest) => boolean; +/** + * Get Async Operation Result Request + */ type AsyncResultRequest = { type: "GET-OP-RESULT"; target: string; } +/** + * Get Async Operation Result Request Callback + */ type AsyncResultRequestCallback = (request: AsyncResultRequest) => any; -type RequestType = "READ" | "WRITE" | "OBSERVE" | "CALL" | "CALL-ASYNC" | "GET-OP-STATE" | "GET-OP-RESULT" | "SUBSCRIBE" | "UNSUBSCRIBE" \ No newline at end of file +/** + * Possible Request Types + */ +type RequestType = "READ" | "WRITE" | "OBSERVE" | "CALL" | "CALL-ASYNC" | "GET-OP-STATE" | "GET-OP-RESULT" | "SUBSCRIBE" | "UNSUBSCRIBE" + +/** + * Combined Request Type + */ +export type Request = GetRequest | WriteRequest | ObserveRequest | CallRequest | CallAsyncRequest | AsyncStateRequest | AsyncResultRequest | SubscribeRequest | UnsubscribeRequest; + +/** + * Combined Request Callback Type + */ +export type OnRequestCallback = (request: Request) => any & GetRequestCallback & WriteRequestCallback & ObserveRequestCallback & CallRequestCallback & CallAsyncRequestCallback & AsyncStateRequestCallback & AsyncResultRequestCallback & SubscribeRequestCallback & UnsubscribeRequestCallback; diff --git a/lib/typedoc.json b/lib/typedoc.json new file mode 100644 index 0000000..3374160 --- /dev/null +++ b/lib/typedoc.json @@ -0,0 +1,9 @@ +{ + "$schema": "https://typedoc.org/schema.json", + "entryPoints": ["./src/index.ts"], + "out": "docs", + "plugin": ["typedoc-plugin-extras", "typedoc-plugin-rename-defaults"], + "footerLastModified": true, + "footerTypedocVersion": true, + "customTitle": "Multimessagebroker for Industry 4.0 Applications" +} \ No newline at end of file