Tive recentemente um desafio de criar uma CLI (Command Line Interface), que nada mais é um programa que usamos pelo terminal.
Um dos desafios do código era receber um JSON como input dos dados.
Sendo possível dois tipos de entrada:
Com o usuário digitando os dados
lucas in dev/lucas/readline is 📦 1.0.0 via ⬢ v18.20.2
➜ node index.js
{"key":"value"}
[{"key":"value"}]
Dessa forma, a pessoa digita o JSON, dá enter, isso significa uma linha de input. Na segunda linha, a pessoa poderia digitar um novo JSON ou em caso de não digitar nada, iniciaria o processamento da ferramenta. Neste caso é apenas um console.log
Com input redirection
lucas in dev/lucas/readline is 📦 1.0.0 via ⬢ v18.20.2 took 12,5s
➜ node index.js < input.txt
[{"key":"value"}]
Dessa forma, o usuário utiliza input redirection que é uma forma muito comum de ser utilizada em aplicações de linha de comando quando lidamos com inputs muito grandes.
Como resolvi esse problema.
import readline from "readline";
export const readFileInput = () => {
const rl = readline.createInterface({
input: process.stdin,
});
let allArrays = [];
return new Promise((resolve) => {
rl.on("line", (line) => {
if (line.trim() === '') {
rl.close();
return;
}
const jsonArray = JSON.parse(line.trim());
allArrays.push(jsonArray);
});
rl.on("close", () => {
resolve(allArrays);
});
});
};
Dei uma olhada na documentação do NodeJS - Readline para entender um pouco como funciona.
O primeiro passo é criar uma interface para receber os dados. Utilizamos a biblioteca readline
do NodeJS.
Passamos como parâmetros 1 informação necessária:
input
: De onde vem os dados, no nosso casoprocess.stdin
.
createInterface
pode receber outros parâmetros, isso pode ser visto na documentação do Node.
A biblioteca extende do EventEmitter e trabalhamos escutando eventos.
Evento line
Com esse evento, pegamos cada linha digitada e podemos tomar alguma ação com ela.
No nosso caso, primeiro verificamos se não está vazio, sinal que o usuário não digitou nada, e caso esteja em branco, chamamos rl.close();
para encerrar o input dos dados. Caso tenha algum conteúdo pegamos o conteúdo da linha line
removemos caracteres em branco no final line.trim()
e transformamos em JSON JSON.parse(line.trim())
.
No final, pegamos esse objeto e colocamos em um array para processarmos essa informação posteriormente.
Evento close
Este evento significa que a interface foi encerrada.
Resolvemos a Promise
com os dados digitados.
Promise
envolvendo os eventos
Note que temos uma return new Promise
em volta dos eventos, fazemos isso para que seja possível pegar o que foi digitado e armazenar em uma variável. Como o processo de digitar os dados e encerrar a interface no terminal é um processo assíncrono, precisamos dessa Promise
com um resolve
no evento de close
.
Assim podemos usar essa função da seguinte maneira:
const data = readFileInput()
Onde data
vai conter um array de objetos que são as linhas inseridas na aplicação.