A simple Deno π¦ library that makes spawning processes and managing them as easy and fast as it ever was π.
This library was inspired by zx, which was made by Google
I've always felt Deno's way of dealing with child processes was awful, very awkward and not easy to use overall. So I thought: "Why not make a library that allows you to spawn processes using command line syntax?" and that's how shexec was born.
The shexec project follows Deno's official formatting standards. All source code is automatically formatted using the deno fmt command, with settings defined in the deno.json configuration file.
Since shexec uses npm dependencies, before using it in your projects you need to run
deno install "jsr:@jabonchan/shexec"You can import shexec's multiple exports in your project like this:
import $ from "jsr:@jabonchan/shexec";
import type {
ShexecSubstitution,
ShexecExecInheritedOutput,
ShexecExecPipedOutput
} from "jsr:@jabonchan/shexec";Using echo in unix with a variable
import $ from "jsr:@jabonchan/shexec";
const name = prompt("What's your name?") ?? "Someone";
await $.inherit`echo Hello ${name}`;
// stdin: John
// stdout: Hello JohnObtaining IPv4 on Windows
import $ from "jsr:@jabonchan/shexec";
const IPV4_PATTERN = /IPv4(?:\.|\s)+:(?:\s+)((?:\.|\d)+)/;
const { decoded } = await $`ipconfig`;
const ip = decoded.stdout.match(IPV4_PATTERN)?.[1] ?? "Offline";
console.log("Result: " + ip);
// stdout: Result: 192.X.X.X
// or
// stdout: Result: OfflineRepresents the array of substitutions that are provided to template string functions. Inside this array we find the values that a substitution can have, which are a string, number or an array of both.
type ShexecSubstitution = Array<
string | number | Array<string | number>
>;Represents the output of a inherited stdio shell execution.
success - Indicates whether the execution was successful.
code - The exit code of the process.
signal - The signal that caused the process to terminate, or null if none.
interface ShexecExecInheritedOutput {
success: boolean;
code: number;
signal: Deno.Signal | null;
}Represents the output of a piped stdio shell execution.
decoded - Contains the decoded output streams as strings.
decoded.stdout - The decoded standard output as a string. In UNIX systems TextDecoder("utf-8") is used. In Windows iconv.decode(buf, "cp850") is used since that's Windows' default terminal encoding.
decoded.stderr - The decoded standard error as a string. In UNIX systems TextDecoder("utf-8") is used. In Windows iconv.decode(buf, "cp850") is used since that's Windows' default terminal encoding.
stdout - The raw standard output as a Uint8Array.
stderr - The raw standard error as a Uint8Array.
success - Indicates whether the execution was successful.
code - The exit code of the process.
signal - The signal that caused the process to terminate, or null if none.
interface ShexecExecPipedOutput {
decoded: {
stdout: string;
stderr: string;
};
stdout: Uint8Array<ArrayBuffer>;
stderr: Uint8Array<ArrayBuffer>;
success: boolean;
code: number;
signal: Deno.Signal | null;
}This is a template function that internally creates a Deno.ChildProcess with stdio set to piped and with the executable and arguments passed to the function as a template. It then spawns the process and waits for it to finish, returning a Promise<ShexecExecPipedOutput>.
async function $(template: TemplateStringsArray, ...substitutions: ShexecSubstitution): Promise<ShexecExecPipedOutput>Can be used like this:
$`command argument1 "argument${2}" argument${"3"}`The rules for the syntaxis are:
-
Anything that's not separated by a whitespace is considered a single argument.
-
Only
"works for quoting,'doesn't. -
Supports all JavaScript escape sequences.
-
Arrays are expanded onto multiple arguments, and, if empty, no argument is added.
-
Any whitespace works, including breaklines, tabs, and so on, so multiline command is allowed unless it's inside a quoted argument
-
Arrays cannot be combined with any other argument, that means it can't be put after an argument without a whitespace between or inside a quoted argument. Otherwise an error will be thrown.
-
Numbers and strings are allowed as standalone arguments or to be combined with other arguments.
-
If no command is passed (no first argument) then an error is thrown.
This function behaves exactly like $ with the difference that stdio is set to inherit and therefore can't be used later. It returns a Promise<ShexecExecInheritedOutput>.
async function inherit(template: TemplateStringsArray, ...substitutions: ShexecSubstitution): Promise<ShexecExecInheritedOutput>This function behaves exactly like $ but with some differences. Stdio is set to piped and the process is spawned inmediatly; but it's not awaited and instead returns a Deno.ChildProcess.
function spawn(template: TemplateStringsArray, ...substitutions: ShexecSubstitution): Deno.ChildProcessThis function behaves exactly like $.spawn but with the difference that stdio is set to inherit and therefore trying to access it's contents will throw an error.
function spawnInherit(template: TemplateStringsArray, ...substitutions: ShexecSubstitution): Deno.ChildProcessThis function parses the template tag that is passed to the other $ functions and returns an object with the executable and arguments.
function parse(template: TemplateStringsArray, ...substitutions: ShexecSubstitution): { executable: string; arguments: string[] };shexec uses Deno's built-in test feature. To run all the tests, use the following command:
deno testYou can also pass the --filter flag to run specific tests based on their name pattern:
deno test --filter match-patternTo see the available test names, you can check the source code. Some of the test names include:
parsingspawning
shexec uses Deno's expect from the Deno Standard Library for testing, which is licensed under the MIT license. I do not own nor have any right over this dependency.
shexec uses pillarjs's iconv-lite for decoding, which is licensed under the MIT license. I do not own nor have any right over this dependency.
shexec is licensed under the MIT License. By using this library, you agree to all the terms and conditions stated in the license.
