From 78061f335c068451b15bd1442061bf2541e49543 Mon Sep 17 00:00:00 2001 From: Reversean Date: Wed, 24 Dec 2025 12:32:56 +0300 Subject: [PATCH 1/3] feat(sveltekit-integration): add global error handlers test pages in sveltekit playground --- packages/sveltekit/playground/README.md | 30 ++++ packages/sveltekit/playground/src/app.css | 169 ++++++++++++++++++ .../sveltekit/playground/src/hooks.client.ts | 8 + .../playground/src/routes/+page.svelte | 60 +++++++ .../errors/promise-rejection/+page.svelte | 15 ++ .../routes/errors/runtime-error/+page.svelte | 15 ++ 6 files changed, 297 insertions(+) create mode 100644 packages/sveltekit/playground/src/routes/errors/promise-rejection/+page.svelte create mode 100644 packages/sveltekit/playground/src/routes/errors/runtime-error/+page.svelte diff --git a/packages/sveltekit/playground/README.md b/packages/sveltekit/playground/README.md index 8151b23..81966a4 100644 --- a/packages/sveltekit/playground/README.md +++ b/packages/sveltekit/playground/README.md @@ -5,6 +5,9 @@ Test playground for Hawk Error Tracker integration with SvelteKit. ## Table of Contents - [Getting Started](#getting-started) +- [Hawk Integration](#hawk-integration) +- [Error Handling](#error-handling) +- [Error Test Pages](#error-test-pages) ## Getting Started @@ -40,3 +43,30 @@ Hawk automatically registers global error handlers for: - `window.onerror` - `window.onunhandledrejection` + +**Note:** Hawk Catcher currently catches only client-side errors via global event listeners (๐ŸŸก). + +## Error Handling + +### Global Error Handlers (๐ŸŸก) + +Global browser error handlers that catch unhandled errors: + +- **`window.error`** +- **`window.unhandledrejection`** + +**Caught by Hawk Catcher.** + +## Error Test Pages + +The playground includes test pages to demonstrate each error catching mechanism: + +### Global Error Handlers (๐ŸŸก) - Caught by Hawk + +1. **Runtime Error** (`/errors/runtime-error`) + - Demonstrates synchronous error in event handler + - Caught by window event listener `error` + +2. **Promise Rejection** (`/errors/promise-rejection`) + - Demonstrates unhandled Promise rejection + - Caught by window event listener `unhandledrejection` diff --git a/packages/sveltekit/playground/src/app.css b/packages/sveltekit/playground/src/app.css index e69de29..40f3c7b 100644 --- a/packages/sveltekit/playground/src/app.css +++ b/packages/sveltekit/playground/src/app.css @@ -0,0 +1,169 @@ +@import url('https://fonts.googleapis.com/css2?family=Roboto:wght@400;500;700&display=swap'); + +:root { + --bg-primary: #2f3341; + --bg-secondary: #242732; + --text-primary: #dbe6ff; + --text-secondary: rgba(219, 230, 255, 0.6); + --border-color: rgba(219, 230, 255, 0.1); + --button-primary: #4979e4; + --button-primary-hover: #4869d2; +} + +body { + font-family: Roboto, system-ui, sans-serif; + margin: 0; + padding: 0; + background: var(--bg-primary); + color: var(--text-primary); + font-size: 13px; +} + +header { + padding: 30px; + background: var(--bg-secondary); +} + +h1 { + font-weight: bold; + font-size: 20px; + margin: 0 0 15px; + color: var(--text-primary); +} + +h2 { + font-weight: 500; + margin: 0 0 10px; + font-size: 13px; + color: var(--text-secondary); + letter-spacing: 0.24px; + text-transform: uppercase; +} + +h3 { + margin: 0 0 10px 0; + color: var(--text-primary); + font-size: 16px; + font-weight: 500; +} + +p { + margin: 0.5rem 0; + color: var(--text-primary); +} + +a { + color: inherit; + text-decoration: underline; +} + +a:hover { + color: var(--button-primary); +} + +section { + padding: 15px; + border: 1px solid var(--border-color); + border-radius: 4px; + margin: 15px; +} + +button { + display: inline-block; + padding: 8px 20px; + border: 0; + border-radius: 5px; + background: var(--button-primary); + color: var(--text-primary); + font-weight: 500; + font-size: 14px; + cursor: pointer; + font-family: inherit; +} + +button:hover { + background: var(--button-primary-hover); +} + +button:disabled { + opacity: 0.5; + cursor: not-allowed; +} + +code { + background: var(--bg-secondary); + padding: 2px 6px; + border-radius: 3px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 0.9em; +} + +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 15px; +} + +.test-card { + display: block; + padding: 20px; + border: 2px solid var(--border-color); + border-radius: 8px; + text-decoration: none; + color: inherit; + transition: all 0.2s ease; + background: var(--bg-secondary); +} + +.test-card:hover { + border-color: var(--button-primary); + transform: translateY(-2px); + box-shadow: 0 4px 8px rgba(0, 0, 0, 0.3); +} + +.test-card h3 { + margin: 0 0 10px 0; + font-size: 16px; +} + +.test-card p { + margin: 0; + color: var(--text-secondary); + font-size: 13px; + line-height: 1.5; +} + +.alert { + padding: 15px; + border-left: 4px solid; + border-radius: 4px; + margin: 15px 0; +} + +.alert-warning { + background: rgba(255, 193, 7, 0.15); + border-color: #ffc107; + color: #ffd54f; +} + +.error-fallback { + padding: 1.5rem; + background: rgba(244, 67, 54, 0.15); + border-left: 4px solid #f44336; + border-radius: 4px; +} + +.error-fallback h3 { + margin: 0 0 0.5rem 0; + color: #ff8a80; +} + +.error-fallback p { + margin: 0.5rem 0; +} diff --git a/packages/sveltekit/playground/src/hooks.client.ts b/packages/sveltekit/playground/src/hooks.client.ts index 4154746..298dfe1 100644 --- a/packages/sveltekit/playground/src/hooks.client.ts +++ b/packages/sveltekit/playground/src/hooks.client.ts @@ -5,3 +5,11 @@ if (import.meta.env.VITE_HAWK_TOKEN) { token: import.meta.env.VITE_HAWK_TOKEN, }); } + +window.addEventListener('error', (event) => { + console.error('๐ŸŸก [window.error]', event.error, `at ${event.filename}:${event.lineno}`); +}); + +window.addEventListener('unhandledrejection', (event) => { + console.error('๐ŸŸก [window.unhandledrejection]', event.reason); +}); diff --git a/packages/sveltekit/playground/src/routes/+page.svelte b/packages/sveltekit/playground/src/routes/+page.svelte index dcea8f7..ad9de00 100644 --- a/packages/sveltekit/playground/src/routes/+page.svelte +++ b/packages/sveltekit/playground/src/routes/+page.svelte @@ -1,3 +1,63 @@ + + Hawk Javascript SvelteKit Integration Playground + +
+
+

