sonar-sdk 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (62) hide show
  1. package/README.md +78 -0
  2. package/dist/browser/auto.d.ts +28 -0
  3. package/dist/browser/auto.d.ts.map +1 -0
  4. package/dist/browser/auto.js +207 -0
  5. package/dist/browser/auto.js.map +1 -0
  6. package/dist/browser/consent.d.ts +19 -0
  7. package/dist/browser/consent.d.ts.map +1 -0
  8. package/dist/browser/consent.js +132 -0
  9. package/dist/browser/consent.js.map +1 -0
  10. package/dist/browser/frustration.d.ts +34 -0
  11. package/dist/browser/frustration.d.ts.map +1 -0
  12. package/dist/browser/frustration.js +257 -0
  13. package/dist/browser/frustration.js.map +1 -0
  14. package/dist/browser/index.d.ts +10 -0
  15. package/dist/browser/index.d.ts.map +1 -0
  16. package/dist/browser/index.js +9 -0
  17. package/dist/browser/index.js.map +1 -0
  18. package/dist/browser/screenshot.d.ts +21 -0
  19. package/dist/browser/screenshot.d.ts.map +1 -0
  20. package/dist/browser/screenshot.js +143 -0
  21. package/dist/browser/screenshot.js.map +1 -0
  22. package/dist/browser/session-recorder.d.ts +19 -0
  23. package/dist/browser/session-recorder.d.ts.map +1 -0
  24. package/dist/browser/session-recorder.js +68 -0
  25. package/dist/browser/session-recorder.js.map +1 -0
  26. package/dist/browser/sonar-web.d.ts +28 -0
  27. package/dist/browser/sonar-web.d.ts.map +1 -0
  28. package/dist/browser/sonar-web.js +186 -0
  29. package/dist/browser/sonar-web.js.map +1 -0
  30. package/dist/browser/transport.d.ts +19 -0
  31. package/dist/browser/transport.d.ts.map +1 -0
  32. package/dist/browser/transport.js +128 -0
  33. package/dist/browser/transport.js.map +1 -0
  34. package/dist/browser/types.d.ts +119 -0
  35. package/dist/browser/types.d.ts.map +1 -0
  36. package/dist/browser/types.js +2 -0
  37. package/dist/browser/types.js.map +1 -0
  38. package/dist/browser/video-recorder.d.ts +25 -0
  39. package/dist/browser/video-recorder.d.ts.map +1 -0
  40. package/dist/browser/video-recorder.js +121 -0
  41. package/dist/browser/video-recorder.js.map +1 -0
  42. package/dist/browser/visitor.d.ts +9 -0
  43. package/dist/browser/visitor.d.ts.map +1 -0
  44. package/dist/browser/visitor.js +67 -0
  45. package/dist/browser/visitor.js.map +1 -0
  46. package/dist/client.d.ts +12 -0
  47. package/dist/client.d.ts.map +1 -0
  48. package/dist/client.js +81 -0
  49. package/dist/client.js.map +1 -0
  50. package/dist/index.browser.d.ts +13 -0
  51. package/dist/index.browser.d.ts.map +1 -0
  52. package/dist/index.browser.js +11 -0
  53. package/dist/index.browser.js.map +1 -0
  54. package/dist/index.d.ts +15 -0
  55. package/dist/index.d.ts.map +1 -0
  56. package/dist/index.js +53 -0
  57. package/dist/index.js.map +1 -0
  58. package/dist/types.d.ts +33 -0
  59. package/dist/types.d.ts.map +1 -0
  60. package/dist/types.js +2 -0
  61. package/dist/types.js.map +1 -0
  62. package/package.json +52 -0
