diff --git a/.vscode/launch.json b/.vscode/launch.json index 5797a44..d7df9ef 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -9,7 +9,7 @@ "request": "launch", "name": "Launch Program", "skipFiles": ["/**"], - "program": "${workspaceFolder}\\test\\fileStreamer\\index.js" + "program": "${workspaceFolder}\\test\\command\\external.ws.ws\\simple.js" } ] } diff --git a/Models/Connection/ConnectionInfo.js b/Models/Connection/ConnectionInfo.js index 7bbe2d7..7a1ac6c 100644 --- a/Models/Connection/ConnectionInfo.js +++ b/Models/Connection/ConnectionInfo.js @@ -51,22 +51,5 @@ export default class ConnectionInfo { loadPageAsync(pageName, rawCommand, pageSize, domainId, cancellationToken) { throw new Error("ConnectionInfo.loadPageAsync() method not implemented."); } - /** - * - * @param {string} jsonString - * @returns {DataSourceCollection} - */ - convertJSONToDataSet(content) { - if (content?.sources && Array.isArray(content?.sources)) { - let retVal = []; - content.sources.forEach((source) => { - retVal.push(source.data); - }); - return new DataSourceCollection(retVal); - } else { - throw new WebServerException( - "Error from Edge Connection ;the sources are not available." - ); - } - } + } diff --git a/Models/Connection/EdgeConnectionInfo.js b/Models/Connection/EdgeConnectionInfo.js index b15159e..a2808e0 100644 --- a/Models/Connection/EdgeConnectionInfo.js +++ b/Models/Connection/EdgeConnectionInfo.js @@ -133,4 +133,24 @@ export default class EdgeConnectionInfo extends ConnectionInfo { }); }); } + /** + * + * @param {string} jsonString + * @returns {DataSourceCollection} + */ + convertJSONToDataSet(content) { + if (content?.sources && Array.isArray(content?.sources)) { + let retVal = []; + content.sources.forEach((source) => { + retVal.push(source.data); + }); + return new DataSourceCollection(retVal); + } else { + throw new WebServerException( + "Error from " + + this.name + + " Connection ;the sources are not available." + ); + } + } } diff --git a/Models/Connection/SocketConnectionInfo.js b/Models/Connection/SocketConnectionInfo.js index b916dd1..9352b03 100644 --- a/Models/Connection/SocketConnectionInfo.js +++ b/Models/Connection/SocketConnectionInfo.js @@ -2,7 +2,6 @@ import net from "net"; import ConnectionInfo from "./ConnectionInfo.js"; import DataSourceCollection from "../../renderEngine/Source/DataSourceCollection.js"; import SocketSettingData from "./SocketSettingData.js"; -import WebServerException from "../Exceptions/WebServerException.js"; /** * @typedef {Object} LoadDataRequest @@ -12,14 +11,16 @@ import WebServerException from "../Exceptions/WebServerException.js"; */ export default class SocketConnectionInfo extends ConnectionInfo { /**@type {string} */ - endPoint; + host; + /**@type {string} */ + port; /** * @param {string} name * @param {SocketSettingData} settings */ constructor(name, settings) { super(name); - this.endPoint = settings.endPoint; + [this.host, this.port] = settings.endPoint.split(":"); } /** @@ -27,9 +28,52 @@ export default class SocketConnectionInfo extends ConnectionInfo { * @param {CancellationToken} cancellationToken * @returns {Promise} */ - async LoadDataAsync(cancellationToken, parameters) { - const retVal = await this.sendAsync(parameters); - return this.convertJSONToDataSet(retVal); + async loadDataAsync(parameters, cancellationToken) { + const byteMessage = parameters.hasOwnProperty("byteMessage") + ? parameters["byteMessage"] + : null; + const mySocket = new net.Socket(); + + await new Promise((resolve, reject) => { + mySocket.connect( + { + host: this.host, + port: this.port, + }, + () => { + resolve(); + } + ); + mySocket.on("error", (err) => { + reject(err); + }); + }); + const networkStream = mySocket; + if (byteMessage) { + await new Promise((resolve, reject) => { + networkStream.write(byteMessage, (err) => { + if (err) { + reject(err); + } else { + resolve(); + } + }); + }); + } + let result = await new Promise((resolve, reject) => { + /** @type {Buffer[]}*/ + const buffer = []; + networkStream.on("data", (data) => buffer.push(data)); + networkStream.on("error", (err) => { + reject(err); + }); + networkStream.on("end", () => { + const data = Buffer.concat(buffer); + const retVal = data.toString() + resolve( new DataSourceCollection([[{ result: retVal }]])); + }); + }); + return result; } /** * @param {Request} request @@ -48,37 +92,4 @@ export default class SocketConnectionInfo extends ConnectionInfo { } return result; } - async sendAsync(parameters) { - const byteMessage = parameters.hasOwnProperty("byteMessage") - ? parameters["byteMessage"] - : null; - const mySocket = new net.Socket(); - await new Promise((resolve, reject) => { - mySocket.connect(this.EndPoint, () => { - resolve(); - }); - mySocket.on("error", (err) => { - reject(err); - }); - }); - const networkStream = mySocket; - await new Promise((resolve, reject) => { - networkStream.write(byteMessage, (err) => { - if (err) { - reject(err); - } else { - resolve(); - } - }); - }); - return await new Promise((resolve, reject) => { - networkStream.read((err, data) => { - if (err) { - reject(err); - } else { - resolve(data); - } - }); - }); - } } diff --git a/b.test.db-journal b/b.test.db-journal new file mode 100644 index 0000000..a343c83 Binary files /dev/null and b/b.test.db-journal differ diff --git a/package.json b/package.json index 54f7f77..fa61692 100644 --- a/package.json +++ b/package.json @@ -58,7 +58,10 @@ "index4": "node test\\index4\\simple.js", "unknown": "node test\\command\\UnknownCommand\\simple.js", "fileStreamer": "node test\\fileStreamer\\index.js", - "bug": "node --trace-warnings --trace-deprecation test\\bug.js" + "bug": "node --trace-warnings --trace-deprecation test\\bug.js", + "socket-server": "node test\\connection\\socket\\app.js", + "socket": "node test\\connection\\socket\\connection.js", + "ws": "node test\\command\\external.ws.ws\\simple.js" }, "type": "module", "dependencies": { diff --git a/renderEngine/Command/Source/BaseClasses/SourceCommand.js b/renderEngine/Command/Source/BaseClasses/SourceCommand.js index 6af778c..068726e 100644 --- a/renderEngine/Command/Source/BaseClasses/SourceCommand.js +++ b/renderEngine/Command/Source/BaseClasses/SourceCommand.js @@ -42,7 +42,7 @@ export default class SourceCommand extends CommandBase { async _executeCommandAsync(context) { if (this.members?.items.length > 0) { const name = await this.name.getValueAsync(context); - const dataSet = await this.#loadDataAsync(name, context); + const dataSet = await this._loadDataAsync(name, context); context.cancellation.throwIfCancellationRequested(); if (dataSet.items.length != this.members.items.length) { throw new BasisCoreException( @@ -63,7 +63,7 @@ export default class SourceCommand extends CommandBase { * @param {IContext} context * @returns {Promise} */ - async #loadDataAsync(sourceName, context) { + async _loadDataAsync(sourceName, context) { const [connectionName, command, paramList] = await Promise.all([ this.connectionName.getValueAsync(context), this.toCustomFormatHtmlAsync(context), diff --git a/renderEngine/Command/Source/BaseClasses/WsMember.js b/renderEngine/Command/Source/BaseClasses/WsMember.js new file mode 100644 index 0000000..253446d --- /dev/null +++ b/renderEngine/Command/Source/BaseClasses/WsMember.js @@ -0,0 +1,45 @@ +import IContext from "../../../Context/IContext.js"; +import Member from "./Member.js"; +import CommandElement from "../../CommandElement.js"; +import TokenUtil from "../../../Token/TokenUtil.js"; + +export default class WsMember extends Member { + /** @type {IToken} */ + method; + /**@type {IToken} */ + query; + /** + * @param {object} memberIL + */ + constructor(memberIL) { + super(memberIL); + this.method = TokenUtil.getFiled(memberIL, "method"); + this.query = TokenUtil.getFiled(memberIL, "query"); + } + + /** + * @param {IContext} context + * @returns {Promise} + */ + async createHtmlElementAsync(context) { + const tag = new CommandElement("member"); + tag.addAttributeIfExist("name", this.name); + await Promise.all([ + tag.addAttributeIfExistAsync("preview", this.preview, context), + tag.addAttributeIfExistAsync("sort", this.sort, context), + tag.addAttributeIfExistAsync("method", this.method, context), + tag.addAttributeIfExistAsync("query", this.query, context), + ]); + if (this.extraAttributes) { + if (this.extraAttributes) { + await Promise.all( + Object.entries(this.extraAttributes).map((pair) => + tag.addAttributeIfExistAsync(pair[0], pair[1], context) + ) + ); + } + } + await tag.addRawContentIfExistAsync(this.rawContent, context); + return tag; + } +} diff --git a/renderEngine/Command/Source/BaseClasses/WsMemberCollection.js b/renderEngine/Command/Source/BaseClasses/WsMemberCollection.js new file mode 100644 index 0000000..ba9460f --- /dev/null +++ b/renderEngine/Command/Source/BaseClasses/WsMemberCollection.js @@ -0,0 +1,19 @@ +import JoinMember from "./JoinMember.js"; +import Member from "./Member.js"; +import MemberCollection from "./MemberCollection.js"; +import WsMember from "./wsmember.js"; + +export default class WSMemberCollection extends MemberCollection { + /** @param {object[]} membersIl */ + constructor(membersIl) { + super(membersIl); + } + + /** + * @param {object} memberIl + * @returns {Member} + */ + _createMember(memberIl) { + return new WsMember(memberIl); + } +} diff --git a/renderEngine/Command/Source/InlineSourceCommand.js b/renderEngine/Command/Source/InlineSourceCommand.js index 3d1c5bb..93b9ddd 100644 --- a/renderEngine/Command/Source/InlineSourceCommand.js +++ b/renderEngine/Command/Source/InlineSourceCommand.js @@ -1,7 +1,6 @@ import VoidResult from "../../Models/VoidResult.js"; import { InMemoryMemberCollection } from "./BaseClasses/InMemoryMemberCollection.js"; import SourceCommand from "./BaseClasses/SourceCommand.js"; -import IToken from "../../Token/IToken.js"; import ICommandResult from "../../Models/ICommandResult.js"; import IContext from "../../Context/IContext.js"; export default class InlineSourceCommand extends SourceCommand { diff --git a/renderEngine/Command/Source/ws.js b/renderEngine/Command/Source/ws.js index c870de5..02f7289 100644 --- a/renderEngine/Command/Source/ws.js +++ b/renderEngine/Command/Source/ws.js @@ -1,5 +1,10 @@ import SourceCommand from "./BaseClasses/SourceCommand.js"; import ICommandResult from "../../Models/ICommandResult.js"; +import VoidResult from "../../Models/VoidResult.js"; +import IContext from "../../Context/IContext.js"; +import DataSourceCollection from "../../Source/DataSourceCollection.js"; +import WSMemberCollection from "./BaseClasses/WsMemberCollection.js"; +import MemberCollection from "./BaseClasses/MemberCollection.js"; export default class WsCommand extends SourceCommand { /** * @param {object} wsIl @@ -7,13 +12,19 @@ export default class WsCommand extends SourceCommand { constructor(wsIl) { super(wsIl); } - + /** + * @param {object[]} membersIl + * @returns {MemberCollection} + */ + createMemberCollection(membersIl) { + return new WSMemberCollection(membersIl); + } /** * @param {string} sourceName * @param {IContext} context - * @returns {Promise} + * @returns {Promise} */ - async #loadDataAsync(sourceName, context) { + async _loadDataAsync(sourceName, context) { const [connectionName, command] = await Promise.all([ this.connectionName.getValueAsync(context), this.toCustomFormatHtmlAsync(context), @@ -25,7 +36,7 @@ export default class WsCommand extends SourceCommand { const encoder = new TextEncoder(); const byteMessage = encoder.encode(JSON.stringify(inputs)); const parameters = { - byteMessage, + byteMessage: byteMessage, }; return await context.loadDataAsync(sourceName, connectionName, parameters); } diff --git a/test/command/CommandUtil.js b/test/command/CommandUtil.js index c642471..350e84f 100644 --- a/test/command/CommandUtil.js +++ b/test/command/CommandUtil.js @@ -13,6 +13,7 @@ import UnknownCommand from "../../renderEngine/Command/UnknownCommand.js"; import RepeaterCommand from "../../renderEngine/Command/Collection/RepeaterCommand.js"; import CookieCommand from "../../renderEngine/Command/CookieCommand.js"; import ClientComponent from "../../renderEngine/Command/ClientComponent.js"; +import WsCommand from "../../renderEngine/Command/Source/ws.js"; export default class CommandUtil { /** @@ -76,6 +77,10 @@ export default class CommandUtil { retVal = new ClientComponent(commandIl); break; } + case "external.ws.ws":{ + retVal = new WsCommand(commandIl) + break + } default: { retVal = new UnknownCommand(commandIl); break; diff --git a/test/command/external.ws.ws/simple.js b/test/command/external.ws.ws/simple.js new file mode 100644 index 0000000..21936b6 --- /dev/null +++ b/test/command/external.ws.ws/simple.js @@ -0,0 +1,140 @@ +import ServiceSettings from "../../../models/ServiceSettings.js"; +import CancellationToken from "../../../renderEngine/Cancellation/CancellationToken.js"; +import GroupCommand from "../../../renderEngine/Command/Collection/GroupCommand.js"; +import TestContext from "../../../renderEngine/Context/TestContext.js"; + +var setting = new ServiceSettings({ + Settings: { + "Connections.Socket.mydbsource": { + endPoint: "127.0.0.1:9090", + }, + }, +}); +const context = new TestContext(setting); +context.cancellation = new CancellationToken(); + +const groupIl = { + $type: "group", + core: "group", + name: "ROOT_GROUP", + Commands: [ + { + $type: "external.ws.ws", + core: "external.ws.ws", + "extra-attribute": { + service: "saman", + procedurename: "sbserviceprocedure1", }, + name: "saman", + ConnectionName: "mydbsource", + Members: [ + { + name: "m1", + method: "RequestToken", + sort: "random", + content: + '\r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n \r\n ', + }, + ], + }, + { + $type: "inlinesource", + core: "inlinesource", + name: "view", + Members: [ + { + name: "item", + preview: "true", + content: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }, + { + name: "menu", + preview: "true", + content: ` + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + `, + }, + ], + }, + { + $type: "Print", + core : "print", + "data-member-name": "saman.m1", + faces: [ + { + name: "face1", + content: "

-- @result
", + }, + ], + } + ], +}; + +const group = new GroupCommand(groupIl); +try { + const result = await group.executeAsync(context); + console.log(result); +} catch (ex) { + console.error(ex); +} diff --git a/test/connection/socket/app.js b/test/connection/socket/app.js new file mode 100644 index 0000000..4727703 --- /dev/null +++ b/test/connection/socket/app.js @@ -0,0 +1,32 @@ +import net from "net"; + +const port = 9090; + +const server = net.createServer((socket) => { + console.log("Client connected"); + + socket.on("data", (message) => { + const strData = message.toString(); + const data = JSON.parse(strData); + console.log("Received: ", data); + const result ="Hi from socket"; + socket.write(result); + socket.destroy(); + }); + + socket.on("end", () => { + console.log("Client disconnected"); + }); + + socket.on("error", (error) => { + console.log(`Socket Error: ${error.message}`); + }); +}); + +server.on("error", (error) => { + console.log(`Server Error: ${error.message}`); +}); + +server.listen(port, () => { + console.log(`TCP socket server is running on port: ${port}`); +}); diff --git a/test/connection/socket/connection.js b/test/connection/socket/connection.js new file mode 100644 index 0000000..336004b --- /dev/null +++ b/test/connection/socket/connection.js @@ -0,0 +1,7 @@ +import SocketConnectionInfo from "./../../../models/Connection/SocketConnectionInfo.js"; + +const socket = new SocketConnectionInfo("TEST", { endPoint: "127.0.0.1:9090" }); +const encoder = new TextEncoder(); +const byteMessage = encoder.encode(JSON.stringify("tessssst")); +const result = await socket.loadDataAsync({ byteMessage }, null); +console.log("##############3", result.items[0].data);