@firebreak/vitals 1.0.0 → 1.0.1

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.
Files changed (2) hide show
  1. package/README.md +209 -0
  2. package/package.json +1 -1
package/README.md ADDED
@@ -0,0 +1,209 @@
1
+ # Vitals (Node.js)
2
+
3
+ Structured deep healthcheck endpoints for Node.js services. Register health checks, run them concurrently with timeouts, and expose them via Express.
4
+
5
+ ## Install
6
+
7
+ ```bash
8
+ npm install vitals
9
+ ```
10
+
11
+ Peer dependencies are optional — install only what you need:
12
+
13
+ ```bash
14
+ npm install pg # for PostgreSQL checks
15
+ npm install ioredis # for Redis checks
16
+ npm install express # for Express integration
17
+ ```
18
+
19
+ ## Quick Start
20
+
21
+ ```typescript
22
+ import { HealthcheckRegistry, Status } from 'vitals';
23
+ import { createHealthcheckMiddleware } from 'vitals/express';
24
+ import { pgPoolCheck } from 'vitals/checks/postgres';
25
+ import { ioredisClientCheck } from 'vitals/checks/redis';
26
+ import express from 'express';
27
+
28
+ const registry = new HealthcheckRegistry({ defaultTimeout: 5000 });
29
+
30
+ // Add checks using an existing connection pool / client
31
+ registry.add('postgres', pgPoolCheck(pool));
32
+ registry.add('redis', ioredisClientCheck(redisClient));
33
+
34
+ // Or add a custom check
35
+ registry.add('api', async () => {
36
+ const start = Date.now();
37
+ const res = await fetch('https://api.example.com/ping');
38
+ return {
39
+ status: res.ok ? Status.HEALTHY : Status.OUTAGE,
40
+ latencyMs: Date.now() - start,
41
+ message: res.ok ? '' : `HTTP ${res.status}`,
42
+ };
43
+ });
44
+
45
+ // Mount as Express middleware
46
+ const app = express();
47
+ app.get('/healthcheck/deep', createHealthcheckMiddleware({
48
+ registry,
49
+ token: process.env.HEALTHCHECK_TOKEN,
50
+ }));
51
+ ```
52
+
53
+ ## API
54
+
55
+ ### `HealthcheckRegistry`
56
+
57
+ ```typescript
58
+ const registry = new HealthcheckRegistry({ defaultTimeout: 5000 });
59
+ ```
60
+
61
+ **`registry.add(name, checkFn, options?)`**
62
+
63
+ Register a named async check function. Options: `{ timeout?: number }`.
64
+
65
+ ```typescript
66
+ registry.add('service', async () => ({
67
+ status: Status.HEALTHY,
68
+ latencyMs: 0,
69
+ message: '',
70
+ }), { timeout: 3000 });
71
+ ```
72
+
73
+ **`registry.check(name, checkFn?, options?)`**
74
+
75
+ Decorator-style registration. Can be used as a method decorator or called directly.
76
+
77
+ **`registry.run()`**
78
+
79
+ Execute all registered checks concurrently. Returns a `HealthcheckResponse` with the worst overall status.
80
+
81
+ ```typescript
82
+ const response = await registry.run();
83
+ // { status: 2, timestamp: '...', checks: { service: { status: 2, latencyMs: 12, message: '' } } }
84
+
85
+ const json = toJson(response);
86
+ // { status: 'healthy', timestamp: '...', checks: { ... } }
87
+ ```
88
+
89
+ ### Status
90
+
91
+ ```typescript
92
+ import { Status, statusToLabel, statusFromString, httpStatusCode } from 'vitals';
93
+
94
+ Status.HEALTHY // 2
95
+ Status.DEGRADED // 1
96
+ Status.OUTAGE // 0
97
+
98
+ statusToLabel(Status.HEALTHY) // 'healthy'
99
+ statusFromString('degraded') // Status.DEGRADED
100
+ httpStatusCode(Status.HEALTHY) // 200
101
+ httpStatusCode(Status.OUTAGE) // 503
102
+ ```
103
+
104
+ ### Built-in Checks
105
+
106
+ #### PostgreSQL
107
+
108
+ ```typescript
109
+ import { pgClientCheck, pgPoolCheck } from 'vitals/checks/postgres';
110
+
111
+ // Fresh connection each time (good for validating connectivity)
112
+ registry.add('pg', pgClientCheck('postgresql://localhost:5432/mydb'));
113
+
114
+ // Existing pg.Pool (good for production — reuses connections)
115
+ registry.add('pg', pgPoolCheck(pool));
116
+ ```
117
+
118
+ #### Redis
119
+
120
+ ```typescript
121
+ import { ioredisCheck, ioredisClientCheck } from 'vitals/checks/redis';
122
+
123
+ // Fresh connection each time
124
+ registry.add('redis', ioredisCheck('redis://localhost:6379'));
125
+
126
+ // Existing ioredis client
127
+ registry.add('redis', ioredisClientCheck(client));
128
+ ```
129
+
130
+ ### Sync Checks
131
+
132
+ Wrap synchronous functions to use as health checks:
133
+
134
+ ```typescript
135
+ import { syncCheck, Status } from 'vitals';
136
+
137
+ registry.add('disk', syncCheck(() => {
138
+ const free = checkDiskSpace('/');
139
+ return {
140
+ status: free > 1_000_000_000 ? Status.HEALTHY : Status.DEGRADED,
141
+ latencyMs: 0,
142
+ message: `${free} bytes free`,
143
+ };
144
+ }));
145
+ ```
146
+
147
+ ### Express Integration
148
+
149
+ ```typescript
150
+ import { createHealthcheckMiddleware } from 'vitals/express';
151
+
152
+ app.get('/healthcheck/deep', createHealthcheckMiddleware({
153
+ registry,
154
+ token: 'my-secret-token', // optional — omit to disable auth
155
+ queryParamName: 'token', // default: 'token'
156
+ }));
157
+ ```
158
+
159
+ When a token is configured, requests must provide it via:
160
+ - Query parameter: `?token=my-secret-token`
161
+ - Bearer header: `Authorization: Bearer my-secret-token`
162
+
163
+ ### Authentication
164
+
165
+ ```typescript
166
+ import { verifyToken, extractToken } from 'vitals';
167
+
168
+ // Timing-safe token comparison
169
+ verifyToken('provided-token', 'expected-token'); // boolean
170
+
171
+ // Extract token from request
172
+ const token = extractToken({
173
+ queryParams: { token: 'abc' },
174
+ authorizationHeader: 'Bearer abc',
175
+ queryParamName: 'token',
176
+ });
177
+ ```
178
+
179
+ ## Response Format
180
+
181
+ ```json
182
+ {
183
+ "status": "healthy",
184
+ "timestamp": "2025-02-26T12:00:00.000Z",
185
+ "checks": {
186
+ "postgres": {
187
+ "status": "healthy",
188
+ "latencyMs": 4.2,
189
+ "message": ""
190
+ },
191
+ "redis": {
192
+ "status": "healthy",
193
+ "latencyMs": 1.1,
194
+ "message": ""
195
+ }
196
+ }
197
+ }
198
+ ```
199
+
200
+ | Overall Status | HTTP Code |
201
+ |---------------|-----------|
202
+ | `healthy` | `200` |
203
+ | `degraded` | `503` |
204
+ | `outage` | `503` |
205
+ | Auth failure | `403` |
206
+
207
+ ## Requirements
208
+
209
+ - Node.js >= 20.0.0
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@firebreak/vitals",
3
- "version": "1.0.0",
3
+ "version": "1.0.1",
4
4
  "description": "Deep healthcheck endpoints following the HEALTHCHECK_SPEC format",
5
5
  "type": "module",
6
6
  "exports": {