@tracelog/lib 0.1.0 → 0.2.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.
- package/README.md +58 -24
- package/dist/browser/tracelog.js +1928 -3297
- package/dist/cjs/api.d.ts +33 -19
- package/dist/cjs/api.js +111 -156
- package/dist/cjs/app.constants.d.ts +74 -1
- package/dist/cjs/app.constants.js +77 -3
- package/dist/cjs/app.d.ts +29 -44
- package/dist/cjs/app.js +114 -212
- package/dist/cjs/app.types.d.ts +2 -7
- package/dist/cjs/app.types.js +10 -21
- package/dist/cjs/constants/api.constants.js +11 -5
- package/dist/cjs/constants/config.constants.d.ts +75 -0
- package/dist/cjs/constants/config.constants.js +178 -0
- package/dist/cjs/constants/error.constants.d.ts +29 -0
- package/dist/cjs/constants/error.constants.js +50 -0
- package/dist/cjs/constants/index.d.ts +3 -6
- package/dist/cjs/constants/index.js +3 -6
- package/dist/cjs/constants/performance.constants.d.ts +28 -0
- package/dist/cjs/constants/performance.constants.js +43 -0
- package/dist/cjs/handlers/click.handler.d.ts +1 -0
- package/dist/cjs/handlers/click.handler.js +30 -49
- package/dist/cjs/handlers/error.handler.d.ts +11 -6
- package/dist/cjs/handlers/error.handler.js +91 -51
- package/dist/cjs/handlers/page-view.handler.js +38 -29
- package/dist/cjs/handlers/performance.handler.d.ts +3 -0
- package/dist/cjs/handlers/performance.handler.js +76 -37
- package/dist/cjs/handlers/scroll.handler.d.ts +16 -10
- package/dist/cjs/handlers/scroll.handler.js +119 -185
- package/dist/cjs/handlers/session.handler.d.ts +6 -20
- package/dist/cjs/handlers/session.handler.js +38 -326
- package/dist/cjs/integrations/google-analytics.integration.d.ts +0 -1
- package/dist/cjs/integrations/google-analytics.integration.js +27 -98
- package/dist/cjs/listeners/input-listener-managers.d.ts +18 -9
- package/dist/cjs/listeners/input-listener-managers.js +24 -33
- package/dist/cjs/listeners/touch-listener-manager.d.ts +1 -3
- package/dist/cjs/listeners/touch-listener-manager.js +1 -23
- package/dist/cjs/listeners/visibility-listener-manager.d.ts +1 -4
- package/dist/cjs/listeners/visibility-listener-manager.js +6 -42
- package/dist/cjs/managers/api.manager.d.ts +13 -3
- package/dist/cjs/managers/api.manager.js +35 -5
- package/dist/cjs/managers/config.manager.d.ts +53 -3
- package/dist/cjs/managers/config.manager.js +131 -62
- package/dist/cjs/managers/event.manager.d.ts +57 -36
- package/dist/cjs/managers/event.manager.js +266 -417
- package/dist/cjs/managers/sender.manager.d.ts +40 -22
- package/dist/cjs/managers/sender.manager.js +200 -198
- package/dist/cjs/managers/session.manager.d.ts +80 -66
- package/dist/cjs/managers/session.manager.js +267 -522
- package/dist/cjs/managers/state.manager.d.ts +33 -0
- package/dist/cjs/managers/state.manager.js +79 -6
- package/dist/cjs/managers/storage.manager.d.ts +26 -2
- package/dist/cjs/managers/storage.manager.js +67 -34
- package/dist/cjs/managers/tags.manager.d.ts +31 -7
- package/dist/cjs/managers/tags.manager.js +123 -241
- package/dist/cjs/managers/user.manager.d.ts +14 -5
- package/dist/cjs/managers/user.manager.js +17 -9
- package/dist/cjs/public-api.d.ts +10 -1
- package/dist/cjs/public-api.js +18 -24
- package/dist/cjs/test-bridge.d.ts +48 -0
- package/dist/cjs/test-bridge.js +110 -0
- package/dist/cjs/types/api.types.d.ts +21 -6
- package/dist/cjs/types/api.types.js +21 -6
- package/dist/cjs/types/config.types.d.ts +22 -84
- package/dist/cjs/types/emitter.types.d.ts +11 -0
- package/dist/cjs/types/emitter.types.js +8 -0
- package/dist/cjs/types/event.types.d.ts +8 -11
- package/dist/cjs/types/index.d.ts +3 -1
- package/dist/cjs/types/index.js +3 -1
- package/dist/cjs/types/queue.types.d.ts +1 -0
- package/dist/cjs/types/session.types.d.ts +0 -64
- package/dist/cjs/types/state.types.d.ts +1 -0
- package/dist/cjs/types/test-bridge.types.d.ts +38 -0
- package/dist/cjs/types/validation-error.types.d.ts +7 -0
- package/dist/cjs/types/validation-error.types.js +11 -1
- package/dist/cjs/types/window.types.d.ts +1 -8
- package/dist/cjs/utils/data/uuid.utils.d.ts +1 -1
- package/dist/cjs/utils/data/uuid.utils.js +7 -5
- package/dist/cjs/utils/emitter.utils.d.ts +8 -0
- package/dist/cjs/utils/emitter.utils.js +33 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/logging/debug-logger.utils.d.ts +10 -51
- package/dist/cjs/utils/logging/debug-logger.utils.js +36 -127
- package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +4 -0
- package/dist/cjs/utils/network/fetch-with-timeout.utils.js +25 -0
- package/dist/cjs/utils/network/index.d.ts +1 -0
- package/dist/cjs/utils/network/index.js +1 -0
- package/dist/cjs/utils/network/url.utils.js +2 -42
- package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -8
- package/dist/cjs/utils/security/sanitize.utils.js +7 -41
- package/dist/cjs/utils/validations/config-validations.utils.d.ts +7 -0
- package/dist/cjs/utils/validations/config-validations.utils.js +77 -22
- package/dist/esm/api.d.ts +33 -19
- package/dist/esm/api.js +105 -118
- package/dist/esm/app.constants.d.ts +74 -1
- package/dist/esm/app.constants.js +76 -1
- package/dist/esm/app.d.ts +29 -44
- package/dist/esm/app.js +115 -213
- package/dist/esm/app.types.d.ts +2 -7
- package/dist/esm/app.types.js +1 -7
- package/dist/esm/constants/api.constants.js +10 -4
- package/dist/esm/constants/config.constants.d.ts +75 -0
- package/dist/esm/constants/config.constants.js +174 -0
- package/dist/esm/constants/error.constants.d.ts +29 -0
- package/dist/esm/constants/error.constants.js +47 -0
- package/dist/esm/constants/index.d.ts +3 -6
- package/dist/esm/constants/index.js +3 -6
- package/dist/esm/constants/performance.constants.d.ts +28 -0
- package/dist/esm/constants/performance.constants.js +40 -0
- package/dist/esm/handlers/click.handler.d.ts +1 -0
- package/dist/esm/handlers/click.handler.js +30 -49
- package/dist/esm/handlers/error.handler.d.ts +11 -6
- package/dist/esm/handlers/error.handler.js +91 -51
- package/dist/esm/handlers/page-view.handler.js +38 -29
- package/dist/esm/handlers/performance.handler.d.ts +3 -0
- package/dist/esm/handlers/performance.handler.js +71 -32
- package/dist/esm/handlers/scroll.handler.d.ts +16 -10
- package/dist/esm/handlers/scroll.handler.js +120 -186
- package/dist/esm/handlers/session.handler.d.ts +6 -20
- package/dist/esm/handlers/session.handler.js +38 -326
- package/dist/esm/integrations/google-analytics.integration.d.ts +0 -1
- package/dist/esm/integrations/google-analytics.integration.js +27 -98
- package/dist/esm/listeners/input-listener-managers.d.ts +18 -9
- package/dist/esm/listeners/input-listener-managers.js +23 -32
- package/dist/esm/listeners/touch-listener-manager.d.ts +1 -3
- package/dist/esm/listeners/touch-listener-manager.js +1 -23
- package/dist/esm/listeners/visibility-listener-manager.d.ts +1 -4
- package/dist/esm/listeners/visibility-listener-manager.js +6 -42
- package/dist/esm/managers/api.manager.d.ts +13 -3
- package/dist/esm/managers/api.manager.js +34 -3
- package/dist/esm/managers/config.manager.d.ts +53 -3
- package/dist/esm/managers/config.manager.js +133 -64
- package/dist/esm/managers/event.manager.d.ts +57 -36
- package/dist/esm/managers/event.manager.js +268 -419
- package/dist/esm/managers/sender.manager.d.ts +40 -22
- package/dist/esm/managers/sender.manager.js +201 -199
- package/dist/esm/managers/session.manager.d.ts +80 -66
- package/dist/esm/managers/session.manager.js +269 -524
- package/dist/esm/managers/state.manager.d.ts +33 -0
- package/dist/esm/managers/state.manager.js +78 -6
- package/dist/esm/managers/storage.manager.d.ts +26 -2
- package/dist/esm/managers/storage.manager.js +66 -33
- package/dist/esm/managers/tags.manager.d.ts +31 -7
- package/dist/esm/managers/tags.manager.js +124 -242
- package/dist/esm/managers/user.manager.d.ts +14 -5
- package/dist/esm/managers/user.manager.js +17 -9
- package/dist/esm/public-api.d.ts +10 -1
- package/dist/esm/public-api.js +14 -1
- package/dist/esm/test-bridge.d.ts +48 -0
- package/dist/esm/test-bridge.js +106 -0
- package/dist/esm/types/api.types.d.ts +21 -6
- package/dist/esm/types/api.types.js +21 -6
- package/dist/esm/types/config.types.d.ts +22 -84
- package/dist/esm/types/emitter.types.d.ts +11 -0
- package/dist/esm/types/emitter.types.js +5 -0
- package/dist/esm/types/event.types.d.ts +8 -11
- package/dist/esm/types/index.d.ts +3 -1
- package/dist/esm/types/index.js +3 -1
- package/dist/esm/types/queue.types.d.ts +1 -0
- package/dist/esm/types/session.types.d.ts +0 -64
- package/dist/esm/types/state.types.d.ts +1 -0
- package/dist/esm/types/test-bridge.types.d.ts +38 -0
- package/dist/esm/types/validation-error.types.d.ts +7 -0
- package/dist/esm/types/validation-error.types.js +9 -0
- package/dist/esm/types/window.types.d.ts +1 -8
- package/dist/esm/utils/data/uuid.utils.d.ts +1 -1
- package/dist/esm/utils/data/uuid.utils.js +7 -5
- package/dist/esm/utils/emitter.utils.d.ts +8 -0
- package/dist/esm/utils/emitter.utils.js +29 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/logging/debug-logger.utils.d.ts +10 -51
- package/dist/esm/utils/logging/debug-logger.utils.js +36 -127
- package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +4 -0
- package/dist/esm/utils/network/fetch-with-timeout.utils.js +22 -0
- package/dist/esm/utils/network/index.d.ts +1 -0
- package/dist/esm/utils/network/index.js +1 -0
- package/dist/esm/utils/network/url.utils.js +2 -42
- package/dist/esm/utils/security/sanitize.utils.d.ts +1 -8
- package/dist/esm/utils/security/sanitize.utils.js +6 -39
- package/dist/esm/utils/validations/config-validations.utils.d.ts +7 -0
- package/dist/esm/utils/validations/config-validations.utils.js +76 -22
- package/package.json +23 -16
- package/dist/browser/web-vitals-CCnqwnC8.mjs +0 -198
- package/dist/cjs/constants/browser.constants.d.ts +0 -3
- package/dist/cjs/constants/browser.constants.js +0 -41
- package/dist/cjs/constants/initialization.constants.d.ts +0 -40
- package/dist/cjs/constants/initialization.constants.js +0 -48
- package/dist/cjs/constants/limits.constants.d.ts +0 -27
- package/dist/cjs/constants/limits.constants.js +0 -43
- package/dist/cjs/constants/security.constants.d.ts +0 -1
- package/dist/cjs/constants/security.constants.js +0 -12
- package/dist/cjs/constants/timing.constants.d.ts +0 -22
- package/dist/cjs/constants/timing.constants.js +0 -34
- package/dist/cjs/constants/validation.constants.d.ts +0 -13
- package/dist/cjs/constants/validation.constants.js +0 -31
- package/dist/cjs/handlers/network.handler.d.ts +0 -16
- package/dist/cjs/handlers/network.handler.js +0 -136
- package/dist/cjs/managers/cross-tab-session.manager.d.ts +0 -170
- package/dist/cjs/managers/cross-tab-session.manager.js +0 -730
- package/dist/cjs/managers/sampling.manager.d.ts +0 -8
- package/dist/cjs/managers/sampling.manager.js +0 -53
- package/dist/cjs/managers/session-recovery.manager.d.ts +0 -65
- package/dist/cjs/managers/session-recovery.manager.js +0 -237
- package/dist/cjs/types/web-vitals.types.d.ts +0 -6
- package/dist/esm/constants/browser.constants.d.ts +0 -3
- package/dist/esm/constants/browser.constants.js +0 -38
- package/dist/esm/constants/initialization.constants.d.ts +0 -40
- package/dist/esm/constants/initialization.constants.js +0 -45
- package/dist/esm/constants/limits.constants.d.ts +0 -27
- package/dist/esm/constants/limits.constants.js +0 -40
- package/dist/esm/constants/security.constants.d.ts +0 -1
- package/dist/esm/constants/security.constants.js +0 -9
- package/dist/esm/constants/timing.constants.d.ts +0 -22
- package/dist/esm/constants/timing.constants.js +0 -31
- package/dist/esm/constants/validation.constants.d.ts +0 -13
- package/dist/esm/constants/validation.constants.js +0 -28
- package/dist/esm/handlers/network.handler.d.ts +0 -16
- package/dist/esm/handlers/network.handler.js +0 -132
- package/dist/esm/managers/cross-tab-session.manager.d.ts +0 -170
- package/dist/esm/managers/cross-tab-session.manager.js +0 -726
- package/dist/esm/managers/sampling.manager.d.ts +0 -8
- package/dist/esm/managers/sampling.manager.js +0 -49
- package/dist/esm/managers/session-recovery.manager.d.ts +0 -65
- package/dist/esm/managers/session-recovery.manager.js +0 -233
- package/dist/esm/types/web-vitals.types.d.ts +0 -6
- /package/dist/cjs/types/{web-vitals.types.js → test-bridge.types.js} +0 -0
- /package/dist/esm/types/{web-vitals.types.js → test-bridge.types.js} +0 -0
|
@@ -9,51 +9,31 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
9
9
|
constructor(eventManager) {
|
|
10
10
|
super();
|
|
11
11
|
this.containers = [];
|
|
12
|
-
this.
|
|
13
|
-
this.
|
|
14
|
-
this.
|
|
12
|
+
this.limitWarningLogged = false;
|
|
13
|
+
this.minDepthChange = constants_1.MIN_SCROLL_DEPTH_CHANGE;
|
|
14
|
+
this.minIntervalMs = constants_1.SCROLL_MIN_EVENT_INTERVAL_MS;
|
|
15
|
+
this.maxEventsPerSession = constants_1.MAX_SCROLL_EVENTS_PER_SESSION;
|
|
15
16
|
this.eventManager = eventManager;
|
|
16
17
|
}
|
|
17
18
|
startTracking() {
|
|
19
|
+
this.limitWarningLogged = false;
|
|
20
|
+
this.applyConfigOverrides();
|
|
21
|
+
this.set('scrollEventCount', 0);
|
|
18
22
|
const raw = this.get('config').scrollContainerSelectors;
|
|
19
23
|
const selectors = Array.isArray(raw) ? raw : typeof raw === 'string' ? [raw] : [];
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
24
|
+
const elements = selectors
|
|
25
|
+
.map((sel) => this.safeQuerySelector(sel))
|
|
26
|
+
.filter((element) => element instanceof HTMLElement);
|
|
27
|
+
if (elements.length === 0) {
|
|
28
|
+
elements.push(window);
|
|
25
29
|
}
|
|
26
|
-
const
|
|
27
|
-
const notFoundSelectors = [];
|
|
28
|
-
for (const selector of selectors) {
|
|
29
|
-
const element = this.safeQuerySelector(selector);
|
|
30
|
-
if (element instanceof HTMLElement) {
|
|
31
|
-
foundElements.push(element);
|
|
32
|
-
}
|
|
33
|
-
else if (element === null) {
|
|
34
|
-
notFoundSelectors.push(selector);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
// Setup found elements
|
|
38
|
-
for (const element of foundElements) {
|
|
30
|
+
for (const element of elements) {
|
|
39
31
|
this.setupScrollContainer(element);
|
|
40
32
|
}
|
|
41
|
-
// If we have pending selectors, set up retry logic
|
|
42
|
-
if (notFoundSelectors.length > 0) {
|
|
43
|
-
this.windowFallbackNeeded = true;
|
|
44
|
-
this.setupPendingSelectors(notFoundSelectors);
|
|
45
|
-
}
|
|
46
|
-
else if (this.containers.length === 0) {
|
|
47
|
-
// No elements found and none pending: use window fallback immediately
|
|
48
|
-
this.setupScrollContainer(window);
|
|
49
|
-
}
|
|
50
33
|
}
|
|
51
34
|
stopTracking() {
|
|
52
|
-
logging_1.debugLog.debug('ScrollHandler', 'Stopping scroll tracking', { containersCount: this.containers.length });
|
|
53
35
|
for (const container of this.containers) {
|
|
54
|
-
|
|
55
|
-
clearTimeout(container.debounceTimer);
|
|
56
|
-
}
|
|
36
|
+
this.clearContainerTimer(container);
|
|
57
37
|
if (container.element instanceof Window) {
|
|
58
38
|
window.removeEventListener('scroll', container.listener);
|
|
59
39
|
}
|
|
@@ -62,43 +42,38 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
62
42
|
}
|
|
63
43
|
}
|
|
64
44
|
this.containers.length = 0;
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
this.mutationObserver = null;
|
|
68
|
-
}
|
|
69
|
-
this.pendingSelectors.length = 0;
|
|
45
|
+
this.set('scrollEventCount', 0);
|
|
46
|
+
this.limitWarningLogged = false;
|
|
70
47
|
}
|
|
71
48
|
setupScrollContainer(element) {
|
|
72
|
-
// Skip
|
|
73
|
-
if (
|
|
49
|
+
// Skip setup for non-scrollable elements
|
|
50
|
+
if (element !== window && !this.isElementScrollable(element)) {
|
|
74
51
|
return;
|
|
75
52
|
}
|
|
76
|
-
const container = {
|
|
77
|
-
element,
|
|
78
|
-
lastScrollPos: this.getScrollTop(element),
|
|
79
|
-
debounceTimer: null,
|
|
80
|
-
listener: () => { },
|
|
81
|
-
};
|
|
82
53
|
const handleScroll = () => {
|
|
83
54
|
if (this.get('suppressNextScroll')) {
|
|
84
|
-
this.set('suppressNextScroll', false);
|
|
85
55
|
return;
|
|
86
56
|
}
|
|
87
|
-
|
|
88
|
-
clearTimeout(container.debounceTimer);
|
|
89
|
-
}
|
|
57
|
+
this.clearContainerTimer(container);
|
|
90
58
|
container.debounceTimer = window.setTimeout(() => {
|
|
91
59
|
const scrollData = this.calculateScrollData(container);
|
|
92
60
|
if (scrollData) {
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
scroll_data: scrollData,
|
|
96
|
-
});
|
|
61
|
+
const now = Date.now();
|
|
62
|
+
this.processScrollEvent(container, scrollData, now);
|
|
97
63
|
}
|
|
98
64
|
container.debounceTimer = null;
|
|
99
65
|
}, constants_1.SCROLL_DEBOUNCE_TIME_MS);
|
|
100
66
|
};
|
|
101
|
-
|
|
67
|
+
const initialScrollTop = this.getScrollTop(element);
|
|
68
|
+
const container = {
|
|
69
|
+
element,
|
|
70
|
+
lastScrollPos: initialScrollTop,
|
|
71
|
+
lastDepth: this.calculateScrollDepth(initialScrollTop, this.getScrollHeight(element), this.getViewportHeight(element)),
|
|
72
|
+
lastDirection: types_1.ScrollDirection.DOWN,
|
|
73
|
+
lastEventTime: 0,
|
|
74
|
+
debounceTimer: null,
|
|
75
|
+
listener: handleScroll,
|
|
76
|
+
};
|
|
102
77
|
this.containers.push(container);
|
|
103
78
|
if (element instanceof Window) {
|
|
104
79
|
window.addEventListener('scroll', handleScroll, { passive: true });
|
|
@@ -107,43 +82,95 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
107
82
|
element.addEventListener('scroll', handleScroll, { passive: true });
|
|
108
83
|
}
|
|
109
84
|
}
|
|
85
|
+
processScrollEvent(container, scrollData, timestamp) {
|
|
86
|
+
if (!this.shouldEmitScrollEvent(container, scrollData, timestamp)) {
|
|
87
|
+
return;
|
|
88
|
+
}
|
|
89
|
+
container.lastEventTime = timestamp;
|
|
90
|
+
container.lastDepth = scrollData.depth;
|
|
91
|
+
container.lastDirection = scrollData.direction;
|
|
92
|
+
const currentCount = this.get('scrollEventCount') ?? 0;
|
|
93
|
+
this.set('scrollEventCount', currentCount + 1);
|
|
94
|
+
this.eventManager.track({
|
|
95
|
+
type: types_1.EventType.SCROLL,
|
|
96
|
+
scroll_data: scrollData,
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
shouldEmitScrollEvent(container, scrollData, timestamp) {
|
|
100
|
+
if (this.hasReachedSessionLimit()) {
|
|
101
|
+
this.logLimitOnce();
|
|
102
|
+
return false;
|
|
103
|
+
}
|
|
104
|
+
if (!this.hasElapsedMinimumInterval(container, timestamp)) {
|
|
105
|
+
return false;
|
|
106
|
+
}
|
|
107
|
+
if (!this.hasSignificantDepthChange(container, scrollData.depth)) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
return true;
|
|
111
|
+
}
|
|
112
|
+
hasReachedSessionLimit() {
|
|
113
|
+
const currentCount = this.get('scrollEventCount') ?? 0;
|
|
114
|
+
return currentCount >= this.maxEventsPerSession;
|
|
115
|
+
}
|
|
116
|
+
hasElapsedMinimumInterval(container, timestamp) {
|
|
117
|
+
if (container.lastEventTime === 0) {
|
|
118
|
+
return true;
|
|
119
|
+
}
|
|
120
|
+
return timestamp - container.lastEventTime >= this.minIntervalMs;
|
|
121
|
+
}
|
|
122
|
+
hasSignificantDepthChange(container, newDepth) {
|
|
123
|
+
return Math.abs(newDepth - container.lastDepth) >= this.minDepthChange;
|
|
124
|
+
}
|
|
125
|
+
logLimitOnce() {
|
|
126
|
+
if (this.limitWarningLogged) {
|
|
127
|
+
return;
|
|
128
|
+
}
|
|
129
|
+
this.limitWarningLogged = true;
|
|
130
|
+
logging_1.debugLog.warn('ScrollHandler', 'Max scroll events per session reached', {
|
|
131
|
+
limit: this.maxEventsPerSession,
|
|
132
|
+
});
|
|
133
|
+
}
|
|
134
|
+
applyConfigOverrides() {
|
|
135
|
+
this.minDepthChange = constants_1.MIN_SCROLL_DEPTH_CHANGE;
|
|
136
|
+
this.minIntervalMs = constants_1.SCROLL_MIN_EVENT_INTERVAL_MS;
|
|
137
|
+
this.maxEventsPerSession = constants_1.MAX_SCROLL_EVENTS_PER_SESSION;
|
|
138
|
+
}
|
|
139
|
+
isWindowScrollable() {
|
|
140
|
+
return document.documentElement.scrollHeight > window.innerHeight;
|
|
141
|
+
}
|
|
142
|
+
clearContainerTimer(container) {
|
|
143
|
+
if (container.debounceTimer !== null) {
|
|
144
|
+
clearTimeout(container.debounceTimer);
|
|
145
|
+
container.debounceTimer = null;
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
getScrollDirection(current, previous) {
|
|
149
|
+
return current > previous ? types_1.ScrollDirection.DOWN : types_1.ScrollDirection.UP;
|
|
150
|
+
}
|
|
151
|
+
calculateScrollDepth(scrollTop, scrollHeight, viewportHeight) {
|
|
152
|
+
if (scrollHeight <= viewportHeight) {
|
|
153
|
+
return 0;
|
|
154
|
+
}
|
|
155
|
+
const maxScrollTop = scrollHeight - viewportHeight;
|
|
156
|
+
return Math.min(100, Math.max(0, Math.floor((scrollTop / maxScrollTop) * 100)));
|
|
157
|
+
}
|
|
110
158
|
calculateScrollData(container) {
|
|
111
159
|
const { element, lastScrollPos } = container;
|
|
112
160
|
const scrollTop = this.getScrollTop(element);
|
|
113
|
-
|
|
114
|
-
const scrollHeight = this.getScrollHeight(element);
|
|
115
|
-
const viewportWidth = this.getViewportWidth(element);
|
|
116
|
-
const scrollWidth = this.getScrollWidth(element);
|
|
117
|
-
// Dynamic validation: check if element is scrollable at runtime
|
|
118
|
-
if (element instanceof HTMLElement) {
|
|
119
|
-
// Check if element has scrollable overflow style (can change dynamically)
|
|
120
|
-
if (!this.hasScrollableOverflow(element)) {
|
|
121
|
-
return null;
|
|
122
|
-
}
|
|
123
|
-
// Check if content exceeds viewport (vertical OR horizontal)
|
|
124
|
-
const hasVerticalScroll = scrollHeight > viewportHeight;
|
|
125
|
-
const hasHorizontalScroll = scrollWidth > viewportWidth;
|
|
126
|
-
if (!hasVerticalScroll && !hasHorizontalScroll) {
|
|
127
|
-
return null;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
130
|
-
// For Window: check if content is scrollable (vertical or horizontal)
|
|
131
|
-
if (element instanceof Window) {
|
|
132
|
-
const hasVerticalScroll = scrollHeight > viewportHeight;
|
|
133
|
-
const hasHorizontalScroll = scrollWidth > viewportWidth;
|
|
134
|
-
if (!hasVerticalScroll && !hasHorizontalScroll) {
|
|
135
|
-
return null;
|
|
136
|
-
}
|
|
137
|
-
}
|
|
138
|
-
const direction = scrollTop > lastScrollPos ? types_1.ScrollDirection.DOWN : types_1.ScrollDirection.UP;
|
|
139
|
-
const depth = scrollHeight > viewportHeight
|
|
140
|
-
? Math.min(100, Math.max(0, Math.floor((scrollTop / (scrollHeight - viewportHeight)) * 100)))
|
|
141
|
-
: 0;
|
|
142
|
-
// Only update if scroll position changed significantly
|
|
161
|
+
// Early return: check significant movement first (cheapest check)
|
|
143
162
|
const positionDelta = Math.abs(scrollTop - lastScrollPos);
|
|
144
163
|
if (positionDelta < constants_1.SIGNIFICANT_SCROLL_DELTA) {
|
|
145
164
|
return null;
|
|
146
165
|
}
|
|
166
|
+
// Early return: check if window is scrollable
|
|
167
|
+
if (element === window && !this.isWindowScrollable()) {
|
|
168
|
+
return null;
|
|
169
|
+
}
|
|
170
|
+
const viewportHeight = this.getViewportHeight(element);
|
|
171
|
+
const scrollHeight = this.getScrollHeight(element);
|
|
172
|
+
const direction = this.getScrollDirection(scrollTop, lastScrollPos);
|
|
173
|
+
const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);
|
|
147
174
|
container.lastScrollPos = scrollTop;
|
|
148
175
|
return { depth, direction };
|
|
149
176
|
}
|
|
@@ -156,20 +183,17 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
156
183
|
getScrollHeight(element) {
|
|
157
184
|
return element instanceof Window ? document.documentElement.scrollHeight : element.scrollHeight;
|
|
158
185
|
}
|
|
159
|
-
|
|
160
|
-
return element instanceof Window ? window.innerWidth : element.clientWidth;
|
|
161
|
-
}
|
|
162
|
-
getScrollWidth(element) {
|
|
163
|
-
return element instanceof Window ? document.documentElement.scrollWidth : element.scrollWidth;
|
|
164
|
-
}
|
|
165
|
-
hasScrollableOverflow(element) {
|
|
186
|
+
isElementScrollable(element) {
|
|
166
187
|
const style = getComputedStyle(element);
|
|
167
|
-
|
|
188
|
+
const hasScrollableOverflow = style.overflowY === 'auto' ||
|
|
168
189
|
style.overflowY === 'scroll' ||
|
|
169
190
|
style.overflowX === 'auto' ||
|
|
170
191
|
style.overflowX === 'scroll' ||
|
|
171
192
|
style.overflow === 'auto' ||
|
|
172
|
-
style.overflow === 'scroll'
|
|
193
|
+
style.overflow === 'scroll';
|
|
194
|
+
// Element must have scrollable overflow AND content that exceeds the container
|
|
195
|
+
const hasOverflowContent = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;
|
|
196
|
+
return hasScrollableOverflow && hasOverflowContent;
|
|
173
197
|
}
|
|
174
198
|
safeQuerySelector(selector) {
|
|
175
199
|
try {
|
|
@@ -184,95 +208,5 @@ class ScrollHandler extends state_manager_1.StateManager {
|
|
|
184
208
|
return null;
|
|
185
209
|
}
|
|
186
210
|
}
|
|
187
|
-
setupPendingSelectors(selectors) {
|
|
188
|
-
logging_1.debugLog.debug('ScrollHandler', 'Setting up pending selectors with retry logic', {
|
|
189
|
-
selectors,
|
|
190
|
-
maxRetries: constants_1.MAX_RETRY_ATTEMPTS,
|
|
191
|
-
});
|
|
192
|
-
for (const selector of selectors) {
|
|
193
|
-
this.pendingSelectors.push({ selector, retryCount: 0 });
|
|
194
|
-
}
|
|
195
|
-
this.startMutationObserver();
|
|
196
|
-
this.retryPendingSelectors();
|
|
197
|
-
}
|
|
198
|
-
startMutationObserver() {
|
|
199
|
-
if (this.mutationObserver)
|
|
200
|
-
return;
|
|
201
|
-
this.mutationObserver = new MutationObserver(() => {
|
|
202
|
-
this.checkPendingSelectors();
|
|
203
|
-
});
|
|
204
|
-
this.mutationObserver.observe(document.body, {
|
|
205
|
-
childList: true,
|
|
206
|
-
subtree: true,
|
|
207
|
-
});
|
|
208
|
-
logging_1.debugLog.debug('ScrollHandler', 'MutationObserver started for pending selectors');
|
|
209
|
-
}
|
|
210
|
-
checkPendingSelectors() {
|
|
211
|
-
const remaining = [];
|
|
212
|
-
for (const pending of this.pendingSelectors) {
|
|
213
|
-
const element = this.safeQuerySelector(pending.selector);
|
|
214
|
-
if (element instanceof HTMLElement) {
|
|
215
|
-
logging_1.debugLog.debug('ScrollHandler', 'Found pending selector', { selector: pending.selector });
|
|
216
|
-
this.setupScrollContainer(element);
|
|
217
|
-
}
|
|
218
|
-
else {
|
|
219
|
-
remaining.push(pending);
|
|
220
|
-
}
|
|
221
|
-
}
|
|
222
|
-
this.pendingSelectors.length = 0;
|
|
223
|
-
this.pendingSelectors.push(...remaining);
|
|
224
|
-
if (this.pendingSelectors.length === 0 && this.mutationObserver) {
|
|
225
|
-
this.mutationObserver.disconnect();
|
|
226
|
-
this.mutationObserver = null;
|
|
227
|
-
logging_1.debugLog.debug('ScrollHandler', 'All pending selectors resolved, MutationObserver stopped');
|
|
228
|
-
}
|
|
229
|
-
}
|
|
230
|
-
retryPendingSelectors() {
|
|
231
|
-
setTimeout(() => {
|
|
232
|
-
if (this.pendingSelectors.length === 0)
|
|
233
|
-
return;
|
|
234
|
-
const remaining = [];
|
|
235
|
-
for (const pending of this.pendingSelectors) {
|
|
236
|
-
pending.retryCount++;
|
|
237
|
-
const element = this.safeQuerySelector(pending.selector);
|
|
238
|
-
if (element instanceof HTMLElement) {
|
|
239
|
-
logging_1.debugLog.debug('ScrollHandler', 'Retry found pending selector', {
|
|
240
|
-
selector: pending.selector,
|
|
241
|
-
retryCount: pending.retryCount,
|
|
242
|
-
});
|
|
243
|
-
this.setupScrollContainer(element);
|
|
244
|
-
}
|
|
245
|
-
else if (pending.retryCount < constants_1.MAX_RETRY_ATTEMPTS) {
|
|
246
|
-
remaining.push(pending);
|
|
247
|
-
}
|
|
248
|
-
else {
|
|
249
|
-
logging_1.debugLog.clientWarn('ScrollHandler', 'Selector not found after max retries', {
|
|
250
|
-
selector: pending.selector,
|
|
251
|
-
maxRetries: constants_1.MAX_RETRY_ATTEMPTS,
|
|
252
|
-
});
|
|
253
|
-
}
|
|
254
|
-
}
|
|
255
|
-
this.pendingSelectors.length = 0;
|
|
256
|
-
this.pendingSelectors.push(...remaining);
|
|
257
|
-
if (this.pendingSelectors.length > 0) {
|
|
258
|
-
this.retryPendingSelectors();
|
|
259
|
-
}
|
|
260
|
-
else {
|
|
261
|
-
// All retries complete
|
|
262
|
-
if (this.mutationObserver) {
|
|
263
|
-
this.mutationObserver.disconnect();
|
|
264
|
-
this.mutationObserver = null;
|
|
265
|
-
}
|
|
266
|
-
// Apply window fallback if needed and no containers were set up
|
|
267
|
-
if (this.windowFallbackNeeded && this.containers.length === 0) {
|
|
268
|
-
logging_1.debugLog.debug('ScrollHandler', 'No scroll containers found, using window fallback');
|
|
269
|
-
this.setupScrollContainer(window);
|
|
270
|
-
}
|
|
271
|
-
logging_1.debugLog.debug('ScrollHandler', 'All pending selectors resolved or timed out', {
|
|
272
|
-
containersCount: this.containers.length,
|
|
273
|
-
});
|
|
274
|
-
}
|
|
275
|
-
}, constants_1.RETRY_DELAY_MS);
|
|
276
|
-
}
|
|
277
211
|
}
|
|
278
212
|
exports.ScrollHandler = ScrollHandler;
|
|
@@ -4,26 +4,12 @@ import { StorageManager } from '../managers/storage.manager';
|
|
|
4
4
|
export declare class SessionHandler extends StateManager {
|
|
5
5
|
private readonly eventManager;
|
|
6
6
|
private readonly storageManager;
|
|
7
|
-
private readonly sessionStorageKey;
|
|
8
7
|
private sessionManager;
|
|
9
|
-
private
|
|
10
|
-
private _crossTabSessionManager;
|
|
11
|
-
private heartbeatInterval;
|
|
12
|
-
private _isInitializingCrossTab;
|
|
13
|
-
private get crossTabSessionManager();
|
|
14
|
-
private shouldUseCrossTabs;
|
|
8
|
+
private destroyed;
|
|
15
9
|
constructor(storageManager: StorageManager, eventManager: EventManager);
|
|
16
|
-
startTracking(): void
|
|
17
|
-
|
|
18
|
-
private
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
private forceCleanupSession;
|
|
22
|
-
private trackSession;
|
|
23
|
-
private startInitialSession;
|
|
24
|
-
private checkOrphanedSessions;
|
|
25
|
-
private persistSession;
|
|
26
|
-
private clearPersistedSession;
|
|
27
|
-
private startHeartbeat;
|
|
28
|
-
private stopHeartbeat;
|
|
10
|
+
startTracking(): Promise<void>;
|
|
11
|
+
private isActive;
|
|
12
|
+
private cleanupSessionManager;
|
|
13
|
+
stopTracking(): Promise<void>;
|
|
14
|
+
destroy(): void;
|
|
29
15
|
}
|