or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

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

0

# npm-watch

1

2

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.

3

4

## Package Information

5

6

- **Package Name**: npm-watch

7

- **Package Type**: npm

8

- **Language**: JavaScript

9

- **Installation**: `npm install npm-watch`

10

11

## Core Imports

12

13

For programmatic usage:

14

15

```javascript

16

// Direct import of the main module (recommended)

17

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

18

```

19

20

**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.

21

22

## Basic Usage

23

24

### CLI Usage

25

26

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

27

28

```json

29

{

30

"watch": {

31

"test": "{src,test}/*.js",

32

"build": "src/**/*.js"

33

},

34

"scripts": {

35

"test": "mocha test/*.js",

36

"build": "webpack --mode=development",

37

"watch": "npm-watch"

38

}

39

}

40

```

41

42

Run the watcher:

43

44

```bash

45

npm run watch

46

```

47

48

### Programmatic Usage

49

50

```javascript

51

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

52

53

// Watch all configured tasks

54

const watcher = watchPackage(

55

process.cwd(), // directory containing package.json

56

process.exit, // exit callback

57

"" // empty string watches all tasks

58

);

59

60

// Handle input/output streams

61

process.stdin.pipe(watcher);

62

watcher.stdout.pipe(process.stdout);

63

watcher.stderr.pipe(process.stderr);

64

65

// Watch a specific task only

66

const specificWatcher = watchPackage(

67

"/path/to/project", // project directory

68

(code) => { // custom exit handler

69

console.log(`Watcher exited with code: ${code}`);

70

process.exit(code);

71

},

72

"test" // watch only the "test" script

73

);

74

```

75

76

**Advanced Example with Custom Stream Handling:**

77

78

```javascript

79

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

80

const fs = require("fs");

81

82

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

83

84

// Log all output to a file

85

const logStream = fs.createWriteStream("watch.log", { flags: "a" });

86

watcher.stdout.pipe(logStream);

87

watcher.stderr.pipe(logStream);

88

89

// Also display to console

90

watcher.stdout.pipe(process.stdout);

91

watcher.stderr.pipe(process.stderr);

92

93

// Handle stdin for interactive restart commands

94

process.stdin.pipe(watcher);

95

```

96

97

## Architecture

98

99

npm-watch consists of several key components:

100

101

- **CLI Interface**: Command-line wrapper that sets up PATH and invokes the main module

102

- **Watch Engine**: Main module that reads package.json configuration and manages file watchers

103

- **Process Management**: Spawns and manages nodemon processes for each watch task

104

- **Stream Handling**: Manages stdin/stdout/stderr pipes and input processing

105

- **Cross-Platform Support**: Handles platform differences for Windows and Unix-like systems

106

107

## Capabilities

108

109

### CLI Binary

110

111

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

112

113

```bash { .api }

114

npm-watch [taskName] [directory]

115

```

116

117

**Parameters:**

118

- `taskName` (optional): Specific script name from package.json to watch (process.argv[2])

119

- `directory` (optional): Directory to watch (process.argv[3], defaults to current working directory)

120

121

**Interactive Commands:**

122

- `rs`: Restart all watching processes

123

- `rs <taskName>`: Restart specific watching process

124

125

**Environment Setup:**

126

The CLI automatically handles cross-platform PATH setup:

127

- Adds `<packageDir>/node_modules/.bin` to PATH/Path environment variable

128

- Uses correct executable names for Windows (.cmd) vs Unix systems

129

- Pipes stdin/stdout/stderr between the main process and watch-package module

130

131

### Main Module Export

132

133

Core programmatic interface for creating file watchers.

134

135

```javascript { .api }

136

/**

137

* Creates a watcher for npm scripts based on package.json configuration

138

* @param {string} pkgDir - Directory containing package.json file

139

* @param {function} exit - Exit callback function, called with error code on failure

140

* @param {string} taskName - Specific task to watch; empty string or undefined watches all configured tasks

141

* @returns {Stream} Transform stream (through2) for stdin handling with additional stdout/stderr properties

142

*/

143

function watchPackage(pkgDir, exit, taskName)

144

```

145

146

**Return Value Properties:**

147

- `.stdout`: Transform stream for script output (through2 stream)

148

- `.stderr`: Transform stream for script errors (through2 stream)

149

- Stream itself: Handles stdin input for interactive commands like "rs"

150

151

**Input Commands:**

152

- `rs\n`: Restart all watching processes

153

- `rs <taskName>\n`: Restart specific watching process by name

154

155

**Error Handling:**

156

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

157

- Code 1: Missing "watch" configuration in package.json

158

- Code 2: Specified script doesn't exist in package.json scripts section

159

160

**Process Management:**

161

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

162

163

### Internal Utilities

164

165

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

166

167

```javascript { .api }

168

/**

169

* Creates a transform stream that prefixes output lines with a given prefix

170

* Used internally to distinguish output from different watch tasks

171

* @param {string} prefix - The prefix to add to each line (e.g., "[test]")

172

* @returns {Stream} Transform stream that prefixes each line

173

*/

174

function prefixer(prefix)

175

176

/**

177

* Starts a nodemon process for a specific script with watch configuration

178

* Used internally by watchPackage to create individual watchers

179

* @param {string} script - Script name from package.json

180

* @param {object} pkg - Parsed package.json content

181

* @param {object} processes - Process registry for tracking spawned processes

182

* @param {boolean} setMaxListeners - Whether to set max listeners for event emitters

183

* @param {number} scriptsCount - Total number of scripts for listener calculation

184

*/

185

function startScript(script, pkg, processes, setMaxListeners, scriptsCount)

186

```

