bugcatch-sdk 0.1.5 → 0.1.9
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 +27 -0
- package/dist/index.d.ts +27 -0
- package/dist/index.js +86 -3
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +86 -3
- package/dist/index.mjs.map +1 -1
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -19,6 +19,16 @@ interface BugCatchOptions {
|
|
|
19
19
|
* Default: true.
|
|
20
20
|
*/
|
|
21
21
|
autoCaptureBreadcrumbs?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Automatically intercept fetch() calls and report API timing metrics
|
|
24
|
+
* to BugCatch. Default: false.
|
|
25
|
+
*/
|
|
26
|
+
autoTrackRequests?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* URL patterns to exclude from request tracking. The BugCatch ingest URL
|
|
29
|
+
* is always excluded automatically.
|
|
30
|
+
*/
|
|
31
|
+
trackIgnoreUrls?: Array<string | RegExp>;
|
|
22
32
|
/**
|
|
23
33
|
* A list of URL patterns (strings or RegExps). Any error originating from
|
|
24
34
|
* a script URL that matches will be ignored.
|
|
@@ -103,11 +113,18 @@ declare class BugCatchClient {
|
|
|
103
113
|
addBreadcrumb(crumb: BreadcrumbEntry): void;
|
|
104
114
|
/** Tear down all global listeners. Call when unmounting in SPAs. */
|
|
105
115
|
destroy(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Manually report an API call timing. Use this when `autoTrackRequests`
|
|
118
|
+
* is off or when you want to track server-side (Node.js) requests explicitly.
|
|
119
|
+
*/
|
|
120
|
+
trackRequest(method: string, route: string, durationMs: number, statusCode: number): void;
|
|
106
121
|
private buildExceptionPayload;
|
|
107
122
|
private buildMessagePayload;
|
|
108
123
|
private buildBase;
|
|
109
124
|
private installErrorHandlers;
|
|
110
125
|
private shouldIgnore;
|
|
126
|
+
private installFetchInterceptor;
|
|
127
|
+
private sendMetric;
|
|
111
128
|
private send;
|
|
112
129
|
private log;
|
|
113
130
|
}
|
|
@@ -150,6 +167,16 @@ declare const BugCatch: {
|
|
|
150
167
|
* Manually add a breadcrumb.
|
|
151
168
|
*/
|
|
152
169
|
addBreadcrumb(crumb: BreadcrumbEntry): void;
|
|
170
|
+
/**
|
|
171
|
+
* Manually report an API call timing to BugCatch.
|
|
172
|
+
* Use when `autoTrackRequests` is off or for server-side tracking.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* const start = Date.now();
|
|
176
|
+
* await fetch('/api/orders');
|
|
177
|
+
* BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);
|
|
178
|
+
*/
|
|
179
|
+
trackRequest(method: string, route: string, durationMs: number, statusCode: number): void;
|
|
153
180
|
/**
|
|
154
181
|
* Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.
|
|
155
182
|
*/
|
package/dist/index.d.ts
CHANGED
|
@@ -19,6 +19,16 @@ interface BugCatchOptions {
|
|
|
19
19
|
* Default: true.
|
|
20
20
|
*/
|
|
21
21
|
autoCaptureBreadcrumbs?: boolean;
|
|
22
|
+
/**
|
|
23
|
+
* Automatically intercept fetch() calls and report API timing metrics
|
|
24
|
+
* to BugCatch. Default: false.
|
|
25
|
+
*/
|
|
26
|
+
autoTrackRequests?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* URL patterns to exclude from request tracking. The BugCatch ingest URL
|
|
29
|
+
* is always excluded automatically.
|
|
30
|
+
*/
|
|
31
|
+
trackIgnoreUrls?: Array<string | RegExp>;
|
|
22
32
|
/**
|
|
23
33
|
* A list of URL patterns (strings or RegExps). Any error originating from
|
|
24
34
|
* a script URL that matches will be ignored.
|
|
@@ -103,11 +113,18 @@ declare class BugCatchClient {
|
|
|
103
113
|
addBreadcrumb(crumb: BreadcrumbEntry): void;
|
|
104
114
|
/** Tear down all global listeners. Call when unmounting in SPAs. */
|
|
105
115
|
destroy(): void;
|
|
116
|
+
/**
|
|
117
|
+
* Manually report an API call timing. Use this when `autoTrackRequests`
|
|
118
|
+
* is off or when you want to track server-side (Node.js) requests explicitly.
|
|
119
|
+
*/
|
|
120
|
+
trackRequest(method: string, route: string, durationMs: number, statusCode: number): void;
|
|
106
121
|
private buildExceptionPayload;
|
|
107
122
|
private buildMessagePayload;
|
|
108
123
|
private buildBase;
|
|
109
124
|
private installErrorHandlers;
|
|
110
125
|
private shouldIgnore;
|
|
126
|
+
private installFetchInterceptor;
|
|
127
|
+
private sendMetric;
|
|
111
128
|
private send;
|
|
112
129
|
private log;
|
|
113
130
|
}
|
|
@@ -150,6 +167,16 @@ declare const BugCatch: {
|
|
|
150
167
|
* Manually add a breadcrumb.
|
|
151
168
|
*/
|
|
152
169
|
addBreadcrumb(crumb: BreadcrumbEntry): void;
|
|
170
|
+
/**
|
|
171
|
+
* Manually report an API call timing to BugCatch.
|
|
172
|
+
* Use when `autoTrackRequests` is off or for server-side tracking.
|
|
173
|
+
*
|
|
174
|
+
* @example
|
|
175
|
+
* const start = Date.now();
|
|
176
|
+
* await fetch('/api/orders');
|
|
177
|
+
* BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);
|
|
178
|
+
*/
|
|
179
|
+
trackRequest(method: string, route: string, durationMs: number, statusCode: number): void;
|
|
153
180
|
/**
|
|
154
181
|
* Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.
|
|
155
182
|
*/
|
package/dist/index.js
CHANGED
|
@@ -3,6 +3,8 @@
|
|
|
3
3
|
Object.defineProperty(exports, '__esModule', { value: true });
|
|
4
4
|
|
|
5
5
|
var __defProp = Object.defineProperty;
|
|
6
|
+
var __defProps = Object.defineProperties;
|
|
7
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
6
8
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
7
9
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
8
10
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -18,6 +20,7 @@ var __spreadValues = (a, b) => {
|
|
|
18
20
|
}
|
|
19
21
|
return a;
|
|
20
22
|
};
|
|
23
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
21
24
|
var __objRest = (source, exclude) => {
|
|
22
25
|
var target = {};
|
|
23
26
|
for (var prop in source)
|
|
@@ -225,7 +228,17 @@ function parseDsn(dsn) {
|
|
|
225
228
|
throw new Error(`[BugCatch] Could not extract projectId from DSN path: "${dsn}"`);
|
|
226
229
|
}
|
|
227
230
|
const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;
|
|
228
|
-
|
|
231
|
+
const metricsUrl = `${url.origin}${url.pathname}/metrics?key=${sdkKey}`;
|
|
232
|
+
return { ingestUrl, metricsUrl, projectId, sdkKey };
|
|
233
|
+
}
|
|
234
|
+
function normalizeUrl(rawUrl) {
|
|
235
|
+
let pathname;
|
|
236
|
+
try {
|
|
237
|
+
pathname = new URL(rawUrl).pathname;
|
|
238
|
+
} catch (e) {
|
|
239
|
+
pathname = rawUrl.split("?")[0];
|
|
240
|
+
}
|
|
241
|
+
return pathname.replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "/:id").replace(/\/\d{1,20}(?=\/|$)/g, "/:id");
|
|
229
242
|
}
|
|
230
243
|
function matchesPattern(value, patterns) {
|
|
231
244
|
return patterns.some(
|
|
@@ -241,7 +254,8 @@ var BugCatchClient = class {
|
|
|
241
254
|
debug: false,
|
|
242
255
|
maxBreadcrumbs: 100,
|
|
243
256
|
autoCaptureErrors: true,
|
|
244
|
-
autoCaptureBreadcrumbs: true
|
|
257
|
+
autoCaptureBreadcrumbs: true,
|
|
258
|
+
autoTrackRequests: false
|
|
245
259
|
}, options);
|
|
246
260
|
this.dsn = parseDsn(options.dsn);
|
|
247
261
|
this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);
|
|
@@ -253,6 +267,9 @@ var BugCatchClient = class {
|
|
|
253
267
|
this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));
|
|
254
268
|
this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));
|
|
255
269
|
}
|
|
270
|
+
if (this.opts.autoTrackRequests) {
|
|
271
|
+
this.cleanups.push(this.installFetchInterceptor());
|
|
272
|
+
}
|
|
256
273
|
this.log("Initialized. Project:", this.dsn.projectId);
|
|
257
274
|
}
|
|
258
275
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
@@ -267,7 +284,9 @@ var BugCatchClient = class {
|
|
|
267
284
|
return event.event_id;
|
|
268
285
|
}
|
|
269
286
|
setUser(user) {
|
|
270
|
-
this.user = __spreadValues({}, user)
|
|
287
|
+
this.user = __spreadProps(__spreadValues({}, user), {
|
|
288
|
+
id: user.id != null ? String(user.id) : void 0
|
|
289
|
+
});
|
|
271
290
|
}
|
|
272
291
|
clearUser() {
|
|
273
292
|
this.user = {};
|
|
@@ -285,6 +304,13 @@ var BugCatchClient = class {
|
|
|
285
304
|
}
|
|
286
305
|
this.cleanups.length = 0;
|
|
287
306
|
}
|
|
307
|
+
/**
|
|
308
|
+
* Manually report an API call timing. Use this when `autoTrackRequests`
|
|
309
|
+
* is off or when you want to track server-side (Node.js) requests explicitly.
|
|
310
|
+
*/
|
|
311
|
+
trackRequest(method, route, durationMs, statusCode) {
|
|
312
|
+
void this.sendMetric({ method: method.toUpperCase(), route, duration_ms: durationMs, status_code: statusCode });
|
|
313
|
+
}
|
|
288
314
|
// ─── Internal: build payloads ────────────────────────────────────────────
|
|
289
315
|
buildExceptionPayload(error, extra) {
|
|
290
316
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -381,6 +407,51 @@ var BugCatchClient = class {
|
|
|
381
407
|
}
|
|
382
408
|
return false;
|
|
383
409
|
}
|
|
410
|
+
// ─── Internal: request tracking ──────────────────────────────────────────
|
|
411
|
+
installFetchInterceptor() {
|
|
412
|
+
const original = globalThis.fetch.bind(globalThis);
|
|
413
|
+
const self = this;
|
|
414
|
+
globalThis.fetch = async function patchedFetch(input, init) {
|
|
415
|
+
var _a;
|
|
416
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
417
|
+
if (url.includes(self.dsn.ingestUrl.split("?")[0])) {
|
|
418
|
+
return original(input, init);
|
|
419
|
+
}
|
|
420
|
+
if (self.opts.trackIgnoreUrls && matchesPattern(url, self.opts.trackIgnoreUrls)) {
|
|
421
|
+
return original(input, init);
|
|
422
|
+
}
|
|
423
|
+
const method = ((_a = init == null ? void 0 : init.method) != null ? _a : input instanceof Request ? input.method : "GET").toUpperCase();
|
|
424
|
+
const route = normalizeUrl(url);
|
|
425
|
+
const start = Date.now();
|
|
426
|
+
try {
|
|
427
|
+
const response = await original(input, init);
|
|
428
|
+
void self.sendMetric({
|
|
429
|
+
method,
|
|
430
|
+
route,
|
|
431
|
+
duration_ms: Date.now() - start,
|
|
432
|
+
status_code: response.status,
|
|
433
|
+
user_id: self.user.id
|
|
434
|
+
});
|
|
435
|
+
return response;
|
|
436
|
+
} catch (err) {
|
|
437
|
+
void self.sendMetric({ method, route, duration_ms: Date.now() - start, status_code: 0 });
|
|
438
|
+
throw err;
|
|
439
|
+
}
|
|
440
|
+
};
|
|
441
|
+
return () => {
|
|
442
|
+
globalThis.fetch = original;
|
|
443
|
+
};
|
|
444
|
+
}
|
|
445
|
+
async sendMetric(metric) {
|
|
446
|
+
try {
|
|
447
|
+
await fetch(this.dsn.metricsUrl, {
|
|
448
|
+
method: "POST",
|
|
449
|
+
headers: { "Content-Type": "application/json" },
|
|
450
|
+
body: JSON.stringify(metric)
|
|
451
|
+
});
|
|
452
|
+
} catch (e) {
|
|
453
|
+
}
|
|
454
|
+
}
|
|
384
455
|
// ─── Internal: transport ─────────────────────────────────────────────────
|
|
385
456
|
async send(event) {
|
|
386
457
|
let finalEvent = event;
|
|
@@ -488,6 +559,18 @@ var BugCatch = {
|
|
|
488
559
|
addBreadcrumb(crumb) {
|
|
489
560
|
getClient().addBreadcrumb(crumb);
|
|
490
561
|
},
|
|
562
|
+
/**
|
|
563
|
+
* Manually report an API call timing to BugCatch.
|
|
564
|
+
* Use when `autoTrackRequests` is off or for server-side tracking.
|
|
565
|
+
*
|
|
566
|
+
* @example
|
|
567
|
+
* const start = Date.now();
|
|
568
|
+
* await fetch('/api/orders');
|
|
569
|
+
* BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);
|
|
570
|
+
*/
|
|
571
|
+
trackRequest(method, route, durationMs, statusCode) {
|
|
572
|
+
getClient().trackRequest(method, route, durationMs, statusCode);
|
|
573
|
+
},
|
|
491
574
|
/**
|
|
492
575
|
* Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.
|
|
493
576
|
*/
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse-stack.ts","../src/breadcrumbs.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { StackFrame } from './types.js';\n\n// Chrome/V8: \" at functionName (filename:line:col)\"\n// \" at filename:line:col\"\nconst CHROME_RE = /^\\s*at (?:(.*?) \\()?(.+?):(\\d+):(\\d+)\\)?$/;\n\n// Firefox/Safari: \"functionName@filename:line:col\"\n// \"@filename:line:col\"\nconst FIREFOX_RE = /^(?:(.+?)@)?(.+?):(\\d+):(\\d+)$/;\n\n// Origins that are not \"in-app\" frames\nconst INTERNAL_PATTERNS = [/node_modules\\//, /bugcatch[-_]?sdk/, /^\\(native\\)$/, /^native code/];\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n return !INTERNAL_PATTERNS.some((p) => p.test(filename));\n}\n\nfunction parseChromeLine(line: string): StackFrame | null {\n const m = CHROME_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nfunction parseFirefoxLine(line: string): StackFrame | null {\n const m = FIREFOX_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nexport function parseStack(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('Error') || trimmed.startsWith(error.message ?? '')) {\n continue;\n }\n const frame = parseChromeLine(trimmed) ?? parseFirefoxLine(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n // The API fingerprinting uses the LAST in-app frame, which maps to innermost\n // call. Return in innermost-first order (as captured).\n return frames;\n}\n","import type { BreadcrumbEntry } from './types.js';\n\nexport class BreadcrumbBuffer {\n private readonly buffer: BreadcrumbEntry[] = [];\n private readonly max: number;\n\n constructor(max = 100) {\n this.max = max;\n }\n\n add(crumb: BreadcrumbEntry): void {\n if (this.buffer.length >= this.max) {\n this.buffer.shift();\n }\n this.buffer.push(crumb);\n }\n\n getAll(): BreadcrumbEntry[] {\n return [...this.buffer];\n }\n\n clear(): void {\n this.buffer.length = 0;\n }\n}\n\n// ─── Auto-capture helpers ─────────────────────────────────────────────────────\n\ntype AddFn = (crumb: BreadcrumbEntry) => void;\n\n/**\n * Patch History API (pushState / replaceState / popstate) to capture\n * navigation breadcrumbs.\n */\nexport function installNavigationBreadcrumbs(add: AddFn): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n const originalPush = history.pushState.bind(history);\n const originalReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalPush(...args);\n };\n\n history.replaceState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Replaced state: ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalReplace(...args);\n };\n\n const onPopState = () => {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated back/forward to ${window.location.href}`,\n data: { to: window.location.href },\n });\n };\n\n window.addEventListener('popstate', onPopState);\n\n return () => {\n history.pushState = originalPush;\n history.replaceState = originalReplace;\n window.removeEventListener('popstate', onPopState);\n };\n}\n\n/**\n * Capture click events as breadcrumbs (element tag + text).\n */\nexport function installClickBreadcrumbs(add: AddFn): () => void {\n if (typeof document === 'undefined') return () => undefined;\n\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const tag = target.tagName?.toLowerCase() ?? 'unknown';\n const text = (target.textContent ?? '').trim().slice(0, 50);\n const id = target.id ? `#${target.id}` : '';\n const cls = target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').join('.')}`\n : '';\n add({\n timestamp: new Date().toISOString(),\n type: 'user',\n category: 'ui.click',\n message: `Click on <${tag}${id}${cls}>`,\n data: { tag, text: text || undefined },\n });\n };\n\n document.addEventListener('click', handler, { capture: true, passive: true });\n\n return () => {\n document.removeEventListener('click', handler, { capture: true });\n };\n}\n\n/**\n * Capture console.warn and console.error calls as breadcrumbs.\n */\nexport function installConsoleBreadcrumbs(add: AddFn): () => void {\n if (typeof console === 'undefined') return () => undefined;\n\n const originalWarn = console.warn.bind(console);\n const originalError = console.error.bind(console);\n\n const formatArgs = (args: unknown[]): string =>\n args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ').slice(0, 200);\n\n console.warn = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'warning' },\n });\n originalWarn(...args);\n };\n\n console.error = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'error' },\n });\n originalError(...args);\n };\n\n return () => {\n console.warn = originalWarn;\n console.error = originalError;\n };\n}\n","import type {\n BugCatchOptions,\n UserContext,\n BreadcrumbEntry,\n EventPayload,\n ParsedDsn,\n ExceptionValue,\n} from './types.js';\nimport { parseStack } from './parse-stack.js';\nimport {\n BreadcrumbBuffer,\n installNavigationBreadcrumbs,\n installClickBreadcrumbs,\n installConsoleBreadcrumbs,\n} from './breadcrumbs.js';\n\n// ─── UUID ─────────────────────────────────────────────────────────────────────\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ─── DSN parser ───────────────────────────────────────────────────────────────\n\nfunction parseDsn(dsn: string): ParsedDsn {\n let url: URL;\n try {\n url = new URL(dsn);\n } catch {\n throw new Error(`[BugCatch] Invalid DSN: \"${dsn}\"`);\n }\n\n const sdkKey = url.searchParams.get('key');\n if (!sdkKey) {\n throw new Error(`[BugCatch] DSN is missing the \"key\" query parameter: \"${dsn}\"`);\n }\n\n // Extract projectId from the last path segment (/ingest/{projectId})\n const segments = url.pathname.split('/').filter(Boolean);\n const projectId = segments[segments.length - 1];\n if (!projectId) {\n throw new Error(`[BugCatch] Could not extract projectId from DSN path: \"${dsn}\"`);\n }\n\n // Reconstruct the URL without extra query params\n const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;\n\n return { ingestUrl, projectId, sdkKey };\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────────\n\nfunction matchesPattern(value: string, patterns: Array<string | RegExp>): boolean {\n return patterns.some((p) =>\n typeof p === 'string' ? value.includes(p) : p.test(value),\n );\n}\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\nexport class BugCatchClient {\n private readonly opts: Required<\n Pick<BugCatchOptions, 'debug' | 'maxBreadcrumbs' | 'autoCaptureErrors' | 'autoCaptureBreadcrumbs'>\n > & BugCatchOptions;\n\n private readonly dsn: ParsedDsn;\n private readonly crumbs: BreadcrumbBuffer;\n private user: UserContext = {};\n private tags: Record<string, string> = {};\n private readonly cleanups: Array<() => void> = [];\n\n constructor(options: BugCatchOptions) {\n this.opts = {\n debug: false,\n maxBreadcrumbs: 100,\n autoCaptureErrors: true,\n autoCaptureBreadcrumbs: true,\n ...options,\n };\n\n this.dsn = parseDsn(options.dsn);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n\n if (this.opts.autoCaptureErrors) {\n this.installErrorHandlers();\n }\n\n if (this.opts.autoCaptureBreadcrumbs) {\n this.cleanups.push(installNavigationBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));\n }\n\n this.log('Initialized. Project:', this.dsn.projectId);\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n const event = this.buildExceptionPayload(error, extra);\n void this.send(event);\n return event.event_id;\n }\n\n captureMessage(message: string, level: string = 'info', extra?: Record<string, unknown>): string {\n const event = this.buildMessagePayload(message, level, extra);\n void this.send(event);\n return event.event_id;\n }\n\n setUser(user: UserContext): void {\n this.user = { ...user };\n }\n\n clearUser(): void {\n this.user = {};\n }\n\n setTag(key: string, value: string): void {\n this.tags[key] = value;\n }\n\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n this.crumbs.add(crumb);\n }\n\n /** Tear down all global listeners. Call when unmounting in SPAs. */\n destroy(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups.length = 0;\n }\n\n // ─── Internal: build payloads ────────────────────────────────────────────\n\n private buildExceptionPayload(\n error: unknown,\n extra?: Record<string, unknown>,\n ): EventPayload {\n const err = error instanceof Error ? error : new Error(String(error));\n const frames = parseStack(err);\n\n const exceptionValue: ExceptionValue = {\n type: err.name || 'Error',\n value: err.message,\n stacktrace: frames.length > 0 ? { frames } : undefined,\n };\n\n return this.buildBase({\n level: 'error',\n exception: { values: [exceptionValue] },\n extra,\n });\n }\n\n private buildMessagePayload(\n message: string,\n level: string,\n extra?: Record<string, unknown>,\n ): EventPayload {\n return this.buildBase({ level, message, extra });\n }\n\n private buildBase(\n overrides: Partial<EventPayload> & { extra?: Record<string, unknown> },\n ): EventPayload {\n const { extra, ...rest } = overrides;\n const payload: EventPayload = {\n event_id: uuid(),\n timestamp: new Date().toISOString(),\n platform: 'javascript',\n ...rest,\n };\n\n if (this.opts.release) payload.release = this.opts.release;\n if (this.opts.environment) payload.environment = this.opts.environment;\n\n if (Object.keys(this.user).length > 0) {\n payload.user = { ...this.user };\n }\n\n if (Object.keys(this.tags).length > 0) {\n payload.tags = { ...this.tags };\n }\n\n if (extra && Object.keys(extra).length > 0) {\n payload.extra = extra;\n }\n\n const breadcrumbs = this.crumbs.getAll();\n if (breadcrumbs.length > 0) {\n payload.breadcrumbs = breadcrumbs;\n }\n\n // Capture browser request context\n if (typeof window !== 'undefined') {\n payload.request = {\n url: window.location.href,\n headers: {\n 'user-agent': navigator.userAgent,\n },\n };\n }\n\n return payload;\n }\n\n // ─── Internal: error handlers ────────────────────────────────────────────\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') {\n // Node.js environment\n const onUncaught = (err: Error) => {\n this.captureException(err, { handler: 'uncaughtException' });\n };\n const onUnhandled = (reason: unknown) => {\n this.captureException(reason, { handler: 'unhandledRejection' });\n };\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onUnhandled);\n this.cleanups.push(() => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onUnhandled);\n });\n return;\n }\n\n // Browser environment\n const onError = (event: ErrorEvent) => {\n if (!event.error) return;\n if (this.shouldIgnore(event.error, event.filename ?? '')) return;\n this.captureException(event.error, { handler: 'window.onerror' });\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason as unknown;\n if (this.shouldIgnore(reason, '')) return;\n this.captureException(reason, { handler: 'unhandledrejection' });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n this.cleanups.push(() => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n });\n }\n\n private shouldIgnore(error: unknown, scriptUrl: string): boolean {\n const { ignoreUrls, ignoreErrors } = this.opts;\n\n if (ignoreUrls?.length && scriptUrl) {\n if (matchesPattern(scriptUrl, ignoreUrls)) return true;\n }\n\n if (ignoreErrors?.length) {\n const message = error instanceof Error ? error.message : String(error);\n if (matchesPattern(message, ignoreErrors)) return true;\n }\n\n return false;\n }\n\n // ─── Internal: transport ─────────────────────────────────────────────────\n\n private async send(event: EventPayload): Promise<void> {\n let finalEvent: EventPayload | false = event;\n\n if (this.opts.beforeSend) {\n finalEvent = this.opts.beforeSend(event);\n if (finalEvent === false) {\n this.log('Event dropped by beforeSend hook');\n return;\n }\n }\n\n this.log('Sending event:', finalEvent.event_id, finalEvent.level);\n\n let body: string;\n try {\n body = JSON.stringify(finalEvent);\n } catch (err) {\n console.warn('[BugCatch] Failed to serialize event:', err);\n return;\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n };\n\n // keepalive is browser-only; Node.js fetch (undici) enforces a 64 KB body\n // limit with keepalive: true, which silently drops large payloads.\n if (typeof window !== 'undefined') {\n fetchOptions.keepalive = true;\n }\n\n const res = await fetch(this.dsn.ingestUrl, fetchOptions);\n\n if (!res.ok) {\n console.warn(`[BugCatch] Ingest responded with ${res.status}:`, await res.text());\n }\n } catch (err) {\n console.warn('[BugCatch] Failed to send event:', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.opts.debug) {\n console.debug('[BugCatch]', ...args);\n }\n }\n}\n","import { BugCatchClient } from './client.js';\nimport type { BugCatchOptions, UserContext, BreadcrumbEntry } from './types.js';\n\nexport type { BugCatchOptions, UserContext, BreadcrumbEntry };\nexport type { EventPayload, StackFrame, ParsedDsn } from './types.js';\nexport { BugCatchClient };\n\n// ─── Singleton instance ───────────────────────────────────────────────────────\n\nlet _client: BugCatchClient | null = null;\n\nfunction getClient(): BugCatchClient {\n if (!_client) {\n throw new Error('[BugCatch] SDK not initialized. Call BugCatch.init(options) first.');\n }\n return _client;\n}\n\n// ─── Public singleton API ─────────────────────────────────────────────────────\n\nconst BugCatch = {\n /**\n * Initialize the SDK. Call this once, as early as possible in your app.\n *\n * @example\n * BugCatch.init({\n * dsn: 'http://localhost:3000/ingest/project-id?key=sdk-key',\n * release: '1.0.0',\n * environment: 'production',\n * });\n */\n init(options: BugCatchOptions): BugCatchClient {\n if (_client) {\n console.warn('[BugCatch] init() called more than once. Ignoring.');\n return _client;\n }\n _client = new BugCatchClient(options);\n return _client;\n },\n\n /**\n * Capture an Error object or any value as an error event.\n * Returns the generated event_id.\n */\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n return getClient().captureException(error, extra);\n },\n\n /**\n * Capture a plain text message as an event.\n * Returns the generated event_id.\n */\n captureMessage(message: string, level?: string, extra?: Record<string, unknown>): string {\n return getClient().captureMessage(message, level, extra);\n },\n\n /**\n * Set the current user context. Attached to all subsequent events.\n */\n setUser(user: UserContext): void {\n getClient().setUser(user);\n },\n\n /**\n * Clear the current user context (e.g. on logout).\n */\n clearUser(): void {\n getClient().clearUser();\n },\n\n /**\n * Set a tag that will be attached to all subsequent events.\n */\n setTag(key: string, value: string): void {\n getClient().setTag(key, value);\n },\n\n /**\n * Manually add a breadcrumb.\n */\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n getClient().addBreadcrumb(crumb);\n },\n\n /**\n * Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.\n */\n destroy(): void {\n _client?.destroy();\n _client = null;\n },\n};\n\n// Named export for CJS consumers: const { BugCatch } = require('bugcatch-sdk')\nexport { BugCatch };\n\n// Default export for ESM consumers: import BugCatch from 'bugcatch-sdk'\nexport default BugCatch;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/parse-stack.ts","../src/breadcrumbs.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.js","sourcesContent":["import type { StackFrame } from './types.js';\n\n// Chrome/V8: \" at functionName (filename:line:col)\"\n// \" at filename:line:col\"\nconst CHROME_RE = /^\\s*at (?:(.*?) \\()?(.+?):(\\d+):(\\d+)\\)?$/;\n\n// Firefox/Safari: \"functionName@filename:line:col\"\n// \"@filename:line:col\"\nconst FIREFOX_RE = /^(?:(.+?)@)?(.+?):(\\d+):(\\d+)$/;\n\n// Origins that are not \"in-app\" frames\nconst INTERNAL_PATTERNS = [/node_modules\\//, /bugcatch[-_]?sdk/, /^\\(native\\)$/, /^native code/];\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n return !INTERNAL_PATTERNS.some((p) => p.test(filename));\n}\n\nfunction parseChromeLine(line: string): StackFrame | null {\n const m = CHROME_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nfunction parseFirefoxLine(line: string): StackFrame | null {\n const m = FIREFOX_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nexport function parseStack(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('Error') || trimmed.startsWith(error.message ?? '')) {\n continue;\n }\n const frame = parseChromeLine(trimmed) ?? parseFirefoxLine(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n // The API fingerprinting uses the LAST in-app frame, which maps to innermost\n // call. Return in innermost-first order (as captured).\n return frames;\n}\n","import type { BreadcrumbEntry } from './types.js';\n\nexport class BreadcrumbBuffer {\n private readonly buffer: BreadcrumbEntry[] = [];\n private readonly max: number;\n\n constructor(max = 100) {\n this.max = max;\n }\n\n add(crumb: BreadcrumbEntry): void {\n if (this.buffer.length >= this.max) {\n this.buffer.shift();\n }\n this.buffer.push(crumb);\n }\n\n getAll(): BreadcrumbEntry[] {\n return [...this.buffer];\n }\n\n clear(): void {\n this.buffer.length = 0;\n }\n}\n\n// ─── Auto-capture helpers ─────────────────────────────────────────────────────\n\ntype AddFn = (crumb: BreadcrumbEntry) => void;\n\n/**\n * Patch History API (pushState / replaceState / popstate) to capture\n * navigation breadcrumbs.\n */\nexport function installNavigationBreadcrumbs(add: AddFn): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n const originalPush = history.pushState.bind(history);\n const originalReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalPush(...args);\n };\n\n history.replaceState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Replaced state: ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalReplace(...args);\n };\n\n const onPopState = () => {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated back/forward to ${window.location.href}`,\n data: { to: window.location.href },\n });\n };\n\n window.addEventListener('popstate', onPopState);\n\n return () => {\n history.pushState = originalPush;\n history.replaceState = originalReplace;\n window.removeEventListener('popstate', onPopState);\n };\n}\n\n/**\n * Capture click events as breadcrumbs (element tag + text).\n */\nexport function installClickBreadcrumbs(add: AddFn): () => void {\n if (typeof document === 'undefined') return () => undefined;\n\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const tag = target.tagName?.toLowerCase() ?? 'unknown';\n const text = (target.textContent ?? '').trim().slice(0, 50);\n const id = target.id ? `#${target.id}` : '';\n const cls = target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').join('.')}`\n : '';\n add({\n timestamp: new Date().toISOString(),\n type: 'user',\n category: 'ui.click',\n message: `Click on <${tag}${id}${cls}>`,\n data: { tag, text: text || undefined },\n });\n };\n\n document.addEventListener('click', handler, { capture: true, passive: true });\n\n return () => {\n document.removeEventListener('click', handler, { capture: true });\n };\n}\n\n/**\n * Capture console.warn and console.error calls as breadcrumbs.\n */\nexport function installConsoleBreadcrumbs(add: AddFn): () => void {\n if (typeof console === 'undefined') return () => undefined;\n\n const originalWarn = console.warn.bind(console);\n const originalError = console.error.bind(console);\n\n const formatArgs = (args: unknown[]): string =>\n args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ').slice(0, 200);\n\n console.warn = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'warning' },\n });\n originalWarn(...args);\n };\n\n console.error = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'error' },\n });\n originalError(...args);\n };\n\n return () => {\n console.warn = originalWarn;\n console.error = originalError;\n };\n}\n","import type {\n BugCatchOptions,\n UserContext,\n BreadcrumbEntry,\n EventPayload,\n MetricPayload,\n ParsedDsn,\n ExceptionValue,\n} from './types.js';\nimport { parseStack } from './parse-stack.js';\nimport {\n BreadcrumbBuffer,\n installNavigationBreadcrumbs,\n installClickBreadcrumbs,\n installConsoleBreadcrumbs,\n} from './breadcrumbs.js';\n\n// ─── UUID ─────────────────────────────────────────────────────────────────────\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ─── DSN parser ───────────────────────────────────────────────────────────────\n\nfunction parseDsn(dsn: string): ParsedDsn & { metricsUrl: string } {\n let url: URL;\n try {\n url = new URL(dsn);\n } catch {\n throw new Error(`[BugCatch] Invalid DSN: \"${dsn}\"`);\n }\n\n const sdkKey = url.searchParams.get('key');\n if (!sdkKey) {\n throw new Error(`[BugCatch] DSN is missing the \"key\" query parameter: \"${dsn}\"`);\n }\n\n // Extract projectId from the last path segment (/ingest/{projectId})\n const segments = url.pathname.split('/').filter(Boolean);\n const projectId = segments[segments.length - 1];\n if (!projectId) {\n throw new Error(`[BugCatch] Could not extract projectId from DSN path: \"${dsn}\"`);\n }\n\n // Reconstruct the URL without extra query params\n const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;\n const metricsUrl = `${url.origin}${url.pathname}/metrics?key=${sdkKey}`;\n\n return { ingestUrl, metricsUrl, projectId, sdkKey };\n}\n\n// ─── Route normalizer ─────────────────────────────────────────────────────────\n\n/**\n * Strips the origin and query string from a URL and replaces dynamic path\n * segments (UUIDs, numeric IDs) with `:id` so metrics group by route template.\n *\n * e.g. https://api.example.com/users/42/orders/abc-123?page=1 → /users/:id/orders/:id\n */\nfunction normalizeUrl(rawUrl: string): string {\n let pathname: string;\n try {\n pathname = new URL(rawUrl).pathname;\n } catch {\n // rawUrl is already a path (e.g. \"/api/users/1\")\n pathname = rawUrl.split('?')[0];\n }\n return pathname\n .replace(/\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/:id')\n .replace(/\\/\\d{1,20}(?=\\/|$)/g, '/:id');\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────────\n\nfunction matchesPattern(value: string, patterns: Array<string | RegExp>): boolean {\n return patterns.some((p) =>\n typeof p === 'string' ? value.includes(p) : p.test(value),\n );\n}\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\nexport class BugCatchClient {\n private readonly opts: Required<\n Pick<BugCatchOptions, 'debug' | 'maxBreadcrumbs' | 'autoCaptureErrors' | 'autoCaptureBreadcrumbs' | 'autoTrackRequests'>\n > & BugCatchOptions;\n\n private readonly dsn: ParsedDsn & { metricsUrl: string };\n private readonly crumbs: BreadcrumbBuffer;\n private user: UserContext = {};\n private tags: Record<string, string> = {};\n private readonly cleanups: Array<() => void> = [];\n\n constructor(options: BugCatchOptions) {\n this.opts = {\n debug: false,\n maxBreadcrumbs: 100,\n autoCaptureErrors: true,\n autoCaptureBreadcrumbs: true,\n autoTrackRequests: false,\n ...options,\n };\n\n this.dsn = parseDsn(options.dsn);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n\n if (this.opts.autoCaptureErrors) {\n this.installErrorHandlers();\n }\n\n if (this.opts.autoCaptureBreadcrumbs) {\n this.cleanups.push(installNavigationBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));\n }\n\n if (this.opts.autoTrackRequests) {\n this.cleanups.push(this.installFetchInterceptor());\n }\n\n this.log('Initialized. Project:', this.dsn.projectId);\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n const event = this.buildExceptionPayload(error, extra);\n void this.send(event);\n return event.event_id;\n }\n\n captureMessage(message: string, level: string = 'info', extra?: Record<string, unknown>): string {\n const event = this.buildMessagePayload(message, level, extra);\n void this.send(event);\n return event.event_id;\n }\n\n setUser(user: UserContext): void {\n this.user = {\n ...user,\n id: user.id != null ? String(user.id) : undefined,\n };\n }\n\n clearUser(): void {\n this.user = {};\n }\n\n setTag(key: string, value: string): void {\n this.tags[key] = value;\n }\n\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n this.crumbs.add(crumb);\n }\n\n /** Tear down all global listeners. Call when unmounting in SPAs. */\n destroy(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups.length = 0;\n }\n\n /**\n * Manually report an API call timing. Use this when `autoTrackRequests`\n * is off or when you want to track server-side (Node.js) requests explicitly.\n */\n trackRequest(method: string, route: string, durationMs: number, statusCode: number): void {\n void this.sendMetric({ method: method.toUpperCase(), route, duration_ms: durationMs, status_code: statusCode });\n }\n\n // ─── Internal: build payloads ────────────────────────────────────────────\n\n private buildExceptionPayload(\n error: unknown,\n extra?: Record<string, unknown>,\n ): EventPayload {\n const err = error instanceof Error ? error : new Error(String(error));\n const frames = parseStack(err);\n\n const exceptionValue: ExceptionValue = {\n type: err.name || 'Error',\n value: err.message,\n stacktrace: frames.length > 0 ? { frames } : undefined,\n };\n\n return this.buildBase({\n level: 'error',\n exception: { values: [exceptionValue] },\n extra,\n });\n }\n\n private buildMessagePayload(\n message: string,\n level: string,\n extra?: Record<string, unknown>,\n ): EventPayload {\n return this.buildBase({ level, message, extra });\n }\n\n private buildBase(\n overrides: Partial<EventPayload> & { extra?: Record<string, unknown> },\n ): EventPayload {\n const { extra, ...rest } = overrides;\n const payload: EventPayload = {\n event_id: uuid(),\n timestamp: new Date().toISOString(),\n platform: 'javascript',\n ...rest,\n };\n\n if (this.opts.release) payload.release = this.opts.release;\n if (this.opts.environment) payload.environment = this.opts.environment;\n\n if (Object.keys(this.user).length > 0) {\n payload.user = { ...this.user };\n }\n\n if (Object.keys(this.tags).length > 0) {\n payload.tags = { ...this.tags };\n }\n\n if (extra && Object.keys(extra).length > 0) {\n payload.extra = extra;\n }\n\n const breadcrumbs = this.crumbs.getAll();\n if (breadcrumbs.length > 0) {\n payload.breadcrumbs = breadcrumbs;\n }\n\n // Capture browser request context\n if (typeof window !== 'undefined') {\n payload.request = {\n url: window.location.href,\n headers: {\n 'user-agent': navigator.userAgent,\n },\n };\n }\n\n return payload;\n }\n\n // ─── Internal: error handlers ────────────────────────────────────────────\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') {\n // Node.js environment\n const onUncaught = (err: Error) => {\n this.captureException(err, { handler: 'uncaughtException' });\n };\n const onUnhandled = (reason: unknown) => {\n this.captureException(reason, { handler: 'unhandledRejection' });\n };\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onUnhandled);\n this.cleanups.push(() => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onUnhandled);\n });\n return;\n }\n\n // Browser environment\n const onError = (event: ErrorEvent) => {\n if (!event.error) return;\n if (this.shouldIgnore(event.error, event.filename ?? '')) return;\n this.captureException(event.error, { handler: 'window.onerror' });\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason as unknown;\n if (this.shouldIgnore(reason, '')) return;\n this.captureException(reason, { handler: 'unhandledrejection' });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n this.cleanups.push(() => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n });\n }\n\n private shouldIgnore(error: unknown, scriptUrl: string): boolean {\n const { ignoreUrls, ignoreErrors } = this.opts;\n\n if (ignoreUrls?.length && scriptUrl) {\n if (matchesPattern(scriptUrl, ignoreUrls)) return true;\n }\n\n if (ignoreErrors?.length) {\n const message = error instanceof Error ? error.message : String(error);\n if (matchesPattern(message, ignoreErrors)) return true;\n }\n\n return false;\n }\n\n // ─── Internal: request tracking ──────────────────────────────────────────\n\n private installFetchInterceptor(): () => void {\n const original = globalThis.fetch.bind(globalThis);\n const self = this;\n\n globalThis.fetch = async function patchedFetch(\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n const url = input instanceof Request ? input.url : String(input);\n\n // Never intercept BugCatch's own ingest/metrics requests\n if (url.includes(self.dsn.ingestUrl.split('?')[0])) {\n return original(input, init);\n }\n\n if (self.opts.trackIgnoreUrls && matchesPattern(url, self.opts.trackIgnoreUrls)) {\n return original(input, init);\n }\n\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase();\n const route = normalizeUrl(url);\n const start = Date.now();\n\n try {\n const response = await original(input, init);\n void self.sendMetric({\n method,\n route,\n duration_ms: Date.now() - start,\n status_code: response.status,\n user_id: self.user.id,\n });\n return response;\n } catch (err) {\n // Network error — report as status 0\n void self.sendMetric({ method, route, duration_ms: Date.now() - start, status_code: 0 });\n throw err;\n }\n };\n\n // Return cleanup function that restores original fetch\n return () => {\n globalThis.fetch = original;\n };\n }\n\n private async sendMetric(metric: MetricPayload): Promise<void> {\n try {\n await fetch(this.dsn.metricsUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(metric),\n });\n } catch {\n // Silently ignore — metric loss is acceptable\n }\n }\n\n // ─── Internal: transport ─────────────────────────────────────────────────\n\n private async send(event: EventPayload): Promise<void> {\n let finalEvent: EventPayload | false = event;\n\n if (this.opts.beforeSend) {\n finalEvent = this.opts.beforeSend(event);\n if (finalEvent === false) {\n this.log('Event dropped by beforeSend hook');\n return;\n }\n }\n\n this.log('Sending event:', finalEvent.event_id, finalEvent.level);\n\n let body: string;\n try {\n body = JSON.stringify(finalEvent);\n } catch (err) {\n console.warn('[BugCatch] Failed to serialize event:', err);\n return;\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n };\n\n // keepalive is browser-only; Node.js fetch (undici) enforces a 64 KB body\n // limit with keepalive: true, which silently drops large payloads.\n if (typeof window !== 'undefined') {\n fetchOptions.keepalive = true;\n }\n\n const res = await fetch(this.dsn.ingestUrl, fetchOptions);\n\n if (!res.ok) {\n console.warn(`[BugCatch] Ingest responded with ${res.status}:`, await res.text());\n }\n } catch (err) {\n console.warn('[BugCatch] Failed to send event:', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.opts.debug) {\n console.debug('[BugCatch]', ...args);\n }\n }\n}\n","import { BugCatchClient } from './client.js';\nimport type { BugCatchOptions, UserContext, BreadcrumbEntry } from './types.js';\n\nexport type { BugCatchOptions, UserContext, BreadcrumbEntry };\nexport type { EventPayload, StackFrame, ParsedDsn } from './types.js';\nexport { BugCatchClient };\n\n// ─── Singleton instance ───────────────────────────────────────────────────────\n\nlet _client: BugCatchClient | null = null;\n\nfunction getClient(): BugCatchClient {\n if (!_client) {\n throw new Error('[BugCatch] SDK not initialized. Call BugCatch.init(options) first.');\n }\n return _client;\n}\n\n// ─── Public singleton API ─────────────────────────────────────────────────────\n\nconst BugCatch = {\n /**\n * Initialize the SDK. Call this once, as early as possible in your app.\n *\n * @example\n * BugCatch.init({\n * dsn: 'http://localhost:3000/ingest/project-id?key=sdk-key',\n * release: '1.0.0',\n * environment: 'production',\n * });\n */\n init(options: BugCatchOptions): BugCatchClient {\n if (_client) {\n console.warn('[BugCatch] init() called more than once. Ignoring.');\n return _client;\n }\n _client = new BugCatchClient(options);\n return _client;\n },\n\n /**\n * Capture an Error object or any value as an error event.\n * Returns the generated event_id.\n */\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n return getClient().captureException(error, extra);\n },\n\n /**\n * Capture a plain text message as an event.\n * Returns the generated event_id.\n */\n captureMessage(message: string, level?: string, extra?: Record<string, unknown>): string {\n return getClient().captureMessage(message, level, extra);\n },\n\n /**\n * Set the current user context. Attached to all subsequent events.\n */\n setUser(user: UserContext): void {\n getClient().setUser(user);\n },\n\n /**\n * Clear the current user context (e.g. on logout).\n */\n clearUser(): void {\n getClient().clearUser();\n },\n\n /**\n * Set a tag that will be attached to all subsequent events.\n */\n setTag(key: string, value: string): void {\n getClient().setTag(key, value);\n },\n\n /**\n * Manually add a breadcrumb.\n */\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n getClient().addBreadcrumb(crumb);\n },\n\n /**\n * Manually report an API call timing to BugCatch.\n * Use when `autoTrackRequests` is off or for server-side tracking.\n *\n * @example\n * const start = Date.now();\n * await fetch('/api/orders');\n * BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);\n */\n trackRequest(method: string, route: string, durationMs: number, statusCode: number): void {\n getClient().trackRequest(method, route, durationMs, statusCode);\n },\n\n /**\n * Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.\n */\n destroy(): void {\n _client?.destroy();\n _client = null;\n },\n};\n\n// Named export for CJS consumers: const { BugCatch } = require('bugcatch-sdk')\nexport { BugCatch };\n\n// Default export for ESM consumers: import BugCatch from 'bugcatch-sdk'\nexport default BugCatch;\n"]}
|
package/dist/index.mjs
CHANGED
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
var __defProp = Object.defineProperty;
|
|
2
|
+
var __defProps = Object.defineProperties;
|
|
3
|
+
var __getOwnPropDescs = Object.getOwnPropertyDescriptors;
|
|
2
4
|
var __getOwnPropSymbols = Object.getOwnPropertySymbols;
|
|
3
5
|
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
4
6
|
var __propIsEnum = Object.prototype.propertyIsEnumerable;
|
|
@@ -14,6 +16,7 @@ var __spreadValues = (a, b) => {
|
|
|
14
16
|
}
|
|
15
17
|
return a;
|
|
16
18
|
};
|
|
19
|
+
var __spreadProps = (a, b) => __defProps(a, __getOwnPropDescs(b));
|
|
17
20
|
var __objRest = (source, exclude) => {
|
|
18
21
|
var target = {};
|
|
19
22
|
for (var prop in source)
|
|
@@ -221,7 +224,17 @@ function parseDsn(dsn) {
|
|
|
221
224
|
throw new Error(`[BugCatch] Could not extract projectId from DSN path: "${dsn}"`);
|
|
222
225
|
}
|
|
223
226
|
const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;
|
|
224
|
-
|
|
227
|
+
const metricsUrl = `${url.origin}${url.pathname}/metrics?key=${sdkKey}`;
|
|
228
|
+
return { ingestUrl, metricsUrl, projectId, sdkKey };
|
|
229
|
+
}
|
|
230
|
+
function normalizeUrl(rawUrl) {
|
|
231
|
+
let pathname;
|
|
232
|
+
try {
|
|
233
|
+
pathname = new URL(rawUrl).pathname;
|
|
234
|
+
} catch (e) {
|
|
235
|
+
pathname = rawUrl.split("?")[0];
|
|
236
|
+
}
|
|
237
|
+
return pathname.replace(/\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, "/:id").replace(/\/\d{1,20}(?=\/|$)/g, "/:id");
|
|
225
238
|
}
|
|
226
239
|
function matchesPattern(value, patterns) {
|
|
227
240
|
return patterns.some(
|
|
@@ -237,7 +250,8 @@ var BugCatchClient = class {
|
|
|
237
250
|
debug: false,
|
|
238
251
|
maxBreadcrumbs: 100,
|
|
239
252
|
autoCaptureErrors: true,
|
|
240
|
-
autoCaptureBreadcrumbs: true
|
|
253
|
+
autoCaptureBreadcrumbs: true,
|
|
254
|
+
autoTrackRequests: false
|
|
241
255
|
}, options);
|
|
242
256
|
this.dsn = parseDsn(options.dsn);
|
|
243
257
|
this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);
|
|
@@ -249,6 +263,9 @@ var BugCatchClient = class {
|
|
|
249
263
|
this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));
|
|
250
264
|
this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));
|
|
251
265
|
}
|
|
266
|
+
if (this.opts.autoTrackRequests) {
|
|
267
|
+
this.cleanups.push(this.installFetchInterceptor());
|
|
268
|
+
}
|
|
252
269
|
this.log("Initialized. Project:", this.dsn.projectId);
|
|
253
270
|
}
|
|
254
271
|
// ─── Public API ─────────────────────────────────────────────────────────────
|
|
@@ -263,7 +280,9 @@ var BugCatchClient = class {
|
|
|
263
280
|
return event.event_id;
|
|
264
281
|
}
|
|
265
282
|
setUser(user) {
|
|
266
|
-
this.user = __spreadValues({}, user)
|
|
283
|
+
this.user = __spreadProps(__spreadValues({}, user), {
|
|
284
|
+
id: user.id != null ? String(user.id) : void 0
|
|
285
|
+
});
|
|
267
286
|
}
|
|
268
287
|
clearUser() {
|
|
269
288
|
this.user = {};
|
|
@@ -281,6 +300,13 @@ var BugCatchClient = class {
|
|
|
281
300
|
}
|
|
282
301
|
this.cleanups.length = 0;
|
|
283
302
|
}
|
|
303
|
+
/**
|
|
304
|
+
* Manually report an API call timing. Use this when `autoTrackRequests`
|
|
305
|
+
* is off or when you want to track server-side (Node.js) requests explicitly.
|
|
306
|
+
*/
|
|
307
|
+
trackRequest(method, route, durationMs, statusCode) {
|
|
308
|
+
void this.sendMetric({ method: method.toUpperCase(), route, duration_ms: durationMs, status_code: statusCode });
|
|
309
|
+
}
|
|
284
310
|
// ─── Internal: build payloads ────────────────────────────────────────────
|
|
285
311
|
buildExceptionPayload(error, extra) {
|
|
286
312
|
const err = error instanceof Error ? error : new Error(String(error));
|
|
@@ -377,6 +403,51 @@ var BugCatchClient = class {
|
|
|
377
403
|
}
|
|
378
404
|
return false;
|
|
379
405
|
}
|
|
406
|
+
// ─── Internal: request tracking ──────────────────────────────────────────
|
|
407
|
+
installFetchInterceptor() {
|
|
408
|
+
const original = globalThis.fetch.bind(globalThis);
|
|
409
|
+
const self = this;
|
|
410
|
+
globalThis.fetch = async function patchedFetch(input, init) {
|
|
411
|
+
var _a;
|
|
412
|
+
const url = input instanceof Request ? input.url : String(input);
|
|
413
|
+
if (url.includes(self.dsn.ingestUrl.split("?")[0])) {
|
|
414
|
+
return original(input, init);
|
|
415
|
+
}
|
|
416
|
+
if (self.opts.trackIgnoreUrls && matchesPattern(url, self.opts.trackIgnoreUrls)) {
|
|
417
|
+
return original(input, init);
|
|
418
|
+
}
|
|
419
|
+
const method = ((_a = init == null ? void 0 : init.method) != null ? _a : input instanceof Request ? input.method : "GET").toUpperCase();
|
|
420
|
+
const route = normalizeUrl(url);
|
|
421
|
+
const start = Date.now();
|
|
422
|
+
try {
|
|
423
|
+
const response = await original(input, init);
|
|
424
|
+
void self.sendMetric({
|
|
425
|
+
method,
|
|
426
|
+
route,
|
|
427
|
+
duration_ms: Date.now() - start,
|
|
428
|
+
status_code: response.status,
|
|
429
|
+
user_id: self.user.id
|
|
430
|
+
});
|
|
431
|
+
return response;
|
|
432
|
+
} catch (err) {
|
|
433
|
+
void self.sendMetric({ method, route, duration_ms: Date.now() - start, status_code: 0 });
|
|
434
|
+
throw err;
|
|
435
|
+
}
|
|
436
|
+
};
|
|
437
|
+
return () => {
|
|
438
|
+
globalThis.fetch = original;
|
|
439
|
+
};
|
|
440
|
+
}
|
|
441
|
+
async sendMetric(metric) {
|
|
442
|
+
try {
|
|
443
|
+
await fetch(this.dsn.metricsUrl, {
|
|
444
|
+
method: "POST",
|
|
445
|
+
headers: { "Content-Type": "application/json" },
|
|
446
|
+
body: JSON.stringify(metric)
|
|
447
|
+
});
|
|
448
|
+
} catch (e) {
|
|
449
|
+
}
|
|
450
|
+
}
|
|
380
451
|
// ─── Internal: transport ─────────────────────────────────────────────────
|
|
381
452
|
async send(event) {
|
|
382
453
|
let finalEvent = event;
|
|
@@ -484,6 +555,18 @@ var BugCatch = {
|
|
|
484
555
|
addBreadcrumb(crumb) {
|
|
485
556
|
getClient().addBreadcrumb(crumb);
|
|
486
557
|
},
|
|
558
|
+
/**
|
|
559
|
+
* Manually report an API call timing to BugCatch.
|
|
560
|
+
* Use when `autoTrackRequests` is off or for server-side tracking.
|
|
561
|
+
*
|
|
562
|
+
* @example
|
|
563
|
+
* const start = Date.now();
|
|
564
|
+
* await fetch('/api/orders');
|
|
565
|
+
* BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);
|
|
566
|
+
*/
|
|
567
|
+
trackRequest(method, route, durationMs, statusCode) {
|
|
568
|
+
getClient().trackRequest(method, route, durationMs, statusCode);
|
|
569
|
+
},
|
|
487
570
|
/**
|
|
488
571
|
* Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.
|
|
489
572
|
*/
|
package/dist/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/parse-stack.ts","../src/breadcrumbs.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { StackFrame } from './types.js';\n\n// Chrome/V8: \" at functionName (filename:line:col)\"\n// \" at filename:line:col\"\nconst CHROME_RE = /^\\s*at (?:(.*?) \\()?(.+?):(\\d+):(\\d+)\\)?$/;\n\n// Firefox/Safari: \"functionName@filename:line:col\"\n// \"@filename:line:col\"\nconst FIREFOX_RE = /^(?:(.+?)@)?(.+?):(\\d+):(\\d+)$/;\n\n// Origins that are not \"in-app\" frames\nconst INTERNAL_PATTERNS = [/node_modules\\//, /bugcatch[-_]?sdk/, /^\\(native\\)$/, /^native code/];\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n return !INTERNAL_PATTERNS.some((p) => p.test(filename));\n}\n\nfunction parseChromeLine(line: string): StackFrame | null {\n const m = CHROME_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nfunction parseFirefoxLine(line: string): StackFrame | null {\n const m = FIREFOX_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nexport function parseStack(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('Error') || trimmed.startsWith(error.message ?? '')) {\n continue;\n }\n const frame = parseChromeLine(trimmed) ?? parseFirefoxLine(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n // The API fingerprinting uses the LAST in-app frame, which maps to innermost\n // call. Return in innermost-first order (as captured).\n return frames;\n}\n","import type { BreadcrumbEntry } from './types.js';\n\nexport class BreadcrumbBuffer {\n private readonly buffer: BreadcrumbEntry[] = [];\n private readonly max: number;\n\n constructor(max = 100) {\n this.max = max;\n }\n\n add(crumb: BreadcrumbEntry): void {\n if (this.buffer.length >= this.max) {\n this.buffer.shift();\n }\n this.buffer.push(crumb);\n }\n\n getAll(): BreadcrumbEntry[] {\n return [...this.buffer];\n }\n\n clear(): void {\n this.buffer.length = 0;\n }\n}\n\n// ─── Auto-capture helpers ─────────────────────────────────────────────────────\n\ntype AddFn = (crumb: BreadcrumbEntry) => void;\n\n/**\n * Patch History API (pushState / replaceState / popstate) to capture\n * navigation breadcrumbs.\n */\nexport function installNavigationBreadcrumbs(add: AddFn): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n const originalPush = history.pushState.bind(history);\n const originalReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalPush(...args);\n };\n\n history.replaceState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Replaced state: ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalReplace(...args);\n };\n\n const onPopState = () => {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated back/forward to ${window.location.href}`,\n data: { to: window.location.href },\n });\n };\n\n window.addEventListener('popstate', onPopState);\n\n return () => {\n history.pushState = originalPush;\n history.replaceState = originalReplace;\n window.removeEventListener('popstate', onPopState);\n };\n}\n\n/**\n * Capture click events as breadcrumbs (element tag + text).\n */\nexport function installClickBreadcrumbs(add: AddFn): () => void {\n if (typeof document === 'undefined') return () => undefined;\n\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const tag = target.tagName?.toLowerCase() ?? 'unknown';\n const text = (target.textContent ?? '').trim().slice(0, 50);\n const id = target.id ? `#${target.id}` : '';\n const cls = target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').join('.')}`\n : '';\n add({\n timestamp: new Date().toISOString(),\n type: 'user',\n category: 'ui.click',\n message: `Click on <${tag}${id}${cls}>`,\n data: { tag, text: text || undefined },\n });\n };\n\n document.addEventListener('click', handler, { capture: true, passive: true });\n\n return () => {\n document.removeEventListener('click', handler, { capture: true });\n };\n}\n\n/**\n * Capture console.warn and console.error calls as breadcrumbs.\n */\nexport function installConsoleBreadcrumbs(add: AddFn): () => void {\n if (typeof console === 'undefined') return () => undefined;\n\n const originalWarn = console.warn.bind(console);\n const originalError = console.error.bind(console);\n\n const formatArgs = (args: unknown[]): string =>\n args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ').slice(0, 200);\n\n console.warn = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'warning' },\n });\n originalWarn(...args);\n };\n\n console.error = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'error' },\n });\n originalError(...args);\n };\n\n return () => {\n console.warn = originalWarn;\n console.error = originalError;\n };\n}\n","import type {\n BugCatchOptions,\n UserContext,\n BreadcrumbEntry,\n EventPayload,\n ParsedDsn,\n ExceptionValue,\n} from './types.js';\nimport { parseStack } from './parse-stack.js';\nimport {\n BreadcrumbBuffer,\n installNavigationBreadcrumbs,\n installClickBreadcrumbs,\n installConsoleBreadcrumbs,\n} from './breadcrumbs.js';\n\n// ─── UUID ─────────────────────────────────────────────────────────────────────\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ─── DSN parser ───────────────────────────────────────────────────────────────\n\nfunction parseDsn(dsn: string): ParsedDsn {\n let url: URL;\n try {\n url = new URL(dsn);\n } catch {\n throw new Error(`[BugCatch] Invalid DSN: \"${dsn}\"`);\n }\n\n const sdkKey = url.searchParams.get('key');\n if (!sdkKey) {\n throw new Error(`[BugCatch] DSN is missing the \"key\" query parameter: \"${dsn}\"`);\n }\n\n // Extract projectId from the last path segment (/ingest/{projectId})\n const segments = url.pathname.split('/').filter(Boolean);\n const projectId = segments[segments.length - 1];\n if (!projectId) {\n throw new Error(`[BugCatch] Could not extract projectId from DSN path: \"${dsn}\"`);\n }\n\n // Reconstruct the URL without extra query params\n const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;\n\n return { ingestUrl, projectId, sdkKey };\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────────\n\nfunction matchesPattern(value: string, patterns: Array<string | RegExp>): boolean {\n return patterns.some((p) =>\n typeof p === 'string' ? value.includes(p) : p.test(value),\n );\n}\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\nexport class BugCatchClient {\n private readonly opts: Required<\n Pick<BugCatchOptions, 'debug' | 'maxBreadcrumbs' | 'autoCaptureErrors' | 'autoCaptureBreadcrumbs'>\n > & BugCatchOptions;\n\n private readonly dsn: ParsedDsn;\n private readonly crumbs: BreadcrumbBuffer;\n private user: UserContext = {};\n private tags: Record<string, string> = {};\n private readonly cleanups: Array<() => void> = [];\n\n constructor(options: BugCatchOptions) {\n this.opts = {\n debug: false,\n maxBreadcrumbs: 100,\n autoCaptureErrors: true,\n autoCaptureBreadcrumbs: true,\n ...options,\n };\n\n this.dsn = parseDsn(options.dsn);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n\n if (this.opts.autoCaptureErrors) {\n this.installErrorHandlers();\n }\n\n if (this.opts.autoCaptureBreadcrumbs) {\n this.cleanups.push(installNavigationBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));\n }\n\n this.log('Initialized. Project:', this.dsn.projectId);\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n const event = this.buildExceptionPayload(error, extra);\n void this.send(event);\n return event.event_id;\n }\n\n captureMessage(message: string, level: string = 'info', extra?: Record<string, unknown>): string {\n const event = this.buildMessagePayload(message, level, extra);\n void this.send(event);\n return event.event_id;\n }\n\n setUser(user: UserContext): void {\n this.user = { ...user };\n }\n\n clearUser(): void {\n this.user = {};\n }\n\n setTag(key: string, value: string): void {\n this.tags[key] = value;\n }\n\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n this.crumbs.add(crumb);\n }\n\n /** Tear down all global listeners. Call when unmounting in SPAs. */\n destroy(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups.length = 0;\n }\n\n // ─── Internal: build payloads ────────────────────────────────────────────\n\n private buildExceptionPayload(\n error: unknown,\n extra?: Record<string, unknown>,\n ): EventPayload {\n const err = error instanceof Error ? error : new Error(String(error));\n const frames = parseStack(err);\n\n const exceptionValue: ExceptionValue = {\n type: err.name || 'Error',\n value: err.message,\n stacktrace: frames.length > 0 ? { frames } : undefined,\n };\n\n return this.buildBase({\n level: 'error',\n exception: { values: [exceptionValue] },\n extra,\n });\n }\n\n private buildMessagePayload(\n message: string,\n level: string,\n extra?: Record<string, unknown>,\n ): EventPayload {\n return this.buildBase({ level, message, extra });\n }\n\n private buildBase(\n overrides: Partial<EventPayload> & { extra?: Record<string, unknown> },\n ): EventPayload {\n const { extra, ...rest } = overrides;\n const payload: EventPayload = {\n event_id: uuid(),\n timestamp: new Date().toISOString(),\n platform: 'javascript',\n ...rest,\n };\n\n if (this.opts.release) payload.release = this.opts.release;\n if (this.opts.environment) payload.environment = this.opts.environment;\n\n if (Object.keys(this.user).length > 0) {\n payload.user = { ...this.user };\n }\n\n if (Object.keys(this.tags).length > 0) {\n payload.tags = { ...this.tags };\n }\n\n if (extra && Object.keys(extra).length > 0) {\n payload.extra = extra;\n }\n\n const breadcrumbs = this.crumbs.getAll();\n if (breadcrumbs.length > 0) {\n payload.breadcrumbs = breadcrumbs;\n }\n\n // Capture browser request context\n if (typeof window !== 'undefined') {\n payload.request = {\n url: window.location.href,\n headers: {\n 'user-agent': navigator.userAgent,\n },\n };\n }\n\n return payload;\n }\n\n // ─── Internal: error handlers ────────────────────────────────────────────\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') {\n // Node.js environment\n const onUncaught = (err: Error) => {\n this.captureException(err, { handler: 'uncaughtException' });\n };\n const onUnhandled = (reason: unknown) => {\n this.captureException(reason, { handler: 'unhandledRejection' });\n };\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onUnhandled);\n this.cleanups.push(() => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onUnhandled);\n });\n return;\n }\n\n // Browser environment\n const onError = (event: ErrorEvent) => {\n if (!event.error) return;\n if (this.shouldIgnore(event.error, event.filename ?? '')) return;\n this.captureException(event.error, { handler: 'window.onerror' });\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason as unknown;\n if (this.shouldIgnore(reason, '')) return;\n this.captureException(reason, { handler: 'unhandledrejection' });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n this.cleanups.push(() => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n });\n }\n\n private shouldIgnore(error: unknown, scriptUrl: string): boolean {\n const { ignoreUrls, ignoreErrors } = this.opts;\n\n if (ignoreUrls?.length && scriptUrl) {\n if (matchesPattern(scriptUrl, ignoreUrls)) return true;\n }\n\n if (ignoreErrors?.length) {\n const message = error instanceof Error ? error.message : String(error);\n if (matchesPattern(message, ignoreErrors)) return true;\n }\n\n return false;\n }\n\n // ─── Internal: transport ─────────────────────────────────────────────────\n\n private async send(event: EventPayload): Promise<void> {\n let finalEvent: EventPayload | false = event;\n\n if (this.opts.beforeSend) {\n finalEvent = this.opts.beforeSend(event);\n if (finalEvent === false) {\n this.log('Event dropped by beforeSend hook');\n return;\n }\n }\n\n this.log('Sending event:', finalEvent.event_id, finalEvent.level);\n\n let body: string;\n try {\n body = JSON.stringify(finalEvent);\n } catch (err) {\n console.warn('[BugCatch] Failed to serialize event:', err);\n return;\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n };\n\n // keepalive is browser-only; Node.js fetch (undici) enforces a 64 KB body\n // limit with keepalive: true, which silently drops large payloads.\n if (typeof window !== 'undefined') {\n fetchOptions.keepalive = true;\n }\n\n const res = await fetch(this.dsn.ingestUrl, fetchOptions);\n\n if (!res.ok) {\n console.warn(`[BugCatch] Ingest responded with ${res.status}:`, await res.text());\n }\n } catch (err) {\n console.warn('[BugCatch] Failed to send event:', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.opts.debug) {\n console.debug('[BugCatch]', ...args);\n }\n }\n}\n","import { BugCatchClient } from './client.js';\nimport type { BugCatchOptions, UserContext, BreadcrumbEntry } from './types.js';\n\nexport type { BugCatchOptions, UserContext, BreadcrumbEntry };\nexport type { EventPayload, StackFrame, ParsedDsn } from './types.js';\nexport { BugCatchClient };\n\n// ─── Singleton instance ───────────────────────────────────────────────────────\n\nlet _client: BugCatchClient | null = null;\n\nfunction getClient(): BugCatchClient {\n if (!_client) {\n throw new Error('[BugCatch] SDK not initialized. Call BugCatch.init(options) first.');\n }\n return _client;\n}\n\n// ─── Public singleton API ─────────────────────────────────────────────────────\n\nconst BugCatch = {\n /**\n * Initialize the SDK. Call this once, as early as possible in your app.\n *\n * @example\n * BugCatch.init({\n * dsn: 'http://localhost:3000/ingest/project-id?key=sdk-key',\n * release: '1.0.0',\n * environment: 'production',\n * });\n */\n init(options: BugCatchOptions): BugCatchClient {\n if (_client) {\n console.warn('[BugCatch] init() called more than once. Ignoring.');\n return _client;\n }\n _client = new BugCatchClient(options);\n return _client;\n },\n\n /**\n * Capture an Error object or any value as an error event.\n * Returns the generated event_id.\n */\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n return getClient().captureException(error, extra);\n },\n\n /**\n * Capture a plain text message as an event.\n * Returns the generated event_id.\n */\n captureMessage(message: string, level?: string, extra?: Record<string, unknown>): string {\n return getClient().captureMessage(message, level, extra);\n },\n\n /**\n * Set the current user context. Attached to all subsequent events.\n */\n setUser(user: UserContext): void {\n getClient().setUser(user);\n },\n\n /**\n * Clear the current user context (e.g. on logout).\n */\n clearUser(): void {\n getClient().clearUser();\n },\n\n /**\n * Set a tag that will be attached to all subsequent events.\n */\n setTag(key: string, value: string): void {\n getClient().setTag(key, value);\n },\n\n /**\n * Manually add a breadcrumb.\n */\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n getClient().addBreadcrumb(crumb);\n },\n\n /**\n * Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.\n */\n destroy(): void {\n _client?.destroy();\n _client = null;\n },\n};\n\n// Named export for CJS consumers: const { BugCatch } = require('bugcatch-sdk')\nexport { BugCatch };\n\n// Default export for ESM consumers: import BugCatch from 'bugcatch-sdk'\nexport default BugCatch;\n"]}
|
|
1
|
+
{"version":3,"sources":["../src/parse-stack.ts","../src/breadcrumbs.ts","../src/client.ts","../src/index.ts"],"names":[],"mappings":"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","file":"index.mjs","sourcesContent":["import type { StackFrame } from './types.js';\n\n// Chrome/V8: \" at functionName (filename:line:col)\"\n// \" at filename:line:col\"\nconst CHROME_RE = /^\\s*at (?:(.*?) \\()?(.+?):(\\d+):(\\d+)\\)?$/;\n\n// Firefox/Safari: \"functionName@filename:line:col\"\n// \"@filename:line:col\"\nconst FIREFOX_RE = /^(?:(.+?)@)?(.+?):(\\d+):(\\d+)$/;\n\n// Origins that are not \"in-app\" frames\nconst INTERNAL_PATTERNS = [/node_modules\\//, /bugcatch[-_]?sdk/, /^\\(native\\)$/, /^native code/];\n\nfunction isInApp(filename: string | undefined): boolean {\n if (!filename) return false;\n return !INTERNAL_PATTERNS.some((p) => p.test(filename));\n}\n\nfunction parseChromeLine(line: string): StackFrame | null {\n const m = CHROME_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nfunction parseFirefoxLine(line: string): StackFrame | null {\n const m = FIREFOX_RE.exec(line);\n if (!m) return null;\n const [, fn, filename, lineno, colno] = m;\n return {\n function: fn ?? '<anonymous>',\n filename: filename ?? undefined,\n lineno: lineno ? parseInt(lineno, 10) : undefined,\n colno: colno ? parseInt(colno, 10) : undefined,\n in_app: isInApp(filename ?? undefined),\n };\n}\n\nexport function parseStack(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) return [];\n\n const lines = stack.split('\\n');\n const frames: StackFrame[] = [];\n\n for (const line of lines) {\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith('Error') || trimmed.startsWith(error.message ?? '')) {\n continue;\n }\n const frame = parseChromeLine(trimmed) ?? parseFirefoxLine(trimmed);\n if (frame) {\n frames.push(frame);\n }\n }\n\n // The API fingerprinting uses the LAST in-app frame, which maps to innermost\n // call. Return in innermost-first order (as captured).\n return frames;\n}\n","import type { BreadcrumbEntry } from './types.js';\n\nexport class BreadcrumbBuffer {\n private readonly buffer: BreadcrumbEntry[] = [];\n private readonly max: number;\n\n constructor(max = 100) {\n this.max = max;\n }\n\n add(crumb: BreadcrumbEntry): void {\n if (this.buffer.length >= this.max) {\n this.buffer.shift();\n }\n this.buffer.push(crumb);\n }\n\n getAll(): BreadcrumbEntry[] {\n return [...this.buffer];\n }\n\n clear(): void {\n this.buffer.length = 0;\n }\n}\n\n// ─── Auto-capture helpers ─────────────────────────────────────────────────────\n\ntype AddFn = (crumb: BreadcrumbEntry) => void;\n\n/**\n * Patch History API (pushState / replaceState / popstate) to capture\n * navigation breadcrumbs.\n */\nexport function installNavigationBreadcrumbs(add: AddFn): () => void {\n if (typeof window === 'undefined') return () => undefined;\n\n const originalPush = history.pushState.bind(history);\n const originalReplace = history.replaceState.bind(history);\n\n history.pushState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated to ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalPush(...args);\n };\n\n history.replaceState = function (...args) {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Replaced state: ${String(args[2] ?? '')}`,\n data: { to: String(args[2] ?? '') },\n });\n return originalReplace(...args);\n };\n\n const onPopState = () => {\n add({\n timestamp: new Date().toISOString(),\n type: 'navigation',\n category: 'navigation',\n message: `Navigated back/forward to ${window.location.href}`,\n data: { to: window.location.href },\n });\n };\n\n window.addEventListener('popstate', onPopState);\n\n return () => {\n history.pushState = originalPush;\n history.replaceState = originalReplace;\n window.removeEventListener('popstate', onPopState);\n };\n}\n\n/**\n * Capture click events as breadcrumbs (element tag + text).\n */\nexport function installClickBreadcrumbs(add: AddFn): () => void {\n if (typeof document === 'undefined') return () => undefined;\n\n const handler = (e: MouseEvent) => {\n const target = e.target as HTMLElement | null;\n if (!target) return;\n const tag = target.tagName?.toLowerCase() ?? 'unknown';\n const text = (target.textContent ?? '').trim().slice(0, 50);\n const id = target.id ? `#${target.id}` : '';\n const cls = target.className && typeof target.className === 'string'\n ? `.${target.className.split(' ').join('.')}`\n : '';\n add({\n timestamp: new Date().toISOString(),\n type: 'user',\n category: 'ui.click',\n message: `Click on <${tag}${id}${cls}>`,\n data: { tag, text: text || undefined },\n });\n };\n\n document.addEventListener('click', handler, { capture: true, passive: true });\n\n return () => {\n document.removeEventListener('click', handler, { capture: true });\n };\n}\n\n/**\n * Capture console.warn and console.error calls as breadcrumbs.\n */\nexport function installConsoleBreadcrumbs(add: AddFn): () => void {\n if (typeof console === 'undefined') return () => undefined;\n\n const originalWarn = console.warn.bind(console);\n const originalError = console.error.bind(console);\n\n const formatArgs = (args: unknown[]): string =>\n args.map((a) => (typeof a === 'string' ? a : JSON.stringify(a))).join(' ').slice(0, 200);\n\n console.warn = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'warning' },\n });\n originalWarn(...args);\n };\n\n console.error = (...args: unknown[]) => {\n add({\n timestamp: new Date().toISOString(),\n type: 'console',\n category: 'console',\n message: formatArgs(args),\n data: { level: 'error' },\n });\n originalError(...args);\n };\n\n return () => {\n console.warn = originalWarn;\n console.error = originalError;\n };\n}\n","import type {\n BugCatchOptions,\n UserContext,\n BreadcrumbEntry,\n EventPayload,\n MetricPayload,\n ParsedDsn,\n ExceptionValue,\n} from './types.js';\nimport { parseStack } from './parse-stack.js';\nimport {\n BreadcrumbBuffer,\n installNavigationBreadcrumbs,\n installClickBreadcrumbs,\n installConsoleBreadcrumbs,\n} from './breadcrumbs.js';\n\n// ─── UUID ─────────────────────────────────────────────────────────────────────\n\nfunction uuid(): string {\n if (typeof crypto !== 'undefined' && typeof crypto.randomUUID === 'function') {\n return crypto.randomUUID();\n }\n // Fallback for older environments\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n}\n\n// ─── DSN parser ───────────────────────────────────────────────────────────────\n\nfunction parseDsn(dsn: string): ParsedDsn & { metricsUrl: string } {\n let url: URL;\n try {\n url = new URL(dsn);\n } catch {\n throw new Error(`[BugCatch] Invalid DSN: \"${dsn}\"`);\n }\n\n const sdkKey = url.searchParams.get('key');\n if (!sdkKey) {\n throw new Error(`[BugCatch] DSN is missing the \"key\" query parameter: \"${dsn}\"`);\n }\n\n // Extract projectId from the last path segment (/ingest/{projectId})\n const segments = url.pathname.split('/').filter(Boolean);\n const projectId = segments[segments.length - 1];\n if (!projectId) {\n throw new Error(`[BugCatch] Could not extract projectId from DSN path: \"${dsn}\"`);\n }\n\n // Reconstruct the URL without extra query params\n const ingestUrl = `${url.origin}${url.pathname}?key=${sdkKey}`;\n const metricsUrl = `${url.origin}${url.pathname}/metrics?key=${sdkKey}`;\n\n return { ingestUrl, metricsUrl, projectId, sdkKey };\n}\n\n// ─── Route normalizer ─────────────────────────────────────────────────────────\n\n/**\n * Strips the origin and query string from a URL and replaces dynamic path\n * segments (UUIDs, numeric IDs) with `:id` so metrics group by route template.\n *\n * e.g. https://api.example.com/users/42/orders/abc-123?page=1 → /users/:id/orders/:id\n */\nfunction normalizeUrl(rawUrl: string): string {\n let pathname: string;\n try {\n pathname = new URL(rawUrl).pathname;\n } catch {\n // rawUrl is already a path (e.g. \"/api/users/1\")\n pathname = rawUrl.split('?')[0];\n }\n return pathname\n .replace(/\\/[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi, '/:id')\n .replace(/\\/\\d{1,20}(?=\\/|$)/g, '/:id');\n}\n\n// ─── Pattern matching ─────────────────────────────────────────────────────────\n\nfunction matchesPattern(value: string, patterns: Array<string | RegExp>): boolean {\n return patterns.some((p) =>\n typeof p === 'string' ? value.includes(p) : p.test(value),\n );\n}\n\n// ─── Client ───────────────────────────────────────────────────────────────────\n\nexport class BugCatchClient {\n private readonly opts: Required<\n Pick<BugCatchOptions, 'debug' | 'maxBreadcrumbs' | 'autoCaptureErrors' | 'autoCaptureBreadcrumbs' | 'autoTrackRequests'>\n > & BugCatchOptions;\n\n private readonly dsn: ParsedDsn & { metricsUrl: string };\n private readonly crumbs: BreadcrumbBuffer;\n private user: UserContext = {};\n private tags: Record<string, string> = {};\n private readonly cleanups: Array<() => void> = [];\n\n constructor(options: BugCatchOptions) {\n this.opts = {\n debug: false,\n maxBreadcrumbs: 100,\n autoCaptureErrors: true,\n autoCaptureBreadcrumbs: true,\n autoTrackRequests: false,\n ...options,\n };\n\n this.dsn = parseDsn(options.dsn);\n this.crumbs = new BreadcrumbBuffer(this.opts.maxBreadcrumbs);\n\n if (this.opts.autoCaptureErrors) {\n this.installErrorHandlers();\n }\n\n if (this.opts.autoCaptureBreadcrumbs) {\n this.cleanups.push(installNavigationBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installClickBreadcrumbs((c) => this.addBreadcrumb(c)));\n this.cleanups.push(installConsoleBreadcrumbs((c) => this.addBreadcrumb(c)));\n }\n\n if (this.opts.autoTrackRequests) {\n this.cleanups.push(this.installFetchInterceptor());\n }\n\n this.log('Initialized. Project:', this.dsn.projectId);\n }\n\n // ─── Public API ─────────────────────────────────────────────────────────────\n\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n const event = this.buildExceptionPayload(error, extra);\n void this.send(event);\n return event.event_id;\n }\n\n captureMessage(message: string, level: string = 'info', extra?: Record<string, unknown>): string {\n const event = this.buildMessagePayload(message, level, extra);\n void this.send(event);\n return event.event_id;\n }\n\n setUser(user: UserContext): void {\n this.user = {\n ...user,\n id: user.id != null ? String(user.id) : undefined,\n };\n }\n\n clearUser(): void {\n this.user = {};\n }\n\n setTag(key: string, value: string): void {\n this.tags[key] = value;\n }\n\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n this.crumbs.add(crumb);\n }\n\n /** Tear down all global listeners. Call when unmounting in SPAs. */\n destroy(): void {\n for (const cleanup of this.cleanups) {\n cleanup();\n }\n this.cleanups.length = 0;\n }\n\n /**\n * Manually report an API call timing. Use this when `autoTrackRequests`\n * is off or when you want to track server-side (Node.js) requests explicitly.\n */\n trackRequest(method: string, route: string, durationMs: number, statusCode: number): void {\n void this.sendMetric({ method: method.toUpperCase(), route, duration_ms: durationMs, status_code: statusCode });\n }\n\n // ─── Internal: build payloads ────────────────────────────────────────────\n\n private buildExceptionPayload(\n error: unknown,\n extra?: Record<string, unknown>,\n ): EventPayload {\n const err = error instanceof Error ? error : new Error(String(error));\n const frames = parseStack(err);\n\n const exceptionValue: ExceptionValue = {\n type: err.name || 'Error',\n value: err.message,\n stacktrace: frames.length > 0 ? { frames } : undefined,\n };\n\n return this.buildBase({\n level: 'error',\n exception: { values: [exceptionValue] },\n extra,\n });\n }\n\n private buildMessagePayload(\n message: string,\n level: string,\n extra?: Record<string, unknown>,\n ): EventPayload {\n return this.buildBase({ level, message, extra });\n }\n\n private buildBase(\n overrides: Partial<EventPayload> & { extra?: Record<string, unknown> },\n ): EventPayload {\n const { extra, ...rest } = overrides;\n const payload: EventPayload = {\n event_id: uuid(),\n timestamp: new Date().toISOString(),\n platform: 'javascript',\n ...rest,\n };\n\n if (this.opts.release) payload.release = this.opts.release;\n if (this.opts.environment) payload.environment = this.opts.environment;\n\n if (Object.keys(this.user).length > 0) {\n payload.user = { ...this.user };\n }\n\n if (Object.keys(this.tags).length > 0) {\n payload.tags = { ...this.tags };\n }\n\n if (extra && Object.keys(extra).length > 0) {\n payload.extra = extra;\n }\n\n const breadcrumbs = this.crumbs.getAll();\n if (breadcrumbs.length > 0) {\n payload.breadcrumbs = breadcrumbs;\n }\n\n // Capture browser request context\n if (typeof window !== 'undefined') {\n payload.request = {\n url: window.location.href,\n headers: {\n 'user-agent': navigator.userAgent,\n },\n };\n }\n\n return payload;\n }\n\n // ─── Internal: error handlers ────────────────────────────────────────────\n\n private installErrorHandlers(): void {\n if (typeof window === 'undefined') {\n // Node.js environment\n const onUncaught = (err: Error) => {\n this.captureException(err, { handler: 'uncaughtException' });\n };\n const onUnhandled = (reason: unknown) => {\n this.captureException(reason, { handler: 'unhandledRejection' });\n };\n process.on('uncaughtException', onUncaught);\n process.on('unhandledRejection', onUnhandled);\n this.cleanups.push(() => {\n process.off('uncaughtException', onUncaught);\n process.off('unhandledRejection', onUnhandled);\n });\n return;\n }\n\n // Browser environment\n const onError = (event: ErrorEvent) => {\n if (!event.error) return;\n if (this.shouldIgnore(event.error, event.filename ?? '')) return;\n this.captureException(event.error, { handler: 'window.onerror' });\n };\n\n const onUnhandledRejection = (event: PromiseRejectionEvent) => {\n const reason = event.reason as unknown;\n if (this.shouldIgnore(reason, '')) return;\n this.captureException(reason, { handler: 'unhandledrejection' });\n };\n\n window.addEventListener('error', onError);\n window.addEventListener('unhandledrejection', onUnhandledRejection);\n\n this.cleanups.push(() => {\n window.removeEventListener('error', onError);\n window.removeEventListener('unhandledrejection', onUnhandledRejection);\n });\n }\n\n private shouldIgnore(error: unknown, scriptUrl: string): boolean {\n const { ignoreUrls, ignoreErrors } = this.opts;\n\n if (ignoreUrls?.length && scriptUrl) {\n if (matchesPattern(scriptUrl, ignoreUrls)) return true;\n }\n\n if (ignoreErrors?.length) {\n const message = error instanceof Error ? error.message : String(error);\n if (matchesPattern(message, ignoreErrors)) return true;\n }\n\n return false;\n }\n\n // ─── Internal: request tracking ──────────────────────────────────────────\n\n private installFetchInterceptor(): () => void {\n const original = globalThis.fetch.bind(globalThis);\n const self = this;\n\n globalThis.fetch = async function patchedFetch(\n input: RequestInfo | URL,\n init?: RequestInit,\n ): Promise<Response> {\n const url = input instanceof Request ? input.url : String(input);\n\n // Never intercept BugCatch's own ingest/metrics requests\n if (url.includes(self.dsn.ingestUrl.split('?')[0])) {\n return original(input, init);\n }\n\n if (self.opts.trackIgnoreUrls && matchesPattern(url, self.opts.trackIgnoreUrls)) {\n return original(input, init);\n }\n\n const method = (init?.method ?? (input instanceof Request ? input.method : 'GET')).toUpperCase();\n const route = normalizeUrl(url);\n const start = Date.now();\n\n try {\n const response = await original(input, init);\n void self.sendMetric({\n method,\n route,\n duration_ms: Date.now() - start,\n status_code: response.status,\n user_id: self.user.id,\n });\n return response;\n } catch (err) {\n // Network error — report as status 0\n void self.sendMetric({ method, route, duration_ms: Date.now() - start, status_code: 0 });\n throw err;\n }\n };\n\n // Return cleanup function that restores original fetch\n return () => {\n globalThis.fetch = original;\n };\n }\n\n private async sendMetric(metric: MetricPayload): Promise<void> {\n try {\n await fetch(this.dsn.metricsUrl, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify(metric),\n });\n } catch {\n // Silently ignore — metric loss is acceptable\n }\n }\n\n // ─── Internal: transport ─────────────────────────────────────────────────\n\n private async send(event: EventPayload): Promise<void> {\n let finalEvent: EventPayload | false = event;\n\n if (this.opts.beforeSend) {\n finalEvent = this.opts.beforeSend(event);\n if (finalEvent === false) {\n this.log('Event dropped by beforeSend hook');\n return;\n }\n }\n\n this.log('Sending event:', finalEvent.event_id, finalEvent.level);\n\n let body: string;\n try {\n body = JSON.stringify(finalEvent);\n } catch (err) {\n console.warn('[BugCatch] Failed to serialize event:', err);\n return;\n }\n\n try {\n const fetchOptions: RequestInit = {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body,\n };\n\n // keepalive is browser-only; Node.js fetch (undici) enforces a 64 KB body\n // limit with keepalive: true, which silently drops large payloads.\n if (typeof window !== 'undefined') {\n fetchOptions.keepalive = true;\n }\n\n const res = await fetch(this.dsn.ingestUrl, fetchOptions);\n\n if (!res.ok) {\n console.warn(`[BugCatch] Ingest responded with ${res.status}:`, await res.text());\n }\n } catch (err) {\n console.warn('[BugCatch] Failed to send event:', err);\n }\n }\n\n private log(...args: unknown[]): void {\n if (this.opts.debug) {\n console.debug('[BugCatch]', ...args);\n }\n }\n}\n","import { BugCatchClient } from './client.js';\nimport type { BugCatchOptions, UserContext, BreadcrumbEntry } from './types.js';\n\nexport type { BugCatchOptions, UserContext, BreadcrumbEntry };\nexport type { EventPayload, StackFrame, ParsedDsn } from './types.js';\nexport { BugCatchClient };\n\n// ─── Singleton instance ───────────────────────────────────────────────────────\n\nlet _client: BugCatchClient | null = null;\n\nfunction getClient(): BugCatchClient {\n if (!_client) {\n throw new Error('[BugCatch] SDK not initialized. Call BugCatch.init(options) first.');\n }\n return _client;\n}\n\n// ─── Public singleton API ─────────────────────────────────────────────────────\n\nconst BugCatch = {\n /**\n * Initialize the SDK. Call this once, as early as possible in your app.\n *\n * @example\n * BugCatch.init({\n * dsn: 'http://localhost:3000/ingest/project-id?key=sdk-key',\n * release: '1.0.0',\n * environment: 'production',\n * });\n */\n init(options: BugCatchOptions): BugCatchClient {\n if (_client) {\n console.warn('[BugCatch] init() called more than once. Ignoring.');\n return _client;\n }\n _client = new BugCatchClient(options);\n return _client;\n },\n\n /**\n * Capture an Error object or any value as an error event.\n * Returns the generated event_id.\n */\n captureException(error: unknown, extra?: Record<string, unknown>): string {\n return getClient().captureException(error, extra);\n },\n\n /**\n * Capture a plain text message as an event.\n * Returns the generated event_id.\n */\n captureMessage(message: string, level?: string, extra?: Record<string, unknown>): string {\n return getClient().captureMessage(message, level, extra);\n },\n\n /**\n * Set the current user context. Attached to all subsequent events.\n */\n setUser(user: UserContext): void {\n getClient().setUser(user);\n },\n\n /**\n * Clear the current user context (e.g. on logout).\n */\n clearUser(): void {\n getClient().clearUser();\n },\n\n /**\n * Set a tag that will be attached to all subsequent events.\n */\n setTag(key: string, value: string): void {\n getClient().setTag(key, value);\n },\n\n /**\n * Manually add a breadcrumb.\n */\n addBreadcrumb(crumb: BreadcrumbEntry): void {\n getClient().addBreadcrumb(crumb);\n },\n\n /**\n * Manually report an API call timing to BugCatch.\n * Use when `autoTrackRequests` is off or for server-side tracking.\n *\n * @example\n * const start = Date.now();\n * await fetch('/api/orders');\n * BugCatch.trackRequest('GET', '/api/orders', Date.now() - start, 200);\n */\n trackRequest(method: string, route: string, durationMs: number, statusCode: number): void {\n getClient().trackRequest(method, route, durationMs, statusCode);\n },\n\n /**\n * Tear down all listeners. Useful in SPA cleanup or hot-reload scenarios.\n */\n destroy(): void {\n _client?.destroy();\n _client = null;\n },\n};\n\n// Named export for CJS consumers: const { BugCatch } = require('bugcatch-sdk')\nexport { BugCatch };\n\n// Default export for ESM consumers: import BugCatch from 'bugcatch-sdk'\nexport default BugCatch;\n"]}
|