@tracelog/lib 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (301) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +217 -0
  3. package/dist/browser/tracelog.js +4040 -0
  4. package/dist/browser/web-vitals-CCnqwnC8.mjs +198 -0
  5. package/dist/cjs/api.d.ts +46 -0
  6. package/dist/cjs/api.js +224 -0
  7. package/dist/cjs/app.constants.d.ts +1 -0
  8. package/dist/cjs/app.constants.js +5 -0
  9. package/dist/cjs/app.d.ts +59 -0
  10. package/dist/cjs/app.js +272 -0
  11. package/dist/cjs/app.types.d.ts +6 -0
  12. package/dist/cjs/app.types.js +22 -0
  13. package/dist/cjs/constants/api.constants.d.ts +4 -0
  14. package/dist/cjs/constants/api.constants.js +18 -0
  15. package/dist/cjs/constants/browser.constants.d.ts +3 -0
  16. package/dist/cjs/constants/browser.constants.js +41 -0
  17. package/dist/cjs/constants/index.d.ts +8 -0
  18. package/dist/cjs/constants/index.js +24 -0
  19. package/dist/cjs/constants/initialization.constants.d.ts +40 -0
  20. package/dist/cjs/constants/initialization.constants.js +48 -0
  21. package/dist/cjs/constants/limits.constants.d.ts +25 -0
  22. package/dist/cjs/constants/limits.constants.js +40 -0
  23. package/dist/cjs/constants/security.constants.d.ts +1 -0
  24. package/dist/cjs/constants/security.constants.js +12 -0
  25. package/dist/cjs/constants/storage.constants.d.ts +9 -0
  26. package/dist/cjs/constants/storage.constants.js +22 -0
  27. package/dist/cjs/constants/timing.constants.d.ts +22 -0
  28. package/dist/cjs/constants/timing.constants.js +34 -0
  29. package/dist/cjs/constants/validation.constants.d.ts +13 -0
  30. package/dist/cjs/constants/validation.constants.js +31 -0
  31. package/dist/cjs/handlers/click.handler.d.ts +17 -0
  32. package/dist/cjs/handlers/click.handler.js +199 -0
  33. package/dist/cjs/handlers/error.handler.d.ts +15 -0
  34. package/dist/cjs/handlers/error.handler.js +97 -0
  35. package/dist/cjs/handlers/network.handler.d.ts +16 -0
  36. package/dist/cjs/handlers/network.handler.js +136 -0
  37. package/dist/cjs/handlers/page-view.handler.d.ts +15 -0
  38. package/dist/cjs/handlers/page-view.handler.js +83 -0
  39. package/dist/cjs/handlers/performance.handler.d.ts +19 -0
  40. package/dist/cjs/handlers/performance.handler.js +255 -0
  41. package/dist/cjs/handlers/scroll.handler.d.ts +16 -0
  42. package/dist/cjs/handlers/scroll.handler.js +138 -0
  43. package/dist/cjs/handlers/session.handler.d.ts +29 -0
  44. package/dist/cjs/handlers/session.handler.js +357 -0
  45. package/dist/cjs/integrations/google-analytics.integration.d.ts +18 -0
  46. package/dist/cjs/integrations/google-analytics.integration.js +159 -0
  47. package/dist/cjs/listeners/activity-listener-manager.d.ts +8 -0
  48. package/dist/cjs/listeners/activity-listener-manager.js +32 -0
  49. package/dist/cjs/listeners/index.d.ts +6 -0
  50. package/dist/cjs/listeners/index.js +14 -0
  51. package/dist/cjs/listeners/input-listener-managers.d.ts +15 -0
  52. package/dist/cjs/listeners/input-listener-managers.js +58 -0
  53. package/dist/cjs/listeners/listeners.types.d.ts +4 -0
  54. package/dist/cjs/listeners/listeners.types.js +2 -0
  55. package/dist/cjs/listeners/touch-listener-manager.d.ts +10 -0
  56. package/dist/cjs/listeners/touch-listener-manager.js +56 -0
  57. package/dist/cjs/listeners/unload-listener-manager.d.ts +8 -0
  58. package/dist/cjs/listeners/unload-listener-manager.js +30 -0
  59. package/dist/cjs/listeners/visibility-listener-manager.d.ts +12 -0
  60. package/dist/cjs/listeners/visibility-listener-manager.js +83 -0
  61. package/dist/cjs/managers/api.manager.d.ts +3 -0
  62. package/dist/cjs/managers/api.manager.js +14 -0
  63. package/dist/cjs/managers/config.manager.d.ts +7 -0
  64. package/dist/cjs/managers/config.manager.js +94 -0
  65. package/dist/cjs/managers/cross-tab-session.manager.d.ts +170 -0
  66. package/dist/cjs/managers/cross-tab-session.manager.js +730 -0
  67. package/dist/cjs/managers/event.manager.d.ts +61 -0
  68. package/dist/cjs/managers/event.manager.js +508 -0
  69. package/dist/cjs/managers/sampling.manager.d.ts +8 -0
  70. package/dist/cjs/managers/sampling.manager.js +53 -0
  71. package/dist/cjs/managers/sender.manager.d.ts +46 -0
  72. package/dist/cjs/managers/sender.manager.js +304 -0
  73. package/dist/cjs/managers/session-recovery.manager.d.ts +65 -0
  74. package/dist/cjs/managers/session-recovery.manager.js +237 -0
  75. package/dist/cjs/managers/session.manager.d.ts +72 -0
  76. package/dist/cjs/managers/session.manager.js +587 -0
  77. package/dist/cjs/managers/state.manager.d.ts +5 -0
  78. package/dist/cjs/managers/state.manager.js +23 -0
  79. package/dist/cjs/managers/storage.manager.d.ts +10 -0
  80. package/dist/cjs/managers/storage.manager.js +81 -0
  81. package/dist/cjs/managers/tags.manager.d.ts +12 -0
  82. package/dist/cjs/managers/tags.manager.js +289 -0
  83. package/dist/cjs/managers/user.manager.d.ts +7 -0
  84. package/dist/cjs/managers/user.manager.js +22 -0
  85. package/dist/cjs/public-api.d.ts +1 -0
  86. package/dist/cjs/public-api.js +37 -0
  87. package/dist/cjs/types/api.types.d.ts +21 -0
  88. package/dist/cjs/types/api.types.js +25 -0
  89. package/dist/cjs/types/common.types.d.ts +1 -0
  90. package/dist/cjs/types/common.types.js +2 -0
  91. package/dist/cjs/types/config.types.d.ts +104 -0
  92. package/dist/cjs/types/config.types.js +2 -0
  93. package/dist/cjs/types/device.types.d.ts +6 -0
  94. package/dist/cjs/types/device.types.js +10 -0
  95. package/dist/cjs/types/event.types.d.ts +104 -0
  96. package/dist/cjs/types/event.types.js +25 -0
  97. package/dist/cjs/types/index.d.ts +13 -0
  98. package/dist/cjs/types/index.js +29 -0
  99. package/dist/cjs/types/log.types.d.ts +4 -0
  100. package/dist/cjs/types/log.types.js +2 -0
  101. package/dist/cjs/types/mode.types.d.ts +7 -0
  102. package/dist/cjs/types/mode.types.js +11 -0
  103. package/dist/cjs/types/queue.types.d.ts +23 -0
  104. package/dist/cjs/types/queue.types.js +2 -0
  105. package/dist/cjs/types/session.types.d.ts +65 -0
  106. package/dist/cjs/types/session.types.js +2 -0
  107. package/dist/cjs/types/state.types.d.ts +12 -0
  108. package/dist/cjs/types/state.types.js +2 -0
  109. package/dist/cjs/types/tag.types.d.ts +43 -0
  110. package/dist/cjs/types/tag.types.js +31 -0
  111. package/dist/cjs/types/validation-error.types.d.ts +42 -0
  112. package/dist/cjs/types/validation-error.types.js +68 -0
  113. package/dist/cjs/types/web-vitals.types.d.ts +6 -0
  114. package/dist/cjs/types/web-vitals.types.js +2 -0
  115. package/dist/cjs/types/window.types.d.ts +17 -0
  116. package/dist/cjs/types/window.types.js +2 -0
  117. package/dist/cjs/utils/browser/device-detector.utils.d.ts +6 -0
  118. package/dist/cjs/utils/browser/device-detector.utils.js +71 -0
  119. package/dist/cjs/utils/browser/index.d.ts +2 -0
  120. package/dist/cjs/utils/browser/index.js +18 -0
  121. package/dist/cjs/utils/browser/utm-params.utils.d.ts +6 -0
  122. package/dist/cjs/utils/browser/utm-params.utils.js +37 -0
  123. package/dist/cjs/utils/data/index.d.ts +1 -0
  124. package/dist/cjs/utils/data/index.js +17 -0
  125. package/dist/cjs/utils/data/uuid.utils.d.ts +5 -0
  126. package/dist/cjs/utils/data/uuid.utils.js +18 -0
  127. package/dist/cjs/utils/index.d.ts +6 -0
  128. package/dist/cjs/utils/index.js +22 -0
  129. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +56 -0
  130. package/dist/cjs/utils/logging/debug-logger.utils.js +139 -0
  131. package/dist/cjs/utils/logging/index.d.ts +1 -0
  132. package/dist/cjs/utils/logging/index.js +5 -0
  133. package/dist/cjs/utils/network/index.d.ts +1 -0
  134. package/dist/cjs/utils/network/index.js +17 -0
  135. package/dist/cjs/utils/network/url.utils.d.ts +20 -0
  136. package/dist/cjs/utils/network/url.utils.js +172 -0
  137. package/dist/cjs/utils/security/index.d.ts +1 -0
  138. package/dist/cjs/utils/security/index.js +17 -0
  139. package/dist/cjs/utils/security/sanitize.utils.d.ts +32 -0
  140. package/dist/cjs/utils/security/sanitize.utils.js +319 -0
  141. package/dist/cjs/utils/validations/config-validations.utils.d.ts +42 -0
  142. package/dist/cjs/utils/validations/config-validations.utils.js +297 -0
  143. package/dist/cjs/utils/validations/event-validations.utils.d.ts +12 -0
  144. package/dist/cjs/utils/validations/event-validations.utils.js +30 -0
  145. package/dist/cjs/utils/validations/index.d.ts +5 -0
  146. package/dist/cjs/utils/validations/index.js +21 -0
  147. package/dist/cjs/utils/validations/metadata-validations.utils.d.ts +22 -0
  148. package/dist/cjs/utils/validations/metadata-validations.utils.js +115 -0
  149. package/dist/cjs/utils/validations/type-guards.utils.d.ts +6 -0
  150. package/dist/cjs/utils/validations/type-guards.utils.js +31 -0
  151. package/dist/cjs/utils/validations/url-validations.utils.d.ts +15 -0
  152. package/dist/cjs/utils/validations/url-validations.utils.js +47 -0
  153. package/dist/esm/api.d.ts +46 -0
  154. package/dist/esm/api.js +183 -0
  155. package/dist/esm/app.constants.d.ts +1 -0
  156. package/dist/esm/app.constants.js +1 -0
  157. package/dist/esm/app.d.ts +59 -0
  158. package/dist/esm/app.js +268 -0
  159. package/dist/esm/app.types.d.ts +6 -0
  160. package/dist/esm/app.types.js +6 -0
  161. package/dist/esm/constants/api.constants.d.ts +4 -0
  162. package/dist/esm/constants/api.constants.js +14 -0
  163. package/dist/esm/constants/browser.constants.d.ts +3 -0
  164. package/dist/esm/constants/browser.constants.js +38 -0
  165. package/dist/esm/constants/index.d.ts +8 -0
  166. package/dist/esm/constants/index.js +8 -0
  167. package/dist/esm/constants/initialization.constants.d.ts +40 -0
  168. package/dist/esm/constants/initialization.constants.js +45 -0
  169. package/dist/esm/constants/limits.constants.d.ts +25 -0
  170. package/dist/esm/constants/limits.constants.js +37 -0
  171. package/dist/esm/constants/security.constants.d.ts +1 -0
  172. package/dist/esm/constants/security.constants.js +9 -0
  173. package/dist/esm/constants/storage.constants.d.ts +9 -0
  174. package/dist/esm/constants/storage.constants.js +11 -0
  175. package/dist/esm/constants/timing.constants.d.ts +22 -0
  176. package/dist/esm/constants/timing.constants.js +31 -0
  177. package/dist/esm/constants/validation.constants.d.ts +13 -0
  178. package/dist/esm/constants/validation.constants.js +28 -0
  179. package/dist/esm/handlers/click.handler.d.ts +17 -0
  180. package/dist/esm/handlers/click.handler.js +195 -0
  181. package/dist/esm/handlers/error.handler.d.ts +15 -0
  182. package/dist/esm/handlers/error.handler.js +93 -0
  183. package/dist/esm/handlers/network.handler.d.ts +16 -0
  184. package/dist/esm/handlers/network.handler.js +132 -0
  185. package/dist/esm/handlers/page-view.handler.d.ts +15 -0
  186. package/dist/esm/handlers/page-view.handler.js +79 -0
  187. package/dist/esm/handlers/performance.handler.d.ts +19 -0
  188. package/dist/esm/handlers/performance.handler.js +218 -0
  189. package/dist/esm/handlers/scroll.handler.d.ts +16 -0
  190. package/dist/esm/handlers/scroll.handler.js +134 -0
  191. package/dist/esm/handlers/session.handler.d.ts +29 -0
  192. package/dist/esm/handlers/session.handler.js +353 -0
  193. package/dist/esm/integrations/google-analytics.integration.d.ts +18 -0
  194. package/dist/esm/integrations/google-analytics.integration.js +155 -0
  195. package/dist/esm/listeners/activity-listener-manager.d.ts +8 -0
  196. package/dist/esm/listeners/activity-listener-manager.js +28 -0
  197. package/dist/esm/listeners/index.d.ts +6 -0
  198. package/dist/esm/listeners/index.js +5 -0
  199. package/dist/esm/listeners/input-listener-managers.d.ts +15 -0
  200. package/dist/esm/listeners/input-listener-managers.js +53 -0
  201. package/dist/esm/listeners/listeners.types.d.ts +4 -0
  202. package/dist/esm/listeners/listeners.types.js +1 -0
  203. package/dist/esm/listeners/touch-listener-manager.d.ts +10 -0
  204. package/dist/esm/listeners/touch-listener-manager.js +52 -0
  205. package/dist/esm/listeners/unload-listener-manager.d.ts +8 -0
  206. package/dist/esm/listeners/unload-listener-manager.js +26 -0
  207. package/dist/esm/listeners/visibility-listener-manager.d.ts +12 -0
  208. package/dist/esm/listeners/visibility-listener-manager.js +79 -0
  209. package/dist/esm/managers/api.manager.d.ts +3 -0
  210. package/dist/esm/managers/api.manager.js +10 -0
  211. package/dist/esm/managers/config.manager.d.ts +7 -0
  212. package/dist/esm/managers/config.manager.js +90 -0
  213. package/dist/esm/managers/cross-tab-session.manager.d.ts +170 -0
  214. package/dist/esm/managers/cross-tab-session.manager.js +726 -0
  215. package/dist/esm/managers/event.manager.d.ts +61 -0
  216. package/dist/esm/managers/event.manager.js +504 -0
  217. package/dist/esm/managers/sampling.manager.d.ts +8 -0
  218. package/dist/esm/managers/sampling.manager.js +49 -0
  219. package/dist/esm/managers/sender.manager.d.ts +46 -0
  220. package/dist/esm/managers/sender.manager.js +300 -0
  221. package/dist/esm/managers/session-recovery.manager.d.ts +65 -0
  222. package/dist/esm/managers/session-recovery.manager.js +233 -0
  223. package/dist/esm/managers/session.manager.d.ts +72 -0
  224. package/dist/esm/managers/session.manager.js +583 -0
  225. package/dist/esm/managers/state.manager.d.ts +5 -0
  226. package/dist/esm/managers/state.manager.js +19 -0
  227. package/dist/esm/managers/storage.manager.d.ts +10 -0
  228. package/dist/esm/managers/storage.manager.js +77 -0
  229. package/dist/esm/managers/tags.manager.d.ts +12 -0
  230. package/dist/esm/managers/tags.manager.js +285 -0
  231. package/dist/esm/managers/user.manager.d.ts +7 -0
  232. package/dist/esm/managers/user.manager.js +18 -0
  233. package/dist/esm/public-api.d.ts +1 -0
  234. package/dist/esm/public-api.js +1 -0
  235. package/dist/esm/types/api.types.d.ts +21 -0
  236. package/dist/esm/types/api.types.js +22 -0
  237. package/dist/esm/types/common.types.d.ts +1 -0
  238. package/dist/esm/types/common.types.js +1 -0
  239. package/dist/esm/types/config.types.d.ts +104 -0
  240. package/dist/esm/types/config.types.js +1 -0
  241. package/dist/esm/types/device.types.d.ts +6 -0
  242. package/dist/esm/types/device.types.js +7 -0
  243. package/dist/esm/types/event.types.d.ts +104 -0
  244. package/dist/esm/types/event.types.js +22 -0
  245. package/dist/esm/types/index.d.ts +13 -0
  246. package/dist/esm/types/index.js +13 -0
  247. package/dist/esm/types/log.types.d.ts +4 -0
  248. package/dist/esm/types/log.types.js +1 -0
  249. package/dist/esm/types/mode.types.d.ts +7 -0
  250. package/dist/esm/types/mode.types.js +8 -0
  251. package/dist/esm/types/queue.types.d.ts +23 -0
  252. package/dist/esm/types/queue.types.js +1 -0
  253. package/dist/esm/types/session.types.d.ts +65 -0
  254. package/dist/esm/types/session.types.js +1 -0
  255. package/dist/esm/types/state.types.d.ts +12 -0
  256. package/dist/esm/types/state.types.js +1 -0
  257. package/dist/esm/types/tag.types.d.ts +43 -0
  258. package/dist/esm/types/tag.types.js +28 -0
  259. package/dist/esm/types/validation-error.types.d.ts +42 -0
  260. package/dist/esm/types/validation-error.types.js +59 -0
  261. package/dist/esm/types/web-vitals.types.d.ts +6 -0
  262. package/dist/esm/types/web-vitals.types.js +1 -0
  263. package/dist/esm/types/window.types.d.ts +17 -0
  264. package/dist/esm/types/window.types.js +1 -0
  265. package/dist/esm/utils/browser/device-detector.utils.d.ts +6 -0
  266. package/dist/esm/utils/browser/device-detector.utils.js +67 -0
  267. package/dist/esm/utils/browser/index.d.ts +2 -0
  268. package/dist/esm/utils/browser/index.js +2 -0
  269. package/dist/esm/utils/browser/utm-params.utils.d.ts +6 -0
  270. package/dist/esm/utils/browser/utm-params.utils.js +33 -0
  271. package/dist/esm/utils/data/index.d.ts +1 -0
  272. package/dist/esm/utils/data/index.js +1 -0
  273. package/dist/esm/utils/data/uuid.utils.d.ts +5 -0
  274. package/dist/esm/utils/data/uuid.utils.js +14 -0
  275. package/dist/esm/utils/index.d.ts +6 -0
  276. package/dist/esm/utils/index.js +6 -0
  277. package/dist/esm/utils/logging/debug-logger.utils.d.ts +56 -0
  278. package/dist/esm/utils/logging/debug-logger.utils.js +136 -0
  279. package/dist/esm/utils/logging/index.d.ts +1 -0
  280. package/dist/esm/utils/logging/index.js +1 -0
  281. package/dist/esm/utils/network/index.d.ts +1 -0
  282. package/dist/esm/utils/network/index.js +1 -0
  283. package/dist/esm/utils/network/url.utils.d.ts +20 -0
  284. package/dist/esm/utils/network/url.utils.js +166 -0
  285. package/dist/esm/utils/security/index.d.ts +1 -0
  286. package/dist/esm/utils/security/index.js +1 -0
  287. package/dist/esm/utils/security/sanitize.utils.d.ts +32 -0
  288. package/dist/esm/utils/security/sanitize.utils.js +311 -0
  289. package/dist/esm/utils/validations/config-validations.utils.d.ts +42 -0
  290. package/dist/esm/utils/validations/config-validations.utils.js +289 -0
  291. package/dist/esm/utils/validations/event-validations.utils.d.ts +12 -0
  292. package/dist/esm/utils/validations/event-validations.utils.js +26 -0
  293. package/dist/esm/utils/validations/index.d.ts +5 -0
  294. package/dist/esm/utils/validations/index.js +5 -0
  295. package/dist/esm/utils/validations/metadata-validations.utils.d.ts +22 -0
  296. package/dist/esm/utils/validations/metadata-validations.utils.js +110 -0
  297. package/dist/esm/utils/validations/type-guards.utils.d.ts +6 -0
  298. package/dist/esm/utils/validations/type-guards.utils.js +27 -0
  299. package/dist/esm/utils/validations/url-validations.utils.d.ts +15 -0
  300. package/dist/esm/utils/validations/url-validations.utils.js +42 -0
  301. package/package.json +80 -0
