or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-npm-watch

CLI tool that automatically runs npm scripts when files change using configurable file watching patterns

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/npm-watch@0.13.x

To install, run

npx @tessl/cli install tessl/npm-npm-watch@0.13.0

index.mddocs/

npm-watch

npm-watch is a CLI tool and Node.js module that automatically runs npm scripts when files in your project change. It wraps nodemon to provide configuration-driven file watching, enabling development workflows with automatic test execution, live reloading, and build processes.

Package Information

  • Package Name: npm-watch
  • Package Type: npm
  • Language: JavaScript
  • Installation: npm install npm-watch

Core Imports

For programmatic usage:

// Direct import of the main module (recommended)
const watchPackage = require("npm-watch/watch-package");

Important: The package.json specifies "main": "index.js" but this file doesn't exist in the package. The actual entry point is watch-package.js, so you must specify the full path when requiring the module programmatically.

Basic Usage

CLI Usage

Add a "watch" configuration to your package.json and a watch script:

{
  "watch": {
    "test": "{src,test}/*.js",
    "build": "src/**/*.js"
  },
  "scripts": {
    "test": "mocha test/*.js",
    "build": "webpack --mode=development", 
    "watch": "npm-watch"
  }
}

Run the watcher:

npm run watch

Programmatic Usage

const watchPackage = require("npm-watch/watch-package");

// Watch all configured tasks
const watcher = watchPackage(
  process.cwd(),        // directory containing package.json
  process.exit,         // exit callback
  ""                    // empty string watches all tasks
);

// Handle input/output streams
process.stdin.pipe(watcher);
watcher.stdout.pipe(process.stdout);
watcher.stderr.pipe(process.stderr);

// Watch a specific task only
const specificWatcher = watchPackage(
  "/path/to/project",   // project directory
  (code) => {           // custom exit handler
    console.log(`Watcher exited with code: ${code}`);
    process.exit(code);
  },
  "test"               // watch only the "test" script
);

Advanced Example with Custom Stream Handling:

const watchPackage = require("npm-watch/watch-package");
const fs = require("fs");

const watcher = watchPackage(process.cwd(), process.exit, "");

// Log all output to a file
const logStream = fs.createWriteStream("watch.log", { flags: "a" });
watcher.stdout.pipe(logStream);
watcher.stderr.pipe(logStream);

// Also display to console
watcher.stdout.pipe(process.stdout);
watcher.stderr.pipe(process.stderr);

// Handle stdin for interactive restart commands
process.stdin.pipe(watcher);

Architecture

npm-watch consists of several key components:

  • CLI Interface: Command-line wrapper that sets up PATH and invokes the main module
  • Watch Engine: Main module that reads package.json configuration and manages file watchers
  • Process Management: Spawns and manages nodemon processes for each watch task
  • Stream Handling: Manages stdin/stdout/stderr pipes and input processing
  • Cross-Platform Support: Handles platform differences for Windows and Unix-like systems

Capabilities

CLI Binary

Command-line interface for running npm-watch. The CLI automatically adds node_modules/.bin to the PATH before executing.

npm-watch [taskName] [directory]

Parameters:

  • taskName (optional): Specific script name from package.json to watch (process.argv[2])
  • directory (optional): Directory to watch (process.argv[3], defaults to current working directory)

Interactive Commands:

  • rs: Restart all watching processes
  • rs <taskName>: Restart specific watching process

Environment Setup: The CLI automatically handles cross-platform PATH setup:

  • Adds <packageDir>/node_modules/.bin to PATH/Path environment variable
  • Uses correct executable names for Windows (.cmd) vs Unix systems
  • Pipes stdin/stdout/stderr between the main process and watch-package module

Main Module Export

Core programmatic interface for creating file watchers.

/**
 * Creates a watcher for npm scripts based on package.json configuration
 * @param {string} pkgDir - Directory containing package.json file
 * @param {function} exit - Exit callback function, called with error code on failure
 * @param {string} taskName - Specific task to watch; empty string or undefined watches all configured tasks
 * @returns {Stream} Transform stream (through2) for stdin handling with additional stdout/stderr properties
 */
function watchPackage(pkgDir, exit, taskName)

Return Value Properties:

  • .stdout: Transform stream for script output (through2 stream)
  • .stderr: Transform stream for script errors (through2 stream)
  • Stream itself: Handles stdin input for interactive commands like "rs"

Input Commands:

  • rs\n: Restart all watching processes
  • rs <taskName>\n: Restart specific watching process by name

Error Handling: The function validates configuration and calls the exit callback with error codes:

  • Code 1: Missing "watch" configuration in package.json
  • Code 2: Specified script doesn't exist in package.json scripts section

Process Management: Creates nodemon child processes for each configured watch task, manages their stdio streams, and handles process cleanup on termination.

Internal Utilities

These functions are used internally but may be useful for understanding the implementation:

/**
 * Creates a transform stream that prefixes output lines with a given prefix
 * Used internally to distinguish output from different watch tasks
 * @param {string} prefix - The prefix to add to each line (e.g., "[test]")
 * @returns {Stream} Transform stream that prefixes each line
 */
