@tracelog/lib 0.5.5 → 0.6.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 (202) hide show
  1. package/README.md +157 -180
  2. package/dist/browser/tracelog.esm.js +1124 -1377
  3. package/dist/browser/tracelog.esm.js.map +1 -0
  4. package/dist/browser/tracelog.js +2 -2
  5. package/dist/browser/tracelog.js.map +1 -0
  6. package/dist/cjs/api.d.ts +12 -2
  7. package/dist/cjs/api.js +74 -29
  8. package/dist/cjs/app.d.ts +2 -2
  9. package/dist/cjs/app.js +26 -32
  10. package/dist/cjs/constants/config.constants.d.ts +7 -2
  11. package/dist/cjs/constants/config.constants.js +9 -18
  12. package/dist/cjs/constants/index.d.ts +0 -1
  13. package/dist/cjs/constants/index.js +0 -1
  14. package/dist/cjs/constants/storage.constants.d.ts +3 -2
  15. package/dist/cjs/constants/storage.constants.js +4 -4
  16. package/dist/cjs/handlers/click.handler.js +3 -6
  17. package/dist/cjs/handlers/error.handler.js +1 -11
  18. package/dist/cjs/handlers/page-view.handler.js +0 -4
  19. package/dist/cjs/handlers/performance.handler.js +14 -29
  20. package/dist/cjs/handlers/scroll.handler.js +7 -6
  21. package/dist/cjs/handlers/session.handler.js +7 -6
  22. package/dist/cjs/integrations/google-analytics.integration.js +2 -6
  23. package/dist/cjs/listeners/activity-listener-manager.js +3 -3
  24. package/dist/cjs/listeners/input-listener-managers.js +3 -3
  25. package/dist/cjs/listeners/touch-listener-manager.js +3 -3
  26. package/dist/cjs/listeners/unload-listener-manager.js +3 -3
  27. package/dist/cjs/listeners/visibility-listener-manager.js +3 -3
  28. package/dist/cjs/managers/event.manager.d.ts +5 -1
  29. package/dist/cjs/managers/event.manager.js +103 -40
  30. package/dist/cjs/managers/sender.manager.js +29 -36
  31. package/dist/cjs/managers/session.manager.js +5 -13
  32. package/dist/cjs/managers/state.manager.d.ts +0 -3
  33. package/dist/cjs/managers/state.manager.js +1 -43
  34. package/dist/cjs/managers/storage.manager.d.ts +21 -2
  35. package/dist/cjs/managers/storage.manager.js +164 -21
  36. package/dist/cjs/managers/user.manager.d.ts +1 -1
  37. package/dist/cjs/managers/user.manager.js +2 -2
  38. package/dist/cjs/public-api.d.ts +3 -3
  39. package/dist/cjs/public-api.js +1 -1
  40. package/dist/cjs/test-bridge.d.ts +1 -0
  41. package/dist/cjs/test-bridge.js +37 -2
  42. package/dist/cjs/types/config.types.d.ts +17 -20
  43. package/dist/cjs/types/config.types.js +6 -0
  44. package/dist/cjs/types/event.types.d.ts +1 -13
  45. package/dist/cjs/types/index.d.ts +0 -2
  46. package/dist/cjs/types/index.js +0 -2
  47. package/dist/cjs/types/mode.types.d.ts +1 -2
  48. package/dist/cjs/types/mode.types.js +0 -1
  49. package/dist/cjs/types/queue.types.d.ts +0 -6
  50. package/dist/cjs/types/state.types.d.ts +2 -0
  51. package/dist/cjs/types/test-bridge.types.d.ts +2 -2
  52. package/dist/cjs/types/validation-error.types.d.ts +0 -6
  53. package/dist/cjs/types/validation-error.types.js +1 -10
  54. package/dist/cjs/utils/browser/device-detector.utils.js +2 -24
  55. package/dist/cjs/utils/browser/index.d.ts +1 -0
  56. package/dist/cjs/utils/browser/index.js +1 -0
  57. package/dist/cjs/utils/browser/qa-mode.utils.d.ts +13 -0
  58. package/dist/cjs/utils/browser/qa-mode.utils.js +43 -0
  59. package/dist/cjs/utils/browser/utm-params.utils.js +0 -15
  60. package/dist/cjs/utils/data/uuid.utils.d.ts +13 -0
  61. package/dist/cjs/utils/data/uuid.utils.js +37 -1
  62. package/dist/cjs/utils/index.d.ts +1 -1
  63. package/dist/cjs/utils/index.js +1 -1
  64. package/dist/cjs/utils/logging.utils.d.ts +21 -0
  65. package/dist/cjs/utils/logging.utils.js +86 -0
  66. package/dist/cjs/utils/network/index.d.ts +0 -1
  67. package/dist/cjs/utils/network/index.js +0 -1
  68. package/dist/cjs/utils/network/url.utils.d.ts +2 -8
  69. package/dist/cjs/utils/network/url.utils.js +45 -90
  70. package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -13
  71. package/dist/cjs/utils/security/sanitize.utils.js +15 -178
  72. package/dist/cjs/utils/validations/config-validations.utils.d.ts +3 -9
  73. package/dist/cjs/utils/validations/config-validations.utils.js +56 -93
  74. package/dist/cjs/utils/validations/event-validations.utils.js +11 -5
  75. package/dist/cjs/utils/validations/index.d.ts +0 -1
  76. package/dist/cjs/utils/validations/index.js +0 -1
  77. package/dist/cjs/utils/validations/metadata-validations.utils.js +0 -1
  78. package/dist/cjs/utils/validations/type-guards.utils.d.ts +2 -2
  79. package/dist/cjs/utils/validations/type-guards.utils.js +50 -4
  80. package/dist/esm/api.d.ts +12 -2
  81. package/dist/esm/api.js +73 -29
  82. package/dist/esm/app.d.ts +2 -2
  83. package/dist/esm/app.js +28 -34
  84. package/dist/esm/constants/config.constants.d.ts +7 -2
  85. package/dist/esm/constants/config.constants.js +7 -16
  86. package/dist/esm/constants/index.d.ts +0 -1
  87. package/dist/esm/constants/index.js +0 -1
  88. package/dist/esm/constants/storage.constants.d.ts +3 -2
  89. package/dist/esm/constants/storage.constants.js +3 -2
  90. package/dist/esm/handlers/click.handler.js +3 -6
  91. package/dist/esm/handlers/error.handler.js +1 -11
  92. package/dist/esm/handlers/page-view.handler.js +0 -4
  93. package/dist/esm/handlers/performance.handler.js +14 -29
  94. package/dist/esm/handlers/scroll.handler.js +7 -6
  95. package/dist/esm/handlers/session.handler.js +7 -6
  96. package/dist/esm/integrations/google-analytics.integration.js +3 -7
  97. package/dist/esm/listeners/activity-listener-manager.js +3 -3
  98. package/dist/esm/listeners/input-listener-managers.js +3 -3
  99. package/dist/esm/listeners/touch-listener-manager.js +3 -3
  100. package/dist/esm/listeners/unload-listener-manager.js +3 -3
  101. package/dist/esm/listeners/visibility-listener-manager.js +3 -3
  102. package/dist/esm/managers/event.manager.d.ts +5 -1
  103. package/dist/esm/managers/event.manager.js +106 -43
  104. package/dist/esm/managers/sender.manager.js +31 -38
  105. package/dist/esm/managers/session.manager.js +5 -13
  106. package/dist/esm/managers/state.manager.d.ts +0 -3
  107. package/dist/esm/managers/state.manager.js +1 -43
  108. package/dist/esm/managers/storage.manager.d.ts +21 -2
  109. package/dist/esm/managers/storage.manager.js +164 -21
  110. package/dist/esm/managers/user.manager.d.ts +1 -1
  111. package/dist/esm/managers/user.manager.js +2 -2
  112. package/dist/esm/public-api.d.ts +3 -3
  113. package/dist/esm/public-api.js +1 -1
  114. package/dist/esm/test-bridge.d.ts +1 -0
  115. package/dist/esm/test-bridge.js +37 -2
  116. package/dist/esm/types/config.types.d.ts +17 -20
  117. package/dist/esm/types/config.types.js +5 -1
  118. package/dist/esm/types/event.types.d.ts +1 -13
  119. package/dist/esm/types/index.d.ts +0 -2
  120. package/dist/esm/types/index.js +0 -2
  121. package/dist/esm/types/mode.types.d.ts +1 -2
  122. package/dist/esm/types/mode.types.js +0 -1
  123. package/dist/esm/types/queue.types.d.ts +0 -6
  124. package/dist/esm/types/state.types.d.ts +2 -0
  125. package/dist/esm/types/test-bridge.types.d.ts +2 -2
  126. package/dist/esm/types/validation-error.types.d.ts +0 -6
  127. package/dist/esm/types/validation-error.types.js +0 -8
  128. package/dist/esm/utils/browser/device-detector.utils.js +2 -24
  129. package/dist/esm/utils/browser/index.d.ts +1 -0
  130. package/dist/esm/utils/browser/index.js +1 -0
  131. package/dist/esm/utils/browser/qa-mode.utils.d.ts +13 -0
  132. package/dist/esm/utils/browser/qa-mode.utils.js +39 -0
  133. package/dist/esm/utils/browser/utm-params.utils.js +0 -15
  134. package/dist/esm/utils/data/uuid.utils.d.ts +13 -0
  135. package/dist/esm/utils/data/uuid.utils.js +35 -0
  136. package/dist/esm/utils/index.d.ts +1 -1
  137. package/dist/esm/utils/index.js +1 -1
  138. package/dist/esm/utils/logging.utils.d.ts +21 -0
  139. package/dist/esm/utils/logging.utils.js +81 -0
  140. package/dist/esm/utils/network/index.d.ts +0 -1
  141. package/dist/esm/utils/network/index.js +0 -1
  142. package/dist/esm/utils/network/url.utils.d.ts +2 -8
  143. package/dist/esm/utils/network/url.utils.js +44 -88
  144. package/dist/esm/utils/security/sanitize.utils.d.ts +1 -13
  145. package/dist/esm/utils/security/sanitize.utils.js +15 -176
  146. package/dist/esm/utils/validations/config-validations.utils.d.ts +3 -9
  147. package/dist/esm/utils/validations/config-validations.utils.js +57 -93
  148. package/dist/esm/utils/validations/event-validations.utils.js +11 -5
  149. package/dist/esm/utils/validations/index.d.ts +0 -1
  150. package/dist/esm/utils/validations/index.js +0 -1
  151. package/dist/esm/utils/validations/metadata-validations.utils.js +0 -1
  152. package/dist/esm/utils/validations/type-guards.utils.d.ts +2 -2
  153. package/dist/esm/utils/validations/type-guards.utils.js +50 -4
  154. package/package.json +3 -2
  155. package/dist/cjs/app.types.d.ts +0 -2
  156. package/dist/cjs/app.types.js +0 -12
  157. package/dist/cjs/constants/api.constants.d.ts +0 -6
  158. package/dist/cjs/constants/api.constants.js +0 -14
  159. package/dist/cjs/managers/api.manager.d.ts +0 -13
  160. package/dist/cjs/managers/api.manager.js +0 -44
  161. package/dist/cjs/managers/config.builder.d.ts +0 -33
  162. package/dist/cjs/managers/config.builder.js +0 -116
  163. package/dist/cjs/managers/config.manager.d.ts +0 -56
  164. package/dist/cjs/managers/config.manager.js +0 -157
  165. package/dist/cjs/managers/tags.manager.d.ts +0 -36
  166. package/dist/cjs/managers/tags.manager.js +0 -171
  167. package/dist/cjs/types/api.types.d.ts +0 -52
  168. package/dist/cjs/types/api.types.js +0 -56
  169. package/dist/cjs/types/tag.types.d.ts +0 -43
  170. package/dist/cjs/types/tag.types.js +0 -31
  171. package/dist/cjs/utils/logging/debug-logger.utils.d.ts +0 -14
  172. package/dist/cjs/utils/logging/debug-logger.utils.js +0 -47
  173. package/dist/cjs/utils/logging/index.d.ts +0 -1
  174. package/dist/cjs/utils/logging/index.js +0 -5
  175. package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  176. package/dist/cjs/utils/network/fetch-with-timeout.utils.js +0 -25
  177. package/dist/cjs/utils/validations/url-validations.utils.d.ts +0 -15
  178. package/dist/cjs/utils/validations/url-validations.utils.js +0 -47
  179. package/dist/esm/app.types.d.ts +0 -2
  180. package/dist/esm/app.types.js +0 -1
  181. package/dist/esm/constants/api.constants.d.ts +0 -6
  182. package/dist/esm/constants/api.constants.js +0 -11
  183. package/dist/esm/managers/api.manager.d.ts +0 -13
  184. package/dist/esm/managers/api.manager.js +0 -41
  185. package/dist/esm/managers/config.builder.d.ts +0 -33
  186. package/dist/esm/managers/config.builder.js +0 -112
  187. package/dist/esm/managers/config.manager.d.ts +0 -56
  188. package/dist/esm/managers/config.manager.js +0 -153
  189. package/dist/esm/managers/tags.manager.d.ts +0 -36
  190. package/dist/esm/managers/tags.manager.js +0 -167
  191. package/dist/esm/types/api.types.d.ts +0 -52
  192. package/dist/esm/types/api.types.js +0 -53
  193. package/dist/esm/types/tag.types.d.ts +0 -43
  194. package/dist/esm/types/tag.types.js +0 -28
  195. package/dist/esm/utils/logging/debug-logger.utils.d.ts +0 -14
  196. package/dist/esm/utils/logging/debug-logger.utils.js +0 -44
  197. package/dist/esm/utils/logging/index.d.ts +0 -1
  198. package/dist/esm/utils/logging/index.js +0 -1
  199. package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +0 -4
  200. package/dist/esm/utils/network/fetch-with-timeout.utils.js +0 -22
  201. package/dist/esm/utils/validations/url-validations.utils.d.ts +0 -15
  202. package/dist/esm/utils/validations/url-validations.utils.js +0 -42
