@bugspotter/sdk 0.1.0-alpha.1

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 (67) hide show
  1. package/CHANGELOG.md +69 -0
  2. package/LICENSE +21 -0
  3. package/README.md +639 -0
  4. package/dist/bugspotter.min.js +2 -0
  5. package/dist/bugspotter.min.js.LICENSE.txt +14 -0
  6. package/dist/capture/base-capture.d.ts +34 -0
  7. package/dist/capture/base-capture.js +23 -0
  8. package/dist/capture/capture-lifecycle.d.ts +24 -0
  9. package/dist/capture/capture-lifecycle.js +2 -0
  10. package/dist/capture/console.d.ts +29 -0
  11. package/dist/capture/console.js +107 -0
  12. package/dist/capture/metadata.d.ts +21 -0
  13. package/dist/capture/metadata.js +76 -0
  14. package/dist/capture/network.d.ts +32 -0
  15. package/dist/capture/network.js +135 -0
  16. package/dist/capture/screenshot.d.ts +19 -0
  17. package/dist/capture/screenshot.js +52 -0
  18. package/dist/collectors/dom.d.ts +67 -0
  19. package/dist/collectors/dom.js +164 -0
  20. package/dist/collectors/index.d.ts +2 -0
  21. package/dist/collectors/index.js +5 -0
  22. package/dist/core/buffer.d.ts +50 -0
  23. package/dist/core/buffer.js +88 -0
  24. package/dist/core/circular-buffer.d.ts +42 -0
  25. package/dist/core/circular-buffer.js +77 -0
  26. package/dist/core/compress.d.ts +49 -0
  27. package/dist/core/compress.js +245 -0
  28. package/dist/core/offline-queue.d.ts +76 -0
  29. package/dist/core/offline-queue.js +301 -0
  30. package/dist/core/transport.d.ts +73 -0
  31. package/dist/core/transport.js +352 -0
  32. package/dist/core/upload-helpers.d.ts +32 -0
  33. package/dist/core/upload-helpers.js +79 -0
  34. package/dist/core/uploader.d.ts +70 -0
  35. package/dist/core/uploader.js +185 -0
  36. package/dist/index.d.ts +140 -0
  37. package/dist/index.esm.js +205 -0
  38. package/dist/index.js +244 -0
  39. package/dist/utils/logger.d.ts +28 -0
  40. package/dist/utils/logger.js +84 -0
  41. package/dist/utils/sanitize-patterns.d.ts +103 -0
  42. package/dist/utils/sanitize-patterns.js +282 -0
  43. package/dist/utils/sanitize.d.ts +73 -0
  44. package/dist/utils/sanitize.js +254 -0
  45. package/dist/widget/button.d.ts +33 -0
  46. package/dist/widget/button.js +143 -0
  47. package/dist/widget/components/dom-element-cache.d.ts +62 -0
  48. package/dist/widget/components/dom-element-cache.js +105 -0
  49. package/dist/widget/components/form-validator.d.ts +66 -0
  50. package/dist/widget/components/form-validator.js +115 -0
  51. package/dist/widget/components/pii-detection-display.d.ts +64 -0
  52. package/dist/widget/components/pii-detection-display.js +142 -0
  53. package/dist/widget/components/redaction-canvas.d.ts +95 -0
  54. package/dist/widget/components/redaction-canvas.js +230 -0
  55. package/dist/widget/components/screenshot-processor.d.ts +44 -0
  56. package/dist/widget/components/screenshot-processor.js +191 -0
  57. package/dist/widget/components/style-manager.d.ts +37 -0
  58. package/dist/widget/components/style-manager.js +296 -0
  59. package/dist/widget/components/template-manager.d.ts +66 -0
  60. package/dist/widget/components/template-manager.js +198 -0
  61. package/dist/widget/modal.d.ts +62 -0
  62. package/dist/widget/modal.js +299 -0
  63. package/docs/CDN.md +213 -0
  64. package/docs/FRAMEWORK_INTEGRATION.md +1104 -0
  65. package/docs/PUBLISHING.md +550 -0
  66. package/docs/SESSION_REPLAY.md +381 -0
  67. package/package.json +90 -0
