@mushi-mushi/core 1.9.0 → 1.10.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.d.cts CHANGED
@@ -1065,6 +1065,28 @@ interface MushiSDKInstance {
1065
1065
  * welcome" nudges (first-session, beta-onboarding).
1066
1066
  */
1067
1067
  pulseTrigger(): void;
1068
+ /**
1069
+ * Returns the signed-in reporter's own report history.
1070
+ * Keyed to the persistent `reporterToken` stored in localStorage /
1071
+ * AsyncStorage. Returns an empty array when no token exists yet.
1072
+ */
1073
+ listMyReports(): Promise<MushiReporterReport[]>;
1074
+ /**
1075
+ * Returns the comment thread for a given report. Only returns comments
1076
+ * visible to the reporter (their own comments + team replies).
1077
+ */
1078
+ listMyComments(reportId: string): Promise<MushiReporterComment[]>;
1079
+ /**
1080
+ * Post a follow-up comment on one of the reporter's own reports.
1081
+ * Returns the newly created comment, or null on failure.
1082
+ */
1083
+ replyToReport(reportId: string, body: string): Promise<MushiReporterComment | null>;
1084
+ /**
1085
+ * Returns the global contributor hall-of-fame ranked by total points.
1086
+ * Safe to call without an authenticated user; uses public endpoint.
1087
+ * @param limit Maximum entries to return (default 20).
1088
+ */
1089
+ getHallOfFame(limit?: number): Promise<MushiHallOfFameEntry[]>;
1068
1090
  }
1069
1091
  interface MushiCaptureExceptionOptions {
1070
1092
  /** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
@@ -1164,6 +1186,20 @@ interface MushiApiClient {
1164
1186
  items: unknown[];
1165
1187
  total: number;
1166
1188
  }>>;
1189
+ /** Fetch the project's public leaderboard (top contributors). */
1190
+ getHallOfFame(limit?: number): Promise<MushiApiResponse<{
1191
+ data: Array<{
1192
+ display_name: string;
1193
+ email_hash: string | null;
1194
+ tier_slug: string | null;
1195
+ tier_name: string | null;
1196
+ points_30d: number;
1197
+ total_points: number;
1198
+ }>;
1199
+ meta: {
1200
+ project_name: string;
1201
+ };
1202
+ }>>;
1167
1203
  }
1168
1204
  /**
1169
1205
  * Wire shape of a single discovery event sent by the SDK to
@@ -1227,6 +1263,14 @@ interface MushiReporterComment {
1227
1263
  visible_to_reporter?: boolean;
1228
1264
  created_at: string;
1229
1265
  }
1266
+ interface MushiHallOfFameEntry {
1267
+ display_name: string;
1268
+ email_hash: string | null;
1269
+ tier_slug: string | null;
1270
+ tier_name: string | null;
1271
+ points_30d: number;
1272
+ total_points: number;
1273
+ }
1230
1274
 
1231
1275
  interface ApiClientOptions {
1232
1276
  projectId: string;
@@ -1537,4 +1581,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1537
1581
  */
1538
1582
  declare const noopLogger: Logger;
1539
1583
 
1540
- export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1584
+ export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
package/dist/index.d.ts CHANGED
@@ -1065,6 +1065,28 @@ interface MushiSDKInstance {
1065
1065
  * welcome" nudges (first-session, beta-onboarding).
1066
1066
  */
1067
1067
  pulseTrigger(): void;
1068
+ /**
1069
+ * Returns the signed-in reporter's own report history.
1070
+ * Keyed to the persistent `reporterToken` stored in localStorage /
1071
+ * AsyncStorage. Returns an empty array when no token exists yet.
1072
+ */
1073
+ listMyReports(): Promise<MushiReporterReport[]>;
1074
+ /**
1075
+ * Returns the comment thread for a given report. Only returns comments
1076
+ * visible to the reporter (their own comments + team replies).
1077
+ */
1078
+ listMyComments(reportId: string): Promise<MushiReporterComment[]>;
1079
+ /**
1080
+ * Post a follow-up comment on one of the reporter's own reports.
1081
+ * Returns the newly created comment, or null on failure.
1082
+ */
1083
+ replyToReport(reportId: string, body: string): Promise<MushiReporterComment | null>;
1084
+ /**
1085
+ * Returns the global contributor hall-of-fame ranked by total points.
1086
+ * Safe to call without an authenticated user; uses public endpoint.
1087
+ * @param limit Maximum entries to return (default 20).
1088
+ */
1089
+ getHallOfFame(limit?: number): Promise<MushiHallOfFameEntry[]>;
1068
1090
  }
