diff --git a/packages/svelte/playground/.env.example b/packages/svelte/playground/.env.example new file mode 100644 index 0000000..24fe108 --- /dev/null +++ b/packages/svelte/playground/.env.example @@ -0,0 +1 @@ +VITE_HAWK_TOKEN=your_integration_token_here diff --git a/packages/svelte/playground/.gitignore b/packages/svelte/playground/.gitignore new file mode 100644 index 0000000..c9588f4 --- /dev/null +++ b/packages/svelte/playground/.gitignore @@ -0,0 +1,23 @@ +# Dependencies +node_modules + +# Build output +.output +.vercel +.netlify +.wrangler +.svelte-kit +build +dist + +# OS +.DS_Store +Thumbs.db + +# IDE +.idea/ + +# Environment +.env +.env.example +!.env.example diff --git a/packages/svelte/playground/README.md b/packages/svelte/playground/README.md new file mode 100644 index 0000000..632e344 --- /dev/null +++ b/packages/svelte/playground/README.md @@ -0,0 +1,153 @@ +# Hawk Error Tracker - SvelteKit Playground + +Test playground for Hawk Error Tracker integration with SvelteKit and Svelte 5. + +## Table of Contents + +- [Getting Started](#getting-started) +- [What Hawk Catches](#what-hawk-catches) +- [Error Test Scenarios](#error-test-scenarios) +- [Testing Guide](#testing-guide) + +## Getting Started + +### Prerequisites + +- Node.js 18+ +- Yarn 1.x + +### Setup + +1. Install dependencies: + +```shell +yarn install +``` + +2. Configure Hawk token: + +```shell +cp .env.example .env +``` + +Then add your token from [hawk.so](https://garage.hawk.so) to `.env`: + +```env +VITE_HAWK_TOKEN=your_integration_token_here +``` + +3. Start development server: + +```shell +yarn dev +``` + +## What Hawk Catches + +### โœ… Automatically Caught + +Hawk automatically catches these errors via `window.onerror` and `window.onunhandledrejection`: + +- Event handler errors (`onclick`, `onsubmit`, etc.) +- Lifecycle errors (`onMount`, `onDestroy`) +- Reactive errors (`$effect`, `$derived`) +- Async errors (`setTimeout`, `setInterval`) +- Unhandled promise rejections +- Component rendering errors + +### โŒ Not Caught + +- Form validation errors (intentional, use `fail()`) +- Errors caught by `` (requires manual `hawk.send()`) +- SvelteKit `handleError` hook errors (requires manual `hawk.send()`) + +## Error Test Scenarios + +Visit `/errors` to test 14 error scenarios: + +### Load Functions + +- **Load Expected** - `error()` helper in `+page.ts` +- **Load Unexpected** - Direct throw in `+page.ts` +- **Server Load** - Error in `+page.server.ts` + +### Component Lifecycle + +- **onMount Error** - Error in `onMount()` hook +- **$effect Error** - Error in Svelte 5 `$effect` rune + +### Event Handlers + +- **Click Handler** - Error in `onclick` +- **Submit Handler** - Error in form `onsubmit` + +### Async Errors + +- **setTimeout Error** - Error inside `setTimeout` +- **Promise Rejection** - Unhandled promise rejection + +### Form Actions + +- **Form Validation** - `fail()` helper (not tracked) +- **Form Unexpected** - Unexpected form action error + +### Error Boundaries + +- **Boundary Render** - Component rendering error +- **Boundary Effect** - `$effect` error inside boundary + +### Stores + +- **Store Subscription** - Error in store callback + +## Testing Guide + +### Manual Testing + +```bash +yarn dev +``` + +1. Open `http://localhost:5173/errors` +2. Open DevTools Console (F12) +3. Click each test card +4. Trigger the error +5. Check Hawk dashboard for tracked errors + +### Console Markers + +| Marker | Handler | Description | +|--------|---------------------|------------------------------| +| ๐Ÿ”ด | `handleError` hook | Load/form action errors | +| ๐ŸŸก | Global handlers | Event/async/lifecycle errors | +| ๐ŸŸข | `` | Component rendering errors | + +### Expected Behavior + +| Error Type | Caught by Hawk | Notes | +|------------------|----------------|----------------------------| +| Event handlers | โœ… | Auto via `window.onerror` | +| Lifecycle hooks | โœ… | Auto via `window.onerror` | +| Async errors | โœ… | Auto via global handlers | +| Load functions | โŒ | Needs manual `hawk.send()` | +| Form actions | โŒ | Needs manual `hawk.send()` | +| Error boundaries | โŒ | Needs manual `hawk.send()` | + +## Integration + +Current integration in `hooks.client.ts`: + +```typescript +import HawkCatcher from '@hawk.so/javascript'; + +if (import.meta.env.VITE_HAWK_TOKEN) { + new HawkCatcher(import.meta.env.VITE_HAWK_TOKEN); +} +``` + +Hawk automatically registers global error handlers for: + +- `window.onerror` +- `window.onunhandledrejection` + +**Note:** HawkCatcher is browser-only and cannot run on the server (uses `localStorage`, `window`, etc.). Server-side errors are not tracked automatically. diff --git a/packages/svelte/playground/package.json b/packages/svelte/playground/package.json new file mode 100644 index 0000000..30625d7 --- /dev/null +++ b/packages/svelte/playground/package.json @@ -0,0 +1,23 @@ +{ + "name": "hawk-svelte-playground", + "private": true, + "version": "1.0.0", + "description": "SvelteKit playground for testing Hawk.so error handling integration", + "type": "module", + "scripts": { + "dev": "vite dev", + "build": "vite build", + "preview": "vite preview" + }, + "dependencies": { + "@hawk.so/javascript": "file:../../.." + }, + "devDependencies": { + "@sveltejs/adapter-auto": "^7.0.0", + "@sveltejs/kit": "^2.48.5", + "@sveltejs/vite-plugin-svelte": "^6.2.1", + "svelte": "^5.45.10", + "typescript": "^5.9.3", + "vite": "^7.2.2" + } +} diff --git a/packages/svelte/playground/src/app.css b/packages/svelte/playground/src/app.css new file mode 100644 index 0000000..7e1762f --- /dev/null +++ b/packages/svelte/playground/src/app.css @@ -0,0 +1,394 @@ +/* Hawk.so Example Styles */ +@import url('https://fonts.googleapis.com/css?family=Roboto:400,500,700&display=swap'); + +:root { + --bg-primary: #2f3341; + --bg-secondary: #242732; + --bg-input: rgba(36, 39, 50, 0.68); + --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; + --border-input: rgba(0, 0, 0, 0.18); +} + +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-align: left; + text-transform: uppercase; +} + +h2 small { + text-transform: none; + font-size: 14px; + opacity: 0.6; + font-weight: normal; + margin-left: 15px; +} + +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; +} + +label { + display: block; + margin-bottom: 10px; + font-size: 15px; +} + +input, +select, +textarea { + background: var(--bg-input); + border: 1px solid var(--border-input); + border-radius: 3px; + padding: 10px 15px; + font-size: 15px; + color: inherit; + font-family: inherit; +} + +input:focus, +select:focus, +textarea:focus { + outline: none; + border-color: var(--button-primary); +} + +code { + background: var(--bg-secondary); + padding: 2px 6px; + border-radius: 3px; + font-family: 'Monaco', 'Menlo', 'Ubuntu Mono', monospace; + font-size: 0.9em; +} + +pre { + background: var(--bg-secondary); + padding: 15px; + border-radius: 4px; + overflow-x: auto; +} + +pre code { + background: none; + padding: 0; +} + +/* Navigation styles */ +nav { + padding: 15px 30px; + background: var(--bg-secondary); + border-bottom: 1px solid var(--border-color); +} + +nav a { + margin-right: 20px; + text-decoration: none; + color: var(--text-primary); + font-weight: 500; +} + +nav a:hover { + color: var(--button-primary); +} + +/* Card/Grid styles for error tests */ +.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; + color: var(--text-primary); + font-size: 16px; + font-weight: 500; +} + +.test-card p { + margin: 0; + color: var(--text-secondary); + font-size: 13px; + line-height: 1.5; +} + +/* Alert/Notice boxes */ +.alert { + padding: 15px; + border-left: 4px solid; + border-radius: 4px; + margin: 15px 0; +} + +.alert-info { + background: rgba(73, 121, 228, 0.15); + border-color: var(--button-primary); + color: var(--text-primary); +} + +.alert-warning { + background: rgba(255, 193, 7, 0.15); + border-color: #ffc107; + color: #ffd54f; +} + +.alert-error { + background: rgba(244, 67, 54, 0.15); + border-color: #f44336; + color: #ff8a80; +} + +.alert-success { + background: rgba(76, 175, 80, 0.15); + border-color: #4caf50; + color: #81c784; +} + +/* Container */ +.container { + max-width: 1200px; + margin: 0 auto; + padding: 20px; +} + +/* Grid system */ +.grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(300px, 1fr)); + gap: 15px; +} + +/* Utility classes */ +.text-center { + text-align: center; +} + +.mt-1 { + margin-top: 10px; +} + +.mt-2 { + margin-top: 20px; +} + +.mb-1 { + margin-bottom: 10px; +} + +.mb-2 { + margin-bottom: 20px; +} + +.p-1 { + padding: 10px; +} + +.p-2 { + padding: 20px; +} + +/* Error test page styles */ +.error-page { + padding: 2rem; +} + +.error-description { + margin: 1rem 0; +} + +.error-trigger { + margin: 2rem 0; +} + +.error-note { + margin: 2rem 0; + padding: 1rem; + background: rgba(73, 121, 228, 0.15); + border-left: 4px solid var(--button-primary); + border-radius: 4px; +} + +.error-boundary-container { + margin: 2rem 0; + padding: 1rem; + border: 2px solid var(--button-primary); + border-radius: 4px; +} + +.error-boundary-message { + padding: 1.5rem; + background: rgba(244, 67, 54, 0.15); + border-left: 4px solid #f44336; + border-radius: 4px; +} + +.error-boundary-message h3 { + margin: 0 0 0.5rem 0; + color: #ff8a80; +} + +.error-boundary-message p { + margin: 0.5rem 0; + color: var(--text-primary); +} + +.error-success-message { + padding: 1rem; + background: rgba(76, 175, 80, 0.15); + border-left: 4px solid #4caf50; + border-radius: 4px; + margin-top: 1rem; +} + +.error-success-message p { + margin: 0.5rem 0; + color: var(--text-primary); +} + +.error-success-message strong { + color: #81c784; +} + +.form-group { + margin-bottom: 1rem; +} + +.form-error { + padding: 1rem; + background: rgba(244, 67, 54, 0.15); + color: var(--text-primary); + border-left: 4px solid #f44336; + border-radius: 4px; + margin-bottom: 1rem; +} + +.form-error strong { + color: #ff8a80; +} + +.form-success { + padding: 1rem; + background: rgba(76, 175, 80, 0.15); + color: var(--text-primary); + border-left: 4px solid #4caf50; + border-radius: 4px; + margin-bottom: 1rem; +} + +.form-success strong { + color: #81c784; +} + +.form-input { + padding: 0.5rem; + font-size: 1rem; + width: 300px; + margin-right: 0.5rem; +} + +.form-input-error { + border-color: #f44336; +} + +.button-primary { + padding: 1rem 2rem; + font-size: 1.2rem; + background: #f44336; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.button-submit { + padding: 0.5rem 1rem; + font-size: 1rem; + background: #2196f3; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} + +.button-reset { + margin-top: 1rem; + padding: 0.5rem 1rem; + background: #2196f3; + color: white; + border: none; + border-radius: 4px; + cursor: pointer; +} diff --git a/packages/svelte/playground/src/app.d.ts b/packages/svelte/playground/src/app.d.ts new file mode 100644 index 0000000..520c421 --- /dev/null +++ b/packages/svelte/playground/src/app.d.ts @@ -0,0 +1,13 @@ +// See https://svelte.dev/docs/kit/types#app.d.ts +// for information about these interfaces +declare global { + namespace App { + // interface Error {} + // interface Locals {} + // interface PageData {} + // interface PageState {} + // interface Platform {} + } +} + +export {}; diff --git a/packages/svelte/playground/src/app.html b/packages/svelte/playground/src/app.html new file mode 100644 index 0000000..d57bbe3 --- /dev/null +++ b/packages/svelte/playground/src/app.html @@ -0,0 +1,11 @@ + + + + + + %sveltekit.head% + + +
%sveltekit.body%
+ + diff --git a/packages/svelte/playground/src/hooks.client.ts b/packages/svelte/playground/src/hooks.client.ts new file mode 100644 index 0000000..0145735 --- /dev/null +++ b/packages/svelte/playground/src/hooks.client.ts @@ -0,0 +1,22 @@ +import type {HandleClientError} from '@sveltejs/kit'; +import HawkCatcher from '@hawk.so/javascript'; + +if (import.meta.env.VITE_HAWK_TOKEN) { + new HawkCatcher(import.meta.env.VITE_HAWK_TOKEN); +} + +export const handleError: HandleClientError = async ({error, event, status, message}) => { + console.error('๐Ÿ”ด [Client handleError] Caught error:', { + error, + status, + message, + route: event.route.id, + url: event.url.pathname + }); + + return { + message: message || 'An unexpected client error occurred', + code: (error as any)?.code ?? 'UNKNOWN_ERROR', + route: event.route.id + }; +}; diff --git a/packages/svelte/playground/src/hooks.server.ts b/packages/svelte/playground/src/hooks.server.ts new file mode 100644 index 0000000..adc61a9 --- /dev/null +++ b/packages/svelte/playground/src/hooks.server.ts @@ -0,0 +1,17 @@ +import type {HandleServerError} from '@sveltejs/kit'; + +export const handleError: HandleServerError = async ({error, event, status, message}) => { + console.error('๐Ÿ”ด [Server handleError] Caught error:', { + error, + status, + message, + route: event.route.id, + url: event.url.pathname + }); + + return { + message: message || 'An unexpected server error occurred', + code: (error as any)?.code ?? 'UNKNOWN_ERROR', + route: event.route.id + }; +}; diff --git a/packages/svelte/playground/src/lib/assets/favicon.svg b/packages/svelte/playground/src/lib/assets/favicon.svg new file mode 100644 index 0000000..a8410f8 --- /dev/null +++ b/packages/svelte/playground/src/lib/assets/favicon.svg @@ -0,0 +1 @@ + svelte-logo diff --git a/packages/svelte/playground/src/lib/stores/errorStore.ts b/packages/svelte/playground/src/lib/stores/errorStore.ts new file mode 100644 index 0000000..e1a8618 --- /dev/null +++ b/packages/svelte/playground/src/lib/stores/errorStore.ts @@ -0,0 +1,10 @@ +import {writable} from 'svelte/store'; + +export const errorStore = writable(0); + +// Store subscription that throws an error +errorStore.subscribe((value) => { + if (value > 0) { + throw new Error('Error in store subscription callback'); + } +}); diff --git a/packages/svelte/playground/src/routes/+layout.svelte b/packages/svelte/playground/src/routes/+layout.svelte new file mode 100644 index 0000000..50ac706 --- /dev/null +++ b/packages/svelte/playground/src/routes/+layout.svelte @@ -0,0 +1,42 @@ + + + + + + + + +{@render children()} diff --git a/packages/svelte/playground/src/routes/+page.svelte b/packages/svelte/playground/src/routes/+page.svelte new file mode 100644 index 0000000..7ccf0e9 --- /dev/null +++ b/packages/svelte/playground/src/routes/+page.svelte @@ -0,0 +1,58 @@ + + Hawk Javascript SvelteKit Integration Playground + + +
+
+

