@watchupltd/svelte 1.0.0 → 1.0.2

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.
Files changed (2) hide show
  1. package/README.md +509 -0
  2. package/package.json +4 -4
package/README.md ADDED
@@ -0,0 +1,509 @@
1
+ # @watchupltd/svelte
2
+
3
+ Svelte integration for incident tracking with store-based state management.
4
+
5
+ ## Installation
6
+
7
+ ```bash
8
+ npm install @watchupltd/svelte
9
+ ```
10
+
11
+ ## Quick Start
12
+
13
+ ```typescript
14
+ // main.ts
15
+ import { initIncident } from '@watchupltd/svelte';
16
+ import App from './App.svelte';
17
+
18
+ // Initialize incident tracking
19
+ initIncident({
20
+ apiKey: 'your-api-key',
21
+ projectId: 'your-project-id',
22
+ environment: 'production',
23
+ captureConsoleErrors: true
24
+ });
25
+
26
+ const app = new App({
27
+ target: document.body
28
+ });
29
+
30
+ export default app;
31
+ ```
32
+
33
+ ## Usage in Components
34
+
35
+ ### Using Helper Functions
36
+
37
+ ```svelte
38
+ <script>
39
+ import { captureError, captureMessage, addBreadcrumb, setUser } from '@watchupltd/svelte';
40
+
41
+ async function handleClick() {
42
+ addBreadcrumb({
43
+ message: 'User clicked button',
44
+ category: 'user-action'
45
+ });
46
+
47
+ try {
48
+ await fetchData();
49
+ captureMessage('Data loaded successfully', 'info');
50
+ } catch (error) {
51
+ captureError(error, {
52
+ tags: { component: 'DataFetcher' }
53
+ });
54
+ }
55
+ }
56
+ </script>
57
+
58
+ <button on:click={handleClick}>Load Data</button>
59
+ ```
60
+
61
+ ### Using the Store
62
+
63
+ ```svelte
64
+ <script>
65
+ import { incidentStore } from '@watchupltd/svelte';
66
+
67
+ async function handleError() {
68
+ try {
69
+ await riskyOperation();
70
+ } catch (error) {
71
+ $incidentStore?.captureError(error);
72
+ }
73
+ }
74
+ </script>
75
+ ```
76
+
77
+ ### Using the Client Directly
78
+
79
+ ```svelte
80
+ <script>
81
+ import { getIncidentClient } from '@watchupltd/svelte';
82
+
83
+ const client = getIncidentClient();
84
+
85
+ function trackEvent() {
86
+ client?.captureMessage('Custom event', 'info');
87
+ }
88
+ </script>
89
+ ```
90
+
91
+ ## What It Tracks
92
+
93
+ ### Automatic Tracking
94
+
95
+ - **Global JavaScript Errors**: Via `window.onerror`
96
+ - **Unhandled Promise Rejections**: Via `window.onunhandledrejection`
97
+ - **Console Errors**: Optional via `captureConsoleErrors` config
98
+
99
+ ### Manual Tracking
100
+
101
+ - Custom errors via `captureError()`
102
+ - Log messages via `captureMessage()`
103
+ - User context via `setUser()`
104
+ - Breadcrumbs via `addBreadcrumb()`
105
+
106
+ ## API Reference
107
+
108
+ ### `initIncident(config: SvelteIncidentConfig): IncidentClient`
109
+
110
+ Initialize the incident tracking SDK. Call once at app startup.
111
+
112
+ ```typescript
113
+ import { initIncident } from '@watchupltd/svelte';
114
+
115
+ const client = initIncident({
116
+ apiKey: 'your-api-key',
117
+ projectId: 'your-project-id',
118
+ environment: 'production',
119
+ captureConsoleErrors: true
120
+ });
121
+ ```
122
+
123
+ ### Helper Functions
124
+
125
+ **`captureError(error: Error, context?: any): Promise<string | null>`**
126
+ ```typescript
127
+ import { captureError } from '@watchupltd/svelte';
128
+
129
+ try {
130
+ await riskyOperation();
131
+ } catch (error) {
132
+ captureError(error, {
133
+ tags: { operation: 'data-fetch' },
134
+ extra: { userId: '123' }
135
+ });
136
+ }
137
+ ```
138
+
139
+ **`captureMessage(message: string, level?: SeverityLevel, context?: any): Promise<string | null>`**
140
+ ```typescript
141
+ import { captureMessage } from '@watchupltd/svelte';
142
+
143
+ captureMessage('User completed checkout', 'info', {
144
+ tags: { flow: 'checkout' }
145
+ });
146
+ ```
147
+
148
+ **`addBreadcrumb(breadcrumb: any): void`**
149
+ ```typescript
150
+ import { addBreadcrumb } from '@watchupltd/svelte';
151
+
152
+ addBreadcrumb({
153
+ message: 'User clicked submit button',
154
+ category: 'user-action',
155
+ level: 'info'
156
+ });
157
+ ```
158
+
159
+ **`setUser(user: any): void`**
160
+ ```typescript
161
+ import { setUser } from '@watchupltd/svelte';
162
+
163
+ setUser({
164
+ id: 'user-123',
165
+ email: 'user@example.com',
166
+ username: 'john_doe'
167
+ });
168
+ ```
169
+
170
+ ### Store
171
+
172
+ **`incidentStore`**
173
+
174
+ A Svelte store containing the `IncidentClient` instance.
175
+
176
+ ```svelte
177
+ <script>
178
+ import { incidentStore } from '@watchupltd/svelte';
179
+
180
+ $: if ($incidentStore) {
181
+ $incidentStore.setTag('version', '1.0.0');
182
+ }
183
+ </script>
184
+ ```
185
+
186
+ ### Client Access
187
+
188
+ **`getIncidentClient(): IncidentClient | null`**
189
+
190
+ Get the current client instance.
191
+
192
+ ```typescript
193
+ import { getIncidentClient } from '@watchupltd/svelte';
194
+
195
+ const client = getIncidentClient();
196
+ if (client) {
197
+ client.captureMessage('App initialized', 'info');
198
+ }
199
+ ```
200
+
201
+ ## Configuration
202
+
203
+ ```typescript
204
+ interface SvelteIncidentConfig {
205
+ apiKey: string; // Required: Your API key
206
+ projectId: string; // Required: Your project ID
207
+ endpoint?: string; // Optional: Custom API endpoint
208
+ environment?: string; // Optional: Environment (default: 'production')
209
+ batchInterval?: number; // Optional: Batch interval in ms (default: 5000)
210
+ maxBatchSize?: number; // Optional: Max events per batch (default: 10)
211
+ maxRetries?: number; // Optional: Max retry attempts (default: 3)
212
+ enabled?: boolean; // Optional: Enable/disable SDK (default: true)
213
+ captureConsoleErrors?: boolean; // Optional: Capture console.error (default: false)
214
+ }
215
+ ```
216
+
217
+ ## Examples
218
+
219
+ ### Track User Login
220
+
221
+ ```svelte
222
+ <script>
223
+ import { captureError, captureMessage, setUser, addBreadcrumb } from '@watchupltd/svelte';
224
+
225
+ let email = '';
226
+ let password = '';
227
+
228
+ async function handleLogin() {
229
+ addBreadcrumb({
230
+ message: 'User attempting login',
231
+ category: 'auth'
232
+ });
233
+
234
+ try {
235
+ const user = await login(email, password);
236
+
237
+ setUser({
238
+ id: user.id,
239
+ email: user.email,
240
+ username: user.username
241
+ });
242
+
243
+ captureMessage('User logged in successfully', 'info');
244
+ } catch (error) {
245
+ captureError(error, {
246
+ tags: { flow: 'authentication' }
247
+ });
248
+ }
249
+ }
250
+ </script>
251
+
252
+ <form on:submit|preventDefault={handleLogin}>
253
+ <input type="email" bind:value={email} />
254
+ <input type="password" bind:value={password} />
255
+ <button type="submit">Login</button>
256
+ </form>
257
+ ```
258
+
259
+ ### Track API Calls
260
+
261
+ ```svelte
262
+ <script>
263
+ import { onMount } from 'svelte';
264
+ import { captureError, addBreadcrumb } from '@watchupltd/svelte';
265
+
266
+ let data = null;
267
+
268
+ onMount(async () => {
269
+ addBreadcrumb({
270
+ message: 'Fetching user data',
271
+ category: 'api'
272
+ });
273
+
274
+ try {
275
+ data = await fetchUserData();
276
+ } catch (error) {
277
+ captureError(error, {
278
+ tags: { api: 'users', endpoint: '/api/users' }
279
+ });
280
+ }
281
+ });
282
+ </script>
283
+
284
+ {#if data}
285
+ <div>{data.name}</div>
286
+ {/if}
287
+ ```
288
+
289
+ ### Track Form Validation
290
+
291
+ ```svelte
292
+ <script>
293
+ import { captureMessage } from '@watchupltd/svelte';
294
+
295
+ let formData = {
296
+ email: '',
297
+ message: ''
298
+ };
299
+
300
+ function validateForm() {
301
+ const errors = [];
302
+
303
+ if (!formData.email) {
304
+ errors.push('Email is required');
305
+ }
306
+
307
+ if (!formData.message) {
308
+ errors.push('Message is required');
309
+ }
310
+
311
+ if (errors.length > 0) {
312
+ captureMessage(
313
+ `Form validation failed: ${errors.join(', ')}`,
314
+ 'warning',
315
+ {
316
+ tags: { form: 'contact' },
317
+ extra: { errors }
318
+ }
319
+ );
320
+ return false;
321
+ }
322
+
323
+ return true;
324
+ }
325
+
326
+ function handleSubmit() {
327
+ if (validateForm()) {
328
+ // Submit form
329
+ }
330
+ }
331
+ </script>
332
+
333
+ <form on:submit|preventDefault={handleSubmit}>
334
+ <input type="email" bind:value={formData.email} />
335
+ <textarea bind:value={formData.message}></textarea>
336
+ <button type="submit">Submit</button>
337
+ </form>
338
+ ```
339
+
340
+ ### Track Store Changes
341
+
342
+ ```svelte
343
+ <script>
344
+ import { writable } from 'svelte/store';
345
+ import { addBreadcrumb } from '@watchupltd/svelte';
346
+
347
+ const count = writable(0);
348
+
349
+ count.subscribe(value => {
350
+ addBreadcrumb({
351
+ message: `Count changed to ${value}`,
352
+ category: 'state-change',
353
+ data: { count: value }
354
+ });
355
+ });
356
+
357
+ function increment() {
358
+ count.update(n => n + 1);
359
+ }
360
+ </script>
361
+
362
+ <button on:click={increment}>
363
+ Count: {$count}
364
+ </button>
365
+ ```
366
+
367
+ ### Error Boundary Pattern
368
+
369
+ ```svelte
370
+ <script>
371
+ import { captureError } from '@watchupltd/svelte';
372
+
373
+ let error = null;
374
+
375
+ async function loadData() {
376
+ try {
377
+ error = null;
378
+ await fetchData();
379
+ } catch (e) {
380
+ error = e;
381
+ captureError(e, {
382
+ tags: { component: 'DataLoader' }
383
+ });
384
+ }
385
+ }
386
+ </script>
387
+
388
+ {#if error}
389
+ <div class="error">
390
+ <h2>Something went wrong</h2>
391
+ <p>We've been notified and are working on it.</p>
392
+ <button on:click={loadData}>Try Again</button>
393
+ </div>
394
+ {:else}
395
+ <!-- Your content -->
396
+ {/if}
397
+ ```
398
+
399
+ ## TypeScript Support
400
+
401
+ Full TypeScript support with type definitions included.
402
+
403
+ ```typescript
404
+ import type { SvelteIncidentConfig, IncidentClient } from '@watchupltd/svelte';
405
+
406
+ const config: SvelteIncidentConfig = {
407
+ apiKey: 'your-api-key',
408
+ projectId: 'your-project-id'
409
+ };
410
+ ```
411
+
412
+ ## SvelteKit Support
413
+
414
+ Works with SvelteKit. Initialize in your root layout:
415
+
416
+ ```svelte
417
+ <!-- +layout.svelte -->
418
+ <script>
419
+ import { browser } from '$app/environment';
420
+ import { initIncident } from '@watchupltd/svelte';
421
+
422
+ if (browser) {
423
+ initIncident({
424
+ apiKey: import.meta.env.VITE_INCIDENT_API_KEY,
425
+ projectId: import.meta.env.VITE_INCIDENT_PROJECT_ID
426
+ });
427
+ }
428
+ </script>
429
+
430
+ <slot />
431
+ ```
432
+
433
+ ## Data Models
434
+
435
+ ### Event Model
436
+
437
+ ```json
438
+ {
439
+ "id": "550e8400-e29b-41d4-a716-446655440000",
440
+ "project_id": "proj_abc123",
441
+ "fingerprint": "a1b2c3d4e5f6...",
442
+ "title": "Error",
443
+ "message": "Something went wrong",
444
+ "stack_trace": "Error: Something went wrong\n at Component (App.svelte:10:5)",
445
+ "service": "frontend",
446
+ "environment": "production",
447
+ "severity": "error",
448
+ "timestamp": 1678901234567,
449
+ "platform": "javascript",
450
+ "release": "1.2.3",
451
+ "metadata": {
452
+ "svelte": {
453
+ "component": "App"
454
+ }
455
+ },
456
+ "user": {
457
+ "id": "user-123",
458
+ "email": "user@example.com",
459
+ "username": "john_doe"
460
+ },
461
+ "tags": {
462
+ "component": "App",
463
+ "version": "1.2.3"
464
+ },
465
+ "breadcrumbs": [
466
+ {
467
+ "timestamp": 1678901230000,
468
+ "message": "Component mounted",
469
+ "category": "svelte",
470
+ "level": "info",
471
+ "data": {"component": "App"}
472
+ }
473
+ ],
474
+ "context": {
475
+ "svelte": {
476
+ "version": "4.0.0"
477
+ }
478
+ }
479
+ }
480
+ ```
481
+
482
+ ### User Model
483
+
484
+ ```json
485
+ {
486
+ "id": "user-123",
487
+ "email": "user@example.com",
488
+ "username": "john_doe",
489
+ "ip_address": "192.168.1.1"
490
+ }
491
+ ```
492
+
493
+ ### Breadcrumb Model
494
+
495
+ ```json
496
+ {
497
+ "timestamp": 1678901234567,
498
+ "message": "User action description",
499
+ "category": "user-action | navigation | http | database | console",
500
+ "level": "fatal | error | warning | info | debug",
501
+ "data": {
502
+ "key": "value"
503
+ }
504
+ }
505
+ ```
506
+
507
+ ## License
508
+
509
+ MIT
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@watchupltd/svelte",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "main": "./dist/index.js",
5
5
  "module": "./dist/index.mjs",
6
6
  "types": "./dist/index.d.ts",
@@ -12,11 +12,11 @@
12
12
  }
13
13
  },
14
14
  "scripts": {
15
- "build": "tsup src/index.ts --format cjs,esm --dts --external svelte",
16
- "dev": "tsup src/index.ts --format cjs,esm --dts --external svelte --watch"
15
+ "build": "tsup src/index.ts --format cjs,esm --dts --external svelte --external @watchupltd/core --no-splitting",
16
+ "dev": "tsup src/index.ts --format cjs,esm --dts --external svelte --external @watchupltd/core --no-splitting --watch"
17
17
  },
18
18
  "dependencies": {
19
- "@watchupltd/core": "file:../core"
19
+ "@watchupltd/core": "^1.0.0"
20
20
  },
21
21
  "peerDependencies": {
22
22
  "svelte": ">=3.0.0"