function prefixer(prefix)

/**
 * Starts a nodemon process for a specific script with watch configuration
 * Used internally by watchPackage to create individual watchers
 * @param {string} script - Script name from package.json
 * @param {object} pkg - Parsed package.json content
 * @param {object} processes - Process registry for tracking spawned processes
 * @param {boolean} setMaxListeners - Whether to set max listeners for event emitters
 * @param {number} scriptsCount - Total number of scripts for listener calculation
 */
function startScript(script, pkg, processes, setMaxListeners, scriptsCount)

Configuration Schema

npm-watch reads configuration from the "watch" object in package.json.

Simple Pattern Format

interface SimpleWatchConfig {
  [scriptName: string]: string | string[];
}

Example:

{
  "watch": {
    "test": "src/**/*.js",
    "build": ["src", "config"]
  }
}

Advanced Configuration Format

interface AdvancedWatchConfig {
  [scriptName: string]: {
    patterns: string | string[];           // Glob patterns to watch
    extensions?: string;                   // Comma-separated file extensions
    ignore?: string | string[];            // Patterns to ignore
    quiet?: boolean;                       // Hide script name in output
    inherit?: boolean;                     // Inherit parent process stdio
    legacyWatch?: boolean;                 // Enable nodemon legacy watch mode
    delay?: number;                        // Restart delay in milliseconds
    clearBuffer?: boolean;                 // Clear output buffer on restart
    verbose?: boolean;                     // Enable nodemon verbose mode
    runOnChangeOnly?: boolean;             // Run only on file changes, not startup
    silent?: boolean;                      // Enable nodemon silent mode
  };
}

Example:

{
  "watch": {
    "test": {
      "patterns": ["src", "test"],
      "extensions": "js,jsx,ts",
      "ignore": ["build", "node_modules"],
      "quiet": false,
      "legacyWatch": false,
      "delay": 1000,
      "runOnChangeOnly": true
    },
    "build": {
      "patterns": ["src/**/*.js"],
      "extensions": "js,ts",
      "clearBuffer": true,
      "verbose": false,
      "silent": false
    },
    "lint": {
      "patterns": "src",
      "extensions": "js,jsx,ts,tsx",
      "inherit": true,
      "ignore": "src/vendor"
    }
  }
}

Real-world Configuration Examples:

{
  "watch": {
    "test:unit": {
      "patterns": ["src", "test/unit"],
      "extensions": "js,ts",
      "runOnChangeOnly": true,
      "quiet": true
    },
    "test:integration": {
      "patterns": ["src", "test/integration"],
      "extensions": "js,ts",
      "delay": 2000
    },
    "build:dev": {
      "patterns": "src",
      "extensions": "js,jsx,ts,tsx",
      "clearBuffer": true,
      "ignore": ["src/**/*.test.js", "src/**/*.spec.js"]
    }
  },
  "scripts": {
    "test:unit": "jest --testPathPattern=unit",
    "test:integration": "jest --testPathPattern=integration",
    "build:dev": "webpack --mode=development"
  }
}

Global Configuration

interface WatchGlobalConfig {
  setMaxListeners?: boolean;              // Set max event listeners to avoid warnings
}

Applied to package.json as:

{
  "watchGlobalConfig": {
    "setMaxListeners": true
  }
}

Error Handling

npm-watch provides several types of error handling:

  • Configuration Validation: Verifies that "watch" configuration exists in package.json
  • Script Validation: Ensures specified scripts exist in the "scripts" section
  • Option Conflicts: Detects and reports conflicting options (e.g., verbose + silent)
  • Process Management: Handles child process failures and cleanup

Common Errors:

  • No "watch" config in package.json: Missing watch configuration
  • No such script "scriptName": Referenced script doesn't exist
  • Silent and Verbose can not both be on: Conflicting configuration options

Platform Support

npm-watch provides cross-platform compatibility:

  • Windows: Uses .cmd variants of executables (npm.cmd, nodemon.cmd) and handles PATH differences
  • Unix-like Systems: Uses standard executables and ANSI escape sequences
  • Shell Integration: Automatically adds node_modules/.bin to PATH for script execution

Dependencies

npm-watch relies on these key dependencies:

  • nodemon (^3.0.1): Core file watching and process restarting functionality
  • through2 (^4.0.2): Stream transformation utilities for input/output handling
  • child_process.spawn: Node.js built-in for process creation and management

Troubleshooting

Common Issues

Monorepo Setups: In monorepo environments, npm-watch may fail with ENOENT errors. This typically occurs when nodemon is not available in the expected location. The solution is to install nodemon globally:

npm install -g nodemon

PATH Issues: The CLI automatically adds node_modules/.bin to PATH, but in some environments this may not work as expected. Ensure nodemon is installed as a dependency or globally available.

Memory Warnings: If you see "MaxListenersExceededWarning" messages, add the global configuration:

{
  "watchGlobalConfig": {
    "setMaxListeners": true
  }
}