@tracelog/lib 0.0.8 → 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.
- package/README.md +58 -24
- package/dist/browser/tracelog.js +1934 -3226
- package/dist/cjs/api.d.ts +33 -19
- package/dist/cjs/api.js +111 -156
- package/dist/cjs/app.constants.d.ts +80 -1
- package/dist/cjs/app.constants.js +90 -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 +15 -0
- package/dist/cjs/handlers/scroll.handler.js +105 -31
- 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 +80 -1
- package/dist/esm/app.constants.js +89 -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 +15 -0
- package/dist/esm/handlers/scroll.handler.js +106 -32
- 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 -25
- package/dist/cjs/constants/limits.constants.js +0 -40
- 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 -25
- package/dist/esm/constants/limits.constants.js +0 -37
- 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
package/dist/esm/app.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { getApiUrlForProject } from './managers/api.manager';
|
|
2
2
|
import { ConfigManager } from './managers/config.manager';
|
|
3
3
|
import { EventManager } from './managers/event.manager';
|
|
4
4
|
import { UserManager } from './managers/user.manager';
|
|
@@ -7,262 +7,164 @@ import { SessionHandler } from './handlers/session.handler';
|
|
|
7
7
|
import { PageViewHandler } from './handlers/page-view.handler';
|
|
8
8
|
import { ClickHandler } from './handlers/click.handler';
|
|
9
9
|
import { ScrollHandler } from './handlers/scroll.handler';
|
|
10
|
-
import {
|
|
11
|
-
import { EventType } from './types/event.types';
|
|
10
|
+
import { EventType } from './types';
|
|
12
11
|
import { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';
|
|
13
|
-
import { getDeviceType, normalizeUrl } from './utils';
|
|
12
|
+
import { isEventValid, getDeviceType, normalizeUrl, debugLog, Emitter, normalizeConfig } from './utils';
|
|
14
13
|
import { StorageManager } from './managers/storage.manager';
|
|
15
|
-
import { SCROLL_DEBOUNCE_TIME_MS,
|
|
14
|
+
import { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';
|
|
16
15
|
import { PerformanceHandler } from './handlers/performance.handler';
|
|
17
16
|
import { ErrorHandler } from './handlers/error.handler';
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
17
|
+
/**
|
|
18
|
+
* Main application class for TraceLog analytics
|
|
19
|
+
* Orchestrates event tracking, session management, and integrations
|
|
20
|
+
*/
|
|
21
21
|
export class App extends StateManager {
|
|
22
22
|
constructor() {
|
|
23
23
|
super(...arguments);
|
|
24
24
|
this.isInitialized = false;
|
|
25
|
-
this.googleAnalytics = null;
|
|
26
25
|
this.suppressNextScrollTimer = null;
|
|
26
|
+
this.emitter = new Emitter();
|
|
27
|
+
this.managers = {};
|
|
28
|
+
this.handlers = {};
|
|
29
|
+
this.integrations = {};
|
|
27
30
|
}
|
|
28
|
-
/**
|
|
29
|
-
* Returns the initialization status of the app
|
|
30
|
-
* @returns true if the app is fully initialized, false otherwise
|
|
31
|
-
*/
|
|
32
31
|
get initialized() {
|
|
33
32
|
return this.isInitialized;
|
|
34
33
|
}
|
|
35
34
|
async init(appConfig) {
|
|
36
35
|
if (this.isInitialized) {
|
|
37
|
-
debugLog.debug('App', 'App already initialized, skipping re-initialization', { projectId: appConfig.id });
|
|
38
36
|
return;
|
|
39
37
|
}
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
if (!appConfig.id?.trim()) {
|
|
39
|
+
throw new Error('Project ID is required');
|
|
40
|
+
}
|
|
41
|
+
this.managers.storage = new StorageManager();
|
|
42
42
|
try {
|
|
43
|
-
this.
|
|
44
|
-
await this.
|
|
45
|
-
|
|
46
|
-
this.
|
|
47
|
-
await this.
|
|
48
|
-
|
|
49
|
-
debugLog.info('App', 'App initialization completed successfully', {
|
|
50
|
-
projectId: appConfig.id,
|
|
43
|
+
await this.setupState(appConfig);
|
|
44
|
+
await this.setupIntegrations();
|
|
45
|
+
this.managers.event = new EventManager(this.managers.storage, this.integrations.googleAnalytics, this.emitter);
|
|
46
|
+
this.initializeHandlers();
|
|
47
|
+
await this.managers.event.recoverPersistedEvents().catch(() => {
|
|
48
|
+
debugLog.warn('App', 'Failed to recover persisted events');
|
|
51
49
|
});
|
|
50
|
+
this.isInitialized = true;
|
|
52
51
|
}
|
|
53
52
|
catch (error) {
|
|
54
|
-
this.
|
|
55
|
-
|
|
56
|
-
throw error;
|
|
57
|
-
}
|
|
58
|
-
}
|
|
59
|
-
/**
|
|
60
|
-
* Validates that the app is ready to initialize with the provided config
|
|
61
|
-
* This is a lightweight runtime validation layer that ensures the app receives proper config
|
|
62
|
-
* @param appConfig - The validated and normalized configuration
|
|
63
|
-
* @throws {ProjectIdValidationError} If project ID is invalid at runtime
|
|
64
|
-
*/
|
|
65
|
-
validateAppReadiness(appConfig) {
|
|
66
|
-
// Lightweight validation - config should already be validated and normalized by api.ts
|
|
67
|
-
if (!appConfig?.id) {
|
|
68
|
-
debugLog.clientError('App', 'Configuration integrity check failed - missing project ID', {
|
|
69
|
-
hasConfig: !!appConfig,
|
|
70
|
-
hasId: !!appConfig?.id,
|
|
71
|
-
});
|
|
72
|
-
throw new ProjectIdValidationError('Configuration integrity check failed', 'app');
|
|
53
|
+
await this.destroy(true);
|
|
54
|
+
throw new Error(`TraceLog initialization failed: ${error}`);
|
|
73
55
|
}
|
|
74
56
|
}
|
|
75
57
|
sendCustomEvent(name, metadata) {
|
|
76
|
-
if (!this.
|
|
77
|
-
debugLog.warn('App', 'Custom event attempted before eventManager initialization', { eventName: name });
|
|
58
|
+
if (!this.managers.event) {
|
|
78
59
|
return;
|
|
79
60
|
}
|
|
80
61
|
const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);
|
|
81
|
-
if (valid) {
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
custom_event: {
|
|
86
|
-
name,
|
|
87
|
-
...(sanitizedMetadata && { metadata: sanitizedMetadata }),
|
|
88
|
-
},
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
else {
|
|
92
|
-
const currentMode = this.get('config')?.mode;
|
|
93
|
-
debugLog.clientError('App', `Custom event validation failed: ${error ?? 'unknown error'}`, {
|
|
94
|
-
eventName: name,
|
|
95
|
-
validationError: error,
|
|
96
|
-
hasMetadata: !!metadata,
|
|
97
|
-
mode: currentMode,
|
|
98
|
-
});
|
|
99
|
-
if (currentMode === 'qa' || currentMode === 'debug') {
|
|
100
|
-
throw new Error(`custom event "${name}" validation failed (${error ?? 'unknown error'}). Please, review your event data and try again.`);
|
|
62
|
+
if (!valid) {
|
|
63
|
+
const config = this.get('config');
|
|
64
|
+
if (config?.mode === 'qa' || config?.mode === 'debug') {
|
|
65
|
+
throw new Error(`Custom event "${name}" validation failed: ${error}`);
|
|
101
66
|
}
|
|
67
|
+
return;
|
|
102
68
|
}
|
|
69
|
+
this.managers.event.track({
|
|
70
|
+
type: EventType.CUSTOM,
|
|
71
|
+
custom_event: {
|
|
72
|
+
name,
|
|
73
|
+
...(sanitizedMetadata && { metadata: sanitizedMetadata }),
|
|
74
|
+
},
|
|
75
|
+
});
|
|
76
|
+
}
|
|
77
|
+
on(event, callback) {
|
|
78
|
+
this.emitter.on(event, callback);
|
|
79
|
+
}
|
|
80
|
+
off(event, callback) {
|
|
81
|
+
this.emitter.off(event, callback);
|
|
103
82
|
}
|
|
104
|
-
destroy() {
|
|
105
|
-
if (!this.isInitialized) {
|
|
106
|
-
debugLog.warn('App', 'Destroy called but app was not initialized');
|
|
83
|
+
async destroy(force = false) {
|
|
84
|
+
if (!this.isInitialized && !force) {
|
|
107
85
|
return;
|
|
108
86
|
}
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
}
|
|
122
|
-
if (this.scrollHandler) {
|
|
123
|
-
this.scrollHandler.stopTracking();
|
|
124
|
-
}
|
|
125
|
-
if (this.performanceHandler) {
|
|
126
|
-
this.performanceHandler.stopTracking();
|
|
127
|
-
}
|
|
128
|
-
if (this.errorHandler) {
|
|
129
|
-
this.errorHandler.stopTracking();
|
|
130
|
-
}
|
|
131
|
-
if (this.networkHandler) {
|
|
132
|
-
this.networkHandler.stopTracking();
|
|
133
|
-
}
|
|
87
|
+
this.integrations.googleAnalytics?.cleanup();
|
|
88
|
+
const handlerCleanups = Object.values(this.handlers)
|
|
89
|
+
.filter(Boolean)
|
|
90
|
+
.map(async (handler) => {
|
|
91
|
+
try {
|
|
92
|
+
await handler.stopTracking();
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
debugLog.warn('App', 'Failed to stop tracking');
|
|
96
|
+
}
|
|
97
|
+
});
|
|
98
|
+
await Promise.allSettled(handlerCleanups);
|
|
134
99
|
if (this.suppressNextScrollTimer) {
|
|
135
100
|
clearTimeout(this.suppressNextScrollTimer);
|
|
136
101
|
this.suppressNextScrollTimer = null;
|
|
137
102
|
}
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
}
|
|
103
|
+
this.managers.event?.stop();
|
|
104
|
+
this.emitter.removeAllListeners();
|
|
141
105
|
this.set('hasStartSession', false);
|
|
142
106
|
this.set('suppressNextScroll', false);
|
|
143
107
|
this.set('sessionId', null);
|
|
144
108
|
this.isInitialized = false;
|
|
145
|
-
|
|
146
|
-
}
|
|
147
|
-
async setState(appConfig) {
|
|
148
|
-
this.setApiUrl(appConfig.id, appConfig.allowHttp);
|
|
149
|
-
await this.setConfig(appConfig);
|
|
150
|
-
this.setUserId();
|
|
151
|
-
this.setDevice();
|
|
152
|
-
this.setPageUrl();
|
|
109
|
+
this.handlers = {};
|
|
153
110
|
}
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
111
|
+
async setupState(appConfig) {
|
|
112
|
+
// Set API URL
|
|
113
|
+
const apiUrl = getApiUrlForProject(appConfig.id, appConfig.allowHttp);
|
|
114
|
+
this.set('apiUrl', apiUrl);
|
|
115
|
+
// Get remote configuration
|
|
159
116
|
const configManager = new ConfigManager();
|
|
160
|
-
const config = await configManager.get(
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
const
|
|
165
|
-
const userId = userManager.getId();
|
|
117
|
+
const config = await configManager.get(apiUrl, appConfig);
|
|
118
|
+
const { config: normalizedConfig } = normalizeConfig(config);
|
|
119
|
+
this.set('config', normalizedConfig);
|
|
120
|
+
// Set user ID
|
|
121
|
+
const userId = UserManager.getId(this.managers.storage, normalizedConfig.id);
|
|
166
122
|
this.set('userId', userId);
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
this.set('
|
|
171
|
-
}
|
|
172
|
-
|
|
173
|
-
const
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
}
|
|
184
|
-
async initHandlers() {
|
|
185
|
-
if (!this.eventManager) {
|
|
186
|
-
throw new Error('EventManager must be initialized before handlers');
|
|
187
|
-
}
|
|
188
|
-
if (!this.storageManager) {
|
|
189
|
-
throw new Error('StorageManager must be initialized before handlers');
|
|
190
|
-
}
|
|
191
|
-
this.initSessionHandler();
|
|
192
|
-
this.initPageViewHandler();
|
|
193
|
-
this.initClickHandler();
|
|
194
|
-
this.initScrollHandler();
|
|
195
|
-
await this.initPerformanceHandler();
|
|
196
|
-
this.initErrorHandler();
|
|
197
|
-
this.initNetworkHandler();
|
|
198
|
-
}
|
|
199
|
-
initStorage() {
|
|
200
|
-
this.storageManager = new StorageManager();
|
|
201
|
-
}
|
|
202
|
-
setEventManager() {
|
|
203
|
-
if (!this.storageManager) {
|
|
204
|
-
throw new Error('StorageManager must be initialized before EventManager');
|
|
205
|
-
}
|
|
206
|
-
this.eventManager = new EventManager(this.storageManager, this.googleAnalytics);
|
|
207
|
-
}
|
|
208
|
-
initSessionHandler() {
|
|
209
|
-
if (!this.storageManager || !this.eventManager) {
|
|
210
|
-
throw new Error('StorageManager and EventManager must be initialized before SessionHandler');
|
|
211
|
-
}
|
|
212
|
-
this.sessionHandler = new SessionHandler(this.storageManager, this.eventManager);
|
|
213
|
-
this.sessionHandler.startTracking();
|
|
214
|
-
}
|
|
215
|
-
initPageViewHandler() {
|
|
216
|
-
if (!this.eventManager) {
|
|
217
|
-
throw new Error('EventManager must be initialized before PageViewHandler');
|
|
218
|
-
}
|
|
219
|
-
const onPageViewTrack = () => this.onPageViewTrack();
|
|
220
|
-
this.pageViewHandler = new PageViewHandler(this.eventManager, onPageViewTrack);
|
|
221
|
-
this.pageViewHandler.startTracking();
|
|
222
|
-
}
|
|
223
|
-
onPageViewTrack() {
|
|
224
|
-
this.set('suppressNextScroll', true);
|
|
225
|
-
if (this.suppressNextScrollTimer) {
|
|
226
|
-
clearTimeout(this.suppressNextScrollTimer);
|
|
227
|
-
this.suppressNextScrollTimer = null;
|
|
228
|
-
}
|
|
229
|
-
this.suppressNextScrollTimer = window.setTimeout(() => {
|
|
230
|
-
this.set('suppressNextScroll', false);
|
|
231
|
-
}, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESSION_CONSTANTS.SUPPRESS_MULTIPLIER);
|
|
232
|
-
}
|
|
233
|
-
initClickHandler() {
|
|
234
|
-
if (!this.eventManager) {
|
|
235
|
-
throw new Error('EventManager must be initialized before ClickHandler');
|
|
236
|
-
}
|
|
237
|
-
this.clickHandler = new ClickHandler(this.eventManager);
|
|
238
|
-
this.clickHandler.startTracking();
|
|
239
|
-
}
|
|
240
|
-
initScrollHandler() {
|
|
241
|
-
if (!this.eventManager) {
|
|
242
|
-
throw new Error('EventManager must be initialized before ScrollHandler');
|
|
243
|
-
}
|
|
244
|
-
this.scrollHandler = new ScrollHandler(this.eventManager);
|
|
245
|
-
this.scrollHandler.startTracking();
|
|
246
|
-
}
|
|
247
|
-
async initPerformanceHandler() {
|
|
248
|
-
if (!this.eventManager) {
|
|
249
|
-
throw new Error('EventManager must be initialized before PerformanceHandler');
|
|
250
|
-
}
|
|
251
|
-
this.performanceHandler = new PerformanceHandler(this.eventManager);
|
|
252
|
-
await this.performanceHandler.startTracking();
|
|
253
|
-
}
|
|
254
|
-
initErrorHandler() {
|
|
255
|
-
if (!this.eventManager) {
|
|
256
|
-
throw new Error('EventManager must be initialized before ErrorHandler');
|
|
123
|
+
// Set device and page info
|
|
124
|
+
this.set('device', getDeviceType());
|
|
125
|
+
const pageUrl = normalizeUrl(window.location.href, normalizedConfig.sensitiveQueryParams);
|
|
126
|
+
this.set('pageUrl', pageUrl);
|
|
127
|
+
}
|
|
128
|
+
async setupIntegrations() {
|
|
129
|
+
const config = this.get('config');
|
|
130
|
+
const measurementId = config.integrations?.googleAnalytics?.measurementId;
|
|
131
|
+
if (!config.ipExcluded && measurementId?.trim()) {
|
|
132
|
+
try {
|
|
133
|
+
this.integrations.googleAnalytics = new GoogleAnalyticsIntegration();
|
|
134
|
+
await this.integrations.googleAnalytics.initialize();
|
|
135
|
+
}
|
|
136
|
+
catch {
|
|
137
|
+
this.integrations.googleAnalytics = undefined;
|
|
138
|
+
}
|
|
257
139
|
}
|
|
258
|
-
this.errorHandler = new ErrorHandler(this.eventManager);
|
|
259
|
-
this.errorHandler.startTracking();
|
|
260
140
|
}
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
141
|
+
initializeHandlers() {
|
|
142
|
+
this.handlers.session = new SessionHandler(this.managers.storage, this.managers.event);
|
|
143
|
+
this.handlers.session.startTracking().catch((error) => {
|
|
144
|
+
debugLog.error('App', 'Session handler failed to start', {
|
|
145
|
+
message: error instanceof Error ? error.message : 'Unknown error',
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
const onPageView = () => {
|
|
149
|
+
this.set('suppressNextScroll', true);
|
|
150
|
+
if (this.suppressNextScrollTimer) {
|
|
151
|
+
clearTimeout(this.suppressNextScrollTimer);
|
|
152
|
+
}
|
|
153
|
+
this.suppressNextScrollTimer = window.setTimeout(() => {
|
|
154
|
+
this.set('suppressNextScroll', false);
|
|
155
|
+
}, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESS_MULTIPLIER);
|
|
156
|
+
};
|
|
157
|
+
this.handlers.pageView = new PageViewHandler(this.managers.event, onPageView);
|
|
158
|
+
this.handlers.pageView.startTracking();
|
|
159
|
+
this.handlers.click = new ClickHandler(this.managers.event);
|
|
160
|
+
this.handlers.click.startTracking();
|
|
161
|
+
this.handlers.scroll = new ScrollHandler(this.managers.event);
|
|
162
|
+
this.handlers.scroll.startTracking();
|
|
163
|
+
this.handlers.performance = new PerformanceHandler(this.managers.event);
|
|
164
|
+
this.handlers.performance.startTracking().catch(() => {
|
|
165
|
+
debugLog.warn('App', 'Failed to start performance tracking');
|
|
166
|
+
});
|
|
167
|
+
this.handlers.error = new ErrorHandler(this.managers.event);
|
|
168
|
+
this.handlers.error.startTracking();
|
|
267
169
|
}
|
|
268
170
|
}
|
package/dist/esm/app.types.d.ts
CHANGED
|
@@ -1,7 +1,2 @@
|
|
|
1
|
-
export
|
|
2
|
-
export
|
|
3
|
-
export * from './types/device.types';
|
|
4
|
-
export * from './types/event.types';
|
|
5
|
-
export * from './types/mode.types';
|
|
6
|
-
export * from './types/queue.types';
|
|
7
|
-
export * from './types/tag.types';
|
|
1
|
+
export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
|
|
2
|
+
export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
|
package/dist/esm/app.types.js
CHANGED
|
@@ -1,7 +1 @@
|
|
|
1
|
-
export
|
|
2
|
-
export * from './types/config.types';
|
|
3
|
-
export * from './types/device.types';
|
|
4
|
-
export * from './types/event.types';
|
|
5
|
-
export * from './types/mode.types';
|
|
6
|
-
export * from './types/queue.types';
|
|
7
|
-
export * from './types/tag.types';
|
|
1
|
+
export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
|
|
@@ -1,13 +1,19 @@
|
|
|
1
|
-
import { DEFAULT_SAMPLING_RATE } from './
|
|
2
|
-
import { DEFAULT_SESSION_TIMEOUT_MS } from './timing.constants';
|
|
1
|
+
import { DEFAULT_SAMPLING_RATE, DEFAULT_SESSION_TIMEOUT, MAX_SAMPLING_RATE, MIN_SAMPLING_RATE, } from './config.constants';
|
|
3
2
|
export const DEFAULT_API_CONFIG = {
|
|
4
3
|
samplingRate: DEFAULT_SAMPLING_RATE,
|
|
5
|
-
tags: [],
|
|
6
4
|
excludedUrlPaths: [],
|
|
5
|
+
tags: [],
|
|
6
|
+
ipExcluded: false,
|
|
7
7
|
};
|
|
8
8
|
export const DEFAULT_CONFIG = (config) => ({
|
|
9
9
|
...DEFAULT_API_CONFIG,
|
|
10
10
|
...config,
|
|
11
|
-
sessionTimeout: DEFAULT_SESSION_TIMEOUT_MS,
|
|
12
11
|
allowHttp: false,
|
|
12
|
+
sessionTimeout: DEFAULT_SESSION_TIMEOUT,
|
|
13
|
+
samplingRate: config.samplingRate && config.samplingRate > MIN_SAMPLING_RATE && config.samplingRate <= MAX_SAMPLING_RATE
|
|
14
|
+
? config.samplingRate
|
|
15
|
+
: DEFAULT_SAMPLING_RATE,
|
|
16
|
+
excludedUrlPaths: config.excludedUrlPaths ?? [],
|
|
17
|
+
tags: config.tags ?? [],
|
|
18
|
+
ipExcluded: config.ipExcluded ?? false,
|
|
13
19
|
});
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Consolidated configuration constants for TraceLog
|
|
3
|
+
* This file centralizes all timing, limits, browser, and initialization constants
|
|
4
|
+
*/
|
|
5
|
+
export declare const DEFAULT_SESSION_TIMEOUT: number;
|
|
6
|
+
export declare const DUPLICATE_EVENT_THRESHOLD_MS = 1000;
|
|
7
|
+
export declare const EVENT_SENT_INTERVAL_MS = 10000;
|
|
8
|
+
export declare const SCROLL_DEBOUNCE_TIME_MS = 250;
|
|
9
|
+
export declare const DEFAULT_VISIBILITY_TIMEOUT_MS = 2000;
|
|
10
|
+
export declare const EVENT_EXPIRY_HOURS = 24;
|
|
11
|
+
export declare const EVENT_PERSISTENCE_MAX_AGE_MS: number;
|
|
12
|
+
export declare const MAX_EVENTS_QUEUE_LENGTH = 500;
|
|
13
|
+
export declare const MAX_RETRIES = 3;
|
|
14
|
+
export declare const RETRY_DELAY_MS = 5000;
|
|
15
|
+
export declare const REQUEST_TIMEOUT_MS = 10000;
|
|
16
|
+
export declare const MAX_METADATA_SIZE = 5000;
|
|
17
|
+
export declare const DEFAULT_MOTION_THRESHOLD = 2;
|
|
18
|
+
export declare const SIGNIFICANT_SCROLL_DELTA = 10;
|
|
19
|
+
export declare const MIN_SCROLL_DEPTH_CHANGE = 5;
|
|
20
|
+
export declare const SCROLL_MIN_EVENT_INTERVAL_MS = 500;
|
|
21
|
+
export declare const MAX_SCROLL_EVENTS_PER_SESSION = 120;
|
|
22
|
+
export declare const DEFAULT_SAMPLING_RATE = 1;
|
|
23
|
+
export declare const MIN_SAMPLING_RATE = 0;
|
|
24
|
+
export declare const MAX_SAMPLING_RATE = 1;
|
|
25
|
+
export declare const BATCH_SIZE_THRESHOLD = 50;
|
|
26
|
+
export declare const MIN_SESSION_TIMEOUT_MS = 30000;
|
|
27
|
+
export declare const MAX_SESSION_TIMEOUT_MS = 86400000;
|
|
28
|
+
export declare const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;
|
|
29
|
+
export declare const MAX_CUSTOM_EVENT_STRING_SIZE: number;
|
|
30
|
+
export declare const MAX_CUSTOM_EVENT_KEYS = 10;
|
|
31
|
+
export declare const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;
|
|
32
|
+
export declare const MAX_TEXT_LENGTH = 255;
|
|
33
|
+
export declare const MAX_STRING_LENGTH = 1000;
|
|
34
|
+
export declare const MAX_ARRAY_LENGTH = 100;
|
|
35
|
+
export declare const MAX_OBJECT_DEPTH = 3;
|
|
36
|
+
export declare const PRECISION_TWO_DECIMALS: 2;
|
|
37
|
+
export declare const SYNC_XHR_TIMEOUT_MS = 2000;
|
|
38
|
+
export declare const MAX_FINGERPRINTS = 1000;
|
|
39
|
+
export declare const FINGERPRINT_CLEANUP_MULTIPLIER = 10;
|
|
40
|
+
export declare const MAX_FINGERPRINTS_HARD_LIMIT = 2000;
|
|
41
|
+
export declare const HTML_DATA_ATTR_PREFIX = "data-tl";
|
|
42
|
+
export declare const INTERACTIVE_SELECTORS: readonly ["button", "a", "input[type=\"button\"]", "input[type=\"submit\"]", "input[type=\"reset\"]", "input[type=\"checkbox\"]", "input[type=\"radio\"]", "select", "textarea", "[role=\"button\"]", "[role=\"link\"]", "[role=\"tab\"]", "[role=\"menuitem\"]", "[role=\"option\"]", "[role=\"checkbox\"]", "[role=\"radio\"]", "[role=\"switch\"]", "[routerLink]", "[ng-click]", "[data-action]", "[data-click]", "[data-navigate]", "[data-toggle]", "[onclick]", ".btn", ".button", ".clickable", ".nav-link", ".menu-item", "[data-testid]", "[tabindex=\"0\"]"];
|
|
43
|
+
export declare const UTM_PARAMS: string[];
|
|
44
|
+
export declare const INITIALIZATION_MAX_CONCURRENT_RETRIES = 20;
|
|
45
|
+
export declare const INITIALIZATION_CONCURRENT_RETRY_DELAY_MS = 50;
|
|
46
|
+
export declare const INITIALIZATION_TIMEOUT_MS = 10000;
|
|
47
|
+
export declare const SESSION_SYNC_TIMEOUT_MS = 2000;
|
|
48
|
+
export declare const SESSION_MAX_RETRY_ATTEMPTS = 3;
|
|
49
|
+
export declare const SESSION_CLEANUP_DELAY_MS = 100;
|
|
50
|
+
export declare const CROSS_TAB_INITIALIZATION_LOCK_TIMEOUT_MS = 5000;
|
|
51
|
+
export declare const TAB_HEARTBEAT_INTERVAL_MS = 5000;
|
|
52
|
+
export declare const TAB_ELECTION_TIMEOUT_MS = 2000;
|
|
53
|
+
export declare const TAB_CLEANUP_DELAY_MS = 1000;
|
|
54
|
+
export declare const SESSION_RECOVERY_WINDOW_MULTIPLIER = 2;
|
|
55
|
+
export declare const MAX_SESSION_RECOVERY_ATTEMPTS = 3;
|
|
56
|
+
export declare const MAX_SESSION_RECOVERY_WINDOW_MS: number;
|
|
57
|
+
export declare const MIN_SESSION_RECOVERY_WINDOW_MS: number;
|
|
58
|
+
export declare const SCROLL_SUPPRESS_MULTIPLIER = 2;
|
|
59
|
+
export declare const RETRY_BACKOFF_INITIAL = 1000;
|
|
60
|
+
export declare const RETRY_BACKOFF_MAX = 30000;
|
|
61
|
+
export declare const RATE_LIMIT_INTERVAL = 1000;
|
|
62
|
+
export declare const MAX_RETRY_ATTEMPTS = 10;
|
|
63
|
+
export declare const ALLOWED_API_CONFIG_KEYS: Set<"mode" | "samplingRate" | "excludedUrlPaths" | keyof import("../types").ExclusiveApiConfig>;
|
|
64
|
+
export declare const VALIDATION_MESSAGES: {
|
|
65
|
+
readonly MISSING_PROJECT_ID: "Project ID is required";
|
|
66
|
+
readonly PROJECT_ID_EMPTY_AFTER_TRIM: "Project ID is required";
|
|
67
|
+
readonly INVALID_SESSION_TIMEOUT: "Session timeout must be between 30000ms (30 seconds) and 86400000ms (24 hours)";
|
|
68
|
+
readonly INVALID_SAMPLING_RATE: "Sampling rate must be greater than 0 and less than or equal to 1";
|
|
69
|
+
readonly INVALID_ERROR_SAMPLING_RATE: "Error sampling must be between 0 and 1";
|
|
70
|
+
readonly INVALID_GOOGLE_ANALYTICS_ID: "Google Analytics measurement ID is required when integration is enabled";
|
|
71
|
+
readonly INVALID_SCROLL_CONTAINER_SELECTORS: "Scroll container selectors must be valid CSS selectors";
|
|
72
|
+
readonly INVALID_GLOBAL_METADATA: "Global metadata must be an object";
|
|
73
|
+
readonly INVALID_SENSITIVE_QUERY_PARAMS: "Sensitive query params must be an array of strings";
|
|
74
|
+
};
|
|
75
|
+
export declare const XSS_PATTERNS: readonly [RegExp, RegExp, RegExp, RegExp, RegExp, RegExp];
|