@gquittet/graceful-server
Advanced tools
Comparing version 1.2.8 to 2.0.0
@@ -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,healthCheck:!0,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.STARTING="STARTING",e.READY="READY",e.SHUTTING_DOWN="SHUTTING_DOWN",e.SHUTDOWN="SHUTDOWN"}(a||(a={}));var c=a;var l=e=>new Promise(t=>setTimeout(t,e));var d=(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 l(i),await Promise.all(a.map(e=>e())),await e.stop(),t.status.set(c.SHUTDOWN,u),process.exit(128+o)},p=n(0);const{livenessEndpoint:f,readinessEndpoint:y}=s;var v={apply:e=>{e.get(f,()=>{}),e.get(y,()=>{}),e._router.stack.unshift(e._router.stack.pop()),e._router.stack.unshift(e._router.stack.pop())}};var m=e=>e&&e._router&&Array.isArray(e._router.stack)&&e.request&&e.response&&e===e.request.app&&e===e.response.app&&"function"==typeof e.init&&"function"==typeof e.listen&&"function"==typeof e.use;var _=(()=>{let e=!0;return{validate:e=>m(e),patch:t=>{e&&(v.apply(t),e=!1)}}})();var h=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 T=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 S=(e,t)=>{const{healthCheck:n}=s,o=T(),r=T();let i=!1;e.on("connection",o.onConnection),e.on("secureConnection",r.onConnection);const a=e.listeners("request");e.removeAllListeners("request"),n&&(a.forEach(e=>{_.validate(e)&&_.patch(e)}),e.on("request",h(t))),a.forEach(n=>e.on("request",(e,o)=>{t.isReady()?n(e,o):e.socket.destroy()}));return Object.assign(e,{stop:async()=>{if(e.listening&&!i)return i=!0,e.removeAllListeners("request"),e.on("request",(e,t)=>{if(!t.headersSent)return t.setHeader("connection","close")}),await Promise.all([o.closeAll(),r.closeAll()]),new Promise((t,n)=>{e.close(e=>{e?n(e):t()})})}})};var E=e=>{let t=c.STARTING;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 p.EventEmitter,n=E(t),o=S(e,n);return{status:n,init:function(){return u(this)},shutdown:function(e,t,n){return d(o,this)(e,t,n)},on:(e,n)=>t.on(e,n)}};const b=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=b}]);const __export__=module.exports;module.exports=__export__.default,Object.assign(module.exports,__export__); | ||
module.exports=(()=>{"use strict";var e={11:(e,t,n)=>{n.r(t),n.d(t,{default:()=>E});const s={closePromises:[],timeout:1e3,healthCheck:!0,livenessEndpoint:"/live",readinessEndpoint:"/ready"};let o=!0;const r=e=>(o&&(Object.freeze(Object.assign(s,e)),o=!1),s),i=s,a=[{type:"SIGHUP",code:1},{type:"SIGBREAK",code:1},{type:"SIGINT",code:2},{type:"SIGTERM",code:15},{type:"uncaughtException",code:2}];var c;!function(e){e.STARTING="STARTING",e.READY="READY",e.SHUTTING_DOWN="SHUTTING_DOWN",e.SHUTDOWN="SHUTDOWN"}(c||(c={}));const u=c,d=(e,t)=>async(n,s,o)=>{const{timeout:r,closePromises:a}=i,c=o&&o.message?o:new Error(n);var d;t.status.set(u.SHUTTING_DOWN,c),await(d=r,new Promise((e=>setTimeout(e,d)))),await Promise.all(a.map((e=>e()))),await e.stop(),t.status.set(u.SHUTDOWN,c),process.exit(128+s)},p=require("events"),{livenessEndpoint:l,readinessEndpoint:y}=i,f=e=>{e.get(l,(()=>{})),e.get(y,(()=>{})),e._router.stack.unshift(e._router.stack.pop()),e._router.stack.unshift(e._router.stack.pop())},m=(()=>{let e=!0;return{validate:e=>{return(t=e)&&t._router&&Array.isArray(t._router.stack)&&t.request&&t.response&&t===t.request.app&&t===t.response.app&&"function"==typeof t.init&&"function"==typeof t.listen&&"function"==typeof t.use;var t},patch:t=>{e&&(f(t),e=!1)}}})(),h=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)}},T=(e,t)=>{const{healthCheck:n}=i,s=h(),o=h();let r=!1;e.on("connection",s.onConnection),e.on("secureConnection",o.onConnection);const a=e.listeners("request");return e.removeAllListeners("request"),n&&(a.forEach((e=>{m.validate(e)&&m.patch(e)})),e.on("request",(e=>(t,n)=>{const{livenessEndpoint:s,readinessEndpoint:o}=i;if(!n.headersSent)return t.url===s&&"GET"===t.method?(n.statusCode=200,n.setHeader("Content-Type","application/json"),n.end(JSON.stringify({uptime:0|process.uptime()}))):t.url===o&&"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})(t))),a.forEach((n=>e.on("request",((e,s)=>{t.isReady()?n(e,s):e.socket.destroy()})))),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([s.closeAll(),o.closeAll()]),new Promise(((t,n)=>{e.close((e=>{e?n(e):t()}))}))}})},S=e=>{let t=u.STARTING;return{set:function(n,s){return t=n,e.emit(n,s),this},get:()=>t,setReady:function(){this.set(u.READY)},isReady:()=>t===u.READY}},_=e=>{const t=new p.EventEmitter,n=S(t),s=T(e,n);return{status:n,init:function(){return(e=>{for(const t of a)process.on(t.type,(async n=>{await e.shutdown(t.type,t.code,n)}));return e})(this)},shutdown:function(e,t,n){return d(s,this)(e,t,n)},on:(e,n)=>t.on(e,n)}},E=Object.assign(((e,t)=>{r(t);const n=_(e).init();return{isReady:()=>n.status.isReady(),setReady:()=>n.status.setReady(),on:n.on}}),u)}},t={};function n(s){if(t[s])return t[s].exports;var o=t[s]={exports:{}};return e[s](o,o.exports,n),o.exports}return n.d=(e,t)=>{for(var s in t)n.o(t,s)&&!n.o(e,s)&&Object.defineProperty(e,s,{enumerable:!0,get:t[s]})},n.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),n.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n(11)})();const __export__=module.exports;module.exports=__export__.default,Object.assign(module.exports,__export__); |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import ImprovedServer from "../interface/improvedServer"; | ||
@@ -3,0 +2,0 @@ import IStatus from "../interface/status"; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import ICore from "../interface/core"; | ||
@@ -3,0 +2,0 @@ import * as http from 'http'; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import IStatus from "../interface/status"; | ||
@@ -3,0 +2,0 @@ import { EventEmitter } from 'events'; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import State from "./core/state"; | ||
@@ -3,0 +2,0 @@ import IGracefulServer from "./interface/gracefulServer"; |
/// <reference types="node" /> | ||
import { EventEmitter } from 'events'; | ||
export default interface IGracefulServer { | ||
isReady: () => Boolean; | ||
isReady: () => boolean; | ||
setReady: () => void; | ||
on: (name: string, callback: (...args: any[]) => void) => EventEmitter; | ||
} |
@@ -6,3 +6,3 @@ import State from "../core/state"; | ||
setReady: () => void; | ||
isReady: () => Boolean; | ||
isReady: () => boolean; | ||
} |
@@ -0,3 +1,4 @@ | ||
/// <reference types="express-serve-static-core" /> | ||
import * as express from 'express'; | ||
declare const validate: (requestListener: express.Express) => boolean; | ||
export default validate; |
@@ -1,2 +0,1 @@ | ||
/// <reference types="node" /> | ||
import IStatus from "../interface/status"; | ||
@@ -3,0 +2,0 @@ import * as http from 'http'; |
@@ -19,3 +19,3 @@ { | ||
"engines": { | ||
"node": ">=8" | ||
"node": ">=10.13.0" | ||
}, | ||
@@ -31,3 +31,3 @@ "keywords": [ | ||
"license": "MIT", | ||
"version": "1.2.8", | ||
"version": "2.0.0", | ||
"main": "./lib/index.js", | ||
@@ -49,42 +49,40 @@ "types": "./lib/types/index.d.ts", | ||
}, | ||
"dependencies": {}, | ||
"devDependencies": { | ||
"@babel/cli": "^7.8.4", | ||
"@babel/core": "^7.9.0", | ||
"@babel/plugin-proposal-class-properties": "^7.8.3", | ||
"@babel/plugin-proposal-object-rest-spread": "^7.9.0", | ||
"@babel/preset-env": "^7.9.0", | ||
"@babel/preset-typescript": "^7.9.0", | ||
"@types/express": "^4.17.4", | ||
"@types/jest": "^25.1.5", | ||
"@types/node": "^13.11.0", | ||
"@types/stoppable": "^1.1.0", | ||
"@typescript-eslint/eslint-plugin": "^2.26.0", | ||
"@typescript-eslint/parser": "^2.26.0", | ||
"add-module-exports-webpack-plugin": "^1.0.0", | ||
"babel-loader": "^8.1.0", | ||
"babel-plugin-module-resolver": "^4.0.0", | ||
"eslint": "^6.8.0", | ||
"eslint-config-prettier": "^6.10.1", | ||
"eslint-config-standard": "^14.1.1", | ||
"eslint-import-resolver-babel-module": "^5.1.2", | ||
"eslint-plugin-import": "^2.20.2", | ||
"eslint-plugin-module-resolver": "^0.16.0", | ||
"eslint-plugin-node": "^11.1.0", | ||
"eslint-plugin-promise": "^4.2.1", | ||
"eslint-plugin-standard": "^4.0.1", | ||
"esm": "^3.2.25", | ||
"fork-ts-checker-webpack-plugin": "^4.1.2", | ||
"husky": "^4.2.3", | ||
"jest": "^25.2.7", | ||
"prettier": "^2.0.2", | ||
"pretty-quick": "^2.0.1", | ||
"rimraf": "^3.0.2", | ||
"ts-jest": "^25.3.1", | ||
"ts-node": "^8.8.1", | ||
"ttypescript": "^1.5.10", | ||
"typescript": "^3.8.3", | ||
"typescript-transform-paths": "^1.1.14", | ||
"webpack": "^4.42.1", | ||
"webpack-cli": "^3.3.11" | ||
"@babel/cli": "7.12.1", | ||
"@babel/core": "7.12.3", | ||
"@babel/plugin-proposal-class-properties": "7.12.1", | ||
"@babel/plugin-proposal-object-rest-spread": "7.12.1", | ||
"@babel/preset-env": "7.12.1", | ||
"@babel/preset-typescript": "7.12.1", | ||
"@types/express": "4.17.8", | ||
"@types/jest": "26.0.15", | ||
"@types/node": "14.11.11", | ||
"@typescript-eslint/eslint-plugin": "4.5.0", | ||
"@typescript-eslint/parser": "4.5.0", | ||
"add-module-exports-webpack-plugin": "2.0.0", | ||
"babel-loader": "8.1.0", | ||
"babel-plugin-module-resolver": "4.0.0", | ||
"eslint": "7.11.0", | ||
"eslint-config-prettier": "6.13.0", | ||
"eslint-config-standard": "14.1.1", | ||
"eslint-import-resolver-babel-module": "5.2.0", | ||
"eslint-plugin-import": "2.22.1", | ||
"eslint-plugin-module-resolver": "1.0.0", | ||
"eslint-plugin-node": "11.1.0", | ||
"eslint-plugin-promise": "4.2.1", | ||
"eslint-plugin-standard": "4.0.1", | ||
"esm": "3.2.25", | ||
"fork-ts-checker-webpack-plugin": "5.2.0", | ||
"husky": "4.3.0", | ||
"jest": "26.6.0", | ||
"prettier": "2.1.2", | ||
"pretty-quick": "3.1.0", | ||
"rimraf": "3.0.2", | ||
"ts-jest": "26.4.1", | ||
"ts-node": "9.0.0", | ||
"ttypescript": "1.5.12", | ||
"typescript": "4.0.3", | ||
"typescript-transform-paths": "2.0.1", | ||
"webpack": "5.1.3", | ||
"webpack-cli": "4.1.0" | ||
}, | ||
@@ -91,0 +89,0 @@ "husky": { |
@@ -27,3 +27,3 @@ <h1 align="center"> | ||
<p align="center"> | ||
Tiny (~5k), KISS, dependency-free Node.JS library to make your API more graceful | ||
Tiny (~5k), KISS, dependency-free Node.JS library to make your Rest API graceful. | ||
</p> | ||
@@ -44,2 +44,3 @@ | ||
- [Fastify](#fastify) | ||
- [Koa](#koa) | ||
- [HTTP Server](#http-server) | ||
@@ -76,3 +77,3 @@ - [API](#api) | ||
✔ NodeJS >= 8 | ||
✔ NodeJS >= 10.13.0 | ||
@@ -186,6 +187,5 @@ ## Installation | ||
gracefulServer.on(GracefulServer.SHUTTING_DOWN, () => { | ||
console.log('Server is shutting down' | ||
console.log('Server is shutting down') | ||
}) | ||
gracefulServer.on(GracefulServer.SHUTDOWN, error => { | ||
@@ -214,2 +214,46 @@ console.log('Server is down because of', error.message) | ||
### Koa | ||
```javascript | ||
const GracefulServer = require('@gquittet/graceful-server') | ||
const Koa = require('koa') | ||
const http = require('http') | ||
const Router = require('koa-router') | ||
const app = new Koa() | ||
const router = new Router() | ||
const server = http.createServer(app.callback()) | ||
gracefulServer = GracefulServer(server) | ||
router.get('/test') | ||
app.use(router.routes()) | ||
// response | ||
app.use(ctx => { | ||
ctx.body = 'Hello Koa' | ||
}) | ||
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 () => { | ||
await connectToDb() | ||
gracefulServer.setReady() | ||
}) | ||
``` | ||
As you can see, we're using the `app` object from Express to set up the endpoints and middleware. | ||
But it can't listen (you can do it but `app` hasn't any liveness or readiness). The listening | ||
of HTTP calls need to be done by the default NodeJS HTTP object (aka **_server_**). | ||
### HTTP Server | ||
@@ -279,3 +323,3 @@ | ||
export default interface IGracefulServer { | ||
isReady: () => Boolean | ||
isReady: () => boolean | ||
setReady: () => void | ||
@@ -282,0 +326,0 @@ on: (name: string, callback: (...args: any[]) => void) => EventEmitter |
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
License Policy Violation
LicenseThis package is not allowed per your license policy. Review the package's license to ensure compliance.
Found 1 instance in 1 package
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
25117
37
479
0
118