tinyexec: Minimal Node.js Process Execution

1.1.1 · active · verified Tue Apr 21

tinyexec is a lightweight Node.js library designed for executing child processes, offering a streamlined, promise-based API as an alternative to Node.js's native `child_process` module or more feature-rich libraries like `execa`. It abstracts away direct stream manipulation, providing a simpler interface for spawning, piping, and awaiting process results. As of its current stable version, 1.1.1, it supports both asynchronous (`x`) and synchronous (`xSync`) command execution, including options for setting timeouts, integrating `AbortSignal` for cancellation, and passing `stdin` input. Key differentiators include its focus on minimalism, automatic resolution of local `node_modules` binaries, and the ability to iterate over process output lines asynchronously. The package is actively maintained with frequent minor releases and bug fixes, and it is ESM-only since version 1.0.0, requiring Node.js 18 or higher.

Common errors

Warnings

Install

Imports

Quickstart

Demonstrates asynchronous (`x`) and synchronous (`xSync`) command execution, including options, piping, and async iteration over output lines. It also shows optional use of `args-tokenizer` for command string parsing.

import { x, xSync } from 'tinyexec';
import { tokenizeArgs } from 'args-tokenizer'; // Optional, for parsing string commands

async function runExample() {
  console.log('--- Async Example (x) ---');
  try {
    const result = await x('ls', ['-l', '.'], {
      timeout: 5000, // Process will be killed after 5 seconds
      throwOnError: true, // Throws an error if exitCode is non-zero
      env: { ...process.env, MY_CUSTOM_VAR: 'hello' } // Pass custom environment variables
    });
    console.log('stdout:', result.stdout.trim());
    console.log('stderr:', result.stderr.trim());
    console.log('exitCode:', result.exitCode);
  } catch (error) {
    console.error('Async process failed:', error);
  }

  console.log('\n--- Async Iteration Example ---');
  const proc = x('node', ['-e', 'console.log("Line 1"); await new Promise(r => setTimeout(r, 10)); console.log("Line 2");']);
  console.log('Output lines:');
  for await (const line of proc) {
    console.log(`- ${line.trim()}`);
  }

  console.log('\n--- Sync Example (xSync) ---');
  try {
    const syncResult = xSync('node', ['-e', 'console.log("Hello from sync"); process.exit(0);']);
    console.log('sync stdout:', syncResult.stdout.trim());
  } catch (error) {
    console.error('Sync process failed:', error);
  }

  console.log('\n--- Piping Example ---');
  // Using args-tokenizer for a more realistic command string parsing example
  const commandString = 'grep .mjs';
  const [grepCommand, ...grepArgs] = tokenizeArgs(commandString);

  const proc1 = x('ls', ['.']);
  const proc2 = proc1.pipe(grepCommand, grepArgs);
  const pipedResult = await proc2;
  console.log('Piped .mjs files:', pipedResult.stdout.trim());
}

runExample();

view raw JSON →