- 0.23.3Latest
- 0.23.2
- 0.23.0
- 0.22.13
- 0.22.12
- 0.22.10
- 0.22.9
- 0.22.8
- 0.22.6
- 0.22.5
- 0.22.4
- 0.22.3
- 0.22.2
- 0.22.1
- 0.22.0
- 0.21.10
- 0.21.9
- 0.21.8
- 0.21.7
- 0.21.6
- 0.21.5
- 0.21.4
- 0.21.3
- 0.21.2
- 0.21.1
- 0.21.0
- 0.20.48
- 0.20.47
- 0.20.46
- 0.20.45
- 0.20.44
- 0.20.43
- 0.20.42
- 0.20.41
- 0.20.40
- 0.20.39
- 0.20.38
- 0.20.37
- 0.20.36
- 0.20.35
- 0.20.34
- 0.20.33
- 0.20.32
- 0.20.31
- 0.20.30
- 0.20.29
- 0.20.28
- 0.20.27
- 0.20.26
- 0.20.25
- 0.20.24
- 0.20.23
- 0.20.22
- 0.20.21
- 0.20.20
- 0.20.19
- 0.20.18
- 0.20.17
- 0.20.16
- 0.20.15
- 0.20.14
- 0.20.13
- 0.20.12
- 0.20.11
- 0.20.10
- 0.20.9
- 0.20.8
- 0.20.7
- 0.20.6
- 0.20.5
- 0.20.4
- 0.20.3
- 0.20.2
- 0.20.1
- 0.20.0
- 0.19.13
- 0.19.12
- 0.19.11
- 0.19.10
- 0.19.9
- 0.19.8
- 0.19.7
- 0.19.6
- 0.19.5
- 0.19.4
- 0.19.3
- 0.19.2
- 0.19.1
- 0.19.0
- 0.18.0
- 0.17.0
- 0.16.0
- 0.15.0
- 0.14.4
- 0.14.3
- 0.14.2
- 0.14.1
- 0.14.0
- 0.13.8
- 0.13.7
- 0.13.6
- 0.13.5
- 0.13.4
- 0.13.3
- 0.13.2
- 0.13.1
- 0.13.0
- 0.12.2
- 0.12.1
- 0.12.0
- 0.11.1
- 0.11.0
- 0.10.0
- 0.9.2
- 0.9.1
- 0.9.0
- 0.8.0
- 0.7.0
- 0.6.1
- 0.6.0
- 0.5.0
- 0.4.0
- 0.3.0
- 0.2.0
- 0.1.0
- 0.0.8
- 0.0.7
- 0.0.6
- 0.0.5
- 0.0.4
- 0.0.3
- 0.0.2
- 0.0.1
- 0.0.0
proc
An easy way to run processes like a shell script - in Deno.
proc lets you write process-handling code in readable, idiomatic Typescript
using async/await and AsyncIterator promisy goodness. It provides a variety
of powerful and flexible input and output handlers, making using processes
comfortable and intuitive. And proc handles closing and shutting down
process-related resources in a sane manner - because you have enough to worry
about, right?
For more ramblings, see Key Concepts.
Documentation
deno doc --reload https://deno.land/x/proc/mod.ts 2> /dev/nullExamples
- Simple Examples for Input and Output Handlers
- Playing Sounds with
aplay - Count the Unique Words in War and Peace
- Use
PushIterableto Implement Workers
Related Projects
Input and Output Types
Processes really just deal with one type of data - bytes, in streams. Many programs will take this one step further and internally translate to and from text data, processing this data one line at a time.
proc treats process data as either Uint8Array or AsyncIterable<Uint8Array>
for byte data, or string or AsyncIterable<string> (as lines of text) for
text. It defines a set of standard input and output handlers that provide both
type information and data handling behavior to the runner.
An Example
To get you started, here is a simple example where we pass a text string to a
process and get back a Uint8Array - text compressed to bytes using gzip.
/**
* Use `gzip` to compress some text.
* @param text The text to compress.
* @return The text compressed into bytes.
*/
async function gzip(text: string): Promise<Uint8Array> {
return await runner(stringInput(), bytesOutput())().run({
cmd: ["gzip", "-c"],
}, text);
}
console.dir(await gzip("Hello, world."));
/* prints an array of bytes to console. */Input Types
| Name | Description |
|---|---|
emptyInput() |
There is no process input. |
stringInput() |
Process input is a string. |
stringArrayInput() |
Process input is a string[]. |
bytesInput() |
Process input is a Uint8Array. |
readerInput()* |
Process input is a Deno.Reader & Deno.Closer. |
readerUnbufferedInput()* |
Process input is a Deno.Reader & Deno.Closer, unbuffered. |
stringIterableInput() |
Process input is an AsyncIterable<string>. |
stringIterableUnbufferedInput() |
Process input is an AsyncIterable<string>, unbuffered. |
bytesIterableInput() |
Process input is an AsyncIterable<Uint8Array>. |
bytesIterableUnbufferedInput() |
Process input is an AsyncIterable<Uint8Array>, unbuffered. |
* - readerInput() and readerUnbufferedInput() are special input
types that do not have corresponding output types.
Output Types
| Name | Description |
|---|---|
stringOutput() |
Process output is a string. |
stringArrayOutput() |
Process output is a string[]. |
bytesOutput() |
Process output is a Uint8Array. |
stringIterableOutput() |
Process output is an AsyncIterable<string>. |
stringIterableUnbufferedOutput() |
Process output is an AsyncIterable<string>, unbuffered. |
bytesIterableOutput() |
Process output is an AsyncIterable<Uint8Array>. |
bytesIterableUnbufferedOutput() |
Process output is an AsyncIterable<Uint8Array>, unbuffered. |
stderrToStdoutStringIterableOutput()* |
stdout and stderr are converted to text lines (string) and multiplexed together. |
* - Special output handler that mixes stdout and stderr together.
stdout must be text data. stdout is unbuffered to allow the text lines to be
multiplexed as accurately as possible.
ℹ️ You must fully consume
Iterableoutputs. If you only partially consumeIterables, process errors will not propagate properly. For correct behavior, we have to return all the data from the process streams before we can propagate an error.
Running a Command
proc is easiest to use with a wildcard import.
import * as proc from "https://deno.land/x/proc@0.0.0/mod.ts";First, create a template. The template is a static definition and may be reused. The input and output handlers determine the data types used by your runner.
const template = proc.runner(proc.emptyInput(), proc.stringOutput());Next, create a runner by binding the template to a group.
const pg = proc.group();
const runner: proc.Runner<void, string> = template(pg);Finally, use the runner to execute a command.
try {
console.log(runner.run({ cmd: ["ls", "-la"] }));
} finally {
pg.close();
}A Simpler Alternative - The Global Group
It is not strictly necessary to create and close a local Group. If you don’t
specify a group, proc will use the global Group that exists for the lifetime
of the Deno process.
const runner = proc.runner(proc.emptyInput(), proc.stringOutput())();
console.log(runner.run({ cmd: ["ls", "-la"] }));Notice the empty parentheses at the end of the first line in the second example.
This is using the implicit global Group (which you don’t need to close
manually).
Most of the time, proc can automatically clean up processes. In some cases
where the output of one process feeds into the input of another, the first
process won’t be fully processed and therefore cannot be automatically shut
down. This can also happen if you don’t fully process AsyncIterable output of
a process. This will result in resource leakage. If your program is short and
does not start many processes, or if you are sure that the way you are using
processes is well behaved (either non-streaming output or all output data is
fully consumed), you can use the short form safely.
Direct Control Over stderr
For most of the output handlers, the first argument is optional and allows you
to pass a function to process stderr yourself.
- The function is passed one argument - an
AsyncIterator<string>ofstderrlines in text form (unbuffered) - You can optionally return a
string[]of lines from this function; these are attached to theProcessExitErrorif the process returns a non-zero error code - You can throw an error from this function; this allows you to scrape
stderrand do special error handling
The examples use this feature a couple of times.
See stderr-support.ts for some functions that
provide non-default stderr bahaviors. You can use these directly, and they
also serve as good working examples.
Overriding the Default Exit-Code Error Handling Behavior
For most of the output handlers, the second argument is optional and allows you
to redefine the way that proc raises errors based on the process exit code.
This doesn’t come up very often, but occasionally you may not want to treat all
non-zero exit codes as an error. You also may want to throw your own error
rather than the standard ProcessExitError.
The default error handling definition is defined in error-support.ts. Refer to this code if you want to create a custom error handler.