@tracelog/lib 0.5.4 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (200) hide show
  1. package/README.md +157 -180
  2. package/dist/browser/tracelog.esm.js +1007 -1357
  3. package/dist/browser/tracelog.js +2 -2
  4. package/dist/cjs/api.d.ts +12 -2
  5. package/dist/cjs/api.js +63 -27
  6. package/dist/cjs/app.d.ts +2 -2
  7. package/dist/cjs/app.js +26 -32
  8. package/dist/cjs/constants/config.constants.d.ts +4 -2
  9. package/dist/cjs/constants/config.constants.js +6 -18
  10. package/dist/cjs/constants/index.d.ts +0 -1
  11. package/dist/cjs/constants/index.js +0 -1
  12. package/dist/cjs/constants/storage.constants.d.ts +3 -2
  13. package/dist/cjs/constants/storage.constants.js +4 -4
  14. package/dist/cjs/handlers/click.handler.js +3 -6
  15. package/dist/cjs/handlers/error.handler.js +1 -11
  16. package/dist/cjs/handlers/page-view.handler.js +0 -4
  17. package/dist/cjs/handlers/performance.handler.js +14 -29
  18. package/dist/cjs/handlers/scroll.handler.js +7 -6
  19. package/dist/cjs/handlers/session.handler.js +7 -6
  20. package/dist/cjs/integrations/google-analytics.integration.js +2 -6
  21. package/dist/cjs/listeners/activity-listener-manager.js +3 -3
  22. package/dist/cjs/listeners/input-listener-managers.js +3 -3
  23. package/dist/cjs/listeners/touch-listener-manager.js +3 -3
  24. package/dist/cjs/listeners/unload-listener-manager.js +3 -3
  25. package/dist/cjs/listeners/visibility-listener-manager.js +3 -3
  26. package/dist/cjs/managers/event.manager.d.ts +2 -1
  27. package/dist/cjs/managers/event.manager.js +60 -38
  28. package/dist/cjs/managers/sender.manager.js +29 -36
  29. package/dist/cjs/managers/session.manager.js +5 -13
  30. package/dist/cjs/managers/state.manager.d.ts +0 -3
  31. package/dist/cjs/managers/state.manager.js +1 -43
  32. package/dist/cjs/managers/storage.manager.d.ts +16 -2
  33. package/dist/cjs/managers/storage.manager.js +73 -19
  34. package/dist/cjs/managers/user.manager.d.ts +1 -1
  35. package/dist/cjs/managers/user.manager.js +2 -2
  36. package/dist/cjs/public-api.d.ts +3 -3
  37. package/dist/cjs/public-api.js +1 -1
  38. package/dist/cjs/test-bridge.d.ts +1 -0
  39. package/dist/cjs/test-bridge.js +37 -2
  40. package/dist/cjs/types/config.types.d.ts +15 -18
  41. package/dist/cjs/types/config.types.js +6 -0
  42. package/dist/cjs/types/event.types.d.ts +1 -13
  43. package/dist/cjs/types/index.d.ts +0 -2
  44. package/dist/cjs/types/index.js +0 -2
  45. package/dist/cjs/types/mode.types.d.ts +1 -2
  46. package/dist/cjs/types/mode.types.js +0 -1
  47. package/dist/cjs/types/queue.types.d.ts +0 -6
  48. package/dist/cjs/types/state.types.d.ts +2 -0
  49. package/dist/cjs/types/test-bridge.types.d.ts +2 -2
  50. package/dist/cjs/types/validation-error.types.d.ts +0 -6
  51. package/dist/cjs/types/validation-error.types.js +1 -10
  52. package/dist/cjs/utils/browser/device-detector.utils.js +2 -24
  53. package/dist/cjs/utils/browser/index.d.ts +1 -0
  54. package/dist/cjs/utils/browser/index.js +1 -0
  55. package/dist/cjs/utils/browser/qa-mode.utils.d.ts +13 -0
  56. package/dist/cjs/utils/browser/qa-mode.utils.js +43 -0
  57. package/dist/cjs/utils/browser/utm-params.utils.js +0 -15
  58. package/dist/cjs/utils/data/uuid.utils.d.ts +13 -0
  59. package/dist/cjs/utils/data/uuid.utils.js +37 -1
  60. package/dist/cjs/utils/index.d.ts +1 -1
  61. package/dist/cjs/utils/index.js +1 -1
  62. package/dist/cjs/utils/logging.utils.d.ts +6 -0
  63. package/dist/cjs/utils/logging.utils.js +25 -0
  64. package/dist/cjs/utils/network/index.d.ts +0 -1
  65. package/dist/cjs/utils/network/index.js +0 -1
  66. package/dist/cjs/utils/network/url.utils.d.ts +2 -8
  67. package/dist/cjs/utils/network/url.utils.js +46 -90
  68. package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -13
  69. package/dist/cjs/utils/security/sanitize.utils.js +15 -178
  70. package/dist/cjs/utils/validations/config-validations.utils.d.ts +3 -9
  71. package/dist/cjs/utils/validations/config-validations.utils.js +48 -94
  72. package/dist/cjs/utils/validations/event-validations.utils.js +11 -5
  73. package/dist/cjs/utils/validations/index.d.ts +0 -1
  74. package/dist/cjs/utils/validations/index.js +0 -1
  75. package/dist/cjs/utils/validations/metadata-validations.utils.js +0 -1
  76. package/dist/cjs/utils/validations/type-guards.utils.d.ts +2 -2
  77. package/dist/cjs/utils/validations/type-guards.utils.js +50 -4
  78. package/dist/esm/api.d.ts +12 -2
  79. package/dist/esm/api.js +62 -27
  80. package/dist/esm/app.d.ts +2 -2
  81. package/dist/esm/app.js +28 -34
  82. package/dist/esm/constants/config.constants.d.ts +4 -2
  83. package/dist/esm/constants/config.constants.js +4 -16
  84. package/dist/esm/constants/index.d.ts +0 -1
  85. package/dist/esm/constants/index.js +0 -1
  86. package/dist/esm/constants/storage.constants.d.ts +3 -2
  87. package/dist/esm/constants/storage.constants.js +3 -2
  88. package/dist/esm/handlers/click.handler.js +3 -6
  89. package/dist/esm/handlers/error.handler.js +1 -11
  90. package/dist/esm/handlers/page-view.handler.js +0 -4
  91. package/dist/esm/handlers/performance.handler.js +14 -29
  92. package/dist/esm/handlers/scroll.handler.js +7 -6
  93. package/dist/esm/handlers/session.handler.js +7 -6
  94. package/dist/esm/integrations/google-analytics.integration.js +3 -7
  95. package/dist/esm/listeners/activity-listener-manager.js +3 -3
  96. package/dist/esm/listeners/input-listener-managers.js +3 -3
  97. package/dist/esm/listeners/touch-listener-manager.js +3 -3
  98. package/dist/esm/listeners/unload-listener-manager.js +3 -3
  99. package/dist/esm/listeners/visibility-listener-manager.js +3 -3
  100. package/dist/esm/managers/event.manager.d.ts +2 -1
  101. package/dist/esm/managers/event.manager.js +62 -40
  102. package/dist/esm/managers/sender.manager.js +31 -38
  103. package/dist/esm/managers/session.manager.js +5 -13
  104. package/dist/esm/managers/state.manager.d.ts +0 -3
  105. package/dist/esm/managers/state.manager.js +1 -43
  106. package/dist/esm/managers/storage.manager.d.ts +16 -2
  107. package/dist/esm/managers/storage.manager.js +73 -19
  108. package/dist/esm/managers/user.manager.d.ts +1 -1
  109. package/dist/esm/managers/user.manager.js +2 -2
  110. package/dist/esm/public-api.d.ts +3 -3
  111. package/dist/esm/public-api.js +1 -1
  112. package/dist/esm/test-bridge.d.ts +1 -0
  113. package/dist/esm/test-bridge.js +37 -2
  114. package/dist/esm/types/config.types.d.ts +15 -18
  115. package/dist/esm/types/config.types.js +5 -1
  116. package/dist/esm/types/event.types.d.ts +1 -13
  117. package/dist/esm/types/index.d.ts +0 -2
  118. package/dist/esm/types/index.js +0 -2
  119. package/dist/esm/types/mode.types.d.ts +1 -2
  120. package/dist/esm/types/mode.types.js +0 -1
  121. package/dist/esm/types/queue.types.d.ts +0 -6
  122. package/dist/esm/types/state.types.d.ts +2 -0
  123. package/dist/esm/types/test-bridge.types.d.ts +2 -2
  124. package/dist/esm/types/validation-error.types.d.ts +0 -6
  125. package/dist/esm/types/validation-error.types.js +0 -8
  126. package/dist/esm/utils/browser/device-detector.utils.js +2 -24
  127. package/dist/esm/utils/browser/index.d.ts +1 -0
  128. package/dist/esm/utils/browser/index.js +1 -0
  129. package/dist/esm/utils/browser/qa-mode.utils.d.ts +13 -0
  130. package/dist/esm/utils/browser/qa-mode.utils.js +39 -0
  131. package/dist/esm/utils/browser/utm-params.utils.js +0 -15
  132. package/dist/esm/utils/data/uuid.utils.d.ts +13 -0
  133. package/dist/esm/utils/data/uuid.utils.js +35 -0
  134. package/dist/esm/utils/index.d.ts +1 -1
  135. package/dist/esm/utils/index.js +1 -1
  136. package/dist/esm/utils/logging.utils.d.ts +6 -0
  137. package/dist/esm/utils/logging.utils.js +20 -0
  138. package/dist/esm/utils/network/index.d.ts +0 -1
  139. package/dist/esm/utils/network/index.js +0 -1
  140. package/dist/esm/utils/network/url.utils.d.ts +2 -8
  141. package/dist/esm/utils/network/url.utils.js +45 -88
  142. package/dist/esm/utils/security/sanitize.utils.d.ts +1 -13
  143. package/dist/esm/utils/security/sanitize.utils.js +15 -176
  144. package/dist/esm/utils/validations/config-validations.utils.d.ts +3 -9
  145. package/dist/esm/utils/validations/config-validations.utils.js +49 -94
  146. package/dist/esm/utils/validations/event-validations.utils.js +11 -5
  147. package/dist/esm/utils/validations/index.d.ts +0 -1
  148. package/dist/esm/utils/validations/index.js +0 -1
  149. package/dist/esm/utils/validations/metadata-validations.utils.js +0 -1
  150. package/dist/esm/utils/validations/type-guards.utils.d.ts +2 -2
  151. package/dist/esm/utils/validations/type-guards.utils.js +50 -4
  152. package/package.json +1 -1
  153. package/dist/cjs/app.types.d.ts +0 -2
  154. package/dist/cjs/app.types.js +0 -12
  155. package/dist/cjs/constants/api.constants.d.ts +0 -6
  156. package/dist/cjs/constants/api.constants.js +0 -14
  157. package/dist/cjs/managers/api.manager.d.ts +0 -13
  158. package/dist/cjs/managers/api.manager.js +0 -44
  159. package/dist/cjs/managers/config.builder.d.ts +0 -33
  160. package/dist/cjs/managers/config.builder.js +0 -116
  161. package/dist/cjs/managers/config.manager.d.ts +0 -56
  162. package/dist/cjs/managers/config.manager.js +0 -157
  163. package/dist/cjs/managers/tags.manager.d.ts +0 -36
  164. package/dist/cjs/managers/tags.manager.js +0 -171
  165. package/dist/cjs/types/api.types.d.ts +0 -52
  166. package/dist/cjs/types/api.types.js +0 -56
  167. package/dist/cjs/types/tag.types.d.ts +0 -43
  168. package/dist/cjs/types/tag.types.js +0 -31
  169. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +0 -14
  170. package/dist/cjs/utils/logging/debug-logger.utils.js +0 -47
  171. package/dist/cjs/utils/logging/index.d.ts +0 -1
  172. package/dist/cjs/utils/logging/index.js +0 -5
  173. package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  174. package/dist/cjs/utils/network/fetch-with-timeout.utils.js +0 -25
  175. package/dist/cjs/utils/validations/url-validations.utils.d.ts +0 -15
  176. package/dist/cjs/utils/validations/url-validations.utils.js +0 -47
  177. package/dist/esm/app.types.d.ts +0 -2
  178. package/dist/esm/app.types.js +0 -1
  179. package/dist/esm/constants/api.constants.d.ts +0 -6
  180. package/dist/esm/constants/api.constants.js +0 -11
  181. package/dist/esm/managers/api.manager.d.ts +0 -13
  182. package/dist/esm/managers/api.manager.js +0 -41
  183. package/dist/esm/managers/config.builder.d.ts +0 -33
  184. package/dist/esm/managers/config.builder.js +0 -112
  185. package/dist/esm/managers/config.manager.d.ts +0 -56
  186. package/dist/esm/managers/config.manager.js +0 -153
  187. package/dist/esm/managers/tags.manager.d.ts +0 -36
  188. package/dist/esm/managers/tags.manager.js +0 -167
  189. package/dist/esm/types/api.types.d.ts +0 -52
  190. package/dist/esm/types/api.types.js +0 -53
  191. package/dist/esm/types/tag.types.d.ts +0 -43
  192. package/dist/esm/types/tag.types.js +0 -28
  193. package/dist/esm/utils/logging/debug-logger.utils.d.ts +0 -14
  194. package/dist/esm/utils/logging/debug-logger.utils.js +0 -44
  195. package/dist/esm/utils/logging/index.d.ts +0 -1
  196. package/dist/esm/utils/logging/index.js +0 -1
  197. package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  198. package/dist/esm/utils/network/fetch-with-timeout.utils.js +0 -22
  199. package/dist/esm/utils/validations/url-validations.utils.d.ts +0 -15
  200. package/dist/esm/utils/validations/url-validations.utils.js +0 -42
