node-comfortv2.0.0

nc.sys

Processes and the system: run commands and get their output, find executables, shut down cleanly, open URLs, and learn about the machine. Behaves the same on Windows, macOS and Linux; on Windows, run("npm", [...]) finds npm.cmd and escapes arguments safely.

const { sys } = require("@ix-xs/node-comfort");
import { run } from "@ix-xs/node-comfort/sys";
const { stdout } = await sys.run("git", ["rev-parse", "HEAD"]);
sys.onShutdown(async () => {
  await server.close();
  await db.close();
});
GuideExplanations and examples for nc.sys.
Read the guide →

Functions

nc.sys.run()

run(file: string, args?: string[], options?: RunOptions): Promise<RunResult>

Runs a program without a shell, so arguments are passed as they are and user input can't inject anything. Resolves with the output; rejects with a ProcessError if the exit code isn't 0.

Parameters

NameTypeDescription
filestringA name found in PATH, or a path.
argsoptionalstring[]Default: []
optionsoptionalRunOptions

Returns Promise<RunResult>

Throws ProcessError If it can't start, fails (unless reject: false) or times out.

Example

const { stdout } = await sys.run("git", ["log", "-1", "--format=%s"]);
await sys.run("npm", ["install"], { cwd: "./app", stdio: "inherit" });
await sys.run("ffmpeg", ["-i", input, output], { timeout: "5m" });

nc.sys.exec()

exec(command: string, options?: RunOptions): Promise<RunResult>

Runs a command line through the shell, so pipes, && and variables work. Don't build it from untrusted input; use run() for that.

Parameters

NameType
commandstring
optionsoptionalRunOptions

Returns Promise<RunResult>

Throws ProcessError If it fails (unless reject: false) or times out.

Example

const { stdout } = await sys.exec("git status --short | wc -l");
const { exitCode } = await sys.exec("npm test", { reject: false, stdio: "inherit" });

nc.sys.which()

which(command: string): string | undefined

Finds an executable in PATH, like the which command.

Parameters

NameType
commandstring

Returns string | undefined

Example

sys.which("git");  // "/usr/bin/git"
sys.which("nope"); // undefined

nc.sys.open()

open(target: string): boolean

Opens a URL, file or folder with the default app.

Parameters

NameType
targetstring

Returns boolean: true if the opener started.

Example

sys.open("http://localhost:3000");

nc.sys.onShutdown()

onShutdown(handler: () => unknown, options?: ShutdownOptions): () => void

Runs cleanup code when the process is asked to stop (Ctrl+C, docker stop, kill): close servers, flush logs, disconnect databases. Handlers run in reverse order, then the process exits. If they take longer than timeout, the exit is forced; a second Ctrl+C exits at once.

Parameters

NameTypeDescription
handler() => unknownCan be async.
optionsoptionalShutdownOptions

Returns () => void: Removes the handler.

Example

const server = app.listen(3000);
sys.onShutdown(() => new Promise((done) => server.close(done)));
sys.onShutdown(() => db.close());

nc.sys.isWindows()

isWindows(): boolean

Are we on Windows?

Returns boolean

nc.sys.isMac()

isMac(): boolean

Are we on macOS?

Returns boolean

nc.sys.isLinux()

isLinux(): boolean

Are we on Linux? WSL counts.

Returns boolean

nc.sys.isCI()

isCI(): boolean

Are we running in CI? Detects GitHub Actions, GitLab, CircleCI, Jenkins, Azure, Vercel, Netlify and more.

Returns boolean

Example

if (sys.isCI()) nc.setLevel("warn");

nc.sys.isDocker()

isDocker(): boolean

Are we running inside a container?

Returns boolean

nc.sys.isWSL()

isWSL(): boolean

Are we running in WSL?

Returns boolean

nc.sys.info()

info(): SystemInfo

Facts about the machine and the runtime, handy for bug reports.

Returns SystemInfo

Example

console.table(sys.info());

nc.sys.memory()

memory(): { rss: number; heapTotal: number; heapUsed: number; external: number; arrayBuffers: number; }

Memory used by this process, in bytes.

Returns { rss: number, heapTotal: number, heapUsed: number, external: number, arrayBuffers: number }

Example

nc.num.formatBytes(sys.memory().heapUsed); // "42.1 MB"

Types

Import any of them in TypeScript with import type { RunOptions } from "@ix-xs/node-comfort", or in JavaScript with import("@ix-xs/node-comfort").RunOptions.

RunOptions

Options for run() and exec().

PropertyTypeDescription
cwdoptionalstringWhere to run the command.
envoptionalRecord<string, string | undefined>Extra environment variables, added to process.env.
extendEnvoptionalbooleanSet to false to pass only env, without process.env.
inputoptionalstring | Buffer<ArrayBufferLike>Written to the command's stdin.
timeoutoptionalstring | numberKill the command after this long, like "30s".
signaloptionalAbortSignalKills the command when aborted.
stdiooptional"pipe" | "inherit""inherit" shows the output live instead of capturing it. Defaults to "pipe".
onStdoutoptional((line: string) => void)Called for each line of stdout.
onStderroptional((line: string) => void)Called for each line of stderr.
rejectoptionalbooleanThrow when the exit code isn't 0. Defaults to true.
trimoptionalbooleanDrop the final newline of the output. Defaults to true.

RunResult

A finished command.

PropertyTypeDescription
commandstringThe command line that ran.
stdoutstring
stderrstring
exitCodenumber | nullnull if a signal killed it.
signalstring | null
durationnumberIn milliseconds.

ShutdownOptions

Options for onShutdown(). They apply to all handlers.

PropertyTypeDescription
timeoutoptionalstring | numberHow long the handlers get before the exit is forced. Defaults to 10 seconds.
exitCodeoptionalnumberExit code after a clean shutdown. Defaults to 0.
signalsoptionalSignals[]Signals that trigger it. Defaults to SIGINT, SIGTERM and SIGHUP.

SystemInfo

Returned by info().

PropertyTypeDescription
platformPlatform"win32", "darwin", "linux"...
archstring"x64", "arm64"...
releasestringOS release.
nodestringNode.js version.
cpusnumberNumber of logical CPUs.
cpuModelstring
memory{ total: number; free: number; used: number; }System memory, in bytes.
uptimenumberIn seconds.
hostnamestring
userstring
pidnumber
cibooleanRunning in CI.
dockerbooleanRunning in a container.
wslbooleanRunning in WSL.
node-comfort v2.0.0View the source