@bbearai/core 0.9.5 → 0.9.7

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 CHANGED
@@ -413,6 +413,16 @@ interface TestAssignment {
413
413
  isVerification?: boolean;
414
414
  /** Original report ID if this is a verification assignment */
415
415
  originalReportId?: string;
416
+ /** Original bug report data (populated for verification assignments) */
417
+ originalReport?: {
418
+ id: string;
419
+ title: string;
420
+ description: string;
421
+ severity: Severity | null;
422
+ screenshotUrls: string[];
423
+ resolutionNotes?: string;
424
+ route?: string;
425
+ };
416
426
  }
417
427
  interface TestStep {
418
428
  stepNumber: number;
@@ -1280,6 +1290,20 @@ declare class BugBearClient {
1280
1290
  queued?: boolean;
1281
1291
  error?: string;
1282
1292
  }>;
1293
+ /**
1294
+ * Submit feedback about the BugBear widget itself.
1295
+ * Sends to BugBear's own internal project via a dedicated API endpoint.
1296
+ */
1297
+ submitWidgetFeedback(feedback: {
1298
+ description: string;
1299
+ type: 'bug' | 'feedback' | 'suggestion';
1300
+ severity?: Severity;
1301
+ title?: string;
1302
+ screenshots?: string[];
1303
+ }): Promise<{
1304
+ success: boolean;
1305
+ error?: string;
1306
+ }>;
1283
1307
  /**
1284
1308
  * Capture an email for QA testing.
1285
1309
  * Called by the email interceptor — not typically called directly.
package/dist/index.d.ts CHANGED
@@ -413,6 +413,16 @@ interface TestAssignment {
413
413
  isVerification?: boolean;
414
414
  /** Original report ID if this is a verification assignment */
415
415
  originalReportId?: string;
416
+ /** Original bug report data (populated for verification assignments) */
417
+ originalReport?: {
418
+ id: string;
419
+ title: string;
420
+ description: string;
421
+ severity: Severity | null;
422
+ screenshotUrls: string[];
423
+ resolutionNotes?: string;
424
+ route?: string;
425
+ };
416
426
  }
