clarity-js 0.8.41 → 0.8.42
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 +26 -26
- package/build/clarity.extended.js +1 -1
- package/build/clarity.insight.js +1 -1
- package/build/clarity.js +6027 -6027
- package/build/clarity.min.js +1 -1
- package/build/clarity.module.js +6027 -6027
- package/build/clarity.performance.js +1 -1
- package/package.json +70 -70
- package/rollup.config.ts +161 -161
- package/src/clarity.ts +65 -65
- package/src/core/api.ts +8 -8
- package/src/core/config.ts +29 -29
- package/src/core/copy.ts +3 -3
- package/src/core/event.ts +53 -53
- package/src/core/hash.ts +19 -19
- package/src/core/history.ts +71 -71
- package/src/core/index.ts +81 -81
- package/src/core/measure.ts +19 -19
- package/src/core/report.ts +28 -28
- package/src/core/scrub.ts +202 -202
- package/src/core/task.ts +181 -181
- package/src/core/throttle.ts +46 -46
- package/src/core/time.ts +26 -26
- package/src/core/timeout.ts +10 -10
- package/src/core/version.ts +2 -2
- package/src/data/baseline.ts +162 -162
- package/src/data/compress.ts +31 -31
- package/src/data/consent.ts +77 -77
- package/src/data/custom.ts +23 -23
- package/src/data/dimension.ts +53 -53
- package/src/data/encode.ts +155 -155
- package/src/data/envelope.ts +53 -53
- package/src/data/extract.ts +211 -211
- package/src/data/index.ts +50 -50
- package/src/data/limit.ts +44 -44
- package/src/data/metadata.ts +408 -408
- package/src/data/metric.ts +51 -51
- package/src/data/ping.ts +36 -36
- package/src/data/signal.ts +30 -30
- package/src/data/summary.ts +34 -34
- package/src/data/token.ts +39 -39
- package/src/data/upgrade.ts +44 -44
- package/src/data/upload.ts +333 -333
- package/src/data/variable.ts +83 -83
- package/src/diagnostic/encode.ts +40 -40
- package/src/diagnostic/fraud.ts +36 -36
- package/src/diagnostic/index.ts +13 -13
- package/src/diagnostic/internal.ts +28 -28
- package/src/diagnostic/script.ts +35 -35
- package/src/dynamic/agent/blank.ts +2 -2
- package/src/dynamic/agent/crisp.ts +40 -40
- package/src/dynamic/agent/encode.ts +25 -25
- package/src/dynamic/agent/index.ts +8 -8
- package/src/dynamic/agent/livechat.ts +58 -58
- package/src/dynamic/agent/tidio.ts +44 -44
- package/src/global.ts +6 -6
- package/src/index.ts +9 -9
- package/src/insight/blank.ts +14 -14
- package/src/insight/encode.ts +60 -60
- package/src/insight/snapshot.ts +114 -114
- package/src/interaction/change.ts +38 -38
- package/src/interaction/click.ts +173 -173
- package/src/interaction/clipboard.ts +32 -32
- package/src/interaction/encode.ts +210 -210
- package/src/interaction/index.ts +60 -60
- package/src/interaction/input.ts +57 -57
- package/src/interaction/pointer.ts +137 -137
- package/src/interaction/resize.ts +50 -50
- package/src/interaction/scroll.ts +129 -129
- package/src/interaction/selection.ts +66 -66
- package/src/interaction/submit.ts +30 -30
- package/src/interaction/timeline.ts +69 -69
- package/src/interaction/unload.ts +26 -26
- package/src/interaction/visibility.ts +27 -27
- package/src/layout/animation.ts +133 -133
- package/src/layout/custom.ts +42 -42
- package/src/layout/discover.ts +31 -31
- package/src/layout/document.ts +46 -46
- package/src/layout/dom.ts +439 -439
- package/src/layout/encode.ts +154 -154
- package/src/layout/index.ts +42 -42
- package/src/layout/mutation.ts +411 -411
- package/src/layout/node.ts +294 -294
- package/src/layout/offset.ts +19 -19
- package/src/layout/region.ts +151 -151
- package/src/layout/schema.ts +63 -63
- package/src/layout/selector.ts +82 -82
- package/src/layout/style.ts +159 -159
- package/src/layout/target.ts +32 -32
- package/src/layout/traverse.ts +27 -27
- package/src/performance/blank.ts +9 -9
- package/src/performance/encode.ts +31 -31
- package/src/performance/index.ts +12 -12
- package/src/performance/interaction.ts +125 -125
- package/src/performance/navigation.ts +31 -31
- package/src/performance/observer.ts +112 -112
- package/src/queue.ts +33 -33
- package/test/core.test.ts +139 -139
- package/test/helper.ts +162 -162
- package/test/html/core.html +27 -27
- package/test/stub.test.ts +7 -7
- package/test/tsconfig.test.json +5 -5
- package/tsconfig.json +21 -21
- package/tslint.json +32 -32
- package/types/agent.d.ts +39 -39
- package/types/core.d.ts +150 -150
- package/types/data.d.ts +571 -571
- package/types/diagnostic.d.ts +24 -24
- package/types/global.d.ts +30 -30
- package/types/index.d.ts +40 -40
- package/types/interaction.d.ts +177 -177
- package/types/layout.d.ts +276 -276
- package/types/performance.d.ts +31 -31
package/src/data/extract.ts
CHANGED
|
@@ -1,211 +1,211 @@
|
|
|
1
|
-
import { ExtractSource, Syntax, Type } from "@clarity-types/core";
|
|
2
|
-
import { Event, Setting, ExtractData } from "@clarity-types/data";
|
|
3
|
-
import encode from "./encode";
|
|
4
|
-
import * as internal from "@src/diagnostic/internal";
|
|
5
|
-
import { Code, Constant, Severity } from "@clarity-types/data";
|
|
6
|
-
import { hashText } from "@src/clarity";
|
|
7
|
-
import hash from "@src/core/hash";
|
|
8
|
-
|
|
9
|
-
export let data: ExtractData = {};
|
|
10
|
-
export let keys: Set<number> = new Set();
|
|
11
|
-
|
|
12
|
-
let variables : { [key: number]: { [key: number]: Syntax[] }} = {};
|
|
13
|
-
let selectors : { [key: number]: { [key: number]: string }} = {};
|
|
14
|
-
let hashes : { [key: number]: { [key: number]: string }} = {};
|
|
15
|
-
let validation : { [key: number]: string } = {};
|
|
16
|
-
|
|
17
|
-
export function start(): void {
|
|
18
|
-
reset();
|
|
19
|
-
}
|
|
20
|
-
|
|
21
|
-
// Input string is of the following form:
|
|
22
|
-
// EXTRACT 101|element { "1": ".class1", "2": "~window.a.b", "3": "!abc"}
|
|
23
|
-
// if element is present on the page it will set up event 101 to grab the contents of the class1 selector into component 1,
|
|
24
|
-
// the javascript evaluated contents of window.a.b into component 2,
|
|
25
|
-
// and the contents of Clarity's hash abc into component 3
|
|
26
|
-
export function trigger(input: string): void {
|
|
27
|
-
try {
|
|
28
|
-
var parts = input && input.length > 0 ? input.split(/ (.*)/) : [Constant.Empty];
|
|
29
|
-
var keyparts = parts[0].split(/\|(.*)/);
|
|
30
|
-
var key = parseInt(keyparts[0]);
|
|
31
|
-
var element = keyparts.length > 1 ? keyparts[1] : Constant.Empty;
|
|
32
|
-
var values = parts.length > 1 ? JSON.parse(parts[1]) : {};
|
|
33
|
-
variables[key] = {};
|
|
34
|
-
selectors[key] = {};
|
|
35
|
-
hashes[key] = {};
|
|
36
|
-
validation[key] = element;
|
|
37
|
-
for (var v in values) {
|
|
38
|
-
// values is a set of strings for proper JSON parsing, but it's more efficient
|
|
39
|
-
// to interact with them as numbers
|
|
40
|
-
let id = parseInt(v);
|
|
41
|
-
let value = values[v] as string;
|
|
42
|
-
let source = ExtractSource.Text;
|
|
43
|
-
if (value.startsWith(Constant.Tilde)) {
|
|
44
|
-
source = ExtractSource.Javascript
|
|
45
|
-
} else if (value.startsWith(Constant.Bang)) {
|
|
46
|
-
source = ExtractSource.Hash
|
|
47
|
-
}
|
|
48
|
-
switch (source) {
|
|
49
|
-
case ExtractSource.Javascript:
|
|
50
|
-
let variable = value.slice(1);
|
|
51
|
-
variables[key][id] = parse(variable);
|
|
52
|
-
break;
|
|
53
|
-
case ExtractSource.Text:
|
|
54
|
-
selectors[key][id] = value;
|
|
55
|
-
break;
|
|
56
|
-
case ExtractSource.Hash:
|
|
57
|
-
let hash = value.slice(1);
|
|
58
|
-
hashes[key][id] = hash;
|
|
59
|
-
break;
|
|
60
|
-
}
|
|
61
|
-
}
|
|
62
|
-
}
|
|
63
|
-
catch(e) {
|
|
64
|
-
internal.log(Code.Config, Severity.Warning, e ? e.name : null);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
export function clone(v: Syntax[]): Syntax[] {
|
|
69
|
-
return JSON.parse(JSON.stringify(v));
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export function compute(): void {
|
|
73
|
-
try {
|
|
74
|
-
for (let v in variables) {
|
|
75
|
-
let key = parseInt(v);
|
|
76
|
-
if (validation[key] == Constant.Empty || document.querySelector(validation[key]))
|
|
77
|
-
{
|
|
78
|
-
let variableData = variables[key];
|
|
79
|
-
for (let v in variableData) {
|
|
80
|
-
let variableKey = parseInt(v);
|
|
81
|
-
let value = str(evaluate(clone(variableData[variableKey])));
|
|
82
|
-
if (value) {
|
|
83
|
-
update(key, variableKey, value);
|
|
84
|
-
}
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
let selectorData = selectors[key];
|
|
88
|
-
for (let s in selectorData) {
|
|
89
|
-
let shouldMask = false;
|
|
90
|
-
let selectorKey = parseInt(s);
|
|
91
|
-
let selector = selectorData[selectorKey];
|
|
92
|
-
if (selector.startsWith(Constant.At)){
|
|
93
|
-
shouldMask = true;
|
|
94
|
-
selector = selector.slice(1);
|
|
95
|
-
}
|
|
96
|
-
let nodes = document.querySelectorAll(selector) as NodeListOf<HTMLElement>;
|
|
97
|
-
if (nodes) {
|
|
98
|
-
let text = Array.from(nodes).map(e => e.textContent).join(Constant.Seperator);
|
|
99
|
-
update(key, selectorKey, (shouldMask ? hash(text).trim() : text).slice(0, Setting.ExtractLimit));
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
let hashData = hashes[key];
|
|
104
|
-
for (let h in hashData) {
|
|
105
|
-
let hashKey = parseInt(h);
|
|
106
|
-
let content = hashText(hashData[hashKey]).trim().slice(0, Setting.ExtractLimit);
|
|
107
|
-
update(key, hashKey, content);
|
|
108
|
-
}
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
if (keys.size > 0) {
|
|
113
|
-
encode(Event.Extract);
|
|
114
|
-
}
|
|
115
|
-
}
|
|
116
|
-
catch (e) { internal.log(Code.Selector, Severity.Warning, e ? e.name : null); }
|
|
117
|
-
}
|
|
118
|
-
|
|
119
|
-
export function reset(): void {
|
|
120
|
-
keys.clear();
|
|
121
|
-
}
|
|
122
|
-
|
|
123
|
-
export function update(key: number, subkey: number, value: string): void {
|
|
124
|
-
var update = false;
|
|
125
|
-
if (!(key in data)) {
|
|
126
|
-
data[key] = {};
|
|
127
|
-
update = true;
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
if (!isEmpty(hashes[key])
|
|
131
|
-
&& (!(subkey in data[key]) || data[key][subkey] != value))
|
|
132
|
-
{
|
|
133
|
-
update = true;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
data[key][subkey] = value;
|
|
137
|
-
if (update) {
|
|
138
|
-
keys.add(key);
|
|
139
|
-
}
|
|
140
|
-
|
|
141
|
-
return;
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
export function stop(): void {
|
|
145
|
-
reset();
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
function parse(variable: string): Syntax[] {
|
|
149
|
-
let syntax: Syntax[] = [];
|
|
150
|
-
let parts = variable.split(Constant.Dot);
|
|
151
|
-
while (parts.length > 0) {
|
|
152
|
-
let part = parts.shift();
|
|
153
|
-
let arrayStart = part.indexOf(Constant.ArrayStart);
|
|
154
|
-
let conditionStart = part.indexOf(Constant.ConditionStart);
|
|
155
|
-
let conditionEnd = part.indexOf(Constant.ConditionEnd);
|
|
156
|
-
syntax.push({
|
|
157
|
-
name : arrayStart > 0 ? part.slice(0, arrayStart) : (conditionStart > 0 ? part.slice(0, conditionStart) : part),
|
|
158
|
-
type : arrayStart > 0 ? Type.Array : (conditionStart > 0 ? Type.Object : Type.Simple),
|
|
159
|
-
condition : conditionStart > 0 ? part.slice(conditionStart + 1, conditionEnd) : null
|
|
160
|
-
});
|
|
161
|
-
}
|
|
162
|
-
|
|
163
|
-
return syntax;
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
// The function below takes in a variable name in following format: "a.b.c" and safely evaluates its value in javascript context
|
|
167
|
-
// For instance, for a.b.c, it will first check window["a"]. If it exists, it will recursively look at: window["a"]["b"] and finally,
|
|
168
|
-
// return the value for window["a"]["b"]["c"].
|
|
169
|
-
function evaluate(variable: Syntax[], base: Object = window): any {
|
|
170
|
-
if (variable.length == 0) { return base; }
|
|
171
|
-
let part = variable.shift();
|
|
172
|
-
let output;
|
|
173
|
-
if (base && base[part.name]) {
|
|
174
|
-
let obj = base[part.name];
|
|
175
|
-
if (part.type !== Type.Array && match(obj, part.condition)) {
|
|
176
|
-
output = evaluate(variable, obj);
|
|
177
|
-
}
|
|
178
|
-
else if (Array.isArray(obj)) {
|
|
179
|
-
let filtered = [];
|
|
180
|
-
for (var value of obj) {
|
|
181
|
-
if (match(value, part.condition)) {
|
|
182
|
-
let op = evaluate(variable, value)
|
|
183
|
-
if (op) { filtered.push(op); }
|
|
184
|
-
}
|
|
185
|
-
}
|
|
186
|
-
output = filtered;
|
|
187
|
-
}
|
|
188
|
-
|
|
189
|
-
return output;
|
|
190
|
-
}
|
|
191
|
-
|
|
192
|
-
return null;
|
|
193
|
-
}
|
|
194
|
-
|
|
195
|
-
function str(input: string): string {
|
|
196
|
-
// Automatically trim string to max of Setting.ExtractLimit to avoid fetching long strings
|
|
197
|
-
return input ? JSON.stringify(input).slice(0, Setting.ExtractLimit) : input;
|
|
198
|
-
}
|
|
199
|
-
|
|
200
|
-
function match(base: Object, condition: string): boolean {
|
|
201
|
-
if (condition) {
|
|
202
|
-
let prop = condition.split(":");
|
|
203
|
-
return prop.length > 1 ? base[prop[0]] == prop[1] : base[prop[0]]
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
return true;
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
function isEmpty(obj: Object): boolean {
|
|
210
|
-
return Object.keys(obj).length == 0;
|
|
211
|
-
}
|
|
1
|
+
import { ExtractSource, Syntax, Type } from "@clarity-types/core";
|
|
2
|
+
import { Event, Setting, ExtractData } from "@clarity-types/data";
|
|
3
|
+
import encode from "./encode";
|
|
4
|
+
import * as internal from "@src/diagnostic/internal";
|
|
5
|
+
import { Code, Constant, Severity } from "@clarity-types/data";
|
|
6
|
+
import { hashText } from "@src/clarity";
|
|
7
|
+
import hash from "@src/core/hash";
|
|
8
|
+
|
|
9
|
+
export let data: ExtractData = {};
|
|
10
|
+
export let keys: Set<number> = new Set();
|
|
11
|
+
|
|
12
|
+
let variables : { [key: number]: { [key: number]: Syntax[] }} = {};
|
|
13
|
+
let selectors : { [key: number]: { [key: number]: string }} = {};
|
|
14
|
+
let hashes : { [key: number]: { [key: number]: string }} = {};
|
|
15
|
+
let validation : { [key: number]: string } = {};
|
|
16
|
+
|
|
17
|
+
export function start(): void {
|
|
18
|
+
reset();
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
// Input string is of the following form:
|
|
22
|
+
// EXTRACT 101|element { "1": ".class1", "2": "~window.a.b", "3": "!abc"}
|
|
23
|
+
// if element is present on the page it will set up event 101 to grab the contents of the class1 selector into component 1,
|
|
24
|
+
// the javascript evaluated contents of window.a.b into component 2,
|
|
25
|
+
// and the contents of Clarity's hash abc into component 3
|
|
26
|
+
export function trigger(input: string): void {
|
|
27
|
+
try {
|
|
28
|
+
var parts = input && input.length > 0 ? input.split(/ (.*)/) : [Constant.Empty];
|
|
29
|
+
var keyparts = parts[0].split(/\|(.*)/);
|
|
30
|
+
var key = parseInt(keyparts[0]);
|
|
31
|
+
var element = keyparts.length > 1 ? keyparts[1] : Constant.Empty;
|
|
32
|
+
var values = parts.length > 1 ? JSON.parse(parts[1]) : {};
|
|
33
|
+
variables[key] = {};
|
|
34
|
+
selectors[key] = {};
|
|
35
|
+
hashes[key] = {};
|
|
36
|
+
validation[key] = element;
|
|
37
|
+
for (var v in values) {
|
|
38
|
+
// values is a set of strings for proper JSON parsing, but it's more efficient
|
|
39
|
+
// to interact with them as numbers
|
|
40
|
+
let id = parseInt(v);
|
|
41
|
+
let value = values[v] as string;
|
|
42
|
+
let source = ExtractSource.Text;
|
|
43
|
+
if (value.startsWith(Constant.Tilde)) {
|
|
44
|
+
source = ExtractSource.Javascript
|
|
45
|
+
} else if (value.startsWith(Constant.Bang)) {
|
|
46
|
+
source = ExtractSource.Hash
|
|
47
|
+
}
|
|
48
|
+
switch (source) {
|
|
49
|
+
case ExtractSource.Javascript:
|
|
50
|
+
let variable = value.slice(1);
|
|
51
|
+
variables[key][id] = parse(variable);
|
|
52
|
+
break;
|
|
53
|
+
case ExtractSource.Text:
|
|
54
|
+
selectors[key][id] = value;
|
|
55
|
+
break;
|
|
56
|
+
case ExtractSource.Hash:
|
|
57
|
+
let hash = value.slice(1);
|
|
58
|
+
hashes[key][id] = hash;
|
|
59
|
+
break;
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
catch(e) {
|
|
64
|
+
internal.log(Code.Config, Severity.Warning, e ? e.name : null);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
export function clone(v: Syntax[]): Syntax[] {
|
|
69
|
+
return JSON.parse(JSON.stringify(v));
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
export function compute(): void {
|
|
73
|
+
try {
|
|
74
|
+
for (let v in variables) {
|
|
75
|
+
let key = parseInt(v);
|
|
76
|
+
if (validation[key] == Constant.Empty || document.querySelector(validation[key]))
|
|
77
|
+
{
|
|
78
|
+
let variableData = variables[key];
|
|
79
|
+
for (let v in variableData) {
|
|
80
|
+
let variableKey = parseInt(v);
|
|
81
|
+
let value = str(evaluate(clone(variableData[variableKey])));
|
|
82
|
+
if (value) {
|
|
83
|
+
update(key, variableKey, value);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
let selectorData = selectors[key];
|
|
88
|
+
for (let s in selectorData) {
|
|
89
|
+
let shouldMask = false;
|
|
90
|
+
let selectorKey = parseInt(s);
|
|
91
|
+
let selector = selectorData[selectorKey];
|
|
92
|
+
if (selector.startsWith(Constant.At)){
|
|
93
|
+
shouldMask = true;
|
|
94
|
+
selector = selector.slice(1);
|
|
95
|
+
}
|
|
96
|
+
let nodes = document.querySelectorAll(selector) as NodeListOf<HTMLElement>;
|
|
97
|
+
if (nodes) {
|
|
98
|
+
let text = Array.from(nodes).map(e => e.textContent).join(Constant.Seperator);
|
|
99
|
+
update(key, selectorKey, (shouldMask ? hash(text).trim() : text).slice(0, Setting.ExtractLimit));
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
let hashData = hashes[key];
|
|
104
|
+
for (let h in hashData) {
|
|
105
|
+
let hashKey = parseInt(h);
|
|
106
|
+
let content = hashText(hashData[hashKey]).trim().slice(0, Setting.ExtractLimit);
|
|
107
|
+
update(key, hashKey, content);
|
|
108
|
+
}
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
if (keys.size > 0) {
|
|
113
|
+
encode(Event.Extract);
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
catch (e) { internal.log(Code.Selector, Severity.Warning, e ? e.name : null); }
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export function reset(): void {
|
|
120
|
+
keys.clear();
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
export function update(key: number, subkey: number, value: string): void {
|
|
124
|
+
var update = false;
|
|
125
|
+
if (!(key in data)) {
|
|
126
|
+
data[key] = {};
|
|
127
|
+
update = true;
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
if (!isEmpty(hashes[key])
|
|
131
|
+
&& (!(subkey in data[key]) || data[key][subkey] != value))
|
|
132
|
+
{
|
|
133
|
+
update = true;
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
data[key][subkey] = value;
|
|
137
|
+
if (update) {
|
|
138
|
+
keys.add(key);
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
return;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
export function stop(): void {
|
|
145
|
+
reset();
|
|
146
|
+
}
|
|
147
|
+
|
|
148
|
+
function parse(variable: string): Syntax[] {
|
|
149
|
+
let syntax: Syntax[] = [];
|
|
150
|
+
let parts = variable.split(Constant.Dot);
|
|
151
|
+
while (parts.length > 0) {
|
|
152
|
+
let part = parts.shift();
|
|
153
|
+
let arrayStart = part.indexOf(Constant.ArrayStart);
|
|
154
|
+
let conditionStart = part.indexOf(Constant.ConditionStart);
|
|
155
|
+
let conditionEnd = part.indexOf(Constant.ConditionEnd);
|
|
156
|
+
syntax.push({
|
|
157
|
+
name : arrayStart > 0 ? part.slice(0, arrayStart) : (conditionStart > 0 ? part.slice(0, conditionStart) : part),
|
|
158
|
+
type : arrayStart > 0 ? Type.Array : (conditionStart > 0 ? Type.Object : Type.Simple),
|
|
159
|
+
condition : conditionStart > 0 ? part.slice(conditionStart + 1, conditionEnd) : null
|
|
160
|
+
});
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
return syntax;
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
// The function below takes in a variable name in following format: "a.b.c" and safely evaluates its value in javascript context
|
|
167
|
+
// For instance, for a.b.c, it will first check window["a"]. If it exists, it will recursively look at: window["a"]["b"] and finally,
|
|
168
|
+
// return the value for window["a"]["b"]["c"].
|
|
169
|
+
function evaluate(variable: Syntax[], base: Object = window): any {
|
|
170
|
+
if (variable.length == 0) { return base; }
|
|
171
|
+
let part = variable.shift();
|
|
172
|
+
let output;
|
|
173
|
+
if (base && base[part.name]) {
|
|
174
|
+
let obj = base[part.name];
|
|
175
|
+
if (part.type !== Type.Array && match(obj, part.condition)) {
|
|
176
|
+
output = evaluate(variable, obj);
|
|
177
|
+
}
|
|
178
|
+
else if (Array.isArray(obj)) {
|
|
179
|
+
let filtered = [];
|
|
180
|
+
for (var value of obj) {
|
|
181
|
+
if (match(value, part.condition)) {
|
|
182
|
+
let op = evaluate(variable, value)
|
|
183
|
+
if (op) { filtered.push(op); }
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
output = filtered;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
return output;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
return null;
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
function str(input: string): string {
|
|
196
|
+
// Automatically trim string to max of Setting.ExtractLimit to avoid fetching long strings
|
|
197
|
+
return input ? JSON.stringify(input).slice(0, Setting.ExtractLimit) : input;
|
|
198
|
+
}
|
|
199
|
+
|
|
200
|
+
function match(base: Object, condition: string): boolean {
|
|
201
|
+
if (condition) {
|
|
202
|
+
let prop = condition.split(":");
|
|
203
|
+
return prop.length > 1 ? base[prop[0]] == prop[1] : base[prop[0]]
|
|
204
|
+
}
|
|
205
|
+
|
|
206
|
+
return true;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
function isEmpty(obj: Object): boolean {
|
|
210
|
+
return Object.keys(obj).length == 0;
|
|
211
|
+
}
|
package/src/data/index.ts
CHANGED
|
@@ -1,50 +1,50 @@
|
|
|
1
|
-
import measure from "@src/core/measure";
|
|
2
|
-
import * as baseline from "@src/data/baseline";
|
|
3
|
-
import * as consent from "@src/data/consent";
|
|
4
|
-
import * as envelope from "@src/data/envelope";
|
|
5
|
-
import * as dimension from "@src/data/dimension";
|
|
6
|
-
import * as metadata from "@src/data/metadata";
|
|
7
|
-
import { Module } from "@clarity-types/core";
|
|
8
|
-
import * as metric from "@src/data/metric";
|
|
9
|
-
import * as ping from "@src/data/ping";
|
|
10
|
-
import * as limit from "@src/data/limit";
|
|
11
|
-
import * as summary from "@src/data/summary";
|
|
12
|
-
import * as upgrade from "@src/data/upgrade";
|
|
13
|
-
import * as upload from "@src/data/upload";
|
|
14
|
-
import * as variable from "@src/data/variable";
|
|
15
|
-
import * as extract from "@src/data/extract";
|
|
16
|
-
export { event } from "@src/data/custom";
|
|
17
|
-
export { consent, consentv2, metadata } from "@src/data/metadata";
|
|
18
|
-
export { upgrade } from "@src/data/upgrade";
|
|
19
|
-
export { set, identify } from "@src/data/variable";
|
|
20
|
-
export { signal } from "@src/data/signal";
|
|
21
|
-
export { max as maxMetric } from "@src/data/metric";
|
|
22
|
-
export { log as dlog } from "@src/data/dimension";
|
|
23
|
-
|
|
24
|
-
const modules: Module[] = [baseline, dimension, variable, limit, summary, consent, metadata, envelope, upload, ping, upgrade, extract];
|
|
25
|
-
|
|
26
|
-
export function start(): void {
|
|
27
|
-
// Metric needs to be initialized before we can start measuring. so metric is not wrapped in measure
|
|
28
|
-
metric.start();
|
|
29
|
-
modules.forEach(x => measure(x.start)());
|
|
30
|
-
}
|
|
31
|
-
|
|
32
|
-
export function stop(): void {
|
|
33
|
-
// Stop modules in the reverse order of their initialization
|
|
34
|
-
// The ordering below should respect inter-module dependency.
|
|
35
|
-
// E.g. if upgrade depends on upload, then upgrade needs to end before upload.
|
|
36
|
-
// Similarly, if upload depends on metadata, upload needs to end before metadata.
|
|
37
|
-
modules.slice().reverse().forEach(x => measure(x.stop)());
|
|
38
|
-
metric.stop();
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
export function compute(): void {
|
|
42
|
-
variable.compute();
|
|
43
|
-
baseline.compute();
|
|
44
|
-
dimension.compute();
|
|
45
|
-
metric.compute();
|
|
46
|
-
summary.compute();
|
|
47
|
-
limit.compute();
|
|
48
|
-
extract.compute();
|
|
49
|
-
consent.compute();
|
|
50
|
-
}
|
|
1
|
+
import measure from "@src/core/measure";
|
|
2
|
+
import * as baseline from "@src/data/baseline";
|
|
3
|
+
import * as consent from "@src/data/consent";
|
|
4
|
+
import * as envelope from "@src/data/envelope";
|
|
5
|
+
import * as dimension from "@src/data/dimension";
|
|
6
|
+
import * as metadata from "@src/data/metadata";
|
|
7
|
+
import { Module } from "@clarity-types/core";
|
|
8
|
+
import * as metric from "@src/data/metric";
|
|
9
|
+
import * as ping from "@src/data/ping";
|
|
10
|
+
import * as limit from "@src/data/limit";
|
|
11
|
+
import * as summary from "@src/data/summary";
|
|
12
|
+
import * as upgrade from "@src/data/upgrade";
|
|
13
|
+
import * as upload from "@src/data/upload";
|
|
14
|
+
import * as variable from "@src/data/variable";
|
|
15
|
+
import * as extract from "@src/data/extract";
|
|
16
|
+
export { event } from "@src/data/custom";
|
|
17
|
+
export { consent, consentv2, metadata } from "@src/data/metadata";
|
|
18
|
+
export { upgrade } from "@src/data/upgrade";
|
|
19
|
+
export { set, identify } from "@src/data/variable";
|
|
20
|
+
export { signal } from "@src/data/signal";
|
|
21
|
+
export { max as maxMetric } from "@src/data/metric";
|
|
22
|
+
export { log as dlog } from "@src/data/dimension";
|
|
23
|
+
|
|
24
|
+
const modules: Module[] = [baseline, dimension, variable, limit, summary, consent, metadata, envelope, upload, ping, upgrade, extract];
|
|
25
|
+
|
|
26
|
+
export function start(): void {
|
|
27
|
+
// Metric needs to be initialized before we can start measuring. so metric is not wrapped in measure
|
|
28
|
+
metric.start();
|
|
29
|
+
modules.forEach(x => measure(x.start)());
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
export function stop(): void {
|
|
33
|
+
// Stop modules in the reverse order of their initialization
|
|
34
|
+
// The ordering below should respect inter-module dependency.
|
|
35
|
+
// E.g. if upgrade depends on upload, then upgrade needs to end before upload.
|
|
36
|
+
// Similarly, if upload depends on metadata, upload needs to end before metadata.
|
|
37
|
+
modules.slice().reverse().forEach(x => measure(x.stop)());
|
|
38
|
+
metric.stop();
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
export function compute(): void {
|
|
42
|
+
variable.compute();
|
|
43
|
+
baseline.compute();
|
|
44
|
+
dimension.compute();
|
|
45
|
+
metric.compute();
|
|
46
|
+
summary.compute();
|
|
47
|
+
limit.compute();
|
|
48
|
+
extract.compute();
|
|
49
|
+
consent.compute();
|
|
50
|
+
}
|
package/src/data/limit.ts
CHANGED
|
@@ -1,44 +1,44 @@
|
|
|
1
|
-
import { Check, Event, LimitData, Setting } from "@clarity-types/data";
|
|
2
|
-
import * as clarity from "@src/clarity";
|
|
3
|
-
import { time } from "@src/core/time";
|
|
4
|
-
import * as envelope from "@src/data/envelope";
|
|
5
|
-
import * as metadata from "@src/data/metadata";
|
|
6
|
-
import encode from "./encode";
|
|
7
|
-
|
|
8
|
-
export let data: LimitData;
|
|
9
|
-
|
|
10
|
-
export function start(): void {
|
|
11
|
-
data = { check: Check.None };
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
export function check(bytes: number): void {
|
|
15
|
-
if (data.check === Check.None) {
|
|
16
|
-
let reason = data.check;
|
|
17
|
-
reason = envelope.data.sequence >= Setting.PayloadLimit ? Check.Payload : reason;
|
|
18
|
-
reason = envelope.data.pageNum >= Setting.PageLimit ? Check.Page : reason;
|
|
19
|
-
reason = time() > Setting.ShutdownLimit ? Check.Shutdown : reason;
|
|
20
|
-
reason = bytes > Setting.PlaybackBytesLimit ? Check.Shutdown : reason;
|
|
21
|
-
if (reason !== data.check) {
|
|
22
|
-
trigger(reason);
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
export function trigger(reason: Check): void {
|
|
28
|
-
data.check = reason;
|
|
29
|
-
// limit the dimensions we collect, but we don't need to stop Clarity entirely if we hit the limit
|
|
30
|
-
if (reason !== Check.Collection) {
|
|
31
|
-
metadata.clear();
|
|
32
|
-
clarity.stop();
|
|
33
|
-
}
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
export function compute(): void {
|
|
37
|
-
if (data.check !== Check.None) {
|
|
38
|
-
encode(Event.Limit);
|
|
39
|
-
}
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
export function stop(): void {
|
|
43
|
-
data = null;
|
|
44
|
-
}
|
|
1
|
+
import { Check, Event, LimitData, Setting } from "@clarity-types/data";
|
|
2
|
+
import * as clarity from "@src/clarity";
|
|
3
|
+
import { time } from "@src/core/time";
|
|
4
|
+
import * as envelope from "@src/data/envelope";
|
|
5
|
+
import * as metadata from "@src/data/metadata";
|
|
6
|
+
import encode from "./encode";
|
|
7
|
+
|
|
8
|
+
export let data: LimitData;
|
|
9
|
+
|
|
10
|
+
export function start(): void {
|
|
11
|
+
data = { check: Check.None };
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export function check(bytes: number): void {
|
|
15
|
+
if (data.check === Check.None) {
|
|
16
|
+
let reason = data.check;
|
|
17
|
+
reason = envelope.data.sequence >= Setting.PayloadLimit ? Check.Payload : reason;
|
|
18
|
+
reason = envelope.data.pageNum >= Setting.PageLimit ? Check.Page : reason;
|
|
19
|
+
reason = time() > Setting.ShutdownLimit ? Check.Shutdown : reason;
|
|
20
|
+
reason = bytes > Setting.PlaybackBytesLimit ? Check.Shutdown : reason;
|
|
21
|
+
if (reason !== data.check) {
|
|
22
|
+
trigger(reason);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
export function trigger(reason: Check): void {
|
|
28
|
+
data.check = reason;
|
|
29
|
+
// limit the dimensions we collect, but we don't need to stop Clarity entirely if we hit the limit
|
|
30
|
+
if (reason !== Check.Collection) {
|
|
31
|
+
metadata.clear();
|
|
32
|
+
clarity.stop();
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
export function compute(): void {
|
|
37
|
+
if (data.check !== Check.None) {
|
|
38
|
+
encode(Event.Limit);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
export function stop(): void {
|
|
43
|
+
data = null;
|
|
44
|
+
}
|