@mushi-mushi/core 1.2.0 → 1.6.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
@@ -21,6 +21,10 @@ interface MushiConfig {
21
21
  rewards?: MushiRewardsConfig;
22
22
  debug?: boolean;
23
23
  enabled?: boolean;
24
+ /** Hook called before a report is sent. Return null to cancel, or return the (possibly modified) report. */
25
+ beforeSendFeedback?: (report: MushiReport) => MushiReport | null | Promise<MushiReport | null>;
26
+ /** Called once if the app crashed during the previous session. */
27
+ onCrashedLastRun?: (crashed: boolean) => void;
24
28
  }
25
29
  interface MushiSentryConfig {
26
30
  dsn?: string;
@@ -73,6 +77,38 @@ interface MushiWidgetConfig {
73
77
  * actively inviting feedback.
74
78
  */
75
79
  betaMode?: MushiBetaModeConfig;
80
+ /**
81
+ * Absolute base URL of the Mushi admin console (e.g. `https://mushi.example.com`).
82
+ * When set, the success step surfaces a one-tap link to the user's own report
83
+ * on the console so they can watch the status change in real time. Without
84
+ * this the success step still confirms submission but cannot deep-link.
85
+ *
86
+ * This is intentionally separate from the API endpoint — production apps
87
+ * usually have the API on `api.mushi.example.com` and the console on
88
+ * `app.mushi.example.com`.
89
+ */
90
+ dashboardUrl?: string;
91
+ /**
92
+ * Override the SLA copy shown in the success step's "what happens next"
93
+ * line. Defaults to "We aim to review within 48h". Set to an empty string
94
+ * to hide the line entirely (e.g. internal-only deployments where SLA
95
+ * messaging would be over-promising).
96
+ */
97
+ responseSlaLabel?: string;
98
+ /**
99
+ * Show a first-class "Feature request" card at the top of the category
100
+ * step. Defaults to true. Set to false for production-only deployments
101
+ * where you don't want to invite feature ideas through the widget.
102
+ * Internally this maps to `category='other'` with
103
+ * `user_category='Feature request'` so no DB migration is needed.
104
+ */
105
+ featureRequestCard?: boolean;
106
+ /** Override the localised label for the feature-request card. */
107
+ featureRequestLabel?: string;
108
+ /** Override the helper text shown under the feature-request card. */
109
+ featureRequestDescription?: string;
110
+ /** Minimum description character count before the submit button enables. */
111
+ minDescriptionLength?: number;
76
112
  }
77
113
  interface MushiBetaModeConfig {
78
114
  enabled?: boolean;
@@ -198,6 +234,17 @@ interface MushiPrivacyConfig {
198
234
  maskSelectors?: string[];
199
235
  /** DOM subtrees to remove from screenshots before upload. */
200
236
  blockSelectors?: string[];
237
+ /**
238
+ * CSS selectors whose matching elements are blacked-out (filled with an
239
+ * opaque black rectangle) in screenshots before upload. Intended for
240
+ * sensitive fields that should never appear in any form — passwords, PII,
241
+ * financial data. Applied in addition to `maskSelectors`.
242
+ *
243
+ * Default: `['input[type="password"]', '[data-mushi-redact]']`
244
+ *
245
+ * To disable the default redaction, pass an empty array.
246
+ */
247
+ redactSelectors?: string[];
201
248
  /** Let reporters remove an attached screenshot before submitting. Defaults to true. */
202
249
  allowUserRemoveScreenshot?: boolean;
203
250
  }
@@ -207,6 +254,38 @@ interface MushiProactiveConfig {
207
254
  longTask?: boolean;
208
255
  apiCascade?: boolean | MushiApiCascadeConfig;
209
256
  cooldown?: MushiCooldownConfig;
257
+ /**
258
+ * Beta-mode nudge: fire after the user has been on the same route for
259
+ * `thresholdMs` continuous milliseconds (default 5min). Pass `true` to
260
+ * accept the default threshold, or a config object to override. Use
261
+ * conservatively — set the per-session cap in `cooldown` to avoid
262
+ * nag fatigue.
263
+ */
264
+ pageDwell?: boolean | MushiPageDwellConfig;
265
+ /**
266
+ * One-shot welcome prompt for first-time visitors. Fires `delayMs` after
267
+ * `Mushi.init` (default 45s) and is suppressed permanently after the
268
+ * first fire via localStorage. Recommended for beta deployments.
269
+ */
270
+ firstSession?: boolean | MushiFirstSessionConfig;
271
+ }
272
+ interface MushiPageDwellConfig {
273
+ /** Continuous dwell time before firing. Defaults to 5 minutes. */
274
+ thresholdMs?: number;
275
+ /**
276
+ * Route path prefixes (or glob-style patterns with `*`) that suppress the
277
+ * dwell nudge. Auth routes are excluded by default so users aren't prompted
278
+ * during login/signup flows.
279
+ *
280
+ * Default: `['/login', '/logout', '/signup', '/sso/*', '/auth/*']`
281
+ */
282
+ excludeRoutes?: string[];
283
+ }
284
+ interface MushiFirstSessionConfig {
285
+ /** Delay before firing the welcome nudge. Defaults to 45 seconds. */
286
+ delayMs?: number;
287
+ /** Override the localStorage key used to mark the user as welcomed. */
288
+ storageKey?: string;
210
289
  }
211
290
  type MushiUrlMatcher = string | RegExp;
212
291
  interface MushiApiCascadeConfig {
@@ -665,6 +744,13 @@ interface MushiPerformanceMetrics {
665
744
  inp?: number;
666
745
  ttfb?: number;
667
746
  longTasks?: number;
747
+ inpAttribution?: {
748
+ eventType?: string;
749
+ targetSelector?: string;
750
+ inputDelay?: number;
751
+ processingDuration?: number;
752
+ presentationDelay?: number;
753
+ };
668
754
  }
669
755
  interface MushiSelectedElement {
670
756
  tagName: string;
@@ -697,7 +783,7 @@ interface MushiTimelineEntry {
697
783
  kind: MushiTimelineKind;
698
784
  payload: Record<string, unknown>;
699
785
  }
700
- type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
786
+ type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed' | 'report:dispatched';
701
787
  type MushiEventHandler = (event: {
702
788
  type: MushiEventType;
703
789
  data?: unknown;
@@ -714,8 +800,16 @@ interface MushiDiagnosticsResult {
714
800
  sdkVersion: string;
715
801
  }
716
802
  interface MushiSDKInstance {
803
+ /**
804
+ * Open the reporter widget. With no options, opens to the category
805
+ * picker so the user can choose between bug categories and the
806
+ * feature-request shortcut. Pass `{ category }` to deep-link into a
807
+ * specific bug intent, or `{ featureRequest: true }` to deep-link into
808
+ * the feature-request description step (skips intent picker).
809
+ */
717
810
  report(options?: {
718
811
  category?: MushiReportCategory;
812
+ featureRequest?: boolean;
719
813
  }): void;
720
814
  on(event: MushiEventType, handler: MushiEventHandler): () => void;
721
815
  setUser(user: {
@@ -816,6 +910,12 @@ interface MushiSDKInstance {
816
910
  * No-op when rewards are disabled or the user has not opted in.
817
911
  */
818
912
  recordActivity(action: string, metadata?: Record<string, unknown>): void;
913
+ /**
914
+ * Briefly animate the bug-report trigger button to draw the user's
915
+ * attention without opening the full widget. Ideal for subtle "feedback
916
+ * welcome" nudges (first-session, beta-onboarding).
917
+ */
918
+ pulseTrigger(): void;
819
919
  }
820
920
  interface MushiCaptureExceptionOptions {
821
921
  /** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
package/dist/index.d.ts CHANGED
@@ -21,6 +21,10 @@ interface MushiConfig {
21
21
  rewards?: MushiRewardsConfig;
22
22
  debug?: boolean;
23
23
  enabled?: boolean;
24
+ /** Hook called before a report is sent. Return null to cancel, or return the (possibly modified) report. */
25
+ beforeSendFeedback?: (report: MushiReport) => MushiReport | null | Promise<MushiReport | null>;
26
+ /** Called once if the app crashed during the previous session. */
27
+ onCrashedLastRun?: (crashed: boolean) => void;
24
28
  }
25
29
  interface MushiSentryConfig {
26
30
  dsn?: string;
@@ -73,6 +77,38 @@ interface MushiWidgetConfig {
73
77
  * actively inviting feedback.
74
78
  */
75
79
  betaMode?: MushiBetaModeConfig;
80
+ /**
81
+ * Absolute base URL of the Mushi admin console (e.g. `https://mushi.example.com`).
82
+ * When set, the success step surfaces a one-tap link to the user's own report
83
+ * on the console so they can watch the status change in real time. Without
84
+ * this the success step still confirms submission but cannot deep-link.
85
+ *
86
+ * This is intentionally separate from the API endpoint — production apps
87
+ * usually have the API on `api.mushi.example.com` and the console on
88
+ * `app.mushi.example.com`.
89
+ */
90
+ dashboardUrl?: string;
91
+ /**
92
+ * Override the SLA copy shown in the success step's "what happens next"
93
+ * line. Defaults to "We aim to review within 48h". Set to an empty string
94
+ * to hide the line entirely (e.g. internal-only deployments where SLA
95
+ * messaging would be over-promising).
96
+ */
97
+ responseSlaLabel?: string;
98
+ /**
99
+ * Show a first-class "Feature request" card at the top of the category
100
+ * step. Defaults to true. Set to false for production-only deployments
101
+ * where you don't want to invite feature ideas through the widget.
102
+ * Internally this maps to `category='other'` with
103
+ * `user_category='Feature request'` so no DB migration is needed.
104
+ */
105
+ featureRequestCard?: boolean;
106
+ /** Override the localised label for the feature-request card. */
107
+ featureRequestLabel?: string;
108
+ /** Override the helper text shown under the feature-request card. */
109
+ featureRequestDescription?: string;
110
+ /** Minimum description character count before the submit button enables. */
111
+ minDescriptionLength?: number;
76
112
  }
77
113
  interface MushiBetaModeConfig {
78
114
  enabled?: boolean;
@@ -198,6 +234,17 @@ interface MushiPrivacyConfig {
198
234
  maskSelectors?: string[];
199
235
  /** DOM subtrees to remove from screenshots before upload. */
200
236
  blockSelectors?: string[];
237
+ /**
238
+ * CSS selectors whose matching elements are blacked-out (filled with an
239
+ * opaque black rectangle) in screenshots before upload. Intended for
240
+ * sensitive fields that should never appear in any form — passwords, PII,
241
+ * financial data. Applied in addition to `maskSelectors`.
242
+ *
243
+ * Default: `['input[type="password"]', '[data-mushi-redact]']`
244
+ *
245
+ * To disable the default redaction, pass an empty array.
246
+ */
247
+ redactSelectors?: string[];
201
248
  /** Let reporters remove an attached screenshot before submitting. Defaults to true. */
202
249
  allowUserRemoveScreenshot?: boolean;
203
250
  }
@@ -207,6 +254,38 @@ interface MushiProactiveConfig {
207
254
  longTask?: boolean;
208
255
  apiCascade?: boolean | MushiApiCascadeConfig;
209
256
  cooldown?: MushiCooldownConfig;
257
+ /**
258
+ * Beta-mode nudge: fire after the user has been on the same route for
259
+ * `thresholdMs` continuous milliseconds (default 5min). Pass `true` to
260
+ * accept the default threshold, or a config object to override. Use
261
+ * conservatively — set the per-session cap in `cooldown` to avoid
262
+ * nag fatigue.
263
+ */
264
+ pageDwell?: boolean | MushiPageDwellConfig;
265
+ /**
266
+ * One-shot welcome prompt for first-time visitors. Fires `delayMs` after
267
+ * `Mushi.init` (default 45s) and is suppressed permanently after the
268
+ * first fire via localStorage. Recommended for beta deployments.
269
+ */
270
+ firstSession?: boolean | MushiFirstSessionConfig;
271
+ }
272
+ interface MushiPageDwellConfig {
273
+ /** Continuous dwell time before firing. Defaults to 5 minutes. */
274
+ thresholdMs?: number;
275
+ /**
276
+ * Route path prefixes (or glob-style patterns with `*`) that suppress the
277
+ * dwell nudge. Auth routes are excluded by default so users aren't prompted
278
+ * during login/signup flows.
279
+ *
280
+ * Default: `['/login', '/logout', '/signup', '/sso/*', '/auth/*']`
281
+ */
282
+ excludeRoutes?: string[];
283
+ }
284
+ interface MushiFirstSessionConfig {
285
+ /** Delay before firing the welcome nudge. Defaults to 45 seconds. */
286
+ delayMs?: number;
287
+ /** Override the localStorage key used to mark the user as welcomed. */
288
+ storageKey?: string;
210
289
  }
211
290
  type MushiUrlMatcher = string | RegExp;
212
291
  interface MushiApiCascadeConfig {
@@ -665,6 +744,13 @@ interface MushiPerformanceMetrics {
665
744
  inp?: number;
666
745
  ttfb?: number;
667
746
  longTasks?: number;
747
+ inpAttribution?: {
748
+ eventType?: string;
749
+ targetSelector?: string;
750
+ inputDelay?: number;
751
+ processingDuration?: number;
752
+ presentationDelay?: number;
753
+ };
668
754
  }
669
755
  interface MushiSelectedElement {
670
756
  tagName: string;
@@ -697,7 +783,7 @@ interface MushiTimelineEntry {
697
783
  kind: MushiTimelineKind;
698
784
  payload: Record<string, unknown>;
699
785
  }
700
- type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed';
786
+ type MushiEventType = 'report:submitted' | 'report:queued' | 'report:sent' | 'report:failed' | 'widget:opened' | 'widget:closed' | 'proactive:triggered' | 'proactive:dismissed' | 'report:dispatched';
701
787
  type MushiEventHandler = (event: {
702
788
  type: MushiEventType;
703
789
  data?: unknown;
@@ -714,8 +800,16 @@ interface MushiDiagnosticsResult {
714
800
  sdkVersion: string;
715
801
  }
716
802
  interface MushiSDKInstance {
803
+ /**
804
+ * Open the reporter widget. With no options, opens to the category
805
+ * picker so the user can choose between bug categories and the
806
+ * feature-request shortcut. Pass `{ category }` to deep-link into a
807
+ * specific bug intent, or `{ featureRequest: true }` to deep-link into
808
+ * the feature-request description step (skips intent picker).
809
+ */
717
810
  report(options?: {
718
811
  category?: MushiReportCategory;
812
+ featureRequest?: boolean;
719
813
  }): void;
720
814
  on(event: MushiEventType, handler: MushiEventHandler): () => void;
721
815
  setUser(user: {
@@ -816,6 +910,12 @@ interface MushiSDKInstance {
816
910
  * No-op when rewards are disabled or the user has not opted in.
817
911
  */
818
912
  recordActivity(action: string, metadata?: Record<string, unknown>): void;
913
+ /**
914
+ * Briefly animate the bug-report trigger button to draw the user's
915
+ * attention without opening the full widget. Ideal for subtle "feedback
916
+ * welcome" nudges (first-session, beta-onboarding).
917
+ */
918
+ pulseTrigger(): void;
819
919
  }
820
920
  interface MushiCaptureExceptionOptions {
821
921
  /** Override the default `'bug'` category (e.g. `'slow'` for timeouts). */
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/core",
3
- "version": "1.2.0",
3
+ "version": "1.6.0",
4
4
  "description": "Core types, API client, and pre-filter for Mushi Mushi SDK",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -62,6 +62,15 @@
62
62
  "provenance": true
63
63
  },
64
64
  "sideEffects": false,
65
+ "scripts": {
66
+ "build": "tsup",
67
+ "dev": "tsup --watch",
68
+ "clean": "rm -rf dist .turbo",
69
+ "lint": "eslint src/",
70
+ "typecheck": "tsc --noEmit",
71
+ "test": "vitest run",
72
+ "size": "size-limit"
73
+ },
65
74
  "size-limit": [
66
75
  {
67
76
  "path": "dist/index.js",
@@ -69,27 +78,18 @@
69
78
  }
70
79
  ],
71
80
  "devDependencies": {
81
+ "@mushi-mushi/eslint-config": "workspace:*",
82
+ "@mushi-mushi/tsconfig": "workspace:*",
72
83
  "@size-limit/file": "^12.1.0",
73
84
  "eslint": "^10.3.0",
74
85
  "jsdom": "^29.1.1",
75
86
  "size-limit": "^12.1.0",
76
87
  "tsup": "^8.5.1",
77
88
  "typescript": "^6.0.3",
78
- "vitest": "^4.1.5",
79
- "@mushi-mushi/eslint-config": "0.0.0",
80
- "@mushi-mushi/tsconfig": "0.0.0"
89
+ "vitest": "^4.1.5"
81
90
  },
82
91
  "author": "Kenji Sakuramoto",
83
92
  "engines": {
84
93
  "node": ">=20"
85
- },
86
- "scripts": {
87
- "build": "tsup",
88
- "dev": "tsup --watch",
89
- "clean": "rm -rf dist .turbo",
90
- "lint": "eslint src/",
91
- "typecheck": "tsc --noEmit",
92
- "test": "vitest run",
93
- "size": "size-limit"
94
94
  }
95
- }
95
+ }