417
427
  interface TestStep {
418
428
  stepNumber: number;
@@ -1280,6 +1290,20 @@ declare class BugBearClient {
1280
1290
  queued?: boolean;
1281
1291
  error?: string;
1282
1292
  }>;
1293
+ /**
1294
+ * Submit feedback about the BugBear widget itself.
1295
+ * Sends to BugBear's own internal project via a dedicated API endpoint.
1296
+ */
1297
+ submitWidgetFeedback(feedback: {
1298
+ description: string;
1299
+ type: 'bug' | 'feedback' | 'suggestion';
1300
+ severity?: Severity;
1301
+ title?: string;
1302
+ screenshots?: string[];
1303
+ }): Promise<{
1304
+ success: boolean;
1305
+ error?: string;
1306
+ }>;
1283
1307
  /**
1284
1308
  * Capture an email for QA testing.
1285
1309
  * Called by the email interceptor — not typically called directly.
package/dist/index.js CHANGED
@@ -1200,12 +1200,12 @@ var BugBearClient = class {
1200
1200
  return { success: true };
1201
1201
  });
1202
1202
  this._queue.registerHandler("message", async (payload) => {
1203
- const { error } = await this.supabase.from("discussion_messages").insert(payload);
1203
+ const { error } = await this.supabase.from("discussion_messages").insert(payload).select("id").single();
1204
1204
  if (error) return { success: false, error: error.message };
1205
1205
  return { success: true };
1206
1206
  });
1207
1207
  this._queue.registerHandler("feedback", async (payload) => {
1208
- const { error } = await this.supabase.from("test_feedback").insert(payload);
1208
+ const { error } = await this.supabase.from("test_feedback").insert(payload).select("id").single();
1209
1209
  if (error) return { success: false, error: error.message };
1210
1210
  return { success: true };
1211
1211
  });
@@ -1229,6 +1229,8 @@ var BugBearClient = class {
1229
1229
  subscribeToChanges(callbacks) {
1230
1230
  this.unsubscribeAll();
1231
1231
  const projectId = this.config.projectId;
1232
+ if (!projectId) return () => {
1233
+ };
1232
1234
  const debounce = (fn, ms = 500) => {
1233
1235
  let timer;
1234
1236
  return () => {
@@ -1352,7 +1354,7 @@ var BugBearClient = class {
1352
1354
  return { success: false, error: validationError };
1353
1355
  }
1354
1356
  const userInfo = await this.getCurrentUserInfo();
1355
- const rateLimitId = userInfo?.email || this.config.projectId;
1357
+ const rateLimitId = userInfo?.email || this.config.projectId || "unknown";
1356
1358
  const rateLimit = await this.checkRateLimit(rateLimitId, "report_submit");
1357
1359
  if (!rateLimit.allowed) {
1358
1360
  return { success: false, error: rateLimit.error };
@@ -1415,6 +1417,43 @@ var BugBearClient = class {
1415
1417
  this.reportSubmitInFlight = false;
1416
1418
  }
1417
1419
  }
1420
+ /**
1421
+ * Submit feedback about the BugBear widget itself.
1422
+ * Sends to BugBear's own internal project via a dedicated API endpoint.
1423
+ */
1424
+ async submitWidgetFeedback(feedback) {
1425
+ try {
1426
+ await this.ready();
1427
+ const baseUrl = (this.config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, "");
1428
+ const testerInfo = await this.getTesterInfo();
1429
+ const response = await fetch(`${baseUrl}/api/v1/widget-feedback`, {
1430
+ method: "POST",
1431
+ headers: {
1432
+ "Content-Type": "application/json",
1433
+ ...this.config.apiKey ? { "Authorization": `Bearer ${this.config.apiKey}` } : {}
1434
+ },
1435
+ body: JSON.stringify({
1436
+ description: feedback.description,
1437
+ type: feedback.type,
1438
+ severity: feedback.severity,
1439
+ title: feedback.title,
1440
+ screenshots: feedback.screenshots,
1441
+ deviceInfo: this.getDeviceInfo(),
1442
+ appContext: this.getAppContext(),
1443
+ reporterName: testerInfo?.name || null,
1444
+ reporterEmail: testerInfo?.email || null
1445
+ })
1446
+ });
1447
+ if (!response.ok) {
1448
+ const body = await response.json().catch(() => ({}));
1449
+ return { success: false, error: body.error || `HTTP ${response.status}` };
1450
+ }
1451
+ return { success: true };
1452
+ } catch (err) {
1453
+ const message = err instanceof Error ? err.message : "Widget feedback submission failed";
1454
+ return { success: false, error: message };
1455
+ }
1456
+ }
1418
1457
  /**
1419
1458
  * Capture an email for QA testing.
1420
1459
  * Called by the email interceptor — not typically called directly.
@@ -1473,6 +1512,15 @@ var BugBearClient = class {
1473
1512
  is_verification,
1474
1513
  original_report_id,
1475
1514
  notes,
1515
+ original_report:reports(
1516
+ id,
1517
+ title,
1518
+ description,
1519
+ severity,
1520
+ screenshot_urls,
1521
+ resolution_notes,
1522
+ app_context
1523
+ ),
1476
1524
  test_case:test_cases(
1477
1525
  id,
1478
1526
  title,
@@ -1522,6 +1570,16 @@ var BugBearClient = class {
1522
1570
  ];
1523
1571
  const mapItem = (item) => {
1524
1572
  const tc = item.test_case;
1573
+ const rpt = item.original_report;
1574
+ const originalReport = rpt ? {
1575
+ id: rpt.id,
1576
+ title: rpt.title,
1577
+ description: rpt.description,
1578
+ severity: rpt.severity,
1579
+ screenshotUrls: rpt.screenshot_urls || [],
1580
+ resolutionNotes: rpt.resolution_notes || void 0,
1581
+ route: rpt.app_context?.currentRoute || void 0
1582
+ } : void 0;
1525
1583
  return {
1526
1584
  id: item.id,
1527
1585
  status: item.status,
@@ -1529,6 +1587,7 @@ var BugBearClient = class {
1529
1587
  skipReason: item.skip_reason,
1530
1588
  isVerification: item.is_verification || false,
1531
1589
  originalReportId: item.original_report_id,
1590
+ originalReport,
1532
1591
  testCase: tc ? {
1533
1592
  id: tc.id,
1534
1593
  title: tc.title,
@@ -1563,15 +1622,15 @@ var BugBearClient = class {
1563
1622
  } : void 0,
1564
1623
  platforms: tc.platforms || void 0
1565
1624
  } : {
1566
- // Standalone verification assignment (bug reported without a test case)
1625
+ // Standalone verification use original report data when available
1567
1626
  id: item.original_report_id || item.id,
1568
- title: item.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification",
1627
+ title: rpt?.title || (item.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification"),
1569
1628
  testKey: "VERIFY",
1570
- description: "Verify that the reported bug has been fixed",
1629
+ description: rpt?.description || "Verify that the reported bug has been fixed",
1571
1630
  steps: [],
1572
1631
  expectedResult: "The bug should no longer be reproducible",
1573
1632
  priority: "P1",
1574
- targetRoute: void 0,
1633
+ targetRoute: rpt?.app_context?.currentRoute || void 0,
1575
1634
  track: void 0,
1576
1635
  group: void 0,
1577
1636
  role: void 0,
@@ -1607,6 +1666,18 @@ var BugBearClient = class {
1607
1666
  started_at,
1608
1667
  completed_at,
1609
1668
  duration_seconds,
1669
+ is_verification,
1670
+ original_report_id,
1671
+ notes,
1672
+ original_report:reports(
1673
+ id,
1674
+ title,
1675
+ description,
1676
+ severity,
1677
+ screenshot_urls,
1678
+ resolution_notes,
1679
+ app_context
1680
+ ),
1610
1681
  test_case:test_cases(
1611
1682
  id,
1612
1683
  title,
@@ -1629,17 +1700,30 @@ var BugBearClient = class {
1629
1700
  `).eq("id", assignmentId).single();
1630
1701
  if (error || !data) return null;
1631
1702
  const testCase = data.test_case;
1632
- if (!testCase) {
1703
+ const rpt = data.original_report;
1704
+ const originalReport = rpt ? {
1705
+ id: rpt.id,
1706
+ title: rpt.title,
1707
+ description: rpt.description,
1708
+ severity: rpt.severity,
1709
+ screenshotUrls: rpt.screenshot_urls || [],
1710
+ resolutionNotes: rpt.resolution_notes || void 0,
1711
+ route: rpt.app_context?.currentRoute || void 0
1712
+ } : void 0;
1713
+ if (!testCase && !data.is_verification) {
1633
1714
  console.error("BugBear: Assignment returned without test_case");
1634
1715
  return null;
1635
1716
  }
1636
- const track = testCase.track;
1717
+ const track = testCase?.track;
1637
1718
  return {
1638
1719
  id: data.id,
1639
1720
  status: data.status,
1640
1721
  startedAt: data.started_at,
1641
1722
  durationSeconds: data.duration_seconds,
1642
- testCase: {
1723
+ isVerification: data.is_verification || false,
1724
+ originalReportId: data.original_report_id,
1725
+ originalReport,
1726
+ testCase: testCase ? {
1643
1727
  id: testCase.id,
1644
1728
  title: testCase.title,
1645
1729
  testKey: testCase.test_key,
@@ -1657,6 +1741,16 @@ var BugBearClient = class {
1657
1741
  rubricMode: track.rubric_mode || "pass_fail",
1658
1742
  description: track.description
1659
1743
  } : void 0
1744
+ } : {
1745
+ id: data.original_report_id || data.id,
1746
+ title: rpt?.title || (data.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification"),
1747
+ testKey: "VERIFY",
1748
+ description: rpt?.description || "Verify that the reported bug has been fixed",
1749
+ steps: [],
1750
+ expectedResult: "The bug should no longer be reproducible",
1751
+ priority: "P1",
1752
+ targetRoute: rpt?.app_context?.currentRoute || void 0,
1753
+ track: void 0
1660
1754
  }
1661
1755
  };
1662
1756
  } catch (err) {
package/dist/index.mjs CHANGED
@@ -1154,12 +1154,12 @@ var BugBearClient = class {
1154
1154
  return { success: true };
1155
1155
  });
1156
1156
  this._queue.registerHandler("message", async (payload) => {
1157
- const { error } = await this.supabase.from("discussion_messages").insert(payload);
1157
+ const { error } = await this.supabase.from("discussion_messages").insert(payload).select("id").single();
1158
1158
  if (error) return { success: false, error: error.message };
1159
1159
  return { success: true };
1160
1160
  });
1161
1161
  this._queue.registerHandler("feedback", async (payload) => {
1162
- const { error } = await this.supabase.from("test_feedback").insert(payload);
1162
+ const { error } = await this.supabase.from("test_feedback").insert(payload).select("id").single();
1163
1163
  if (error) return { success: false, error: error.message };
1164
1164
  return { success: true };
1165
1165
  });
@@ -1183,6 +1183,8 @@ var BugBearClient = class {
1183
1183
  subscribeToChanges(callbacks) {
1184
1184
  this.unsubscribeAll();
1185
1185
  const projectId = this.config.projectId;
1186
+ if (!projectId) return () => {
1187
+ };
1186
1188
  const debounce = (fn, ms = 500) => {
1187
1189
  let timer;
1188
1190
  return () => {
@@ -1306,7 +1308,7 @@ var BugBearClient = class {
1306
1308
  return { success: false, error: validationError };
1307
1309
  }
1308
1310
  const userInfo = await this.getCurrentUserInfo();
1309
- const rateLimitId = userInfo?.email || this.config.projectId;
1311
+ const rateLimitId = userInfo?.email || this.config.projectId || "unknown";
1310
1312
  const rateLimit = await this.checkRateLimit(rateLimitId, "report_submit");
1311
1313
  if (!rateLimit.allowed) {
1312
1314
  return { success: false, error: rateLimit.error };
@@ -1369,6 +1371,43 @@ var BugBearClient = class {
1369
1371
  this.reportSubmitInFlight = false;
1370
1372
  }
1371
1373
  }
1374
+ /**
1375
+ * Submit feedback about the BugBear widget itself.
1376
+ * Sends to BugBear's own internal project via a dedicated API endpoint.
1377
+ */
1378
+ async submitWidgetFeedback(feedback) {
1379
+ try {
1380
+ await this.ready();
1381
+ const baseUrl = (this.config.apiBaseUrl || DEFAULT_API_BASE_URL).replace(/\/$/, "");
1382
+ const testerInfo = await this.getTesterInfo();
1383
+ const response = await fetch(`${baseUrl}/api/v1/widget-feedback`, {
1384
+ method: "POST",
1385
+ headers: {
1386
+ "Content-Type": "application/json",
1387
+ ...this.config.apiKey ? { "Authorization": `Bearer ${this.config.apiKey}` } : {}
1388
+ },
1389
+ body: JSON.stringify({
1390
+ description: feedback.description,
1391
+ type: feedback.type,
1392
+ severity: feedback.severity,
1393
+ title: feedback.title,
1394
+ screenshots: feedback.screenshots,
1395
+ deviceInfo: this.getDeviceInfo(),
1396
+ appContext: this.getAppContext(),
1397
+ reporterName: testerInfo?.name || null,
1398
+ reporterEmail: testerInfo?.email || null
1399
+ })
1400
+ });
1401
+ if (!response.ok) {
1402
+ const body = await response.json().catch(() => ({}));
1403
+ return { success: false, error: body.error || `HTTP ${response.status}` };
1404
+ }
1405
+ return { success: true };
1406
+ } catch (err) {
1407
+ const message = err instanceof Error ? err.message : "Widget feedback submission failed";
1408
+ return { success: false, error: message };
1409
+ }
1410
+ }
1372
1411
  /**
1373
1412
  * Capture an email for QA testing.
1374
1413
  * Called by the email interceptor — not typically called directly.
@@ -1427,6 +1466,15 @@ var BugBearClient = class {
1427
1466
  is_verification,
1428
1467
  original_report_id,
1429
1468
  notes,
1469
+ original_report:reports(
1470
+ id,
1471
+ title,
1472
+ description,
1473
+ severity,
1474
+ screenshot_urls,
1475
+ resolution_notes,
1476
+ app_context
1477
+ ),
1430
1478
  test_case:test_cases(
1431
1479
  id,
1432
1480
  title,
@@ -1476,6 +1524,16 @@ var BugBearClient = class {
1476
1524
  ];
1477
1525
  const mapItem = (item) => {
1478
1526
  const tc = item.test_case;
1527
+ const rpt = item.original_report;
1528
+ const originalReport = rpt ? {
1529
+ id: rpt.id,
1530
+ title: rpt.title,
1531
+ description: rpt.description,
1532
+ severity: rpt.severity,
1533
+ screenshotUrls: rpt.screenshot_urls || [],
1534
+ resolutionNotes: rpt.resolution_notes || void 0,
1535
+ route: rpt.app_context?.currentRoute || void 0
1536
+ } : void 0;
1479
1537
  return {
1480
1538
  id: item.id,
1481
1539
  status: item.status,
@@ -1483,6 +1541,7 @@ var BugBearClient = class {
1483
1541
  skipReason: item.skip_reason,
1484
1542
  isVerification: item.is_verification || false,
1485
1543
  originalReportId: item.original_report_id,
1544
+ originalReport,
1486
1545
  testCase: tc ? {
1487
1546
  id: tc.id,
1488
1547
  title: tc.title,
@@ -1517,15 +1576,15 @@ var BugBearClient = class {
1517
1576
  } : void 0,
1518
1577
  platforms: tc.platforms || void 0
1519
1578
  } : {
1520
- // Standalone verification assignment (bug reported without a test case)
1579
+ // Standalone verification use original report data when available
1521
1580
  id: item.original_report_id || item.id,
1522
- title: item.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification",
1581
+ title: rpt?.title || (item.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification"),
1523
1582
  testKey: "VERIFY",
1524
- description: "Verify that the reported bug has been fixed",
1583
+ description: rpt?.description || "Verify that the reported bug has been fixed",
1525
1584
  steps: [],
1526
1585
  expectedResult: "The bug should no longer be reproducible",
1527
1586
  priority: "P1",
1528
- targetRoute: void 0,
1587
+ targetRoute: rpt?.app_context?.currentRoute || void 0,
1529
1588
  track: void 0,
1530
1589
  group: void 0,
1531
1590
  role: void 0,
@@ -1561,6 +1620,18 @@ var BugBearClient = class {
1561
1620
  started_at,
1562
1621
  completed_at,
1563
1622
  duration_seconds,
1623
+ is_verification,
1624
+ original_report_id,
1625
+ notes,
1626
+ original_report:reports(
1627
+ id,
1628
+ title,
1629
+ description,
1630
+ severity,
1631
+ screenshot_urls,
1632
+ resolution_notes,
1633
+ app_context
1634
+ ),
1564
1635
  test_case:test_cases(
1565
1636
  id,
1566
1637
  title,
@@ -1583,17 +1654,30 @@ var BugBearClient = class {
1583
1654
  `).eq("id", assignmentId).single();
1584
1655
  if (error || !data) return null;
1585
1656
  const testCase = data.test_case;
1586
- if (!testCase) {
1657
+ const rpt = data.original_report;
1658
+ const originalReport = rpt ? {
1659
+ id: rpt.id,
1660
+ title: rpt.title,
1661
+ description: rpt.description,
1662
+ severity: rpt.severity,
1663
+ screenshotUrls: rpt.screenshot_urls || [],
1664
+ resolutionNotes: rpt.resolution_notes || void 0,
1665
+ route: rpt.app_context?.currentRoute || void 0
1666
+ } : void 0;
1667
+ if (!testCase && !data.is_verification) {
1587
1668
  console.error("BugBear: Assignment returned without test_case");
1588
1669
  return null;
1589
1670
  }
1590
- const track = testCase.track;
1671
+ const track = testCase?.track;
1591
1672
  return {
1592
1673
  id: data.id,
1593
1674
  status: data.status,
1594
1675
  startedAt: data.started_at,
1595
1676
  durationSeconds: data.duration_seconds,
1596
- testCase: {
1677
+ isVerification: data.is_verification || false,
1678
+ originalReportId: data.original_report_id,
1679
+ originalReport,
1680
+ testCase: testCase ? {
1597
1681
  id: testCase.id,
1598
1682
  title: testCase.title,
1599
1683
  testKey: testCase.test_key,
@@ -1611,6 +1695,16 @@ var BugBearClient = class {
1611
1695
  rubricMode: track.rubric_mode || "pass_fail",
1612
1696
  description: track.description
1613
1697
  } : void 0
1698
+ } : {
1699
+ id: data.original_report_id || data.id,
1700
+ title: rpt?.title || (data.notes?.replace(/^Verification:\s*/i, "") || "Bug Verification"),
1701
+ testKey: "VERIFY",
1702
+ description: rpt?.description || "Verify that the reported bug has been fixed",
1703
+ steps: [],
1704
+ expectedResult: "The bug should no longer be reproducible",
1705
+ priority: "P1",
1706
+ targetRoute: rpt?.app_context?.currentRoute || void 0,
1707
+ track: void 0
1614
1708
  }
1615
1709
  };
1616
1710
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bbearai/core",
3
- "version": "0.9.5",
3
+ "version": "0.9.7",
4
4
  "description": "Core utilities and types for BugBear QA platform",
5
5
  "main": "./dist/index.js",
6
6
  "module": "./dist/index.mjs",