@visulima/health-check 1.0.4 → 1.0.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +7 -0
- package/README.md +3 -3
- package/dist/index.js +12 -12
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +4 -4
- package/dist/index.mjs.map +1 -1
- package/package.json +10 -10
package/CHANGELOG.md
CHANGED
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
## @visulima/health-check [1.0.5](https://github.com/visulima/visulima/compare/@visulima/health-check@1.0.4...@visulima/health-check@1.0.5) (2023-06-06)
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
### Bug Fixes
|
|
5
|
+
|
|
6
|
+
* Add npm package provenance, see https://docs.npmjs.com/generating-provenance-statements for more info ([9e7da04](https://github.com/visulima/visulima/commit/9e7da0491584e16a806fc7575c00080f192ec15e))
|
|
7
|
+
|
|
1
8
|
## @visulima/health-check [1.0.4](https://github.com/visulima/visulima/compare/@visulima/health-check@1.0.3...@visulima/health-check@1.0.4) (2023-05-25)
|
|
2
9
|
|
|
3
10
|
|
package/README.md
CHANGED
|
@@ -41,7 +41,7 @@ pnpm add @visulima/health-check
|
|
|
41
41
|
|
|
42
42
|
## Usecases for API health check endpoints
|
|
43
43
|
|
|
44
|
-
Keeping the API health check endpoints generic allows
|
|
44
|
+
Keeping the API health check endpoints generic allows to use them for multiple purposes. In this section, we will review of the everyday use cases of an API health check endpoint
|
|
45
45
|
|
|
46
46
|
- Container orchestrators and API load balancers can use API health check endpoint to find out about the process status
|
|
47
47
|
- Usage of memory, disk, and other server resources can be monitored via API health check endpoints
|
|
@@ -63,7 +63,7 @@ export default healthCheckHandler(HealthCheckService); // returns a http handler
|
|
|
63
63
|
|
|
64
64
|
There are at least three different types of API health check endpoints designed to serve specific purposes.
|
|
65
65
|
|
|
66
|
-
- _The readiness endpoint_, often available via `/health/ready`, returns the readiness state to accept incoming requests from the gateway or the upstream proxy. Readiness signals that the app is running normally but isn’t ready to receive requests
|
|
66
|
+
- _The readiness endpoint_, often available via `/health/ready`, returns the readiness state to accept incoming requests from the gateway or the upstream proxy. Readiness signals that the app is running normally but isn’t ready to receive requests yet.
|
|
67
67
|
|
|
68
68
|
- _The liveness endpoint_, often available via `/health/live`, returns the liveness of a microservice. If the check does not return the expected response, it means that the process is unhealthy or dead and should be replaced as soon as possible.
|
|
69
69
|
|
|
@@ -71,7 +71,7 @@ There are at least three different types of API health check endpoints designed
|
|
|
71
71
|
|
|
72
72
|
Consider the following example: an API that loads JSON-based data into memory to serve requests.
|
|
73
73
|
|
|
74
|
-
The `/health/ready` continues to respond with `NOT_READY` signal while the API is loading the JSON file since the API cannot serve any request without the file in memory. Therefore, it may take
|
|
74
|
+
The `/health/ready` continues to respond with `NOT_READY` signal while the API is loading the JSON file since the API cannot serve any request without the file in memory. Therefore, it may take time for the API to process the entire file.
|
|
75
75
|
|
|
76
76
|
The `/health/live` immediately signals `LIVE`, even though the app is not ready, to prevent the container orchestrator layer from restarting the app.
|
|
77
77
|
|
package/dist/index.js
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
1
|
'use strict';
|
|
2
2
|
|
|
3
3
|
var httpStatusCodes = require('http-status-codes');
|
|
4
|
-
var
|
|
4
|
+
var k = require('cacheable-lookup');
|
|
5
5
|
var assert = require('assert');
|
|
6
|
-
var
|
|
6
|
+
var R = require('pingman');
|
|
7
7
|
|
|
8
8
|
function _interopDefault (e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
9
|
|
|
10
|
-
var
|
|
11
|
-
var
|
|
10
|
+
var k__default = /*#__PURE__*/_interopDefault(k);
|
|
11
|
+
var R__default = /*#__PURE__*/_interopDefault(R);
|
|
12
12
|
|
|
13
|
-
var
|
|
13
|
+
var f=(t,e=!0)=>async(a,r)=>{let{healthy:s,report:o}=await t.getReport(),l={status:s?"ok":"error",message:s?"Health check successful":"Health check failed",appName:process.env.APP_NAME??"unknown",appVersion:process.env.APP_VERSION??"unknown",timestamp:new Date().toISOString(),reports:o};r.statusCode=s?httpStatusCodes.StatusCodes.OK:httpStatusCodes.StatusCodes.SERVICE_UNAVAILABLE,e&&r.setHeader("Content-Type","application/json"),r.end(JSON.stringify(l,null,2));};var u=t=>async(e,a)=>{let{healthy:r}=await t.getReport();a.statusCode=r?httpStatusCodes.StatusCodes.NO_CONTENT:httpStatusCodes.StatusCodes.SERVICE_UNAVAILABLE,a.end();};var c=class{constructor(){this.healthCheckers={};}get servicesList(){return Object.keys(this.healthCheckers)}async invokeChecker(e,a){let r=this.healthCheckers[e],s;try{s=await r(),s.displayName=s.displayName||e;}catch(o){s={displayName:e,health:{healthy:!1,message:o.message,timestamp:new Date().toISOString()},meta:{fatal:!0}};}return a[e]=s,s.health.healthy}addChecker(e,a){this.healthCheckers[e]=a;}async getReport(){let e={};return await Promise.all(Object.keys(this.healthCheckers).map(r=>this.invokeChecker(r,e))),{healthy:!Object.keys(e).find(r=>!e[r].health.healthy),report:e}}async isLive(){let{healthy:e}=await this.getReport();return e}},g=c;var i="DNS check for",C=(t,e,a)=>async()=>{let{hints:r,family:s="all",...o}=a??{},l=new k__default.default(o);try{let n=await l.lookupAsync(t.replace(/^https?:\/\//,""),{hints:r,...s==="all"?{all:!0}:{family:s}});return Array.isArray(e)&&!e.includes(n.address)?{displayName:`${i} ${t}`,health:{healthy:!1,message:`${i} ${t} returned address ${n.address} instead of ${e.join(", ")}.`,timestamp:new Date().toISOString()},meta:{host:t,addresses:n}}:{displayName:`${i} ${t}`,health:{healthy:!0,message:`${i} ${t} were resolved.`,timestamp:new Date().toISOString()},meta:{host:t,addresses:n}}}catch(n){return {displayName:`${i} ${t}`,health:{healthy:!1,message:n.message,timestamp:new Date().toISOString()},meta:{host:t}}}},S=C;var h="HTTP check for",$=(t,e)=>async()=>{try{let a=await fetch(t,e?.fetchOptions??{});if(e?.expected?.status!==void 0&&e.expected.status!==a.status)throw new Error(`${h} ${t} returned status ${a.status} instead of ${e.expected.status}`);if(e?.expected?.body!==void 0){let r=await a.text();try{assert.deepStrictEqual(r,e.expected.body);}catch{throw new Error(`${h} ${t} returned body ${JSON.stringify(r)} instead of ${JSON.stringify(e.expected.body)}`)}}return {displayName:`${h} ${t}`,health:{healthy:!0,message:`${h} ${t} was successful.`,timestamp:new Date().toISOString()},meta:{host:t,method:e?.fetchOptions?.method??"GET",status:a.status}}}catch(a){return {displayName:`${h} ${t}`,health:{healthy:!1,message:a.message,timestamp:new Date().toISOString()},meta:{host:t,method:e?.fetchOptions?.method??"GET"}}}},O=$;var y="Node Environment Check",E=t=>async()=>{let e="production",a;return t!==void 0&&e!==t?a=`NODE_ENV environment variable is set to "${e}" instead of "${t}".`:e,a!==void 0?{displayName:y,health:{healthy:!1,message:a,timestamp:new Date().toISOString()}}:{displayName:y,health:{healthy:!0,timestamp:new Date().toISOString()},meta:{env:e}}},I=E;var p="Ping check for",w=(t,e)=>async()=>{try{let a=await R__default.default(t.replace(/^https?:\/\//,""),e);return a.alive?{displayName:`${p} ${t}`,health:{healthy:!0,message:`${p} ${t} was successful.`,timestamp:new Date().toISOString()},meta:a}:{displayName:`${p} ${t}`,health:{healthy:!1,message:`Ping failed for ${t}.`,timestamp:new Date().toISOString()},meta:a}}catch(a){return {displayName:`${p} ${t}`,health:{healthy:!1,message:a.message,timestamp:new Date().toISOString()}}}},x=w;
|
|
14
14
|
|
|
15
|
-
exports.HealthCheck =
|
|
16
|
-
exports.dnsCheck =
|
|
17
|
-
exports.healthCheckHandler =
|
|
18
|
-
exports.healthReadyHandler =
|
|
19
|
-
exports.httpCheck =
|
|
20
|
-
exports.nodeEnvCheck =
|
|
21
|
-
exports.pingCheck =
|
|
15
|
+
exports.HealthCheck = g;
|
|
16
|
+
exports.dnsCheck = S;
|
|
17
|
+
exports.healthCheckHandler = f;
|
|
18
|
+
exports.healthReadyHandler = u;
|
|
19
|
+
exports.httpCheck = O;
|
|
20
|
+
exports.nodeEnvCheck = I;
|
|
21
|
+
exports.pingCheck = x;
|
|
22
22
|
//# sourceMappingURL=out.js.map
|
|
23
23
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/handler/healthcheck.ts","../src/handler/readyhandler.ts","../src/healthcheck.ts","../src/checks/dns-check.ts","../src/checks/http-check.ts","../src/checks/node-environment-check.ts","../src/checks/ping-check.ts"],"names":["StatusCodes","healthcheck_default","healthCheck","sendHeader","_","response","healthy","report","payload","readyhandler_default","_request","Healthcheck","__publicField","service","reportSheet","checker","error","CacheableLookup","DISPLAY_NAME","dnsCheck","host","expectedAddresses","options","hints","family","config","cacheable","meta","dns_check_default","deepStrictEqual","httpCheck","textBody","http_check_default","nodeEnvironmentCheck","expectedEnvironment","environment","errorMessage","node_environment_check_default","ping","pingCheck","ping_check_default"],"mappings":"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","sourcesContent":["import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck, HealthReport } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default (healthCheck: HealthCheck, sendHeader: boolean | undefined = true) => async <Request extends IncomingMessage, Response extends ServerResponse>(_: Request, response: Response): Promise<void> => {\n const { healthy, report } = await healthCheck.getReport();\n\n const payload: HealthCheckApiPayload = {\n status: healthy ? \"ok\" : \"error\",\n message: healthy ? \"Health check successful\" : \"Health check failed\",\n appName: process.env[\"APP_NAME\"] ?? \"unknown\",\n appVersion: process.env[\"APP_VERSION\"] ?? \"unknown\",\n timestamp: new Date().toISOString(),\n reports: report,\n };\n\n response.statusCode = healthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE;\n\n if (sendHeader) {\n response.setHeader(\"Content-Type\", \"application/json\");\n }\n\n response.end(JSON.stringify(payload, null, 2));\n};\n\nexport type HealthCheckApiPayload = {\n status: \"error\" | \"ok\";\n message: string;\n appName: string;\n appVersion: string;\n timestamp: string;\n reports: HealthReport;\n};\n","import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default <Request extends IncomingMessage, Response extends ServerResponse>(healthCheck: HealthCheck) => async (_request: Request, response: Response): Promise<void> => {\n const { healthy } = await healthCheck.getReport();\n\n response.statusCode = healthy ? StatusCodes.NO_CONTENT : StatusCodes.SERVICE_UNAVAILABLE;\n response.end();\n};\n","import type {\n Checker, HealthCheck as HealthcheckInterface, HealthReport, HealthReportEntry,\n} from \"./types.d\";\n\nclass Healthcheck implements HealthcheckInterface {\n /**\n * A copy of registered checkers\n */\n private healthCheckers: { [service: string]: Checker } = {};\n\n /**\n * Returns an array of registered services names\n */\n public get servicesList(): string[] {\n return Object.keys(this.healthCheckers);\n }\n\n /**\n * Invokes a given checker to collect the report metrics.\n */\n private async invokeChecker(service: string, reportSheet: HealthReport): Promise<boolean> {\n const checker = this.healthCheckers[service] as Checker;\n\n let report: HealthReportEntry;\n\n try {\n report = await checker();\n\n report.displayName = report.displayName || service;\n } catch (error: any) {\n report = {\n displayName: service,\n health: { healthy: false, message: (error as Error).message, timestamp: new Date().toISOString() },\n meta: { fatal: true },\n };\n }\n\n // eslint-disable-next-line no-param-reassign\n reportSheet[service] = report;\n\n return report.health.healthy;\n }\n\n public addChecker(service: string, checker: Checker): void {\n this.healthCheckers[service] = checker;\n }\n\n /**\n * Returns the health check reports. The health checks are performed when\n * this method is invoked.\n */\n public async getReport(): Promise<{ healthy: boolean; report: HealthReport }> {\n const report: HealthReport = {};\n\n // eslint-disable-next-line compat/compat\n await Promise.all(Object.keys(this.healthCheckers).map((service) => this.invokeChecker(service, report)));\n\n /**\n * Finding unhealthy service to know if system is healthy or not\n */\n const unhealthyService = Object.keys(report).find((service) => !(report[service] as HealthReportEntry).health.healthy);\n\n return { healthy: !unhealthyService, report };\n }\n\n public async isLive(): Promise<boolean> {\n const { healthy } = await this.getReport();\n\n return healthy;\n }\n}\n\nexport default Healthcheck;\n","import type { IPFamily, Options } from \"cacheable-lookup\";\nimport CacheableLookup from \"cacheable-lookup\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"DNS check for\";\n\n/**\n * Register the `dns` checker to ensure that a domain is reachable.\n */\nconst dnsCheck = (\n host: string,\n expectedAddresses?: string[],\n options?: Options & {\n family?: IPFamily | \"all\";\n hints?: number;\n },\n): Checker => async () => {\n const { hints, family = \"all\", ...config } = options ?? {};\n\n const cacheable = new CacheableLookup(config);\n\n try {\n const meta = await cacheable.lookupAsync(host.replace(/^https?:\\/\\//, \"\"), {\n hints,\n ...(family === \"all\" ? { all: true } : { family }),\n });\n\n if (Array.isArray(expectedAddresses) && !expectedAddresses.includes(meta.address)) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `${DISPLAY_NAME} ${host} returned address ${meta.address} instead of ${expectedAddresses.join(\", \")}.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} were resolved.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n },\n };\n }\n};\n\nexport default dnsCheck;\n","import { deepStrictEqual } from \"node:assert\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"HTTP check for\";\n\n/**\n * Register the `http` checker to ensure http body and status is correct.\n */\nconst httpCheck = (host: RequestInfo | URL, options?: {\n fetchOptions?: RequestInit,\n expected?: { status?: number; body?: string }\n}): Checker => async () => {\n try {\n // eslint-disable-next-line compat/compat\n const response = await fetch(host, options?.fetchOptions ?? {});\n\n if (options?.expected?.status !== undefined && options.expected.status !== response.status) {\n throw new Error(`${DISPLAY_NAME} ${host} returned status ${response.status} instead of ${options.expected.status}`);\n }\n\n if (options?.expected?.body !== undefined) {\n const textBody = await response.text();\n\n try {\n deepStrictEqual(textBody, options.expected.body);\n } catch {\n throw new Error(`${DISPLAY_NAME} ${host} returned body ${JSON.stringify(textBody)} instead of ${JSON.stringify(options.expected.body)}`);\n }\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n status: response.status,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n },\n };\n }\n};\n\nexport default httpCheck;\n","import type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Node Environment Check\";\n\n/**\n * Register the `env` checker to ensure that `NODE_ENV` environment\n * variable is defined.\n */\nconst nodeEnvironmentCheck = (expectedEnvironment?: string): Checker => async () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const environment: string | undefined = process.env[\"NODE_ENV\"];\n\n let errorMessage: string | undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (environment !== undefined && expectedEnvironment !== undefined && environment !== expectedEnvironment) {\n errorMessage = `NODE_ENV environment variable is set to \"${environment}\" instead of \"${expectedEnvironment}\".`;\n } else if (!environment) {\n errorMessage = [\"Missing NODE_ENV environment variable.\", \"It can make some parts of the application misbehave\"].join(\" \");\n }\n\n if (errorMessage !== undefined) {\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: false,\n message: errorMessage,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: true,\n timestamp: new Date().toISOString(),\n },\n meta: {\n env: environment,\n },\n };\n};\n\nexport default nodeEnvironmentCheck;\n","import type { extendedPingOptions } from \"pingman\";\nimport ping from \"pingman\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Ping check for\";\n\n/**\n * Register the `ping` checker to ensure that a domain is reachable.\n */\nconst pingCheck = (host: string, options?: extendedPingOptions): Checker => async () => {\n try {\n const response = await ping(host.replace(/^https?:\\/\\//, \"\"), options);\n\n if (!response.alive) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `Ping failed for ${host}.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n };\n }\n};\n\nexport default pingCheck;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/handler/healthcheck.ts","../src/handler/readyhandler.ts","../src/healthcheck.ts","../src/checks/dns-check.ts","../src/checks/http-check.ts","../src/checks/node-environment-check.ts","../src/checks/ping-check.ts"],"names":["StatusCodes","healthcheck_default","healthCheck","sendHeader","_","response","healthy","report","payload","readyhandler_default","_request","Healthcheck","service","reportSheet","checker","error","CacheableLookup","DISPLAY_NAME","dnsCheck","host","expectedAddresses","options","hints","family","config","cacheable","meta","dns_check_default","deepStrictEqual","httpCheck","textBody","http_check_default","nodeEnvironmentCheck","expectedEnvironment","environment","errorMessage","node_environment_check_default","ping","pingCheck","ping_check_default"],"mappings":"AAAA,OAAS,eAAAA,MAAmB,oBAM5B,IAAOC,EAAQ,CAACC,EAA0BC,EAAkC,KAAS,MAAyEC,EAAYC,IAAsC,CAC5M,GAAM,CAAE,QAAAC,EAAS,OAAAC,CAAO,EAAI,MAAML,EAAY,UAAU,EAElDM,EAAiC,CACnC,OAAQF,EAAU,KAAO,QACzB,QAASA,EAAU,0BAA4B,sBAC/C,QAAS,QAAQ,IAAI,UAAe,UACpC,WAAY,QAAQ,IAAI,aAAkB,UAC1C,UAAW,IAAI,KAAK,EAAE,YAAY,EAClC,QAASC,CACb,EAEAF,EAAS,WAAaC,EAAUN,EAAY,GAAKA,EAAY,oBAEzDG,GACAE,EAAS,UAAU,eAAgB,kBAAkB,EAGzDA,EAAS,IAAI,KAAK,UAAUG,EAAS,KAAM,CAAC,CAAC,CACjD,ECzBA,OAAS,eAAAR,MAAmB,oBAM5B,IAAOS,EAA2EP,GAA6B,MAAOQ,EAAmBL,IAAsC,CAC3K,GAAM,CAAE,QAAAC,CAAQ,EAAI,MAAMJ,EAAY,UAAU,EAEhDG,EAAS,WAAaC,EAAUN,EAAY,WAAaA,EAAY,oBACrEK,EAAS,IAAI,CACjB,ECPA,IAAMM,EAAN,KAAkD,CAAlD,cAII,KAAQ,eAAiD,CAAC,EAK1D,IAAW,cAAyB,CAChC,OAAO,OAAO,KAAK,KAAK,cAAc,CAC1C,CAKA,MAAc,cAAcC,EAAiBC,EAA6C,CACtF,IAAMC,EAAU,KAAK,eAAeF,CAAO,EAEvCL,EAEJ,GAAI,CACAA,EAAS,MAAMO,EAAQ,EAEvBP,EAAO,YAAcA,EAAO,aAAeK,CAC/C,OAASG,EAAP,CACER,EAAS,CACL,YAAaK,EACb,OAAQ,CAAE,QAAS,GAAO,QAAUG,EAAgB,QAAS,UAAW,IAAI,KAAK,EAAE,YAAY,CAAE,EACjG,KAAM,CAAE,MAAO,EAAK,CACxB,CACJ,CAGA,OAAAF,EAAYD,CAAO,EAAIL,EAEhBA,EAAO,OAAO,OACzB,CAEO,WAAWK,EAAiBE,EAAwB,CACvD,KAAK,eAAeF,CAAO,EAAIE,CACnC,CAMA,MAAa,WAAiE,CAC1E,IAAMP,EAAuB,CAAC,EAG9B,aAAM,QAAQ,IAAI,OAAO,KAAK,KAAK,cAAc,EAAE,IAAKK,GAAY,KAAK,cAAcA,EAASL,CAAM,CAAC,CAAC,EAOjG,CAAE,QAAS,CAFO,OAAO,KAAKA,CAAM,EAAE,KAAMK,GAAY,CAAEL,EAAOK,CAAO,EAAwB,OAAO,OAAO,EAEhF,OAAAL,CAAO,CAChD,CAEA,MAAa,QAA2B,CACpC,GAAM,CAAE,QAAAD,CAAQ,EAAI,MAAM,KAAK,UAAU,EAEzC,OAAOA,CACX,CACJ,EAEOL,EAAQU,ECvEf,OAAOK,MAAqB,mBAI5B,IAAMC,EAAe,gBAKfC,EAAW,CACbC,EACAC,EACAC,IAIU,SAAY,CACtB,GAAM,CAAE,MAAAC,EAAO,OAAAC,EAAS,MAAO,GAAGC,CAAO,EAAIH,GAAW,CAAC,EAEnDI,EAAY,IAAIT,EAAgBQ,CAAM,EAE5C,GAAI,CACA,IAAME,EAAO,MAAMD,EAAU,YAAYN,EAAK,QAAQ,eAAgB,EAAE,EAAG,CACvE,MAAAG,EACA,GAAIC,IAAW,MAAQ,CAAE,IAAK,EAAK,EAAI,CAAE,OAAAA,CAAO,CACpD,CAAC,EAED,OAAI,MAAM,QAAQH,CAAiB,GAAK,CAACA,EAAkB,SAASM,EAAK,OAAO,EACrE,CACH,YAAa,GAAGT,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAS,GAAGF,KAAgBE,sBAAyBO,EAAK,sBAAsBN,EAAkB,KAAK,IAAI,KAC3G,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,KAAAD,EACA,UAAWO,CACf,CACJ,EAGG,CACH,YAAa,GAAGT,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAS,GAAGF,KAAgBE,mBAC5B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,KAAAA,EACA,UAAWO,CACf,CACJ,CACJ,OAASX,EAAP,CACE,MAAO,CACH,YAAa,GAAGE,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAUJ,EAAgB,QAC1B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,KAAAI,CACJ,CACJ,CACJ,CACJ,EAEOQ,EAAQT,ECtEf,OAAS,mBAAAU,MAAuB,SAIhC,IAAMX,EAAe,iBAKfY,EAAY,CACdV,EACAE,IAIU,SAAY,CACtB,GAAI,CAEA,IAAMhB,EAAW,MAAM,MAAMc,EAAME,GAAS,cAAgB,CAAC,CAAC,EAE9D,GAAIA,GAAS,UAAU,SAAW,QAAaA,EAAQ,SAAS,SAAWhB,EAAS,OAChF,MAAM,IAAI,MAAM,GAAGY,KAAgBE,qBAAwBd,EAAS,qBAAqBgB,EAAQ,SAAS,QAAQ,EAGtH,GAAIA,GAAS,UAAU,OAAS,OAAW,CACvC,IAAMS,EAAW,MAAMzB,EAAS,KAAK,EAErC,GAAI,CACAuB,EAAgBE,EAAUT,EAAQ,SAAS,IAAI,CACnD,MAAE,CACE,MAAM,IAAI,MAAM,GAAGJ,KAAgBE,mBAAsB,KAAK,UAAUW,CAAQ,gBAAgB,KAAK,UAAUT,EAAQ,SAAS,IAAI,GAAG,CAC3I,EAGJ,MAAO,CACH,YAAa,GAAGJ,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAS,GAAGF,KAAgBE,oBAC5B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,KAAAA,EACA,OAAQE,GAAS,cAAc,QAAU,MACzC,OAAQhB,EAAS,MACrB,CACJ,CACJ,OAASU,EAAP,CACE,MAAO,CACH,YAAa,GAAGE,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAUJ,EAAgB,QAC1B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,KAAAI,EACA,OAAQE,GAAS,cAAc,QAAU,KAC7C,CACJ,CACJ,CACJ,EAEOU,EAAQF,EC7Df,IAAMZ,EAAe,yBAMfe,EAAwBC,GAA0C,SAAY,CAEhF,IAAMC,EAAkC,aAEpCC,EASJ,OANID,IAAgB,QAAaD,IAAwB,QAAaC,IAAgBD,EAClFE,EAAe,4CAA4CD,kBAA4BD,MAC/EC,IACRC,EAAe,CAAC,yCAA0C,qDAAqD,EAAE,KAAK,GAAG,GAGzHA,IAAiB,OACV,CACH,YAAalB,EACb,OAAQ,CACJ,QAAS,GACT,QAASkB,EACT,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,CACJ,EAGG,CACH,YAAalB,EACb,OAAQ,CACJ,QAAS,GACT,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAM,CACF,IAAKiB,CACT,CACJ,CACJ,EAEOE,EAAQJ,EC3Cf,OAAOK,MAAU,UAIjB,IAAMpB,EAAe,iBAKfqB,EAAY,CAACnB,EAAcE,IAA2C,SAAY,CACpF,GAAI,CACA,IAAMhB,EAAW,MAAMgC,EAAKlB,EAAK,QAAQ,eAAgB,EAAE,EAAGE,CAAO,EAErE,OAAKhB,EAAS,MAYP,CACH,YAAa,GAAGY,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAS,GAAGF,KAAgBE,oBAC5B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAMd,CACV,EAnBW,CACH,YAAa,GAAGY,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAS,mBAAmBA,KAC5B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,EACA,KAAMd,CACV,CAYR,OAASU,EAAP,CACE,MAAO,CACH,YAAa,GAAGE,KAAgBE,IAChC,OAAQ,CACJ,QAAS,GACT,QAAUJ,EAAgB,QAC1B,UAAW,IAAI,KAAK,EAAE,YAAY,CACtC,CACJ,CACJ,CACJ,EAEOwB,EAAQD","sourcesContent":["import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck, HealthReport } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default (healthCheck: HealthCheck, sendHeader: boolean | undefined = true) => async <Request extends IncomingMessage, Response extends ServerResponse>(_: Request, response: Response): Promise<void> => {\n const { healthy, report } = await healthCheck.getReport();\n\n const payload: HealthCheckApiPayload = {\n status: healthy ? \"ok\" : \"error\",\n message: healthy ? \"Health check successful\" : \"Health check failed\",\n appName: process.env[\"APP_NAME\"] ?? \"unknown\",\n appVersion: process.env[\"APP_VERSION\"] ?? \"unknown\",\n timestamp: new Date().toISOString(),\n reports: report,\n };\n\n response.statusCode = healthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE;\n\n if (sendHeader) {\n response.setHeader(\"Content-Type\", \"application/json\");\n }\n\n response.end(JSON.stringify(payload, null, 2));\n};\n\nexport type HealthCheckApiPayload = {\n status: \"error\" | \"ok\";\n message: string;\n appName: string;\n appVersion: string;\n timestamp: string;\n reports: HealthReport;\n};\n","import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default <Request extends IncomingMessage, Response extends ServerResponse>(healthCheck: HealthCheck) => async (_request: Request, response: Response): Promise<void> => {\n const { healthy } = await healthCheck.getReport();\n\n response.statusCode = healthy ? StatusCodes.NO_CONTENT : StatusCodes.SERVICE_UNAVAILABLE;\n response.end();\n};\n","import type {\n Checker, HealthCheck as HealthcheckInterface, HealthReport, HealthReportEntry,\n} from \"./types.d\";\n\nclass Healthcheck implements HealthcheckInterface {\n /**\n * A copy of registered checkers\n */\n private healthCheckers: { [service: string]: Checker } = {};\n\n /**\n * Returns an array of registered services names\n */\n public get servicesList(): string[] {\n return Object.keys(this.healthCheckers);\n }\n\n /**\n * Invokes a given checker to collect the report metrics.\n */\n private async invokeChecker(service: string, reportSheet: HealthReport): Promise<boolean> {\n const checker = this.healthCheckers[service] as Checker;\n\n let report: HealthReportEntry;\n\n try {\n report = await checker();\n\n report.displayName = report.displayName || service;\n } catch (error: any) {\n report = {\n displayName: service,\n health: { healthy: false, message: (error as Error).message, timestamp: new Date().toISOString() },\n meta: { fatal: true },\n };\n }\n\n // eslint-disable-next-line no-param-reassign\n reportSheet[service] = report;\n\n return report.health.healthy;\n }\n\n public addChecker(service: string, checker: Checker): void {\n this.healthCheckers[service] = checker;\n }\n\n /**\n * Returns the health check reports. The health checks are performed when\n * this method is invoked.\n */\n public async getReport(): Promise<{ healthy: boolean; report: HealthReport }> {\n const report: HealthReport = {};\n\n // eslint-disable-next-line compat/compat\n await Promise.all(Object.keys(this.healthCheckers).map((service) => this.invokeChecker(service, report)));\n\n /**\n * Finding unhealthy service to know if system is healthy or not\n */\n const unhealthyService = Object.keys(report).find((service) => !(report[service] as HealthReportEntry).health.healthy);\n\n return { healthy: !unhealthyService, report };\n }\n\n public async isLive(): Promise<boolean> {\n const { healthy } = await this.getReport();\n\n return healthy;\n }\n}\n\nexport default Healthcheck;\n","import type { IPFamily, Options } from \"cacheable-lookup\";\nimport CacheableLookup from \"cacheable-lookup\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"DNS check for\";\n\n/**\n * Register the `dns` checker to ensure that a domain is reachable.\n */\nconst dnsCheck = (\n host: string,\n expectedAddresses?: string[],\n options?: Options & {\n family?: IPFamily | \"all\";\n hints?: number;\n },\n): Checker => async () => {\n const { hints, family = \"all\", ...config } = options ?? {};\n\n const cacheable = new CacheableLookup(config);\n\n try {\n const meta = await cacheable.lookupAsync(host.replace(/^https?:\\/\\//, \"\"), {\n hints,\n ...(family === \"all\" ? { all: true } : { family }),\n });\n\n if (Array.isArray(expectedAddresses) && !expectedAddresses.includes(meta.address)) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `${DISPLAY_NAME} ${host} returned address ${meta.address} instead of ${expectedAddresses.join(\", \")}.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} were resolved.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n },\n };\n }\n};\n\nexport default dnsCheck;\n","import { deepStrictEqual } from \"node:assert\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"HTTP check for\";\n\n/**\n * Register the `http` checker to ensure http body and status is correct.\n */\nconst httpCheck = (\n host: RequestInfo | URL,\n options?: {\n fetchOptions?: RequestInit;\n expected?: { status?: number; body?: string };\n },\n): Checker => async () => {\n try {\n // eslint-disable-next-line compat/compat\n const response = await fetch(host, options?.fetchOptions ?? {});\n\n if (options?.expected?.status !== undefined && options.expected.status !== response.status) {\n throw new Error(`${DISPLAY_NAME} ${host} returned status ${response.status} instead of ${options.expected.status}`);\n }\n\n if (options?.expected?.body !== undefined) {\n const textBody = await response.text();\n\n try {\n deepStrictEqual(textBody, options.expected.body);\n } catch {\n throw new Error(`${DISPLAY_NAME} ${host} returned body ${JSON.stringify(textBody)} instead of ${JSON.stringify(options.expected.body)}`);\n }\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n status: response.status,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n },\n };\n }\n};\n\nexport default httpCheck;\n","import type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Node Environment Check\";\n\n/**\n * Register the `env` checker to ensure that `NODE_ENV` environment\n * variable is defined.\n */\nconst nodeEnvironmentCheck = (expectedEnvironment?: string): Checker => async () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const environment: string | undefined = process.env[\"NODE_ENV\"];\n\n let errorMessage: string | undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (environment !== undefined && expectedEnvironment !== undefined && environment !== expectedEnvironment) {\n errorMessage = `NODE_ENV environment variable is set to \"${environment}\" instead of \"${expectedEnvironment}\".`;\n } else if (!environment) {\n errorMessage = [\"Missing NODE_ENV environment variable.\", \"It can make some parts of the application misbehave\"].join(\" \");\n }\n\n if (errorMessage !== undefined) {\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: false,\n message: errorMessage,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: true,\n timestamp: new Date().toISOString(),\n },\n meta: {\n env: environment,\n },\n };\n};\n\nexport default nodeEnvironmentCheck;\n","import type { extendedPingOptions } from \"pingman\";\nimport ping from \"pingman\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Ping check for\";\n\n/**\n * Register the `ping` checker to ensure that a domain is reachable.\n */\nconst pingCheck = (host: string, options?: extendedPingOptions): Checker => async () => {\n try {\n const response = await ping(host.replace(/^https?:\\/\\//, \"\"), options);\n\n if (!response.alive) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `Ping failed for ${host}.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n };\n }\n};\n\nexport default pingCheck;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
import { StatusCodes } from 'http-status-codes';
|
|
2
|
-
import
|
|
2
|
+
import k from 'cacheable-lookup';
|
|
3
3
|
import { deepStrictEqual } from 'assert';
|
|
4
|
-
import
|
|
4
|
+
import R from 'pingman';
|
|
5
5
|
|
|
6
|
-
var
|
|
6
|
+
var f=(t,e=!0)=>async(a,r)=>{let{healthy:s,report:o}=await t.getReport(),l={status:s?"ok":"error",message:s?"Health check successful":"Health check failed",appName:process.env.APP_NAME??"unknown",appVersion:process.env.APP_VERSION??"unknown",timestamp:new Date().toISOString(),reports:o};r.statusCode=s?StatusCodes.OK:StatusCodes.SERVICE_UNAVAILABLE,e&&r.setHeader("Content-Type","application/json"),r.end(JSON.stringify(l,null,2));};var u=t=>async(e,a)=>{let{healthy:r}=await t.getReport();a.statusCode=r?StatusCodes.NO_CONTENT:StatusCodes.SERVICE_UNAVAILABLE,a.end();};var c=class{constructor(){this.healthCheckers={};}get servicesList(){return Object.keys(this.healthCheckers)}async invokeChecker(e,a){let r=this.healthCheckers[e],s;try{s=await r(),s.displayName=s.displayName||e;}catch(o){s={displayName:e,health:{healthy:!1,message:o.message,timestamp:new Date().toISOString()},meta:{fatal:!0}};}return a[e]=s,s.health.healthy}addChecker(e,a){this.healthCheckers[e]=a;}async getReport(){let e={};return await Promise.all(Object.keys(this.healthCheckers).map(r=>this.invokeChecker(r,e))),{healthy:!Object.keys(e).find(r=>!e[r].health.healthy),report:e}}async isLive(){let{healthy:e}=await this.getReport();return e}},g=c;var i="DNS check for",C=(t,e,a)=>async()=>{let{hints:r,family:s="all",...o}=a??{},l=new k(o);try{let n=await l.lookupAsync(t.replace(/^https?:\/\//,""),{hints:r,...s==="all"?{all:!0}:{family:s}});return Array.isArray(e)&&!e.includes(n.address)?{displayName:`${i} ${t}`,health:{healthy:!1,message:`${i} ${t} returned address ${n.address} instead of ${e.join(", ")}.`,timestamp:new Date().toISOString()},meta:{host:t,addresses:n}}:{displayName:`${i} ${t}`,health:{healthy:!0,message:`${i} ${t} were resolved.`,timestamp:new Date().toISOString()},meta:{host:t,addresses:n}}}catch(n){return {displayName:`${i} ${t}`,health:{healthy:!1,message:n.message,timestamp:new Date().toISOString()},meta:{host:t}}}},S=C;var h="HTTP check for",$=(t,e)=>async()=>{try{let a=await fetch(t,e?.fetchOptions??{});if(e?.expected?.status!==void 0&&e.expected.status!==a.status)throw new Error(`${h} ${t} returned status ${a.status} instead of ${e.expected.status}`);if(e?.expected?.body!==void 0){let r=await a.text();try{deepStrictEqual(r,e.expected.body);}catch{throw new Error(`${h} ${t} returned body ${JSON.stringify(r)} instead of ${JSON.stringify(e.expected.body)}`)}}return {displayName:`${h} ${t}`,health:{healthy:!0,message:`${h} ${t} was successful.`,timestamp:new Date().toISOString()},meta:{host:t,method:e?.fetchOptions?.method??"GET",status:a.status}}}catch(a){return {displayName:`${h} ${t}`,health:{healthy:!1,message:a.message,timestamp:new Date().toISOString()},meta:{host:t,method:e?.fetchOptions?.method??"GET"}}}},O=$;var y="Node Environment Check",E=t=>async()=>{let e="production",a;return t!==void 0&&e!==t?a=`NODE_ENV environment variable is set to "${e}" instead of "${t}".`:e,a!==void 0?{displayName:y,health:{healthy:!1,message:a,timestamp:new Date().toISOString()}}:{displayName:y,health:{healthy:!0,timestamp:new Date().toISOString()},meta:{env:e}}},I=E;var p="Ping check for",w=(t,e)=>async()=>{try{let a=await R(t.replace(/^https?:\/\//,""),e);return a.alive?{displayName:`${p} ${t}`,health:{healthy:!0,message:`${p} ${t} was successful.`,timestamp:new Date().toISOString()},meta:a}:{displayName:`${p} ${t}`,health:{healthy:!1,message:`Ping failed for ${t}.`,timestamp:new Date().toISOString()},meta:a}}catch(a){return {displayName:`${p} ${t}`,health:{healthy:!1,message:a.message,timestamp:new Date().toISOString()}}}},x=w;
|
|
7
7
|
|
|
8
|
-
export {
|
|
8
|
+
export { g as HealthCheck, S as dnsCheck, f as healthCheckHandler, u as healthReadyHandler, O as httpCheck, I as nodeEnvCheck, x as pingCheck };
|
|
9
9
|
//# sourceMappingURL=out.js.map
|
|
10
10
|
//# sourceMappingURL=index.mjs.map
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/handler/healthcheck.ts","../src/handler/readyhandler.ts","../src/healthcheck.ts","../src/checks/dns-check.ts","../src/checks/http-check.ts","../src/checks/node-environment-check.ts","../src/checks/ping-check.ts"],"names":["StatusCodes","healthcheck_default","healthCheck","sendHeader","_","response","healthy","report","payload","readyhandler_default","_request","Healthcheck","__publicField","service","reportSheet","checker","error","CacheableLookup","DISPLAY_NAME","dnsCheck","host","expectedAddresses","options","hints","family","config","cacheable","meta","dns_check_default","deepStrictEqual","httpCheck","textBody","http_check_default","nodeEnvironmentCheck","expectedEnvironment","environment","errorMessage","node_environment_check_default","ping","pingCheck","ping_check_default"],"mappings":"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","sourcesContent":["import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck, HealthReport } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default (healthCheck: HealthCheck, sendHeader: boolean | undefined = true) => async <Request extends IncomingMessage, Response extends ServerResponse>(_: Request, response: Response): Promise<void> => {\n const { healthy, report } = await healthCheck.getReport();\n\n const payload: HealthCheckApiPayload = {\n status: healthy ? \"ok\" : \"error\",\n message: healthy ? \"Health check successful\" : \"Health check failed\",\n appName: process.env[\"APP_NAME\"] ?? \"unknown\",\n appVersion: process.env[\"APP_VERSION\"] ?? \"unknown\",\n timestamp: new Date().toISOString(),\n reports: report,\n };\n\n response.statusCode = healthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE;\n\n if (sendHeader) {\n response.setHeader(\"Content-Type\", \"application/json\");\n }\n\n response.end(JSON.stringify(payload, null, 2));\n};\n\nexport type HealthCheckApiPayload = {\n status: \"error\" | \"ok\";\n message: string;\n appName: string;\n appVersion: string;\n timestamp: string;\n reports: HealthReport;\n};\n","import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default <Request extends IncomingMessage, Response extends ServerResponse>(healthCheck: HealthCheck) => async (_request: Request, response: Response): Promise<void> => {\n const { healthy } = await healthCheck.getReport();\n\n response.statusCode = healthy ? StatusCodes.NO_CONTENT : StatusCodes.SERVICE_UNAVAILABLE;\n response.end();\n};\n","import type {\n Checker, HealthCheck as HealthcheckInterface, HealthReport, HealthReportEntry,\n} from \"./types.d\";\n\nclass Healthcheck implements HealthcheckInterface {\n /**\n * A copy of registered checkers\n */\n private healthCheckers: { [service: string]: Checker } = {};\n\n /**\n * Returns an array of registered services names\n */\n public get servicesList(): string[] {\n return Object.keys(this.healthCheckers);\n }\n\n /**\n * Invokes a given checker to collect the report metrics.\n */\n private async invokeChecker(service: string, reportSheet: HealthReport): Promise<boolean> {\n const checker = this.healthCheckers[service] as Checker;\n\n let report: HealthReportEntry;\n\n try {\n report = await checker();\n\n report.displayName = report.displayName || service;\n } catch (error: any) {\n report = {\n displayName: service,\n health: { healthy: false, message: (error as Error).message, timestamp: new Date().toISOString() },\n meta: { fatal: true },\n };\n }\n\n // eslint-disable-next-line no-param-reassign\n reportSheet[service] = report;\n\n return report.health.healthy;\n }\n\n public addChecker(service: string, checker: Checker): void {\n this.healthCheckers[service] = checker;\n }\n\n /**\n * Returns the health check reports. The health checks are performed when\n * this method is invoked.\n */\n public async getReport(): Promise<{ healthy: boolean; report: HealthReport }> {\n const report: HealthReport = {};\n\n // eslint-disable-next-line compat/compat\n await Promise.all(Object.keys(this.healthCheckers).map((service) => this.invokeChecker(service, report)));\n\n /**\n * Finding unhealthy service to know if system is healthy or not\n */\n const unhealthyService = Object.keys(report).find((service) => !(report[service] as HealthReportEntry).health.healthy);\n\n return { healthy: !unhealthyService, report };\n }\n\n public async isLive(): Promise<boolean> {\n const { healthy } = await this.getReport();\n\n return healthy;\n }\n}\n\nexport default Healthcheck;\n","import type { IPFamily, Options } from \"cacheable-lookup\";\nimport CacheableLookup from \"cacheable-lookup\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"DNS check for\";\n\n/**\n * Register the `dns` checker to ensure that a domain is reachable.\n */\nconst dnsCheck = (\n host: string,\n expectedAddresses?: string[],\n options?: Options & {\n family?: IPFamily | \"all\";\n hints?: number;\n },\n): Checker => async () => {\n const { hints, family = \"all\", ...config } = options ?? {};\n\n const cacheable = new CacheableLookup(config);\n\n try {\n const meta = await cacheable.lookupAsync(host.replace(/^https?:\\/\\//, \"\"), {\n hints,\n ...(family === \"all\" ? { all: true } : { family }),\n });\n\n if (Array.isArray(expectedAddresses) && !expectedAddresses.includes(meta.address)) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `${DISPLAY_NAME} ${host} returned address ${meta.address} instead of ${expectedAddresses.join(\", \")}.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} were resolved.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n },\n };\n }\n};\n\nexport default dnsCheck;\n","import { deepStrictEqual } from \"node:assert\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"HTTP check for\";\n\n/**\n * Register the `http` checker to ensure http body and status is correct.\n */\nconst httpCheck = (host: RequestInfo | URL, options?: {\n fetchOptions?: RequestInit,\n expected?: { status?: number; body?: string }\n}): Checker => async () => {\n try {\n // eslint-disable-next-line compat/compat\n const response = await fetch(host, options?.fetchOptions ?? {});\n\n if (options?.expected?.status !== undefined && options.expected.status !== response.status) {\n throw new Error(`${DISPLAY_NAME} ${host} returned status ${response.status} instead of ${options.expected.status}`);\n }\n\n if (options?.expected?.body !== undefined) {\n const textBody = await response.text();\n\n try {\n deepStrictEqual(textBody, options.expected.body);\n } catch {\n throw new Error(`${DISPLAY_NAME} ${host} returned body ${JSON.stringify(textBody)} instead of ${JSON.stringify(options.expected.body)}`);\n }\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n status: response.status,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n },\n };\n }\n};\n\nexport default httpCheck;\n","import type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Node Environment Check\";\n\n/**\n * Register the `env` checker to ensure that `NODE_ENV` environment\n * variable is defined.\n */\nconst nodeEnvironmentCheck = (expectedEnvironment?: string): Checker => async () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const environment: string | undefined = process.env[\"NODE_ENV\"];\n\n let errorMessage: string | undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (environment !== undefined && expectedEnvironment !== undefined && environment !== expectedEnvironment) {\n errorMessage = `NODE_ENV environment variable is set to \"${environment}\" instead of \"${expectedEnvironment}\".`;\n } else if (!environment) {\n errorMessage = [\"Missing NODE_ENV environment variable.\", \"It can make some parts of the application misbehave\"].join(\" \");\n }\n\n if (errorMessage !== undefined) {\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: false,\n message: errorMessage,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: true,\n timestamp: new Date().toISOString(),\n },\n meta: {\n env: environment,\n },\n };\n};\n\nexport default nodeEnvironmentCheck;\n","import type { extendedPingOptions } from \"pingman\";\nimport ping from \"pingman\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Ping check for\";\n\n/**\n * Register the `ping` checker to ensure that a domain is reachable.\n */\nconst pingCheck = (host: string, options?: extendedPingOptions): Checker => async () => {\n try {\n const response = await ping(host.replace(/^https?:\\/\\//, \"\"), options);\n\n if (!response.alive) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `Ping failed for ${host}.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n };\n }\n};\n\nexport default pingCheck;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/handler/healthcheck.ts","../src/handler/readyhandler.ts","../src/healthcheck.ts","../src/checks/dns-check.ts","../src/checks/http-check.ts","../src/checks/node-environment-check.ts","../src/checks/ping-check.ts"],"names":["StatusCodes","healthcheck_default","healthCheck","sendHeader","_","response","healthy","report","payload","readyhandler_default","_request","Healthcheck","service","reportSheet","checker","error","CacheableLookup","DISPLAY_NAME","dnsCheck","host","expectedAddresses","options","hints","family","config","cacheable","meta","dns_check_default","deepStrictEqual","httpCheck","textBody","http_check_default","nodeEnvironmentCheck","expectedEnvironment","environment","errorMessage","node_environment_check_default","ping","pingCheck","ping_check_default"],"mappings":"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","sourcesContent":["import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck, HealthReport } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default (healthCheck: HealthCheck, sendHeader: boolean | undefined = true) => async <Request extends IncomingMessage, Response extends ServerResponse>(_: Request, response: Response): Promise<void> => {\n const { healthy, report } = await healthCheck.getReport();\n\n const payload: HealthCheckApiPayload = {\n status: healthy ? \"ok\" : \"error\",\n message: healthy ? \"Health check successful\" : \"Health check failed\",\n appName: process.env[\"APP_NAME\"] ?? \"unknown\",\n appVersion: process.env[\"APP_VERSION\"] ?? \"unknown\",\n timestamp: new Date().toISOString(),\n reports: report,\n };\n\n response.statusCode = healthy ? StatusCodes.OK : StatusCodes.SERVICE_UNAVAILABLE;\n\n if (sendHeader) {\n response.setHeader(\"Content-Type\", \"application/json\");\n }\n\n response.end(JSON.stringify(payload, null, 2));\n};\n\nexport type HealthCheckApiPayload = {\n status: \"error\" | \"ok\";\n message: string;\n appName: string;\n appVersion: string;\n timestamp: string;\n reports: HealthReport;\n};\n","import { StatusCodes } from \"http-status-codes\";\nimport type { IncomingMessage, ServerResponse } from \"node:http\";\n\nimport type { HealthCheck } from \"../types\";\n\n// eslint-disable-next-line max-len\nexport default <Request extends IncomingMessage, Response extends ServerResponse>(healthCheck: HealthCheck) => async (_request: Request, response: Response): Promise<void> => {\n const { healthy } = await healthCheck.getReport();\n\n response.statusCode = healthy ? StatusCodes.NO_CONTENT : StatusCodes.SERVICE_UNAVAILABLE;\n response.end();\n};\n","import type {\n Checker, HealthCheck as HealthcheckInterface, HealthReport, HealthReportEntry,\n} from \"./types.d\";\n\nclass Healthcheck implements HealthcheckInterface {\n /**\n * A copy of registered checkers\n */\n private healthCheckers: { [service: string]: Checker } = {};\n\n /**\n * Returns an array of registered services names\n */\n public get servicesList(): string[] {\n return Object.keys(this.healthCheckers);\n }\n\n /**\n * Invokes a given checker to collect the report metrics.\n */\n private async invokeChecker(service: string, reportSheet: HealthReport): Promise<boolean> {\n const checker = this.healthCheckers[service] as Checker;\n\n let report: HealthReportEntry;\n\n try {\n report = await checker();\n\n report.displayName = report.displayName || service;\n } catch (error: any) {\n report = {\n displayName: service,\n health: { healthy: false, message: (error as Error).message, timestamp: new Date().toISOString() },\n meta: { fatal: true },\n };\n }\n\n // eslint-disable-next-line no-param-reassign\n reportSheet[service] = report;\n\n return report.health.healthy;\n }\n\n public addChecker(service: string, checker: Checker): void {\n this.healthCheckers[service] = checker;\n }\n\n /**\n * Returns the health check reports. The health checks are performed when\n * this method is invoked.\n */\n public async getReport(): Promise<{ healthy: boolean; report: HealthReport }> {\n const report: HealthReport = {};\n\n // eslint-disable-next-line compat/compat\n await Promise.all(Object.keys(this.healthCheckers).map((service) => this.invokeChecker(service, report)));\n\n /**\n * Finding unhealthy service to know if system is healthy or not\n */\n const unhealthyService = Object.keys(report).find((service) => !(report[service] as HealthReportEntry).health.healthy);\n\n return { healthy: !unhealthyService, report };\n }\n\n public async isLive(): Promise<boolean> {\n const { healthy } = await this.getReport();\n\n return healthy;\n }\n}\n\nexport default Healthcheck;\n","import type { IPFamily, Options } from \"cacheable-lookup\";\nimport CacheableLookup from \"cacheable-lookup\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"DNS check for\";\n\n/**\n * Register the `dns` checker to ensure that a domain is reachable.\n */\nconst dnsCheck = (\n host: string,\n expectedAddresses?: string[],\n options?: Options & {\n family?: IPFamily | \"all\";\n hints?: number;\n },\n): Checker => async () => {\n const { hints, family = \"all\", ...config } = options ?? {};\n\n const cacheable = new CacheableLookup(config);\n\n try {\n const meta = await cacheable.lookupAsync(host.replace(/^https?:\\/\\//, \"\"), {\n hints,\n ...(family === \"all\" ? { all: true } : { family }),\n });\n\n if (Array.isArray(expectedAddresses) && !expectedAddresses.includes(meta.address)) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `${DISPLAY_NAME} ${host} returned address ${meta.address} instead of ${expectedAddresses.join(\", \")}.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} were resolved.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n addresses: meta,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n },\n };\n }\n};\n\nexport default dnsCheck;\n","import { deepStrictEqual } from \"node:assert\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"HTTP check for\";\n\n/**\n * Register the `http` checker to ensure http body and status is correct.\n */\nconst httpCheck = (\n host: RequestInfo | URL,\n options?: {\n fetchOptions?: RequestInit;\n expected?: { status?: number; body?: string };\n },\n): Checker => async () => {\n try {\n // eslint-disable-next-line compat/compat\n const response = await fetch(host, options?.fetchOptions ?? {});\n\n if (options?.expected?.status !== undefined && options.expected.status !== response.status) {\n throw new Error(`${DISPLAY_NAME} ${host} returned status ${response.status} instead of ${options.expected.status}`);\n }\n\n if (options?.expected?.body !== undefined) {\n const textBody = await response.text();\n\n try {\n deepStrictEqual(textBody, options.expected.body);\n } catch {\n throw new Error(`${DISPLAY_NAME} ${host} returned body ${JSON.stringify(textBody)} instead of ${JSON.stringify(options.expected.body)}`);\n }\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n status: response.status,\n },\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n meta: {\n host,\n method: options?.fetchOptions?.method ?? \"GET\",\n },\n };\n }\n};\n\nexport default httpCheck;\n","import type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Node Environment Check\";\n\n/**\n * Register the `env` checker to ensure that `NODE_ENV` environment\n * variable is defined.\n */\nconst nodeEnvironmentCheck = (expectedEnvironment?: string): Checker => async () => {\n // eslint-disable-next-line @typescript-eslint/dot-notation\n const environment: string | undefined = process.env[\"NODE_ENV\"];\n\n let errorMessage: string | undefined;\n\n // eslint-disable-next-line @typescript-eslint/no-unnecessary-condition\n if (environment !== undefined && expectedEnvironment !== undefined && environment !== expectedEnvironment) {\n errorMessage = `NODE_ENV environment variable is set to \"${environment}\" instead of \"${expectedEnvironment}\".`;\n } else if (!environment) {\n errorMessage = [\"Missing NODE_ENV environment variable.\", \"It can make some parts of the application misbehave\"].join(\" \");\n }\n\n if (errorMessage !== undefined) {\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: false,\n message: errorMessage,\n timestamp: new Date().toISOString(),\n },\n };\n }\n\n return {\n displayName: DISPLAY_NAME,\n health: {\n healthy: true,\n timestamp: new Date().toISOString(),\n },\n meta: {\n env: environment,\n },\n };\n};\n\nexport default nodeEnvironmentCheck;\n","import type { extendedPingOptions } from \"pingman\";\nimport ping from \"pingman\";\n\nimport type { Checker } from \"../types\";\n\nconst DISPLAY_NAME = \"Ping check for\";\n\n/**\n * Register the `ping` checker to ensure that a domain is reachable.\n */\nconst pingCheck = (host: string, options?: extendedPingOptions): Checker => async () => {\n try {\n const response = await ping(host.replace(/^https?:\\/\\//, \"\"), options);\n\n if (!response.alive) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: `Ping failed for ${host}.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n }\n\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: true,\n message: `${DISPLAY_NAME} ${host} was successful.`,\n timestamp: new Date().toISOString(),\n },\n meta: response,\n };\n } catch (error: any) {\n return {\n displayName: `${DISPLAY_NAME} ${host}`,\n health: {\n healthy: false,\n message: (error as Error).message,\n timestamp: new Date().toISOString(),\n },\n };\n }\n};\n\nexport default pingCheck;\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@visulima/health-check",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.5",
|
|
4
4
|
"description": "A library built to provide support for defining service health for node services. It allows you to register async health checks for your dependencies and the service itself, provides a health endpoint that exposes their status, and health metrics.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"anolilab",
|
|
@@ -60,7 +60,7 @@
|
|
|
60
60
|
"build:prod": "cross-env NODE_ENV=production tsup",
|
|
61
61
|
"clean": "rimraf node_modules dist .eslintcache",
|
|
62
62
|
"coverage": "vitest run --coverage",
|
|
63
|
-
"dev": "pnpm
|
|
63
|
+
"dev": "pnpm run build --watch",
|
|
64
64
|
"lint:eslint": "cross-env NO_LOGS=true eslint . --ext js,jsx,ts,tsx --max-warnings=0 --config .eslintrc.cjs --cache --cache-strategy content .",
|
|
65
65
|
"lint:eslint:fix": "pnpm run lint:eslint --fix",
|
|
66
66
|
"test": "vitest run",
|
|
@@ -75,11 +75,11 @@
|
|
|
75
75
|
"@anolilab/eslint-config": "^5.0.5",
|
|
76
76
|
"@anolilab/semantic-release-preset": "^2.2.1",
|
|
77
77
|
"@rushstack/eslint-plugin-security": "^0.6.0",
|
|
78
|
-
"@types/node": "18.16.
|
|
79
|
-
"@types/react": "^18.2.
|
|
78
|
+
"@types/node": "18.16.16",
|
|
79
|
+
"@types/react": "^18.2.8",
|
|
80
80
|
"@types/react-dom": "^18.2.4",
|
|
81
|
-
"@typescript-eslint/eslint-plugin": "^5.59.
|
|
82
|
-
"@typescript-eslint/parser": "^5.59.
|
|
81
|
+
"@typescript-eslint/eslint-plugin": "^5.59.8",
|
|
82
|
+
"@typescript-eslint/parser": "^5.59.8",
|
|
83
83
|
"@vitest/coverage-c8": "^0.31.1",
|
|
84
84
|
"cross-env": "^7.0.3",
|
|
85
85
|
"cross-fetch": "^3.1.6",
|
|
@@ -104,12 +104,11 @@
|
|
|
104
104
|
"eslint-plugin-unicorn": "^47.0.0",
|
|
105
105
|
"eslint-plugin-you-dont-need-lodash-underscore": "^6.12.0",
|
|
106
106
|
"eslint-plugin-you-dont-need-momentjs": "^1.6.0",
|
|
107
|
-
"next": "^13.
|
|
107
|
+
"next": "^13.4.4",
|
|
108
108
|
"node-mocks-http": "^1.12.2",
|
|
109
109
|
"prettier": "^2.8.8",
|
|
110
110
|
"react": "^18.2.0",
|
|
111
111
|
"react-dom": "^18.2.0",
|
|
112
|
-
"read-pkg": "^8.0.0",
|
|
113
112
|
"rimraf": "^5.0.1",
|
|
114
113
|
"semantic-release": "^21.0.2",
|
|
115
114
|
"tsup": "^6.7.0",
|
|
@@ -117,12 +116,13 @@
|
|
|
117
116
|
"vitest": "^0.31.1"
|
|
118
117
|
},
|
|
119
118
|
"optionalDependencies": {
|
|
120
|
-
"next": "^13.
|
|
119
|
+
"next": "^13.4.4"
|
|
121
120
|
},
|
|
122
121
|
"engines": {
|
|
123
122
|
"node": ">=16.18.0 <=20.*"
|
|
124
123
|
},
|
|
125
124
|
"publishConfig": {
|
|
126
|
-
"access": "public"
|
|
125
|
+
"access": "public",
|
|
126
|
+
"provenance": true
|
|
127
127
|
}
|
|
128
128
|
}
|