Node.js Destroyable Server
Destroyable-Server, currently at version 1.1.1, is a compact Node.js module designed to enhance the `net.Server` API by providing a reliable and immediate mechanism to terminate all active client connections. When `server.close()` is invoked, it merely ceases to accept new connections, often leaving existing ones open and preventing the Node.js process from exiting cleanly. This library introduces a `destroy()` method to server instances via its `makeDestroyable` utility, which not only stops listening but also forcibly closes every tracked socket. This capability is critical for scenarios requiring rapid server restarts, robust test suite teardowns, or graceful application shutdowns. It works across various `net.Server` subclasses, including HTTP and TLS, and uniquely offers a promise-based interface for awaiting complete connection termination, differentiating it from `server.closeIdleConnections()` which might miss active connections or not be universally available. The project maintains a stable, low-cadence release cycle, reflecting its focused utility and role as part of HTTP Toolkit.
Common errors
-
TypeError: server.destroy is not a function
cause You are attempting to call `destroy()` on a server object that has not been enhanced by `makeDestroyable`.fixEnsure you have called `server = makeDestroyable(server);` (or similar assignment) on your server instance before attempting to invoke `server.destroy()`. -
Error: listen EADDRINUSE: address already in use :::PORT
cause A previous server instance on the same port was not fully shut down before a new one attempted to bind to the port. This often happens when `server.destroy()` was called but not awaited, or if the process exited before the cleanup completed.fixAlways `await server.destroy()` during shutdown routines to guarantee that all connections are closed and the port is released before attempting to restart the server or exit the process.
Warnings
- gotcha The `makeDestroyable` function mutates the server object passed to it, adding internal tracking for connections and the `destroy()` method directly to the instance. Be aware that the original server object reference will be modified.
- gotcha The `server.destroy()` method returns a Promise that resolves once all connections are terminated and the server is fully closed. Failing to `await` this promise can lead to premature process exits or other cleanup logic running before all resources are released, potentially causing resource leaks or 'address already in use' errors on restart.
- gotcha This module is specifically designed for `net.Server` instances and objects following its patterns. Attempting to use `makeDestroyable` on objects that are not `net.Server` instances or lack the necessary underlying socket management may lead to unexpected behavior or errors.
Install
-
npm install destroyable-server -
yarn add destroyable-server -
pnpm add destroyable-server
Imports
- makeDestroyable
import makeDestroyable from 'destroyable-server';
import { makeDestroyable } from 'destroyable-server'; - makeDestroyable
const makeDestroyable = require('destroyable-server');const { makeDestroyable } = require('destroyable-server'); - MakeDestroyable
import type { MakeDestroyable } from 'destroyable-server';
Quickstart
import { createServer } from 'net';
import { makeDestroyable } from 'destroyable-server';
const PORT = process.env.PORT ?? 8000;
// Create a basic TCP server
let server = createServer((socket) => {
console.log('Client connected.');
socket.write('Hello from destroyable-server!\n');
socket.on('end', () => {
console.log('Client disconnected.');
});
// Example: close connection after 5 seconds
setTimeout(() => {
if (!socket.destroyed) {
socket.end('Server closing connection.\n');
}
}, 5000);
});
// Make the server destroyable
server = makeDestroyable(server);
server.listen(PORT, () => {
console.log(`Server listening on port ${PORT}.`);
});
// Simulate a shutdown after 10 seconds
setTimeout(async () => {
console.log('Initiating server shutdown...');
try {
await server.destroy();
console.log('Server and all connections destroyed successfully.');
} catch (error) {
console.error('Error during server destruction:', error);
}
// In a real application, you might then exit the process: process.exit(0);
}, 10000);