diff --git a/modules/cli/src/interact.ts b/modules/cli/src/interact.ts index 1938cc1..cd39e2d 100644 --- a/modules/cli/src/interact.ts +++ b/modules/cli/src/interact.ts @@ -14,11 +14,34 @@ import { getDispatcher } from "../../../lib/dispatcher/getDispatcher"; import { nopeDispatcherManager } from "../../../lib/dispatcher/nopeDispatcherManager"; import { getNopeLogger } from "../../../lib/logger/getLogger"; import { ICommunicationBridge } from "../../../lib/types/nope/nopeCommunication.interface"; +import { INopeObserver } from "../../../lib/types/nope/nopeObservable.interface"; inquirer.registerPrompt("search-list", require("inquirer-search-list")); const sleep = promisify(setTimeout); +async function getJsonInput() { + const data = ( + await inquirer.prompt([ + { + type: "input", + message: "Please enter valid JSON.", + name: "data", + validate(content) { + try { + JSON.parse(content); + return true; + } catch (e) { + return false; + } + } + } + ]) + ).data; + + return JSON.parse(data); +} + export async function interact( additionalArguments: { help: string; @@ -144,9 +167,33 @@ export async function interact( ] }, { - name: "browse - Operations to browse data of the NoPE-System", - value: "browse", + name: "data - Operations to work with data of the NoPE-System", + value: "data", items: [ + { + name: "show-data - show current data", + value: "show-data" + }, + { + name: "set-data - manipulate data manually", + value: "set-data" + }, + { + name: "subscribe - subscribe to data-updates", + value: "subscribe" + }, + { + name: "show-subscriptions - shows all subscriptions", + value: "show-subscriptions" + }, + { + name: "unsubscribe - unsubscribe a specific topic", + value: "unsubscribe" + }, + { + name: "unsubscribe-all - unsubscribes all observed data-items.", + value: "unsubscribe-all" + }, { name: "back - Back to the main menu", value: "back" @@ -164,6 +211,8 @@ export async function interact( let question = choices; + let subscriptions: { [index: string]: INopeObserver } = {}; + while (!exit) { const result = ( await inquirer.prompt([ @@ -242,7 +291,6 @@ export async function interact( console.log("No services are available."); } break; - case "execute-service": if (dispatcher.externalProvidedServices.getContent().length > 0) { const service = ( @@ -385,6 +433,150 @@ export async function interact( console.log("No instance are available."); } break; + case "show-data": + // Filter the hosts: + if (dispatcher.publishedEvents.getContent().length > 0) { + + // Show all Elements / Properties + const dataPath = ( + await inquirer.prompt([ + { + type: "search-list", + message: "Select the data to show.", + name: "dataPath", + choices: dispatcher.publishedEvents.getContent(), + } + ]) + ).dataPath; + + // Now we create a Promise, that we will use to + // receive the data of the element the user wants + // to observe. We use the promise to achieve a + // "blocking" behavior of the element. + + let _resolve = null; + const promise = new Promise((resolve, reject) => _resolve = resolve); + + // The Subscription to receive the Data. + const subscription = await dispatcher.subscribeToEvent(dataPath, (content) => { + // Now we have received some content and we will + // exit this subscription + subscription.unsubscribe(); + + // Now we use the content to return it: + _resolve(content); + }, {}); + + // Now render the content + logger.info("content=", await promise); + } else { + logger.warn("No topics are available."); + } + break; + case "set-data": + // Filter the hosts: + if (dispatcher.subscribedEvents.getContent().length > 0) { + + // Show all Elements / Properties + const dataPath = ( + await inquirer.prompt([ + { + type: "search-list", + message: "Select the data to show.", + name: "dataPath", + choices: dispatcher.subscribedEvents.getContent(), + } + ]) + ).dataPath; + + const data = await getJsonInput(); + + try { + await dispatcher.emit(dataPath, data); + // await dispatcher.emit(dataPath, data); + } catch (e) { + logger.warn("failed to update the data"); + logger.error(e); + } + + } else { + logger.warn("No data is available."); + } + break; + case "subscribe": + // Filter the hosts: + if (dispatcher.publishedEvents.getContent().length > 0) { + + // Show all Elements / Properties + const dataPath = ( + await inquirer.prompt([ + { + type: "search-list", + message: "Select the data to show.", + name: "dataPath", + choices: dispatcher.publishedEvents.getContent(), + } + ]) + ).dataPath; + + if (subscriptions[dataPath] === undefined) { + // The Subscription to receive the Data. + subscriptions[dataPath] = await dispatcher.subscribeToEvent(dataPath, (content) => { + // Now we use the content to return it: + logger.info(dataPath + "=", content); + }, {}); + } else { + logger.info("already subscribed the desired topic"); + } + + } else { + logger.warn("No data is available."); + } + break; + case "unsubscribe": + if (dispatcher.publishedEvents.getContent().length > 0) { + + // Show all Elements / Properties + const dataPath = ( + await inquirer.prompt([ + { + type: "search-list", + message: "Select the data to unsubscribe.", + name: "dataPath", + choices: Object.keys(subscriptions), + } + ]) + ).dataPath; + + if (subscriptions[dataPath] !== undefined) { + // The Subscription to receive the Data. + subscriptions[dataPath].unsubscribe(); + delete subscriptions[dataPath]; + + } else { + logger.info("already subscribed the desired topic"); + } + + } else { + logger.warn("No data is available."); + } + break; + case "show-subscriptions": + // Iterate over the available subscriptions + // an delete the subscriptions. + for (const key in subscriptions) { + console.log("*\t", key); + } + break; + case "unsubscribe-all": + // Iterate over the available subscriptions + // an delete the subscriptions. + for (const key in subscriptions) { + subscriptions[key].unsubscribe(); + } + subscriptions = {}; + logger.info("cleared subscriptions"); + break; case "exit": exit = true; break;