@logcaffe/browser 0.3.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 (53) hide show
  1. package/dist/breadcrumbs.d.ts +11 -0
  2. package/dist/breadcrumbs.d.ts.map +1 -0
  3. package/dist/breadcrumbs.js +96 -0
  4. package/dist/breadcrumbs.js.map +1 -0
  5. package/dist/buffer.d.ts +18 -0
  6. package/dist/buffer.d.ts.map +1 -0
  7. package/dist/buffer.js +58 -0
  8. package/dist/buffer.js.map +1 -0
  9. package/dist/client.d.ts +10 -0
  10. package/dist/client.d.ts.map +1 -0
  11. package/dist/client.js +43 -0
  12. package/dist/client.js.map +1 -0
  13. package/dist/collectors/console.d.ts +4 -0
  14. package/dist/collectors/console.d.ts.map +1 -0
  15. package/dist/collectors/console.js +45 -0
  16. package/dist/collectors/console.js.map +1 -0
  17. package/dist/collectors/errors.d.ts +7 -0
  18. package/dist/collectors/errors.d.ts.map +1 -0
  19. package/dist/collectors/errors.js +108 -0
  20. package/dist/collectors/errors.js.map +1 -0
  21. package/dist/collectors/network.d.ts +4 -0
  22. package/dist/collectors/network.d.ts.map +1 -0
  23. package/dist/collectors/network.js +50 -0
  24. package/dist/collectors/network.js.map +1 -0
  25. package/dist/collectors/performance.d.ts +3 -0
  26. package/dist/collectors/performance.d.ts.map +1 -0
  27. package/dist/collectors/performance.js +113 -0
  28. package/dist/collectors/performance.js.map +1 -0
  29. package/dist/context.d.ts +10 -0
  30. package/dist/context.d.ts.map +1 -0
  31. package/dist/context.js +35 -0
  32. package/dist/context.js.map +1 -0
  33. package/dist/device.d.ts +12 -0
  34. package/dist/device.d.ts.map +1 -0
  35. package/dist/device.js +85 -0
  36. package/dist/device.js.map +1 -0
  37. package/dist/fingerprint.d.ts +6 -0
  38. package/dist/fingerprint.d.ts.map +1 -0
  39. package/dist/fingerprint.js +48 -0
  40. package/dist/fingerprint.js.map +1 -0
  41. package/dist/index.d.ts +28 -0
  42. package/dist/index.d.ts.map +1 -0
  43. package/dist/index.js +156 -0
  44. package/dist/index.js.map +1 -0
  45. package/dist/react/ErrorBoundary.d.ts +21 -0
  46. package/dist/react/ErrorBoundary.d.ts.map +1 -0
  47. package/dist/react/ErrorBoundary.js +43 -0
  48. package/dist/react/ErrorBoundary.js.map +1 -0
  49. package/dist/types.d.ts +25 -0
  50. package/dist/types.d.ts.map +1 -0
  51. package/dist/types.js +3 -0
  52. package/dist/types.js.map +1 -0
  53. package/package.json +38 -0
