server-reviver
v0.1.3
Published
Zero-dependency HTTP endpoint to reload or kill Node.js servers — works with Express, NestJS, Fastify, and raw http.
Maintainers
Readme
server-reviver
Zero-dependency TypeScript library that injects a reload / kill / status HTTP endpoint into any Node.js server — Express, NestJS, Fastify, or raw http.
Inspired by the need to reset server memory without SSH or pm2 access, with proper secret auth and auto-detection of the server entrypoint.
Install
yarn add server-revivernpm install server-reviverpnpm add server-reviverQuick start
Express
import express from 'express';
import { expressReviver } from 'server-reviver';
const app = express();
app.use(expressReviver({
path: '/reviver',
secret: process.env.REVIVER_SECRET,
}));
app.listen(3000);NestJS
// app.module.ts
import { Module, NestModule, MiddlewareConsumer } from '@nestjs/common';
import { nestReviver } from 'server-reviver';
@Module({})
export class AppModule implements NestModule {
configure(consumer: MiddlewareConsumer) {
consumer
.apply(nestReviver({
path: '/reviver',
secret: process.env.REVIVER_SECRET,
})).forRoutes('*');
}
}Standalone HTTPS sidecar (separate port)
import { startReviverServer } from 'server-reviver';
startReviverServer({
port: 9119,
host: '127.0.0.1',
secret: process.env.REVIVER_SECRET,
tls: {
key: './certs/key.pem',
cert: './certs/cert.pem',
fromFiles: true,
},
});Examples
Runnable sample apps are in examples/:
TypeScript config for those examples: examples/tsconfig.json.
Endpoints
All requests go to the configured path (default /reviver).
| Action | Method | Query param / Header | Effect |
|----------|--------|-----------------------------------------------|-------------------------------------------|
| status | GET | ?action=status (default if omitted) | Returns uptime, PID, memory |
| reload | GET | ?action=reload&secret=<secret> | Spawns new process, then process.exit() |
| kill | GET | ?action=kill&secret=<secret> | process.exit(0) after delay |
Secret can be passed as:
- Query param:
?secret=my-secret - Header:
x-reviver-secret: my-secret
Status response example
{
"status": "running",
"pid": 12345,
"uptime": 3661,
"uptimeHuman": "1h 1m 1s",
"memory": {
"heapUsed": "42.10 MB",
"heapTotal": "64.00 MB",
"rss": "88.20 MB",
"external": "1.23 MB"
},
"node": "v20.11.0",
"platform": "linux",
"env": "production",
"timestamp": "2026-05-18T12:00:00.000Z"
}Reload response example
{
"action": "reload",
"message": "Server is restarting.",
"entrypoint": "/app/dist/main.js",
"detectedVia": "package.json",
"pid": 12345,
"at": "2026-05-18T12:00:00.000Z"
}Entrypoint detection
On reload, the lib auto-detects the script to re-spawn using this priority:
options.entrypoint(explicit override)package.json→"main"fieldpackage.json→"scripts.start"(parses the command to find the JS/TS file)- Convention files:
main.js,index.js,server.js,app.js,src/main.js,dist/main.js, etc. process.argv[1](currently running script as last fallback)
API reference
expressReviver(options?): RequestHandler
Connect-compatible middleware for Express / Koa / any Connect-based framework.
nestReviver(options?): NestMiddleware['use']
Functional middleware compatible with MiddlewareConsumer.apply().
createReviverMiddleware(options?): class
Class-based NestJS middleware (injectable).
attachReviver(server, options?): void
Attaches to an existing http.Server without replacing its listeners.
startReviverServer(options?): http.Server | https.Server
Starts an isolated server on a dedicated port (optionally TLS).
createCoreHandler(options?): AsyncFunction
Framework-agnostic handler (req, res) => Promise<boolean>. Returns true if the request was handled.
Options
| Option | Type | Default | Description |
|------------------|-----------------------------------------|---------------|---------------------------------------------------------------|
| path | string | '/reviver' | URL path to expose |
| secret | string | '' (open) | Required secret token. Leave empty only in local dev |
| gracefulDelayMs| number | 200 | Ms to wait before executing action (lets response flush) |
| entrypoint | string | auto-detected | Explicit path to the script to spawn on reload |
| spawnOptions | SpawnOptions | {} | Extra options for child_process.spawn |
| onRequest | (req) => boolean \| Promise<boolean> | () => true | Hook called before auth. Return false to deny |
| onAction | (action, payload) => void | no-op | Hook called after action is dispatched |
| logger | (msg: string) => void \| false | console.log | Pass false to silence all logs |
Security notes
- Always set
secretin any internet-accessible environment. - Bind the standalone sidecar to
127.0.0.1to prevent public exposure. - Use TLS (
startReviverServer({ tls: ... })) for any non-loopback traffic. - Use
onRequestto allow-list IPs or add custom auth logic.
curl examples
# Status (no secret needed if endpoint is open)
curl https://localhost:9119/reviver?action=status -k
# Reload via query param
curl "https://localhost:9119/reviver?action=reload&secret=my-secret" -k
# Reload via header
curl -H "x-reviver-secret: my-secret" "https://localhost:9119/reviver?action=reload" -k
# Kill
curl "https://localhost:9119/reviver?action=kill&secret=my-secret" -kLicense
The MIT License.
