@mushi-mushi/core 0.7.0 → 0.8.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
@@ -2,15 +2,18 @@ interface MushiConfig {
2
2
  projectId: string;
3
3
  apiKey: string;
4
4
  apiEndpoint?: string;
5
+ /** Opinionated defaults for common environments. Explicit config wins. */
6
+ preset?: MushiPreset;
5
7
  /**
6
8
  * Fetch non-secret widget/capture settings from the Mushi project at
7
9
  * startup. Defaults to true so console changes apply without rebuilding
8
10
  * host apps. Set false for fully static/offline deployments.
9
11
  */
10
- runtimeConfig?: boolean;
12
+ runtimeConfig?: boolean | 'auto';
11
13
  sentry?: MushiSentryConfig;
12
14
  widget?: MushiWidgetConfig;
13
15
  capture?: MushiCaptureConfig;
16
+ privacy?: MushiPrivacyConfig;
14
17
  proactive?: MushiProactiveConfig;
15
18
  preFilter?: MushiPreFilterConfig;
16
19
  integrations?: MushiIntegrationsConfig;
@@ -27,6 +30,11 @@ interface MushiSentryConfig {
27
30
  }
28
31
  interface MushiWidgetConfig {
29
32
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
33
+ /**
34
+ * Raw CSS anchors for app shells with bottom navs/chat composers/cookie
35
+ * banners. When set, these values win over `position` + numeric `inset`.
36
+ */
37
+ anchor?: MushiWidgetAnchor;
30
38
  theme?: 'auto' | 'light' | 'dark';
31
39
  triggerText?: string;
32
40
  expandedTitle?: string;
@@ -54,6 +62,10 @@ interface MushiWidgetConfig {
54
62
  /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
55
63
  smartHide?: boolean | MushiWidgetSmartHideConfig;
56
64
  draggable?: boolean;
65
+ /** Show the tiny "Powered by Mushi vX" footer inside the widget panel. */
66
+ brandFooter?: boolean;
67
+ /** How the widget should surface SDK freshness warnings. Defaults to auto. */
68
+ outdatedBanner?: 'auto' | 'banner' | 'console-only' | 'off';
57
69
  }
58
70
  interface MushiWidgetInset {
59
71
  top?: number | 'auto';
@@ -61,6 +73,13 @@ interface MushiWidgetInset {
61
73
  bottom?: number | 'auto';
62
74
  left?: number | 'auto';
63
75
  }
76
+ interface MushiWidgetAnchor {
77
+ top?: string;
78
+ right?: string;
79
+ bottom?: string;
80
+ left?: string;
81
+ }
82
+ type MushiPreset = 'production-calm' | 'beta-loud' | 'internal-debug' | 'manual-only';
64
83
  interface MushiWidgetSmartHideConfig {
65
84
  onMobile?: 'edge-tab' | 'hide' | false;
66
85
  onScroll?: 'shrink' | 'hide' | false;
@@ -69,18 +88,41 @@ interface MushiWidgetSmartHideConfig {
69
88
  interface MushiCaptureConfig {
70
89
  console?: boolean;
71
90
  network?: boolean;
91
+ /**
92
+ * URLs that should never be captured as host-app traffic. Strings are
93
+ * substring matches; RegExp values are tested against the fully resolved URL.
94
+ */
95
+ ignoreUrls?: MushiUrlMatcher[];
72
96
  performance?: boolean;
73
97
  screenshot?: 'on-report' | 'auto' | 'off';
74
98
  elementSelector?: boolean;
75
99
  replay?: 'sentry' | 'rrweb' | 'lite' | 'off';
76
100
  }
101
+ interface MushiPrivacyConfig {
102
+ /** DOM nodes to visually mask in screenshots before upload. */
103
+ maskSelectors?: string[];
104
+ /** DOM subtrees to remove from screenshots before upload. */
105
+ blockSelectors?: string[];
106
+ /** Let reporters remove an attached screenshot before submitting. Defaults to true. */
107
+ allowUserRemoveScreenshot?: boolean;
108
+ }
77
109
  interface MushiProactiveConfig {
78
110
  rageClick?: boolean;
79
111
  errorBoundary?: boolean;
80
112
  longTask?: boolean;
81
- apiCascade?: boolean;
113
+ apiCascade?: boolean | MushiApiCascadeConfig;
82
114
  cooldown?: MushiCooldownConfig;
83
115
  }
116
+ type MushiUrlMatcher = string | RegExp;
117
+ interface MushiApiCascadeConfig {
118
+ enabled?: boolean;
119
+ /**
120
+ * URLs ignored by the API cascade detector. The SDK always ignores its own
121
+ * gateway endpoints as well; this hook lets host apps exclude analytics,
122
+ * health probes, or third-party scripts that are noisy by design.
123
+ */
124
+ ignoreUrls?: MushiUrlMatcher[];
125
+ }
84
126
  interface MushiCooldownConfig {
85
127
  maxProactivePerSession?: number;
86
128
  dismissCooldownHours?: number;
@@ -167,6 +209,7 @@ interface MushiReport {
167
209
  consoleLogs?: MushiConsoleEntry[];
168
210
  networkLogs?: MushiNetworkEntry[];
169
211
  performanceMetrics?: MushiPerformanceMetrics;
212
+ timeline?: MushiTimelineEntry[];
170
213
  screenshotDataUrl?: string;
171
214
  selectedElement?: MushiSelectedElement;
172
215
  metadata?: Record<string, unknown>;
@@ -179,6 +222,10 @@ interface MushiReport {
179
222
  */
180
223
  fingerprintHash?: string;
181
224
  appVersion?: string;
225
+ /** SDK package that submitted the report, e.g. `@mushi-mushi/web`. */
226
+ sdkPackage?: string;
227
+ /** npm package version that submitted the report, e.g. `0.8.0`. */
228
+ sdkVersion?: string;
182
229
  proactiveTrigger?: string;
183
230
  sentryEventId?: string;
184
231
  sentryReplayId?: string;
@@ -248,11 +295,28 @@ interface MushiSelectedElement {
248
295
  height: number;
249
296
  };
250
297
  }
298
+ type MushiTimelineKind = 'route' | 'click' | 'request' | 'log' | 'screen';
299
+ interface MushiTimelineEntry {
300
+ ts: number;
301
+ kind: MushiTimelineKind;
302
+ payload: Record<string, unknown>;
303
+ }
251
304
  type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
252
305
  type MushiEventHandler = (event: {
253
306
  type: MushiEventType;
254
307
  data?: unknown;
255
308
  }) => void;
309
+ interface MushiDiagnosticsResult {
310
+ apiEndpointReachable: boolean;
311
+ cspAllowsEndpoint: boolean;
312
+ widgetMounted: boolean;
313
+ shadowDomAvailable: boolean;
314
+ dialogSupported: boolean;
315
+ runtimeConfigLoaded: boolean;
316
+ captureScreenshotAvailable: boolean;
317
+ captureNetworkIntercepting: boolean;
318
+ sdkVersion: string;
319
+ }
256
320
  interface MushiSDKInstance {
257
321
  report(options?: {
258
322
  category?: MushiReportCategory;
@@ -264,6 +328,11 @@ interface MushiSDKInstance {
264
328
  name?: string;
265
329
  }): void;
266
330
  setMetadata(key: string, value: unknown): void;
331
+ setScreen(screen: {
332
+ name: string;
333
+ route?: string;
334
+ feature?: string;
335
+ }): void;
267
336
  isOpen(): boolean;
268
337
  open(): void;
269
338
  openWith(category: MushiReportCategory): void;
@@ -274,6 +343,7 @@ interface MushiSDKInstance {
274
343
  close(): void;
275
344
  destroy(): void;
276
345
  updateConfig(config: MushiRuntimeSdkConfig): void;
346
+ diagnose(): Promise<MushiDiagnosticsResult>;
277
347
  /**
278
348
  * Wave G4 — unified `captureEvent` API. Submits a bug report
279
349
  * programmatically without opening the widget. Useful for adapters
@@ -320,6 +390,16 @@ interface MushiApiClient {
320
390
  status: MushiReportStatus;
321
391
  }>>;
322
392
  getSdkConfig(): Promise<MushiApiResponse<MushiRuntimeSdkConfig>>;
393
+ getLatestSdkVersion(packageName: string): Promise<MushiApiResponse<MushiSdkVersionInfo>>;
394
+ listReporterReports(reporterToken: string): Promise<MushiApiResponse<{
395
+ reports: MushiReporterReport[];
396
+ }>>;
397
+ listReporterComments(reportId: string, reporterToken: string): Promise<MushiApiResponse<{
398
+ comments: MushiReporterComment[];
399
+ }>>;
400
+ replyToReporterReport(reportId: string, reporterToken: string, body: string): Promise<MushiApiResponse<{
401
+ comment: MushiReporterComment;
402
+ }>>;
323
403
  }
324
404
  interface MushiApiResponse<T> {
325
405
  ok: boolean;
@@ -339,6 +419,34 @@ interface MushiRuntimeSdkConfig {
339
419
  minDescriptionLength?: number;
340
420
  };
341
421
  }
422
+ interface MushiSdkVersionInfo {
423
+ package: string;
424
+ latest: string | null;
425
+ current?: string;
426
+ deprecated: boolean;
427
+ deprecationMessage?: string | null;
428
+ releasedAt?: string | null;
429
+ }
430
+ interface MushiReporterReport {
431
+ id: string;
432
+ status: string;
433
+ category: string;
434
+ severity?: string | null;
435
+ summary?: string | null;
436
+ description?: string | null;
437
+ created_at: string;
438
+ last_admin_reply_at?: string | null;
439
+ last_reporter_reply_at?: string | null;
440
+ unread_count?: number;
441
+ }
442
+ interface MushiReporterComment {
443
+ id: number;
444
+ author_kind: 'admin' | 'reporter';
445
+ author_name?: string | null;
446
+ body: string;
447
+ visible_to_reporter?: boolean;
448
+ created_at: string;
449
+ }
342
450
 
343
451
  interface ApiClientOptions {
344
452
  projectId: string;
@@ -352,6 +460,9 @@ interface ApiClientOptions {
352
460
  maxRetries?: number;
353
461
  }
354
462
  declare const DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
463
+ declare const MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
464
+ declare const MUSHI_INTERNAL_INIT_MARKER = "__mushiInternal";
465
+ type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose';
355
466
  declare function createApiClient(options: ApiClientOptions): MushiApiClient;
356
467
 
357
468
  /**
@@ -543,4 +654,4 @@ declare function createLogger(options: LoggerOptions): Logger;
543
654
  */
544
655
  declare const noopLogger: Logger;
545
656
 
546
- export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
657
+ export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, 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 MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiTimelineEntry, type MushiTimelineKind, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
package/dist/index.d.ts CHANGED
@@ -2,15 +2,18 @@ interface MushiConfig {
2
2
  projectId: string;
3
3
  apiKey: string;
4
4
  apiEndpoint?: string;
5
+ /** Opinionated defaults for common environments. Explicit config wins. */
6
+ preset?: MushiPreset;
5
7
  /**
6
8
  * Fetch non-secret widget/capture settings from the Mushi project at
7
9
  * startup. Defaults to true so console changes apply without rebuilding
8
10
  * host apps. Set false for fully static/offline deployments.
9
11
  */
10
- runtimeConfig?: boolean;
12
+ runtimeConfig?: boolean | 'auto';
11
13
  sentry?: MushiSentryConfig;
12
14
  widget?: MushiWidgetConfig;
13
15
  capture?: MushiCaptureConfig;
16
+ privacy?: MushiPrivacyConfig;
14
17
  proactive?: MushiProactiveConfig;
15
18
  preFilter?: MushiPreFilterConfig;
16
19
  integrations?: MushiIntegrationsConfig;
@@ -27,6 +30,11 @@ interface MushiSentryConfig {
27
30
  }
28
31
  interface MushiWidgetConfig {
29
32
  position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
33
+ /**
34
+ * Raw CSS anchors for app shells with bottom navs/chat composers/cookie
35
+ * banners. When set, these values win over `position` + numeric `inset`.
36
+ */
37
+ anchor?: MushiWidgetAnchor;
30
38
  theme?: 'auto' | 'light' | 'dark';
31
39
  triggerText?: string;
32
40
  expandedTitle?: string;
@@ -54,6 +62,10 @@ interface MushiWidgetConfig {
54
62
  /** Opt-in smart trigger behavior; planned to become the default in a later minor. */
55
63
  smartHide?: boolean | MushiWidgetSmartHideConfig;
56
64
  draggable?: boolean;
65
+ /** Show the tiny "Powered by Mushi vX" footer inside the widget panel. */
66
+ brandFooter?: boolean;
67
+ /** How the widget should surface SDK freshness warnings. Defaults to auto. */
68
+ outdatedBanner?: 'auto' | 'banner' | 'console-only' | 'off';
57
69
  }
58
70
  interface MushiWidgetInset {
59
71
  top?: number | 'auto';
@@ -61,6 +73,13 @@ interface MushiWidgetInset {
61
73
  bottom?: number | 'auto';
62
74
  left?: number | 'auto';
63
75
  }
76
+ interface MushiWidgetAnchor {
77
+ top?: string;
78
+ right?: string;
79
+ bottom?: string;
80
+ left?: string;
81
+ }
82
+ type MushiPreset = 'production-calm' | 'beta-loud' | 'internal-debug' | 'manual-only';
64
83
  interface MushiWidgetSmartHideConfig {
65
84
  onMobile?: 'edge-tab' | 'hide' | false;
66
85
  onScroll?: 'shrink' | 'hide' | false;
@@ -69,18 +88,41 @@ interface MushiWidgetSmartHideConfig {
69
88
  interface MushiCaptureConfig {
70
89
  console?: boolean;
71
90
  network?: boolean;
91
+ /**
92
+ * URLs that should never be captured as host-app traffic. Strings are
93
+ * substring matches; RegExp values are tested against the fully resolved URL.
94
+ */
95
+ ignoreUrls?: MushiUrlMatcher[];
72
96
  performance?: boolean;
73
97
  screenshot?: 'on-report' | 'auto' | 'off';
74
98
  elementSelector?: boolean;
75
99
  replay?: 'sentry' | 'rrweb' | 'lite' | 'off';
76
100
  }
101
+ interface MushiPrivacyConfig {
102
+ /** DOM nodes to visually mask in screenshots before upload. */
103
+ maskSelectors?: string[];
104
+ /** DOM subtrees to remove from screenshots before upload. */
105
+ blockSelectors?: string[];
106
+ /** Let reporters remove an attached screenshot before submitting. Defaults to true. */
107
+ allowUserRemoveScreenshot?: boolean;
108
+ }
77
109
  interface MushiProactiveConfig {
78
110
  rageClick?: boolean;
79
111
  errorBoundary?: boolean;
80
112
  longTask?: boolean;
81
- apiCascade?: boolean;
113
+ apiCascade?: boolean | MushiApiCascadeConfig;
82
114
  cooldown?: MushiCooldownConfig;
83
115
  }
116
+ type MushiUrlMatcher = string | RegExp;
117
+ interface MushiApiCascadeConfig {
118
+ enabled?: boolean;
119
+ /**
120
+ * URLs ignored by the API cascade detector. The SDK always ignores its own
121
+ * gateway endpoints as well; this hook lets host apps exclude analytics,
122
+ * health probes, or third-party scripts that are noisy by design.
123
+ */
124
+ ignoreUrls?: MushiUrlMatcher[];
125
+ }
84
126
  interface MushiCooldownConfig {
85
127
  maxProactivePerSession?: number;
86
128
  dismissCooldownHours?: number;
@@ -167,6 +209,7 @@ interface MushiReport {
167
209
  consoleLogs?: MushiConsoleEntry[];
168
210
  networkLogs?: MushiNetworkEntry[];
169
211
  performanceMetrics?: MushiPerformanceMetrics;
212
+ timeline?: MushiTimelineEntry[];
170
213
  screenshotDataUrl?: string;
171
214
  selectedElement?: MushiSelectedElement;
172
215
  metadata?: Record<string, unknown>;
@@ -179,6 +222,10 @@ interface MushiReport {
179
222
  */
180
223
  fingerprintHash?: string;
181
224
  appVersion?: string;
225
+ /** SDK package that submitted the report, e.g. `@mushi-mushi/web`. */
226
+ sdkPackage?: string;
227
+ /** npm package version that submitted the report, e.g. `0.8.0`. */
228
+ sdkVersion?: string;
182
229
  proactiveTrigger?: string;
183
230
  sentryEventId?: string;
184
231
  sentryReplayId?: string;
@@ -248,11 +295,28 @@ interface MushiSelectedElement {
248
295
  height: number;
249
296
  };
250
297
  }
298
+ type MushiTimelineKind = 'route' | 'click' | 'request' | 'log' | 'screen';
299
+ interface MushiTimelineEntry {
300
+ ts: number;
301
+ kind: MushiTimelineKind;
302
+ payload: Record<string, unknown>;
303
+ }
251
304
  type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
252
305
  type MushiEventHandler = (event: {
253
306
  type: MushiEventType;
254
307
  data?: unknown;
255
308
  }) => void;
309
+ interface MushiDiagnosticsResult {
310
+ apiEndpointReachable: boolean;
311
+ cspAllowsEndpoint: boolean;
312
+ widgetMounted: boolean;
313
+ shadowDomAvailable: boolean;
314
+ dialogSupported: boolean;
315
+ runtimeConfigLoaded: boolean;
316
+ captureScreenshotAvailable: boolean;
317
+ captureNetworkIntercepting: boolean;
318
+ sdkVersion: string;
319
+ }
256
320
  interface MushiSDKInstance {
257
321
  report(options?: {
258
322
  category?: MushiReportCategory;
@@ -264,6 +328,11 @@ interface MushiSDKInstance {
264
328
  name?: string;
265
329
  }): void;
266
330
  setMetadata(key: string, value: unknown): void;
331
+ setScreen(screen: {
332
+ name: string;
333
+ route?: string;
334
+ feature?: string;
335
+ }): void;
267
336
  isOpen(): boolean;
268
337
  open(): void;
269
338
  openWith(category: MushiReportCategory): void;
@@ -274,6 +343,7 @@ interface MushiSDKInstance {
274
343
  close(): void;
275
344
  destroy(): void;
276
345
  updateConfig(config: MushiRuntimeSdkConfig): void;
346
+ diagnose(): Promise<MushiDiagnosticsResult>;
277
347
  /**
278
348
  * Wave G4 — unified `captureEvent` API. Submits a bug report
279
349
  * programmatically without opening the widget. Useful for adapters
@@ -320,6 +390,16 @@ interface MushiApiClient {
320
390
  status: MushiReportStatus;
321
391
  }>>;
322
392
  getSdkConfig(): Promise<MushiApiResponse<MushiRuntimeSdkConfig>>;
393
+ getLatestSdkVersion(packageName: string): Promise<MushiApiResponse<MushiSdkVersionInfo>>;
394
+ listReporterReports(reporterToken: string): Promise<MushiApiResponse<{
395
+ reports: MushiReporterReport[];
396
+ }>>;
397
+ listReporterComments(reportId: string, reporterToken: string): Promise<MushiApiResponse<{
398
+ comments: MushiReporterComment[];
399
+ }>>;
400
+ replyToReporterReport(reportId: string, reporterToken: string, body: string): Promise<MushiApiResponse<{
401
+ comment: MushiReporterComment;
402
+ }>>;
323
403
  }
324
404
  interface MushiApiResponse<T> {
325
405
  ok: boolean;
@@ -339,6 +419,34 @@ interface MushiRuntimeSdkConfig {
339
419
  minDescriptionLength?: number;
340
420
  };
341
421
  }
422
+ interface MushiSdkVersionInfo {
423
+ package: string;
424
+ latest: string | null;
425
+ current?: string;
426
+ deprecated: boolean;
427
+ deprecationMessage?: string | null;
428
+ releasedAt?: string | null;
429
+ }
430
+ interface MushiReporterReport {
431
+ id: string;
432
+ status: string;
433
+ category: string;
434
+ severity?: string | null;
435
+ summary?: string | null;
436
+ description?: string | null;
437
+ created_at: string;
438
+ last_admin_reply_at?: string | null;
439
+ last_reporter_reply_at?: string | null;
440
+ unread_count?: number;
441
+ }
442
+ interface MushiReporterComment {
443
+ id: number;
444
+ author_kind: 'admin' | 'reporter';
445
+ author_name?: string | null;
446
+ body: string;
447
+ visible_to_reporter?: boolean;
448
+ created_at: string;
449
+ }
342
450
 
343
451
  interface ApiClientOptions {
344
452
  projectId: string;
@@ -352,6 +460,9 @@ interface ApiClientOptions {
352
460
  maxRetries?: number;
353
461
  }
354
462
  declare const DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
463
+ declare const MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
464
+ declare const MUSHI_INTERNAL_INIT_MARKER = "__mushiInternal";
465
+ type MushiInternalRequestKind = 'sdk-config' | 'report-submit' | 'report-status' | 'reporter-poll' | 'diagnose';
355
466
  declare function createApiClient(options: ApiClientOptions): MushiApiClient;
356
467
 
357
468
  /**
@@ -543,4 +654,4 @@ declare function createLogger(options: LoggerOptions): Logger;
543
654
  */
544
655
  declare const noopLogger: Logger;
545
656
 
546
- export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiOnDeviceClassifier, type MushiOnDeviceClassifierInput, type MushiOnDeviceClassifierResult, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiRegion, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
657
+ export { type ApiClientOptions, DEFAULT_API_ENDPOINT, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, type MushiApiCascadeConfig, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiCaptureEventInput, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiDiagnosticsResult, 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 MushiRewardsConfig, type MushiRuntimeSdkConfig, type MushiSDKInstance, type MushiSdkVersionInfo, type MushiSelectedElement, type MushiSentryConfig, type MushiTimelineEntry, type MushiTimelineKind, type MushiUrlMatcher, type MushiWidgetAnchor, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, REGION_ENDPOINTS, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
package/dist/index.js CHANGED
@@ -1,5 +1,7 @@
1
1
  // src/api-client.ts
2
2
  var DEFAULT_API_ENDPOINT = "https://dxptnwrhwsqckaftyymj.supabase.co/functions/v1/api";
3
+ var MUSHI_INTERNAL_HEADER = "X-Mushi-Internal";
4
+ var MUSHI_INTERNAL_INIT_MARKER = "__mushiInternal";
3
5
  var DEFAULT_TIMEOUT = 1e4;
4
6
  var DEFAULT_MAX_RETRIES = 2;
5
7
  function createApiClient(options) {
@@ -11,7 +13,7 @@ function createApiClient(options) {
11
13
  maxRetries = DEFAULT_MAX_RETRIES
12
14
  } = options;
13
15
  let baseUrl = apiEndpoint.replace(/\/$/, "");
14
- async function request(method, path, body, retries = maxRetries) {
16
+ async function request(method, path, body, retries = maxRetries, internalKind) {
15
17
  const url = `${baseUrl}${path}`;
16
18
  const controller = new AbortController();
17
19
  const timer = setTimeout(() => controller.abort(), timeout);
@@ -21,10 +23,12 @@ function createApiClient(options) {
21
23
  headers: {
22
24
  "Content-Type": "application/json",
23
25
  "X-Mushi-Api-Key": apiKey,
24
- "X-Mushi-Project": projectId
26
+ "X-Mushi-Project": projectId,
27
+ ...internalKind ? { [MUSHI_INTERNAL_HEADER]: internalKind } : {}
25
28
  },
26
29
  body: body ? JSON.stringify(body) : void 0,
27
- signal: controller.signal
30
+ signal: controller.signal,
31
+ ...internalKind ? { [MUSHI_INTERNAL_INIT_MARKER]: internalKind } : {}
28
32
  });
29
33
  clearTimeout(timer);
30
34
  if (response.status === 307 || response.status === 308) {
@@ -33,7 +37,7 @@ function createApiClient(options) {
33
37
  const targetBase = target.replace(/\/v1\/.*$/, "").replace(/\/$/, "");
34
38
  if (targetBase !== baseUrl) {
35
39
  baseUrl = targetBase;
36
- return request(method, path, body, retries - 1);
40
+ return request(method, path, body, retries - 1, internalKind);
37
41
  }
38
42
  }
39
43
  }
@@ -41,7 +45,7 @@ function createApiClient(options) {
41
45
  const errorBody = await response.json().catch(() => ({}));
42
46
  if (response.status >= 500 && retries > 0) {
43
47
  await sleep(getBackoffDelay(maxRetries - retries));
44
- return request(method, path, body, retries - 1);
48
+ return request(method, path, body, retries - 1, internalKind);
45
49
  }
46
50
  return {
47
51
  ok: false,
@@ -58,7 +62,7 @@ function createApiClient(options) {
58
62
  clearTimeout(timer);
59
63
  if (retries > 0 && isRetryable(error)) {
60
64
  await sleep(getBackoffDelay(maxRetries - retries));
61
- return request(method, path, body, retries - 1);
65
+ return request(method, path, body, retries - 1, internalKind);
62
66
  }
63
67
  return {
64
68
  ok: false,
@@ -69,18 +73,87 @@ function createApiClient(options) {
69
73
  };
70
74
  }
71
75
  }
76
+ async function requestForReporter(method, path, reporterToken, body) {
77
+ const tokenHash = await sha256Hex(reporterToken);
78
+ const ts = String(Date.now());
79
+ const hmac = await hmacSha256Hex(apiKey, `${projectId}.${ts}.${tokenHash}`);
80
+ const url = `${baseUrl}${path}`;
81
+ const response = await fetch(url, {
82
+ method,
83
+ headers: {
84
+ "Content-Type": "application/json",
85
+ "X-Mushi-Api-Key": apiKey,
86
+ "X-Mushi-Project": projectId,
87
+ [MUSHI_INTERNAL_HEADER]: "reporter-poll",
88
+ "X-Reporter-Token-Hash": tokenHash,
89
+ "X-Reporter-Ts": ts,
90
+ "X-Reporter-Hmac": hmac
91
+ },
92
+ body: body ? JSON.stringify(body) : void 0,
93
+ [MUSHI_INTERNAL_INIT_MARKER]: "reporter-poll"
94
+ });
95
+ if (!response.ok) {
96
+ const errorBody = await response.json().catch(() => ({}));
97
+ return {
98
+ ok: false,
99
+ error: {
100
+ code: `HTTP_${response.status}`,
101
+ message: errorBody.error?.message ?? errorBody.message ?? `HTTP ${response.status} error`
102
+ }
103
+ };
104
+ }
105
+ const payload = await response.json();
106
+ return { ok: true, data: payload.data ?? payload };
107
+ }
72
108
  return {
73
109
  async submitReport(report) {
74
- return request("POST", "/v1/reports", report);
110
+ return request("POST", "/v1/reports", report, maxRetries, "report-submit");
75
111
  },
76
112
  async getReportStatus(reportId) {
77
- return request("GET", `/v1/reports/${reportId}/status`);
113
+ return request("GET", `/v1/reports/${reportId}/status`, void 0, maxRetries, "report-status");
78
114
  },
79
115
  async getSdkConfig() {
80
- return request("GET", "/v1/sdk/config");
116
+ return request("GET", "/v1/sdk/config", void 0, maxRetries, "sdk-config");
117
+ },
118
+ async getLatestSdkVersion(packageName) {
119
+ const query = new URLSearchParams({ package: packageName }).toString();
120
+ return request("GET", `/v1/sdk/latest-version?${query}`, void 0, maxRetries, "sdk-config");
121
+ },
122
+ async listReporterReports(reporterToken) {
123
+ return requestForReporter("GET", "/v1/reporter/reports", reporterToken);
124
+ },
125
+ async listReporterComments(reportId, reporterToken) {
126
+ return requestForReporter(
127
+ "GET",
128
+ `/v1/reporter/reports/${reportId}/comments`,
129
+ reporterToken
130
+ );
131
+ },
132
+ async replyToReporterReport(reportId, reporterToken, body) {
133
+ return requestForReporter(
134
+ "POST",
135
+ `/v1/reporter/reports/${reportId}/reply`,
136
+ reporterToken,
137
+ { body }
138
+ );
81
139
  }
82
140
  };
83
141
  }
142
+ async function sha256Hex(value) {
143
+ const buffer = await crypto.subtle.digest("SHA-256", new TextEncoder().encode(value));
144
+ return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
145
+ }
146
+ async function hmacSha256Hex(secret, value) {
147
+ const key = await crypto.subtle.importKey(
148
+ "raw",
149
+ new TextEncoder().encode(secret),
150
+ { name: "HMAC", hash: "SHA-256" },
151
+ false,
152
+ ["sign"]
153
+ );
154
+ const buffer = await crypto.subtle.sign("HMAC", key, new TextEncoder().encode(value));
155
+ return Array.from(new Uint8Array(buffer)).map((b) => b.toString(16).padStart(2, "0")).join("");
156
+ }
84
157
  function sleep(ms) {
85
158
  return new Promise((resolve) => setTimeout(resolve, ms));
86
159
  }
@@ -774,7 +847,7 @@ function collectInputs() {
774
847
  hardwareConcurrency: nav?.hardwareConcurrency
775
848
  };
776
849
  }
777
- async function sha256Hex(input) {
850
+ async function sha256Hex2(input) {
778
851
  if (typeof crypto !== "undefined" && crypto.subtle) {
779
852
  const buf = new TextEncoder().encode(input);
780
853
  const digest = await crypto.subtle.digest("SHA-256", buf);
@@ -794,7 +867,7 @@ async function getDeviceFingerprintHash() {
794
867
  }
795
868
  const inputs = collectInputs();
796
869
  const serialised = JSON.stringify(inputs);
797
- const hash = await sha256Hex(serialised);
870
+ const hash = await sha256Hex2(serialised);
798
871
  if (typeof localStorage !== "undefined") {
799
872
  try {
800
873
  localStorage.setItem(CACHE_KEY, hash);
@@ -930,6 +1003,6 @@ function scrubPii(text, config) {
930
1003
  return createPiiScrubber(config).scrub(text);
931
1004
  }
932
1005
 
933
- export { DEFAULT_API_ENDPOINT, REGION_ENDPOINTS, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
1006
+ export { DEFAULT_API_ENDPOINT, MUSHI_INTERNAL_HEADER, MUSHI_INTERNAL_INIT_MARKER, REGION_ENDPOINTS, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getDeviceFingerprintHash, getReporterToken, getSessionId, noopLogger, resolveRegionEndpoint, scrubPii };
934
1007
  //# sourceMappingURL=index.js.map
935
1008
  //# sourceMappingURL=index.js.map