1069
1091
  interface MushiCaptureExceptionOptions {
1070
1092
  /** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
@@ -1164,6 +1186,20 @@ interface MushiApiClient {
1164
1186
  items: unknown[];
1165
1187
  total: number;
1166
1188
  }>>;
1189
+ /** Fetch the project's public leaderboard (top contributors). */
1190
+ getHallOfFame(limit?: number): Promise<MushiApiResponse<{
1191
+ data: Array<{
1192
+ display_name: string;
1193
+ email_hash: string | null;
1194
+ tier_slug: string | null;
1195
+ tier_name: string | null;
1196
+ points_30d: number;
1197
+ total_points: number;
1198
+ }>;
1199
+ meta: {
1200
+ project_name: string;
1201
+ };
1202
+ }>>;
1167
1203
  }
1168
1204
  /**
1169
1205
  * Wire shape of a single discovery event sent by the SDK to
@@ -1227,6 +1263,14 @@ interface MushiReporterComment {
1227
1263
  visible_to_reporter?: boolean;
1228
1264
  created_at: string;
1229
1265
  }
1266
+ interface MushiHallOfFameEntry {
1267
+ display_name: string;
1268
+ email_hash: string | null;
1269
+ tier_slug: string | null;
1270
+ tier_name: string | null;
1271
+ points_30d: number;
1272
+ total_points: number;
1273
+ }
1230
1274
 
1231
1275
  interface ApiClientOptions {
1232
1276
  projectId: string;
@@ -1537,4 +1581,4 @@ declare function createLogger(options: LoggerOptions): Logger;
1537
1581
  */
1538
1582
  declare const noopLogger: Logger;
1539
1583
 
1540
- export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
1584
+ export { type ApiClientOptions, type BreadcrumbBuffer, type BreadcrumbBufferOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiActivityEvent, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiBannerConfig, type MushiBannerLink, type MushiBetaChangelogEntry, type MushiBetaModeConfig, type MushiBreadcrumb, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiCaptureExceptionOptions, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, type MushiDiscoverInventoryConfig, type MushiDiscoveryEventPayload, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiHallOfFameEntry, type MushiIntegrationsConfig, type MushiInternalRequestKind, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiPreset, type MushiPrivacyConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiReporterComment, type MushiReporterReport, type MushiReputationResult, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiSentryContext, type MushiTierResult, type MushiTimelineEntry, type MushiTimelineKind, type MushiTracePropagationConfig, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type NormalisedException, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createBreadcrumbBuffer, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, newUuid, noopLogger, normaliseThrown, resolveRegionEndpoint, scrubPii };
package/dist/index.js CHANGED
@@ -192,6 +192,15 @@ function createApiClient(options) {
192
192
  1,
193
193
  "reporter-poll"
194
194
  );
195
+ },
196
+ async getHallOfFame(limit = 10) {
197
+ return request(
198
+ "GET",
199
+ `/v1/sdk/hall-of-fame?limit=${limit}`,
200
+ void 0,
201
+ 1,
202
+ "reporter-poll"
203
+ );
195
204
  }
196
205
  };
197
206
  }