@@ -0,0 +1,11 @@
1
+ import type { Breadcrumb } from '@logcaffe/shared';
2
+ export type { Breadcrumb } from '@logcaffe/shared';
3
+ export declare function setMaxBreadcrumbs(max: number): void;
4
+ export declare function addBreadcrumb(crumb: Breadcrumb): void;
5
+ export declare function getBreadcrumbs(): Breadcrumb[];
6
+ export declare function clearBreadcrumbs(): void;
7
+ export declare function startClickCapture(): void;
8
+ export declare function stopClickCapture(): void;
9
+ export declare function startNavigationCapture(): void;
10
+ export declare function stopNavigationCapture(): void;
11
+ //# sourceMappingURL=breadcrumbs.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.d.ts","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAEnD,YAAY,EAAE,UAAU,EAAE,MAAM,kBAAkB,CAAC;AAKnD,wBAAgB,iBAAiB,CAAC,GAAG,EAAE,MAAM,GAAG,IAAI,CAEnD;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,UAAU,GAAG,IAAI,CAKrD;AAED,wBAAgB,cAAc,IAAI,UAAU,EAAE,CAE7C;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAEvC;AAMD,wBAAgB,iBAAiB,IAAI,IAAI,CAIxC;AAED,wBAAgB,gBAAgB,IAAI,IAAI,CAIvC;AA6BD,wBAAgB,sBAAsB,IAAI,IAAI,CAyB7C;AAED,wBAAgB,qBAAqB,IAAI,IAAI,CAK5C"}
@@ -0,0 +1,96 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.setMaxBreadcrumbs = setMaxBreadcrumbs;
4
+ exports.addBreadcrumb = addBreadcrumb;
5
+ exports.getBreadcrumbs = getBreadcrumbs;
6
+ exports.clearBreadcrumbs = clearBreadcrumbs;
7
+ exports.startClickCapture = startClickCapture;
8
+ exports.stopClickCapture = stopClickCapture;
9
+ exports.startNavigationCapture = startNavigationCapture;
10
+ exports.stopNavigationCapture = stopNavigationCapture;
11
+ const breadcrumbs = [];
12
+ let maxBreadcrumbs = 20;
13
+ function setMaxBreadcrumbs(max) {
14
+ maxBreadcrumbs = max;
15
+ }
16
+ function addBreadcrumb(crumb) {
17
+ breadcrumbs.push(crumb);
18
+ if (breadcrumbs.length > maxBreadcrumbs) {
19
+ breadcrumbs.shift();
20
+ }
21
+ }
22
+ function getBreadcrumbs() {
23
+ return [...breadcrumbs];
24
+ }
25
+ function clearBreadcrumbs() {
26
+ breadcrumbs.length = 0;
27
+ }
28
+ // ─── Auto-capture: Click events ───
29
+ let clickListenerActive = false;
30
+ function startClickCapture() {
31
+ if (clickListenerActive)
32
+ return;
33
+ clickListenerActive = true;
34
+ document.addEventListener('click', onClickCapture, true);
35
+ }
36
+ function stopClickCapture() {
37
+ if (!clickListenerActive)
38
+ return;
39
+ clickListenerActive = false;
40
+ document.removeEventListener('click', onClickCapture, true);
41
+ }
42
+ function onClickCapture(e) {
43
+ const target = e.target;
44
+ if (!target)
45
+ return;
46
+ const tag = target.tagName?.toLowerCase();
47
+ const text = target.textContent?.trim().substring(0, 50);
48
+ const id = target.id ? `#${target.id}` : '';
49
+ const className = target.className && typeof target.className === 'string'
50
+ ? `.${target.className.split(' ')[0]}`
51
+ : '';
52
+ addBreadcrumb({
53
+ type: 'click',
54
+ category: 'ui.click',
55
+ message: `${tag}${id}${className}${text ? ` "${text}"` : ''}`,
56
+ timestamp: Date.now(),
57
+ data: { tag, id: target.id, className: target.className },
58
+ });
59
+ }
60
+ // ─── Auto-capture: Navigation (pushState / replaceState) ───
61
+ let navigationPatched = false;
62
+ const originalPushState = history.pushState;
63
+ const originalReplaceState = history.replaceState;
64
+ function startNavigationCapture() {
65
+ if (navigationPatched)
66
+ return;
67
+ navigationPatched = true;
68
+ history.pushState = function (...args) {
69
+ addBreadcrumb({
70
+ type: 'navigation',
71
+ category: 'navigation',
72
+ message: `${args[2] ?? ''}`,
73
+ timestamp: Date.now(),
74
+ data: { from: location.href, to: args[2] },
75
+ });
76
+ return originalPushState.apply(this, args);
77
+ };
78
+ history.replaceState = function (...args) {
79
+ addBreadcrumb({
80
+ type: 'navigation',
81
+ category: 'navigation.replace',
82
+ message: `${args[2] ?? ''}`,
83
+ timestamp: Date.now(),
84
+ data: { from: location.href, to: args[2] },
85
+ });
86
+ return originalReplaceState.apply(this, args);
87
+ };
88
+ }
89
+ function stopNavigationCapture() {
90
+ if (!navigationPatched)
91
+ return;
92
+ navigationPatched = false;
93
+ history.pushState = originalPushState;
94
+ history.replaceState = originalReplaceState;
95
+ }
96
+ //# sourceMappingURL=breadcrumbs.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"breadcrumbs.js","sourceRoot":"","sources":["../src/breadcrumbs.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,18 @@
1
+ import type { FrontendErrorEntry } from '@logcaffe/shared';
2
+ import type { BrowserHttpClient } from './client.js';
3
+ import type { BrowserConfig } from './types.js';
4
+ export declare class BrowserBuffer {
5
+ private items;
6
+ private client;
7
+ private timer;
8
+ private maxBatchSize;
9
+ private flushing;
10
+ private beforeSend?;
11
+ constructor(client: BrowserHttpClient, flushInterval: number, maxBatchSize: number, beforeSend?: BrowserConfig['beforeSend']);
12
+ add(entry: FrontendErrorEntry): void;
13
+ flush(): Promise<void>;
14
+ /** Use sendBeacon on page unload */
15
+ flushSync(): void;
16
+ shutdown(): void;
17
+ }
18
+ //# sourceMappingURL=buffer.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.d.ts","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,iBAAiB,EAAE,MAAM,aAAa,CAAC;AACrD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,YAAY,CAAC;AAEhD,qBAAa,aAAa;IACxB,OAAO,CAAC,KAAK,CAA4B;IACzC,OAAO,CAAC,MAAM,CAAoB;IAClC,OAAO,CAAC,KAAK,CAA+C;IAC5D,OAAO,CAAC,YAAY,CAAS;IAC7B,OAAO,CAAC,QAAQ,CAAS;IACzB,OAAO,CAAC,UAAU,CAAC,CAA8B;gBAG/C,MAAM,EAAE,iBAAiB,EACzB,aAAa,EAAE,MAAM,EACrB,YAAY,EAAE,MAAM,EACpB,UAAU,CAAC,EAAE,aAAa,CAAC,YAAY,CAAC;IAQ1C,GAAG,CAAC,KAAK,EAAE,kBAAkB,GAAG,IAAI;IAc9B,KAAK,IAAI,OAAO,CAAC,IAAI,CAAC;IAe5B,oCAAoC;IACpC,SAAS,IAAI,IAAI;IAMjB,QAAQ,IAAI,IAAI;CAOjB"}
package/dist/buffer.js ADDED
@@ -0,0 +1,58 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BrowserBuffer = void 0;
4
+ class BrowserBuffer {
5
+ items = [];
6
+ client;
7
+ timer = null;
8
+ maxBatchSize;
9
+ flushing = false;
10
+ beforeSend;
11
+ constructor(client, flushInterval, maxBatchSize, beforeSend) {
12
+ this.client = client;
13
+ this.maxBatchSize = maxBatchSize;
14
+ this.beforeSend = beforeSend;
15
+ this.timer = setInterval(() => this.flush(), flushInterval);
16
+ }
17
+ add(entry) {
18
+ // Apply beforeSend filter/transform
19
+ if (this.beforeSend) {
20
+ const result = this.beforeSend(entry);
21
+ if (!result)
22
+ return; // Drop this entry
23
+ entry = result;
24
+ }
25
+ this.items.push(entry);
26
+ if (this.items.length >= this.maxBatchSize) {
27
+ this.flush();
28
+ }
29
+ }
30
+ async flush() {
31
+ if (this.flushing || this.items.length === 0)
32
+ return;
33
+ this.flushing = true;
34
+ const batch = this.items.splice(0, this.maxBatchSize);
35
+ const success = await this.client.sendBatch(batch);
36
+ if (!success) {
37
+ // One retry
38
+ await this.client.sendBatch(batch);
39
+ }
40
+ this.flushing = false;
41
+ }
42
+ /** Use sendBeacon on page unload */
43
+ flushSync() {
44
+ if (this.items.length === 0)
45
+ return;
46
+ const batch = this.items.splice(0, this.maxBatchSize);
47
+ this.client.sendBeacon(batch);
48
+ }
49
+ shutdown() {
50
+ if (this.timer) {
51
+ clearInterval(this.timer);
52
+ this.timer = null;
53
+ }
54
+ this.flushSync();
55
+ }
56
+ }
57
+ exports.BrowserBuffer = BrowserBuffer;
58
+ //# sourceMappingURL=buffer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"buffer.js","sourceRoot":"","sources":["../src/buffer.ts"],"names":[],"mappings":";;;AAIA,MAAa,aAAa;IAChB,KAAK,GAAyB,EAAE,CAAC;IACjC,MAAM,CAAoB;IAC1B,KAAK,GAA0C,IAAI,CAAC;IACpD,YAAY,CAAS;IACrB,QAAQ,GAAG,KAAK,CAAC;IACjB,UAAU,CAA+B;IAEjD,YACE,MAAyB,EACzB,aAAqB,EACrB,YAAoB,EACpB,UAAwC;QAExC,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;QACrB,IAAI,CAAC,YAAY,GAAG,YAAY,CAAC;QACjC,IAAI,CAAC,UAAU,GAAG,UAAU,CAAC;QAC7B,IAAI,CAAC,KAAK,GAAG,WAAW,CAAC,GAAG,EAAE,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,aAAa,CAAC,CAAC;IAC9D,CAAC;IAED,GAAG,CAAC,KAAyB;QAC3B,oCAAoC;QACpC,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;YACpB,MAAM,MAAM,GAAG,IAAI,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;YACtC,IAAI,CAAC,MAAM;gBAAE,OAAO,CAAC,kBAAkB;YACvC,KAAK,GAAG,MAAM,CAAC;QACjB,CAAC;QAED,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QACvB,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;YAC3C,IAAI,CAAC,KAAK,EAAE,CAAC;QACf,CAAC;IACH,CAAC;IAED,KAAK,CAAC,KAAK;QACT,IAAI,IAAI,CAAC,QAAQ,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACrD,IAAI,CAAC,QAAQ,GAAG,IAAI,CAAC;QAErB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACtD,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QAEnD,IAAI,CAAC,OAAO,EAAE,CAAC;YACb,YAAY;YACZ,MAAM,IAAI,CAAC,MAAM,CAAC,SAAS,CAAC,KAAK,CAAC,CAAC;QACrC,CAAC;QAED,IAAI,CAAC,QAAQ,GAAG,KAAK,CAAC;IACxB,CAAC;IAED,oCAAoC;IACpC,SAAS;QACP,IAAI,IAAI,CAAC,KAAK,CAAC,MAAM,KAAK,CAAC;YAAE,OAAO;QACpC,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,EAAE,IAAI,CAAC,YAAY,CAAC,CAAC;QACtD,IAAI,CAAC,MAAM,CAAC,UAAU,CAAC,KAAK,CAAC,CAAC;IAChC,CAAC;IAED,QAAQ;QACN,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;YACf,aAAa,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC1B,IAAI,CAAC,KAAK,GAAG,IAAI,CAAC;QACpB,CAAC;QACD,IAAI,CAAC,SAAS,EAAE,CAAC;IACnB,CAAC;CACF;AA/DD,sCA+DC"}
@@ -0,0 +1,10 @@
1
+ import type { FrontendErrorEntry } from '@logcaffe/shared';
2
+ export declare class BrowserHttpClient {
3
+ private serverUrl;
4
+ private apiKey;
5
+ constructor(serverUrl: string, apiKey: string);
6
+ sendBatch(frontendErrors: FrontendErrorEntry[]): Promise<boolean>;
7
+ /** Use sendBeacon for page unload — fire and forget */
8
+ sendBeacon(frontendErrors: FrontendErrorEntry[]): boolean;
9
+ }
10
+ //# sourceMappingURL=client.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.d.ts","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAE3D,qBAAa,iBAAiB;IAC5B,OAAO,CAAC,SAAS,CAAS;IAC1B,OAAO,CAAC,MAAM,CAAS;gBAEX,SAAS,EAAE,MAAM,EAAE,MAAM,EAAE,MAAM;IAKvC,SAAS,CAAC,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO,CAAC,OAAO,CAAC;IAqBvE,uDAAuD;IACvD,UAAU,CAAC,cAAc,EAAE,kBAAkB,EAAE,GAAG,OAAO;CAS1D"}
package/dist/client.js ADDED
@@ -0,0 +1,43 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.BrowserHttpClient = void 0;
4
+ class BrowserHttpClient {
5
+ serverUrl;
6
+ apiKey;
7
+ constructor(serverUrl, apiKey) {
8
+ this.serverUrl = serverUrl.replace(/\/$/, '');
9
+ this.apiKey = apiKey;
10
+ }
11
+ async sendBatch(frontendErrors) {
12
+ try {
13
+ const url = `${this.serverUrl}/api/ingest/batch`;
14
+ const body = JSON.stringify({ frontendErrors });
15
+ const response = await fetch(url, {
16
+ method: 'POST',
17
+ headers: {
18
+ 'Content-Type': 'application/json',
19
+ 'x-api-key': this.apiKey,
20
+ },
21
+ body,
22
+ keepalive: true, // Allow request to complete even if page is unloading
23
+ });
24
+ return response.ok;
25
+ }
26
+ catch {
27
+ return false;
28
+ }
29
+ }
30
+ /** Use sendBeacon for page unload — fire and forget */
31
+ sendBeacon(frontendErrors) {
32
+ try {
33
+ const url = `${this.serverUrl}/api/ingest/batch?apiKey=${this.apiKey}`;
34
+ const body = JSON.stringify({ frontendErrors });
35
+ return navigator.sendBeacon(url, body);
36
+ }
37
+ catch {
38
+ return false;
39
+ }
40
+ }
41
+ }
42
+ exports.BrowserHttpClient = BrowserHttpClient;
43
+ //# sourceMappingURL=client.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"client.js","sourceRoot":"","sources":["../src/client.ts"],"names":[],"mappings":";;;AAEA,MAAa,iBAAiB;IACpB,SAAS,CAAS;IAClB,MAAM,CAAS;IAEvB,YAAY,SAAiB,EAAE,MAAc;QAC3C,IAAI,CAAC,SAAS,GAAG,SAAS,CAAC,OAAO,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC;QAC9C,IAAI,CAAC,MAAM,GAAG,MAAM,CAAC;IACvB,CAAC;IAED,KAAK,CAAC,SAAS,CAAC,cAAoC;QAClD,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,mBAAmB,CAAC;YACjD,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;YAEhD,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,GAAG,EAAE;gBAChC,MAAM,EAAE,MAAM;gBACd,OAAO,EAAE;oBACP,cAAc,EAAE,kBAAkB;oBAClC,WAAW,EAAE,IAAI,CAAC,MAAM;iBACzB;gBACD,IAAI;gBACJ,SAAS,EAAE,IAAI,EAAE,sDAAsD;aACxE,CAAC,CAAC;YAEH,OAAO,QAAQ,CAAC,EAAE,CAAC;QACrB,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;IAED,uDAAuD;IACvD,UAAU,CAAC,cAAoC;QAC7C,IAAI,CAAC;YACH,MAAM,GAAG,GAAG,GAAG,IAAI,CAAC,SAAS,4BAA4B,IAAI,CAAC,MAAM,EAAE,CAAC;YACvE,MAAM,IAAI,GAAG,IAAI,CAAC,SAAS,CAAC,EAAE,cAAc,EAAE,CAAC,CAAC;YAChD,OAAO,SAAS,CAAC,UAAU,CAAC,GAAG,EAAE,IAAI,CAAC,CAAC;QACzC,CAAC;QAAC,MAAM,CAAC;YACP,OAAO,KAAK,CAAC;QACf,CAAC;IACH,CAAC;CACF;AAxCD,8CAwCC"}
@@ -0,0 +1,4 @@
1
+ import type { BrowserBuffer } from '../buffer.js';
2
+ export declare function interceptConsole(buffer: BrowserBuffer): void;
3
+ export declare function restoreConsole(): void;
4
+ //# sourceMappingURL=console.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.d.ts","sourceRoot":"","sources":["../../src/collectors/console.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AASlD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAgC5D;AAED,wBAAgB,cAAc,IAAI,IAAI,CAKrC"}
@@ -0,0 +1,45 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interceptConsole = interceptConsole;
4
+ exports.restoreConsole = restoreConsole;
5
+ const originalConsole = {
6
+ error: console.error,
7
+ warn: console.warn,
8
+ };
9
+ let intercepted = false;
10
+ function interceptConsole(buffer) {
11
+ if (intercepted)
12
+ return;
13
+ intercepted = true;
14
+ console.error = (...args) => {
15
+ originalConsole.error.apply(console, args);
16
+ const message = args
17
+ .map((a) => (typeof a === 'string' ? a : JSON.stringify(a)))
18
+ .join(' ');
19
+ buffer.add({
20
+ message: `[console.error] ${message}`.substring(0, 10000),
21
+ stack: args[0] instanceof Error ? args[0].stack : undefined,
22
+ url: window.location.href,
23
+ userAgent: navigator.userAgent,
24
+ });
25
+ };
26
+ console.warn = (...args) => {
27
+ originalConsole.warn.apply(console, args);
28
+ const message = args
29
+ .map((a) => (typeof a === 'string' ? a : JSON.stringify(a)))
30
+ .join(' ');
31
+ buffer.add({
32
+ message: `[console.warn] ${message}`.substring(0, 10000),
33
+ url: window.location.href,
34
+ userAgent: navigator.userAgent,
35
+ });
36
+ };
37
+ }
38
+ function restoreConsole() {
39
+ if (!intercepted)
40
+ return;
41
+ intercepted = false;
42
+ console.error = originalConsole.error;
43
+ console.warn = originalConsole.warn;
44
+ }
45
+ //# sourceMappingURL=console.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"console.js","sourceRoot":"","sources":["../../src/collectors/console.ts"],"names":[],"mappings":";;AASA,4CAgCC;AAED,wCAKC;AA9CD,MAAM,eAAe,GAAG;IACtB,KAAK,EAAE,OAAO,CAAC,KAAK;IACpB,IAAI,EAAE,OAAO,CAAC,IAAI;CACnB,CAAC;AAEF,IAAI,WAAW,GAAG,KAAK,CAAC;AAExB,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,IAAI,WAAW;QAAE,OAAO;IACxB,WAAW,GAAG,IAAI,CAAC;IAEnB,OAAO,CAAC,KAAK,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;QACrC,eAAe,CAAC,KAAK,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAE3C,MAAM,OAAO,GAAG,IAAI;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3D,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,MAAM,CAAC,GAAG,CAAC;YACT,OAAO,EAAE,mBAAmB,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC;YACzD,KAAK,EAAE,IAAI,CAAC,CAAC,CAAC,YAAY,KAAK,CAAC,CAAC,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,SAAS;YAC3D,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;YACzB,SAAS,EAAE,SAAS,CAAC,SAAS;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC;IAEF,OAAO,CAAC,IAAI,GAAG,CAAC,GAAG,IAAe,EAAE,EAAE;QACpC,eAAe,CAAC,IAAI,CAAC,KAAK,CAAC,OAAO,EAAE,IAAI,CAAC,CAAC;QAE1C,MAAM,OAAO,GAAG,IAAI;aACjB,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,OAAO,CAAC,KAAK,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,CAAC,CAAC;aAC3D,IAAI,CAAC,GAAG,CAAC,CAAC;QAEb,MAAM,CAAC,GAAG,CAAC;YACT,OAAO,EAAE,kBAAkB,OAAO,EAAE,CAAC,SAAS,CAAC,CAAC,EAAE,KAAK,CAAC;YACxD,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;YACzB,SAAS,EAAE,SAAS,CAAC,SAAS;SAC/B,CAAC,CAAC;IACL,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc;IAC5B,IAAI,CAAC,WAAW;QAAE,OAAO;IACzB,WAAW,GAAG,KAAK,CAAC;IACpB,OAAO,CAAC,KAAK,GAAG,eAAe,CAAC,KAAK,CAAC;IACtC,OAAO,CAAC,IAAI,GAAG,eAAe,CAAC,IAAI,CAAC;AACtC,CAAC"}
@@ -0,0 +1,7 @@
1
+ import type { FrontendErrorEntry } from '@logcaffe/shared';
2
+ import type { BrowserBuffer } from '../buffer.js';
3
+ import type { BrowserConfig } from '../types.js';
4
+ export declare function enrichEntry(entry: FrontendErrorEntry, config: BrowserConfig): FrontendErrorEntry;
5
+ export declare function setupErrorCapture(buffer: BrowserBuffer, config: BrowserConfig): void;
6
+ export declare function removeErrorCapture(): void;
7
+ //# sourceMappingURL=errors.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.d.ts","sourceRoot":"","sources":["../../src/collectors/errors.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,kBAAkB,CAAC;AAC3D,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAClD,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,aAAa,CAAC;AAsBjD,wBAAgB,WAAW,CACzB,KAAK,EAAE,kBAAkB,EACzB,MAAM,EAAE,aAAa,GACpB,kBAAkB,CAyBpB;AAKD,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,aAAa,EAAE,MAAM,EAAE,aAAa,GAAG,IAAI,CAyDpF;AAED,wBAAgB,kBAAkB,IAAI,IAAI,CAQzC"}
@@ -0,0 +1,108 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.enrichEntry = enrichEntry;
4
+ exports.setupErrorCapture = setupErrorCapture;
5
+ exports.removeErrorCapture = removeErrorCapture;
6
+ const context_js_1 = require("../context.js");
7
+ const device_js_1 = require("../device.js");
8
+ const breadcrumbs_js_1 = require("../breadcrumbs.js");
9
+ const fingerprint_js_1 = require("../fingerprint.js");
10
+ function shouldIgnore(message, config) {
11
+ if (!config.ignoreErrors)
12
+ return false;
13
+ return config.ignoreErrors.some((pattern) => {
14
+ if (typeof pattern === 'string')
15
+ return message.includes(pattern);
16
+ return pattern.test(message);
17
+ });
18
+ }
19
+ function shouldIgnoreUrl(url, config) {
20
+ if (!config.ignoreUrls)
21
+ return false;
22
+ return config.ignoreUrls.some((pattern) => {
23
+ if (typeof pattern === 'string')
24
+ return url.includes(pattern);
25
+ return pattern.test(url);
26
+ });
27
+ }
28
+ function enrichEntry(entry, config) {
29
+ const user = (0, context_js_1.getUser)();
30
+ const device = (0, device_js_1.getDeviceInfo)();
31
+ entry.userId = user?.id;
32
+ entry.sessionId = (0, context_js_1.getSessionId)();
33
+ entry.browserName = device.browserName;
34
+ entry.browserVersion = device.browserVersion;
35
+ entry.osName = device.osName;
36
+ entry.screenSize = device.screenSize;
37
+ entry.connectionType = device.connectionType;
38
+ entry.fingerprint = (0, fingerprint_js_1.generateBrowserFingerprint)(entry.message, entry.stack);
39
+ entry.breadcrumbs = (0, breadcrumbs_js_1.getBreadcrumbs)();
40
+ entry.release = config.release;
41
+ entry.environment = config.environment;
42
+ entry.tags = config.defaultTags;
43
+ if (!entry.meta)
44
+ entry.meta = {};
45
+ entry.meta.language = device.language;
46
+ entry.meta.deviceType = device.deviceType;
47
+ entry.meta.referrer = document.referrer;
48
+ entry.meta.pageTitle = document.title;
49
+ entry.meta.timestamp = Date.now();
50
+ return entry;
51
+ }
52
+ let prevOnError = null;
53
+ let rejectionHandler = null;
54
+ function setupErrorCapture(buffer, config) {
55
+ // window.onerror — catches runtime JS errors
56
+ if (config.captureErrors !== false) {
57
+ prevOnError = window.onerror;
58
+ window.onerror = (message, source, lineno, colno, error) => {
59
+ const msg = String(message);
60
+ if (shouldIgnore(msg, config))
61
+ return;
62
+ if (source && shouldIgnoreUrl(String(source), config))
63
+ return;
64
+ const entry = enrichEntry({
65
+ message: msg,
66
+ stack: error?.stack,
67
+ url: window.location.href,
68
+ userAgent: navigator.userAgent,
69
+ meta: { source, lineno, colno },
70
+ }, config);
71
+ buffer.add(entry);
72
+ // Call previous handler if any
73
+ if (typeof prevOnError === 'function') {
74
+ prevOnError(message, source, lineno, colno, error);
75
+ }
76
+ };
77
+ }
78
+ // unhandledrejection — catches unhandled promise rejections
79
+ if (config.captureRejections !== false) {
80
+ rejectionHandler = (event) => {
81
+ const reason = event.reason;
82
+ const msg = reason instanceof Error
83
+ ? reason.message
84
+ : typeof reason === 'string'
85
+ ? reason
86
+ : JSON.stringify(reason);
87
+ if (shouldIgnore(msg, config))
88
+ return;
89
+ const entry = enrichEntry({
90
+ message: `Unhandled Rejection: ${msg}`,
91
+ stack: reason instanceof Error ? reason.stack : undefined,
92
+ url: window.location.href,
93
+ userAgent: navigator.userAgent,
94
+ }, config);
95
+ buffer.add(entry);
96
+ };
97
+ window.addEventListener('unhandledrejection', rejectionHandler);
98
+ }
99
+ }
100
+ function removeErrorCapture() {
101
+ window.onerror = prevOnError;
102
+ prevOnError = null;
103
+ if (rejectionHandler) {
104
+ window.removeEventListener('unhandledrejection', rejectionHandler);
105
+ rejectionHandler = null;
106
+ }
107
+ }
108
+ //# sourceMappingURL=errors.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"errors.js","sourceRoot":"","sources":["../../src/collectors/errors.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ import type { BrowserBuffer } from '../buffer.js';
2
+ export declare function interceptNetwork(buffer: BrowserBuffer): void;
3
+ export declare function restoreNetwork(): void;
4
+ //# sourceMappingURL=network.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.d.ts","sourceRoot":"","sources":["../../src/collectors/network.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAIlD,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAwC5D;AAED,wBAAgB,cAAc,IAAI,IAAI,CAKrC"}
@@ -0,0 +1,50 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.interceptNetwork = interceptNetwork;
4
+ exports.restoreNetwork = restoreNetwork;
5
+ let originalFetch = null;
6
+ function interceptNetwork(buffer) {
7
+ if (originalFetch)
8
+ return; // Already intercepted
9
+ originalFetch = window.fetch;
10
+ window.fetch = async (input, init) => {
11
+ const url = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url;
12
+ try {
13
+ const response = await originalFetch(input, init);
14
+ if (response.status >= 500) {
15
+ buffer.add({
16
+ message: `API Error: ${response.status} ${url}`,
17
+ url: window.location.href,
18
+ userAgent: navigator.userAgent,
19
+ meta: {
20
+ type: 'network',
21
+ endpoint: url,
22
+ status: response.status,
23
+ method: init?.method || 'GET',
24
+ },
25
+ });
26
+ }
27
+ return response;
28
+ }
29
+ catch (err) {
30
+ buffer.add({
31
+ message: `Network Error: ${err instanceof Error ? err.message : String(err)}`,
32
+ url: window.location.href,
33
+ userAgent: navigator.userAgent,
34
+ meta: {
35
+ type: 'network',
36
+ endpoint: url,
37
+ method: init?.method || 'GET',
38
+ },
39
+ });
40
+ throw err;
41
+ }
42
+ };
43
+ }
44
+ function restoreNetwork() {
45
+ if (originalFetch) {
46
+ window.fetch = originalFetch;
47
+ originalFetch = null;
48
+ }
49
+ }
50
+ //# sourceMappingURL=network.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"network.js","sourceRoot":"","sources":["../../src/collectors/network.ts"],"names":[],"mappings":";;AAIA,4CAwCC;AAED,wCAKC;AAjDD,IAAI,aAAa,GAA+B,IAAI,CAAC;AAErD,SAAgB,gBAAgB,CAAC,MAAqB;IACpD,IAAI,aAAa;QAAE,OAAO,CAAC,sBAAsB;IAEjD,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;IAE7B,MAAM,CAAC,KAAK,GAAG,KAAK,EAAE,KAAwB,EAAE,IAAkB,EAAqB,EAAE;QACvF,MAAM,GAAG,GAAG,OAAO,KAAK,KAAK,QAAQ,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,YAAY,GAAG,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC,KAAK,CAAC,GAAG,CAAC;QAE9F,IAAI,CAAC;YACH,MAAM,QAAQ,GAAG,MAAM,aAAc,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;YAEnD,IAAI,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE,CAAC;gBAC3B,MAAM,CAAC,GAAG,CAAC;oBACT,OAAO,EAAE,cAAc,QAAQ,CAAC,MAAM,IAAI,GAAG,EAAE;oBAC/C,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;oBACzB,SAAS,EAAE,SAAS,CAAC,SAAS;oBAC9B,IAAI,EAAE;wBACJ,IAAI,EAAE,SAAS;wBACf,QAAQ,EAAE,GAAG;wBACb,MAAM,EAAE,QAAQ,CAAC,MAAM;wBACvB,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK;qBAC9B;iBACF,CAAC,CAAC;YACL,CAAC;YAED,OAAO,QAAQ,CAAC;QAClB,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACb,MAAM,CAAC,GAAG,CAAC;gBACT,OAAO,EAAE,kBAAkB,GAAG,YAAY,KAAK,CAAC,CAAC,CAAC,GAAG,CAAC,OAAO,CAAC,CAAC,CAAC,MAAM,CAAC,GAAG,CAAC,EAAE;gBAC7E,GAAG,EAAE,MAAM,CAAC,QAAQ,CAAC,IAAI;gBACzB,SAAS,EAAE,SAAS,CAAC,SAAS;gBAC9B,IAAI,EAAE;oBACJ,IAAI,EAAE,SAAS;oBACf,QAAQ,EAAE,GAAG;oBACb,MAAM,EAAE,IAAI,EAAE,MAAM,IAAI,KAAK;iBAC9B;aACF,CAAC,CAAC;YACH,MAAM,GAAG,CAAC;QACZ,CAAC;IACH,CAAC,CAAC;AACJ,CAAC;AAED,SAAgB,cAAc;IAC5B,IAAI,aAAa,EAAE,CAAC;QAClB,MAAM,CAAC,KAAK,GAAG,aAAa,CAAC;QAC7B,aAAa,GAAG,IAAI,CAAC;IACvB,CAAC;AACH,CAAC"}
@@ -0,0 +1,3 @@
1
+ import type { BrowserBuffer } from '../buffer.js';
2
+ export declare function collectPerformanceMetrics(buffer: BrowserBuffer): void;
3
+ //# sourceMappingURL=performance.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"performance.d.ts","sourceRoot":"","sources":["../../src/collectors/performance.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,cAAc,CAAC;AAElD,wBAAgB,yBAAyB,CAAC,MAAM,EAAE,aAAa,GAAG,IAAI,CAarE"}
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.collectPerformanceMetrics = collectPerformanceMetrics;
4
+ function collectPerformanceMetrics(buffer) {
5
+ // Wait for page to fully load before collecting navigation timing
6
+ if (document.readyState === 'complete') {
7
+ sendNavigationMetrics(buffer);
8
+ }
9
+ else {
10
+ window.addEventListener('load', () => {
11
+ // Small delay to ensure loadEventEnd is populated
12
+ setTimeout(() => sendNavigationMetrics(buffer), 100);
13
+ });
14
+ }
15
+ // Observe Web Vitals via PerformanceObserver
16
+ observeWebVitals(buffer);
17
+ }
18
+ function sendNavigationMetrics(buffer) {
19
+ try {
20
+ const entries = performance.getEntriesByType('navigation');
21
+ if (entries.length === 0)
22
+ return;
23
+ const nav = entries[0];
24
+ buffer.add({
25
+ message: 'Page Load Metrics',
26
+ url: window.location.href,
27
+ userAgent: navigator.userAgent,
28
+ meta: {
29
+ type: 'performance',
30
+ pageLoadTime: Math.round(nav.loadEventEnd - nav.startTime),
31
+ domContentLoaded: Math.round(nav.domContentLoadedEventEnd - nav.startTime),
32
+ ttfb: Math.round(nav.responseStart - nav.requestStart),
33
+ dnsLookup: Math.round(nav.domainLookupEnd - nav.domainLookupStart),
34
+ tlsHandshake: Math.round(nav.connectEnd - nav.secureConnectionStart),
35
+ downloadTime: Math.round(nav.responseEnd - nav.responseStart),
36
+ domInteractive: Math.round(nav.domInteractive - nav.startTime),
37
+ },
38
+ });
39
+ }
40
+ catch {
41
+ // Performance API not available
42
+ }
43
+ }
44
+ function observeWebVitals(buffer) {
45
+ if (typeof PerformanceObserver === 'undefined')
46
+ return;
47
+ // LCP — Largest Contentful Paint
48
+ try {
49
+ const lcpObserver = new PerformanceObserver((list) => {
50
+ const entries = list.getEntries();
51
+ const last = entries[entries.length - 1];
52
+ if (last) {
53
+ buffer.add({
54
+ message: 'Web Vital: LCP',
55
+ url: window.location.href,
56
+ userAgent: navigator.userAgent,
57
+ meta: { type: 'web-vital', metric: 'LCP', value: Math.round(last.startTime) },
58
+ });
59
+ }
60
+ });
61
+ lcpObserver.observe({ type: 'largest-contentful-paint', buffered: true });
62
+ }
63
+ catch {
64
+ // Not supported
65
+ }
66
+ // FID — First Input Delay
67
+ try {
68
+ const fidObserver = new PerformanceObserver((list) => {
69
+ const entries = list.getEntries();
70
+ const first = entries[0];
71
+ if (first) {
72
+ const fid = first.processingStart - first.startTime;
73
+ buffer.add({
74
+ message: 'Web Vital: FID',
75
+ url: window.location.href,
76
+ userAgent: navigator.userAgent,
77
+ meta: { type: 'web-vital', metric: 'FID', value: Math.round(fid) },
78
+ });
79
+ }
80
+ });
81
+ fidObserver.observe({ type: 'first-input', buffered: true });
82
+ }
83
+ catch {
84
+ // Not supported
85
+ }
86
+ // CLS — Cumulative Layout Shift
87
+ try {
88
+ let clsValue = 0;
89
+ const clsObserver = new PerformanceObserver((list) => {
90
+ for (const entry of list.getEntries()) {
91
+ if (!entry.hadRecentInput) {
92
+ clsValue += entry.value;
93
+ }
94
+ }
95
+ });
96
+ clsObserver.observe({ type: 'layout-shift', buffered: true });
97
+ // Report CLS when page is hidden (most accurate time)
98
+ document.addEventListener('visibilitychange', () => {
99
+ if (document.visibilityState === 'hidden' && clsValue > 0) {
100
+ buffer.add({
101
+ message: 'Web Vital: CLS',
102
+ url: window.location.href,
103
+ userAgent: navigator.userAgent,
104
+ meta: { type: 'web-vital', metric: 'CLS', value: Math.round(clsValue * 1000) / 1000 },
105
+ });
106
+ }
107
+ }, { once: true });
108
+ }
109
+ catch {
110
+ // Not supported
111
+ }
112
+ }
113
+ //# sourceMappingURL=performance.js.map