Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@gquittet/graceful-server

Package Overview
Dependencies
Maintainers
1
Versions
63
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@gquittet/graceful-server - npm Package Compare versions

Comparing version 1.0.0 to 1.1.0

lib/types/interface/gracefulServerOptions.d.ts

2

lib/index.js

@@ -1,1 +0,1 @@

module.exports=function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t){e.exports=require("events")},function(e,t,n){"use strict";n.r(t);const o={closePromises:[],timeout:1e3,livenessEndpoint:"/live",readinessEndpoint:"/ready"};let r=!0;var s=o;var i=[{type:"SIGHUP",code:1},{type:"SIGBREAK",code:1},{type:"SIGINT",code:2},{type:"SIGTERM",code:15},{type:"uncaughtException",code:2}];var a,u=e=>{for(const t of i)process.on(t.type,async n=>{await e.shutdown(t.type,t.code,n)});return e};!function(e){e.NOT_READY="NOT_READY",e.READY="READY",e.SHUTDOWN="SHUTDOWN",e.SHUTTING_DOWN="SHUTTING_DOWN"}(a||(a={}));var c=a;var d=e=>new Promise(t=>setTimeout(t,e));var l=(e,t)=>async(n,o,r)=>{const{timeout:i,closePromises:a}=s,u=r&&r.message?r:new Error(n);t.status.set(c.SHUTTING_DOWN,u),await d(i),await Promise.all(a.map(e=>e())),await e.stop(),t.status.set(c.SHUTDOWN,u),process.exit(128+o)},f=n(0);var p=e=>(t,n)=>{const{livenessEndpoint:o,readinessEndpoint:r}=s;if(!n.headersSent)return t.url===o&&"GET"===t.method?(n.statusCode=200,n.setHeader("Content-Type","application/json"),n.end(JSON.stringify({uptime:0|process.uptime()}))):t.url===r&&"GET"===t.method?e.isReady()?(n.statusCode=200,n.setHeader("Content-Type","application/json"),n.end(JSON.stringify({status:"ready"}))):(n.statusCode=503,n.end()):void 0};var y=e=>{const t=e||new Set,n=e=>{e.destroy(),t.delete(e)};return{onConnection:e=>{t.add(e),e.once("close",()=>t.delete(e))},closeAll:async()=>t.forEach(n)}};var v=(e,t)=>{const n=y(),o=y();let r=!1;e.on("connection",n.onConnection),e.on("secureConnection",o.onConnection);const s=e.listeners("request");e.removeAllListeners("request"),e.on("request",p(t)),s.forEach(n=>e.on("request",(e,o)=>{t.isReady()?n(e,o):e.socket.destroy()}));return Object.assign(e,{stop:async()=>{if(e.listening&&!r)return r=!0,e.removeAllListeners("request"),e.on("request",(e,t)=>{if(!t.headersSent)return t.setHeader("connection","close")}),await Promise.all([n.closeAll(),o.closeAll()]),new Promise((t,n)=>{e.close(e=>{e?n(e):t()})})}})};var m=e=>{let t=c.NOT_READY;return{set:function(n,o){return t=n,e.emit(n,o),this},get:()=>t,setReady:function(){this.set(c.READY)},isReady:()=>t===c.READY}};var O=e=>{const t=new f.EventEmitter,n=m(t),o=v(e,n);return{status:n,init:function(){return u(this)},shutdown:function(e,t,n){return l(o,this)(e,t,n)},on:(e,n)=>t.on(e,n)}};const E=(e,t)=>{var n;n=t,r&&(Object.freeze(Object.assign(o,n)),r=!1);const s=O(e).init();return{isReady:()=>s.status.isReady(),setReady:()=>s.status.setReady(),on:s.on}};Object.assign(E,c);t.default=E}]).default;
module.exports=function(e){var t={};function n(o){if(t[o])return t[o].exports;var r=t[o]={i:o,l:!1,exports:{}};return e[o].call(r.exports,r,r.exports,n),r.l=!0,r.exports}return n.m=e,n.c=t,n.d=function(e,t,o){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:o})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var o=Object.create(null);if(n.r(o),Object.defineProperty(o,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)n.d(o,r,function(t){return e[t]}.bind(null,r));return o},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=1)}([function(e,t){e.exports=require("events")},function(e,t,n){"use strict";n.r(t);const o={closePromises:[],timeout:1e3,livenessEndpoint:"/live",readinessEndpoint:"/ready"};let r=!0;var s=o;var i=[{type:"SIGHUP",code:1},{type:"SIGBREAK",code:1},{type:"SIGINT",code:2},{type:"SIGTERM",code:15},{type:"uncaughtException",code:2}];var a,u=e=>{for(const t of i)process.on(t.type,async n=>{await e.shutdown(t.type,t.code,n)});return e};!function(e){e.NOT_READY="NOT_READY",e.READY="READY",e.SHUTDOWN="SHUTDOWN",e.SHUTTING_DOWN="SHUTTING_DOWN"}(a||(a={}));var c=a;var d=e=>new Promise(t=>setTimeout(t,e));var l=(e,t)=>async(n,o,r)=>{const{timeout:i,closePromises:a}=s,u=r&&r.message?r:new Error(n);t.status.set(c.SHUTTING_DOWN,u),await d(i),await Promise.all(a.map(e=>e())),await e.stop(),t.status.set(c.SHUTDOWN,u),process.exit(128+o)},f=n(0);var p=e=>(t,n)=>{const{livenessEndpoint:o,readinessEndpoint:r}=s;if(!n.headersSent)return t.url===o&&"GET"===t.method?(n.statusCode=200,n.setHeader("Content-Type","application/json"),n.end(JSON.stringify({uptime:0|process.uptime()}))):t.url===r&&"GET"===t.method?e.isReady()?(n.statusCode=200,n.setHeader("Content-Type","application/json"),n.end(JSON.stringify({status:"ready"}))):(n.statusCode=503,n.end()):void 0};var y=e=>{const t=e||new Set,n=e=>{e.destroy(),t.delete(e)};return{onConnection:e=>{t.add(e),e.once("close",()=>t.delete(e))},closeAll:async()=>t.forEach(n)}};var v=(e,t)=>{const n=y(),o=y();let r=!1;e.on("connection",n.onConnection),e.on("secureConnection",o.onConnection);const s=e.listeners("request");e.removeAllListeners("request"),e.on("request",p(t)),s.forEach(n=>e.on("request",(e,o)=>{t.isReady()?n(e,o):e.socket.destroy()}));return Object.assign(e,{stop:async()=>{if(e.listening&&!r)return r=!0,e.removeAllListeners("request"),e.on("request",(e,t)=>{if(!t.headersSent)return t.setHeader("connection","close")}),await Promise.all([n.closeAll(),o.closeAll()]),new Promise((t,n)=>{e.close(e=>{e?n(e):t()})})}})};var m=e=>{let t=c.NOT_READY;return{set:function(n,o){return t=n,e.emit(n,o),this},get:()=>t,setReady:function(){this.set(c.READY)},isReady:()=>t===c.READY}};var O=e=>{const t=new f.EventEmitter,n=m(t),o=v(e,n);return{status:n,init:function(){return u(this)},shutdown:function(e,t,n){return l(o,this)(e,t,n)},on:(e,n)=>t.on(e,n)}};const E=Object.assign((e,t)=>{var n;n=t,r&&(Object.freeze(Object.assign(o,n)),r=!1);const s=O(e).init();return{isReady:()=>s.status.isReady(),setReady:()=>s.status.setReady(),on:s.on}},c);t.default=E}]).default;

