bugstack-sdk 1.0.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/README.md +317 -0
- package/dist/index.d.mts +391 -0
- package/dist/index.d.ts +391 -0
- package/dist/index.js +514 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +503 -0
- package/dist/index.mjs.map +1 -0
- package/package.json +71 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,391 @@
|
|
|
1
|
+
import { NextRequest } from 'next/server';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Configuration options for the BugStack error capture SDK
|
|
5
|
+
*/
|
|
6
|
+
interface ErrorCaptureConfig {
|
|
7
|
+
/**
|
|
8
|
+
* API key for authenticating with the BugStack error service
|
|
9
|
+
*/
|
|
10
|
+
apiKey: string;
|
|
11
|
+
/**
|
|
12
|
+
* URL of the BugStack error service endpoint
|
|
13
|
+
* @default process.env.BUGSTACK_ENDPOINT || "http://localhost:3001/api/errors"
|
|
14
|
+
*/
|
|
15
|
+
endpoint?: string;
|
|
16
|
+
/**
|
|
17
|
+
* Unique identifier for your project
|
|
18
|
+
*/
|
|
19
|
+
projectId?: string;
|
|
20
|
+
/**
|
|
21
|
+
* Environment name (e.g., "production", "staging", "development")
|
|
22
|
+
* @default process.env.NODE_ENV || "development"
|
|
23
|
+
*/
|
|
24
|
+
environment?: string;
|
|
25
|
+
/**
|
|
26
|
+
* Enable or disable error capture
|
|
27
|
+
* Useful for disabling in certain environments
|
|
28
|
+
* @default true
|
|
29
|
+
*/
|
|
30
|
+
enabled?: boolean;
|
|
31
|
+
/**
|
|
32
|
+
* Whether to capture request body in error reports
|
|
33
|
+
* @default true
|
|
34
|
+
*/
|
|
35
|
+
captureRequestBody?: boolean;
|
|
36
|
+
/**
|
|
37
|
+
* Whether to capture query parameters in error reports
|
|
38
|
+
* @default true
|
|
39
|
+
*/
|
|
40
|
+
captureQueryParams?: boolean;
|
|
41
|
+
/**
|
|
42
|
+
* Whether to capture request headers in error reports
|
|
43
|
+
* @default true
|
|
44
|
+
*/
|
|
45
|
+
captureHeaders?: boolean;
|
|
46
|
+
/**
|
|
47
|
+
* Maximum size of request body to capture (in bytes)
|
|
48
|
+
* Bodies larger than this will be truncated
|
|
49
|
+
* @default 10000 (10KB)
|
|
50
|
+
*/
|
|
51
|
+
maxBodySize?: number;
|
|
52
|
+
/**
|
|
53
|
+
* Additional fields to redact from request body and headers
|
|
54
|
+
* Common sensitive fields are redacted by default
|
|
55
|
+
*/
|
|
56
|
+
redactFields?: string[];
|
|
57
|
+
/**
|
|
58
|
+
* Custom metadata to include with every error report
|
|
59
|
+
*/
|
|
60
|
+
metadata?: Record<string, unknown>;
|
|
61
|
+
/**
|
|
62
|
+
* Timeout for sending error reports (in milliseconds)
|
|
63
|
+
* @default 5000
|
|
64
|
+
*/
|
|
65
|
+
timeout?: number;
|
|
66
|
+
/**
|
|
67
|
+
* Whether to log SDK errors to console
|
|
68
|
+
* @default true in development, false in production
|
|
69
|
+
*/
|
|
70
|
+
debug?: boolean;
|
|
71
|
+
/**
|
|
72
|
+
* Custom error filter function
|
|
73
|
+
* Return false to skip reporting certain errors
|
|
74
|
+
*/
|
|
75
|
+
shouldCapture?: (error: Error, request: NextRequest) => boolean;
|
|
76
|
+
/**
|
|
77
|
+
* Hook called before sending error report
|
|
78
|
+
* Can be used to modify or enrich error data
|
|
79
|
+
*/
|
|
80
|
+
beforeSend?: (error: CapturedError) => CapturedError | null;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* Resolved configuration with all defaults applied
|
|
84
|
+
*/
|
|
85
|
+
interface ResolvedConfig {
|
|
86
|
+
apiKey: string;
|
|
87
|
+
endpoint: string;
|
|
88
|
+
projectId: string;
|
|
89
|
+
environment: string;
|
|
90
|
+
enabled: boolean;
|
|
91
|
+
captureRequestBody: boolean;
|
|
92
|
+
captureQueryParams: boolean;
|
|
93
|
+
captureHeaders: boolean;
|
|
94
|
+
maxBodySize: number;
|
|
95
|
+
redactFields: string[];
|
|
96
|
+
metadata: Record<string, unknown>;
|
|
97
|
+
timeout: number;
|
|
98
|
+
debug: boolean;
|
|
99
|
+
shouldCapture?: (error: Error, request: NextRequest) => boolean;
|
|
100
|
+
beforeSend?: (error: CapturedError) => CapturedError | null;
|
|
101
|
+
}
|
|
102
|
+
/**
|
|
103
|
+
* Captured error data sent to the error service
|
|
104
|
+
*/
|
|
105
|
+
interface CapturedError {
|
|
106
|
+
/**
|
|
107
|
+
* Unique identifier for this error instance
|
|
108
|
+
*/
|
|
109
|
+
id: string;
|
|
110
|
+
/**
|
|
111
|
+
* Error message
|
|
112
|
+
*/
|
|
113
|
+
message: string;
|
|
114
|
+
/**
|
|
115
|
+
* Error name/type (e.g., "TypeError", "ReferenceError")
|
|
116
|
+
*/
|
|
117
|
+
name: string;
|
|
118
|
+
/**
|
|
119
|
+
* Full stack trace
|
|
120
|
+
*/
|
|
121
|
+
stack?: string;
|
|
122
|
+
/**
|
|
123
|
+
* Parsed stack frames for easier analysis
|
|
124
|
+
*/
|
|
125
|
+
stackFrames?: StackFrame[];
|
|
126
|
+
/**
|
|
127
|
+
* ISO 8601 timestamp when the error occurred
|
|
128
|
+
*/
|
|
129
|
+
timestamp: string;
|
|
130
|
+
/**
|
|
131
|
+
* API route path (e.g., "/api/users/[id]")
|
|
132
|
+
*/
|
|
133
|
+
route: string;
|
|
134
|
+
/**
|
|
135
|
+
* HTTP method (GET, POST, etc.)
|
|
136
|
+
*/
|
|
137
|
+
method: string;
|
|
138
|
+
/**
|
|
139
|
+
* HTTP status code
|
|
140
|
+
* @default 500
|
|
141
|
+
*/
|
|
142
|
+
statusCode: number;
|
|
143
|
+
/**
|
|
144
|
+
* Full request URL
|
|
145
|
+
*/
|
|
146
|
+
url: string;
|
|
147
|
+
/**
|
|
148
|
+
* Query parameters (sanitized)
|
|
149
|
+
*/
|
|
150
|
+
queryParams?: Record<string, string>;
|
|
151
|
+
/**
|
|
152
|
+
* Request body (sanitized and truncated)
|
|
153
|
+
*/
|
|
154
|
+
requestBody?: unknown;
|
|
155
|
+
/**
|
|
156
|
+
* Request headers (sanitized)
|
|
157
|
+
*/
|
|
158
|
+
requestHeaders?: Record<string, string>;
|
|
159
|
+
/**
|
|
160
|
+
* Environment (production, staging, development)
|
|
161
|
+
*/
|
|
162
|
+
environment: string;
|
|
163
|
+
/**
|
|
164
|
+
* Project identifier
|
|
165
|
+
*/
|
|
166
|
+
projectId?: string;
|
|
167
|
+
/**
|
|
168
|
+
* Route parameters (e.g., { id: "123" })
|
|
169
|
+
*/
|
|
170
|
+
routeParams?: Record<string, string>;
|
|
171
|
+
/**
|
|
172
|
+
* Additional custom metadata
|
|
173
|
+
*/
|
|
174
|
+
metadata?: Record<string, unknown>;
|
|
175
|
+
/**
|
|
176
|
+
* SDK version that captured this error
|
|
177
|
+
*/
|
|
178
|
+
sdkVersion: string;
|
|
179
|
+
/**
|
|
180
|
+
* Node.js version
|
|
181
|
+
*/
|
|
182
|
+
nodeVersion: string;
|
|
183
|
+
/**
|
|
184
|
+
* Next.js version (if available)
|
|
185
|
+
*/
|
|
186
|
+
nextVersion?: string;
|
|
187
|
+
}
|
|
188
|
+
/**
|
|
189
|
+
* Parsed stack frame for easier debugging
|
|
190
|
+
*/
|
|
191
|
+
interface StackFrame {
|
|
192
|
+
/**
|
|
193
|
+
* Function name
|
|
194
|
+
*/
|
|
195
|
+
function?: string;
|
|
196
|
+
/**
|
|
197
|
+
* File path
|
|
198
|
+
*/
|
|
199
|
+
file?: string;
|
|
200
|
+
/**
|
|
201
|
+
* Line number
|
|
202
|
+
*/
|
|
203
|
+
line?: number;
|
|
204
|
+
/**
|
|
205
|
+
* Column number
|
|
206
|
+
*/
|
|
207
|
+
column?: number;
|
|
208
|
+
/**
|
|
209
|
+
* Whether this frame is from node_modules
|
|
210
|
+
*/
|
|
211
|
+
isNodeModule?: boolean;
|
|
212
|
+
/**
|
|
213
|
+
* Whether this frame is from internal Node.js code
|
|
214
|
+
*/
|
|
215
|
+
isInternal?: boolean;
|
|
216
|
+
}
|
|
217
|
+
/**
|
|
218
|
+
* Payload sent to the error service
|
|
219
|
+
*/
|
|
220
|
+
interface ErrorReportPayload {
|
|
221
|
+
/**
|
|
222
|
+
* The captured error data
|
|
223
|
+
*/
|
|
224
|
+
error: CapturedError;
|
|
225
|
+
/**
|
|
226
|
+
* Source code context around the error (if available)
|
|
227
|
+
*/
|
|
228
|
+
sourceContext?: SourceContext;
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Source code context around the error location
|
|
232
|
+
*/
|
|
233
|
+
interface SourceContext {
|
|
234
|
+
/**
|
|
235
|
+
* File path
|
|
236
|
+
*/
|
|
237
|
+
filePath: string;
|
|
238
|
+
/**
|
|
239
|
+
* Line number where error occurred
|
|
240
|
+
*/
|
|
241
|
+
lineNumber: number;
|
|
242
|
+
/**
|
|
243
|
+
* Lines of code before the error line
|
|
244
|
+
*/
|
|
245
|
+
preContext: string[];
|
|
246
|
+
/**
|
|
247
|
+
* The line where the error occurred
|
|
248
|
+
*/
|
|
249
|
+
contextLine: string;
|
|
250
|
+
/**
|
|
251
|
+
* Lines of code after the error line
|
|
252
|
+
*/
|
|
253
|
+
postContext: string[];
|
|
254
|
+
}
|
|
255
|
+
/**
|
|
256
|
+
* Next.js App Router route handler type
|
|
257
|
+
*/
|
|
258
|
+
type NextRouteHandler<T = unknown> = (request: NextRequest, context: RouteContext<T>) => Response | Promise<Response>;
|
|
259
|
+
/**
|
|
260
|
+
* Route context passed to Next.js handlers
|
|
261
|
+
*/
|
|
262
|
+
interface RouteContext<T = unknown> {
|
|
263
|
+
params: T extends Record<string, string> ? T : Record<string, string>;
|
|
264
|
+
}
|
|
265
|
+
/**
|
|
266
|
+
* Options that can be passed to withErrorCapture per-route
|
|
267
|
+
*/
|
|
268
|
+
interface RouteOptions {
|
|
269
|
+
/**
|
|
270
|
+
* Override the status code reported for errors in this route
|
|
271
|
+
*/
|
|
272
|
+
statusCode?: number;
|
|
273
|
+
/**
|
|
274
|
+
* Additional metadata specific to this route
|
|
275
|
+
*/
|
|
276
|
+
metadata?: Record<string, unknown>;
|
|
277
|
+
/**
|
|
278
|
+
* Custom error filter for this route
|
|
279
|
+
*/
|
|
280
|
+
shouldCapture?: (error: Error) => boolean;
|
|
281
|
+
}
|
|
282
|
+
type BugStackConfig = ErrorCaptureConfig;
|
|
283
|
+
|
|
284
|
+
/**
|
|
285
|
+
* Type for the wrapped handler function
|
|
286
|
+
*/
|
|
287
|
+
type WrappedHandler<T> = (request: NextRequest, context: RouteContext<T>) => Response | Promise<Response>;
|
|
288
|
+
/**
|
|
289
|
+
* Wrap a Next.js App Router API route handler with error capture
|
|
290
|
+
*
|
|
291
|
+
* @example
|
|
292
|
+
* ```typescript
|
|
293
|
+
* // Basic usage
|
|
294
|
+
* export const GET = withErrorCapture(async (request) => {
|
|
295
|
+
* return NextResponse.json({ data: "hello" });
|
|
296
|
+
* });
|
|
297
|
+
*
|
|
298
|
+
* // With configuration (first call only)
|
|
299
|
+
* export const GET = withErrorCapture(
|
|
300
|
+
* async (request) => {
|
|
301
|
+
* return NextResponse.json({ data: "hello" });
|
|
302
|
+
* },
|
|
303
|
+
* { apiKey: "your-api-key" }
|
|
304
|
+
* );
|
|
305
|
+
*
|
|
306
|
+
* // With route-specific options
|
|
307
|
+
* export const POST = withErrorCapture(
|
|
308
|
+
* async (request) => {
|
|
309
|
+
* return NextResponse.json({ data: "created" });
|
|
310
|
+
* },
|
|
311
|
+
* undefined,
|
|
312
|
+
* { statusCode: 400, metadata: { operation: "create" } }
|
|
313
|
+
* );
|
|
314
|
+
* ```
|
|
315
|
+
*/
|
|
316
|
+
declare function withErrorCapture<T = Record<string, string>>(handler: WrappedHandler<T>, config?: ErrorCaptureConfig, routeOptions?: RouteOptions): WrappedHandler<T>;
|
|
317
|
+
declare const withBugStack: typeof withErrorCapture;
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* BugStack Error Capture Client
|
|
321
|
+
*
|
|
322
|
+
* Singleton client for capturing and reporting errors to the BugStack service.
|
|
323
|
+
*/
|
|
324
|
+
declare class ErrorCaptureClient {
|
|
325
|
+
private config;
|
|
326
|
+
private static instance;
|
|
327
|
+
constructor(config: ErrorCaptureConfig);
|
|
328
|
+
/**
|
|
329
|
+
* Initialize the singleton client instance
|
|
330
|
+
*/
|
|
331
|
+
static init(config: ErrorCaptureConfig): ErrorCaptureClient;
|
|
332
|
+
/**
|
|
333
|
+
* Get the singleton client instance
|
|
334
|
+
*/
|
|
335
|
+
static getInstance(): ErrorCaptureClient | null;
|
|
336
|
+
/**
|
|
337
|
+
* Check if the client has been initialized
|
|
338
|
+
*/
|
|
339
|
+
static isInitialized(): boolean;
|
|
340
|
+
/**
|
|
341
|
+
* Reset the client (mainly for testing)
|
|
342
|
+
*/
|
|
343
|
+
static reset(): void;
|
|
344
|
+
/**
|
|
345
|
+
* Report an error to the BugStack service
|
|
346
|
+
*/
|
|
347
|
+
reportError(error: CapturedError, sourceContext?: SourceContext): Promise<boolean>;
|
|
348
|
+
/**
|
|
349
|
+
* Get the resolved configuration
|
|
350
|
+
*/
|
|
351
|
+
getConfig(): ResolvedConfig;
|
|
352
|
+
/**
|
|
353
|
+
* Check if a field should be redacted
|
|
354
|
+
*/
|
|
355
|
+
shouldRedact(fieldName: string): boolean;
|
|
356
|
+
/**
|
|
357
|
+
* Get the SDK version
|
|
358
|
+
*/
|
|
359
|
+
static getVersion(): string;
|
|
360
|
+
private log;
|
|
361
|
+
private logError;
|
|
362
|
+
}
|
|
363
|
+
declare const BugStackClient: typeof ErrorCaptureClient;
|
|
364
|
+
|
|
365
|
+
/**
|
|
366
|
+
* Parse a V8 stack trace into structured frames
|
|
367
|
+
*/
|
|
368
|
+
declare function parseStackTrace(stack: string | undefined): StackFrame[];
|
|
369
|
+
/**
|
|
370
|
+
* Get the first application frame (non-node_modules, non-internal)
|
|
371
|
+
*/
|
|
372
|
+
declare function getFirstAppFrame(frames: StackFrame[]): StackFrame | undefined;
|
|
373
|
+
/**
|
|
374
|
+
* Filter stack frames to only include application code
|
|
375
|
+
*/
|
|
376
|
+
declare function getAppFrames(frames: StackFrame[]): StackFrame[];
|
|
377
|
+
|
|
378
|
+
/**
|
|
379
|
+
* Sanitize headers by removing sensitive values
|
|
380
|
+
*/
|
|
381
|
+
declare function sanitizeHeaders(headers: Headers, client?: ErrorCaptureClient | null): Record<string, string>;
|
|
382
|
+
/**
|
|
383
|
+
* Sanitize query parameters by redacting sensitive values
|
|
384
|
+
*/
|
|
385
|
+
declare function sanitizeQueryParams(url: URL, client?: ErrorCaptureClient | null): Record<string, string>;
|
|
386
|
+
/**
|
|
387
|
+
* Recursively sanitize an object by redacting sensitive fields
|
|
388
|
+
*/
|
|
389
|
+
declare function sanitizeObject(obj: unknown, client?: ErrorCaptureClient | null, maxDepth?: number, currentDepth?: number): unknown;
|
|
390
|
+
|
|
391
|
+
export { BugStackClient, type BugStackConfig, type CapturedError, ErrorCaptureClient, type ErrorCaptureConfig, type ErrorReportPayload, type NextRouteHandler, type ResolvedConfig, type RouteContext, type RouteOptions, type SourceContext, type StackFrame, getAppFrames, getFirstAppFrame, parseStackTrace, sanitizeHeaders, sanitizeObject, sanitizeQueryParams, withBugStack, withErrorCapture };
|