@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.
Files changed (228) hide show
  1. package/README.md +58 -24
  2. package/dist/browser/tracelog.js +1934 -3226
  3. package/dist/cjs/api.d.ts +33 -19
  4. package/dist/cjs/api.js +111 -156
  5. package/dist/cjs/app.constants.d.ts +80 -1
  6. package/dist/cjs/app.constants.js +90 -3
  7. package/dist/cjs/app.d.ts +29 -44
  8. package/dist/cjs/app.js +114 -212
  9. package/dist/cjs/app.types.d.ts +2 -7
  10. package/dist/cjs/app.types.js +10 -21
  11. package/dist/cjs/constants/api.constants.js +11 -5
  12. package/dist/cjs/constants/config.constants.d.ts +75 -0
  13. package/dist/cjs/constants/config.constants.js +178 -0
  14. package/dist/cjs/constants/error.constants.d.ts +29 -0
  15. package/dist/cjs/constants/error.constants.js +50 -0
  16. package/dist/cjs/constants/index.d.ts +3 -6
  17. package/dist/cjs/constants/index.js +3 -6
  18. package/dist/cjs/constants/performance.constants.d.ts +28 -0
  19. package/dist/cjs/constants/performance.constants.js +43 -0
  20. package/dist/cjs/handlers/click.handler.d.ts +1 -0
  21. package/dist/cjs/handlers/click.handler.js +30 -49
  22. package/dist/cjs/handlers/error.handler.d.ts +11 -6
  23. package/dist/cjs/handlers/error.handler.js +91 -51
  24. package/dist/cjs/handlers/page-view.handler.js +38 -29
  25. package/dist/cjs/handlers/performance.handler.d.ts +3 -0
  26. package/dist/cjs/handlers/performance.handler.js +76 -37
  27. package/dist/cjs/handlers/scroll.handler.d.ts +15 -0
  28. package/dist/cjs/handlers/scroll.handler.js +105 -31
  29. package/dist/cjs/handlers/session.handler.d.ts +6 -20
  30. package/dist/cjs/handlers/session.handler.js +38 -326
  31. package/dist/cjs/integrations/google-analytics.integration.d.ts +0 -1
  32. package/dist/cjs/integrations/google-analytics.integration.js +27 -98
  33. package/dist/cjs/listeners/input-listener-managers.d.ts +18 -9
  34. package/dist/cjs/listeners/input-listener-managers.js +24 -33
  35. package/dist/cjs/listeners/touch-listener-manager.d.ts +1 -3
  36. package/dist/cjs/listeners/touch-listener-manager.js +1 -23
  37. package/dist/cjs/listeners/visibility-listener-manager.d.ts +1 -4
  38. package/dist/cjs/listeners/visibility-listener-manager.js +6 -42
  39. package/dist/cjs/managers/api.manager.d.ts +13 -3
  40. package/dist/cjs/managers/api.manager.js +35 -5
  41. package/dist/cjs/managers/config.manager.d.ts +53 -3
  42. package/dist/cjs/managers/config.manager.js +131 -62
  43. package/dist/cjs/managers/event.manager.d.ts +57 -36
  44. package/dist/cjs/managers/event.manager.js +266 -417
  45. package/dist/cjs/managers/sender.manager.d.ts +40 -22
  46. package/dist/cjs/managers/sender.manager.js +200 -198
  47. package/dist/cjs/managers/session.manager.d.ts +80 -66
  48. package/dist/cjs/managers/session.manager.js +267 -522
  49. package/dist/cjs/managers/state.manager.d.ts +33 -0
  50. package/dist/cjs/managers/state.manager.js +79 -6
  51. package/dist/cjs/managers/storage.manager.d.ts +26 -2
  52. package/dist/cjs/managers/storage.manager.js +67 -34
  53. package/dist/cjs/managers/tags.manager.d.ts +31 -7
  54. package/dist/cjs/managers/tags.manager.js +123 -241
  55. package/dist/cjs/managers/user.manager.d.ts +14 -5
  56. package/dist/cjs/managers/user.manager.js +17 -9
  57. package/dist/cjs/public-api.d.ts +10 -1
  58. package/dist/cjs/public-api.js +18 -24
  59. package/dist/cjs/test-bridge.d.ts +48 -0
  60. package/dist/cjs/test-bridge.js +110 -0
  61. package/dist/cjs/types/api.types.d.ts +21 -6
  62. package/dist/cjs/types/api.types.js +21 -6
  63. package/dist/cjs/types/config.types.d.ts +22 -84
  64. package/dist/cjs/types/emitter.types.d.ts +11 -0
  65. package/dist/cjs/types/emitter.types.js +8 -0
  66. package/dist/cjs/types/event.types.d.ts +8 -11
  67. package/dist/cjs/types/index.d.ts +3 -1
  68. package/dist/cjs/types/index.js +3 -1
  69. package/dist/cjs/types/queue.types.d.ts +1 -0
  70. package/dist/cjs/types/session.types.d.ts +0 -64
  71. package/dist/cjs/types/state.types.d.ts +1 -0
  72. package/dist/cjs/types/test-bridge.types.d.ts +38 -0
  73. package/dist/cjs/types/validation-error.types.d.ts +7 -0
  74. package/dist/cjs/types/validation-error.types.js +11 -1
  75. package/dist/cjs/types/window.types.d.ts +1 -8
  76. package/dist/cjs/utils/data/uuid.utils.d.ts +1 -1
  77. package/dist/cjs/utils/data/uuid.utils.js +7 -5
  78. package/dist/cjs/utils/emitter.utils.d.ts +8 -0
  79. package/dist/cjs/utils/emitter.utils.js +33 -0
  80. package/dist/cjs/utils/index.d.ts +1 -0
  81. package/dist/cjs/utils/index.js +1 -0
  82. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +10 -51
  83. package/dist/cjs/utils/logging/debug-logger.utils.js +36 -127
  84. package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +4 -0
  85. package/dist/cjs/utils/network/fetch-with-timeout.utils.js +25 -0
  86. package/dist/cjs/utils/network/index.d.ts +1 -0
  87. package/dist/cjs/utils/network/index.js +1 -0
  88. package/dist/cjs/utils/network/url.utils.js +2 -42
  89. package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -8
  90. package/dist/cjs/utils/security/sanitize.utils.js +7 -41
  91. package/dist/cjs/utils/validations/config-validations.utils.d.ts +7 -0
  92. package/dist/cjs/utils/validations/config-validations.utils.js +77 -22
  93. package/dist/esm/api.d.ts +33 -19
  94. package/dist/esm/api.js +105 -118
  95. package/dist/esm/app.constants.d.ts +80 -1
  96. package/dist/esm/app.constants.js +89 -1
  97. package/dist/esm/app.d.ts +29 -44
  98. package/dist/esm/app.js +115 -213
  99. package/dist/esm/app.types.d.ts +2 -7
  100. package/dist/esm/app.types.js +1 -7
  101. package/dist/esm/constants/api.constants.js +10 -4
  102. package/dist/esm/constants/config.constants.d.ts +75 -0
  103. package/dist/esm/constants/config.constants.js +174 -0
  104. package/dist/esm/constants/error.constants.d.ts +29 -0
  105. package/dist/esm/constants/error.constants.js +47 -0
  106. package/dist/esm/constants/index.d.ts +3 -6
  107. package/dist/esm/constants/index.js +3 -6
  108. package/dist/esm/constants/performance.constants.d.ts +28 -0
  109. package/dist/esm/constants/performance.constants.js +40 -0
  110. package/dist/esm/handlers/click.handler.d.ts +1 -0
  111. package/dist/esm/handlers/click.handler.js +30 -49
  112. package/dist/esm/handlers/error.handler.d.ts +11 -6
  113. package/dist/esm/handlers/error.handler.js +91 -51
  114. package/dist/esm/handlers/page-view.handler.js +38 -29
  115. package/dist/esm/handlers/performance.handler.d.ts +3 -0
  116. package/dist/esm/handlers/performance.handler.js +71 -32
  117. package/dist/esm/handlers/scroll.handler.d.ts +15 -0
  118. package/dist/esm/handlers/scroll.handler.js +106 -32
  119. package/dist/esm/handlers/session.handler.d.ts +6 -20
  120. package/dist/esm/handlers/session.handler.js +38 -326
  121. package/dist/esm/integrations/google-analytics.integration.d.ts +0 -1
  122. package/dist/esm/integrations/google-analytics.integration.js +27 -98
  123. package/dist/esm/listeners/input-listener-managers.d.ts +18 -9
  124. package/dist/esm/listeners/input-listener-managers.js +23 -32
  125. package/dist/esm/listeners/touch-listener-manager.d.ts +1 -3
  126. package/dist/esm/listeners/touch-listener-manager.js +1 -23
  127. package/dist/esm/listeners/visibility-listener-manager.d.ts +1 -4
  128. package/dist/esm/listeners/visibility-listener-manager.js +6 -42
  129. package/dist/esm/managers/api.manager.d.ts +13 -3
  130. package/dist/esm/managers/api.manager.js +34 -3
  131. package/dist/esm/managers/config.manager.d.ts +53 -3
  132. package/dist/esm/managers/config.manager.js +133 -64
  133. package/dist/esm/managers/event.manager.d.ts +57 -36
  134. package/dist/esm/managers/event.manager.js +268 -419
  135. package/dist/esm/managers/sender.manager.d.ts +40 -22
  136. package/dist/esm/managers/sender.manager.js +201 -199
  137. package/dist/esm/managers/session.manager.d.ts +80 -66
  138. package/dist/esm/managers/session.manager.js +269 -524
  139. package/dist/esm/managers/state.manager.d.ts +33 -0
  140. package/dist/esm/managers/state.manager.js +78 -6
  141. package/dist/esm/managers/storage.manager.d.ts +26 -2
  142. package/dist/esm/managers/storage.manager.js +66 -33
  143. package/dist/esm/managers/tags.manager.d.ts +31 -7
  144. package/dist/esm/managers/tags.manager.js +124 -242
  145. package/dist/esm/managers/user.manager.d.ts +14 -5
  146. package/dist/esm/managers/user.manager.js +17 -9
  147. package/dist/esm/public-api.d.ts +10 -1
  148. package/dist/esm/public-api.js +14 -1
  149. package/dist/esm/test-bridge.d.ts +48 -0
  150. package/dist/esm/test-bridge.js +106 -0
  151. package/dist/esm/types/api.types.d.ts +21 -6
  152. package/dist/esm/types/api.types.js +21 -6
  153. package/dist/esm/types/config.types.d.ts +22 -84
  154. package/dist/esm/types/emitter.types.d.ts +11 -0
  155. package/dist/esm/types/emitter.types.js +5 -0
  156. package/dist/esm/types/event.types.d.ts +8 -11
  157. package/dist/esm/types/index.d.ts +3 -1
  158. package/dist/esm/types/index.js +3 -1
  159. package/dist/esm/types/queue.types.d.ts +1 -0
  160. package/dist/esm/types/session.types.d.ts +0 -64
  161. package/dist/esm/types/state.types.d.ts +1 -0
  162. package/dist/esm/types/test-bridge.types.d.ts +38 -0
  163. package/dist/esm/types/validation-error.types.d.ts +7 -0
  164. package/dist/esm/types/validation-error.types.js +9 -0
  165. package/dist/esm/types/window.types.d.ts +1 -8
  166. package/dist/esm/utils/data/uuid.utils.d.ts +1 -1
  167. package/dist/esm/utils/data/uuid.utils.js +7 -5
  168. package/dist/esm/utils/emitter.utils.d.ts +8 -0
  169. package/dist/esm/utils/emitter.utils.js +29 -0
  170. package/dist/esm/utils/index.d.ts +1 -0
  171. package/dist/esm/utils/index.js +1 -0
  172. package/dist/esm/utils/logging/debug-logger.utils.d.ts +10 -51
  173. package/dist/esm/utils/logging/debug-logger.utils.js +36 -127
  174. package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +4 -0
  175. package/dist/esm/utils/network/fetch-with-timeout.utils.js +22 -0
  176. package/dist/esm/utils/network/index.d.ts +1 -0
  177. package/dist/esm/utils/network/index.js +1 -0
  178. package/dist/esm/utils/network/url.utils.js +2 -42
  179. package/dist/esm/utils/security/sanitize.utils.d.ts +1 -8
  180. package/dist/esm/utils/security/sanitize.utils.js +6 -39
  181. package/dist/esm/utils/validations/config-validations.utils.d.ts +7 -0
  182. package/dist/esm/utils/validations/config-validations.utils.js +76 -22
  183. package/package.json +23 -16
  184. package/dist/browser/web-vitals-CCnqwnC8.mjs +0 -198
  185. package/dist/cjs/constants/browser.constants.d.ts +0 -3
  186. package/dist/cjs/constants/browser.constants.js +0 -41
  187. package/dist/cjs/constants/initialization.constants.d.ts +0 -40
  188. package/dist/cjs/constants/initialization.constants.js +0 -48
  189. package/dist/cjs/constants/limits.constants.d.ts +0 -25
  190. package/dist/cjs/constants/limits.constants.js +0 -40
  191. package/dist/cjs/constants/security.constants.d.ts +0 -1
  192. package/dist/cjs/constants/security.constants.js +0 -12
  193. package/dist/cjs/constants/timing.constants.d.ts +0 -22
  194. package/dist/cjs/constants/timing.constants.js +0 -34
  195. package/dist/cjs/constants/validation.constants.d.ts +0 -13
  196. package/dist/cjs/constants/validation.constants.js +0 -31
  197. package/dist/cjs/handlers/network.handler.d.ts +0 -16
  198. package/dist/cjs/handlers/network.handler.js +0 -136
  199. package/dist/cjs/managers/cross-tab-session.manager.d.ts +0 -170
  200. package/dist/cjs/managers/cross-tab-session.manager.js +0 -730
  201. package/dist/cjs/managers/sampling.manager.d.ts +0 -8
  202. package/dist/cjs/managers/sampling.manager.js +0 -53
  203. package/dist/cjs/managers/session-recovery.manager.d.ts +0 -65
  204. package/dist/cjs/managers/session-recovery.manager.js +0 -237
  205. package/dist/cjs/types/web-vitals.types.d.ts +0 -6
  206. package/dist/esm/constants/browser.constants.d.ts +0 -3
  207. package/dist/esm/constants/browser.constants.js +0 -38
  208. package/dist/esm/constants/initialization.constants.d.ts +0 -40
  209. package/dist/esm/constants/initialization.constants.js +0 -45
  210. package/dist/esm/constants/limits.constants.d.ts +0 -25
  211. package/dist/esm/constants/limits.constants.js +0 -37
  212. package/dist/esm/constants/security.constants.d.ts +0 -1
  213. package/dist/esm/constants/security.constants.js +0 -9
  214. package/dist/esm/constants/timing.constants.d.ts +0 -22
  215. package/dist/esm/constants/timing.constants.js +0 -31
  216. package/dist/esm/constants/validation.constants.d.ts +0 -13
  217. package/dist/esm/constants/validation.constants.js +0 -28
  218. package/dist/esm/handlers/network.handler.d.ts +0 -16
  219. package/dist/esm/handlers/network.handler.js +0 -132
  220. package/dist/esm/managers/cross-tab-session.manager.d.ts +0 -170
  221. package/dist/esm/managers/cross-tab-session.manager.js +0 -726
  222. package/dist/esm/managers/sampling.manager.d.ts +0 -8
  223. package/dist/esm/managers/sampling.manager.js +0 -49
  224. package/dist/esm/managers/session-recovery.manager.d.ts +0 -65
  225. package/dist/esm/managers/session-recovery.manager.js +0 -233
  226. package/dist/esm/types/web-vitals.types.d.ts +0 -6
  227. /package/dist/cjs/types/{web-vitals.types.js → test-bridge.types.js} +0 -0
  228. /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 { ApiManager } from './managers/api.manager';
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 { isEventValid } from './utils/validations';
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, SCROLL_SUPPRESSION_CONSTANTS } from './constants';
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
- import { NetworkHandler } from './handlers/network.handler';
19
- import { ProjectIdValidationError } from './types/validation-error.types';
20
- import { debugLog } from './utils/logging';
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
- debugLog.info('App', 'App initialization started', { projectId: appConfig.id });
41
- this.validateAppReadiness(appConfig);
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.initStorage();
44
- await this.setState(appConfig);
45
- await this.setIntegrations();
46
- this.setEventManager();
47
- await this.initHandlers();
48
- this.isInitialized = true;
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.isInitialized = false;
55
- debugLog.error('App', 'App initialization failed', { projectId: appConfig.id, error });
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.eventManager) {
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
- debugLog.debug('App', 'Custom event validated and queued', { eventName: name, hasMetadata: !!sanitizedMetadata });
83
- this.eventManager.track({
84
- type: EventType.CUSTOM,
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
- debugLog.info('App', 'App cleanup started');
110
- if (this.googleAnalytics) {
111
- this.googleAnalytics.cleanup();
112
- }
113
- if (this.sessionHandler) {
114
- this.sessionHandler.stopTracking();
115
- }
116
- if (this.pageViewHandler) {
117
- this.pageViewHandler.stopTracking();
118
- }
119
- if (this.clickHandler) {
120
- this.clickHandler.stopTracking();
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
- if (this.eventManager) {
139
- this.eventManager.stop();
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
- debugLog.info('App', 'App cleanup completed successfully');
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
- setApiUrl(id, allowHttp = false) {
155
- const apiManager = new ApiManager();
156
- this.set('apiUrl', apiManager.getUrl(id, allowHttp));
157
- }
158
- async setConfig(appConfig) {
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(this.get('apiUrl'), appConfig);
161
- this.set('config', config);
162
- }
163
- setUserId() {
164
- const userManager = new UserManager(this.storageManager);
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
- setDevice() {
169
- const device = getDeviceType();
170
- this.set('device', device);
171
- }
172
- setPageUrl() {
173
- const initialUrl = normalizeUrl(window.location.href, this.get('config').sensitiveQueryParams);
174
- this.set('pageUrl', initialUrl);
175
- }
176
- async setIntegrations() {
177
- const isIPExcluded = this.get('config').ipExcluded;
178
- const measurementId = this.get('config').integrations?.googleAnalytics?.measurementId;
179
- if (!isIPExcluded && measurementId?.trim()) {
180
- this.googleAnalytics = new GoogleAnalyticsIntegration();
181
- await this.googleAnalytics.initialize();
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
- initNetworkHandler() {
262
- if (!this.eventManager) {
263
- throw new Error('EventManager must be initialized before NetworkHandler');
264
- }
265
- this.networkHandler = new NetworkHandler(this.eventManager);
266
- this.networkHandler.startTracking();
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
  }
@@ -1,7 +1,2 @@
1
- export * from './types/common.types';
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';
2
+ export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
@@ -1,7 +1 @@
1
- export * from './types/common.types';
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 './limits.constants';
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];