I have problem to write stdin in deno version 1.37.0 (release, x86_64-pc-windows-msvc)
. I search in documentation, google, try the code and not work. I found related code in https://github.com/denoland/deno/issues/7713 but not compatible with the latest version.
I have code like this:
// parent.ts
const command = new Deno.Command(Deno.execPath(), {
args: [
"run",
"-A",
"child.ts"
],
stdout: "piped",
stdin: "piped"
});
const p = command.spawn();
// child.ts
const decoder = new TextDecoder();
for await (const chunk of Deno.stdin.readable) {
const text = decoder.decode(chunk);
console.log(text);
}
Deno.stdin.close();
Does anyone know how to solve it?
You can connect any standard I/O stream of the parent process to a
child process by using the
value "inherit"
for the
option corresponding to
that stream (stdout
, stderr
, stdin
) — for example:
./parent.ts
:
const childProcess = new Deno.Command(Deno.execPath(), {
args: ["run", import.meta.resolve("./child.ts")],
stderr: "inherit", // Connect stderr of child to stderr of this process
stdin: "inherit", // Connect stdin of child to stdin of this process
stdout: "inherit", // Connect stdout of child to stdout of this process
}).spawn();
await childProcess.status;
In fact — when spawning a child process in Deno v
1.37.0
—"inherit"
is the default option value for these streams, so you don't need to specify it. (But I suggest doing so in case the default ever changes — defaults have changed in the past! See denoland/deno#17025 and denoland/deno#17334.)
So that you can reproduce this example, here's the content of ./child.ts
:
// Raw mode needs to be enabled for this example — you can read more about it in Deno's API documentation:
Deno.stdin.setRaw(true, { cbreak: true });
for await (
const str of Deno.stdin.readable.pipeThrough(new TextDecoderStream())
) {
const timestamp = new Date().toISOString();
console.log(timestamp, str);
}
Now, you can run the parent process in your temrinal using this command:
deno run --allow-read --allow-run=deno parent.ts
As you type into (the stdin
of) your terminal, the data stream will be
forwarded to the child process. The example child module uses
console.log
(which
writes values to stdout
, followed by a newline). Because the code above also
specified to connect the stdout
streams of the child and parent processes, you
should see each of your inputs preceded by a timestamp on a new line in your
terminal.
If — for example — you type H e l l o W o r l d into your terminal, then you'll see output very similar to this:
2023-09-26T01:03:35.640Z H
2023-09-26T01:03:35.852Z e
2023-09-26T01:03:35.892Z l
2023-09-26T01:03:36.023Z l
2023-09-26T01:03:36.273Z o
2023-09-26T01:03:36.700Z
2023-09-26T01:03:36.936Z W
2023-09-26T01:03:37.097Z o
2023-09-26T01:03:37.152Z r
2023-09-26T01:03:37.276Z l
2023-09-26T01:03:37.365Z d
To stop the Deno parent process, use Ctrl + c to send
the interrupt signal (SIGINT
).
In Deno, the standard I/O strems
(stdout
,
stderr
, and
stdin
) each have a corresponding
readable
or
writable
property which is an instance of a
web standard stream.
There is a Stack Overflow tag for the topic of those streams: whatwg-streams-api
To do something such as connecting the parent stdin
to the child and also
write directly to the child stdin
in your program code, you'll need to use
additional third-party code to merge those input streams, such as this module in
Deno's std
library:
https://deno.land/std@0.202.0/streams/merge_readable_streams.ts