@tracelog/lib 0.0.8 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +58 -24
- package/dist/browser/tracelog.js +1934 -3226
- package/dist/cjs/api.d.ts +33 -19
- package/dist/cjs/api.js +111 -156
- package/dist/cjs/app.constants.d.ts +80 -1
- package/dist/cjs/app.constants.js +90 -3
- package/dist/cjs/app.d.ts +29 -44
- package/dist/cjs/app.js +114 -212
- package/dist/cjs/app.types.d.ts +2 -7
- package/dist/cjs/app.types.js +10 -21
- package/dist/cjs/constants/api.constants.js +11 -5
- package/dist/cjs/constants/config.constants.d.ts +75 -0
- package/dist/cjs/constants/config.constants.js +178 -0
- package/dist/cjs/constants/error.constants.d.ts +29 -0
- package/dist/cjs/constants/error.constants.js +50 -0
- package/dist/cjs/constants/index.d.ts +3 -6
- package/dist/cjs/constants/index.js +3 -6
- package/dist/cjs/constants/performance.constants.d.ts +28 -0
- package/dist/cjs/constants/performance.constants.js +43 -0
- package/dist/cjs/handlers/click.handler.d.ts +1 -0
- package/dist/cjs/handlers/click.handler.js +30 -49
- package/dist/cjs/handlers/error.handler.d.ts +11 -6
- package/dist/cjs/handlers/error.handler.js +91 -51
- package/dist/cjs/handlers/page-view.handler.js +38 -29
- package/dist/cjs/handlers/performance.handler.d.ts +3 -0
- package/dist/cjs/handlers/performance.handler.js +76 -37
- package/dist/cjs/handlers/scroll.handler.d.ts +15 -0
- package/dist/cjs/handlers/scroll.handler.js +105 -31
- package/dist/cjs/handlers/session.handler.d.ts +6 -20
- package/dist/cjs/handlers/session.handler.js +38 -326
- package/dist/cjs/integrations/google-analytics.integration.d.ts +0 -1
- package/dist/cjs/integrations/google-analytics.integration.js +27 -98
- package/dist/cjs/listeners/input-listener-managers.d.ts +18 -9
- package/dist/cjs/listeners/input-listener-managers.js +24 -33
- package/dist/cjs/listeners/touch-listener-manager.d.ts +1 -3
- package/dist/cjs/listeners/touch-listener-manager.js +1 -23
- package/dist/cjs/listeners/visibility-listener-manager.d.ts +1 -4
- package/dist/cjs/listeners/visibility-listener-manager.js +6 -42
- package/dist/cjs/managers/api.manager.d.ts +13 -3
- package/dist/cjs/managers/api.manager.js +35 -5
- package/dist/cjs/managers/config.manager.d.ts +53 -3
- package/dist/cjs/managers/config.manager.js +131 -62
- package/dist/cjs/managers/event.manager.d.ts +57 -36
- package/dist/cjs/managers/event.manager.js +266 -417
- package/dist/cjs/managers/sender.manager.d.ts +40 -22
- package/dist/cjs/managers/sender.manager.js +200 -198
- package/dist/cjs/managers/session.manager.d.ts +80 -66
- package/dist/cjs/managers/session.manager.js +267 -522
- package/dist/cjs/managers/state.manager.d.ts +33 -0
- package/dist/cjs/managers/state.manager.js +79 -6
- package/dist/cjs/managers/storage.manager.d.ts +26 -2
- package/dist/cjs/managers/storage.manager.js +67 -34
- package/dist/cjs/managers/tags.manager.d.ts +31 -7
- package/dist/cjs/managers/tags.manager.js +123 -241
- package/dist/cjs/managers/user.manager.d.ts +14 -5
- package/dist/cjs/managers/user.manager.js +17 -9
- package/dist/cjs/public-api.d.ts +10 -1
- package/dist/cjs/public-api.js +18 -24
- package/dist/cjs/test-bridge.d.ts +48 -0
- package/dist/cjs/test-bridge.js +110 -0
- package/dist/cjs/types/api.types.d.ts +21 -6
- package/dist/cjs/types/api.types.js +21 -6
- package/dist/cjs/types/config.types.d.ts +22 -84
- package/dist/cjs/types/emitter.types.d.ts +11 -0
- package/dist/cjs/types/emitter.types.js +8 -0
- package/dist/cjs/types/event.types.d.ts +8 -11
- package/dist/cjs/types/index.d.ts +3 -1
- package/dist/cjs/types/index.js +3 -1
- package/dist/cjs/types/queue.types.d.ts +1 -0
- package/dist/cjs/types/session.types.d.ts +0 -64
- package/dist/cjs/types/state.types.d.ts +1 -0
- package/dist/cjs/types/test-bridge.types.d.ts +38 -0
- package/dist/cjs/types/validation-error.types.d.ts +7 -0
- package/dist/cjs/types/validation-error.types.js +11 -1
- package/dist/cjs/types/window.types.d.ts +1 -8
- package/dist/cjs/utils/data/uuid.utils.d.ts +1 -1
- package/dist/cjs/utils/data/uuid.utils.js +7 -5
- package/dist/cjs/utils/emitter.utils.d.ts +8 -0
- package/dist/cjs/utils/emitter.utils.js +33 -0
- package/dist/cjs/utils/index.d.ts +1 -0
- package/dist/cjs/utils/index.js +1 -0
- package/dist/cjs/utils/logging/debug-logger.utils.d.ts +10 -51
- package/dist/cjs/utils/logging/debug-logger.utils.js +36 -127
- package/dist/cjs/utils/network/fetch-with-timeout.utils.d.ts +4 -0
- package/dist/cjs/utils/network/fetch-with-timeout.utils.js +25 -0
- package/dist/cjs/utils/network/index.d.ts +1 -0
- package/dist/cjs/utils/network/index.js +1 -0
- package/dist/cjs/utils/network/url.utils.js +2 -42
- package/dist/cjs/utils/security/sanitize.utils.d.ts +1 -8
- package/dist/cjs/utils/security/sanitize.utils.js +7 -41
- package/dist/cjs/utils/validations/config-validations.utils.d.ts +7 -0
- package/dist/cjs/utils/validations/config-validations.utils.js +77 -22
- package/dist/esm/api.d.ts +33 -19
- package/dist/esm/api.js +105 -118
- package/dist/esm/app.constants.d.ts +80 -1
- package/dist/esm/app.constants.js +89 -1
- package/dist/esm/app.d.ts +29 -44
- package/dist/esm/app.js +115 -213
- package/dist/esm/app.types.d.ts +2 -7
- package/dist/esm/app.types.js +1 -7
- package/dist/esm/constants/api.constants.js +10 -4
- package/dist/esm/constants/config.constants.d.ts +75 -0
- package/dist/esm/constants/config.constants.js +174 -0
- package/dist/esm/constants/error.constants.d.ts +29 -0
- package/dist/esm/constants/error.constants.js +47 -0
- package/dist/esm/constants/index.d.ts +3 -6
- package/dist/esm/constants/index.js +3 -6
- package/dist/esm/constants/performance.constants.d.ts +28 -0
- package/dist/esm/constants/performance.constants.js +40 -0
- package/dist/esm/handlers/click.handler.d.ts +1 -0
- package/dist/esm/handlers/click.handler.js +30 -49
- package/dist/esm/handlers/error.handler.d.ts +11 -6
- package/dist/esm/handlers/error.handler.js +91 -51
- package/dist/esm/handlers/page-view.handler.js +38 -29
- package/dist/esm/handlers/performance.handler.d.ts +3 -0
- package/dist/esm/handlers/performance.handler.js +71 -32
- package/dist/esm/handlers/scroll.handler.d.ts +15 -0
- package/dist/esm/handlers/scroll.handler.js +106 -32
- package/dist/esm/handlers/session.handler.d.ts +6 -20
- package/dist/esm/handlers/session.handler.js +38 -326
- package/dist/esm/integrations/google-analytics.integration.d.ts +0 -1
- package/dist/esm/integrations/google-analytics.integration.js +27 -98
- package/dist/esm/listeners/input-listener-managers.d.ts +18 -9
- package/dist/esm/listeners/input-listener-managers.js +23 -32
- package/dist/esm/listeners/touch-listener-manager.d.ts +1 -3
- package/dist/esm/listeners/touch-listener-manager.js +1 -23
- package/dist/esm/listeners/visibility-listener-manager.d.ts +1 -4
- package/dist/esm/listeners/visibility-listener-manager.js +6 -42
- package/dist/esm/managers/api.manager.d.ts +13 -3
- package/dist/esm/managers/api.manager.js +34 -3
- package/dist/esm/managers/config.manager.d.ts +53 -3
- package/dist/esm/managers/config.manager.js +133 -64
- package/dist/esm/managers/event.manager.d.ts +57 -36
- package/dist/esm/managers/event.manager.js +268 -419
- package/dist/esm/managers/sender.manager.d.ts +40 -22
- package/dist/esm/managers/sender.manager.js +201 -199
- package/dist/esm/managers/session.manager.d.ts +80 -66
- package/dist/esm/managers/session.manager.js +269 -524
- package/dist/esm/managers/state.manager.d.ts +33 -0
- package/dist/esm/managers/state.manager.js +78 -6
- package/dist/esm/managers/storage.manager.d.ts +26 -2
- package/dist/esm/managers/storage.manager.js +66 -33
- package/dist/esm/managers/tags.manager.d.ts +31 -7
- package/dist/esm/managers/tags.manager.js +124 -242
- package/dist/esm/managers/user.manager.d.ts +14 -5
- package/dist/esm/managers/user.manager.js +17 -9
- package/dist/esm/public-api.d.ts +10 -1
- package/dist/esm/public-api.js +14 -1
- package/dist/esm/test-bridge.d.ts +48 -0
- package/dist/esm/test-bridge.js +106 -0
- package/dist/esm/types/api.types.d.ts +21 -6
- package/dist/esm/types/api.types.js +21 -6
- package/dist/esm/types/config.types.d.ts +22 -84
- package/dist/esm/types/emitter.types.d.ts +11 -0
- package/dist/esm/types/emitter.types.js +5 -0
- package/dist/esm/types/event.types.d.ts +8 -11
- package/dist/esm/types/index.d.ts +3 -1
- package/dist/esm/types/index.js +3 -1
- package/dist/esm/types/queue.types.d.ts +1 -0
- package/dist/esm/types/session.types.d.ts +0 -64
- package/dist/esm/types/state.types.d.ts +1 -0
- package/dist/esm/types/test-bridge.types.d.ts +38 -0
- package/dist/esm/types/validation-error.types.d.ts +7 -0
- package/dist/esm/types/validation-error.types.js +9 -0
- package/dist/esm/types/window.types.d.ts +1 -8
- package/dist/esm/utils/data/uuid.utils.d.ts +1 -1
- package/dist/esm/utils/data/uuid.utils.js +7 -5
- package/dist/esm/utils/emitter.utils.d.ts +8 -0
- package/dist/esm/utils/emitter.utils.js +29 -0
- package/dist/esm/utils/index.d.ts +1 -0
- package/dist/esm/utils/index.js +1 -0
- package/dist/esm/utils/logging/debug-logger.utils.d.ts +10 -51
- package/dist/esm/utils/logging/debug-logger.utils.js +36 -127
- package/dist/esm/utils/network/fetch-with-timeout.utils.d.ts +4 -0
- package/dist/esm/utils/network/fetch-with-timeout.utils.js +22 -0
- package/dist/esm/utils/network/index.d.ts +1 -0
- package/dist/esm/utils/network/index.js +1 -0
- package/dist/esm/utils/network/url.utils.js +2 -42
- package/dist/esm/utils/security/sanitize.utils.d.ts +1 -8
- package/dist/esm/utils/security/sanitize.utils.js +6 -39
- package/dist/esm/utils/validations/config-validations.utils.d.ts +7 -0
- package/dist/esm/utils/validations/config-validations.utils.js +76 -22
- package/package.json +23 -16
- package/dist/browser/web-vitals-CCnqwnC8.mjs +0 -198
- package/dist/cjs/constants/browser.constants.d.ts +0 -3
- package/dist/cjs/constants/browser.constants.js +0 -41
- package/dist/cjs/constants/initialization.constants.d.ts +0 -40
- package/dist/cjs/constants/initialization.constants.js +0 -48
- package/dist/cjs/constants/limits.constants.d.ts +0 -25
- package/dist/cjs/constants/limits.constants.js +0 -40
- package/dist/cjs/constants/security.constants.d.ts +0 -1
- package/dist/cjs/constants/security.constants.js +0 -12
- package/dist/cjs/constants/timing.constants.d.ts +0 -22
- package/dist/cjs/constants/timing.constants.js +0 -34
- package/dist/cjs/constants/validation.constants.d.ts +0 -13
- package/dist/cjs/constants/validation.constants.js +0 -31
- package/dist/cjs/handlers/network.handler.d.ts +0 -16
- package/dist/cjs/handlers/network.handler.js +0 -136
- package/dist/cjs/managers/cross-tab-session.manager.d.ts +0 -170
- package/dist/cjs/managers/cross-tab-session.manager.js +0 -730
- package/dist/cjs/managers/sampling.manager.d.ts +0 -8
- package/dist/cjs/managers/sampling.manager.js +0 -53
- package/dist/cjs/managers/session-recovery.manager.d.ts +0 -65
- package/dist/cjs/managers/session-recovery.manager.js +0 -237
- package/dist/cjs/types/web-vitals.types.d.ts +0 -6
- package/dist/esm/constants/browser.constants.d.ts +0 -3
- package/dist/esm/constants/browser.constants.js +0 -38
- package/dist/esm/constants/initialization.constants.d.ts +0 -40
- package/dist/esm/constants/initialization.constants.js +0 -45
- package/dist/esm/constants/limits.constants.d.ts +0 -25
- package/dist/esm/constants/limits.constants.js +0 -37
- package/dist/esm/constants/security.constants.d.ts +0 -1
- package/dist/esm/constants/security.constants.js +0 -9
- package/dist/esm/constants/timing.constants.d.ts +0 -22
- package/dist/esm/constants/timing.constants.js +0 -31
- package/dist/esm/constants/validation.constants.d.ts +0 -13
- package/dist/esm/constants/validation.constants.js +0 -28
- package/dist/esm/handlers/network.handler.d.ts +0 -16
- package/dist/esm/handlers/network.handler.js +0 -132
- package/dist/esm/managers/cross-tab-session.manager.d.ts +0 -170
- package/dist/esm/managers/cross-tab-session.manager.js +0 -726
- package/dist/esm/managers/sampling.manager.d.ts +0 -8
- package/dist/esm/managers/sampling.manager.js +0 -49
- package/dist/esm/managers/session-recovery.manager.d.ts +0 -65
- package/dist/esm/managers/session-recovery.manager.js +0 -233
- package/dist/esm/types/web-vitals.types.d.ts +0 -6
- /package/dist/cjs/types/{web-vitals.types.js → test-bridge.types.js} +0 -0
- /package/dist/esm/types/{web-vitals.types.js → test-bridge.types.js} +0 -0
|
@@ -1,256 +1,116 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { TagConditionOperator, TagConditionType, TagLogicalOperator, } from '../types';
|
|
2
2
|
import { StateManager } from './state.manager';
|
|
3
3
|
export class TagsManager extends StateManager {
|
|
4
|
+
/**
|
|
5
|
+
* Gets matching tag IDs for an event based on configured tag conditions
|
|
6
|
+
*/
|
|
4
7
|
getEventTagsIds(event, deviceType) {
|
|
5
|
-
|
|
6
|
-
case EventType.PAGE_VIEW: {
|
|
7
|
-
return this.checkEventTypePageView(event, deviceType);
|
|
8
|
-
}
|
|
9
|
-
case EventType.CLICK: {
|
|
10
|
-
return this.checkEventTypeClick(event, deviceType);
|
|
11
|
-
}
|
|
12
|
-
default: {
|
|
13
|
-
return [];
|
|
14
|
-
}
|
|
15
|
-
}
|
|
16
|
-
}
|
|
17
|
-
checkEventTypePageView(event, deviceType) {
|
|
18
|
-
const tags = this.get('config')?.tags?.filter((tag) => tag.triggerType === EventType.PAGE_VIEW) ?? [];
|
|
8
|
+
const tags = this.get('config')?.tags?.filter((tag) => tag.triggerType === event.type) ?? [];
|
|
19
9
|
if (tags.length === 0) {
|
|
20
10
|
return [];
|
|
21
11
|
}
|
|
22
|
-
const
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
case TagConditionType.URL_MATCHES: {
|
|
29
|
-
results.push(this.matchUrlMatches(condition, event.page_url));
|
|
30
|
-
break;
|
|
31
|
-
}
|
|
32
|
-
case TagConditionType.DEVICE_TYPE: {
|
|
33
|
-
results.push(this.matchDeviceType(condition, deviceType));
|
|
34
|
-
break;
|
|
35
|
-
}
|
|
36
|
-
case TagConditionType.UTM_SOURCE: {
|
|
37
|
-
results.push(this.matchUtmCondition(condition, event.utm?.source));
|
|
38
|
-
break;
|
|
39
|
-
}
|
|
40
|
-
case TagConditionType.UTM_MEDIUM: {
|
|
41
|
-
results.push(this.matchUtmCondition(condition, event.utm?.medium));
|
|
42
|
-
break;
|
|
43
|
-
}
|
|
44
|
-
case TagConditionType.UTM_CAMPAIGN: {
|
|
45
|
-
results.push(this.matchUtmCondition(condition, event.utm?.campaign));
|
|
46
|
-
break;
|
|
47
|
-
}
|
|
48
|
-
}
|
|
49
|
-
}
|
|
50
|
-
let isMatch = false;
|
|
51
|
-
isMatch = logicalOperator === TagLogicalOperator.AND ? results.every(Boolean) : results.some(Boolean);
|
|
52
|
-
if (isMatch) {
|
|
53
|
-
matchedTagIds.push(id);
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
|
-
return matchedTagIds;
|
|
12
|
+
const context = {
|
|
13
|
+
event,
|
|
14
|
+
deviceType,
|
|
15
|
+
clickData: event.click_data,
|
|
16
|
+
};
|
|
17
|
+
return tags.filter((tag) => this.evaluateTagConditions(tag, context)).map((tag) => tag.id);
|
|
57
18
|
}
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
for (const tag of tags) {
|
|
65
|
-
const { id, logicalOperator, conditions } = tag;
|
|
66
|
-
const results = [];
|
|
67
|
-
for (const condition of conditions) {
|
|
68
|
-
if (!event.click_data) {
|
|
69
|
-
results.push(false);
|
|
70
|
-
continue;
|
|
71
|
-
}
|
|
72
|
-
const clickData = event.click_data;
|
|
73
|
-
switch (condition.type) {
|
|
74
|
-
case TagConditionType.ELEMENT_MATCHES: {
|
|
75
|
-
results.push(this.matchElementSelector(condition, clickData));
|
|
76
|
-
break;
|
|
77
|
-
}
|
|
78
|
-
case TagConditionType.DEVICE_TYPE: {
|
|
79
|
-
results.push(this.matchDeviceType(condition, deviceType));
|
|
80
|
-
break;
|
|
81
|
-
}
|
|
82
|
-
case TagConditionType.URL_MATCHES: {
|
|
83
|
-
results.push(this.matchUrlMatches(condition, event.page_url));
|
|
84
|
-
break;
|
|
85
|
-
}
|
|
86
|
-
case TagConditionType.UTM_SOURCE: {
|
|
87
|
-
results.push(this.matchUtmCondition(condition, event.utm?.source));
|
|
88
|
-
break;
|
|
89
|
-
}
|
|
90
|
-
case TagConditionType.UTM_MEDIUM: {
|
|
91
|
-
results.push(this.matchUtmCondition(condition, event.utm?.medium));
|
|
92
|
-
break;
|
|
93
|
-
}
|
|
94
|
-
case TagConditionType.UTM_CAMPAIGN: {
|
|
95
|
-
results.push(this.matchUtmCondition(condition, event.utm?.campaign));
|
|
96
|
-
break;
|
|
97
|
-
}
|
|
98
|
-
}
|
|
99
|
-
}
|
|
100
|
-
let isMatch = false;
|
|
101
|
-
isMatch = logicalOperator === TagLogicalOperator.AND ? results.every(Boolean) : results.some(Boolean);
|
|
102
|
-
if (isMatch) {
|
|
103
|
-
matchedTagIds.push(id);
|
|
104
|
-
}
|
|
105
|
-
}
|
|
106
|
-
return matchedTagIds;
|
|
107
|
-
}
|
|
108
|
-
matchUrlMatches(condition, url) {
|
|
109
|
-
if (condition.type !== TagConditionType.URL_MATCHES) {
|
|
19
|
+
/**
|
|
20
|
+
* Evaluates all conditions for a tag using logical operators
|
|
21
|
+
*/
|
|
22
|
+
evaluateTagConditions(tag, context) {
|
|
23
|
+
const { conditions, logicalOperator = TagLogicalOperator.OR } = tag;
|
|
24
|
+
if (!conditions || conditions.length === 0) {
|
|
110
25
|
return false;
|
|
111
26
|
}
|
|
112
|
-
const
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return
|
|
131
|
-
|
|
132
|
-
|
|
27
|
+
const results = conditions.map((condition) => this.evaluateCondition(condition, context));
|
|
28
|
+
return logicalOperator === TagLogicalOperator.AND ? results.every(Boolean) : results.some(Boolean);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Evaluates a single tag condition
|
|
32
|
+
*/
|
|
33
|
+
evaluateCondition(condition, context) {
|
|
34
|
+
try {
|
|
35
|
+
switch (condition.type) {
|
|
36
|
+
case TagConditionType.URL_MATCHES:
|
|
37
|
+
return this.matchStringCondition(condition, context.event.page_url);
|
|
38
|
+
case TagConditionType.DEVICE_TYPE:
|
|
39
|
+
return this.matchStringCondition(condition, context.deviceType);
|
|
40
|
+
case TagConditionType.UTM_SOURCE:
|
|
41
|
+
return this.matchStringCondition(condition, context.event.utm?.source ?? '');
|
|
42
|
+
case TagConditionType.UTM_MEDIUM:
|
|
43
|
+
return this.matchStringCondition(condition, context.event.utm?.medium ?? '');
|
|
44
|
+
case TagConditionType.UTM_CAMPAIGN:
|
|
45
|
+
return this.matchStringCondition(condition, context.event.utm?.campaign ?? '');
|
|
46
|
+
case TagConditionType.ELEMENT_MATCHES:
|
|
47
|
+
return context.clickData ? this.matchElementCondition(condition, context.clickData) : false;
|
|
48
|
+
default:
|
|
133
49
|
return false;
|
|
134
|
-
}
|
|
135
|
-
}
|
|
136
|
-
default: {
|
|
137
|
-
return false;
|
|
138
50
|
}
|
|
139
51
|
}
|
|
140
|
-
|
|
141
|
-
matchDeviceType(condition, deviceType) {
|
|
142
|
-
if (condition.type !== TagConditionType.DEVICE_TYPE) {
|
|
52
|
+
catch {
|
|
143
53
|
return false;
|
|
144
54
|
}
|
|
145
|
-
const targetValue = condition.value.toLowerCase();
|
|
146
|
-
const targetDevice = deviceType.toLowerCase();
|
|
147
|
-
switch (condition.operator) {
|
|
148
|
-
case TagConditionOperator.EQUALS: {
|
|
149
|
-
return targetDevice === targetValue;
|
|
150
|
-
}
|
|
151
|
-
case TagConditionOperator.CONTAINS: {
|
|
152
|
-
return targetDevice.includes(targetValue);
|
|
153
|
-
}
|
|
154
|
-
case TagConditionOperator.STARTS_WITH: {
|
|
155
|
-
return targetDevice.startsWith(targetValue);
|
|
156
|
-
}
|
|
157
|
-
case TagConditionOperator.ENDS_WITH: {
|
|
158
|
-
return targetDevice.endsWith(targetValue);
|
|
159
|
-
}
|
|
160
|
-
case TagConditionOperator.REGEX: {
|
|
161
|
-
try {
|
|
162
|
-
const regex = new RegExp(targetValue, 'gi');
|
|
163
|
-
return regex.test(targetDevice);
|
|
164
|
-
}
|
|
165
|
-
catch {
|
|
166
|
-
return false;
|
|
167
|
-
}
|
|
168
|
-
}
|
|
169
|
-
default: {
|
|
170
|
-
return false;
|
|
171
|
-
}
|
|
172
|
-
}
|
|
173
55
|
}
|
|
174
|
-
|
|
175
|
-
|
|
56
|
+
/**
|
|
57
|
+
* Unified string matching logic for all string-based conditions
|
|
58
|
+
*/
|
|
59
|
+
matchStringCondition(condition, value) {
|
|
60
|
+
if (!value &&
|
|
61
|
+
condition.operator !== TagConditionOperator.EXISTS &&
|
|
62
|
+
condition.operator !== TagConditionOperator.NOT_EXISTS) {
|
|
176
63
|
return false;
|
|
177
64
|
}
|
|
178
|
-
const
|
|
179
|
-
|
|
180
|
-
clickData.class ?? '',
|
|
181
|
-
clickData.tag ?? '',
|
|
182
|
-
clickData.text ?? '',
|
|
183
|
-
clickData.href ?? '',
|
|
184
|
-
clickData.title ?? '',
|
|
185
|
-
clickData.alt ?? '',
|
|
186
|
-
clickData.role ?? '',
|
|
187
|
-
clickData.ariaLabel ?? '',
|
|
188
|
-
...Object.values(clickData.dataAttributes ?? {}),
|
|
189
|
-
].join(' ');
|
|
190
|
-
const targetValue = condition.value.toLowerCase();
|
|
191
|
-
const targetElementData = elementData.toLowerCase();
|
|
65
|
+
const conditionValue = condition.value.toLowerCase();
|
|
66
|
+
const targetValue = value.toLowerCase();
|
|
192
67
|
switch (condition.operator) {
|
|
193
|
-
case TagConditionOperator.EQUALS:
|
|
194
|
-
return
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
case TagConditionOperator.
|
|
200
|
-
return
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
case TagConditionOperator.
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
return regex.test(targetElementData);
|
|
209
|
-
}
|
|
210
|
-
catch {
|
|
211
|
-
return false;
|
|
212
|
-
}
|
|
213
|
-
}
|
|
214
|
-
default: {
|
|
68
|
+
case TagConditionOperator.EQUALS:
|
|
69
|
+
return targetValue === conditionValue;
|
|
70
|
+
case TagConditionOperator.CONTAINS:
|
|
71
|
+
return targetValue.includes(conditionValue);
|
|
72
|
+
case TagConditionOperator.STARTS_WITH:
|
|
73
|
+
return targetValue.startsWith(conditionValue);
|
|
74
|
+
case TagConditionOperator.ENDS_WITH:
|
|
75
|
+
return targetValue.endsWith(conditionValue);
|
|
76
|
+
case TagConditionOperator.REGEX:
|
|
77
|
+
return this.testRegex(conditionValue, targetValue);
|
|
78
|
+
case TagConditionOperator.EXISTS:
|
|
79
|
+
return !!value;
|
|
80
|
+
case TagConditionOperator.NOT_EXISTS:
|
|
81
|
+
return !value;
|
|
82
|
+
default:
|
|
215
83
|
return false;
|
|
216
|
-
}
|
|
217
84
|
}
|
|
218
85
|
}
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
86
|
+
/**
|
|
87
|
+
* Element-specific matching logic with optimized data extraction
|
|
88
|
+
*/
|
|
89
|
+
matchElementCondition(condition, clickData) {
|
|
90
|
+
if (condition.operator === TagConditionOperator.EQUALS) {
|
|
91
|
+
return this.matchElementFieldExact(condition, clickData);
|
|
222
92
|
}
|
|
223
|
-
|
|
224
|
-
const
|
|
225
|
-
const
|
|
93
|
+
// Build searchable element data string once
|
|
94
|
+
const elementData = this.buildElementDataString(clickData).toLowerCase();
|
|
95
|
+
const conditionValue = condition.value.toLowerCase();
|
|
226
96
|
switch (condition.operator) {
|
|
227
|
-
case TagConditionOperator.
|
|
228
|
-
return
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
case TagConditionOperator.
|
|
234
|
-
return
|
|
235
|
-
|
|
236
|
-
case TagConditionOperator.ENDS_WITH: {
|
|
237
|
-
return targetUtmValue.endsWith(targetValue);
|
|
238
|
-
}
|
|
239
|
-
case TagConditionOperator.REGEX: {
|
|
240
|
-
try {
|
|
241
|
-
const regex = new RegExp(targetValue, 'gi');
|
|
242
|
-
return regex.test(targetUtmValue);
|
|
243
|
-
}
|
|
244
|
-
catch {
|
|
245
|
-
return false;
|
|
246
|
-
}
|
|
247
|
-
}
|
|
248
|
-
default: {
|
|
97
|
+
case TagConditionOperator.CONTAINS:
|
|
98
|
+
return elementData.includes(conditionValue);
|
|
99
|
+
case TagConditionOperator.STARTS_WITH:
|
|
100
|
+
return elementData.startsWith(conditionValue);
|
|
101
|
+
case TagConditionOperator.ENDS_WITH:
|
|
102
|
+
return elementData.endsWith(conditionValue);
|
|
103
|
+
case TagConditionOperator.REGEX:
|
|
104
|
+
return this.testRegex(conditionValue, elementData);
|
|
105
|
+
default:
|
|
249
106
|
return false;
|
|
250
|
-
}
|
|
251
107
|
}
|
|
252
108
|
}
|
|
253
|
-
|
|
109
|
+
/**
|
|
110
|
+
* Exact field matching for element EQUALS operations
|
|
111
|
+
*/
|
|
112
|
+
matchElementFieldExact(condition, clickData) {
|
|
113
|
+
const conditionValue = condition.value.toLowerCase();
|
|
254
114
|
const fields = [
|
|
255
115
|
clickData.id,
|
|
256
116
|
clickData.class,
|
|
@@ -262,24 +122,46 @@ export class TagsManager extends StateManager {
|
|
|
262
122
|
clickData.role,
|
|
263
123
|
clickData.ariaLabel,
|
|
264
124
|
];
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
const target = targetValue.toLowerCase();
|
|
269
|
-
if (fieldValue === target) {
|
|
270
|
-
return true;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
125
|
+
// Check standard fields
|
|
126
|
+
if (fields.some((field) => field && field.toLowerCase() === conditionValue)) {
|
|
127
|
+
return true;
|
|
273
128
|
}
|
|
129
|
+
// Check data attributes
|
|
274
130
|
if (clickData.dataAttributes) {
|
|
275
|
-
|
|
276
|
-
const fieldValue = dataValue.toLowerCase();
|
|
277
|
-
const target = targetValue.toLowerCase();
|
|
278
|
-
if (fieldValue === target) {
|
|
279
|
-
return true;
|
|
280
|
-
}
|
|
281
|
-
}
|
|
131
|
+
return Object.values(clickData.dataAttributes).some((value) => value.toLowerCase() === conditionValue);
|
|
282
132
|
}
|
|
283
133
|
return false;
|
|
284
134
|
}
|
|
135
|
+
/**
|
|
136
|
+
* Builds searchable element data string with null safety
|
|
137
|
+
*/
|
|
138
|
+
buildElementDataString(clickData) {
|
|
139
|
+
const parts = [
|
|
140
|
+
clickData.id,
|
|
141
|
+
clickData.class,
|
|
142
|
+
clickData.tag,
|
|
143
|
+
clickData.text,
|
|
144
|
+
clickData.href,
|
|
145
|
+
clickData.title,
|
|
146
|
+
clickData.alt,
|
|
147
|
+
clickData.role,
|
|
148
|
+
clickData.ariaLabel,
|
|
149
|
+
].filter(Boolean);
|
|
150
|
+
if (clickData.dataAttributes) {
|
|
151
|
+
parts.push(...Object.values(clickData.dataAttributes));
|
|
152
|
+
}
|
|
153
|
+
return parts.join(' ');
|
|
154
|
+
}
|
|
155
|
+
/**
|
|
156
|
+
* Safe regex testing with error handling
|
|
157
|
+
*/
|
|
158
|
+
testRegex(pattern, text) {
|
|
159
|
+
try {
|
|
160
|
+
const regex = new RegExp(pattern, 'gi');
|
|
161
|
+
return regex.test(text);
|
|
162
|
+
}
|
|
163
|
+
catch {
|
|
164
|
+
return false;
|
|
165
|
+
}
|
|
166
|
+
}
|
|
285
167
|
}
|
|
@@ -1,7 +1,16 @@
|
|
|
1
|
-
import { StateManager } from './state.manager';
|
|
2
1
|
import { StorageManager } from './storage.manager';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
2
|
+
/**
|
|
3
|
+
* Simple utility for managing user identification.
|
|
4
|
+
* Generates and persists unique user IDs per project.
|
|
5
|
+
*/
|
|
6
|
+
export declare class UserManager {
|
|
7
|
+
/**
|
|
8
|
+
* Gets or creates a unique user ID for the given project.
|
|
9
|
+
* The user ID is persisted in localStorage and reused across sessions.
|
|
10
|
+
*
|
|
11
|
+
* @param storageManager - Storage manager instance
|
|
12
|
+
* @param projectId - Project identifier for namespacing
|
|
13
|
+
* @returns Persistent unique user ID
|
|
14
|
+
*/
|
|
15
|
+
static getId(storageManager: StorageManager, projectId?: string): string;
|
|
7
16
|
}
|
|
@@ -1,18 +1,26 @@
|
|
|
1
1
|
import { USER_ID_KEY } from '../constants';
|
|
2
2
|
import { generateUUID } from '../utils';
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
3
|
+
/**
|
|
4
|
+
* Simple utility for managing user identification.
|
|
5
|
+
* Generates and persists unique user IDs per project.
|
|
6
|
+
*/
|
|
7
|
+
export class UserManager {
|
|
8
|
+
/**
|
|
9
|
+
* Gets or creates a unique user ID for the given project.
|
|
10
|
+
* The user ID is persisted in localStorage and reused across sessions.
|
|
11
|
+
*
|
|
12
|
+
* @param storageManager - Storage manager instance
|
|
13
|
+
* @param projectId - Project identifier for namespacing
|
|
14
|
+
* @returns Persistent unique user ID
|
|
15
|
+
*/
|
|
16
|
+
static getId(storageManager, projectId) {
|
|
17
|
+
const storageKey = USER_ID_KEY(projectId ?? '');
|
|
18
|
+
const storedUserId = storageManager.getItem(storageKey);
|
|
11
19
|
if (storedUserId) {
|
|
12
20
|
return storedUserId;
|
|
13
21
|
}
|
|
14
22
|
const newUserId = generateUUID();
|
|
15
|
-
|
|
23
|
+
storageManager.setItem(storageKey, newUserId);
|
|
16
24
|
return newUserId;
|
|
17
25
|
}
|
|
18
26
|
}
|
package/dist/esm/public-api.d.ts
CHANGED
|
@@ -1 +1,10 @@
|
|
|
1
|
-
export *
|
|
1
|
+
export * from './app.constants';
|
|
2
|
+
export * from './app.types';
|
|
3
|
+
export declare const tracelog: {
|
|
4
|
+
init: (appConfig: import("./app.types").AppConfig) => Promise<void>;
|
|
5
|
+
event: (name: string, metadata?: Record<string, import("./app.types").MetadataType>) => void;
|
|
6
|
+
on: <K extends keyof import("./types").EmitterMap>(event: K, callback: import("./types").EmitterCallback<import("./types").EmitterMap[K]>) => void;
|
|
7
|
+
off: <K extends keyof import("./types").EmitterMap>(event: K, callback: import("./types").EmitterCallback<import("./types").EmitterMap[K]>) => void;
|
|
8
|
+
isInitialized: () => boolean;
|
|
9
|
+
destroy: () => Promise<void>;
|
|
10
|
+
};
|
package/dist/esm/public-api.js
CHANGED
|
@@ -1 +1,14 @@
|
|
|
1
|
-
|
|
1
|
+
import { init, event, on, off, isInitialized, destroy } from './api';
|
|
2
|
+
// Constants
|
|
3
|
+
export * from './app.constants';
|
|
4
|
+
// Types
|
|
5
|
+
export * from './app.types';
|
|
6
|
+
// TraceLog namespace containing all API methods
|
|
7
|
+
export const tracelog = {
|
|
8
|
+
init,
|
|
9
|
+
event,
|
|
10
|
+
on,
|
|
11
|
+
off,
|
|
12
|
+
isInitialized,
|
|
13
|
+
destroy,
|
|
14
|
+
};
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
import { App } from './app';
|
|
2
|
+
import { ClickHandler } from './handlers/click.handler';
|
|
3
|
+
import { ErrorHandler } from './handlers/error.handler';
|
|
4
|
+
import { PageViewHandler } from './handlers/page-view.handler';
|
|
5
|
+
import { PerformanceHandler } from './handlers/performance.handler';
|
|
6
|
+
import { ScrollHandler } from './handlers/scroll.handler';
|
|
7
|
+
import { SessionHandler } from './handlers/session.handler';
|
|
8
|
+
import { GoogleAnalyticsIntegration } from './integrations/google-analytics.integration';
|
|
9
|
+
import { EventManager } from './managers/event.manager';
|
|
10
|
+
import { StorageManager } from './managers/storage.manager';
|
|
11
|
+
import { State, TraceLogTestBridge } from './types';
|
|
12
|
+
/**
|
|
13
|
+
* Test bridge for E2E testing
|
|
14
|
+
*/
|
|
15
|
+
export declare class TestBridge extends App implements TraceLogTestBridge {
|
|
16
|
+
private _isInitializing;
|
|
17
|
+
private _isDestroying;
|
|
18
|
+
constructor(isInitializing: boolean, isDestroying: boolean);
|
|
19
|
+
isInitializing(): boolean;
|
|
20
|
+
sendCustomEvent(name: string, data?: Record<string, unknown>): void;
|
|
21
|
+
getSessionData(): Record<string, unknown> | null;
|
|
22
|
+
setSessionTimeout(timeout: number): void;
|
|
23
|
+
getQueueLength(): number;
|
|
24
|
+
forceInitLock(enabled?: boolean): void;
|
|
25
|
+
get<T extends keyof State>(key: T): State[T];
|
|
26
|
+
getStorageManager(): StorageManager | null;
|
|
27
|
+
getEventManager(): EventManager | null;
|
|
28
|
+
getSessionHandler(): SessionHandler | null;
|
|
29
|
+
getPageViewHandler(): PageViewHandler | null;
|
|
30
|
+
getClickHandler(): ClickHandler | null;
|
|
31
|
+
getScrollHandler(): ScrollHandler | null;
|
|
32
|
+
getPerformanceHandler(): PerformanceHandler | null;
|
|
33
|
+
getErrorHandler(): ErrorHandler | null;
|
|
34
|
+
getGoogleAnalytics(): GoogleAnalyticsIntegration | null;
|
|
35
|
+
destroy(): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* Helper to safely access managers/handlers and convert undefined to null
|
|
38
|
+
*/
|
|
39
|
+
private safeAccess;
|
|
40
|
+
/**
|
|
41
|
+
* Ensures the app is initialized, throws if not
|
|
42
|
+
*/
|
|
43
|
+
private ensureInitialized;
|
|
44
|
+
/**
|
|
45
|
+
* Ensures destroy operation is not in progress, throws if it is
|
|
46
|
+
*/
|
|
47
|
+
private ensureNotDestroying;
|
|
48
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import { App } from './app';
|
|
2
|
+
import { normalizeConfig } from './utils';
|
|
3
|
+
/**
|
|
4
|
+
* Test bridge for E2E testing
|
|
5
|
+
*/
|
|
6
|
+
export class TestBridge extends App {
|
|
7
|
+
constructor(isInitializing, isDestroying) {
|
|
8
|
+
super();
|
|
9
|
+
this._isDestroying = false;
|
|
10
|
+
this._isInitializing = isInitializing;
|
|
11
|
+
this._isDestroying = isDestroying;
|
|
12
|
+
}
|
|
13
|
+
isInitializing() {
|
|
14
|
+
return this._isInitializing;
|
|
15
|
+
}
|
|
16
|
+
sendCustomEvent(name, data) {
|
|
17
|
+
this.ensureInitialized();
|
|
18
|
+
super.sendCustomEvent(name, data);
|
|
19
|
+
}
|
|
20
|
+
getSessionData() {
|
|
21
|
+
return {
|
|
22
|
+
id: this.get('sessionId'),
|
|
23
|
+
isActive: !!this.get('sessionId'),
|
|
24
|
+
timeout: this.get('config')?.sessionTimeout ?? 15 * 60 * 1000,
|
|
25
|
+
};
|
|
26
|
+
}
|
|
27
|
+
setSessionTimeout(timeout) {
|
|
28
|
+
const config = this.get('config');
|
|
29
|
+
if (config) {
|
|
30
|
+
const { config: normalizedConfig } = normalizeConfig({ ...config, sessionTimeout: timeout });
|
|
31
|
+
this.set('config', normalizedConfig);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
getQueueLength() {
|
|
35
|
+
return this.managers.event?.getQueueLength() ?? 0;
|
|
36
|
+
}
|
|
37
|
+
forceInitLock(enabled = true) {
|
|
38
|
+
this._isInitializing = enabled;
|
|
39
|
+
}
|
|
40
|
+
get(key) {
|
|
41
|
+
return super.get(key);
|
|
42
|
+
}
|
|
43
|
+
// Manager accessors
|
|
44
|
+
getStorageManager() {
|
|
45
|
+
return this.safeAccess(this.managers?.storage);
|
|
46
|
+
}
|
|
47
|
+
getEventManager() {
|
|
48
|
+
return this.safeAccess(this.managers?.event);
|
|
49
|
+
}
|
|
50
|
+
// Handler accessors
|
|
51
|
+
getSessionHandler() {
|
|
52
|
+
return this.safeAccess(this.handlers?.session);
|
|
53
|
+
}
|
|
54
|
+
getPageViewHandler() {
|
|
55
|
+
return this.safeAccess(this.handlers?.pageView);
|
|
56
|
+
}
|
|
57
|
+
getClickHandler() {
|
|
58
|
+
return this.safeAccess(this.handlers?.click);
|
|
59
|
+
}
|
|
60
|
+
getScrollHandler() {
|
|
61
|
+
return this.safeAccess(this.handlers?.scroll);
|
|
62
|
+
}
|
|
63
|
+
getPerformanceHandler() {
|
|
64
|
+
return this.safeAccess(this.handlers?.performance);
|
|
65
|
+
}
|
|
66
|
+
getErrorHandler() {
|
|
67
|
+
return this.safeAccess(this.handlers?.error);
|
|
68
|
+
}
|
|
69
|
+
// Integration accessors
|
|
70
|
+
getGoogleAnalytics() {
|
|
71
|
+
return this.safeAccess(this.integrations?.googleAnalytics);
|
|
72
|
+
}
|
|
73
|
+
async destroy() {
|
|
74
|
+
this.ensureInitialized();
|
|
75
|
+
this.ensureNotDestroying();
|
|
76
|
+
this._isDestroying = true;
|
|
77
|
+
try {
|
|
78
|
+
await super.destroy();
|
|
79
|
+
}
|
|
80
|
+
finally {
|
|
81
|
+
this._isDestroying = false;
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Helper to safely access managers/handlers and convert undefined to null
|
|
86
|
+
*/
|
|
87
|
+
safeAccess(value) {
|
|
88
|
+
return value ?? null;
|
|
89
|
+
}
|
|
90
|
+
/**
|
|
91
|
+
* Ensures the app is initialized, throws if not
|
|
92
|
+
*/
|
|
93
|
+
ensureInitialized() {
|
|
94
|
+
if (!this.initialized) {
|
|
95
|
+
throw new Error('App not initialized');
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Ensures destroy operation is not in progress, throws if it is
|
|
100
|
+
*/
|
|
101
|
+
ensureNotDestroying() {
|
|
102
|
+
if (this._isDestroying) {
|
|
103
|
+
throw new Error('Destroy operation already in progress');
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
}
|