๐Ÿฆ… Hawk Javascript SvelteKit Integration Playground

+ + https://github.com/codex-team/hawk.javascript + +
+ +
+

Welcome

+

+ This playground demonstrates various error handling scenarios in SvelteKit + to help design and test the Hawk.so integration. +

+
+ +
+

๐Ÿงช Error Test Suite

+

+ We've created a comprehensive test suite to demonstrate all error handling + mechanisms in SvelteKit. +

+ + + +
+ +
+

๐Ÿ“š What You'll Find

+
    +
  • Load Function Errors - Expected and unexpected errors in load functions
  • +
  • Component Lifecycle Errors - Errors in onMount, effects, etc.
  • +
  • Event Handler Errors - Errors in click, submit handlers
  • +
  • Async Errors - setTimeout and promise rejection errors
  • +
  • Form Action Errors - Validation and unexpected form errors
  • +
  • Error Boundaries - Testing <svelte:boundary>
  • +
  • Store Errors - Store subscription error scenarios
  • +
+
+ +
+

๐Ÿ” Testing Setup

+

The playground includes:

+
    +
  • โœ… Server-side handleError hook (hooks.server.ts)
  • +
  • โœ… Client-side handleError hook (hooks.client.ts)
  • +
  • โœ… Global error handlers (window.onerror, unhandledrejection)
  • +
  • โœ… Error boundaries where applicable
  • +
