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

node-wrap

v0.2.0

Published

A lightweight, zero-dependency package that wraps your script to restart it once it crashes and to provide other useful stuff

Downloads

6

Readme

Node-Wrap v0.2.0

A lightweight, zero-dependency package that wraps your script to restart it once it crashes and to provide other useful stuff

Install it:

>  npm i --save node-wrap


Menu:    Minimal Example - Full Example - Boot Loop Detection - Forceful KeepAlive - Disclaimer / Issues / Licensing - Status Code Table - TLDR


Let's say you develop a server side application...

...whether it is an API of some sort or something like a Discord bot, you will run into these problems:

  • Node always exits the script if an error can't be caught
  • Even if you don't have that problem, you might still want the ability to restart the entire script

And that is where this package comes into play:

require("node-wrap")("./path/to/the/script/that/should/be/wrapped.js");

The above is the smallest possible way to call the wrapper.

Let's see what that example does:

First of all, it sets these default settings if none are provided:

restartOnCrash: true,    // whether the child process should be restarted after it crashed
crashTimeout: 2000,      // the timeout after a crash after which the child process should be restarted
restartTimeout: 0,       // the timeout after a restart command after which the child process should be restarted
console: true,           // whether node-wrap should log some important info to the main console (stuff like "Starting process" and "Restarting process")
logFile: null,           // logs all status codes to that file, leave null or undefined for no file logging                
logConsoleOutput: null,  // logs all console outputs of the child process to that file, leave null or undefined for no file logging
logTimestamp: true,      // whether a timestamp should be added to the above logs
restartCodes: [],        // what additional exit codes should invoke a restart
bootLoopDetection: 0,    // boot loop prevention mechanism: enter the estimated time in milliseconds it usually takes to INITIALIZE (until an infinite loop of some sort gets started) the child process (0 or leave empty to disable) (higher number = higher stability but also longer delay until the boot loop detection kicks in - if you're unsure or it's unstable, take the biggest number of your measurements)
alwaysKeepAlive: false   // set to true to force node-wrap to insistently keep alive / restart the child process as fast and reliably as possible (unaffected by boot loop detection though)

Afterwards the script begins by starting the provided script as a child process. Because the "logConsoleOutput" property defaulted to null, all stdout (console) output of the child script will be sent to the console of the wrapper. Now the child process already runs! To activate the wrapper's magic powers, you need to exit the child process with a certain code from the following list.

Status Codes

| Code | Action | Description |
| --- | --- | --- |
| 0 | Stop | This completely stops the child and wrapping process |
| 1 | Crash | This triggers a restart if the "restartOnCrash" property of the settings was not set to false (it defaults to true) |
| 2 | Restart | This triggers an intentional restart |

So let's say your Discord bot has a developer-only "/restart" command. To trigger an intentional restart you need to exit the script with the status code 2 (see the table above), just like this:

process.exit(2);

...uhh yes, that's it already! You don't need to add anything more to your script(s)!

Boot Loop Detection:

The boot loop detection mechanism was added in the 0.2.0 update. It basically detects a boot loop and shuts down the script to preserve processing power and bandwidth and free up not needed RAM. Maybe you just introduced an experimental feature to your heavy, resource intensive API. This feature could break your startup sequence completely, resulting in a boot loop. With that error (and you for example on vacation for a week or just at work) you could basically DOS yourself and compromise your entire network and other services / APIs.

Good thing you have Node-Wrap!

It's really simple! You just need to measure the time it takes for your script to initialize (aka connect to other services, read / process files / etc. until it reaches an "infinite loop") and add it to the options object like this:

require("node-wrap")("./index.js", {
    ...
    bootLoopDetection: 3000    // (in ms) highest number of your measurements (the higher the more stable but also a longer delay until the detection kicks in)
}

The above setting will calculate a threshold time for you. If while this threshold is not reached the child process crashes five times in a row, the child process will not be restarted on crash anymore. You might have to play around with this time a bit but usually the time until your script initialized is the median value.

But what if you want stability instead?

Node-Wrap has got you covered again! Just add the alwaysKeepAlive property to your options object like this:

require("node-wrap")("./index.js", {
    ...
    alwaysKeepAlive: true    // this makes node-wrap try its hardest to keep the child process alive at all cost
}

The above example will force Node-Wrap to restart the child process even if an internal error occurred. Note: this disables all boot loop detections and automatically reduces all timeouts to 50ms. This means a boot loop could be hogging resources like crazy if it occurred.

Just to recap / TLDR:

  1. Create another script file that only contains the minimal example above or the full example at the bottom of this readme if you want to configure it yourself
  2. Change the "main" property in your "package.json" to start the new file you just made instead (also change other things if you have any to make sure the new file is being run)
  3. Add the needed process.exit(code) function(s) to your script(s) to trigger the wanted action(s)

Full example with all options (some of them changed from default):

require("node-wrap")("./index.js", {
    restartOnCrash: true,                   // whether the child process should be restarted after it crashed
    crashTimeout: 20000,                    // the timeout after a crash after which the child process should be restarted
    restartTimeout: 1000,                   // the timeout after a restart command after which the child process should be restarted
    console: true,                          // whether node-wrap should log some important info to the main console (stuff like "Starting process" and "Restarting process")
    logFile: "./logs/wrapper.log",          // logs all status codes to that file, leave null or undefined for no file logging
    logConsoleOutput: "./logs/console.log", // logs all console outputs of the child process to that file, leave null or undefined for no file logging
    logTimestamp: false,                    // whether a timestamp should be added to the above logs
    restartCodes: [2, 3, 4],                // what additional exit codes should invoke a restart
    bootLoopDetection: 3000,                // boot loop prevention mechanism: enter the estimated time in milliseconds it usually takes to INITIALIZE (until an infinite loop of some sort gets started) the child process (0 or leave empty to disable) (higher number = higher stability but also longer delay until the boot loop detection kicks in - if you're unsure or it's unstable, take the biggest number of your measurements and/or add a few seconds)
    alwaysKeepAlive: false                  // set to true to force node-wrap to insistently keep alive / restart the child process as fast and reliably as possible (unaffected by boot loop detection though)
});

Disclaimer / Issues / Licensing:

Even though this package should do the job just fine, I can't guarantee anything. I try my best to make it as reliable as possible but if you have any complaints or want to suggest a feature, please create a new issue here and I will get to you ASAP. Additionally, I hereby (and by the provided MIT license) free myself of any liability and legal consequences. This package was not made with the intention of being malicious so if it is used in criminal activities, I can't be held responsible. If you modify or share this package you are free to do that under one single condition: It has to still include the "LICENSE" file (also I'd be happy if you contact me, maybe I'll even advertise your version)