@@ -1,7 +1,38 @@
1
+ import { MAX_NESTED_OBJECT_KEYS } from '../../constants';
1
2
  /**
2
- * Checks if an object contains only primitive fields (string, number, boolean, or string arrays)
3
+ * Validates if an item in an array is a valid nested object
4
+ * @param item - The item to validate
5
+ * @returns True if the item is a valid nested object
6
+ */
7
+ const isValidArrayItem = (item) => {
8
+ if (typeof item === 'string') {
9
+ return true;
10
+ }
11
+ // Allow objects with primitive fields only (one level deep)
12
+ if (typeof item === 'object' && item !== null && !Array.isArray(item)) {
13
+ const entries = Object.entries(item);
14
+ // Check key count limit
15
+ if (entries.length > MAX_NESTED_OBJECT_KEYS) {
16
+ return false;
17
+ }
18
+ // All values must be primitives (no nested objects or arrays)
19
+ for (const [, value] of entries) {
20
+ if (value === null || value === undefined) {
21
+ continue;
22
+ }
23
+ const type = typeof value;
24
+ if (type !== 'string' && type !== 'number' && type !== 'boolean') {
25
+ return false;
26
+ }
27
+ }
28
+ return true;
29
+ }
30
+ return false;
31
+ };
32
+ /**
33
+ * Checks if an object contains only primitive fields, string arrays, or arrays of flat objects
3
34
  * @param object - The object to check
4
- * @returns True if the object contains only primitive fields
35
+ * @returns True if the object contains only valid fields
5
36
  */
