From 4c48fdbb4d363cf71605fe180df715e16ba29ebf Mon Sep 17 00:00:00 2001 From: "Namhyeon, Go" Date: Sun, 12 Apr 2026 19:11:30 +0900 Subject: [PATCH] Add stdio server, mcploader and JSON-RPC extract Introduce a StdioServer module and mcploader entry script, and extend jsonrpc2 with an extract() helper. stdio-server.js provides an EventTarget-based wrapper for reading/writing via WScript stdio. mcploader.js uses the server and JsonRpc2.extract to parse incoming JSON-RPC messages and respond. Also change DEFAULT_JSONRPC2_URL to http://localhost:5555, export the new extract function, and bump jsonrpc2 version to 0.1.6. --- lib/jsonrpc2.js | 54 +++++++++++++++++++++++++++++++++++++++-- lib/stdio-server.js | 58 +++++++++++++++++++++++++++++++++++++++++++++ mcploader.js | 30 +++++++++++++++++++++++ 3 files changed, 140 insertions(+), 2 deletions(-) create mode 100644 lib/stdio-server.js create mode 100644 mcploader.js diff --git a/lib/jsonrpc2.js b/lib/jsonrpc2.js index 2f14f3f..6186e3e 100644 --- a/lib/jsonrpc2.js +++ b/lib/jsonrpc2.js @@ -38,6 +38,55 @@ function JsonRpc2(url) { } } +function extract(message, callback) { + var data; + + if (typeof callback !== "function") { + throw new Error("Invalid callback"); + } + + try { + data = JSON.parse(message); + } catch (e) { + throw new Error("Invalid JSON: " + e.message); + } + + if (!data || typeof data !== "object") { + throw new Error("Invalid request object"); + } + + if (data.jsonrpc !== "2.0") { + throw new Error("Invalid JSON-RPC version"); + } + + if (!data.method || typeof data.method !== "string") { + throw new Error("Missing or invalid method"); + } + + var params = data.params !== undefined ? data.params : null; + var id = data.id !== undefined ? data.id : null; + + try { + var result = callback(data.method, params, id); + + return { + jsonrpc: "2.0", + result: result === undefined ? null : result, + id: id + }; + + } catch (e) { + return { + jsonrpc: "2.0", + error: { + code: -32603, + message: e && e.message ? e.message : "Internal error" + }, + id: id + }; + } +} + function wrap(method, params, id) { return { "jsonrpc": "2.0", @@ -51,14 +100,15 @@ function create(url) { return new JsonRpc2(url); } -var DEFAULT_JSONRPC2_URL = "https://azure-ashlan-40.tiiny.io/"; +var DEFAULT_JSONRPC2_URL = "http://localhost:5555"; +exports.extract = extract; exports.wrap = wrap; exports.create = create; exports.DEFAULT_JSONRPC2_URL = DEFAULT_JSONRPC2_URL; -exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.5"; +exports.VERSIONINFO = "JSON-RPC 2.0 wrapper (jsonrpc2.js) version 0.1.6"; exports.AUTHOR = "gnh1201@catswords.re.kr"; exports.global = global; exports.require = global.require; diff --git a/lib/stdio-server.js b/lib/stdio-server.js new file mode 100644 index 0000000..54faf96 --- /dev/null +++ b/lib/stdio-server.js @@ -0,0 +1,58 @@ +// stdio-server.js +// Copyright 2019-2026, Namhyeon Go and the WelsonJS contributors. +// SPDX-License-Identifier: GPL-3.0-or-later +// https://github.com/gnh1201/welsonjs +// +var STD = require("lib/std"); + +function StdioServer() { + // Set event-attachable object + STD.EventTarget.apply(this, arguments); + + this.messages = []; + + this.receive = function () { + return this.messages.shift(); + }; + + this.send = function (message) { + WScript.StdOut.WriteLine(message); + }; + + this.listen = function () { + while (!WScript.StdIn.AtEndOfStream) { + this.messages.push(WScript.StdIn.ReadLine()); + this.dispatchEvent(new STD.Event("message")); + } + }; +} +StdioServer.prototype = new STD.EventTarget(); +StdioServer.prototype.constructor = StdioServer; + +/* + +// For example +var server = new StdioServer(); + +server.addEventListener("message", function(e) { + // receive message + var message = e.target.receive(); + + console.log(message); + + // send message + e.target.send("Hello world"); +}); + +server.listen(); + +*/ + +exports.create = function () { + return new StdioServer(); +}; + +exports.VERSIONINFO = "Stdio Server (stdio-server.js) version 0.1"; +exports.AUTHOR = "gnh1201@catswords.re.kr"; +exports.global = global; +exports.require = global.require; diff --git a/mcploader.js b/mcploader.js new file mode 100644 index 0000000..05b37d8 --- /dev/null +++ b/mcploader.js @@ -0,0 +1,30 @@ +// mcploader.js +// Copyright 2019-2026, Namhyeon Go and the WelsonJS contributors. +// SPDX-License-Identifier: GPL-3.0-or-later +// https://github.com/gnh1201/welsonjs +// +var StdioServer = require("lib/stdio-server"); +var JsonRpc2 = require("lib/jsonrpc2"); + +function main(args) { + var server = StdioServer.create(); + + server.addEventListener("message", function(e) { + var message = e.target.receive(); + + try { + JsonRpc2.extract(message, function(method, params, id) { + console.log("Received method: " + method); + }); + } catch (e) { + console.log("Ignored"); + } + + // send message + e.target.send("Hello world"); + }); + + server.listen(); +} + +exports.main = main;