{"id":10733,"library":"destroyable-server","title":"Node.js Destroyable Server","description":"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.","status":"active","version":"1.1.1","language":"javascript","source_language":"en","source_url":"ssh://git@github.com/httptoolkit/destroyable-server","tags":["javascript","server","close","destroy","shutdown","net","tls","http","typescript"],"install":[{"cmd":"npm install destroyable-server","lang":"bash","label":"npm"},{"cmd":"yarn add destroyable-server","lang":"bash","label":"yarn"},{"cmd":"pnpm add destroyable-server","lang":"bash","label":"pnpm"}],"dependencies":[],"imports":[{"note":"This package uses named exports. A default import is incorrect.","wrong":"import makeDestroyable from 'destroyable-server';","symbol":"makeDestroyable","correct":"import { makeDestroyable } from 'destroyable-server';"},{"note":"CommonJS requires destructuring for the named export. Importing the entire module directly would result in an object containing the function.","wrong":"const makeDestroyable = require('destroyable-server');","symbol":"makeDestroyable","correct":"const { makeDestroyable } = require('destroyable-server');"},{"note":"TypeScript users can import the `MakeDestroyable` type for explicit type annotations on server instances that have been made destroyable.","symbol":"MakeDestroyable","correct":"import type { MakeDestroyable } from 'destroyable-server';"}],"quickstart":{"code":"import { createServer } from 'net';\nimport { makeDestroyable } from 'destroyable-server';\n\nconst PORT = process.env.PORT ?? 8000;\n\n// Create a basic TCP server\nlet server = createServer((socket) => {\n  console.log('Client connected.');\n\n  socket.write('Hello from destroyable-server!\\n');\n  socket.on('end', () => {\n    console.log('Client disconnected.');\n  });\n\n  // Example: close connection after 5 seconds\n  setTimeout(() => {\n    if (!socket.destroyed) {\n      socket.end('Server closing connection.\\n');\n    }\n  }, 5000);\n});\n\n// Make the server destroyable\nserver = makeDestroyable(server);\n\nserver.listen(PORT, () => {\n  console.log(`Server listening on port ${PORT}.`);\n});\n\n// Simulate a shutdown after 10 seconds\nsetTimeout(async () => {\n  console.log('Initiating server shutdown...');\n  try {\n    await server.destroy();\n    console.log('Server and all connections destroyed successfully.');\n  } catch (error) {\n    console.error('Error during server destruction:', error);\n  }\n  // In a real application, you might then exit the process: process.exit(0);\n}, 10000);\n","lang":"typescript","description":"This quickstart demonstrates creating a Node.js TCP server, making it destroyable, and then gracefully shutting it down by forcibly closing all active connections after a delay."},"warnings":[{"fix":"While the mutation is intended behavior, developers should treat the return value of `makeDestroyable` as the primary reference for the enhanced server, as shown in `server = makeDestroyable(server);`.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Always use `await server.destroy();` when initiating a shutdown to ensure complete resource cleanup before continuing or exiting the process.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"},{"fix":"Ensure that the object passed to `makeDestroyable` is an instance of `net.Server` or a compatible derivative like `http.Server` or `https.Server`.","message":"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.","severity":"gotcha","affected_versions":">=1.0.0"}],"env_vars":null,"last_verified":"2026-04-19T00:00:00.000Z","next_check":"2026-07-18T00:00:00.000Z","problems":[{"fix":"Ensure you have called `server = makeDestroyable(server);` (or similar assignment) on your server instance before attempting to invoke `server.destroy()`.","cause":"You are attempting to call `destroy()` on a server object that has not been enhanced by `makeDestroyable`.","error":"TypeError: server.destroy is not a function"},{"fix":"Always `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.","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.","error":"Error: listen EADDRINUSE: address already in use :::PORT"}],"ecosystem":"npm"}