@@ -0,0 +1,136 @@
1
+ import { StateManager } from '../../managers/state.manager';
2
+ /**
3
+ * Debug logger class that extends StateManager for clean access to global state
4
+ */
5
+ class DebugLogger extends StateManager {
6
+ /**
7
+ * Client-facing error - Configuration/usage errors by the client
8
+ * Console: qa and debug modes | Events: NODE_ENV=dev
9
+ */
10
+ clientError(namespace, message, data) {
11
+ this.logMessage('CLIENT_ERROR', namespace, message, data);
12
+ }
13
+ /**
14
+ * Client-facing warning - Configuration/usage warnings by the client
15
+ * Console: qa and debug modes | Events: NODE_ENV=dev
16
+ */
17
+ clientWarn(namespace, message, data) {
18
+ this.logMessage('CLIENT_WARN', namespace, message, data);
19
+ }
20
+ /**
21
+ * General operational information
22
+ * Console: qa and debug modes | Events: NODE_ENV=dev
23
+ */
24
+ info(namespace, message, data) {
25
+ this.logMessage('INFO', namespace, message, data);
26
+ }
27
+ /**
28
+ * Internal library errors
29
+ * Console: debug mode only | Events: NODE_ENV=dev
30
+ */
31
+ error(namespace, message, data) {
32
+ this.logMessage('ERROR', namespace, message, data);
33
+ }
34
+ /**
35
+ * Internal library warnings
36
+ * Console: debug mode only | Events: NODE_ENV=dev
37
+ */
38
+ warn(namespace, message, data) {
39
+ this.logMessage('WARN', namespace, message, data);
40
+ }
41
+ /**
42
+ * Strategic debug information
43
+ * Console: debug mode only | Events: NODE_ENV=dev
44
+ */
45
+ debug(namespace, message, data) {
46
+ this.logMessage('DEBUG', namespace, message, data);
47
+ }
48
+ /**
49
+ * Detailed trace information
50
+ * Console: debug mode only | Events: NODE_ENV=dev
51
+ */
52
+ verbose(namespace, message, data) {
53
+ this.logMessage('VERBOSE', namespace, message, data);
54
+ }
55
+ getCurrentMode() {
56
+ try {
57
+ return this.get('config')?.mode;
58
+ }
59
+ catch {
60
+ return undefined;
61
+ }
62
+ }
63
+ shouldShowLog(level) {
64
+ const mode = this.getCurrentMode();
65
+ switch (mode) {
66
+ case 'qa':
67
+ return ['INFO', 'CLIENT_ERROR', 'CLIENT_WARN'].includes(level);
68
+ case 'debug':
69
+ return true;
70
+ default:
71
+ return false;
72
+ }
73
+ }
74
+ formatMessage(namespace, message) {
75
+ return `[TraceLog:${namespace}] ${message}`;
76
+ }
77
+ getConsoleMethod(level) {
78
+ switch (level) {
79
+ case 'CLIENT_ERROR':
80
+ case 'ERROR':
81
+ return 'error';
82
+ case 'CLIENT_WARN':
83
+ case 'WARN':
84
+ return 'warn';
85
+ case 'INFO':
86
+ case 'DEBUG':
87
+ case 'VERBOSE':
88
+ default:
89
+ return 'log';
90
+ }
91
+ }
92
+ logMessage(level, namespace, message, data) {
93
+ if (!this.shouldShowLog(level)) {
94
+ return;
95
+ }
96
+ const formattedMessage = this.formatMessage(namespace, message);
97
+ const consoleMethod = this.getConsoleMethod(level);
98
+ if (data !== undefined) {
99
+ console[consoleMethod](formattedMessage, data);
100
+ }
101
+ else {
102
+ console[consoleMethod](formattedMessage);
103
+ }
104
+ if (process.env.NODE_ENV === 'dev') {
105
+ this.dispatchEvent(level, namespace, message, data);
106
+ }
107
+ }
108
+ /**
109
+ * Dispatches tracelog:log events for E2E testing and development debugging
110
+ */
111
+ dispatchEvent(level, namespace, message, data) {
112
+ if (typeof window === 'undefined' || typeof CustomEvent === 'undefined') {
113
+ return;
114
+ }
115
+ try {
116
+ const event = new CustomEvent('tracelog:log', {
117
+ detail: {
118
+ timestamp: new Date().toISOString(),
119
+ level,
120
+ namespace,
121
+ message,
122
+ data,
123
+ },
124
+ });
125
+ window.dispatchEvent(event);
126
+ }
127
+ catch {
128
+ console.log(`[TraceLog:${namespace}] ${message}`, data);
129
+ }
130
+ }
131
+ }
132
+ /**
133
+ * Singleton debug logger instance
134
+ * Provides the same API as before: debugLog.clientError(), debugLog.info(), etc.
135
+ */
136
+ export const debugLog = new DebugLogger();
@@ -0,0 +1 @@
1
+ export { debugLog } from './debug-logger.utils';
@@ -0,0 +1 @@
1
+ export { debugLog } from './debug-logger.utils';
@@ -0,0 +1 @@
1
+ export * from './url.utils';
@@ -0,0 +1 @@
1
+ export * from './url.utils';
@@ -0,0 +1,20 @@
1
+ /**
2
+ * Generates an API URL based on project ID and current domain
3
+ * @param id - The project ID
4
+ * @returns The generated API URL
5
+ */
6
+ export declare const getApiUrl: (id: string, allowHttp?: boolean) => string;
7
+ /**
8
+ * Normalizes a URL by removing sensitive query parameters
9
+ * @param url - The URL to normalize
10
+ * @param sensitiveQueryParams - Array of parameter names to remove
11
+ * @returns The normalized URL
12
+ */
13
+ export declare const normalizeUrl: (url: string, sensitiveQueryParams?: string[]) => string;
14
+ /**
15
+ * Checks if a URL path should be excluded from tracking
16
+ * @param url - The URL to check
17
+ * @param excludedPaths - Array of patterns to match against
18
+ * @returns True if the URL should be excluded
19
+ */
20
+ export declare const isUrlPathExcluded: (url: string, excludedPaths?: string[]) => boolean;
@@ -0,0 +1,166 @@
1
+ import { isValidUrl } from '../validations';
2
+ import { debugLog } from '../logging';
3
+ /**
4
+ * Generates an API URL based on project ID and current domain
5
+ * @param id - The project ID
6
+ * @returns The generated API URL
7
+ */
8
+ export const getApiUrl = (id, allowHttp = false) => {
9
+ debugLog.debug('URLUtils', 'Generating API URL', { projectId: id, allowHttp });
10
+ const url = new URL(window.location.href);
11
+ const host = url.hostname;
12
+ const parts = host.split('.');
13
+ if (parts.length === 0) {
14
+ debugLog.clientError('URLUtils', 'Invalid hostname - no domain parts found', { hostname: host });
15
+ throw new Error('Invalid URL');
16
+ }
17
+ const cleanDomain = parts.slice(-2).join('.');
18
+ const protocol = allowHttp && url.protocol === 'http:' ? 'http' : 'https';
19
+ const apiUrl = `${protocol}://${id}.${cleanDomain}`;
20
+ debugLog.debug('URLUtils', 'Generated API URL', {
21
+ originalUrl: window.location.href,
22
+ hostname: host,
23
+ domainParts: parts.length,
24
+ cleanDomain,
25
+ protocol,
26
+ generatedUrl: apiUrl,
27
+ });
28
+ const isValid = isValidUrl(apiUrl, allowHttp);
29
+ if (!isValid) {
30
+ debugLog.clientError('URLUtils', 'Generated API URL failed validation', {
31
+ apiUrl,
32
+ allowHttp,
33
+ });
34
+ throw new Error('Invalid URL');
35
+ }
36
+ debugLog.debug('URLUtils', 'API URL generation completed successfully', { apiUrl });
37
+ return apiUrl;
38
+ };
39
+ /**
40
+ * Normalizes a URL by removing sensitive query parameters
41
+ * @param url - The URL to normalize
42
+ * @param sensitiveQueryParams - Array of parameter names to remove
43
+ * @returns The normalized URL
44
+ */
45
+ export const normalizeUrl = (url, sensitiveQueryParams = []) => {
46
+ debugLog.debug('URLUtils', 'Normalizing URL', {
47
+ urlLength: url.length,
48
+ sensitiveParamsCount: sensitiveQueryParams.length,
49
+ });
50
+ try {
51
+ const urlObject = new URL(url);
52
+ const searchParams = urlObject.searchParams;
53
+ const originalParamCount = Array.from(searchParams.keys()).length;
54
+ let hasChanged = false;
55
+ const removedParams = [];
56
+ sensitiveQueryParams.forEach((param) => {
57
+ if (searchParams.has(param)) {
58
+ searchParams.delete(param);
59
+ hasChanged = true;
60
+ removedParams.push(param);
61
+ }
62
+ });
63
+ if (hasChanged) {
64
+ debugLog.debug('URLUtils', 'Sensitive parameters removed from URL', {
65
+ removedParams,
66
+ originalParamCount,
67
+ finalParamCount: Array.from(searchParams.keys()).length,
68
+ });
69
+ }
70
+ if (!hasChanged && url.includes('?')) {
71
+ debugLog.debug('URLUtils', 'URL normalization - no changes needed');
72
+ return url;
73
+ }
74
+ urlObject.search = searchParams.toString();
75
+ const result = urlObject.toString();
76
+ debugLog.debug('URLUtils', 'URL normalization completed', {
77
+ hasChanged,
78
+ originalLength: url.length,
79
+ normalizedLength: result.length,
80
+ });
81
+ return result;
82
+ }
83
+ catch (error) {
84
+ debugLog.warn('URLUtils', 'URL normalization failed, returning original', {
85
+ url: url.slice(0, 100),
86
+ error: error instanceof Error ? error.message : error,
87
+ });
88
+ return url;
89
+ }
90
+ };
91
+ /**
92
+ * Checks if a URL path should be excluded from tracking
93
+ * @param url - The URL to check
94
+ * @param excludedPaths - Array of patterns to match against
95
+ * @returns True if the URL should be excluded
96
+ */
97
+ export const isUrlPathExcluded = (url, excludedPaths = []) => {
98
+ debugLog.debug('URLUtils', 'Checking if URL path is excluded', {
99
+ urlLength: url.length,
100
+ excludedPathsCount: excludedPaths.length,
101
+ });
102
+ if (excludedPaths.length === 0) {
103
+ debugLog.debug('URLUtils', 'No excluded paths configured');
104
+ return false;
105
+ }
106
+ let path;
107
+ try {
108
+ path = new URL(url, window.location.origin).pathname;
109
+ debugLog.debug('URLUtils', 'Extracted path from URL', { path });
110
+ }
111
+ catch (error) {
112
+ debugLog.warn('URLUtils', 'Failed to parse URL for path exclusion check', {
113
+ url: url.slice(0, 100),
114
+ error: error instanceof Error ? error.message : error,
115
+ });
116
+ return false;
117
+ }
118
+ const isRegularExpression = (value) => typeof value === 'object' && value !== undefined && typeof value.test === 'function';
119
+ const escapeRegexString = (string_) => string_.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&');
120
+ const wildcardToRegex = (string_) => new RegExp('^' +
121
+ string_
122
+ .split('*')
123
+ .map((element) => escapeRegexString(element))
124
+ .join('.+') +
125
+ '$');
126
+ const matchedPattern = excludedPaths.find((pattern) => {
127
+ try {
128
+ if (isRegularExpression(pattern)) {
129
+ const matches = pattern.test(path);
130
+ if (matches) {
131
+ debugLog.debug('URLUtils', 'Path matched regex pattern', { path, pattern: pattern.toString() });
132
+ }
133
+ return matches;
134
+ }
135
+ if (pattern.includes('*')) {
136
+ const regex = wildcardToRegex(pattern);
137
+ const matches = regex.test(path);
138
+ if (matches) {
139
+ debugLog.debug('URLUtils', 'Path matched wildcard pattern', { path, pattern, regex: regex.toString() });
140
+ }
141
+ return matches;
142
+ }
143
+ const matches = pattern === path;
144
+ if (matches) {
145
+ debugLog.debug('URLUtils', 'Path matched exact pattern', { path, pattern });
146
+ }
147
+ return matches;
148
+ }
149
+ catch (error) {
150
+ debugLog.warn('URLUtils', 'Error testing exclusion pattern', {
151
+ pattern,
152
+ path,
153
+ error: error instanceof Error ? error.message : error,
154
+ });
155
+ return false;
156
+ }
157
+ });
158
+ const isExcluded = !!matchedPattern;
159
+ debugLog.debug('URLUtils', 'URL path exclusion check completed', {
160
+ path,
161
+ isExcluded,
162
+ matchedPattern: matchedPattern ?? null,
163
+ totalPatternsChecked: excludedPaths.length,
164
+ });
165
+ return isExcluded;
166
+ };
@@ -0,0 +1 @@
1
+ export * from './sanitize.utils';
@@ -0,0 +1 @@
1
+ export * from './sanitize.utils';
@@ -0,0 +1,32 @@
1
+ import { MetadataType } from '../../types/common.types';
2
+ import { ApiConfig } from '../../types/config.types';
3
+ /**
4
+ * Sanitizes a string value to prevent XSS attacks
5
+ * @param value - The string to sanitize
6
+ * @returns The sanitized string
7
+ */
8
+ export declare const sanitizeString: (value: string) => string;
9
+ /**
10
+ * Sanitizes a path string for route exclusion checks
11
+ * @param value - The path string to sanitize
12
+ * @returns The sanitized path string
13
+ */
14
+ export declare const sanitizePathString: (value: string) => string;
15
+ /**
16
+ * Sanitizes API configuration data with strict validation
17
+ * @param data - The API config data to sanitize
18
+ * @returns The sanitized API config
19
+ */
20
+ export declare const sanitizeApiConfig: (data: unknown) => ApiConfig;
21
+ /**
22
+ * Sanitizes user metadata for custom events
23
+ * @param metadata - The metadata to sanitize
24
+ * @returns The sanitized metadata
25
+ */
26
+ export declare const sanitizeMetadata: (metadata: unknown) => Record<string, MetadataType>;
27
+ /**
28
+ * Sanitizes URL strings for tracking
29
+ * @param url - The URL to sanitize
30
+ * @returns The sanitized URL
31
+ */
32
+ export declare const sanitizeUrl: (url: string) => string;
@@ -0,0 +1,311 @@
1
+ import { ALLOWED_API_CONFIG_KEYS, MAX_ARRAY_LENGTH, MAX_OBJECT_DEPTH, MAX_STRING_LENGTH, XSS_PATTERNS, } from '../../constants';
2
+ import { debugLog } from '../logging';
3
+ /**
4
+ * Sanitizes a string value to prevent XSS attacks
5
+ * @param value - The string to sanitize
6
+ * @returns The sanitized string
7
+ */
8
+ export const sanitizeString = (value) => {
9
+ if (!value || typeof value !== 'string' || value.trim().length === 0) {
10
+ debugLog.debug('Sanitize', 'String sanitization skipped - empty or invalid input', { value, type: typeof value });
11
+ return '';
12
+ }
13
+ const originalLength = value.length;
14
+ let sanitized = value;
15
+ // Limit string length
16
+ if (value.length > MAX_STRING_LENGTH) {
17
+ sanitized = value.slice(0, Math.max(0, MAX_STRING_LENGTH));
18
+ debugLog.warn('Sanitize', 'String truncated due to length limit', {
19
+ originalLength,
20
+ maxLength: MAX_STRING_LENGTH,
21
+ truncatedLength: sanitized.length,
22
+ });
23
+ }
24
+ // Remove potential XSS patterns
25
+ let xssPatternMatches = 0;
26
+ for (const pattern of XSS_PATTERNS) {
27
+ const beforeReplace = sanitized;
28
+ sanitized = sanitized.replace(pattern, '');
29
+ if (beforeReplace !== sanitized) {
30
+ xssPatternMatches++;
31
+ }
32
+ }
33
+ if (xssPatternMatches > 0) {
34
+ debugLog.warn('Sanitize', 'XSS patterns detected and removed', {
35
+ patternMatches: xssPatternMatches,
36
+ originalValue: value.slice(0, 100), // Log first 100 chars for debugging
37
+ });
38
+ }
39
+ // Basic HTML entity encoding for critical characters
40
+ sanitized = sanitized
41
+ .replaceAll('&', '&amp;')
42
+ .replaceAll('<', '&lt;')
43
+ .replaceAll('>', '&gt;')
44
+ .replaceAll('"', '&quot;')
45
+ .replaceAll("'", '&#x27;')
46
+ .replaceAll('/', '&#x2F;');
47
+ const result = sanitized.trim();
48
+ if (originalLength > 50 || xssPatternMatches > 0) {
49
+ debugLog.debug('Sanitize', 'String sanitization completed', {
50
+ originalLength,
51
+ sanitizedLength: result.length,
52
+ xssPatternMatches,
53
+ wasTruncated: originalLength > MAX_STRING_LENGTH,
54
+ });
55
+ }
56
+ return result;
57
+ };
58
+ /**
59
+ * Sanitizes a path string for route exclusion checks
60
+ * @param value - The path string to sanitize
61
+ * @returns The sanitized path string
62
+ */
63
+ export const sanitizePathString = (value) => {
64
+ if (typeof value !== 'string') {
65
+ return '';
66
+ }
67
+ if (value.length > MAX_STRING_LENGTH) {
68
+ value = value.slice(0, Math.max(0, MAX_STRING_LENGTH));
69
+ }
70
+ let sanitized = value;
71
+ for (const pattern of XSS_PATTERNS) {
72
+ sanitized = sanitized.replace(pattern, '');
73
+ }
74
+ sanitized = sanitized
75
+ .replaceAll('&', '&amp;')
76
+ .replaceAll('<', '&lt;')
77
+ .replaceAll('>', '&gt;')
78
+ .replaceAll('"', '&quot;')
79
+ .replaceAll("'", '&#x27;');
80
+ return sanitized.trim();
81
+ };
82
+ /**
83
+ * Sanitizes any value recursively with depth protection
84
+ * @param value - The value to sanitize
85
+ * @param depth - Current recursion depth
86
+ * @returns The sanitized value
87
+ */
88
+ const sanitizeValue = (value, depth = 0) => {
89
+ // Prevent infinite recursion
90
+ if (depth > MAX_OBJECT_DEPTH) {
91
+ debugLog.warn('Sanitize', 'Maximum object depth exceeded during sanitization', {
92
+ depth,
93
+ maxDepth: MAX_OBJECT_DEPTH,
94
+ });
95
+ return null;
96
+ }
97
+ if (value === null || value === undefined) {
98
+ return null;
99
+ }
100
+ if (typeof value === 'string') {
101
+ return sanitizeString(value);
102
+ }
103
+ if (typeof value === 'number') {
104
+ if (!Number.isFinite(value) || value < -Number.MAX_SAFE_INTEGER || value > Number.MAX_SAFE_INTEGER) {
105
+ debugLog.warn('Sanitize', 'Invalid number sanitized to 0', { value, isFinite: Number.isFinite(value) });
106
+ return 0;
107
+ }
108
+ return value;
109
+ }
110
+ if (typeof value === 'boolean') {
111
+ return value;
112
+ }
113
+ if (Array.isArray(value)) {
114
+ const originalLength = value.length;
115
+ const limitedArray = value.slice(0, MAX_ARRAY_LENGTH);
116
+ if (originalLength > MAX_ARRAY_LENGTH) {
117
+ debugLog.warn('Sanitize', 'Array truncated due to length limit', {
118
+ originalLength,
119
+ maxLength: MAX_ARRAY_LENGTH,
120
+ depth,
121
+ });
122
+ }
123
+ const sanitizedArray = limitedArray.map((item) => sanitizeValue(item, depth + 1)).filter((item) => item !== null);
124
+ if (originalLength > 0 && sanitizedArray.length === 0) {
125
+ debugLog.warn('Sanitize', 'All array items were filtered out during sanitization', { originalLength, depth });
126
+ }
127
+ return sanitizedArray;
128
+ }
129
+ if (typeof value === 'object') {
130
+ const sanitizedObject = {};
131
+ const entries = Object.entries(value);
132
+ const originalKeysCount = entries.length;
133
+ const limitedEntries = entries.slice(0, 20);
134
+ if (originalKeysCount > 20) {
135
+ debugLog.warn('Sanitize', 'Object keys truncated due to limit', {
136
+ originalKeys: originalKeysCount,
137
+ maxKeys: 20,
138
+ depth,
139
+ });
140
+ }
141
+ let filteredKeysCount = 0;
142
+ for (const [key, value_] of limitedEntries) {
143
+ const sanitizedKey = sanitizeString(key);
144
+ if (sanitizedKey) {
145
+ const sanitizedValue = sanitizeValue(value_, depth + 1);
146
+ if (sanitizedValue !== null) {
147
+ sanitizedObject[sanitizedKey] = sanitizedValue;
148
+ }
149
+ else {
150
+ filteredKeysCount++;
151
+ }
152
+ }
153
+ else {
154
+ filteredKeysCount++;
155
+ }
156
+ }
157
+ if (filteredKeysCount > 0) {
158
+ debugLog.debug('Sanitize', 'Object properties filtered during sanitization', {
159
+ filteredKeysCount,
160
+ remainingKeys: Object.keys(sanitizedObject).length,
161
+ depth,
162
+ });
163
+ }
164
+ return sanitizedObject;
165
+ }
166
+ debugLog.debug('Sanitize', 'Unknown value type sanitized to null', { type: typeof value, depth });
167
+ return null;
168
+ };
169
+ /**
170
+ * Sanitizes API configuration data with strict validation
171
+ * @param data - The API config data to sanitize
172
+ * @returns The sanitized API config
173
+ */
174
+ export const sanitizeApiConfig = (data) => {
175
+ debugLog.debug('Sanitize', 'Starting API config sanitization');
176
+ const safeData = {};
177
+ if (typeof data !== 'object' || data === null) {
178
+ debugLog.warn('Sanitize', 'API config data is not an object', { data, type: typeof data });
179
+ return safeData;
180
+ }
181
+ try {
182
+ const originalKeys = Object.keys(data);
183
+ let processedKeys = 0;
184
+ let filteredKeys = 0;
185
+ for (const key of originalKeys) {
186
+ if (ALLOWED_API_CONFIG_KEYS.has(key)) {
187
+ const value = data[key];
188
+ if (key === 'excludedUrlPaths') {
189
+ const paths = Array.isArray(value) ? value : typeof value === 'string' ? [value] : [];
190
+ const originalPathsCount = paths.length;
191
+ safeData.excludedUrlPaths = paths.map((path) => sanitizePathString(String(path))).filter(Boolean);
192
+ const filteredPathsCount = originalPathsCount - safeData.excludedUrlPaths.length;
193
+ if (filteredPathsCount > 0) {
194
+ debugLog.warn('Sanitize', 'Some excluded URL paths were filtered during sanitization', {
195
+ originalCount: originalPathsCount,
196
+ filteredCount: filteredPathsCount,
197
+ });
198
+ }
199
+ }
200
+ else if (key === 'tags') {
201
+ if (Array.isArray(value)) {
202
+ safeData.tags = value;
203
+ debugLog.debug('Sanitize', 'Tags processed', { count: value.length });
204
+ }
205
+ else {
206
+ debugLog.warn('Sanitize', 'Tags value is not an array', { value, type: typeof value });
207
+ }
208
+ }
209
+ else {
210
+ const sanitizedValue = sanitizeValue(value);
211
+ if (sanitizedValue !== null) {
212
+ safeData[key] = sanitizedValue;
213
+ }
214
+ else {
215
+ debugLog.warn('Sanitize', 'API config value sanitized to null', { key, originalValue: value });
216
+ }
217
+ }
218
+ processedKeys++;
219
+ }
220
+ else {
221
+ filteredKeys++;
222
+ debugLog.debug('Sanitize', 'API config key not allowed', { key });
223
+ }
224
+ }
225
+ debugLog.info('Sanitize', 'API config sanitization completed', {
226
+ originalKeys: originalKeys.length,
227
+ processedKeys,
228
+ filteredKeys,
229
+ finalKeys: Object.keys(safeData).length,
230
+ });
231
+ }
232
+ catch (error) {
233
+ debugLog.error('Sanitize', 'API config sanitization failed', {
234
+ error: error instanceof Error ? error.message : error,
235
+ });
236
+ throw new Error(`API config sanitization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
237
+ }
238
+ return safeData;
239
+ };
240
+ /**
241
+ * Sanitizes user metadata for custom events
242
+ * @param metadata - The metadata to sanitize
243
+ * @returns The sanitized metadata
244
+ */
245
+ export const sanitizeMetadata = (metadata) => {
246
+ debugLog.debug('Sanitize', 'Starting metadata sanitization', { hasMetadata: metadata != null });
247
+ if (typeof metadata !== 'object' || metadata === null) {
248
+ debugLog.debug('Sanitize', 'Metadata is not an object, returning empty object', {
249
+ metadata,
250
+ type: typeof metadata,
251
+ });
252
+ return {};
253
+ }
254
+ try {
255
+ const originalKeys = Object.keys(metadata).length;
256
+ const sanitized = sanitizeValue(metadata);
257
+ const result = typeof sanitized === 'object' && sanitized !== null ? sanitized : {};
258
+ const finalKeys = Object.keys(result).length;
259
+ debugLog.debug('Sanitize', 'Metadata sanitization completed', {
260
+ originalKeys,
261
+ finalKeys,
262
+ keysFiltered: originalKeys - finalKeys,
263
+ });
264
+ return result;
265
+ }
266
+ catch (error) {
267
+ debugLog.error('Sanitize', 'Metadata sanitization failed', {
268
+ error: error instanceof Error ? error.message : error,
269
+ });
270
+ throw new Error(`Metadata sanitization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
271
+ }
272
+ };
273
+ /**
274
+ * Sanitizes URL strings for tracking
275
+ * @param url - The URL to sanitize
276
+ * @returns The sanitized URL
277
+ */
278
+ export const sanitizeUrl = (url) => {
279
+ debugLog.debug('Sanitize', 'Starting URL sanitization', { urlLength: typeof url === 'string' ? url.length : 0 });
280
+ if (typeof url !== 'string') {
281
+ debugLog.warn('Sanitize', 'URL is not a string', { url, type: typeof url });
282
+ return '';
283
+ }
284
+ try {
285
+ // Basic URL validation
286
+ const urlObject = new URL(url);
287
+ // Only allow http/https protocols
288
+ if (!['http:', 'https:'].includes(urlObject.protocol)) {
289
+ debugLog.warn('Sanitize', 'URL protocol not allowed', {
290
+ protocol: urlObject.protocol,
291
+ allowedProtocols: ['http:', 'https:'],
292
+ });
293
+ return '';
294
+ }
295
+ // Sanitize the URL string
296
+ const result = sanitizeString(urlObject.href);
297
+ debugLog.debug('Sanitize', 'URL sanitization completed via URL object', {
298
+ originalLength: url.length,
299
+ sanitizedLength: result.length,
300
+ protocol: urlObject.protocol,
301
+ });
302
+ return result;
303
+ }
304
+ catch {
305
+ // If URL parsing fails, sanitize as string
306
+ debugLog.warn('Sanitize', 'URL parsing failed, falling back to string sanitization', {
307
+ urlPreview: url.slice(0, 100),
308
+ });
309
+ return sanitizeString(url);
310
+ }
311
+ };