@@ -290,8 +299,10 @@ var SPAM_PATTERNS = [
290
299
  // numbers only
291
300
  /^[^a-zA-Z\u00C0-\u024F\u4E00-\u9FFF\u3040-\u309F\u30A0-\u30FF]{10,}$/,
292
301
  // no real letters
293
- /\b(test|asdf|qwerty|lorem ipsum)\b/i
294
- // common test strings
302
+ // "test" removed — users legitimately write "I was testing…" in real reports.
303
+ // Keep clearly-nonsense patterns that are never real sentences.
304
+ /^(asdf|qwerty|lorem ipsum)[.,!?\s]*$/i
305
+ // standalone keyboard-mash or placeholder
295
306
  ];
296
307
  var GIBBERISH_PATTERN = /^[bcdfghjklmnpqrstvwxz]{6,}/i;
297
308
  function createPreFilter(config = {}) {
@@ -581,9 +592,11 @@ var DB_VERSION = 1;
581
592
  var LS_KEY = "mushi_offline_queue";
582
593
  var BATCH_SIZE = 10;
583
594
  var MAX_BACKOFF_MS = 6e4;
595
+ var AUTO_FLUSH_INTERVAL_MS = 3e4;
584
596
  function createOfflineQueue(config = {}) {
585
597
  const { enabled = true, maxQueueSize = 50, syncOnReconnect = true, encryptAtRest = true } = config;
586
598
  let syncCleanup = null;
599
+ let flushInterval = null;
587
600
  let backendType = null;
588
601
  async function wrapForStorage(report) {
589
602
  const queuedAt = (/* @__PURE__ */ new Date()).toISOString();
@@ -778,6 +791,7 @@ function createOfflineQueue(config = {}) {
778
791
  const permanent = result.error?.code === "HTTP_400" || result.error?.code === "HTTP_422" || result.error?.code === "INGEST_ERROR" || result.error?.code === "VALIDATION_ERROR" || typeof result.error?.message === "string" && /invalid payload|description must be at least|validation/i.test(
779
792
  result.error.message
780
793
  );
794
+ const transient = !permanent && (result.error?.code === "NETWORK_ERROR" || result.error?.code === "HTTP_403" || result.error?.code === "HTTP_429" || result.error?.code === "HTTP_502" || result.error?.code === "HTTP_503" || result.error?.code === "HTTP_504" || typeof result.error?.code === "string" && result.error.code.startsWith("HTTP_5"));
781
795
  if (permanent) {
782
796
  try {
783
797
  if (backend === "indexeddb") await idbDelete(rowId);
@@ -785,6 +799,11 @@ function createOfflineQueue(config = {}) {
785
799
  } catch {
786
800
  lsDelete(rowId);
787
801
  }
802
+ } else if (transient) {
803
+ queueLog.debug("Offline queue: transient failure, will retry", {
804
+ id: rowId,
805
+ code: result.error?.code
806
+ });
788
807
  }
789
808
  failed++;
790
809
  if (i < batch.length - 1) {
@@ -820,14 +839,25 @@ function createOfflineQueue(config = {}) {
820
839
  }
821
840
  function startAutoSync(client) {
822
841
  if (!enabled || !syncOnReconnect || typeof window === "undefined") return;
823
- const handler = () => {
842
+ const tryFlush = () => {
824
843
  if (navigator.onLine) {
825
844
  flush(client).catch(() => {
826
845
  });
827
846
  }
828
847
  };
829
- window.addEventListener("online", handler);
830
- syncCleanup = () => window.removeEventListener("online", handler);
848
+ window.addEventListener("online", tryFlush);
849
+ flushInterval = setInterval(() => {
850
+ void size().then((n) => {
851
+ if (n > 0) tryFlush();
852
+ });
853
+ }, AUTO_FLUSH_INTERVAL_MS);
854
+ syncCleanup = () => {
855
+ window.removeEventListener("online", tryFlush);
856
+ if (flushInterval) {
857
+ clearInterval(flushInterval);
858
+ flushInterval = null;
859
+ }
860
+ };
831
861
  }
832
862
  function stopAutoSync() {
833
863
  syncCleanup?.();