@mushi-mushi/svelte 0.8.4 → 1.0.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/CONTRIBUTING.md CHANGED
@@ -63,7 +63,7 @@ packages/
63
63
  verify/ Fix verification (BSL)
64
64
  apps/
65
65
  admin/ Admin dashboard (React + Tailwind)
66
- docs/ Documentation site (planned)
66
+ docs/ Documentation site (Nextra — apps/docs)
67
67
  tooling/
68
68
  eslint-config/ Shared ESLint flat config
69
69
  tsconfig/ Shared TypeScript configs
@@ -81,6 +81,28 @@ tooling/
81
81
  ```
82
82
  6. Open a pull request
83
83
 
84
+ ### Documentation (docs-as-code)
85
+
86
+ If your PR changes **user-visible SDK or CLI behavior**, update docs in the **same PR**:
87
+
88
+ | Surface | When to update |
89
+ | --- | --- |
90
+ | `packages/*/README.md` | npm-facing install/API/config changes for that package |
91
+ | `apps/docs/content/**/*.mdx` | Long-form guides, quickstarts, admin console docs |
92
+ | Root `README.md` | Marketing stats only when counts change — run `pnpm check:docs-stats` |
93
+
94
+ Guardrails (run locally before pushing):
95
+
96
+ ```bash
97
+ pnpm check:docs-stats # root README stat badges
98
+ pnpm check:sdk-version-matrix # apps/docs/content/sdks/index.mdx versions
99
+ pnpm check:internal-doc-links # dead /foo links in MDX
100
+ pnpm check:bundle-docs # @mushi-mushi/web size-limit vs README
101
+ pnpm gen:llms-txt # regenerate apps/docs/public/llms.txt after nav changes
102
+ ```
103
+
104
+ README changes on npm packages only appear on [npmjs.com](https://www.npmjs.com) after the next **Changesets publish**.
105
+
84
106
  ## Changesets
85
107
 
86
108
  We use [Changesets](https://github.com/changesets/changesets) for versioning. If your PR modifies a published package (`core`, `web`, `react`, `vue`, `svelte`, `angular`, `react-native`, `cli`, `mcp`), add a changeset:
package/README.md CHANGED
@@ -6,26 +6,50 @@ Svelte SDK for Mushi Mushi bug reporting. **API-only** — captures errors and s
6
6
  >
7
7
  > **Other frameworks:** [`@mushi-mushi/react`](https://npmjs.com/package/@mushi-mushi/react) · [`@mushi-mushi/vue`](https://npmjs.com/package/@mushi-mushi/vue) · [`@mushi-mushi/angular`](https://npmjs.com/package/@mushi-mushi/angular) · [`@mushi-mushi/react-native`](https://npmjs.com/package/@mushi-mushi/react-native) · [`@mushi-mushi/capacitor`](https://npmjs.com/package/@mushi-mushi/capacitor) · [`@mushi-mushi/web`](https://npmjs.com/package/@mushi-mushi/web) (vanilla JS)
8
8
 
9
+ ## Install
10
+
11
+ ```bash
12
+ npm install @mushi-mushi/svelte @mushi-mushi/web
13
+ # or: npx mushi-mushi
14
+ ```
15
+
16
+ ## Environment variables
17
+
18
+ | Stack | Project ID | API key |
19
+ | --- | --- | --- |
20
+ | Vite / SvelteKit | `VITE_MUSHI_PROJECT_ID` | `VITE_MUSHI_API_KEY` |
21
+
22
+ See [Project ID & API keys](https://docs.mushimushi.dev/concepts/credentials).
23
+
9
24
  ## Usage
10
25
 
11
26
  ```ts
12
27
  import { initMushi, getMushi } from '@mushi-mushi/svelte'
13
28
 
14
- initMushi({ projectId: 'proj_xxx', apiKey: 'mushi_xxx' })
29
+ initMushi({
30
+ projectId: import.meta.env.VITE_MUSHI_PROJECT_ID,
31
+ apiKey: import.meta.env.VITE_MUSHI_API_KEY,
32
+ })
15
33
 
16
- // Later
17
34
  const mushi = getMushi()
18
35
  mushi.submitReport({ title: 'broken', description: '...' })
19
36
  ```
20
37
 
21
- ### With Widget UI
38
+ ### With widget UI
22
39
 
23
40
  ```ts
24
41
  import { initMushi } from '@mushi-mushi/svelte'