@@ -0,0 +1,1104 @@
1
+ # BugSpotter SDK - Framework Integration Guide
2
+
3
+ Complete guide for integrating BugSpotter SDK into React, Vue, Angular, and other JavaScript frameworks.
4
+
5
+ ## Table of Contents
6
+
7
+ - [React Integration](#react-integration)
8
+ - [Vue Integration](#vue-integration)
9
+ - [Angular Integration](#angular-integration)
10
+ - [Next.js Integration](#nextjs-integration)
11
+ - [Nuxt Integration](#nuxt-integration)
12
+ - [Svelte Integration](#svelte-integration)
13
+ - [Vanilla JavaScript](#vanilla-javascript)
14
+ - [TypeScript Support](#typescript-support)
15
+ - [Best Practices](#best-practices)
16
+ - [Troubleshooting](#troubleshooting)
17
+
18
+ ---
19
+
20
+ ## React Integration
21
+
22
+ ### Installation
23
+
24
+ ```bash
25
+ # Install the SDK
26
+ npm install @bugspotter/sdk
27
+ # or
28
+ yarn add @bugspotter/sdk
29
+ # or
30
+ pnpm add @bugspotter/sdk
31
+ ```
32
+
33
+ ### Basic Setup with Hook
34
+
35
+ Create a custom hook for BugSpotter:
36
+
37
+ ```typescript
38
+ // hooks/useBugSpotter.ts
39
+ import { useEffect, useRef } from 'react';
40
+ import BugSpotter from '@bugspotter/sdk';
41
+
42
+ export function useBugSpotter() {
43
+ const bugSpotterRef = useRef<any>(null);
44
+
45
+ useEffect(() => {
46
+ // Initialize BugSpotter on mount
47
+ bugSpotterRef.current = BugSpotter.init({
48
+ apiKey: process.env.REACT_APP_BUGSPOTTER_API_KEY,
49
+ endpoint: process.env.REACT_APP_BUGSPOTTER_ENDPOINT,
50
+ showWidget: true,
51
+ widgetOptions: {
52
+ position: 'bottom-right',
53
+ icon: '🐛',
54
+ },
55
+ sanitize: {
56
+ enabled: true,
57
+ patterns: ['email', 'phone', 'creditcard'],
58
+ },
59
+ replay: {
60
+ enabled: true,
61
+ duration: 30,
62
+ },
63
+ });
64
+
65
+ // Cleanup on unmount
66
+ return () => {
67
+ if (bugSpotterRef.current) {
68
+ bugSpotterRef.current.destroy();
69
+ }
70
+ };
71
+ }, []);
72
+
73
+ return bugSpotterRef.current;
74
+ }
75
+ ```
76
+
77
+ ### Usage in App Component
78
+
79
+ ```typescript
80
+ // App.tsx
81
+ import React from 'react';
82
+ import { useBugSpotter } from './hooks/useBugSpotter';
83
+
84
+ function App() {
85
+ const bugSpotter = useBugSpotter();
86
+
87
+ return (
88
+ <div className="App">
89
+ <h1>My Application</h1>
90
+ {/* Your app content */}
91
+ </div>
92
+ );
93
+ }
94
+
95
+ export default App;
96
+ ```
97
+
98
+ ### Context Provider Pattern
99
+
100
+ For more control, create a context:
101
+
102
+ ```typescript
103
+ // context/BugSpotterContext.tsx
104
+ import React, { createContext, useContext, useEffect, useState } from 'react';
105
+ import BugSpotter from '@bugspotter/sdk';
106
+
107
+ interface BugSpotterContextType {
108
+ bugSpotter: any | null;
109
+ reportBug: () => Promise<void>;
110
+ isInitialized: boolean;
111
+ }
112
+
113
+ const BugSpotterContext = createContext<BugSpotterContextType>({
114
+ bugSpotter: null,
115
+ reportBug: async () => {},
116
+ isInitialized: false,
117
+ });
118
+
119
+ export function BugSpotterProvider({ children }: { children: React.ReactNode }) {
120
+ const [bugSpotter, setBugSpotter] = useState<any>(null);
121
+ const [isInitialized, setIsInitialized] = useState(false);
122
+
123
+ useEffect(() => {
124
+ const instance = BugSpotter.init({
125
+ apiKey: process.env.REACT_APP_BUGSPOTTER_API_KEY,
126
+ endpoint: process.env.REACT_APP_BUGSPOTTER_ENDPOINT,
127
+ showWidget: true,
128
+ });
129
+
130
+ setBugSpotter(instance);
131
+ setIsInitialized(true);
132
+
133
+ return () => {
134
+ instance.destroy();
135
+ };
136
+ }, []);
137
+
138
+ const reportBug = async () => {
139
+ if (bugSpotter) {
140
+ const report = await bugSpotter.capture();
141
+ console.log('Bug report captured:', report);
142
+ }
143
+ };
144
+
145
+ return (
146
+ <BugSpotterContext.Provider value={{ bugSpotter, reportBug, isInitialized }}>
147
+ {children}
148
+ </BugSpotterContext.Provider>
149
+ );
150
+ }
151
+
152
+ export function useBugSpotterContext() {
153
+ return useContext(BugSpotterContext);
154
+ }
155
+ ```
156
+
157
+ ```typescript
158
+ // index.tsx
159
+ import { BugSpotterProvider } from './context/BugSpotterContext';
160
+
161
+ ReactDOM.render(
162
+ <BugSpotterProvider>
163
+ <App />
164
+ </BugSpotterProvider>,
165
+ document.getElementById('root')
166
+ );
167
+ ```
168
+
169
+ ### Manual Bug Reporting Component
170
+
171
+ ```typescript
172
+ // components/BugReportButton.tsx
173
+ import React from 'react';
174
+ import { useBugSpotterContext } from '../context/BugSpotterContext';
175
+
176
+ export function BugReportButton() {
177
+ const { reportBug, isInitialized } = useBugSpotterContext();
178
+
179
+ const handleClick = async () => {
180
+ try {
181
+ await reportBug();
182
+ alert('Bug report submitted!');
183
+ } catch (error) {
184
+ console.error('Failed to submit bug report:', error);
185
+ }
186
+ };
187
+
188
+ if (!isInitialized) return null;
189
+
190
+ return (
191
+ <button onClick={handleClick} className="bug-report-btn">
192
+ Report Bug
193
+ </button>
194
+ );
195
+ }
196
+ ```
197
+
198
+ ### Error Boundary Integration
199
+
200
+ ```typescript
201
+ // components/ErrorBoundary.tsx
202
+ import React, { Component, ErrorInfo, ReactNode } from 'react';
203
+ import BugSpotter from '@bugspotter/sdk';
204
+
205
+ interface Props {
206
+ children: ReactNode;
207
+ }
208
+
209
+ interface State {
210
+ hasError: boolean;
211
+ }
212
+
213
+ class ErrorBoundary extends Component<Props, State> {
214
+ public state: State = {
215
+ hasError: false,
216
+ };
217
+
218
+ private bugSpotter: any;
219
+
220
+ constructor(props: Props) {
221
+ super(props);
222
+ this.bugSpotter = BugSpotter.init({
223
+ apiKey: process.env.REACT_APP_BUGSPOTTER_API_KEY,
224
+ endpoint: process.env.REACT_APP_BUGSPOTTER_ENDPOINT,
225
+ showWidget: false, // Hide widget in error boundary
226
+ });
227
+ }
228
+
229
+ public static getDerivedStateFromError(): State {
230
+ return { hasError: true };
231
+ }
232
+
233
+ public async componentDidCatch(error: Error, errorInfo: ErrorInfo) {
234
+ console.error('Uncaught error:', error, errorInfo);
235
+
236
+ // Automatically capture and report the error
237
+ try {
238
+ const report = await this.bugSpotter.capture();
239
+ // Send report with error details
240
+ console.log('Error report captured:', report);
241
+ } catch (captureError) {
242
+ console.error('Failed to capture error report:', captureError);
243
+ }
244
+ }
245
+
246
+ public render() {
247
+ if (this.state.hasError) {
248
+ return (
249
+ <div className="error-fallback">
250
+ <h1>Something went wrong</h1>
251
+ <p>The error has been automatically reported.</p>
252
+ </div>
253
+ );
254
+ }
255
+
256
+ return this.props.children;
257
+ }
258
+ }
259
+
260
+ export default ErrorBoundary;
261
+ ```
262
+
263
+ ---
264
+
265
+ ## Vue Integration
266
+
267
+ ### Vue 3 Composition API
268
+
269
+ ```typescript
270
+ // composables/useBugSpotter.ts
271
+ import { onMounted, onUnmounted, ref } from 'vue';
272
+ import BugSpotter from '@bugspotter/sdk';
273
+
274
+ export function useBugSpotter() {
275
+ const bugSpotter = ref<any>(null);
276
+ const isInitialized = ref(false);
277
+
278
+ onMounted(() => {
279
+ bugSpotter.value = BugSpotter.init({
280
+ apiKey: import.meta.env.VITE_BUGSPOTTER_API_KEY,
281
+ endpoint: import.meta.env.VITE_BUGSPOTTER_ENDPOINT,
282
+ showWidget: true,
283
+ widgetOptions: {
284
+ position: 'bottom-right',
285
+ icon: '🐛',
286
+ },
287
+ });
288
+ isInitialized.value = true;
289
+ });
290
+
291
+ onUnmounted(() => {
292
+ if (bugSpotter.value) {
293
+ bugSpotter.value.destroy();
294
+ }
295
+ });
296
+
297
+ const reportBug = async () => {
298
+ if (bugSpotter.value) {
299
+ return await bugSpotter.value.capture();
300
+ }
301
+ };
302
+
303
+ return {
304
+ bugSpotter,
305
+ isInitialized,
306
+ reportBug,
307
+ };
308
+ }
309
+ ```
310
+
311
+ ### Usage in Component
312
+
313
+ ```vue
314
+ <!-- App.vue -->
315
+ <script setup lang="ts">
316
+ import { useBugSpotter } from './composables/useBugSpotter';
317
+
318
+ const { isInitialized, reportBug } = useBugSpotter();
319
+
320
+ const handleReportBug = async () => {
321
+ try {
322
+ const report = await reportBug();
323
+ console.log('Bug reported:', report);
324
+ } catch (error) {
325
+ console.error('Failed to report bug:', error);
326
+ }
327
+ };
328
+ </script>
329
+
330
+ <template>
331
+ <div id="app">
332
+ <h1>My Vue Application</h1>
333
+ <button v-if="isInitialized" @click="handleReportBug">Report Bug</button>
334
+ </div>
335
+ </template>
336
+ ```
337
+
338
+ ### Vue 3 Plugin
339
+
340
+ ```typescript
341
+ // plugins/bugspotter.ts
342
+ import type { App } from 'vue';
343
+ import BugSpotter from '@bugspotter/sdk';
344
+
345
+ export default {
346
+ install: (app: App, options: any) => {
347
+ const bugSpotter = BugSpotter.init({
348
+ apiKey: options.apiKey,
349
+ endpoint: options.endpoint,
350
+ showWidget: true,
351
+ ...options,
352
+ });
353
+
354
+ // Make available globally
355
+ app.config.globalProperties.$bugSpotter = bugSpotter;
356
+
357
+ // Provide/inject pattern
358
+ app.provide('bugSpotter', bugSpotter);
359
+
360
+ // Global error handler
361
+ app.config.errorHandler = async (err, instance, info) => {
362
+ console.error('Global error:', err, info);
363
+ try {
364
+ await bugSpotter.capture();
365
+ } catch (captureError) {
366
+ console.error('Failed to capture error:', captureError);
367
+ }
368
+ };
369
+ },
370
+ };
371
+ ```
372
+
373
+ ```typescript
374
+ // main.ts
375
+ import { createApp } from 'vue';
376
+ import App from './App.vue';
377
+ import BugSpotterPlugin from './plugins/bugspotter';
378
+
379
+ const app = createApp(App);
380
+
381
+ app.use(BugSpotterPlugin, {
382
+ apiKey: import.meta.env.VITE_BUGSPOTTER_API_KEY,
383
+ endpoint: import.meta.env.VITE_BUGSPOTTER_ENDPOINT,
384
+ });
385
+
386
+ app.mount('#app');
387
+ ```
388
+
389
+ ### Vue 2 (Options API)
390
+
391
+ ```javascript
392
+ // main.js
393
+ import Vue from 'vue';
394
+ import App from './App.vue';
395
+ import BugSpotter from '@bugspotter/sdk';
396
+
397
+ // Initialize BugSpotter
398
+ const bugSpotter = BugSpotter.init({
399
+ apiKey: process.env.VUE_APP_BUGSPOTTER_API_KEY,
400
+ endpoint: process.env.VUE_APP_BUGSPOTTER_ENDPOINT,
401
+ showWidget: true,
402
+ });
403
+
404
+ // Make available globally
405
+ Vue.prototype.$bugSpotter = bugSpotter;
406
+
407
+ // Global error handler
408
+ Vue.config.errorHandler = async (err, vm, info) => {
409
+ console.error('Global error:', err, info);
410
+ try {
411
+ await bugSpotter.capture();
412
+ } catch (captureError) {
413
+ console.error('Failed to capture error:', captureError);
414
+ }
415
+ };
416
+
417
+ new Vue({
418
+ render: (h) => h(App),
419
+ }).$mount('#app');
420
+ ```
421
+
422
+ ---
423
+
424
+ ## Angular Integration
425
+
426
+ ### Service Setup
427
+
428
+ ```typescript
429
+ // services/bugspotter.service.ts
430
+ import { Injectable, OnDestroy } from '@angular/core';
431
+ import BugSpotter from '@bugspotter/sdk';
432
+ import { environment } from '../environments/environment';
433
+
434
+ @Injectable({
435
+ providedIn: 'root',
436
+ })
437
+ export class BugSpotterService implements OnDestroy {
438
+ private bugSpotter: any;
439
+ private initialized = false;
440
+
441
+ constructor() {
442
+ this.initialize();
443
+ }
444
+
445
+ private initialize(): void {
446
+ this.bugSpotter = BugSpotter.init({
447
+ apiKey: environment.bugspotterApiKey,
448
+ endpoint: environment.bugspotterEndpoint,
449
+ showWidget: true,
450
+ widgetOptions: {
451
+ position: 'bottom-right',
452
+ icon: '🐛',
453
+ },
454
+ sanitize: {
455
+ enabled: true,
456
+ patterns: ['email', 'phone', 'creditcard'],
457
+ },
458
+ });
459
+ this.initialized = true;
460
+ }
461
+
462
+ async capture(): Promise<any> {
463
+ if (!this.initialized) {
464
+ throw new Error('BugSpotter not initialized');
465
+ }
466
+ return await this.bugSpotter.capture();
467
+ }
468
+
469
+ getConfig() {
470
+ return this.bugSpotter?.getConfig();
471
+ }
472
+
473
+ ngOnDestroy(): void {
474
+ if (this.bugSpotter) {
475
+ this.bugSpotter.destroy();
476
+ }
477
+ }
478
+ }
479
+ ```
480
+
481
+ ### Environment Configuration
482
+
483
+ ```typescript
484
+ // environments/environment.ts
485
+ export const environment = {
486
+ production: false,
487
+ bugspotterApiKey: 'bgs_your_dev_api_key',
488
+ bugspotterEndpoint: 'http://localhost:3000',
489
+ };
490
+
491
+ // environments/environment.prod.ts
492
+ export const environment = {
493
+ production: true,
494
+ bugspotterApiKey: 'bgs_your_prod_api_key',
495
+ bugspotterEndpoint: 'https://api.bugspotter.com',
496
+ };
497
+ ```
498
+
499
+ ### Global Error Handler
500
+
501
+ ```typescript
502
+ // app.module.ts
503
+ import { ErrorHandler, NgModule } from '@angular/core';
504
+ import { BugSpotterService } from './services/bugspotter.service';
505
+
506
+ class GlobalErrorHandler implements ErrorHandler {
507
+ constructor(private bugSpotter: BugSpotterService) {}
508
+
509
+ async handleError(error: Error): Promise<void> {
510
+ console.error('Global error:', error);
511
+ try {
512
+ await this.bugSpotter.capture();
513
+ } catch (captureError) {
514
+ console.error('Failed to capture error:', captureError);
515
+ }
516
+ }
517
+ }
518
+
519
+ @NgModule({
520
+ providers: [
521
+ {
522
+ provide: ErrorHandler,
523
+ useClass: GlobalErrorHandler,
524
+ deps: [BugSpotterService],
525
+ },
526
+ ],
527
+ })
528
+ export class AppModule {}
529
+ ```
530
+
531
+ ### Component Usage
532
+
533
+ ```typescript
534
+ // components/bug-report-button.component.ts
535
+ import { Component } from '@angular/core';
536
+ import { BugSpotterService } from '../services/bugspotter.service';
537
+
538
+ @Component({
539
+ selector: 'app-bug-report-button',
540
+ template: ` <button (click)="reportBug()" class="bug-report-btn">Report Bug</button> `,
541
+ })
542
+ export class BugReportButtonComponent {
543
+ constructor(private bugSpotter: BugSpotterService) {}
544
+
545
+ async reportBug(): Promise<void> {
546
+ try {
547
+ const report = await this.bugSpotter.capture();
548
+ console.log('Bug report captured:', report);
549
+ alert('Bug report submitted!');
550
+ } catch (error) {
551
+ console.error('Failed to submit bug report:', error);
552
+ }
553
+ }
554
+ }
555
+ ```
556
+
557
+ ---
558
+
559
+ ## Next.js Integration
560
+
561
+ ### App Router (Next.js 13+)
562
+
563
+ ```typescript
564
+ // app/providers.tsx
565
+ 'use client';
566
+
567
+ import { useEffect, useRef } from 'react';
568
+ import BugSpotter from '@bugspotter/sdk';
569
+
570
+ export function BugSpotterProvider({ children }: { children: React.ReactNode }) {
571
+ const bugSpotterRef = useRef<any>(null);
572
+
573
+ useEffect(() => {
574
+ // Only initialize on client side
575
+ if (typeof window !== 'undefined' && !bugSpotterRef.current) {
576
+ bugSpotterRef.current = BugSpotter.init({
577
+ apiKey: process.env.NEXT_PUBLIC_BUGSPOTTER_API_KEY,
578
+ endpoint: process.env.NEXT_PUBLIC_BUGSPOTTER_ENDPOINT,
579
+ showWidget: true,
580
+ });
581
+ }
582
+
583
+ return () => {
584
+ if (bugSpotterRef.current) {
585
+ bugSpotterRef.current.destroy();
586
+ }
587
+ };
588
+ }, []);
589
+
590
+ return <>{children}</>;
591
+ }
592
+ ```
593
+
594
+ ```typescript
595
+ // app/layout.tsx
596
+ import { BugSpotterProvider } from './providers';
597
+
598
+ export default function RootLayout({ children }: { children: React.ReactNode }) {
599
+ return (
600
+ <html lang="en">
601
+ <body>
602
+ <BugSpotterProvider>{children}</BugSpotterProvider>
603
+ </body>
604
+ </html>
605
+ );
606
+ }
607
+ ```
608
+
609
+ ### Pages Router (Next.js 12 and below)
610
+
611
+ ```typescript
612
+ // pages/_app.tsx
613
+ import type { AppProps } from 'next/app';
614
+ import { useEffect } from 'react';
615
+ import BugSpotter from '@bugspotter/sdk';
616
+
617
+ function MyApp({ Component, pageProps }: AppProps) {
618
+ useEffect(() => {
619
+ // Initialize BugSpotter on client side only
620
+ const bugSpotter = BugSpotter.init({
621
+ apiKey: process.env.NEXT_PUBLIC_BUGSPOTTER_API_KEY,
622
+ endpoint: process.env.NEXT_PUBLIC_BUGSPOTTER_ENDPOINT,
623
+ showWidget: true,
624
+ });
625
+
626
+ return () => {
627
+ bugSpotter.destroy();
628
+ };
629
+ }, []);
630
+
631
+ return <Component {...pageProps} />;
632
+ }
633
+
634
+ export default MyApp;
635
+ ```
636
+
637
+ ### Environment Variables
638
+
639
+ ```bash
640
+ # .env.local
641
+ NEXT_PUBLIC_BUGSPOTTER_API_KEY=bgs_your_api_key
642
+ NEXT_PUBLIC_BUGSPOTTER_ENDPOINT=https://api.bugspotter.com
643
+ ```
644
+
645
+ ---
646
+
647
+ ## Nuxt Integration
648
+
649
+ ### Nuxt 3
650
+
651
+ ```typescript
652
+ // plugins/bugspotter.client.ts
653
+ import BugSpotter from '@bugspotter/sdk';
654
+
655
+ export default defineNuxtPlugin(() => {
656
+ const config = useRuntimeConfig();
657
+
658
+ const bugSpotter = BugSpotter.init({
659
+ apiKey: config.public.bugspotterApiKey,
660
+ endpoint: config.public.bugspotterEndpoint,
661
+ showWidget: true,
662
+ });
663
+
664
+ return {
665
+ provide: {
666
+ bugSpotter,
667
+ },
668
+ };
669
+ });
670
+ ```
671
+
672
+ ```typescript
673
+ // nuxt.config.ts
674
+ export default defineNuxtConfig({
675
+ runtimeConfig: {
676
+ public: {
677
+ bugspotterApiKey: process.env.NUXT_PUBLIC_BUGSPOTTER_API_KEY,
678
+ bugspotterEndpoint: process.env.NUXT_PUBLIC_BUGSPOTTER_ENDPOINT,
679
+ },
680
+ },
681
+ });
682
+ ```
683
+
684
+ ### Usage in Component
685
+
686
+ ```vue
687
+ <script setup lang="ts">
688
+ const { $bugSpotter } = useNuxtApp();
689
+
690
+ const reportBug = async () => {
691
+ const report = await $bugSpotter.capture();
692
+ console.log('Bug reported:', report);
693
+ };
694
+ </script>
695
+
696
+ <template>
697
+ <div>
698
+ <button @click="reportBug">Report Bug</button>
699
+ </div>
700
+ </template>
701
+ ```
702
+
703
+ ---
704
+
705
+ ## Svelte Integration
706
+
707
+ ### SvelteKit
708
+
709
+ ```typescript
710
+ // src/hooks.client.ts
711
+ import BugSpotter from '@bugspotter/sdk';
712
+ import { browser } from '$app/environment';
713
+ import { PUBLIC_BUGSPOTTER_API_KEY, PUBLIC_BUGSPOTTER_ENDPOINT } from '$env/static/public';
714
+
715
+ if (browser) {
716
+ BugSpotter.init({
717
+ apiKey: PUBLIC_BUGSPOTTER_API_KEY,
718
+ endpoint: PUBLIC_BUGSPOTTER_ENDPOINT,
719
+ showWidget: true,
720
+ });
721
+ }
722
+ ```
723
+
724
+ ### Svelte Store
725
+
726
+ ```typescript
727
+ // stores/bugspotter.ts
728
+ import { writable } from 'svelte/store';
729
+ import BugSpotter from '@bugspotter/sdk';
730
+ import { browser } from '$app/environment';
731
+
732
+ function createBugSpotterStore() {
733
+ const { subscribe, set } = writable<any>(null);
734
+
735
+ if (browser) {
736
+ const instance = BugSpotter.init({
737
+ apiKey: import.meta.env.VITE_BUGSPOTTER_API_KEY,
738
+ endpoint: import.meta.env.VITE_BUGSPOTTER_ENDPOINT,
739
+ showWidget: true,
740
+ });
741
+ set(instance);
742
+ }
743
+
744
+ return {
745
+ subscribe,
746
+ capture: async () => {
747
+ let instance: any;
748
+ subscribe((value) => (instance = value))();
749
+ if (instance) {
750
+ return await instance.capture();
751
+ }
752
+ },
753
+ };
754
+ }
755
+
756
+ export const bugSpotter = createBugSpotterStore();
757
+ ```
758
+
759
+ ---
760
+
761
+ ## Vanilla JavaScript
762
+
763
+ ### Script Tag (CDN)
764
+
765
+ ```html
766
+ <!DOCTYPE html>
767
+ <html lang="en">
768
+ <head>
769
+ <meta charset="UTF-8" />
770
+ <title>My App</title>
771
+ </head>
772
+ <body>
773
+ <h1>My Application</h1>
774
+ <button id="report-bug">Report Bug</button>
775
+
776
+ <!-- Load BugSpotter SDK from CDN -->
777
+ <script src="https://cdn.bugspotter.io/sdk/bugspotter-latest.min.js"></script>
778
+ <script>
779
+ // Initialize BugSpotter
780
+ var bugSpotter = BugSpotter.init({
781
+ apiKey: 'bgs_your_api_key',
782
+ endpoint: 'https://api.bugspotter.com',
783
+ showWidget: true,
784
+ });
785
+
786
+ // Manual bug reporting
787
+ document.getElementById('report-bug').addEventListener('click', async function () {
788
+ try {
789
+ var report = await bugSpotter.capture();
790
+ console.log('Bug reported:', report);
791
+ alert('Bug report submitted!');
792
+ } catch (error) {
793
+ console.error('Failed to report bug:', error);
794
+ }
795
+ });
796
+ </script>
797
+ </body>
798
+ </html>
799
+ ```
800
+
801
+ ### ES Modules
802
+
803
+ ```javascript
804
+ // app.js
805
+ import BugSpotter from '@bugspotter/sdk';
806
+
807
+ // Initialize
808
+ const bugSpotter = BugSpotter.init({
809
+ apiKey: 'bgs_your_api_key',
810
+ endpoint: 'https://api.bugspotter.com',
811
+ showWidget: true,
812
+ widgetOptions: {
813
+ position: 'bottom-right',
814
+ icon: '🐛',
815
+ },
816
+ });
817
+
818
+ // Manual reporting
819
+ document.getElementById('report-bug').addEventListener('click', async () => {
820
+ const report = await bugSpotter.capture();
821
+ console.log('Report captured:', report);
822
+ });
823
+ ```
824
+
825
+ ---
826
+
827
+ ## TypeScript Support
828
+
829
+ ### Type Definitions
830
+
831
+ ```typescript
832
+ // types/bugspotter.d.ts
833
+ declare module '@bugspotter/sdk' {
834
+ export interface BugSpotterConfig {
835
+ apiKey?: string;
836
+ endpoint?: string;
837
+ showWidget?: boolean;
838
+ widgetOptions?: {
839
+ position?: 'bottom-right' | 'bottom-left' | 'top-right' | 'top-left';
840
+ icon?: string;
841
+ backgroundColor?: string;
842
+ size?: number;
843
+ };
844
+ replay?: {
845
+ enabled?: boolean;
846
+ duration?: number;
847
+ sampling?: {
848
+ mousemove?: number;
849
+ scroll?: number;
850
+ };
851
+ };
852
+ sanitize?: {
853
+ enabled?: boolean;
854
+ patterns?: string[];
855
+ customPatterns?: Array<{ name: string; regex: RegExp }>;
856
+ excludeSelectors?: string[];
857
+ };
858
+ }
859
+
860
+ export interface BugReport {
861
+ screenshot: string;
862
+ console: ConsoleLog[];
863
+ network: NetworkRequest[];
864
+ metadata: BrowserMetadata;
865
+ replay: any[];
866
+ }
867
+
868
+ export interface ConsoleLog {
869
+ level: string;
870
+ message: string;
871
+ timestamp: number;
872
+ stack?: string;
873
+ }
874
+
875
+ export interface NetworkRequest {
876
+ url: string;
877
+ method: string;
878
+ status: number;
879
+ duration: number;
880
+ timestamp: number;
881
+ error?: string;
882
+ }
883
+
884
+ export interface BrowserMetadata {
885
+ userAgent: string;
886
+ viewport: { width: number; height: number };
887
+ browser: string;
888
+ os: string;
889
+ url: string;
890
+ timestamp: number;
891
+ }
892
+
893
+ export interface BugSpotterInstance {
894
+ capture(): Promise<BugReport>;
895
+ getConfig(): Readonly<BugSpotterConfig>;
896
+ destroy(): void;
897
+ }
898
+
899
+ export default class BugSpotter {
900
+ static init(config: BugSpotterConfig): BugSpotterInstance;
901
+ }
902
+ }
903
+ ```
904
+
905
+ ### Usage with Types
906
+
907
+ ```typescript
908
+ import BugSpotter, { BugSpotterConfig, BugReport } from '@bugspotter/sdk';
909
+
910
+ const config: BugSpotterConfig = {
911
+ apiKey: process.env.BUGSPOTTER_API_KEY,
912
+ endpoint: process.env.BUGSPOTTER_ENDPOINT,
913
+ showWidget: true,
914
+ };
915
+
916
+ const bugSpotter = BugSpotter.init(config);
917
+
918
+ async function captureReport(): Promise<BugReport> {
919
+ return await bugSpotter.capture();
920
+ }
921
+ ```
922
+
923
+ ---
924
+
925
+ ## Best Practices
926
+
927
+ ### 1. Environment-Based Configuration
928
+
929
+ Use different configurations for development and production:
930
+
931
+ ```typescript
932
+ const config = {
933
+ apiKey:
934
+ process.env.NODE_ENV === 'production'
935
+ ? process.env.PROD_BUGSPOTTER_API_KEY
936
+ : process.env.DEV_BUGSPOTTER_API_KEY,
937
+ endpoint:
938
+ process.env.NODE_ENV === 'production' ? 'https://api.bugspotter.com' : 'http://localhost:3000',
939
+ showWidget: process.env.NODE_ENV === 'development', // Only in dev
940
+ };
941
+ ```
942
+
943
+ ### 2. Lazy Loading
944
+
945
+ Load BugSpotter only when needed to reduce initial bundle size:
946
+
947
+ ```typescript
948
+ // Lazy load BugSpotter
949
+ const loadBugSpotter = async () => {
950
+ const BugSpotter = await import('@bugspotter/sdk');
951
+ return BugSpotter.default.init({
952
+ apiKey: process.env.BUGSPOTTER_API_KEY,
953
+ endpoint: process.env.BUGSPOTTER_ENDPOINT,
954
+ });
955
+ };
956
+
957
+ // Use when needed
958
+ button.addEventListener('click', async () => {
959
+ const bugSpotter = await loadBugSpotter();
960
+ await bugSpotter.capture();
961
+ });
962
+ ```
963
+
964
+ ### 3. Error Handling
965
+
966
+ Always wrap BugSpotter calls in try-catch:
967
+
968
+ ```typescript
969
+ async function reportBug() {
970
+ try {
971
+ const report = await bugSpotter.capture();
972
+ console.log('Report captured:', report);
973
+ } catch (error) {
974
+ console.error('Failed to capture report:', error);
975
+ // Fallback: Show user a message or use alternative error reporting
976
+ }
977
+ }
978
+ ```
979
+
980
+ ### 4. PII Sanitization
981
+
982
+ Enable PII sanitization in production:
983
+
984
+ ```typescript
985
+ BugSpotter.init({
986
+ sanitize: {
987
+ enabled: true,
988
+ patterns: ['email', 'phone', 'creditcard', 'ssn'],
989
+ excludeSelectors: ['.public-data'],
990
+ },
991
+ });
992
+ ```
993
+
994
+ ### 5. Performance Optimization
995
+
996
+ Configure session replay sampling for better performance:
997
+
998
+ ```typescript
999
+ BugSpotter.init({
1000
+ replay: {
1001
+ enabled: true,
1002
+ duration: 15, // Shorter buffer for less memory usage
1003
+ sampling: {
1004
+ mousemove: 100, // Higher = less CPU usage
1005
+ scroll: 200,
1006
+ },
1007
+ },
1008
+ });
1009
+ ```
1010
+
1011
+ ### 6. Testing
1012
+
1013
+ Mock BugSpotter in tests:
1014
+
1015
+ ```typescript
1016
+ // __mocks__/@bugspotter/sdk.ts
1017
+ export default {
1018
+ init: jest.fn(() => ({
1019
+ capture: jest.fn(() => Promise.resolve({})),
1020
+ destroy: jest.fn(),
1021
+ getConfig: jest.fn(() => ({})),
1022
+ })),
1023
+ };
1024
+ ```
1025
+
1026
+ ---
1027
+
1028
+ ## Troubleshooting
1029
+
1030
+ ### Widget Not Appearing
1031
+
1032
+ **Issue**: BugSpotter widget doesn't show up.
1033
+
1034
+ **Solutions**:
1035
+
1036
+ - Ensure `showWidget: true` in config
1037
+ - Check CSS z-index conflicts
1038
+ - Verify BugSpotter is initialized after DOM is ready
1039
+ - Check browser console for errors
1040
+
1041
+ ### CSP (Content Security Policy) Errors
1042
+
1043
+ **Issue**: Content Security Policy blocks BugSpotter.
1044
+
1045
+ **Solution**: Add to your CSP headers:
1046
+
1047
+ ```
1048
+ img-src 'self' data: blob:;
1049
+ script-src 'self';
1050
+ ```
1051
+
1052
+ ### Memory Issues
1053
+
1054
+ **Issue**: High memory usage with session replay.
1055
+
1056
+ **Solutions**:
1057
+
1058
+ - Reduce replay duration: `replay: { duration: 15 }`
1059
+ - Increase sampling intervals: `sampling: { mousemove: 100 }`
1060
+ - Disable replay if not needed: `replay: { enabled: false }`
1061
+
1062
+ ### Build Errors
1063
+
1064
+ **Issue**: Module not found or build failures.
1065
+
1066
+ **Solutions**:
1067
+
1068
+ - Ensure package is installed: `npm install @bugspotter/sdk`
1069
+ - Check import path: `import BugSpotter from '@bugspotter/sdk'`
1070
+ - Clear node_modules and reinstall: `rm -rf node_modules && npm install`
1071
+
1072
+ ### SSR/SSG Issues (Next.js, Nuxt)
1073
+
1074
+ **Issue**: "window is not defined" or similar SSR errors.
1075
+
1076
+ **Solutions**:
1077
+
1078
+ - Use `.client` suffix for plugins (Nuxt)
1079
+ - Check `typeof window !== 'undefined'` before initializing
1080
+ - Use `useEffect` or `onMounted` hooks
1081
+ - Mark components as client-only
1082
+
1083
+ ### TypeScript Errors
1084
+
1085
+ **Issue**: Type errors or missing types.
1086
+
1087
+ **Solutions**:
1088
+
1089
+ - Add type definitions file (see TypeScript Support section)
1090
+ - Use `@ts-ignore` as temporary fix
1091
+ - Check if types are exported from package
1092
+
1093
+ ---
1094
+
1095
+ ## Additional Resources
1096
+
1097
+ - [SDK README](../README.md) - Complete SDK documentation
1098
+ - [Session Replay Guide](./SESSION_REPLAY.md) - Session replay configuration
1099
+ - [API Documentation](../../../API_DOCUMENTATION.md) - Backend API reference
1100
+ - [Demo App](../../../apps/demo/README.md) - Working example
1101
+
1102
+ ---
1103
+
1104
+ **Need Help?** Open an issue on [GitHub](https://github.com/apexbridge-tech/bugspotter) or contact support.