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 🙏

© 2024 – Pkg Stats / Ryan Hefner

spawn-wrap

v2.0.0

Published

Wrap all spawned Node.js child processes by adding environs and arguments ahead of the main JavaScript file argument.

Downloads

18,341,943

Readme

spawn-wrap

Wrap all spawned Node.js child processes by adding environs and arguments ahead of the main JavaScript file argument.

Any child processes launched by that child process will also be wrapped in a similar fashion.

This is a bit of a brutal hack, designed primarily to support code coverage reporting in cases where tests or the system under test are loaded via child processes rather than via require().

It can also be handy if you want to run your own mock executable instead of some other thing when child procs call into it.

Build Status

USAGE

var wrap = require('spawn-wrap')

// wrap(wrapperArgs, environs)
var unwrap = wrap(['/path/to/my/main.js', 'foo=bar'], { FOO: 1 })

// later to undo the wrapping, you can call the returned function
unwrap()

In this example, the /path/to/my/main.js file will be used as the "main" module, whenever any Node or io.js child process is started, whether via a call to spawn or exec, whether node is invoked directly as the command or as the result of a shebang #! lookup.

In /path/to/my/main.js, you can do whatever instrumentation or environment manipulation you like. When you're done, and ready to run the "real" main.js file (ie, the one that was spawned in the first place), you can do this:

// /path/to/my/main.js
// process.argv[1] === 'foo=bar'
// and process.env.FOO === '1'

// my wrapping manipulations
setupInstrumentationOrCoverageOrWhatever()
process.on('exit', function (code) {
  storeCoverageInfoSynchronously()
})

// now run the instrumented and covered or whatever codes
require('spawn-wrap').runMain()

ENVIRONMENT VARIABLES

Spawn-wrap responds to two environment variables, both of which are preserved through child processes.

SPAWN_WRAP_DEBUG=1 in the environment will make this module dump a lot of information to stderr.

SPAWN_WRAP_SHIM_ROOT can be set to a path on the filesystem where the shim files are written in a .node-spawn-wrap-<id> folder. By default this is done in $HOME, but in some environments you may wish to point it at some other root. (For example, if $HOME is mounted as read-only in a virtual machine or container.)

CONTRACTS and CAVEATS

The initial wrap call uses synchronous I/O. Probably you should not be using this script in any production environments anyway.

Also, this will slow down child process execution by a lot, since we're adding a few layers of indirection.

The contract which this library aims to uphold is:

  • Wrapped processes behave identical to their unwrapped counterparts for all intents and purposes. That means that the wrapper script propagates all signals and exit codes.
  • If you send a signal to the wrapper, the child gets the signal.
  • If the child exits with a numeric status code, then the wrapper exits with that code.
  • If the child dies with a signal, then the wrapper dies with the same signal.
  • If you execute any Node child process, in any of the various ways that such a thing can be done, it will be wrapped.
  • Children of wrapped processes are also wrapped.

(Much of this made possible by foreground-child.)

There are a few ways situations in which this contract cannot be adhered to, despite best efforts:

  1. In order to handle cases where node is invoked in a shell script, the PATH environment variable is modified such that the the shim will be run before the "real" node. However, since Windows does not allow executing shebang scripts like regular programs, a node.cmd file is required.
  2. Signal propagation through dash doesn't always work. So, if you use child_process.exec() on systems where /bin/sh is actually dash, then the process may exit with a status code > 128 rather than indicating that it received a signal.
  3. cmd.exe is even stranger with how it propagates and interprets unix signals. If you want your programs to be portable, then probably you wanna not rely on signals too much.
  4. It is possible to escape the wrapping, if you spawn a bash script, and that script modifies the PATH, and then calls a specific node binary explicitly.