@@ -1,4 +0,5 @@

import IOptions from '@/interface/options';
import IGracefulServerOptions from "../interface/gracefulServerOptions";
import IOptions from "../interface/options";
declare const options: IOptions;
export declare const makeOptions: (newOptions?: IOptions | undefined) => IOptions;
export declare const makeOptions: (newOptions?: IGracefulServerOptions | undefined) => IOptions;
export default options;
/// <reference types="node" />
import ImprovedServer from '@/interface/improvedServer';
import IStatus from '@/interface/status';
import ImprovedServer from "../interface/improvedServer";
import IStatus from "../interface/status";
import http from 'http';
declare const improvedServer: (server: http.Server, serverStatus: IStatus) => ImprovedServer;
export default improvedServer;
/// <reference types="node" />
import ICore from '@/interface/core';
import ICore from "../interface/core";
import http from 'http';
declare const core: (server: http.Server) => ICore;
export default core;
/// <reference types="node" />
import IStatus from '@/interface/status';
import IStatus from "../interface/status";
import { EventEmitter } from 'events';
declare const Status: (eventEmitter: EventEmitter) => IStatus;
export default Status;
/// <reference types="node" />
import IGracefulServer from '@/interface/gracefulServer';
import IOptions from '@/interface/options';
import State from "./core/state";
import IGracefulServer from "./interface/gracefulServer";
import IGracefulServerOptions from "./interface/gracefulServerOptions";
import http from 'http';
declare const GracefulServer: (server: http.Server, options: IOptions) => IGracefulServer;
declare const GracefulServer: ((server: http.Server, options?: IGracefulServerOptions | undefined) => IGracefulServer) & typeof State;
export default GracefulServer;
/// <reference types="node" />
import { EventEmitter } from 'events';
import IStatus from './status';
import IStatus from "./status";
export default interface ICore {

@@ -5,0 +5,0 @@ status: IStatus;

@@ -1,2 +0,2 @@

import State from '@/core/state';
import State from "../core/state";
export default interface IStatus {

@@ -3,0 +3,0 @@ set: (status: State, error?: Error) => IStatus;

@@ -1,3 +0,3 @@

import ICore from '@/interface/core';
import ICore from "../interface/core";
declare const init: (parent: ICore) => ICore;
export default init;
/// <reference types="node" />
import IStatus from '@/interface/status';
import IStatus from "../interface/status";
import http from 'http';
declare const onRequest: (serverStatus: IStatus) => (req: http.IncomingMessage, res: http.ServerResponse) => void;
export default onRequest;

@@ -1,4 +0,4 @@

import ICore from '@/interface/core';
import ImprovedServer from '@/interface/improvedServer';
import ICore from "../interface/core";
import ImprovedServer from "../interface/improvedServer";
declare const shutdown: (server: ImprovedServer, parent: ICore) => (type: string, value: number, body?: Error | undefined) => Promise<never>;
export default shutdown;

@@ -30,3 +30,3 @@ {

"license": "MIT",
"version": "1.0.0",
"version": "1.1.0",
"main": "./lib/index.js",

@@ -36,6 +36,6 @@ "types": "./lib/types/index.d.ts",

"clean": "rimraf lib/",
"type-check": "tsc --noEmit",
"type-check": "ttsc --noEmit",
"type-check:watch": "npm run type-check -- --watch",
"build": "npm run build:types && npm run bundle",
"build:types": "tsc --emitDeclarationOnly",
"build:types": "ttsc --emitDeclarationOnly",
"bundle": "webpack",

@@ -81,3 +81,5 @@ "lint": "eslint src/**/*.ts",

"ts-node": "^8.6.2",
"ttypescript": "^1.5.10",
"typescript": "^3.7.5",
"typescript-transform-paths": "^1.1.14",
"webpack": "^4.41.5",

@@ -84,0 +86,0 @@ "webpack-cli": "^3.3.10"

@@ -37,6 +37,12 @@ <h1 align="center">

- [Yarn](#yarn)
- [Endpoint](#endpoint)
- [<code>/live</code>](#live)
- [<code>/ready</code>](#ready)
- [Example](#example)
- [ExpressJS](#expressjs)
- [HTTP Server](#http-server)
- [Options](#options)
- [API](#api)
- [GracefulServer](#gracefulserver)
- [IGracefulServerOptions](#igracefulserveroptions)
- [GracefulServer Instance](#gracefulserver-instance)
- [Integration with Docker](#integration-with-docker)

@@ -60,2 +66,4 @@ - [HEALTH CHECK in Dockerfile](#health-check-in-dockerfile)

✔ It avoid boilerplate codes.
## Requirements

@@ -79,2 +87,32 @@

## Endpoint
Below you can find the default endpoint but you can setup them. To do that, check out the [Options](#options) part.
<a name="lightship-behaviour-live"></a>
### <code>/live</code>
The endpoint responds:
* `200` status code with the uptime of the server in second.
```json
{ "uptime": 42 }
```
Used to configure liveness probe.
<a name="lightship-behaviour-ready"></a>
### <code>/ready</code>
The endpoint responds:
* `200` status code if the server is ready.
```json
{ "status": "ready" }
```
* `503` status code with an empty response if the server is not ready (started, shutting down, etc).
## Example

@@ -86,9 +124,19 @@

const express = require('express')
const helmet = require('helmet')
const http = require('http')
const GracefulServer = require('@gquittet/graceful-server')
const { connectToDb, closeDbConnection } = require('./db')
const app = express()
app.disable('x-powered-by')
// Exclude the liveness and readiness endpoints from express
app.get('/live', () => {})
app.get('/ready', () => {})
// Add below your express middleware
app.use(helmet())
app.get('/test', (_, res) => {
return res.send({ uptime: process.uptime() | 0 })
return res.send({ uptime: process.uptime() | 0 })
})

@@ -99,2 +147,14 @@

gracefulServer.on(GracefulServer.READY, () => {
console.log('Server is ready')
})
gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => {
console.log('Server is shutting down')
})
gracefulServer.on(GracefulServer.SHUTDOWN, error => {
console.log('Server is down because of', error.message)
})
server.listen(8080, async () => {

@@ -144,4 +204,16 @@ await connectToDb()

## Options
## API
### GracefulServer
```typescript
((server: http.Server, options?: IGracefulServerOptions | undefined) => IGracefulServer) & typeof State
```
where `State` is an enum that contains `READY`, `SHUTTING_DOWN` and `SHUTDOWN`.
### IGracefulServerOptions
All of the below options are optional.
| Name | Type | Default | Description |

@@ -154,2 +226,12 @@ | ----------------- | :------------------------: | :-----: | ---------------------------------------------------------------: |

### GracefulServer Instance
```typescript
export default interface IGracefulServer {
isReady: () => Boolean
setReady: () => void
on: (name: string, callback: (...args: any[]) => void) => EventEmitter,
}
```
## Integration with Docker

@@ -278,3 +360,3 @@

path: /live
port: 9000
port: 8080
failureThreshold: 3

@@ -293,6 +375,16 @@ initialDelaySeconds: 10

★ [Bret Fisher](https://github.com/BretFisher)
★ [Stoppable](https://github.com/hunterloftis/stoppable)
★ [http-terminator](https://github.com/gajus/http-terminator)
★ [Bret Fisher](https://github.com/BretFisher) for its great articles and videos
★ [IBM documentation](https://cloud.ibm.com/docs/node?topic=nodejs-node-healthcheck)
★ [Node HTTP documentation](https://nodejs.org/api/http.html)
★ [Cloud Health](https://github.com/CloudNativeJS/cloud-health)
★ [Cloud Health Connect](https://github.com/CloudNativeJS/cloud-health-connect)
## Donate

@@ -299,0 +391,0 @@

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc