prompts icon indicating copy to clipboard operation
prompts copied to clipboard

Prompt not waited for when running as pipe target

Open pke opened this issue 4 years ago • 4 comments

Describe the bug

Prompt is not waited for when in non TTY mode but as a pipe target.

I'd like to pipe some curl data to a prompt, let the user select an entry and output this choice for the next member in the pipe chain as input.

curl mysite.com/prompt | myscript.js | someotherscript.ja

To Reproduce

  1. Create a file with the README sample code
#!/usr/bin/env node
// eslint-disable-next-line node/shebang
const prompts = require("prompts");

(async () => {
  if (!process.stdin.isTTY) {
    //process.stdin.resume()

    process.stdin.setEncoding("utf8")
    
    const json = await new Promise((resolve, reject) => {
      var data = ""
      process.stdin.on("data", function(chunk) {
        data += chunk
      })  
      process.stdin.on("end", () => {
        resolve(JSON.parse(data))
      })
      process.stdin.on("error", reject)
    })
   
  }

  const response = await prompts({
    type: "number",
    name: "value",
    message: "How old are you?",
    validate: value => value < 18 ? "Nightclub is 18+ only" : true
  })

  console.log(response) // => { value: 24 }
})()

Pipe some input to it: curl google.com | myscript.js

Expected behavior

Expected the prompt to be shown (it does show) and waited for user input.

pke avatar Nov 12 '19 00:11 pke

You could try using the Node package ttys and setting the stdin property of the Prompts object to ttys.stdin?

For example:

const ttys = require('ttys');
const prompts = require("prompts");
// Use rest of your code here to deal with piped in data via `process.stdin`...
const response = await prompts({
    type: "number",
    name: "value",
    message: "How old are you?",
    validate: value => value < 18 ? "Nightclub is 18+ only" : true,
    stdin: ttys.stdin
});

Hope this helps.

guypursey avatar Jun 14 '20 14:06 guypursey

Thank you for the issue and for the suggestion @guypursey. I'll have this in mind for the next major rewrite 👍

terkelg avatar Jun 15 '20 18:06 terkelg

You could try using the Node package ttys and setting the stdin property of the Prompts object to ttys.stdin?

For example:

const ttys = require('ttys');
const prompts = require("prompts");
// Use rest of your code here to deal with piped in data via `process.stdin`...
const response = await prompts({
    type: "number",
    name: "value",
    message: "How old are you?",
    validate: value => value < 18 ? "Nightclub is 18+ only" : true,
    stdin: ttys.stdin
});

Hope this helps.

I got the error when I using ttys on OSX.

Error: ENXIO: no such device or address, open '/dev/tty'

wing1003 avatar Feb 02 '21 08:02 wing1003

I seem to have a similar issue when readin the input from a file like this:

const inputStream = fs.createReadStream("input.txt");
const response = await prompts({
    type: "number",
    name: "value",
    message: "How old are you?",
    validate: value => value < 18 ? "Nightclub is 18+ only" : true,
    stdin: inputStream,
});

Is there a workaround?

I'm trying to write an end-to-end test of the application with pre-defined values.

nikeee avatar Jan 27 '22 13:01 nikeee