187

188

### Configuration Schema

189

190

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

191

192

#### Simple Pattern Format

193

194

```javascript { .api }

195

interface SimpleWatchConfig {

196

[scriptName: string]: string | string[];

197

}

198

```

199

200

**Example:**

201

```json

202

{

203

"watch": {

204

"test": "src/**/*.js",

205

"build": ["src", "config"]

206

}

207

}

208

```

209

210

#### Advanced Configuration Format

211

212

```javascript { .api }

213

interface AdvancedWatchConfig {

214

[scriptName: string]: {

215

patterns: string | string[]; // Glob patterns to watch

216

extensions?: string; // Comma-separated file extensions

217

ignore?: string | string[]; // Patterns to ignore

218

quiet?: boolean; // Hide script name in output

219

inherit?: boolean; // Inherit parent process stdio

220

legacyWatch?: boolean; // Enable nodemon legacy watch mode

221

delay?: number; // Restart delay in milliseconds

222

clearBuffer?: boolean; // Clear output buffer on restart

223

verbose?: boolean; // Enable nodemon verbose mode

224

runOnChangeOnly?: boolean; // Run only on file changes, not startup

225

silent?: boolean; // Enable nodemon silent mode

226

};

227

}

228

```

229

230

**Example:**

231

```json

232

{

233

"watch": {

234

"test": {

235

"patterns": ["src", "test"],

236

"extensions": "js,jsx,ts",

237

"ignore": ["build", "node_modules"],

238

"quiet": false,

239

"legacyWatch": false,

240

"delay": 1000,

241

"runOnChangeOnly": true

242

},

243

"build": {

244

"patterns": ["src/**/*.js"],

245

"extensions": "js,ts",

246

"clearBuffer": true,

247

"verbose": false,

248

"silent": false

249

},

250

"lint": {

251

"patterns": "src",

252

"extensions": "js,jsx,ts,tsx",

253

"inherit": true,

254

"ignore": "src/vendor"

255

}

256

}

257

}

258

```

259

260

**Real-world Configuration Examples:**

261

262

```json

263

{

264

"watch": {

265

"test:unit": {

266

"patterns": ["src", "test/unit"],

267

"extensions": "js,ts",

268

"runOnChangeOnly": true,

269

"quiet": true

270

},

271

"test:integration": {

272

"patterns": ["src", "test/integration"],

273

"extensions": "js,ts",

274

"delay": 2000

275

},

276

"build:dev": {

277

"patterns": "src",

278

"extensions": "js,jsx,ts,tsx",

279

"clearBuffer": true,

280

"ignore": ["src/**/*.test.js", "src/**/*.spec.js"]

281

}

282

},

283

"scripts": {

284

"test:unit": "jest --testPathPattern=unit",

285

"test:integration": "jest --testPathPattern=integration",

286

"build:dev": "webpack --mode=development"

287

}

288

}

289

```

290

291

#### Global Configuration

292

293

```javascript { .api }

294

interface WatchGlobalConfig {

295

setMaxListeners?: boolean; // Set max event listeners to avoid warnings

296

}

297

```

298

299

Applied to package.json as:

300

```json

301

{

302

"watchGlobalConfig": {

303

"setMaxListeners": true

304

}

305

}

306

```

307

308

309

## Error Handling

310

311

npm-watch provides several types of error handling:

312

313

- **Configuration Validation**: Verifies that `"watch"` configuration exists in package.json

314

- **Script Validation**: Ensures specified scripts exist in the `"scripts"` section

315

- **Option Conflicts**: Detects and reports conflicting options (e.g., verbose + silent)

316

- **Process Management**: Handles child process failures and cleanup

317

318

**Common Errors:**

319

- `No "watch" config in package.json`: Missing watch configuration

320

- `No such script "scriptName"`: Referenced script doesn't exist

321

- `Silent and Verbose can not both be on`: Conflicting configuration options

322

323

## Platform Support

324

325

npm-watch provides cross-platform compatibility:

326

327

- **Windows**: Uses `.cmd` variants of executables (npm.cmd, nodemon.cmd) and handles PATH differences

328

- **Unix-like Systems**: Uses standard executables and ANSI escape sequences

329

- **Shell Integration**: Automatically adds node_modules/.bin to PATH for script execution

330

331

## Dependencies

332

333

npm-watch relies on these key dependencies:

334

335

- **nodemon** (^3.0.1): Core file watching and process restarting functionality

336

- **through2** (^4.0.2): Stream transformation utilities for input/output handling

337

- **child_process.spawn**: Node.js built-in for process creation and management

338

339

## Troubleshooting

340

341

### Common Issues

342

343

**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:

344

345

```bash

346

npm install -g nodemon

347

```

348

349

**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.

350

351

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

352

353

```json

354

{

355

"watchGlobalConfig": {

356

"setMaxListeners": true

357

}

358

}

359

```