25
42
  import { Mushi } from '@mushi-mushi/web'
26
43
 
27
- initMushi({ projectId: 'proj_xxx', apiKey: 'mushi_xxx' })
28
- Mushi.init({ projectId: 'proj_xxx', apiKey: 'mushi_xxx' })
44
+ initMushi({
45
+ projectId: import.meta.env.VITE_MUSHI_PROJECT_ID,
46
+ apiKey: import.meta.env.VITE_MUSHI_API_KEY,
47
+ })
48
+
49
+ Mushi.init({
50
+ projectId: import.meta.env.VITE_MUSHI_PROJECT_ID,
51
+ apiKey: import.meta.env.VITE_MUSHI_API_KEY,
52
+ })
29
53
  ```
30
54
 
31
55
  ### SvelteKit error handler
@@ -36,7 +60,15 @@ import { createMushiErrorHandler } from '@mushi-mushi/svelte'
36
60
  export const handleError = createMushiErrorHandler()
37
61
  ```
38
62
 
39
- ## Peer Dependencies
63
+ ## API
64
+
65
+ | Export | Purpose |
66
+ | --- | --- |
67
+ | `initMushi(config)` | Initialize once at app startup |
68
+ | `getMushi()` | Access the SDK instance |
69
+ | `createMushiErrorHandler()` | SvelteKit `handleError` integration |
70
+
71
+ ## Peer dependencies
40
72
 
41
73
  - `svelte` >= 4
42
74
 
package/dist/index.cjs CHANGED
@@ -22,24 +22,23 @@ var index_exports = {};
22
22
  __export(index_exports, {
23
23
  createMushiErrorHandler: () => createMushiErrorHandler,
24
24
  getMushi: () => getMushi,
25
- initMushi: () => initMushi
25
+ initMushi: () => initMushi,
26
+ mushiHandleError: () => mushiHandleError
26
27
  });
27
28
  module.exports = __toCommonJS(index_exports);
28
29
  var import_web = require("@mushi-mushi/web");
29
- function toCoreConfig(config) {
30
- return {
31
- projectId: config.projectId,
32
- apiKey: config.apiKey,
33
- ...config.endpoint ? { apiEndpoint: config.endpoint } : {},
34
- ...config.capture !== void 0 ? { capture: config.capture } : {}
35
- };
36
- }
30
+ var isBrowser = () => typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.document !== "undefined";
37
31
  function initMushi(config) {
38
- return import_web.Mushi.init(toCoreConfig(config));
32
+ if (!isBrowser()) return null;
33
+ return import_web.Mushi.init(config);
39
34
  }
40
35
  function getMushi() {
41
36
  const instance = import_web.Mushi.getInstance();
42
- if (!instance) throw new Error("Call initMushi() first");
37
+ if (!instance) {
38
+ throw new Error(
39
+ "Mushi not initialised \u2014 call initMushi() in src/hooks.client.ts or a top-level +layout.svelte onMount."
40
+ );
41
+ }
43
42
  return instance;
44
43
  }
45
44
  function createMushiErrorHandler() {
@@ -54,9 +53,29 @@ function createMushiErrorHandler() {
54
53
  }
55
54
  };
56
55
  }
56
+ function mushiHandleError(opts = {}) {
57
+ return (input) => {
58
+ const { error, event, status, message } = input;
59
+ const instance = import_web.Mushi.getInstance();
60
+ if (instance) {
61
+ instance.captureException(error, {
62
+ source: "sveltekit-handle-error",
63
+ metadata: {
64
+ route: event?.url?.pathname,
65
+ method: event?.request?.method,
66
+ status,
67
+ message
68
+ }
69
+ }).catch(() => {
70
+ });
71
+ }
72
+ return opts.format?.(error, event);
73
+ };
74
+ }
57
75
  // Annotate the CommonJS export names for ESM import in node:
58
76
  0 && (module.exports = {
59
77
  createMushiErrorHandler,
60
78
  getMushi,
61
- initMushi
79
+ initMushi,
80
+ mushiHandleError
62
81
  });
package/dist/index.d.cts CHANGED
@@ -1,22 +1,38 @@
1
- import { MushiSDKInstance } from '@mushi-mushi/core';
1
+ import { MushiSDKInstance, MushiConfig } from '@mushi-mushi/core';
2
+ export { MushiConfig, MushiReportCategory, MushiSDKInstance } from '@mushi-mushi/core';
2
3
 