@@ -1,30 +1,54 @@
1
- import { isValidUrl } from '../validations';
2
- import { debugLog } from '../logging';
1
+ import { log } from '../logging.utils';
2
+ /**
3
+ * Validates if a URL is valid and optionally allows HTTP URLs
4
+ * @param url - The URL to validate
5
+ * @param allowHttp - Whether to allow HTTP URLs (default: false)
6
+ * @returns True if the URL is valid, false otherwise
7
+ */
8
+ const isValidUrl = (url, allowHttp = false) => {
9
+ try {
10
+ const parsed = new URL(url);
11
+ const isHttps = parsed.protocol === 'https:';
12
+ const isHttp = parsed.protocol === 'http:';
13
+ return isHttps || (allowHttp && isHttp);
14
+ }
15
+ catch {
16
+ return false;
17
+ }
18
+ };
3
19
  /**
4
20
  * Generates an API URL based on project ID and current domain
5
21
  * @param id - The project ID
6
22
  * @returns The generated API URL
7
23
  */
8
- export const getApiUrl = (id, allowHttp = false) => {
9
- const url = new URL(window.location.href);
10
- const host = url.hostname;
11
- const parts = host.split('.');
12
- if (parts.length === 0) {
13
- debugLog.clientError('URLUtils', 'Invalid hostname - no domain parts found', { hostname: host });
14
- throw new Error('Invalid URL');
24
+ export const getApiUrl = (config) => {
25
+ const allowHttp = config.allowHttp ?? false;
26
+ if (config.integrations?.tracelog?.projectId) {
27
+ const url = new URL(window.location.href);
28
+ const host = url.hostname;
29
+ const parts = host.split('.');
30
+ if (parts.length === 0) {
31
+ throw new Error('Invalid URL');
32
+ }
33
+ const projectId = config.integrations.tracelog.projectId;
34
+ const cleanDomain = parts.slice(-2).join('.');
35
+ const protocol = allowHttp && url.protocol === 'http:' ? 'http' : 'https';
36
+ const apiUrl = `${protocol}://${projectId}.${cleanDomain}`;
37
+ const isValid = isValidUrl(apiUrl, allowHttp);
38
+ if (!isValid) {
39
+ throw new Error('Invalid URL');
40
+ }
41
+ return apiUrl;
15
42
  }
16
- const cleanDomain = parts.slice(-2).join('.');
17
- const protocol = allowHttp && url.protocol === 'http:' ? 'http' : 'https';
18
- const apiUrl = `${protocol}://${id}.${cleanDomain}`;
19
- const isValid = isValidUrl(apiUrl, allowHttp);
20
- if (!isValid) {
21
- debugLog.clientError('URLUtils', 'Generated API URL failed validation', {
22
- apiUrl,
23
- allowHttp,
24
- });
25
- throw new Error('Invalid URL');
43
+ if (config.integrations?.custom?.apiUrl) {
44
+ const apiUrl = config.integrations.custom.apiUrl;
45
+ const isValid = isValidUrl(apiUrl, allowHttp);
46
+ if (!isValid) {
47
+ throw new Error('Invalid URL');
48
+ }
49
+ return apiUrl;
26
50
  }
27
- return apiUrl;
51
+ return '';
28
52
  };
29
53
  /**
30
54
  * Normalizes a URL by removing sensitive query parameters
@@ -36,7 +60,6 @@ export const normalizeUrl = (url, sensitiveQueryParams = []) => {
36
60
  try {
37
61
  const urlObject = new URL(url);
38
62
  const searchParams = urlObject.searchParams;
39
- const originalParamCount = Array.from(searchParams.keys()).length;
40
63
  let hasChanged = false;
41
64
  const removedParams = [];
42
65
  sensitiveQueryParams.forEach((param) => {
@@ -46,13 +69,6 @@ export const normalizeUrl = (url, sensitiveQueryParams = []) => {
46
69
  removedParams.push(param);
47
70
  }
48
71
  });
49
- if (hasChanged) {
50
- debugLog.debug('URLUtils', 'Sensitive parameters removed from URL', {
51
- removedParams,
52
- originalParamCount,
53
- finalParamCount: Array.from(searchParams.keys()).length,
54
- });
55
- }
56
72
  if (!hasChanged && url.includes('?')) {
57
73
  return url;
58
74
  }
@@ -61,66 +77,7 @@ export const normalizeUrl = (url, sensitiveQueryParams = []) => {
61
77
  return result;
62
78
  }
63
79
  catch (error) {
64
- debugLog.warn('URLUtils', 'URL normalization failed, returning original', {
65
- url: url.slice(0, 100),
66
- error: error instanceof Error ? error.message : error,
67
- });
80
+ log('warn', 'URL normalization failed, returning original', { error, data: { url: url.slice(0, 100) } });
68
81
  return url;
69
82
  }
70
83
  };
71
- /**
72
- * Checks if a URL path should be excluded from tracking
73
- * @param url - The URL to check
74
- * @param excludedPaths - Array of patterns to match against
75
- * @returns True if the URL should be excluded
76
- */
77
- export const isUrlPathExcluded = (url, excludedPaths = []) => {
78
- if (excludedPaths.length === 0) {
79
- return false;
80
- }
81
- let path;
82
- try {
83
- const parsedUrl = new URL(url, window.location.origin);
84
- path = parsedUrl.pathname + (parsedUrl.hash ?? '');
85
- }
86
- catch (error) {
87
- debugLog.warn('URLUtils', 'Failed to parse URL for path exclusion check', {
88
- url: url.slice(0, 100),
89
- error: error instanceof Error ? error.message : error,
90
- });
91
- return false;
92
- }
93
- const isRegularExpression = (value) => typeof value === 'object' && value !== undefined && typeof value.test === 'function';
94
- const escapeRegexString = (string_) => string_.replaceAll(/[$()*+.?[\\\]^{|}]/g, '\\$&');
95
- const wildcardToRegex = (string_) => new RegExp('^' +
96
- string_
97
- .split('*')
98
- .map((element) => escapeRegexString(element))
99
- .join('.+') +
100
- '$');
101
- const matchedPattern = excludedPaths.find((pattern) => {
102
- try {
103
- if (isRegularExpression(pattern)) {
104
- const matches = pattern.test(path);
105
- return matches;
106
- }
107
- if (pattern.includes('*')) {
108
- const regex = wildcardToRegex(pattern);
109
- const matches = regex.test(path);
110
- return matches;
111
- }
112
- const matches = pattern === path;
113
- return matches;
114
- }
115
- catch (error) {
116
- debugLog.warn('URLUtils', 'Error testing exclusion pattern', {
117
- pattern,
118
- path,
119
- error: error instanceof Error ? error.message : error,
120
- });
121
- return false;
122
- }
123
- });
124
- const isExcluded = !!matchedPattern;
125
- return isExcluded;
126
- };
@@ -1,22 +1,10 @@
1
- import { MetadataType, ApiConfig } from '../../types';
1
+ import { MetadataType } from '../../types';
2
2
  /**
3
3
  * Sanitizes a string value to prevent XSS attacks
4
4
  * @param value - The string to sanitize
5
5
  * @returns The sanitized string
6
6
  */
7
7
  export declare const sanitizeString: (value: string) => string;
8
- /**
9
- * Sanitizes a path string for route exclusion checks
10
- * @param value - The path string to sanitize
11
- * @returns The sanitized path string
12
- */
13
- export declare const sanitizePathString: (value: string) => string;
14
- /**
15
- * Sanitizes API configuration data with strict validation
16
- * @param data - The API config data to sanitize
17
- * @returns The sanitized API config
18
- */
19
- export declare const sanitizeApiConfig: (data: unknown) => ApiConfig;
20
8
  /**
21
9
  * Sanitizes user metadata for custom events
22
10
  * @param metadata - The metadata to sanitize
@@ -1,5 +1,5 @@
1
- import { ALLOWED_API_CONFIG_KEYS, MAX_ARRAY_LENGTH, MAX_OBJECT_DEPTH, MAX_STRING_LENGTH, XSS_PATTERNS, } from '../../constants';
2
- import { debugLog } from '../logging';
1
+ import { MAX_ARRAY_LENGTH, MAX_OBJECT_DEPTH, MAX_STRING_LENGTH, XSS_PATTERNS } from '../../constants';
2
+ import { log } from '../logging.utils';
3
3
  /**
4
4
  * Sanitizes a string value to prevent XSS attacks
5
5
  * @param value - The string to sanitize
@@ -7,19 +7,13 @@ import { debugLog } from '../logging';
7
7
  */
8
8
  export const sanitizeString = (value) => {
9
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
10
  return '';
12
11
  }
13
- const originalLength = value.length;
14
12
  let sanitized = value;
15
13
  // Limit string length
16
14
  if (value.length > MAX_STRING_LENGTH) {
17
15
  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
- });
16
+ // Silent truncation - this is expected behavior for long strings
23
17
  }
24
18
  // Remove potential XSS patterns
25
19
  let xssPatternMatches = 0;
@@ -31,9 +25,11 @@ export const sanitizeString = (value) => {
31
25
  }
32
26
  }
