@mushi-mushi/core 0.1.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/LICENSE +21 -0
- package/README.md +30 -0
- package/dist/index.cjs +680 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +330 -0
- package/dist/index.d.ts +330 -0
- package/dist/index.js +668 -0
- package/dist/index.js.map +1 -0
- package/package.json +75 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,330 @@
|
|
|
1
|
+
interface MushiConfig {
|
|
2
|
+
projectId: string;
|
|
3
|
+
apiKey: string;
|
|
4
|
+
apiEndpoint?: string;
|
|
5
|
+
sentry?: MushiSentryConfig;
|
|
6
|
+
widget?: MushiWidgetConfig;
|
|
7
|
+
capture?: MushiCaptureConfig;
|
|
8
|
+
proactive?: MushiProactiveConfig;
|
|
9
|
+
preFilter?: MushiPreFilterConfig;
|
|
10
|
+
integrations?: MushiIntegrationsConfig;
|
|
11
|
+
offline?: MushiOfflineConfig;
|
|
12
|
+
rewards?: MushiRewardsConfig;
|
|
13
|
+
debug?: boolean;
|
|
14
|
+
enabled?: boolean;
|
|
15
|
+
}
|
|
16
|
+
interface MushiSentryConfig {
|
|
17
|
+
dsn?: string;
|
|
18
|
+
consumeUserFeedback?: boolean;
|
|
19
|
+
enrichWithSeer?: boolean;
|
|
20
|
+
useReplay?: boolean;
|
|
21
|
+
}
|
|
22
|
+
interface MushiWidgetConfig {
|
|
23
|
+
position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
|
|
24
|
+
theme?: 'auto' | 'light' | 'dark';
|
|
25
|
+
triggerText?: string;
|
|
26
|
+
expandedTitle?: string;
|
|
27
|
+
mode?: 'simple' | 'conversational';
|
|
28
|
+
locale?: string;
|
|
29
|
+
zIndex?: number;
|
|
30
|
+
}
|
|
31
|
+
interface MushiCaptureConfig {
|
|
32
|
+
console?: boolean;
|
|
33
|
+
network?: boolean;
|
|
34
|
+
performance?: boolean;
|
|
35
|
+
screenshot?: 'on-report' | 'auto' | 'off';
|
|
36
|
+
elementSelector?: boolean;
|
|
37
|
+
replay?: 'sentry' | 'rrweb' | 'lite' | 'off';
|
|
38
|
+
}
|
|
39
|
+
interface MushiProactiveConfig {
|
|
40
|
+
rageClick?: boolean;
|
|
41
|
+
errorBoundary?: boolean;
|
|
42
|
+
longTask?: boolean;
|
|
43
|
+
apiCascade?: boolean;
|
|
44
|
+
cooldown?: MushiCooldownConfig;
|
|
45
|
+
}
|
|
46
|
+
interface MushiCooldownConfig {
|
|
47
|
+
maxProactivePerSession?: number;
|
|
48
|
+
dismissCooldownHours?: number;
|
|
49
|
+
suppressAfterDismissals?: number;
|
|
50
|
+
}
|
|
51
|
+
interface MushiPreFilterConfig {
|
|
52
|
+
enabled?: boolean;
|
|
53
|
+
blockObviousSpam?: boolean;
|
|
54
|
+
minDescriptionLength?: number;
|
|
55
|
+
maxDescriptionLength?: number;
|
|
56
|
+
}
|
|
57
|
+
interface MushiIntegrationsConfig {
|
|
58
|
+
opentelemetry?: {
|
|
59
|
+
traceContext?: boolean;
|
|
60
|
+
};
|
|
61
|
+
vercel?: {
|
|
62
|
+
analyticsId?: string;
|
|
63
|
+
};
|
|
64
|
+
custom?: (report: MushiReportBuilder) => void;
|
|
65
|
+
}
|
|
66
|
+
interface MushiOfflineConfig {
|
|
67
|
+
enabled?: boolean;
|
|
68
|
+
maxQueueSize?: number;
|
|
69
|
+
syncOnReconnect?: boolean;
|
|
70
|
+
}
|
|
71
|
+
interface MushiRewardsConfig {
|
|
72
|
+
enabled?: boolean;
|
|
73
|
+
requireAuth?: boolean;
|
|
74
|
+
showNotifications?: boolean;
|
|
75
|
+
webhookOnReward?: string;
|
|
76
|
+
}
|
|
77
|
+
type MushiReportCategory = 'bug' | 'slow' | 'visual' | 'confusing' | 'other';
|
|
78
|
+
type MushiReportStatus = 'pending' | 'submitted' | 'classified' | 'grouped' | 'fixing' | 'fixed' | 'dismissed';
|
|
79
|
+
interface MushiReport {
|
|
80
|
+
id: string;
|
|
81
|
+
projectId: string;
|
|
82
|
+
category: MushiReportCategory;
|
|
83
|
+
description: string;
|
|
84
|
+
userIntent?: string;
|
|
85
|
+
environment: MushiEnvironment;
|
|
86
|
+
consoleLogs?: MushiConsoleEntry[];
|
|
87
|
+
networkLogs?: MushiNetworkEntry[];
|
|
88
|
+
performanceMetrics?: MushiPerformanceMetrics;
|
|
89
|
+
screenshotDataUrl?: string;
|
|
90
|
+
selectedElement?: MushiSelectedElement;
|
|
91
|
+
metadata?: Record<string, unknown>;
|
|
92
|
+
sessionId?: string;
|
|
93
|
+
reporterToken: string;
|
|
94
|
+
appVersion?: string;
|
|
95
|
+
proactiveTrigger?: string;
|
|
96
|
+
sentryEventId?: string;
|
|
97
|
+
sentryReplayId?: string;
|
|
98
|
+
queuedAt?: string;
|
|
99
|
+
createdAt: string;
|
|
100
|
+
}
|
|
101
|
+
interface MushiReportBuilder {
|
|
102
|
+
addMetadata(key: string, value: unknown): void;
|
|
103
|
+
setCategory(category: MushiReportCategory): void;
|
|
104
|
+
setDescription(description: string): void;
|
|
105
|
+
}
|
|
106
|
+
interface MushiEnvironment {
|
|
107
|
+
userAgent: string;
|
|
108
|
+
platform: string;
|
|
109
|
+
language: string;
|
|
110
|
+
viewport: {
|
|
111
|
+
width: number;
|
|
112
|
+
height: number;
|
|
113
|
+
};
|
|
114
|
+
url: string;
|
|
115
|
+
referrer: string;
|
|
116
|
+
timestamp: string;
|
|
117
|
+
timezone: string;
|
|
118
|
+
connection?: {
|
|
119
|
+
effectiveType?: string;
|
|
120
|
+
downlink?: number;
|
|
121
|
+
rtt?: number;
|
|
122
|
+
};
|
|
123
|
+
deviceMemory?: number;
|
|
124
|
+
hardwareConcurrency?: number;
|
|
125
|
+
}
|
|
126
|
+
interface MushiConsoleEntry {
|
|
127
|
+
level: 'log' | 'warn' | 'error' | 'info' | 'debug';
|
|
128
|
+
message: string;
|
|
129
|
+
timestamp: number;
|
|
130
|
+
stack?: string;
|
|
131
|
+
}
|
|
132
|
+
interface MushiNetworkEntry {
|
|
133
|
+
method: string;
|
|
134
|
+
url: string;
|
|
135
|
+
status: number;
|
|
136
|
+
duration: number;
|
|
137
|
+
timestamp: number;
|
|
138
|
+
requestHeaders?: Record<string, string>;
|
|
139
|
+
responseHeaders?: Record<string, string>;
|
|
140
|
+
error?: string;
|
|
141
|
+
}
|
|
142
|
+
interface MushiPerformanceMetrics {
|
|
143
|
+
fcp?: number;
|
|
144
|
+
lcp?: number;
|
|
145
|
+
cls?: number;
|
|
146
|
+
fid?: number;
|
|
147
|
+
inp?: number;
|
|
148
|
+
ttfb?: number;
|
|
149
|
+
longTasks?: number;
|
|
150
|
+
}
|
|
151
|
+
interface MushiSelectedElement {
|
|
152
|
+
tagName: string;
|
|
153
|
+
id?: string;
|
|
154
|
+
className?: string;
|
|
155
|
+
textContent?: string;
|
|
156
|
+
xpath?: string;
|
|
157
|
+
rect?: {
|
|
158
|
+
x: number;
|
|
159
|
+
y: number;
|
|
160
|
+
width: number;
|
|
161
|
+
height: number;
|
|
162
|
+
};
|
|
163
|
+
}
|
|
164
|
+
type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
|
|
165
|
+
type MushiEventHandler = (event: {
|
|
166
|
+
type: MushiEventType;
|
|
167
|
+
data?: unknown;
|
|
168
|
+
}) => void;
|
|
169
|
+
interface MushiSDKInstance {
|
|
170
|
+
report(options?: {
|
|
171
|
+
category?: MushiReportCategory;
|
|
172
|
+
}): void;
|
|
173
|
+
on(event: MushiEventType, handler: MushiEventHandler): () => void;
|
|
174
|
+
setUser(user: {
|
|
175
|
+
id: string;
|
|
176
|
+
email?: string;
|
|
177
|
+
name?: string;
|
|
178
|
+
}): void;
|
|
179
|
+
setMetadata(key: string, value: unknown): void;
|
|
180
|
+
isOpen(): boolean;
|
|
181
|
+
open(): void;
|
|
182
|
+
close(): void;
|
|
183
|
+
destroy(): void;
|
|
184
|
+
}
|
|
185
|
+
interface MushiApiClient {
|
|
186
|
+
submitReport(report: MushiReport): Promise<MushiApiResponse<{
|
|
187
|
+
reportId: string;
|
|
188
|
+
}>>;
|
|
189
|
+
getReportStatus(reportId: string): Promise<MushiApiResponse<{
|
|
190
|
+
status: MushiReportStatus;
|
|
191
|
+
}>>;
|
|
192
|
+
}
|
|
193
|
+
interface MushiApiResponse<T> {
|
|
194
|
+
ok: boolean;
|
|
195
|
+
data?: T;
|
|
196
|
+
error?: {
|
|
197
|
+
code: string;
|
|
198
|
+
message: string;
|
|
199
|
+
};
|
|
200
|
+
}
|
|
201
|
+
|
|
202
|
+
interface ApiClientOptions {
|
|
203
|
+
projectId: string;
|
|
204
|
+
apiKey: string;
|
|
205
|
+
apiEndpoint: string;
|
|
206
|
+
timeout?: number;
|
|
207
|
+
maxRetries?: number;
|
|
208
|
+
}
|
|
209
|
+
declare function createApiClient(options: ApiClientOptions): MushiApiClient;
|
|
210
|
+
|
|
211
|
+
interface PreFilterResult {
|
|
212
|
+
passed: boolean;
|
|
213
|
+
reason?: string;
|
|
214
|
+
}
|
|
215
|
+
declare function createPreFilter(config?: MushiPreFilterConfig): {
|
|
216
|
+
check: (description: string) => PreFilterResult;
|
|
217
|
+
truncate: (description: string) => string;
|
|
218
|
+
};
|
|
219
|
+
|
|
220
|
+
interface OfflineQueue {
|
|
221
|
+
enqueue(report: MushiReport): Promise<void>;
|
|
222
|
+
flush(client: MushiApiClient): Promise<{
|
|
223
|
+
sent: number;
|
|
224
|
+
failed: number;
|
|
225
|
+
}>;
|
|
226
|
+
size(): Promise<number>;
|
|
227
|
+
clear(): Promise<void>;
|
|
228
|
+
startAutoSync(client: MushiApiClient): void;
|
|
229
|
+
stopAutoSync(): void;
|
|
230
|
+
}
|
|
231
|
+
declare function createOfflineQueue(config?: MushiOfflineConfig): OfflineQueue;
|
|
232
|
+
|
|
233
|
+
declare function captureEnvironment(): MushiEnvironment;
|
|
234
|
+
|
|
235
|
+
declare function getReporterToken(): string;
|
|
236
|
+
|
|
237
|
+
declare function getSessionId(): string;
|
|
238
|
+
|
|
239
|
+
interface RateLimiterConfig {
|
|
240
|
+
maxBurst?: number;
|
|
241
|
+
refillRate?: number;
|
|
242
|
+
refillIntervalMs?: number;
|
|
243
|
+
}
|
|
244
|
+
interface RateLimiter {
|
|
245
|
+
tryConsume(): boolean;
|
|
246
|
+
reset(): void;
|
|
247
|
+
availableTokens(): number;
|
|
248
|
+
}
|
|
249
|
+
declare function createRateLimiter(config?: RateLimiterConfig): RateLimiter;
|
|
250
|
+
|
|
251
|
+
interface PiiScrubberConfig {
|
|
252
|
+
emails?: boolean;
|
|
253
|
+
phones?: boolean;
|
|
254
|
+
creditCards?: boolean;
|
|
255
|
+
ssns?: boolean;
|
|
256
|
+
ipAddresses?: boolean;
|
|
257
|
+
}
|
|
258
|
+
declare function createPiiScrubber(config?: PiiScrubberConfig): {
|
|
259
|
+
scrub: (text: string) => string;
|
|
260
|
+
scrubObject: <T extends Record<string, unknown>>(obj: T, keys: string[]) => T;
|
|
261
|
+
};
|
|
262
|
+
declare function scrubPii(text: string, config?: PiiScrubberConfig): string;
|
|
263
|
+
|
|
264
|
+
/**
|
|
265
|
+
* FILE: logger.ts
|
|
266
|
+
* PURPOSE: Zero-dependency structured logger for the mushi-mushi SDK ecosystem.
|
|
267
|
+
*
|
|
268
|
+
* OVERVIEW:
|
|
269
|
+
* - Production-grade logging with levels, scoped namespaces, and child loggers
|
|
270
|
+
* - JSON output for server/production, pretty-formatted output for development
|
|
271
|
+
* - Automatic environment detection (browser vs Node vs Deno)
|
|
272
|
+
* - Structured metadata on every log entry
|
|
273
|
+
* - No external dependencies — safe to ship in any SDK bundle
|
|
274
|
+
*
|
|
275
|
+
* USAGE:
|
|
276
|
+
* import { createLogger } from '@mushi-mushi/core'
|
|
277
|
+
* const log = createLogger({ scope: 'mushi:api' })
|
|
278
|
+
* log.info('Request received', { method: 'POST', path: '/v1/reports' })
|
|
279
|
+
* const child = log.child('ingest', { reportId: 'abc' })
|
|
280
|
+
* child.warn('Slow query', { latencyMs: 420 })
|
|
281
|
+
*
|
|
282
|
+
* TECHNICAL DETAILS:
|
|
283
|
+
* - Log levels: debug(10) < info(20) < warn(30) < error(40) < fatal(50) < silent(99)
|
|
284
|
+
* - Format auto-detected: JSON in production/server, pretty in development
|
|
285
|
+
* - Pretty format uses ANSI colors when supported (Node/Deno TTY)
|
|
286
|
+
* - Child loggers inherit parent scope + metadata, can override level
|
|
287
|
+
* - Timestamps are ISO 8601 with millisecond precision
|
|
288
|
+
*/
|
|
289
|
+
type LogLevel = 'debug' | 'info' | 'warn' | 'error' | 'fatal' | 'silent';
|
|
290
|
+
type LogFormat = 'json' | 'pretty' | 'auto';
|
|
291
|
+
interface LoggerOptions {
|
|
292
|
+
scope: string;
|
|
293
|
+
level?: LogLevel;
|
|
294
|
+
meta?: Record<string, unknown>;
|
|
295
|
+
format?: LogFormat;
|
|
296
|
+
}
|
|
297
|
+
interface Logger {
|
|
298
|
+
debug(msg: string, meta?: Record<string, unknown>): void;
|
|
299
|
+
info(msg: string, meta?: Record<string, unknown>): void;
|
|
300
|
+
warn(msg: string, meta?: Record<string, unknown>): void;
|
|
301
|
+
error(msg: string, meta?: Record<string, unknown>): void;
|
|
302
|
+
fatal(msg: string, meta?: Record<string, unknown>): void;
|
|
303
|
+
child(scope: string, meta?: Record<string, unknown>): Logger;
|
|
304
|
+
setLevel(level: LogLevel): void;
|
|
305
|
+
}
|
|
306
|
+
interface LogEntry {
|
|
307
|
+
ts: string;
|
|
308
|
+
level: LogLevel;
|
|
309
|
+
scope: string;
|
|
310
|
+
msg: string;
|
|
311
|
+
[key: string]: unknown;
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Create a structured logger instance.
|
|
315
|
+
*
|
|
316
|
+
* @example
|
|
317
|
+
* const log = createLogger({ scope: 'mushi:api', level: 'info' })
|
|
318
|
+
* log.info('Server started', { port: 3000 })
|
|
319
|
+
*
|
|
320
|
+
* const child = log.child('auth', { userId: 'u-123' })
|
|
321
|
+
* child.warn('Token expired')
|
|
322
|
+
*/
|
|
323
|
+
declare function createLogger(options: LoggerOptions): Logger;
|
|
324
|
+
/**
|
|
325
|
+
* Noop logger that discards all output.
|
|
326
|
+
* Useful when logging should be completely disabled.
|
|
327
|
+
*/
|
|
328
|
+
declare const noopLogger: Logger;
|
|
329
|
+
|
|
330
|
+
export { type ApiClientOptions, type LogEntry, type LogFormat, type LogLevel, type Logger, type LoggerOptions, type MushiApiClient, type MushiApiResponse, type MushiCaptureConfig, type MushiConfig, type MushiConsoleEntry, type MushiCooldownConfig, type MushiEnvironment, type MushiEventHandler, type MushiEventType, type MushiIntegrationsConfig, type MushiNetworkEntry, type MushiOfflineConfig, type MushiPerformanceMetrics, type MushiPreFilterConfig, type MushiProactiveConfig, type MushiReport, type MushiReportBuilder, type MushiReportCategory, type MushiReportStatus, type MushiRewardsConfig, type MushiSDKInstance, type MushiSelectedElement, type MushiSentryConfig, type MushiWidgetConfig, type OfflineQueue, type PiiScrubberConfig, type PreFilterResult, type RateLimiter, type RateLimiterConfig, captureEnvironment, createApiClient, createLogger, createOfflineQueue, createPiiScrubber, createPreFilter, createRateLimiter, getReporterToken, getSessionId, noopLogger, scrubPii };
|