@bbearai/core 0.9.3 → 0.9.5
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 +34 -2
- package/dist/index.d.ts +34 -2
- package/dist/index.js +59 -9
- package/dist/index.mjs +59 -9
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -72,6 +72,14 @@ interface EnhancedBugContext {
|
|
|
72
72
|
pageLoadTime?: number;
|
|
73
73
|
memoryUsage?: number;
|
|
74
74
|
fps?: number;
|
|
75
|
+
/** First Contentful Paint (ms) */
|
|
76
|
+
fcp?: number;
|
|
77
|
+
/** Largest Contentful Paint (ms) */
|
|
78
|
+
lcp?: number;
|
|
79
|
+
/** Cumulative Layout Shift (score) */
|
|
80
|
+
cls?: number;
|
|
81
|
+
/** Time to First Byte (ms) */
|
|
82
|
+
ttfb?: number;
|
|
75
83
|
};
|
|
76
84
|
/** Browser/environment info */
|
|
77
85
|
environment?: {
|
|
@@ -80,6 +88,10 @@ interface EnhancedBugContext {
|
|
|
80
88
|
cookiesEnabled?: boolean;
|
|
81
89
|
localStorage?: boolean;
|
|
82
90
|
online?: boolean;
|
|
91
|
+
/** Effective connection type (e.g. '4g', '3g') */
|
|
92
|
+
connectionType?: string;
|
|
93
|
+
/** Downlink speed in Mbps */
|
|
94
|
+
connectionDownlink?: number;
|
|
83
95
|
};
|
|
84
96
|
}
|
|
85
97
|
interface DeviceInfo {
|
|
@@ -96,6 +108,13 @@ interface DeviceInfo {
|
|
|
96
108
|
width: number;
|
|
97
109
|
height: number;
|
|
98
110
|
};
|
|
111
|
+
/** Viewport dimensions (visible area) */
|
|
112
|
+
viewport?: {
|
|
113
|
+
width: number;
|
|
114
|
+
height: number;
|
|
115
|
+
};
|
|
116
|
+
/** Device pixel ratio */
|
|
117
|
+
devicePixelRatio?: number;
|
|
99
118
|
/** User agent (web) */
|
|
100
119
|
userAgent?: string;
|
|
101
120
|
}
|
|
@@ -296,6 +315,17 @@ interface MonitoringEvent {
|
|
|
296
315
|
clickCount?: number;
|
|
297
316
|
/** CSS selector of the clicked element (rage clicks only) */
|
|
298
317
|
targetSelector?: string;
|
|
318
|
+
/** Whether the tab was visible when the event fired */
|
|
319
|
+
tabVisible?: boolean;
|
|
320
|
+
/** CSS selector of the focused element at event time */
|
|
321
|
+
focusedElement?: string;
|
|
322
|
+
/** Rage click coordinates */
|
|
323
|
+
clickCoordinates?: {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
};
|
|
327
|
+
/** Response body snippet for API failures (max 300 chars) */
|
|
328
|
+
apiErrorBody?: string;
|
|
299
329
|
/** Sentry event ID — populated by @bbearai/sentry adapter */
|
|
300
330
|
sentryEventId?: string;
|
|
301
331
|
/** Sentry breadcrumbs — populated by @bbearai/sentry adapter */
|
|
@@ -1359,8 +1389,9 @@ declare class BugBearClient {
|
|
|
1359
1389
|
/**
|
|
1360
1390
|
* Get issue counts for the tester (Open, Done, Reopened)
|
|
1361
1391
|
* Used by the widget HomeScreen cards
|
|
1392
|
+
* @param mineOnly - If true (default), only counts the tester's own reports. If false, counts all project reports.
|
|
1362
1393
|
*/
|
|
1363
|
-
getIssueCounts(): Promise<{
|
|
1394
|
+
getIssueCounts(mineOnly?: boolean): Promise<{
|
|
1364
1395
|
open: number;
|
|
1365
1396
|
done: number;
|
|
1366
1397
|
reopened: number;
|
|
@@ -1369,8 +1400,9 @@ declare class BugBearClient {
|
|
|
1369
1400
|
* Get issues for the tester by category.
|
|
1370
1401
|
* Returns enriched data: done issues include verification proof,
|
|
1371
1402
|
* reopened issues include original bug context.
|
|
1403
|
+
* @param mineOnly - If true (default), only returns the tester's own reports. If false, returns all project reports.
|
|
1372
1404
|
*/
|
|
1373
|
-
getIssues(category: 'open' | 'done' | 'reopened'): Promise<TesterIssue[]>;
|
|
1405
|
+
getIssues(category: 'open' | 'done' | 'reopened', mineOnly?: boolean): Promise<TesterIssue[]>;
|
|
1374
1406
|
/**
|
|
1375
1407
|
* Reopen a done issue that the tester believes isn't actually fixed.
|
|
1376
1408
|
* Transitions the report from a done status back to 'confirmed'.
|
package/dist/index.d.ts
CHANGED
|
@@ -72,6 +72,14 @@ interface EnhancedBugContext {
|
|
|
72
72
|
pageLoadTime?: number;
|
|
73
73
|
memoryUsage?: number;
|
|
74
74
|
fps?: number;
|
|
75
|
+
/** First Contentful Paint (ms) */
|
|
76
|
+
fcp?: number;
|
|
77
|
+
/** Largest Contentful Paint (ms) */
|
|
78
|
+
lcp?: number;
|
|
79
|
+
/** Cumulative Layout Shift (score) */
|
|
80
|
+
cls?: number;
|
|
81
|
+
/** Time to First Byte (ms) */
|
|
82
|
+
ttfb?: number;
|
|
75
83
|
};
|
|
76
84
|
/** Browser/environment info */
|
|
77
85
|
environment?: {
|
|
@@ -80,6 +88,10 @@ interface EnhancedBugContext {
|
|
|
80
88
|
cookiesEnabled?: boolean;
|
|
81
89
|
localStorage?: boolean;
|
|
82
90
|
online?: boolean;
|
|
91
|
+
/** Effective connection type (e.g. '4g', '3g') */
|
|
92
|
+
connectionType?: string;
|
|
93
|
+
/** Downlink speed in Mbps */
|
|
94
|
+
connectionDownlink?: number;
|
|
83
95
|
};
|
|
84
96
|
}
|
|
85
97
|
interface DeviceInfo {
|
|
@@ -96,6 +108,13 @@ interface DeviceInfo {
|
|
|
96
108
|
width: number;
|
|
97
109
|
height: number;
|
|
98
110
|
};
|
|
111
|
+
/** Viewport dimensions (visible area) */
|
|
112
|
+
viewport?: {
|
|
113
|
+
width: number;
|
|
114
|
+
height: number;
|
|
115
|
+
};
|
|
116
|
+
/** Device pixel ratio */
|
|
117
|
+
devicePixelRatio?: number;
|
|
99
118
|
/** User agent (web) */
|
|
100
119
|
userAgent?: string;
|
|
101
120
|
}
|
|
@@ -296,6 +315,17 @@ interface MonitoringEvent {
|
|
|
296
315
|
clickCount?: number;
|
|
297
316
|
/** CSS selector of the clicked element (rage clicks only) */
|
|
298
317
|
targetSelector?: string;
|
|
318
|
+
/** Whether the tab was visible when the event fired */
|
|
319
|
+
tabVisible?: boolean;
|
|
320
|
+
/** CSS selector of the focused element at event time */
|
|
321
|
+
focusedElement?: string;
|
|
322
|
+
/** Rage click coordinates */
|
|
323
|
+
clickCoordinates?: {
|
|
324
|
+
x: number;
|
|
325
|
+
y: number;
|
|
326
|
+
};
|
|
327
|
+
/** Response body snippet for API failures (max 300 chars) */
|
|
328
|
+
apiErrorBody?: string;
|
|
299
329
|
/** Sentry event ID — populated by @bbearai/sentry adapter */
|
|
300
330
|
sentryEventId?: string;
|
|
301
331
|
/** Sentry breadcrumbs — populated by @bbearai/sentry adapter */
|
|
@@ -1359,8 +1389,9 @@ declare class BugBearClient {
|
|
|
1359
1389
|
/**
|
|
1360
1390
|
* Get issue counts for the tester (Open, Done, Reopened)
|
|
1361
1391
|
* Used by the widget HomeScreen cards
|
|
1392
|
+
* @param mineOnly - If true (default), only counts the tester's own reports. If false, counts all project reports.
|
|
1362
1393
|
*/
|
|
1363
|
-
getIssueCounts(): Promise<{
|
|
1394
|
+
getIssueCounts(mineOnly?: boolean): Promise<{
|
|
1364
1395
|
open: number;
|
|
1365
1396
|
done: number;
|
|
1366
1397
|
reopened: number;
|
|
@@ -1369,8 +1400,9 @@ declare class BugBearClient {
|
|
|
1369
1400
|
* Get issues for the tester by category.
|
|
1370
1401
|
* Returns enriched data: done issues include verification proof,
|
|
1371
1402
|
* reopened issues include original bug context.
|
|
1403
|
+
* @param mineOnly - If true (default), only returns the tester's own reports. If false, returns all project reports.
|
|
1372
1404
|
*/
|
|
1373
|
-
getIssues(category: 'open' | 'done' | 'reopened'): Promise<TesterIssue[]>;
|
|
1405
|
+
getIssues(category: 'open' | 'done' | 'reopened', mineOnly?: boolean): Promise<TesterIssue[]>;
|
|
1374
1406
|
/**
|
|
1375
1407
|
* Reopen a done issue that the tester believes isn't actually fixed.
|
|
1376
1408
|
* Transitions the report from a done status back to 'confirmed'.
|
package/dist/index.js
CHANGED
|
@@ -279,17 +279,43 @@ var ContextCaptureManager = class {
|
|
|
279
279
|
}
|
|
280
280
|
} catch {
|
|
281
281
|
}
|
|
282
|
+
try {
|
|
283
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
284
|
+
if (navigation) {
|
|
285
|
+
metrics.ttfb = Math.round(navigation.responseStart - navigation.startTime);
|
|
286
|
+
}
|
|
287
|
+
const paintEntries = performance.getEntriesByType("paint");
|
|
288
|
+
const fcp = paintEntries.find((e) => e.name === "first-contentful-paint");
|
|
289
|
+
if (fcp) metrics.fcp = Math.round(fcp.startTime);
|
|
290
|
+
const lcpEntries = performance.getEntriesByType("largest-contentful-paint");
|
|
291
|
+
if (lcpEntries.length > 0) {
|
|
292
|
+
metrics.lcp = Math.round(lcpEntries[lcpEntries.length - 1].startTime);
|
|
293
|
+
}
|
|
294
|
+
const clsEntries = performance.getEntriesByType("layout-shift");
|
|
295
|
+
if (clsEntries.length > 0) {
|
|
296
|
+
metrics.cls = parseFloat(
|
|
297
|
+
clsEntries.filter((e) => !e.hadRecentInput).reduce((sum, e) => sum + (e.value ?? 0), 0).toFixed(4)
|
|
298
|
+
);
|
|
299
|
+
}
|
|
300
|
+
} catch {
|
|
301
|
+
}
|
|
282
302
|
return Object.keys(metrics).length > 0 ? metrics : void 0;
|
|
283
303
|
}
|
|
284
304
|
getEnvironmentInfo() {
|
|
285
305
|
if (typeof window === "undefined" || typeof navigator === "undefined" || typeof document === "undefined") return void 0;
|
|
286
|
-
|
|
306
|
+
const env = {
|
|
287
307
|
language: navigator.language,
|
|
288
308
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
289
309
|
cookiesEnabled: navigator.cookieEnabled ?? false,
|
|
290
310
|
localStorage: typeof localStorage !== "undefined",
|
|
291
311
|
online: navigator.onLine ?? true
|
|
292
312
|
};
|
|
313
|
+
const conn = navigator.connection;
|
|
314
|
+
if (conn) {
|
|
315
|
+
env.connectionType = conn.effectiveType;
|
|
316
|
+
env.connectionDownlink = conn.downlink;
|
|
317
|
+
}
|
|
318
|
+
return env;
|
|
293
319
|
}
|
|
294
320
|
};
|
|
295
321
|
var contextCapture = new ContextCaptureManager();
|
|
@@ -571,6 +597,10 @@ var ErrorMonitor = class {
|
|
|
571
597
|
...event.requestMethod ? { requestMethod: event.requestMethod } : {},
|
|
572
598
|
...event.clickCount ? { clickCount: event.clickCount } : {},
|
|
573
599
|
...event.targetSelector ? { targetSelector: event.targetSelector } : {},
|
|
600
|
+
...event.tabVisible !== void 0 ? { tabVisible: event.tabVisible } : {},
|
|
601
|
+
...event.focusedElement ? { focusedElement: event.focusedElement } : {},
|
|
602
|
+
...event.clickCoordinates ? { clickCoordinates: event.clickCoordinates } : {},
|
|
603
|
+
...event.apiErrorBody ? { apiErrorBody: event.apiErrorBody } : {},
|
|
574
604
|
...event.sentryEventId ? { sentryEventId: event.sentryEventId } : {}
|
|
575
605
|
}
|
|
576
606
|
},
|
|
@@ -664,7 +694,9 @@ var WebCrashHandler = class {
|
|
|
664
694
|
message: msg,
|
|
665
695
|
route,
|
|
666
696
|
timestamp: Date.now(),
|
|
667
|
-
error: error ?? new Error(msg)
|
|
697
|
+
error: error ?? new Error(msg),
|
|
698
|
+
tabVisible: !document.hidden,
|
|
699
|
+
focusedElement: document.activeElement instanceof Element ? getSelector(document.activeElement) : void 0
|
|
668
700
|
});
|
|
669
701
|
if (typeof this.prevOnError === "function") {
|
|
670
702
|
return this.prevOnError(message, source, lineno, colno, error);
|
|
@@ -682,7 +714,9 @@ var WebCrashHandler = class {
|
|
|
682
714
|
message: msg,
|
|
683
715
|
route,
|
|
684
716
|
timestamp: Date.now(),
|
|
685
|
-
error
|
|
717
|
+
error,
|
|
718
|
+
tabVisible: !document.hidden,
|
|
719
|
+
focusedElement: document.activeElement instanceof Element ? getSelector(document.activeElement) : void 0
|
|
686
720
|
});
|
|
687
721
|
};
|
|
688
722
|
window.addEventListener("unhandledrejection", this.rejectionHandler);
|
|
@@ -711,6 +745,13 @@ var WebApiFailureHandler = class {
|
|
|
711
745
|
const method = (init?.method ?? "GET").toUpperCase();
|
|
712
746
|
const route = currentRoute();
|
|
713
747
|
const msg = `${method} ${url} failed with ${response.status}`;
|
|
748
|
+
let apiErrorBody;
|
|
749
|
+
try {
|
|
750
|
+
const cloned = response.clone();
|
|
751
|
+
const text = await cloned.text();
|
|
752
|
+
if (text) apiErrorBody = text.slice(0, 300);
|
|
753
|
+
} catch {
|
|
754
|
+
}
|
|
714
755
|
onEvent({
|
|
715
756
|
source: "api_failure",
|
|
716
757
|
fingerprint: generateFingerprint("api_failure", msg, route),
|
|
@@ -719,7 +760,9 @@ var WebApiFailureHandler = class {
|
|
|
719
760
|
timestamp: Date.now(),
|
|
720
761
|
requestUrl: url,
|
|
721
762
|
requestMethod: method,
|
|
722
|
-
statusCode: response.status
|
|
763
|
+
statusCode: response.status,
|
|
764
|
+
tabVisible: !document.hidden,
|
|
765
|
+
apiErrorBody
|
|
723
766
|
});
|
|
724
767
|
}
|
|
725
768
|
return response;
|
|
@@ -745,7 +788,8 @@ var WebRageClickHandler = class {
|
|
|
745
788
|
route,
|
|
746
789
|
timestamp: Date.now(),
|
|
747
790
|
clickCount: rageEvent.clickCount,
|
|
748
|
-
targetSelector: rageEvent.targetSelector
|
|
791
|
+
targetSelector: rageEvent.targetSelector,
|
|
792
|
+
clickCoordinates: { x: rageEvent.x, y: rageEvent.y }
|
|
749
793
|
});
|
|
750
794
|
});
|
|
751
795
|
}
|
|
@@ -1993,14 +2037,16 @@ var BugBearClient = class {
|
|
|
1993
2037
|
/**
|
|
1994
2038
|
* Get issue counts for the tester (Open, Done, Reopened)
|
|
1995
2039
|
* Used by the widget HomeScreen cards
|
|
2040
|
+
* @param mineOnly - If true (default), only counts the tester's own reports. If false, counts all project reports.
|
|
1996
2041
|
*/
|
|
1997
|
-
async getIssueCounts() {
|
|
2042
|
+
async getIssueCounts(mineOnly = true) {
|
|
1998
2043
|
try {
|
|
1999
2044
|
const testerInfo = await this.getTesterInfo();
|
|
2000
2045
|
if (!testerInfo) return { open: 0, done: 0, reopened: 0 };
|
|
2001
2046
|
const { data, error } = await this.supabase.rpc("get_tester_issue_counts", {
|
|
2002
2047
|
p_project_id: this.config.projectId,
|
|
2003
|
-
p_tester_id: testerInfo.id
|
|
2048
|
+
p_tester_id: testerInfo.id,
|
|
2049
|
+
p_mine_only: mineOnly
|
|
2004
2050
|
});
|
|
2005
2051
|
if (error) {
|
|
2006
2052
|
console.error("BugBear: Failed to fetch issue counts", formatPgError(error));
|
|
@@ -2020,15 +2066,17 @@ var BugBearClient = class {
|
|
|
2020
2066
|
* Get issues for the tester by category.
|
|
2021
2067
|
* Returns enriched data: done issues include verification proof,
|
|
2022
2068
|
* reopened issues include original bug context.
|
|
2069
|
+
* @param mineOnly - If true (default), only returns the tester's own reports. If false, returns all project reports.
|
|
2023
2070
|
*/
|
|
2024
|
-
async getIssues(category) {
|
|
2071
|
+
async getIssues(category, mineOnly = true) {
|
|
2025
2072
|
try {
|
|
2026
2073
|
const testerInfo = await this.getTesterInfo();
|
|
2027
2074
|
if (!testerInfo) return [];
|
|
2028
2075
|
const { data, error } = await this.supabase.rpc("get_tester_issues", {
|
|
2029
2076
|
p_project_id: this.config.projectId,
|
|
2030
2077
|
p_tester_id: testerInfo.id,
|
|
2031
|
-
p_category: category
|
|
2078
|
+
p_category: category,
|
|
2079
|
+
p_mine_only: mineOnly
|
|
2032
2080
|
});
|
|
2033
2081
|
if (error) {
|
|
2034
2082
|
console.error("BugBear: Failed to fetch issues", formatPgError(error));
|
|
@@ -2505,6 +2553,8 @@ var BugBearClient = class {
|
|
|
2505
2553
|
height: window.screen.height
|
|
2506
2554
|
};
|
|
2507
2555
|
}
|
|
2556
|
+
info.viewport = { width: window.innerWidth, height: window.innerHeight };
|
|
2557
|
+
info.devicePixelRatio = window.devicePixelRatio;
|
|
2508
2558
|
return info;
|
|
2509
2559
|
}
|
|
2510
2560
|
return { platform: "web" };
|
package/dist/index.mjs
CHANGED
|
@@ -233,17 +233,43 @@ var ContextCaptureManager = class {
|
|
|
233
233
|
}
|
|
234
234
|
} catch {
|
|
235
235
|
}
|
|
236
|
+
try {
|
|
237
|
+
const navigation = performance.getEntriesByType("navigation")[0];
|
|
238
|
+
if (navigation) {
|
|
239
|
+
metrics.ttfb = Math.round(navigation.responseStart - navigation.startTime);
|
|
240
|
+
}
|
|
241
|
+
const paintEntries = performance.getEntriesByType("paint");
|
|
242
|
+
const fcp = paintEntries.find((e) => e.name === "first-contentful-paint");
|
|
243
|
+
if (fcp) metrics.fcp = Math.round(fcp.startTime);
|
|
244
|
+
const lcpEntries = performance.getEntriesByType("largest-contentful-paint");
|
|
245
|
+
if (lcpEntries.length > 0) {
|
|
246
|
+
metrics.lcp = Math.round(lcpEntries[lcpEntries.length - 1].startTime);
|
|
247
|
+
}
|
|
248
|
+
const clsEntries = performance.getEntriesByType("layout-shift");
|
|
249
|
+
if (clsEntries.length > 0) {
|
|
250
|
+
metrics.cls = parseFloat(
|
|
251
|
+
clsEntries.filter((e) => !e.hadRecentInput).reduce((sum, e) => sum + (e.value ?? 0), 0).toFixed(4)
|
|
252
|
+
);
|
|
253
|
+
}
|
|
254
|
+
} catch {
|
|
255
|
+
}
|
|
236
256
|
return Object.keys(metrics).length > 0 ? metrics : void 0;
|
|
237
257
|
}
|
|
238
258
|
getEnvironmentInfo() {
|
|
239
259
|
if (typeof window === "undefined" || typeof navigator === "undefined" || typeof document === "undefined") return void 0;
|
|
240
|
-
|
|
260
|
+
const env = {
|
|
241
261
|
language: navigator.language,
|
|
242
262
|
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
|
|
243
263
|
cookiesEnabled: navigator.cookieEnabled ?? false,
|
|
244
264
|
localStorage: typeof localStorage !== "undefined",
|
|
245
265
|
online: navigator.onLine ?? true
|
|
246
266
|
};
|
|
267
|
+
const conn = navigator.connection;
|
|
268
|
+
if (conn) {
|
|
269
|
+
env.connectionType = conn.effectiveType;
|
|
270
|
+
env.connectionDownlink = conn.downlink;
|
|
271
|
+
}
|
|
272
|
+
return env;
|
|
247
273
|
}
|
|
248
274
|
};
|
|
249
275
|
var contextCapture = new ContextCaptureManager();
|
|
@@ -525,6 +551,10 @@ var ErrorMonitor = class {
|
|
|
525
551
|
...event.requestMethod ? { requestMethod: event.requestMethod } : {},
|
|
526
552
|
...event.clickCount ? { clickCount: event.clickCount } : {},
|
|
527
553
|
...event.targetSelector ? { targetSelector: event.targetSelector } : {},
|
|
554
|
+
...event.tabVisible !== void 0 ? { tabVisible: event.tabVisible } : {},
|
|
555
|
+
...event.focusedElement ? { focusedElement: event.focusedElement } : {},
|
|
556
|
+
...event.clickCoordinates ? { clickCoordinates: event.clickCoordinates } : {},
|
|
557
|
+
...event.apiErrorBody ? { apiErrorBody: event.apiErrorBody } : {},
|
|
528
558
|
...event.sentryEventId ? { sentryEventId: event.sentryEventId } : {}
|
|
529
559
|
}
|
|
530
560
|
},
|
|
@@ -618,7 +648,9 @@ var WebCrashHandler = class {
|
|
|
618
648
|
message: msg,
|
|
619
649
|
route,
|
|
620
650
|
timestamp: Date.now(),
|
|
621
|
-
error: error ?? new Error(msg)
|
|
651
|
+
error: error ?? new Error(msg),
|
|
652
|
+
tabVisible: !document.hidden,
|
|
653
|
+
focusedElement: document.activeElement instanceof Element ? getSelector(document.activeElement) : void 0
|
|
622
654
|
});
|
|
623
655
|
if (typeof this.prevOnError === "function") {
|
|
624
656
|
return this.prevOnError(message, source, lineno, colno, error);
|
|
@@ -636,7 +668,9 @@ var WebCrashHandler = class {
|
|
|
636
668
|
message: msg,
|
|
637
669
|
route,
|
|
638
670
|
timestamp: Date.now(),
|
|
639
|
-
error
|
|
671
|
+
error,
|
|
672
|
+
tabVisible: !document.hidden,
|
|
673
|
+
focusedElement: document.activeElement instanceof Element ? getSelector(document.activeElement) : void 0
|
|
640
674
|
});
|
|
641
675
|
};
|
|
642
676
|
window.addEventListener("unhandledrejection", this.rejectionHandler);
|
|
@@ -665,6 +699,13 @@ var WebApiFailureHandler = class {
|
|
|
665
699
|
const method = (init?.method ?? "GET").toUpperCase();
|
|
666
700
|
const route = currentRoute();
|
|
667
701
|
const msg = `${method} ${url} failed with ${response.status}`;
|
|
702
|
+
let apiErrorBody;
|
|
703
|
+
try {
|
|
704
|
+
const cloned = response.clone();
|
|
705
|
+
const text = await cloned.text();
|
|
706
|
+
if (text) apiErrorBody = text.slice(0, 300);
|
|
707
|
+
} catch {
|
|
708
|
+
}
|
|
668
709
|
onEvent({
|
|
669
710
|
source: "api_failure",
|
|
670
711
|
fingerprint: generateFingerprint("api_failure", msg, route),
|
|
@@ -673,7 +714,9 @@ var WebApiFailureHandler = class {
|
|
|
673
714
|
timestamp: Date.now(),
|
|
674
715
|
requestUrl: url,
|
|
675
716
|
requestMethod: method,
|
|
676
|
-
statusCode: response.status
|
|
717
|
+
statusCode: response.status,
|
|
718
|
+
tabVisible: !document.hidden,
|
|
719
|
+
apiErrorBody
|
|
677
720
|
});
|
|
678
721
|
}
|
|
679
722
|
return response;
|
|
@@ -699,7 +742,8 @@ var WebRageClickHandler = class {
|
|
|
699
742
|
route,
|
|
700
743
|
timestamp: Date.now(),
|
|
701
744
|
clickCount: rageEvent.clickCount,
|
|
702
|
-
targetSelector: rageEvent.targetSelector
|
|
745
|
+
targetSelector: rageEvent.targetSelector,
|
|
746
|
+
clickCoordinates: { x: rageEvent.x, y: rageEvent.y }
|
|
703
747
|
});
|
|
704
748
|
});
|
|
705
749
|
}
|
|
@@ -1947,14 +1991,16 @@ var BugBearClient = class {
|
|
|
1947
1991
|
/**
|
|
1948
1992
|
* Get issue counts for the tester (Open, Done, Reopened)
|
|
1949
1993
|
* Used by the widget HomeScreen cards
|
|
1994
|
+
* @param mineOnly - If true (default), only counts the tester's own reports. If false, counts all project reports.
|
|
1950
1995
|
*/
|
|
1951
|
-
async getIssueCounts() {
|
|
1996
|
+
async getIssueCounts(mineOnly = true) {
|
|
1952
1997
|
try {
|
|
1953
1998
|
const testerInfo = await this.getTesterInfo();
|
|
1954
1999
|
if (!testerInfo) return { open: 0, done: 0, reopened: 0 };
|
|
1955
2000
|
const { data, error } = await this.supabase.rpc("get_tester_issue_counts", {
|
|
1956
2001
|
p_project_id: this.config.projectId,
|
|
1957
|
-
p_tester_id: testerInfo.id
|
|
2002
|
+
p_tester_id: testerInfo.id,
|
|
2003
|
+
p_mine_only: mineOnly
|
|
1958
2004
|
});
|
|
1959
2005
|
if (error) {
|
|
1960
2006
|
console.error("BugBear: Failed to fetch issue counts", formatPgError(error));
|
|
@@ -1974,15 +2020,17 @@ var BugBearClient = class {
|
|
|
1974
2020
|
* Get issues for the tester by category.
|
|
1975
2021
|
* Returns enriched data: done issues include verification proof,
|
|
1976
2022
|
* reopened issues include original bug context.
|
|
2023
|
+
* @param mineOnly - If true (default), only returns the tester's own reports. If false, returns all project reports.
|
|
1977
2024
|
*/
|
|
1978
|
-
async getIssues(category) {
|
|
2025
|
+
async getIssues(category, mineOnly = true) {
|
|
1979
2026
|
try {
|
|
1980
2027
|
const testerInfo = await this.getTesterInfo();
|
|
1981
2028
|
if (!testerInfo) return [];
|
|
1982
2029
|
const { data, error } = await this.supabase.rpc("get_tester_issues", {
|
|
1983
2030
|
p_project_id: this.config.projectId,
|
|
1984
2031
|
p_tester_id: testerInfo.id,
|
|
1985
|
-
p_category: category
|
|
2032
|
+
p_category: category,
|
|
2033
|
+
p_mine_only: mineOnly
|
|
1986
2034
|
});
|
|
1987
2035
|
if (error) {
|
|
1988
2036
|
console.error("BugBear: Failed to fetch issues", formatPgError(error));
|
|
@@ -2459,6 +2507,8 @@ var BugBearClient = class {
|
|
|
2459
2507
|
height: window.screen.height
|
|
2460
2508
|
};
|
|
2461
2509
|
}
|
|
2510
|
+
info.viewport = { width: window.innerWidth, height: window.innerHeight };
|
|
2511
|
+
info.devicePixelRatio = window.devicePixelRatio;
|
|
2462
2512
|
return info;
|
|
2463
2513
|
}
|
|
2464
2514
|
return { platform: "web" };
|