33
27
  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
28
+ log('warn', 'XSS patterns detected and removed', {
29
+ data: {
30
+ patternMatches: xssPatternMatches,
31
+ originalValue: value.slice(0, 100),
32
+ },
37
33
  });
38
34
  }
39
35
  // Basic HTML entity encoding for critical characters
@@ -45,40 +41,8 @@ export const sanitizeString = (value) => {
45
41
  .replaceAll("'", ''')
46
42
  .replaceAll('/', '/');
47
43
  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
44
  return result;
57
45
  };
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('&', '&')
76
- .replaceAll('<', '&lt;')
77
- .replaceAll('>', '&gt;')
78
- .replaceAll('"', '&quot;')
79
- .replaceAll("'", '&#x27;');
80
- return sanitized.trim();
81
- };
82
46
  /**
83
47
  * Sanitizes any value recursively with depth protection
84
48
  * @param value - The value to sanitize
@@ -88,10 +52,7 @@ export const sanitizePathString = (value) => {
88
52
  const sanitizeValue = (value, depth = 0) => {
89
53
  // Prevent infinite recursion
90
54
  if (depth > MAX_OBJECT_DEPTH) {
91
- debugLog.warn('Sanitize', 'Maximum object depth exceeded during sanitization', {
92
- depth,
93
- maxDepth: MAX_OBJECT_DEPTH,
94
- });
55
+ // Silent depth limit - prevents stack overflow
95
56
  return null;
96
57
  }
97
58
  if (value === null || value === undefined) {
@@ -102,7 +63,7 @@ const sanitizeValue = (value, depth = 0) => {
102
63
  }
103
64
  if (typeof value === 'number') {
104
65
  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) });
66
+ // Silent normalization - invalid numbers become 0
106
67
  return 0;
107
68
  }
108
69
  return value;
@@ -111,34 +72,17 @@ const sanitizeValue = (value, depth = 0) => {
111
72
  return value;
112
73
  }
113
74
  if (Array.isArray(value)) {
114
- const originalLength = value.length;
115
75
  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
- }
76
+ // Silent array length limit
123
77
  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
- }
78
+ // Silent filter - empty arrays are valid results
127
79
  return sanitizedArray;
128
80
  }
129
81
  if (typeof value === 'object') {
130
82
  const sanitizedObject = {};
131
83
  const entries = Object.entries(value);
132
- const originalKeysCount = entries.length;
133
84
  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;
85
+ // Silent object keys limit
142
86
  for (const [key, value_] of limitedEntries) {
143
87
  const sanitizedKey = sanitizeString(key);
144
88
  if (sanitizedKey) {
@@ -146,133 +90,28 @@ const sanitizeValue = (value, depth = 0) => {
146
90
  if (sanitizedValue !== null) {
147
91
  sanitizedObject[sanitizedKey] = sanitizedValue;
148
92
  }
149
- else {
150
- filteredKeysCount++;
151
- }
152
- }
153
- else {
154
- filteredKeysCount++;
155
93
  }
156
94
  }
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
95
  return sanitizedObject;
165
96
  }
166
- debugLog.debug('Sanitize', 'Unknown value type sanitized to null', { type: typeof value, depth });
167
97
  return null;
168
98
  };
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 if (key === 'samplingRate') {
210
- const sanitizedValue = sanitizeValue(value);
211
- if (typeof sanitizedValue === 'number') {
212
- safeData.samplingRate = sanitizedValue;
213
- }
214
- }
215
- else {
216
- const sanitizedValue = sanitizeValue(value);
217
- if (sanitizedValue !== null) {
218
- safeData[key] = sanitizedValue;
219
- }
220
- else {
221
- debugLog.warn('Sanitize', 'API config value sanitized to null', { key, originalValue: value });
222
- }
223
- }
224
- processedKeys++;
225
- }
226
- else {
227
- filteredKeys++;
228
- debugLog.debug('Sanitize', 'API config key not allowed', { key });
229
- }
230
- }
231
- debugLog.info('Sanitize', 'API config sanitization completed', {
232
- originalKeys: originalKeys.length,
233
- processedKeys,
234
- filteredKeys,
235
- finalKeys: Object.keys(safeData).length,
236
- });
237
- }
238
- catch (error) {
239
- debugLog.error('Sanitize', 'API config sanitization failed', {
240
- error: error instanceof Error ? error.message : error,
241
- });
242
- throw new Error(`API config sanitization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
243
- }
244
- return safeData;
245
- };
246
99
  /**
247
100
  * Sanitizes user metadata for custom events
248
101
  * @param metadata - The metadata to sanitize
249
102
  * @returns The sanitized metadata
250
103
  */
251
104
  export const sanitizeMetadata = (metadata) => {
252
- debugLog.debug('Sanitize', 'Starting metadata sanitization', { hasMetadata: metadata != null });
253
105
  if (typeof metadata !== 'object' || metadata === null) {
254
- debugLog.debug('Sanitize', 'Metadata is not an object, returning empty object', {
255
- metadata,
256
- type: typeof metadata,
257
- });
258
106
  return {};
259
107
  }
260
108
  try {
261
- const originalKeys = Object.keys(metadata).length;
262
109
  const sanitized = sanitizeValue(metadata);
263
110
  const result = typeof sanitized === 'object' && sanitized !== null ? sanitized : {};
264
- const finalKeys = Object.keys(result).length;
265
- debugLog.debug('Sanitize', 'Metadata sanitization completed', {
266
- originalKeys,
267
- finalKeys,
268
- keysFiltered: originalKeys - finalKeys,
269
- });
270
111
  return result;
271
112
  }
272
113
  catch (error) {
273
- debugLog.error('Sanitize', 'Metadata sanitization failed', {
274
- error: error instanceof Error ? error.message : error,
275
- });
276
- throw new Error(`Metadata sanitization failed: ${error instanceof Error ? error.message : 'Unknown error'}`);
114
+ const errorMessage = error instanceof Error ? error.message : String(error);
115
+ throw new Error(`[TraceLog] Metadata sanitization failed: ${errorMessage}`);
277
116
  }
278
117
  };
@@ -1,4 +1,4 @@
1
- import { AppConfig, ApiConfig } from '../../types';
1
+ import { Config } from '../../types';
2
2
  /**
3
3
  * Validates the app configuration object (before normalization)
4
4
  * This validates the structure and basic types but allows for normalization afterward
@@ -6,7 +6,7 @@ import { AppConfig, ApiConfig } from '../../types';
6
6
  * @throws {ProjectIdValidationError} If project ID validation fails
7
7
  * @throws {AppConfigValidationError} If other configuration validation fails
8
8
  */
9
- export declare const validateAppConfig: (config: AppConfig) => void;
9
+ export declare const validateAppConfig: (config: Config) => void;
10
10
  /**
11
11
  * Validates and normalizes the app configuration
12
12
  * This is the primary validation entry point that ensures consistent behavior
@@ -15,10 +15,4 @@ export declare const validateAppConfig: (config: AppConfig) => void;
15
15
  * @throws {ProjectIdValidationError} If project ID validation fails after normalization
16
16
  * @throws {AppConfigValidationError} If other configuration validation fails
17
17
  */
18
- export declare const validateAndNormalizeConfig: (config: AppConfig) => AppConfig;
19
- /**
20
- * Type guard to check if a JSON response is a valid API config
21
- * @param json - The JSON to validate
22
- * @returns True if the JSON is a valid API config
23
- */
24
- export declare const isValidConfigApiResponse: (json: unknown) => json is ApiConfig;
18
+ export declare const validateAndNormalizeConfig: (config: Config) => Config;