@bugwatch/core 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,590 @@
1
+ 'use strict';
2
+
3
+ var __defProp = Object.defineProperty;
4
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
5
+ var __getOwnPropNames = Object.getOwnPropertyNames;
6
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
7
+ var __esm = (fn, res) => function __init() {
8
+ return fn && (res = (0, fn[__getOwnPropNames(fn)[0]])(fn = 0)), res;
9
+ };
10
+ var __export = (target, all) => {
11
+ for (var name in all)
12
+ __defProp(target, name, { get: all[name], enumerable: true });
13
+ };
14
+ var __copyProps = (to, from, except, desc) => {
15
+ if (from && typeof from === "object" || typeof from === "function") {
16
+ for (let key of __getOwnPropNames(from))
17
+ if (!__hasOwnProp.call(to, key) && key !== except)
18
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
19
+ }
20
+ return to;
21
+ };
22
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
23
+
24
+ // src/transport.ts
25
+ var DEFAULT_ENDPOINT; exports.HttpTransport = void 0; exports.NoopTransport = void 0; exports.ConsoleTransport = void 0; exports.BatchTransport = void 0;
26
+ var init_transport = __esm({
27
+ "src/transport.ts"() {
28
+ DEFAULT_ENDPOINT = "https://api.bugwatch.dev";
29
+ exports.HttpTransport = class {
30
+ endpoint;
31
+ apiKey;
32
+ debug;
33
+ constructor(options) {
34
+ this.endpoint = options.endpoint || DEFAULT_ENDPOINT;
35
+ this.apiKey = options.apiKey;
36
+ this.debug = options.debug || false;
37
+ }
38
+ async send(event) {
39
+ const url = `${this.endpoint}/api/v1/events`;
40
+ if (this.debug) {
41
+ console.log("[Bugwatch] Sending event:", event.event_id);
42
+ }
43
+ try {
44
+ const response = await this.fetch(url, {
45
+ method: "POST",
46
+ headers: {
47
+ "Content-Type": "application/json",
48
+ "X-API-Key": this.apiKey,
49
+ "X-Bugwatch-SDK": event.sdk?.name || "bugwatch-core",
50
+ "X-Bugwatch-SDK-Version": event.sdk?.version || "0.1.0"
51
+ },
52
+ body: JSON.stringify(event)
53
+ });
54
+ if (!response.ok) {
55
+ const errorText = await response.text();
56
+ if (this.debug) {
57
+ console.error("[Bugwatch] Failed to send event:", response.status, errorText);
58
+ }
59
+ if (response.status === 429) {
60
+ const retryAfter = response.headers.get("Retry-After");
61
+ if (this.debug) {
62
+ console.warn(`[Bugwatch] Rate limited. Retry after ${retryAfter}s`);
63
+ }
64
+ }
65
+ throw new Error(`Failed to send event: ${response.status}`);
66
+ }
67
+ if (this.debug) {
68
+ console.log("[Bugwatch] Event sent successfully:", event.event_id);
69
+ }
70
+ } catch (error) {
71
+ if (this.debug) {
72
+ console.error("[Bugwatch] Transport error:", error);
73
+ }
74
+ }
75
+ }
76
+ /**
77
+ * Abstract fetch to support different environments
78
+ */
79
+ async fetch(url, options) {
80
+ if (typeof globalThis.fetch === "function") {
81
+ return globalThis.fetch(url, options);
82
+ }
83
+ throw new Error("No fetch implementation available");
84
+ }
85
+ };
86
+ exports.NoopTransport = class {
87
+ async send(_event) {
88
+ }
89
+ };
90
+ exports.ConsoleTransport = class {
91
+ async send(event) {
92
+ console.log("[Bugwatch Event]", JSON.stringify(event, null, 2));
93
+ }
94
+ };
95
+ exports.BatchTransport = class {
96
+ transport;
97
+ queue = [];
98
+ maxBatchSize;
99
+ flushInterval;
100
+ timer = null;
101
+ constructor(transport, options = {}) {
102
+ this.transport = transport;
103
+ this.maxBatchSize = options.maxBatchSize || 10;
104
+ this.flushInterval = options.flushInterval || 5e3;
105
+ this.startTimer();
106
+ }
107
+ async send(event) {
108
+ this.queue.push(event);
109
+ if (this.queue.length >= this.maxBatchSize) {
110
+ await this.flush();
111
+ }
112
+ }
113
+ async flush() {
114
+ if (this.queue.length === 0) {
115
+ return;
116
+ }
117
+ const events = this.queue.splice(0, this.maxBatchSize);
118
+ await Promise.all(events.map((event) => this.transport.send(event)));
119
+ }
120
+ startTimer() {
121
+ if (typeof setInterval !== "undefined") {
122
+ this.timer = setInterval(() => {
123
+ this.flush().catch(() => {
124
+ });
125
+ }, this.flushInterval);
126
+ if (this.timer && typeof this.timer === "object" && "unref" in this.timer) {
127
+ this.timer.unref();
128
+ }
129
+ }
130
+ }
131
+ destroy() {
132
+ if (this.timer) {
133
+ clearInterval(this.timer);
134
+ this.timer = null;
135
+ }
136
+ }
137
+ };
138
+ }
139
+ });
140
+
141
+ // src/stacktrace.ts
142
+ function parseStackTrace(error) {
143
+ const stack = error.stack;
144
+ if (!stack) {
145
+ return [];
146
+ }
147
+ const frames = [];
148
+ const lines = stack.split("\n");
149
+ for (const line of lines) {
150
+ const frame = parseStackLine(line);
151
+ if (frame) {
152
+ frames.push(frame);
153
+ }
154
+ }
155
+ return frames;
156
+ }
157
+ function parseStackLine(line) {
158
+ const trimmed = line.trim();
159
+ if (!trimmed || trimmed.startsWith("Error:") || trimmed.startsWith("at ") === false && !trimmed.includes("@")) {
160
+ if (!trimmed.includes("@") && !trimmed.startsWith("at ")) {
161
+ return null;
162
+ }
163
+ }
164
+ const chromeMatch = trimmed.match(
165
+ /^\s*at\s+(?:(.+?)\s+\()?(?:(.+?):(\d+):(\d+)|(.+?):(\d+)|(.+))\)?$/
166
+ );
167
+ if (chromeMatch) {
168
+ const [, func, file1, line1, col1, file2, line2, file3] = chromeMatch;
169
+ const filename = file1 || file2 || file3 || "<anonymous>";
170
+ const lineno = parseInt(line1 || line2 || "0", 10);
171
+ const colno = parseInt(col1 || "0", 10);
172
+ return {
173
+ filename: normalizeFilename(filename),
174
+ function: func || "<anonymous>",
175
+ lineno,
176
+ colno,
177
+ in_app: isInAppFrame(filename)
178
+ };
179
+ }
180
+ const firefoxMatch = trimmed.match(/^(.+?)@(.+?):(\d+):(\d+)$/);
181
+ if (firefoxMatch) {
182
+ const [, func, file, lineStr, colStr] = firefoxMatch;
183
+ const filename = file || "<anonymous>";
184
+ const lineno = parseInt(lineStr || "0", 10);
185
+ const colno = parseInt(colStr || "0", 10);
186
+ return {
187
+ filename: normalizeFilename(filename),
188
+ function: func || "<anonymous>",
189
+ lineno,
190
+ colno,
191
+ in_app: isInAppFrame(filename)
192
+ };
193
+ }
194
+ return null;
195
+ }
196
+ function normalizeFilename(filename) {
197
+ let normalized = filename.replace(/^webpack:\/\/[^/]*\//, "");
198
+ normalized = normalized.replace(/^file:\/\//, "");
199
+ normalized = normalized.replace(/^\.\//, "");
200
+ normalized = normalized.replace(/\?.*$/, "");
201
+ return normalized;
202
+ }
203
+ function isInAppFrame(filename) {
204
+ if (filename.includes("node_modules")) {
205
+ return false;
206
+ }
207
+ if (filename.startsWith("node:") || filename.startsWith("internal/") || filename.includes("(native)")) {
208
+ return false;
209
+ }
210
+ if (filename.startsWith("<") || filename === "native code") {
211
+ return false;
212
+ }
213
+ const internalPatterns = [
214
+ /webpack\/runtime/,
215
+ /webpack\/bootstrap/,
216
+ /turbopack/,
217
+ /__next/,
218
+ /next\/dist/,
219
+ /react-dom/,
220
+ /react\/cjs/,
221
+ /scheduler/
222
+ ];
223
+ for (const pattern of internalPatterns) {
224
+ if (pattern.test(filename)) {
225
+ return false;
226
+ }
227
+ }
228
+ return true;
229
+ }
230
+ function extractErrorInfo(error) {
231
+ const type = error.name || "Error";
232
+ const value = error.message || String(error);
233
+ return { type, value };
234
+ }
235
+ var init_stacktrace = __esm({
236
+ "src/stacktrace.ts"() {
237
+ }
238
+ });
239
+
240
+ // src/fingerprint.ts
241
+ function generateFingerprint(errorType, message, stacktrace) {
242
+ const components = [];
243
+ components.push(errorType);
244
+ const normalizedMessage = normalizeErrorMessage(message);
245
+ components.push(normalizedMessage);
246
+ if (stacktrace && stacktrace.length > 0) {
247
+ const topInAppFrame = stacktrace.find((frame) => frame.in_app);
248
+ if (topInAppFrame) {
249
+ components.push(`${topInAppFrame.filename}:${topInAppFrame.function}`);
250
+ } else {
251
+ const firstFrame = stacktrace[0];
252
+ if (firstFrame) {
253
+ components.push(`${firstFrame.filename}:${firstFrame.function}`);
254
+ }
255
+ }
256
+ }
257
+ return hashString(components.join("|"));
258
+ }
259
+ function fingerprintFromException(exception) {
260
+ return generateFingerprint(
261
+ exception.type,
262
+ exception.value,
263
+ exception.stacktrace
264
+ );
265
+ }
266
+ function normalizeErrorMessage(message) {
267
+ return message.replace(
268
+ /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,
269
+ "<UUID>"
270
+ ).replace(/0x[0-9a-f]+/gi, "<ADDR>").replace(/\b\d+\b/g, "<N>").replace(/"[^"]*"/g, '"<STR>"').replace(/'[^']*'/g, "'<STR>'").replace(/https?:\/\/[^\s]+/g, "<URL>").replace(/\/[\w\-./]+\.\w+/g, "<PATH>").replace(/\s+/g, " ").trim();
271
+ }
272
+ function hashString(str) {
273
+ let hash = 2166136261;
274
+ for (let i = 0; i < str.length; i++) {
275
+ hash ^= str.charCodeAt(i);
276
+ hash = Math.imul(hash, 16777619);
277
+ }
278
+ return (hash >>> 0).toString(16).padStart(8, "0");
279
+ }
280
+ var init_fingerprint = __esm({
281
+ "src/fingerprint.ts"() {
282
+ }
283
+ });
284
+
285
+ // src/client.ts
286
+ var client_exports = {};
287
+ __export(client_exports, {
288
+ Bugwatch: () => exports.Bugwatch
289
+ });
290
+ function generateEventId() {
291
+ const timestamp = Date.now().toString(36);
292
+ const random = Math.random().toString(36).substring(2, 10);
293
+ return `${timestamp}${random}`;
294
+ }
295
+ var SDK_NAME, SDK_VERSION, DEFAULT_OPTIONS; exports.Bugwatch = void 0;
296
+ var init_client = __esm({
297
+ "src/client.ts"() {
298
+ init_transport();
299
+ init_stacktrace();
300
+ init_fingerprint();
301
+ SDK_NAME = "@bugwatch/core";
302
+ SDK_VERSION = "0.1.0";
303
+ DEFAULT_OPTIONS = {
304
+ endpoint: "https://api.bugwatch.dev",
305
+ debug: false,
306
+ sampleRate: 1,
307
+ maxBreadcrumbs: 100,
308
+ environment: "production"
309
+ };
310
+ exports.Bugwatch = class {
311
+ options;
312
+ transport;
313
+ breadcrumbs = [];
314
+ tags = {};
315
+ extra = {};
316
+ user = null;
317
+ integrations = [];
318
+ initialized = false;
319
+ constructor(options) {
320
+ this.options = { ...DEFAULT_OPTIONS, ...options };
321
+ this.transport = this.createTransport();
322
+ if (options.tags) {
323
+ this.tags = { ...options.tags };
324
+ }
325
+ if (options.user) {
326
+ this.user = options.user;
327
+ }
328
+ this.initialized = true;
329
+ }
330
+ createTransport() {
331
+ if (!this.options.apiKey) {
332
+ if (this.options.debug) {
333
+ console.warn("[Bugwatch] No API key provided, SDK is disabled");
334
+ }
335
+ return new exports.NoopTransport();
336
+ }
337
+ return new exports.HttpTransport(this.options);
338
+ }
339
+ /**
340
+ * Register an integration
341
+ */
342
+ use(integration) {
343
+ this.integrations.push(integration);
344
+ integration.setup(this);
345
+ return this;
346
+ }
347
+ /**
348
+ * Get SDK options
349
+ */
350
+ getOptions() {
351
+ return this.options;
352
+ }
353
+ /**
354
+ * Capture an exception
355
+ */
356
+ captureException(error, context) {
357
+ if (!this.initialized) {
358
+ return "";
359
+ }
360
+ if (Math.random() > (this.options.sampleRate || 1)) {
361
+ return "";
362
+ }
363
+ if (this.shouldIgnoreError(error)) {
364
+ return "";
365
+ }
366
+ const event = this.createEventFromError(error, context);
367
+ const processedEvent = this.options.beforeSend ? this.options.beforeSend(event) : event;
368
+ if (!processedEvent) {
369
+ if (this.options.debug) {
370
+ console.log("[Bugwatch] Event dropped by beforeSend");
371
+ }
372
+ return "";
373
+ }
374
+ this.transport.send(processedEvent).catch(() => {
375
+ });
376
+ return processedEvent.event_id;
377
+ }
378
+ /**
379
+ * Capture a message
380
+ */
381
+ captureMessage(message, level = "info") {
382
+ if (!this.initialized) {
383
+ return "";
384
+ }
385
+ const event = this.createEvent({
386
+ message,
387
+ level
388
+ });
389
+ const processedEvent = this.options.beforeSend ? this.options.beforeSend(event) : event;
390
+ if (!processedEvent) {
391
+ return "";
392
+ }
393
+ this.transport.send(processedEvent).catch(() => {
394
+ });
395
+ return processedEvent.event_id;
396
+ }
397
+ /**
398
+ * Add a breadcrumb
399
+ */
400
+ addBreadcrumb(breadcrumb) {
401
+ const crumb = {
402
+ ...breadcrumb,
403
+ timestamp: (/* @__PURE__ */ new Date()).toISOString()
404
+ };
405
+ this.breadcrumbs.push(crumb);
406
+ const max = this.options.maxBreadcrumbs || 100;
407
+ if (this.breadcrumbs.length > max) {
408
+ this.breadcrumbs = this.breadcrumbs.slice(-max);
409
+ }
410
+ }
411
+ /**
412
+ * Set user context
413
+ */
414
+ setUser(user) {
415
+ this.user = user;
416
+ }
417
+ /**
418
+ * Set a tag
419
+ */
420
+ setTag(key, value) {
421
+ this.tags[key] = value;
422
+ }
423
+ /**
424
+ * Set extra context
425
+ */
426
+ setExtra(key, value) {
427
+ this.extra[key] = value;
428
+ }
429
+ /**
430
+ * Clear breadcrumbs
431
+ */
432
+ clearBreadcrumbs() {
433
+ this.breadcrumbs = [];
434
+ }
435
+ /**
436
+ * Create an event from an Error object
437
+ */
438
+ createEventFromError(error, context) {
439
+ const { type, value } = extractErrorInfo(error);
440
+ const stacktrace = parseStackTrace(error);
441
+ const exception = {
442
+ type,
443
+ value,
444
+ stacktrace
445
+ };
446
+ return this.createEvent({
447
+ level: "error",
448
+ message: `${type}: ${value}`,
449
+ exception,
450
+ ...context
451
+ });
452
+ }
453
+ /**
454
+ * Create a base event
455
+ */
456
+ createEvent(partial) {
457
+ const event = {
458
+ event_id: generateEventId(),
459
+ timestamp: (/* @__PURE__ */ new Date()).toISOString(),
460
+ platform: this.detectPlatform(),
461
+ level: partial.level || "error",
462
+ message: partial.message || "",
463
+ environment: this.options.environment,
464
+ release: this.options.release,
465
+ tags: { ...this.tags, ...partial.tags },
466
+ extra: { ...this.extra, ...partial.extra },
467
+ breadcrumbs: [...this.breadcrumbs],
468
+ sdk: {
469
+ name: SDK_NAME,
470
+ version: SDK_VERSION
471
+ },
472
+ ...partial
473
+ };
474
+ if (this.user || partial.user) {
475
+ event.user = { ...this.user, ...partial.user };
476
+ }
477
+ if (event.exception) {
478
+ const fingerprint = fingerprintFromException(event.exception);
479
+ event.tags = { ...event.tags, fingerprint };
480
+ }
481
+ return event;
482
+ }
483
+ /**
484
+ * Check if error should be ignored
485
+ */
486
+ shouldIgnoreError(error) {
487
+ if (!this.options.ignoreErrors || this.options.ignoreErrors.length === 0) {
488
+ return false;
489
+ }
490
+ const message = error.message || String(error);
491
+ for (const pattern of this.options.ignoreErrors) {
492
+ if (typeof pattern === "string") {
493
+ if (message.includes(pattern)) {
494
+ return true;
495
+ }
496
+ } else if (pattern instanceof RegExp) {
497
+ if (pattern.test(message)) {
498
+ return true;
499
+ }
500
+ }
501
+ }
502
+ return false;
503
+ }
504
+ /**
505
+ * Detect the current platform
506
+ */
507
+ detectPlatform() {
508
+ if (typeof window !== "undefined") {
509
+ return "javascript";
510
+ }
511
+ if (typeof process !== "undefined" && process.versions?.node) {
512
+ return "node";
513
+ }
514
+ if (typeof EdgeRuntime !== "undefined") {
515
+ return "edge";
516
+ }
517
+ return "javascript";
518
+ }
519
+ };
520
+ }
521
+ });
522
+
523
+ // src/index.ts
524
+ init_client();
525
+ init_transport();
526
+ init_stacktrace();
527
+ init_fingerprint();
528
+ var globalClient = null;
529
+ function init(options) {
530
+ const { Bugwatch: Bugwatch2 } = (init_client(), __toCommonJS(client_exports));
531
+ const client = new Bugwatch2(options);
532
+ globalClient = client;
533
+ return client;
534
+ }
535
+ function getClient() {
536
+ return globalClient;
537
+ }
538
+ function captureException(error, context) {
539
+ if (!globalClient) {
540
+ console.warn("[Bugwatch] SDK not initialized. Call init() first.");
541
+ return "";
542
+ }
543
+ return globalClient.captureException(error, context);
544
+ }
545
+ function captureMessage(message, level) {
546
+ if (!globalClient) {
547
+ console.warn("[Bugwatch] SDK not initialized. Call init() first.");
548
+ return "";
549
+ }
550
+ return globalClient.captureMessage(message, level);
551
+ }
552
+ function addBreadcrumb(breadcrumb) {
553
+ if (!globalClient) {
554
+ return;
555
+ }
556
+ globalClient.addBreadcrumb(breadcrumb);
557
+ }
558
+ function setUser(user) {
559
+ if (!globalClient) {
560
+ return;
561
+ }
562
+ globalClient.setUser(user);
563
+ }
564
+ function setTag(key, value) {
565
+ if (!globalClient) {
566
+ return;
567
+ }
568
+ globalClient.setTag(key, value);
569
+ }
570
+ function setExtra(key, value) {
571
+ if (!globalClient) {
572
+ return;
573
+ }
574
+ globalClient.setExtra(key, value);
575
+ }
576
+
577
+ exports.addBreadcrumb = addBreadcrumb;
578
+ exports.captureException = captureException;
579
+ exports.captureMessage = captureMessage;
580
+ exports.extractErrorInfo = extractErrorInfo;
581
+ exports.fingerprintFromException = fingerprintFromException;
582
+ exports.generateFingerprint = generateFingerprint;
583
+ exports.getClient = getClient;
584
+ exports.init = init;
585
+ exports.parseStackTrace = parseStackTrace;
586
+ exports.setExtra = setExtra;
587
+ exports.setTag = setTag;
588
+ exports.setUser = setUser;
589
+ //# sourceMappingURL=index.js.map
590
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"sources":["../src/transport.ts","../src/stacktrace.ts","../src/fingerprint.ts","../src/client.ts","../src/index.ts"],"names":["HttpTransport","NoopTransport","ConsoleTransport","BatchTransport","Bugwatch"],"mappings":"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","file":"index.js","sourcesContent":["import type { ErrorEvent, Transport, BugwatchOptions } from \"./types\";\n\nconst DEFAULT_ENDPOINT = \"https://api.bugwatch.dev\";\n\n/**\n * HTTP transport for sending events to the Bugwatch API\n */\nexport class HttpTransport implements Transport {\n private endpoint: string;\n private apiKey: string;\n private debug: boolean;\n\n constructor(options: BugwatchOptions) {\n this.endpoint = options.endpoint || DEFAULT_ENDPOINT;\n this.apiKey = options.apiKey;\n this.debug = options.debug || false;\n }\n\n async send(event: ErrorEvent): Promise<void> {\n const url = `${this.endpoint}/api/v1/events`;\n\n if (this.debug) {\n console.log(\"[Bugwatch] Sending event:\", event.event_id);\n }\n\n try {\n const response = await this.fetch(url, {\n method: \"POST\",\n headers: {\n \"Content-Type\": \"application/json\",\n \"X-API-Key\": this.apiKey,\n \"X-Bugwatch-SDK\": event.sdk?.name || \"bugwatch-core\",\n \"X-Bugwatch-SDK-Version\": event.sdk?.version || \"0.1.0\",\n },\n body: JSON.stringify(event),\n });\n\n if (!response.ok) {\n const errorText = await response.text();\n if (this.debug) {\n console.error(\"[Bugwatch] Failed to send event:\", response.status, errorText);\n }\n\n // Handle rate limiting\n if (response.status === 429) {\n const retryAfter = response.headers.get(\"Retry-After\");\n if (this.debug) {\n console.warn(`[Bugwatch] Rate limited. Retry after ${retryAfter}s`);\n }\n }\n\n throw new Error(`Failed to send event: ${response.status}`);\n }\n\n if (this.debug) {\n console.log(\"[Bugwatch] Event sent successfully:\", event.event_id);\n }\n } catch (error) {\n if (this.debug) {\n console.error(\"[Bugwatch] Transport error:\", error);\n }\n // Don't throw - we don't want SDK errors to break the application\n }\n }\n\n /**\n * Abstract fetch to support different environments\n */\n private async fetch(\n url: string,\n options: RequestInit\n ): Promise<Response> {\n // Use global fetch (available in Node 18+, browsers, and edge runtimes)\n if (typeof globalThis.fetch === \"function\") {\n return globalThis.fetch(url, options);\n }\n\n throw new Error(\"No fetch implementation available\");\n }\n}\n\n/**\n * No-op transport for testing or disabled SDK\n */\nexport class NoopTransport implements Transport {\n async send(_event: ErrorEvent): Promise<void> {\n // Do nothing\n }\n}\n\n/**\n * Console transport for development/debugging\n */\nexport class ConsoleTransport implements Transport {\n async send(event: ErrorEvent): Promise<void> {\n console.log(\"[Bugwatch Event]\", JSON.stringify(event, null, 2));\n }\n}\n\n/**\n * Batching transport that queues events and sends them in batches\n */\nexport class BatchTransport implements Transport {\n private transport: Transport;\n private queue: ErrorEvent[] = [];\n private maxBatchSize: number;\n private flushInterval: number;\n private timer: ReturnType<typeof setInterval> | null = null;\n\n constructor(\n transport: Transport,\n options: { maxBatchSize?: number; flushInterval?: number } = {}\n ) {\n this.transport = transport;\n this.maxBatchSize = options.maxBatchSize || 10;\n this.flushInterval = options.flushInterval || 5000;\n\n // Start flush timer\n this.startTimer();\n }\n\n async send(event: ErrorEvent): Promise<void> {\n this.queue.push(event);\n\n if (this.queue.length >= this.maxBatchSize) {\n await this.flush();\n }\n }\n\n async flush(): Promise<void> {\n if (this.queue.length === 0) {\n return;\n }\n\n const events = this.queue.splice(0, this.maxBatchSize);\n\n // Send events in parallel\n await Promise.all(events.map((event) => this.transport.send(event)));\n }\n\n private startTimer(): void {\n if (typeof setInterval !== \"undefined\") {\n this.timer = setInterval(() => {\n this.flush().catch(() => {\n // Ignore flush errors\n });\n }, this.flushInterval);\n\n // Unref timer in Node.js to not block process exit\n if (this.timer && typeof this.timer === \"object\" && \"unref\" in this.timer) {\n (this.timer as NodeJS.Timeout).unref();\n }\n }\n }\n\n destroy(): void {\n if (this.timer) {\n clearInterval(this.timer);\n this.timer = null;\n }\n }\n}\n","import type { StackFrame } from \"./types\";\n\n/**\n * Parse an Error's stack trace into structured frames\n */\nexport function parseStackTrace(error: Error): StackFrame[] {\n const stack = error.stack;\n if (!stack) {\n return [];\n }\n\n const frames: StackFrame[] = [];\n const lines = stack.split(\"\\n\");\n\n for (const line of lines) {\n const frame = parseStackLine(line);\n if (frame) {\n frames.push(frame);\n }\n }\n\n return frames;\n}\n\n/**\n * Parse a single stack trace line\n * Handles various formats:\n * - Chrome/Node: \" at functionName (file:line:col)\"\n * - Firefox: \"functionName@file:line:col\"\n * - Safari: \"functionName@file:line:col\"\n */\nfunction parseStackLine(line: string): StackFrame | null {\n // Skip empty lines and error message lines\n const trimmed = line.trim();\n if (!trimmed || trimmed.startsWith(\"Error:\") || trimmed.startsWith(\"at \") === false && !trimmed.includes(\"@\")) {\n // Check if it's a Chrome/Node format without \"at\"\n if (!trimmed.includes(\"@\") && !trimmed.startsWith(\"at \")) {\n return null;\n }\n }\n\n // Chrome/Node format: \"at functionName (file:line:col)\" or \"at file:line:col\"\n const chromeMatch = trimmed.match(\n /^\\s*at\\s+(?:(.+?)\\s+\\()?(?:(.+?):(\\d+):(\\d+)|(.+?):(\\d+)|(.+))\\)?$/\n );\n\n if (chromeMatch) {\n const [, func, file1, line1, col1, file2, line2, file3] = chromeMatch;\n const filename = file1 || file2 || file3 || \"<anonymous>\";\n const lineno = parseInt(line1 || line2 || \"0\", 10);\n const colno = parseInt(col1 || \"0\", 10);\n\n return {\n filename: normalizeFilename(filename),\n function: func || \"<anonymous>\",\n lineno,\n colno,\n in_app: isInAppFrame(filename),\n };\n }\n\n // Firefox/Safari format: \"functionName@file:line:col\"\n const firefoxMatch = trimmed.match(/^(.+?)@(.+?):(\\d+):(\\d+)$/);\n\n if (firefoxMatch) {\n const [, func, file, lineStr, colStr] = firefoxMatch;\n const filename = file || \"<anonymous>\";\n const lineno = parseInt(lineStr || \"0\", 10);\n const colno = parseInt(colStr || \"0\", 10);\n\n return {\n filename: normalizeFilename(filename),\n function: func || \"<anonymous>\",\n lineno,\n colno,\n in_app: isInAppFrame(filename),\n };\n }\n\n return null;\n}\n\n/**\n * Normalize filename by removing common prefixes\n */\nfunction normalizeFilename(filename: string): string {\n // Remove webpack:// prefix\n let normalized = filename.replace(/^webpack:\\/\\/[^/]*\\//, \"\");\n\n // Remove file:// prefix\n normalized = normalized.replace(/^file:\\/\\//, \"\");\n\n // Remove leading ./\n normalized = normalized.replace(/^\\.\\//, \"\");\n\n // Remove query strings\n normalized = normalized.replace(/\\?.*$/, \"\");\n\n return normalized;\n}\n\n/**\n * Determine if a frame is from the application code (not a library)\n */\nfunction isInAppFrame(filename: string): boolean {\n // Node modules are not in-app\n if (filename.includes(\"node_modules\")) {\n return false;\n }\n\n // Internal Node.js modules\n if (\n filename.startsWith(\"node:\") ||\n filename.startsWith(\"internal/\") ||\n filename.includes(\"(native)\")\n ) {\n return false;\n }\n\n // Browser built-ins\n if (filename.startsWith(\"<\") || filename === \"native code\") {\n return false;\n }\n\n // Common bundler/framework internals\n const internalPatterns = [\n /webpack\\/runtime/,\n /webpack\\/bootstrap/,\n /turbopack/,\n /__next/,\n /next\\/dist/,\n /react-dom/,\n /react\\/cjs/,\n /scheduler/,\n ];\n\n for (const pattern of internalPatterns) {\n if (pattern.test(filename)) {\n return false;\n }\n }\n\n return true;\n}\n\n/**\n * Extract error name and message from Error object\n */\nexport function extractErrorInfo(error: Error): { type: string; value: string } {\n const type = error.name || \"Error\";\n const value = error.message || String(error);\n\n return { type, value };\n}\n","import type { ExceptionInfo, StackFrame } from \"./types\";\n\n/**\n * Generate a fingerprint for an error to group similar errors together.\n * Uses a combination of error type, message patterns, and stack trace.\n */\nexport function generateFingerprint(\n errorType: string,\n message: string,\n stacktrace?: StackFrame[]\n): string {\n const components: string[] = [];\n\n // 1. Error type\n components.push(errorType);\n\n // 2. Normalized message (remove dynamic values)\n const normalizedMessage = normalizeErrorMessage(message);\n components.push(normalizedMessage);\n\n // 3. Top in-app stack frame location\n if (stacktrace && stacktrace.length > 0) {\n const topInAppFrame = stacktrace.find((frame) => frame.in_app);\n if (topInAppFrame) {\n components.push(`${topInAppFrame.filename}:${topInAppFrame.function}`);\n } else {\n // Fall back to first frame\n const firstFrame = stacktrace[0];\n if (firstFrame) {\n components.push(`${firstFrame.filename}:${firstFrame.function}`);\n }\n }\n }\n\n // Generate hash from components\n return hashString(components.join(\"|\"));\n}\n\n/**\n * Generate fingerprint from exception info\n */\nexport function fingerprintFromException(exception: ExceptionInfo): string {\n return generateFingerprint(\n exception.type,\n exception.value,\n exception.stacktrace\n );\n}\n\n/**\n * Normalize error message by removing dynamic values like:\n * - Numbers\n * - UUIDs\n * - URLs with dynamic segments\n * - Timestamps\n * - Memory addresses\n */\nfunction normalizeErrorMessage(message: string): string {\n return (\n message\n // Replace UUIDs\n .replace(\n /[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}/gi,\n \"<UUID>\"\n )\n // Replace hex addresses (0x...)\n .replace(/0x[0-9a-f]+/gi, \"<ADDR>\")\n // Replace numbers\n .replace(/\\b\\d+\\b/g, \"<N>\")\n // Replace quoted strings\n .replace(/\"[^\"]*\"/g, '\"<STR>\"')\n .replace(/'[^']*'/g, \"'<STR>'\")\n // Replace URLs\n .replace(/https?:\\/\\/[^\\s]+/g, \"<URL>\")\n // Replace file paths\n .replace(/\\/[\\w\\-./]+\\.\\w+/g, \"<PATH>\")\n // Collapse whitespace\n .replace(/\\s+/g, \" \")\n .trim()\n );\n}\n\n/**\n * Simple string hash function (FNV-1a)\n */\nfunction hashString(str: string): string {\n let hash = 2166136261;\n for (let i = 0; i < str.length; i++) {\n hash ^= str.charCodeAt(i);\n hash = Math.imul(hash, 16777619);\n }\n // Convert to hex string\n return (hash >>> 0).toString(16).padStart(8, \"0\");\n}\n","import type {\n BugwatchOptions,\n BugwatchClient,\n ErrorEvent,\n Breadcrumb,\n UserContext,\n Transport,\n Integration,\n ExceptionInfo,\n} from \"./types\";\nimport { HttpTransport, NoopTransport } from \"./transport\";\nimport { parseStackTrace, extractErrorInfo } from \"./stacktrace\";\nimport { fingerprintFromException } from \"./fingerprint\";\n\nconst SDK_NAME = \"@bugwatch/core\";\nconst SDK_VERSION = \"0.1.0\";\n\n/**\n * Generate a unique event ID\n */\nfunction generateEventId(): string {\n const timestamp = Date.now().toString(36);\n const random = Math.random().toString(36).substring(2, 10);\n return `${timestamp}${random}`;\n}\n\n/**\n * Default options\n */\nconst DEFAULT_OPTIONS: Partial<BugwatchOptions> = {\n endpoint: \"https://api.bugwatch.dev\",\n debug: false,\n sampleRate: 1.0,\n maxBreadcrumbs: 100,\n environment: \"production\",\n};\n\n/**\n * Core Bugwatch client implementation\n */\nexport class Bugwatch implements BugwatchClient {\n private options: BugwatchOptions;\n private transport: Transport;\n private breadcrumbs: Breadcrumb[] = [];\n private tags: Record<string, string> = {};\n private extra: Record<string, unknown> = {};\n private user: UserContext | null = null;\n private integrations: Integration[] = [];\n private initialized = false;\n\n constructor(options: BugwatchOptions) {\n this.options = { ...DEFAULT_OPTIONS, ...options };\n this.transport = this.createTransport();\n\n // Apply initial tags\n if (options.tags) {\n this.tags = { ...options.tags };\n }\n\n // Apply initial user\n if (options.user) {\n this.user = options.user;\n }\n\n this.initialized = true;\n }\n\n private createTransport(): Transport {\n if (!this.options.apiKey) {\n if (this.options.debug) {\n console.warn(\"[Bugwatch] No API key provided, SDK is disabled\");\n }\n return new NoopTransport();\n }\n\n return new HttpTransport(this.options);\n }\n\n /**\n * Register an integration\n */\n use(integration: Integration): this {\n this.integrations.push(integration);\n integration.setup(this);\n return this;\n }\n\n /**\n * Get SDK options\n */\n getOptions(): BugwatchOptions {\n return this.options;\n }\n\n /**\n * Capture an exception\n */\n captureException(error: Error, context?: Partial<ErrorEvent>): string {\n if (!this.initialized) {\n return \"\";\n }\n\n // Sample rate check\n if (Math.random() > (this.options.sampleRate || 1.0)) {\n return \"\";\n }\n\n // Check ignore patterns\n if (this.shouldIgnoreError(error)) {\n return \"\";\n }\n\n const event = this.createEventFromError(error, context);\n\n // Run beforeSend hook\n const processedEvent = this.options.beforeSend\n ? this.options.beforeSend(event)\n : event;\n\n if (!processedEvent) {\n if (this.options.debug) {\n console.log(\"[Bugwatch] Event dropped by beforeSend\");\n }\n return \"\";\n }\n\n // Send event asynchronously\n this.transport.send(processedEvent).catch(() => {\n // Errors are logged by transport\n });\n\n return processedEvent.event_id;\n }\n\n /**\n * Capture a message\n */\n captureMessage(\n message: string,\n level: ErrorEvent[\"level\"] = \"info\"\n ): string {\n if (!this.initialized) {\n return \"\";\n }\n\n const event = this.createEvent({\n message,\n level,\n });\n\n // Run beforeSend hook\n const processedEvent = this.options.beforeSend\n ? this.options.beforeSend(event)\n : event;\n\n if (!processedEvent) {\n return \"\";\n }\n\n this.transport.send(processedEvent).catch(() => {\n // Errors are logged by transport\n });\n\n return processedEvent.event_id;\n }\n\n /**\n * Add a breadcrumb\n */\n addBreadcrumb(breadcrumb: Omit<Breadcrumb, \"timestamp\">): void {\n const crumb: Breadcrumb = {\n ...breadcrumb,\n timestamp: new Date().toISOString(),\n };\n\n this.breadcrumbs.push(crumb);\n\n // Limit breadcrumbs\n const max = this.options.maxBreadcrumbs || 100;\n if (this.breadcrumbs.length > max) {\n this.breadcrumbs = this.breadcrumbs.slice(-max);\n }\n }\n\n /**\n * Set user context\n */\n setUser(user: UserContext | null): void {\n this.user = user;\n }\n\n /**\n * Set a tag\n */\n setTag(key: string, value: string): void {\n this.tags[key] = value;\n }\n\n /**\n * Set extra context\n */\n setExtra(key: string, value: unknown): void {\n this.extra[key] = value;\n }\n\n /**\n * Clear breadcrumbs\n */\n clearBreadcrumbs(): void {\n this.breadcrumbs = [];\n }\n\n /**\n * Create an event from an Error object\n */\n private createEventFromError(\n error: Error,\n context?: Partial<ErrorEvent>\n ): ErrorEvent {\n const { type, value } = extractErrorInfo(error);\n const stacktrace = parseStackTrace(error);\n\n const exception: ExceptionInfo = {\n type,\n value,\n stacktrace,\n };\n\n return this.createEvent({\n level: \"error\",\n message: `${type}: ${value}`,\n exception,\n ...context,\n });\n }\n\n /**\n * Create a base event\n */\n private createEvent(partial: Partial<ErrorEvent>): ErrorEvent {\n const event: ErrorEvent = {\n event_id: generateEventId(),\n timestamp: new Date().toISOString(),\n platform: this.detectPlatform(),\n level: partial.level || \"error\",\n message: partial.message || \"\",\n environment: this.options.environment,\n release: this.options.release,\n tags: { ...this.tags, ...partial.tags },\n extra: { ...this.extra, ...partial.extra },\n breadcrumbs: [...this.breadcrumbs],\n sdk: {\n name: SDK_NAME,\n version: SDK_VERSION,\n },\n ...partial,\n };\n\n // Add user context\n if (this.user || partial.user) {\n event.user = { ...this.user, ...partial.user };\n }\n\n // Generate fingerprint if exception exists\n if (event.exception) {\n const fingerprint = fingerprintFromException(event.exception);\n event.tags = { ...event.tags, fingerprint };\n }\n\n return event;\n }\n\n /**\n * Check if error should be ignored\n */\n private shouldIgnoreError(error: Error): boolean {\n if (!this.options.ignoreErrors || this.options.ignoreErrors.length === 0) {\n return false;\n }\n\n const message = error.message || String(error);\n\n for (const pattern of this.options.ignoreErrors) {\n if (typeof pattern === \"string\") {\n if (message.includes(pattern)) {\n return true;\n }\n } else if (pattern instanceof RegExp) {\n if (pattern.test(message)) {\n return true;\n }\n }\n }\n\n return false;\n }\n\n /**\n * Detect the current platform\n */\n private detectPlatform(): string {\n if (typeof window !== \"undefined\") {\n return \"javascript\";\n }\n if (typeof process !== \"undefined\" && process.versions?.node) {\n return \"node\";\n }\n if (typeof EdgeRuntime !== \"undefined\") {\n return \"edge\";\n }\n return \"javascript\";\n }\n}\n\n// Type declaration for edge runtime\ndeclare const EdgeRuntime: string | undefined;\n","// Core client\nexport { Bugwatch } from \"./client\";\n\n// Types\nexport type {\n BugwatchOptions,\n BugwatchClient,\n ErrorEvent,\n ExceptionInfo,\n StackFrame,\n Breadcrumb,\n UserContext,\n RequestContext,\n RuntimeInfo,\n SdkInfo,\n Transport,\n Integration,\n} from \"./types\";\n\n// Transport implementations\nexport {\n HttpTransport,\n NoopTransport,\n ConsoleTransport,\n BatchTransport,\n} from \"./transport\";\n\n// Utilities\nexport { parseStackTrace, extractErrorInfo } from \"./stacktrace\";\nexport { generateFingerprint, fingerprintFromException } from \"./fingerprint\";\n\n// Global instance management\nlet globalClient: import(\"./client\").Bugwatch | null = null;\n\n/**\n * Initialize the global Bugwatch client\n */\nexport function init(options: import(\"./types\").BugwatchOptions): import(\"./client\").Bugwatch {\n const { Bugwatch } = require(\"./client\");\n const client = new Bugwatch(options);\n globalClient = client;\n return client;\n}\n\n/**\n * Get the global Bugwatch client\n */\nexport function getClient(): import(\"./client\").Bugwatch | null {\n return globalClient;\n}\n\n/**\n * Capture an exception using the global client\n */\nexport function captureException(\n error: Error,\n context?: Partial<import(\"./types\").ErrorEvent>\n): string {\n if (!globalClient) {\n console.warn(\"[Bugwatch] SDK not initialized. Call init() first.\");\n return \"\";\n }\n return globalClient.captureException(error, context);\n}\n\n/**\n * Capture a message using the global client\n */\nexport function captureMessage(\n message: string,\n level?: import(\"./types\").ErrorEvent[\"level\"]\n): string {\n if (!globalClient) {\n console.warn(\"[Bugwatch] SDK not initialized. Call init() first.\");\n return \"\";\n }\n return globalClient.captureMessage(message, level);\n}\n\n/**\n * Add a breadcrumb using the global client\n */\nexport function addBreadcrumb(\n breadcrumb: Omit<import(\"./types\").Breadcrumb, \"timestamp\">\n): void {\n if (!globalClient) {\n return;\n }\n globalClient.addBreadcrumb(breadcrumb);\n}\n\n/**\n * Set user context on the global client\n */\nexport function setUser(user: import(\"./types\").UserContext | null): void {\n if (!globalClient) {\n return;\n }\n globalClient.setUser(user);\n}\n\n/**\n * Set a tag on the global client\n */\nexport function setTag(key: string, value: string): void {\n if (!globalClient) {\n return;\n }\n globalClient.setTag(key, value);\n}\n\n/**\n * Set extra context on the global client\n */\nexport function setExtra(key: string, value: unknown): void {\n if (!globalClient) {\n return;\n }\n globalClient.setExtra(key, value);\n}\n"]}