@@ -0,0 +1,186 @@
1
+ import { ConsentManager } from './consent';
2
+ import { VisitorManager } from './visitor';
3
+ import { BatchTransport } from './transport';
4
+ import { AutoTracker } from './auto';
5
+ import { SessionRecorder } from './session-recorder';
6
+ import { VideoRecorder } from './video-recorder';
7
+ import { SmartScreenshotCapture, ensureHtml2canvas, captureViewport } from './screenshot';
8
+ import { FrustrationDetector } from './frustration';
9
+ export class SonarWeb {
10
+ consent;
11
+ visitor;
12
+ transport;
13
+ autoTracker = null;
14
+ sessionRecorder = null;
15
+ videoRecorder = null;
16
+ smartScreenshot = null;
17
+ frustrationDetector = null;
18
+ releaseUnlistenConsent = null;
19
+ started = false;
20
+ constructor(options) {
21
+ if (typeof window === 'undefined' || typeof document === 'undefined') {
22
+ throw new Error('sonar-sdk browser module can only be used in a browser environment');
23
+ }
24
+ const endpoint = options.endpoint ?? 'https://sonar-api-xi.vercel.app';
25
+ const bannerOpts = typeof options.consent?.banner === 'object' ? options.consent.banner : undefined;
26
+ this.consent = new ConsentManager(bannerOpts);
27
+ this.visitor = new VisitorManager();
28
+ this.transport = new BatchTransport(options.apiKey, endpoint);
29
+ this.transport.setSession({
30
+ visitorId: this.visitor.visitorId,
31
+ sessionId: this.visitor.sessionId,
32
+ startUrl: window.location.href,
33
+ referrer: document.referrer || undefined,
34
+ userAgent: navigator.userAgent,
35
+ pageViews: 1,
36
+ eventCount: 0,
37
+ isBounce: true,
38
+ });
39
+ if (options.captureScreenshots) {
40
+ const ssOpts = typeof options.captureScreenshots === 'object' ? { enabled: true, ...options.captureScreenshots } : { enabled: true };
41
+ this.smartScreenshot = new SmartScreenshotCapture(ssOpts, this);
42
+ }
43
+ if (typeof options.autoTrack === 'object') {
44
+ this.autoTracker = new AutoTracker(this, options.autoTrack);
45
+ }
46
+ else if (options.autoTrack === true) {
47
+ this.autoTracker = new AutoTracker(this, {});
48
+ }
49
+ if (options.sessionRecording) {
50
+ const srOpts = typeof options.sessionRecording === 'object' ? options.sessionRecording : {};
51
+ this.sessionRecorder = new SessionRecorder(this, srOpts);
52
+ const videoOpts = typeof srOpts.video === 'object' ? srOpts.video : srOpts.video === true ? {} : null;
53
+ if (videoOpts) {
54
+ this.videoRecorder = new VideoRecorder({ sessionId: this.visitor.sessionId, apiKey: options.apiKey, endpoint }, videoOpts);
55
+ }
56
+ }
57
+ if (options.intelligence) {
58
+ this.initIntelligence(options.intelligence);
59
+ }
60
+ this.releaseUnlistenConsent = this.consent.onChange((state) => {
61
+ if (state === 'granted')
62
+ this.start();
63
+ else
64
+ this.stop();
65
+ });
66
+ this.consent.showBanner();
67
+ if (this.consent.getConsent() === 'granted') {
68
+ this.start();
69
+ }
70
+ }
71
+ initIntelligence(intel) {
72
+ if (intel.frustration) {
73
+ const frustOpts = intel.frustration === true ? {} : intel.frustration;
74
+ this.frustrationDetector = new FrustrationDetector(this, frustOpts);
75
+ }
76
+ if (intel.screenshots) {
77
+ const ssOpts = intel.screenshots === true ? { enabled: true } : { enabled: true, ...intel.screenshots };
78
+ this.smartScreenshot = new SmartScreenshotCapture(ssOpts, this);
79
+ }
80
+ }
81
+ start() {
82
+ if (this.started)
83
+ return;
84
+ this.started = true;
85
+ this.page('page_view', { title: document.title });
86
+ this.autoTracker?.init();
87
+ this.sessionRecorder?.init();
88
+ this.videoRecorder?.init();
89
+ this.frustrationDetector?.init();
90
+ }
91
+ stop() {
92
+ this.started = false;
93
+ this.autoTracker?.destroy();
94
+ this.sessionRecorder?.destroy();
95
+ this.videoRecorder?.destroy();
96
+ this.frustrationDetector?.destroy();
97
+ }
98
+ // FrustrationHost.requestScreenshot
99
+ requestScreenshot(reason) {
100
+ if (reason === 'frustration_rage_click' || reason === 'frustration_cascade') {
101
+ this.smartScreenshot?.capture(reason, 'high');
102
+ }
103
+ else if (reason === 'frustration_dead_click') {
104
+ this.smartScreenshot?.capture(reason, 'normal');
105
+ }
106
+ else {
107
+ this.smartScreenshot?.capture(reason, 'normal');
108
+ }
109
+ }
110
+ identify(visitorId, traits) {
111
+ try {
112
+ localStorage.setItem('sonar_visitor_id', visitorId);
113
+ }
114
+ catch { /* noop */ }
115
+ this.track('identify', { ...traits, visitorId });
116
+ }
117
+ page(name, properties) {
118
+ this.track('page_view', {
119
+ ...properties,
120
+ name: name ?? document.title,
121
+ url: window.location.href,
122
+ });
123
+ }
124
+ // AutoTrackerHost + FrustrationHost:
125
+ // Normal calls: track('page_view', { title })
126
+ // Frustration calls: track('rage_click', 0.85, { count: 5 })
127
+ track(event, propertiesOrSeverity, maybeProperties) {
128
+ this.visitor.touch();
129
+ let severity = 0;
130
+ let props;
131
+ if (typeof propertiesOrSeverity === 'number') {
132
+ severity = propertiesOrSeverity;
133
+ props = maybeProperties;
134
+ }
135
+ else {
136
+ props = propertiesOrSeverity;
137
+ }
138
+ const payload = {
139
+ type: event,
140
+ category: 'manual',
141
+ name: props?.name,
142
+ url: window.location.href,
143
+ referrer: document.referrer || undefined,
144
+ userAgent: navigator.userAgent,
145
+ viewportWidth: window.innerWidth,
146
+ viewportHeight: window.innerHeight,
147
+ screenWidth: window.screen.width,
148
+ screenHeight: window.screen.height,
149
+ payload: props ? JSON.stringify(props) : undefined,
150
+ sessionId: this.visitor.sessionId,
151
+ visitorId: this.visitor.visitorId,
152
+ consentGranted: this.consent.getConsent() === 'granted',
153
+ timestamp: new Date().toISOString(),
154
+ };
155
+ if (severity > 0)
156
+ payload.severity = severity;
157
+ if (props?.name)
158
+ payload.name = String(props.name);
159
+ this.transport.push(payload);
160
+ }
161
+ async screenshot() {
162
+ const ok = await ensureHtml2canvas();
163
+ if (!ok)
164
+ return null;
165
+ return captureViewport();
166
+ }
167
+ setConsent(state) {
168
+ this.consent.setConsent(state);
169
+ }
170
+ getConsent() {
171
+ return this.consent.getConsent();
172
+ }
173
+ destroy() {
174
+ this.transport.flush();
175
+ this.transport.stop();
176
+ this.autoTracker?.destroy();
177
+ this.sessionRecorder?.destroy();
178
+ this.videoRecorder?.destroy();
179
+ this.frustrationDetector?.destroy();
180
+ this.smartScreenshot?.destroy();
181
+ this.consent.hideBanner();
182
+ this.releaseUnlistenConsent?.();
183
+ this.started = false;
184
+ }
185
+ }
186
+ //# sourceMappingURL=sonar-web.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"sonar-web.js","sourceRoot":"","sources":["../../src/browser/sonar-web.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,WAAW,CAAA;AAC1C,OAAO,EAAE,cAAc,EAAE,MAAM,aAAa,CAAA;AAC5C,OAAO,EAAE,WAAW,EAAE,MAAM,QAAQ,CAAA;AAEpC,OAAO,EAAE,eAAe,EAAE,MAAM,oBAAoB,CAAA;AACpD,OAAO,EAAE,aAAa,EAAE,MAAM,kBAAkB,CAAA;AAChD,OAAO,EAAE,sBAAsB,EAAE,iBAAiB,EAAE,eAAe,EAAE,MAAM,cAAc,CAAA;AACzF,OAAO,EAAE,mBAAmB,EAAE,MAAM,eAAe,CAAA;AAGnD,MAAM,OAAO,QAAQ;IACX,OAAO,CAAgB;IACvB,OAAO,CAAgB;IACvB,SAAS,CAAgB;IACzB,WAAW,GAAuB,IAAI,CAAA;IACtC,eAAe,GAA2B,IAAI,CAAA;IAC9C,aAAa,GAAyB,IAAI,CAAA;IAC1C,eAAe,GAAkC,IAAI,CAAA;IACrD,mBAAmB,GAA+B,IAAI,CAAA;IACtD,sBAAsB,GAAwB,IAAI,CAAA;IAClD,OAAO,GAAG,KAAK,CAAA;IAEvB,YAAY,OAAwB;QAClC,IAAI,OAAO,MAAM,KAAK,WAAW,IAAI,OAAO,QAAQ,KAAK,WAAW,EAAE,CAAC;YACrE,MAAM,IAAI,KAAK,CAAC,oEAAoE,CAAC,CAAA;QACvF,CAAC;QAED,MAAM,QAAQ,GAAG,OAAO,CAAC,QAAQ,IAAI,iCAAiC,CAAA;QACtE,MAAM,UAAU,GAAG,OAAO,OAAO,CAAC,OAAO,EAAE,MAAM,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,OAAO,CAAC,MAAM,CAAC,CAAC,CAAC,SAAS,CAAA;QACnG,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,CAAC,UAAU,CAAC,CAAA;QAC7C,IAAI,CAAC,OAAO,GAAG,IAAI,cAAc,EAAE,CAAA;QACnC,IAAI,CAAC,SAAS,GAAG,IAAI,cAAc,CAAC,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QAE7D,IAAI,CAAC,SAAS,CAAC,UAAU,CAAC;YACxB,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,QAAQ,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;YAC9B,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,SAAS;YACxC,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,SAAS,EAAE,CAAC;YACZ,UAAU,EAAE,CAAC;YACb,QAAQ,EAAE,IAAI;SACf,CAAC,CAAA;QAEF,IAAI,OAAO,CAAC,kBAAkB,EAAE,CAAC;YAC/B,MAAM,MAAM,GAAG,OAAO,OAAO,CAAC,kBAAkB,KAAK,QAAQ,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,OAAO,CAAC,kBAAkB,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAA;YACpI,IAAI,CAAC,eAAe,GAAG,IAAI,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACjE,CAAC;QAED,IAAI,OAAO,OAAO,CAAC,SAAS,KAAK,QAAQ,EAAE,CAAC;YAC1C,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,OAAO,CAAC,SAAS,CAAC,CAAA;QAC7D,CAAC;aAAM,IAAI,OAAO,CAAC,SAAS,KAAK,IAAI,EAAE,CAAC;YACtC,IAAI,CAAC,WAAW,GAAG,IAAI,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAA;QAC9C,CAAC;QAED,IAAI,OAAO,CAAC,gBAAgB,EAAE,CAAC;YAC7B,MAAM,MAAM,GAAG,OAAO,OAAO,CAAC,gBAAgB,KAAK,QAAQ,CAAC,CAAC,CAAC,OAAO,CAAC,gBAAgB,CAAC,CAAC,CAAC,EAAE,CAAA;YAC3F,IAAI,CAAC,eAAe,GAAG,IAAI,eAAe,CAAC,IAAI,EAAE,MAAM,CAAC,CAAA;YACxD,MAAM,SAAS,GAAG,OAAO,MAAM,CAAC,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,CAAC,CAAC,CAAC,MAAM,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,IAAI,CAAA;YACrG,IAAI,SAAS,EAAE,CAAC;gBACd,IAAI,CAAC,aAAa,GAAG,IAAI,aAAa,CACpC,EAAE,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS,EAAE,MAAM,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,EAAE,EACvE,SAAS,CACV,CAAA;YACH,CAAC;QACH,CAAC;QAED,IAAI,OAAO,CAAC,YAAY,EAAE,CAAC;YACzB,IAAI,CAAC,gBAAgB,CAAC,OAAO,CAAC,YAAY,CAAC,CAAA;QAC7C,CAAC;QAED,IAAI,CAAC,sBAAsB,GAAG,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC,KAAmB,EAAE,EAAE;YAC1E,IAAI,KAAK,KAAK,SAAS;gBAAE,IAAI,CAAC,KAAK,EAAE,CAAA;;gBAChC,IAAI,CAAC,IAAI,EAAE,CAAA;QAClB,CAAC,CAAC,CAAA;QAEF,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAA;QAEzB,IAAI,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,SAAS,EAAE,CAAC;YAC5C,IAAI,CAAC,KAAK,EAAE,CAAA;QACd,CAAC;IACH,CAAC;IAEO,gBAAgB,CAAC,KAAmD;QAC1E,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,SAAS,GAAG,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,KAAK,CAAC,WAAW,CAAA;YACrE,IAAI,CAAC,mBAAmB,GAAG,IAAI,mBAAmB,CAAC,IAAI,EAAE,SAAS,CAAC,CAAA;QACrE,CAAC;QAED,IAAI,KAAK,CAAC,WAAW,EAAE,CAAC;YACtB,MAAM,MAAM,GAAG,KAAK,CAAC,WAAW,KAAK,IAAI,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC,WAAW,EAAE,CAAA;YACvG,IAAI,CAAC,eAAe,GAAG,IAAI,sBAAsB,CAAC,MAAM,EAAE,IAAI,CAAC,CAAA;QACjE,CAAC;IACH,CAAC;IAEO,KAAK;QACX,IAAI,IAAI,CAAC,OAAO;YAAE,OAAM;QACxB,IAAI,CAAC,OAAO,GAAG,IAAI,CAAA;QAEnB,IAAI,CAAC,IAAI,CAAC,WAAW,EAAE,EAAE,KAAK,EAAE,QAAQ,CAAC,KAAK,EAAE,CAAC,CAAA;QAEjD,IAAI,CAAC,WAAW,EAAE,IAAI,EAAE,CAAA;QACxB,IAAI,CAAC,eAAe,EAAE,IAAI,EAAE,CAAA;QAC5B,IAAI,CAAC,aAAa,EAAE,IAAI,EAAE,CAAA;QAC1B,IAAI,CAAC,mBAAmB,EAAE,IAAI,EAAE,CAAA;IAClC,CAAC;IAEO,IAAI;QACV,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;QACpB,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,CAAA;QAC3B,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAA;QAC/B,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,mBAAmB,EAAE,OAAO,EAAE,CAAA;IACrC,CAAC;IAED,oCAAoC;IACpC,iBAAiB,CAAC,MAAc;QAC9B,IAAI,MAAM,KAAK,wBAAwB,IAAI,MAAM,KAAK,qBAAqB,EAAE,CAAC;YAC5E,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,MAAM,CAAC,CAAA;QAC/C,CAAC;aAAM,IAAI,MAAM,KAAK,wBAAwB,EAAE,CAAC;YAC/C,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACjD,CAAC;aAAM,CAAC;YACN,IAAI,CAAC,eAAe,EAAE,OAAO,CAAC,MAAM,EAAE,QAAQ,CAAC,CAAA;QACjD,CAAC;IACH,CAAC;IAED,QAAQ,CAAC,SAAiB,EAAE,MAAgC;QAC1D,IAAI,CAAC;YAAC,YAAY,CAAC,OAAO,CAAC,kBAAkB,EAAE,SAAS,CAAC,CAAA;QAAC,CAAC;QAAC,MAAM,CAAC,CAAC,UAAU,CAAC,CAAC;QAChF,IAAI,CAAC,KAAK,CAAC,UAAU,EAAE,EAAE,GAAG,MAAM,EAAE,SAAS,EAAE,CAAC,CAAA;IAClD,CAAC;IAED,IAAI,CAAC,IAAa,EAAE,UAAoC;QACtD,IAAI,CAAC,KAAK,CAAC,WAAW,EAAE;YACtB,GAAG,UAAU;YACb,IAAI,EAAE,IAAI,IAAI,QAAQ,CAAC,KAAK;YAC5B,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;SAC1B,CAAC,CAAA;IACJ,CAAC;IAED,qCAAqC;IACrC,8CAA8C;IAC9C,6DAA6D;IAC7D,KAAK,CAAC,KAAa,EAAE,oBAAuD,EAAE,eAAyC;QACrH,IAAI,CAAC,OAAO,CAAC,KAAK,EAAE,CAAA;QAEpB,IAAI,QAAQ,GAAG,CAAC,CAAA;QAChB,IAAI,KAA0C,CAAA;QAE9C,IAAI,OAAO,oBAAoB,KAAK,QAAQ,EAAE,CAAC;YAC7C,QAAQ,GAAG,oBAAoB,CAAA;YAC/B,KAAK,GAAG,eAAe,CAAA;QACzB,CAAC;aAAM,CAAC;YACN,KAAK,GAAG,oBAAoB,CAAA;QAC9B,CAAC;QAED,MAAM,OAAO,GAA0B;YACrC,IAAI,EAAE,KAAK;YACX,QAAQ,EAAE,QAAQ;YAClB,IAAI,EAAE,KAAK,EAAE,IAA0B;YACvC,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;YACzB,QAAQ,EAAE,QAAQ,CAAC,QAAQ,IAAI,SAAS;YACxC,SAAS,EAAE,SAAS,CAAC,SAAS;YAC9B,aAAa,EAAE,MAAM,CAAC,UAAU;YAChC,cAAc,EAAE,MAAM,CAAC,WAAW;YAClC,WAAW,EAAE,MAAM,CAAC,MAAM,CAAC,KAAK;YAChC,YAAY,EAAE,MAAM,CAAC,MAAM,CAAC,MAAM;YAClC,OAAO,EAAE,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,SAAS;YAClD,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,SAAS,EAAE,IAAI,CAAC,OAAO,CAAC,SAAS;YACjC,cAAc,EAAE,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,KAAK,SAAS;YACvD,SAAS,EAAE,IAAI,IAAI,EAAE,CAAC,WAAW,EAAE;SACpC,CAAA;QAED,IAAI,QAAQ,GAAG,CAAC;YAAE,OAAO,CAAC,QAAQ,GAAG,QAAQ,CAAA;QAC7C,IAAI,KAAK,EAAE,IAAI;YAAE,OAAO,CAAC,IAAI,GAAG,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAA;QAElD,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,OAAO,CAAC,CAAA;IAC9B,CAAC;IAED,KAAK,CAAC,UAAU;QACd,MAAM,EAAE,GAAG,MAAM,iBAAiB,EAAE,CAAA;QACpC,IAAI,CAAC,EAAE;YAAE,OAAO,IAAI,CAAA;QACpB,OAAO,eAAe,EAAE,CAAA;IAC1B,CAAC;IAED,UAAU,CAAC,KAAmB;QAC5B,IAAI,CAAC,OAAO,CAAC,UAAU,CAAC,KAAK,CAAC,CAAA;IAChC,CAAC;IAED,UAAU;QACR,OAAO,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAA;IAClC,CAAC;IAED,OAAO;QACL,IAAI,CAAC,SAAS,CAAC,KAAK,EAAE,CAAA;QACtB,IAAI,CAAC,SAAS,CAAC,IAAI,EAAE,CAAA;QACrB,IAAI,CAAC,WAAW,EAAE,OAAO,EAAE,CAAA;QAC3B,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAA;QAC/B,IAAI,CAAC,aAAa,EAAE,OAAO,EAAE,CAAA;QAC7B,IAAI,CAAC,mBAAmB,EAAE,OAAO,EAAE,CAAA;QACnC,IAAI,CAAC,eAAe,EAAE,OAAO,EAAE,CAAA;QAC/B,IAAI,CAAC,OAAO,CAAC,UAAU,EAAE,CAAA;QACzB,IAAI,CAAC,sBAAsB,EAAE,EAAE,CAAA;QAC/B,IAAI,CAAC,OAAO,GAAG,KAAK,CAAA;IACtB,CAAC;CACF"}
@@ -0,0 +1,19 @@
1
+ import type { AnalyticsEventPayload, AnalyticsSessionPayload } from './types';
2
+ export declare class BatchTransport {
3
+ private buffer;
4
+ private flushTimer;
5
+ private endpoint;
6
+ private apiKey;
7
+ private session;
8
+ private flushing;
9
+ constructor(apiKey: string, endpoint: string);
10
+ setSession(session: AnalyticsSessionPayload | null): void;
11
+ push(event: AnalyticsEventPayload): void;
12
+ private startAutoFlush;
13
+ stop(): void;
14
+ private send;
15
+ flush(): Promise<void>;
16
+ flushUrgent(): Promise<void>;
17
+ private flushSync;
18
+ }
19
+ //# sourceMappingURL=transport.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.d.ts","sourceRoot":"","sources":["../../src/browser/transport.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,qBAAqB,EAAE,uBAAuB,EAAE,MAAM,SAAS,CAAA;AAO7E,qBAAa,cAAc;IACzB,OAAO,CAAC,MAAM,CAA8B;IAC5C,OAAO,CAAC,UAAU,CAA8C;IAChE,OAAO,CAAC,QAAQ,CAAQ;IACxB,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,OAAO,CAAuC;IACtD,OAAO,CAAC,QAAQ,CAAQ;gBAEZ,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM;IAa5C,UAAU,CAAC,OAAO,EAAE,uBAAuB,GAAG,IAAI;IAIlD,IAAI,CAAC,KAAK,EAAE,qBAAqB;IAUjC,OAAO,CAAC,cAAc;IAItB,IAAI;YAOU,IAAI;IAuBZ,KAAK;IAWL,WAAW;IAwBjB,OAAO,CAAC,SAAS;CAoBlB"}
@@ -0,0 +1,128 @@
1
+ const FLUSH_INTERVAL_MS = 5000;
2
+ const MAX_BUFFER_SIZE = 50;
3
+ const MAX_RETRIES = 3;
4
+ const URGENT_SEVERITY_THRESHOLD = 0.8;
5
+ export class BatchTransport {
6
+ buffer = [];
7
+ flushTimer = null;
8
+ endpoint;
9
+ apiKey;
10
+ session = null;
11
+ flushing = false;
12
+ constructor(apiKey, endpoint) {
13
+ this.apiKey = apiKey;
14
+ this.endpoint = `${endpoint.replace(/\/+$/, '')}/ingest/analytics`;
15
+ this.startAutoFlush();
16
+ if (typeof document !== 'undefined') {
17
+ document.addEventListener('visibilitychange', () => {
18
+ if (document.visibilityState === 'hidden')
19
+ this.flushSync();
20
+ });
21
+ window.addEventListener('beforeunload', () => this.flushSync());
22
+ }
23
+ }
24
+ setSession(session) {
25
+ this.session = session;
26
+ }
27
+ push(event) {
28
+ this.buffer.push(event);
29
+ if (event.severity !== undefined && event.severity >= URGENT_SEVERITY_THRESHOLD) {
30
+ this.flushUrgent();
31
+ }
32
+ else if (this.buffer.length >= MAX_BUFFER_SIZE) {
33
+ this.flush();
34
+ }
35
+ }
36
+ startAutoFlush() {
37
+ this.flushTimer = setInterval(() => this.flush(), FLUSH_INTERVAL_MS);
38
+ }
39
+ stop() {
40
+ if (this.flushTimer) {
41
+ clearInterval(this.flushTimer);
42
+ this.flushTimer = null;
43
+ }
44
+ }
45
+ async send(payload) {
46
+ for (let attempt = 0; attempt < MAX_RETRIES; attempt++) {
47
+ try {
48
+ const res = await fetch(this.endpoint, {
49
+ method: 'POST',
50
+ headers: {
51
+ 'Content-Type': 'application/json',
52
+ Authorization: `Bearer ${this.apiKey}`,
53
+ },
54
+ body: JSON.stringify(payload),
55
+ });
56
+ if (res.ok)
57
+ return true;
58
+ if (res.status >= 400 && res.status < 500)
59
+ return false;
60
+ }
61
+ catch {
62
+ // retry
63
+ }
64
+ if (attempt < MAX_RETRIES - 1) {
65
+ await new Promise((r) => setTimeout(r, Math.pow(2, attempt) * 200));
66
+ }
67
+ }
68
+ return false;
69
+ }
70
+ async flush() {
71
+ if (this.flushing || this.buffer.length === 0)
72
+ return;
73
+ this.flushing = true;
74
+ const batch = this.buffer.splice(0, this.buffer.length);
75
+ const payload = { events: batch };
76
+ if (this.session)
77
+ payload.session = this.session;
78
+ await this.send(payload);
79
+ this.flushing = false;
80
+ }
81
+ async flushUrgent() {
82
+ if (this.buffer.length === 0)
83
+ return;
84
+ this.flushing = true;
85
+ const batch = this.buffer.splice(0, this.buffer.length);
86
+ const payload = { events: batch };
87
+ if (this.session)
88
+ payload.session = this.session;
89
+ try {
90
+ await fetch(this.endpoint, {
91
+ method: 'POST',
92
+ headers: {
93
+ 'Content-Type': 'application/json',
94
+ Authorization: `Bearer ${this.apiKey}`,
95
+ },
96
+ body: JSON.stringify(payload),
97
+ keepalive: true,
98
+ });
99
+ }
100
+ catch {
101
+ // best-effort
102
+ }
103
+ this.flushing = false;
104
+ }
105
+ flushSync() {
106
+ if (this.buffer.length === 0)
107
+ return;
108
+ const batch = this.buffer.splice(0, this.buffer.length);
109
+ const payload = { events: batch };
110
+ if (this.session)
111
+ payload.session = this.session;
112
+ try {
113
+ fetch(this.endpoint, {
114
+ method: 'POST',
115
+ headers: {
116
+ 'Content-Type': 'application/json',
117
+ Authorization: `Bearer ${this.apiKey}`,
118
+ },
119
+ body: JSON.stringify(payload),
120
+ keepalive: true,
121
+ });
122
+ }
123
+ catch {
124
+ // best-effort
125
+ }
126
+ }
127
+ }
128
+ //# sourceMappingURL=transport.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"transport.js","sourceRoot":"","sources":["../../src/browser/transport.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,119 @@
1
+ export type ConsentState = 'granted' | 'denied' | 'pending';
2
+ export type ConsentBannerOptions = {
3
+ position?: 'bottom' | 'bottom-left' | 'bottom-right' | 'top';
4
+ text?: string;
5
+ acceptText?: string;
6
+ declineText?: string;
7
+ privacyPolicyUrl?: string;
8
+ theme?: 'light' | 'dark';
9
+ };
10
+ export type AutoTrackOptions = {
11
+ pageViews?: boolean;
12
+ linkClicks?: boolean;
13
+ formSubmissions?: boolean;
14
+ scrollDepth?: boolean;
15
+ consoleErrors?: boolean;
16
+ clickTracking?: boolean;
17
+ };
18
+ export type VideoRecorderOptions = {
19
+ enabled?: boolean;
20
+ fps?: number;
21
+ quality?: number;
22
+ maxWidth?: number;
23
+ };
24
+ export type SessionRecorderOptions = {
25
+ enabled?: boolean;
26
+ sampleIntervalMs?: number;
27
+ video?: boolean | VideoRecorderOptions;
28
+ };
29
+ export type ScreenshotOptions = {
30
+ enabled?: boolean;
31
+ onError?: boolean;
32
+ quality?: number;
33
+ };
34
+ export type FrustrationRageClickOptions = {
35
+ enabled?: boolean;
36
+ threshold?: number;
37
+ windowMs?: number;
38
+ };
39
+ export type FrustrationDeadClickOptions = {
40
+ enabled?: boolean;
41
+ timeoutMs?: number;
42
+ };
43
+ export type FrustrationHesitationOptions = {
44
+ enabled?: boolean;
45
+ thresholdMs?: number;
46
+ };
47
+ export type FrustrationScrollChaosOptions = {
48
+ enabled?: boolean;
49
+ };
50
+ export type FrustrationCascadeOptions = {
51
+ enabled?: boolean;
52
+ windowMs?: number;
53
+ };
54
+ export type FrustrationOptions = {
55
+ rageClick?: boolean | FrustrationRageClickOptions;
56
+ deadClick?: boolean | FrustrationDeadClickOptions;
57
+ hoverHesitation?: boolean | FrustrationHesitationOptions;
58
+ scrollChaos?: boolean | FrustrationScrollChaosOptions;
59
+ cascadeDetection?: boolean | FrustrationCascadeOptions;
60
+ };
61
+ export type SmartScreenshotTriggers = {
62
+ onError?: boolean;
63
+ onRageClick?: boolean;
64
+ onDeadClick?: boolean;
65
+ onUnload?: boolean;
66
+ onCriticalAction?: boolean;
67
+ };
68
+ export type SmartScreenshotOptions = {
69
+ enabled?: boolean;
70
+ quality?: number;
71
+ maxWidth?: number;
72
+ triggers?: SmartScreenshotTriggers;
73
+ };
74
+ export type IntelligenceOptions = {
75
+ frustration?: boolean | FrustrationOptions;
76
+ screenshots?: boolean | SmartScreenshotOptions;
77
+ };
78
+ export type SonarWebOptions = {
79
+ apiKey: string;
80
+ endpoint?: string;
81
+ autoTrack?: boolean | AutoTrackOptions;
82
+ captureScreenshots?: boolean | ScreenshotOptions;
83
+ sessionRecording?: boolean | SessionRecorderOptions;
84
+ consent?: {
85
+ banner?: boolean | ConsentBannerOptions;
86
+ };
87
+ release?: string;
88
+ intelligence?: IntelligenceOptions;
89
+ };
90
+ export type AnalyticsEventPayload = {
91
+ type: string;
92
+ category?: string;
93
+ name?: string;
94
+ url: string;
95
+ referrer?: string;
96
+ userAgent?: string;
97
+ viewportWidth?: number;
98
+ viewportHeight?: number;
99
+ screenWidth?: number;
100
+ screenHeight?: number;
101
+ payload?: string;
102
+ sessionId?: string;
103
+ visitorId?: string;
104
+ consentGranted?: boolean;
105
+ timestamp: string;
106
+ severity?: number;
107
+ fingerprint?: string;
108
+ };
109
+ export type AnalyticsSessionPayload = {
110
+ visitorId?: string;
111
+ sessionId?: string;
112
+ startUrl: string;
113
+ referrer?: string;
114
+ userAgent?: string;
115
+ pageViews?: number;
116
+ eventCount?: number;
117
+ isBounce?: boolean;
118
+ };
119
+ //# sourceMappingURL=types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/browser/types.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=types.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/browser/types.ts"],"names":[],"mappings":""}
@@ -0,0 +1,25 @@
1
+ import type { VideoRecorderOptions } from './types';
2
+ export type VideoRecorderHost = {
3
+ sessionId: string;
4
+ apiKey: string;
5
+ endpoint: string;
6
+ };
7
+ export declare class VideoRecorder {
8
+ private host;
9
+ private opts;
10
+ private canvas;
11
+ private ctx;
12
+ private stream;
13
+ private recorder;
14
+ private recorded;
15
+ private captureTimer;
16
+ private active;
17
+ private destroyed;
18
+ private unloadHandler;
19
+ constructor(host: VideoRecorderHost, opts: VideoRecorderOptions);
20
+ init(): Promise<void>;
21
+ private captureFrame;
22
+ private upload;
23
+ destroy(): void;
24
+ }
25
+ //# sourceMappingURL=video-recorder.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-recorder.d.ts","sourceRoot":"","sources":["../../src/browser/video-recorder.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,SAAS,CAAA;AAGnD,MAAM,MAAM,iBAAiB,GAAG;IAC9B,SAAS,EAAE,MAAM,CAAA;IACjB,MAAM,EAAE,MAAM,CAAA;IACd,QAAQ,EAAE,MAAM,CAAA;CACjB,CAAA;AAUD,qBAAa,aAAa;IACxB,OAAO,CAAC,IAAI,CAAmB;IAC/B,OAAO,CAAC,IAAI,CAAgC;IAC5C,OAAO,CAAC,MAAM,CAAiC;IAC/C,OAAO,CAAC,GAAG,CAAwC;IACnD,OAAO,CAAC,MAAM,CAA2B;IACzC,OAAO,CAAC,QAAQ,CAA6B;IAC7C,OAAO,CAAC,QAAQ,CAAoB;IACpC,OAAO,CAAC,YAAY,CAA8C;IAClE,OAAO,CAAC,MAAM,CAAQ;IACtB,OAAO,CAAC,SAAS,CAAQ;IACzB,OAAO,CAAC,aAAa,CAA4B;gBAErC,IAAI,EAAE,iBAAiB,EAAE,IAAI,EAAE,oBAAoB;IAUzD,IAAI;YAkCI,YAAY;YAiBZ,MAAM;IAmBpB,OAAO;CAmBR"}
@@ -0,0 +1,121 @@
1
+ import { ensureHtml2canvas, captureViewport } from './screenshot';
2
+ function getMimeType() {
3
+ if (typeof MediaRecorder === 'undefined')
4
+ return '';
5
+ for (const mt of ['video/webm;codecs=vp9', 'video/webm;codecs=vp8', 'video/webm', 'video/mp4']) {
6
+ if (MediaRecorder.isTypeSupported(mt))
7
+ return mt;
8
+ }
9
+ return '';
10
+ }
11
+ export class VideoRecorder {
12
+ host;
13
+ opts;
14
+ canvas = null;
15
+ ctx = null;
16
+ stream = null;
17
+ recorder = null;
18
+ recorded = null;
19
+ captureTimer = null;
20
+ active = false;
21
+ destroyed = false;
22
+ unloadHandler = null;
23
+ constructor(host, opts) {
24
+ this.host = host;
25
+ this.opts = {
26
+ enabled: opts.enabled ?? true,
27
+ fps: opts.fps ?? 1,
28
+ quality: opts.quality ?? 0.6,
29
+ maxWidth: opts.maxWidth ?? 1280,
30
+ };
31
+ }
32
+ async init() {
33
+ if (this.active || !this.opts.enabled)
34
+ return;
35
+ const mimeType = getMimeType();
36
+ if (!mimeType)
37
+ return;
38
+ const ok = await ensureHtml2canvas();
39
+ if (!ok)
40
+ return;
41
+ this.active = true;
42
+ const scale = Math.min(1, this.opts.maxWidth / window.innerWidth);
43
+ this.canvas = document.createElement('canvas');
44
+ this.canvas.width = Math.round(window.innerWidth * scale);
45
+ this.canvas.height = Math.round(window.innerHeight * scale);
46
+ Object.assign(this.canvas.style, {
47
+ position: 'fixed', left: '-9999px', top: '0',
48
+ pointerEvents: 'none',
49
+ });
50
+ document.body.appendChild(this.canvas);
51
+ this.ctx = this.canvas.getContext('2d');
52
+ this.stream = this.canvas.captureStream(this.opts.fps);
53
+ this.recorder = new MediaRecorder(this.stream, { mimeType });
54
+ this.recorder.ondataavailable = (e) => {
55
+ if (e.data.size > 0)
56
+ this.recorded = e.data;
57
+ };
58
+ this.recorder.start();
59
+ this.captureTimer = setInterval(() => this.captureFrame(), 1000 / this.opts.fps);
60
+ this.unloadHandler = () => this.destroy();
61
+ window.addEventListener('beforeunload', this.unloadHandler);
62
+ }
63
+ async captureFrame() {
64
+ if (this.destroyed || !this.ctx || !this.canvas)
65
+ return;
66
+ try {
67
+ const dataUrl = await captureViewport();
68
+ if (!dataUrl)
69
+ return;
70
+ const img = new Image();
71
+ await new Promise((resolve, reject) => {
72
+ img.onload = resolve;
73
+ img.onerror = reject;
74
+ img.src = dataUrl;
75
+ });
76
+ this.ctx.drawImage(img, 0, 0, this.canvas.width, this.canvas.height);
77
+ }
78
+ catch {
79
+ // skip frame
80
+ }
81
+ }
82
+ async upload() {
83
+ if (!this.recorded)
84
+ return;
85
+ const blob = this.recorded;
86
+ const formData = new FormData();
87
+ formData.append('video', blob, `session-${this.host.sessionId}.webm`);
88
+ formData.append('sessionId', this.host.sessionId);
89
+ try {
90
+ await fetch(`${this.host.endpoint}/ingest/session-video`, {
91
+ method: 'POST',
92
+ headers: { Authorization: `Bearer ${this.host.apiKey}` },
93
+ body: formData,
94
+ keepalive: true,
95
+ });
96
+ }
97
+ catch {
98
+ // best-effort
99
+ }
100
+ this.recorded = null;
101
+ }
102
+ destroy() {
103
+ if (this.destroyed)
104
+ return;
105
+ this.destroyed = true;
106
+ this.active = false;
107
+ if (this.unloadHandler)
108
+ window.removeEventListener('beforeunload', this.unloadHandler);
109
+ if (this.captureTimer)
110
+ clearInterval(this.captureTimer);
111
+ if (this.recorder?.state === 'recording') {
112
+ this.recorder.stop();
113
+ }
114
+ this.stream?.getTracks().forEach((t) => t.stop());
115
+ this.stream = null;
116
+ this.upload();
117
+ if (this.canvas?.parentNode)
118
+ this.canvas.parentNode.removeChild(this.canvas);
119
+ }
120
+ }
121
+ //# sourceMappingURL=video-recorder.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"video-recorder.js","sourceRoot":"","sources":["../../src/browser/video-recorder.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,9 @@
1
+ export declare class VisitorManager {
2
+ private _visitorId;
3
+ private _sessionId;
4
+ constructor();
5
+ get visitorId(): string;
6
+ get sessionId(): string;
7
+ touch(): void;
8
+ }
9
+ //# sourceMappingURL=visitor.d.ts.map