6
37
  export const isOnlyPrimitiveFields = (object) => {
7
38
  if (typeof object !== 'object' || object === null) {
@@ -16,8 +47,23 @@ export const isOnlyPrimitiveFields = (object) => {
16
47
  continue;
17
48
  }
18
49
  if (Array.isArray(value)) {
19
- if (!value.every((item) => typeof item === 'string')) {
20
- return false;
50
+ if (value.length === 0) {
51
+ continue;
52
+ }
53
+ // Determine array type from first item
54
+ const firstItem = value[0];
55
+ const isStringArray = typeof firstItem === 'string';
56
+ // All items must be of the same type (all strings OR all objects)
57
+ if (isStringArray) {
58
+ if (!value.every((item) => typeof item === 'string')) {
59
+ return false;
60
+ }
61
+ }
62
+ else {
63
+ // Must be all objects
64
+ if (!value.every((item) => isValidArrayItem(item))) {
65
+ return false;
66
+ }
21
67
  }
22
68
  continue;
23
69
  }
package/package.json CHANGED
@@ -2,7 +2,7 @@
2
2
  "name": "@tracelog/lib",
3
3
  "description": "JavaScript library for web analytics and real-time event tracking",
4
4
  "license": "MIT",
5
- "version": "0.5.5",
5
+ "version": "0.6.1",
6
6
  "main": "./dist/cjs/public-api.js",
7
7
  "module": "./dist/esm/public-api.js",
8
8
  "types": "./dist/esm/public-api.d.ts",
@@ -43,6 +43,7 @@
43
43
  "serve": "http-server playground -p 3000 --cors",
44
44
  "playground:setup": "npm run build:browser:dev && cp dist/browser/tracelog.esm.js playground/tracelog.js",
45
45
  "playground:dev": "npm run playground:setup && npm run serve",
46
+ "playground:gh-pages": "npm run build:browser && cp dist/browser/tracelog.esm.js playground/tracelog.js",
46
47
  "test:e2e": "npm run build:browser:dev && cp dist/browser/tracelog.esm.js playground/tracelog.js && NODE_ENV=dev playwright test",
47
48
  "ci:build": "npm run build:all",
48
49
  "prepare": "husky",
@@ -55,7 +56,7 @@
55
56
  "changelog:preview": "node scripts/generate-changelog.js --dry-run"
56
57
  },
57
58
  "dependencies": {
58
- "web-vitals": "^4.2.4"
59
+ "web-vitals": "4.2.4"
59
60
  },
60
61
  "devDependencies": {
61
62
  "@commitlint/config-conventional": "^19.8.1",
@@ -1,2 +0,0 @@
1
- export { Mode, EventType, DeviceType, ScrollDirection, ErrorType, TagConditionOperator, TagLogicalOperator, TagConditionType, } from './types';
2
- export type { ScrollData, ClickData, CustomEventData, MetadataType, WebVitalsData, ErrorData, PageViewData, UTM, EventLocation, EventData, AppConfig, ApiConfig, ExtendedEventsQueueDto, TagConfig, BaseEventsQueueDto, WebVitalType, SessionEndReason, } from './types';
@@ -1,12 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.TagConditionType = exports.TagLogicalOperator = exports.TagConditionOperator = exports.ErrorType = exports.ScrollDirection = exports.DeviceType = exports.EventType = exports.Mode = void 0;
4
- var types_1 = require("./types");
5
- Object.defineProperty(exports, "Mode", { enumerable: true, get: function () { return types_1.Mode; } });
6
- Object.defineProperty(exports, "EventType", { enumerable: true, get: function () { return types_1.EventType; } });
7
- Object.defineProperty(exports, "DeviceType", { enumerable: true, get: function () { return types_1.DeviceType; } });
8
- Object.defineProperty(exports, "ScrollDirection", { enumerable: true, get: function () { return types_1.ScrollDirection; } });
9
- Object.defineProperty(exports, "ErrorType", { enumerable: true, get: function () { return types_1.ErrorType; } });
10
- Object.defineProperty(exports, "TagConditionOperator", { enumerable: true, get: function () { return types_1.TagConditionOperator; } });
11
- Object.defineProperty(exports, "TagLogicalOperator", { enumerable: true, get: function () { return types_1.TagLogicalOperator; } });
12
- Object.defineProperty(exports, "TagConditionType", { enumerable: true, get: function () { return types_1.TagConditionType; } });
@@ -1,6 +0,0 @@
1
- import { ApiConfig } from '../types';
2
- /**
3
- * Default API configuration values
4
- * Used as fallback when API config is not available or incomplete
5
- */
6
- export declare const DEFAULT_API_CONFIG: ApiConfig;
@@ -1,14 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.DEFAULT_API_CONFIG = void 0;
4
- const config_constants_1 = require("./config.constants");
5
- /**
6
- * Default API configuration values
7
- * Used as fallback when API config is not available or incomplete
8
- */
9
- exports.DEFAULT_API_CONFIG = {
10
- samplingRate: config_constants_1.DEFAULT_SAMPLING_RATE,
11
- excludedUrlPaths: [],
12
- tags: [],
13
- ipExcluded: false,
14
- };
@@ -1,13 +0,0 @@
1
- /**
2
- * Generates API URL for TraceLog service based on project ID
3
- *
4
- * Handles two special cases:
5
- * - 'localhost:8080' or 'localhost:9999' - for local development (generates http://localhost:PORT)
6
- * - Regular project IDs - generates subdomain URLs via getApiUrl utility
7
- *
8
- * @param id Project ID or localhost address
9
- * @param allowHttp Whether to allow HTTP protocol (default: false)
10
- * @returns Generated API URL
11
- * @throws Error if URL generation or validation fails
12
- */
13
- export declare function getApiUrlForProject(id: string, allowHttp?: boolean): string;
@@ -1,44 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.getApiUrlForProject = getApiUrlForProject;
4
- const utils_1 = require("../utils");
5
- const types_1 = require("../types");
6
- const logging_1 = require("../utils/logging");
7
- /**
8
- * Generates API URL for TraceLog service based on project ID
9
- *
10
- * Handles two special cases:
11
- * - 'localhost:8080' or 'localhost:9999' - for local development (generates http://localhost:PORT)
12
- * - Regular project IDs - generates subdomain URLs via getApiUrl utility
13
- *
14
- * @param id Project ID or localhost address
15
- * @param allowHttp Whether to allow HTTP protocol (default: false)
16
- * @returns Generated API URL
17
- * @throws Error if URL generation or validation fails
18
- */
19
- function getApiUrlForProject(id, allowHttp = false) {
20
- try {
21
- // Handle localhost development case (localhost:8080 or localhost:9999)
22
- if (id === types_1.SpecialProjectId.Localhost || id === types_1.SpecialProjectId.Fail) {
23
- const url = `http://${id}`;
24
- if (!(0, utils_1.isValidUrl)(url, true)) {
25
- throw new Error(`Invalid localhost URL format: ${id}`);
26
- }
27
- return url;
28
- }
29
- // Handle regular project ID case
30
- const url = (0, utils_1.getApiUrl)(id, allowHttp);
31
- if (!(0, utils_1.isValidUrl)(url, allowHttp)) {
32
- throw new Error(`Generated API URL failed validation: ${url}`);
33
- }
34
- return url;
35
- }
36
- catch (error) {
37
- logging_1.debugLog.error('ApiManager', 'API URL generation failed', {
38
- projectId: id,
39
- allowHttp,
40
- error: error instanceof Error ? error.message : error,
41
- });
42
- throw error;
43
- }
44
- }
@@ -1,33 +0,0 @@
1
- import { AppConfig, ApiConfig, Config } from '../types';
2
- /**
3
- * Centralized configuration builder
4
- * Single source of truth for merging and building final configuration
5
- */
6
- export declare class ConfigBuilder {
7
- /**
8
- * Builds final configuration from app config and API config
9
- * Applies clear precedence: API overrides client, with defaults as fallback
10
- */
11
- static build(appConfig: AppConfig, apiConfig?: ApiConfig): Config;
12
- /**
13
- * Resolves session timeout with validation
14
- * Returns default if undefined or out of valid range
15
- */
16
- private static resolveSessionTimeout;
17
- /**
18
- * Resolves sampling rate with validation
19
- * Priority: API config > app config > default
20
- */
21
- private static resolveSamplingRate;
22
- /**
23
- * Resolves error sampling rate based on mode
24
- * In debug/qa modes: uses provided value or defaults to full sampling (1.0)
25
- * In production: uses provided value or defaults to 10% sampling (0.1)
26
- */
27
- private static resolveErrorSampling;
28
- /**
29
- * Resolves mode with special project ID handling
30
- * Priority: Special project ID > API mode > app mode
31
- */
32
- private static resolveMode;
33
- }
@@ -1,116 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConfigBuilder = void 0;
4
- const config_constants_1 = require("../constants/config.constants");
5
- const types_1 = require("../types");
6
- const logging_1 = require("../utils/logging");
7
- /**
8
- * Centralized configuration builder
9
- * Single source of truth for merging and building final configuration
10
- */
11
- class ConfigBuilder {
12
- /**
13
- * Builds final configuration from app config and API config
14
- * Applies clear precedence: API overrides client, with defaults as fallback
15
- */
16
- static build(appConfig, apiConfig = {}) {
17
- // Resolve mode first as it affects other settings (like errorSampling)
18
- const finalMode = this.resolveMode(appConfig, apiConfig.mode);
19
- const config = {
20
- // Core identifiers
21
- id: appConfig.id,
22
- // Session configuration
23
- sessionTimeout: this.resolveSessionTimeout(appConfig.sessionTimeout),
24
- // Mode configuration (resolved first)
25
- mode: finalMode,
26
- // Sampling configuration (depends on mode)
27
- samplingRate: this.resolveSamplingRate(apiConfig.samplingRate, appConfig.samplingRate),
28
- errorSampling: this.resolveErrorSampling(appConfig.errorSampling, finalMode),
29
- // Filtering configuration
30
- excludedUrlPaths: apiConfig.excludedUrlPaths ?? appConfig.excludedUrlPaths ?? [],
31
- tags: apiConfig.tags ?? [],
32
- ipExcluded: apiConfig.ipExcluded ?? false,
33
- // Client-only configuration
34
- globalMetadata: appConfig.globalMetadata ?? {},
35
- scrollContainerSelectors: appConfig.scrollContainerSelectors,
36
- sensitiveQueryParams: appConfig.sensitiveQueryParams ?? [],
37
- integrations: appConfig.integrations,
38
- // Security configuration
39
- allowHttp: appConfig.allowHttp ?? false,
40
- };
41
- logging_1.debugLog.debug('ConfigBuilder', 'Configuration built', {
42
- projectId: config.id,
43
- mode: config.mode,
44
- samplingRate: config.samplingRate,
45
- errorSampling: config.errorSampling,
46
- hasTags: !!config.tags?.length,
47
- hasExclusions: !!config.excludedUrlPaths?.length,
48
- });
49
- return config;
50
- }
51
- /**
52
- * Resolves session timeout with validation
53
- * Returns default if undefined or out of valid range
54
- */
55
- static resolveSessionTimeout(timeout) {
56
- if (timeout === undefined) {
57
- return config_constants_1.DEFAULT_SESSION_TIMEOUT;
58
- }
59
- if (timeout < config_constants_1.MIN_SESSION_TIMEOUT_MS || timeout > config_constants_1.MAX_SESSION_TIMEOUT_MS) {
60
- logging_1.debugLog.warn('ConfigBuilder', 'Invalid session timeout, using default', {
61
- provided: timeout,
62
- min: config_constants_1.MIN_SESSION_TIMEOUT_MS,
63
- max: config_constants_1.MAX_SESSION_TIMEOUT_MS,
64
- default: config_constants_1.DEFAULT_SESSION_TIMEOUT,
65
- });
66
- return config_constants_1.DEFAULT_SESSION_TIMEOUT;
67
- }
68
- return timeout;
69
- }
70
- /**
71
- * Resolves sampling rate with validation
72
- * Priority: API config > app config > default
73
- */
74
- static resolveSamplingRate(apiRate, appRate) {
75
- const rate = apiRate ?? appRate;
76
- if (rate === undefined) {
77
- return config_constants_1.DEFAULT_SAMPLING_RATE;
78
- }
79
- if (rate < config_constants_1.MIN_SAMPLING_RATE || rate > config_constants_1.MAX_SAMPLING_RATE) {
80
- logging_1.debugLog.warn('ConfigBuilder', 'Invalid sampling rate, using default', {
81
- provided: rate,
82
- default: config_constants_1.DEFAULT_SAMPLING_RATE,
83
- });
84
- return config_constants_1.DEFAULT_SAMPLING_RATE;
85
- }
86
- return rate;
87
- }
88
- /**
89
- * Resolves error sampling rate based on mode
90
- * In debug/qa modes: uses provided value or defaults to full sampling (1.0)
91
- * In production: uses provided value or defaults to 10% sampling (0.1)
92
- */
93
- static resolveErrorSampling(appErrorSampling, apiMode) {
94
- const isDebugMode = apiMode === types_1.Mode.DEBUG || apiMode === types_1.Mode.QA;
95
- if (isDebugMode) {
96
- // In debug mode, respect explicit value or default to full sampling
97
- return appErrorSampling ?? 1;
98
- }
99
- return appErrorSampling ?? 0.1; // Default to 10% sampling in production
100
- }
101
- /**
102
- * Resolves mode with special project ID handling
103
- * Priority: Special project ID > API mode > app mode
104
- */
105
- static resolveMode(appConfig, apiMode) {
106
- // Force DEBUG mode for special project IDs
107
- if (appConfig.id === types_1.SpecialProjectId.Skip ||
108
- appConfig.id === types_1.SpecialProjectId.Fail ||
109
- appConfig.id.toLowerCase().startsWith('skip-')) {
110
- return types_1.Mode.DEBUG;
111
- }
112
- // API mode takes precedence over app mode
113
- return apiMode ?? appConfig.mode;
114
- }
115
- }
116
- exports.ConfigBuilder = ConfigBuilder;
@@ -1,56 +0,0 @@
1
- import { AppConfig, Config } from '../types';
2
- /**
3
- * Configuration manager responsible for loading and merging application configuration.
4
- *
5
- * Handles configuration from two sources:
6
- * 1. API configuration (server-side settings)
7
- * 2. App configuration (client initialization settings)
8
- *
9
- * Uses ConfigBuilder for centralized merge logic.
10
- *
11
- * Supports special project IDs for development and testing:
12
- * - 'skip': Bypasses all network calls, uses defaults
13
- * - 'localhost:8080': Loads config from local development server
14
- */
15
- export declare class ConfigManager {
16
- private static readonly PRODUCTION_DOMAINS;
17
- /**
18
- * Gets complete configuration by loading API config and building final config.
19
- *
20
- * @param apiUrl - Base URL for the configuration API
21
- * @param appConfig - Client-side configuration from init()
22
- * @returns Promise<Config> - Merged configuration object
23
- */
24
- get(apiUrl: string, appConfig: AppConfig): Promise<Config>;
25
- /**
26
- * Loads configuration from API and returns sanitized API config.
27
- * Only returns values explicitly provided by the API.
28
- */
29
- private loadFromApi;
30
- /**
31
- * Builds the configuration URL based on project type and QA mode.
32
- */
33
- private buildConfigUrl;
34
- /**
35
- * Builds request headers based on project configuration.
36
- * Always includes X-TraceLog-Project header for consistent identification.
37
- */
38
- private buildHeaders;
39
- /**
40
- * Parses and validates JSON response from config API.
41
- */
42
- private parseJsonResponse;
43
- /**
44
- * Checks if QA mode is enabled via URL parameter.
45
- */
46
- private isQaModeEnabled;
47
- /**
48
- * Applies QA mode to API config if enabled via URL parameter.
49
- */
50
- private applyQaModeIfEnabled;
51
- /**
52
- * Creates default configuration for skip mode and fallback scenarios.
53
- * Only uses API defaults for fields not provided by the app config.
54
- */
55
- private createDefaultConfig;
56
- }
@@ -1,157 +0,0 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.ConfigManager = void 0;
4
- const constants_1 = require("../constants");
5
- const types_1 = require("../types");
6
- const utils_1 = require("../utils");
7
- const logging_1 = require("../utils/logging");
8
- const config_builder_1 = require("./config.builder");
9
- /**
10
- * Configuration manager responsible for loading and merging application configuration.
11
- *
12
- * Handles configuration from two sources:
13
- * 1. API configuration (server-side settings)
14
- * 2. App configuration (client initialization settings)
15
- *
16
- * Uses ConfigBuilder for centralized merge logic.
17
- *
18
- * Supports special project IDs for development and testing:
19
- * - 'skip': Bypasses all network calls, uses defaults
20
- * - 'localhost:8080': Loads config from local development server
21
- */
22
- class ConfigManager {
23
- /**
24
- * Gets complete configuration by loading API config and building final config.
25
- *
26
- * @param apiUrl - Base URL for the configuration API
27
- * @param appConfig - Client-side configuration from init()
28
- * @returns Promise<Config> - Merged configuration object
29
- */
30
- async get(apiUrl, appConfig) {
31
- // Handle skip mode - no network calls for config
32
- // Support 'skip' or any ID starting with 'skip-' (e.g., 'skip-1', 'skip-2')
33
- // Also handle 'fail' mode (SpecialProjectId.Fail) - skip config but fail event sends
34
- if (appConfig.id === types_1.SpecialProjectId.Skip ||
35
- appConfig.id === types_1.SpecialProjectId.Fail ||
36
- appConfig.id.toLowerCase().startsWith('skip-')) {
37
- return this.createDefaultConfig(appConfig);
38
- }
39
- const apiConfig = await this.loadFromApi(apiUrl, appConfig);
40
- // Apply QA mode from URL parameter if set
41
- const finalApiConfig = this.applyQaModeIfEnabled(apiConfig);
42
- const config = config_builder_1.ConfigBuilder.build(appConfig, finalApiConfig);
43
- logging_1.debugLog.info('ConfigManager', 'Configuration loaded', {
44
- projectId: config.id,
45
- mode: config.mode,
46
- hasTags: !!config.tags?.length,
47
- hasExclusions: !!config.excludedUrlPaths?.length,
48
- });
49
- return config;
50
- }
51
- /**
52
- * Loads configuration from API and returns sanitized API config.
53
- * Only returns values explicitly provided by the API.
54
- */
55
- async loadFromApi(apiUrl, appConfig) {
56
- try {
57
- const configUrl = this.buildConfigUrl(apiUrl, appConfig);
58
- const headers = this.buildHeaders(appConfig);
59
- const response = await (0, utils_1.fetchWithTimeout)(configUrl, {
60
- method: 'GET',
61
- headers,
62
- timeout: constants_1.REQUEST_TIMEOUT_MS,
63
- });
64
- if (!response.ok) {
65
- throw new Error(`HTTP ${response.status}: ${response.statusText}`);
66
- }
67
- const rawData = await this.parseJsonResponse(response);
68
- const apiConfig = (0, utils_1.sanitizeApiConfig)(rawData);
69
- // Only merge defaults for fields that are arrays (to ensure they're never undefined)
70
- return {
71
- ...apiConfig,
72
- excludedUrlPaths: apiConfig.excludedUrlPaths ?? constants_1.DEFAULT_API_CONFIG.excludedUrlPaths,
73
- tags: apiConfig.tags ?? constants_1.DEFAULT_API_CONFIG.tags,
74
- };
75
- }
76
- catch (error) {
77
- const errorMessage = error instanceof Error ? error.message : 'Unknown error';
78
- logging_1.debugLog.error('ConfigManager', 'Failed to load configuration', {
79
- error: errorMessage,
80
- apiUrl,
81
- projectId: appConfig.id,
82
- });
83
- throw new Error(`Configuration load failed: ${errorMessage}`);
84
- }
85
- }
86
- /**
87
- * Builds the configuration URL based on project type and QA mode.
88
- */
89
- buildConfigUrl(apiUrl, appConfig) {
90
- const isLocalhost = appConfig.id === types_1.SpecialProjectId.Localhost || appConfig.id === types_1.SpecialProjectId.Fail;
91
- if (isLocalhost) {
92
- return `http://${appConfig.id}/config`;
93
- }
94
- const baseUrl = `${apiUrl}/config`;
95
- const isQaMode = this.isQaModeEnabled();
96
- return isQaMode ? `${baseUrl}?qaMode=true` : baseUrl;
97
- }
98
- /**
99
- * Builds request headers based on project configuration.
100
- * Always includes X-TraceLog-Project header for consistent identification.
101
- */
102
- buildHeaders(appConfig) {
103
- return {
104
- 'Content-Type': 'application/json',
105
- 'X-TraceLog-Project': appConfig.id,
106
- };
107
- }
108
- /**
109
- * Parses and validates JSON response from config API.
110
- */
111
- async parseJsonResponse(response) {
112
- const contentType = response.headers.get('content-type');
113
- if (!contentType?.includes('application/json')) {
114
- throw new Error('Invalid response content-type, expected JSON');
115
- }
116
- const rawData = await response.json();
117
- if (!rawData || typeof rawData !== 'object' || Array.isArray(rawData)) {
118
- throw new Error('Invalid response format, expected object');
119
- }
120
- return rawData;
121
- }
122
- /**
123
- * Checks if QA mode is enabled via URL parameter.
124
- */
125
- isQaModeEnabled() {
126
- const params = new URLSearchParams(window.location.search);
127
- return params.get('qaMode') === 'true';
128
- }
129
- /**
130
- * Applies QA mode to API config if enabled via URL parameter.
131
- */
132
- applyQaModeIfEnabled(apiConfig) {
133
- if (this.isQaModeEnabled() && !apiConfig.mode) {
134
- logging_1.debugLog.info('ConfigManager', 'QA mode enabled via URL parameter');
135
- return { ...apiConfig, mode: types_1.Mode.QA };
136
- }
137
- return apiConfig;
138
- }
139
- /**
140
- * Creates default configuration for skip mode and fallback scenarios.
141
- * Only uses API defaults for fields not provided by the app config.
142
- */
143
- createDefaultConfig(appConfig) {
144
- // Only use DEFAULT_API_CONFIG for fields not provided in appConfig
145
- const apiConfig = {
146
- // Only use defaults if app config doesn't provide these values
147
- tags: constants_1.DEFAULT_API_CONFIG.tags,
148
- ipExcluded: constants_1.DEFAULT_API_CONFIG.ipExcluded,
149
- ...(appConfig.samplingRate === undefined && { samplingRate: constants_1.DEFAULT_API_CONFIG.samplingRate }),
150
- // Don't override excludedUrlPaths if provided by app config
151
- // ConfigBuilder will handle the fallback to [] if both are undefined
152
- };
153
- return config_builder_1.ConfigBuilder.build(appConfig, apiConfig);
154
- }
155
- }
156
- exports.ConfigManager = ConfigManager;
157
- ConfigManager.PRODUCTION_DOMAINS = [/^https:\/\/.*\.tracelog\.app$/, /^https:\/\/.*\.tracelog\.dev$/];
@@ -1,36 +0,0 @@
1
- import { DeviceType, EventData } from '../types';
2
- import { StateManager } from './state.manager';
3
- export declare class TagsManager extends StateManager {
4
- /**
5
- * Gets matching tag IDs for an event based on configured tag conditions
6
- */
7
- getEventTagsIds(event: EventData, deviceType: DeviceType): string[];
8
- /**
9
- * Evaluates all conditions for a tag using logical operators
10
- */
11
- private evaluateTagConditions;
12
- /**
13
- * Evaluates a single tag condition
14
- */
15
- private evaluateCondition;
16
- /**
17
- * Unified string matching logic for all string-based conditions
18
- */
19
- private matchStringCondition;
20
- /**
21
- * Element-specific matching logic with optimized data extraction
22
- */
23
- private matchElementCondition;
24
- /**
25
- * Exact field matching for element EQUALS operations
26
- */
27
- private matchElementFieldExact;
28
- /**
29
- * Builds searchable element data string with null safety
30
- */
31
- private buildElementDataString;
32
- /**
33
- * Safe regex testing with error handling
34
- */
35
- private testRegex;
36
- }