3
4
  /**
4
5
  * FILE: packages/svelte/src/index.ts
5
- * PURPOSE: Svelte SDK for Mushi Mushi — delegates entirely to @mushi-mushi/web
6
- * so offline queue, PII scrubber, breadcrumb buffer, and rate limiter
7
- * are all inherited automatically. Mirrors the React provider pattern.
6
+ * PURPOSE: Svelte / SvelteKit SDK for Mushi Mushi — delegates entirely
7
+ * to @mushi-mushi/web so offline queue, PII scrubber, breadcrumb
8
+ * buffer, rate limiter, INP capture, beforeSendFeedback, and
9
+ * onCrashedLastRun are all inherited automatically.
10
+ *
11
+ * Round 8 (2026-05-21):
12
+ * - `MushiConfig` is now the canonical core type. Consumers get the
13
+ * full Round 7 surface (theme, position, locale, beforeSendFeedback,
14
+ * onCrashedLastRun, …) with no narrow re-shape.
15
+ * - SSR guard around `initMushi` so SvelteKit's first server-render
16
+ * doesn't reach for `window`.
17
+ * - `mushiHandleError` is the SvelteKit-shaped server-hook helper
18
+ * for `src/hooks.server.ts` — it returns `App.Error | void` to fit
19
+ * the SvelteKit type contract.
8
20
  */
9
21
 
10
- interface MushiConfig {
11
- projectId: string;
12
- apiKey: string;
13
- endpoint?: string;
14
- capture?: {
15
- discoverInventory?: boolean;
16
- };
17
- }
18
- declare function initMushi(config: MushiConfig): MushiSDKInstance;
22
+ /**
23
+ * Initialise the Mushi SDK. SSR-safe: returns `null` when run on the
24
+ * server (SvelteKit's hooks.server.ts) so the runner can skip wiring
25
+ * up on the wrong side. Mount this from `src/hooks.client.ts`'s
26
+ * `init` export, or from a top-level `+layout.svelte`'s `onMount`.
27
+ */
28
+ declare function initMushi(config: MushiConfig): MushiSDKInstance | null;
19
29
  declare function getMushi(): MushiSDKInstance;
