npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

@awalgawe/spawn

v2.1.0

Published

A simple promise wrapper for child_process.spawn that lets you process output streams while waiting for completion

Readme

@awalgawe/spawn

A simple promise wrapper for child_process.spawn that lets you process output streams while waiting for completion.

Why?

Sometimes you need to:

  • Process command output line by line as it comes
  • Wait for the command to finish before continuing
  • Cancel long-running commands
  • Handle errors properly

This is a thin wrapper that makes these common patterns easier.

Installation

npm install @awalgawe/spawn

Usage

Get command output automatically

import spawn from "@awalgawe/spawn";

const { stdout } = await spawn("ls", ["-la"]);
console.log("Files:", stdout.toString());

Handle errors and still get output

try {
  const { code, signal, stdout, stderr } = await spawn("grep", [
    "pattern",
    "nonexistent.txt",
  ]);
  // ...
} catch (err) {
  const { code, signal, stdout, stderr } = err.cause;
  console.log("Command failed:", err.message);
  console.log("Stdout:", stdout.toString());
  console.log("Stderr:", stderr.toString());
}

try {
  let processedStdout = "";
  let processedStderr = "";

  const { code, signal } = await spawn("grep", ["pattern", "nonexistent.txt"], {
    onStdOut: (chunk, abort) => {
      // Process output as it comes
      processedStdout += doSomething(chunk);
    },
    onStdErr: (chunk, abort) => {
      processedStderr += doSomethingElse(chunk);
    },
  });
} catch (err) {
  const { code, signal } = err.cause;
  // ...
}

Process output as it comes

import spawn from "@awalgawe/spawn";

await spawn("ping", ["-c", "5", "google.com"], {
  onStdOut: (chunk, abort) => {
    console.log("Ping:", chunk.toString().trim());
    // You can abort the process at any time
    // if (someCondition) abort();
  },
  onStdErr: (chunk, abort) => {
    console.error("Error:", chunk.toString().trim());
  },
});
console.log("Ping completed");

Handle errors with exit codes

try {
  await spawn("grep", ["pattern", "nonexistent.txt"]);
} catch (err) {
  const { code } = err.cause;
  if (code === 1) {
    console.log("No matches found");
  } else if (code === 2) {
    console.log("File not found or other error");
  }
}

Run commands in specific directories

// Run command in a specific directory
const { stdout } = await spawn("ls", ["-la"], { cwd: "/path/to/directory" });

// Build project in its directory
await spawn("npm", ["install"], { cwd: "./my-project" });
await spawn("npm", ["run", "build"], { cwd: "./my-project" });

Cancel long-running commands

const controller = new AbortController();
setTimeout(() => controller.abort(), 5000);

try {
  await spawn("ping", ["google.com"], {
    signal: controller.signal,
    onStdOut: (chunk, abort) => console.log(chunk.toString()),
  });
} catch (err) {
  console.log("Command was cancelled or failed");
}

Real-world example: Processing log files

let lineBuffer = "";
const errors = [];

await spawn("tail", ["-f", "app.log"], {
  onStdOut: (chunk, abort) => {
    lineBuffer += chunk.toString();
    const lines = lineBuffer.split("\n");
    lineBuffer = lines.pop() || ""; // Keep incomplete line

    lines.forEach((line) => {
      if (line.includes("ERROR")) {
        errors.push(line);
        console.log("Found error:", line);

        // Optionally abort on critical errors
        if (line.includes("CRITICAL")) {
          abort();
        }
      }
    });
  },
  signal: someAbortSignal,
});

TypeScript Support

The return type changes based on which callbacks you provide:

// No callbacks → includes stdout and stderr
const result1 = await spawn("ls");
result1.stdout; // ✅ Buffer
result1.stderr; // ✅ Buffer

// With onStdOut → no stdout property
const result2 = await spawn("ls", [], { onStdOut: (chunk, abort) => {} });
result2.stdout; // ❌ TypeScript error
result2.stderr; // ✅ Buffer

// With onStdErr → no stderr property
const result3 = await spawn("ls", [], { onStdErr: (chunk, abort) => {} });
result3.stdout; // ✅ Buffer
result3.stderr; // ❌ TypeScript error

// With both callbacks → no output properties
const result4 = await spawn("ls", [], {
  onStdOut: (chunk, abort) => {},
  onStdErr: (chunk, abort) => {},
});
result4.stdout; // ❌ TypeScript error
result4.stderr; // ❌ TypeScript error

API

spawn(command, args?, options?)

Returns a promise that resolves when the process completes.

  • command: Command to execute
  • args: Command arguments (optional)
  • options:
    • onStdOut(chunk, abort): Process stdout data as it arrives. The abort function can be called to immediately terminate the process.
    • onStdErr(chunk, abort): Process stderr data as it arrives. The abort function can be called to immediately terminate the process.
    • signal: AbortSignal to cancel the command
    • cwd: Working directory for the child process

Return type varies based on callbacks:

  • No callbacks: { code, signal, stdout: Buffer, stderr: Buffer }
  • With onStdOut: { code, signal, stderr: Buffer }
  • With onStdErr: { code, signal, stdout: Buffer }
  • With both: { code, signal }

Rejects with error details in error.cause which includes { code, signal, stdout?: Buffer, stderr?: Buffer }.

License

MIT