@lahin31/debugcontext-core 0.1.1 → 0.1.2
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/README.md +279 -6
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -1,6 +1,16 @@
|
|
|
1
1
|
# @lahin31/debugcontext-core
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
**Zero-configuration debugging context SDK for Node.js.**
|
|
4
|
+
|
|
5
|
+
When your application throws, DebugContext automatically captures everything you need to investigate the issue — request details, runtime state, system resources, Git metadata, and a full error trace — structured into one clean `Incident` object.
|
|
6
|
+
|
|
7
|
+
> DebugContext is **not** an error tracking service (like Sentry) and **not** a logging library (like Winston). It generates structured debug context so you can ship it wherever you need — a file, a webhook, Slack, your own database.
|
|
8
|
+
|
|
9
|
+
[](https://www.npmjs.com/package/@lahin31/debugcontext-core)
|
|
10
|
+
[](https://www.npmjs.com/package/@lahin31/debugcontext-core)
|
|
11
|
+
[](https://opensource.org/licenses/MIT)
|
|
12
|
+
|
|
13
|
+
---
|
|
4
14
|
|
|
5
15
|
## Install
|
|
6
16
|
|
|
@@ -8,30 +18,293 @@ Framework-agnostic core SDK for [DebugContext](../../README.md).
|
|
|
8
18
|
npm install @lahin31/debugcontext-core
|
|
9
19
|
```
|
|
10
20
|
|
|
11
|
-
|
|
21
|
+
For Express support, also install the adapter:
|
|
22
|
+
|
|
23
|
+
```bash
|
|
24
|
+
npm install @lahin31/debugcontext-core @lahin31/debugcontext-express
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
---
|
|
28
|
+
|
|
29
|
+
## Quick Start
|
|
12
30
|
|
|
13
31
|
```typescript
|
|
14
32
|
import DebugContext from '@lahin31/debugcontext-core';
|
|
15
33
|
|
|
34
|
+
// 1. Initialise once at startup
|
|
16
35
|
DebugContext.init();
|
|
17
36
|
|
|
37
|
+
// 2. Capture any error
|
|
18
38
|
try {
|
|
19
39
|
throw new Error('database connection failed');
|
|
20
40
|
} catch (err) {
|
|
21
41
|
const incident = DebugContext.capture(err);
|
|
42
|
+
|
|
43
|
+
// Print to console
|
|
22
44
|
DebugContext.toConsole(incident);
|
|
23
45
|
|
|
24
|
-
//
|
|
46
|
+
// Get as JSON string
|
|
25
47
|
console.log(DebugContext.toJSON(incident));
|
|
48
|
+
|
|
49
|
+
// Write to NDJSON file
|
|
50
|
+
DebugContext.toFile(incident, { path: 'logs/incidents.ndjson' });
|
|
51
|
+
}
|
|
52
|
+
```
|
|
53
|
+
|
|
54
|
+
---
|
|
55
|
+
|
|
56
|
+
## Express Integration
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
import express from 'express';
|
|
60
|
+
import DebugContext from '@lahin31/debugcontext-core';
|
|
61
|
+
import DebugContextExpress from '@lahin31/debugcontext-express';
|
|
62
|
+
|
|
63
|
+
DebugContext.init();
|
|
64
|
+
|
|
65
|
+
const app = express();
|
|
66
|
+
app.use(express.json());
|
|
67
|
+
|
|
68
|
+
// Optional: mount before routes to enable route param capture
|
|
69
|
+
app.use(DebugContextExpress.requestMiddleware());
|
|
70
|
+
|
|
71
|
+
// Your routes
|
|
72
|
+
app.get('/users/:id', (req, res) => {
|
|
73
|
+
throw new Error('User not found'); // captured automatically
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
// Mount error middleware LAST
|
|
77
|
+
app.use(DebugContextExpress.errorMiddleware());
|
|
78
|
+
|
|
79
|
+
app.listen(3000);
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## What an Incident looks like
|
|
85
|
+
|
|
86
|
+
```json
|
|
87
|
+
{
|
|
88
|
+
"incidentId": "3f2a1b4c-8e1d-4a2f-b3c9-1d2e3f4a5b6c",
|
|
89
|
+
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
90
|
+
"request": {
|
|
91
|
+
"method": "GET",
|
|
92
|
+
"url": "/users/42",
|
|
93
|
+
"params": { "id": "42" },
|
|
94
|
+
"query": {},
|
|
95
|
+
"body": null,
|
|
96
|
+
"headers": {
|
|
97
|
+
"authorization": "[REDACTED]",
|
|
98
|
+
"content-type": "application/json"
|
|
99
|
+
},
|
|
100
|
+
"ip": "127.0.0.1",
|
|
101
|
+
"userAgent": "Mozilla/5.0 ..."
|
|
102
|
+
},
|
|
103
|
+
"runtime": {
|
|
104
|
+
"timestamp": "2024-01-15T10:30:00.000Z",
|
|
105
|
+
"environment": "production",
|
|
106
|
+
"nodeVersion": "v20.11.0",
|
|
107
|
+
"pid": 1234,
|
|
108
|
+
"hostname": "prod-server-1",
|
|
109
|
+
"uptimeSeconds": 3600.5,
|
|
110
|
+
"workingDirectory": "/app"
|
|
111
|
+
},
|
|
112
|
+
"system": {
|
|
113
|
+
"memory": {
|
|
114
|
+
"rss": 52428800,
|
|
115
|
+
"heapTotal": 30408704,
|
|
116
|
+
"heapUsed": 18200000,
|
|
117
|
+
"external": 1234,
|
|
118
|
+
"arrayBuffers": 456
|
|
119
|
+
},
|
|
120
|
+
"heapUsagePercent": 59.8,
|
|
121
|
+
"cpuLoadAvg": [0.5, 0.3, 0.2],
|
|
122
|
+
"platform": "linux",
|
|
123
|
+
"arch": "x64",
|
|
124
|
+
"totalMemory": 8589934592,
|
|
125
|
+
"freeMemory": 2147483648
|
|
126
|
+
},
|
|
127
|
+
"git": {
|
|
128
|
+
"commitHash": "a1b2c3d4",
|
|
129
|
+
"branch": "main",
|
|
130
|
+
"packageVersion": "1.2.3"
|
|
131
|
+
},
|
|
132
|
+
"error": {
|
|
133
|
+
"name": "Error",
|
|
134
|
+
"message": "User not found",
|
|
135
|
+
"stack": "Error: User not found\n at ...",
|
|
136
|
+
"cause": null
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
---
|
|
142
|
+
|
|
143
|
+
## API
|
|
144
|
+
|
|
145
|
+
### `DebugContext.init(options?)`
|
|
146
|
+
|
|
147
|
+
Initialises the SDK. Call once at startup.
|
|
148
|
+
|
|
149
|
+
```typescript
|
|
150
|
+
DebugContext.init({
|
|
151
|
+
// Extra header names to redact
|
|
152
|
+
sensitiveHeaders: ['x-my-secret-header'],
|
|
153
|
+
|
|
154
|
+
// Extra body fields to redact
|
|
155
|
+
sensitiveFields: ['myApiKey', 'internalToken'],
|
|
156
|
+
|
|
157
|
+
// Hook called after every captured incident
|
|
158
|
+
onIncident: async (incident) => {
|
|
159
|
+
await fetch('https://my-backend.example.com/incidents', {
|
|
160
|
+
method: 'POST',
|
|
161
|
+
body: JSON.stringify(incident),
|
|
162
|
+
});
|
|
163
|
+
},
|
|
164
|
+
|
|
165
|
+
// Attach global uncaughtException + unhandledRejection handlers
|
|
166
|
+
// Default: true
|
|
167
|
+
captureGlobalErrors: true,
|
|
168
|
+
});
|
|
169
|
+
```
|
|
170
|
+
|
|
171
|
+
---
|
|
172
|
+
|
|
173
|
+
### `DebugContext.capture(error, requestContext?)`
|
|
174
|
+
|
|
175
|
+
Manually captures any error. Returns the `Incident`.
|
|
176
|
+
|
|
177
|
+
```typescript
|
|
178
|
+
try {
|
|
179
|
+
await riskyDatabaseCall();
|
|
180
|
+
} catch (err) {
|
|
181
|
+
const incident = DebugContext.capture(err);
|
|
182
|
+
DebugContext.toConsole(incident);
|
|
26
183
|
}
|
|
27
184
|
```
|
|
28
185
|
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### `DebugContext.toConsole(incident?)`
|
|
189
|
+
|
|
190
|
+
Prints a human-readable incident summary to `console.error`. Defaults to the last captured incident.
|
|
191
|
+
|
|
192
|
+
```
|
|
193
|
+
────────────────────────────────────────────────────────────
|
|
194
|
+
🐛 DebugContext Incident 3f2a1b4c-...
|
|
195
|
+
────────────────────────────────────────────────────────────
|
|
196
|
+
|
|
197
|
+
Error : Error: User not found
|
|
198
|
+
Timestamp : 2024-01-15T10:30:00.000Z
|
|
199
|
+
Environment: production
|
|
200
|
+
Node : v20.11.0
|
|
201
|
+
Commit : a1b2c3d4 (main)
|
|
202
|
+
Heap : 59.8% used
|
|
203
|
+
|
|
204
|
+
Request:
|
|
205
|
+
GET /users/42
|
|
206
|
+
IP : 127.0.0.1
|
|
207
|
+
User-Agent: curl/8.4.0
|
|
208
|
+
|
|
209
|
+
Stack:
|
|
210
|
+
Error: User not found
|
|
211
|
+
at /app/routes/users.js:12:9
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
---
|
|
215
|
+
|
|
216
|
+
### `DebugContext.toJSON(incident?)`
|
|
217
|
+
|
|
218
|
+
Returns the incident as a pretty-printed JSON string.
|
|
219
|
+
|
|
220
|
+
```typescript
|
|
221
|
+
const json = DebugContext.toJSON();
|
|
222
|
+
fs.writeFileSync('incident.json', json ?? '');
|
|
223
|
+
```
|
|
224
|
+
|
|
225
|
+
---
|
|
226
|
+
|
|
227
|
+
### `DebugContext.toFile(incident?, options?)`
|
|
228
|
+
|
|
229
|
+
Appends the incident as a single line to an NDJSON file. Creates the file and parent directories if they don't exist.
|
|
230
|
+
|
|
231
|
+
```typescript
|
|
232
|
+
// Default path: incidents.ndjson in cwd
|
|
233
|
+
DebugContext.toFile(incident);
|
|
234
|
+
|
|
235
|
+
// Custom path
|
|
236
|
+
DebugContext.toFile(incident, { path: 'logs/incidents.ndjson' });
|
|
237
|
+
|
|
238
|
+
// Use with onIncident hook to log every error automatically
|
|
239
|
+
DebugContext.init({
|
|
240
|
+
onIncident: (i) => DebugContext.toFile(i, { path: 'logs/incidents.ndjson' }),
|
|
241
|
+
});
|
|
242
|
+
```
|
|
243
|
+
|
|
244
|
+
---
|
|
245
|
+
|
|
246
|
+
### `DebugContext.middleware()`
|
|
247
|
+
|
|
248
|
+
Returns a framework-agnostic capture function. Use this when building custom adapters.
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
const capture = DebugContext.middleware();
|
|
252
|
+
const incident = capture(error, requestContext);
|
|
253
|
+
```
|
|
254
|
+
|
|
255
|
+
---
|
|
256
|
+
|
|
257
|
+
## Automatic Redaction
|
|
258
|
+
|
|
259
|
+
Sensitive values are **always** replaced with `"[REDACTED]"` before they appear in an Incident.
|
|
260
|
+
|
|
261
|
+
**Headers (always redacted):**
|
|
262
|
+
`authorization`, `cookie`, `set-cookie`, `x-api-key`, `x-auth-token`, `x-access-token`, `proxy-authorization`, `www-authenticate`
|
|
263
|
+
|
|
264
|
+
**Body fields (always redacted):**
|
|
265
|
+
`password`, `secret`, `token`, `apikey`, `access_token`, `refresh_token`, `credit_card`, `cvv`, `ssn`, `private_key`, and more.
|
|
266
|
+
|
|
267
|
+
Add extra names via `init()`:
|
|
268
|
+
|
|
269
|
+
```typescript
|
|
270
|
+
DebugContext.init({
|
|
271
|
+
sensitiveHeaders: ['x-internal-token'],
|
|
272
|
+
sensitiveFields: ['myCustomSecret'],
|
|
273
|
+
});
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
---
|
|
277
|
+
|
|
29
278
|
## Tree-shakable named exports
|
|
30
279
|
|
|
31
280
|
```typescript
|
|
32
|
-
import { init, capture, toJSON, toConsole } from '@lahin31/debugcontext-core';
|
|
33
|
-
|
|
281
|
+
import { init, capture, toJSON, toConsole, toFile, middleware } from '@lahin31/debugcontext-core';
|
|
282
|
+
|
|
283
|
+
// Individual collectors — compose your own pipeline
|
|
284
|
+
import { collectRuntime, collectSystem, collectGit, collectError } from '@lahin31/debugcontext-core';
|
|
285
|
+
|
|
286
|
+
// Redaction utilities — useful for custom adapters
|
|
34
287
|
import { redactHeaders, redactBody } from '@lahin31/debugcontext-core';
|
|
35
288
|
```
|
|
36
289
|
|
|
37
|
-
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Design Principles
|
|
293
|
+
|
|
294
|
+
- **Zero config** — works with a single `DebugContext.init()` call
|
|
295
|
+
- **No external dependencies** — only Node.js built-ins (`crypto`, `os`, `child_process`, `fs`)
|
|
296
|
+
- **No cloud, no database** — incidents are plain objects, send them anywhere
|
|
297
|
+
- **Tree-shakable** — unused collectors are dropped by bundlers
|
|
298
|
+
- **Dual ESM/CJS** — works in both `import` and `require` projects
|
|
299
|
+
|
|
300
|
+
---
|
|
301
|
+
|
|
302
|
+
## Related Packages
|
|
303
|
+
|
|
304
|
+
- [`@lahin31/debugcontext-express`](https://www.npmjs.com/package/@lahin31/debugcontext-express) — Express middleware adapter
|
|
305
|
+
|
|
306
|
+
---
|
|
307
|
+
|
|
308
|
+
## License
|
|
309
|
+
|
|
310
|
+
MIT © [lahin31](https://github.com/lahin31)
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@lahin31/debugcontext-core",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Zero-configuration debugging context SDK for Node.js — automatically captures request, runtime, system, git, and error context on every thrown error.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"debugging",
|