@entwico/health-probes 1.1.0

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 entwico GmbH
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,320 @@
1
+ # health-probes
2
+
3
+ Health check probes for Node.js. Provides liveness, readiness, startup, and health status endpoints on a separate HTTP server. Framework-agnostic — works with any Node.js application.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @entwico/health-probes
9
+ ```
10
+
11
+ ## Usage
12
+
13
+ ```ts
14
+ import { checks, probes, server } from '@entwico/health-probes';
15
+
16
+ // start health server on a separate port
17
+ // default host is '127.0.0.1' for security reasons
18
+ // use host: '0.0.0.0' in k8s containers so the kubelet can reach the probes
19
+ server.start({ host: '0.0.0.0', port: 9090 });
20
+
21
+ // enable liveness immediately
22
+ probes.live.enable();
23
+
24
+ // initialize your app...
25
+ await connectToDatabase();
26
+
27
+ // register health checks
28
+ checks.register('database', () => db.ping());
29
+
30
+ // enable startup probe (initialization complete)
31
+ probes.startup.enable();
32
+
33
+ // enable readiness probe (ready for traffic)
34
+ probes.ready.enable();
35
+ ```
36
+
37
+ ### Graceful shutdown
38
+
39
+ ```ts
40
+ // disable readiness first (stop receiving traffic)
41
+ probes.ready.disable();
42
+
43
+ await disconnectFromDatabase();
44
+
45
+ // stop health server
46
+ await server.stop();
47
+ ```
48
+
49
+ ## Probes
50
+
51
+ ### Liveness Probe
52
+
53
+ Indicates if the process is running. If this fails, the orchestrator should restart the container.
54
+
55
+ ```ts
56
+ probes.live.enable(); // returns 200 OK
57
+ probes.live.disable(); // returns 503 Service Unavailable
58
+ ```
59
+
60
+ ### Startup Probe
61
+
62
+ Indicates if the application has finished initializing.
63
+
64
+ ```ts
65
+ probes.startup.enable();
66
+ probes.startup.disable();
67
+ ```
68
+
69
+ ### Readiness Probe
70
+
71
+ Indicates if the application is ready to receive traffic. When disabled or when required health checks fail, returns 503.
72
+
73
+ ```ts
74
+ probes.ready.enable();
75
+ probes.ready.disable();
76
+ ```
77
+
78
+ The readiness probe automatically runs all non-optional health checks and returns 503 if any fail.
79
+
80
+ ### Health Status
81
+
82
+ Returns detailed JSON status of all probes and health checks. Useful for debugging and dashboards.
83
+
84
+ ```json
85
+ {
86
+ "status": "healthy",
87
+ "probes": {
88
+ "live": true,
89
+ "startup": true,
90
+ "ready": true
91
+ },
92
+ "checks": {
93
+ "database": {
94
+ "status": "healthy",
95
+ "latency": 12
96
+ },
97
+ "redis": {
98
+ "status": "unhealthy",
99
+ "latency": 5003,
100
+ "error": "check \"redis\" timed out after 5000ms"
101
+ }
102
+ }
103
+ }
104
+ ```
105
+
106
+ Status values:
107
+
108
+ - `healthy` — all checks pass
109
+ - `degraded` — optional checks failing, required checks pass
110
+ - `unhealthy` — required checks failing
111
+
112
+ ## Health Checks
113
+
114
+ Register health checks to verify dependencies are working:
115
+
116
+ ```ts
117
+ import { checks } from '@entwico/health-probes';
118
+
119
+ // return result (recommended for boolean checks)
120
+ checks.register('database', () => ({
121
+ status: db.isConnected() ? 'healthy' : 'unhealthy',
122
+ error: db.isConnected() ? undefined : 'connection lost',
123
+ }));
124
+
125
+ // throw-based (classic pattern)
126
+ checks.register('cache', async () => {
127
+ await redis.ping(); // throws if fails
128
+ });
129
+
130
+ // with options
131
+ checks.register({
132
+ name: 'external-api',
133
+ check: () => fetch('https://api.example.com/health').then(() => {}),
134
+ optional: true, // doesn't affect readiness, only health status
135
+ timeout: 10000, // custom timeout (default: 5000ms)
136
+ });
137
+ ```
138
+
139
+ The check function can either:
140
+
141
+ - Return `HealthCheckResult` with status and optional error
142
+ - Return `void` (completing without error = healthy)
143
+ - Throw an error (= unhealthy with error message)
144
+
145
+ ### Unregistering Checks
146
+
147
+ `register()` returns an unregister function:
148
+
149
+ ```ts
150
+ const unregister = checks.register({
151
+ name: 'database',
152
+ check: () => db.ping(),
153
+ });
154
+
155
+ // later...
156
+ unregister();
157
+ ```
158
+
159
+ ## Server Options
160
+
161
+ ```ts
162
+ server.start({
163
+ host: '0.0.0.0', // default: '127.0.0.1'
164
+ port: 9090, // default: 9090
165
+ });
166
+ ```
167
+
168
+ Resolution order: **explicit option > environment variable > default**.
169
+
170
+ | Setting | Env Variable | Default |
171
+ | ------- | --------------- | ------------- |
172
+ | host | `HEALTH_HOST` | `127.0.0.1` |
173
+ | port | `HEALTH_PORT` | `9090` |
174
+
175
+ This means `server.start()` with no arguments will pick up `HEALTH_HOST` / `HEALTH_PORT` from the environment if set.
176
+
177
+ ### Custom Paths
178
+
179
+ By default, endpoints use Kubernetes-style paths (`/livez`, `/readyz`, `/startupz`, `/healthz`). You can customize them:
180
+
181
+ ```ts
182
+ import { SimplePaths } from '@entwico/health-probes';
183
+
184
+ // use simple paths: /live, /ready, /startup, /health
185
+ server.start({ paths: SimplePaths });
186
+
187
+ // or mix and match
188
+ server.start({
189
+ paths: {
190
+ live: '/healthcheck',
191
+ ready: '/ready',
192
+ },
193
+ });
194
+ ```
195
+
196
+ Built-in path presets:
197
+
198
+ | Preset | live | startup | ready | health |
199
+ | -------------------- | -------- | ----------- | --------- | ---------- |
200
+ | `K8sPaths` (default) | `/livez` | `/startupz` | `/readyz` | `/healthz` |
201
+ | `SimplePaths` | `/live` | `/startup` | `/ready` | `/health` |
202
+
203
+ ## Kubernetes Configuration
204
+
205
+ ```yaml
206
+ apiVersion: v1
207
+ kind: Pod
208
+ spec:
209
+ containers:
210
+ - name: app
211
+ ports:
212
+ - containerPort: 3000 # app
213
+ - containerPort: 9090 # health
214
+ livenessProbe:
215
+ httpGet:
216
+ path: /livez
217
+ port: 9090
218
+ initialDelaySeconds: 0
219
+ periodSeconds: 10
220
+ startupProbe:
221
+ httpGet:
222
+ path: /startupz
223
+ port: 9090
224
+ failureThreshold: 30
225
+ periodSeconds: 2
226
+ readinessProbe:
227
+ httpGet:
228
+ path: /readyz
229
+ port: 9090
230
+ periodSeconds: 5
231
+ ```
232
+
233
+ ## API Reference
234
+
235
+ ### Server
236
+
237
+ ```ts
238
+ import { server } from '@entwico/health-probes';
239
+
240
+ server.start(options?: HealthServerOptions): void;
241
+ server.stop(): Promise<void>;
242
+ ```
243
+
244
+ ### Probes
245
+
246
+ ```ts
247
+ import { probes } from '@entwico/health-probes';
248
+
249
+ probes.live.enable(): void;
250
+ probes.live.disable(): void;
251
+ probes.live.get(): Promise<HealthProbeResult>;
252
+ probes.live.response(): Promise<Response>;
253
+
254
+ // same for startup, ready
255
+
256
+ probes.health.get(): Promise<HealthResult>;
257
+ probes.health.response(): Promise<Response>;
258
+ ```
259
+
260
+ ### Checks
261
+
262
+ ```ts
263
+ import { checks } from '@entwico/health-probes';
264
+
265
+ checks.register(name: string, check: CheckFn): () => void;
266
+ checks.register(check: HealthCheck): () => void;
267
+
268
+ // CheckFn = () => Promise<HealthCheckResult | void> | HealthCheckResult | void
269
+ checks.getChecks(): HealthCheck[];
270
+ checks.runAll(): Promise<Record<string, HealthCheckResult>>;
271
+ checks.runRequired(): Promise<boolean>;
272
+ ```
273
+
274
+ ## Types
275
+
276
+ ```ts
277
+ interface ProbePaths {
278
+ live?: string;
279
+ startup?: string;
280
+ ready?: string;
281
+ health?: string;
282
+ }
283
+
284
+ interface HealthServerOptions {
285
+ host?: string; // env: HEALTH_HOST, default: '127.0.0.1'
286
+ port?: number; // env: HEALTH_PORT, default: 9090
287
+ paths?: ProbePaths; // default: K8sPaths
288
+ }
289
+
290
+ interface HealthCheck {
291
+ name: string;
292
+ check: () => Promise<HealthCheckResult | void> | HealthCheckResult | void;
293
+ optional?: boolean; // default: false
294
+ timeout?: number; // default: 5000
295
+ }
296
+
297
+ interface HealthCheckResult {
298
+ status: 'healthy' | 'unhealthy';
299
+ latency?: number;
300
+ error?: string;
301
+ }
302
+
303
+ interface HealthProbeResult {
304
+ passing: boolean;
305
+ }
306
+
307
+ interface HealthResult {
308
+ status: 'healthy' | 'degraded' | 'unhealthy';
309
+ probes: {
310
+ live: boolean;
311
+ startup: boolean;
312
+ ready: boolean;
313
+ };
314
+ checks: Record<string, HealthCheckResult>;
315
+ }
316
+ ```
317
+
318
+ ## License
319
+
320
+ MIT
@@ -0,0 +1,12 @@
1
+ import type { HealthCheck, HealthCheckResult } from './types.js';
2
+ export declare class HealthChecks {
3
+ private readonly registered;
4
+ register(name: string, check: () => Promise<HealthCheckResult | void> | HealthCheckResult | void): () => void;
5
+ register(check: HealthCheck): () => void;
6
+ private run;
7
+ runAll(): Promise<Record<string, HealthCheckResult>>;
8
+ runRequired(): Promise<boolean>;
9
+ getChecks(): HealthCheck[];
10
+ }
11
+ export declare const checks: HealthChecks;
12
+ //# sourceMappingURL=checks.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.d.ts","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,WAAW,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAOjE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAC,UAAU,CAAkC;IAM7D,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,KAAK,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,iBAAiB,GAAG,IAAI,GAAG,MAAM,IAAI;IAC7G,QAAQ,CAAC,KAAK,EAAE,WAAW,GAAG,MAAM,IAAI;YAqB1B,GAAG;IA8BX,MAAM,IAAI,OAAO,CAAC,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;IAkBpD,WAAW,IAAI,OAAO,CAAC,OAAO,CAAC;IAqBrC,SAAS,IAAI,WAAW,EAAE;CAG3B;AAED,eAAO,MAAM,MAAM,cAAqB,CAAC"}
package/dist/checks.js ADDED
@@ -0,0 +1,63 @@
1
+ const DEFAULT_TIMEOUT = 5000;
2
+ export class HealthChecks {
3
+ registered = new Map();
4
+ register(nameOrCheck, checkFn) {
5
+ const check = typeof nameOrCheck === 'string' ? { name: nameOrCheck, check: checkFn } : nameOrCheck;
6
+ if (this.registered.has(check.name)) {
7
+ console.warn(`[health] overwriting existing check "${check.name}"`);
8
+ }
9
+ this.registered.set(check.name, check);
10
+ return () => {
11
+ this.registered.delete(check.name);
12
+ };
13
+ }
14
+ async run(check) {
15
+ const timeout = check.timeout ?? DEFAULT_TIMEOUT;
16
+ const start = performance.now();
17
+ try {
18
+ const result = await Promise.race([
19
+ Promise.resolve(check.check()),
20
+ new Promise((_, reject) => {
21
+ setTimeout(() => reject(new Error(`check "${check.name}" timed out after ${timeout}ms`)), timeout);
22
+ }),
23
+ ]);
24
+ const latency = Math.round(performance.now() - start);
25
+ if (result) {
26
+ return { ...result, latency };
27
+ }
28
+ return { status: 'healthy', latency };
29
+ }
30
+ catch (error) {
31
+ const latency = Math.round(performance.now() - start);
32
+ const errorMessage = error instanceof Error ? error.message : String(error);
33
+ return { status: 'unhealthy', latency, error: errorMessage };
34
+ }
35
+ }
36
+ async runAll() {
37
+ const results = {};
38
+ const checks = [...this.registered.values()];
39
+ const checkPromises = checks.map(async (check) => {
40
+ const result = await this.run(check);
41
+ results[check.name] = result;
42
+ });
43
+ await Promise.all(checkPromises);
44
+ return results;
45
+ }
46
+ async runRequired() {
47
+ const requiredChecks = [...this.registered.values()].filter((check) => !check.optional);
48
+ if (requiredChecks.length === 0) {
49
+ return true;
50
+ }
51
+ const checkPromises = requiredChecks.map(async (check) => {
52
+ const result = await this.run(check);
53
+ return result.status === 'healthy';
54
+ });
55
+ const results = await Promise.all(checkPromises);
56
+ return results.every(Boolean);
57
+ }
58
+ getChecks() {
59
+ return [...this.registered.values()];
60
+ }
61
+ }
62
+ export const checks = new HealthChecks();
63
+ //# sourceMappingURL=checks.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"checks.js","sourceRoot":"","sources":["../src/checks.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export { server } from './server.js';
2
+ export { probes } from './probes.js';
3
+ export { checks } from './checks.js';
4
+ export { HealthServer } from './server.js';
5
+ export { HealthProbes } from './probes.js';
6
+ export { HealthChecks } from './checks.js';
7
+ export { K8sPaths, SimplePaths } from './paths.js';
8
+ export type { HealthCheck, HealthCheckResult, HealthProbe, HealthProbeResult, HealthResult, HealthServerOptions, HealthStatusProbe, ProbePaths, } from './types.js';
9
+ //# sourceMappingURL=index.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC;AAGnD,YAAY,EACV,WAAW,EACX,iBAAiB,EACjB,WAAW,EACX,iBAAiB,EACjB,YAAY,EACZ,mBAAmB,EACnB,iBAAiB,EACjB,UAAU,GACX,MAAM,YAAY,CAAC"}
package/dist/index.js ADDED
@@ -0,0 +1,8 @@
1
+ export { server } from './server.js';
2
+ export { probes } from './probes.js';
3
+ export { checks } from './checks.js';
4
+ export { HealthServer } from './server.js';
5
+ export { HealthProbes } from './probes.js';
6
+ export { HealthChecks } from './checks.js';
7
+ export { K8sPaths, SimplePaths } from './paths.js';
8
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AACrC,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAGrC,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAC3C,OAAO,EAAE,YAAY,EAAE,MAAM,aAAa,CAAC;AAG3C,OAAO,EAAE,QAAQ,EAAE,WAAW,EAAE,MAAM,YAAY,CAAC"}
@@ -0,0 +1,4 @@
1
+ import type { ProbePaths } from './types.js';
2
+ export declare const K8sPaths: Required<ProbePaths>;
3
+ export declare const SimplePaths: Required<ProbePaths>;
4
+ //# sourceMappingURL=paths.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.d.ts","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,YAAY,CAAC;AAM7C,eAAO,MAAM,QAAQ,EAAE,QAAQ,CAAC,UAAU,CAKzC,CAAC;AAKF,eAAO,MAAM,WAAW,EAAE,QAAQ,CAAC,UAAU,CAK5C,CAAC"}
package/dist/paths.js ADDED
@@ -0,0 +1,13 @@
1
+ export const K8sPaths = {
2
+ live: '/livez',
3
+ startup: '/startupz',
4
+ ready: '/readyz',
5
+ health: '/healthz',
6
+ };
7
+ export const SimplePaths = {
8
+ live: '/live',
9
+ startup: '/startup',
10
+ ready: '/ready',
11
+ health: '/health',
12
+ };
13
+ //# sourceMappingURL=paths.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"paths.js","sourceRoot":"","sources":["../src/paths.ts"],"names":[],"mappings":"AAMA,MAAM,CAAC,MAAM,QAAQ,GAAyB;IAC5C,IAAI,EAAE,QAAQ;IACd,OAAO,EAAE,WAAW;IACpB,KAAK,EAAE,SAAS;IAChB,MAAM,EAAE,UAAU;CACnB,CAAC;AAKF,MAAM,CAAC,MAAM,WAAW,GAAyB;IAC/C,IAAI,EAAE,OAAO;IACb,OAAO,EAAE,UAAU;IACnB,KAAK,EAAE,QAAQ;IACf,MAAM,EAAE,SAAS;CAClB,CAAC"}
@@ -0,0 +1,11 @@
1
+ import type { HealthProbe, HealthStatusProbe } from './types.js';
2
+ export declare class HealthProbes {
3
+ private state;
4
+ private createProbeResponse;
5
+ readonly live: HealthProbe;
6
+ readonly startup: HealthProbe;
7
+ readonly ready: HealthProbe;
8
+ readonly health: HealthStatusProbe;
9
+ }
10
+ export declare const probes: HealthProbes;
11
+ //# sourceMappingURL=probes.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probes.d.ts","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAmC,iBAAiB,EAAE,MAAM,YAAY,CAAC;AAKlG,qBAAa,YAAY;IACvB,OAAO,CAAC,KAAK,CAIX;IAEF,OAAO,CAAC,mBAAmB;IAO3B,QAAQ,CAAC,IAAI,EAAE,WAAW,CAaxB;IAEF,QAAQ,CAAC,OAAO,EAAE,WAAW,CAa3B;IAEF,QAAQ,CAAC,KAAK,EAAE,WAAW,CAazB;IAEF,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAiChC;CACH;AAED,eAAO,MAAM,MAAM,cAAqB,CAAC"}
package/dist/probes.js ADDED
@@ -0,0 +1,87 @@
1
+ import { checks } from './checks.js';
2
+ export class HealthProbes {
3
+ state = {
4
+ live: false,
5
+ startup: false,
6
+ ready: false,
7
+ };
8
+ createProbeResponse(result) {
9
+ return new Response(result.passing ? 'OK' : 'Service Unavailable', {
10
+ status: result.passing ? 200 : 503,
11
+ headers: { 'Content-Type': 'text/plain' },
12
+ });
13
+ }
14
+ live = {
15
+ enable: () => {
16
+ this.state.live = true;
17
+ },
18
+ disable: () => {
19
+ this.state.live = false;
20
+ },
21
+ get: async () => {
22
+ return { passing: this.state.live };
23
+ },
24
+ response: async () => {
25
+ return this.createProbeResponse(await this.live.get());
26
+ },
27
+ };
28
+ startup = {
29
+ enable: () => {
30
+ this.state.startup = true;
31
+ },
32
+ disable: () => {
33
+ this.state.startup = false;
34
+ },
35
+ get: async () => {
36
+ return { passing: this.state.startup };
37
+ },
38
+ response: async () => {
39
+ return this.createProbeResponse(await this.startup.get());
40
+ },
41
+ };
42
+ ready = {
43
+ enable: () => {
44
+ this.state.ready = true;
45
+ },
46
+ disable: () => {
47
+ this.state.ready = false;
48
+ },
49
+ get: async () => {
50
+ return { passing: this.state.ready ? await checks.runRequired() : false };
51
+ },
52
+ response: async () => {
53
+ return this.createProbeResponse(await this.ready.get());
54
+ },
55
+ };
56
+ health = {
57
+ get: async () => {
58
+ const checkResults = await checks.runAll();
59
+ const registered = checks.getChecks();
60
+ const hasUnhealthy = Object.values(checkResults).some((c) => c.status === 'unhealthy');
61
+ const hasRequiredUnhealthy = registered
62
+ .filter((check) => !check.optional)
63
+ .some((check) => checkResults[check.name]?.status !== 'healthy');
64
+ let status = 'healthy';
65
+ if (hasRequiredUnhealthy) {
66
+ status = 'unhealthy';
67
+ }
68
+ else if (hasUnhealthy) {
69
+ status = 'degraded';
70
+ }
71
+ return {
72
+ status,
73
+ probes: { live: this.state.live, startup: this.state.startup, ready: this.state.ready },
74
+ checks: checkResults,
75
+ };
76
+ },
77
+ response: async () => {
78
+ const result = await this.health.get();
79
+ return new Response(JSON.stringify(result, null, 2), {
80
+ status: 200,
81
+ headers: { 'Content-Type': 'application/json' },
82
+ });
83
+ },
84
+ };
85
+ }
86
+ export const probes = new HealthProbes();
87
+ //# sourceMappingURL=probes.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"probes.js","sourceRoot":"","sources":["../src/probes.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ import type { HealthServerOptions } from './types.js';
2
+ export declare class HealthServer {
3
+ private instance;
4
+ start(options?: HealthServerOptions): void;
5
+ stop(): Promise<void>;
6
+ private handleRequest;
7
+ }
8
+ export declare const server: HealthServer;
9
+ //# sourceMappingURL=server.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAIA,OAAO,KAAK,EAAE,mBAAmB,EAAc,MAAM,YAAY,CAAC;AAKlE,qBAAa,YAAY;IACvB,OAAO,CAAC,QAAQ,CAAuB;IAKvC,KAAK,CAAC,OAAO,GAAE,mBAAwB,GAAG,IAAI;IAqC9C,IAAI,IAAI,OAAO,CAAC,IAAI,CAAC;YAmBP,aAAa;CAc5B;AAED,eAAO,MAAM,MAAM,cAAqB,CAAC"}
package/dist/server.js ADDED
@@ -0,0 +1,66 @@
1
+ import { createServer } from 'node:http';
2
+ import { K8sPaths } from './paths.js';
3
+ import { probes } from './probes.js';
4
+ export class HealthServer {
5
+ instance = null;
6
+ start(options = {}) {
7
+ if (this.instance) {
8
+ return;
9
+ }
10
+ const host = options.host ?? process.env['HEALTH_HOST'] ?? '127.0.0.1';
11
+ const port = options.port ?? (process.env['HEALTH_PORT'] ? Number(process.env['HEALTH_PORT']) : 9090);
12
+ const paths = { ...K8sPaths, ...options.paths };
13
+ const instance = createServer(async (req, res) => {
14
+ try {
15
+ const url = new URL(req.url ?? '/', `http://${req.headers.host ?? 'localhost'}`);
16
+ const response = await this.handleRequest(url.pathname, paths);
17
+ res.statusCode = response.status;
18
+ for (const [key, value] of response.headers.entries()) {
19
+ res.setHeader(key, value);
20
+ }
21
+ const body = await response.text();
22
+ res.end(body);
23
+ }
24
+ catch {
25
+ res.statusCode = 500;
26
+ res.setHeader('Content-Type', 'text/plain');
27
+ res.end('Internal Server Error');
28
+ }
29
+ });
30
+ instance.listen(port, host);
31
+ this.instance = instance;
32
+ }
33
+ stop() {
34
+ return new Promise((resolve, reject) => {
35
+ if (!this.instance) {
36
+ resolve();
37
+ return;
38
+ }
39
+ this.instance.close((err) => {
40
+ if (err) {
41
+ reject(err);
42
+ }
43
+ else {
44
+ this.instance = null;
45
+ resolve();
46
+ }
47
+ });
48
+ });
49
+ }
50
+ async handleRequest(pathname, paths) {
51
+ switch (pathname) {
52
+ case paths.live:
53
+ return probes.live.response();
54
+ case paths.startup:
55
+ return probes.startup.response();
56
+ case paths.ready:
57
+ return probes.ready.response();
58
+ case paths.health:
59
+ return probes.health.response();
60
+ default:
61
+ return new Response('Not Found', { status: 404 });
62
+ }
63
+ }
64
+ }
65
+ export const server = new HealthServer();
66
+ //# sourceMappingURL=server.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"server.js","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,45 @@
1
+ export interface ProbePaths {
2
+ live?: string | undefined;
3
+ startup?: string | undefined;
4
+ ready?: string | undefined;
5
+ health?: string | undefined;
6
+ }
7
+ export interface HealthServerOptions {
8
+ host?: string | undefined;
9
+ port?: number | undefined;
10
+ paths?: ProbePaths | undefined;
11
+ }
12
+ export interface HealthCheck {
13
+ name: string;
14
+ check: () => Promise<HealthCheckResult | void> | HealthCheckResult | void;
15
+ optional?: boolean | undefined;
16
+ timeout?: number | undefined;
17
+ }
18
+ export interface HealthCheckResult {
19
+ status: 'healthy' | 'unhealthy';
20
+ latency?: number | undefined;
21
+ error?: string | undefined;
22
+ }
23
+ export interface HealthProbeResult {
24
+ passing: boolean;
25
+ }
26
+ export interface HealthResult {
27
+ status: 'healthy' | 'degraded' | 'unhealthy';
28
+ probes: {
29
+ live: boolean;
30
+ startup: boolean;
31
+ ready: boolean;
32
+ };
33
+ checks: Record<string, HealthCheckResult>;
34
+ }
35
+ export interface HealthProbe {
36
+ enable(): void;
37
+ disable(): void;
38
+ get(): Promise<HealthProbeResult>;
39
+ response(): Promise<Response>;
40
+ }
41
+ export interface HealthStatusProbe {
42
+ get(): Promise<HealthResult>;
43
+ response(): Promise<Response>;
44
+ }
45
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAGA,MAAM,WAAW,UAAU;IACzB,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC1B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC7B;AAKD,MAAM,WAAW,mBAAmB;IAMlC,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAO1B,IAAI,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAM1B,KAAK,CAAC,EAAE,UAAU,GAAG,SAAS,CAAC;CAChC;AAKD,MAAM,WAAW,WAAW;IAI1B,IAAI,EAAE,MAAM,CAAC;IAOb,KAAK,EAAE,MAAM,OAAO,CAAC,iBAAiB,GAAG,IAAI,CAAC,GAAG,iBAAiB,GAAG,IAAI,CAAC;IAO1E,QAAQ,CAAC,EAAE,OAAO,GAAG,SAAS,CAAC;IAM/B,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC9B;AAKD,MAAM,WAAW,iBAAiB;IAChC,MAAM,EAAE,SAAS,GAAG,WAAW,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;IAC7B,KAAK,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;CAC5B;AAKD,MAAM,WAAW,iBAAiB;IAChC,OAAO,EAAE,OAAO,CAAC;CAClB;AAKD,MAAM,WAAW,YAAY;IAC3B,MAAM,EAAE,SAAS,GAAG,UAAU,GAAG,WAAW,CAAC;IAC7C,MAAM,EAAE;QACN,IAAI,EAAE,OAAO,CAAC;QACd,OAAO,EAAE,OAAO,CAAC;QACjB,KAAK,EAAE,OAAO,CAAC;KAChB,CAAC;IACF,MAAM,EAAE,MAAM,CAAC,MAAM,EAAE,iBAAiB,CAAC,CAAC;CAC3C;AAKD,MAAM,WAAW,WAAW;IAI1B,MAAM,IAAI,IAAI,CAAC;IAKf,OAAO,IAAI,IAAI,CAAC;IAKhB,GAAG,IAAI,OAAO,CAAC,iBAAiB,CAAC,CAAC;IAKlC,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC/B;AAKD,MAAM,WAAW,iBAAiB;IAIhC,GAAG,IAAI,OAAO,CAAC,YAAY,CAAC,CAAC;IAK7B,QAAQ,IAAI,OAAO,CAAC,QAAQ,CAAC,CAAC;CAC/B"}
package/dist/types.js ADDED
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
package/package.json ADDED
@@ -0,0 +1,73 @@
1
+ {
2
+ "name": "@entwico/health-probes",
3
+ "version": "1.1.0",
4
+ "description": "Kubernetes-style health check probes for Node.js — framework-agnostic /livez, /readyz, /startupz, and /healthz endpoints",
5
+ "license": "MIT",
6
+ "author": "admin@entwico.com",
7
+ "type": "module",
8
+ "main": "./dist/index.js",
9
+ "module": "./dist/index.js",
10
+ "types": "./dist/index.d.ts",
11
+ "exports": {
12
+ ".": {
13
+ "types": "./dist/index.d.ts",
14
+ "import": "./dist/index.js"
15
+ }
16
+ },
17
+ "files": [
18
+ "dist",
19
+ "README.md",
20
+ "LICENSE"
21
+ ],
22
+ "keywords": [
23
+ "health",
24
+ "healthcheck",
25
+ "probes",
26
+ "kubernetes",
27
+ "k8s",
28
+ "livez",
29
+ "readyz",
30
+ "startupz",
31
+ "healthz",
32
+ "typescript"
33
+ ],
34
+ "repository": {
35
+ "type": "git",
36
+ "url": "https://github.com/entwico/health-probes"
37
+ },
38
+ "scripts": {
39
+ "build": "tsc --project tsconfig.build.json",
40
+ "clean": "rm -rf dist",
41
+ "prebuild": "npm run clean",
42
+ "prepublishOnly": "npm run build && npm run test && npm run lint",
43
+ "validate": "run-s lint typecheck test",
44
+ "lint": "eslint . --report-unused-disable-directives --max-warnings 0",
45
+ "typecheck": "tsc",
46
+ "test": "npx tsx --test --experimental-test-coverage src/index.test.ts",
47
+ "prepare": "husky",
48
+ "semantic-release": "semantic-release"
49
+ },
50
+ "publishConfig": {
51
+ "access": "public",
52
+ "provenance": true
53
+ },
54
+ "devDependencies": {
55
+ "@commitlint/cli": "^20.4.1",
56
+ "@commitlint/config-conventional": "^20.4.1",
57
+ "@semantic-release/changelog": "^6.0.3",
58
+ "@semantic-release/git": "^10.0.1",
59
+ "@types/node": "^25.2.0",
60
+ "@typescript-eslint/eslint-plugin": "^8.54.0",
61
+ "eslint": "^9.39.2",
62
+ "eslint-config-prettier": "^10.1.8",
63
+ "eslint-import-resolver-typescript": "^4.4.4",
64
+ "eslint-plugin-import": "^2.32.0",
65
+ "eslint-plugin-prettier": "^5.5.5",
66
+ "husky": "^9.1.7",
67
+ "npm-run-all": "^4.1.5",
68
+ "semantic-release": "^25.0.3",
69
+ "tsx": "^4.21.0",
70
+ "typescript": "^5.9.3",
71
+ "typescript-eslint": "^8.54.0"
72
+ }
73
+ }