@mushi-mushi/web 0.2.0 → 0.3.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 CHANGED
@@ -1,4 +1,4 @@
1
- import { createLogger, noopLogger, createApiClient, createPreFilter, createOfflineQueue, createRateLimiter, createPiiScrubber, getReporterToken, getSessionId, captureEnvironment } from '@mushi-mushi/core';
1
+ import { createLogger, noopLogger, createApiClient, createPreFilter, createOfflineQueue, createRateLimiter, createPiiScrubber, getDeviceFingerprintHash, getReporterToken, getSessionId, captureEnvironment } from '@mushi-mushi/core';
2
2
 
3
3
  // src/mushi.ts
4
4
 
@@ -1543,6 +1543,7 @@ function createInstance(config) {
1543
1543
  }
1544
1544
  const scrubbedDescription = piiScrubber.scrub(preFilter.truncate(description));
1545
1545
  const sentryCtx = config.sentry ? captureSentryContext(config.sentry) : void 0;
1546
+ const fingerprintHash = await getDeviceFingerprintHash().catch(() => null);
1546
1547
  const report = {
1547
1548
  id: crypto.randomUUID?.() ?? `mushi_${Date.now()}_${Math.random().toString(36).slice(2)}`,
1548
1549
  projectId: config.projectId,
@@ -1562,6 +1563,7 @@ function createInstance(config) {
1562
1563
  },
1563
1564
  sessionId: getSessionId(),
1564
1565
  reporterToken: getReporterToken(),
1566
+ ...fingerprintHash ? { fingerprintHash } : {},
1565
1567
  appVersion: config.integrations?.vercel?.analyticsId,
1566
1568
  proactiveTrigger: pendingProactiveTrigger ?? void 0,
1567
1569
  sentryEventId: sentryCtx?.eventId,
@@ -1638,6 +1640,58 @@ function createInstance(config) {
1638
1640
  listeners.clear();
1639
1641
  instance = null;
1640
1642
  log.debug("Destroyed");
1643
+ },
1644
+ // Wave G4 — unified `captureEvent` API for programmatic/adapter-driven
1645
+ // reports. Skips the widget, runs the same PII scrub + rate limit +
1646
+ // offline-queue path as `submit()`, and returns the server report id.
1647
+ async captureEvent(input) {
1648
+ if (!rateLimiter.tryConsume()) {
1649
+ log.warn("captureEvent throttled \u2014 rate limit exceeded");
1650
+ return null;
1651
+ }
1652
+ const description = piiScrubber.scrub(preFilter.truncate(input.description));
1653
+ const category = input.category ?? "bug";
1654
+ const report = {
1655
+ id: crypto.randomUUID?.() ?? `mushi_${Date.now()}_${Math.random().toString(36).slice(2)}`,
1656
+ projectId: config.projectId,
1657
+ category,
1658
+ description,
1659
+ environment: captureEnvironment(),
1660
+ metadata: {
1661
+ ...input.metadata ?? {},
1662
+ ...userInfo ? { user: userInfo } : {},
1663
+ ...input.tags ? { tags: input.tags } : {},
1664
+ ...input.error ? { error: input.error } : {},
1665
+ ...input.severity ? { severity: input.severity } : {},
1666
+ ...input.component ? { component: input.component } : {},
1667
+ ...input.source ? { source: input.source } : { source: "captureEvent" }
1668
+ },
1669
+ sessionId: getSessionId(),
1670
+ reporterToken: getReporterToken(),
1671
+ createdAt: (/* @__PURE__ */ new Date()).toISOString()
1672
+ };
1673
+ emit("report:submitted", { reportId: report.id });
1674
+ if (typeof navigator !== "undefined" && !navigator.onLine) {
1675
+ await offlineQueue.enqueue(report);
1676
+ emit("report:queued", { reportId: report.id });
1677
+ return null;
1678
+ }
1679
+ const res = await apiClient.submitReport(report);
1680
+ if (res.ok) {
1681
+ emit("report:sent", { reportId: res.data?.reportId });
1682
+ return res.data?.reportId ?? null;
1683
+ }
1684
+ await offlineQueue.enqueue(report);
1685
+ emit("report:failed", { reportId: report.id, error: res.error });
1686
+ return null;
1687
+ },
1688
+ identify(userId, traits) {
1689
+ userInfo = { id: userId, ...traits?.email ? { email: traits.email } : {}, ...traits?.name ? { name: traits.name } : {} };
1690
+ if (traits) {
1691
+ for (const [k, v] of Object.entries(traits)) {
1692
+ if (k !== "email" && k !== "name") customMetadata[`user.${k}`] = v;
1693
+ }
1694
+ }
1641
1695
  }
1642
1696
  };
1643
1697
  return sdk;
@@ -1659,6 +1713,9 @@ function createNoopInstance() {
1659
1713
  },
1660
1714
  destroy: () => {
1661
1715
  instance = null;
1716
+ },
1717
+ captureEvent: async () => null,
1718
+ identify: () => {
1662
1719
  }
1663
1720
  };
1664
1721
  }