@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/README.md +27 -2
- package/dist/index.cjs +86 -11
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +114 -3
- package/dist/index.d.ts +114 -3
- package/dist/index.js +85 -12
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
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
|
|
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
|
|
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
|