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/README.md
ADDED
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
# bugstack-sdk
|
|
2
|
+
|
|
3
|
+
Error capture SDK for Next.js 14+ App Router API routes. Automatically captures errors with full context and reports them to the BugStack service for AI-powered fix generation.
|
|
4
|
+
|
|
5
|
+
**Get your API key at:** https://dashboard.bugstack.ai
|
|
6
|
+
|
|
7
|
+
## Features
|
|
8
|
+
|
|
9
|
+
- **Zero-config wrapping** - Simply wrap your route handlers with `withErrorCapture`
|
|
10
|
+
- **Full error context** - Captures stack traces, request body, headers, query params
|
|
11
|
+
- **Automatic sanitization** - Sensitive data (passwords, tokens, etc.) is automatically redacted
|
|
12
|
+
- **Non-blocking** - Error reporting happens asynchronously without slowing down responses
|
|
13
|
+
- **TypeScript first** - Full type safety with comprehensive type definitions
|
|
14
|
+
- **Production ready** - Configurable timeouts, error handling, and kill switches
|
|
15
|
+
|
|
16
|
+
## Installation
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
npm install bugstack-sdk
|
|
20
|
+
# or
|
|
21
|
+
pnpm add bugstack-sdk
|
|
22
|
+
# or
|
|
23
|
+
yarn add bugstack-sdk
|
|
24
|
+
```
|
|
25
|
+
|
|
26
|
+
## Quick Start
|
|
27
|
+
|
|
28
|
+
### 1. Initialize the client (once, in a shared file)
|
|
29
|
+
|
|
30
|
+
```typescript
|
|
31
|
+
// lib/bugstack.ts
|
|
32
|
+
import { ErrorCaptureClient } from "bugstack-sdk";
|
|
33
|
+
|
|
34
|
+
export const bugstack = ErrorCaptureClient.init({
|
|
35
|
+
apiKey: process.env.BUGSTACK_API_KEY!,
|
|
36
|
+
projectId: "my-project",
|
|
37
|
+
// Optional: customize endpoint
|
|
38
|
+
// endpoint: "https://your-bugstack-server.com/api/capture",
|
|
39
|
+
});
|
|
40
|
+
```
|
|
41
|
+
|
|
42
|
+
### 2. Wrap your API routes
|
|
43
|
+
|
|
44
|
+
```typescript
|
|
45
|
+
// app/api/users/route.ts
|
|
46
|
+
import { NextResponse } from "next/server";
|
|
47
|
+
import { withErrorCapture } from "bugstack-sdk";
|
|
48
|
+
import "@/lib/bugstack"; // Ensure client is initialized
|
|
49
|
+
|
|
50
|
+
export const GET = withErrorCapture(async (request) => {
|
|
51
|
+
const users = await db.users.findMany();
|
|
52
|
+
return NextResponse.json({ users });
|
|
53
|
+
});
|
|
54
|
+
|
|
55
|
+
export const POST = withErrorCapture(async (request) => {
|
|
56
|
+
const body = await request.json();
|
|
57
|
+
const user = await db.users.create({ data: body });
|
|
58
|
+
return NextResponse.json({ user }, { status: 201 });
|
|
59
|
+
});
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
### 3. Dynamic routes with params
|
|
63
|
+
|
|
64
|
+
```typescript
|
|
65
|
+
// app/api/users/[id]/route.ts
|
|
66
|
+
import { NextResponse } from "next/server";
|
|
67
|
+
import { withErrorCapture } from "bugstack-sdk";
|
|
68
|
+
import "@/lib/bugstack";
|
|
69
|
+
|
|
70
|
+
export const GET = withErrorCapture<{ id: string }>(
|
|
71
|
+
async (request, { params }) => {
|
|
72
|
+
const user = await db.users.findUnique({
|
|
73
|
+
where: { id: params.id },
|
|
74
|
+
});
|
|
75
|
+
|
|
76
|
+
if (!user) {
|
|
77
|
+
throw new Error("User not found");
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
return NextResponse.json({ user });
|
|
81
|
+
}
|
|
82
|
+
);
|
|
83
|
+
```
|
|
84
|
+
|
|
85
|
+
## Configuration
|
|
86
|
+
|
|
87
|
+
### Full Configuration Options
|
|
88
|
+
|
|
89
|
+
```typescript
|
|
90
|
+
import { ErrorCaptureClient } from "bugstack-sdk";
|
|
91
|
+
|
|
92
|
+
ErrorCaptureClient.init({
|
|
93
|
+
// Required
|
|
94
|
+
apiKey: "your-api-key",
|
|
95
|
+
|
|
96
|
+
// Optional - defaults shown
|
|
97
|
+
endpoint: "http://localhost:3001/api/capture",
|
|
98
|
+
projectId: "",
|
|
99
|
+
environment: process.env.NODE_ENV, // "development", "production", etc.
|
|
100
|
+
enabled: true, // Set to false to disable capture
|
|
101
|
+
|
|
102
|
+
// Request capture options
|
|
103
|
+
captureRequestBody: true,
|
|
104
|
+
captureQueryParams: true,
|
|
105
|
+
captureHeaders: true,
|
|
106
|
+
maxBodySize: 10000, // 10KB max body capture
|
|
107
|
+
|
|
108
|
+
// Additional fields to redact (added to defaults)
|
|
109
|
+
redactFields: ["customSecret", "internalToken"],
|
|
110
|
+
|
|
111
|
+
// Custom metadata included with every error
|
|
112
|
+
metadata: {
|
|
113
|
+
service: "api",
|
|
114
|
+
version: "1.0.0",
|
|
115
|
+
},
|
|
116
|
+
|
|
117
|
+
// Network options
|
|
118
|
+
timeout: 5000, // 5 second timeout for error reporting
|
|
119
|
+
|
|
120
|
+
// Debug logging (defaults to true in development)
|
|
121
|
+
debug: true,
|
|
122
|
+
|
|
123
|
+
// Custom filter - return false to skip certain errors
|
|
124
|
+
shouldCapture: (error, request) => {
|
|
125
|
+
// Don't capture 404s
|
|
126
|
+
if (error.message.includes("not found")) {
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
return true;
|
|
130
|
+
},
|
|
131
|
+
|
|
132
|
+
// Transform errors before sending
|
|
133
|
+
beforeSend: (capturedError) => {
|
|
134
|
+
// Add custom data
|
|
135
|
+
capturedError.metadata = {
|
|
136
|
+
...capturedError.metadata,
|
|
137
|
+
customField: "value",
|
|
138
|
+
};
|
|
139
|
+
return capturedError;
|
|
140
|
+
// Return null to skip this error
|
|
141
|
+
},
|
|
142
|
+
});
|
|
143
|
+
```
|
|
144
|
+
|
|
145
|
+
### Environment Variables
|
|
146
|
+
|
|
147
|
+
The SDK automatically reads these environment variables:
|
|
148
|
+
|
|
149
|
+
```bash
|
|
150
|
+
# Required
|
|
151
|
+
BUGSTACK_API_KEY=your-api-key
|
|
152
|
+
|
|
153
|
+
# Optional
|
|
154
|
+
BUGSTACK_ENDPOINT=https://bugstack-error-service.onrender.com/api/capture
|
|
155
|
+
BUGSTACK_PROJECT_ID=my-project
|
|
156
|
+
NODE_ENV=production
|
|
157
|
+
```
|
|
158
|
+
|
|
159
|
+
**Note:** The default endpoint is `http://localhost:3001/api/capture` for local development. Set `BUGSTACK_ENDPOINT` to the production URL shown above for deployed applications.
|
|
160
|
+
|
|
161
|
+
### Per-Route Options
|
|
162
|
+
|
|
163
|
+
You can override options for specific routes:
|
|
164
|
+
|
|
165
|
+
```typescript
|
|
166
|
+
export const POST = withErrorCapture(
|
|
167
|
+
async (request) => {
|
|
168
|
+
// handler code
|
|
169
|
+
},
|
|
170
|
+
undefined, // Use existing client config
|
|
171
|
+
{
|
|
172
|
+
// Route-specific options
|
|
173
|
+
statusCode: 400, // Report as 400 instead of 500
|
|
174
|
+
metadata: {
|
|
175
|
+
operation: "createUser",
|
|
176
|
+
critical: true,
|
|
177
|
+
},
|
|
178
|
+
shouldCapture: (error) => {
|
|
179
|
+
// Route-specific filter
|
|
180
|
+
return error.name !== "ValidationError";
|
|
181
|
+
},
|
|
182
|
+
}
|
|
183
|
+
);
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## Captured Error Data
|
|
187
|
+
|
|
188
|
+
Each error report includes:
|
|
189
|
+
|
|
190
|
+
```typescript
|
|
191
|
+
interface CapturedError {
|
|
192
|
+
id: string; // Unique error ID (err_xxx_xxx)
|
|
193
|
+
name: string; // Error name (TypeError, etc.)
|
|
194
|
+
message: string; // Error message
|
|
195
|
+
stack: string; // Full stack trace
|
|
196
|
+
stackFrames: StackFrame[]; // Parsed stack frames
|
|
197
|
+
timestamp: string; // ISO 8601 timestamp
|
|
198
|
+
route: string; // API route path
|
|
199
|
+
method: string; // HTTP method
|
|
200
|
+
statusCode: number; // HTTP status code
|
|
201
|
+
url: string; // Full request URL
|
|
202
|
+
queryParams: object; // Query parameters (sanitized)
|
|
203
|
+
requestBody: unknown; // Request body (sanitized)
|
|
204
|
+
requestHeaders: object; // Headers (sanitized)
|
|
205
|
+
routeParams: object; // Dynamic route params
|
|
206
|
+
environment: string; // Environment name
|
|
207
|
+
projectId: string; // Project identifier
|
|
208
|
+
sdkVersion: string; // SDK version
|
|
209
|
+
nodeVersion: string; // Node.js version
|
|
210
|
+
nextVersion: string; // Next.js version
|
|
211
|
+
metadata: object; // Custom metadata
|
|
212
|
+
}
|
|
213
|
+
```
|
|
214
|
+
|
|
215
|
+
## Automatic Data Sanitization
|
|
216
|
+
|
|
217
|
+
The SDK automatically redacts sensitive fields from:
|
|
218
|
+
- Request headers (Authorization, Cookie, etc.)
|
|
219
|
+
- Request body
|
|
220
|
+
- Query parameters
|
|
221
|
+
|
|
222
|
+
**Default redacted fields:**
|
|
223
|
+
- password, secret, token
|
|
224
|
+
- apikey, api_key, apiKey
|
|
225
|
+
- authorization, auth, credential
|
|
226
|
+
- credit_card, creditcard, card_number
|
|
227
|
+
- cvv, ssn, social_security
|
|
228
|
+
|
|
229
|
+
Add custom fields via `redactFields` config option.
|
|
230
|
+
|
|
231
|
+
## Error Handling
|
|
232
|
+
|
|
233
|
+
The SDK is designed to never interfere with your application:
|
|
234
|
+
|
|
235
|
+
- **Network failures** - Silently ignored, your app continues normally
|
|
236
|
+
- **Timeouts** - Configurable, defaults to 5 seconds
|
|
237
|
+
- **SDK errors** - Caught and logged (in debug mode), never thrown
|
|
238
|
+
- **Re-throws original error** - Next.js still handles the error response
|
|
239
|
+
|
|
240
|
+
## Advanced Usage
|
|
241
|
+
|
|
242
|
+
### Manual Error Reporting
|
|
243
|
+
|
|
244
|
+
```typescript
|
|
245
|
+
import { ErrorCaptureClient } from "bugstack-sdk";
|
|
246
|
+
|
|
247
|
+
const client = ErrorCaptureClient.getInstance();
|
|
248
|
+
|
|
249
|
+
if (client) {
|
|
250
|
+
await client.reportError({
|
|
251
|
+
id: "manual_001",
|
|
252
|
+
name: "CustomError",
|
|
253
|
+
message: "Something went wrong",
|
|
254
|
+
timestamp: new Date().toISOString(),
|
|
255
|
+
route: "/api/custom",
|
|
256
|
+
method: "POST",
|
|
257
|
+
statusCode: 500,
|
|
258
|
+
url: "https://example.com/api/custom",
|
|
259
|
+
environment: "production",
|
|
260
|
+
sdkVersion: "1.0.0",
|
|
261
|
+
nodeVersion: process.version,
|
|
262
|
+
});
|
|
263
|
+
}
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
### Stack Trace Utilities
|
|
267
|
+
|
|
268
|
+
```typescript
|
|
269
|
+
import {
|
|
270
|
+
parseStackTrace,
|
|
271
|
+
getFirstAppFrame,
|
|
272
|
+
getAppFrames,
|
|
273
|
+
} from "bugstack-sdk";
|
|
274
|
+
|
|
275
|
+
const frames = parseStackTrace(error.stack);
|
|
276
|
+
const firstAppFrame = getFirstAppFrame(frames); // First non-node_modules frame
|
|
277
|
+
const appFrames = getAppFrames(frames); // All application frames
|
|
278
|
+
```
|
|
279
|
+
|
|
280
|
+
### Sanitization Utilities
|
|
281
|
+
|
|
282
|
+
```typescript
|
|
283
|
+
import {
|
|
284
|
+
sanitizeHeaders,
|
|
285
|
+
sanitizeQueryParams,
|
|
286
|
+
sanitizeObject,
|
|
287
|
+
} from "bugstack-sdk";
|
|
288
|
+
|
|
289
|
+
const safeHeaders = sanitizeHeaders(request.headers);
|
|
290
|
+
const safeParams = sanitizeQueryParams(new URL(request.url));
|
|
291
|
+
const safeBody = sanitizeObject(requestBody);
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
## TypeScript Support
|
|
295
|
+
|
|
296
|
+
Full type definitions are included:
|
|
297
|
+
|
|
298
|
+
```typescript
|
|
299
|
+
import type {
|
|
300
|
+
ErrorCaptureConfig,
|
|
301
|
+
CapturedError,
|
|
302
|
+
StackFrame,
|
|
303
|
+
RouteOptions,
|
|
304
|
+
NextRouteHandler,
|
|
305
|
+
RouteContext,
|
|
306
|
+
} from "bugstack-sdk";
|
|
307
|
+
```
|
|
308
|
+
|
|
309
|
+
## Compatibility
|
|
310
|
+
|
|
311
|
+
- **Next.js**: 14.0.0+
|
|
312
|
+
- **Node.js**: 18.0.0+
|
|
313
|
+
- **TypeScript**: 5.0.0+ (optional)
|
|
314
|
+
|
|
315
|
+
## License
|
|
316
|
+
|
|
317
|
+
MIT
|
package/dist/index.d.mts
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 };
|