+
+ Tip: Open your browser's DevTools Console before testing. +
+
+
diff --git a/packages/svelte/playground/src/routes/errors/+page.svelte b/packages/svelte/playground/src/routes/errors/+page.svelte new file mode 100644 index 0000000..96e91b7 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/+page.svelte @@ -0,0 +1,150 @@ + + + + Error Test Scenarios - Hawk.so SvelteKit Integration + + +
+
+

๐Ÿงช SvelteKit Error Handling Test Suite

+ โ† Back to Home +
+ +
+ โš ๏ธ Testing Instructions: +
    +
  • Open your browser's DevTools Console to see error logs
  • +
  • Look for colored emoji markers: +
      +
    • ๐Ÿ”ด = Caught by handleError hook
    • +
    • ๐ŸŸก = Caught by global window.onerror or unhandledrejection
    • +
    • ๐ŸŸข = Caught by <svelte:boundary>
    • +
    +
  • +
  • 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/svelte/playground/src/routes/errors/async-promise/+page.svelte b/packages/svelte/playground/src/routes/errors/async-promise/+page.svelte new file mode 100644 index 0000000..de5caa5 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/async-promise/+page.svelte @@ -0,0 +1,40 @@ + + + + Promise Rejection Test + + +
+

Unhandled Promise Rejection Test

