@tracelog/lib 0.11.2 → 0.11.4

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 (539) hide show
  1. package/dist/browser/tracelog.esm.js +308 -251
  2. package/dist/browser/tracelog.esm.js.map +1 -1
  3. package/dist/browser/tracelog.js +2 -2
  4. package/dist/browser/tracelog.js.map +1 -1
  5. package/dist/public-api.cjs +4427 -0
  6. package/dist/public-api.cjs.map +1 -0
  7. package/dist/public-api.d.mts +913 -0
  8. package/dist/public-api.d.ts +913 -0
  9. package/dist/public-api.js +4388 -0
  10. package/dist/public-api.js.map +1 -0
  11. package/package.json +17 -18
  12. package/dist/cjs/api.d.ts +0 -19
  13. package/dist/cjs/api.d.ts.map +0 -1
  14. package/dist/cjs/api.js +0 -183
  15. package/dist/cjs/api.js.map +0 -1
  16. package/dist/cjs/app.constants.d.ts +0 -80
  17. package/dist/cjs/app.constants.d.ts.map +0 -1
  18. package/dist/cjs/app.constants.js +0 -94
  19. package/dist/cjs/app.constants.js.map +0 -1
  20. package/dist/cjs/app.d.ts +0 -43
  21. package/dist/cjs/app.d.ts.map +0 -1
  22. package/dist/cjs/app.js +0 -165
  23. package/dist/cjs/app.js.map +0 -1
  24. package/dist/cjs/constants/config.constants.d.ts +0 -109
  25. package/dist/cjs/constants/config.constants.d.ts.map +0 -1
  26. package/dist/cjs/constants/config.constants.js +0 -216
  27. package/dist/cjs/constants/config.constants.js.map +0 -1
  28. package/dist/cjs/constants/error.constants.d.ts +0 -56
  29. package/dist/cjs/constants/error.constants.d.ts.map +0 -1
  30. package/dist/cjs/constants/error.constants.js +0 -89
  31. package/dist/cjs/constants/error.constants.js.map +0 -1
  32. package/dist/cjs/constants/index.d.ts +0 -5
  33. package/dist/cjs/constants/index.d.ts.map +0 -1
  34. package/dist/cjs/constants/index.js +0 -21
  35. package/dist/cjs/constants/index.js.map +0 -1
  36. package/dist/cjs/constants/performance.constants.d.ts +0 -29
  37. package/dist/cjs/constants/performance.constants.d.ts.map +0 -1
  38. package/dist/cjs/constants/performance.constants.js +0 -44
  39. package/dist/cjs/constants/performance.constants.js.map +0 -1
  40. package/dist/cjs/constants/storage.constants.d.ts +0 -11
  41. package/dist/cjs/constants/storage.constants.d.ts.map +0 -1
  42. package/dist/cjs/constants/storage.constants.js +0 -23
  43. package/dist/cjs/constants/storage.constants.js.map +0 -1
  44. package/dist/cjs/handlers/click.handler.d.ts +0 -36
  45. package/dist/cjs/handlers/click.handler.d.ts.map +0 -1
  46. package/dist/cjs/handlers/click.handler.js +0 -263
  47. package/dist/cjs/handlers/click.handler.js.map +0 -1
  48. package/dist/cjs/handlers/error.handler.d.ts +0 -28
  49. package/dist/cjs/handlers/error.handler.d.ts.map +0 -1
  50. package/dist/cjs/handlers/error.handler.js +0 -168
  51. package/dist/cjs/handlers/error.handler.js.map +0 -1
  52. package/dist/cjs/handlers/page-view.handler.d.ts +0 -17
  53. package/dist/cjs/handlers/page-view.handler.d.ts.map +0 -1
  54. package/dist/cjs/handlers/page-view.handler.js +0 -100
  55. package/dist/cjs/handlers/page-view.handler.js.map +0 -1
  56. package/dist/cjs/handlers/performance.handler.d.ts +0 -23
  57. package/dist/cjs/handlers/performance.handler.d.ts.map +0 -1
  58. package/dist/cjs/handlers/performance.handler.js +0 -274
  59. package/dist/cjs/handlers/performance.handler.js.map +0 -1
  60. package/dist/cjs/handlers/scroll.handler.d.ts +0 -40
  61. package/dist/cjs/handlers/scroll.handler.d.ts.map +0 -1
  62. package/dist/cjs/handlers/scroll.handler.js +0 -327
  63. package/dist/cjs/handlers/scroll.handler.js.map +0 -1
  64. package/dist/cjs/handlers/session.handler.d.ts +0 -16
  65. package/dist/cjs/handlers/session.handler.d.ts.map +0 -1
  66. package/dist/cjs/handlers/session.handler.js +0 -74
  67. package/dist/cjs/handlers/session.handler.js.map +0 -1
  68. package/dist/cjs/handlers/viewport.handler.d.ts +0 -44
  69. package/dist/cjs/handlers/viewport.handler.d.ts.map +0 -1
  70. package/dist/cjs/handlers/viewport.handler.js +0 -286
  71. package/dist/cjs/handlers/viewport.handler.js.map +0 -1
  72. package/dist/cjs/integrations/google-analytics.integration.d.ts +0 -18
  73. package/dist/cjs/integrations/google-analytics.integration.d.ts.map +0 -1
  74. package/dist/cjs/integrations/google-analytics.integration.js +0 -90
  75. package/dist/cjs/integrations/google-analytics.integration.js.map +0 -1
  76. package/dist/cjs/listeners/activity-listener-manager.d.ts +0 -9
  77. package/dist/cjs/listeners/activity-listener-manager.d.ts.map +0 -1
  78. package/dist/cjs/listeners/activity-listener-manager.js +0 -33
  79. package/dist/cjs/listeners/activity-listener-manager.js.map +0 -1
  80. package/dist/cjs/listeners/index.d.ts +0 -7
  81. package/dist/cjs/listeners/index.d.ts.map +0 -1
  82. package/dist/cjs/listeners/index.js +0 -15
  83. package/dist/cjs/listeners/index.js.map +0 -1
  84. package/dist/cjs/listeners/input-listener-managers.d.ts +0 -25
  85. package/dist/cjs/listeners/input-listener-managers.d.ts.map +0 -1
  86. package/dist/cjs/listeners/input-listener-managers.js +0 -50
  87. package/dist/cjs/listeners/input-listener-managers.js.map +0 -1
  88. package/dist/cjs/listeners/listeners.types.d.ts +0 -5
  89. package/dist/cjs/listeners/listeners.types.d.ts.map +0 -1
  90. package/dist/cjs/listeners/listeners.types.js +0 -3
  91. package/dist/cjs/listeners/listeners.types.js.map +0 -1
  92. package/dist/cjs/listeners/touch-listener-manager.d.ts +0 -9
  93. package/dist/cjs/listeners/touch-listener-manager.d.ts.map +0 -1
  94. package/dist/cjs/listeners/touch-listener-manager.js +0 -35
  95. package/dist/cjs/listeners/touch-listener-manager.js.map +0 -1
  96. package/dist/cjs/listeners/unload-listener-manager.d.ts +0 -9
  97. package/dist/cjs/listeners/unload-listener-manager.d.ts.map +0 -1
  98. package/dist/cjs/listeners/unload-listener-manager.js +0 -31
  99. package/dist/cjs/listeners/unload-listener-manager.js.map +0 -1
  100. package/dist/cjs/listeners/visibility-listener-manager.d.ts +0 -10
  101. package/dist/cjs/listeners/visibility-listener-manager.d.ts.map +0 -1
  102. package/dist/cjs/listeners/visibility-listener-manager.js +0 -48
  103. package/dist/cjs/listeners/visibility-listener-manager.js.map +0 -1
  104. package/dist/cjs/managers/event.manager.d.ts +0 -62
  105. package/dist/cjs/managers/event.manager.d.ts.map +0 -1
  106. package/dist/cjs/managers/event.manager.js +0 -508
  107. package/dist/cjs/managers/event.manager.js.map +0 -1
  108. package/dist/cjs/managers/sender.manager.d.ts +0 -32
  109. package/dist/cjs/managers/sender.manager.d.ts.map +0 -1
  110. package/dist/cjs/managers/sender.manager.js +0 -271
  111. package/dist/cjs/managers/sender.manager.js.map +0 -1
  112. package/dist/cjs/managers/session.manager.d.ts +0 -40
  113. package/dist/cjs/managers/session.manager.d.ts.map +0 -1
  114. package/dist/cjs/managers/session.manager.js +0 -282
  115. package/dist/cjs/managers/session.manager.js.map +0 -1
  116. package/dist/cjs/managers/state.manager.d.ts +0 -9
  117. package/dist/cjs/managers/state.manager.d.ts.map +0 -1
  118. package/dist/cjs/managers/state.manager.js +0 -27
  119. package/dist/cjs/managers/state.manager.js.map +0 -1
  120. package/dist/cjs/managers/storage.manager.d.ts +0 -60
  121. package/dist/cjs/managers/storage.manager.d.ts.map +0 -1
  122. package/dist/cjs/managers/storage.manager.js +0 -277
  123. package/dist/cjs/managers/storage.manager.js.map +0 -1
  124. package/dist/cjs/managers/user.manager.d.ts +0 -17
  125. package/dist/cjs/managers/user.manager.d.ts.map +0 -1
  126. package/dist/cjs/managers/user.manager.js +0 -31
  127. package/dist/cjs/managers/user.manager.js.map +0 -1
  128. package/dist/cjs/public-api.d.ts +0 -11
  129. package/dist/cjs/public-api.d.ts.map +0 -1
  130. package/dist/cjs/public-api.js +0 -32
  131. package/dist/cjs/public-api.js.map +0 -1
  132. package/dist/cjs/test-bridge.d.ts +0 -47
  133. package/dist/cjs/test-bridge.d.ts.map +0 -1
  134. package/dist/cjs/test-bridge.js +0 -165
  135. package/dist/cjs/test-bridge.js.map +0 -1
  136. package/dist/cjs/types/common.types.d.ts +0 -6
  137. package/dist/cjs/types/common.types.d.ts.map +0 -1
  138. package/dist/cjs/types/common.types.js +0 -3
  139. package/dist/cjs/types/common.types.js.map +0 -1
  140. package/dist/cjs/types/config.types.d.ts +0 -49
  141. package/dist/cjs/types/config.types.d.ts.map +0 -1
  142. package/dist/cjs/types/config.types.js +0 -9
  143. package/dist/cjs/types/config.types.js.map +0 -1
  144. package/dist/cjs/types/device.types.d.ts +0 -7
  145. package/dist/cjs/types/device.types.d.ts.map +0 -1
  146. package/dist/cjs/types/device.types.js +0 -11
  147. package/dist/cjs/types/device.types.js.map +0 -1
  148. package/dist/cjs/types/emitter.types.d.ts +0 -12
  149. package/dist/cjs/types/emitter.types.d.ts.map +0 -1
  150. package/dist/cjs/types/emitter.types.js +0 -9
  151. package/dist/cjs/types/emitter.types.js.map +0 -1
  152. package/dist/cjs/types/error.types.d.ts +0 -12
  153. package/dist/cjs/types/error.types.d.ts.map +0 -1
  154. package/dist/cjs/types/error.types.js +0 -23
  155. package/dist/cjs/types/error.types.js.map +0 -1
  156. package/dist/cjs/types/event.types.d.ts +0 -235
  157. package/dist/cjs/types/event.types.d.ts.map +0 -1
  158. package/dist/cjs/types/event.types.js +0 -48
  159. package/dist/cjs/types/event.types.js.map +0 -1
  160. package/dist/cjs/types/index.d.ts +0 -17
  161. package/dist/cjs/types/index.d.ts.map +0 -1
  162. package/dist/cjs/types/index.js +0 -33
  163. package/dist/cjs/types/index.js.map +0 -1
  164. package/dist/cjs/types/log.types.d.ts +0 -5
  165. package/dist/cjs/types/log.types.d.ts.map +0 -1
  166. package/dist/cjs/types/log.types.js +0 -3
  167. package/dist/cjs/types/log.types.js.map +0 -1
  168. package/dist/cjs/types/mode.types.d.ts +0 -7
  169. package/dist/cjs/types/mode.types.d.ts.map +0 -1
  170. package/dist/cjs/types/mode.types.js +0 -11
  171. package/dist/cjs/types/mode.types.js.map +0 -1
  172. package/dist/cjs/types/queue.types.d.ts +0 -19
  173. package/dist/cjs/types/queue.types.d.ts.map +0 -1
  174. package/dist/cjs/types/queue.types.js +0 -3
  175. package/dist/cjs/types/queue.types.js.map +0 -1
  176. package/dist/cjs/types/scroll.types.d.ts +0 -16
  177. package/dist/cjs/types/scroll.types.d.ts.map +0 -1
  178. package/dist/cjs/types/scroll.types.js +0 -12
  179. package/dist/cjs/types/scroll.types.js.map +0 -1
  180. package/dist/cjs/types/session.types.d.ts +0 -2
  181. package/dist/cjs/types/session.types.d.ts.map +0 -1
  182. package/dist/cjs/types/session.types.js +0 -3
  183. package/dist/cjs/types/session.types.js.map +0 -1
  184. package/dist/cjs/types/state.types.d.ts +0 -16
  185. package/dist/cjs/types/state.types.d.ts.map +0 -1
  186. package/dist/cjs/types/state.types.js +0 -3
  187. package/dist/cjs/types/state.types.js.map +0 -1
  188. package/dist/cjs/types/test-bridge.types.d.ts +0 -40
  189. package/dist/cjs/types/test-bridge.types.d.ts.map +0 -1
  190. package/dist/cjs/types/test-bridge.types.js +0 -3
  191. package/dist/cjs/types/test-bridge.types.js.map +0 -1
  192. package/dist/cjs/types/validation-error.types.d.ts +0 -44
  193. package/dist/cjs/types/validation-error.types.d.ts.map +0 -1
  194. package/dist/cjs/types/validation-error.types.js +0 -70
  195. package/dist/cjs/types/validation-error.types.js.map +0 -1
  196. package/dist/cjs/types/viewport.types.d.ts +0 -55
  197. package/dist/cjs/types/viewport.types.d.ts.map +0 -1
  198. package/dist/cjs/types/viewport.types.js +0 -3
  199. package/dist/cjs/types/viewport.types.js.map +0 -1
  200. package/dist/cjs/types/window.types.d.ts +0 -16
  201. package/dist/cjs/types/window.types.d.ts.map +0 -1
  202. package/dist/cjs/types/window.types.js +0 -3
  203. package/dist/cjs/types/window.types.js.map +0 -1
  204. package/dist/cjs/utils/browser/device-detector.utils.d.ts +0 -7
  205. package/dist/cjs/utils/browser/device-detector.utils.d.ts.map +0 -1
  206. package/dist/cjs/utils/browser/device-detector.utils.js +0 -50
  207. package/dist/cjs/utils/browser/device-detector.utils.js.map +0 -1
  208. package/dist/cjs/utils/browser/index.d.ts +0 -4
  209. package/dist/cjs/utils/browser/index.d.ts.map +0 -1
  210. package/dist/cjs/utils/browser/index.js +0 -20
  211. package/dist/cjs/utils/browser/index.js.map +0 -1
  212. package/dist/cjs/utils/browser/qa-mode.utils.d.ts +0 -14
  213. package/dist/cjs/utils/browser/qa-mode.utils.d.ts.map +0 -1
  214. package/dist/cjs/utils/browser/qa-mode.utils.js +0 -44
  215. package/dist/cjs/utils/browser/qa-mode.utils.js.map +0 -1
  216. package/dist/cjs/utils/browser/utm-params.utils.d.ts +0 -7
  217. package/dist/cjs/utils/browser/utm-params.utils.d.ts.map +0 -1
  218. package/dist/cjs/utils/browser/utm-params.utils.js +0 -23
  219. package/dist/cjs/utils/browser/utm-params.utils.js.map +0 -1
  220. package/dist/cjs/utils/data/index.d.ts +0 -2
  221. package/dist/cjs/utils/data/index.d.ts.map +0 -1
  222. package/dist/cjs/utils/data/index.js +0 -18
  223. package/dist/cjs/utils/data/index.js.map +0 -1
  224. package/dist/cjs/utils/data/uuid.utils.d.ts +0 -19
  225. package/dist/cjs/utils/data/uuid.utils.d.ts.map +0 -1
  226. package/dist/cjs/utils/data/uuid.utils.js +0 -57
  227. package/dist/cjs/utils/data/uuid.utils.js.map +0 -1
  228. package/dist/cjs/utils/emitter.utils.d.ts +0 -9
  229. package/dist/cjs/utils/emitter.utils.d.ts.map +0 -1
  230. package/dist/cjs/utils/emitter.utils.js +0 -36
  231. package/dist/cjs/utils/emitter.utils.js.map +0 -1
  232. package/dist/cjs/utils/index.d.ts +0 -8
  233. package/dist/cjs/utils/index.d.ts.map +0 -1
  234. package/dist/cjs/utils/index.js +0 -24
  235. package/dist/cjs/utils/index.js.map +0 -1
  236. package/dist/cjs/utils/logging.utils.d.ts +0 -22
  237. package/dist/cjs/utils/logging.utils.d.ts.map +0 -1
  238. package/dist/cjs/utils/logging.utils.js +0 -87
  239. package/dist/cjs/utils/logging.utils.js.map +0 -1
  240. package/dist/cjs/utils/network/index.d.ts +0 -2
  241. package/dist/cjs/utils/network/index.d.ts.map +0 -1
  242. package/dist/cjs/utils/network/index.js +0 -18
  243. package/dist/cjs/utils/network/index.js.map +0 -1
  244. package/dist/cjs/utils/network/url.utils.d.ts +0 -16
  245. package/dist/cjs/utils/network/url.utils.d.ts.map +0 -1
  246. package/dist/cjs/utils/network/url.utils.js +0 -92
  247. package/dist/cjs/utils/network/url.utils.js.map +0 -1
  248. package/dist/cjs/utils/security/index.d.ts +0 -2
  249. package/dist/cjs/utils/security/index.d.ts.map +0 -1
  250. package/dist/cjs/utils/security/index.js +0 -18
  251. package/dist/cjs/utils/security/index.js.map +0 -1
  252. package/dist/cjs/utils/security/sanitize.utils.d.ts +0 -14
  253. package/dist/cjs/utils/security/sanitize.utils.d.ts.map +0 -1
  254. package/dist/cjs/utils/security/sanitize.utils.js +0 -123
  255. package/dist/cjs/utils/security/sanitize.utils.js.map +0 -1
  256. package/dist/cjs/utils/validations/config-validations.utils.d.ts +0 -19
  257. package/dist/cjs/utils/validations/config-validations.utils.d.ts.map +0 -1
  258. package/dist/cjs/utils/validations/config-validations.utils.js +0 -236
  259. package/dist/cjs/utils/validations/config-validations.utils.js.map +0 -1
  260. package/dist/cjs/utils/validations/event-validations.utils.d.ts +0 -13
  261. package/dist/cjs/utils/validations/event-validations.utils.d.ts.map +0 -1
  262. package/dist/cjs/utils/validations/event-validations.utils.js +0 -37
  263. package/dist/cjs/utils/validations/event-validations.utils.js.map +0 -1
  264. package/dist/cjs/utils/validations/index.d.ts +0 -5
  265. package/dist/cjs/utils/validations/index.d.ts.map +0 -1
  266. package/dist/cjs/utils/validations/index.js +0 -21
  267. package/dist/cjs/utils/validations/index.js.map +0 -1
  268. package/dist/cjs/utils/validations/metadata-validations.utils.d.ts +0 -23
  269. package/dist/cjs/utils/validations/metadata-validations.utils.d.ts.map +0 -1
  270. package/dist/cjs/utils/validations/metadata-validations.utils.js +0 -153
  271. package/dist/cjs/utils/validations/metadata-validations.utils.js.map +0 -1
  272. package/dist/cjs/utils/validations/type-guards.utils.d.ts +0 -9
  273. package/dist/cjs/utils/validations/type-guards.utils.d.ts.map +0 -1
  274. package/dist/cjs/utils/validations/type-guards.utils.js +0 -90
  275. package/dist/cjs/utils/validations/type-guards.utils.js.map +0 -1
  276. package/dist/esm/api.d.ts +0 -19
  277. package/dist/esm/api.d.ts.map +0 -1
  278. package/dist/esm/api.js +0 -173
  279. package/dist/esm/api.js.map +0 -1
  280. package/dist/esm/app.constants.d.ts +0 -80
  281. package/dist/esm/app.constants.d.ts.map +0 -1
  282. package/dist/esm/app.constants.js +0 -82
  283. package/dist/esm/app.constants.js.map +0 -1
  284. package/dist/esm/app.d.ts +0 -43
  285. package/dist/esm/app.d.ts.map +0 -1
  286. package/dist/esm/app.js +0 -161
  287. package/dist/esm/app.js.map +0 -1
  288. package/dist/esm/constants/config.constants.d.ts +0 -109
  289. package/dist/esm/constants/config.constants.d.ts.map +0 -1
  290. package/dist/esm/constants/config.constants.js +0 -212
  291. package/dist/esm/constants/config.constants.js.map +0 -1
  292. package/dist/esm/constants/error.constants.d.ts +0 -56
  293. package/dist/esm/constants/error.constants.d.ts.map +0 -1
  294. package/dist/esm/constants/error.constants.js +0 -86
  295. package/dist/esm/constants/error.constants.js.map +0 -1
  296. package/dist/esm/constants/index.d.ts +0 -5
  297. package/dist/esm/constants/index.d.ts.map +0 -1
  298. package/dist/esm/constants/index.js +0 -5
  299. package/dist/esm/constants/index.js.map +0 -1
  300. package/dist/esm/constants/performance.constants.d.ts +0 -29
  301. package/dist/esm/constants/performance.constants.d.ts.map +0 -1
  302. package/dist/esm/constants/performance.constants.js +0 -41
  303. package/dist/esm/constants/performance.constants.js.map +0 -1
  304. package/dist/esm/constants/storage.constants.d.ts +0 -11
  305. package/dist/esm/constants/storage.constants.d.ts.map +0 -1
  306. package/dist/esm/constants/storage.constants.js +0 -13
  307. package/dist/esm/constants/storage.constants.js.map +0 -1
  308. package/dist/esm/handlers/click.handler.d.ts +0 -36
  309. package/dist/esm/handlers/click.handler.d.ts.map +0 -1
  310. package/dist/esm/handlers/click.handler.js +0 -259
  311. package/dist/esm/handlers/click.handler.js.map +0 -1
  312. package/dist/esm/handlers/error.handler.d.ts +0 -28
  313. package/dist/esm/handlers/error.handler.d.ts.map +0 -1
  314. package/dist/esm/handlers/error.handler.js +0 -164
  315. package/dist/esm/handlers/error.handler.js.map +0 -1
  316. package/dist/esm/handlers/page-view.handler.d.ts +0 -17
  317. package/dist/esm/handlers/page-view.handler.d.ts.map +0 -1
  318. package/dist/esm/handlers/page-view.handler.js +0 -96
  319. package/dist/esm/handlers/page-view.handler.js.map +0 -1
  320. package/dist/esm/handlers/performance.handler.d.ts +0 -23
  321. package/dist/esm/handlers/performance.handler.d.ts.map +0 -1
  322. package/dist/esm/handlers/performance.handler.js +0 -237
  323. package/dist/esm/handlers/performance.handler.js.map +0 -1
  324. package/dist/esm/handlers/scroll.handler.d.ts +0 -40
  325. package/dist/esm/handlers/scroll.handler.d.ts.map +0 -1
  326. package/dist/esm/handlers/scroll.handler.js +0 -323
  327. package/dist/esm/handlers/scroll.handler.js.map +0 -1
  328. package/dist/esm/handlers/session.handler.d.ts +0 -16
  329. package/dist/esm/handlers/session.handler.d.ts.map +0 -1
  330. package/dist/esm/handlers/session.handler.js +0 -70
  331. package/dist/esm/handlers/session.handler.js.map +0 -1
  332. package/dist/esm/handlers/viewport.handler.d.ts +0 -44
  333. package/dist/esm/handlers/viewport.handler.d.ts.map +0 -1
  334. package/dist/esm/handlers/viewport.handler.js +0 -282
  335. package/dist/esm/handlers/viewport.handler.js.map +0 -1
  336. package/dist/esm/integrations/google-analytics.integration.d.ts +0 -18
  337. package/dist/esm/integrations/google-analytics.integration.d.ts.map +0 -1
  338. package/dist/esm/integrations/google-analytics.integration.js +0 -86
  339. package/dist/esm/integrations/google-analytics.integration.js.map +0 -1
  340. package/dist/esm/listeners/activity-listener-manager.d.ts +0 -9
  341. package/dist/esm/listeners/activity-listener-manager.d.ts.map +0 -1
  342. package/dist/esm/listeners/activity-listener-manager.js +0 -29
  343. package/dist/esm/listeners/activity-listener-manager.js.map +0 -1
  344. package/dist/esm/listeners/index.d.ts +0 -7
  345. package/dist/esm/listeners/index.d.ts.map +0 -1
  346. package/dist/esm/listeners/index.js +0 -6
  347. package/dist/esm/listeners/index.js.map +0 -1
  348. package/dist/esm/listeners/input-listener-managers.d.ts +0 -25
  349. package/dist/esm/listeners/input-listener-managers.d.ts.map +0 -1
  350. package/dist/esm/listeners/input-listener-managers.js +0 -45
  351. package/dist/esm/listeners/input-listener-managers.js.map +0 -1
  352. package/dist/esm/listeners/listeners.types.d.ts +0 -5
  353. package/dist/esm/listeners/listeners.types.d.ts.map +0 -1
  354. package/dist/esm/listeners/listeners.types.js +0 -2
  355. package/dist/esm/listeners/listeners.types.js.map +0 -1
  356. package/dist/esm/listeners/touch-listener-manager.d.ts +0 -9
  357. package/dist/esm/listeners/touch-listener-manager.d.ts.map +0 -1
  358. package/dist/esm/listeners/touch-listener-manager.js +0 -31
  359. package/dist/esm/listeners/touch-listener-manager.js.map +0 -1
  360. package/dist/esm/listeners/unload-listener-manager.d.ts +0 -9
  361. package/dist/esm/listeners/unload-listener-manager.d.ts.map +0 -1
  362. package/dist/esm/listeners/unload-listener-manager.js +0 -27
  363. package/dist/esm/listeners/unload-listener-manager.js.map +0 -1
  364. package/dist/esm/listeners/visibility-listener-manager.d.ts +0 -10
  365. package/dist/esm/listeners/visibility-listener-manager.d.ts.map +0 -1
  366. package/dist/esm/listeners/visibility-listener-manager.js +0 -44
  367. package/dist/esm/listeners/visibility-listener-manager.js.map +0 -1
  368. package/dist/esm/managers/event.manager.d.ts +0 -62
  369. package/dist/esm/managers/event.manager.d.ts.map +0 -1
  370. package/dist/esm/managers/event.manager.js +0 -504
  371. package/dist/esm/managers/event.manager.js.map +0 -1
  372. package/dist/esm/managers/sender.manager.d.ts +0 -32
  373. package/dist/esm/managers/sender.manager.d.ts.map +0 -1
  374. package/dist/esm/managers/sender.manager.js +0 -267
  375. package/dist/esm/managers/sender.manager.js.map +0 -1
  376. package/dist/esm/managers/session.manager.d.ts +0 -40
  377. package/dist/esm/managers/session.manager.d.ts.map +0 -1
  378. package/dist/esm/managers/session.manager.js +0 -278
  379. package/dist/esm/managers/session.manager.js.map +0 -1
  380. package/dist/esm/managers/state.manager.d.ts +0 -9
  381. package/dist/esm/managers/state.manager.d.ts.map +0 -1
  382. package/dist/esm/managers/state.manager.js +0 -21
  383. package/dist/esm/managers/state.manager.js.map +0 -1
  384. package/dist/esm/managers/storage.manager.d.ts +0 -60
  385. package/dist/esm/managers/storage.manager.d.ts.map +0 -1
  386. package/dist/esm/managers/storage.manager.js +0 -273
  387. package/dist/esm/managers/storage.manager.js.map +0 -1
  388. package/dist/esm/managers/user.manager.d.ts +0 -17
  389. package/dist/esm/managers/user.manager.d.ts.map +0 -1
  390. package/dist/esm/managers/user.manager.js +0 -27
  391. package/dist/esm/managers/user.manager.js.map +0 -1
  392. package/dist/esm/public-api.d.ts +0 -11
  393. package/dist/esm/public-api.d.ts.map +0 -1
  394. package/dist/esm/public-api.js +0 -15
  395. package/dist/esm/public-api.js.map +0 -1
  396. package/dist/esm/test-bridge.d.ts +0 -47
  397. package/dist/esm/test-bridge.d.ts.map +0 -1
  398. package/dist/esm/test-bridge.js +0 -161
  399. package/dist/esm/test-bridge.js.map +0 -1
  400. package/dist/esm/types/common.types.d.ts +0 -6
  401. package/dist/esm/types/common.types.d.ts.map +0 -1
  402. package/dist/esm/types/common.types.js +0 -2
  403. package/dist/esm/types/common.types.js.map +0 -1
  404. package/dist/esm/types/config.types.d.ts +0 -49
  405. package/dist/esm/types/config.types.d.ts.map +0 -1
  406. package/dist/esm/types/config.types.js +0 -6
  407. package/dist/esm/types/config.types.js.map +0 -1
  408. package/dist/esm/types/device.types.d.ts +0 -7
  409. package/dist/esm/types/device.types.d.ts.map +0 -1
  410. package/dist/esm/types/device.types.js +0 -8
  411. package/dist/esm/types/device.types.js.map +0 -1
  412. package/dist/esm/types/emitter.types.d.ts +0 -12
  413. package/dist/esm/types/emitter.types.d.ts.map +0 -1
  414. package/dist/esm/types/emitter.types.js +0 -6
  415. package/dist/esm/types/emitter.types.js.map +0 -1
  416. package/dist/esm/types/error.types.d.ts +0 -12
  417. package/dist/esm/types/error.types.d.ts.map +0 -1
  418. package/dist/esm/types/error.types.js +0 -19
  419. package/dist/esm/types/error.types.js.map +0 -1
  420. package/dist/esm/types/event.types.d.ts +0 -235
  421. package/dist/esm/types/event.types.d.ts.map +0 -1
  422. package/dist/esm/types/event.types.js +0 -45
  423. package/dist/esm/types/event.types.js.map +0 -1
  424. package/dist/esm/types/index.d.ts +0 -17
  425. package/dist/esm/types/index.d.ts.map +0 -1
  426. package/dist/esm/types/index.js +0 -17
  427. package/dist/esm/types/index.js.map +0 -1
  428. package/dist/esm/types/log.types.d.ts +0 -5
  429. package/dist/esm/types/log.types.d.ts.map +0 -1
  430. package/dist/esm/types/log.types.js +0 -2
  431. package/dist/esm/types/log.types.js.map +0 -1
  432. package/dist/esm/types/mode.types.d.ts +0 -7
  433. package/dist/esm/types/mode.types.d.ts.map +0 -1
  434. package/dist/esm/types/mode.types.js +0 -8
  435. package/dist/esm/types/mode.types.js.map +0 -1
  436. package/dist/esm/types/queue.types.d.ts +0 -19
  437. package/dist/esm/types/queue.types.d.ts.map +0 -1
  438. package/dist/esm/types/queue.types.js +0 -2
  439. package/dist/esm/types/queue.types.js.map +0 -1
  440. package/dist/esm/types/scroll.types.d.ts +0 -16
  441. package/dist/esm/types/scroll.types.d.ts.map +0 -1
  442. package/dist/esm/types/scroll.types.js +0 -8
  443. package/dist/esm/types/scroll.types.js.map +0 -1
  444. package/dist/esm/types/session.types.d.ts +0 -2
  445. package/dist/esm/types/session.types.d.ts.map +0 -1
  446. package/dist/esm/types/session.types.js +0 -2
  447. package/dist/esm/types/session.types.js.map +0 -1
  448. package/dist/esm/types/state.types.d.ts +0 -16
  449. package/dist/esm/types/state.types.d.ts.map +0 -1
  450. package/dist/esm/types/state.types.js +0 -2
  451. package/dist/esm/types/state.types.js.map +0 -1
  452. package/dist/esm/types/test-bridge.types.d.ts +0 -40
  453. package/dist/esm/types/test-bridge.types.d.ts.map +0 -1
  454. package/dist/esm/types/test-bridge.types.js +0 -2
  455. package/dist/esm/types/test-bridge.types.js.map +0 -1
  456. package/dist/esm/types/validation-error.types.d.ts +0 -44
  457. package/dist/esm/types/validation-error.types.d.ts.map +0 -1
  458. package/dist/esm/types/validation-error.types.js +0 -61
  459. package/dist/esm/types/validation-error.types.js.map +0 -1
  460. package/dist/esm/types/viewport.types.d.ts +0 -55
  461. package/dist/esm/types/viewport.types.d.ts.map +0 -1
  462. package/dist/esm/types/viewport.types.js +0 -2
  463. package/dist/esm/types/viewport.types.js.map +0 -1
  464. package/dist/esm/types/window.types.d.ts +0 -16
  465. package/dist/esm/types/window.types.d.ts.map +0 -1
  466. package/dist/esm/types/window.types.js +0 -2
  467. package/dist/esm/types/window.types.js.map +0 -1
  468. package/dist/esm/utils/browser/device-detector.utils.d.ts +0 -7
  469. package/dist/esm/utils/browser/device-detector.utils.d.ts.map +0 -1
  470. package/dist/esm/utils/browser/device-detector.utils.js +0 -46
  471. package/dist/esm/utils/browser/device-detector.utils.js.map +0 -1
  472. package/dist/esm/utils/browser/index.d.ts +0 -4
  473. package/dist/esm/utils/browser/index.d.ts.map +0 -1
  474. package/dist/esm/utils/browser/index.js +0 -4
  475. package/dist/esm/utils/browser/index.js.map +0 -1
  476. package/dist/esm/utils/browser/qa-mode.utils.d.ts +0 -14
  477. package/dist/esm/utils/browser/qa-mode.utils.d.ts.map +0 -1
  478. package/dist/esm/utils/browser/qa-mode.utils.js +0 -40
  479. package/dist/esm/utils/browser/qa-mode.utils.js.map +0 -1
  480. package/dist/esm/utils/browser/utm-params.utils.d.ts +0 -7
  481. package/dist/esm/utils/browser/utm-params.utils.d.ts.map +0 -1
  482. package/dist/esm/utils/browser/utm-params.utils.js +0 -19
  483. package/dist/esm/utils/browser/utm-params.utils.js.map +0 -1
  484. package/dist/esm/utils/data/index.d.ts +0 -2
  485. package/dist/esm/utils/data/index.d.ts.map +0 -1
  486. package/dist/esm/utils/data/index.js +0 -2
  487. package/dist/esm/utils/data/index.js.map +0 -1
  488. package/dist/esm/utils/data/uuid.utils.d.ts +0 -19
  489. package/dist/esm/utils/data/uuid.utils.d.ts.map +0 -1
  490. package/dist/esm/utils/data/uuid.utils.js +0 -52
  491. package/dist/esm/utils/data/uuid.utils.js.map +0 -1
  492. package/dist/esm/utils/emitter.utils.d.ts +0 -9
  493. package/dist/esm/utils/emitter.utils.d.ts.map +0 -1
  494. package/dist/esm/utils/emitter.utils.js +0 -32
  495. package/dist/esm/utils/emitter.utils.js.map +0 -1
  496. package/dist/esm/utils/index.d.ts +0 -8
  497. package/dist/esm/utils/index.d.ts.map +0 -1
  498. package/dist/esm/utils/index.js +0 -8
  499. package/dist/esm/utils/index.js.map +0 -1
  500. package/dist/esm/utils/logging.utils.d.ts +0 -22
  501. package/dist/esm/utils/logging.utils.d.ts.map +0 -1
  502. package/dist/esm/utils/logging.utils.js +0 -82
  503. package/dist/esm/utils/logging.utils.js.map +0 -1
  504. package/dist/esm/utils/network/index.d.ts +0 -2
  505. package/dist/esm/utils/network/index.d.ts.map +0 -1
  506. package/dist/esm/utils/network/index.js +0 -2
  507. package/dist/esm/utils/network/index.js.map +0 -1
  508. package/dist/esm/utils/network/url.utils.d.ts +0 -16
  509. package/dist/esm/utils/network/url.utils.d.ts.map +0 -1
  510. package/dist/esm/utils/network/url.utils.js +0 -87
  511. package/dist/esm/utils/network/url.utils.js.map +0 -1
  512. package/dist/esm/utils/security/index.d.ts +0 -2
  513. package/dist/esm/utils/security/index.d.ts.map +0 -1
  514. package/dist/esm/utils/security/index.js +0 -2
  515. package/dist/esm/utils/security/index.js.map +0 -1
  516. package/dist/esm/utils/security/sanitize.utils.d.ts +0 -14
  517. package/dist/esm/utils/security/sanitize.utils.d.ts.map +0 -1
  518. package/dist/esm/utils/security/sanitize.utils.js +0 -118
  519. package/dist/esm/utils/security/sanitize.utils.js.map +0 -1
  520. package/dist/esm/utils/validations/config-validations.utils.d.ts +0 -19
  521. package/dist/esm/utils/validations/config-validations.utils.d.ts.map +0 -1
  522. package/dist/esm/utils/validations/config-validations.utils.js +0 -231
  523. package/dist/esm/utils/validations/config-validations.utils.js.map +0 -1
  524. package/dist/esm/utils/validations/event-validations.utils.d.ts +0 -13
  525. package/dist/esm/utils/validations/event-validations.utils.d.ts.map +0 -1
  526. package/dist/esm/utils/validations/event-validations.utils.js +0 -33
  527. package/dist/esm/utils/validations/event-validations.utils.js.map +0 -1
  528. package/dist/esm/utils/validations/index.d.ts +0 -5
  529. package/dist/esm/utils/validations/index.d.ts.map +0 -1
  530. package/dist/esm/utils/validations/index.js +0 -5
  531. package/dist/esm/utils/validations/index.js.map +0 -1
  532. package/dist/esm/utils/validations/metadata-validations.utils.d.ts +0 -23
  533. package/dist/esm/utils/validations/metadata-validations.utils.d.ts.map +0 -1
  534. package/dist/esm/utils/validations/metadata-validations.utils.js +0 -148
  535. package/dist/esm/utils/validations/metadata-validations.utils.js.map +0 -1
  536. package/dist/esm/utils/validations/type-guards.utils.d.ts +0 -9
  537. package/dist/esm/utils/validations/type-guards.utils.d.ts.map +0 -1
  538. package/dist/esm/utils/validations/type-guards.utils.js +0 -86
  539. package/dist/esm/utils/validations/type-guards.utils.js.map +0 -1
@@ -1 +1 @@
1
- {"version":3,"file":"tracelog.esm.js","sources":["../../src/constants/config.constants.ts","../../src/types/config.types.ts","../../src/types/device.types.ts","../../src/types/emitter.types.ts","../../src/types/error.types.ts","../../src/types/event.types.ts","../../src/types/mode.types.ts","../../src/types/scroll.types.ts","../../src/types/validation-error.types.ts","../../src/utils/logging.utils.ts","../../src/utils/browser/device-detector.utils.ts","../../src/constants/storage.constants.ts","../../src/constants/performance.constants.ts","../../src/constants/error.constants.ts","../../src/utils/browser/qa-mode.utils.ts","../../src/utils/browser/utm-params.utils.ts","../../src/utils/data/uuid.utils.ts","../../src/utils/network/url.utils.ts","../../src/utils/security/sanitize.utils.ts","../../src/utils/validations/config-validations.utils.ts","../../src/utils/validations/type-guards.utils.ts","../../src/utils/validations/metadata-validations.utils.ts","../../src/utils/validations/event-validations.utils.ts","../../src/utils/emitter.utils.ts","../../src/managers/state.manager.ts","../../src/managers/sender.manager.ts","../../src/managers/event.manager.ts","../../src/managers/user.manager.ts","../../src/managers/session.manager.ts","../../src/handlers/session.handler.ts","../../src/handlers/page-view.handler.ts","../../src/handlers/click.handler.ts","../../src/handlers/scroll.handler.ts","../../src/handlers/viewport.handler.ts","../../src/integrations/google-analytics.integration.ts","../../src/managers/storage.manager.ts","../../src/handlers/performance.handler.ts","../../src/handlers/error.handler.ts","../../src/app.ts","../../src/api.ts","../../src/app.constants.ts","../../src/public-api.ts","../../node_modules/web-vitals/dist/web-vitals.js"],"sourcesContent":["/**\n * Consolidated configuration constants for TraceLog\n * This file centralizes all timing, limits, browser, and initialization constants\n */\n\n// ============================================================================\n// SESSION & TIMING\n// ============================================================================\n\nexport const DEFAULT_SESSION_TIMEOUT = 15 * 60 * 1000; // 15 minutes\nexport const DUPLICATE_EVENT_THRESHOLD_MS = 500; // 500ms\nexport const EVENT_SENT_INTERVAL_MS = 10000; // 10 seconds\n\n// Throttling and debouncing\nexport const SCROLL_DEBOUNCE_TIME_MS = 250;\nexport const DEFAULT_VISIBILITY_TIMEOUT_MS = 2000;\nexport const DEFAULT_PAGE_VIEW_THROTTLE_MS = 1000; // 1 second throttle for page views\nexport const DEFAULT_CLICK_THROTTLE_MS = 300; // 300ms throttle for clicks per element\nexport const DEFAULT_VIEWPORT_COOLDOWN_PERIOD = 60000; // 60 seconds cooldown for viewport events\nexport const DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS = 100; // Maximum elements to track (Phase 3)\nexport const VIEWPORT_MUTATION_DEBOUNCE_MS = 100; // Debounce for mutation observer re-scanning\n\n// Event expiry\nexport const EVENT_EXPIRY_HOURS = 2;\nexport const EVENT_PERSISTENCE_MAX_AGE_MS = 2 * 60 * 60 * 1000; // 2 hours\n\n// ============================================================================\n// LIMITS & REQUESTS\n// ============================================================================\n\nexport const MAX_EVENTS_QUEUE_LENGTH = 100;\nexport const REQUEST_TIMEOUT_MS = 10000;\nexport const MAX_METADATA_SIZE = 5000;\n\n// Motion and interaction thresholds\nexport const DEFAULT_MOTION_THRESHOLD = 2;\nexport const SIGNIFICANT_SCROLL_DELTA = 10;\nexport const MIN_SCROLL_DEPTH_CHANGE = 5;\nexport const SCROLL_MIN_EVENT_INTERVAL_MS = 500;\nexport const MAX_SCROLL_EVENTS_PER_SESSION = 120;\n\n// Sampling and rate limits\nexport const DEFAULT_SAMPLING_RATE = 1;\nexport const MIN_SAMPLING_RATE = 0;\nexport const MAX_SAMPLING_RATE = 1;\nexport const RATE_LIMIT_WINDOW_MS = 1000; // 1 second window\nexport const MAX_EVENTS_PER_SECOND = 50; // Maximum 50 events per second (Phase 3: reduced from 200)\nexport const MAX_SAME_EVENT_PER_MINUTE = 60; // Maximum same custom event name per minute (prevents infinite loops)\nexport const PER_EVENT_RATE_LIMIT_WINDOW_MS = 60000; // 60 second window for per-event-name rate limiting\n\n// Per-session event caps (Phase 3)\nexport const MAX_EVENTS_PER_SESSION = 1000;\nexport const MAX_CLICKS_PER_SESSION = 500;\nexport const MAX_PAGE_VIEWS_PER_SESSION = 100;\nexport const MAX_CUSTOM_EVENTS_PER_SESSION = 500;\nexport const MAX_VIEWPORT_EVENTS_PER_SESSION = 200;\n\n// Queue and batch limits\nexport const BATCH_SIZE_THRESHOLD = 50;\nexport const MAX_PENDING_EVENTS_BUFFER = 100; // Maximum events to buffer before session init\n\n// Session timeout validation limits\nexport const MIN_SESSION_TIMEOUT_MS = 30000; // 30 seconds minimum\nexport const MAX_SESSION_TIMEOUT_MS = 86400000; // 24 hours maximum\n\n// Custom event validation limits\nexport const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;\nexport const MAX_CUSTOM_EVENT_STRING_SIZE = 8 * 1024; // 8KB\nexport const MAX_CUSTOM_EVENT_KEYS = 10;\nexport const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;\nexport const MAX_NESTED_OBJECT_KEYS = 20; // Maximum keys in nested objects within arrays\nexport const MAX_METADATA_NESTING_DEPTH = 1; // Maximum nesting depth for metadata objects\n\n// Text content limits\nexport const MAX_TEXT_LENGTH = 255; // For click tracking text content\n\n// Data sanitization limits\nexport const MAX_STRING_LENGTH = 1000;\nexport const MAX_STRING_LENGTH_IN_ARRAY = 500; // Strings within arrays are more limited\nexport const MAX_ARRAY_LENGTH = 100;\nexport const MAX_OBJECT_DEPTH = 3;\n\n// Precision for numeric metrics\nexport const PRECISION_TWO_DECIMALS = 2 as const;\n\n// Sync XHR timeout\nexport const SYNC_XHR_TIMEOUT_MS = 2000; // 2 seconds\n\n// sendBeacon payload size limit (Phase 3)\nexport const MAX_BEACON_PAYLOAD_SIZE = 64 * 1024; // 64KB browser limit\n\n// Event fingerprint management\nexport const MAX_FINGERPRINTS = 1000; // Maximum fingerprints stored before cleanup\nexport const FINGERPRINT_CLEANUP_MULTIPLIER = 10; // Cleanup fingerprints older than 10x threshold\nexport const MAX_FINGERPRINTS_HARD_LIMIT = 2000; // Hard limit for aggressive cleanup\n\n// ============================================================================\n// BROWSER & HTML\n// ============================================================================\n\nexport const HTML_DATA_ATTR_PREFIX = 'data-tlog';\n\n// Interactive element selectors for click tracking\nexport const INTERACTIVE_SELECTORS = [\n 'button',\n 'a',\n 'input[type=\"button\"]',\n 'input[type=\"submit\"]',\n 'input[type=\"reset\"]',\n 'input[type=\"checkbox\"]',\n 'input[type=\"radio\"]',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[routerLink]',\n '[ng-click]',\n '[data-action]',\n '[data-click]',\n '[data-navigate]',\n '[data-toggle]',\n '[onclick]',\n '.btn',\n '.button',\n '.clickable',\n '.nav-link',\n '.menu-item',\n '[data-testid]',\n '[tabindex=\"0\"]',\n] as const;\n\n// UTM parameters for tracking\nexport const UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];\n\n// Default sensitive query parameters to remove from URLs (privacy protection)\nexport const DEFAULT_SENSITIVE_QUERY_PARAMS = [\n 'token',\n 'auth',\n 'key',\n 'session',\n 'reset',\n 'password',\n 'api_key',\n 'apikey',\n 'secret',\n 'access_token',\n 'refresh_token',\n 'verification',\n 'code',\n 'otp',\n] as const;\n\n// ============================================================================\n// ============================================================================\n// INITIALIZATION\n// ============================================================================\n\nexport const INITIALIZATION_MAX_CONCURRENT_RETRIES = 20;\nexport const INITIALIZATION_CONCURRENT_RETRY_DELAY_MS = 50;\nexport const INITIALIZATION_TIMEOUT_MS = 10000;\n\n// ============================================================================\n// SESSION MANAGEMENT\n// ============================================================================\n\nexport const SESSION_SYNC_TIMEOUT_MS = 2000;\nexport const SESSION_MAX_RETRY_ATTEMPTS = 3;\nexport const SESSION_CLEANUP_DELAY_MS = 100;\n\n// Cross-tab coordination\nexport const CROSS_TAB_INITIALIZATION_LOCK_TIMEOUT_MS = 5000;\nexport const TAB_HEARTBEAT_INTERVAL_MS = 5000; // 5 seconds\nexport const TAB_ELECTION_TIMEOUT_MS = 2000; // 2 seconds\nexport const TAB_CLEANUP_DELAY_MS = 1000; // 1 second\n\n// Session recovery\nexport const SESSION_RECOVERY_WINDOW_MULTIPLIER = 2; // 2x session timeout\nexport const MAX_SESSION_RECOVERY_ATTEMPTS = 3;\nexport const MAX_SESSION_RECOVERY_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours max\nexport const MIN_SESSION_RECOVERY_WINDOW_MS = 2 * 60 * 1000; // 2 minutes minimum\n\n// ============================================================================\n// SCROLL SUPPRESSION\n// ============================================================================\n\nexport const SCROLL_SUPPRESS_MULTIPLIER = 2;\n\n// ============================================================================\n// NETWORK TIMING\n// ============================================================================\n\nexport const RETRY_BACKOFF_INITIAL = 1000; // 1 second\nexport const RETRY_BACKOFF_MAX = 30_000; // 30 seconds\nexport const RATE_LIMIT_INTERVAL = 1000; // 1 second\nexport const MAX_RETRY_ATTEMPTS = 10;\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n// Validation error messages - standardized across all layers\nexport const VALIDATION_MESSAGES = {\n MISSING_PROJECT_ID: 'Project ID is required',\n PROJECT_ID_EMPTY_AFTER_TRIM: 'Project ID is required',\n INVALID_SESSION_TIMEOUT: `Session timeout must be between ${MIN_SESSION_TIMEOUT_MS}ms (30 seconds) and ${MAX_SESSION_TIMEOUT_MS}ms (24 hours)`,\n INVALID_SAMPLING_RATE: 'Sampling rate must be between 0 and 1',\n INVALID_ERROR_SAMPLING_RATE: 'Error sampling must be between 0 and 1',\n INVALID_TRACELOG_PROJECT_ID: 'TraceLog project ID is required when integration is enabled',\n INVALID_CUSTOM_API_URL: 'Custom API URL is required when integration is enabled',\n INVALID_GOOGLE_ANALYTICS_ID: 'Google Analytics measurement ID is required when integration is enabled',\n INVALID_SCROLL_CONTAINER_SELECTORS: 'Scroll container selectors must be valid CSS selectors',\n INVALID_GLOBAL_METADATA: 'Global metadata must be an object',\n INVALID_SENSITIVE_QUERY_PARAMS: 'Sensitive query params must be an array of strings',\n INVALID_PRIMARY_SCROLL_SELECTOR: 'Primary scroll selector must be a non-empty string',\n INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX: 'Invalid CSS selector syntax for primaryScrollSelector',\n INVALID_PAGE_VIEW_THROTTLE: 'Page view throttle must be a non-negative number',\n INVALID_CLICK_THROTTLE: 'Click throttle must be a non-negative number',\n INVALID_MAX_SAME_EVENT_PER_MINUTE: 'Max same event per minute must be a positive number',\n INVALID_VIEWPORT_CONFIG: 'Viewport config must be an object',\n INVALID_VIEWPORT_ELEMENTS: 'Viewport elements must be a non-empty array',\n INVALID_VIEWPORT_ELEMENT: 'Each viewport element must have a valid selector string',\n INVALID_VIEWPORT_ELEMENT_ID: 'Viewport element id must be a non-empty string',\n INVALID_VIEWPORT_ELEMENT_NAME: 'Viewport element name must be a non-empty string',\n INVALID_VIEWPORT_THRESHOLD: 'Viewport threshold must be a number between 0 and 1',\n INVALID_VIEWPORT_MIN_DWELL_TIME: 'Viewport minDwellTime must be a non-negative number',\n INVALID_VIEWPORT_COOLDOWN_PERIOD: 'Viewport cooldownPeriod must be a non-negative number',\n INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS: 'Viewport maxTrackedElements must be a positive number',\n} as const;\n\n// ============================================================================\n// SECURITY\n// ============================================================================\n\n// XSS protection patterns\nexport const XSS_PATTERNS = [\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n /javascript:/gi,\n /on\\w+\\s*=/gi,\n /<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi,\n /<embed\\b[^>]*>/gi,\n /<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi,\n] as const;\n","import { MetadataType } from './common.types';\nimport { ViewportConfig } from './viewport.types';\n\nexport interface Config {\n /** Session inactivity timeout in milliseconds. @default 900000 */\n sessionTimeout?: number;\n /** Metadata appended to every tracked event. */\n globalMetadata?: Record<string, MetadataType>;\n /** Query parameters to remove before tracking URLs. */\n sensitiveQueryParams?: string[];\n /** Error event sampling rate between 0 and 1. @default 1 */\n errorSampling?: number;\n /** Event sampling rate between 0 and 1. @default 1 */\n samplingRate?: number;\n /** CSS selector to manually override primary scroll container detection. */\n primaryScrollSelector?: string;\n /** Viewport visibility tracking configuration. */\n viewport?: ViewportConfig;\n /** Page view throttle duration in milliseconds to prevent rapid navigation spam. @default 1000 */\n pageViewThrottleMs?: number;\n /** Click throttle duration in milliseconds to prevent double-clicks and rapid spam. @default 300 */\n clickThrottleMs?: number;\n /** Maximum number of same custom event name allowed per minute to prevent infinite loops. @default 60 */\n maxSameEventPerMinute?: number;\n /** Optional configuration for third-party integrations. */\n integrations?: {\n /** TraceLog integration options. */\n tracelog?: {\n /** Required project ID TraceLog SaaS integration. */\n projectId: string;\n };\n /** Custom integration options. */\n custom?: {\n /** Endpoint for collecting events. */\n collectApiUrl: string;\n /** Allow HTTP URLs (not recommended for production). @default false */\n allowHttp?: boolean;\n };\n /** Google Analytics integration options. */\n googleAnalytics?: {\n /** Required measurement ID for Google Analytics. */\n measurementId: string;\n };\n };\n}\n\nexport enum SpecialApiUrl {\n Localhost = 'localhost:8080',\n Fail = 'localhost:9999',\n}\n","export enum DeviceType {\n Mobile = 'mobile',\n Tablet = 'tablet',\n Desktop = 'desktop',\n Unknown = 'unknown',\n}\n","import { EventData } from './event.types';\nimport { BaseEventsQueueDto } from './queue.types';\n\nexport type EmitterCallback<T = any> = (data: T) => void;\n\nexport enum EmitterEvent {\n EVENT = 'event',\n QUEUE = 'queue',\n}\n\nexport interface EmitterMap {\n [EmitterEvent.EVENT]: EventData;\n [EmitterEvent.QUEUE]: BaseEventsQueueDto;\n}\n","/**\n * Custom error types for TraceLog\n */\n\n/**\n * Represents a permanent HTTP error (4xx) that should not be retried\n * Examples: 400 Bad Request, 403 Forbidden, 404 Not Found\n */\nexport class PermanentError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n ) {\n super(message);\n this.name = 'PermanentError';\n\n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PermanentError);\n }\n }\n}\n","import { MetadataType } from './common.types';\nimport { SessionEndReason } from './session.types';\n\n/**\n * Coordinate information from a click event\n * Includes absolute and relative positioning\n */\nexport type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;\n\n/**\n * Web performance metric types tracked by the library\n * - LCP: Largest Contentful Paint\n * - CLS: Cumulative Layout Shift\n * - INP: Interaction to Next Paint\n * - FCP: First Contentful Paint\n * - TTFB: Time to First Byte\n * - LONG_TASK: Tasks exceeding 50ms\n */\nexport type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB' | 'LONG_TASK';\n\n/**\n * Core event types tracked by TraceLog\n */\nexport enum EventType {\n /** Page navigation and view tracking */\n PAGE_VIEW = 'page_view',\n /** User click interactions */\n CLICK = 'click',\n /** Scroll depth and behavior */\n SCROLL = 'scroll',\n /** Session initialization */\n SESSION_START = 'session_start',\n /** Session termination */\n SESSION_END = 'session_end',\n /** Custom business events */\n CUSTOM = 'custom',\n /** Performance metrics */\n WEB_VITALS = 'web_vitals',\n /** JavaScript errors and rejections */\n ERROR = 'error',\n /** Element visibility tracking */\n VIEWPORT_VISIBLE = 'viewport_visible',\n}\n\n/**\n * Scroll direction indicators\n */\nexport enum ScrollDirection {\n /** Scrolling upward */\n UP = 'up',\n /** Scrolling downward */\n DOWN = 'down',\n}\n\n/**\n * JavaScript error classification\n */\nexport enum ErrorType {\n /** Runtime JavaScript errors */\n JS_ERROR = 'js_error',\n /** Unhandled promise rejections */\n PROMISE_REJECTION = 'promise_rejection',\n}\n\n/**\n * Scroll event data captured during user scrolling\n */\nexport interface ScrollData {\n /** Current scroll depth as percentage (0-100) */\n depth: number;\n /** Direction of scroll movement */\n direction: ScrollDirection;\n /** CSS selector of the scrolled container */\n container_selector: string;\n /** Whether this is the primary viewport scroll */\n is_primary: boolean;\n /** Scroll velocity in pixels per second */\n velocity: number;\n /** Maximum scroll depth reached during session (0-100) */\n max_depth_reached: number;\n}\n\n/**\n * Click event data capturing user interaction details\n */\nexport interface ClickData {\n /** Absolute X coordinate in viewport (pixels) */\n x: number;\n /** Absolute Y coordinate in viewport (pixels) */\n y: number;\n /** Relative X position within element (0-1) */\n relativeX: number;\n /** Relative Y position within element (0-1) */\n relativeY: number;\n /** Element ID attribute */\n id?: string;\n /** Element class attribute */\n class?: string;\n /** HTML tag name */\n tag?: string;\n /** Element text content (truncated) */\n text?: string;\n /** Link href for anchor elements */\n href?: string;\n /** Element title attribute */\n title?: string;\n /** Image alt text for img elements */\n alt?: string;\n /** ARIA role attribute */\n role?: string;\n /** ARIA label attribute */\n ariaLabel?: string;\n /** Custom data attributes (data-*) */\n dataAttributes?: Record<string, string>;\n}\n\n/**\n * Element data for specialized click tracking\n * Used for form inputs and interactive elements\n */\nexport interface ClickTrackingElementData {\n /** DOM element being tracked */\n element: HTMLElement;\n /** Descriptive name for the element */\n name: string;\n /** Element value (for inputs) */\n value?: string;\n}\n\n/**\n * Custom event data for business-specific tracking\n */\nexport interface CustomEventData {\n /** Event name identifier */\n name: string;\n /** Additional event metadata */\n metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n}\n\n/**\n * Web performance metrics data\n */\nexport interface WebVitalsData {\n /** Type of performance metric */\n type: WebVitalType;\n /** Metric value (varies by type) */\n value: number;\n}\n\n/**\n * JavaScript error details\n */\nexport interface ErrorData {\n /** Error classification */\n type: ErrorType;\n /** Error message text */\n message: string;\n /** Source file where error occurred */\n filename?: string;\n /** Line number in source file */\n line?: number;\n /** Column number in source file */\n column?: number;\n}\n\n/**\n * UTM campaign tracking parameters\n */\nexport interface UTM {\n /** Campaign source (e.g., google, newsletter) */\n source?: string;\n /** Campaign medium (e.g., cpc, email) */\n medium?: string;\n /** Campaign name identifier */\n campaign?: string;\n /** Campaign search term */\n term?: string;\n /** Campaign content variation */\n content?: string;\n}\n\n/**\n * Page view navigation data\n */\nexport interface PageViewData {\n /** Previous page URL */\n referrer?: string;\n /** Page title from document */\n title?: string;\n /** URL pathname */\n pathname?: string;\n /** URL query string */\n search?: string;\n /** URL hash fragment */\n hash?: string;\n}\n\n/**\n * Data captured when element becomes visible\n */\nexport interface ViewportEventData {\n /** CSS selector that matched the element */\n selector: string;\n /** Optional unique identifier for analytics (if configured) */\n id?: string;\n /** Optional human-readable name (if configured) */\n name?: string;\n /** Actual time (ms) element was visible before event fired */\n dwellTime: number;\n /** Actual visibility ratio when event fired (0-1) */\n visibilityRatio: number;\n}\n\n/**\n * Complete event data structure\n * All events share base properties with type-specific data\n */\nexport interface EventData {\n /** Unique event identifier */\n id: string;\n /** Event type classification */\n type: EventType;\n /** Current page URL where event occurred */\n page_url: string;\n /** Unix timestamp (milliseconds) */\n timestamp: number;\n /** HTTP referrer header */\n referrer?: string;\n /** Previous page URL for navigation events */\n from_page_url?: string;\n /** Scroll event details (when type is SCROLL) */\n scroll_data?: ScrollData;\n /** Click event details (when type is CLICK) */\n click_data?: ClickData;\n /** Custom event details (when type is CUSTOM) */\n custom_event?: CustomEventData;\n /** Performance metrics (when type is WEB_VITALS) */\n web_vitals?: WebVitalsData;\n /** Page view details (when type is PAGE_VIEW) */\n page_view?: PageViewData;\n /** Session termination reason (when type is SESSION_END) */\n session_end_reason?: SessionEndReason;\n /** Error details (when type is ERROR) */\n error_data?: ErrorData;\n /** Viewport visibility details (when type is VIEWPORT_VISIBLE) */\n viewport_data?: ViewportEventData;\n /** Campaign tracking parameters */\n utm?: UTM;\n}\n","/**\n * App modes for the TraceLog Library\n */\nexport enum Mode {\n QA = 'qa',\n}\n","import { EventData, EventType, ScrollData } from './event.types';\n\nexport type PrimaryScrollEvent = EventData & {\n type: EventType.SCROLL;\n scroll_data: ScrollData & { is_primary: true };\n};\n\nexport type SecondaryScrollEvent = EventData & {\n type: EventType.SCROLL;\n scroll_data: ScrollData & { is_primary: false };\n};\n\nexport function isPrimaryScrollEvent(event: EventData): event is PrimaryScrollEvent {\n return (\n event.type === EventType.SCROLL && 'scroll_data' in event && (event.scroll_data as ScrollData).is_primary === true\n );\n}\n\nexport function isSecondaryScrollEvent(event: EventData): event is SecondaryScrollEvent {\n return (\n event.type === EventType.SCROLL && 'scroll_data' in event && (event.scroll_data as ScrollData).is_primary === false\n );\n}\n","/**\n * Custom error classes for TraceLog validation errors\n * Provides better error handling and consistency across validation layers\n */\n\n/**\n * Base class for all TraceLog validation errors\n */\nexport abstract class TraceLogValidationError extends Error {\n constructor(\n message: string,\n public readonly errorCode: string,\n public readonly layer: 'config' | 'app' | 'runtime',\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when app configuration validation fails\n */\nexport class AppConfigValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'APP_CONFIG_INVALID', layer);\n }\n}\n\n/**\n * Thrown when session timeout validation fails\n */\nexport class SessionTimeoutValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SESSION_TIMEOUT_INVALID', layer);\n }\n}\n\n/**\n * Thrown when sampling rate validation fails\n */\nexport class SamplingRateValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SAMPLING_RATE_INVALID', layer);\n }\n}\n\n/**\n * Thrown when integrations validation fails\n */\nexport class IntegrationValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'INTEGRATION_INVALID', layer);\n }\n}\n\n/**\n * Thrown when initialization exceeds the maximum allowed timeout\n */\nexport class InitializationTimeoutError extends TraceLogValidationError {\n constructor(\n message: string,\n public readonly timeoutMs: number,\n layer: 'config' | 'app' | 'runtime' = 'runtime',\n ) {\n super(message, 'INITIALIZATION_TIMEOUT', layer);\n }\n}\n","export const formatLogMsg = (msg: string, error?: unknown): string => {\n if (error) {\n // In production, sanitize error messages to avoid exposing sensitive paths\n if (process.env.NODE_ENV !== 'dev' && error instanceof Error) {\n // Remove file paths and line numbers from error messages\n const sanitizedMessage = error.message.replace(/\\s+at\\s+.*$/gm, '').replace(/\\(.*?:\\d+:\\d+\\)/g, '');\n return `[TraceLog] ${msg}: ${sanitizedMessage}`;\n }\n return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : 'Unknown error'}`;\n }\n\n return `[TraceLog] ${msg}`;\n};\n\n/**\n * Safe logging utility that respects production environment\n *\n * @param type - Log level (info, warn, error, debug)\n * @param msg - Message to log\n * @param extra - Optional extra data\n *\n * Production behavior:\n * - debug: Never logged in production\n * - info: Only logged if showToClient=true\n * - warn: Always logged (important for debugging production issues)\n * - error: Always logged\n * - Stack traces are sanitized\n * - Data objects are sanitized\n */\nexport const log = (\n type: 'info' | 'warn' | 'error' | 'debug',\n msg: string,\n extra?: { error?: unknown; data?: Record<string, unknown>; showToClient?: boolean },\n): void => {\n const { error, data, showToClient = false } = extra ?? {};\n const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;\n const method = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';\n\n // Production logging strategy:\n // - Development: Log everything\n // - Production:\n // - debug: never logged\n // - info: only if showToClient=true\n // - warn: always logged (critical for debugging)\n // - error: always logged\n const isProduction = process.env.NODE_ENV !== 'dev';\n\n if (isProduction) {\n // Never log debug in production\n if (type === 'debug') {\n return;\n }\n\n // Log info only if explicitly flagged\n if (type === 'info' && !showToClient) {\n return;\n }\n\n // warn and error always logged in production\n }\n\n // In production, sanitize data to avoid exposing sensitive information\n if (isProduction && data !== undefined) {\n const sanitizedData = sanitizeLogData(data);\n console[method](formattedMsg, sanitizedData);\n } else if (data !== undefined) {\n console[method](formattedMsg, data);\n } else {\n console[method](formattedMsg);\n }\n};\n\n/**\n * Sanitizes log data in production to prevent sensitive information leakage\n * Simple approach: redact sensitive keys only\n */\nconst sanitizeLogData = (data: Record<string, unknown>): Record<string, unknown> => {\n const sanitized: Record<string, unknown> = {};\n const sensitiveKeys = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'sessionid', 'session_id'];\n\n for (const [key, value] of Object.entries(data)) {\n const lowerKey = key.toLowerCase();\n\n // Redact sensitive keys\n if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {\n sanitized[key] = '[REDACTED]';\n } else {\n sanitized[key] = value;\n }\n }\n\n return sanitized;\n};\n","import { DeviceType } from '../../types/device.types';\nimport { log } from '../logging.utils';\n\nlet coarsePointerQuery: MediaQueryList | undefined;\nlet noHoverQuery: MediaQueryList | undefined;\n\nconst initMediaQueries = (): void => {\n if (typeof window !== 'undefined' && !coarsePointerQuery) {\n coarsePointerQuery = window.matchMedia('(pointer: coarse)');\n noHoverQuery = window.matchMedia('(hover: none)');\n }\n};\n\ninterface NavigatorWithUserAgentData extends Navigator {\n userAgentData?: {\n mobile: boolean;\n platform?: string;\n };\n}\n\n/**\n * Detects the device type based on screen size, user agent, and browser capabilities\n * @returns The detected device type\n */\nexport const getDeviceType = (): DeviceType => {\n try {\n const nav = navigator as NavigatorWithUserAgentData;\n\n if (nav.userAgentData && typeof nav.userAgentData.mobile === 'boolean') {\n if (nav.userAgentData.platform && /ipad|tablet/i.test(nav.userAgentData.platform)) {\n return DeviceType.Tablet;\n }\n\n const result = nav.userAgentData.mobile ? DeviceType.Mobile : DeviceType.Desktop;\n return result;\n }\n\n initMediaQueries();\n\n const width = window.innerWidth;\n const hasCoarsePointer = coarsePointerQuery?.matches ?? false;\n const hasNoHover = noHoverQuery?.matches ?? false;\n const hasTouchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const ua = navigator.userAgent.toLowerCase();\n const isMobileUA = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(ua);\n const isTabletUA = /tablet|ipad|android(?!.*mobile)/.test(ua);\n\n if (width <= 767 || (isMobileUA && hasTouchSupport)) {\n return DeviceType.Mobile;\n }\n\n if ((width >= 768 && width <= 1024) || isTabletUA || (hasCoarsePointer && hasNoHover && hasTouchSupport)) {\n return DeviceType.Tablet;\n }\n\n return DeviceType.Desktop;\n } catch (error) {\n log('warn', 'Device detection failed, defaulting to desktop', { error });\n\n return DeviceType.Desktop;\n }\n};\n","export const STORAGE_BASE_KEY = 'tlog';\nexport const QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;\nexport const USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;\n\nexport const QUEUE_KEY = (id: string): string => (id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`);\nexport const SESSION_STORAGE_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;\n\n// Cross-tab session management storage keys\nexport const CROSS_TAB_SESSION_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:cross_tab_session` : `${STORAGE_BASE_KEY}:cross_tab_session`;\nexport const TAB_INFO_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:tab_info` : `${STORAGE_BASE_KEY}:tab_info`;\n\nexport const TAB_SPECIFIC_INFO_KEY = (projectId: string, tabId: string): string =>\n `${STORAGE_BASE_KEY}:${projectId}:tab:${tabId}:info`;\nexport const SESSION_RECOVERY_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:recovery` : `${STORAGE_BASE_KEY}:recovery`;\n\n// BroadcastChannel name for cross-tab communication\nexport const BROADCAST_CHANNEL_NAME = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;\n","/**\n * Performance monitoring and web vitals constants for TraceLog\n * Centralizes thresholds and configuration for performance tracking\n */\n\nimport { WebVitalType } from '../types';\n\n// ============================================================================\n// WEB VITALS THRESHOLDS\n// ============================================================================\n\n/**\n * Web Vitals thresholds in milliseconds (except CLS which is unitless)\n * These define the minimum values required to report a web vital metric\n *\n * Based on Core Web Vitals standards:\n * - LCP (Largest Contentful Paint): 4000ms threshold (poor threshold)\n * - FCP (First Contentful Paint): 1800ms threshold (good threshold)\n * - CLS (Cumulative Layout Shift): 0.25 threshold (unitless, needs improvement threshold)\n * - INP (Interaction to Next Paint): 200ms threshold (good threshold)\n * - TTFB (Time to First Byte): 800ms threshold (good/needs improvement boundary, aligned with Web Vitals standard)\n * - LONG_TASK: 50ms threshold for long task detection\n */\nexport const WEB_VITALS_THRESHOLDS: Record<WebVitalType, number> = {\n LCP: 4000,\n FCP: 1800,\n CLS: 0.25,\n INP: 200,\n TTFB: 800,\n LONG_TASK: 50,\n} as const;\n\n// ============================================================================\n// PERFORMANCE MONITORING LIMITS\n// ============================================================================\n\n/**\n * Long task throttling interval in milliseconds\n * Prevents excessive long task events from being sent\n */\nexport const LONG_TASK_THROTTLE_MS = 1000;\n\n/**\n * Precision for performance metric values\n * All performance metrics are rounded to 2 decimal places\n */\nexport const PERFORMANCE_PRECISION_DECIMALS = 2 as const;\n","/**\n * Error handling and PII sanitization constants for TraceLog\n * Centralizes patterns and limits for error tracking and data protection\n */\n\n// ============================================================================\n// PII SANITIZATION PATTERNS\n// ============================================================================\n\n/**\n * Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)\n * These patterns are used to replace sensitive information with [REDACTED] in error messages\n */\nexport const PII_PATTERNS = [\n // Email addresses\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/gi,\n\n // US Phone numbers (various formats)\n /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n\n // Credit card numbers (16 digits with optional separators)\n /\\b\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/g,\n\n // IBAN (International Bank Account Number)\n /\\b[A-Z]{2}\\d{2}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/gi,\n\n // API keys/tokens (sk_test_, sk_live_, pk_test_, pk_live_, etc.)\n /\\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\\b/gi,\n\n // Bearer tokens (JWT-like patterns - matches complete and partial tokens)\n /Bearer\\s+[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)?(?:\\.[A-Za-z0-9_-]+)?/gi,\n\n // Passwords in connection strings (protocol://user:password@host)\n /:\\/\\/[^:/]+:([^@]+)@/gi,\n] as const;\n\n// ============================================================================\n// ERROR TRACKING LIMITS\n// ============================================================================\n\n/**\n * Maximum length for error messages before truncation\n * Prevents extremely long error messages from consuming excessive storage\n */\nexport const MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Time window for error suppression in milliseconds\n * Prevents duplicate errors from flooding the system within this timeframe\n */\nexport const ERROR_SUPPRESSION_WINDOW_MS = 5_000; // 5 seconds\n\n/**\n * Maximum number of unique errors to track for suppression\n * Prevents memory usage from growing indefinitely\n */\nexport const MAX_TRACKED_ERRORS = 50;\n\n/**\n * Hard limit for error tracking before aggressive cleanup\n * If this limit is exceeded, the entire error map is cleared\n */\nexport const MAX_TRACKED_ERRORS_HARD_LIMIT = MAX_TRACKED_ERRORS * 2;\n\n// ============================================================================\n// ERROR SAMPLING\n// ============================================================================\n\n/**\n * Default error sampling rate\n * Controls what percentage of errors are actually reported\n */\nexport const DEFAULT_ERROR_SAMPLING_RATE = 1; // 100% of errors\n\n// ============================================================================\n// ERROR BURST DETECTION (Phase 3)\n// ============================================================================\n\n/**\n * Time window for error burst detection in milliseconds\n * Tracks unique errors within this window\n */\nexport const ERROR_BURST_WINDOW_MS = 1000; // 1 second\n\n/**\n * Maximum number of unique errors allowed in burst window\n * Exceeding this triggers a cooldown period\n */\nexport const ERROR_BURST_THRESHOLD = 10; // 10 unique errors\n\n/**\n * Backoff period after burst detection in milliseconds\n * No errors will be tracked during this cooldown\n */\nexport const ERROR_BURST_BACKOFF_MS = 5000; // 5 seconds\n\n// ============================================================================\n// PERMANENT ERROR LOGGING\n// ============================================================================\n\n/**\n * Time window for throttling permanent error logs in milliseconds\n * Same error status codes are logged at most once per this window\n * Prevents console spam when backend repeatedly returns 4xx errors\n */\nexport const PERMANENT_ERROR_LOG_THROTTLE_MS = 60_000; // 1 minute\n","import { QA_MODE_KEY } from '../../constants';\nimport { log } from '../logging.utils';\n\nconst QA_MODE_PARAM = 'tlog_mode';\nconst QA_MODE_VALUE = 'qa';\n\n/**\n * Detects if QA mode should be active based on URL query parameter or sessionStorage\n *\n * Detection flow:\n * 1. Check if already active in sessionStorage\n * 2. Check for ?tlog_mode=qa query parameter\n * 3. If found in URL:\n * - Persist to sessionStorage\n * - Clean param from URL\n *\n * @returns True if QA mode is active, false otherwise\n */\nexport const detectQaMode = (): boolean => {\n const stored = sessionStorage.getItem(QA_MODE_KEY);\n\n if (stored === 'true') {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const modeParam = params.get(QA_MODE_PARAM);\n const isQaMode = modeParam === QA_MODE_VALUE;\n\n if (isQaMode) {\n sessionStorage.setItem(QA_MODE_KEY, 'true');\n\n params.delete(QA_MODE_PARAM);\n\n const newSearch = params.toString();\n const newUrl = `${window.location.pathname}${newSearch ? '?' + newSearch : ''}${window.location.hash}`;\n\n try {\n window.history.replaceState({}, '', newUrl);\n } catch (error) {\n log('warn', 'History API not available, cannot replace URL', { error });\n }\n\n console.log(\n '%c[TraceLog] QA Mode ACTIVE',\n 'background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;',\n );\n }\n\n return isQaMode;\n};\n","import { UTM_PARAMS } from '../../constants';\nimport { UTM } from '../../types/event.types';\n\n/**\n * Extracts UTM parameters from the current URL\n * @returns UTM parameters object or undefined if none found\n */\nexport const getUTMParameters = (): UTM | undefined => {\n const urlParams = new URLSearchParams(window.location.search);\n const utmParams: Partial<Record<keyof UTM, string>> = {};\n\n UTM_PARAMS.forEach((param) => {\n const value = urlParams.get(param);\n\n if (value) {\n const key = param.split('utm_')[1] as keyof UTM;\n utmParams[key] = value;\n }\n });\n\n const result = Object.keys(utmParams).length ? utmParams : undefined;\n\n return result;\n};\n","/**\n * Generates a RFC4122 compliant UUID v4 using native crypto API with fallback\n * @returns A UUID string\n */\nexport const generateUUID = (): string => {\n // Use native crypto.randomUUID() if available (modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * Generates a unique event ID optimized for high-frequency event tracking\n *\n * Uses a simple hybrid approach:\n * - Timestamp for temporal ordering\n * - Random component for uniqueness across tabs/processes\n *\n * Format: {timestamp}-{random}\n * Example: \"1704067200000-a3f9c2b1\"\n *\n * @returns Unique event ID string\n */\nexport const generateEventId = (): string => {\n const timestamp = Date.now();\n\n // Generate 8 random hex chars (32 bits entropy)\n let random = '';\n try {\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const bytes = crypto.getRandomValues(new Uint8Array(4));\n if (bytes) {\n random = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n }\n } catch {\n // crypto failed, use fallback\n }\n\n // Fallback to Math.random if crypto unavailable\n if (!random) {\n random = Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, '0');\n }\n\n return `${timestamp}-${random}`;\n};\n","import { Config } from '../../types';\nimport { DEFAULT_SENSITIVE_QUERY_PARAMS } from '../../constants';\nimport { log } from '../logging.utils';\n\n/**\n * Validates if a URL is valid and optionally allows HTTP URLs\n * @param url - The URL to validate\n * @param allowHttp - Whether to allow HTTP URLs (default: false)\n * @returns True if the URL is valid, false otherwise\n */\nconst isValidUrl = (url: string, allowHttp = false): boolean => {\n try {\n const parsed = new URL(url);\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n return isHttps || (allowHttp && isHttp);\n } catch {\n return false;\n }\n};\n\n/**\n * Generates an API URL based on project ID and current domain\n * @param id - The project ID\n * @returns The generated API URL\n */\nexport const getCollectApiUrl = (config: Config): string => {\n if (config.integrations?.tracelog?.projectId) {\n const url = new URL(window.location.href);\n const host = url.hostname;\n const parts = host.split('.');\n\n if (parts.length === 0) {\n throw new Error('Invalid URL');\n }\n\n const projectId = config.integrations.tracelog.projectId;\n const cleanDomain = parts.slice(-2).join('.');\n const collectApiUrl = `https://${projectId}.${cleanDomain}/collect`;\n const isValid = isValidUrl(collectApiUrl);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n const collectApiUrl = config.integrations?.custom?.collectApiUrl;\n\n if (collectApiUrl) {\n const allowHttp = config.integrations?.custom?.allowHttp ?? false;\n const isValid = isValidUrl(collectApiUrl, allowHttp);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n return '';\n};\n\n/**\n * Normalizes a URL by removing sensitive query parameters\n * Combines default sensitive parameters with custom ones provided by user\n * @param url - The URL to normalize\n * @param sensitiveQueryParams - Array of parameter names to remove (merged with defaults)\n * @returns The normalized URL\n */\nexport const normalizeUrl = (url: string, sensitiveQueryParams: string[] = []): string => {\n try {\n const urlObject = new URL(url);\n const searchParams = urlObject.searchParams;\n\n // Merge default sensitive params with user-provided ones (deduped via Set)\n const allSensitiveParams = [...new Set([...DEFAULT_SENSITIVE_QUERY_PARAMS, ...sensitiveQueryParams])];\n\n let hasChanged = false;\n const removedParams: string[] = [];\n\n allSensitiveParams.forEach((param) => {\n if (searchParams.has(param)) {\n searchParams.delete(param);\n hasChanged = true;\n removedParams.push(param);\n }\n });\n\n if (!hasChanged && url.includes('?')) {\n return url;\n }\n\n urlObject.search = searchParams.toString();\n const result = urlObject.toString();\n\n return result;\n } catch (error) {\n log('warn', 'URL normalization failed, returning original', { error, data: { url: url.slice(0, 100) } });\n\n return url;\n }\n};\n","import {\n MAX_ARRAY_LENGTH,\n MAX_OBJECT_DEPTH,\n MAX_STRING_LENGTH,\n MAX_NESTED_OBJECT_KEYS,\n XSS_PATTERNS,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\n\n/**\n * Sanitizes a string value to prevent XSS attacks\n * @param value - The string to sanitize\n * @returns The sanitized string\n */\nexport const sanitizeString = (value: string): string => {\n if (!value || typeof value !== 'string' || value.trim().length === 0) {\n return '';\n }\n\n let sanitized = value;\n\n // Limit string length\n if (value.length > MAX_STRING_LENGTH) {\n sanitized = value.slice(0, Math.max(0, MAX_STRING_LENGTH));\n // Silent truncation - this is expected behavior for long strings\n }\n\n // Remove potential XSS patterns\n let xssPatternMatches = 0;\n for (const pattern of XSS_PATTERNS) {\n const beforeReplace = sanitized;\n sanitized = sanitized.replace(pattern, '');\n if (beforeReplace !== sanitized) {\n xssPatternMatches++;\n }\n }\n\n if (xssPatternMatches > 0) {\n log('warn', 'XSS patterns detected and removed', {\n data: {\n patternMatches: xssPatternMatches,\n originalValue: value.slice(0, 100),\n },\n });\n }\n\n // Basic HTML entity encoding for critical characters\n sanitized = sanitized\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#x27;')\n .replaceAll('/', '&#x2F;');\n\n const result = sanitized.trim();\n\n return result;\n};\n\n/**\n * Sanitizes any value recursively with depth protection\n * @param value - The value to sanitize\n * @param depth - Current recursion depth\n * @returns The sanitized value\n */\nconst sanitizeValue = (value: unknown, depth = 0): unknown => {\n // Prevent infinite recursion\n if (depth > MAX_OBJECT_DEPTH) {\n // Silent depth limit - prevents stack overflow\n return null;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return sanitizeString(value);\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < -Number.MAX_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {\n // Silent normalization - invalid numbers become 0\n return 0;\n }\n\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (Array.isArray(value)) {\n const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);\n\n // Silent array length limit\n const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);\n\n // Silent filter - empty arrays are valid results\n return sanitizedArray;\n }\n\n if (typeof value === 'object') {\n const sanitizedObject: Record<string, unknown> = {};\n const entries = Object.entries(value);\n const limitedEntries = entries.slice(0, MAX_NESTED_OBJECT_KEYS);\n\n // Silent object keys limit\n for (const [key, value_] of limitedEntries) {\n const sanitizedKey = sanitizeString(key);\n\n if (sanitizedKey) {\n const sanitizedValue = sanitizeValue(value_, depth + 1);\n\n if (sanitizedValue !== null) {\n sanitizedObject[sanitizedKey] = sanitizedValue;\n }\n }\n }\n\n return sanitizedObject;\n }\n\n return null;\n};\n\n/**\n * Sanitizes user metadata for custom events\n * @param metadata - The metadata to sanitize\n * @returns The sanitized metadata\n */\nexport const sanitizeMetadata = (metadata: unknown): Record<string, MetadataType> => {\n if (typeof metadata !== 'object' || metadata === null) {\n return {};\n }\n\n try {\n const sanitized = sanitizeValue(metadata);\n const result =\n typeof sanitized === 'object' && sanitized !== null ? (sanitized as Record<string, MetadataType>) : {};\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] Metadata sanitization failed: ${errorMessage}`);\n }\n};\n","import {\n MAX_SESSION_TIMEOUT_MS,\n MIN_SESSION_TIMEOUT_MS,\n DEFAULT_SESSION_TIMEOUT,\n DEFAULT_SAMPLING_RATE,\n VALIDATION_MESSAGES,\n DEFAULT_PAGE_VIEW_THROTTLE_MS,\n DEFAULT_CLICK_THROTTLE_MS,\n MAX_SAME_EVENT_PER_MINUTE,\n DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n DEFAULT_VISIBILITY_TIMEOUT_MS,\n} from '../../constants';\nimport { DEFAULT_ERROR_SAMPLING_RATE } from '../../constants/error.constants';\nimport { Config } from '../../types';\nimport {\n AppConfigValidationError,\n SessionTimeoutValidationError,\n SamplingRateValidationError,\n IntegrationValidationError,\n} from '../../types/validation-error.types';\n\n/**\n * Validates the app configuration object (before normalization)\n * This validates the structure and basic types but allows for normalization afterward\n * @param config - The app configuration to validate\n * @throws {ProjectIdValidationError} If project ID validation fails\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAppConfig = (config?: Config): void => {\n if (config !== undefined && (config === null || typeof config !== 'object')) {\n throw new AppConfigValidationError('Configuration must be an object', 'config');\n }\n\n if (!config) {\n return;\n }\n\n if (config.sessionTimeout !== undefined) {\n if (\n typeof config.sessionTimeout !== 'number' ||\n config.sessionTimeout < MIN_SESSION_TIMEOUT_MS ||\n config.sessionTimeout > MAX_SESSION_TIMEOUT_MS\n ) {\n throw new SessionTimeoutValidationError(VALIDATION_MESSAGES.INVALID_SESSION_TIMEOUT, 'config');\n }\n }\n\n if (config.globalMetadata !== undefined) {\n if (typeof config.globalMetadata !== 'object' || config.globalMetadata === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_GLOBAL_METADATA, 'config');\n }\n }\n\n if (config.integrations) {\n validateIntegrations(config.integrations);\n }\n\n if (config.sensitiveQueryParams !== undefined) {\n if (!Array.isArray(config.sensitiveQueryParams)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SENSITIVE_QUERY_PARAMS, 'config');\n }\n\n for (const param of config.sensitiveQueryParams) {\n if (typeof param !== 'string') {\n throw new AppConfigValidationError('All sensitive query params must be strings', 'config');\n }\n }\n }\n\n if (config.errorSampling !== undefined) {\n if (typeof config.errorSampling !== 'number' || config.errorSampling < 0 || config.errorSampling > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_ERROR_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.samplingRate !== undefined) {\n if (typeof config.samplingRate !== 'number' || config.samplingRate < 0 || config.samplingRate > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.primaryScrollSelector !== undefined) {\n if (typeof config.primaryScrollSelector !== 'string' || !config.primaryScrollSelector.trim()) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_PRIMARY_SCROLL_SELECTOR, 'config');\n }\n\n // Validate CSS selector syntax (skip for 'window' special value)\n if (config.primaryScrollSelector !== 'window') {\n try {\n document.querySelector(config.primaryScrollSelector);\n } catch {\n throw new AppConfigValidationError(\n `${VALIDATION_MESSAGES.INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX}: \"${config.primaryScrollSelector}\"`,\n 'config',\n );\n }\n }\n }\n\n if (config.pageViewThrottleMs !== undefined) {\n if (typeof config.pageViewThrottleMs !== 'number' || config.pageViewThrottleMs < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_PAGE_VIEW_THROTTLE, 'config');\n }\n }\n\n if (config.clickThrottleMs !== undefined) {\n if (typeof config.clickThrottleMs !== 'number' || config.clickThrottleMs < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_CLICK_THROTTLE, 'config');\n }\n }\n\n if (config.maxSameEventPerMinute !== undefined) {\n if (typeof config.maxSameEventPerMinute !== 'number' || config.maxSameEventPerMinute <= 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_MAX_SAME_EVENT_PER_MINUTE, 'config');\n }\n }\n\n if (config.viewport !== undefined) {\n validateViewportConfig(config.viewport);\n }\n};\n\n/**\n * Validates viewport configuration\n * @param viewport - Viewport configuration to validate\n */\nconst validateViewportConfig = (viewport: Config['viewport']): void => {\n if (typeof viewport !== 'object' || viewport === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_CONFIG, 'config');\n }\n\n // Validate elements array\n if (!viewport.elements || !Array.isArray(viewport.elements)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENTS, 'config');\n }\n\n if (viewport.elements.length === 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENTS, 'config');\n }\n\n // Track unique selectors to detect duplicates\n const uniqueSelectors = new Set<string>();\n\n // Validate each element\n for (const element of viewport.elements) {\n if (!element.selector || typeof element.selector !== 'string' || !element.selector.trim()) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT, 'config');\n }\n\n // Check for duplicate selectors\n const normalizedSelector = element.selector.trim();\n if (uniqueSelectors.has(normalizedSelector)) {\n throw new AppConfigValidationError(\n `Duplicate viewport selector found: \"${normalizedSelector}\". Each selector should appear only once.`,\n 'config',\n );\n }\n uniqueSelectors.add(normalizedSelector);\n\n if (element.id !== undefined && (typeof element.id !== 'string' || !element.id.trim())) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT_ID, 'config');\n }\n\n if (element.name !== undefined && (typeof element.name !== 'string' || !element.name.trim())) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT_NAME, 'config');\n }\n }\n\n // Validate threshold\n if (viewport.threshold !== undefined) {\n if (typeof viewport.threshold !== 'number' || viewport.threshold < 0 || viewport.threshold > 1) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_THRESHOLD, 'config');\n }\n }\n\n // Validate minDwellTime\n if (viewport.minDwellTime !== undefined) {\n if (typeof viewport.minDwellTime !== 'number' || viewport.minDwellTime < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_MIN_DWELL_TIME, 'config');\n }\n }\n\n // Validate cooldownPeriod\n if (viewport.cooldownPeriod !== undefined) {\n if (typeof viewport.cooldownPeriod !== 'number' || viewport.cooldownPeriod < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_COOLDOWN_PERIOD, 'config');\n }\n }\n\n // Validate maxTrackedElements\n if (viewport.maxTrackedElements !== undefined) {\n if (typeof viewport.maxTrackedElements !== 'number' || viewport.maxTrackedElements <= 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS, 'config');\n }\n }\n};\n\n/**\n * Validates integrations configuration\n * @param integrations - Integrations configuration to validate\n */\nconst validateIntegrations = (integrations: Config['integrations']): void => {\n if (!integrations) {\n return;\n }\n\n if (integrations.tracelog) {\n if (\n !integrations.tracelog.projectId ||\n typeof integrations.tracelog.projectId !== 'string' ||\n integrations.tracelog.projectId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_TRACELOG_PROJECT_ID, 'config');\n }\n }\n\n if (integrations.custom) {\n if (\n !integrations.custom.collectApiUrl ||\n typeof integrations.custom.collectApiUrl !== 'string' ||\n integrations.custom.collectApiUrl.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_CUSTOM_API_URL, 'config');\n }\n\n if (integrations.custom.allowHttp !== undefined && typeof integrations.custom.allowHttp !== 'boolean') {\n throw new IntegrationValidationError('allowHttp must be a boolean', 'config');\n }\n\n const collectApiUrl = integrations.custom.collectApiUrl.trim();\n\n if (!collectApiUrl.startsWith('http://') && !collectApiUrl.startsWith('https://')) {\n throw new IntegrationValidationError('Custom API URL must start with \"http://\" or \"https://\"', 'config');\n }\n\n const allowHttp = integrations.custom.allowHttp ?? false;\n\n if (!allowHttp && collectApiUrl.startsWith('http://')) {\n throw new IntegrationValidationError(\n 'Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)',\n 'config',\n );\n }\n }\n\n if (integrations.googleAnalytics) {\n if (\n !integrations.googleAnalytics.measurementId ||\n typeof integrations.googleAnalytics.measurementId !== 'string' ||\n integrations.googleAnalytics.measurementId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_GOOGLE_ANALYTICS_ID, 'config');\n }\n\n const measurementId = integrations.googleAnalytics.measurementId.trim();\n\n if (!measurementId.match(/^(G-|UA-)/)) {\n throw new IntegrationValidationError('Google Analytics measurement ID must start with \"G-\" or \"UA-\"', 'config');\n }\n }\n};\n\n/**\n * Validates and normalizes the app configuration\n * This is the primary validation entry point that ensures consistent behavior\n * @param config - The app configuration to validate and normalize\n * @returns The normalized configuration\n * @throws {ProjectIdValidationError} If project ID validation fails after normalization\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAndNormalizeConfig = (config?: Config): Config => {\n validateAppConfig(config);\n\n const normalizedConfig: Config = {\n ...(config ?? {}),\n sessionTimeout: config?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,\n globalMetadata: config?.globalMetadata ?? {},\n sensitiveQueryParams: config?.sensitiveQueryParams ?? [],\n errorSampling: config?.errorSampling ?? DEFAULT_ERROR_SAMPLING_RATE,\n samplingRate: config?.samplingRate ?? DEFAULT_SAMPLING_RATE,\n pageViewThrottleMs: config?.pageViewThrottleMs ?? DEFAULT_PAGE_VIEW_THROTTLE_MS,\n clickThrottleMs: config?.clickThrottleMs ?? DEFAULT_CLICK_THROTTLE_MS,\n maxSameEventPerMinute: config?.maxSameEventPerMinute ?? MAX_SAME_EVENT_PER_MINUTE,\n };\n\n // Normalize integrations\n if (normalizedConfig.integrations?.custom) {\n normalizedConfig.integrations.custom = {\n ...normalizedConfig.integrations.custom,\n allowHttp: normalizedConfig.integrations.custom.allowHttp ?? false,\n };\n }\n\n // Normalize viewport config\n if (normalizedConfig.viewport) {\n normalizedConfig.viewport = {\n ...normalizedConfig.viewport,\n threshold: normalizedConfig.viewport.threshold ?? 0.5,\n minDwellTime: normalizedConfig.viewport.minDwellTime ?? DEFAULT_VISIBILITY_TIMEOUT_MS,\n cooldownPeriod: normalizedConfig.viewport.cooldownPeriod ?? DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n maxTrackedElements: normalizedConfig.viewport.maxTrackedElements ?? DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n };\n }\n\n return normalizedConfig;\n};\n","import { MAX_NESTED_OBJECT_KEYS, MAX_METADATA_NESTING_DEPTH } from '../../constants';\n\n/**\n * Validates if an item in an array is a valid nested object\n * @param item - The item to validate\n * @returns True if the item is a valid nested object\n */\nconst isValidArrayItem = (item: unknown): boolean => {\n if (typeof item === 'string') {\n return true;\n }\n\n // Allow objects with primitive fields only (one level deep)\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const entries = Object.entries(item);\n\n // Check key count limit\n if (entries.length > MAX_NESTED_OBJECT_KEYS) {\n return false;\n }\n\n // All values must be primitives (no nested objects or arrays)\n for (const [, value] of entries) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n};\n\n/**\n * Checks if an object contains only primitive fields, string arrays, arrays of flat objects,\n * or nested objects with primitive fields\n * @param object - The object to check\n * @param depth - Current nesting depth (default: 0, max: MAX_METADATA_NESTING_DEPTH)\n * @returns True if the object contains only valid fields\n */\nexport const isOnlyPrimitiveFields = (object: Record<string, unknown>, depth = 0): boolean => {\n if (typeof object !== 'object' || object === null) {\n return false;\n }\n\n if (depth > MAX_METADATA_NESTING_DEPTH) {\n return false;\n }\n\n for (const value of Object.values(object)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type === 'string' || type === 'number' || type === 'boolean') {\n continue;\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n\n // Determine array type from first item\n const firstItem = value[0];\n const isStringArray = typeof firstItem === 'string';\n\n // All items must be of the same type (all strings OR all objects)\n if (isStringArray) {\n if (!value.every((item) => typeof item === 'string')) {\n return false;\n }\n } else {\n // Must be all objects\n if (!value.every((item) => isValidArrayItem(item))) {\n return false;\n }\n }\n\n continue;\n }\n\n // Allow nested objects at depth 0 only (one level deep)\n if (type === 'object' && depth === 0) {\n if (!isOnlyPrimitiveFields(value as Record<string, unknown>, depth + 1)) {\n return false;\n }\n continue;\n }\n\n return false;\n }\n\n return true;\n};\n","import {\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_STRING_LENGTH,\n MAX_STRING_LENGTH_IN_ARRAY,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { sanitizeMetadata } from '../security/sanitize.utils';\nimport { isOnlyPrimitiveFields } from './type-guards.utils';\n\n/**\n * Validates an event name\n * @param eventName - The event name to validate\n * @returns Validation result with error message if invalid\n */\nexport const isValidEventName = (eventName: string): { valid: boolean; error?: string } => {\n if (typeof eventName !== 'string') {\n return {\n valid: false,\n error: 'Event name must be a string',\n };\n }\n\n if (eventName.length === 0) {\n return {\n valid: false,\n error: 'Event name cannot be empty',\n };\n }\n\n if (eventName.length > MAX_CUSTOM_EVENT_NAME_LENGTH) {\n return {\n valid: false,\n error: `Event name is too long (max ${MAX_CUSTOM_EVENT_NAME_LENGTH} characters)`,\n };\n }\n\n if (eventName.includes('<') || eventName.includes('>') || eventName.includes('&')) {\n return {\n valid: false,\n error: 'Event name contains invalid characters',\n };\n }\n\n const reservedWords = ['constructor', 'prototype', '__proto__', 'eval', 'function', 'var', 'let', 'const'];\n\n if (reservedWords.includes(eventName.toLowerCase())) {\n return {\n valid: false,\n error: 'Event name cannot be a reserved word',\n };\n }\n\n return { valid: true };\n};\n\n/**\n * Validates a single metadata object\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata object to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nconst validateSingleMetadata = (\n eventName: string,\n metadata: Record<string, unknown>,\n type?: 'globalMetadata' | 'customEvent',\n): { valid: boolean; error?: string; sanitizedMetadata?: Record<string, MetadataType> } => {\n const sanitizedMetadata = sanitizeMetadata(metadata);\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n if (!isOnlyPrimitiveFields(sanitizedMetadata)) {\n return {\n valid: false,\n error: `${intro}: object has invalid types. Valid types are string, number, boolean or string arrays.`,\n };\n }\n\n let jsonString: string;\n\n try {\n jsonString = JSON.stringify(sanitizedMetadata);\n } catch {\n return {\n valid: false,\n error: `${intro}: object contains circular references or cannot be serialized.`,\n };\n }\n\n if (jsonString.length > MAX_CUSTOM_EVENT_STRING_SIZE) {\n return {\n valid: false,\n error: `${intro}: object is too large (max ${MAX_CUSTOM_EVENT_STRING_SIZE / 1024} KB).`,\n };\n }\n\n const keyCount = Object.keys(sanitizedMetadata).length;\n\n if (keyCount > MAX_CUSTOM_EVENT_KEYS) {\n return {\n valid: false,\n error: `${intro}: object has too many keys (max ${MAX_CUSTOM_EVENT_KEYS} keys).`,\n };\n }\n\n for (const [key, value] of Object.entries(sanitizedMetadata)) {\n if (Array.isArray(value)) {\n if (value.length > MAX_CUSTOM_EVENT_ARRAY_SIZE) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" is too large (max ${MAX_CUSTOM_EVENT_ARRAY_SIZE} items).`,\n };\n }\n\n for (const item of value) {\n if (typeof item === 'string' && item.length > MAX_STRING_LENGTH_IN_ARRAY) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" contains strings that are too long (max ${MAX_STRING_LENGTH_IN_ARRAY} characters).`,\n };\n }\n }\n }\n\n if (typeof value === 'string' && value.length > MAX_STRING_LENGTH) {\n return {\n valid: false,\n error: `${intro}: property \"${key}\" is too long (max ${MAX_STRING_LENGTH} characters).`,\n };\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata,\n };\n};\n\n/**\n * Validates metadata for events (supports both objects and arrays of objects)\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isValidMetadata = (\n eventName: string,\n metadata: Record<string, unknown> | Record<string, unknown>[],\n type?: 'globalMetadata' | 'customEvent',\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n if (Array.isArray(metadata)) {\n const sanitizedArray: Record<string, MetadataType>[] = [];\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n for (let i = 0; i < metadata.length; i++) {\n const item = metadata[i];\n\n if (typeof item !== 'object' || item === null || Array.isArray(item)) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} must be an object.`,\n };\n }\n\n const itemValidation = validateSingleMetadata(eventName, item, type);\n\n if (!itemValidation.valid) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} is invalid: ${itemValidation.error}`,\n };\n }\n\n if (itemValidation.sanitizedMetadata) {\n sanitizedArray.push(itemValidation.sanitizedMetadata);\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata: sanitizedArray,\n };\n }\n\n return validateSingleMetadata(eventName, metadata, type);\n};\n","import { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\nimport { isValidEventName, isValidMetadata } from './metadata-validations.utils';\n\n/**\n * Validates a complete event with name and optional metadata\n * @param eventName - The event name to validate\n * @param metadata - Optional metadata to validate\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isEventValid = (\n eventName: string,\n metadata?: Record<string, unknown> | Record<string, unknown>[],\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n const nameValidation = isValidEventName(eventName);\n\n if (!nameValidation.valid) {\n log('error', 'Event name validation failed', {\n showToClient: true,\n data: { eventName, error: nameValidation.error },\n });\n\n return nameValidation;\n }\n\n if (!metadata) {\n return { valid: true };\n }\n\n const metadataValidation = isValidMetadata(eventName, metadata, 'customEvent');\n\n if (!metadataValidation.valid) {\n log('error', 'Event metadata validation failed', {\n showToClient: true,\n data: {\n eventName,\n error: metadataValidation.error,\n },\n });\n }\n\n return metadataValidation;\n};\n","import { EmitterCallback, EmitterMap } from '../types';\n\nexport class Emitter {\n private readonly listeners: Map<string, EmitterCallback[]> = new Map();\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n\n this.listeners.get(event)!.push(callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n const index = callbacks.indexOf(callback);\n\n if (index > -1) {\n callbacks.splice(index, 1);\n }\n }\n }\n\n emit<K extends keyof EmitterMap>(event: K, data: EmitterMap[K]): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n callbacks.forEach((callback) => {\n callback(data);\n });\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { State } from '../types';\n\nconst globalState: State = {} as State;\n\nexport function getGlobalState(): Readonly<State> {\n return globalState;\n}\n\nexport function resetGlobalState(): void {\n Object.keys(globalState).forEach((key) => {\n delete globalState[key as keyof State];\n });\n}\n\nexport abstract class StateManager {\n protected get<T extends keyof State>(key: T): State[T] {\n return globalState[key];\n }\n\n protected set<T extends keyof State>(key: T, value: State[T]): void {\n globalState[key] = value;\n }\n\n protected getState(): Readonly<State> {\n return { ...globalState };\n }\n}\n","import {\n QUEUE_KEY,\n EVENT_EXPIRY_HOURS,\n REQUEST_TIMEOUT_MS,\n PERMANENT_ERROR_LOG_THROTTLE_MS,\n MAX_BEACON_PAYLOAD_SIZE,\n} from '../constants';\nimport { PersistedQueueData, BaseEventsQueueDto, SpecialApiUrl, PermanentError } from '../types';\nimport { log } from '../utils';\nimport { StorageManager } from './storage.manager';\nimport { StateManager } from './state.manager';\n\ninterface SendCallbacks {\n onSuccess?: (eventCount?: number, events?: any[], body?: BaseEventsQueueDto) => void;\n onFailure?: () => void;\n}\n\nexport class SenderManager extends StateManager {\n private readonly storeManager: StorageManager;\n private lastPermanentErrorLog: { statusCode?: number; timestamp: number } | null = null;\n\n constructor(storeManager: StorageManager) {\n super();\n this.storeManager = storeManager;\n }\n\n private getQueueStorageKey(): string {\n const userId = this.get('userId') || 'anonymous';\n return QUEUE_KEY(userId);\n }\n\n sendEventsQueueSync(body: BaseEventsQueueDto): boolean {\n if (this.shouldSkipSend()) {\n return true;\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure (sync)', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n return this.sendQueueSyncInternal(body);\n }\n\n async sendEventsQueue(body: BaseEventsQueueDto, callbacks?: SendCallbacks): Promise<boolean> {\n try {\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n callbacks?.onSuccess?.(body.events.length, body.events, body);\n } else {\n this.persistEvents(body);\n callbacks?.onFailure?.();\n }\n\n return success;\n } catch (error) {\n if (error instanceof PermanentError) {\n this.logPermanentError('Permanent error, not retrying', error);\n this.clearPersistedEvents();\n callbacks?.onFailure?.();\n return false;\n }\n\n this.persistEvents(body);\n callbacks?.onFailure?.();\n return false;\n }\n }\n\n async recoverPersistedEvents(callbacks?: SendCallbacks): Promise<void> {\n try {\n const persistedData = this.getPersistedData();\n\n if (!persistedData || !this.isDataRecent(persistedData) || persistedData.events.length === 0) {\n this.clearPersistedEvents();\n return;\n }\n\n const body = this.createRecoveryBody(persistedData);\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n callbacks?.onSuccess?.(persistedData.events.length, persistedData.events, body);\n } else {\n callbacks?.onFailure?.();\n }\n } catch (error) {\n if (error instanceof PermanentError) {\n this.logPermanentError('Permanent error during recovery, clearing persisted events', error);\n this.clearPersistedEvents();\n callbacks?.onFailure?.();\n return;\n }\n\n log('error', 'Failed to recover persisted events', { error });\n }\n }\n\n stop(): void {}\n\n private async send(body: BaseEventsQueueDto): Promise<boolean> {\n if (this.shouldSkipSend()) {\n return this.simulateSuccessfulSend();\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const { url, payload } = this.prepareRequest(body);\n\n try {\n const response = await this.sendWithTimeout(url, payload);\n\n return response.ok;\n } catch (error) {\n if (error instanceof PermanentError) {\n throw error;\n }\n\n log('error', 'Send request failed', {\n error,\n data: {\n events: body.events.length,\n url: url.replace(/\\/\\/[^/]+/, '//[DOMAIN]'),\n },\n });\n\n return false;\n }\n }\n\n private async sendWithTimeout(url: string, payload: string): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n body: payload,\n keepalive: true,\n credentials: 'include',\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const isPermanentError = response.status >= 400 && response.status < 500;\n\n if (isPermanentError) {\n throw new PermanentError(`HTTP ${response.status}: ${response.statusText}`, response.status);\n }\n\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private sendQueueSyncInternal(body: BaseEventsQueueDto): boolean {\n const { url, payload } = this.prepareRequest(body);\n\n // Check payload size against 64KB browser limit (Phase 3)\n if (payload.length > MAX_BEACON_PAYLOAD_SIZE) {\n log('warn', 'Payload exceeds sendBeacon limit, persisting for recovery', {\n data: {\n size: payload.length,\n limit: MAX_BEACON_PAYLOAD_SIZE,\n events: body.events.length,\n },\n });\n this.persistEvents(body);\n return false;\n }\n\n const blob = new Blob([payload], { type: 'application/json' });\n\n if (!this.isSendBeaconAvailable()) {\n log('warn', 'sendBeacon not available, persisting events for recovery');\n this.persistEvents(body);\n return false;\n }\n\n // sendBeacon only returns true/false without HTTP status codes\n // true: browser accepted the request for sending\n // false: request rejected (queue full, size limits, etc.)\n const accepted = navigator.sendBeacon(url, blob);\n\n if (!accepted) {\n log('warn', 'sendBeacon rejected request, persisting events for recovery');\n this.persistEvents(body);\n }\n\n return accepted;\n }\n\n private prepareRequest(body: BaseEventsQueueDto): { url: string; payload: string } {\n // Enrich payload with metadata for sendBeacon() fallback\n // sendBeacon() doesn't send custom headers, so we include referer in payload\n const enrichedBody = {\n ...body,\n _metadata: {\n referer: typeof window !== 'undefined' ? window.location.href : undefined,\n timestamp: Date.now(),\n },\n };\n\n return {\n url: this.get('collectApiUrl'),\n payload: JSON.stringify(enrichedBody),\n };\n }\n\n private getPersistedData(): PersistedQueueData | null {\n try {\n const storageKey = this.getQueueStorageKey();\n const persistedDataString = this.storeManager.getItem(storageKey);\n\n if (persistedDataString) {\n return JSON.parse(persistedDataString);\n }\n } catch (error) {\n log('warn', 'Failed to parse persisted data', { error });\n this.clearPersistedEvents();\n }\n\n return null;\n }\n\n private isDataRecent(data: PersistedQueueData): boolean {\n if (!data.timestamp || typeof data.timestamp !== 'number') {\n return false;\n }\n\n const ageInHours = (Date.now() - data.timestamp) / (1000 * 60 * 60);\n return ageInHours < EVENT_EXPIRY_HOURS;\n }\n\n private createRecoveryBody(data: PersistedQueueData): BaseEventsQueueDto {\n return {\n user_id: data.userId,\n session_id: data.sessionId,\n device: data.device,\n events: data.events,\n ...(data.global_metadata && { global_metadata: data.global_metadata }),\n };\n }\n\n private persistEvents(body: BaseEventsQueueDto): boolean {\n try {\n const persistedData: PersistedQueueData = {\n userId: body.user_id,\n sessionId: body.session_id,\n device: body.device,\n events: body.events,\n timestamp: Date.now(),\n ...(body.global_metadata && { global_metadata: body.global_metadata }),\n };\n\n const storageKey = this.getQueueStorageKey();\n this.storeManager.setItem(storageKey, JSON.stringify(persistedData));\n\n return !!this.storeManager.getItem(storageKey);\n } catch (error) {\n log('warn', 'Failed to persist events', { error });\n return false;\n }\n }\n\n private clearPersistedEvents(): void {\n try {\n const key = this.getQueueStorageKey();\n this.storeManager.removeItem(key);\n } catch (error) {\n log('warn', 'Failed to clear persisted events', { error });\n }\n }\n\n private shouldSkipSend(): boolean {\n return !this.get('collectApiUrl');\n }\n\n private async simulateSuccessfulSend(): Promise<boolean> {\n const delay = Math.random() * 400 + 100;\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return true;\n }\n\n private isSendBeaconAvailable(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n }\n\n private logPermanentError(context: string, error: PermanentError): void {\n const now = Date.now();\n const shouldLog =\n !this.lastPermanentErrorLog ||\n this.lastPermanentErrorLog.statusCode !== error.statusCode ||\n now - this.lastPermanentErrorLog.timestamp >= PERMANENT_ERROR_LOG_THROTTLE_MS;\n\n if (shouldLog) {\n log('error', context, {\n data: { status: error.statusCode, message: error.message },\n });\n\n this.lastPermanentErrorLog = { statusCode: error.statusCode, timestamp: now };\n }\n }\n}\n","import {\n EVENT_SENT_INTERVAL_MS,\n MAX_EVENTS_QUEUE_LENGTH,\n DUPLICATE_EVENT_THRESHOLD_MS,\n RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SECOND,\n MAX_PENDING_EVENTS_BUFFER,\n BATCH_SIZE_THRESHOLD,\n MAX_SAME_EVENT_PER_MINUTE,\n PER_EVENT_RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SESSION,\n MAX_CLICKS_PER_SESSION,\n MAX_PAGE_VIEWS_PER_SESSION,\n MAX_CUSTOM_EVENTS_PER_SESSION,\n MAX_VIEWPORT_EVENTS_PER_SESSION,\n MAX_SCROLL_EVENTS_PER_SESSION,\n MAX_FINGERPRINTS,\n FINGERPRINT_CLEANUP_MULTIPLIER,\n MAX_FINGERPRINTS_HARD_LIMIT,\n} from '../constants/config.constants';\nimport { BaseEventsQueueDto, EmitterEvent, EventData, EventType, Mode } from '../types';\nimport { getUTMParameters, log, Emitter, generateEventId } from '../utils';\nimport { SenderManager } from './sender.manager';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { GoogleAnalyticsIntegration } from '../integrations/google-analytics.integration';\n\nexport class EventManager extends StateManager {\n private readonly googleAnalytics: GoogleAnalyticsIntegration | null;\n private readonly dataSender: SenderManager;\n private readonly emitter: Emitter | null;\n\n private eventsQueue: EventData[] = [];\n private pendingEventsBuffer: Partial<EventData>[] = [];\n private readonly recentEventFingerprints = new Map<string, number>(); // Time-based deduplication cache\n private sendIntervalId: number | null = null;\n private rateLimitCounter = 0;\n private rateLimitWindowStart = 0;\n private readonly perEventRateLimits: Map<string, number[]> = new Map();\n private sessionEventCounts: {\n total: number;\n [key: string]: number;\n } = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n private lastSessionId: string | null = null;\n\n constructor(\n storeManager: StorageManager,\n googleAnalytics: GoogleAnalyticsIntegration | null = null,\n emitter: Emitter | null = null,\n ) {\n super();\n\n this.googleAnalytics = googleAnalytics;\n this.dataSender = new SenderManager(storeManager);\n this.emitter = emitter;\n }\n\n async recoverPersistedEvents(): Promise<void> {\n await this.dataSender.recoverPersistedEvents({\n onSuccess: (_eventCount, recoveredEvents, body) => {\n if (recoveredEvents && recoveredEvents.length > 0) {\n const eventIds = recoveredEvents.map((e) => e.id);\n this.removeProcessedEvents(eventIds);\n\n if (body) {\n this.emitEventsQueue(body);\n }\n }\n },\n onFailure: () => {\n log('warn', 'Failed to recover persisted events');\n },\n });\n }\n\n track({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n }: Partial<EventData>): void {\n if (!type) {\n log('error', 'Event type is required - event will be ignored');\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n if (this.pendingEventsBuffer.length >= MAX_PENDING_EVENTS_BUFFER) {\n this.pendingEventsBuffer.shift();\n log('warn', 'Pending events buffer full - dropping oldest event', {\n data: { maxBufferSize: MAX_PENDING_EVENTS_BUFFER },\n });\n }\n\n this.pendingEventsBuffer.push({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n });\n\n return;\n }\n\n // Reset session counters if session ID changed (Phase 3)\n if (this.lastSessionId !== currentSessionId) {\n this.lastSessionId = currentSessionId;\n this.sessionEventCounts = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n }\n\n const isCriticalEvent = type === EventType.SESSION_START || type === EventType.SESSION_END;\n if (!isCriticalEvent && !this.checkRateLimit()) {\n return;\n }\n\n const eventType = type as EventType;\n\n // Per-session event caps (Phase 3) - skip for critical events\n if (!isCriticalEvent) {\n // Check total session limit\n if (this.sessionEventCounts.total >= MAX_EVENTS_PER_SESSION) {\n log('warn', 'Session event limit reached', {\n data: {\n type: eventType,\n total: this.sessionEventCounts.total,\n limit: MAX_EVENTS_PER_SESSION,\n },\n });\n return;\n }\n\n // Check type-specific limits\n const typeLimit = this.getTypeLimitForEvent(eventType);\n if (typeLimit) {\n const currentCount = this.sessionEventCounts[eventType];\n if (currentCount !== undefined && currentCount >= typeLimit) {\n log('warn', 'Session event type limit reached', {\n data: {\n type: eventType,\n count: currentCount,\n limit: typeLimit,\n },\n });\n return;\n }\n }\n }\n\n // Per-event-name rate limiting for CUSTOM events to prevent infinite loops\n if (eventType === EventType.CUSTOM && custom_event?.name) {\n const maxSameEventPerMinute = this.get('config')?.maxSameEventPerMinute ?? MAX_SAME_EVENT_PER_MINUTE;\n if (!this.checkPerEventRateLimit(custom_event.name, maxSameEventPerMinute)) {\n return;\n }\n }\n const isSessionStart = eventType === EventType.SESSION_START;\n\n const currentPageUrl = (page_url as string) || this.get('pageUrl');\n const payload = this.buildEventPayload({\n type: eventType,\n page_url: currentPageUrl,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n });\n\n if (!isCriticalEvent && !this.shouldSample()) {\n return;\n }\n\n if (isSessionStart) {\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n log('error', 'Session start event requires sessionId - event will be ignored');\n return;\n }\n\n if (this.get('hasStartSession')) {\n log('warn', 'Duplicate session_start detected', {\n data: { sessionId: currentSessionId },\n });\n\n return;\n }\n\n this.set('hasStartSession', true);\n }\n\n if (this.isDuplicateEvent(payload)) {\n return;\n }\n\n if (this.get('mode') === Mode.QA && eventType === EventType.CUSTOM && custom_event) {\n console.log('[TraceLog] Event', {\n name: custom_event.name,\n ...(custom_event.metadata && { metadata: custom_event.metadata }),\n });\n\n this.emitEvent(payload);\n\n return;\n }\n\n this.addToQueue(payload);\n\n // Increment session counters (Phase 3) - only for non-critical events\n if (!isCriticalEvent) {\n this.sessionEventCounts.total++;\n if (this.sessionEventCounts[eventType] !== undefined) {\n this.sessionEventCounts[eventType]++;\n }\n }\n }\n\n stop(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n\n this.eventsQueue = [];\n this.pendingEventsBuffer = [];\n this.recentEventFingerprints.clear();\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = 0;\n this.perEventRateLimits.clear();\n this.sessionEventCounts = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n this.lastSessionId = null;\n\n this.dataSender.stop();\n }\n\n async flushImmediately(): Promise<boolean> {\n return this.flushEvents(false);\n }\n\n flushImmediatelySync(): boolean {\n return this.flushEvents(true) as boolean;\n }\n\n getQueueLength(): number {\n return this.eventsQueue.length;\n }\n\n flushPendingEvents(): void {\n if (this.pendingEventsBuffer.length === 0) {\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n if (!currentSessionId) {\n log('warn', 'Cannot flush pending events: session not initialized - keeping in buffer', {\n data: { bufferedEventCount: this.pendingEventsBuffer.length },\n });\n\n return;\n }\n\n const bufferedEvents = [...this.pendingEventsBuffer];\n this.pendingEventsBuffer = [];\n\n bufferedEvents.forEach((event) => {\n this.track(event);\n });\n }\n\n private clearSendInterval(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n }\n\n private flushEvents(isSync: boolean): boolean | Promise<boolean> {\n if (this.eventsQueue.length === 0) {\n return isSync ? true : Promise.resolve(true);\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n if (isSync) {\n const success = this.dataSender.sendEventsQueueSync(body);\n\n if (success) {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n }\n\n return success;\n } else {\n return this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n log('warn', 'Async flush failed', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n }\n\n private async sendEventsQueue(): Promise<void> {\n if (!this.get('sessionId') || this.eventsQueue.length === 0) {\n return;\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n await this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n log('warn', 'Events send failed, keeping in queue', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n\n private buildEventsPayload(): BaseEventsQueueDto {\n const eventMap = new Map<string, EventData>();\n const order: string[] = [];\n\n for (const event of this.eventsQueue) {\n const signature = this.createEventSignature(event);\n\n if (!eventMap.has(signature)) {\n order.push(signature);\n }\n\n eventMap.set(signature, event);\n }\n\n const events = order\n .map((signature) => eventMap.get(signature))\n .filter((event): event is EventData => Boolean(event))\n .sort((a, b) => a.timestamp - b.timestamp);\n\n return {\n user_id: this.get('userId'),\n session_id: this.get('sessionId') as string,\n device: this.get('device'),\n events,\n ...(this.get('config')?.globalMetadata && { global_metadata: this.get('config')?.globalMetadata }),\n };\n }\n\n private buildEventPayload(data: Partial<EventData>): EventData {\n const isSessionStart = data.type === EventType.SESSION_START;\n const currentPageUrl = data.page_url ?? this.get('pageUrl');\n\n const payload: EventData = {\n id: generateEventId(),\n type: data.type as EventType,\n page_url: currentPageUrl,\n timestamp: Date.now(),\n ...(isSessionStart && { referrer: document.referrer || 'Direct' }),\n ...(data.from_page_url && { from_page_url: data.from_page_url }),\n ...(data.scroll_data && { scroll_data: data.scroll_data }),\n ...(data.click_data && { click_data: data.click_data }),\n ...(data.custom_event && { custom_event: data.custom_event }),\n ...(data.web_vitals && { web_vitals: data.web_vitals }),\n ...(data.error_data && { error_data: data.error_data }),\n ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),\n ...(data.viewport_data && { viewport_data: data.viewport_data }),\n ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),\n };\n\n return payload;\n }\n\n /**\n * Checks if event is a duplicate using time-based cache\n * Tracks recent event fingerprints with timestamp-based cleanup\n */\n private isDuplicateEvent(event: EventData): boolean {\n const now = Date.now();\n const fingerprint = this.createEventFingerprint(event);\n\n const lastSeen = this.recentEventFingerprints.get(fingerprint);\n\n // Check if seen recently\n if (lastSeen && now - lastSeen < DUPLICATE_EVENT_THRESHOLD_MS) {\n this.recentEventFingerprints.set(fingerprint, now); // Update timestamp\n return true; // Duplicate\n }\n\n // Add to cache\n this.recentEventFingerprints.set(fingerprint, now);\n\n // Cleanup if cache too large (soft limit)\n if (this.recentEventFingerprints.size > MAX_FINGERPRINTS) {\n this.pruneOldFingerprints();\n }\n\n // Hard limit: aggressive cleanup\n if (this.recentEventFingerprints.size > MAX_FINGERPRINTS_HARD_LIMIT) {\n this.recentEventFingerprints.clear();\n this.recentEventFingerprints.set(fingerprint, now);\n log('warn', 'Event fingerprint cache exceeded hard limit, cleared', {\n data: { hardLimit: MAX_FINGERPRINTS_HARD_LIMIT },\n });\n }\n\n return false;\n }\n\n /**\n * Prunes old fingerprints from cache based on timestamp\n * Removes entries older than 10x the duplicate threshold (5 seconds)\n */\n private pruneOldFingerprints(): void {\n const now = Date.now();\n const cutoff = DUPLICATE_EVENT_THRESHOLD_MS * FINGERPRINT_CLEANUP_MULTIPLIER; // 5 seconds\n\n for (const [fingerprint, timestamp] of this.recentEventFingerprints.entries()) {\n if (now - timestamp > cutoff) {\n this.recentEventFingerprints.delete(fingerprint);\n }\n }\n\n log('debug', 'Pruned old event fingerprints', {\n data: {\n remaining: this.recentEventFingerprints.size,\n cutoffMs: cutoff,\n },\n });\n }\n\n private createEventFingerprint(event: EventData): string {\n let fingerprint = `${event.type}_${event.page_url}`;\n\n if (event.click_data) {\n const x = Math.round((event.click_data.x || 0) / 10) * 10;\n const y = Math.round((event.click_data.y || 0) / 10) * 10;\n fingerprint += `_click_${x}_${y}`;\n }\n\n if (event.scroll_data) {\n fingerprint += `_scroll_${event.scroll_data.depth}_${event.scroll_data.direction}`;\n }\n\n if (event.custom_event) {\n fingerprint += `_custom_${event.custom_event.name}`;\n }\n\n if (event.web_vitals) {\n fingerprint += `_vitals_${event.web_vitals.type}`;\n }\n\n if (event.error_data) {\n fingerprint += `_error_${event.error_data.type}_${event.error_data.message}`;\n }\n\n return fingerprint;\n }\n\n private createEventSignature(event: EventData): string {\n return this.createEventFingerprint(event);\n }\n\n private addToQueue(event: EventData): void {\n this.eventsQueue.push(event);\n\n this.emitEvent(event);\n\n if (this.eventsQueue.length > MAX_EVENTS_QUEUE_LENGTH) {\n const nonCriticalIndex = this.eventsQueue.findIndex(\n (e) => e.type !== EventType.SESSION_START && e.type !== EventType.SESSION_END,\n );\n\n const removedEvent =\n nonCriticalIndex >= 0 ? this.eventsQueue.splice(nonCriticalIndex, 1)[0] : this.eventsQueue.shift();\n\n log('warn', 'Event queue overflow, oldest non-critical event removed', {\n data: {\n maxLength: MAX_EVENTS_QUEUE_LENGTH,\n currentLength: this.eventsQueue.length,\n removedEventType: removedEvent?.type,\n wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,\n },\n });\n }\n\n if (!this.sendIntervalId) {\n this.startSendInterval();\n }\n\n // Dynamic flush: Send immediately when batch size threshold is reached\n if (this.eventsQueue.length >= BATCH_SIZE_THRESHOLD) {\n void this.sendEventsQueue();\n }\n\n this.handleGoogleAnalyticsIntegration(event);\n }\n\n private startSendInterval(): void {\n this.sendIntervalId = window.setInterval(() => {\n if (this.eventsQueue.length > 0) {\n void this.sendEventsQueue();\n }\n }, EVENT_SENT_INTERVAL_MS);\n }\n\n private handleGoogleAnalyticsIntegration(event: EventData): void {\n if (this.googleAnalytics && event.type === EventType.CUSTOM && event.custom_event) {\n if (this.get('mode') === Mode.QA) {\n return;\n }\n\n this.googleAnalytics.trackEvent(event.custom_event.name, event.custom_event.metadata ?? {});\n }\n }\n\n private shouldSample(): boolean {\n const samplingRate = this.get('config')?.samplingRate ?? 1;\n return Math.random() < samplingRate;\n }\n\n private checkRateLimit(): boolean {\n const now = Date.now();\n\n if (now - this.rateLimitWindowStart > RATE_LIMIT_WINDOW_MS) {\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = now;\n }\n\n if (this.rateLimitCounter >= MAX_EVENTS_PER_SECOND) {\n return false;\n }\n\n this.rateLimitCounter++;\n return true;\n }\n\n /**\n * Checks per-event-name rate limiting to prevent infinite loops in user code\n * Tracks timestamps per event name and limits to maxSameEventPerMinute per minute\n */\n private checkPerEventRateLimit(eventName: string, maxSameEventPerMinute: number): boolean {\n const now = Date.now();\n const timestamps = this.perEventRateLimits.get(eventName) ?? [];\n\n // Remove timestamps older than the rate limit window (60 seconds)\n const validTimestamps = timestamps.filter((ts) => now - ts < PER_EVENT_RATE_LIMIT_WINDOW_MS);\n\n if (validTimestamps.length >= maxSameEventPerMinute) {\n log('warn', 'Per-event rate limit exceeded for custom event', {\n data: {\n eventName,\n limit: maxSameEventPerMinute,\n window: `${PER_EVENT_RATE_LIMIT_WINDOW_MS / 1000}s`,\n },\n });\n return false;\n }\n\n // Add current timestamp and update map\n validTimestamps.push(now);\n this.perEventRateLimits.set(eventName, validTimestamps);\n\n return true;\n }\n\n /**\n * Gets the per-session limit for a specific event type (Phase 3)\n */\n private getTypeLimitForEvent(type: EventType): number | null {\n const limits: Partial<Record<EventType, number>> = {\n [EventType.CLICK]: MAX_CLICKS_PER_SESSION,\n [EventType.PAGE_VIEW]: MAX_PAGE_VIEWS_PER_SESSION,\n [EventType.CUSTOM]: MAX_CUSTOM_EVENTS_PER_SESSION,\n [EventType.VIEWPORT_VISIBLE]: MAX_VIEWPORT_EVENTS_PER_SESSION,\n [EventType.SCROLL]: MAX_SCROLL_EVENTS_PER_SESSION,\n };\n return limits[type] ?? null;\n }\n\n private removeProcessedEvents(eventIds: string[]): void {\n const eventIdSet = new Set(eventIds);\n\n this.eventsQueue = this.eventsQueue.filter((event) => {\n return !eventIdSet.has(event.id);\n });\n }\n\n private emitEvent(eventData: EventData): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.EVENT, eventData);\n }\n }\n\n private emitEventsQueue(queue: BaseEventsQueueDto): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.QUEUE, queue);\n }\n }\n}\n","import { USER_ID_KEY } from '../constants';\nimport { generateUUID } from '../utils';\nimport { StorageManager } from './storage.manager';\n\n/**\n * Simple utility for managing user identification.\n * Generates and persists unique user IDs per project.\n */\nexport class UserManager {\n /**\n * Gets or creates a unique user ID for the given project.\n * The user ID is persisted in localStorage and reused across sessions.\n *\n * @param storageManager - Storage manager instance\n * @param projectId - Project identifier for namespacing\n * @returns Persistent unique user ID\n */\n static getId(storageManager: StorageManager): string {\n const storageKey = USER_ID_KEY;\n const storedUserId = storageManager.getItem(storageKey);\n\n if (storedUserId) {\n return storedUserId;\n }\n\n const newUserId = generateUUID();\n storageManager.setItem(storageKey, newUserId);\n\n return newUserId;\n }\n}\n","import { BROADCAST_CHANNEL_NAME, DEFAULT_SESSION_TIMEOUT, SESSION_STORAGE_KEY } from '../constants';\nimport { EventType } from '../types';\nimport { SessionEndReason } from '../types/session.types';\nimport { log } from '../utils';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { EventManager } from './event.manager';\n\ninterface StoredSessionData {\n id: string;\n lastActivity: number;\n}\n\nexport class SessionManager extends StateManager {\n private readonly storageManager: StorageManager;\n private readonly eventManager: EventManager;\n private readonly projectId: string;\n private sessionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private broadcastChannel: BroadcastChannel | null = null;\n private activityHandler: (() => void) | null = null;\n private visibilityChangeHandler: (() => void) | null = null;\n private beforeUnloadHandler: ((event: BeforeUnloadEvent) => void) | null = null;\n private isTracking = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager, projectId: string) {\n super();\n this.storageManager = storageManager;\n this.eventManager = eventManager;\n this.projectId = projectId;\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') {\n log('warn', 'BroadcastChannel not supported');\n return;\n }\n\n const projectId = this.getProjectId();\n this.broadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME(projectId));\n\n this.broadcastChannel.onmessage = (event): void => {\n const { action, sessionId, timestamp, projectId: messageProjectId } = event.data ?? {};\n\n if (messageProjectId !== projectId) {\n return;\n }\n\n if (action === 'session_end') {\n this.resetSessionState();\n return;\n }\n\n if (sessionId && typeof timestamp === 'number' && timestamp > Date.now() - 5000) {\n this.set('sessionId', sessionId);\n this.set('hasStartSession', true);\n this.persistSession(sessionId, timestamp);\n if (this.isTracking) {\n this.setupSessionTimeout();\n }\n }\n };\n }\n\n private shareSession(sessionId: string): void {\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_start',\n projectId: this.getProjectId(),\n sessionId,\n timestamp: Date.now(),\n });\n }\n }\n\n private broadcastSessionEnd(sessionId: string | null, reason: SessionEndReason): void {\n if (!sessionId) {\n return;\n }\n\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n try {\n this.broadcastChannel.postMessage({\n action: 'session_end',\n projectId: this.getProjectId(),\n sessionId,\n reason,\n timestamp: Date.now(),\n });\n } catch (error) {\n log('warn', 'Failed to broadcast session end', { error, data: { sessionId, reason } });\n }\n }\n }\n\n private cleanupCrossTabSync(): void {\n if (this.broadcastChannel) {\n if (typeof this.broadcastChannel.close === 'function') {\n this.broadcastChannel.close();\n }\n this.broadcastChannel = null;\n }\n }\n\n private recoverSession(): string | null {\n const storedSession = this.loadStoredSession();\n\n if (!storedSession) {\n return null;\n }\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n if (Date.now() - storedSession.lastActivity > sessionTimeout) {\n this.clearStoredSession();\n return null;\n }\n\n return storedSession.id;\n }\n\n private persistSession(sessionId: string, lastActivity: number = Date.now()): void {\n this.saveStoredSession({\n id: sessionId,\n lastActivity,\n });\n }\n\n private clearStoredSession(): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.removeItem(storageKey);\n }\n\n private loadStoredSession(): StoredSessionData | null {\n const storageKey = this.getSessionStorageKey();\n const storedData = this.storageManager.getItem(storageKey);\n\n if (!storedData) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(storedData) as StoredSessionData;\n if (!parsed.id || typeof parsed.lastActivity !== 'number') {\n return null;\n }\n return parsed;\n } catch {\n this.storageManager.removeItem(storageKey);\n return null;\n }\n }\n\n private saveStoredSession(session: StoredSessionData): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.setItem(storageKey, JSON.stringify(session));\n }\n\n private getSessionStorageKey(): string {\n return SESSION_STORAGE_KEY(this.getProjectId());\n }\n\n private getProjectId(): string {\n return this.projectId;\n }\n\n startTracking(): void {\n if (this.isTracking) {\n log('warn', 'Session tracking already active');\n return;\n }\n\n const recoveredSessionId = this.recoverSession();\n const sessionId = recoveredSessionId ?? this.generateSessionId();\n const isRecovered = Boolean(recoveredSessionId);\n\n this.isTracking = true;\n\n try {\n this.set('sessionId', sessionId);\n this.persistSession(sessionId);\n\n if (!isRecovered) {\n this.eventManager.track({\n type: EventType.SESSION_START,\n });\n }\n\n this.initCrossTabSync();\n this.shareSession(sessionId);\n this.setupSessionTimeout();\n this.setupActivityListeners();\n this.setupLifecycleListeners();\n } catch (error) {\n this.isTracking = false;\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n this.set('sessionId', null);\n\n throw error;\n }\n }\n\n private generateSessionId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private setupSessionTimeout(): void {\n this.clearSessionTimeout();\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n this.sessionTimeoutId = setTimeout(() => {\n this.endSession('inactivity');\n }, sessionTimeout);\n }\n\n private resetSessionTimeout(): void {\n this.setupSessionTimeout();\n const sessionId = this.get('sessionId') as string;\n if (sessionId) {\n this.persistSession(sessionId);\n }\n }\n\n private clearSessionTimeout(): void {\n if (this.sessionTimeoutId) {\n clearTimeout(this.sessionTimeoutId);\n this.sessionTimeoutId = null;\n }\n }\n\n private setupActivityListeners(): void {\n this.activityHandler = (): void => {\n this.resetSessionTimeout();\n };\n\n document.addEventListener('click', this.activityHandler, { passive: true });\n document.addEventListener('keydown', this.activityHandler, { passive: true });\n document.addEventListener('scroll', this.activityHandler, { passive: true });\n }\n\n private cleanupActivityListeners(): void {\n if (this.activityHandler) {\n document.removeEventListener('click', this.activityHandler);\n document.removeEventListener('keydown', this.activityHandler);\n document.removeEventListener('scroll', this.activityHandler);\n this.activityHandler = null;\n }\n }\n\n private setupLifecycleListeners(): void {\n if (this.visibilityChangeHandler || this.beforeUnloadHandler) {\n return;\n }\n\n this.visibilityChangeHandler = (): void => {\n if (document.hidden) {\n this.clearSessionTimeout();\n } else {\n const sessionId = this.get('sessionId');\n if (sessionId) {\n this.setupSessionTimeout();\n }\n }\n };\n\n this.beforeUnloadHandler = (): void => {\n this.endSession('page_unload');\n };\n\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n }\n\n private cleanupLifecycleListeners(): void {\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n }\n\n private endSession(reason: SessionEndReason): void {\n const sessionId = this.get('sessionId');\n\n if (!sessionId) {\n log('warn', 'endSession called without active session', { data: { reason } });\n this.resetSessionState(reason);\n return;\n }\n\n this.eventManager.track({\n type: EventType.SESSION_END,\n session_end_reason: reason,\n });\n\n const flushResult = this.eventManager.flushImmediatelySync();\n\n if (!flushResult) {\n log('warn', 'Sync flush failed during session end, events persisted for recovery', {\n data: { reason, sessionId },\n });\n }\n\n this.broadcastSessionEnd(sessionId, reason);\n this.resetSessionState(reason);\n }\n\n private resetSessionState(reason?: SessionEndReason): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n\n if (reason !== 'page_unload') {\n this.clearStoredSession();\n }\n\n this.set('sessionId', null);\n this.set('hasStartSession', false);\n this.isTracking = false;\n }\n\n stopTracking(): void {\n this.endSession('manual_stop');\n }\n\n destroy(): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupCrossTabSync();\n this.cleanupLifecycleListeners();\n this.isTracking = false;\n this.set('hasStartSession', false);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { SessionManager } from '../managers/session.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { StorageManager } from '../managers/storage.manager';\nimport { log } from '../utils';\n\nexport class SessionHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly storageManager: StorageManager;\n private sessionManager: SessionManager | null = null;\n private destroyed = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n this.storageManager = storageManager;\n }\n\n startTracking(): void {\n if (this.isActive()) {\n return;\n }\n\n if (this.destroyed) {\n log('warn', 'Cannot start tracking on destroyed handler');\n return;\n }\n\n const config = this.get('config');\n const projectId =\n config?.integrations?.tracelog?.projectId ?? config?.integrations?.custom?.collectApiUrl ?? 'default';\n\n if (!projectId) {\n throw new Error('Cannot start session tracking: config not available');\n }\n\n try {\n this.sessionManager = new SessionManager(this.storageManager, this.eventManager, projectId);\n this.sessionManager.startTracking();\n\n // Flush any events that were buffered during initialization\n this.eventManager.flushPendingEvents();\n } catch (error) {\n if (this.sessionManager) {\n try {\n this.sessionManager.destroy();\n } catch {\n // Ignore cleanup errors\n }\n this.sessionManager = null;\n }\n\n log('error', 'Failed to start session tracking', { error });\n throw error;\n }\n }\n\n private isActive(): boolean {\n return this.sessionManager !== null && !this.destroyed;\n }\n\n private cleanupSessionManager(): void {\n if (this.sessionManager) {\n this.sessionManager.stopTracking();\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n }\n\n stopTracking(): void {\n this.cleanupSessionManager();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.sessionManager) {\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n\n this.destroyed = true;\n this.set('hasStartSession', false);\n }\n}\n","import { EventType, PageViewData } from '../types';\nimport { normalizeUrl } from '../utils';\nimport { StateManager } from '../managers/state.manager';\nimport { EventManager } from '../managers/event.manager';\nimport { DEFAULT_PAGE_VIEW_THROTTLE_MS } from '../constants/config.constants';\n\nexport class PageViewHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly onTrack: () => void;\n\n private originalPushState?: typeof window.history.pushState;\n private originalReplaceState?: typeof window.history.replaceState;\n private lastPageViewTime = 0;\n\n constructor(eventManager: EventManager, onTrack: () => void) {\n super();\n\n this.eventManager = eventManager;\n this.onTrack = onTrack;\n }\n\n startTracking(): void {\n this.trackInitialPageView();\n\n window.addEventListener('popstate', this.trackCurrentPage, true);\n window.addEventListener('hashchange', this.trackCurrentPage, true);\n\n this.patchHistory('pushState');\n this.patchHistory('replaceState');\n }\n\n stopTracking(): void {\n window.removeEventListener('popstate', this.trackCurrentPage, true);\n window.removeEventListener('hashchange', this.trackCurrentPage, true);\n\n if (this.originalPushState) {\n window.history.pushState = this.originalPushState;\n }\n\n if (this.originalReplaceState) {\n window.history.replaceState = this.originalReplaceState;\n }\n\n this.lastPageViewTime = 0;\n }\n\n private patchHistory(method: 'pushState' | 'replaceState'): void {\n const original = window.history[method];\n\n if (method === 'pushState' && !this.originalPushState) {\n this.originalPushState = original;\n } else if (method === 'replaceState' && !this.originalReplaceState) {\n this.originalReplaceState = original;\n }\n\n window.history[method] = (...args: [unknown, string, string | URL | null | undefined]): void => {\n original.apply(window.history, args);\n this.trackCurrentPage();\n };\n }\n\n private readonly trackCurrentPage = (): void => {\n const rawUrl = window.location.href;\n const normalizedUrl = normalizeUrl(rawUrl, this.get('config').sensitiveQueryParams);\n\n if (this.get('pageUrl') === normalizedUrl) {\n return;\n }\n\n // Throttle: Prevent rapid navigation spam\n const now = Date.now();\n const throttleMs = this.get('config').pageViewThrottleMs ?? DEFAULT_PAGE_VIEW_THROTTLE_MS;\n\n if (now - this.lastPageViewTime < throttleMs) {\n return;\n }\n\n this.lastPageViewTime = now;\n\n this.onTrack();\n\n const fromUrl = this.get('pageUrl');\n\n this.set('pageUrl', normalizedUrl);\n\n const pageViewData = this.extractPageViewData();\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: this.get('pageUrl'),\n from_page_url: fromUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n };\n\n private trackInitialPageView(): void {\n const normalizedUrl = normalizeUrl(window.location.href, this.get('config').sensitiveQueryParams);\n const pageViewData = this.extractPageViewData();\n\n this.lastPageViewTime = Date.now();\n\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: normalizedUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n\n this.onTrack();\n }\n\n private extractPageViewData(): PageViewData | undefined {\n const { pathname, search, hash } = window.location;\n const { referrer } = document;\n const { title } = document;\n\n // Early return if no meaningful data\n if (!referrer && !title && !pathname && !search && !hash) {\n return undefined;\n }\n\n const data: PageViewData = {\n ...(referrer && { referrer }),\n ...(title && { title }),\n ...(pathname && { pathname }),\n ...(search && { search }),\n ...(hash && { hash }),\n };\n\n return data;\n }\n}\n","import {\n HTML_DATA_ATTR_PREFIX,\n MAX_TEXT_LENGTH,\n INTERACTIVE_SELECTORS,\n PII_PATTERNS,\n DEFAULT_CLICK_THROTTLE_MS,\n} from '../constants';\nimport { ClickCoordinates, ClickData, ClickTrackingElementData, EventType } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\nexport class ClickHandler extends StateManager {\n private readonly eventManager: EventManager;\n\n private clickHandler?: (event: Event) => void;\n private readonly lastClickTimes: Map<string, number> = new Map();\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n if (this.clickHandler) {\n return;\n }\n\n this.clickHandler = (event: Event): void => {\n const mouseEvent = event as MouseEvent;\n const target = mouseEvent.target;\n const clickedElement =\n typeof HTMLElement !== 'undefined' && target instanceof HTMLElement\n ? target\n : typeof HTMLElement !== 'undefined' && target instanceof Node && target.parentElement instanceof HTMLElement\n ? target.parentElement\n : null;\n\n if (!clickedElement) {\n log('warn', 'Click target not found or not an element');\n return;\n }\n\n if (this.shouldIgnoreElement(clickedElement)) {\n return;\n }\n\n // Throttle clicks per element to prevent double-clicks and spam\n const clickThrottleMs = this.get('config')?.clickThrottleMs ?? DEFAULT_CLICK_THROTTLE_MS;\n if (clickThrottleMs > 0 && !this.checkClickThrottle(clickedElement, clickThrottleMs)) {\n return;\n }\n\n const trackingElement = this.findTrackingElement(clickedElement);\n const relevantClickElement = this.getRelevantClickElement(clickedElement);\n const coordinates = this.calculateClickCoordinates(mouseEvent, clickedElement);\n\n if (trackingElement) {\n const trackingData = this.extractTrackingData(trackingElement);\n\n if (trackingData) {\n const attributeData = this.createCustomEventData(trackingData);\n\n this.eventManager.track({\n type: EventType.CUSTOM,\n custom_event: {\n name: attributeData.name,\n ...(attributeData.value && { metadata: { value: attributeData.value } }),\n },\n });\n }\n }\n\n const clickData = this.generateClickData(clickedElement, relevantClickElement, coordinates);\n\n this.eventManager.track({\n type: EventType.CLICK,\n click_data: clickData,\n });\n };\n\n window.addEventListener('click', this.clickHandler, true);\n }\n\n stopTracking(): void {\n if (this.clickHandler) {\n window.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = undefined;\n }\n this.lastClickTimes.clear();\n }\n\n private shouldIgnoreElement(element: HTMLElement): boolean {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-ignore`)) {\n return true;\n }\n\n const parent = element.closest(`[${HTML_DATA_ATTR_PREFIX}-ignore]`);\n\n return parent !== null;\n }\n\n /**\n * Checks per-element click throttling to prevent double-clicks and rapid spam\n * Returns true if the click should be tracked, false if throttled\n */\n private checkClickThrottle(element: HTMLElement, throttleMs: number): boolean {\n const signature = this.getElementSignature(element);\n const now = Date.now();\n const lastClickTime = this.lastClickTimes.get(signature);\n\n if (lastClickTime !== undefined && now - lastClickTime < throttleMs) {\n log('debug', 'ClickHandler: Click suppressed by throttle', {\n data: {\n signature,\n throttleRemaining: throttleMs - (now - lastClickTime),\n },\n });\n return false;\n }\n\n this.lastClickTimes.set(signature, now);\n return true;\n }\n\n /**\n * Creates a stable signature for an element to track throttling\n * Priority: id > data-testid > data-tlog-name > DOM path\n */\n private getElementSignature(element: HTMLElement): string {\n // Priority 1: Element ID (most stable)\n if (element.id) {\n return `#${element.id}`;\n }\n\n // Priority 2: data-testid (common in tests)\n const testId = element.getAttribute('data-testid');\n if (testId) {\n return `[data-testid=\"${testId}\"]`;\n }\n\n // Priority 3: data-tlog-name (our own tracking attribute)\n const tlogName = element.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n if (tlogName) {\n return `[${HTML_DATA_ATTR_PREFIX}-name=\"${tlogName}\"]`;\n }\n\n // Priority 4: Generate DOM path as fallback\n return this.getElementPath(element);\n }\n\n /**\n * Generates a DOM path for an element (e.g., \"body>div>button\")\n */\n private getElementPath(element: HTMLElement): string {\n const path: string[] = [];\n let current: HTMLElement | null = element;\n\n while (current && current !== document.body) {\n let selector = current.tagName.toLowerCase();\n\n // Add class if available (first class only for brevity)\n if (current.className) {\n const firstClass = current.className.split(' ')[0];\n if (firstClass) {\n selector += `.${firstClass}`;\n }\n }\n\n path.unshift(selector);\n current = current.parentElement;\n }\n\n return path.join('>') || 'unknown';\n }\n\n private findTrackingElement(element: HTMLElement): HTMLElement | undefined {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-name`)) {\n return element;\n }\n\n const closest = element.closest(`[${HTML_DATA_ATTR_PREFIX}-name]`) as HTMLElement;\n\n return closest;\n }\n\n private getRelevantClickElement(element: HTMLElement): HTMLElement {\n for (const selector of INTERACTIVE_SELECTORS) {\n try {\n if (element.matches(selector)) {\n return element;\n }\n\n const parent = element.closest(selector) as HTMLElement;\n\n if (parent) {\n return parent;\n }\n } catch (error) {\n log('warn', 'Invalid selector in element search', { error, data: { selector } });\n continue;\n }\n }\n\n return element;\n }\n\n private clamp(value: number): number {\n return Math.max(0, Math.min(1, Number(value.toFixed(3))));\n }\n\n private calculateClickCoordinates(event: MouseEvent, element: HTMLElement): ClickCoordinates {\n const rect = element.getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n const relativeX = rect.width > 0 ? this.clamp((x - rect.left) / rect.width) : 0;\n const relativeY = rect.height > 0 ? this.clamp((y - rect.top) / rect.height) : 0;\n\n return { x, y, relativeX, relativeY };\n }\n\n private extractTrackingData(trackingElement: HTMLElement): ClickTrackingElementData | undefined {\n const name = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n const value = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-value`);\n\n if (!name) {\n return undefined;\n }\n\n return {\n element: trackingElement,\n name,\n ...(value && { value }),\n };\n }\n\n private generateClickData(\n clickedElement: HTMLElement,\n relevantElement: HTMLElement,\n coordinates: ClickCoordinates,\n ): ClickData {\n const { x, y, relativeX, relativeY } = coordinates;\n const text = this.getRelevantText(clickedElement, relevantElement);\n const attributes = this.extractElementAttributes(relevantElement);\n\n return {\n x,\n y,\n relativeX,\n relativeY,\n tag: relevantElement.tagName.toLowerCase(),\n ...(relevantElement.id && { id: relevantElement.id }),\n ...(relevantElement.className && { class: relevantElement.className }),\n ...(text && { text }),\n ...(attributes.href && { href: attributes.href }),\n ...(attributes.title && { title: attributes.title }),\n ...(attributes.alt && { alt: attributes.alt }),\n ...(attributes.role && { role: attributes.role }),\n ...(attributes['aria-label'] && { ariaLabel: attributes['aria-label'] }),\n ...(Object.keys(attributes).length > 0 && { dataAttributes: attributes }),\n };\n }\n\n private sanitizeText(text: string): string {\n let sanitized = text;\n\n for (const pattern of PII_PATTERNS) {\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private getRelevantText(clickedElement: HTMLElement, relevantElement: HTMLElement): string {\n const clickedText = clickedElement.textContent?.trim() ?? '';\n const relevantText = relevantElement.textContent?.trim() ?? '';\n\n if (!clickedText && !relevantText) {\n return '';\n }\n\n let finalText = '';\n\n if (clickedText && clickedText.length <= MAX_TEXT_LENGTH) {\n finalText = clickedText;\n } else if (relevantText.length <= MAX_TEXT_LENGTH) {\n finalText = relevantText;\n } else {\n finalText = relevantText.slice(0, MAX_TEXT_LENGTH - 3) + '...';\n }\n\n return this.sanitizeText(finalText);\n }\n\n private extractElementAttributes(element: HTMLElement): Record<string, string> {\n const commonAttributes = [\n 'id',\n 'class',\n 'data-testid',\n 'aria-label',\n 'title',\n 'href',\n 'type',\n 'name',\n 'alt',\n 'role',\n ];\n const result: Record<string, string> = {};\n\n for (const attributeName of commonAttributes) {\n const value = element.getAttribute(attributeName);\n\n if (value) {\n result[attributeName] = value;\n }\n }\n\n return result;\n }\n\n private createCustomEventData(trackingData: ClickTrackingElementData): { name: string; value?: string } {\n return {\n name: trackingData.name,\n ...(trackingData.value && { value: trackingData.value }),\n };\n }\n}\n","import {\n MAX_SCROLL_EVENTS_PER_SESSION,\n MIN_SCROLL_DEPTH_CHANGE,\n SCROLL_DEBOUNCE_TIME_MS,\n SCROLL_MIN_EVENT_INTERVAL_MS,\n SIGNIFICANT_SCROLL_DELTA,\n} from '../constants';\nimport { EventType, ScrollData, ScrollDirection } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\ninterface ScrollContainer {\n element: Window | HTMLElement;\n selector: string;\n isPrimary: boolean;\n lastScrollPos: number;\n lastDepth: number;\n lastDirection: ScrollDirection;\n lastEventTime: number;\n maxDepthReached: number;\n debounceTimer: number | null;\n listener: EventListener;\n}\n\nexport class ScrollHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly containers: ScrollContainer[] = [];\n private limitWarningLogged = false;\n private minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n private minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n private maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n private windowScrollableCache: boolean | null = null;\n private retryTimeoutId: number | null = null;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n this.limitWarningLogged = false;\n this.applyConfigOverrides();\n this.set('scrollEventCount', 0);\n this.tryDetectScrollContainers(0);\n }\n\n stopTracking(): void {\n if (this.retryTimeoutId !== null) {\n clearTimeout(this.retryTimeoutId);\n this.retryTimeoutId = null;\n }\n\n for (const container of this.containers) {\n this.clearContainerTimer(container);\n\n if (container.element instanceof Window) {\n window.removeEventListener('scroll', container.listener);\n } else {\n container.element.removeEventListener('scroll', container.listener);\n }\n }\n\n this.containers.length = 0;\n this.set('scrollEventCount', 0);\n this.limitWarningLogged = false;\n this.windowScrollableCache = null;\n }\n\n private tryDetectScrollContainers(attempt: number): void {\n const elements = this.findScrollableElements();\n\n if (elements.length > 0) {\n for (const element of elements) {\n const selector = this.getElementSelector(element);\n this.setupScrollContainer(element, selector);\n }\n\n this.applyPrimaryScrollSelectorIfConfigured();\n\n return;\n }\n\n if (attempt < 5) {\n this.retryTimeoutId = window.setTimeout(() => {\n this.retryTimeoutId = null;\n this.tryDetectScrollContainers(attempt + 1);\n }, 200);\n\n return;\n }\n\n if (this.containers.length === 0) {\n this.setupScrollContainer(window, 'window');\n }\n\n this.applyPrimaryScrollSelectorIfConfigured();\n }\n\n private applyPrimaryScrollSelectorIfConfigured(): void {\n const config = this.get('config');\n\n if (config?.primaryScrollSelector) {\n this.applyPrimaryScrollSelector(config.primaryScrollSelector);\n }\n }\n\n private findScrollableElements(): HTMLElement[] {\n if (!document.body) {\n return [];\n }\n\n const elements: HTMLElement[] = [];\n\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node) => {\n const element = node as HTMLElement;\n\n if (!element.isConnected || !element.offsetParent) {\n return NodeFilter.FILTER_SKIP;\n }\n\n const style = getComputedStyle(element);\n const hasScrollableStyle =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n return hasScrollableStyle ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n },\n });\n\n let node: Node | null;\n\n while ((node = walker.nextNode()) && elements.length < 10) {\n const element = node as HTMLElement;\n\n if (this.isElementScrollable(element)) {\n elements.push(element);\n }\n }\n\n return elements;\n }\n\n private getElementSelector(element: Window | HTMLElement): string {\n if (element === window) {\n return 'window';\n }\n\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.id) {\n return `#${htmlElement.id}`;\n }\n\n if (htmlElement.className && typeof htmlElement.className === 'string') {\n const firstClass = htmlElement.className.split(' ').filter((c) => c.trim())[0];\n\n if (firstClass) {\n return `.${firstClass}`;\n }\n }\n\n return htmlElement.tagName.toLowerCase();\n }\n\n private determineIfPrimary(element: Window | HTMLElement): boolean {\n // Window scrollable → window is primary\n if (this.isWindowScrollable()) {\n return element === window;\n }\n\n // Window not scrollable → first detected container is primary\n return this.containers.length === 0;\n }\n\n private setupScrollContainer(element: Window | HTMLElement, selector: string): void {\n const alreadyTracking = this.containers.some((c) => c.element === element);\n\n if (alreadyTracking) {\n return;\n }\n\n if (element !== window && !this.isElementScrollable(element as HTMLElement)) {\n return;\n }\n\n const handleScroll = (): void => {\n if (this.get('suppressNextScroll')) {\n return;\n }\n\n this.clearContainerTimer(container);\n\n container.debounceTimer = window.setTimeout(() => {\n const scrollData = this.calculateScrollData(container);\n\n if (scrollData) {\n const now = Date.now();\n\n this.processScrollEvent(container, scrollData, now);\n }\n\n container.debounceTimer = null;\n }, SCROLL_DEBOUNCE_TIME_MS);\n };\n\n const initialScrollTop = this.getScrollTop(element);\n const initialDepth = this.calculateScrollDepth(\n initialScrollTop,\n this.getScrollHeight(element),\n this.getViewportHeight(element),\n );\n const isPrimary = this.determineIfPrimary(element);\n const container: ScrollContainer = {\n element,\n selector,\n isPrimary,\n lastScrollPos: initialScrollTop,\n lastDepth: initialDepth,\n lastDirection: ScrollDirection.DOWN,\n lastEventTime: 0,\n maxDepthReached: initialDepth,\n debounceTimer: null,\n listener: handleScroll,\n };\n\n this.containers.push(container);\n\n if (element instanceof Window) {\n window.addEventListener('scroll', handleScroll, { passive: true });\n } else {\n element.addEventListener('scroll', handleScroll, { passive: true });\n }\n }\n\n private processScrollEvent(\n container: ScrollContainer,\n scrollData: Omit<ScrollData, 'container_selector' | 'is_primary'>,\n timestamp: number,\n ): void {\n if (!this.shouldEmitScrollEvent(container, scrollData, timestamp)) {\n return;\n }\n\n container.lastEventTime = timestamp;\n container.lastDepth = scrollData.depth;\n container.lastDirection = scrollData.direction;\n\n const currentCount = this.get('scrollEventCount') ?? 0;\n this.set('scrollEventCount', currentCount + 1);\n\n this.eventManager.track({\n type: EventType.SCROLL,\n scroll_data: {\n ...scrollData,\n container_selector: container.selector,\n is_primary: container.isPrimary,\n },\n });\n }\n\n private shouldEmitScrollEvent(\n container: ScrollContainer,\n scrollData: Omit<ScrollData, 'container_selector' | 'is_primary'>,\n timestamp: number,\n ): boolean {\n if (this.hasReachedSessionLimit()) {\n this.logLimitOnce();\n return false;\n }\n\n if (!this.hasElapsedMinimumInterval(container, timestamp)) {\n return false;\n }\n\n if (!this.hasSignificantDepthChange(container, scrollData.depth)) {\n return false;\n }\n\n return true;\n }\n\n private hasReachedSessionLimit(): boolean {\n const currentCount = this.get('scrollEventCount') ?? 0;\n return currentCount >= this.maxEventsPerSession;\n }\n\n private hasElapsedMinimumInterval(container: ScrollContainer, timestamp: number): boolean {\n if (container.lastEventTime === 0) {\n return true;\n }\n return timestamp - container.lastEventTime >= this.minIntervalMs;\n }\n\n private hasSignificantDepthChange(container: ScrollContainer, newDepth: number): boolean {\n return Math.abs(newDepth - container.lastDepth) >= this.minDepthChange;\n }\n\n private logLimitOnce(): void {\n if (this.limitWarningLogged) {\n return;\n }\n\n this.limitWarningLogged = true;\n\n log('warn', 'Max scroll events per session reached', {\n data: { limit: this.maxEventsPerSession },\n });\n }\n\n private applyConfigOverrides(): void {\n this.minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n this.minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n this.maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n }\n\n private isWindowScrollable(): boolean {\n if (this.windowScrollableCache !== null) {\n return this.windowScrollableCache;\n }\n\n this.windowScrollableCache = document.documentElement.scrollHeight > window.innerHeight;\n return this.windowScrollableCache;\n }\n\n private clearContainerTimer(container: ScrollContainer): void {\n if (container.debounceTimer !== null) {\n clearTimeout(container.debounceTimer);\n container.debounceTimer = null;\n }\n }\n\n private getScrollDirection(current: number, previous: number): ScrollDirection {\n return current > previous ? ScrollDirection.DOWN : ScrollDirection.UP;\n }\n\n private calculateScrollDepth(scrollTop: number, scrollHeight: number, viewportHeight: number): number {\n if (scrollHeight <= viewportHeight) {\n return 0;\n }\n\n const maxScrollTop = scrollHeight - viewportHeight;\n return Math.min(100, Math.max(0, Math.floor((scrollTop / maxScrollTop) * 100)));\n }\n\n private calculateScrollData(\n container: ScrollContainer,\n ): Omit<ScrollData, 'container_selector' | 'is_primary'> | null {\n const { element, lastScrollPos, lastEventTime } = container;\n const scrollTop = this.getScrollTop(element);\n const now = Date.now();\n\n const positionDelta = Math.abs(scrollTop - lastScrollPos);\n if (positionDelta < SIGNIFICANT_SCROLL_DELTA) {\n return null;\n }\n\n if (element === window && !this.isWindowScrollable()) {\n return null;\n }\n\n const viewportHeight = this.getViewportHeight(element);\n const scrollHeight = this.getScrollHeight(element);\n const direction = this.getScrollDirection(scrollTop, lastScrollPos);\n const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);\n\n const timeDelta = lastEventTime > 0 ? now - lastEventTime : 0;\n const velocity = timeDelta > 0 ? Math.round((positionDelta / timeDelta) * 1000) : 0;\n\n if (depth > container.maxDepthReached) {\n container.maxDepthReached = depth;\n }\n\n container.lastScrollPos = scrollTop;\n\n return {\n depth,\n direction,\n velocity,\n max_depth_reached: container.maxDepthReached,\n };\n }\n\n private getScrollTop(element: Window | HTMLElement): number {\n return element instanceof Window ? window.scrollY : element.scrollTop;\n }\n\n private getViewportHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? window.innerHeight : element.clientHeight;\n }\n\n private getScrollHeight(element: Window | HTMLElement): number {\n return element instanceof Window ? document.documentElement.scrollHeight : element.scrollHeight;\n }\n\n private isElementScrollable(element: HTMLElement): boolean {\n const style = getComputedStyle(element);\n const hasScrollableOverflow =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflowX === 'auto' ||\n style.overflowX === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n const hasOverflowContent = element.scrollHeight > element.clientHeight || element.scrollWidth > element.clientWidth;\n\n return hasScrollableOverflow && hasOverflowContent;\n }\n\n private applyPrimaryScrollSelector(selector: string): void {\n let targetElement: Window | HTMLElement;\n\n if (selector === 'window') {\n targetElement = window;\n } else {\n const element = document.querySelector(selector);\n if (!(element instanceof HTMLElement)) {\n log('warn', `Selector \"${selector}\" did not match an HTMLElement`);\n return;\n }\n targetElement = element;\n }\n\n this.containers.forEach((container) => {\n this.updateContainerPrimary(container, container.element === targetElement);\n });\n\n const targetAlreadyTracked = this.containers.some((c) => c.element === targetElement);\n if (!targetAlreadyTracked && targetElement instanceof HTMLElement) {\n if (this.isElementScrollable(targetElement)) {\n this.setupScrollContainer(targetElement, selector);\n }\n }\n }\n\n private updateContainerPrimary(container: ScrollContainer, isPrimary: boolean): void {\n container.isPrimary = isPrimary;\n }\n}\n","import {\n HTML_DATA_ATTR_PREFIX,\n DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n VIEWPORT_MUTATION_DEBOUNCE_MS,\n} from '../constants';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, ViewportConfig, ViewportEventData } from '../types';\nimport { log } from '../utils';\n\ninterface TrackedElement {\n element: Element;\n selector: string;\n id?: string;\n name?: string;\n startTime: number | null;\n timeoutId: number | null;\n lastFiredTime: number | null;\n}\n\n/**\n * Handles viewport visibility tracking using IntersectionObserver API.\n * Fires events when elements become visible for a minimum dwell time.\n */\nexport class ViewportHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly trackedElements = new Map<Element, TrackedElement>();\n private observer: IntersectionObserver | null = null;\n private mutationObserver: MutationObserver | null = null;\n private mutationDebounceTimer: number | null = null;\n private config: ViewportConfig | null = null;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n /**\n * Starts tracking viewport visibility for configured elements\n */\n startTracking(): void {\n // Get viewport config from state\n const config = this.get('config');\n this.config = config.viewport ?? null;\n\n if (!this.config?.elements || this.config.elements.length === 0) {\n return;\n }\n\n // Set defaults\n const threshold = this.config.threshold ?? 0.5;\n const minDwellTime = this.config.minDwellTime ?? 1000;\n\n if (threshold < 0 || threshold > 1) {\n log('warn', 'ViewportHandler: Invalid threshold, must be between 0 and 1');\n return;\n }\n\n if (minDwellTime < 0) {\n log('warn', 'ViewportHandler: Invalid minDwellTime, must be non-negative');\n return;\n }\n\n // Check IntersectionObserver support\n if (typeof IntersectionObserver === 'undefined') {\n log('warn', 'ViewportHandler: IntersectionObserver not supported in this browser');\n return;\n }\n\n // Create observer\n this.observer = new IntersectionObserver(this.handleIntersection, {\n threshold,\n });\n\n // Find and observe all matching elements\n this.observeElements();\n\n // Set up MutationObserver to detect dynamically added elements\n this.setupMutationObserver();\n }\n\n /**\n * Stops tracking and cleans up resources\n */\n stopTracking(): void {\n // Disconnect observers\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n // Clear debounce timer\n if (this.mutationDebounceTimer !== null) {\n window.clearTimeout(this.mutationDebounceTimer);\n this.mutationDebounceTimer = null;\n }\n\n // Clear all timers and tracked elements\n for (const tracked of this.trackedElements.values()) {\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n }\n }\n\n this.trackedElements.clear();\n }\n\n /**\n * Query and observe all elements matching configured elements\n */\n private observeElements(): void {\n if (!this.config || !this.observer) return;\n\n const maxTrackedElements = this.config.maxTrackedElements ?? DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS;\n let totalTracked = this.trackedElements.size;\n\n for (const elementConfig of this.config.elements) {\n try {\n const elements = document.querySelectorAll(elementConfig.selector);\n\n for (const element of Array.from(elements)) {\n // Check max limit (Phase 3)\n if (totalTracked >= maxTrackedElements) {\n log('warn', 'ViewportHandler: Maximum tracked elements reached', {\n data: {\n limit: maxTrackedElements,\n selector: elementConfig.selector,\n message: 'Some elements will not be tracked. Consider more specific selectors.',\n },\n });\n return; // Stop tracking more elements\n }\n\n // Skip if element has data-tlog-ignore attribute\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-ignore`)) {\n continue;\n }\n\n // Skip if already tracked\n if (this.trackedElements.has(element)) {\n continue;\n }\n\n // Track and observe element with identifiers\n this.trackedElements.set(element, {\n element,\n selector: elementConfig.selector,\n id: elementConfig.id,\n name: elementConfig.name,\n startTime: null,\n timeoutId: null,\n lastFiredTime: null,\n });\n\n this.observer?.observe(element);\n totalTracked++;\n }\n } catch (error) {\n log('warn', `ViewportHandler: Invalid selector \"${elementConfig.selector}\"`, { error });\n }\n }\n\n log('debug', 'ViewportHandler: Elements tracked', {\n data: { count: totalTracked, limit: maxTrackedElements },\n });\n }\n\n /**\n * Handles intersection events from IntersectionObserver\n */\n private readonly handleIntersection = (entries: IntersectionObserverEntry[]): void => {\n if (!this.config) return;\n\n const minDwellTime = this.config.minDwellTime ?? 1000;\n\n for (const entry of entries) {\n const tracked = this.trackedElements.get(entry.target);\n if (!tracked) continue;\n\n if (entry.isIntersecting) {\n // Element became visible\n if (tracked.startTime === null) {\n tracked.startTime = performance.now();\n\n // Set timer to fire event after minDwellTime\n tracked.timeoutId = window.setTimeout(() => {\n this.fireViewportEvent(tracked, entry.intersectionRatio);\n }, minDwellTime);\n }\n } else {\n // Element became hidden\n if (tracked.startTime !== null) {\n // Clear timer if element hidden before minDwellTime elapsed\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n tracked.timeoutId = null;\n }\n tracked.startTime = null;\n }\n }\n }\n };\n\n /**\n * Fires a viewport visible event\n */\n private fireViewportEvent(tracked: TrackedElement, visibilityRatio: number): void {\n if (tracked.startTime === null) return;\n\n const dwellTime = Math.round(performance.now() - tracked.startTime);\n\n // Check data-tlog-ignore again (element might have changed)\n if (tracked.element.hasAttribute('data-tlog-ignore')) {\n return;\n }\n\n // Check cooldown period to prevent repeated events from carousels/sticky elements\n const cooldownPeriod = this.config?.cooldownPeriod ?? DEFAULT_VIEWPORT_COOLDOWN_PERIOD;\n const now = Date.now();\n if (tracked.lastFiredTime !== null && now - tracked.lastFiredTime < cooldownPeriod) {\n log('debug', 'ViewportHandler: Event suppressed by cooldown period', {\n data: {\n selector: tracked.selector,\n cooldownRemaining: cooldownPeriod - (now - tracked.lastFiredTime),\n },\n });\n tracked.startTime = null;\n tracked.timeoutId = null;\n return;\n }\n\n const eventData: ViewportEventData = {\n selector: tracked.selector,\n dwellTime,\n visibilityRatio,\n ...(tracked.id !== undefined && { id: tracked.id }),\n ...(tracked.name !== undefined && { name: tracked.name }),\n };\n\n this.eventManager.track({\n type: EventType.VIEWPORT_VISIBLE,\n viewport_data: eventData,\n });\n\n // Reset tracking state after firing event and record timestamp\n tracked.startTime = null;\n tracked.timeoutId = null;\n tracked.lastFiredTime = now;\n }\n\n /**\n * Sets up MutationObserver to detect dynamically added elements\n */\n private setupMutationObserver(): void {\n if (!this.config || typeof MutationObserver === 'undefined') {\n return;\n }\n\n // Check if document.body exists\n if (!document.body) {\n log('warn', 'ViewportHandler: document.body not available, skipping MutationObserver setup');\n return;\n }\n\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasAddedNodes = false;\n\n // Check what changed\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n if (mutation.addedNodes.length > 0) {\n hasAddedNodes = true;\n }\n if (mutation.removedNodes.length > 0) {\n // Clean up removed nodes immediately\n this.cleanupRemovedNodes(mutation.removedNodes);\n }\n }\n }\n\n // Debounce re-observing for added nodes (batch multiple mutations)\n if (hasAddedNodes) {\n if (this.mutationDebounceTimer !== null) {\n window.clearTimeout(this.mutationDebounceTimer);\n }\n this.mutationDebounceTimer = window.setTimeout(() => {\n this.observeElements();\n this.mutationDebounceTimer = null;\n }, VIEWPORT_MUTATION_DEBOUNCE_MS);\n }\n });\n\n // Observe the entire document for added/removed nodes\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n /**\n * Cleans up tracking for removed DOM nodes\n */\n private cleanupRemovedNodes(removedNodes: NodeList): void {\n removedNodes.forEach((node) => {\n if (node.nodeType !== 1) return; // 1 = ELEMENT_NODE\n\n const element = node as Element;\n const tracked = this.trackedElements.get(element);\n\n if (tracked) {\n // Clear pending timer\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n }\n\n // Unobserve and remove from tracking\n this.observer?.unobserve(element);\n this.trackedElements.delete(element);\n }\n\n // Also check descendants\n const descendants = Array.from(this.trackedElements.keys()).filter((el) => element.contains(el));\n descendants.forEach((el) => {\n const descendantTracked = this.trackedElements.get(el);\n if (descendantTracked && descendantTracked.timeoutId !== null) {\n window.clearTimeout(descendantTracked.timeoutId);\n }\n this.observer?.unobserve(el);\n this.trackedElements.delete(el);\n });\n });\n }\n}\n","import { MetadataType } from '../types';\nimport { log } from '../utils';\nimport { StateManager } from '../managers/state.manager';\n\ndeclare global {\n interface Window {\n gtag?: (...args: unknown[]) => void;\n dataLayer?: unknown[];\n }\n}\n\nexport class GoogleAnalyticsIntegration extends StateManager {\n private isInitialized = false;\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n const measurementId = this.get('config').integrations?.googleAnalytics?.measurementId;\n const userId = this.get('userId');\n\n if (!measurementId?.trim() || !userId?.trim()) {\n return;\n }\n\n try {\n if (this.isScriptAlreadyLoaded()) {\n this.isInitialized = true;\n return;\n }\n\n await this.loadScript(measurementId);\n this.configureGtag(measurementId, userId);\n this.isInitialized = true;\n } catch (error) {\n log('error', 'Google Analytics initialization failed', { error });\n }\n }\n\n trackEvent(eventName: string, metadata: Record<string, MetadataType> | Record<string, MetadataType>[]): void {\n if (!eventName?.trim() || !this.isInitialized || typeof window.gtag !== 'function') {\n return;\n }\n\n try {\n const normalizedMetadata = Array.isArray(metadata) ? { items: metadata } : metadata;\n window.gtag('event', eventName, normalizedMetadata);\n } catch (error) {\n log('error', 'Google Analytics event tracking failed', { error });\n }\n }\n\n cleanup(): void {\n this.isInitialized = false;\n const script = document.getElementById('tracelog-ga-script');\n if (script) {\n script.remove();\n }\n }\n\n private isScriptAlreadyLoaded(): boolean {\n // Check if we already loaded the script\n if (document.getElementById('tracelog-ga-script')) {\n return true;\n }\n\n // Check if GA is already loaded by another source\n const existingGAScript = document.querySelector('script[src*=\"googletagmanager.com/gtag/js\"]');\n return !!existingGAScript;\n }\n\n private async loadScript(measurementId: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.id = 'tracelog-ga-script';\n script.async = true;\n script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;\n\n script.onload = () => {\n resolve();\n };\n script.onerror = () => {\n reject(new Error('Failed to load Google Analytics script'));\n };\n\n document.head.appendChild(script);\n });\n }\n\n private configureGtag(measurementId: string, userId: string): void {\n const gaScriptConfig = document.createElement('script');\n gaScriptConfig.innerHTML = `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${measurementId}', {\n 'user_id': '${userId}'\n });\n `;\n document.head.appendChild(gaScriptConfig);\n }\n}\n","import { log } from '../utils';\n\n/**\n * Manages localStorage and sessionStorage with automatic fallback to in-memory storage.\n * Provides a consistent interface for storing session data, configuration,\n * and analytics metadata across browser environments.\n */\nexport class StorageManager {\n private readonly storage: Storage | null;\n private readonly sessionStorageRef: Storage | null;\n private readonly fallbackStorage = new Map<string, string>();\n private readonly fallbackSessionStorage = new Map<string, string>();\n\n private hasQuotaExceededError = false;\n\n constructor() {\n this.storage = this.initializeStorage('localStorage');\n this.sessionStorageRef = this.initializeStorage('sessionStorage');\n\n if (!this.storage) {\n log('warn', 'localStorage not available, using memory fallback');\n }\n if (!this.sessionStorageRef) {\n log('warn', 'sessionStorage not available, using memory fallback');\n }\n }\n\n /**\n * Retrieves an item from storage\n */\n getItem(key: string): string | null {\n try {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n return this.fallbackStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in storage\n */\n setItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n // This ensures fallback is in sync and can serve as backup if storage fails\n this.fallbackStorage.set(key, value);\n\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n this.hasQuotaExceededError = true;\n\n log('warn', 'localStorage quota exceeded, attempting cleanup', {\n data: { key, valueSize: value.length },\n });\n\n // Attempt to free up space by removing old TraceLog data\n const cleanedUp = this.cleanupOldData();\n\n if (cleanedUp) {\n // Retry after cleanup\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n // Successfully stored after cleanup\n return;\n }\n } catch (retryError) {\n log('error', 'localStorage quota exceeded even after cleanup - data will not persist', {\n error: retryError,\n data: { key, valueSize: value.length },\n });\n }\n } else {\n log('error', 'localStorage quota exceeded and no data to cleanup - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from storage\n */\n removeItem(key: string): void {\n try {\n if (this.storage) {\n this.storage.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackStorage.delete(key);\n }\n\n /**\n * Clears all TracLog-related items from storage\n */\n clear(): void {\n if (!this.storage) {\n this.fallbackStorage.clear();\n return;\n }\n\n try {\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => {\n this.storage!.removeItem(key);\n });\n this.fallbackStorage.clear();\n } catch (error) {\n log('error', 'Failed to clear storage', { error });\n this.fallbackStorage.clear();\n }\n }\n\n /**\n * Checks if storage is available\n */\n isAvailable(): boolean {\n return this.storage !== null;\n }\n\n /**\n * Checks if a QuotaExceededError has occurred\n * This indicates localStorage is full and data may not persist\n */\n hasQuotaError(): boolean {\n return this.hasQuotaExceededError;\n }\n\n /**\n * Attempts to cleanup old TraceLog data from storage to free up space\n * Returns true if any data was removed, false otherwise\n */\n private cleanupOldData(): boolean {\n if (!this.storage) {\n return false;\n }\n\n try {\n const tracelogKeys: string[] = [];\n const persistedEventsKeys: string[] = [];\n\n // Collect all TraceLog keys\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n tracelogKeys.push(key);\n\n // Prioritize removing old persisted events\n if (key.startsWith('tracelog_persisted_events_')) {\n persistedEventsKeys.push(key);\n }\n }\n }\n\n // First, try to remove old persisted events (usually the largest data)\n if (persistedEventsKeys.length > 0) {\n persistedEventsKeys.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n // If no persisted events, remove non-critical keys\n // Define critical key prefixes that should be preserved\n const criticalPrefixes = ['tracelog_session_', 'tracelog_user_id', 'tracelog_device_id', 'tracelog_config'];\n\n const nonCriticalKeys = tracelogKeys.filter((key) => {\n // Keep keys that start with any critical prefix\n return !criticalPrefixes.some((prefix) => key.startsWith(prefix));\n });\n\n if (nonCriticalKeys.length > 0) {\n // Remove up to 5 non-critical keys\n const keysToRemove = nonCriticalKeys.slice(0, 5);\n keysToRemove.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n return false;\n } catch (error) {\n log('error', 'Failed to cleanup old data', { error });\n return false;\n }\n }\n\n /**\n * Initialize storage (localStorage or sessionStorage) with feature detection\n */\n private initializeStorage(type: 'localStorage' | 'sessionStorage'): Storage | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const storage = type === 'localStorage' ? window.localStorage : window.sessionStorage;\n const testKey = '__tracelog_test__';\n\n storage.setItem(testKey, 'test');\n storage.removeItem(testKey);\n\n return storage;\n } catch {\n return null;\n }\n }\n\n /**\n * Retrieves an item from sessionStorage\n */\n getSessionItem(key: string): string | null {\n try {\n if (this.sessionStorageRef) {\n return this.sessionStorageRef.getItem(key);\n }\n return this.fallbackSessionStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackSessionStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in sessionStorage\n */\n setSessionItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n this.fallbackSessionStorage.set(key, value);\n\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n log('error', 'sessionStorage quota exceeded - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackSessionStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from sessionStorage\n */\n removeSessionItem(key: string): void {\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackSessionStorage.delete(key);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, WebVitalType } from '../types';\nimport { LONG_TASK_THROTTLE_MS, PRECISION_TWO_DECIMALS, WEB_VITALS_THRESHOLDS } from '../constants';\nimport { log } from '../utils';\n\ntype LayoutShiftEntry = PerformanceEntry & { value?: number; hadRecentInput?: boolean };\n\nexport class PerformanceHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly reportedByNav: Map<string, Set<string>> = new Map();\n\n private readonly observers: PerformanceObserver[] = [];\n private lastLongTaskSentAt = 0;\n\n private readonly vitalThresholds = WEB_VITALS_THRESHOLDS;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n async startTracking(): Promise<void> {\n await this.initWebVitals();\n this.observeLongTasks();\n }\n\n stopTracking(): void {\n this.observers.forEach((obs, index) => {\n try {\n obs.disconnect();\n } catch (error) {\n log('warn', 'Failed to disconnect performance observer', { error, data: { observerIndex: index } });\n }\n });\n\n this.observers.length = 0;\n this.reportedByNav.clear();\n }\n\n private observeWebVitalsFallback(): void {\n this.reportTTFB();\n\n this.safeObserve(\n 'largest-contentful-paint',\n (list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1] as (PerformanceEntry & { startTime: number }) | undefined;\n\n if (!last) {\n return;\n }\n\n this.sendVital({ type: 'LCP', value: Number(last.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'largest-contentful-paint', buffered: true },\n true,\n );\n\n let clsValue = 0;\n let currentNavId = this.getNavigationId();\n\n this.safeObserve(\n 'layout-shift',\n (list) => {\n const navId = this.getNavigationId();\n\n if (navId !== currentNavId) {\n clsValue = 0;\n currentNavId = navId;\n }\n\n const entries = list.getEntries() as LayoutShiftEntry[];\n\n for (const entry of entries) {\n if (entry.hadRecentInput === true) {\n continue;\n }\n\n const value = typeof entry.value === 'number' ? entry.value : 0;\n clsValue += value;\n }\n\n this.sendVital({ type: 'CLS', value: Number(clsValue.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'layout-shift', buffered: true },\n );\n\n this.safeObserve(\n 'paint',\n (list) => {\n for (const entry of list.getEntries()) {\n if (entry.name === 'first-contentful-paint') {\n this.sendVital({ type: 'FCP', value: Number(entry.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n }\n },\n { type: 'paint', buffered: true },\n true,\n );\n\n this.safeObserve(\n 'event',\n (list) => {\n let worst = 0;\n const entries = list.getEntries() as Array<{ startTime: number; processingEnd?: number }>;\n\n for (const entry of entries) {\n const dur = (entry.processingEnd ?? 0) - (entry.startTime ?? 0);\n worst = Math.max(worst, dur);\n }\n\n if (worst > 0) {\n this.sendVital({ type: 'INP', value: Number(worst.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n },\n { type: 'event', buffered: true },\n );\n }\n\n private async initWebVitals(): Promise<void> {\n try {\n const { onLCP, onCLS, onFCP, onTTFB, onINP } = await import('web-vitals');\n\n const report =\n (type: WebVitalType) =>\n (metric: { value: number }): void => {\n const value = Number(metric.value.toFixed(PRECISION_TWO_DECIMALS));\n this.sendVital({ type, value });\n };\n\n onLCP(report('LCP'), { reportAllChanges: false });\n onCLS(report('CLS'), { reportAllChanges: false });\n onFCP(report('FCP'), { reportAllChanges: false });\n onTTFB(report('TTFB'), { reportAllChanges: false });\n onINP(report('INP'), { reportAllChanges: false });\n } catch (error) {\n log('warn', 'Failed to load web-vitals library, using fallback', { error });\n this.observeWebVitalsFallback();\n }\n }\n\n private reportTTFB(): void {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return;\n }\n\n const ttfb = nav.responseStart;\n\n // TTFB can be 0 in some browsers (especially Mobile Safari) when:\n // - Response is served from cache\n // - Connection is reused\n // - Browser cannot determine exact timing\n // We still report it as it's a valid measurement\n if (typeof ttfb === 'number' && Number.isFinite(ttfb)) {\n this.sendVital({ type: 'TTFB', value: Number(ttfb.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n } catch (error) {\n log('warn', 'Failed to report TTFB', { error });\n }\n }\n\n private observeLongTasks(): void {\n this.safeObserve(\n 'longtask',\n (list) => {\n const entries = list.getEntries() as Array<{ duration: number }>;\n\n for (const entry of entries) {\n const duration = Number(entry.duration.toFixed(PRECISION_TWO_DECIMALS));\n const now = Date.now();\n\n if (now - this.lastLongTaskSentAt >= LONG_TASK_THROTTLE_MS) {\n if (this.shouldSendVital('LONG_TASK', duration)) {\n this.trackWebVital('LONG_TASK', duration);\n }\n this.lastLongTaskSentAt = now;\n }\n }\n },\n { type: 'longtask', buffered: true },\n );\n }\n\n private sendVital(sample: { type: WebVitalType; value: number }): void {\n if (!this.shouldSendVital(sample.type, sample.value)) {\n return;\n }\n\n const navId = this.getNavigationId();\n\n // Check for duplicates if we have a navigation ID\n if (navId) {\n const reportedForNav = this.reportedByNav.get(navId);\n const isDuplicate = reportedForNav?.has(sample.type);\n\n if (isDuplicate) {\n return;\n }\n\n // Initialize or update reported vitals for this navigation\n if (!reportedForNav) {\n this.reportedByNav.set(navId, new Set([sample.type]));\n } else {\n reportedForNav.add(sample.type);\n }\n }\n\n this.trackWebVital(sample.type, sample.value);\n }\n\n private trackWebVital(type: WebVitalType, value: number): void {\n if (!Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return;\n }\n\n this.eventManager.track({\n type: EventType.WEB_VITALS,\n web_vitals: {\n type,\n value,\n },\n });\n }\n\n private getNavigationId(): string | null {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return null;\n }\n\n // Use more precise timestamp and add random component to prevent collisions\n const timestamp = nav.startTime || performance.now();\n const random = Math.random().toString(36).substr(2, 5);\n return `${timestamp.toFixed(2)}_${window.location.pathname}_${random}`;\n } catch (error) {\n log('warn', 'Failed to get navigation ID', { error });\n return null;\n }\n }\n\n private isObserverSupported(type: string): boolean {\n if (typeof PerformanceObserver === 'undefined') return false;\n const supported = PerformanceObserver.supportedEntryTypes;\n return !supported || supported.includes(type);\n }\n\n private safeObserve(\n type: string,\n cb: PerformanceObserverCallback,\n options?: PerformanceObserverInit,\n once = false,\n ): boolean {\n try {\n if (!this.isObserverSupported(type)) {\n return false;\n }\n\n const obs = new PerformanceObserver((list, observer) => {\n try {\n cb(list, observer);\n } catch (callbackError) {\n log('warn', 'Observer callback failed', {\n error: callbackError,\n data: { type },\n });\n }\n\n if (once) {\n try {\n observer.disconnect();\n } catch {\n // Disconnect errors are safe to ignore\n }\n }\n });\n\n obs.observe(options ?? { type, buffered: true });\n\n if (!once) {\n this.observers.push(obs);\n }\n\n return true;\n } catch (error) {\n log('warn', 'Failed to create performance observer', {\n error,\n data: { type },\n });\n return false;\n }\n }\n\n private shouldSendVital(type: WebVitalType, value?: number): boolean {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return false;\n }\n\n const threshold = this.vitalThresholds[type];\n\n if (typeof threshold === 'number' && value <= threshold) {\n return false;\n }\n\n return true;\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { ErrorType, EventType } from '../types';\nimport { log } from '../utils';\nimport {\n PII_PATTERNS,\n MAX_ERROR_MESSAGE_LENGTH,\n ERROR_SUPPRESSION_WINDOW_MS,\n MAX_TRACKED_ERRORS,\n MAX_TRACKED_ERRORS_HARD_LIMIT,\n DEFAULT_ERROR_SAMPLING_RATE,\n ERROR_BURST_WINDOW_MS,\n ERROR_BURST_THRESHOLD,\n ERROR_BURST_BACKOFF_MS,\n} from '../constants/error.constants';\n\n/**\n * Simplified error handler for tracking JavaScript errors and unhandled promise rejections\n * Includes PII sanitization and sampling support\n */\nexport class ErrorHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly recentErrors = new Map<string, number>();\n private errorBurstCounter = 0;\n private burstWindowStart = 0;\n private burstBackoffUntil = 0;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n window.addEventListener('error', this.handleError);\n window.addEventListener('unhandledrejection', this.handleRejection);\n }\n\n stopTracking(): void {\n window.removeEventListener('error', this.handleError);\n window.removeEventListener('unhandledrejection', this.handleRejection);\n this.recentErrors.clear();\n this.errorBurstCounter = 0;\n this.burstWindowStart = 0;\n this.burstBackoffUntil = 0;\n }\n\n /**\n * Checks sampling rate and burst detection (Phase 3)\n * Returns false if in cooldown period after burst detection\n */\n private shouldSample(): boolean {\n const now = Date.now();\n\n // Check if in backoff period (Phase 3)\n if (now < this.burstBackoffUntil) {\n return false;\n }\n\n // Reset burst counter if window expired\n if (now - this.burstWindowStart > ERROR_BURST_WINDOW_MS) {\n this.errorBurstCounter = 0;\n this.burstWindowStart = now;\n }\n\n // Increment burst counter\n this.errorBurstCounter++;\n\n // Trigger backoff if burst threshold exceeded\n if (this.errorBurstCounter > ERROR_BURST_THRESHOLD) {\n this.burstBackoffUntil = now + ERROR_BURST_BACKOFF_MS;\n log('warn', 'Error burst detected - entering cooldown', {\n data: {\n errorsInWindow: this.errorBurstCounter,\n cooldownMs: ERROR_BURST_BACKOFF_MS,\n },\n });\n return false;\n }\n\n // Normal sampling logic\n const config = this.get('config');\n const samplingRate = config?.errorSampling ?? DEFAULT_ERROR_SAMPLING_RATE;\n return Math.random() < samplingRate;\n }\n\n private readonly handleError = (event: ErrorEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const sanitizedMessage = this.sanitize(event.message || 'Unknown error');\n\n if (this.shouldSuppressError(ErrorType.JS_ERROR, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.JS_ERROR,\n message: sanitizedMessage,\n ...(event.filename && { filename: event.filename }),\n ...(event.lineno && { line: event.lineno }),\n ...(event.colno && { column: event.colno }),\n },\n });\n };\n\n private readonly handleRejection = (event: PromiseRejectionEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const message = this.extractRejectionMessage(event.reason);\n const sanitizedMessage = this.sanitize(message);\n\n if (this.shouldSuppressError(ErrorType.PROMISE_REJECTION, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.PROMISE_REJECTION,\n message: sanitizedMessage,\n },\n });\n };\n\n private extractRejectionMessage(reason: unknown): string {\n if (!reason) return 'Unknown rejection';\n\n if (typeof reason === 'string') return reason;\n\n if (reason instanceof Error) {\n return reason.stack ?? reason.message ?? reason.toString();\n }\n\n if (typeof reason === 'object' && 'message' in reason) {\n return String(reason.message);\n }\n\n try {\n return JSON.stringify(reason);\n } catch {\n return String(reason);\n }\n }\n\n private sanitize(text: string): string {\n let sanitized = text.length > MAX_ERROR_MESSAGE_LENGTH ? text.slice(0, MAX_ERROR_MESSAGE_LENGTH) + '...' : text;\n\n for (const pattern of PII_PATTERNS) {\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private shouldSuppressError(type: ErrorType, message: string): boolean {\n const now = Date.now();\n const key = `${type}:${message}`;\n const lastSeenAt = this.recentErrors.get(key);\n\n if (lastSeenAt && now - lastSeenAt < ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.set(key, now);\n return true;\n }\n\n this.recentErrors.set(key, now);\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS_HARD_LIMIT) {\n this.recentErrors.clear();\n this.recentErrors.set(key, now);\n\n return false;\n }\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS) {\n this.pruneOldErrors();\n }\n\n return false;\n }\n\n private pruneOldErrors(): void {\n const now = Date.now();\n for (const [key, timestamp] of this.recentErrors.entries()) {\n if (now - timestamp > ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.delete(key);\n }\n }\n\n if (this.recentErrors.size <= MAX_TRACKED_ERRORS) {\n return;\n }\n\n const entries = Array.from(this.recentErrors.entries()).sort((a, b) => a[1] - b[1]);\n const excess = this.recentErrors.size - MAX_TRACKED_ERRORS;\n\n for (let index = 0; index < excess; index += 1) {\n const entry = entries[index];\n if (entry) {\n this.recentErrors.delete(entry[0]);\n }\n }\n }\n}\n","import { EventManager } from './managers/event.manager';\nimport { UserManager } from './managers/user.manager';\nimport { StateManager } from './managers/state.manager';\nimport { SessionHandler } from './handlers/session.handler';\nimport { PageViewHandler } from './handlers/page-view.handler';\nimport { ClickHandler } from './handlers/click.handler';\nimport { ScrollHandler } from './handlers/scroll.handler';\nimport { ViewportHandler } from './handlers/viewport.handler';\nimport { Config, EventType, EmitterCallback, EmitterMap, Mode } from './types';\nimport { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';\nimport { isEventValid, getDeviceType, normalizeUrl, Emitter, getCollectApiUrl, detectQaMode, log } from './utils';\nimport { StorageManager } from './managers/storage.manager';\nimport { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';\nimport { PerformanceHandler } from './handlers/performance.handler';\nimport { ErrorHandler } from './handlers/error.handler';\n\nexport class App extends StateManager {\n private isInitialized = false;\n private suppressNextScrollTimer: number | null = null;\n\n private readonly emitter = new Emitter();\n\n protected managers: {\n storage?: StorageManager;\n event?: EventManager;\n } = {};\n\n protected handlers: {\n session?: SessionHandler;\n pageView?: PageViewHandler;\n click?: ClickHandler;\n scroll?: ScrollHandler;\n performance?: PerformanceHandler;\n error?: ErrorHandler;\n viewport?: ViewportHandler;\n } = {};\n\n protected integrations: {\n googleAnalytics?: GoogleAnalyticsIntegration;\n } = {};\n\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n async init(config: Config = {}): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n this.managers.storage = new StorageManager();\n\n try {\n this.setupState(config);\n await this.setupIntegrations();\n\n this.managers.event = new EventManager(this.managers.storage, this.integrations.googleAnalytics, this.emitter);\n\n this.initializeHandlers();\n\n await this.managers.event.recoverPersistedEvents().catch((error) => {\n log('warn', 'Failed to recover persisted events', { error });\n });\n\n this.isInitialized = true;\n } catch (error) {\n this.destroy(true);\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] TraceLog initialization failed: ${errorMessage}`);\n }\n }\n\n sendCustomEvent(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void {\n if (!this.managers.event) {\n return;\n }\n\n const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);\n\n if (!valid) {\n if (this.get('mode') === Mode.QA) {\n throw new Error(`[TraceLog] Custom event \"${name}\" validation failed: ${error}`);\n }\n\n return;\n }\n\n this.managers.event.track({\n type: EventType.CUSTOM,\n custom_event: {\n name,\n ...(sanitizedMetadata && { metadata: sanitizedMetadata }),\n },\n });\n }\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.on(event, callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.off(event, callback);\n }\n\n destroy(force = false): void {\n if (!this.isInitialized && !force) {\n return;\n }\n\n this.integrations.googleAnalytics?.cleanup();\n\n Object.values(this.handlers)\n .filter(Boolean)\n .forEach((handler) => {\n try {\n handler.stopTracking();\n } catch (error) {\n log('warn', 'Failed to stop tracking', { error });\n }\n });\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n this.suppressNextScrollTimer = null;\n }\n\n this.managers.event?.flushImmediatelySync();\n\n this.managers.event?.stop();\n\n this.emitter.removeAllListeners();\n\n this.set('hasStartSession', false);\n this.set('suppressNextScroll', false);\n this.set('sessionId', null);\n\n this.isInitialized = false;\n this.handlers = {};\n }\n\n private setupState(config: Config = {}): void {\n this.set('config', config);\n\n const userId = UserManager.getId(this.managers.storage as StorageManager);\n this.set('userId', userId);\n\n const collectApiUrl = getCollectApiUrl(config);\n this.set('collectApiUrl', collectApiUrl);\n\n const device = getDeviceType();\n this.set('device', device);\n\n const pageUrl = normalizeUrl(window.location.href, config.sensitiveQueryParams);\n this.set('pageUrl', pageUrl);\n\n const mode = detectQaMode() ? Mode.QA : undefined;\n\n if (mode) {\n this.set('mode', mode);\n }\n }\n\n private async setupIntegrations(): Promise<void> {\n const config = this.get('config');\n const measurementId = config.integrations?.googleAnalytics?.measurementId;\n\n if (measurementId?.trim()) {\n try {\n this.integrations.googleAnalytics = new GoogleAnalyticsIntegration();\n await this.integrations.googleAnalytics.initialize();\n } catch {\n this.integrations.googleAnalytics = undefined;\n }\n }\n }\n\n private initializeHandlers(): void {\n this.handlers.session = new SessionHandler(\n this.managers.storage as StorageManager,\n this.managers.event as EventManager,\n );\n\n this.handlers.session.startTracking();\n\n const onPageView = (): void => {\n this.set('suppressNextScroll', true);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n }\n\n this.suppressNextScrollTimer = window.setTimeout(() => {\n this.set('suppressNextScroll', false);\n }, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESS_MULTIPLIER);\n };\n\n this.handlers.pageView = new PageViewHandler(this.managers.event as EventManager, onPageView);\n this.handlers.pageView.startTracking();\n\n this.handlers.click = new ClickHandler(this.managers.event as EventManager);\n this.handlers.click.startTracking();\n\n this.handlers.scroll = new ScrollHandler(this.managers.event as EventManager);\n this.handlers.scroll.startTracking();\n\n this.handlers.performance = new PerformanceHandler(this.managers.event as EventManager);\n this.handlers.performance.startTracking().catch((error) => {\n log('warn', 'Failed to start performance tracking', { error });\n });\n\n this.handlers.error = new ErrorHandler(this.managers.event as EventManager);\n this.handlers.error.startTracking();\n\n if (this.get('config').viewport) {\n this.handlers.viewport = new ViewportHandler(this.managers.event as EventManager);\n this.handlers.viewport.startTracking();\n }\n }\n}\n","import { App } from './app';\nimport { MetadataType, Config, EmitterCallback, EmitterMap } from './types';\nimport { log, validateAndNormalizeConfig } from './utils';\nimport { TestBridge } from './test-bridge';\nimport { INITIALIZATION_TIMEOUT_MS } from './constants';\nimport './types/window.types';\n\ninterface PendingListener {\n event: keyof EmitterMap;\n callback: EmitterCallback<EmitterMap[keyof EmitterMap]>;\n}\n\n// Buffer for listeners registered before init()\nconst pendingListeners: PendingListener[] = [];\n\nlet app: App | null = null;\nlet isInitializing = false;\nlet isDestroying = false;\n\nexport const init = async (config?: Config): Promise<void> => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (window.__traceLogDisabled) {\n return;\n }\n\n if (app) {\n return;\n }\n\n if (isInitializing) {\n return;\n }\n\n isInitializing = true;\n\n try {\n const validatedConfig = validateAndNormalizeConfig(config ?? {});\n const instance = new App();\n\n try {\n pendingListeners.forEach(({ event, callback }) => {\n instance.on(event, callback);\n });\n\n pendingListeners.length = 0;\n\n const initPromise = instance.init(validatedConfig);\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`[TraceLog] Initialization timeout after ${INITIALIZATION_TIMEOUT_MS}ms`));\n }, INITIALIZATION_TIMEOUT_MS);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n\n app = instance;\n } catch (error) {\n try {\n instance.destroy(true);\n } catch (cleanupError) {\n log('error', 'Failed to cleanup partially initialized app', { error: cleanupError });\n }\n\n throw error;\n }\n } catch (error) {\n app = null;\n throw error;\n } finally {\n isInitializing = false;\n }\n};\n\nexport const event = (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app) {\n throw new Error('[TraceLog] TraceLog not initialized. Please call init() first.');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Cannot send events while TraceLog is being destroyed');\n }\n\n app.sendCustomEvent(name, metadata);\n};\n\nexport const on = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app || isInitializing) {\n // Buffer listeners registered before or during init()\n pendingListeners.push({ event, callback } as PendingListener);\n return;\n }\n\n app.on(event, callback);\n};\n\nexport const off = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app) {\n // Remove from pending listeners if not yet initialized\n const index = pendingListeners.findIndex((l) => l.event === event && l.callback === callback);\n if (index !== -1) {\n pendingListeners.splice(index, 1);\n }\n return;\n }\n\n app.off(event, callback);\n};\n\nexport const isInitialized = (): boolean => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return false;\n }\n\n return app !== null;\n};\n\nexport const destroy = (): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Destroy operation already in progress');\n }\n\n if (!app) {\n throw new Error('[TraceLog] App not initialized');\n }\n\n isDestroying = true;\n\n try {\n app.destroy();\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Clear TestBridge reference in dev mode to prevent stale references\n if (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined' && window.__traceLogBridge) {\n // Don't call destroy on bridge (would cause recursion), just clear reference\n window.__traceLogBridge = undefined as any;\n }\n } catch (error) {\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Log error but don't re-throw - destroy should always complete successfully\n // Applications should be able to tear down TraceLog even if internal cleanup fails\n log('warn', 'Error during destroy, forced cleanup completed', { error });\n } finally {\n isDestroying = false;\n }\n};\n\nif (process.env.NODE_ENV === 'dev' && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const injectTestingBridge = (): void => {\n window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectTestingBridge);\n } else {\n injectTestingBridge();\n }\n}\n\n/**\n * Internal sync function - ONLY for TestBridge in development\n *\n * WARNING: This function is internal and should NEVER be called directly.\n * It's only exported for TestBridge synchronization in dev mode.\n *\n * @internal\n */\nexport const __setAppInstance = (instance: App | null): void => {\n if (instance !== null) {\n const hasRequiredMethods =\n typeof instance === 'object' &&\n 'init' in instance &&\n 'destroy' in instance &&\n 'on' in instance &&\n 'off' in instance;\n\n if (!hasRequiredMethods) {\n throw new Error('[TraceLog] Invalid app instance type');\n }\n }\n\n // Prevent overwriting an already initialized app (except when clearing)\n if (app !== null && instance !== null && app !== instance) {\n throw new Error('[TraceLog] Cannot overwrite existing app instance. Call destroy() first.');\n }\n\n app = instance;\n};\n","import { WEB_VITALS_THRESHOLDS } from './constants/performance.constants';\nimport { PII_PATTERNS } from './constants/error.constants';\n\nexport {\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_NESTED_OBJECT_KEYS,\n MAX_METADATA_NESTING_DEPTH,\n MAX_STRING_LENGTH,\n MAX_STRING_LENGTH_IN_ARRAY,\n MAX_ARRAY_LENGTH,\n} from './constants';\n\nexport const PERFORMANCE_CONFIG = {\n WEB_VITALS_THRESHOLDS, // Business thresholds for performance analysis\n} as const;\n\nexport const DATA_PROTECTION = {\n PII_PATTERNS, // Patterns for sensitive data protection\n} as const;\n\nexport const ENGAGEMENT_THRESHOLDS = {\n LOW_ACTIVITY_EVENT_COUNT: 50,\n HIGH_ACTIVITY_EVENT_COUNT: 1000,\n MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,\n MIN_EVENTS_FOR_TREND_ANALYSIS: 30,\n BOUNCE_RATE_SESSION_THRESHOLD: 1, // Sessions with 1 page view = bounce\n MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1000,\n MIN_SCROLL_DEPTH_ENGAGEMENT: 25, // 25% scroll depth for engagement\n} as const;\n\nexport const SESSION_ANALYTICS = {\n INACTIVITY_TIMEOUT_MS: 30 * 60 * 1000, // 30min for analytics (vs 15min client)\n SHORT_SESSION_THRESHOLD_MS: 30 * 1000,\n MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1000,\n LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1000,\n MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1000, // Filter outliers\n} as const;\n\nexport const DEVICE_ANALYTICS = {\n MOBILE_MAX_WIDTH: 768,\n TABLET_MAX_WIDTH: 1024,\n MOBILE_PERFORMANCE_FACTOR: 1.5, // Mobile typically 1.5x slower\n TABLET_PERFORMANCE_FACTOR: 1.2,\n} as const;\n\nexport const CONTENT_ANALYTICS = {\n MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,\n MIN_CLICKS_FOR_HOT_ELEMENT: 10, // Popular element threshold\n MIN_SCROLL_COMPLETION_PERCENT: 80, // Page consumption threshold\n MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1000,\n} as const;\n\nexport const INSIGHT_THRESHOLDS = {\n SIGNIFICANT_CHANGE_PERCENT: 20,\n MAJOR_CHANGE_PERCENT: 50,\n MIN_EVENTS_FOR_INSIGHT: 100,\n MIN_SESSIONS_FOR_INSIGHT: 10,\n MIN_CORRELATION_STRENGTH: 0.7, // Strong correlation threshold\n LOW_ERROR_RATE_PERCENT: 1,\n HIGH_ERROR_RATE_PERCENT: 5,\n CRITICAL_ERROR_RATE_PERCENT: 10,\n} as const;\n\nexport const TEMPORAL_ANALYSIS = {\n SHORT_TERM_TREND_HOURS: 24,\n MEDIUM_TERM_TREND_DAYS: 7,\n LONG_TERM_TREND_DAYS: 30,\n MIN_DATA_POINTS_FOR_TREND: 5,\n WEEKLY_PATTERN_MIN_WEEKS: 4,\n DAILY_PATTERN_MIN_DAYS: 14,\n} as const;\n\nexport const SEGMENTATION_ANALYTICS = {\n MIN_SEGMENT_SIZE: 10,\n MIN_COHORT_SIZE: 5,\n COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],\n MIN_FUNNEL_EVENTS: 20,\n} as const;\n\nexport const ANALYTICS_QUERY_LIMITS = {\n DEFAULT_EVENTS_LIMIT: 5,\n DEFAULT_SESSIONS_LIMIT: 5,\n DEFAULT_PAGES_LIMIT: 5,\n MAX_EVENTS_FOR_DEEP_ANALYSIS: 10000,\n MAX_TIME_RANGE_DAYS: 365,\n ANALYTICS_BATCH_SIZE: 1000, // For historical analysis\n} as const;\n\nexport const ANOMALY_DETECTION = {\n ANOMALY_THRESHOLD_SIGMA: 2.5,\n STRONG_ANOMALY_THRESHOLD_SIGMA: 3.0,\n TRAFFIC_DROP_ALERT_PERCENT: -30,\n TRAFFIC_SPIKE_ALERT_PERCENT: 200,\n MIN_BASELINE_DAYS: 7,\n MIN_EVENTS_FOR_ANOMALY_DETECTION: 50,\n} as const;\n\nexport const SPECIAL_PAGE_URLS = {\n PAGE_URL_EXCLUDED: 'excluded',\n PAGE_URL_UNKNOWN: 'unknown',\n} as const;\n","import { init, event, on, off, isInitialized, destroy } from './api';\n\n// Constants\nexport * from './app.constants';\n\n// Types\nexport * from './types';\n\n// TraceLog namespace containing all API methods\nexport const tracelog = {\n init,\n event,\n on,\n off,\n isInitialized,\n destroy,\n};\n","var e,n,t,r,i,o=-1,a=function(e){addEventListener(\"pageshow\",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r=\"navigate\";o>=0?r=\"back-forward-cache\":t&&(document.prerendering||u()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":t.type&&(r=t.type.replace(/_/g,\"-\")));return{name:e,value:void 0===n?-1:n,rating:\"good\",delta:0,entries:[],id:\"v4-\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?\"poor\":e>n[0]?\"needs-improvement\":\"good\"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener(\"visibilitychange\",(function(){\"hidden\"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return\"hidden\"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){\"hidden\"===document.visibilityState&&m>-1&&(m=\"visibilitychange\"===e.type?e.timeStamp:0,T())},y=function(){addEventListener(\"visibilitychange\",g,!0),addEventListener(\"prerenderingchange\",g,!0)},T=function(){removeEventListener(\"visibilitychange\",g,!0),removeEventListener(\"prerenderingchange\",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener(\"prerenderingchange\",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"FCP\"),o=s(\"paint\",(function(e){e.forEach((function(e){\"first-contentful-paint\"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f(\"FCP\"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f(\"CLS\",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s(\"layout-shift\",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f(\"CLS\",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){\"interactionCount\"in performance||e||(e=s(\"event\",M,{type:\"event\",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||\"first-input\"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),\"hidden\"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){\"PerformanceEventTiming\"in self&&\"interactionId\"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f(\"INP\"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s(\"event\",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:\"first-input\",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f(\"INP\"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"LCP\"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s(\"largest-contentful-paint\",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));[\"keydown\",\"click\"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f(\"LCP\"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):\"complete\"!==document.readyState?addEventListener(\"load\",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f(\"TTFB\"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f(\"TTFB\",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:\"first-input\",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;\"pointerdown\"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener(\"pointerup\",t,U),removeEventListener(\"pointercancel\",r,U)};addEventListener(\"pointerup\",t,U),addEventListener(\"pointercancel\",r,U)}(n,e):W(n,e)}},Z=function(e){[\"mousedown\",\"keydown\",\"touchstart\",\"pointerdown\"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f(\"FID\"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s(\"first-input\",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f(\"FID\"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};\n"],"names":["MAX_CUSTOM_EVENT_NAME_LENGTH","MAX_CUSTOM_EVENT_STRING_SIZE","MAX_CUSTOM_EVENT_KEYS","MAX_CUSTOM_EVENT_ARRAY_SIZE","MAX_NESTED_OBJECT_KEYS","MAX_METADATA_NESTING_DEPTH","MAX_STRING_LENGTH","MAX_STRING_LENGTH_IN_ARRAY","MAX_ARRAY_LENGTH","HTML_DATA_ATTR_PREFIX","INTERACTIVE_SELECTORS","UTM_PARAMS","DEFAULT_SENSITIVE_QUERY_PARAMS","VALIDATION_MESSAGES","XSS_PATTERNS","SpecialApiUrl","DeviceType","EmitterEvent","PermanentError","message","statusCode","EventType","ScrollDirection","ErrorType","Mode","isPrimaryScrollEvent","event","isSecondaryScrollEvent","TraceLogValidationError","errorCode","layer","AppConfigValidationError","SessionTimeoutValidationError","SamplingRateValidationError","IntegrationValidationError","InitializationTimeoutError","timeoutMs","formatLogMsg","msg","error","sanitizedMessage","log","type","extra","data","showToClient","formattedMsg","method","sanitizedData","sanitizeLogData","sanitized","sensitiveKeys","key","value","lowerKey","sensitiveKey","coarsePointerQuery","noHoverQuery","initMediaQueries","getDeviceType","nav","width","hasCoarsePointer","hasNoHover","hasTouchSupport","ua","isMobileUA","isTabletUA","STORAGE_BASE_KEY","QA_MODE_KEY","USER_ID_KEY","QUEUE_KEY","id","SESSION_STORAGE_KEY","BROADCAST_CHANNEL_NAME","WEB_VITALS_THRESHOLDS","LONG_TASK_THROTTLE_MS","PII_PATTERNS","MAX_ERROR_MESSAGE_LENGTH","ERROR_SUPPRESSION_WINDOW_MS","MAX_TRACKED_ERRORS","MAX_TRACKED_ERRORS_HARD_LIMIT","DEFAULT_ERROR_SAMPLING_RATE","ERROR_BURST_WINDOW_MS","ERROR_BURST_THRESHOLD","ERROR_BURST_BACKOFF_MS","PERMANENT_ERROR_LOG_THROTTLE_MS","QA_MODE_PARAM","QA_MODE_VALUE","detectQaMode","params","isQaMode","newSearch","newUrl","getUTMParameters","urlParams","utmParams","param","generateUUID","c","r","generateEventId","timestamp","random","bytes","b","isValidUrl","url","allowHttp","parsed","isHttps","isHttp","getCollectApiUrl","config","parts","projectId","cleanDomain","collectApiUrl","normalizeUrl","sensitiveQueryParams","urlObject","searchParams","allSensitiveParams","hasChanged","removedParams","sanitizeString","xssPatternMatches","pattern","beforeReplace","sanitizeValue","depth","item","sanitizedObject","limitedEntries","value_","sanitizedKey","sanitizedValue","sanitizeMetadata","metadata","errorMessage","validateAppConfig","validateIntegrations","validateViewportConfig","viewport","uniqueSelectors","element","normalizedSelector","integrations","validateAndNormalizeConfig","normalizedConfig","isValidArrayItem","entries","isOnlyPrimitiveFields","object","isValidEventName","eventName","validateSingleMetadata","sanitizedMetadata","intro","jsonString","isValidMetadata","sanitizedArray","itemValidation","isEventValid","nameValidation","metadataValidation","Emitter","callback","callbacks","index","globalState","StateManager","SenderManager","storeManager","userId","body","success","persistedData","payload","controller","timeoutId","response","blob","accepted","enrichedBody","storageKey","persistedDataString","delay","resolve","context","now","EventManager","googleAnalytics","emitter","_eventCount","recoveredEvents","eventIds","e","page_url","from_page_url","scroll_data","click_data","custom_event","web_vitals","error_data","session_end_reason","viewport_data","currentSessionId","isCriticalEvent","eventType","typeLimit","currentCount","maxSameEventPerMinute","isSessionStart","currentPageUrl","bufferedEvents","isSync","eventsToSend","eventMap","order","signature","events","a","fingerprint","lastSeen","cutoff","x","y","nonCriticalIndex","removedEvent","samplingRate","validTimestamps","ts","eventIdSet","eventData","queue","UserManager","storageManager","storedUserId","newUserId","SessionManager","eventManager","action","sessionId","messageProjectId","reason","storedSession","sessionTimeout","lastActivity","storedData","session","recoveredSessionId","isRecovered","SessionHandler","PageViewHandler","onTrack","original","args","rawUrl","normalizedUrl","throttleMs","fromUrl","pageViewData","pathname","search","hash","referrer","title","ClickHandler","mouseEvent","target","clickedElement","clickThrottleMs","trackingElement","relevantClickElement","coordinates","trackingData","attributeData","clickData","lastClickTime","testId","tlogName","path","current","selector","firstClass","parent","rect","relativeX","relativeY","name","relevantElement","text","attributes","regex","clickedText","relevantText","finalText","commonAttributes","result","attributeName","ScrollHandler","container","attempt","elements","walker","node","style","htmlElement","handleScroll","scrollData","initialScrollTop","initialDepth","isPrimary","newDepth","previous","scrollTop","scrollHeight","viewportHeight","maxScrollTop","lastScrollPos","lastEventTime","positionDelta","direction","timeDelta","velocity","hasScrollableOverflow","hasOverflowContent","targetElement","ViewportHandler","threshold","minDwellTime","tracked","maxTrackedElements","totalTracked","elementConfig","entry","visibilityRatio","dwellTime","cooldownPeriod","mutations","hasAddedNodes","mutation","removedNodes","el","descendantTracked","GoogleAnalyticsIntegration","measurementId","normalizedMetadata","script","reject","gaScriptConfig","StorageManager","retryError","keysToRemove","i","tracelogKeys","persistedEventsKeys","criticalPrefixes","nonCriticalKeys","prefix","storage","testKey","PerformanceHandler","obs","list","last","clsValue","currentNavId","navId","worst","dur","onLCP","onCLS","onFCP","onTTFB","onINP","webVitals","report","metric","ttfb","duration","sample","reportedForNav","supported","cb","options","once","observer","callbackError","ErrorHandler","lastSeenAt","excess","App","valid","force","handler","device","pageUrl","mode","onPageView","pendingListeners","app","isInitializing","isDestroying","init","validatedConfig","instance","initPromise","timeoutPromise","_","cleanupError","on","off","l","isInitialized","destroy","PERFORMANCE_CONFIG","DATA_PROTECTION","ENGAGEMENT_THRESHOLDS","SESSION_ANALYTICS","DEVICE_ANALYTICS","CONTENT_ANALYTICS","INSIGHT_THRESHOLDS","TEMPORAL_ANALYSIS","SEGMENTATION_ANALYTICS","ANALYTICS_QUERY_LIMITS","ANOMALY_DETECTION","SPECIAL_PAGE_URLS","tracelog","o","n","u","f","s","d","p","v","m","h","g","T","E","C","S","L","w","t","A","I","P","M","k","F","D","R","B","H","q","O","N","j","z","G","J","K","Q"],"mappings":"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","x_google_ignoreList":[42]}
1
+ {"version":3,"file":"tracelog.esm.js","sources":["../../src/constants/config.constants.ts","../../src/types/config.types.ts","../../src/types/device.types.ts","../../src/types/emitter.types.ts","../../src/types/error.types.ts","../../src/types/event.types.ts","../../src/types/mode.types.ts","../../src/types/scroll.types.ts","../../src/types/validation-error.types.ts","../../src/utils/logging.utils.ts","../../src/utils/browser/device-detector.utils.ts","../../src/constants/storage.constants.ts","../../src/constants/performance.constants.ts","../../src/constants/error.constants.ts","../../src/utils/browser/qa-mode.utils.ts","../../src/utils/browser/utm-params.utils.ts","../../src/utils/data/uuid.utils.ts","../../src/utils/network/url.utils.ts","../../src/utils/security/sanitize.utils.ts","../../src/utils/validations/config-validations.utils.ts","../../src/utils/validations/type-guards.utils.ts","../../src/utils/validations/metadata-validations.utils.ts","../../src/utils/validations/event-validations.utils.ts","../../src/utils/emitter.utils.ts","../../src/managers/state.manager.ts","../../src/managers/sender.manager.ts","../../src/managers/event.manager.ts","../../src/managers/user.manager.ts","../../src/managers/session.manager.ts","../../src/handlers/session.handler.ts","../../src/handlers/page-view.handler.ts","../../src/handlers/click.handler.ts","../../src/handlers/scroll.handler.ts","../../src/handlers/viewport.handler.ts","../../src/integrations/google-analytics.integration.ts","../../src/managers/storage.manager.ts","../../src/handlers/performance.handler.ts","../../src/handlers/error.handler.ts","../../src/app.ts","../../src/api.ts","../../src/app.constants.ts","../../src/public-api.ts","../../node_modules/web-vitals/dist/web-vitals.js"],"sourcesContent":["/**\n * Consolidated configuration constants for TraceLog\n * This file centralizes all timing, limits, browser, and initialization constants\n */\n\n// ============================================================================\n// SESSION & TIMING\n// ============================================================================\n\nexport const DEFAULT_SESSION_TIMEOUT = 15 * 60 * 1000; // 15 minutes\nexport const DUPLICATE_EVENT_THRESHOLD_MS = 500; // 500ms\nexport const EVENT_SENT_INTERVAL_MS = 10000; // 10 seconds\n\n// Throttling and debouncing\nexport const SCROLL_DEBOUNCE_TIME_MS = 250;\nexport const DEFAULT_VISIBILITY_TIMEOUT_MS = 2000;\nexport const DEFAULT_PAGE_VIEW_THROTTLE_MS = 1000; // 1 second throttle for page views\nexport const DEFAULT_CLICK_THROTTLE_MS = 300; // 300ms throttle for clicks per element\nexport const DEFAULT_VIEWPORT_COOLDOWN_PERIOD = 60000; // 60 seconds cooldown for viewport events\nexport const DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS = 100; // Maximum elements to track (Phase 3)\nexport const VIEWPORT_MUTATION_DEBOUNCE_MS = 100; // Debounce for mutation observer re-scanning\n\n// Click throttle cache limits\nexport const MAX_THROTTLE_CACHE_ENTRIES = 1000; // Maximum element signatures to track\nexport const THROTTLE_ENTRY_TTL_MS = 300000; // 5 minutes TTL for throttle entries\nexport const THROTTLE_PRUNE_INTERVAL_MS = 30000; // 30 seconds interval for cache pruning\n\n// Event expiry\nexport const EVENT_EXPIRY_HOURS = 2;\nexport const EVENT_PERSISTENCE_MAX_AGE_MS = 2 * 60 * 60 * 1000; // 2 hours\nexport const PERSISTENCE_THROTTLE_MS = 1000; // 1 second throttle for cross-tab persistence coordination\n\n// ============================================================================\n// LIMITS & REQUESTS\n// ============================================================================\n\nexport const MAX_EVENTS_QUEUE_LENGTH = 100;\nexport const REQUEST_TIMEOUT_MS = 10000;\nexport const MAX_METADATA_SIZE = 5000;\n\n// Motion and interaction thresholds\nexport const DEFAULT_MOTION_THRESHOLD = 2;\nexport const SIGNIFICANT_SCROLL_DELTA = 10;\nexport const MIN_SCROLL_DEPTH_CHANGE = 5;\nexport const SCROLL_MIN_EVENT_INTERVAL_MS = 500;\nexport const MAX_SCROLL_EVENTS_PER_SESSION = 120;\n\n// Sampling and rate limits\nexport const DEFAULT_SAMPLING_RATE = 1;\nexport const MIN_SAMPLING_RATE = 0;\nexport const MAX_SAMPLING_RATE = 1;\nexport const RATE_LIMIT_WINDOW_MS = 1000; // 1 second window\nexport const MAX_EVENTS_PER_SECOND = 50; // Maximum 50 events per second (Phase 3: reduced from 200)\nexport const MAX_SAME_EVENT_PER_MINUTE = 60; // Maximum same custom event name per minute (prevents infinite loops)\nexport const PER_EVENT_RATE_LIMIT_WINDOW_MS = 60000; // 60 second window for per-event-name rate limiting\n\n// Per-session event caps (Phase 3)\nexport const MAX_EVENTS_PER_SESSION = 1000;\nexport const MAX_CLICKS_PER_SESSION = 500;\nexport const MAX_PAGE_VIEWS_PER_SESSION = 100;\nexport const MAX_CUSTOM_EVENTS_PER_SESSION = 500;\nexport const MAX_VIEWPORT_EVENTS_PER_SESSION = 200;\n\n// Queue and batch limits\nexport const BATCH_SIZE_THRESHOLD = 50;\nexport const MAX_PENDING_EVENTS_BUFFER = 100; // Maximum events to buffer before session init\n\n// Session timeout validation limits\nexport const MIN_SESSION_TIMEOUT_MS = 30000; // 30 seconds minimum\nexport const MAX_SESSION_TIMEOUT_MS = 86400000; // 24 hours maximum\n\n// Custom event validation limits\nexport const MAX_CUSTOM_EVENT_NAME_LENGTH = 120;\nexport const MAX_CUSTOM_EVENT_STRING_SIZE = 8 * 1024; // 8KB\nexport const MAX_CUSTOM_EVENT_KEYS = 10;\nexport const MAX_CUSTOM_EVENT_ARRAY_SIZE = 10;\nexport const MAX_NESTED_OBJECT_KEYS = 20; // Maximum keys in nested objects within arrays\nexport const MAX_METADATA_NESTING_DEPTH = 1; // Maximum nesting depth for metadata objects\n\n// Text content limits\nexport const MAX_TEXT_LENGTH = 255; // For click tracking text content\n\n// Data sanitization limits\nexport const MAX_STRING_LENGTH = 1000;\nexport const MAX_STRING_LENGTH_IN_ARRAY = 500; // Strings within arrays are more limited\nexport const MAX_ARRAY_LENGTH = 100;\nexport const MAX_OBJECT_DEPTH = 3;\n\n// Precision for numeric metrics\nexport const PRECISION_TWO_DECIMALS = 2 as const;\n\n// Sync XHR timeout\nexport const SYNC_XHR_TIMEOUT_MS = 2000; // 2 seconds\n\n// sendBeacon payload size limit (Phase 3)\nexport const MAX_BEACON_PAYLOAD_SIZE = 64 * 1024; // 64KB browser limit\n\n// Event fingerprint management\nexport const MAX_FINGERPRINTS = 1000; // Maximum fingerprints stored before cleanup\nexport const FINGERPRINT_CLEANUP_MULTIPLIER = 10; // Cleanup fingerprints older than 10x threshold\nexport const MAX_FINGERPRINTS_HARD_LIMIT = 2000; // Hard limit for aggressive cleanup\n\n// ============================================================================\n// BROWSER & HTML\n// ============================================================================\n\nexport const HTML_DATA_ATTR_PREFIX = 'data-tlog';\n\n// Interactive element selectors for click tracking\nexport const INTERACTIVE_SELECTORS = [\n 'button',\n 'a',\n 'input[type=\"button\"]',\n 'input[type=\"submit\"]',\n 'input[type=\"reset\"]',\n 'input[type=\"checkbox\"]',\n 'input[type=\"radio\"]',\n 'select',\n 'textarea',\n '[role=\"button\"]',\n '[role=\"link\"]',\n '[role=\"tab\"]',\n '[role=\"menuitem\"]',\n '[role=\"option\"]',\n '[role=\"checkbox\"]',\n '[role=\"radio\"]',\n '[role=\"switch\"]',\n '[routerLink]',\n '[ng-click]',\n '[data-action]',\n '[data-click]',\n '[data-navigate]',\n '[data-toggle]',\n '[onclick]',\n '.btn',\n '.button',\n '.clickable',\n '.nav-link',\n '.menu-item',\n '[data-testid]',\n '[tabindex=\"0\"]',\n] as const;\n\n// UTM parameters for tracking\nexport const UTM_PARAMS = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content'];\n\n// Default sensitive query parameters to remove from URLs (privacy protection)\nexport const DEFAULT_SENSITIVE_QUERY_PARAMS = [\n 'token',\n 'auth',\n 'key',\n 'session',\n 'reset',\n 'password',\n 'api_key',\n 'apikey',\n 'secret',\n 'access_token',\n 'refresh_token',\n 'verification',\n 'code',\n 'otp',\n] as const;\n\n// ============================================================================\n// ============================================================================\n// INITIALIZATION\n// ============================================================================\n\nexport const INITIALIZATION_MAX_CONCURRENT_RETRIES = 20;\nexport const INITIALIZATION_CONCURRENT_RETRY_DELAY_MS = 50;\nexport const INITIALIZATION_TIMEOUT_MS = 10000;\n\n// ============================================================================\n// SESSION MANAGEMENT\n// ============================================================================\n\nexport const SESSION_SYNC_TIMEOUT_MS = 2000;\nexport const SESSION_MAX_RETRY_ATTEMPTS = 3;\nexport const SESSION_CLEANUP_DELAY_MS = 100;\n\n// Cross-tab coordination\nexport const CROSS_TAB_INITIALIZATION_LOCK_TIMEOUT_MS = 5000;\nexport const TAB_HEARTBEAT_INTERVAL_MS = 5000; // 5 seconds\nexport const TAB_ELECTION_TIMEOUT_MS = 2000; // 2 seconds\nexport const TAB_CLEANUP_DELAY_MS = 1000; // 1 second\n\n// Session recovery\nexport const SESSION_RECOVERY_WINDOW_MULTIPLIER = 2; // 2x session timeout\nexport const MAX_SESSION_RECOVERY_ATTEMPTS = 3;\nexport const MAX_SESSION_RECOVERY_WINDOW_MS = 24 * 60 * 60 * 1000; // 24 hours max\nexport const MIN_SESSION_RECOVERY_WINDOW_MS = 2 * 60 * 1000; // 2 minutes minimum\n\n// ============================================================================\n// SCROLL SUPPRESSION\n// ============================================================================\n\nexport const SCROLL_SUPPRESS_MULTIPLIER = 2;\n\n// ============================================================================\n// NETWORK TIMING\n// ============================================================================\n\nexport const RATE_LIMIT_INTERVAL = 1000; // 1 second\n\n// ============================================================================\n// VALIDATION\n// ============================================================================\n\n// Validation error messages - standardized across all layers\nexport const VALIDATION_MESSAGES = {\n MISSING_PROJECT_ID: 'Project ID is required',\n PROJECT_ID_EMPTY_AFTER_TRIM: 'Project ID is required',\n INVALID_SESSION_TIMEOUT: `Session timeout must be between ${MIN_SESSION_TIMEOUT_MS}ms (30 seconds) and ${MAX_SESSION_TIMEOUT_MS}ms (24 hours)`,\n INVALID_SAMPLING_RATE: 'Sampling rate must be between 0 and 1',\n INVALID_ERROR_SAMPLING_RATE: 'Error sampling must be between 0 and 1',\n INVALID_TRACELOG_PROJECT_ID: 'TraceLog project ID is required when integration is enabled',\n INVALID_CUSTOM_API_URL: 'Custom API URL is required when integration is enabled',\n INVALID_GOOGLE_ANALYTICS_ID: 'Google Analytics measurement ID is required when integration is enabled',\n INVALID_SCROLL_CONTAINER_SELECTORS: 'Scroll container selectors must be valid CSS selectors',\n INVALID_GLOBAL_METADATA: 'Global metadata must be an object',\n INVALID_SENSITIVE_QUERY_PARAMS: 'Sensitive query params must be an array of strings',\n INVALID_PRIMARY_SCROLL_SELECTOR: 'Primary scroll selector must be a non-empty string',\n INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX: 'Invalid CSS selector syntax for primaryScrollSelector',\n INVALID_PAGE_VIEW_THROTTLE: 'Page view throttle must be a non-negative number',\n INVALID_CLICK_THROTTLE: 'Click throttle must be a non-negative number',\n INVALID_MAX_SAME_EVENT_PER_MINUTE: 'Max same event per minute must be a positive number',\n INVALID_VIEWPORT_CONFIG: 'Viewport config must be an object',\n INVALID_VIEWPORT_ELEMENTS: 'Viewport elements must be a non-empty array',\n INVALID_VIEWPORT_ELEMENT: 'Each viewport element must have a valid selector string',\n INVALID_VIEWPORT_ELEMENT_ID: 'Viewport element id must be a non-empty string',\n INVALID_VIEWPORT_ELEMENT_NAME: 'Viewport element name must be a non-empty string',\n INVALID_VIEWPORT_THRESHOLD: 'Viewport threshold must be a number between 0 and 1',\n INVALID_VIEWPORT_MIN_DWELL_TIME: 'Viewport minDwellTime must be a non-negative number',\n INVALID_VIEWPORT_COOLDOWN_PERIOD: 'Viewport cooldownPeriod must be a non-negative number',\n INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS: 'Viewport maxTrackedElements must be a positive number',\n} as const;\n\n// ============================================================================\n// SECURITY\n// ============================================================================\n\n// XSS protection patterns\nexport const XSS_PATTERNS = [\n /<script\\b[^<]*(?:(?!<\\/script>)<[^<]*)*<\\/script>/gi,\n /javascript:/gi,\n /on\\w+\\s*=/gi,\n /<iframe\\b[^<]*(?:(?!<\\/iframe>)<[^<]*)*<\\/iframe>/gi,\n /<embed\\b[^>]*>/gi,\n /<object\\b[^<]*(?:(?!<\\/object>)<[^<]*)*<\\/object>/gi,\n] as const;\n","import { MetadataType } from './common.types';\nimport { ViewportConfig } from './viewport.types';\n\nexport interface Config {\n /** Session inactivity timeout in milliseconds. @default 900000 */\n sessionTimeout?: number;\n /** Metadata appended to every tracked event. */\n globalMetadata?: Record<string, MetadataType>;\n /** Query parameters to remove before tracking URLs. */\n sensitiveQueryParams?: string[];\n /** Error event sampling rate between 0 and 1. @default 1 */\n errorSampling?: number;\n /** Event sampling rate between 0 and 1. @default 1 */\n samplingRate?: number;\n /** CSS selector to manually override primary scroll container detection. */\n primaryScrollSelector?: string;\n /** Viewport visibility tracking configuration. */\n viewport?: ViewportConfig;\n /** Page view throttle duration in milliseconds to prevent rapid navigation spam. @default 1000 */\n pageViewThrottleMs?: number;\n /** Click throttle duration in milliseconds to prevent double-clicks and rapid spam. @default 300 */\n clickThrottleMs?: number;\n /** Maximum number of same custom event name allowed per minute to prevent infinite loops. @default 60 */\n maxSameEventPerMinute?: number;\n /** Optional configuration for third-party integrations. */\n integrations?: {\n /** TraceLog integration options. */\n tracelog?: {\n /** Required project ID TraceLog SaaS integration. */\n projectId: string;\n };\n /** Custom integration options. */\n custom?: {\n /** Endpoint for collecting events. */\n collectApiUrl: string;\n /** Allow HTTP URLs (not recommended for production). @default false */\n allowHttp?: boolean;\n };\n /** Google Analytics integration options. */\n googleAnalytics?: {\n /** Required measurement ID for Google Analytics. */\n measurementId: string;\n };\n };\n}\n\nexport enum SpecialApiUrl {\n Localhost = 'localhost:8080',\n Fail = 'localhost:9999',\n}\n","export enum DeviceType {\n Mobile = 'mobile',\n Tablet = 'tablet',\n Desktop = 'desktop',\n Unknown = 'unknown',\n}\n","import { EventData } from './event.types';\nimport { EventsQueue } from './queue.types';\n\nexport type EmitterCallback<T = any> = (data: T) => void;\n\nexport enum EmitterEvent {\n EVENT = 'event',\n QUEUE = 'queue',\n}\n\nexport interface EmitterMap {\n [EmitterEvent.EVENT]: EventData;\n [EmitterEvent.QUEUE]: EventsQueue;\n}\n","/**\n * Custom error types for TraceLog\n */\n\n/**\n * Represents a permanent HTTP error (4xx) that should not be retried\n * Examples: 400 Bad Request, 403 Forbidden, 404 Not Found\n */\nexport class PermanentError extends Error {\n constructor(\n message: string,\n public readonly statusCode?: number,\n ) {\n super(message);\n this.name = 'PermanentError';\n\n // Maintain proper stack trace for where our error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, PermanentError);\n }\n }\n}\n","import { MetadataType } from './common.types';\nimport { SessionEndReason } from './session.types';\n\n/**\n * Coordinate information from a click event\n * Includes absolute and relative positioning\n */\nexport type ClickCoordinates = Pick<ClickData, 'x' | 'y' | 'relativeX' | 'relativeY'>;\n\n/**\n * Web performance metric types tracked by the library\n * - LCP: Largest Contentful Paint\n * - CLS: Cumulative Layout Shift\n * - INP: Interaction to Next Paint\n * - FCP: First Contentful Paint\n * - TTFB: Time to First Byte\n * - LONG_TASK: Tasks exceeding 50ms\n */\nexport type WebVitalType = 'LCP' | 'CLS' | 'INP' | 'FCP' | 'TTFB' | 'LONG_TASK';\n\n/**\n * Core event types tracked by TraceLog\n */\nexport enum EventType {\n /** Page navigation and view tracking */\n PAGE_VIEW = 'page_view',\n /** User click interactions */\n CLICK = 'click',\n /** Scroll depth and behavior */\n SCROLL = 'scroll',\n /** Session initialization */\n SESSION_START = 'session_start',\n /** Session termination */\n SESSION_END = 'session_end',\n /** Custom business events */\n CUSTOM = 'custom',\n /** Performance metrics */\n WEB_VITALS = 'web_vitals',\n /** JavaScript errors and rejections */\n ERROR = 'error',\n /** Element visibility tracking */\n VIEWPORT_VISIBLE = 'viewport_visible',\n}\n\n/**\n * Scroll direction indicators\n */\nexport enum ScrollDirection {\n /** Scrolling upward */\n UP = 'up',\n /** Scrolling downward */\n DOWN = 'down',\n}\n\n/**\n * JavaScript error classification\n */\nexport enum ErrorType {\n /** Runtime JavaScript errors */\n JS_ERROR = 'js_error',\n /** Unhandled promise rejections */\n PROMISE_REJECTION = 'promise_rejection',\n}\n\n/**\n * Scroll event data captured during user scrolling\n */\nexport interface ScrollData {\n /** Current scroll depth as percentage (0-100) */\n depth: number;\n /** Direction of scroll movement */\n direction: ScrollDirection;\n /** CSS selector of the scrolled container */\n container_selector: string;\n /** Whether this is the primary viewport scroll */\n is_primary: boolean;\n /** Scroll velocity in pixels per second */\n velocity: number;\n /** Maximum scroll depth reached during session (0-100) */\n max_depth_reached: number;\n}\n\n/**\n * Click event data capturing user interaction details\n */\nexport interface ClickData {\n /** Absolute X coordinate in viewport (pixels) */\n x: number;\n /** Absolute Y coordinate in viewport (pixels) */\n y: number;\n /** Relative X position within element (0-1) */\n relativeX: number;\n /** Relative Y position within element (0-1) */\n relativeY: number;\n /** Element ID attribute */\n id?: string;\n /** Element class attribute */\n class?: string;\n /** HTML tag name */\n tag?: string;\n /** Element text content (truncated) */\n text?: string;\n /** Link href for anchor elements */\n href?: string;\n /** Element title attribute */\n title?: string;\n /** Image alt text for img elements */\n alt?: string;\n /** ARIA role attribute */\n role?: string;\n /** ARIA label attribute */\n ariaLabel?: string;\n /** Custom data attributes (data-*) */\n dataAttributes?: Record<string, string>;\n}\n\n/**\n * Element data for specialized click tracking\n * Used for form inputs and interactive elements\n */\nexport interface ClickTrackingElementData {\n /** DOM element being tracked */\n element: HTMLElement;\n /** Descriptive name for the element */\n name: string;\n /** Element value (for inputs) */\n value?: string;\n}\n\n/**\n * Custom event data for business-specific tracking\n */\nexport interface CustomEventData {\n /** Event name identifier */\n name: string;\n /** Additional event metadata */\n metadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n}\n\n/**\n * Web performance metrics data\n */\nexport interface WebVitalsData {\n /** Type of performance metric */\n type: WebVitalType;\n /** Metric value (varies by type) */\n value: number;\n}\n\n/**\n * JavaScript error details\n */\nexport interface ErrorData {\n /** Error classification */\n type: ErrorType;\n /** Error message text */\n message: string;\n /** Source file where error occurred */\n filename?: string;\n /** Line number in source file */\n line?: number;\n /** Column number in source file */\n column?: number;\n}\n\n/**\n * UTM campaign tracking parameters\n */\nexport interface UTM {\n /** Campaign source (e.g., google, newsletter) */\n source?: string;\n /** Campaign medium (e.g., cpc, email) */\n medium?: string;\n /** Campaign name identifier */\n campaign?: string;\n /** Campaign search term */\n term?: string;\n /** Campaign content variation */\n content?: string;\n}\n\n/**\n * Page view navigation data\n */\nexport interface PageViewData {\n /** Previous page URL */\n referrer?: string;\n /** Page title from document */\n title?: string;\n /** URL pathname */\n pathname?: string;\n /** URL query string */\n search?: string;\n /** URL hash fragment */\n hash?: string;\n}\n\n/**\n * Data captured when element becomes visible\n */\nexport interface ViewportEventData {\n /** CSS selector that matched the element */\n selector: string;\n /** Optional unique identifier for analytics (if configured) */\n id?: string;\n /** Optional human-readable name (if configured) */\n name?: string;\n /** Actual time (ms) element was visible before event fired */\n dwellTime: number;\n /** Actual visibility ratio when event fired (0-1) */\n visibilityRatio: number;\n}\n\n/**\n * Complete event data structure\n * All events share base properties with type-specific data\n */\nexport interface EventData {\n /** Unique event identifier */\n id: string;\n /** Event type classification */\n type: EventType;\n /** Current page URL where event occurred */\n page_url: string;\n /** Unix timestamp (milliseconds) */\n timestamp: number;\n /** HTTP referrer header */\n referrer?: string;\n /** Previous page URL for navigation events */\n from_page_url?: string;\n /** Scroll event details (when type is SCROLL) */\n scroll_data?: ScrollData;\n /** Click event details (when type is CLICK) */\n click_data?: ClickData;\n /** Custom event details (when type is CUSTOM) */\n custom_event?: CustomEventData;\n /** Performance metrics (when type is WEB_VITALS) */\n web_vitals?: WebVitalsData;\n /** Page view details (when type is PAGE_VIEW) */\n page_view?: PageViewData;\n /** Session termination reason (when type is SESSION_END) */\n session_end_reason?: SessionEndReason;\n /** Error details (when type is ERROR) */\n error_data?: ErrorData;\n /** Viewport visibility details (when type is VIEWPORT_VISIBLE) */\n viewport_data?: ViewportEventData;\n /** Campaign tracking parameters */\n utm?: UTM;\n}\n","/**\n * App modes for the TraceLog Library\n */\nexport enum Mode {\n QA = 'qa',\n}\n","import { EventData, EventType, ScrollData } from './event.types';\n\nexport type PrimaryScrollEvent = EventData & {\n type: EventType.SCROLL;\n scroll_data: ScrollData & { is_primary: true };\n};\n\nexport type SecondaryScrollEvent = EventData & {\n type: EventType.SCROLL;\n scroll_data: ScrollData & { is_primary: false };\n};\n\nexport function isPrimaryScrollEvent(event: EventData): event is PrimaryScrollEvent {\n return (\n event.type === EventType.SCROLL && 'scroll_data' in event && (event.scroll_data as ScrollData).is_primary === true\n );\n}\n\nexport function isSecondaryScrollEvent(event: EventData): event is SecondaryScrollEvent {\n return (\n event.type === EventType.SCROLL && 'scroll_data' in event && (event.scroll_data as ScrollData).is_primary === false\n );\n}\n","/**\n * Custom error classes for TraceLog validation errors\n * Provides better error handling and consistency across validation layers\n */\n\n/**\n * Base class for all TraceLog validation errors\n */\nexport abstract class TraceLogValidationError extends Error {\n constructor(\n message: string,\n public readonly errorCode: string,\n public readonly layer: 'config' | 'app' | 'runtime',\n ) {\n super(message);\n this.name = this.constructor.name;\n\n // Maintains proper stack trace for where error was thrown (only available on V8)\n if (Error.captureStackTrace) {\n Error.captureStackTrace(this, this.constructor);\n }\n }\n}\n\n/**\n * Thrown when app configuration validation fails\n */\nexport class AppConfigValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'APP_CONFIG_INVALID', layer);\n }\n}\n\n/**\n * Thrown when session timeout validation fails\n */\nexport class SessionTimeoutValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SESSION_TIMEOUT_INVALID', layer);\n }\n}\n\n/**\n * Thrown when sampling rate validation fails\n */\nexport class SamplingRateValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'SAMPLING_RATE_INVALID', layer);\n }\n}\n\n/**\n * Thrown when integrations validation fails\n */\nexport class IntegrationValidationError extends TraceLogValidationError {\n constructor(message: string, layer: 'config' | 'app' | 'runtime' = 'config') {\n super(message, 'INTEGRATION_INVALID', layer);\n }\n}\n\n/**\n * Thrown when initialization exceeds the maximum allowed timeout\n */\nexport class InitializationTimeoutError extends TraceLogValidationError {\n constructor(\n message: string,\n public readonly timeoutMs: number,\n layer: 'config' | 'app' | 'runtime' = 'runtime',\n ) {\n super(message, 'INITIALIZATION_TIMEOUT', layer);\n }\n}\n","export const formatLogMsg = (msg: string, error?: unknown): string => {\n if (error) {\n // In production, sanitize error messages to avoid exposing sensitive paths\n if (process.env.NODE_ENV !== 'development' && error instanceof Error) {\n // Remove file paths and line numbers from error messages\n const sanitizedMessage = error.message.replace(/\\s+at\\s+.*$/gm, '').replace(/\\(.*?:\\d+:\\d+\\)/g, '');\n return `[TraceLog] ${msg}: ${sanitizedMessage}`;\n }\n return `[TraceLog] ${msg}: ${error instanceof Error ? error.message : 'Unknown error'}`;\n }\n\n return `[TraceLog] ${msg}`;\n};\n\n/**\n * Safe logging utility that respects production environment\n *\n * @param type - Log level (info, warn, error, debug)\n * @param msg - Message to log\n * @param extra - Optional extra data\n *\n * Production behavior:\n * - debug: Never logged in production\n * - info: Only logged if showToClient=true\n * - warn: Always logged (important for debugging production issues)\n * - error: Always logged\n * - Stack traces are sanitized\n * - Data objects are sanitized\n */\nexport const log = (\n type: 'info' | 'warn' | 'error' | 'debug',\n msg: string,\n extra?: { error?: unknown; data?: Record<string, unknown>; showToClient?: boolean },\n): void => {\n const { error, data, showToClient = false } = extra ?? {};\n const formattedMsg = error ? formatLogMsg(msg, error) : `[TraceLog] ${msg}`;\n const method = type === 'error' ? 'error' : type === 'warn' ? 'warn' : 'log';\n\n // Production logging strategy:\n // - Development: Log everything\n // - Production:\n // - debug: never logged\n // - info: only if showToClient=true\n // - warn: always logged (critical for debugging)\n // - error: always logged\n const isProduction = process.env.NODE_ENV !== 'development';\n\n if (isProduction) {\n // Never log debug in production\n if (type === 'debug') {\n return;\n }\n\n // Log info only if explicitly flagged\n if (type === 'info' && !showToClient) {\n return;\n }\n\n // warn and error always logged in production\n }\n\n // In production, sanitize data to avoid exposing sensitive information\n if (isProduction && data !== undefined) {\n const sanitizedData = sanitizeLogData(data);\n console[method](formattedMsg, sanitizedData);\n } else if (data !== undefined) {\n console[method](formattedMsg, data);\n } else {\n console[method](formattedMsg);\n }\n};\n\n/**\n * Sanitizes log data in production to prevent sensitive information leakage\n * Simple approach: redact sensitive keys only\n */\nconst sanitizeLogData = (data: Record<string, unknown>): Record<string, unknown> => {\n const sanitized: Record<string, unknown> = {};\n const sensitiveKeys = ['token', 'password', 'secret', 'key', 'apikey', 'api_key', 'sessionid', 'session_id'];\n\n for (const [key, value] of Object.entries(data)) {\n const lowerKey = key.toLowerCase();\n\n // Redact sensitive keys\n if (sensitiveKeys.some((sensitiveKey) => lowerKey.includes(sensitiveKey))) {\n sanitized[key] = '[REDACTED]';\n } else {\n sanitized[key] = value;\n }\n }\n\n return sanitized;\n};\n","import { DeviceType } from '../../types/device.types';\nimport { log } from '../logging.utils';\n\nlet coarsePointerQuery: MediaQueryList | undefined;\nlet noHoverQuery: MediaQueryList | undefined;\n\nconst initMediaQueries = (): void => {\n if (typeof window !== 'undefined' && !coarsePointerQuery) {\n coarsePointerQuery = window.matchMedia('(pointer: coarse)');\n noHoverQuery = window.matchMedia('(hover: none)');\n }\n};\n\ninterface NavigatorWithUserAgentData extends Navigator {\n userAgentData?: {\n mobile: boolean;\n platform?: string;\n };\n}\n\n/**\n * Detects the device type based on screen size, user agent, and browser capabilities\n * @returns The detected device type\n */\nexport const getDeviceType = (): DeviceType => {\n try {\n const nav = navigator as NavigatorWithUserAgentData;\n\n if (nav.userAgentData && typeof nav.userAgentData.mobile === 'boolean') {\n if (nav.userAgentData.platform && /ipad|tablet/i.test(nav.userAgentData.platform)) {\n return DeviceType.Tablet;\n }\n\n const result = nav.userAgentData.mobile ? DeviceType.Mobile : DeviceType.Desktop;\n return result;\n }\n\n initMediaQueries();\n\n const width = window.innerWidth;\n const hasCoarsePointer = coarsePointerQuery?.matches ?? false;\n const hasNoHover = noHoverQuery?.matches ?? false;\n const hasTouchSupport = 'ontouchstart' in window || navigator.maxTouchPoints > 0;\n const ua = navigator.userAgent.toLowerCase();\n const isMobileUA = /mobile|android|iphone|ipod|blackberry|iemobile|opera mini/.test(ua);\n const isTabletUA = /tablet|ipad|android(?!.*mobile)/.test(ua);\n\n if (width <= 767 || (isMobileUA && hasTouchSupport)) {\n return DeviceType.Mobile;\n }\n\n if ((width >= 768 && width <= 1024) || isTabletUA || (hasCoarsePointer && hasNoHover && hasTouchSupport)) {\n return DeviceType.Tablet;\n }\n\n return DeviceType.Desktop;\n } catch (error) {\n log('warn', 'Device detection failed, defaulting to desktop', { error });\n\n return DeviceType.Desktop;\n }\n};\n","export const STORAGE_BASE_KEY = 'tlog';\nexport const QA_MODE_KEY = `${STORAGE_BASE_KEY}:qa_mode`;\nexport const USER_ID_KEY = `${STORAGE_BASE_KEY}:uid`;\n\nexport const QUEUE_KEY = (id: string): string => (id ? `${STORAGE_BASE_KEY}:${id}:queue` : `${STORAGE_BASE_KEY}:queue`);\nexport const SESSION_STORAGE_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:session` : `${STORAGE_BASE_KEY}:session`;\n\n// Cross-tab session management storage keys\nexport const CROSS_TAB_SESSION_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:cross_tab_session` : `${STORAGE_BASE_KEY}:cross_tab_session`;\nexport const TAB_INFO_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:tab_info` : `${STORAGE_BASE_KEY}:tab_info`;\n\nexport const TAB_SPECIFIC_INFO_KEY = (projectId: string, tabId: string): string =>\n `${STORAGE_BASE_KEY}:${projectId}:tab:${tabId}:info`;\nexport const SESSION_RECOVERY_KEY = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:recovery` : `${STORAGE_BASE_KEY}:recovery`;\n\n// BroadcastChannel name for cross-tab communication\nexport const BROADCAST_CHANNEL_NAME = (id: string): string =>\n id ? `${STORAGE_BASE_KEY}:${id}:broadcast` : `${STORAGE_BASE_KEY}:broadcast`;\n","/**\n * Performance monitoring and web vitals constants for TraceLog\n * Centralizes thresholds and configuration for performance tracking\n */\n\nimport { WebVitalType } from '../types';\n\n// ============================================================================\n// WEB VITALS THRESHOLDS\n// ============================================================================\n\n/**\n * Web Vitals thresholds in milliseconds (except CLS which is unitless)\n * These define the minimum values required to report a web vital metric\n *\n * Based on Core Web Vitals standards:\n * - LCP (Largest Contentful Paint): 4000ms threshold (poor threshold)\n * - FCP (First Contentful Paint): 1800ms threshold (good threshold)\n * - CLS (Cumulative Layout Shift): 0.25 threshold (unitless, needs improvement threshold)\n * - INP (Interaction to Next Paint): 200ms threshold (good threshold)\n * - TTFB (Time to First Byte): 800ms threshold (good/needs improvement boundary, aligned with Web Vitals standard)\n * - LONG_TASK: 50ms threshold for long task detection\n */\nexport const WEB_VITALS_THRESHOLDS: Record<WebVitalType, number> = {\n LCP: 4000,\n FCP: 1800,\n CLS: 0.25,\n INP: 200,\n TTFB: 800,\n LONG_TASK: 50,\n} as const;\n\n// ============================================================================\n// PERFORMANCE MONITORING LIMITS\n// ============================================================================\n\n/**\n * Long task throttling interval in milliseconds\n * Prevents excessive long task events from being sent\n */\nexport const LONG_TASK_THROTTLE_MS = 1000;\n\n/**\n * Maximum number of navigation history entries to keep in memory\n * Prevents unbounded growth of reportedByNav Map in long-running SPAs\n * Uses FIFO eviction when limit is exceeded\n */\nexport const MAX_NAVIGATION_HISTORY = 50;\n\n/**\n * Precision for performance metric values\n * All performance metrics are rounded to 2 decimal places\n */\nexport const PERFORMANCE_PRECISION_DECIMALS = 2 as const;\n","/**\n * Error handling and PII sanitization constants for TraceLog\n * Centralizes patterns and limits for error tracking and data protection\n */\n\n// ============================================================================\n// PII SANITIZATION PATTERNS\n// ============================================================================\n\n/**\n * Regular expressions for detecting and sanitizing Personally Identifiable Information (PII)\n * These patterns are used to replace sensitive information with [REDACTED] in error messages\n */\nexport const PII_PATTERNS = [\n // Email addresses\n /\\b[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\\.[A-Z|a-z]{2,}\\b/gi,\n\n // US Phone numbers (various formats)\n /\\b\\d{3}[-.]?\\d{3}[-.]?\\d{4}\\b/g,\n\n // Credit card numbers (16 digits with optional separators)\n /\\b\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/g,\n\n // IBAN (International Bank Account Number)\n /\\b[A-Z]{2}\\d{2}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}[-\\s]?\\d{4}\\b/gi,\n\n // API keys/tokens (sk_test_, sk_live_, pk_test_, pk_live_, etc.)\n /\\b[sp]k_(test|live)_[a-zA-Z0-9]{10,}\\b/gi,\n\n // Bearer tokens (JWT-like patterns - matches complete and partial tokens)\n /Bearer\\s+[A-Za-z0-9_-]+(?:\\.[A-Za-z0-9_-]+)?(?:\\.[A-Za-z0-9_-]+)?/gi,\n\n // Passwords in connection strings (protocol://user:password@host)\n /:\\/\\/[^:/]+:([^@]+)@/gi,\n] as const;\n\n// ============================================================================\n// ERROR TRACKING LIMITS\n// ============================================================================\n\n/**\n * Maximum length for error messages before truncation\n * Prevents extremely long error messages from consuming excessive storage\n */\nexport const MAX_ERROR_MESSAGE_LENGTH = 500;\n\n/**\n * Time window for error suppression in milliseconds\n * Prevents duplicate errors from flooding the system within this timeframe\n */\nexport const ERROR_SUPPRESSION_WINDOW_MS = 5_000; // 5 seconds\n\n/**\n * Maximum number of unique errors to track for suppression\n * Prevents memory usage from growing indefinitely\n */\nexport const MAX_TRACKED_ERRORS = 50;\n\n/**\n * Hard limit for error tracking before aggressive cleanup\n * If this limit is exceeded, the entire error map is cleared\n */\nexport const MAX_TRACKED_ERRORS_HARD_LIMIT = MAX_TRACKED_ERRORS * 2;\n\n// ============================================================================\n// ERROR SAMPLING\n// ============================================================================\n\n/**\n * Default error sampling rate\n * Controls what percentage of errors are actually reported\n */\nexport const DEFAULT_ERROR_SAMPLING_RATE = 1; // 100% of errors\n\n// ============================================================================\n// ERROR BURST DETECTION (Phase 3)\n// ============================================================================\n\n/**\n * Time window for error burst detection in milliseconds\n * Tracks unique errors within this window\n */\nexport const ERROR_BURST_WINDOW_MS = 1000; // 1 second\n\n/**\n * Maximum number of unique errors allowed in burst window\n * Exceeding this triggers a cooldown period\n */\nexport const ERROR_BURST_THRESHOLD = 10; // 10 unique errors\n\n/**\n * Backoff period after burst detection in milliseconds\n * No errors will be tracked during this cooldown\n */\nexport const ERROR_BURST_BACKOFF_MS = 5000; // 5 seconds\n\n// ============================================================================\n// PERMANENT ERROR LOGGING\n// ============================================================================\n\n/**\n * Time window for throttling permanent error logs in milliseconds\n * Same error status codes are logged at most once per this window\n * Prevents console spam when backend repeatedly returns 4xx errors\n */\nexport const PERMANENT_ERROR_LOG_THROTTLE_MS = 60_000; // 1 minute\n","import { QA_MODE_KEY } from '../../constants';\nimport { log } from '../logging.utils';\n\nconst QA_MODE_PARAM = 'tlog_mode';\nconst QA_MODE_VALUE = 'qa';\n\n/**\n * Detects if QA mode should be active based on URL query parameter or sessionStorage\n *\n * Detection flow:\n * 1. Check if already active in sessionStorage\n * 2. Check for ?tlog_mode=qa query parameter\n * 3. If found in URL:\n * - Persist to sessionStorage\n * - Clean param from URL\n *\n * @returns True if QA mode is active, false otherwise\n */\nexport const detectQaMode = (): boolean => {\n const stored = sessionStorage.getItem(QA_MODE_KEY);\n\n if (stored === 'true') {\n return true;\n }\n\n const params = new URLSearchParams(window.location.search);\n const modeParam = params.get(QA_MODE_PARAM);\n const isQaMode = modeParam === QA_MODE_VALUE;\n\n if (isQaMode) {\n sessionStorage.setItem(QA_MODE_KEY, 'true');\n\n params.delete(QA_MODE_PARAM);\n\n const newSearch = params.toString();\n const newUrl = `${window.location.pathname}${newSearch ? '?' + newSearch : ''}${window.location.hash}`;\n\n try {\n window.history.replaceState({}, '', newUrl);\n } catch (error) {\n log('warn', 'History API not available, cannot replace URL', { error });\n }\n\n console.log(\n '%c[TraceLog] QA Mode ACTIVE',\n 'background: #ff9800; color: white; font-weight: bold; padding: 2px 8px; border-radius: 3px;',\n );\n }\n\n return isQaMode;\n};\n","import { UTM_PARAMS } from '../../constants';\nimport { UTM } from '../../types/event.types';\n\n/**\n * Extracts UTM parameters from the current URL\n * @returns UTM parameters object or undefined if none found\n */\nexport const getUTMParameters = (): UTM | undefined => {\n const urlParams = new URLSearchParams(window.location.search);\n const utmParams: Partial<Record<keyof UTM, string>> = {};\n\n UTM_PARAMS.forEach((param) => {\n const value = urlParams.get(param);\n\n if (value) {\n const key = param.split('utm_')[1] as keyof UTM;\n utmParams[key] = value;\n }\n });\n\n const result = Object.keys(utmParams).length ? utmParams : undefined;\n\n return result;\n};\n","/**\n * Generates a RFC4122 compliant UUID v4 using native crypto API with fallback\n * @returns A UUID string\n */\nexport const generateUUID = (): string => {\n // Use native crypto.randomUUID() if available (modern browsers)\n if (typeof crypto !== 'undefined' && crypto.randomUUID) {\n return crypto.randomUUID();\n }\n\n // Fallback for older browsers\n return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, (c) => {\n const r = (Math.random() * 16) | 0;\n const v = c === 'x' ? r : (r & 0x3) | 0x8;\n return v.toString(16);\n });\n};\n\n/**\n * Generates a unique event ID optimized for high-frequency event tracking\n *\n * Uses a simple hybrid approach:\n * - Timestamp for temporal ordering\n * - Random component for uniqueness across tabs/processes\n *\n * Format: {timestamp}-{random}\n * Example: \"1704067200000-a3f9c2b1\"\n *\n * @returns Unique event ID string\n */\nexport const generateEventId = (): string => {\n const timestamp = Date.now();\n\n // Generate 8 random hex chars (32 bits entropy)\n let random = '';\n try {\n if (typeof crypto !== 'undefined' && crypto.getRandomValues) {\n const bytes = crypto.getRandomValues(new Uint8Array(4));\n if (bytes) {\n random = Array.from(bytes, (b) => b.toString(16).padStart(2, '0')).join('');\n }\n }\n } catch {\n // crypto failed, use fallback\n }\n\n // Fallback to Math.random if crypto unavailable\n if (!random) {\n random = Math.floor(Math.random() * 0xffffffff)\n .toString(16)\n .padStart(8, '0');\n }\n\n return `${timestamp}-${random}`;\n};\n","import { Config } from '../../types';\nimport { DEFAULT_SENSITIVE_QUERY_PARAMS } from '../../constants';\nimport { log } from '../logging.utils';\n\n/**\n * Validates if a URL is valid and optionally allows HTTP URLs\n * @param url - The URL to validate\n * @param allowHttp - Whether to allow HTTP URLs (default: false)\n * @returns True if the URL is valid, false otherwise\n */\nconst isValidUrl = (url: string, allowHttp = false): boolean => {\n try {\n const parsed = new URL(url);\n const isHttps = parsed.protocol === 'https:';\n const isHttp = parsed.protocol === 'http:';\n\n return isHttps || (allowHttp && isHttp);\n } catch {\n return false;\n }\n};\n\n/**\n * Generates an API URL based on project ID and current domain\n * @param id - The project ID\n * @returns The generated API URL\n */\nexport const getCollectApiUrl = (config: Config): string => {\n if (config.integrations?.tracelog?.projectId) {\n try {\n const url = new URL(window.location.href);\n const host = url.hostname;\n\n if (!host || typeof host !== 'string') {\n throw new Error('Invalid hostname');\n }\n\n const parts = host.split('.');\n\n if (!parts || !Array.isArray(parts) || parts.length === 0 || (parts.length === 1 && parts[0] === '')) {\n throw new Error('Invalid hostname structure');\n }\n\n const projectId = config.integrations.tracelog.projectId;\n const cleanDomain = parts.slice(-2).join('.');\n\n if (!cleanDomain) {\n throw new Error('Invalid domain');\n }\n\n const collectApiUrl = `https://${projectId}.${cleanDomain}/collect`;\n const isValid = isValidUrl(collectApiUrl);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n } catch (error) {\n throw new Error(`Invalid URL configuration: ${error instanceof Error ? error.message : String(error)}`);\n }\n }\n\n const collectApiUrl = config.integrations?.custom?.collectApiUrl;\n\n if (collectApiUrl) {\n const allowHttp = config.integrations?.custom?.allowHttp ?? false;\n const isValid = isValidUrl(collectApiUrl, allowHttp);\n\n if (!isValid) {\n throw new Error('Invalid URL');\n }\n\n return collectApiUrl;\n }\n\n return '';\n};\n\n/**\n * Normalizes a URL by removing sensitive query parameters\n * Combines default sensitive parameters with custom ones provided by user\n * @param url - The URL to normalize\n * @param sensitiveQueryParams - Array of parameter names to remove (merged with defaults)\n * @returns The normalized URL\n */\nexport const normalizeUrl = (url: string, sensitiveQueryParams: string[] = []): string => {\n if (!url || typeof url !== 'string') {\n log('warn', 'Invalid URL provided to normalizeUrl', { data: { url: String(url) } });\n return url || '';\n }\n\n try {\n const urlObject = new URL(url);\n const searchParams = urlObject.searchParams;\n\n // Merge default sensitive params with user-provided ones (deduped via Set)\n const allSensitiveParams = [...new Set([...DEFAULT_SENSITIVE_QUERY_PARAMS, ...sensitiveQueryParams])];\n\n let hasChanged = false;\n const removedParams: string[] = [];\n\n allSensitiveParams.forEach((param) => {\n if (searchParams.has(param)) {\n searchParams.delete(param);\n hasChanged = true;\n removedParams.push(param);\n }\n });\n\n if (!hasChanged && url.includes('?')) {\n return url;\n }\n\n urlObject.search = searchParams.toString();\n const result = urlObject.toString();\n\n return result;\n } catch (error) {\n const urlPreview = url && typeof url === 'string' ? url.slice(0, 100) : String(url);\n log('warn', 'URL normalization failed, returning original', { error, data: { url: urlPreview } });\n\n return url;\n }\n};\n","import {\n MAX_ARRAY_LENGTH,\n MAX_OBJECT_DEPTH,\n MAX_STRING_LENGTH,\n MAX_NESTED_OBJECT_KEYS,\n XSS_PATTERNS,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\n\n/**\n * Sanitizes a string value to prevent XSS attacks\n * @param value - The string to sanitize\n * @returns The sanitized string\n */\nexport const sanitizeString = (value: string): string => {\n if (!value || typeof value !== 'string' || value.trim().length === 0) {\n return '';\n }\n\n let sanitized = value;\n\n // Limit string length\n if (value.length > MAX_STRING_LENGTH) {\n sanitized = value.slice(0, Math.max(0, MAX_STRING_LENGTH));\n // Silent truncation - this is expected behavior for long strings\n }\n\n // Remove potential XSS patterns\n let xssPatternMatches = 0;\n for (const pattern of XSS_PATTERNS) {\n const beforeReplace = sanitized;\n sanitized = sanitized.replace(pattern, '');\n if (beforeReplace !== sanitized) {\n xssPatternMatches++;\n }\n }\n\n if (xssPatternMatches > 0) {\n log('warn', 'XSS patterns detected and removed', {\n data: {\n patternMatches: xssPatternMatches,\n originalValue: value.slice(0, 100),\n },\n });\n }\n\n // Basic HTML entity encoding for critical characters\n sanitized = sanitized\n .replaceAll('&', '&amp;')\n .replaceAll('<', '&lt;')\n .replaceAll('>', '&gt;')\n .replaceAll('\"', '&quot;')\n .replaceAll(\"'\", '&#x27;')\n .replaceAll('/', '&#x2F;');\n\n const result = sanitized.trim();\n\n return result;\n};\n\n/**\n * Sanitizes any value recursively with depth protection\n * @param value - The value to sanitize\n * @param depth - Current recursion depth\n * @returns The sanitized value\n */\nconst sanitizeValue = (value: unknown, depth = 0): unknown => {\n // Prevent infinite recursion\n if (depth > MAX_OBJECT_DEPTH) {\n // Silent depth limit - prevents stack overflow\n return null;\n }\n\n if (value === null || value === undefined) {\n return null;\n }\n\n if (typeof value === 'string') {\n return sanitizeString(value);\n }\n\n if (typeof value === 'number') {\n if (!Number.isFinite(value) || value < -Number.MAX_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {\n // Silent normalization - invalid numbers become 0\n return 0;\n }\n\n return value;\n }\n\n if (typeof value === 'boolean') {\n return value;\n }\n\n if (Array.isArray(value)) {\n const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);\n\n // Silent array length limit\n const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);\n\n // Silent filter - empty arrays are valid results\n return sanitizedArray;\n }\n\n if (typeof value === 'object') {\n const sanitizedObject: Record<string, unknown> = {};\n const entries = Object.entries(value);\n const limitedEntries = entries.slice(0, MAX_NESTED_OBJECT_KEYS);\n\n // Silent object keys limit\n for (const [key, value_] of limitedEntries) {\n const sanitizedKey = sanitizeString(key);\n\n if (sanitizedKey) {\n const sanitizedValue = sanitizeValue(value_, depth + 1);\n\n if (sanitizedValue !== null) {\n sanitizedObject[sanitizedKey] = sanitizedValue;\n }\n }\n }\n\n return sanitizedObject;\n }\n\n return null;\n};\n\n/**\n * Sanitizes user metadata for custom events\n * @param metadata - The metadata to sanitize\n * @returns The sanitized metadata\n */\nexport const sanitizeMetadata = (metadata: unknown): Record<string, MetadataType> => {\n if (typeof metadata !== 'object' || metadata === null) {\n return {};\n }\n\n try {\n const sanitized = sanitizeValue(metadata);\n const result =\n typeof sanitized === 'object' && sanitized !== null ? (sanitized as Record<string, MetadataType>) : {};\n\n return result;\n } catch (error) {\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] Metadata sanitization failed: ${errorMessage}`);\n }\n};\n","import {\n MAX_SESSION_TIMEOUT_MS,\n MIN_SESSION_TIMEOUT_MS,\n DEFAULT_SESSION_TIMEOUT,\n DEFAULT_SAMPLING_RATE,\n VALIDATION_MESSAGES,\n DEFAULT_PAGE_VIEW_THROTTLE_MS,\n DEFAULT_CLICK_THROTTLE_MS,\n MAX_SAME_EVENT_PER_MINUTE,\n DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n DEFAULT_VISIBILITY_TIMEOUT_MS,\n} from '../../constants';\nimport { DEFAULT_ERROR_SAMPLING_RATE } from '../../constants/error.constants';\nimport { Config } from '../../types';\nimport {\n AppConfigValidationError,\n SessionTimeoutValidationError,\n SamplingRateValidationError,\n IntegrationValidationError,\n} from '../../types/validation-error.types';\n\n/**\n * Validates the app configuration object (before normalization)\n * This validates the structure and basic types but allows for normalization afterward\n * @param config - The app configuration to validate\n * @throws {ProjectIdValidationError} If project ID validation fails\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAppConfig = (config?: Config): void => {\n if (config !== undefined && (config === null || typeof config !== 'object')) {\n throw new AppConfigValidationError('Configuration must be an object', 'config');\n }\n\n if (!config) {\n return;\n }\n\n if (config.sessionTimeout !== undefined) {\n if (\n typeof config.sessionTimeout !== 'number' ||\n config.sessionTimeout < MIN_SESSION_TIMEOUT_MS ||\n config.sessionTimeout > MAX_SESSION_TIMEOUT_MS\n ) {\n throw new SessionTimeoutValidationError(VALIDATION_MESSAGES.INVALID_SESSION_TIMEOUT, 'config');\n }\n }\n\n if (config.globalMetadata !== undefined) {\n if (typeof config.globalMetadata !== 'object' || config.globalMetadata === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_GLOBAL_METADATA, 'config');\n }\n }\n\n if (config.integrations) {\n validateIntegrations(config.integrations);\n }\n\n if (config.sensitiveQueryParams !== undefined) {\n if (!Array.isArray(config.sensitiveQueryParams)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_SENSITIVE_QUERY_PARAMS, 'config');\n }\n\n for (const param of config.sensitiveQueryParams) {\n if (typeof param !== 'string') {\n throw new AppConfigValidationError('All sensitive query params must be strings', 'config');\n }\n }\n }\n\n if (config.errorSampling !== undefined) {\n if (typeof config.errorSampling !== 'number' || config.errorSampling < 0 || config.errorSampling > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_ERROR_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.samplingRate !== undefined) {\n if (typeof config.samplingRate !== 'number' || config.samplingRate < 0 || config.samplingRate > 1) {\n throw new SamplingRateValidationError(VALIDATION_MESSAGES.INVALID_SAMPLING_RATE, 'config');\n }\n }\n\n if (config.primaryScrollSelector !== undefined) {\n if (typeof config.primaryScrollSelector !== 'string' || !config.primaryScrollSelector.trim()) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_PRIMARY_SCROLL_SELECTOR, 'config');\n }\n\n // Validate CSS selector syntax (skip for 'window' special value)\n if (config.primaryScrollSelector !== 'window') {\n try {\n document.querySelector(config.primaryScrollSelector);\n } catch {\n throw new AppConfigValidationError(\n `${VALIDATION_MESSAGES.INVALID_PRIMARY_SCROLL_SELECTOR_SYNTAX}: \"${config.primaryScrollSelector}\"`,\n 'config',\n );\n }\n }\n }\n\n if (config.pageViewThrottleMs !== undefined) {\n if (typeof config.pageViewThrottleMs !== 'number' || config.pageViewThrottleMs < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_PAGE_VIEW_THROTTLE, 'config');\n }\n }\n\n if (config.clickThrottleMs !== undefined) {\n if (typeof config.clickThrottleMs !== 'number' || config.clickThrottleMs < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_CLICK_THROTTLE, 'config');\n }\n }\n\n if (config.maxSameEventPerMinute !== undefined) {\n if (typeof config.maxSameEventPerMinute !== 'number' || config.maxSameEventPerMinute <= 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_MAX_SAME_EVENT_PER_MINUTE, 'config');\n }\n }\n\n if (config.viewport !== undefined) {\n validateViewportConfig(config.viewport);\n }\n};\n\n/**\n * Validates viewport configuration\n * @param viewport - Viewport configuration to validate\n */\nconst validateViewportConfig = (viewport: Config['viewport']): void => {\n if (typeof viewport !== 'object' || viewport === null) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_CONFIG, 'config');\n }\n\n // Validate elements array\n if (!viewport.elements || !Array.isArray(viewport.elements)) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENTS, 'config');\n }\n\n if (viewport.elements.length === 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENTS, 'config');\n }\n\n // Track unique selectors to detect duplicates\n const uniqueSelectors = new Set<string>();\n\n // Validate each element\n for (const element of viewport.elements) {\n if (!element.selector || typeof element.selector !== 'string' || !element.selector.trim()) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT, 'config');\n }\n\n // Check for duplicate selectors\n const normalizedSelector = element.selector.trim();\n if (uniqueSelectors.has(normalizedSelector)) {\n throw new AppConfigValidationError(\n `Duplicate viewport selector found: \"${normalizedSelector}\". Each selector should appear only once.`,\n 'config',\n );\n }\n uniqueSelectors.add(normalizedSelector);\n\n if (element.id !== undefined && (typeof element.id !== 'string' || !element.id.trim())) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT_ID, 'config');\n }\n\n if (element.name !== undefined && (typeof element.name !== 'string' || !element.name.trim())) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_ELEMENT_NAME, 'config');\n }\n }\n\n // Validate threshold\n if (viewport.threshold !== undefined) {\n if (typeof viewport.threshold !== 'number' || viewport.threshold < 0 || viewport.threshold > 1) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_THRESHOLD, 'config');\n }\n }\n\n // Validate minDwellTime\n if (viewport.minDwellTime !== undefined) {\n if (typeof viewport.minDwellTime !== 'number' || viewport.minDwellTime < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_MIN_DWELL_TIME, 'config');\n }\n }\n\n // Validate cooldownPeriod\n if (viewport.cooldownPeriod !== undefined) {\n if (typeof viewport.cooldownPeriod !== 'number' || viewport.cooldownPeriod < 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_COOLDOWN_PERIOD, 'config');\n }\n }\n\n // Validate maxTrackedElements\n if (viewport.maxTrackedElements !== undefined) {\n if (typeof viewport.maxTrackedElements !== 'number' || viewport.maxTrackedElements <= 0) {\n throw new AppConfigValidationError(VALIDATION_MESSAGES.INVALID_VIEWPORT_MAX_TRACKED_ELEMENTS, 'config');\n }\n }\n};\n\n/**\n * Validates integrations configuration\n * @param integrations - Integrations configuration to validate\n */\nconst validateIntegrations = (integrations: Config['integrations']): void => {\n if (!integrations) {\n return;\n }\n\n if (integrations.tracelog) {\n if (\n !integrations.tracelog.projectId ||\n typeof integrations.tracelog.projectId !== 'string' ||\n integrations.tracelog.projectId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_TRACELOG_PROJECT_ID, 'config');\n }\n }\n\n if (integrations.custom) {\n if (\n !integrations.custom.collectApiUrl ||\n typeof integrations.custom.collectApiUrl !== 'string' ||\n integrations.custom.collectApiUrl.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_CUSTOM_API_URL, 'config');\n }\n\n if (integrations.custom.allowHttp !== undefined && typeof integrations.custom.allowHttp !== 'boolean') {\n throw new IntegrationValidationError('allowHttp must be a boolean', 'config');\n }\n\n const collectApiUrl = integrations.custom.collectApiUrl.trim();\n\n if (!collectApiUrl.startsWith('http://') && !collectApiUrl.startsWith('https://')) {\n throw new IntegrationValidationError('Custom API URL must start with \"http://\" or \"https://\"', 'config');\n }\n\n const allowHttp = integrations.custom.allowHttp ?? false;\n\n if (!allowHttp && collectApiUrl.startsWith('http://')) {\n throw new IntegrationValidationError(\n 'Custom API URL must use HTTPS in production. Set allowHttp: true in integration config to allow HTTP (not recommended)',\n 'config',\n );\n }\n }\n\n if (integrations.googleAnalytics) {\n if (\n !integrations.googleAnalytics.measurementId ||\n typeof integrations.googleAnalytics.measurementId !== 'string' ||\n integrations.googleAnalytics.measurementId.trim() === ''\n ) {\n throw new IntegrationValidationError(VALIDATION_MESSAGES.INVALID_GOOGLE_ANALYTICS_ID, 'config');\n }\n\n const measurementId = integrations.googleAnalytics.measurementId.trim();\n\n if (!measurementId.match(/^(G-|UA-)/)) {\n throw new IntegrationValidationError('Google Analytics measurement ID must start with \"G-\" or \"UA-\"', 'config');\n }\n }\n};\n\n/**\n * Validates and normalizes the app configuration\n * This is the primary validation entry point that ensures consistent behavior\n * @param config - The app configuration to validate and normalize\n * @returns The normalized configuration\n * @throws {ProjectIdValidationError} If project ID validation fails after normalization\n * @throws {AppConfigValidationError} If other configuration validation fails\n */\nexport const validateAndNormalizeConfig = (config?: Config): Config => {\n validateAppConfig(config);\n\n const normalizedConfig: Config = {\n ...(config ?? {}),\n sessionTimeout: config?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT,\n globalMetadata: config?.globalMetadata ?? {},\n sensitiveQueryParams: config?.sensitiveQueryParams ?? [],\n errorSampling: config?.errorSampling ?? DEFAULT_ERROR_SAMPLING_RATE,\n samplingRate: config?.samplingRate ?? DEFAULT_SAMPLING_RATE,\n pageViewThrottleMs: config?.pageViewThrottleMs ?? DEFAULT_PAGE_VIEW_THROTTLE_MS,\n clickThrottleMs: config?.clickThrottleMs ?? DEFAULT_CLICK_THROTTLE_MS,\n maxSameEventPerMinute: config?.maxSameEventPerMinute ?? MAX_SAME_EVENT_PER_MINUTE,\n };\n\n // Normalize integrations\n if (normalizedConfig.integrations?.custom) {\n normalizedConfig.integrations.custom = {\n ...normalizedConfig.integrations.custom,\n allowHttp: normalizedConfig.integrations.custom.allowHttp ?? false,\n };\n }\n\n // Normalize viewport config\n if (normalizedConfig.viewport) {\n normalizedConfig.viewport = {\n ...normalizedConfig.viewport,\n threshold: normalizedConfig.viewport.threshold ?? 0.5,\n minDwellTime: normalizedConfig.viewport.minDwellTime ?? DEFAULT_VISIBILITY_TIMEOUT_MS,\n cooldownPeriod: normalizedConfig.viewport.cooldownPeriod ?? DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n maxTrackedElements: normalizedConfig.viewport.maxTrackedElements ?? DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n };\n }\n\n return normalizedConfig;\n};\n","import { MAX_NESTED_OBJECT_KEYS, MAX_METADATA_NESTING_DEPTH } from '../../constants';\n\n/**\n * Validates if an item in an array is a valid nested object\n * @param item - The item to validate\n * @returns True if the item is a valid nested object\n */\nconst isValidArrayItem = (item: unknown): boolean => {\n if (typeof item === 'string') {\n return true;\n }\n\n // Allow objects with primitive fields only (one level deep)\n if (typeof item === 'object' && item !== null && !Array.isArray(item)) {\n const entries = Object.entries(item);\n\n // Check key count limit\n if (entries.length > MAX_NESTED_OBJECT_KEYS) {\n return false;\n }\n\n // All values must be primitives (no nested objects or arrays)\n for (const [, value] of entries) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type !== 'string' && type !== 'number' && type !== 'boolean') {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n};\n\n/**\n * Checks if an object contains only primitive fields, string arrays, arrays of flat objects,\n * or nested objects with primitive fields\n * @param object - The object to check\n * @param depth - Current nesting depth (default: 0, max: MAX_METADATA_NESTING_DEPTH)\n * @returns True if the object contains only valid fields\n */\nexport const isOnlyPrimitiveFields = (object: Record<string, unknown>, depth = 0): boolean => {\n if (typeof object !== 'object' || object === null) {\n return false;\n }\n\n if (depth > MAX_METADATA_NESTING_DEPTH) {\n return false;\n }\n\n for (const value of Object.values(object)) {\n if (value === null || value === undefined) {\n continue;\n }\n\n const type = typeof value;\n if (type === 'string' || type === 'number' || type === 'boolean') {\n continue;\n }\n\n if (Array.isArray(value)) {\n if (value.length === 0) {\n continue;\n }\n\n // Determine array type from first item\n const firstItem = value[0];\n const isStringArray = typeof firstItem === 'string';\n\n // All items must be of the same type (all strings OR all objects)\n if (isStringArray) {\n if (!value.every((item) => typeof item === 'string')) {\n return false;\n }\n } else {\n // Must be all objects\n if (!value.every((item) => isValidArrayItem(item))) {\n return false;\n }\n }\n\n continue;\n }\n\n // Allow nested objects at depth 0 only (one level deep)\n if (type === 'object' && depth === 0) {\n if (!isOnlyPrimitiveFields(value as Record<string, unknown>, depth + 1)) {\n return false;\n }\n continue;\n }\n\n return false;\n }\n\n return true;\n};\n","import {\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_STRING_LENGTH,\n MAX_STRING_LENGTH_IN_ARRAY,\n} from '../../constants';\nimport { MetadataType } from '../../types';\nimport { sanitizeMetadata } from '../security/sanitize.utils';\nimport { isOnlyPrimitiveFields } from './type-guards.utils';\n\n/**\n * Validates an event name\n * @param eventName - The event name to validate\n * @returns Validation result with error message if invalid\n */\nexport const isValidEventName = (eventName: string): { valid: boolean; error?: string } => {\n if (typeof eventName !== 'string') {\n return {\n valid: false,\n error: 'Event name must be a string',\n };\n }\n\n if (eventName.length === 0) {\n return {\n valid: false,\n error: 'Event name cannot be empty',\n };\n }\n\n if (eventName.length > MAX_CUSTOM_EVENT_NAME_LENGTH) {\n return {\n valid: false,\n error: `Event name is too long (max ${MAX_CUSTOM_EVENT_NAME_LENGTH} characters)`,\n };\n }\n\n if (eventName.includes('<') || eventName.includes('>') || eventName.includes('&')) {\n return {\n valid: false,\n error: 'Event name contains invalid characters',\n };\n }\n\n const reservedWords = ['constructor', 'prototype', '__proto__', 'eval', 'function', 'var', 'let', 'const'];\n\n if (reservedWords.includes(eventName.toLowerCase())) {\n return {\n valid: false,\n error: 'Event name cannot be a reserved word',\n };\n }\n\n return { valid: true };\n};\n\n/**\n * Validates a single metadata object\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata object to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nconst validateSingleMetadata = (\n eventName: string,\n metadata: Record<string, unknown>,\n type?: 'globalMetadata' | 'customEvent',\n): { valid: boolean; error?: string; sanitizedMetadata?: Record<string, MetadataType> } => {\n const sanitizedMetadata = sanitizeMetadata(metadata);\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n if (!isOnlyPrimitiveFields(sanitizedMetadata)) {\n return {\n valid: false,\n error: `${intro}: object has invalid types. Valid types are string, number, boolean or string arrays.`,\n };\n }\n\n let jsonString: string;\n\n try {\n jsonString = JSON.stringify(sanitizedMetadata);\n } catch {\n return {\n valid: false,\n error: `${intro}: object contains circular references or cannot be serialized.`,\n };\n }\n\n if (jsonString.length > MAX_CUSTOM_EVENT_STRING_SIZE) {\n return {\n valid: false,\n error: `${intro}: object is too large (max ${MAX_CUSTOM_EVENT_STRING_SIZE / 1024} KB).`,\n };\n }\n\n const keyCount = Object.keys(sanitizedMetadata).length;\n\n if (keyCount > MAX_CUSTOM_EVENT_KEYS) {\n return {\n valid: false,\n error: `${intro}: object has too many keys (max ${MAX_CUSTOM_EVENT_KEYS} keys).`,\n };\n }\n\n for (const [key, value] of Object.entries(sanitizedMetadata)) {\n if (Array.isArray(value)) {\n if (value.length > MAX_CUSTOM_EVENT_ARRAY_SIZE) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" is too large (max ${MAX_CUSTOM_EVENT_ARRAY_SIZE} items).`,\n };\n }\n\n for (const item of value) {\n if (typeof item === 'string' && item.length > MAX_STRING_LENGTH_IN_ARRAY) {\n return {\n valid: false,\n error: `${intro}: array property \"${key}\" contains strings that are too long (max ${MAX_STRING_LENGTH_IN_ARRAY} characters).`,\n };\n }\n }\n }\n\n if (typeof value === 'string' && value.length > MAX_STRING_LENGTH) {\n return {\n valid: false,\n error: `${intro}: property \"${key}\" is too long (max ${MAX_STRING_LENGTH} characters).`,\n };\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata,\n };\n};\n\n/**\n * Validates metadata for events (supports both objects and arrays of objects)\n * @param eventName - The event name (for error messages)\n * @param metadata - The metadata to validate\n * @param type - Type of metadata (globalMetadata or customEvent)\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isValidMetadata = (\n eventName: string,\n metadata: Record<string, unknown> | Record<string, unknown>[],\n type?: 'globalMetadata' | 'customEvent',\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n if (Array.isArray(metadata)) {\n const sanitizedArray: Record<string, MetadataType>[] = [];\n const intro =\n type && type === 'customEvent' ? `${type} \"${eventName}\" metadata error` : `${eventName} metadata error`;\n\n for (let i = 0; i < metadata.length; i++) {\n const item = metadata[i];\n\n if (typeof item !== 'object' || item === null || Array.isArray(item)) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} must be an object.`,\n };\n }\n\n const itemValidation = validateSingleMetadata(eventName, item, type);\n\n if (!itemValidation.valid) {\n return {\n valid: false,\n error: `${intro}: array item at index ${i} is invalid: ${itemValidation.error}`,\n };\n }\n\n if (itemValidation.sanitizedMetadata) {\n sanitizedArray.push(itemValidation.sanitizedMetadata);\n }\n }\n\n return {\n valid: true,\n sanitizedMetadata: sanitizedArray,\n };\n }\n\n return validateSingleMetadata(eventName, metadata, type);\n};\n","import { MetadataType } from '../../types';\nimport { log } from '../logging.utils';\nimport { isValidEventName, isValidMetadata } from './metadata-validations.utils';\n\n/**\n * Validates a complete event with name and optional metadata\n * @param eventName - The event name to validate\n * @param metadata - Optional metadata to validate\n * @returns Validation result with sanitized metadata if valid\n */\nexport const isEventValid = (\n eventName: string,\n metadata?: Record<string, unknown> | Record<string, unknown>[],\n): {\n valid: boolean;\n error?: string;\n sanitizedMetadata?: Record<string, MetadataType> | Record<string, MetadataType>[];\n} => {\n const nameValidation = isValidEventName(eventName);\n\n if (!nameValidation.valid) {\n log('error', 'Event name validation failed', {\n showToClient: true,\n data: { eventName, error: nameValidation.error },\n });\n\n return nameValidation;\n }\n\n if (!metadata) {\n return { valid: true };\n }\n\n const metadataValidation = isValidMetadata(eventName, metadata, 'customEvent');\n\n if (!metadataValidation.valid) {\n log('error', 'Event metadata validation failed', {\n showToClient: true,\n data: {\n eventName,\n error: metadataValidation.error,\n },\n });\n }\n\n return metadataValidation;\n};\n","import { EmitterCallback, EmitterMap } from '../types';\n\nexport class Emitter {\n private readonly listeners: Map<string, EmitterCallback[]> = new Map();\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n if (!this.listeners.has(event)) {\n this.listeners.set(event, []);\n }\n\n this.listeners.get(event)!.push(callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n const index = callbacks.indexOf(callback);\n\n if (index > -1) {\n callbacks.splice(index, 1);\n }\n }\n }\n\n emit<K extends keyof EmitterMap>(event: K, data: EmitterMap[K]): void {\n const callbacks = this.listeners.get(event);\n\n if (callbacks) {\n callbacks.forEach((callback) => {\n callback(data);\n });\n }\n }\n\n removeAllListeners(): void {\n this.listeners.clear();\n }\n}\n","import { State } from '../types';\n\nconst globalState: State = {} as State;\n\nexport function getGlobalState(): Readonly<State> {\n return globalState;\n}\n\nexport function resetGlobalState(): void {\n Object.keys(globalState).forEach((key) => {\n delete globalState[key as keyof State];\n });\n}\n\nexport abstract class StateManager {\n protected get<T extends keyof State>(key: T): State[T] {\n return globalState[key];\n }\n\n protected set<T extends keyof State>(key: T, value: State[T]): void {\n globalState[key] = value;\n }\n\n protected getState(): Readonly<State> {\n return { ...globalState };\n }\n}\n","import {\n QUEUE_KEY,\n EVENT_EXPIRY_HOURS,\n REQUEST_TIMEOUT_MS,\n PERMANENT_ERROR_LOG_THROTTLE_MS,\n MAX_BEACON_PAYLOAD_SIZE,\n PERSISTENCE_THROTTLE_MS,\n} from '../constants';\nimport { PersistedEventsQueue, EventsQueue, SpecialApiUrl, PermanentError } from '../types';\nimport { log } from '../utils';\nimport { StorageManager } from './storage.manager';\nimport { StateManager } from './state.manager';\n\ninterface SendCallbacks {\n onSuccess?: (eventCount?: number, events?: any[], body?: EventsQueue) => void;\n onFailure?: () => void;\n}\n\nexport class SenderManager extends StateManager {\n private readonly storeManager: StorageManager;\n private lastPermanentErrorLog: { statusCode?: number; timestamp: number } | null = null;\n private recoveryInProgress = false;\n\n constructor(storeManager: StorageManager) {\n super();\n this.storeManager = storeManager;\n }\n\n private getQueueStorageKey(): string {\n const userId = this.get('userId') || 'anonymous';\n return QUEUE_KEY(userId);\n }\n\n sendEventsQueueSync(body: EventsQueue): boolean {\n if (this.shouldSkipSend()) {\n return true;\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure (sync)', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n return this.sendQueueSyncInternal(body);\n }\n\n async sendEventsQueue(body: EventsQueue, callbacks?: SendCallbacks): Promise<boolean> {\n try {\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n callbacks?.onSuccess?.(body.events.length, body.events, body);\n } else {\n this.persistEvents(body);\n callbacks?.onFailure?.();\n }\n\n return success;\n } catch (error) {\n if (error instanceof PermanentError) {\n this.logPermanentError('Permanent error, not retrying', error);\n this.clearPersistedEvents();\n callbacks?.onFailure?.();\n return false;\n }\n\n this.persistEvents(body);\n callbacks?.onFailure?.();\n return false;\n }\n }\n\n async recoverPersistedEvents(callbacks?: SendCallbacks): Promise<void> {\n if (this.recoveryInProgress) {\n log('debug', 'Recovery already in progress, skipping duplicate attempt');\n return;\n }\n\n this.recoveryInProgress = true;\n\n try {\n const persistedData = this.getPersistedData();\n\n if (!persistedData || !this.isDataRecent(persistedData) || persistedData.events.length === 0) {\n this.clearPersistedEvents();\n return;\n }\n\n const body = this.createRecoveryBody(persistedData);\n const success = await this.send(body);\n\n if (success) {\n this.clearPersistedEvents();\n callbacks?.onSuccess?.(persistedData.events.length, persistedData.events, body);\n } else {\n callbacks?.onFailure?.();\n }\n } catch (error) {\n if (error instanceof PermanentError) {\n this.logPermanentError('Permanent error during recovery, clearing persisted events', error);\n this.clearPersistedEvents();\n callbacks?.onFailure?.();\n return;\n }\n\n log('error', 'Failed to recover persisted events', { error });\n } finally {\n this.recoveryInProgress = false;\n }\n }\n\n stop(): void {}\n\n private async send(body: EventsQueue): Promise<boolean> {\n if (this.shouldSkipSend()) {\n return this.simulateSuccessfulSend();\n }\n\n const config = this.get('config');\n\n if (config?.integrations?.custom?.collectApiUrl === SpecialApiUrl.Fail) {\n log('warn', 'Fail mode: simulating network failure', {\n data: { events: body.events.length },\n });\n\n return false;\n }\n\n const { url, payload } = this.prepareRequest(body);\n\n try {\n const response = await this.sendWithTimeout(url, payload);\n\n return response.ok;\n } catch (error) {\n if (error instanceof PermanentError) {\n throw error;\n }\n\n log('error', 'Send request failed', {\n error,\n data: {\n events: body.events.length,\n url: url.replace(/\\/\\/[^/]+/, '//[DOMAIN]'),\n },\n });\n\n return false;\n }\n }\n\n private async sendWithTimeout(url: string, payload: string): Promise<Response> {\n const controller = new AbortController();\n const timeoutId = setTimeout(() => {\n controller.abort();\n }, REQUEST_TIMEOUT_MS);\n\n try {\n const response = await fetch(url, {\n method: 'POST',\n body: payload,\n keepalive: true,\n credentials: 'include',\n signal: controller.signal,\n headers: {\n 'Content-Type': 'application/json',\n },\n });\n\n if (!response.ok) {\n const isPermanentError = response.status >= 400 && response.status < 500;\n\n if (isPermanentError) {\n throw new PermanentError(`HTTP ${response.status}: ${response.statusText}`, response.status);\n }\n\n throw new Error(`HTTP ${response.status}: ${response.statusText}`);\n }\n\n return response;\n } finally {\n clearTimeout(timeoutId);\n }\n }\n\n private sendQueueSyncInternal(body: EventsQueue): boolean {\n const { url, payload } = this.prepareRequest(body);\n\n // Check payload size against 64KB browser limit (Phase 3)\n if (payload.length > MAX_BEACON_PAYLOAD_SIZE) {\n log('warn', 'Payload exceeds sendBeacon limit, persisting for recovery', {\n data: {\n size: payload.length,\n limit: MAX_BEACON_PAYLOAD_SIZE,\n events: body.events.length,\n },\n });\n this.persistEvents(body);\n return false;\n }\n\n const blob = new Blob([payload], { type: 'application/json' });\n\n if (!this.isSendBeaconAvailable()) {\n log('warn', 'sendBeacon not available, persisting events for recovery');\n this.persistEvents(body);\n return false;\n }\n\n // sendBeacon only returns true/false without HTTP status codes\n // true: browser accepted the request for sending\n // false: request rejected (queue full, size limits, etc.)\n const accepted = navigator.sendBeacon(url, blob);\n\n if (!accepted) {\n log('warn', 'sendBeacon rejected request, persisting events for recovery');\n this.persistEvents(body);\n }\n\n return accepted;\n }\n\n private prepareRequest(body: EventsQueue): { url: string; payload: string } {\n // Enrich payload with metadata for sendBeacon() fallback\n // sendBeacon() doesn't send custom headers, so we include referer in payload\n const enrichedBody = {\n ...body,\n _metadata: {\n referer: typeof window !== 'undefined' ? window.location.href : undefined,\n timestamp: Date.now(),\n },\n };\n\n return {\n url: this.get('collectApiUrl'),\n payload: JSON.stringify(enrichedBody),\n };\n }\n\n private getPersistedData(): PersistedEventsQueue | null {\n try {\n const storageKey = this.getQueueStorageKey();\n const persistedDataString = this.storeManager.getItem(storageKey);\n\n if (persistedDataString) {\n return JSON.parse(persistedDataString);\n }\n } catch (error) {\n log('warn', 'Failed to parse persisted data', { error });\n this.clearPersistedEvents();\n }\n\n return null;\n }\n\n private isDataRecent(data: PersistedEventsQueue): boolean {\n if (!data.timestamp || typeof data.timestamp !== 'number') {\n return false;\n }\n\n const ageInHours = (Date.now() - data.timestamp) / (1000 * 60 * 60);\n return ageInHours < EVENT_EXPIRY_HOURS;\n }\n\n private createRecoveryBody(data: PersistedEventsQueue): EventsQueue {\n // eslint-disable-next-line @typescript-eslint/no-unused-vars\n const { timestamp, ...queue } = data;\n return queue;\n }\n\n private persistEvents(body: EventsQueue): boolean {\n try {\n const existing = this.getPersistedData();\n\n if (existing && existing.timestamp) {\n const timeSinceExisting = Date.now() - existing.timestamp;\n\n if (timeSinceExisting < PERSISTENCE_THROTTLE_MS) {\n log('debug', 'Skipping persistence, another tab recently persisted events', {\n data: { timeSinceExisting },\n });\n\n return true;\n }\n }\n\n const persistedData: PersistedEventsQueue = {\n ...body,\n timestamp: Date.now(),\n };\n\n const storageKey = this.getQueueStorageKey();\n\n this.storeManager.setItem(storageKey, JSON.stringify(persistedData));\n\n return !!this.storeManager.getItem(storageKey);\n } catch (error) {\n log('warn', 'Failed to persist events', { error });\n return false;\n }\n }\n\n private clearPersistedEvents(): void {\n try {\n const key = this.getQueueStorageKey();\n this.storeManager.removeItem(key);\n } catch (error) {\n log('warn', 'Failed to clear persisted events', { error });\n }\n }\n\n private shouldSkipSend(): boolean {\n return !this.get('collectApiUrl');\n }\n\n private async simulateSuccessfulSend(): Promise<boolean> {\n const delay = Math.random() * 400 + 100;\n\n await new Promise((resolve) => setTimeout(resolve, delay));\n\n return true;\n }\n\n private isSendBeaconAvailable(): boolean {\n return typeof navigator !== 'undefined' && typeof navigator.sendBeacon === 'function';\n }\n\n private logPermanentError(context: string, error: PermanentError): void {\n const now = Date.now();\n const shouldLog =\n !this.lastPermanentErrorLog ||\n this.lastPermanentErrorLog.statusCode !== error.statusCode ||\n now - this.lastPermanentErrorLog.timestamp >= PERMANENT_ERROR_LOG_THROTTLE_MS;\n\n if (shouldLog) {\n log('error', context, {\n data: { status: error.statusCode, message: error.message },\n });\n\n this.lastPermanentErrorLog = { statusCode: error.statusCode, timestamp: now };\n }\n }\n}\n","import {\n EVENT_SENT_INTERVAL_MS,\n MAX_EVENTS_QUEUE_LENGTH,\n DUPLICATE_EVENT_THRESHOLD_MS,\n RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SECOND,\n MAX_PENDING_EVENTS_BUFFER,\n BATCH_SIZE_THRESHOLD,\n MAX_SAME_EVENT_PER_MINUTE,\n PER_EVENT_RATE_LIMIT_WINDOW_MS,\n MAX_EVENTS_PER_SESSION,\n MAX_CLICKS_PER_SESSION,\n MAX_PAGE_VIEWS_PER_SESSION,\n MAX_CUSTOM_EVENTS_PER_SESSION,\n MAX_VIEWPORT_EVENTS_PER_SESSION,\n MAX_SCROLL_EVENTS_PER_SESSION,\n MAX_FINGERPRINTS,\n FINGERPRINT_CLEANUP_MULTIPLIER,\n MAX_FINGERPRINTS_HARD_LIMIT,\n} from '../constants/config.constants';\nimport { EventsQueue, EmitterEvent, EventData, EventType, Mode } from '../types';\nimport { getUTMParameters, log, Emitter, generateEventId } from '../utils';\nimport { SenderManager } from './sender.manager';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { GoogleAnalyticsIntegration } from '../integrations/google-analytics.integration';\n\nexport class EventManager extends StateManager {\n private readonly googleAnalytics: GoogleAnalyticsIntegration | null;\n private readonly dataSender: SenderManager;\n private readonly emitter: Emitter | null;\n\n private eventsQueue: EventData[] = [];\n private pendingEventsBuffer: Partial<EventData>[] = [];\n private readonly recentEventFingerprints = new Map<string, number>(); // Time-based deduplication cache\n private sendIntervalId: number | null = null;\n private rateLimitCounter = 0;\n private rateLimitWindowStart = 0;\n private readonly perEventRateLimits: Map<string, number[]> = new Map();\n private sessionEventCounts: {\n total: number;\n [key: string]: number;\n } = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n private lastSessionId: string | null = null;\n\n constructor(\n storeManager: StorageManager,\n googleAnalytics: GoogleAnalyticsIntegration | null = null,\n emitter: Emitter | null = null,\n ) {\n super();\n\n this.googleAnalytics = googleAnalytics;\n this.dataSender = new SenderManager(storeManager);\n this.emitter = emitter;\n }\n\n async recoverPersistedEvents(): Promise<void> {\n await this.dataSender.recoverPersistedEvents({\n onSuccess: (_eventCount, recoveredEvents, body) => {\n if (recoveredEvents && recoveredEvents.length > 0) {\n const eventIds = recoveredEvents.map((e) => e.id);\n this.removeProcessedEvents(eventIds);\n\n if (body) {\n this.emitEventsQueue(body);\n }\n }\n },\n onFailure: () => {\n log('warn', 'Failed to recover persisted events');\n },\n });\n }\n\n track({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n }: Partial<EventData>): void {\n if (!type) {\n log('error', 'Event type is required - event will be ignored');\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n if (this.pendingEventsBuffer.length >= MAX_PENDING_EVENTS_BUFFER) {\n this.pendingEventsBuffer.shift();\n log('warn', 'Pending events buffer full - dropping oldest event', {\n data: { maxBufferSize: MAX_PENDING_EVENTS_BUFFER },\n });\n }\n\n this.pendingEventsBuffer.push({\n type,\n page_url,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n });\n\n return;\n }\n\n // Reset session counters if session ID changed (Phase 3)\n if (this.lastSessionId !== currentSessionId) {\n this.lastSessionId = currentSessionId;\n this.sessionEventCounts = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n }\n\n const isCriticalEvent = type === EventType.SESSION_START || type === EventType.SESSION_END;\n if (!isCriticalEvent && !this.checkRateLimit()) {\n return;\n }\n\n const eventType = type as EventType;\n\n // Per-session event caps (Phase 3) - skip for critical events\n if (!isCriticalEvent) {\n // Check total session limit\n if (this.sessionEventCounts.total >= MAX_EVENTS_PER_SESSION) {\n log('warn', 'Session event limit reached', {\n data: {\n type: eventType,\n total: this.sessionEventCounts.total,\n limit: MAX_EVENTS_PER_SESSION,\n },\n });\n return;\n }\n\n // Check type-specific limits\n const typeLimit = this.getTypeLimitForEvent(eventType);\n if (typeLimit) {\n const currentCount = this.sessionEventCounts[eventType];\n if (currentCount !== undefined && currentCount >= typeLimit) {\n log('warn', 'Session event type limit reached', {\n data: {\n type: eventType,\n count: currentCount,\n limit: typeLimit,\n },\n });\n return;\n }\n }\n }\n\n // Per-event-name rate limiting for CUSTOM events to prevent infinite loops\n if (eventType === EventType.CUSTOM && custom_event?.name) {\n const maxSameEventPerMinute = this.get('config')?.maxSameEventPerMinute ?? MAX_SAME_EVENT_PER_MINUTE;\n if (!this.checkPerEventRateLimit(custom_event.name, maxSameEventPerMinute)) {\n return;\n }\n }\n const isSessionStart = eventType === EventType.SESSION_START;\n\n const currentPageUrl = (page_url as string) || this.get('pageUrl');\n const payload = this.buildEventPayload({\n type: eventType,\n page_url: currentPageUrl,\n from_page_url,\n scroll_data,\n click_data,\n custom_event,\n web_vitals,\n error_data,\n session_end_reason,\n viewport_data,\n });\n\n if (!isCriticalEvent && !this.shouldSample()) {\n return;\n }\n\n if (isSessionStart) {\n const currentSessionId = this.get('sessionId');\n\n if (!currentSessionId) {\n log('error', 'Session start event requires sessionId - event will be ignored');\n return;\n }\n\n if (this.get('hasStartSession')) {\n log('warn', 'Duplicate session_start detected', {\n data: { sessionId: currentSessionId },\n });\n\n return;\n }\n\n this.set('hasStartSession', true);\n }\n\n if (this.isDuplicateEvent(payload)) {\n return;\n }\n\n if (this.get('mode') === Mode.QA && eventType === EventType.CUSTOM && custom_event) {\n console.log('[TraceLog] Event', {\n name: custom_event.name,\n ...(custom_event.metadata && { metadata: custom_event.metadata }),\n });\n\n this.emitEvent(payload);\n\n return;\n }\n\n this.addToQueue(payload);\n\n // Increment session counters (Phase 3) - only for non-critical events\n if (!isCriticalEvent) {\n this.sessionEventCounts.total++;\n if (this.sessionEventCounts[eventType] !== undefined) {\n this.sessionEventCounts[eventType]++;\n }\n }\n }\n\n stop(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n\n this.eventsQueue = [];\n this.pendingEventsBuffer = [];\n this.recentEventFingerprints.clear();\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = 0;\n this.perEventRateLimits.clear();\n this.sessionEventCounts = {\n total: 0,\n [EventType.CLICK]: 0,\n [EventType.PAGE_VIEW]: 0,\n [EventType.CUSTOM]: 0,\n [EventType.VIEWPORT_VISIBLE]: 0,\n [EventType.SCROLL]: 0,\n };\n this.lastSessionId = null;\n\n this.dataSender.stop();\n }\n\n async flushImmediately(): Promise<boolean> {\n return this.flushEvents(false);\n }\n\n flushImmediatelySync(): boolean {\n return this.flushEvents(true) as boolean;\n }\n\n getQueueLength(): number {\n return this.eventsQueue.length;\n }\n\n flushPendingEvents(): void {\n if (this.pendingEventsBuffer.length === 0) {\n return;\n }\n\n const currentSessionId = this.get('sessionId');\n if (!currentSessionId) {\n log('warn', 'Cannot flush pending events: session not initialized - keeping in buffer', {\n data: { bufferedEventCount: this.pendingEventsBuffer.length },\n });\n\n return;\n }\n\n const bufferedEvents = [...this.pendingEventsBuffer];\n this.pendingEventsBuffer = [];\n\n bufferedEvents.forEach((event) => {\n this.track(event);\n });\n }\n\n private clearSendInterval(): void {\n if (this.sendIntervalId) {\n clearInterval(this.sendIntervalId);\n this.sendIntervalId = null;\n }\n }\n\n private flushEvents(isSync: boolean): boolean | Promise<boolean> {\n if (this.eventsQueue.length === 0) {\n return isSync ? true : Promise.resolve(true);\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n if (isSync) {\n const success = this.dataSender.sendEventsQueueSync(body);\n\n if (success) {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n } else {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n }\n\n return success;\n } else {\n return this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.clearSendInterval();\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n this.removeProcessedEvents(eventIds);\n\n if (this.eventsQueue.length === 0) {\n this.clearSendInterval();\n }\n\n log('warn', 'Async flush failed, removed from queue and persisted for recovery on next page load', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n }\n\n private async sendEventsQueue(): Promise<void> {\n if (!this.get('sessionId') || this.eventsQueue.length === 0) {\n return;\n }\n\n const body = this.buildEventsPayload();\n const eventsToSend = [...this.eventsQueue];\n const eventIds = eventsToSend.map((e) => e.id);\n\n await this.dataSender.sendEventsQueue(body, {\n onSuccess: () => {\n this.removeProcessedEvents(eventIds);\n this.emitEventsQueue(body);\n },\n onFailure: () => {\n this.removeProcessedEvents(eventIds);\n\n if (this.eventsQueue.length === 0) {\n this.clearSendInterval();\n }\n\n log('warn', 'Events send failed, removed from queue and persisted for recovery on next page load', {\n data: { eventCount: eventsToSend.length },\n });\n },\n });\n }\n\n private buildEventsPayload(): EventsQueue {\n const eventMap = new Map<string, EventData>();\n const order: string[] = [];\n\n for (const event of this.eventsQueue) {\n const signature = this.createEventSignature(event);\n\n if (!eventMap.has(signature)) {\n order.push(signature);\n }\n\n eventMap.set(signature, event);\n }\n\n const events = order\n .map((signature) => eventMap.get(signature))\n .filter((event): event is EventData => Boolean(event))\n .sort((a, b) => a.timestamp - b.timestamp);\n\n return {\n user_id: this.get('userId'),\n session_id: this.get('sessionId') as string,\n device: this.get('device'),\n events,\n ...(this.get('config')?.globalMetadata && { global_metadata: this.get('config')?.globalMetadata }),\n };\n }\n\n private buildEventPayload(data: Partial<EventData>): EventData {\n const isSessionStart = data.type === EventType.SESSION_START;\n const currentPageUrl = data.page_url ?? this.get('pageUrl');\n\n const payload: EventData = {\n id: generateEventId(),\n type: data.type as EventType,\n page_url: currentPageUrl,\n timestamp: Date.now(),\n ...(isSessionStart && { referrer: document.referrer || 'Direct' }),\n ...(data.from_page_url && { from_page_url: data.from_page_url }),\n ...(data.scroll_data && { scroll_data: data.scroll_data }),\n ...(data.click_data && { click_data: data.click_data }),\n ...(data.custom_event && { custom_event: data.custom_event }),\n ...(data.web_vitals && { web_vitals: data.web_vitals }),\n ...(data.error_data && { error_data: data.error_data }),\n ...(data.session_end_reason && { session_end_reason: data.session_end_reason }),\n ...(data.viewport_data && { viewport_data: data.viewport_data }),\n ...(isSessionStart && getUTMParameters() && { utm: getUTMParameters() }),\n };\n\n return payload;\n }\n\n /**\n * Checks if event is a duplicate using time-based cache\n * Tracks recent event fingerprints with timestamp-based cleanup\n */\n private isDuplicateEvent(event: EventData): boolean {\n const now = Date.now();\n const fingerprint = this.createEventFingerprint(event);\n\n const lastSeen = this.recentEventFingerprints.get(fingerprint);\n\n // Check if seen recently\n if (lastSeen && now - lastSeen < DUPLICATE_EVENT_THRESHOLD_MS) {\n this.recentEventFingerprints.set(fingerprint, now); // Update timestamp\n return true; // Duplicate\n }\n\n // Add to cache\n this.recentEventFingerprints.set(fingerprint, now);\n\n // Cleanup if cache too large (soft limit)\n if (this.recentEventFingerprints.size > MAX_FINGERPRINTS) {\n this.pruneOldFingerprints();\n }\n\n // Hard limit: aggressive cleanup\n if (this.recentEventFingerprints.size > MAX_FINGERPRINTS_HARD_LIMIT) {\n this.recentEventFingerprints.clear();\n this.recentEventFingerprints.set(fingerprint, now);\n log('warn', 'Event fingerprint cache exceeded hard limit, cleared', {\n data: { hardLimit: MAX_FINGERPRINTS_HARD_LIMIT },\n });\n }\n\n return false;\n }\n\n /**\n * Prunes old fingerprints from cache based on timestamp\n * Removes entries older than 10x the duplicate threshold (5 seconds)\n */\n private pruneOldFingerprints(): void {\n const now = Date.now();\n const cutoff = DUPLICATE_EVENT_THRESHOLD_MS * FINGERPRINT_CLEANUP_MULTIPLIER; // 5 seconds\n\n for (const [fingerprint, timestamp] of this.recentEventFingerprints.entries()) {\n if (now - timestamp > cutoff) {\n this.recentEventFingerprints.delete(fingerprint);\n }\n }\n\n log('debug', 'Pruned old event fingerprints', {\n data: {\n remaining: this.recentEventFingerprints.size,\n cutoffMs: cutoff,\n },\n });\n }\n\n private createEventFingerprint(event: EventData): string {\n let fingerprint = `${event.type}_${event.page_url}`;\n\n if (event.click_data) {\n const x = Math.round((event.click_data.x || 0) / 10) * 10;\n const y = Math.round((event.click_data.y || 0) / 10) * 10;\n fingerprint += `_click_${x}_${y}`;\n }\n\n if (event.scroll_data) {\n fingerprint += `_scroll_${event.scroll_data.depth}_${event.scroll_data.direction}`;\n }\n\n if (event.custom_event) {\n fingerprint += `_custom_${event.custom_event.name}`;\n }\n\n if (event.web_vitals) {\n fingerprint += `_vitals_${event.web_vitals.type}`;\n }\n\n if (event.error_data) {\n fingerprint += `_error_${event.error_data.type}_${event.error_data.message}`;\n }\n\n return fingerprint;\n }\n\n private createEventSignature(event: EventData): string {\n return this.createEventFingerprint(event);\n }\n\n private addToQueue(event: EventData): void {\n this.eventsQueue.push(event);\n\n this.emitEvent(event);\n\n if (this.eventsQueue.length > MAX_EVENTS_QUEUE_LENGTH) {\n const nonCriticalIndex = this.eventsQueue.findIndex(\n (e) => e.type !== EventType.SESSION_START && e.type !== EventType.SESSION_END,\n );\n\n const removedEvent =\n nonCriticalIndex >= 0 ? this.eventsQueue.splice(nonCriticalIndex, 1)[0] : this.eventsQueue.shift();\n\n log('warn', 'Event queue overflow, oldest non-critical event removed', {\n data: {\n maxLength: MAX_EVENTS_QUEUE_LENGTH,\n currentLength: this.eventsQueue.length,\n removedEventType: removedEvent?.type,\n wasCritical: removedEvent?.type === EventType.SESSION_START || removedEvent?.type === EventType.SESSION_END,\n },\n });\n }\n\n if (!this.sendIntervalId) {\n this.startSendInterval();\n }\n\n // Dynamic flush: Send immediately when batch size threshold is reached\n if (this.eventsQueue.length >= BATCH_SIZE_THRESHOLD) {\n void this.sendEventsQueue();\n }\n\n this.handleGoogleAnalyticsIntegration(event);\n }\n\n private startSendInterval(): void {\n this.sendIntervalId = window.setInterval(() => {\n if (this.eventsQueue.length > 0) {\n void this.sendEventsQueue();\n }\n }, EVENT_SENT_INTERVAL_MS);\n }\n\n private handleGoogleAnalyticsIntegration(event: EventData): void {\n if (this.googleAnalytics && event.type === EventType.CUSTOM && event.custom_event) {\n if (this.get('mode') === Mode.QA) {\n return;\n }\n\n this.googleAnalytics.trackEvent(event.custom_event.name, event.custom_event.metadata ?? {});\n }\n }\n\n private shouldSample(): boolean {\n const samplingRate = this.get('config')?.samplingRate ?? 1;\n return Math.random() < samplingRate;\n }\n\n private checkRateLimit(): boolean {\n const now = Date.now();\n\n if (now - this.rateLimitWindowStart > RATE_LIMIT_WINDOW_MS) {\n this.rateLimitCounter = 0;\n this.rateLimitWindowStart = now;\n }\n\n if (this.rateLimitCounter >= MAX_EVENTS_PER_SECOND) {\n return false;\n }\n\n this.rateLimitCounter++;\n return true;\n }\n\n /**\n * Checks per-event-name rate limiting to prevent infinite loops in user code\n * Tracks timestamps per event name and limits to maxSameEventPerMinute per minute\n */\n private checkPerEventRateLimit(eventName: string, maxSameEventPerMinute: number): boolean {\n const now = Date.now();\n const timestamps = this.perEventRateLimits.get(eventName) ?? [];\n\n // Remove timestamps older than the rate limit window (60 seconds)\n const validTimestamps = timestamps.filter((ts) => now - ts < PER_EVENT_RATE_LIMIT_WINDOW_MS);\n\n if (validTimestamps.length >= maxSameEventPerMinute) {\n log('warn', 'Per-event rate limit exceeded for custom event', {\n data: {\n eventName,\n limit: maxSameEventPerMinute,\n window: `${PER_EVENT_RATE_LIMIT_WINDOW_MS / 1000}s`,\n },\n });\n return false;\n }\n\n // Add current timestamp and update map\n validTimestamps.push(now);\n this.perEventRateLimits.set(eventName, validTimestamps);\n\n return true;\n }\n\n /**\n * Gets the per-session limit for a specific event type (Phase 3)\n */\n private getTypeLimitForEvent(type: EventType): number | null {\n const limits: Partial<Record<EventType, number>> = {\n [EventType.CLICK]: MAX_CLICKS_PER_SESSION,\n [EventType.PAGE_VIEW]: MAX_PAGE_VIEWS_PER_SESSION,\n [EventType.CUSTOM]: MAX_CUSTOM_EVENTS_PER_SESSION,\n [EventType.VIEWPORT_VISIBLE]: MAX_VIEWPORT_EVENTS_PER_SESSION,\n [EventType.SCROLL]: MAX_SCROLL_EVENTS_PER_SESSION,\n };\n return limits[type] ?? null;\n }\n\n private removeProcessedEvents(eventIds: string[]): void {\n const eventIdSet = new Set(eventIds);\n\n this.eventsQueue = this.eventsQueue.filter((event) => {\n return !eventIdSet.has(event.id);\n });\n }\n\n private emitEvent(eventData: EventData): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.EVENT, eventData);\n }\n }\n\n private emitEventsQueue(queue: EventsQueue): void {\n if (this.emitter) {\n this.emitter.emit(EmitterEvent.QUEUE, queue);\n }\n }\n}\n","import { USER_ID_KEY } from '../constants';\nimport { generateUUID } from '../utils';\nimport { StorageManager } from './storage.manager';\n\n/**\n * Simple utility for managing user identification.\n * Generates and persists unique user IDs per project.\n */\nexport class UserManager {\n /**\n * Gets or creates a unique user ID for the given project.\n * The user ID is persisted in localStorage and reused across sessions.\n *\n * @param storageManager - Storage manager instance\n * @param projectId - Project identifier for namespacing\n * @returns Persistent unique user ID\n */\n static getId(storageManager: StorageManager): string {\n const storageKey = USER_ID_KEY;\n const storedUserId = storageManager.getItem(storageKey);\n\n if (storedUserId) {\n return storedUserId;\n }\n\n const newUserId = generateUUID();\n storageManager.setItem(storageKey, newUserId);\n\n return newUserId;\n }\n}\n","import { BROADCAST_CHANNEL_NAME, DEFAULT_SESSION_TIMEOUT, SESSION_STORAGE_KEY } from '../constants';\nimport { EventType } from '../types';\nimport { SessionEndReason } from '../types/session.types';\nimport { log } from '../utils';\nimport { StateManager } from './state.manager';\nimport { StorageManager } from './storage.manager';\nimport { EventManager } from './event.manager';\n\ninterface StoredSessionData {\n id: string;\n lastActivity: number;\n}\n\nexport class SessionManager extends StateManager {\n private readonly storageManager: StorageManager;\n private readonly eventManager: EventManager;\n private readonly projectId: string;\n private sessionTimeoutId: ReturnType<typeof setTimeout> | null = null;\n private broadcastChannel: BroadcastChannel | null = null;\n private activityHandler: (() => void) | null = null;\n private visibilityChangeHandler: (() => void) | null = null;\n private beforeUnloadHandler: ((event: BeforeUnloadEvent) => void) | null = null;\n private isTracking = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager, projectId: string) {\n super();\n this.storageManager = storageManager;\n this.eventManager = eventManager;\n this.projectId = projectId;\n }\n\n private initCrossTabSync(): void {\n if (typeof BroadcastChannel === 'undefined') {\n log('warn', 'BroadcastChannel not supported');\n return;\n }\n\n const projectId = this.getProjectId();\n this.broadcastChannel = new BroadcastChannel(BROADCAST_CHANNEL_NAME(projectId));\n\n this.broadcastChannel.onmessage = (event): void => {\n const { action, sessionId, timestamp, projectId: messageProjectId } = event.data ?? {};\n\n if (messageProjectId !== projectId) {\n return;\n }\n\n if (action === 'session_end') {\n this.resetSessionState();\n return;\n }\n\n if (sessionId && typeof timestamp === 'number' && timestamp > Date.now() - 5000) {\n this.set('sessionId', sessionId);\n this.set('hasStartSession', true);\n this.persistSession(sessionId, timestamp);\n if (this.isTracking) {\n this.setupSessionTimeout();\n }\n }\n };\n }\n\n private shareSession(sessionId: string): void {\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n this.broadcastChannel.postMessage({\n action: 'session_start',\n projectId: this.getProjectId(),\n sessionId,\n timestamp: Date.now(),\n });\n }\n }\n\n private broadcastSessionEnd(sessionId: string | null, reason: SessionEndReason): void {\n if (!sessionId) {\n return;\n }\n\n if (this.broadcastChannel && typeof this.broadcastChannel.postMessage === 'function') {\n try {\n this.broadcastChannel.postMessage({\n action: 'session_end',\n projectId: this.getProjectId(),\n sessionId,\n reason,\n timestamp: Date.now(),\n });\n } catch (error) {\n log('warn', 'Failed to broadcast session end', { error, data: { sessionId, reason } });\n }\n }\n }\n\n private cleanupCrossTabSync(): void {\n if (this.broadcastChannel) {\n if (typeof this.broadcastChannel.close === 'function') {\n this.broadcastChannel.close();\n }\n this.broadcastChannel = null;\n }\n }\n\n private recoverSession(): string | null {\n const storedSession = this.loadStoredSession();\n\n if (!storedSession) {\n return null;\n }\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n if (Date.now() - storedSession.lastActivity > sessionTimeout) {\n this.clearStoredSession();\n return null;\n }\n\n return storedSession.id;\n }\n\n private persistSession(sessionId: string, lastActivity: number = Date.now()): void {\n this.saveStoredSession({\n id: sessionId,\n lastActivity,\n });\n }\n\n private clearStoredSession(): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.removeItem(storageKey);\n }\n\n private loadStoredSession(): StoredSessionData | null {\n const storageKey = this.getSessionStorageKey();\n const storedData = this.storageManager.getItem(storageKey);\n\n if (!storedData) {\n return null;\n }\n\n try {\n const parsed = JSON.parse(storedData) as StoredSessionData;\n if (!parsed.id || typeof parsed.lastActivity !== 'number') {\n return null;\n }\n return parsed;\n } catch {\n this.storageManager.removeItem(storageKey);\n return null;\n }\n }\n\n private saveStoredSession(session: StoredSessionData): void {\n const storageKey = this.getSessionStorageKey();\n this.storageManager.setItem(storageKey, JSON.stringify(session));\n }\n\n private getSessionStorageKey(): string {\n return SESSION_STORAGE_KEY(this.getProjectId());\n }\n\n private getProjectId(): string {\n return this.projectId;\n }\n\n startTracking(): void {\n if (this.isTracking) {\n log('warn', 'Session tracking already active');\n return;\n }\n\n const recoveredSessionId = this.recoverSession();\n const sessionId = recoveredSessionId ?? this.generateSessionId();\n const isRecovered = Boolean(recoveredSessionId);\n\n this.isTracking = true;\n\n try {\n this.set('sessionId', sessionId);\n this.persistSession(sessionId);\n\n if (!isRecovered) {\n this.eventManager.track({\n type: EventType.SESSION_START,\n });\n }\n\n this.initCrossTabSync();\n this.shareSession(sessionId);\n this.setupSessionTimeout();\n this.setupActivityListeners();\n this.setupLifecycleListeners();\n } catch (error) {\n this.isTracking = false;\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n this.set('sessionId', null);\n\n throw error;\n }\n }\n\n private generateSessionId(): string {\n return `${Date.now()}-${Math.random().toString(36).substring(2, 11)}`;\n }\n\n private setupSessionTimeout(): void {\n this.clearSessionTimeout();\n\n const sessionTimeout = this.get('config')?.sessionTimeout ?? DEFAULT_SESSION_TIMEOUT;\n\n this.sessionTimeoutId = setTimeout(() => {\n this.endSession('inactivity');\n }, sessionTimeout);\n }\n\n private resetSessionTimeout(): void {\n this.setupSessionTimeout();\n const sessionId = this.get('sessionId') as string;\n if (sessionId) {\n this.persistSession(sessionId);\n }\n }\n\n private clearSessionTimeout(): void {\n if (this.sessionTimeoutId) {\n clearTimeout(this.sessionTimeoutId);\n this.sessionTimeoutId = null;\n }\n }\n\n private setupActivityListeners(): void {\n this.activityHandler = (): void => {\n this.resetSessionTimeout();\n };\n\n document.addEventListener('click', this.activityHandler, { passive: true });\n document.addEventListener('keydown', this.activityHandler, { passive: true });\n document.addEventListener('scroll', this.activityHandler, { passive: true });\n }\n\n private cleanupActivityListeners(): void {\n if (this.activityHandler) {\n document.removeEventListener('click', this.activityHandler);\n document.removeEventListener('keydown', this.activityHandler);\n document.removeEventListener('scroll', this.activityHandler);\n this.activityHandler = null;\n }\n }\n\n private setupLifecycleListeners(): void {\n if (this.visibilityChangeHandler || this.beforeUnloadHandler) {\n return;\n }\n\n this.visibilityChangeHandler = (): void => {\n if (document.hidden) {\n this.clearSessionTimeout();\n } else {\n const sessionId = this.get('sessionId');\n if (sessionId) {\n this.setupSessionTimeout();\n }\n }\n };\n\n this.beforeUnloadHandler = (): void => {\n this.endSession('page_unload');\n };\n\n document.addEventListener('visibilitychange', this.visibilityChangeHandler);\n window.addEventListener('beforeunload', this.beforeUnloadHandler);\n }\n\n private cleanupLifecycleListeners(): void {\n if (this.visibilityChangeHandler) {\n document.removeEventListener('visibilitychange', this.visibilityChangeHandler);\n this.visibilityChangeHandler = null;\n }\n\n if (this.beforeUnloadHandler) {\n window.removeEventListener('beforeunload', this.beforeUnloadHandler);\n this.beforeUnloadHandler = null;\n }\n }\n\n private endSession(reason: SessionEndReason): void {\n const sessionId = this.get('sessionId');\n\n if (!sessionId) {\n log('warn', 'endSession called without active session', { data: { reason } });\n this.resetSessionState(reason);\n return;\n }\n\n this.eventManager.track({\n type: EventType.SESSION_END,\n session_end_reason: reason,\n });\n\n const flushResult = this.eventManager.flushImmediatelySync();\n\n if (!flushResult) {\n log('warn', 'Sync flush failed during session end, events persisted for recovery', {\n data: { reason, sessionId },\n });\n }\n\n this.broadcastSessionEnd(sessionId, reason);\n this.resetSessionState(reason);\n }\n\n private resetSessionState(reason?: SessionEndReason): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupLifecycleListeners();\n this.cleanupCrossTabSync();\n\n if (reason !== 'page_unload') {\n this.clearStoredSession();\n }\n\n this.set('sessionId', null);\n this.set('hasStartSession', false);\n this.isTracking = false;\n }\n\n stopTracking(): void {\n this.endSession('manual_stop');\n }\n\n destroy(): void {\n this.clearSessionTimeout();\n this.cleanupActivityListeners();\n this.cleanupCrossTabSync();\n this.cleanupLifecycleListeners();\n this.isTracking = false;\n this.set('hasStartSession', false);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { SessionManager } from '../managers/session.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { StorageManager } from '../managers/storage.manager';\nimport { log } from '../utils';\n\nexport class SessionHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly storageManager: StorageManager;\n private sessionManager: SessionManager | null = null;\n private destroyed = false;\n\n constructor(storageManager: StorageManager, eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n this.storageManager = storageManager;\n }\n\n startTracking(): void {\n if (this.isActive()) {\n return;\n }\n\n if (this.destroyed) {\n log('warn', 'Cannot start tracking on destroyed handler');\n return;\n }\n\n const config = this.get('config');\n const projectId =\n config?.integrations?.tracelog?.projectId ?? config?.integrations?.custom?.collectApiUrl ?? 'default';\n\n if (!projectId) {\n throw new Error('Cannot start session tracking: config not available');\n }\n\n try {\n this.sessionManager = new SessionManager(this.storageManager, this.eventManager, projectId);\n this.sessionManager.startTracking();\n\n // Flush any events that were buffered during initialization\n this.eventManager.flushPendingEvents();\n } catch (error) {\n if (this.sessionManager) {\n try {\n this.sessionManager.destroy();\n } catch {\n // Ignore cleanup errors\n }\n this.sessionManager = null;\n }\n\n log('error', 'Failed to start session tracking', { error });\n throw error;\n }\n }\n\n private isActive(): boolean {\n return this.sessionManager !== null && !this.destroyed;\n }\n\n private cleanupSessionManager(): void {\n if (this.sessionManager) {\n this.sessionManager.stopTracking();\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n }\n\n stopTracking(): void {\n this.cleanupSessionManager();\n }\n\n destroy(): void {\n if (this.destroyed) {\n return;\n }\n\n if (this.sessionManager) {\n this.sessionManager.destroy();\n this.sessionManager = null;\n }\n\n this.destroyed = true;\n this.set('hasStartSession', false);\n }\n}\n","import { EventType, PageViewData } from '../types';\nimport { normalizeUrl } from '../utils';\nimport { StateManager } from '../managers/state.manager';\nimport { EventManager } from '../managers/event.manager';\nimport { DEFAULT_PAGE_VIEW_THROTTLE_MS } from '../constants/config.constants';\n\nexport class PageViewHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly onTrack: () => void;\n\n private originalPushState?: typeof window.history.pushState;\n private originalReplaceState?: typeof window.history.replaceState;\n private lastPageViewTime = 0;\n\n constructor(eventManager: EventManager, onTrack: () => void) {\n super();\n\n this.eventManager = eventManager;\n this.onTrack = onTrack;\n }\n\n startTracking(): void {\n this.trackInitialPageView();\n\n window.addEventListener('popstate', this.trackCurrentPage, true);\n window.addEventListener('hashchange', this.trackCurrentPage, true);\n\n this.patchHistory('pushState');\n this.patchHistory('replaceState');\n }\n\n stopTracking(): void {\n window.removeEventListener('popstate', this.trackCurrentPage, true);\n window.removeEventListener('hashchange', this.trackCurrentPage, true);\n\n if (this.originalPushState) {\n window.history.pushState = this.originalPushState;\n }\n\n if (this.originalReplaceState) {\n window.history.replaceState = this.originalReplaceState;\n }\n\n this.lastPageViewTime = 0;\n }\n\n private patchHistory(method: 'pushState' | 'replaceState'): void {\n const original = window.history[method];\n\n if (method === 'pushState' && !this.originalPushState) {\n this.originalPushState = original;\n } else if (method === 'replaceState' && !this.originalReplaceState) {\n this.originalReplaceState = original;\n }\n\n window.history[method] = (...args: [unknown, string, string | URL | null | undefined]): void => {\n original.apply(window.history, args);\n this.trackCurrentPage();\n };\n }\n\n private readonly trackCurrentPage = (): void => {\n const rawUrl = window.location.href;\n const normalizedUrl = normalizeUrl(rawUrl, this.get('config').sensitiveQueryParams);\n\n if (this.get('pageUrl') === normalizedUrl) {\n return;\n }\n\n // Throttle: Prevent rapid navigation spam\n const now = Date.now();\n const throttleMs = this.get('config').pageViewThrottleMs ?? DEFAULT_PAGE_VIEW_THROTTLE_MS;\n\n if (now - this.lastPageViewTime < throttleMs) {\n return;\n }\n\n this.lastPageViewTime = now;\n\n this.onTrack();\n\n const fromUrl = this.get('pageUrl');\n\n this.set('pageUrl', normalizedUrl);\n\n const pageViewData = this.extractPageViewData();\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: this.get('pageUrl'),\n from_page_url: fromUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n };\n\n private trackInitialPageView(): void {\n const normalizedUrl = normalizeUrl(window.location.href, this.get('config').sensitiveQueryParams);\n const pageViewData = this.extractPageViewData();\n\n this.lastPageViewTime = Date.now();\n\n this.eventManager.track({\n type: EventType.PAGE_VIEW,\n page_url: normalizedUrl,\n ...(pageViewData && { page_view: pageViewData }),\n });\n\n this.onTrack();\n }\n\n private extractPageViewData(): PageViewData | undefined {\n const { pathname, search, hash } = window.location;\n const { referrer } = document;\n const { title } = document;\n\n // Early return if no meaningful data\n if (!referrer && !title && !pathname && !search && !hash) {\n return undefined;\n }\n\n const data: PageViewData = {\n ...(referrer && { referrer }),\n ...(title && { title }),\n ...(pathname && { pathname }),\n ...(search && { search }),\n ...(hash && { hash }),\n };\n\n return data;\n }\n}\n","import {\n HTML_DATA_ATTR_PREFIX,\n MAX_TEXT_LENGTH,\n INTERACTIVE_SELECTORS,\n PII_PATTERNS,\n DEFAULT_CLICK_THROTTLE_MS,\n MAX_THROTTLE_CACHE_ENTRIES,\n THROTTLE_ENTRY_TTL_MS,\n THROTTLE_PRUNE_INTERVAL_MS,\n} from '../constants';\nimport { ClickCoordinates, ClickData, ClickTrackingElementData, EventType } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\nexport class ClickHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly lastClickTimes: Map<string, number> = new Map();\n private clickHandler?: (event: Event) => void;\n private lastPruneTime = 0;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n if (this.clickHandler) {\n return;\n }\n\n this.clickHandler = (event: Event): void => {\n const mouseEvent = event as MouseEvent;\n const target = mouseEvent.target;\n const clickedElement =\n typeof HTMLElement !== 'undefined' && target instanceof HTMLElement\n ? target\n : typeof HTMLElement !== 'undefined' && target instanceof Node && target.parentElement instanceof HTMLElement\n ? target.parentElement\n : null;\n\n if (!clickedElement) {\n log('warn', 'Click target not found or not an element');\n return;\n }\n\n if (this.shouldIgnoreElement(clickedElement)) {\n return;\n }\n\n // Throttle clicks per element to prevent double-clicks and spam\n const clickThrottleMs = this.get('config')?.clickThrottleMs ?? DEFAULT_CLICK_THROTTLE_MS;\n if (clickThrottleMs > 0 && !this.checkClickThrottle(clickedElement, clickThrottleMs)) {\n return;\n }\n\n const trackingElement = this.findTrackingElement(clickedElement);\n const relevantClickElement = this.getRelevantClickElement(clickedElement);\n const coordinates = this.calculateClickCoordinates(mouseEvent, clickedElement);\n\n if (trackingElement) {\n const trackingData = this.extractTrackingData(trackingElement);\n\n if (trackingData) {\n const attributeData = this.createCustomEventData(trackingData);\n\n this.eventManager.track({\n type: EventType.CUSTOM,\n custom_event: {\n name: attributeData.name,\n ...(attributeData.value && { metadata: { value: attributeData.value } }),\n },\n });\n }\n }\n\n const clickData = this.generateClickData(clickedElement, relevantClickElement, coordinates);\n\n this.eventManager.track({\n type: EventType.CLICK,\n click_data: clickData,\n });\n };\n\n window.addEventListener('click', this.clickHandler, true);\n }\n\n stopTracking(): void {\n if (this.clickHandler) {\n window.removeEventListener('click', this.clickHandler, true);\n this.clickHandler = undefined;\n }\n this.lastClickTimes.clear();\n this.lastPruneTime = 0;\n }\n\n private shouldIgnoreElement(element: HTMLElement): boolean {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-ignore`)) {\n return true;\n }\n\n const parent = element.closest(`[${HTML_DATA_ATTR_PREFIX}-ignore]`);\n\n return parent !== null;\n }\n\n /**\n * Checks per-element click throttling to prevent double-clicks and rapid spam\n * Returns true if the click should be tracked, false if throttled\n */\n private checkClickThrottle(element: HTMLElement, throttleMs: number): boolean {\n const signature = this.getElementSignature(element);\n const now = Date.now();\n\n // Prune cache periodically to prevent unbounded growth\n this.pruneThrottleCache(now);\n\n const lastClickTime = this.lastClickTimes.get(signature);\n\n if (lastClickTime !== undefined && now - lastClickTime < throttleMs) {\n log('debug', 'ClickHandler: Click suppressed by throttle', {\n data: {\n signature,\n throttleRemaining: throttleMs - (now - lastClickTime),\n },\n });\n return false;\n }\n\n this.lastClickTimes.set(signature, now);\n return true;\n }\n\n /**\n * Prunes stale entries from the throttle cache to prevent memory leaks\n * Uses TTL-based eviction (5 minutes) and enforces max size limit\n * Called during checkClickThrottle with built-in rate limiting (every 30 seconds)\n */\n private pruneThrottleCache(now: number): void {\n if (now - this.lastPruneTime < THROTTLE_PRUNE_INTERVAL_MS) {\n return;\n }\n\n this.lastPruneTime = now;\n const cutoff = now - THROTTLE_ENTRY_TTL_MS;\n\n // Remove entries older than TTL\n for (const [key, timestamp] of this.lastClickTimes.entries()) {\n if (timestamp < cutoff) {\n this.lastClickTimes.delete(key);\n }\n }\n\n // Enforce max size limit (LRU eviction)\n if (this.lastClickTimes.size > MAX_THROTTLE_CACHE_ENTRIES) {\n const entries = Array.from(this.lastClickTimes.entries()).sort((a, b) => a[1] - b[1]); // Sort by timestamp (oldest first)\n\n const excessCount = this.lastClickTimes.size - MAX_THROTTLE_CACHE_ENTRIES;\n const toDelete = entries.slice(0, excessCount);\n\n for (const [key] of toDelete) {\n this.lastClickTimes.delete(key);\n }\n\n log('debug', 'ClickHandler: Pruned throttle cache', {\n data: {\n removed: toDelete.length,\n remaining: this.lastClickTimes.size,\n },\n });\n }\n }\n\n /**\n * Creates a stable signature for an element to track throttling\n * Priority: id > data-testid > data-tlog-name > DOM path\n */\n private getElementSignature(element: HTMLElement): string {\n // Priority 1: Element ID (most stable)\n if (element.id) {\n return `#${element.id}`;\n }\n\n // Priority 2: data-testid (common in tests)\n const testId = element.getAttribute('data-testid');\n if (testId) {\n return `[data-testid=\"${testId}\"]`;\n }\n\n // Priority 3: data-tlog-name (our own tracking attribute)\n const tlogName = element.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n if (tlogName) {\n return `[${HTML_DATA_ATTR_PREFIX}-name=\"${tlogName}\"]`;\n }\n\n // Priority 4: Generate DOM path as fallback\n return this.getElementPath(element);\n }\n\n /**\n * Generates a DOM path for an element (e.g., \"body>div>button\")\n */\n private getElementPath(element: HTMLElement): string {\n const path: string[] = [];\n let current: HTMLElement | null = element;\n\n while (current && current !== document.body) {\n let selector = current.tagName.toLowerCase();\n\n // Add class if available (first class only for brevity)\n if (current.className) {\n const firstClass = current.className.split(' ')[0];\n if (firstClass) {\n selector += `.${firstClass}`;\n }\n }\n\n path.unshift(selector);\n current = current.parentElement;\n }\n\n return path.join('>') || 'unknown';\n }\n\n private findTrackingElement(element: HTMLElement): HTMLElement | undefined {\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-name`)) {\n return element;\n }\n\n const closest = element.closest(`[${HTML_DATA_ATTR_PREFIX}-name]`) as HTMLElement;\n\n return closest;\n }\n\n private getRelevantClickElement(element: HTMLElement): HTMLElement {\n for (const selector of INTERACTIVE_SELECTORS) {\n try {\n if (element.matches(selector)) {\n return element;\n }\n\n const parent = element.closest(selector) as HTMLElement;\n\n if (parent) {\n return parent;\n }\n } catch (error) {\n log('warn', 'Invalid selector in element search', { error, data: { selector } });\n continue;\n }\n }\n\n return element;\n }\n\n private clamp(value: number): number {\n return Math.max(0, Math.min(1, Number(value.toFixed(3))));\n }\n\n private calculateClickCoordinates(event: MouseEvent, element: HTMLElement): ClickCoordinates {\n const rect = element.getBoundingClientRect();\n const x = event.clientX;\n const y = event.clientY;\n const relativeX = rect.width > 0 ? this.clamp((x - rect.left) / rect.width) : 0;\n const relativeY = rect.height > 0 ? this.clamp((y - rect.top) / rect.height) : 0;\n\n return { x, y, relativeX, relativeY };\n }\n\n private extractTrackingData(trackingElement: HTMLElement): ClickTrackingElementData | undefined {\n const name = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-name`);\n const value = trackingElement.getAttribute(`${HTML_DATA_ATTR_PREFIX}-value`);\n\n if (!name) {\n return undefined;\n }\n\n return {\n element: trackingElement,\n name,\n ...(value && { value }),\n };\n }\n\n private generateClickData(\n clickedElement: HTMLElement,\n relevantElement: HTMLElement,\n coordinates: ClickCoordinates,\n ): ClickData {\n const { x, y, relativeX, relativeY } = coordinates;\n const text = this.getRelevantText(clickedElement, relevantElement);\n const attributes = this.extractElementAttributes(relevantElement);\n\n return {\n x,\n y,\n relativeX,\n relativeY,\n tag: relevantElement.tagName.toLowerCase(),\n ...(relevantElement.id && { id: relevantElement.id }),\n ...(relevantElement.className && { class: relevantElement.className }),\n ...(text && { text }),\n ...(attributes.href && { href: attributes.href }),\n ...(attributes.title && { title: attributes.title }),\n ...(attributes.alt && { alt: attributes.alt }),\n ...(attributes.role && { role: attributes.role }),\n ...(attributes['aria-label'] && { ariaLabel: attributes['aria-label'] }),\n ...(Object.keys(attributes).length > 0 && { dataAttributes: attributes }),\n };\n }\n\n private sanitizeText(text: string): string {\n let sanitized = text;\n\n for (const pattern of PII_PATTERNS) {\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private getRelevantText(clickedElement: HTMLElement, relevantElement: HTMLElement): string {\n const clickedText = clickedElement.textContent?.trim() ?? '';\n const relevantText = relevantElement.textContent?.trim() ?? '';\n\n if (!clickedText && !relevantText) {\n return '';\n }\n\n let finalText = '';\n\n if (clickedText && clickedText.length <= MAX_TEXT_LENGTH) {\n finalText = clickedText;\n } else if (relevantText.length <= MAX_TEXT_LENGTH) {\n finalText = relevantText;\n } else {\n finalText = relevantText.slice(0, MAX_TEXT_LENGTH - 3) + '...';\n }\n\n return this.sanitizeText(finalText);\n }\n\n private extractElementAttributes(element: HTMLElement): Record<string, string> {\n const commonAttributes = [\n 'id',\n 'class',\n 'data-testid',\n 'aria-label',\n 'title',\n 'href',\n 'type',\n 'name',\n 'alt',\n 'role',\n ];\n const result: Record<string, string> = {};\n\n for (const attributeName of commonAttributes) {\n const value = element.getAttribute(attributeName);\n\n if (value) {\n result[attributeName] = value;\n }\n }\n\n return result;\n }\n\n private createCustomEventData(trackingData: ClickTrackingElementData): { name: string; value?: string } {\n return {\n name: trackingData.name,\n ...(trackingData.value && { value: trackingData.value }),\n };\n }\n}\n","import {\n MAX_SCROLL_EVENTS_PER_SESSION,\n MIN_SCROLL_DEPTH_CHANGE,\n SCROLL_DEBOUNCE_TIME_MS,\n SCROLL_MIN_EVENT_INTERVAL_MS,\n SIGNIFICANT_SCROLL_DELTA,\n} from '../constants';\nimport { EventType, ScrollData, ScrollDirection } from '../types';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { log } from '../utils';\n\ninterface ScrollContainer {\n element: Window | HTMLElement;\n selector: string;\n isPrimary: boolean;\n lastScrollPos: number;\n lastDepth: number;\n lastDirection: ScrollDirection;\n lastEventTime: number;\n firstScrollEventTime: number | null;\n maxDepthReached: number;\n debounceTimer: number | null;\n listener: EventListener;\n}\n\nexport class ScrollHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly containers: ScrollContainer[] = [];\n private limitWarningLogged = false;\n private minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n private minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n private maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n private containerDiscoveryTimeoutId: number | null = null;\n\n constructor(eventManager: EventManager) {\n super();\n\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n this.limitWarningLogged = false;\n this.applyConfigOverrides();\n this.set('scrollEventCount', 0);\n this.tryDetectScrollContainers(0);\n }\n\n stopTracking(): void {\n if (this.containerDiscoveryTimeoutId !== null) {\n clearTimeout(this.containerDiscoveryTimeoutId);\n this.containerDiscoveryTimeoutId = null;\n }\n\n for (const container of this.containers) {\n this.clearContainerTimer(container);\n\n if (container.element === window) {\n window.removeEventListener('scroll', container.listener);\n } else {\n (container.element as HTMLElement).removeEventListener('scroll', container.listener);\n }\n }\n\n this.containers.length = 0;\n this.set('scrollEventCount', 0);\n this.limitWarningLogged = false;\n }\n\n private tryDetectScrollContainers(attempt: number): void {\n const elements = this.findScrollableElements();\n\n if (this.isWindowScrollable()) {\n this.setupScrollContainer(window, 'window');\n }\n\n if (elements.length > 0) {\n for (const element of elements) {\n const selector = this.getElementSelector(element);\n this.setupScrollContainer(element, selector);\n }\n\n this.applyPrimaryScrollSelectorIfConfigured();\n\n return;\n }\n\n if (attempt < 5) {\n this.containerDiscoveryTimeoutId = window.setTimeout(() => {\n this.containerDiscoveryTimeoutId = null;\n this.tryDetectScrollContainers(attempt + 1);\n }, 200);\n\n return;\n }\n\n if (this.containers.length === 0) {\n this.setupScrollContainer(window, 'window');\n }\n\n this.applyPrimaryScrollSelectorIfConfigured();\n }\n\n private applyPrimaryScrollSelectorIfConfigured(): void {\n const config = this.get('config');\n\n if (config?.primaryScrollSelector) {\n this.applyPrimaryScrollSelector(config.primaryScrollSelector);\n }\n }\n\n private findScrollableElements(): HTMLElement[] {\n if (!document.body) {\n return [];\n }\n\n const elements: HTMLElement[] = [];\n\n const walker = document.createTreeWalker(document.body, NodeFilter.SHOW_ELEMENT, {\n acceptNode: (node) => {\n const element = node as HTMLElement;\n\n if (!element.isConnected || !element.offsetParent) {\n return NodeFilter.FILTER_SKIP;\n }\n\n const style = getComputedStyle(element);\n\n const hasVerticalScrollableStyle =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n return hasVerticalScrollableStyle ? NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_SKIP;\n },\n });\n\n let node: Node | null;\n\n while ((node = walker.nextNode()) && elements.length < 10) {\n const element = node as HTMLElement;\n\n if (this.isElementScrollable(element)) {\n elements.push(element);\n }\n }\n\n return elements;\n }\n\n private getElementSelector(element: Window | HTMLElement): string {\n if (element === window) {\n return 'window';\n }\n\n const htmlElement = element as HTMLElement;\n\n if (htmlElement.id) {\n return `#${htmlElement.id}`;\n }\n\n if (htmlElement.className && typeof htmlElement.className === 'string') {\n const firstClass = htmlElement.className.split(' ').filter((c) => c.trim())[0];\n\n if (firstClass) {\n return `.${firstClass}`;\n }\n }\n\n return htmlElement.tagName.toLowerCase();\n }\n\n private determineIfPrimary(element: Window | HTMLElement): boolean {\n // Window scrollable → window is primary\n if (this.isWindowScrollable()) {\n return element === window;\n }\n\n // Window not scrollable → first detected container is primary\n return this.containers.length === 0;\n }\n\n private setupScrollContainer(element: Window | HTMLElement, selector: string): void {\n const alreadyTracking = this.containers.some((c) => c.element === element);\n\n if (alreadyTracking) {\n return;\n }\n\n if (element !== window && !this.isElementScrollable(element as HTMLElement)) {\n return;\n }\n\n const initialScrollTop = this.getScrollTop(element);\n\n const initialDepth = this.calculateScrollDepth(\n initialScrollTop,\n this.getScrollHeight(element),\n this.getViewportHeight(element),\n );\n\n const isPrimary = this.determineIfPrimary(element);\n\n const container: ScrollContainer = {\n element,\n selector,\n isPrimary,\n lastScrollPos: initialScrollTop,\n lastDepth: initialDepth,\n lastDirection: ScrollDirection.DOWN,\n lastEventTime: 0,\n firstScrollEventTime: null,\n maxDepthReached: initialDepth,\n debounceTimer: null,\n listener: null as any,\n };\n\n const handleScroll = (): void => {\n if (this.get('suppressNextScroll')) {\n return;\n }\n\n if (container.firstScrollEventTime === null) {\n container.firstScrollEventTime = Date.now();\n }\n\n this.clearContainerTimer(container);\n\n container.debounceTimer = window.setTimeout(() => {\n const scrollData = this.calculateScrollData(container);\n\n if (scrollData) {\n const now = Date.now();\n\n this.processScrollEvent(container, scrollData, now);\n }\n\n container.debounceTimer = null;\n }, SCROLL_DEBOUNCE_TIME_MS);\n };\n\n container.listener = handleScroll;\n\n this.containers.push(container);\n\n if (element === window) {\n window.addEventListener('scroll', handleScroll, { passive: true });\n } else {\n (element as HTMLElement).addEventListener('scroll', handleScroll, { passive: true });\n }\n }\n\n private processScrollEvent(\n container: ScrollContainer,\n scrollData: Omit<ScrollData, 'container_selector' | 'is_primary'>,\n timestamp: number,\n ): void {\n if (!this.shouldEmitScrollEvent(container, scrollData, timestamp)) {\n return;\n }\n\n container.lastEventTime = timestamp;\n container.lastDepth = scrollData.depth;\n container.lastDirection = scrollData.direction;\n\n const currentCount = this.get('scrollEventCount') ?? 0;\n this.set('scrollEventCount', currentCount + 1);\n\n this.eventManager.track({\n type: EventType.SCROLL,\n scroll_data: {\n ...scrollData,\n container_selector: container.selector,\n is_primary: container.isPrimary,\n },\n });\n }\n\n private shouldEmitScrollEvent(\n container: ScrollContainer,\n scrollData: Omit<ScrollData, 'container_selector' | 'is_primary'>,\n timestamp: number,\n ): boolean {\n if (this.hasReachedSessionLimit()) {\n this.logLimitOnce();\n return false;\n }\n\n if (!this.hasElapsedMinimumInterval(container, timestamp)) {\n return false;\n }\n\n if (!this.hasSignificantDepthChange(container, scrollData.depth)) {\n return false;\n }\n\n return true;\n }\n\n private hasReachedSessionLimit(): boolean {\n const currentCount = this.get('scrollEventCount') ?? 0;\n return currentCount >= this.maxEventsPerSession;\n }\n\n private hasElapsedMinimumInterval(container: ScrollContainer, timestamp: number): boolean {\n if (container.lastEventTime === 0) {\n return true;\n }\n return timestamp - container.lastEventTime >= this.minIntervalMs;\n }\n\n private hasSignificantDepthChange(container: ScrollContainer, newDepth: number): boolean {\n return Math.abs(newDepth - container.lastDepth) >= this.minDepthChange;\n }\n\n private logLimitOnce(): void {\n if (this.limitWarningLogged) {\n return;\n }\n\n this.limitWarningLogged = true;\n\n log('warn', 'Max scroll events per session reached', {\n data: { limit: this.maxEventsPerSession },\n });\n }\n\n private applyConfigOverrides(): void {\n this.minDepthChange = MIN_SCROLL_DEPTH_CHANGE;\n this.minIntervalMs = SCROLL_MIN_EVENT_INTERVAL_MS;\n this.maxEventsPerSession = MAX_SCROLL_EVENTS_PER_SESSION;\n }\n\n private isWindowScrollable(): boolean {\n return document.documentElement.scrollHeight > window.innerHeight;\n }\n\n private clearContainerTimer(container: ScrollContainer): void {\n if (container.debounceTimer !== null) {\n clearTimeout(container.debounceTimer);\n container.debounceTimer = null;\n }\n }\n\n private getScrollDirection(current: number, previous: number): ScrollDirection {\n return current > previous ? ScrollDirection.DOWN : ScrollDirection.UP;\n }\n\n private calculateScrollDepth(scrollTop: number, scrollHeight: number, viewportHeight: number): number {\n if (scrollHeight <= viewportHeight) {\n return 0;\n }\n\n const maxScrollTop = scrollHeight - viewportHeight;\n return Math.min(100, Math.max(0, Math.floor((scrollTop / maxScrollTop) * 100)));\n }\n\n private calculateScrollData(\n container: ScrollContainer,\n ): Omit<ScrollData, 'container_selector' | 'is_primary'> | null {\n const { element, lastScrollPos, lastEventTime } = container;\n const scrollTop = this.getScrollTop(element);\n const now = Date.now();\n\n const positionDelta = Math.abs(scrollTop - lastScrollPos);\n if (positionDelta < SIGNIFICANT_SCROLL_DELTA) {\n return null;\n }\n\n if (element === window && !this.isWindowScrollable()) {\n return null;\n }\n\n const viewportHeight = this.getViewportHeight(element);\n const scrollHeight = this.getScrollHeight(element);\n const direction = this.getScrollDirection(scrollTop, lastScrollPos);\n const depth = this.calculateScrollDepth(scrollTop, scrollHeight, viewportHeight);\n\n let timeDelta: number;\n\n if (lastEventTime > 0) {\n timeDelta = now - lastEventTime;\n } else if (container.firstScrollEventTime !== null) {\n timeDelta = now - container.firstScrollEventTime;\n } else {\n timeDelta = SCROLL_DEBOUNCE_TIME_MS;\n }\n\n const velocity = Math.round((positionDelta / timeDelta) * 1000);\n\n if (depth > container.maxDepthReached) {\n container.maxDepthReached = depth;\n }\n\n container.lastScrollPos = scrollTop;\n\n return {\n depth,\n direction,\n velocity,\n max_depth_reached: container.maxDepthReached,\n };\n }\n\n private getScrollTop(element: Window | HTMLElement): number {\n return element === window ? window.scrollY : (element as HTMLElement).scrollTop;\n }\n\n private getViewportHeight(element: Window | HTMLElement): number {\n return element === window ? window.innerHeight : (element as HTMLElement).clientHeight;\n }\n\n private getScrollHeight(element: Window | HTMLElement): number {\n return element === window ? document.documentElement.scrollHeight : (element as HTMLElement).scrollHeight;\n }\n\n private isElementScrollable(element: HTMLElement): boolean {\n const style = getComputedStyle(element);\n\n const hasVerticalScrollableOverflow =\n style.overflowY === 'auto' ||\n style.overflowY === 'scroll' ||\n style.overflow === 'auto' ||\n style.overflow === 'scroll';\n\n const hasVerticalOverflowContent = element.scrollHeight > element.clientHeight;\n\n return hasVerticalScrollableOverflow && hasVerticalOverflowContent;\n }\n\n private applyPrimaryScrollSelector(selector: string): void {\n let targetElement: Window | HTMLElement;\n\n if (selector === 'window') {\n targetElement = window;\n } else {\n const element = document.querySelector(selector);\n if (!(element instanceof HTMLElement)) {\n log('warn', `Selector \"${selector}\" did not match an HTMLElement`);\n return;\n }\n targetElement = element;\n }\n\n this.containers.forEach((container) => {\n this.updateContainerPrimary(container, container.element === targetElement);\n });\n\n const targetAlreadyTracked = this.containers.some((c) => c.element === targetElement);\n if (!targetAlreadyTracked && targetElement instanceof HTMLElement) {\n if (this.isElementScrollable(targetElement)) {\n this.setupScrollContainer(targetElement, selector);\n }\n }\n }\n\n private updateContainerPrimary(container: ScrollContainer, isPrimary: boolean): void {\n container.isPrimary = isPrimary;\n }\n}\n","import {\n HTML_DATA_ATTR_PREFIX,\n DEFAULT_VIEWPORT_COOLDOWN_PERIOD,\n DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS,\n VIEWPORT_MUTATION_DEBOUNCE_MS,\n} from '../constants';\nimport { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, ViewportConfig, ViewportEventData } from '../types';\nimport { log } from '../utils';\n\ninterface TrackedElement {\n element: Element;\n selector: string;\n id?: string;\n name?: string;\n startTime: number | null;\n timeoutId: number | null;\n lastFiredTime: number | null;\n}\n\n/**\n * Handles viewport visibility tracking using IntersectionObserver API.\n * Fires events when elements become visible for a minimum dwell time.\n */\nexport class ViewportHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly trackedElements = new Map<Element, TrackedElement>();\n private observer: IntersectionObserver | null = null;\n private mutationObserver: MutationObserver | null = null;\n private mutationDebounceTimer: number | null = null;\n private config: ViewportConfig | null = null;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n /**\n * Starts tracking viewport visibility for configured elements\n */\n startTracking(): void {\n // Get viewport config from state\n const config = this.get('config');\n this.config = config.viewport ?? null;\n\n if (!this.config?.elements || this.config.elements.length === 0) {\n return;\n }\n\n // Set defaults\n const threshold = this.config.threshold ?? 0.5;\n const minDwellTime = this.config.minDwellTime ?? 1000;\n\n if (threshold < 0 || threshold > 1) {\n log('warn', 'ViewportHandler: Invalid threshold, must be between 0 and 1');\n return;\n }\n\n if (minDwellTime < 0) {\n log('warn', 'ViewportHandler: Invalid minDwellTime, must be non-negative');\n return;\n }\n\n // Check IntersectionObserver support\n if (typeof IntersectionObserver === 'undefined') {\n log('warn', 'ViewportHandler: IntersectionObserver not supported in this browser');\n return;\n }\n\n // Create observer\n this.observer = new IntersectionObserver(this.handleIntersection, {\n threshold,\n });\n\n // Find and observe all matching elements\n this.observeElements();\n\n // Set up MutationObserver to detect dynamically added elements\n this.setupMutationObserver();\n }\n\n /**\n * Stops tracking and cleans up resources\n */\n stopTracking(): void {\n // Disconnect observers\n if (this.observer) {\n this.observer.disconnect();\n this.observer = null;\n }\n\n if (this.mutationObserver) {\n this.mutationObserver.disconnect();\n this.mutationObserver = null;\n }\n\n // Clear debounce timer\n if (this.mutationDebounceTimer !== null) {\n window.clearTimeout(this.mutationDebounceTimer);\n this.mutationDebounceTimer = null;\n }\n\n // Clear all timers and tracked elements\n for (const tracked of this.trackedElements.values()) {\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n }\n }\n\n this.trackedElements.clear();\n }\n\n /**\n * Query and observe all elements matching configured elements\n */\n private observeElements(): void {\n if (!this.config || !this.observer) return;\n\n const maxTrackedElements = this.config.maxTrackedElements ?? DEFAULT_VIEWPORT_MAX_TRACKED_ELEMENTS;\n let totalTracked = this.trackedElements.size;\n\n for (const elementConfig of this.config.elements) {\n try {\n const elements = document.querySelectorAll(elementConfig.selector);\n\n for (const element of Array.from(elements)) {\n // Check max limit (Phase 3)\n if (totalTracked >= maxTrackedElements) {\n log('warn', 'ViewportHandler: Maximum tracked elements reached', {\n data: {\n limit: maxTrackedElements,\n selector: elementConfig.selector,\n message: 'Some elements will not be tracked. Consider more specific selectors.',\n },\n });\n return; // Stop tracking more elements\n }\n\n // Skip if element has data-tlog-ignore attribute\n if (element.hasAttribute(`${HTML_DATA_ATTR_PREFIX}-ignore`)) {\n continue;\n }\n\n // Skip if already tracked\n if (this.trackedElements.has(element)) {\n continue;\n }\n\n // Track and observe element with identifiers\n this.trackedElements.set(element, {\n element,\n selector: elementConfig.selector,\n id: elementConfig.id,\n name: elementConfig.name,\n startTime: null,\n timeoutId: null,\n lastFiredTime: null,\n });\n\n this.observer?.observe(element);\n totalTracked++;\n }\n } catch (error) {\n log('warn', `ViewportHandler: Invalid selector \"${elementConfig.selector}\"`, { error });\n }\n }\n\n log('debug', 'ViewportHandler: Elements tracked', {\n data: { count: totalTracked, limit: maxTrackedElements },\n });\n }\n\n /**\n * Handles intersection events from IntersectionObserver\n */\n private readonly handleIntersection = (entries: IntersectionObserverEntry[]): void => {\n if (!this.config) return;\n\n const minDwellTime = this.config.minDwellTime ?? 1000;\n\n for (const entry of entries) {\n const tracked = this.trackedElements.get(entry.target);\n if (!tracked) continue;\n\n if (entry.isIntersecting) {\n // Element became visible\n if (tracked.startTime === null) {\n tracked.startTime = performance.now();\n\n // Set timer to fire event after minDwellTime\n tracked.timeoutId = window.setTimeout(() => {\n const visibilityRatio = Math.round(entry.intersectionRatio * 100) / 100;\n this.fireViewportEvent(tracked, visibilityRatio);\n }, minDwellTime);\n }\n } else {\n // Element became hidden\n if (tracked.startTime !== null) {\n // Clear timer if element hidden before minDwellTime elapsed\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n tracked.timeoutId = null;\n }\n tracked.startTime = null;\n }\n }\n }\n };\n\n /**\n * Fires a viewport visible event\n */\n private fireViewportEvent(tracked: TrackedElement, visibilityRatio: number): void {\n if (tracked.startTime === null) return;\n\n const dwellTime = Math.round(performance.now() - tracked.startTime);\n\n // Check data-tlog-ignore again (element might have changed)\n if (tracked.element.hasAttribute('data-tlog-ignore')) {\n return;\n }\n\n // Check cooldown period to prevent repeated events from carousels/sticky elements\n const cooldownPeriod = this.config?.cooldownPeriod ?? DEFAULT_VIEWPORT_COOLDOWN_PERIOD;\n const now = Date.now();\n if (tracked.lastFiredTime !== null && now - tracked.lastFiredTime < cooldownPeriod) {\n log('debug', 'ViewportHandler: Event suppressed by cooldown period', {\n data: {\n selector: tracked.selector,\n cooldownRemaining: cooldownPeriod - (now - tracked.lastFiredTime),\n },\n });\n tracked.startTime = null;\n tracked.timeoutId = null;\n return;\n }\n\n const eventData: ViewportEventData = {\n selector: tracked.selector,\n dwellTime,\n visibilityRatio,\n ...(tracked.id !== undefined && { id: tracked.id }),\n ...(tracked.name !== undefined && { name: tracked.name }),\n };\n\n this.eventManager.track({\n type: EventType.VIEWPORT_VISIBLE,\n viewport_data: eventData,\n });\n\n // Reset tracking state after firing event and record timestamp\n tracked.startTime = null;\n tracked.timeoutId = null;\n tracked.lastFiredTime = now;\n }\n\n /**\n * Sets up MutationObserver to detect dynamically added elements\n */\n private setupMutationObserver(): void {\n if (!this.config || typeof MutationObserver === 'undefined') {\n return;\n }\n\n // Check if document.body exists\n if (!document.body) {\n log('warn', 'ViewportHandler: document.body not available, skipping MutationObserver setup');\n return;\n }\n\n this.mutationObserver = new MutationObserver((mutations) => {\n let hasAddedNodes = false;\n\n // Check what changed\n for (const mutation of mutations) {\n if (mutation.type === 'childList') {\n if (mutation.addedNodes.length > 0) {\n hasAddedNodes = true;\n }\n if (mutation.removedNodes.length > 0) {\n // Clean up removed nodes immediately\n this.cleanupRemovedNodes(mutation.removedNodes);\n }\n }\n }\n\n // Debounce re-observing for added nodes (batch multiple mutations)\n if (hasAddedNodes) {\n if (this.mutationDebounceTimer !== null) {\n window.clearTimeout(this.mutationDebounceTimer);\n }\n this.mutationDebounceTimer = window.setTimeout(() => {\n this.observeElements();\n this.mutationDebounceTimer = null;\n }, VIEWPORT_MUTATION_DEBOUNCE_MS);\n }\n });\n\n // Observe the entire document for added/removed nodes\n this.mutationObserver.observe(document.body, {\n childList: true,\n subtree: true,\n });\n }\n\n /**\n * Cleans up tracking for removed DOM nodes\n */\n private cleanupRemovedNodes(removedNodes: NodeList): void {\n removedNodes.forEach((node) => {\n if (node.nodeType !== 1) return; // 1 = ELEMENT_NODE\n\n const element = node as Element;\n const tracked = this.trackedElements.get(element);\n\n if (tracked) {\n // Clear pending timer\n if (tracked.timeoutId !== null) {\n window.clearTimeout(tracked.timeoutId);\n }\n\n // Unobserve and remove from tracking\n this.observer?.unobserve(element);\n this.trackedElements.delete(element);\n }\n\n // Also check descendants\n const descendants = Array.from(this.trackedElements.keys()).filter((el) => element.contains(el));\n descendants.forEach((el) => {\n const descendantTracked = this.trackedElements.get(el);\n if (descendantTracked && descendantTracked.timeoutId !== null) {\n window.clearTimeout(descendantTracked.timeoutId);\n }\n this.observer?.unobserve(el);\n this.trackedElements.delete(el);\n });\n });\n }\n}\n","import { MetadataType } from '../types';\nimport { log } from '../utils';\nimport { StateManager } from '../managers/state.manager';\n\ndeclare global {\n interface Window {\n gtag?: (...args: unknown[]) => void;\n dataLayer?: unknown[];\n }\n}\n\nexport class GoogleAnalyticsIntegration extends StateManager {\n private isInitialized = false;\n\n async initialize(): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n const measurementId = this.get('config').integrations?.googleAnalytics?.measurementId;\n const userId = this.get('userId');\n\n if (!measurementId?.trim() || !userId?.trim()) {\n return;\n }\n\n try {\n if (this.isScriptAlreadyLoaded()) {\n this.isInitialized = true;\n return;\n }\n\n await this.loadScript(measurementId);\n this.configureGtag(measurementId, userId);\n this.isInitialized = true;\n } catch (error) {\n log('error', 'Google Analytics initialization failed', { error });\n }\n }\n\n trackEvent(eventName: string, metadata: Record<string, MetadataType> | Record<string, MetadataType>[]): void {\n if (!eventName?.trim() || !this.isInitialized || typeof window.gtag !== 'function') {\n return;\n }\n\n try {\n const normalizedMetadata = Array.isArray(metadata) ? { items: metadata } : metadata;\n window.gtag('event', eventName, normalizedMetadata);\n } catch (error) {\n log('error', 'Google Analytics event tracking failed', { error });\n }\n }\n\n cleanup(): void {\n this.isInitialized = false;\n const script = document.getElementById('tracelog-ga-script');\n if (script) {\n script.remove();\n }\n }\n\n private isScriptAlreadyLoaded(): boolean {\n // Check if we already loaded the script\n if (document.getElementById('tracelog-ga-script')) {\n return true;\n }\n\n // Check if GA is already loaded by another source\n const existingGAScript = document.querySelector('script[src*=\"googletagmanager.com/gtag/js\"]');\n return !!existingGAScript;\n }\n\n private async loadScript(measurementId: string): Promise<void> {\n return new Promise((resolve, reject) => {\n const script = document.createElement('script');\n script.id = 'tracelog-ga-script';\n script.async = true;\n script.src = `https://www.googletagmanager.com/gtag/js?id=${measurementId}`;\n\n script.onload = () => {\n resolve();\n };\n script.onerror = () => {\n reject(new Error('Failed to load Google Analytics script'));\n };\n\n document.head.appendChild(script);\n });\n }\n\n private configureGtag(measurementId: string, userId: string): void {\n const gaScriptConfig = document.createElement('script');\n gaScriptConfig.innerHTML = `\n window.dataLayer = window.dataLayer || [];\n function gtag(){dataLayer.push(arguments);}\n gtag('js', new Date());\n gtag('config', '${measurementId}', {\n 'user_id': '${userId}'\n });\n `;\n document.head.appendChild(gaScriptConfig);\n }\n}\n","import { log } from '../utils';\n\n/**\n * Manages localStorage and sessionStorage with automatic fallback to in-memory storage.\n * Provides a consistent interface for storing session data, configuration,\n * and analytics metadata across browser environments.\n */\nexport class StorageManager {\n private readonly storage: Storage | null;\n private readonly sessionStorageRef: Storage | null;\n private readonly fallbackStorage = new Map<string, string>();\n private readonly fallbackSessionStorage = new Map<string, string>();\n\n private hasQuotaExceededError = false;\n\n constructor() {\n this.storage = this.initializeStorage('localStorage');\n this.sessionStorageRef = this.initializeStorage('sessionStorage');\n\n if (!this.storage) {\n log('warn', 'localStorage not available, using memory fallback');\n }\n if (!this.sessionStorageRef) {\n log('warn', 'sessionStorage not available, using memory fallback');\n }\n }\n\n /**\n * Retrieves an item from storage\n */\n getItem(key: string): string | null {\n try {\n if (this.storage) {\n return this.storage.getItem(key);\n }\n return this.fallbackStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in storage\n */\n setItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n // This ensures fallback is in sync and can serve as backup if storage fails\n this.fallbackStorage.set(key, value);\n\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n this.hasQuotaExceededError = true;\n\n log('warn', 'localStorage quota exceeded, attempting cleanup', {\n data: { key, valueSize: value.length },\n });\n\n // Attempt to free up space by removing old TraceLog data\n const cleanedUp = this.cleanupOldData();\n\n if (cleanedUp) {\n // Retry after cleanup\n try {\n if (this.storage) {\n this.storage.setItem(key, value);\n // Successfully stored after cleanup\n return;\n }\n } catch (retryError) {\n log('error', 'localStorage quota exceeded even after cleanup - data will not persist', {\n error: retryError,\n data: { key, valueSize: value.length },\n });\n }\n } else {\n log('error', 'localStorage quota exceeded and no data to cleanup - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from storage\n */\n removeItem(key: string): void {\n try {\n if (this.storage) {\n this.storage.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackStorage.delete(key);\n }\n\n /**\n * Clears all TracLog-related items from storage\n */\n clear(): void {\n if (!this.storage) {\n this.fallbackStorage.clear();\n return;\n }\n\n try {\n const keysToRemove: string[] = [];\n\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n keysToRemove.push(key);\n }\n }\n\n keysToRemove.forEach((key) => {\n this.storage!.removeItem(key);\n });\n this.fallbackStorage.clear();\n } catch (error) {\n log('error', 'Failed to clear storage', { error });\n this.fallbackStorage.clear();\n }\n }\n\n /**\n * Checks if storage is available\n */\n isAvailable(): boolean {\n return this.storage !== null;\n }\n\n /**\n * Checks if a QuotaExceededError has occurred\n * This indicates localStorage is full and data may not persist\n */\n hasQuotaError(): boolean {\n return this.hasQuotaExceededError;\n }\n\n /**\n * Attempts to cleanup old TraceLog data from storage to free up space\n * Returns true if any data was removed, false otherwise\n */\n private cleanupOldData(): boolean {\n if (!this.storage) {\n return false;\n }\n\n try {\n const tracelogKeys: string[] = [];\n const persistedEventsKeys: string[] = [];\n\n // Collect all TraceLog keys\n for (let i = 0; i < this.storage.length; i++) {\n const key = this.storage.key(i);\n if (key?.startsWith('tracelog_')) {\n tracelogKeys.push(key);\n\n // Prioritize removing old persisted events\n if (key.startsWith('tracelog_persisted_events_')) {\n persistedEventsKeys.push(key);\n }\n }\n }\n\n // First, try to remove old persisted events (usually the largest data)\n if (persistedEventsKeys.length > 0) {\n persistedEventsKeys.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n // If no persisted events, remove non-critical keys\n // Define critical key prefixes that should be preserved\n const criticalPrefixes = ['tracelog_session_', 'tracelog_user_id', 'tracelog_device_id', 'tracelog_config'];\n\n const nonCriticalKeys = tracelogKeys.filter((key) => {\n // Keep keys that start with any critical prefix\n return !criticalPrefixes.some((prefix) => key.startsWith(prefix));\n });\n\n if (nonCriticalKeys.length > 0) {\n // Remove up to 5 non-critical keys\n const keysToRemove = nonCriticalKeys.slice(0, 5);\n keysToRemove.forEach((key) => {\n try {\n this.storage!.removeItem(key);\n } catch {\n // Ignore errors during cleanup\n }\n });\n\n // Successfully cleaned up - no need to log in production\n return true;\n }\n\n return false;\n } catch (error) {\n log('error', 'Failed to cleanup old data', { error });\n return false;\n }\n }\n\n /**\n * Initialize storage (localStorage or sessionStorage) with feature detection\n */\n private initializeStorage(type: 'localStorage' | 'sessionStorage'): Storage | null {\n if (typeof window === 'undefined') {\n return null;\n }\n\n try {\n const storage = type === 'localStorage' ? window.localStorage : window.sessionStorage;\n const testKey = '__tracelog_test__';\n\n storage.setItem(testKey, 'test');\n storage.removeItem(testKey);\n\n return storage;\n } catch {\n return null;\n }\n }\n\n /**\n * Retrieves an item from sessionStorage\n */\n getSessionItem(key: string): string | null {\n try {\n if (this.sessionStorageRef) {\n return this.sessionStorageRef.getItem(key);\n }\n return this.fallbackSessionStorage.get(key) ?? null;\n } catch {\n // Silent fallback - user already warned in constructor\n return this.fallbackSessionStorage.get(key) ?? null;\n }\n }\n\n /**\n * Stores an item in sessionStorage\n */\n setSessionItem(key: string, value: string): void {\n // Always update fallback FIRST for consistency\n this.fallbackSessionStorage.set(key, value);\n\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.setItem(key, value);\n return;\n }\n } catch (error) {\n if (error instanceof DOMException && error.name === 'QuotaExceededError') {\n log('error', 'sessionStorage quota exceeded - data will not persist', {\n error,\n data: { key, valueSize: value.length },\n });\n }\n // Else: Silent fallback - user already warned in constructor\n // Data is already in fallbackSessionStorage (set at beginning)\n }\n }\n\n /**\n * Removes an item from sessionStorage\n */\n removeSessionItem(key: string): void {\n try {\n if (this.sessionStorageRef) {\n this.sessionStorageRef.removeItem(key);\n }\n } catch {\n // Silent - not critical\n }\n\n // Always clean fallback\n this.fallbackSessionStorage.delete(key);\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { EventType, WebVitalType } from '../types';\nimport {\n LONG_TASK_THROTTLE_MS,\n MAX_NAVIGATION_HISTORY,\n PRECISION_TWO_DECIMALS,\n WEB_VITALS_THRESHOLDS,\n} from '../constants';\nimport { log } from '../utils';\n\ntype LayoutShiftEntry = PerformanceEntry & { value?: number; hadRecentInput?: boolean };\n\nexport class PerformanceHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly reportedByNav: Map<string, Set<string>> = new Map();\n private readonly navigationHistory: string[] = []; // FIFO queue for tracking navigation order\n private readonly observers: PerformanceObserver[] = [];\n private readonly vitalThresholds = WEB_VITALS_THRESHOLDS;\n private lastLongTaskSentAt = 0;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n async startTracking(): Promise<void> {\n await this.initWebVitals();\n this.observeLongTasks();\n }\n\n stopTracking(): void {\n this.observers.forEach((obs, index) => {\n try {\n obs.disconnect();\n } catch (error) {\n log('warn', 'Failed to disconnect performance observer', { error, data: { observerIndex: index } });\n }\n });\n\n this.observers.length = 0;\n this.reportedByNav.clear();\n this.navigationHistory.length = 0;\n }\n\n private observeWebVitalsFallback(): void {\n this.reportTTFB();\n\n this.safeObserve(\n 'largest-contentful-paint',\n (list) => {\n const entries = list.getEntries();\n const last = entries[entries.length - 1] as (PerformanceEntry & { startTime: number }) | undefined;\n\n if (!last) {\n return;\n }\n\n this.sendVital({ type: 'LCP', value: Number(last.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'largest-contentful-paint', buffered: true },\n true,\n );\n\n let clsValue = 0;\n let currentNavId = this.getNavigationId();\n\n this.safeObserve(\n 'layout-shift',\n (list) => {\n const navId = this.getNavigationId();\n\n if (navId !== currentNavId) {\n clsValue = 0;\n currentNavId = navId;\n }\n\n const entries = list.getEntries() as LayoutShiftEntry[];\n\n for (const entry of entries) {\n if (entry.hadRecentInput === true) {\n continue;\n }\n\n const value = typeof entry.value === 'number' ? entry.value : 0;\n clsValue += value;\n }\n\n this.sendVital({ type: 'CLS', value: Number(clsValue.toFixed(PRECISION_TWO_DECIMALS)) });\n },\n { type: 'layout-shift', buffered: true },\n );\n\n this.safeObserve(\n 'paint',\n (list) => {\n for (const entry of list.getEntries()) {\n if (entry.name === 'first-contentful-paint') {\n this.sendVital({ type: 'FCP', value: Number(entry.startTime.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n }\n },\n { type: 'paint', buffered: true },\n true,\n );\n\n this.safeObserve(\n 'event',\n (list) => {\n let worst = 0;\n const entries = list.getEntries() as Array<{ startTime: number; processingEnd?: number }>;\n\n for (const entry of entries) {\n const dur = (entry.processingEnd ?? 0) - (entry.startTime ?? 0);\n worst = Math.max(worst, dur);\n }\n\n if (worst > 0) {\n this.sendVital({ type: 'INP', value: Number(worst.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n },\n { type: 'event', buffered: true },\n );\n }\n\n private async initWebVitals(): Promise<void> {\n try {\n const { onLCP, onCLS, onFCP, onTTFB, onINP } = await import('web-vitals');\n\n const report =\n (type: WebVitalType) =>\n (metric: { value: number }): void => {\n const value = Number(metric.value.toFixed(PRECISION_TWO_DECIMALS));\n this.sendVital({ type, value });\n };\n\n onLCP(report('LCP'), { reportAllChanges: false });\n onCLS(report('CLS'), { reportAllChanges: false });\n onFCP(report('FCP'), { reportAllChanges: false });\n onTTFB(report('TTFB'), { reportAllChanges: false });\n onINP(report('INP'), { reportAllChanges: false });\n } catch (error) {\n log('warn', 'Failed to load web-vitals library, using fallback', { error });\n this.observeWebVitalsFallback();\n }\n }\n\n private reportTTFB(): void {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return;\n }\n\n const ttfb = nav.responseStart;\n\n // TTFB can be 0 in some browsers (especially Mobile Safari) when:\n // - Response is served from cache\n // - Connection is reused\n // - Browser cannot determine exact timing\n // We still report it as it's a valid measurement\n if (typeof ttfb === 'number' && Number.isFinite(ttfb)) {\n this.sendVital({ type: 'TTFB', value: Number(ttfb.toFixed(PRECISION_TWO_DECIMALS)) });\n }\n } catch (error) {\n log('warn', 'Failed to report TTFB', { error });\n }\n }\n\n private observeLongTasks(): void {\n this.safeObserve(\n 'longtask',\n (list) => {\n const entries = list.getEntries() as Array<{ duration: number }>;\n\n for (const entry of entries) {\n const duration = Number(entry.duration.toFixed(PRECISION_TWO_DECIMALS));\n const now = Date.now();\n\n if (now - this.lastLongTaskSentAt >= LONG_TASK_THROTTLE_MS) {\n if (this.shouldSendVital('LONG_TASK', duration)) {\n this.trackWebVital('LONG_TASK', duration);\n }\n this.lastLongTaskSentAt = now;\n }\n }\n },\n { type: 'longtask', buffered: true },\n );\n }\n\n private sendVital(sample: { type: WebVitalType; value: number }): void {\n if (!this.shouldSendVital(sample.type, sample.value)) {\n return;\n }\n\n const navId = this.getNavigationId();\n\n // Check for duplicates if we have a navigation ID\n if (navId) {\n const reportedForNav = this.reportedByNav.get(navId);\n const isDuplicate = reportedForNav?.has(sample.type);\n\n if (isDuplicate) {\n return;\n }\n\n // Initialize or update reported vitals for this navigation\n if (!reportedForNav) {\n this.reportedByNav.set(navId, new Set([sample.type]));\n this.navigationHistory.push(navId);\n\n // FIFO eviction: Remove oldest navigation when limit is exceeded\n if (this.navigationHistory.length > MAX_NAVIGATION_HISTORY) {\n const oldestNav = this.navigationHistory.shift();\n if (oldestNav) {\n this.reportedByNav.delete(oldestNav);\n }\n }\n } else {\n reportedForNav.add(sample.type);\n }\n }\n\n this.trackWebVital(sample.type, sample.value);\n }\n\n private trackWebVital(type: WebVitalType, value: number): void {\n if (!Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return;\n }\n\n this.eventManager.track({\n type: EventType.WEB_VITALS,\n web_vitals: {\n type,\n value,\n },\n });\n }\n\n private getNavigationId(): string | null {\n try {\n const nav = performance.getEntriesByType('navigation')[0] as PerformanceNavigationTiming | undefined;\n\n if (!nav) {\n return null;\n }\n\n // Use more precise timestamp and add random component to prevent collisions\n const timestamp = nav.startTime || performance.now();\n const random = Math.random().toString(36).substr(2, 5);\n return `${timestamp.toFixed(2)}_${window.location.pathname}_${random}`;\n } catch (error) {\n log('warn', 'Failed to get navigation ID', { error });\n return null;\n }\n }\n\n private isObserverSupported(type: string): boolean {\n if (typeof PerformanceObserver === 'undefined') return false;\n const supported = PerformanceObserver.supportedEntryTypes;\n return !supported || supported.includes(type);\n }\n\n private safeObserve(\n type: string,\n cb: PerformanceObserverCallback,\n options?: PerformanceObserverInit,\n once = false,\n ): boolean {\n try {\n if (!this.isObserverSupported(type)) {\n return false;\n }\n\n const obs = new PerformanceObserver((list, observer) => {\n try {\n cb(list, observer);\n } catch (callbackError) {\n log('warn', 'Observer callback failed', {\n error: callbackError,\n data: { type },\n });\n }\n\n if (once) {\n try {\n observer.disconnect();\n } catch {\n // Disconnect errors are safe to ignore\n }\n }\n });\n\n obs.observe(options ?? { type, buffered: true });\n\n if (!once) {\n this.observers.push(obs);\n }\n\n return true;\n } catch (error) {\n log('warn', 'Failed to create performance observer', {\n error,\n data: { type },\n });\n return false;\n }\n }\n\n private shouldSendVital(type: WebVitalType, value?: number): boolean {\n if (typeof value !== 'number' || !Number.isFinite(value)) {\n log('warn', 'Invalid web vital value', { data: { type, value } });\n return false;\n }\n\n const threshold = this.vitalThresholds[type];\n\n if (typeof threshold === 'number' && value <= threshold) {\n return false;\n }\n\n return true;\n }\n}\n","import { EventManager } from '../managers/event.manager';\nimport { StateManager } from '../managers/state.manager';\nimport { ErrorType, EventType } from '../types';\nimport { log } from '../utils';\nimport {\n PII_PATTERNS,\n MAX_ERROR_MESSAGE_LENGTH,\n ERROR_SUPPRESSION_WINDOW_MS,\n MAX_TRACKED_ERRORS,\n MAX_TRACKED_ERRORS_HARD_LIMIT,\n DEFAULT_ERROR_SAMPLING_RATE,\n ERROR_BURST_WINDOW_MS,\n ERROR_BURST_THRESHOLD,\n ERROR_BURST_BACKOFF_MS,\n} from '../constants/error.constants';\n\n/**\n * Simplified error handler for tracking JavaScript errors and unhandled promise rejections\n * Includes PII sanitization and sampling support\n */\nexport class ErrorHandler extends StateManager {\n private readonly eventManager: EventManager;\n private readonly recentErrors = new Map<string, number>();\n private errorBurstCounter = 0;\n private burstWindowStart = 0;\n private burstBackoffUntil = 0;\n\n constructor(eventManager: EventManager) {\n super();\n this.eventManager = eventManager;\n }\n\n startTracking(): void {\n window.addEventListener('error', this.handleError);\n window.addEventListener('unhandledrejection', this.handleRejection);\n }\n\n stopTracking(): void {\n window.removeEventListener('error', this.handleError);\n window.removeEventListener('unhandledrejection', this.handleRejection);\n this.recentErrors.clear();\n this.errorBurstCounter = 0;\n this.burstWindowStart = 0;\n this.burstBackoffUntil = 0;\n }\n\n /**\n * Checks sampling rate and burst detection (Phase 3)\n * Returns false if in cooldown period after burst detection\n */\n private shouldSample(): boolean {\n const now = Date.now();\n\n // Check if in backoff period (Phase 3)\n if (now < this.burstBackoffUntil) {\n return false;\n }\n\n // Reset burst counter if window expired\n if (now - this.burstWindowStart > ERROR_BURST_WINDOW_MS) {\n this.errorBurstCounter = 0;\n this.burstWindowStart = now;\n }\n\n // Increment burst counter\n this.errorBurstCounter++;\n\n // Trigger backoff if burst threshold exceeded\n if (this.errorBurstCounter > ERROR_BURST_THRESHOLD) {\n this.burstBackoffUntil = now + ERROR_BURST_BACKOFF_MS;\n log('warn', 'Error burst detected - entering cooldown', {\n data: {\n errorsInWindow: this.errorBurstCounter,\n cooldownMs: ERROR_BURST_BACKOFF_MS,\n },\n });\n return false;\n }\n\n // Normal sampling logic\n const config = this.get('config');\n const samplingRate = config?.errorSampling ?? DEFAULT_ERROR_SAMPLING_RATE;\n return Math.random() < samplingRate;\n }\n\n private readonly handleError = (event: ErrorEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const sanitizedMessage = this.sanitize(event.message || 'Unknown error');\n\n if (this.shouldSuppressError(ErrorType.JS_ERROR, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.JS_ERROR,\n message: sanitizedMessage,\n ...(event.filename && { filename: event.filename }),\n ...(event.lineno && { line: event.lineno }),\n ...(event.colno && { column: event.colno }),\n },\n });\n };\n\n private readonly handleRejection = (event: PromiseRejectionEvent): void => {\n if (!this.shouldSample()) {\n return;\n }\n\n const message = this.extractRejectionMessage(event.reason);\n const sanitizedMessage = this.sanitize(message);\n\n if (this.shouldSuppressError(ErrorType.PROMISE_REJECTION, sanitizedMessage)) {\n return;\n }\n\n this.eventManager.track({\n type: EventType.ERROR,\n error_data: {\n type: ErrorType.PROMISE_REJECTION,\n message: sanitizedMessage,\n },\n });\n };\n\n private extractRejectionMessage(reason: unknown): string {\n if (!reason) return 'Unknown rejection';\n\n if (typeof reason === 'string') return reason;\n\n if (reason instanceof Error) {\n return reason.stack ?? reason.message ?? reason.toString();\n }\n\n if (typeof reason === 'object' && 'message' in reason) {\n return String(reason.message);\n }\n\n try {\n return JSON.stringify(reason);\n } catch {\n return String(reason);\n }\n }\n\n private sanitize(text: string): string {\n let sanitized = text.length > MAX_ERROR_MESSAGE_LENGTH ? text.slice(0, MAX_ERROR_MESSAGE_LENGTH) + '...' : text;\n\n for (const pattern of PII_PATTERNS) {\n const regex = new RegExp(pattern.source, pattern.flags);\n sanitized = sanitized.replace(regex, '[REDACTED]');\n }\n\n return sanitized;\n }\n\n private shouldSuppressError(type: ErrorType, message: string): boolean {\n const now = Date.now();\n const key = `${type}:${message}`;\n const lastSeenAt = this.recentErrors.get(key);\n\n if (lastSeenAt && now - lastSeenAt < ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.set(key, now);\n return true;\n }\n\n this.recentErrors.set(key, now);\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS_HARD_LIMIT) {\n this.recentErrors.clear();\n this.recentErrors.set(key, now);\n\n return false;\n }\n\n if (this.recentErrors.size > MAX_TRACKED_ERRORS) {\n this.pruneOldErrors();\n }\n\n return false;\n }\n\n private pruneOldErrors(): void {\n const now = Date.now();\n for (const [key, timestamp] of this.recentErrors.entries()) {\n if (now - timestamp > ERROR_SUPPRESSION_WINDOW_MS) {\n this.recentErrors.delete(key);\n }\n }\n\n if (this.recentErrors.size <= MAX_TRACKED_ERRORS) {\n return;\n }\n\n const entries = Array.from(this.recentErrors.entries()).sort((a, b) => a[1] - b[1]);\n const excess = this.recentErrors.size - MAX_TRACKED_ERRORS;\n\n for (let index = 0; index < excess; index += 1) {\n const entry = entries[index];\n if (entry) {\n this.recentErrors.delete(entry[0]);\n }\n }\n }\n}\n","import { EventManager } from './managers/event.manager';\nimport { UserManager } from './managers/user.manager';\nimport { StateManager } from './managers/state.manager';\nimport { SessionHandler } from './handlers/session.handler';\nimport { PageViewHandler } from './handlers/page-view.handler';\nimport { ClickHandler } from './handlers/click.handler';\nimport { ScrollHandler } from './handlers/scroll.handler';\nimport { ViewportHandler } from './handlers/viewport.handler';\nimport { Config, EventType, EmitterCallback, EmitterMap, Mode } from './types';\nimport { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';\nimport { isEventValid, getDeviceType, normalizeUrl, Emitter, getCollectApiUrl, detectQaMode, log } from './utils';\nimport { StorageManager } from './managers/storage.manager';\nimport { SCROLL_DEBOUNCE_TIME_MS, SCROLL_SUPPRESS_MULTIPLIER } from './constants/config.constants';\nimport { PerformanceHandler } from './handlers/performance.handler';\nimport { ErrorHandler } from './handlers/error.handler';\n\nexport class App extends StateManager {\n private isInitialized = false;\n private suppressNextScrollTimer: number | null = null;\n\n private readonly emitter = new Emitter();\n\n protected managers: {\n storage?: StorageManager;\n event?: EventManager;\n } = {};\n\n protected handlers: {\n session?: SessionHandler;\n pageView?: PageViewHandler;\n click?: ClickHandler;\n scroll?: ScrollHandler;\n performance?: PerformanceHandler;\n error?: ErrorHandler;\n viewport?: ViewportHandler;\n } = {};\n\n protected integrations: {\n googleAnalytics?: GoogleAnalyticsIntegration;\n } = {};\n\n get initialized(): boolean {\n return this.isInitialized;\n }\n\n async init(config: Config = {}): Promise<void> {\n if (this.isInitialized) {\n return;\n }\n\n this.managers.storage = new StorageManager();\n\n try {\n this.setupState(config);\n await this.setupIntegrations();\n\n this.managers.event = new EventManager(this.managers.storage, this.integrations.googleAnalytics, this.emitter);\n\n this.initializeHandlers();\n\n await this.managers.event.recoverPersistedEvents().catch((error) => {\n log('warn', 'Failed to recover persisted events', { error });\n });\n\n this.isInitialized = true;\n } catch (error) {\n this.destroy(true);\n const errorMessage = error instanceof Error ? error.message : String(error);\n throw new Error(`[TraceLog] TraceLog initialization failed: ${errorMessage}`);\n }\n }\n\n sendCustomEvent(name: string, metadata?: Record<string, unknown> | Record<string, unknown>[]): void {\n if (!this.managers.event) {\n return;\n }\n\n const { valid, error, sanitizedMetadata } = isEventValid(name, metadata);\n\n if (!valid) {\n if (this.get('mode') === Mode.QA) {\n throw new Error(`[TraceLog] Custom event \"${name}\" validation failed: ${error}`);\n }\n\n return;\n }\n\n this.managers.event.track({\n type: EventType.CUSTOM,\n custom_event: {\n name,\n ...(sanitizedMetadata && { metadata: sanitizedMetadata }),\n },\n });\n }\n\n on<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.on(event, callback);\n }\n\n off<K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void {\n this.emitter.off(event, callback);\n }\n\n destroy(force = false): void {\n if (!this.isInitialized && !force) {\n return;\n }\n\n this.integrations.googleAnalytics?.cleanup();\n\n Object.values(this.handlers)\n .filter(Boolean)\n .forEach((handler) => {\n try {\n handler.stopTracking();\n } catch (error) {\n log('warn', 'Failed to stop tracking', { error });\n }\n });\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n this.suppressNextScrollTimer = null;\n }\n\n this.managers.event?.flushImmediatelySync();\n\n this.managers.event?.stop();\n\n this.emitter.removeAllListeners();\n\n this.set('hasStartSession', false);\n this.set('suppressNextScroll', false);\n this.set('sessionId', null);\n\n this.isInitialized = false;\n this.handlers = {};\n }\n\n private setupState(config: Config = {}): void {\n this.set('config', config);\n\n const userId = UserManager.getId(this.managers.storage as StorageManager);\n this.set('userId', userId);\n\n const collectApiUrl = getCollectApiUrl(config);\n this.set('collectApiUrl', collectApiUrl);\n\n const device = getDeviceType();\n this.set('device', device);\n\n const pageUrl = normalizeUrl(window.location.href, config.sensitiveQueryParams);\n this.set('pageUrl', pageUrl);\n\n const mode = detectQaMode() ? Mode.QA : undefined;\n\n if (mode) {\n this.set('mode', mode);\n }\n }\n\n private async setupIntegrations(): Promise<void> {\n const config = this.get('config');\n const measurementId = config.integrations?.googleAnalytics?.measurementId;\n\n if (measurementId?.trim()) {\n try {\n this.integrations.googleAnalytics = new GoogleAnalyticsIntegration();\n await this.integrations.googleAnalytics.initialize();\n } catch {\n this.integrations.googleAnalytics = undefined;\n }\n }\n }\n\n private initializeHandlers(): void {\n this.handlers.session = new SessionHandler(\n this.managers.storage as StorageManager,\n this.managers.event as EventManager,\n );\n\n this.handlers.session.startTracking();\n\n const onPageView = (): void => {\n this.set('suppressNextScroll', true);\n\n if (this.suppressNextScrollTimer) {\n clearTimeout(this.suppressNextScrollTimer);\n }\n\n this.suppressNextScrollTimer = window.setTimeout(() => {\n this.set('suppressNextScroll', false);\n }, SCROLL_DEBOUNCE_TIME_MS * SCROLL_SUPPRESS_MULTIPLIER);\n };\n\n this.handlers.pageView = new PageViewHandler(this.managers.event as EventManager, onPageView);\n this.handlers.pageView.startTracking();\n\n this.handlers.click = new ClickHandler(this.managers.event as EventManager);\n this.handlers.click.startTracking();\n\n this.handlers.scroll = new ScrollHandler(this.managers.event as EventManager);\n this.handlers.scroll.startTracking();\n\n this.handlers.performance = new PerformanceHandler(this.managers.event as EventManager);\n this.handlers.performance.startTracking().catch((error) => {\n log('warn', 'Failed to start performance tracking', { error });\n });\n\n this.handlers.error = new ErrorHandler(this.managers.event as EventManager);\n this.handlers.error.startTracking();\n\n if (this.get('config').viewport) {\n this.handlers.viewport = new ViewportHandler(this.managers.event as EventManager);\n this.handlers.viewport.startTracking();\n }\n }\n}\n","import { App } from './app';\nimport { MetadataType, Config, EmitterCallback, EmitterMap } from './types';\nimport { log, validateAndNormalizeConfig } from './utils';\nimport { TestBridge } from './test-bridge';\nimport { INITIALIZATION_TIMEOUT_MS } from './constants';\nimport './types/window.types';\n\ninterface PendingListener {\n event: keyof EmitterMap;\n callback: EmitterCallback<EmitterMap[keyof EmitterMap]>;\n}\n\n// Buffer for listeners registered before init()\nconst pendingListeners: PendingListener[] = [];\n\nlet app: App | null = null;\nlet isInitializing = false;\nlet isDestroying = false;\n\nexport const init = async (config?: Config): Promise<void> => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (window.__traceLogDisabled) {\n return;\n }\n\n if (app) {\n return;\n }\n\n if (isInitializing) {\n return;\n }\n\n isInitializing = true;\n\n try {\n const validatedConfig = validateAndNormalizeConfig(config ?? {});\n const instance = new App();\n\n try {\n pendingListeners.forEach(({ event, callback }) => {\n instance.on(event, callback);\n });\n\n pendingListeners.length = 0;\n\n const initPromise = instance.init(validatedConfig);\n\n const timeoutPromise = new Promise<never>((_, reject) => {\n setTimeout(() => {\n reject(new Error(`[TraceLog] Initialization timeout after ${INITIALIZATION_TIMEOUT_MS}ms`));\n }, INITIALIZATION_TIMEOUT_MS);\n });\n\n await Promise.race([initPromise, timeoutPromise]);\n\n app = instance;\n } catch (error) {\n try {\n instance.destroy(true);\n } catch (cleanupError) {\n log('error', 'Failed to cleanup partially initialized app', { error: cleanupError });\n }\n\n throw error;\n }\n } catch (error) {\n app = null;\n throw error;\n } finally {\n isInitializing = false;\n }\n};\n\nexport const event = (name: string, metadata?: Record<string, MetadataType> | Record<string, MetadataType>[]): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app) {\n throw new Error('[TraceLog] TraceLog not initialized. Please call init() first.');\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Cannot send events while TraceLog is being destroyed');\n }\n\n app.sendCustomEvent(name, metadata);\n};\n\nexport const on = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app || isInitializing) {\n // Buffer listeners registered before or during init()\n pendingListeners.push({ event, callback } as PendingListener);\n return;\n }\n\n app.on(event, callback);\n};\n\nexport const off = <K extends keyof EmitterMap>(event: K, callback: EmitterCallback<EmitterMap[K]>): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (!app) {\n // Remove from pending listeners if not yet initialized\n const index = pendingListeners.findIndex((l) => l.event === event && l.callback === callback);\n if (index !== -1) {\n pendingListeners.splice(index, 1);\n }\n return;\n }\n\n app.off(event, callback);\n};\n\nexport const isInitialized = (): boolean => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return false;\n }\n\n return app !== null;\n};\n\nexport const destroy = (): void => {\n if (typeof window === 'undefined' || typeof document === 'undefined') {\n return;\n }\n\n if (isDestroying) {\n throw new Error('[TraceLog] Destroy operation already in progress');\n }\n\n if (!app) {\n throw new Error('[TraceLog] App not initialized');\n }\n\n isDestroying = true;\n\n try {\n app.destroy();\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Clear TestBridge reference in dev mode to prevent stale references\n if (process.env.NODE_ENV === 'development' && typeof window !== 'undefined' && window.__traceLogBridge) {\n // Don't call destroy on bridge (would cause recursion), just clear reference\n window.__traceLogBridge = undefined as any;\n }\n } catch (error) {\n app = null;\n isInitializing = false;\n pendingListeners.length = 0;\n\n // Log error but don't re-throw - destroy should always complete successfully\n // Applications should be able to tear down TraceLog even if internal cleanup fails\n log('warn', 'Error during destroy, forced cleanup completed', { error });\n } finally {\n isDestroying = false;\n }\n};\n\n/**\n * Internal sync function - ONLY for TestBridge in development\n *\n * WARNING: This function is internal and should NEVER be called directly.\n * It's only exported for TestBridge synchronization in dev mode.\n *\n * @internal\n */\nexport const __setAppInstance = (instance: App | null): void => {\n if (process.env.NODE_ENV !== 'development') {\n return;\n }\n\n if (instance !== null) {\n const hasRequiredMethods =\n typeof instance === 'object' &&\n 'init' in instance &&\n 'destroy' in instance &&\n 'on' in instance &&\n 'off' in instance;\n\n if (!hasRequiredMethods) {\n throw new Error('[TraceLog] Invalid app instance type');\n }\n }\n\n // Prevent overwriting an already initialized app (except when clearing)\n if (app !== null && instance !== null && app !== instance) {\n throw new Error('[TraceLog] Cannot overwrite existing app instance. Call destroy() first.');\n }\n\n app = instance;\n};\n\nif (process.env.NODE_ENV === 'development' && typeof window !== 'undefined' && typeof document !== 'undefined') {\n const injectTestingBridge = (): void => {\n window.__traceLogBridge = new TestBridge(isInitializing, isDestroying);\n };\n\n if (document.readyState === 'loading') {\n document.addEventListener('DOMContentLoaded', injectTestingBridge);\n } else {\n injectTestingBridge();\n }\n}\n","import { WEB_VITALS_THRESHOLDS } from './constants/performance.constants';\nimport { PII_PATTERNS } from './constants/error.constants';\n\nexport {\n MAX_CUSTOM_EVENT_NAME_LENGTH,\n MAX_CUSTOM_EVENT_STRING_SIZE,\n MAX_CUSTOM_EVENT_KEYS,\n MAX_CUSTOM_EVENT_ARRAY_SIZE,\n MAX_NESTED_OBJECT_KEYS,\n MAX_METADATA_NESTING_DEPTH,\n MAX_STRING_LENGTH,\n MAX_STRING_LENGTH_IN_ARRAY,\n MAX_ARRAY_LENGTH,\n} from './constants';\n\nexport const PERFORMANCE_CONFIG = {\n WEB_VITALS_THRESHOLDS, // Business thresholds for performance analysis\n} as const;\n\nexport const DATA_PROTECTION = {\n PII_PATTERNS, // Patterns for sensitive data protection\n} as const;\n\nexport const ENGAGEMENT_THRESHOLDS = {\n LOW_ACTIVITY_EVENT_COUNT: 50,\n HIGH_ACTIVITY_EVENT_COUNT: 1000,\n MIN_EVENTS_FOR_DYNAMIC_CALCULATION: 100,\n MIN_EVENTS_FOR_TREND_ANALYSIS: 30,\n BOUNCE_RATE_SESSION_THRESHOLD: 1, // Sessions with 1 page view = bounce\n MIN_ENGAGED_SESSION_DURATION_MS: 30 * 1000,\n MIN_SCROLL_DEPTH_ENGAGEMENT: 25, // 25% scroll depth for engagement\n} as const;\n\nexport const SESSION_ANALYTICS = {\n INACTIVITY_TIMEOUT_MS: 30 * 60 * 1000, // 30min for analytics (vs 15min client)\n SHORT_SESSION_THRESHOLD_MS: 30 * 1000,\n MEDIUM_SESSION_THRESHOLD_MS: 5 * 60 * 1000,\n LONG_SESSION_THRESHOLD_MS: 30 * 60 * 1000,\n MAX_REALISTIC_SESSION_DURATION_MS: 8 * 60 * 60 * 1000, // Filter outliers\n} as const;\n\nexport const DEVICE_ANALYTICS = {\n MOBILE_MAX_WIDTH: 768,\n TABLET_MAX_WIDTH: 1024,\n MOBILE_PERFORMANCE_FACTOR: 1.5, // Mobile typically 1.5x slower\n TABLET_PERFORMANCE_FACTOR: 1.2,\n} as const;\n\nexport const CONTENT_ANALYTICS = {\n MIN_TEXT_LENGTH_FOR_ANALYSIS: 10,\n MIN_CLICKS_FOR_HOT_ELEMENT: 10, // Popular element threshold\n MIN_SCROLL_COMPLETION_PERCENT: 80, // Page consumption threshold\n MIN_TIME_ON_PAGE_FOR_READ_MS: 15 * 1000,\n} as const;\n\nexport const INSIGHT_THRESHOLDS = {\n SIGNIFICANT_CHANGE_PERCENT: 20,\n MAJOR_CHANGE_PERCENT: 50,\n MIN_EVENTS_FOR_INSIGHT: 100,\n MIN_SESSIONS_FOR_INSIGHT: 10,\n MIN_CORRELATION_STRENGTH: 0.7, // Strong correlation threshold\n LOW_ERROR_RATE_PERCENT: 1,\n HIGH_ERROR_RATE_PERCENT: 5,\n CRITICAL_ERROR_RATE_PERCENT: 10,\n} as const;\n\nexport const TEMPORAL_ANALYSIS = {\n SHORT_TERM_TREND_HOURS: 24,\n MEDIUM_TERM_TREND_DAYS: 7,\n LONG_TERM_TREND_DAYS: 30,\n MIN_DATA_POINTS_FOR_TREND: 5,\n WEEKLY_PATTERN_MIN_WEEKS: 4,\n DAILY_PATTERN_MIN_DAYS: 14,\n} as const;\n\nexport const SEGMENTATION_ANALYTICS = {\n MIN_SEGMENT_SIZE: 10,\n MIN_COHORT_SIZE: 5,\n COHORT_ANALYSIS_DAYS: [1, 3, 7, 14, 30],\n MIN_FUNNEL_EVENTS: 20,\n} as const;\n\nexport const ANALYTICS_QUERY_LIMITS = {\n DEFAULT_EVENTS_LIMIT: 5,\n DEFAULT_SESSIONS_LIMIT: 5,\n DEFAULT_PAGES_LIMIT: 5,\n MAX_EVENTS_FOR_DEEP_ANALYSIS: 10000,\n MAX_TIME_RANGE_DAYS: 365,\n ANALYTICS_BATCH_SIZE: 1000, // For historical analysis\n} as const;\n\nexport const ANOMALY_DETECTION = {\n ANOMALY_THRESHOLD_SIGMA: 2.5,\n STRONG_ANOMALY_THRESHOLD_SIGMA: 3.0,\n TRAFFIC_DROP_ALERT_PERCENT: -30,\n TRAFFIC_SPIKE_ALERT_PERCENT: 200,\n MIN_BASELINE_DAYS: 7,\n MIN_EVENTS_FOR_ANOMALY_DETECTION: 50,\n} as const;\n\nexport const SPECIAL_PAGE_URLS = {\n PAGE_URL_EXCLUDED: 'excluded',\n PAGE_URL_UNKNOWN: 'unknown',\n} as const;\n","import { init, event, on, off, isInitialized, destroy } from './api';\n\n// Constants\nexport * from './app.constants';\n\n// Types\nexport * from './types';\n\n// TraceLog namespace containing all API methods\nexport const tracelog = {\n init,\n event,\n on,\n off,\n isInitialized,\n destroy,\n};\n","var e,n,t,r,i,o=-1,a=function(e){addEventListener(\"pageshow\",(function(n){n.persisted&&(o=n.timeStamp,e(n))}),!0)},c=function(){var e=self.performance&&performance.getEntriesByType&&performance.getEntriesByType(\"navigation\")[0];if(e&&e.responseStart>0&&e.responseStart<performance.now())return e},u=function(){var e=c();return e&&e.activationStart||0},f=function(e,n){var t=c(),r=\"navigate\";o>=0?r=\"back-forward-cache\":t&&(document.prerendering||u()>0?r=\"prerender\":document.wasDiscarded?r=\"restore\":t.type&&(r=t.type.replace(/_/g,\"-\")));return{name:e,value:void 0===n?-1:n,rating:\"good\",delta:0,entries:[],id:\"v4-\".concat(Date.now(),\"-\").concat(Math.floor(8999999999999*Math.random())+1e12),navigationType:r}},s=function(e,n,t){try{if(PerformanceObserver.supportedEntryTypes.includes(e)){var r=new PerformanceObserver((function(e){Promise.resolve().then((function(){n(e.getEntries())}))}));return r.observe(Object.assign({type:e,buffered:!0},t||{})),r}}catch(e){}},d=function(e,n,t,r){var i,o;return function(a){n.value>=0&&(a||r)&&((o=n.value-(i||0))||void 0===i)&&(i=n.value,n.delta=o,n.rating=function(e,n){return e>n[1]?\"poor\":e>n[0]?\"needs-improvement\":\"good\"}(n.value,t),e(n))}},l=function(e){requestAnimationFrame((function(){return requestAnimationFrame((function(){return e()}))}))},p=function(e){document.addEventListener(\"visibilitychange\",(function(){\"hidden\"===document.visibilityState&&e()}))},v=function(e){var n=!1;return function(){n||(e(),n=!0)}},m=-1,h=function(){return\"hidden\"!==document.visibilityState||document.prerendering?1/0:0},g=function(e){\"hidden\"===document.visibilityState&&m>-1&&(m=\"visibilitychange\"===e.type?e.timeStamp:0,T())},y=function(){addEventListener(\"visibilitychange\",g,!0),addEventListener(\"prerenderingchange\",g,!0)},T=function(){removeEventListener(\"visibilitychange\",g,!0),removeEventListener(\"prerenderingchange\",g,!0)},E=function(){return m<0&&(m=h(),y(),a((function(){setTimeout((function(){m=h(),y()}),0)}))),{get firstHiddenTime(){return m}}},C=function(e){document.prerendering?addEventListener(\"prerenderingchange\",(function(){return e()}),!0):e()},b=[1800,3e3],S=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"FCP\"),o=s(\"paint\",(function(e){e.forEach((function(e){\"first-contentful-paint\"===e.name&&(o.disconnect(),e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries.push(e),t(!0)))}))}));o&&(t=d(e,i,b,n.reportAllChanges),a((function(r){i=f(\"FCP\"),t=d(e,i,b,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,t(!0)}))})))}))},L=[.1,.25],w=function(e,n){n=n||{},S(v((function(){var t,r=f(\"CLS\",0),i=0,o=[],c=function(e){e.forEach((function(e){if(!e.hadRecentInput){var n=o[0],t=o[o.length-1];i&&e.startTime-t.startTime<1e3&&e.startTime-n.startTime<5e3?(i+=e.value,o.push(e)):(i=e.value,o=[e])}})),i>r.value&&(r.value=i,r.entries=o,t())},u=s(\"layout-shift\",c);u&&(t=d(e,r,L,n.reportAllChanges),p((function(){c(u.takeRecords()),t(!0)})),a((function(){i=0,r=f(\"CLS\",0),t=d(e,r,L,n.reportAllChanges),l((function(){return t()}))})),setTimeout(t,0))})))},A=0,I=1/0,P=0,M=function(e){e.forEach((function(e){e.interactionId&&(I=Math.min(I,e.interactionId),P=Math.max(P,e.interactionId),A=P?(P-I)/7+1:0)}))},k=function(){return e?A:performance.interactionCount||0},F=function(){\"interactionCount\"in performance||e||(e=s(\"event\",M,{type:\"event\",buffered:!0,durationThreshold:0}))},D=[],x=new Map,R=0,B=function(){var e=Math.min(D.length-1,Math.floor((k()-R)/50));return D[e]},H=[],q=function(e){if(H.forEach((function(n){return n(e)})),e.interactionId||\"first-input\"===e.entryType){var n=D[D.length-1],t=x.get(e.interactionId);if(t||D.length<10||e.duration>n.latency){if(t)e.duration>t.latency?(t.entries=[e],t.latency=e.duration):e.duration===t.latency&&e.startTime===t.entries[0].startTime&&t.entries.push(e);else{var r={id:e.interactionId,latency:e.duration,entries:[e]};x.set(r.id,r),D.push(r)}D.sort((function(e,n){return n.latency-e.latency})),D.length>10&&D.splice(10).forEach((function(e){return x.delete(e.id)}))}}},O=function(e){var n=self.requestIdleCallback||self.setTimeout,t=-1;return e=v(e),\"hidden\"===document.visibilityState?e():(t=n(e),p(e)),t},N=[200,500],j=function(e,n){\"PerformanceEventTiming\"in self&&\"interactionId\"in PerformanceEventTiming.prototype&&(n=n||{},C((function(){var t;F();var r,i=f(\"INP\"),o=function(e){O((function(){e.forEach(q);var n=B();n&&n.latency!==i.value&&(i.value=n.latency,i.entries=n.entries,r())}))},c=s(\"event\",o,{durationThreshold:null!==(t=n.durationThreshold)&&void 0!==t?t:40});r=d(e,i,N,n.reportAllChanges),c&&(c.observe({type:\"first-input\",buffered:!0}),p((function(){o(c.takeRecords()),r(!0)})),a((function(){R=k(),D.length=0,x.clear(),i=f(\"INP\"),r=d(e,i,N,n.reportAllChanges)})))})))},_=[2500,4e3],z={},G=function(e,n){n=n||{},C((function(){var t,r=E(),i=f(\"LCP\"),o=function(e){n.reportAllChanges||(e=e.slice(-1)),e.forEach((function(e){e.startTime<r.firstHiddenTime&&(i.value=Math.max(e.startTime-u(),0),i.entries=[e],t())}))},c=s(\"largest-contentful-paint\",o);if(c){t=d(e,i,_,n.reportAllChanges);var m=v((function(){z[i.id]||(o(c.takeRecords()),c.disconnect(),z[i.id]=!0,t(!0))}));[\"keydown\",\"click\"].forEach((function(e){addEventListener(e,(function(){return O(m)}),{once:!0,capture:!0})})),p(m),a((function(r){i=f(\"LCP\"),t=d(e,i,_,n.reportAllChanges),l((function(){i.value=performance.now()-r.timeStamp,z[i.id]=!0,t(!0)}))}))}}))},J=[800,1800],K=function e(n){document.prerendering?C((function(){return e(n)})):\"complete\"!==document.readyState?addEventListener(\"load\",(function(){return e(n)}),!0):setTimeout(n,0)},Q=function(e,n){n=n||{};var t=f(\"TTFB\"),r=d(e,t,J,n.reportAllChanges);K((function(){var i=c();i&&(t.value=Math.max(i.responseStart-u(),0),t.entries=[i],r(!0),a((function(){t=f(\"TTFB\",0),(r=d(e,t,J,n.reportAllChanges))(!0)})))}))},U={passive:!0,capture:!0},V=new Date,W=function(e,i){n||(n=i,t=e,r=new Date,Z(removeEventListener),X())},X=function(){if(t>=0&&t<r-V){var e={entryType:\"first-input\",name:n.type,target:n.target,cancelable:n.cancelable,startTime:n.timeStamp,processingStart:n.timeStamp+t};i.forEach((function(n){n(e)})),i=[]}},Y=function(e){if(e.cancelable){var n=(e.timeStamp>1e12?new Date:performance.now())-e.timeStamp;\"pointerdown\"==e.type?function(e,n){var t=function(){W(e,n),i()},r=function(){i()},i=function(){removeEventListener(\"pointerup\",t,U),removeEventListener(\"pointercancel\",r,U)};addEventListener(\"pointerup\",t,U),addEventListener(\"pointercancel\",r,U)}(n,e):W(n,e)}},Z=function(e){[\"mousedown\",\"keydown\",\"touchstart\",\"pointerdown\"].forEach((function(n){return e(n,Y,U)}))},$=[100,300],ee=function(e,r){r=r||{},C((function(){var o,c=E(),u=f(\"FID\"),l=function(e){e.startTime<c.firstHiddenTime&&(u.value=e.processingStart-e.startTime,u.entries.push(e),o(!0))},m=function(e){e.forEach(l)},h=s(\"first-input\",m);o=d(e,u,$,r.reportAllChanges),h&&(p(v((function(){m(h.takeRecords()),h.disconnect()}))),a((function(){var a;u=f(\"FID\"),o=d(e,u,$,r.reportAllChanges),i=[],t=-1,n=null,Z(addEventListener),a=l,i.push(a),X()})))}))};export{L as CLSThresholds,b as FCPThresholds,$ as FIDThresholds,N as INPThresholds,_ as LCPThresholds,J as TTFBThresholds,w as onCLS,S as onFCP,ee as onFID,j as onINP,G as onLCP,Q as onTTFB};\n"],"names":["MAX_CUSTOM_EVENT_NAME_LENGTH","MAX_CUSTOM_EVENT_STRING_SIZE","MAX_CUSTOM_EVENT_KEYS","MAX_CUSTOM_EVENT_ARRAY_SIZE","MAX_NESTED_OBJECT_KEYS","MAX_METADATA_NESTING_DEPTH","MAX_STRING_LENGTH","MAX_STRING_LENGTH_IN_ARRAY","MAX_ARRAY_LENGTH","HTML_DATA_ATTR_PREFIX","INTERACTIVE_SELECTORS","UTM_PARAMS","DEFAULT_SENSITIVE_QUERY_PARAMS","VALIDATION_MESSAGES","XSS_PATTERNS","SpecialApiUrl","DeviceType","EmitterEvent","PermanentError","message","statusCode","EventType","ScrollDirection","ErrorType","Mode","isPrimaryScrollEvent","event","isSecondaryScrollEvent","TraceLogValidationError","errorCode","layer","AppConfigValidationError","SessionTimeoutValidationError","SamplingRateValidationError","IntegrationValidationError","InitializationTimeoutError","timeoutMs","formatLogMsg","msg","error","sanitizedMessage","log","type","extra","data","showToClient","formattedMsg","method","sanitizedData","sanitizeLogData","sanitized","sensitiveKeys","key","value","lowerKey","sensitiveKey","coarsePointerQuery","noHoverQuery","initMediaQueries","getDeviceType","nav","width","hasCoarsePointer","hasNoHover","hasTouchSupport","ua","isMobileUA","isTabletUA","STORAGE_BASE_KEY","QA_MODE_KEY","USER_ID_KEY","QUEUE_KEY","id","SESSION_STORAGE_KEY","BROADCAST_CHANNEL_NAME","WEB_VITALS_THRESHOLDS","LONG_TASK_THROTTLE_MS","MAX_NAVIGATION_HISTORY","PII_PATTERNS","MAX_ERROR_MESSAGE_LENGTH","ERROR_SUPPRESSION_WINDOW_MS","MAX_TRACKED_ERRORS","MAX_TRACKED_ERRORS_HARD_LIMIT","DEFAULT_ERROR_SAMPLING_RATE","ERROR_BURST_WINDOW_MS","ERROR_BURST_THRESHOLD","ERROR_BURST_BACKOFF_MS","PERMANENT_ERROR_LOG_THROTTLE_MS","QA_MODE_PARAM","QA_MODE_VALUE","detectQaMode","params","isQaMode","newSearch","newUrl","getUTMParameters","urlParams","utmParams","param","generateUUID","c","r","generateEventId","timestamp","random","bytes","b","isValidUrl","url","allowHttp","parsed","isHttps","isHttp","getCollectApiUrl","config","host","parts","projectId","cleanDomain","collectApiUrl","normalizeUrl","sensitiveQueryParams","urlObject","searchParams","allSensitiveParams","hasChanged","removedParams","urlPreview","sanitizeString","xssPatternMatches","pattern","beforeReplace","sanitizeValue","depth","item","sanitizedObject","limitedEntries","value_","sanitizedKey","sanitizedValue","sanitizeMetadata","metadata","errorMessage","validateAppConfig","validateIntegrations","validateViewportConfig","viewport","uniqueSelectors","element","normalizedSelector","integrations","validateAndNormalizeConfig","normalizedConfig","isValidArrayItem","entries","isOnlyPrimitiveFields","object","isValidEventName","eventName","validateSingleMetadata","sanitizedMetadata","intro","jsonString","isValidMetadata","sanitizedArray","itemValidation","isEventValid","nameValidation","metadataValidation","Emitter","callback","callbacks","index","globalState","StateManager","SenderManager","storeManager","userId","body","success","persistedData","payload","controller","timeoutId","response","blob","accepted","enrichedBody","storageKey","persistedDataString","queue","existing","timeSinceExisting","delay","resolve","context","now","EventManager","googleAnalytics","emitter","_eventCount","recoveredEvents","eventIds","e","page_url","from_page_url","scroll_data","click_data","custom_event","web_vitals","error_data","session_end_reason","viewport_data","currentSessionId","isCriticalEvent","eventType","typeLimit","currentCount","maxSameEventPerMinute","isSessionStart","currentPageUrl","bufferedEvents","isSync","eventsToSend","eventMap","order","signature","events","a","fingerprint","lastSeen","cutoff","x","y","nonCriticalIndex","removedEvent","samplingRate","validTimestamps","ts","eventIdSet","eventData","UserManager","storageManager","storedUserId","newUserId","SessionManager","eventManager","action","sessionId","messageProjectId","reason","storedSession","sessionTimeout","lastActivity","storedData","session","recoveredSessionId","isRecovered","SessionHandler","PageViewHandler","onTrack","original","args","rawUrl","normalizedUrl","throttleMs","fromUrl","pageViewData","pathname","search","hash","referrer","title","ClickHandler","mouseEvent","target","clickedElement","clickThrottleMs","trackingElement","relevantClickElement","coordinates","trackingData","attributeData","clickData","lastClickTime","excessCount","toDelete","testId","tlogName","path","current","selector","firstClass","parent","rect","relativeX","relativeY","name","relevantElement","text","attributes","regex","clickedText","relevantText","finalText","commonAttributes","result","attributeName","ScrollHandler","container","attempt","elements","walker","node","style","htmlElement","initialScrollTop","initialDepth","isPrimary","handleScroll","scrollData","newDepth","previous","scrollTop","scrollHeight","viewportHeight","maxScrollTop","lastScrollPos","lastEventTime","positionDelta","direction","timeDelta","velocity","hasVerticalScrollableOverflow","hasVerticalOverflowContent","targetElement","ViewportHandler","threshold","minDwellTime","tracked","maxTrackedElements","totalTracked","elementConfig","entry","visibilityRatio","dwellTime","cooldownPeriod","mutations","hasAddedNodes","mutation","removedNodes","el","descendantTracked","GoogleAnalyticsIntegration","measurementId","normalizedMetadata","script","reject","gaScriptConfig","StorageManager","retryError","keysToRemove","i","tracelogKeys","persistedEventsKeys","criticalPrefixes","nonCriticalKeys","prefix","storage","testKey","PerformanceHandler","obs","list","last","clsValue","currentNavId","navId","worst","dur","onLCP","onCLS","onFCP","onTTFB","onINP","webVitals","report","metric","ttfb","duration","sample","reportedForNav","oldestNav","supported","cb","options","once","observer","callbackError","ErrorHandler","lastSeenAt","excess","App","valid","force","handler","device","pageUrl","mode","onPageView","pendingListeners","app","isInitializing","isDestroying","init","validatedConfig","instance","initPromise","timeoutPromise","_","cleanupError","on","off","l","isInitialized","destroy","PERFORMANCE_CONFIG","DATA_PROTECTION","ENGAGEMENT_THRESHOLDS","SESSION_ANALYTICS","DEVICE_ANALYTICS","CONTENT_ANALYTICS","INSIGHT_THRESHOLDS","TEMPORAL_ANALYSIS","SEGMENTATION_ANALYTICS","ANALYTICS_QUERY_LIMITS","ANOMALY_DETECTION","SPECIAL_PAGE_URLS","tracelog","o","n","u","f","s","d","p","v","m","h","g","T","E","C","S","L","w","t","A","I","P","M","k","F","D","R","B","H","q","O","N","j","z","G","J","K","Q"],"mappings":"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","x_google_ignoreList":[42]}