Skip to main content
Deno 2 is finally here 🎉️
Learn more

jog

jogalso known as a leisurely paced run — is a simplified API for running sub-processes in TypeScript for Deno, implemented as a thin wrapper around Deno.run. Stream access to stdout, stdin, and stderr, as well as resource management, is abstracted away. Instead, the data for stdin can be specified once as a buffer, the data from stdout is returned asynchronously as a buffer or mapped to a custom type, and stderr is thrown as an error message if the process terminates unsuccessfully.
jog on GitHub

Tag deno doc License

jog CI Code coverage

Comparison

The following table summarizes the differences between the native Deno API and jog:

Deno.run run.ts
cmd / cwd / env same
stdin Uint8Array / string
stdout / output / status Promise<Uint8Array>
stderr / stderrOutput throw new Error

mod.ts module

The mod.ts module exports all other modules.

run.ts module

The run.ts module defines the run function which starts a sub-process and returns its result asynchronously. The required cmd and optional cwd and env options work exactly like their Deno.run counterparts. The examples assume that the mockcli.ts module is installed as mockcli on the command line. This example demonstrates how run can be used to get data from stdout:

import { Run, run } from "./run.ts";

// Define a process.
const command: Run = {
  cmd: ["mockcli", "answer"],
};

// Run the process.
const buffer: Uint8Array = await run(command);

// print: "42"
Deno.stdout.write(buffer);

Data for stdin can be specified with the input option, either as a string or as a Uint8Array:

import { run } from "./run.ts";

const buffer = await run({
  cmd: ["mockcli", "echo"],
  input: "let's jog!",
});

// print: "let's jog!"
Deno.stdout.write(buffer);

If the process exits with an error, an Error is thrown and the contents of stderr are used as the error message:

import { run } from "./run.ts";

try {
  await run({
    cmd: ["mockcli", "fail"],
    input: "oh no!",
  });
} catch (error) {
  // print: "oh no!"
  console.log(error.message);
}

out.ts module

The out.ts module defines the out function, which extends the run API with an asynchronous mapping function that is applied to the stdout buffer. For example, instead of the buffer itself, one could return its length:

import { Out, out } from "./out.ts";

// Define a process with output mapping.
const command: Out<number> = {
  cmd: ["mockcli", "answer"],
  map: async (x: Promise<Uint8Array>) => (await x).length,
};

// Run the process.
const length: number = await out(command);

// print: 3 (buffer contains "42\n")
console.log(length);

map.ts module

The map.ts module defines common mappings that can be used with the out function, such as getLines, getLinesNonEmpty, getFirst, and getSuccess. For example, getSuccess can be used to check whether a process succeeds:

import { out } from "./out.ts";
import { getSuccess } from "./map.ts";

const worked = await out({
  cmd: ["mockcli", "fail"],
  map: getSuccess,
});

// print: false
console.log(worked);

Custom mapping functions can be defined with the map and mapAsync convenience functions. The pipe function can be used for chaining two mapping functions. In this example, out returns the first line of stdout in uppercase letters:

import { out } from "./out.ts";
import { map, pipe } from "./map.ts";

const result = await out({
  cmd: ["mockcli", "echo"],
  input: "first\nsecond",
  map: pipe(
    pipe(getLines, getFirst),
    map((x) => x.toUpperCase()),
  ),
});

// print: "result"
console.log(line);