+ +

+ This page demonstrates an unhandled promise rejection. +

+

+ Expected: Error should be caught by window.onunhandledrejection (๐ŸŸก) +

+

+ Gap: NOT caught by handleError or <svelte:boundary> +

+ +
+

Note: The rejection was triggered automatically on mount.

+ +
+ +

Check the console to see where the rejection was caught.

+
diff --git a/packages/svelte/playground/src/routes/errors/async-timeout/+page.svelte b/packages/svelte/playground/src/routes/errors/async-timeout/+page.svelte new file mode 100644 index 0000000..af234ef --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/async-timeout/+page.svelte @@ -0,0 +1,42 @@ + + + + setTimeout Error Test + + +
+

setTimeout Error Test

+ +

+ This page demonstrates an error thrown inside setTimeout. +

+

+ Expected: Error should be caught by window.onerror (๐ŸŸก) +

+

+ Gap: NOT caught by handleError or <svelte:boundary> +

+ +
+

Note: The error was triggered automatically on mount.

+ +
+ +

Check the console to see where the error was caught.

+
diff --git a/packages/svelte/playground/src/routes/errors/boundary-effect/+page.svelte b/packages/svelte/playground/src/routes/errors/boundary-effect/+page.svelte new file mode 100644 index 0000000..02c1496 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/boundary-effect/+page.svelte @@ -0,0 +1,63 @@ + + + + Error Boundary - Effect Test + + +
+

Error Boundary - Effect Test

+ +

+ This page demonstrates <svelte:boundary> catching an error in $effect. +

+

+ Expected: Error should be caught by the error boundary (๐ŸŸข) +

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

Error Caught by Boundary!

+

Message: {error.message}

