@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
@@ -1,90 +1,159 @@
1
- import { DEFAULT_API_CONFIG, DEFAULT_CONFIG } from '../constants';
1
+ import { DEFAULT_API_CONFIG, DEFAULT_CONFIG, REQUEST_TIMEOUT_MS } from '../constants';
2
2
  import { Mode, SpecialProjectId } from '../types';
3
- import { isValidUrl, sanitizeApiConfig } from '../utils';
3
+ import { sanitizeApiConfig, fetchWithTimeout, normalizeConfig } from '../utils';
4
4
  import { debugLog } from '../utils/logging';
5
+ /**
6
+ * Configuration manager responsible for loading and merging application configuration.
7
+ *
8
+ * Handles three configuration sources:
9
+ * 1. Default configuration (fallback values)
10
+ * 2. API configuration (server-side settings)
11
+ * 3. App configuration (client initialization settings)
12
+ *
13
+ * Supports special project IDs for development and testing:
14
+ * - 'skip': Bypasses all network calls, uses defaults
15
+ * - 'localhost:PORT': Loads config from local development server
16
+ */
5
17
  export class ConfigManager {
18
+ /**
19
+ * Gets complete configuration by merging default, API, and app configurations.
20
+ *
21
+ * @param apiUrl - Base URL for the configuration API
22
+ * @param appConfig - Client-side configuration from init()
23
+ * @returns Promise<Config> - Merged configuration object
24
+ */
6
25
  async get(apiUrl, appConfig) {
7
- if (appConfig.id === SpecialProjectId.HttpSkip) {
8
- debugLog.debug('ConfigManager', 'Using special project id');
9
- return this.getDefaultConfig(appConfig);
26
+ // Handle skip mode - no network calls
27
+ if (appConfig.id === SpecialProjectId.Skip) {
28
+ return this.createDefaultConfig(appConfig);
10
29
  }
11
- debugLog.debug('ConfigManager', 'Loading config from API', { apiUrl, projectId: appConfig.id });
12
- const config = await this.load(apiUrl, appConfig, appConfig.id === SpecialProjectId.HttpLocal);
13
- debugLog.info('ConfigManager', 'Config loaded successfully', {
30
+ const config = await this.loadFromApi(apiUrl, appConfig);
31
+ const { config: normalizedConfig } = normalizeConfig(config);
32
+ debugLog.info('ConfigManager', 'Configuration loaded', {
14
33
  projectId: appConfig.id,
15
- mode: config.mode,
16
- hasExcludedPaths: !!config.excludedUrlPaths?.length,
17
- hasGlobalMetadata: !!config.globalMetadata,
34
+ mode: normalizedConfig.mode,
35
+ hasTags: !!normalizedConfig.tags?.length,
36
+ hasExclusions: !!normalizedConfig.excludedUrlPaths?.length,
18
37
  });
19
- return config;
38
+ return normalizedConfig;
20
39
  }
21
- async load(apiUrl, appConfig, useLocalServer) {
40
+ /**
41
+ * Loads configuration from API and merges with app config.
42
+ */
43
+ async loadFromApi(apiUrl, appConfig) {
22
44
  try {
23
- const configUrl = useLocalServer ? `${window.location.origin}/config` : this.getUrl(apiUrl);
24
- if (!configUrl) {
25
- throw new Error('Config URL is not valid or not allowed');
26
- }
27
- const response = await fetch(configUrl, {
45
+ const configUrl = this.buildConfigUrl(apiUrl, appConfig);
46
+ const headers = this.buildHeaders(appConfig);
47
+ const response = await fetchWithTimeout(configUrl, {
28
48
  method: 'GET',
29
- headers: { 'Content-Type': 'application/json' },
49
+ headers,
50
+ timeout: REQUEST_TIMEOUT_MS,
30
51
  });
31
52
  if (!response.ok) {
32
- const error = `HTTP ${response.status}: ${response.statusText}`;
33
- debugLog.error('ConfigManager', 'Config API request failed', {
34
- status: response.status,
35
- statusText: response.statusText,
36
- configUrl,
37
- });
38
- throw new Error(error);
39
- }
40
- const rawData = await response.json();
41
- if (rawData === undefined || rawData === null || typeof rawData !== 'object' || Array.isArray(rawData)) {
42
- debugLog.error('ConfigManager', 'Invalid config API response format', {
43
- responseType: typeof rawData,
44
- isArray: Array.isArray(rawData),
45
- });
46
- throw new Error('Invalid config API response: expected object');
47
- }
48
- const safeApiConfig = sanitizeApiConfig(rawData);
49
- const apiConfig = { ...DEFAULT_API_CONFIG, ...safeApiConfig };
50
- const mergedConfig = { ...apiConfig, ...appConfig };
51
- // Check if qaMode=true is in URL and automatically set mode to 'qa'
52
- const urlParameters = new URLSearchParams(window.location.search);
53
- const isQaMode = urlParameters.get('qaMode') === 'true';
54
- if (isQaMode && !mergedConfig.mode) {
55
- mergedConfig.mode = Mode.QA;
56
- debugLog.info('ConfigManager', 'QA mode enabled via URL parameter');
53
+ throw new Error(`HTTP ${response.status}: ${response.statusText}`);
57
54
  }
58
- const errorSampling = Object.values(Mode).includes(mergedConfig.mode)
59
- ? 1
60
- : (mergedConfig.errorSampling ?? 0.1);
61
- const finalConfig = { ...mergedConfig, errorSampling };
62
- return finalConfig;
55
+ const rawData = await this.parseJsonResponse(response);
56
+ return this.mergeConfigurations(rawData, appConfig);
63
57
  }
64
58
  catch (error) {
65
59
  const errorMessage = error instanceof Error ? error.message : 'Unknown error';
66
- debugLog.error('ConfigManager', 'Failed to load config', { error: errorMessage, apiUrl });
67
- throw new Error(`Failed to load config: ${errorMessage}`);
60
+ debugLog.error('ConfigManager', 'Failed to load configuration', {
61
+ error: errorMessage,
62
+ apiUrl,
63
+ projectId: appConfig.id,
64
+ });
65
+ throw new Error(`Configuration load failed: ${errorMessage}`);
66
+ }
67
+ }
68
+ /**
69
+ * Builds the configuration URL based on project type and QA mode.
70
+ */
71
+ buildConfigUrl(apiUrl, appConfig) {
72
+ const isLocalhost = appConfig.id.startsWith(SpecialProjectId.Localhost);
73
+ if (isLocalhost) {
74
+ this.validateLocalhostProjectId(appConfig.id);
75
+ return `http://${appConfig.id}/config`;
76
+ }
77
+ const baseUrl = `${apiUrl}/config`;
78
+ const isQaMode = this.isQaModeEnabled();
79
+ return isQaMode ? `${baseUrl}?qaMode=true` : baseUrl;
80
+ }
81
+ /**
82
+ * Builds request headers based on project configuration.
83
+ */
84
+ buildHeaders(appConfig) {
85
+ const headers = {
86
+ 'Content-Type': 'application/json',
87
+ };
88
+ if (appConfig.id.startsWith(SpecialProjectId.Localhost)) {
89
+ headers['X-TraceLog-Project'] = appConfig.id;
90
+ }
91
+ return headers;
92
+ }
93
+ /**
94
+ * Parses and validates JSON response from config API.
95
+ */
96
+ async parseJsonResponse(response) {
97
+ const contentType = response.headers.get('content-type');
98
+ if (!contentType?.includes('application/json')) {
99
+ throw new Error('Invalid response content-type, expected JSON');
100
+ }
101
+ const rawData = await response.json();
102
+ if (!rawData || typeof rawData !== 'object' || Array.isArray(rawData)) {
103
+ throw new Error('Invalid response format, expected object');
68
104
  }
105
+ return rawData;
69
106
  }
70
- getUrl(apiUrl) {
71
- const urlParameters = new URLSearchParams(window.location.search);
72
- const isQaMode = urlParameters.get('qaMode') === 'true';
73
- let configUrl = `${apiUrl}/config`;
74
- if (isQaMode) {
75
- configUrl += '?qaMode=true';
107
+ /**
108
+ * Validates localhost project ID format and port range.
109
+ */
110
+ validateLocalhostProjectId(projectId) {
111
+ if (!ConfigManager.LOCALHOST_PATTERN.test(projectId)) {
112
+ throw new Error(`Invalid localhost format. Expected 'localhost:PORT', got '${projectId}'`);
76
113
  }
77
- if (!isValidUrl(configUrl)) {
78
- debugLog.clientError('ConfigManager', 'Invalid config URL provided', { configUrl });
79
- throw new Error('Config URL is not valid or not allowed');
114
+ const port = parseInt(projectId.split(':')[1], 10);
115
+ if (port < 1 || port > 65535) {
116
+ throw new Error(`Port must be between 1 and 65535, got ${port}`);
80
117
  }
81
- return configUrl;
82
118
  }
83
- getDefaultConfig(appConfig) {
84
- return DEFAULT_CONFIG({
119
+ /**
120
+ * Checks if QA mode is enabled via URL parameter.
121
+ */
122
+ isQaModeEnabled() {
123
+ const params = new URLSearchParams(window.location.search);
124
+ return params.get('qaMode') === 'true';
125
+ }
126
+ /**
127
+ * Merges API configuration with app configuration and applies mode-specific settings.
128
+ */
129
+ mergeConfigurations(rawApiConfig, appConfig) {
130
+ const safeApiConfig = sanitizeApiConfig(rawApiConfig);
131
+ const apiConfig = { ...DEFAULT_API_CONFIG, ...safeApiConfig };
132
+ const mergedConfig = DEFAULT_CONFIG({ ...appConfig, ...apiConfig });
133
+ const { config: normalizedConfig } = normalizeConfig(mergedConfig);
134
+ // Apply QA mode if enabled via URL parameter
135
+ if (this.isQaModeEnabled() && !normalizedConfig.mode) {
136
+ normalizedConfig.mode = Mode.QA;
137
+ debugLog.info('ConfigManager', 'QA mode enabled via URL parameter');
138
+ }
139
+ // Set error sampling based on mode
140
+ const errorSampling = Object.values(Mode).includes(normalizedConfig.mode)
141
+ ? 1 // Full sampling for debug/qa modes
142
+ : (normalizedConfig.errorSampling ?? 0.1); // Default sampling for production
143
+ return { ...normalizedConfig, errorSampling };
144
+ }
145
+ /**
146
+ * Creates default configuration for skip mode and fallback scenarios.
147
+ */
148
+ createDefaultConfig(appConfig) {
149
+ const defaultConfig = DEFAULT_CONFIG({
85
150
  ...appConfig,
86
151
  errorSampling: 1,
87
- ...(Object.values(SpecialProjectId).includes(appConfig.id) && { mode: Mode.DEBUG }),
152
+ ...(appConfig.id === SpecialProjectId.Skip && { mode: Mode.DEBUG }),
88
153
  });
154
+ const { config } = normalizeConfig(defaultConfig);
155
+ return config;
89
156
  }
90
157
  }
158
+ ConfigManager.LOCALHOST_PATTERN = /^localhost:\d{1,5}$/;
159
+ ConfigManager.PRODUCTION_DOMAINS = [/^https:\/\/.*\.tracelog\.app$/, /^https:\/\/.*\.tracelog\.dev$/];
@@ -1,61 +1,82 @@
1
1
  import { EventData } from '../types';
2
+ import { Emitter } from '../utils';
2
3
  import { StateManager } from './state.manager';
3
4
  import { StorageManager } from './storage.manager';
4
5
  import { GoogleAnalyticsIntegration } from '../integrations/google-analytics.integration';
6
+ /**
7
+ * EventManager - Core event tracking and queue management
8
+ *
9
+ * Responsibilities:
10
+ * - Track user events (clicks, scrolls, page views, custom events)
11
+ * - Queue events and batch send them to the analytics API
12
+ * - Handle deduplication of similar events
13
+ * - Manage event sending intervals and retry logic
14
+ * - Integrate with Google Analytics when configured
15
+ */
5
16
  export declare class EventManager extends StateManager {
6
17
  private readonly googleAnalytics;
7
- private readonly samplingManager;
8
- private readonly tagsManager;
9
18
  private readonly dataSender;
10
- private readonly storageManager;
19
+ private readonly emitter;
11
20
  private eventsQueue;
12
- private lastEvent;
13
- private eventsQueueIntervalId;
14
- private intervalActive;
15
- private failureCount;
16
- private readonly MAX_FAILURES;
17
- private circuitOpen;
18
- private circuitOpenTime;
19
- private backoffDelay;
20
- private circuitResetTimeoutId;
21
- private readonly eventFingerprints;
22
- private readonly PERSISTENCE_KEY;
23
- constructor(storeManager: StorageManager, googleAnalytics?: GoogleAnalyticsIntegration | null);
24
- track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, session_end_reason, session_start_recovered, }: Partial<EventData>): void;
21
+ private lastEventFingerprint;
22
+ private lastEventTime;
23
+ private sendIntervalId;
24
+ constructor(storeManager: StorageManager, googleAnalytics?: GoogleAnalyticsIntegration | null, emitter?: Emitter | null);
25
+ /**
26
+ * Recovers persisted events from localStorage
27
+ * Should be called after initialization to recover any events that failed to send
28
+ */
29
+ recoverPersistedEvents(): Promise<void>;
30
+ /**
31
+ * Track user events with automatic deduplication and queueing
32
+ */
33
+ track({ type, page_url, from_page_url, scroll_data, click_data, custom_event, web_vitals, error_data, session_end_reason, session_start_recovered, }: Partial<EventData>): void;
25
34
  stop(): void;
26
- private processAndSend;
27
- private trackGoogleAnalyticsEvent;
28
- private initEventsQueueInterval;
35
+ /**
36
+ * Flush all queued events immediately (async)
37
+ */
29
38
  flushImmediately(): Promise<boolean>;
39
+ /**
40
+ * Flush all queued events immediately (sync)
41
+ */
30
42
  flushImmediatelySync(): boolean;
43
+ /**
44
+ * Queue management and sending intervals
45
+ */
31
46
  getQueueLength(): number;
32
- private sendEventsQueue;
33
- private buildEventsPayload;
34
- private clearQueueInterval;
35
- private getEventFingerprint;
36
- private isDuplicatedEvent;
47
+ private clearSendInterval;
37
48
  /**
38
- * Cleans up old fingerprints to prevent memory leaks
49
+ * Shared flush implementation for both sync and async modes
39
50
  */
40
- private cleanupOldFingerprints;
51
+ private flushEvents;
41
52
  /**
42
- * Opens the circuit breaker with time-based recovery and event persistence
53
+ * Send queued events to the API
43
54
  */
44
- private openCircuitBreaker;
55
+ private sendEventsQueue;
45
56
  /**
46
- * Resets the circuit breaker and attempts to restore persisted events
57
+ * Build the payload for sending events to the API
58
+ * Includes basic deduplication and sorting
47
59
  */
48
- private resetCircuitBreaker;
60
+ private buildEventsPayload;
49
61
  /**
50
- * Persists current events queue to localStorage for recovery
62
+ * Helper methods for event processing
51
63
  */
52
- private persistEventsToStorage;
64
+ private buildEventPayload;
65
+ private isEventExcluded;
66
+ private isDuplicateEvent;
67
+ private createEventFingerprint;
68
+ private createEventSignature;
69
+ private addToQueue;
70
+ private startSendInterval;
71
+ private handleGoogleAnalyticsIntegration;
72
+ private shouldSample;
73
+ private removeProcessedEvents;
53
74
  /**
54
- * Restores events from localStorage if available and not expired
75
+ * Emit event for external listeners
55
76
  */
56
- private restoreEventsFromStorage;
77
+ private emitEvent;
57
78
  /**
58
- * Clears persisted events from localStorage
79
+ * Emit events queue for external listeners
59
80
  */
60
- private clearPersistedEvents;
81
+ private emitEventsQueue;
61
82
  }