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

@radically-straightforward/node

v3.1.7

Published

🔨 Utilities for Node.js

Downloads

616

Readme

Radically Straightforward · Node

🔨 Utilities for Node.js

Installation

$ npm install @radically-straightforward/node

Usage

import * as node from "@radically-straightforward/node";

Graceful Termination

Importing @radically-straightforward/node enables graceful termination, which gives your application the opportunity to clean up resources before exiting.

Graceful termination works by listening to the following signals:

  • SIGINT: Emitted by pressing ⌃C on the terminal.
  • SIGQUIT: Emitted by pressing ⌃\ on the terminal.
  • SIGBREAK: Emitted by pressing Ctrl+Break on the terminal on Windows.
  • SIGHUP: Emitted when the terminal is closed while the application is still running.
  • SIGTERM: Emitted by process managers that wish to terminate the application, for example, systemd, kill, and so forth.
  • SIGUSR2: Emitted by nodemon to indicate that the application should restart.

Note: Some signals, for example, SIGKILL, which may be sent by kill -9, cannot be handled and cause the process to terminate immediately without the opportunity to clean up resources.

When one of these signals is received, the process.once("gracefulTermination") event is emitted, and your application should handle it to close HTTP servers, clear timers, and so forth. The goal is to leave the Node.js event loop empty so that the process may terminate naturally.

Note: The "gracefulTermination" signal is emitted only once.

As one last step before termination, you may handle Node.js’s process.once("beforeExit") event, which is emitted after the Node.js event loop is empty, but before the application terminates. This is useful, for example, to close a database connection, to log that the application terminated gracefully, and so forth.

Note: You may wish to close a database connection on "beforeExit" instead of "gracefulTermination" because during "gracefulTermination" an HTTP server may still need the database connection while it’s responding to the last undergoing requests before closing.

Note: According to Node.js’s documentation you may use "beforeExit" to add more work to the event loop and prevent the process from terminating, but we advise against using it that way.

Note: Use the "beforeExit" event instead of the "exit" event for the following reasons:

  1. The "exit" event handler runs in a constrained environment that only allows for synchronous operations, but your cleanup may need to be asynchronous.
  2. The "exit" event is emitted even when the process is terminating in abnormal conditions, for example, because of an uncaught exception, and under these abnormal conditions graceful termination isn’t appropriate.

After the "gracefulTermination" event is emitted, if the application doesn’t terminate in 10 seconds, then it’s terminated forcefully with process.exit(1).

Example

import http from "node:http";
import "@radically-straightforward/node";

const server = http
  .createServer((request, response) => {
    response.end("gracefulTermination");
  })
  .listen(8000);
process.once("gracefulTermination", () => {
  // If you comment the line below the application remains running for 10 seconds and then it is forcefully terminated.
  server.close();
});

console.log("gracefulTermination: Press ⌃C to gracefully terminate...");
process.once("gracefulTermination", () => {
  console.log("gracefulTermination: Starting graceful termination...");
});
process.once("beforeExit", () => {
  console.log("gracefulTermination: Succeeded.");
});

backgroundJob()

export function backgroundJob(
  {
    onStop,
    ...utilitiesBackgroundJobOptions
  }: Parameters<typeof utilities.backgroundJob>[0],
  job: Parameters<typeof utilities.backgroundJob>[1],
): ReturnType<typeof utilities.backgroundJob>;

This is an extension of @radically-straightforward/utilities’s backgroundJob() which adds support for graceful termination.

Example

import timers from "node:timers/promises";
import * as node from "@radically-straightforward/node";

node.backgroundJob({ interval: 3 * 1000 }, async () => {
  console.log("backgroundJob(): Running background job...");
  await timers.setTimeout(3 * 1000);
  console.log("backgroundJob(): ...finished running background job.");
});

childProcessKeepAlive()

export function childProcessKeepAlive(
  newChildProcess: () =>
    | ReturnType<(typeof childProcess)["spawn"]>
    | Promise<ReturnType<(typeof childProcess)["spawn"]>>,
): void;

Keep a child process alive. If the child process crashes, respawn it. When the process gracefully terminates, gracefully terminate the child process as well.

Example

node.childProcessKeepAlive(() =>
  childProcess.spawn("node", ["--eval", `http.createServer().listen(18000)`], {
    stdio: "inherit",
  }),
);

exit()

export function exit(): void;

On platforms other than Windows, exit() sends a SIGTERM to the process itself, which starts graceful termination. On Windows, this process.emit()s the gracefulTermination event and process.exit()s.