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 🙏

© 2026 – Pkg Stats / Ryan Hefner

@dwtechs/servpico-express

v0.3.1

Published

Open source library to start and close Express.js service properly.

Readme

License: MIT npm version last version release date Jest:coverage

Synopsis

Servpico-express.js is an open source library to start and close Express.js service properly.

  • ⚡ Built for speed
  • 📦 Only 1 dependency to log service activity properly
  • 🪶 Very lightweight
  • 🧪 Thoroughly tested
  • 🚚 Shipped as ES2022 ECMAScript module
  • 📝 Written in Typescript

Installation

$ npm i @dwtechs/servpico-express

Configuration

Servpico-express reads the following environment variables:

| Variable | Required | Default | Description | | ---------------------- | -------- | ------- | ----------------------------------------------------------------------------------------------- | | PORT | no | 3000 | Port to bind. Must be an integer in [1, 65535]; invalid values fall back to the default. | | SHUTDOWN_TIMEOUT_MS | no | 10000 | Force-exit deadline (ms) if server.close() doesn't complete — see Shutdown behavior. |

Usage


import express from "express";
import { listen, failFast } from "@dwtechs/servpico-express";

// Usual express app initialization
const app = express();
// ...

app.get('/', (req, res) => res.send('Hello World!'));

// Init reference data — fail fast if any init step rejects.
Promise.all([
    // Your init asynchronous functions here
  ])
  .then(() => listen(app))
  .catch(failFast);

// or the simplest way if no asynchronous reference data is needed:
// listen(app);

Using failFast as the .catch handler ensures a rejected init promise terminates the process with exit code 1 (so your container / process manager restarts you) instead of leaving a zombie process alive with no HTTP port bound. See the API Reference for the full rationale.

listen() automatically registers graceful shutdown handlers for SIGTERM, SIGINT, and SIGHUP signals, which will call close() on the server.

Startup errors

Bind failures (EADDRINUSE, EACCES, EADDRNOTAVAIL, ...) surface asynchronously via the underlying HTTP server's error event, not as a synchronous throw. Since 0.3.1 listen() attaches a listener for that event and routes failures through failFast, producing the same clean [servpico-express] App cannot start: ... output as the pre-listen() init path. Post-listen server-level errors (rare — FD exhaustion, kernel socket issues) are logged as Server error after listening: ... and also trigger a deferred process.exit(1). In both cases the orchestrator can restart cleanly rather than seeing an unprefixed Node stack trace or a zombie.

Shutdown behavior

close() (invoked automatically on SIGTERM / SIGINT / SIGHUP) awaits server.close(), which itself waits for all in-flight connections to finish. Long-lived keep-alive, SSE, or WebSocket connections can hold that callback open indefinitely — long enough that Kubernetes / Docker / systemd send SIGKILL and terminate the process dirtily.

Since 0.3.1 close() starts a force-exit timer (default 10000 ms, configurable via SHUTDOWN_TIMEOUT_MS). If server.close() hasn't completed in time, the process logs a warning and exits 1 on its own — inside your own grace window, with a clean log line explaining what happened. The timer is unref'd so it doesn't itself keep the event loop alive.

The success-path exit is also deferred via setImmediate so the final "Service closed" log line flushes to piped stdout / stderr before the process exits.

Test with docker

Get the container id with "docker ps" command and kill the container like this :

$ docker ps
$ docker kill --signal=SIGTERM <container_name_or_id>

API Reference


// Start the server on process.env.PORT (default: 3000).
// Automatically registers SIGTERM, SIGINT, and SIGHUP handlers for graceful shutdown.
// Since 0.3.1: attaches a server 'error' listener; bind failures
// (EADDRINUSE / EACCES / ...) route through failFast for a clean exit
// instead of an unprefixed Node stack trace.
function listen(app: Express): void;

// Gracefully close an HTTP server and exit the process with code 0.
// Called automatically by listen() on termination signals.
// Use this directly only if you manage the server lifecycle yourself.
// Since 0.3.1: starts a force-exit timer (SHUTDOWN_TIMEOUT_MS, default
// 10000ms) so long-lived connections can't zombie the shutdown, and the
// success exit is deferred via setImmediate for log-flush parity with
// failFast.
function close(server: Server): void;

// Terminal handler for unrecoverable boot-time errors. Intended as a
// `.catch` handler on the pre-listen() init pipeline:
//
//   Promise.all([svc1.init(), svc2.init()]).then(() => listen(app)).catch(failFast);
//
// Logs the error (message + stack) with the `[servpico-express]` prefix,
// then defers process.exit(1) by one tick via setImmediate so the log
// line can flush to stderr on piped destinations (Docker, systemd, PM2).
//
// Required (rather than a naked process.exit(1) in your own .catch)
// because: (1) init() rejections mean listen() was never called, so the
// SIGTERM/SIGINT/SIGHUP handlers registered inside listen() don't exist
// — open handles from imported modules (DB pools, timers) would keep the
// Node runtime alive as a zombie; (2) process.exitCode = 1 alone would
// not help because the event loop never drains; (3) synchronous exit
// without setImmediate would truncate the last log line on piped stderr.
//
// Accepts { message }, { msg }, string, and null/undefined error shapes.
function failFast(err: unknown): never;

Logs

Servpico-express.js uses @dwtechs/Winstan library for logging.

Support

| Environment | Version | | :---------- | :-----: | | Node.js | >= 22 |

Contributors

Servpico-express.js is still in development and we would be glad to get all the help you can provide. To contribute please read contributor.md for detailed installation guide.

Stack

| Purpose | Choice | Motivation | | :-------------- | :------------------------------------------: | -------------------------------------------------------------: | | repository | Github | hosting for software development version control using Git | | package manager | npm | default node.js package manager | | language | TypeScript | static type checking along with the latest ECMAScript features | | module bundler | Rollup | advanced module bundler for ES2022 modules | | unit testing | Jest | delightful testing with a focus on simplicity |