๐Ÿงช SvelteKit Error Handling Test Suite

+
+ +
+ โš ๏ธ Testing Instructions: +
    +
  • Open your browser's DevTools Console to see error logs
  • +
  • Look for colored emoji markers: +
      +
    • ๐ŸŸก = Caught by global window.error or window.unhandledrejection
    • +
    +
  • +
  • Each test demonstrates where errors are caught in the SvelteKit error handling hierarchy
  • +
+
+ + {#each categories as category} +
+

{category}

+
+ {#each errorTests.filter(t => t.category === category) as test} + +

{test.title}

+

{test.description}

+
+ {/each} +
+
+ {/each} +
diff --git a/packages/sveltekit/playground/src/routes/errors/promise-rejection/+page.svelte b/packages/sveltekit/playground/src/routes/errors/promise-rejection/+page.svelte new file mode 100644 index 0000000..519ebf5 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/promise-rejection/+page.svelte @@ -0,0 +1,15 @@ + + +
+

Unhandled Promise Rejection Test

+

Click the button to trigger an unhandled promise rejection.

+

Caught by: window.unhandledrejection (๐ŸŸก yellow dot in console)

+ + +
diff --git a/packages/sveltekit/playground/src/routes/errors/runtime-error/+page.svelte b/packages/sveltekit/playground/src/routes/errors/runtime-error/+page.svelte new file mode 100644 index 0000000..b00543a --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/runtime-error/+page.svelte @@ -0,0 +1,15 @@ + + +
+

Window Error Handler Test

+

Click the button to trigger a runtime error.

+

Caught by: window.onerror (๐ŸŸก yellow dot in console)

+ + +
From 74b16fd9f53a20650956d13c30336f20d00a0700 Mon Sep 17 00:00:00 2001 From: Reversean Date: Wed, 24 Dec 2025 12:38:24 +0300 Subject: [PATCH 2/3] feat(sveltekit-integration): add error boundary test page in sveltekit playground --- packages/sveltekit/playground/README.md | 29 +++++++++++++++ .../playground/src/routes/+page.svelte | 9 +++++ .../src/routes/errors/boundary/+page.svelte | 37 +++++++++++++++++++ .../errors/boundary/ErrorComponent.svelte | 9 +++++ 4 files changed, 84 insertions(+) create mode 100644 packages/sveltekit/playground/src/routes/errors/boundary/+page.svelte create mode 100644 packages/sveltekit/playground/src/routes/errors/boundary/ErrorComponent.svelte diff --git a/packages/sveltekit/playground/README.md b/packages/sveltekit/playground/README.md index 81966a4..de61b9b 100644 --- a/packages/sveltekit/playground/README.md +++ b/packages/sveltekit/playground/README.md @@ -57,6 +57,28 @@ Global browser error handlers that catch unhandled errors: **Caught by Hawk Catcher.** +### Error Boundaries (๐ŸŸข) + +Svelte `` catches errors during: + +- Component rendering (synchronous errors in component body) +- Component initialization + +Example usage: + +```svelte + + + + {#snippet failed(error, reset)} +

Error: {error.message}

+ + {/snippet} +
+``` + +**Not caught by Hawk Catcher.** + ## Error Test Pages The playground includes test pages to demonstrate each error catching mechanism: @@ -70,3 +92,10 @@ The playground includes test pages to demonstrate each error catching mechanism: 2. **Promise Rejection** (`/errors/promise-rejection`) - Demonstrates unhandled Promise rejection - Caught by window event listener `unhandledrejection` + +### Error Boundaries (๐ŸŸข) - Not caught by Hawk + +1. **Boundary Error** (`/errors/boundary`) + - Demonstrates svelte boundary feature + - Caught by `` + diff --git a/packages/sveltekit/playground/src/routes/+page.svelte b/packages/sveltekit/playground/src/routes/+page.svelte index ad9de00..e887769 100644 --- a/packages/sveltekit/playground/src/routes/+page.svelte +++ b/packages/sveltekit/playground/src/routes/+page.svelte @@ -20,6 +20,14 @@ href: '/errors/promise-rejection', category: 'Global Error Handlers (๐ŸŸก)' }, + + // Error Boundaries + { + title: 'Boundary Error', + description: 'Error caught by svelte:boundary', + href: '/errors/boundary', + category: 'Error Boundaries (๐ŸŸข)' + }, ]; const categories = Array.from(new Set(errorTests.map(t => t.category))); @@ -41,6 +49,7 @@
  • Look for colored emoji markers:
    • ๐ŸŸก = Caught by global window.error or window.unhandledrejection
    • +
    • ๐ŸŸข = Caught by <svelte:boundary>
  • Each test demonstrates where errors are caught in the SvelteKit error handling hierarchy
  • diff --git a/packages/sveltekit/playground/src/routes/errors/boundary/+page.svelte b/packages/sveltekit/playground/src/routes/errors/boundary/+page.svelte new file mode 100644 index 0000000..56b89f2 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/boundary/+page.svelte @@ -0,0 +1,37 @@ + + +
    +

    Error Boundary Test

    +

    Click the button to trigger a rendering error.

    +

    Caught by: <svelte:boundary> (๐ŸŸข green dot in console)

    + + + + {#snippet failed(error, reset)} +
    +

    Error Boundary Caught Error

    +

    Message: {error.message}

    + +
    + {/snippet} + + + {#if showError} + + {/if} + +
    diff --git a/packages/sveltekit/playground/src/routes/errors/boundary/ErrorComponent.svelte b/packages/sveltekit/playground/src/routes/errors/boundary/ErrorComponent.svelte new file mode 100644 index 0000000..f09d396 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/boundary/ErrorComponent.svelte @@ -0,0 +1,9 @@ + + +
    This should not render if error is thrown
    From 182516f97c0a23f1f91bed4c5133beb1eca85a02 Mon Sep 17 00:00:00 2001 From: Reversean Date: Tue, 3 Feb 2026 01:00:35 +0300 Subject: [PATCH 3/3] feat(sveltekit-integration): add SSR error boundary test page in sveltekit playground --- packages/sveltekit/playground/README.md | 11 +++++++++ .../sveltekit/playground/src/hooks.server.ts | 10 ++++++++ .../playground/src/routes/+page.svelte | 9 ++++++++ .../routes/errors/server-error/+error.svelte | 20 ++++++++++++++++ .../errors/server-error/+page.server.ts | 13 +++++++++++ .../routes/errors/server-error/+page.svelte | 23 +++++++++++++++++++ 6 files changed, 86 insertions(+) create mode 100644 packages/sveltekit/playground/src/hooks.server.ts create mode 100644 packages/sveltekit/playground/src/routes/errors/server-error/+error.svelte create mode 100644 packages/sveltekit/playground/src/routes/errors/server-error/+page.server.ts create mode 100644 packages/sveltekit/playground/src/routes/errors/server-error/+page.svelte diff --git a/packages/sveltekit/playground/README.md b/packages/sveltekit/playground/README.md index de61b9b..a705211 100644 --- a/packages/sveltekit/playground/README.md +++ b/packages/sveltekit/playground/README.md @@ -79,6 +79,12 @@ Example usage: **Not caught by Hawk Catcher.** +### SSR Errors (๐Ÿ”ด) + +Server-side errors in `load` functions are caught by `handleError` hook in `hooks.server.ts`. + +**Not caught by Hawk Catcher.** + ## Error Test Pages The playground includes test pages to demonstrate each error catching mechanism: @@ -99,3 +105,8 @@ The playground includes test pages to demonstrate each error catching mechanism: - Demonstrates svelte boundary feature - Caught by `` +### SSR Errors (๐Ÿ”ด) - Not caught by Hawk + +1. **Server-side Error** (`/errors/server-error`) + - Demonstrates error in `load` function + - Caught by `handleError` in `hooks.server.ts` diff --git a/packages/sveltekit/playground/src/hooks.server.ts b/packages/sveltekit/playground/src/hooks.server.ts new file mode 100644 index 0000000..93dcbcb --- /dev/null +++ b/packages/sveltekit/playground/src/hooks.server.ts @@ -0,0 +1,10 @@ +import type { HandleServerError } from '@sveltejs/kit'; + +export const handleError: HandleServerError = async ({ error, event, status, message }) => { + console.error('๐Ÿ”ด [server.handleError]', error, `at ${event.url.pathname}`); + + return { + message, + status, + }; +}; diff --git a/packages/sveltekit/playground/src/routes/+page.svelte b/packages/sveltekit/playground/src/routes/+page.svelte index e887769..8509a6b 100644 --- a/packages/sveltekit/playground/src/routes/+page.svelte +++ b/packages/sveltekit/playground/src/routes/+page.svelte @@ -28,6 +28,14 @@ href: '/errors/boundary', category: 'Error Boundaries (๐ŸŸข)' }, + + // SSR Errors + { + title: 'Server-side Error', + description: 'Error thrown in load function', + href: '/errors/server-error', + category: 'SSR Errors (๐Ÿ”ด)' + }, ]; const categories = Array.from(new Set(errorTests.map(t => t.category))); @@ -48,6 +56,7 @@
  • Open your browser's DevTools Console to see error logs
  • Look for colored emoji markers:
      +
    • ๐Ÿ”ด = SSR error (caught by handleError in hooks.server.ts)
    • ๐ŸŸก = Caught by global window.error or window.unhandledrejection
    • ๐ŸŸข = Caught by <svelte:boundary>
    diff --git a/packages/sveltekit/playground/src/routes/errors/server-error/+error.svelte b/packages/sveltekit/playground/src/routes/errors/server-error/+error.svelte new file mode 100644 index 0000000..1e697c6 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/server-error/+error.svelte @@ -0,0 +1,20 @@ + + +
    +

    Server-side Error Test

    +

    Caught by: handleError in hooks.server.ts (๐Ÿ”ด red dot in console)

    + +
    +

    Server Error Caught

    +

    Status: {$page.status}

    +

    Message: {$page.error?.message}

    + +
    +
    diff --git a/packages/sveltekit/playground/src/routes/errors/server-error/+page.server.ts b/packages/sveltekit/playground/src/routes/errors/server-error/+page.server.ts new file mode 100644 index 0000000..735d886 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/server-error/+page.server.ts @@ -0,0 +1,13 @@ +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ url }) => { + const shouldError = url.searchParams.get('error') === 'true'; + + if (shouldError) { + throw new Error('Server-side error in load function'); + } + + return { + message: 'Server data loaded successfully', + }; +}; diff --git a/packages/sveltekit/playground/src/routes/errors/server-error/+page.svelte b/packages/sveltekit/playground/src/routes/errors/server-error/+page.svelte new file mode 100644 index 0000000..d9d8cd5 --- /dev/null +++ b/packages/sveltekit/playground/src/routes/errors/server-error/+page.svelte @@ -0,0 +1,23 @@ + + +
    +

    Server-side Error Test

    +

    Click the button to trigger a server-side error in load function.

    +

    Caught by: handleError in hooks.server.ts (๐Ÿ”ด red dot in console)

    + + + +
    +

    {data.message}

    +
    +