@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/README.md +4 -0
- package/dist/index.cjs +57 -0
- package/dist/index.cjs.map +1 -1
- package/dist/index.js +58 -1
- package/dist/index.js.map +1 -1
- package/package.json +16 -5
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
|
}
|