Open robobun opened 11 months ago
ConsoleObject.ts
line 2 defines the async iterator. i touched this code last and probably made some mistakes. i feel like this is "semi" a good first issue but it requires some knowledge on async iterators and readable streams.
for anyone working on this, note that you have to rebuild bun to see changes in this file apply.
You can do something like this.
const decoder = new TextDecoder();
process.stdin.on("readable", () => {
let input = process.stdin.read();
const lines = decoder.decode(input).split(/\\n|\\r\\n/);
const firstLine = lines.shift();
console.log({ firstLine });
console.log({ lines });
});
I wouldn't mix Node.js Streams implementation with WHATWG Streams. Two different implementations.
Keep in mind ECMA-262 does not define STDIO. JavaScript engines and runtimes implement STDIO differently. From the tests I've done no two JavaScript runtimes implement STDIO the same.
I'd appreciate any suggestions on how to unlock the ReadableStream, or how to more elegantly handle this use case.
For a WHATWG Streams version you can pipe the ReadableStream
through a TextDecoderStream()
then pipe to a WritableStream()
and split on newline character, something like
new Blob(["a\nb\nc\n".repeat(100)])
.stream()
.pipeThrough(new TextDecoderStream())
.pipeTo(new WritableStream({
start: () => {
this.firstLineRead = false;
this.lines = [];
},
write: (value) => {
const data = value.split(/\n|\r\n/);
if (this.firstLineRead === false) {
const firstLine = data.shift();
this.firstLineRead = true;
console.log({
firstLine
});
}
this.lines.push(...data)
},
close: () => {
console.log({
lines: this.lines
});
console.log("Stream closed");
}
}));
From my question in stackoverflow:
const stdinIterator = process.stdin.iterator() console.write('What is your name?\n> ') const userName = (await stdinIterator.next()).value.toString().trimEnd() console.log('Hello,', userName) console.write(`What would you like, ${userName}?\n> `) const answer = (await stdinIterator.next()).value.toString().trimEnd() console.log('Do something with answer:', answer)
It works. But then the process is not terminated automatically (I need to press Ctrl+C manually).
I need to read the first line from stdin, perform some logic, and then iterate over the remaining lines of stdin. The suggested way from the docs (https://bun.sh/docs/api/console) to iterate over stdin lines is using its asyncIterator. But there's no suggested method to get a single line.
I attempted to call the asyncIterator method directly:
Defining
firstLine
this way works. However it will fail onconst line of console
with the errorReadableStream is locked
It seems that manually retrieving an item from console's asyncIterator causes its stream to become locked, and I'm unsure how to unlock it.I tried using the
prompt
function with an empty string as the message. But it seemsprompt
will still print a single space character to stdout if called with an empty string as the message. So it's not ideal.The best working solution I have right now is to write a for loop that I break out of after one iteration.
I'd appreciate any suggestions on how to unlock the ReadableStream, or how to more elegantly handle this use case.
Originally reported on Discord:
Calling
nexton
console's asyncIterable causes its stream to become locked