30
+ /**
31
+ * Generic error-handler factory — works in any Svelte / SvelteKit
32
+ * context that surfaces an `{ error, event }` shape. Kept for
33
+ * backwards compatibility; new code should prefer `mushiHandleError`
34
+ * which matches SvelteKit's `handleError` server-hook type exactly.
35
+ */
20
36
  declare function createMushiErrorHandler(): ({ error, event }: {
21
37
  error: unknown;
22
38
  event?: {
@@ -25,5 +41,47 @@ declare function createMushiErrorHandler(): ({ error, event }: {
25
41
  };
26
42
  };
27
43
  }) => void;
44
+ /**
45
+ * SvelteKit `handleError` server-hook helper. Drop into
46
+ * `src/hooks.server.ts` and `src/hooks.client.ts`:
47
+ *
48
+ * ```ts
49
+ * // src/hooks.server.ts
50
+ * import type { HandleServerError } from '@sveltejs/kit'
51
+ * import { mushiHandleError } from '@mushi-mushi/svelte'
52
+ *
53
+ * export const handleError: HandleServerError = mushiHandleError({
54
+ * // optional — the default extracts a stable message from the error
55
+ * format: (error) => ({ message: 'Internal error', code: 'E_INTERNAL' }),
56
+ * })
57
+ * ```
58
+ *
59
+ * The returned hook captures the error to Mushi and forwards the
60
+ * formatted shape to SvelteKit's typed `App.Error` interface so the
61
+ * +error.svelte page receives a consistent payload.
62
+ *
63
+ * Server-side: writes via `Mushi.getInstance()` if `initMushi` was
64
+ * called from `hooks.server.ts`. Otherwise no-ops gracefully.
65
+ */
66
+ interface MushiHandleErrorOptions {
67
+ /** Optional formatter that maps the error to `App.Error`. */
68
+ format?: (error: unknown, event?: SvelteKitErrorEvent) => Record<string, unknown> | void;
69
+ }
70
+ interface SvelteKitErrorEvent {
71
+ url?: {
72
+ pathname?: string;
73
+ };
74
+ request?: {
75
+ method?: string;
76
+ };
77
+ status?: number;
78
+ message?: string;
79
+ }
80
+ declare function mushiHandleError(opts?: MushiHandleErrorOptions): (input: {
81
+ error: unknown;
82
+ event?: SvelteKitErrorEvent;
83
+ status?: number;
84
+ message?: string;
85
+ }) => Record<string, unknown> | void;
28
86
 
29
- export { type MushiConfig, createMushiErrorHandler, getMushi, initMushi };
87
+ export { type MushiHandleErrorOptions, type SvelteKitErrorEvent, createMushiErrorHandler, getMushi, initMushi, mushiHandleError };
package/dist/index.d.ts CHANGED
@@ -1,22 +1,38 @@
1
- import { MushiSDKInstance } from '@mushi-mushi/core';
1
+ import { MushiSDKInstance, MushiConfig } from '@mushi-mushi/core';
2
+ export { MushiConfig, MushiReportCategory, MushiSDKInstance } from '@mushi-mushi/core';
2
3
 
3
4
  /**
4
5
  * FILE: packages/svelte/src/index.ts
5
- * PURPOSE: Svelte SDK for Mushi Mushi — delegates entirely to @mushi-mushi/web
6
- * so offline queue, PII scrubber, breadcrumb buffer, and rate limiter
7
- * are all inherited automatically. Mirrors the React provider pattern.
6
+ * PURPOSE: Svelte / SvelteKit SDK for Mushi Mushi — delegates entirely
7
+ * to @mushi-mushi/web so offline queue, PII scrubber, breadcrumb
8
+ * buffer, rate limiter, INP capture, beforeSendFeedback, and
9
+ * onCrashedLastRun are all inherited automatically.
10
+ *
11
+ * Round 8 (2026-05-21):
12
+ * - `MushiConfig` is now the canonical core type. Consumers get the
13
+ * full Round 7 surface (theme, position, locale, beforeSendFeedback,
14
+ * onCrashedLastRun, …) with no narrow re-shape.
15
+ * - SSR guard around `initMushi` so SvelteKit's first server-render
16
+ * doesn't reach for `window`.
17
+ * - `mushiHandleError` is the SvelteKit-shaped server-hook helper
18
+ * for `src/hooks.server.ts` — it returns `App.Error | void` to fit
19
+ * the SvelteKit type contract.
8
20
  */
9
21
 
10
- interface MushiConfig {
11
- projectId: string;
12
- apiKey: string;
13
- endpoint?: string;
14
- capture?: {
15
- discoverInventory?: boolean;
16
- };
17
- }
18
- declare function initMushi(config: MushiConfig): MushiSDKInstance;
22
+ /**
23
+ * Initialise the Mushi SDK. SSR-safe: returns `null` when run on the
24
+ * server (SvelteKit's hooks.server.ts) so the runner can skip wiring
25
+ * up on the wrong side. Mount this from `src/hooks.client.ts`'s
26
+ * `init` export, or from a top-level `+layout.svelte`'s `onMount`.
27
+ */
28
+ declare function initMushi(config: MushiConfig): MushiSDKInstance | null;
19
29
  declare function getMushi(): MushiSDKInstance;
30
+ /**
31
+ * Generic error-handler factory — works in any Svelte / SvelteKit
32
+ * context that surfaces an `{ error, event }` shape. Kept for
33
+ * backwards compatibility; new code should prefer `mushiHandleError`
34
+ * which matches SvelteKit's `handleError` server-hook type exactly.
35
+ */
20
36
  declare function createMushiErrorHandler(): ({ error, event }: {
21
37
  error: unknown;
22
38
  event?: {
@@ -25,5 +41,47 @@ declare function createMushiErrorHandler(): ({ error, event }: {
25
41
  };
26
42
  };
27
43
  }) => void;
44
+ /**
45
+ * SvelteKit `handleError` server-hook helper. Drop into
46
+ * `src/hooks.server.ts` and `src/hooks.client.ts`:
47
+ *
48
+ * ```ts
49
+ * // src/hooks.server.ts
50
+ * import type { HandleServerError } from '@sveltejs/kit'
51
+ * import { mushiHandleError } from '@mushi-mushi/svelte'
52
+ *
53
+ * export const handleError: HandleServerError = mushiHandleError({
54
+ * // optional — the default extracts a stable message from the error
55
+ * format: (error) => ({ message: 'Internal error', code: 'E_INTERNAL' }),
56
+ * })
57
+ * ```
58
+ *
59
+ * The returned hook captures the error to Mushi and forwards the
60
+ * formatted shape to SvelteKit's typed `App.Error` interface so the
61
+ * +error.svelte page receives a consistent payload.
62
+ *
63
+ * Server-side: writes via `Mushi.getInstance()` if `initMushi` was
64
+ * called from `hooks.server.ts`. Otherwise no-ops gracefully.
65
+ */
66
+ interface MushiHandleErrorOptions {
67
+ /** Optional formatter that maps the error to `App.Error`. */
68
+ format?: (error: unknown, event?: SvelteKitErrorEvent) => Record<string, unknown> | void;
69
+ }
70
+ interface SvelteKitErrorEvent {
71
+ url?: {
72
+ pathname?: string;
73
+ };
74
+ request?: {
75
+ method?: string;
76
+ };
77
+ status?: number;
78
+ message?: string;
79
+ }
80
+ declare function mushiHandleError(opts?: MushiHandleErrorOptions): (input: {
81
+ error: unknown;
82
+ event?: SvelteKitErrorEvent;
83
+ status?: number;
84
+ message?: string;
85
+ }) => Record<string, unknown> | void;
28
86
 
29
- export { type MushiConfig, createMushiErrorHandler, getMushi, initMushi };
87
+ export { type MushiHandleErrorOptions, type SvelteKitErrorEvent, createMushiErrorHandler, getMushi, initMushi, mushiHandleError };
package/dist/index.js CHANGED
@@ -1,19 +1,17 @@
1
1
  // src/index.ts
2
2
  import { Mushi } from "@mushi-mushi/web";
3
- function toCoreConfig(config) {
4
- return {
5
- projectId: config.projectId,
6
- apiKey: config.apiKey,
7
- ...config.endpoint ? { apiEndpoint: config.endpoint } : {},
8
- ...config.capture !== void 0 ? { capture: config.capture } : {}
9
- };
10
- }
3
+ var isBrowser = () => typeof globalThis !== "undefined" && typeof globalThis.window !== "undefined" && typeof globalThis.document !== "undefined";
11
4
  function initMushi(config) {
12
- return Mushi.init(toCoreConfig(config));
5
+ if (!isBrowser()) return null;
6
+ return Mushi.init(config);
13
7
  }
14
8
  function getMushi() {
15
9
  const instance = Mushi.getInstance();
16
- if (!instance) throw new Error("Call initMushi() first");
10
+ if (!instance) {
11
+ throw new Error(
12
+ "Mushi not initialised \u2014 call initMushi() in src/hooks.client.ts or a top-level +layout.svelte onMount."
13
+ );
14
+ }
17
15
  return instance;
18
16
  }
19
17
  function createMushiErrorHandler() {
@@ -28,8 +26,28 @@ function createMushiErrorHandler() {
28
26
  }
29
27
  };
30
28
  }
29
+ function mushiHandleError(opts = {}) {
30
+ return (input) => {
31
+ const { error, event, status, message } = input;
32
+ const instance = Mushi.getInstance();
33
+ if (instance) {
34
+ instance.captureException(error, {
35
+ source: "sveltekit-handle-error",
36
+ metadata: {
37
+ route: event?.url?.pathname,
38
+ method: event?.request?.method,
39
+ status,
40
+ message
41
+ }
42
+ }).catch(() => {
43
+ });
44
+ }
45
+ return opts.format?.(error, event);
46
+ };
47
+ }
31
48
  export {
32
49
  createMushiErrorHandler,
33
50
  getMushi,
34
- initMushi
51
+ initMushi,
52
+ mushiHandleError
35
53
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mushi-mushi/svelte",
3
- "version": "0.8.4",
3
+ "version": "1.0.0",
4
4
  "license": "MIT",
5
5
  "description": "Svelte SDK for Mushi Mushi — context-based init, SvelteKit error hook integration",
6
6
  "main": "./dist/index.js",
@@ -10,8 +10,8 @@
10
10
  "svelte": ">=4"
11
11
  },
12
12
  "dependencies": {
13
- "@mushi-mushi/core": "^1.2.0",
14
- "@mushi-mushi/web": "^1.2.0"
13
+ "@mushi-mushi/core": "^1.15.0",
14
+ "@mushi-mushi/web": "^1.14.1"
15
15
  },
16
16
  "devDependencies": {
17
17
  "eslint": "^10.3.0",