How to get variable from input NodeJs - node.js

I want to get a value from input
const readline = require('node:readline/promises').createInterface({
input: process.stdin,
output: process.stdout
})
const value = await readline.question('enter :');
console.log(value)
readline.close()
And then I get an Error "SyntaxError: await is only valid in async functions and the top level bodies of modules"
On the other hand in the docs example:
import * as readline from 'node:readline/promises';
import { stdin as input, stdout as output } from 'process';
const rl = readline.createInterface({ input, output });
const answer = await rl.question(
'What do you think of Node.js? '
);
console.log(
`Thank you for your valuable feedback: ${answer}`
);
rl.close();
I copy this example and get the same error. I cant use readline synchronously. I want input a value, some variable will equals this value, and THEN it will console.log(). I dont want to use "Prompt" module. TY

Your issue is because you are trying to use top-level-await.
Now this is possible in modern nodejs (16+ I think), but you need to tell explicitly node to use modules, like your in your second code.
Try to upgrade nodeJS to the latest version 18, it should run fine.
(Also you may need to hint node on using modules explicitly, for that either name your file using the extension .mjs or specify "type": "module" in your package.json
Working example using .mjs and current node v18.6 the code is copy pasted from your question, no changes made.

Related

Node.js readline module: stop reprinting the line just read

I'm using the readline module in Node (12) to accept user input as such:
import * as readline from "readline";
process.stdin.setEncoding('utf-8');
console.log("input is a TTY?",process.stdin.isTTY);
const rl = readline.createInterface({input: process.stdin, output: process.stdout, prompt: '> '});
rl.prompt();
rl.on('line' ,inputLine => { inputStringLines.push(inputLine); rl.prompt(); });
rl.on('close',() => { console.log('input has closed'); main(); });
The lines are correctly captured into my inputStringLines array but annoyingly, the process is printing out every line just read:
How can I get rid of the extra lines (the ones without the > prompt)
I fixed it by changing how run my script. Before, I used nodemon with node's -r ts-node/register option. The issue went away when I switched to using ts-node-dev to execute the script.
Note also that process.stdin.isTTY is now correctly set whereas it was undefined before (look at the first line in the image below, vs in the original post)
Still don't know the root cause, but I'm happy to move on.

How to capture JSON from stdin when parent doesn’t close pipe?

I developed a package called transpile-md-to-json that transpile multiple markdown files to a single JSON file.
Running transpile-md-to-json --src examples/content --watch transpiles markdown files to JSON and outputs result to stdout as markdown files are created, edited and deleted.
I tried using get-stdin to capture the JSON and process it some more using another node script.
transpile-md-to-json --src src/privacy-guides --blogify --watch | node test.js
Problem is stdin.on('end') is never fired because the pipe isn’t closed by transpile-md-to-json when watch mode is enabled (--watch).
See https://github.com/sindresorhus/get-stdin/blob/master/index.js#L23-L25
How can I work around this?
As pointed out by Mike in the comments, there appears to be no built-in way of achieving this as the pipe remains open until the parent exits, therefore stdin.on('end') is not fired.
The closest we can get is to use some kind of EOF indicator and use that to end a "cycle". An indicator we can hook to isn’t always present, but in the context of JSON, we’re good as each JSON payload ends with }.
const readline = require("readline")
const fs = require("fs")
process.stdin.setEncoding("utf-8")
const rl = readline.createInterface({
input: process.stdin,
})
var json = ""
rl.on("line", function(line) {
json += `${line}\n`
if (line === "}") {
console.log("done", json)
fs.writeFileSync("test.json", json)
json = ""
}
})

Can't get array of fs.Dirent from fs.readdir

I am using node 8.10.0.
fs.readdir() returns an array of filenames and child directory names, or fs.Dirents[].
I can't get that to work. Here's a simple example:
console.log(require("fs").readdirSync("/", {withFileTypes:true}));
This gives me an array of strings (e.g. ["bin", "mnt", "usr", "var", ...]), not an array of fs.Dirent objects (which is what I want).
How do I get this to work?
Required functionality is added in: v10.10.0, you have to update node.
I've hit the same problem and although I have the latest node.js (v10.16 currently) and intellisense in VS Code is consistent with the online documentation, the run-time reality surprised me. But that is because the code gets executed by node.js v10.2 (inside a VS Code extension).
So on node.js 10.2, this code works for me to get files in a directory:
import * as fs from 'fs';
import util = require('util');
export const readdir = util.promisify(fs.readdir);
let fileNames: string[] = await readdir(directory)
// keep only files, not directories
.filter(fileName => fs.statSync(path.join(directory, fileName)).isFile());
On the latest node.js, the same code could be simplified this way:
let fileEnts: fs.Dirent[] = await fs.promises.readdir(directory, { withFileTypes: true });
let fileNames: string[] = fileEnts
.filter(fileEnt => fileEnt.isFile())
.map(fileEnt => fileEnt.name);
The code snippets are in Typescript.

How to write module in ECMAScript 6

The below code is working with nodejs 4.4:
"use strict";
const test = (res) => {
return (data) => {
return res.json({"message": "testing"});
};
};
module.exports = test;
My question is using const correct, or is it correctly written using ES6?
Yes, you can use const like that. const means "the value of this variable cannot be changed" and the interpreter will complain if you try to assign a new value to it.
Is the code above "correctly written using ES6"? Depends what you mean... for example, ES6 uses export instead of module.exports, but what you've written is not wrong. After all, it works.
ES6 is not a different language - it's Javascript with some new features. It's up to you to decide how many of those features you want to use.

Prompt module in NodeJS repeating the input

I'm making an application using NodeJS and its a CLI application; to get the input from the user, I'm using the "prompt" module. I can use it, but while typing in the prompt's prompt, each character is getting repeated, however the output is fine! The code is below. Please Help.
prompt.start();
prompt.get({
properties: {
name: {
description: "What is your name?".magenta
}
}
}, function (err, result) {
console.log("You said your name is: ".cyan + result.name.cyan);
});
IMAGE:
Before using the "prompt" module, I used the ReadLine interface; sadly I had the same problem. However, the fix was simple:
Remove the rli.close(); and then run it.
Then re-add the rli.close(); and it works!
Thanks mscdex for the input, though :)
FWIW if you just need simple prompting, you can use the built-in readline module's question() method (which does not exhibit the double output issue). Example:
var readline = require('readline');
var rli = readline.createInterface({
input: process.stdin,
output: process.stdout
});
rli.question('What is your name? ', function(answer) {
console.log('You said your name is: ' + answer);
rli.close();
});

Resources