Getting Unprompted Input in NodeJS - node.js

I'm trying to get unprompted input from the user in a NodeJS server. The reason is that I want to be able to send strings that can be interpreted as commands while a server is running such as commands to flush the cache.
Now, originally, I used readline as follows:
import * as ReadLine from 'readline';
export default function InitTerminal() {
const terminal = ReadLine.createInterface({
input: process.stdin,
terminal: false
});
terminal.on('line', (input) => {
console.log(input);
switch(input.toString()) {
default:
console.log('Unknown Command');
break;
}
});
}
The issue was that after most inputs, I would get:
rl.on line * input *
Where * input * refers to the string representation of the buffer input from process.stdin. The weird thing is, the on line triggers only occassionaly and typically I will get that line and my listener doesn't trigger. The same thing happens when I don't use ReadLine and just add a listener to process.stdin. Something is triggering node to print out the output above. I'm using node 11.12.0 and ts-node-dev for typescript in development mode.
So what I'm asking is how can I use node to get unprompted input as commands? Either by modifying my original code or any way I haven't thought of.
Kind thanks.

The problem was that ts-node-dev plays with the stdin. That means it's hard to get the stdin while using it. What I hade to do was create an npm script called build:dev which compiled my typescript and then ran it. Then I could use the process.stdin without concern.
A way to possible watch changes while doing this is to use nodemon instead of ts-node-dev and just compile the typescript when needed

Related

Worker thread postMessage() vs command line command

I recently learned about Worker threads in Node JS. I was trying to create a worker thread to run Stockfish chess engine in node js.
The npm package I am using for this is called stockfish. I tried using node-stockfish before this but it was not installing with npm as it was using an older version of the type definition for the "AbortSignal" variable apparently causing compatibility issues.
For the current npm package that I am using even though I was able to install it successfully, I could find very little documentation on how to use it. So I tried out a few ideas.
import { Worker } from "worker_threads";
const engine = new Worker("./node_modules/stockfish/src/stockfish.js")
engine.on('message', (data) => console.log(data))
engine.postMessage('position startpos move e2e4 e7e5')
engine.postMessage('go movetime 3000')
Here I tried to run the stockfish.js as a worker thread and send commands to it with the postMessage() function. This however did not work and it gave the following output:
worker.js received unknown command undefined
position startpos move e2e4 e7e5
worker.js received unknown command undefined
go movetime 3000
But I know these commands are valid commands if I run the same js from the command line like so:
It might be because I am using the flags --experimental-wasm-threads and --experimental-wasm-simd when I am running it from the command line. I found this command to run it from the little documentation that was present. But I don't know how to mention these flags when I run it through a worker thread.
Otherwise it could also be that I don't understand how worker threads work yet and postMessage() is not the same as sending it a command from the command line.
Any help is greatly appreciated.
I switched to using stockfish.wasm library instead. With this library I was able to achieve what I wanted and I don't need to use any worker threads for now. Maybe I can add this to a worker thread if required later. Here is a simple example:
const Stockfish = require("stockfish.wasm")
Stockfish().then((engine) => {
engine.addMessageListener((output) => {
console.log(output);
// Do something with the output data here
})
engine.postMessage("uci");
engine.postMessage("ucinewgame");
engine.postMessage("position startpos");
engine.postMessage("go depth 20");
});

Interract with a .exe program with js instead of typing in the program

Hello I'm tryna make a Skyrim server Dashboard.
The server look like this =>
On this server i can type some command like this =>
when I manualy wrote /help and it show the output.
I tried to run the executable in node js, the server is working, I can join it, And I can see the output on my VSCode Terminal
But I can't input some text or command
Hope you can help me thanks in advance.
##Its my first ask
Add shell: true to the spawn method so you can still pass commands to the process.
const child = require('child_process').spawn("C:/SkyrimTogetherServer.exe", {
shell: true
});

Unable to read a continuous data stream from a node child process in Node.js

