@sebspark/health-check 1.0.7 → 1.0.8
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/dist/index.d.mts +382 -0
- package/dist/index.d.mts.map +1 -0
- package/dist/index.mjs +550 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +10 -4
- package/dist/index.d.ts +0 -378
- package/dist/index.js +0 -534
- package/dist/index.js.map +0 -1
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,382 @@
|
|
|
1
|
+
import { Router } from "express";
|
|
2
|
+
|
|
3
|
+
//#region src/types.d.ts
|
|
4
|
+
type DependencyStatusValue = 'ok' | 'degraded' | 'error';
|
|
5
|
+
type StatusValue = DependencyStatusValue | 'unknown' | 'draining';
|
|
6
|
+
type Impact = 'critical' | 'non_critical';
|
|
7
|
+
type Mode = 'inline' | 'polled' | 'async';
|
|
8
|
+
type Status = {
|
|
9
|
+
status: StatusValue;
|
|
10
|
+
};
|
|
11
|
+
type System = {
|
|
12
|
+
hostname: string;
|
|
13
|
+
platform: NodeJS.Platform;
|
|
14
|
+
release: string;
|
|
15
|
+
arch: string;
|
|
16
|
+
uptime: number;
|
|
17
|
+
loadavg: [number, number, number];
|
|
18
|
+
totalmem: number;
|
|
19
|
+
freemem: number;
|
|
20
|
+
memUsedRatio: number;
|
|
21
|
+
cpus: {
|
|
22
|
+
count: number;
|
|
23
|
+
model?: string;
|
|
24
|
+
speedMHz?: number;
|
|
25
|
+
};
|
|
26
|
+
};
|
|
27
|
+
type Process = {
|
|
28
|
+
pid: number;
|
|
29
|
+
node: string;
|
|
30
|
+
uptime: number;
|
|
31
|
+
memory: NodeJS.MemoryUsage;
|
|
32
|
+
};
|
|
33
|
+
type Liveness = Status & {
|
|
34
|
+
timestamp: string;
|
|
35
|
+
system: System;
|
|
36
|
+
process: Process;
|
|
37
|
+
};
|
|
38
|
+
type Freshness = {
|
|
39
|
+
lastChecked: string;
|
|
40
|
+
lastSuccess: string | null;
|
|
41
|
+
};
|
|
42
|
+
type Observed = {
|
|
43
|
+
latencyMs: number | null;
|
|
44
|
+
[k: string]: unknown;
|
|
45
|
+
};
|
|
46
|
+
type CheckError = {
|
|
47
|
+
code: string;
|
|
48
|
+
message: string;
|
|
49
|
+
};
|
|
50
|
+
type DependencyCheck = Status & {
|
|
51
|
+
impact: Impact;
|
|
52
|
+
mode: Mode;
|
|
53
|
+
freshness: Freshness;
|
|
54
|
+
observed?: Observed;
|
|
55
|
+
details?: Record<string, unknown>;
|
|
56
|
+
error?: CheckError | null;
|
|
57
|
+
since?: string | null;
|
|
58
|
+
};
|
|
59
|
+
type ReadinessSummary = {
|
|
60
|
+
critical: {
|
|
61
|
+
ok: number;
|
|
62
|
+
failing: number;
|
|
63
|
+
};
|
|
64
|
+
nonCritical: {
|
|
65
|
+
ok: number;
|
|
66
|
+
degraded: number;
|
|
67
|
+
failing: number;
|
|
68
|
+
};
|
|
69
|
+
degradedReasons: string[];
|
|
70
|
+
};
|
|
71
|
+
type ReadinessPayload = Status & {
|
|
72
|
+
timestamp: string;
|
|
73
|
+
service?: {
|
|
74
|
+
name?: string;
|
|
75
|
+
version?: string;
|
|
76
|
+
instanceId?: string;
|
|
77
|
+
};
|
|
78
|
+
summary: ReadinessSummary;
|
|
79
|
+
checks: Record<string, DependencyCheck>;
|
|
80
|
+
};
|
|
81
|
+
type HealthSummary = Status & Pick<ReadinessPayload, 'summary' | 'checks'> & Pick<Liveness, 'system' | 'process'> & {
|
|
82
|
+
timestamp: string;
|
|
83
|
+
};
|
|
84
|
+
declare class TimeoutError extends Error {
|
|
85
|
+
constructor();
|
|
86
|
+
}
|
|
87
|
+
declare class UnknownError extends Error {
|
|
88
|
+
constructor();
|
|
89
|
+
}
|
|
90
|
+
//#endregion
|
|
91
|
+
//#region src/dependency-monitor.d.ts
|
|
92
|
+
/**
|
|
93
|
+
* Base configuration shared by all dependency monitor modes.
|
|
94
|
+
*/
|
|
95
|
+
type BaseConfig = {
|
|
96
|
+
/**
|
|
97
|
+
* Importance of the dependency:
|
|
98
|
+
* - `'critical'` → service cannot run without it
|
|
99
|
+
* - `'non_critical'` → service is degraded but still functional if it fails
|
|
100
|
+
*/
|
|
101
|
+
impact: Impact;
|
|
102
|
+
/**
|
|
103
|
+
* Polling interval in milliseconds.
|
|
104
|
+
* - Required for polled and async modes
|
|
105
|
+
* - Must not be set for inline mode
|
|
106
|
+
*/
|
|
107
|
+
pollRate?: number;
|
|
108
|
+
/**
|
|
109
|
+
* Polling interval in milliseconds for failed calls.
|
|
110
|
+
* - Defaults to pollRate for polled and async modes
|
|
111
|
+
* - Must not be set for inline mode
|
|
112
|
+
*/
|
|
113
|
+
retryRate?: number;
|
|
114
|
+
/**
|
|
115
|
+
* Maximum response time in milliseconds considered healthy.
|
|
116
|
+
* - A call resolving within this time window **and** returning `"ok"` → status `"ok"`
|
|
117
|
+
* - A call resolving after this but **before** `timeoutLimitMs` → status `"degraded"`
|
|
118
|
+
*/
|
|
119
|
+
healthyLimitMs: number;
|
|
120
|
+
/**
|
|
121
|
+
* Absolute upper bound in milliseconds; beyond this a call is considered `"error"`.
|
|
122
|
+
* - Inline: the awaited call is raced with a timeout and rejected past this limit
|
|
123
|
+
* - Polled/Async: escalate `unknown` → `degraded` at `healthyLimitMs`, then `"error"` at `timeoutLimitMs`
|
|
124
|
+
* - Any late `"ok"` result after this limit is ignored
|
|
125
|
+
*/
|
|
126
|
+
timeoutLimitMs: number;
|
|
127
|
+
};
|
|
128
|
+
/**
|
|
129
|
+
* Inline mode configuration (no polling).
|
|
130
|
+
* `syncCall` runs **only** when {@link DependencyMonitor.check} is invoked.
|
|
131
|
+
*/
|
|
132
|
+
type SyncInlineConfig = BaseConfig & {
|
|
133
|
+
/** Performs the check immediately when {@link DependencyMonitor.check} is called. */
|
|
134
|
+
syncCall: () => Promise<DependencyStatusValue | Error>;
|
|
135
|
+
asyncCall?: never;
|
|
136
|
+
pollRate?: undefined;
|
|
137
|
+
retryRate?: undefined;
|
|
138
|
+
};
|
|
139
|
+
/**
|
|
140
|
+
* Polled mode configuration.
|
|
141
|
+
* `syncCall` runs on an interval (`pollRate`) and results are cached.
|
|
142
|
+
*/
|
|
143
|
+
type SyncPolledConfig = BaseConfig & {
|
|
144
|
+
/** Performs the check at each poll interval. */
|
|
145
|
+
syncCall: () => Promise<DependencyStatusValue | Error>;
|
|
146
|
+
/** Polling interval in milliseconds. */
|
|
147
|
+
pollRate: number;
|
|
148
|
+
asyncCall?: never;
|
|
149
|
+
};
|
|
150
|
+
/**
|
|
151
|
+
* Async mode configuration.
|
|
152
|
+
* `asyncCall` starts a check and must report via the provided callback.
|
|
153
|
+
*/
|
|
154
|
+
type AsyncConfig = BaseConfig & {
|
|
155
|
+
/**
|
|
156
|
+
* Starts an asynchronous check. Must call `reportResponse` once a result is available.
|
|
157
|
+
* The callback may be invoked with a `DependencyStatusValue` or an `Error`.
|
|
158
|
+
*/
|
|
159
|
+
asyncCall: (reportResponse: (status: DependencyStatusValue | Error) => void | Promise<void>) => void | Promise<void>;
|
|
160
|
+
/** Polling interval in milliseconds. */
|
|
161
|
+
pollRate: number;
|
|
162
|
+
syncCall?: never;
|
|
163
|
+
};
|
|
164
|
+
/**
|
|
165
|
+
* Discriminated configuration for a dependency monitor.
|
|
166
|
+
* - {@link SyncInlineConfig} → inline checks on demand
|
|
167
|
+
* - {@link SyncPolledConfig} → synchronous checks on a fixed interval
|
|
168
|
+
* - {@link AsyncConfig} → asynchronous checks that report back via callback
|
|
169
|
+
*/
|
|
170
|
+
type DependencyMonitorConfig = SyncInlineConfig | SyncPolledConfig | AsyncConfig;
|
|
171
|
+
/**
|
|
172
|
+
* Tracks the health of a single dependency in one of three modes:
|
|
173
|
+
*
|
|
174
|
+
* - **inline**: `syncCall` executed only when {@link check} is called
|
|
175
|
+
* - **polled**: `syncCall` executed on `pollRate`; latest result cached
|
|
176
|
+
* - **async**: `asyncCall` executed on `pollRate`, result returned via callback
|
|
177
|
+
*
|
|
178
|
+
* The monitor:
|
|
179
|
+
* - classifies results using `healthyLimitMs` and `timeoutLimitMs`
|
|
180
|
+
* - records freshness (`lastChecked`, `lastSuccess`)
|
|
181
|
+
* - records observed latency (ms) when applicable
|
|
182
|
+
*
|
|
183
|
+
* Status interpretation:
|
|
184
|
+
* - `"ok"` only if returned `"ok"` **and** latency ≤ `healthyLimitMs`
|
|
185
|
+
* - `"degraded"` if returned `"degraded"` **or** latency > `healthyLimitMs` but ≤ `timeoutLimitMs`
|
|
186
|
+
* - `"error"` if returned `"error"`, an `Error`, or exceeded `timeoutLimitMs`
|
|
187
|
+
* - `"unknown"` is the initial state before first successful/failed result (polled/async)
|
|
188
|
+
*/
|
|
189
|
+
declare class DependencyMonitor {
|
|
190
|
+
/** Immutable configuration for this monitor. */
|
|
191
|
+
private readonly config;
|
|
192
|
+
/** Operational mode determined from the configuration. */
|
|
193
|
+
private readonly mode;
|
|
194
|
+
/** Last computed status (starts as `"unknown"` until first result). */
|
|
195
|
+
private status;
|
|
196
|
+
/** Optional error details from the last failure. */
|
|
197
|
+
private error?;
|
|
198
|
+
/** Last observed metrics (e.g., latency). */
|
|
199
|
+
private observed?;
|
|
200
|
+
/** Freshness timestamps for last check/success. */
|
|
201
|
+
private freshness?;
|
|
202
|
+
/** Indicates whether this monitor has been disposed. */
|
|
203
|
+
private isDisposed;
|
|
204
|
+
/** Internal timer handle for polling/retry. */
|
|
205
|
+
private timeout?;
|
|
206
|
+
/**
|
|
207
|
+
* Create a new {@link DependencyMonitor}.
|
|
208
|
+
* @param config Monitor configuration (inline, polled, or async).
|
|
209
|
+
*/
|
|
210
|
+
constructor(config: DependencyMonitorConfig);
|
|
211
|
+
/** Impact of this dependency (critical/non_critical). */
|
|
212
|
+
get impact(): Impact;
|
|
213
|
+
/**
|
|
214
|
+
* Run one check cycle depending on the configured mode.
|
|
215
|
+
* - Inline: no-op here (runs in {@link check})
|
|
216
|
+
* - Polled/Async: invoked automatically and re-scheduled as needed
|
|
217
|
+
*/
|
|
218
|
+
private doCheck;
|
|
219
|
+
/**
|
|
220
|
+
* Execute a synchronous (inline/polled) check and update internal state.
|
|
221
|
+
* Classification:
|
|
222
|
+
* - OK if `"ok"` and latency ≤ `healthyLimitMs`
|
|
223
|
+
* - Degraded if `"degraded"` or latency between `(healthyLimitMs, timeoutLimitMs]`
|
|
224
|
+
* - Error if `"error"`, `Error`, or timeout exceeded
|
|
225
|
+
*/
|
|
226
|
+
private doSyncCheck;
|
|
227
|
+
/**
|
|
228
|
+
* Execute an asynchronous check (async mode).
|
|
229
|
+
* - Initializes timers to escalate `unknown` → `degraded` → `error`
|
|
230
|
+
* if no callback result arrives within the thresholds.
|
|
231
|
+
* - On callback, clears timers and classifies the result with latency.
|
|
232
|
+
*/
|
|
233
|
+
private doAsyncCheck;
|
|
234
|
+
/**
|
|
235
|
+
* Normalize a successful dependency response into status + metadata.
|
|
236
|
+
* @param response Returned status value or Error from the dependency
|
|
237
|
+
* @param duration Measured latency in milliseconds
|
|
238
|
+
*/
|
|
239
|
+
private handleDependencyResponse;
|
|
240
|
+
/**
|
|
241
|
+
* Normalize a failed dependency result into `"error"` and update metadata.
|
|
242
|
+
* @param error Error thrown/returned or synthesized (e.g., timeout)
|
|
243
|
+
*/
|
|
244
|
+
private handleDependencyError;
|
|
245
|
+
/**
|
|
246
|
+
* Get a snapshot of the dependency’s current health.
|
|
247
|
+
* - Inline mode: executes the `syncCall` (single-flight guarded)
|
|
248
|
+
* - Polled/Async: returns the cached result
|
|
249
|
+
* @throws if the monitor has been disposed
|
|
250
|
+
*/
|
|
251
|
+
check(): Promise<DependencyCheck>;
|
|
252
|
+
/** Symbol-based disposer for use with `using`. */
|
|
253
|
+
[Symbol.dispose](): void;
|
|
254
|
+
/**
|
|
255
|
+
* Dispose the monitor:
|
|
256
|
+
* - Clears any scheduled timers
|
|
257
|
+
* - Prevents further checks from running
|
|
258
|
+
*/
|
|
259
|
+
dispose(): void;
|
|
260
|
+
}
|
|
261
|
+
//#endregion
|
|
262
|
+
//#region src/health-monitor.d.ts
|
|
263
|
+
interface HealthMonitorConfig {
|
|
264
|
+
throttle: number;
|
|
265
|
+
}
|
|
266
|
+
/**
|
|
267
|
+
* HealthMonitor wires up standard health check endpoints for an Express app.
|
|
268
|
+
*
|
|
269
|
+
* It provides three endpoints under `/health`:
|
|
270
|
+
* - /ping → lightweight always-OK response (`{ status: "ok" }`)
|
|
271
|
+
* - /live → liveness probe (`{ status, uptime, timestamp }`)
|
|
272
|
+
* - /ready → readiness probe with dependency checks (`{ status, checks }`)
|
|
273
|
+
*
|
|
274
|
+
* Dependencies can be added via {@link addDependency} with a {@link DependencyMonitorConfig}.
|
|
275
|
+
* Each dependency is wrapped in a {@link DependencyMonitor} and tracked for readiness.
|
|
276
|
+
*
|
|
277
|
+
* ### Example
|
|
278
|
+
*
|
|
279
|
+
* ```ts
|
|
280
|
+
* import express from 'express'
|
|
281
|
+
* import { HealthMonitor } from './health-monitor'
|
|
282
|
+
*
|
|
283
|
+
* const app = express()
|
|
284
|
+
* const monitor = new HealthMonitor()
|
|
285
|
+
*
|
|
286
|
+
* monitor.addDependency('db', {
|
|
287
|
+
* impact: 'critical',
|
|
288
|
+
* syncCall: async () => {
|
|
289
|
+
* await db.ping()
|
|
290
|
+
* return 'ok'
|
|
291
|
+
* }
|
|
292
|
+
* })
|
|
293
|
+
*
|
|
294
|
+
* app.use(monitor.router)
|
|
295
|
+
* app.listen(3000)
|
|
296
|
+
* ```
|
|
297
|
+
*/
|
|
298
|
+
declare class HealthMonitor {
|
|
299
|
+
private readonly _router;
|
|
300
|
+
private readonly dependencies;
|
|
301
|
+
/**
|
|
302
|
+
* Create a new HealthMonitor instance with its own router and dependency map.
|
|
303
|
+
*/
|
|
304
|
+
constructor(config?: HealthMonitorConfig);
|
|
305
|
+
/**
|
|
306
|
+
* Register a named dependency to be checked as part of readiness.
|
|
307
|
+
*
|
|
308
|
+
* @param name - Identifier for the dependency (e.g. "postgres", "redis").
|
|
309
|
+
* @param dependency - DependencyMonitor
|
|
310
|
+
* @returns this for chaining
|
|
311
|
+
*
|
|
312
|
+
* @example
|
|
313
|
+
* ```ts
|
|
314
|
+
* monitor.addDependency('redis', new DependencyMonitor({
|
|
315
|
+
* impact: 'critical',
|
|
316
|
+
* pollRate: 5000,
|
|
317
|
+
* syncCall: async () => redis.ping() ? 'ok' : 'error'
|
|
318
|
+
* }))
|
|
319
|
+
* ```
|
|
320
|
+
*/
|
|
321
|
+
addDependency(name: string, dependency: DependencyMonitor): this;
|
|
322
|
+
/**
|
|
323
|
+
* Internal: create the Express router with /health routes.
|
|
324
|
+
*/
|
|
325
|
+
private createRouter;
|
|
326
|
+
/**
|
|
327
|
+
* Static ping check — always returns `{ status: "ok" }`.
|
|
328
|
+
*/
|
|
329
|
+
ping(): Status;
|
|
330
|
+
/**
|
|
331
|
+
* Liveness probe: reports uptime and current timestamp.
|
|
332
|
+
*/
|
|
333
|
+
live(): Liveness;
|
|
334
|
+
/**
|
|
335
|
+
* Readiness probe: runs all registered dependencies in parallel
|
|
336
|
+
* and aggregates their results into an overall status.
|
|
337
|
+
*
|
|
338
|
+
* - Any **critical error** → `"error"`
|
|
339
|
+
* - Else any **critical degraded** or any non-critical degraded/error → `"degraded"`
|
|
340
|
+
* - Else → `"ok"`
|
|
341
|
+
*
|
|
342
|
+
* @returns Object with overall `status` and per-dependency `checks`
|
|
343
|
+
*
|
|
344
|
+
* @example
|
|
345
|
+
* ```json
|
|
346
|
+
* {
|
|
347
|
+
* "status": "ok",
|
|
348
|
+
* "checks": {
|
|
349
|
+
* "postgres": {
|
|
350
|
+
* "status": "ok",
|
|
351
|
+
* "impact": "critical",
|
|
352
|
+
* "mode": "inline",
|
|
353
|
+
* "freshness": {
|
|
354
|
+
* "lastChecked": "2025-08-19T12:00:00Z",
|
|
355
|
+
* "lastSuccess": "2025-08-19T12:00:00Z"
|
|
356
|
+
* },
|
|
357
|
+
* "observed": { "latencyMs": 12 }
|
|
358
|
+
* }
|
|
359
|
+
* }
|
|
360
|
+
* }
|
|
361
|
+
* ```
|
|
362
|
+
*/
|
|
363
|
+
ready(): Promise<ReadinessPayload>;
|
|
364
|
+
health(): Promise<HealthSummary>;
|
|
365
|
+
/**
|
|
366
|
+
* Accessor for the Express router that exposes /health endpoints.
|
|
367
|
+
*/
|
|
368
|
+
get router(): Router;
|
|
369
|
+
/**
|
|
370
|
+
* Symbol-based disposer for use with `using`.
|
|
371
|
+
*/
|
|
372
|
+
[Symbol.dispose](): void;
|
|
373
|
+
/**
|
|
374
|
+
* Dispose of the monitor:
|
|
375
|
+
* - marks as disposed
|
|
376
|
+
* - (future: could also stop all dependency monitors)
|
|
377
|
+
*/
|
|
378
|
+
dispose(): void;
|
|
379
|
+
}
|
|
380
|
+
//#endregion
|
|
381
|
+
export { AsyncConfig, CheckError, DependencyCheck, DependencyMonitor, DependencyMonitorConfig, DependencyStatusValue, Freshness, HealthMonitor, HealthMonitorConfig, HealthSummary, Impact, Liveness, Mode, Observed, Process, ReadinessPayload, ReadinessSummary, Status, StatusValue, SyncInlineConfig, SyncPolledConfig, System, TimeoutError, UnknownError };
|
|
382
|
+
//# sourceMappingURL=index.d.mts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/dependency-monitor.ts","../src/health-monitor.ts"],"sourcesContent":[],"mappings":"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"}
|