+ +
+ {/snippet} +
+
+ + {#if !errorCaught} + + {/if} + + {#if errorCaught} +
+

โœ… Success! The error was caught by the error boundary.

+

Error: {errorCaught.error.message}

+
+ {/if} + +

Check the console to see the boundary catch the error.

+
diff --git a/packages/svelte/playground/src/routes/errors/boundary-effect/ErrorEffectComponent.svelte b/packages/svelte/playground/src/routes/errors/boundary-effect/ErrorEffectComponent.svelte new file mode 100644 index 0000000..ce56e12 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/boundary-effect/ErrorEffectComponent.svelte @@ -0,0 +1,14 @@ + + +
+

This component has an effect that can throw an error.

+

Trigger status: {triggerError ? 'Active (will throw error)' : 'Inactive'}

+
diff --git a/packages/svelte/playground/src/routes/errors/boundary-render/+page.svelte b/packages/svelte/playground/src/routes/errors/boundary-render/+page.svelte new file mode 100644 index 0000000..2e73036 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/boundary-render/+page.svelte @@ -0,0 +1,49 @@ + + + + Error Boundary - Rendering Test + + +
+

Error Boundary - Rendering Test

+ +

+ This page demonstrates <svelte:boundary> catching a rendering error. +

+

+ Expected: Error should be caught by the error boundary (๐ŸŸข) +

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

Error Caught by Boundary!

+

Message: {error.message}

+ +
+ {/snippet} +
+
+ + {#if errorCaught} +
+

โœ… Success! The error was caught by the error boundary.

+

Error: {errorCaught.error.message}

+
+ {/if} + +

Check the console to see the boundary catch the error.

+
diff --git a/packages/svelte/playground/src/routes/errors/boundary-render/BrokenComponent.svelte b/packages/svelte/playground/src/routes/errors/boundary-render/BrokenComponent.svelte new file mode 100644 index 0000000..07bdb42 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/boundary-render/BrokenComponent.svelte @@ -0,0 +1,8 @@ + + +
+

This content will never render because the error is thrown first.

+
diff --git a/packages/svelte/playground/src/routes/errors/event-click/+page.svelte b/packages/svelte/playground/src/routes/errors/event-click/+page.svelte new file mode 100644 index 0000000..142cd6c --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/event-click/+page.svelte @@ -0,0 +1,30 @@ + + + + Click Handler Error Test + + +
+

Click Handler Error Test

+ +

+ This page demonstrates an error thrown in an event handler. +

+

+ Expected: Error should be caught by window.onerror (๐ŸŸก), NOT by + handleError +

+ +
+ +
+ +

Check the console to see where the error was caught.

+
diff --git a/packages/svelte/playground/src/routes/errors/event-submit/+page.svelte b/packages/svelte/playground/src/routes/errors/event-submit/+page.svelte new file mode 100644 index 0000000..db9cacc --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/event-submit/+page.svelte @@ -0,0 +1,38 @@ + + + + Submit Handler Error Test + + +
+

Submit Handler Error Test

+ +

+ This page demonstrates an error thrown in a form submit handler. +

+

+ Expected: Error should be caught by window.onerror (๐ŸŸก), NOT by + handleError +

+ +
+
+ + +
+
+ +

Check the console to see where the error was caught.

+
diff --git a/packages/svelte/playground/src/routes/errors/form-unexpected/+page.server.ts b/packages/svelte/playground/src/routes/errors/form-unexpected/+page.server.ts new file mode 100644 index 0000000..00dd4ad --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/form-unexpected/+page.server.ts @@ -0,0 +1,9 @@ +import type {Actions} from './$types'; + +export const actions = { + default: async () => { + // Simulate an unexpected error (e.g., database failure) + // This should be caught by server-side handleError + throw new Error('Unexpected error in form action - database connection failed'); + } +} satisfies Actions; diff --git a/packages/svelte/playground/src/routes/errors/form-unexpected/+page.svelte b/packages/svelte/playground/src/routes/errors/form-unexpected/+page.svelte new file mode 100644 index 0000000..4187e2f --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/form-unexpected/+page.svelte @@ -0,0 +1,23 @@ + + Form Unexpected Error Test + + +
+

Form Action Unexpected Error Test

+ +

+ This page demonstrates an unexpected error in a form action. +

+

+ Expected: Error should be caught by server-side handleError (๐Ÿ”ด) +

+ +
+ +
+ +

When you submit this form, the action will throw an unexpected error.

+

Check the console to see it caught by server-side handleError.

+
diff --git a/packages/svelte/playground/src/routes/errors/form-validation/+page.server.ts b/packages/svelte/playground/src/routes/errors/form-validation/+page.server.ts new file mode 100644 index 0000000..84955ef --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/form-validation/+page.server.ts @@ -0,0 +1,22 @@ +import {fail} from '@sveltejs/kit'; +import type {Actions} from './$types'; + +export const actions = { + default: async ({request}) => { + const data = await request.formData(); + const email = data.get('email'); + + // Validation error - expected error using fail() + if (!email || typeof email !== 'string' || !email.includes('@')) { + return fail(400, { + error: 'Please provide a valid email address', + email: email?.toString() ?? '' + }); + } + + return { + success: true, + message: 'Form submitted successfully!' + }; + } +} satisfies Actions; diff --git a/packages/svelte/playground/src/routes/errors/form-validation/+page.svelte b/packages/svelte/playground/src/routes/errors/form-validation/+page.svelte new file mode 100644 index 0000000..cc067ce --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/form-validation/+page.svelte @@ -0,0 +1,59 @@ + + + + Form Validation Error Test + + +
+

Form Validation Error Test

+ +

+ This page demonstrates using fail() for validation errors. +

+

+ Expected: Validation errors are returned to the page, NOT sent to handleError +

+ +
+
+ + +
+ + {#if form?.error} +
+ Validation Error: {form.error} +
+ {/if} + + {#if form?.success} +
+ Success: {form.message} +
+ {/if} + + +
+ +
+

Try:

+
    +
  • Submit with empty email โ†’ validation error
  • +
  • Submit with invalid email โ†’ validation error
  • +
  • Submit with valid email โ†’ success
  • +
+
+
diff --git a/packages/svelte/playground/src/routes/errors/lifecycle-effect/+page.svelte b/packages/svelte/playground/src/routes/errors/lifecycle-effect/+page.svelte new file mode 100644 index 0000000..87a940d --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/lifecycle-effect/+page.svelte @@ -0,0 +1,34 @@ + + + + $effect Error Test + + +
+

$effect Error Test

+ +

+ This component will throw an error in $effect when you click the button. +

+

+ Expected: Error can be caught by <svelte:boundary> or + window.onerror +

+ +
+ +
+ +

Click the button to increment the count and trigger the error.

+
diff --git a/packages/svelte/playground/src/routes/errors/lifecycle-onmount/+page.svelte b/packages/svelte/playground/src/routes/errors/lifecycle-onmount/+page.svelte new file mode 100644 index 0000000..0e63bf2 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/lifecycle-onmount/+page.svelte @@ -0,0 +1,26 @@ + + + + onMount Error Test + + +
+

onMount Error Test

+ +

+ This component throws an error in onMount(). +

+

+ Expected: Error should be caught by window.onerror (๐ŸŸก), NOT by + handleError +

+ +

Check the console to see where it was caught.

+
diff --git a/packages/svelte/playground/src/routes/errors/load-expected/+page.ts b/packages/svelte/playground/src/routes/errors/load-expected/+page.ts new file mode 100644 index 0000000..ba31801 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/load-expected/+page.ts @@ -0,0 +1,10 @@ +import {error} from '@sveltejs/kit'; +import type {PageLoad} from './$types'; + +export const load: PageLoad = async () => { + // This is an expected error - should be caught by handleError + error(404, { + message: 'This is an expected error from load function', + code: 'TEST_EXPECTED_ERROR' + }); +}; diff --git a/packages/svelte/playground/src/routes/errors/load-server/+page.server.ts b/packages/svelte/playground/src/routes/errors/load-server/+page.server.ts new file mode 100644 index 0000000..605e873 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/load-server/+page.server.ts @@ -0,0 +1,6 @@ +import type {PageServerLoad} from './$types'; + +export const load: PageServerLoad = async () => { + // This error should be caught by server-side handleError + throw new Error('Server-side load function error'); +}; diff --git a/packages/svelte/playground/src/routes/errors/load-server/+page.svelte b/packages/svelte/playground/src/routes/errors/load-server/+page.svelte new file mode 100644 index 0000000..5a08af8 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/load-server/+page.svelte @@ -0,0 +1,2 @@ +

Server Load Error Test

+

This page should never render - error occurs in server load

diff --git a/packages/svelte/playground/src/routes/errors/load-unexpected/+page.ts b/packages/svelte/playground/src/routes/errors/load-unexpected/+page.ts new file mode 100644 index 0000000..34f0851 --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/load-unexpected/+page.ts @@ -0,0 +1,6 @@ +import type {PageLoad} from './$types'; + +export const load: PageLoad = async () => { + // This is an unexpected error - should be caught by handleError + throw new Error('Unexpected error thrown in load function'); +}; diff --git a/packages/svelte/playground/src/routes/errors/store-subscription/+page.svelte b/packages/svelte/playground/src/routes/errors/store-subscription/+page.svelte new file mode 100644 index 0000000..85e219d --- /dev/null +++ b/packages/svelte/playground/src/routes/errors/store-subscription/+page.svelte @@ -0,0 +1,44 @@ + + + + Store Subscription Error Test + + +
+

Store Subscription Error Test

+ +

+ This page demonstrates an error thrown in a store subscription callback. +

+

+ Expected: Error behavior depends on Svelte version +

+

+ Gap: In Svelte 5, these errors may not be caught consistently +

+ +
+

Note: Store subscription errors are a known gap in error handling:

+
    +
  • NOT caught by handleError
  • +
  • NOT caught by <svelte:boundary>
  • +
  • May or may not be caught by window.onerror depending on implementation
  • +
+
+ +
+ +
+ +

Click the button to update the store and trigger the error in the subscription.

+

Check the console to see if/where the error was caught.

+
diff --git a/packages/svelte/playground/svelte.config.js b/packages/svelte/playground/svelte.config.js new file mode 100644 index 0000000..fcf06bd --- /dev/null +++ b/packages/svelte/playground/svelte.config.js @@ -0,0 +1,12 @@ +import adapter from '@sveltejs/adapter-auto'; +import { vitePreprocess } from '@sveltejs/vite-plugin-svelte'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + preprocess: vitePreprocess(), + kit: { + adapter: adapter() + } +}; + +export default config; diff --git a/packages/svelte/playground/tsconfig.json b/packages/svelte/playground/tsconfig.json new file mode 100644 index 0000000..bbeba3a --- /dev/null +++ b/packages/svelte/playground/tsconfig.json @@ -0,0 +1,15 @@ +{ + "extends": "./.svelte-kit/tsconfig.json", + "compilerOptions": { + "rewriteRelativeImportExtensions": true, + "allowJs": true, + "checkJs": true, + "esModuleInterop": true, + "forceConsistentCasingInFileNames": true, + "resolveJsonModule": true, + "skipLibCheck": true, + "sourceMap": true, + "strict": true, + "moduleResolution": "bundler" + } +} diff --git a/packages/svelte/playground/vite.config.ts b/packages/svelte/playground/vite.config.ts new file mode 100644 index 0000000..0ae9d60 --- /dev/null +++ b/packages/svelte/playground/vite.config.ts @@ -0,0 +1,9 @@ +import {sveltekit} from '@sveltejs/kit/vite'; +import {defineConfig} from 'vite'; + +export default defineConfig({ + plugins: [sveltekit()], + server: { + host: true, + }, +}); diff --git a/packages/svelte/playground/yarn.lock b/packages/svelte/playground/yarn.lock new file mode 100644 index 0000000..121c5da --- /dev/null +++ b/packages/svelte/playground/yarn.lock @@ -0,0 +1,391 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@esbuild/linux-x64@0.25.12": + version "0.25.12" + resolved "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.25.12.tgz" + integrity sha512-uqZMTLr/zR/ed4jIGnwSLkaHmPjOjJvnm6TVVitAa08SLS9Z0VM8wIRx7gWbJB5/J54YuIMInDquWyYvQLZkgw== + +"@hawk.so/javascript@file:../../..": + resolved "file:../../.." + +"@jridgewell/gen-mapping@^0.3.5": + version "0.3.13" + resolved "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz" + integrity sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.0" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/remapping@^2.3.4": + version "2.3.5" + resolved "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz" + integrity sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ== + dependencies: + "@jridgewell/gen-mapping" "^0.3.5" + "@jridgewell/trace-mapping" "^0.3.24" + +"@jridgewell/resolve-uri@^3.1.0": + version "3.1.2" + resolved "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz" + integrity sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw== + +"@jridgewell/sourcemap-codec@^1.4.14", "@jridgewell/sourcemap-codec@^1.4.15", "@jridgewell/sourcemap-codec@^1.5.0", "@jridgewell/sourcemap-codec@^1.5.5": + version "1.5.5" + resolved "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz" + integrity sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og== + +"@jridgewell/trace-mapping@^0.3.24": + version "0.3.31" + resolved "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz" + integrity sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw== + dependencies: + "@jridgewell/resolve-uri" "^3.1.0" + "@jridgewell/sourcemap-codec" "^1.4.14" + +"@polka/url@^1.0.0-next.24": + version "1.0.0-next.29" + resolved "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz" + integrity sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww== + +"@rollup/rollup-linux-x64-gnu@4.53.3": + version "4.53.3" + resolved "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.53.3.tgz" + integrity sha512-3EhFi1FU6YL8HTUJZ51imGJWEX//ajQPfqWLI3BQq4TlvHy4X0MOr5q3D2Zof/ka0d5FNdPwZXm3Yyib/UEd+w== + +"@standard-schema/spec@^1.0.0": + version "1.0.0" + resolved "https://registry.npmjs.org/@standard-schema/spec/-/spec-1.0.0.tgz" + integrity sha512-m2bOd0f2RT9k8QJx1JN85cZYyH1RqFBdlwtkSlf4tBDYLCiiZnv1fIIwacK6cqwXavOydf0NPToMQgpKq+dVlA== + +"@sveltejs/acorn-typescript@^1.0.5": + version "1.0.8" + resolved "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.8.tgz" + integrity sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA== + +"@sveltejs/adapter-auto@^7.0.0": + version "7.0.0" + resolved "https://registry.npmjs.org/@sveltejs/adapter-auto/-/adapter-auto-7.0.0.tgz" + integrity sha512-ImDWaErTOCkRS4Gt+5gZuymKFBobnhChXUZ9lhUZLahUgvA4OOvRzi3sahzYgbxGj5nkA6OV0GAW378+dl/gyw== + +"@sveltejs/kit@^2.0.0", "@sveltejs/kit@^2.48.5": + version "2.49.2" + resolved "https://registry.npmjs.org/@sveltejs/kit/-/kit-2.49.2.tgz" + integrity sha512-Vp3zX/qlwerQmHMP6x0Ry1oY7eKKRcOWGc2P59srOp4zcqyn+etJyQpELgOi4+ZSUgteX8Y387NuwruLgGXLUQ== + dependencies: + "@standard-schema/spec" "^1.0.0" + "@sveltejs/acorn-typescript" "^1.0.5" + "@types/cookie" "^0.6.0" + acorn "^8.14.1" + cookie "^0.6.0" + devalue "^5.3.2" + esm-env "^1.2.2" + kleur "^4.1.5" + magic-string "^0.30.5" + mrmime "^2.0.0" + sade "^1.8.1" + set-cookie-parser "^2.6.0" + sirv "^3.0.0" + +"@sveltejs/vite-plugin-svelte-inspector@^5.0.0": + version "5.0.1" + resolved "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte-inspector/-/vite-plugin-svelte-inspector-5.0.1.tgz" + integrity sha512-ubWshlMk4bc8mkwWbg6vNvCeT7lGQojE3ijDh3QTR6Zr/R+GXxsGbyH4PExEPpiFmqPhYiVSVmHBjUcVc1JIrA== + dependencies: + debug "^4.4.1" + +"@sveltejs/vite-plugin-svelte@^3.0.0 || ^4.0.0-next.1 || ^5.0.0 || ^6.0.0-next.0", "@sveltejs/vite-plugin-svelte@^6.0.0-next.0", "@sveltejs/vite-plugin-svelte@^6.2.1": + version "6.2.1" + resolved "https://registry.npmjs.org/@sveltejs/vite-plugin-svelte/-/vite-plugin-svelte-6.2.1.tgz" + integrity sha512-YZs/OSKOQAQCnJvM/P+F1URotNnYNeU3P2s4oIpzm1uFaqUEqRxUB0g5ejMjEb5Gjb9/PiBI5Ktrq4rUUF8UVQ== + dependencies: + "@sveltejs/vite-plugin-svelte-inspector" "^5.0.0" + debug "^4.4.1" + deepmerge "^4.3.1" + magic-string "^0.30.17" + vitefu "^1.1.1" + +"@types/cookie@^0.6.0": + version "0.6.0" + resolved "https://registry.npmjs.org/@types/cookie/-/cookie-0.6.0.tgz" + integrity sha512-4Kh9a6B2bQciAhf7FSuMRRkUWecJgJu9nPnx3yzpsfXX/c50REIqpHY4C82bXP90qrLtXtkDxTZosYO3UpOwlA== + +"@types/estree@^1.0.5", "@types/estree@^1.0.6", "@types/estree@1.0.8": + version "1.0.8" + resolved "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz" + integrity sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w== + +acorn@^8.12.1, acorn@^8.14.1, acorn@^8.9.0: + version "8.15.0" + resolved "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz" + integrity sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg== + +aria-query@^5.3.1: + version "5.3.2" + resolved "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz" + integrity sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw== + +axobject-query@^4.1.0: + version "4.1.0" + resolved "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz" + integrity sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ== + +clsx@^2.1.1: + version "2.1.1" + resolved "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz" + integrity sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA== + +cookie@^0.6.0: + version "0.6.0" + resolved "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz" + integrity sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw== + +debug@^4.4.1: + version "4.4.3" + resolved "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz" + integrity sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA== + dependencies: + ms "^2.1.3" + +deepmerge@^4.3.1: + version "4.3.1" + resolved "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz" + integrity sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A== + +devalue@^5.3.2, devalue@^5.5.0: + version "5.6.1" + resolved "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz" + integrity sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A== + +esbuild@^0.25.0: + version "0.25.12" + resolved "https://registry.npmjs.org/esbuild/-/esbuild-0.25.12.tgz" + integrity sha512-bbPBYYrtZbkt6Os6FiTLCTFxvq4tt3JKall1vRwshA3fdVztsLAatFaZobhkBC8/BrPetoa0oksYoKXoG4ryJg== + optionalDependencies: + "@esbuild/aix-ppc64" "0.25.12" + "@esbuild/android-arm" "0.25.12" + "@esbuild/android-arm64" "0.25.12" + "@esbuild/android-x64" "0.25.12" + "@esbuild/darwin-arm64" "0.25.12" + "@esbuild/darwin-x64" "0.25.12" + "@esbuild/freebsd-arm64" "0.25.12" + "@esbuild/freebsd-x64" "0.25.12" + "@esbuild/linux-arm" "0.25.12" + "@esbuild/linux-arm64" "0.25.12" + "@esbuild/linux-ia32" "0.25.12" + "@esbuild/linux-loong64" "0.25.12" + "@esbuild/linux-mips64el" "0.25.12" + "@esbuild/linux-ppc64" "0.25.12" + "@esbuild/linux-riscv64" "0.25.12" + "@esbuild/linux-s390x" "0.25.12" + "@esbuild/linux-x64" "0.25.12" + "@esbuild/netbsd-arm64" "0.25.12" + "@esbuild/netbsd-x64" "0.25.12" + "@esbuild/openbsd-arm64" "0.25.12" + "@esbuild/openbsd-x64" "0.25.12" + "@esbuild/openharmony-arm64" "0.25.12" + "@esbuild/sunos-x64" "0.25.12" + "@esbuild/win32-arm64" "0.25.12" + "@esbuild/win32-ia32" "0.25.12" + "@esbuild/win32-x64" "0.25.12" + +esm-env@^1.2.1, esm-env@^1.2.2: + version "1.2.2" + resolved "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz" + integrity sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA== + +esrap@^2.2.1: + version "2.2.1" + resolved "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz" + integrity sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +fdir@^6.5.0: + version "6.5.0" + resolved "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz" + integrity sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg== + +is-reference@^3.0.3: + version "3.0.3" + resolved "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz" + integrity sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw== + dependencies: + "@types/estree" "^1.0.6" + +kleur@^4.1.5: + version "4.1.5" + resolved "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz" + integrity sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ== + +locate-character@^3.0.0: + version "3.0.0" + resolved "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz" + integrity sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA== + +magic-string@^0.30.11, magic-string@^0.30.17, magic-string@^0.30.5: + version "0.30.21" + resolved "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz" + integrity sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ== + dependencies: + "@jridgewell/sourcemap-codec" "^1.5.5" + +mri@^1.1.0: + version "1.2.0" + resolved "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz" + integrity sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA== + +mrmime@^2.0.0: + version "2.0.1" + resolved "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz" + integrity sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ== + +ms@^2.1.3: + version "2.1.3" + resolved "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@^3.3.11: + version "3.3.11" + resolved "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz" + integrity sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w== + +picocolors@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz" + integrity sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA== + +"picomatch@^3 || ^4", picomatch@^4.0.3: + version "4.0.3" + resolved "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz" + integrity sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q== + +postcss@^8.5.6: + version "8.5.6" + resolved "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz" + integrity sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg== + dependencies: + nanoid "^3.3.11" + picocolors "^1.1.1" + source-map-js "^1.2.1" + +rollup@^4.43.0: + version "4.53.3" + resolved "https://registry.npmjs.org/rollup/-/rollup-4.53.3.tgz" + integrity sha512-w8GmOxZfBmKknvdXU1sdM9NHcoQejwF/4mNgj2JuEEdRaHwwF12K7e9eXn1nLZ07ad+du76mkVsyeb2rKGllsA== + dependencies: + "@types/estree" "1.0.8" + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.53.3" + "@rollup/rollup-android-arm64" "4.53.3" + "@rollup/rollup-darwin-arm64" "4.53.3" + "@rollup/rollup-darwin-x64" "4.53.3" + "@rollup/rollup-freebsd-arm64" "4.53.3" + "@rollup/rollup-freebsd-x64" "4.53.3" + "@rollup/rollup-linux-arm-gnueabihf" "4.53.3" + "@rollup/rollup-linux-arm-musleabihf" "4.53.3" + "@rollup/rollup-linux-arm64-gnu" "4.53.3" + "@rollup/rollup-linux-arm64-musl" "4.53.3" + "@rollup/rollup-linux-loong64-gnu" "4.53.3" + "@rollup/rollup-linux-ppc64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-gnu" "4.53.3" + "@rollup/rollup-linux-riscv64-musl" "4.53.3" + "@rollup/rollup-linux-s390x-gnu" "4.53.3" + "@rollup/rollup-linux-x64-gnu" "4.53.3" + "@rollup/rollup-linux-x64-musl" "4.53.3" + "@rollup/rollup-openharmony-arm64" "4.53.3" + "@rollup/rollup-win32-arm64-msvc" "4.53.3" + "@rollup/rollup-win32-ia32-msvc" "4.53.3" + "@rollup/rollup-win32-x64-gnu" "4.53.3" + "@rollup/rollup-win32-x64-msvc" "4.53.3" + fsevents "~2.3.2" + +sade@^1.8.1: + version "1.8.1" + resolved "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz" + integrity sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A== + dependencies: + mri "^1.1.0" + +set-cookie-parser@^2.6.0: + version "2.7.2" + resolved "https://registry.npmjs.org/set-cookie-parser/-/set-cookie-parser-2.7.2.tgz" + integrity sha512-oeM1lpU/UvhTxw+g3cIfxXHyJRc/uidd3yK1P242gzHds0udQBYzs3y8j4gCCW+ZJ7ad0yctld8RYO+bdurlvw== + +sirv@^3.0.0: + version "3.0.2" + resolved "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz" + integrity sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g== + dependencies: + "@polka/url" "^1.0.0-next.24" + mrmime "^2.0.0" + totalist "^3.0.0" + +source-map-js@^1.2.1: + version "1.2.1" + resolved "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz" + integrity sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA== + +"svelte@^4.0.0 || ^5.0.0-next.0", svelte@^5.0.0, svelte@^5.45.10: + version "5.45.10" + resolved "https://registry.npmjs.org/svelte/-/svelte-5.45.10.tgz" + integrity sha512-GiWXq6akkEN3zVDMQ1BVlRolmks5JkEdzD/67mvXOz6drRfuddT5JwsGZjMGSnsTRv/PjAXX8fqBcOr2g2qc/Q== + dependencies: + "@jridgewell/remapping" "^2.3.4" + "@jridgewell/sourcemap-codec" "^1.5.0" + "@sveltejs/acorn-typescript" "^1.0.5" + "@types/estree" "^1.0.5" + acorn "^8.12.1" + aria-query "^5.3.1" + axobject-query "^4.1.0" + clsx "^2.1.1" + devalue "^5.5.0" + esm-env "^1.2.1" + esrap "^2.2.1" + is-reference "^3.0.3" + locate-character "^3.0.0" + magic-string "^0.30.11" + zimmerframe "^1.1.2" + +tinyglobby@^0.2.15: + version "0.2.15" + resolved "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.15.tgz" + integrity sha512-j2Zq4NyQYG5XMST4cbs02Ak8iJUdxRM0XI5QyxXuZOzKOINmWurp3smXu3y5wDcJrptwpSjgXHzIQxR0omXljQ== + dependencies: + fdir "^6.5.0" + picomatch "^4.0.3" + +totalist@^3.0.0: + version "3.0.1" + resolved "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz" + integrity sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ== + +typescript@^5.9.3: + version "5.9.3" + resolved "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz" + integrity sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw== + +"vite@^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0-beta.0", "vite@^5.0.3 || ^6.0.0 || ^7.0.0-beta.0", "vite@^6.3.0 || ^7.0.0", vite@^7.2.2: + version "7.2.7" + resolved "https://registry.npmjs.org/vite/-/vite-7.2.7.tgz" + integrity sha512-ITcnkFeR3+fI8P1wMgItjGrR10170d8auB4EpMLPqmx6uxElH3a/hHGQabSHKdqd4FXWO1nFIp9rRn7JQ34ACQ== + dependencies: + esbuild "^0.25.0" + fdir "^6.5.0" + picomatch "^4.0.3" + postcss "^8.5.6" + rollup "^4.43.0" + tinyglobby "^0.2.15" + optionalDependencies: + fsevents "~2.3.3" + +vitefu@^1.1.1: + version "1.1.1" + resolved "https://registry.npmjs.org/vitefu/-/vitefu-1.1.1.tgz" + integrity sha512-B/Fegf3i8zh0yFbpzZ21amWzHmuNlLlmJT6n7bu5e+pCHUKQIfXSYokrqOBGEMMe9UG2sostKQF9mml/vYaWJQ== + +zimmerframe@^1.1.2: + version "1.1.4" + resolved "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz" + integrity sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==