First things first. The goal I want to achieve:
I have two processes:
the first one is webpack that just watches for file changes and pushes the bundled files into the dist/ directory
the second process (Shopify CLI) watches for any file changes in the dist/ directory and pushes them to a remote destination
My goal is to have only one command (like npm run start) which simultaneously runs both processes without printing anything to the terminal so I can print custom messages. And that's where the problem starts:
How can I continuously read child process terminal output?
Printing custom messages for webpack events at the right time is pretty easy, since webpack has a Node API for that. But the Shopify CLI only gives me the ability to capture their output and process it.
Normally, the Shopify CLI prints something like "Finished Upload" as soon as the changed file has been pushed. It works perfectly fine for the first time but after that, nothing is printed to the terminal anymore.
Here is a minimal representation of what my current setup looks like:
const spawn = require('spawn');
const childProcess = spawn('shopify', ['theme', 'serve'], {
stdio: 'pipe',
});
childProcess.stdout.on('data', (data) => {
console.log(data);
});
childProcess.stderr.on('data', (data) => {
// Just to make sure there are no errors
console.log(data);
});

NodeJS REPL double echoing input, making it hard to use

When I use the NodeJS repl on linux, everything I type is echoed twice. If I start it up like this:
$ node
Welcome to Node.js v16.11.0.
Type ".help" for more information.
> let repl;
undefined
> import("repl").then(module => { repl = module });
Promise {
<pending>,
[Symbol(async_id_symbol)]: 294,
[Symbol(trigger_async_id_symbol)]: 283,
[Symbol(destroyed)]: { destroyed: false }
}
> let f = repl.start();
> undefined
>
Now everything that I type is doubled up. If I type the letter d, it shows dd. This is preventing me from creating my own REPL setup script.
What am I doing wrong here?
When you start node.js in a terminal without passing a javascript file, by default node actually creates a REPL instance behind the scenes to give you something to interact with in your terminal. So by importing and starting another REPL you now have two REPL instances reading stdin and so you get twice the echo of stdin to stdout.
You can access the default running REPL by running this.repl in a newly opened node terminal. If you want only your own REPL to run, I would recommend declaring your REPL in a javascript file and then executing that file with the node runtime instead.

Creating a Visual Studio Code integrated terminal with a custom Node script as the shell

I'm working on a Visual Studio Code extension in which I hope to create a terminal which gives access to a custom shell. I have a Node.js script (.js file) which implements this shell. Now, I'm trying to use Code's createTerminal method from my extension to launch a terminal that uses my Node.js script as its shell.
I can't directly set the shellPath to be my js file, because I have no guarantee that the user has Node.js installed, that the system will run such files with Node.js, nor what version of Node is installed. I need to be able to point at a universally-understood binary which can handle the file. Roughly speaking, I want to do this:
let terminal = vscode.window.createTerminal({
name: "My terminal",
shellPath: 'node', // Use the Node.js executable as the target
shellArgs: [path.join(__dirname, 'my-shell-wrapper.js')] // Tell Node to run my shell
});
terminal.show();
How can I accomplish this? Is there an executable that ships with Code that I can point to which runs Node scripts? Or is there another mechanism which I'm missing?
VSCode now (as of the past year or so) has the option of specifying custom behaviors for terminals aside from just the underlying shell executable. createTerminal has an overload which takes ExtensionTerminalOptions; this has a pty property which allows you to specify custom handlers for reading from and writing to the terminal. From their Pseudoterminal documentation:
const writeEmitter = new vscode.EventEmitter<string>();
const pty: vscode.Pseudoterminal = {
onDidWrite: writeEmitter.event,
open: () => {},
close: () => {},
handleInput: data => writeEmitter.fire(data === '\r' ? '\r\n' : data)
};
vscode.window.createTerminal({ name: 'Local echo', pty });
This can be used to implement arbitrary terminal interactions.

Resources