clarity-decode 0.8.42 → 0.8.43

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/src/clarity.ts CHANGED
@@ -1,233 +1,233 @@
1
- import { Data, version } from "clarity-js";
2
- import { BaselineEvent, CustomEvent, DecodedPayload, DecodedVersion, DimensionEvent } from "../types/data";
3
- import { LimitEvent, MetricEvent, PingEvent, SummaryEvent, UpgradeEvent, UploadEvent, VariableEvent, ExtractEvent, ConsentEvent } from "../types/data";
4
- import { FraudEvent, LogEvent, ScriptErrorEvent } from "../types/diagnostic";
5
- import { ChangeEvent, ClickEvent, ContextMenuEvent, ClipboardEvent, InputEvent, PointerEvent, ResizeEvent, ScrollEvent } from "../types/interaction";
6
- import { SelectionEvent, SubmitEvent, TimelineEvent, UnloadEvent, VisibilityEvent, FocusEvent } from "../types/interaction";
7
- import { CustomElementEvent, DocumentEvent, DomEvent, RegionEvent } from "../types/layout";
8
- import { NavigationEvent } from "../types/performance";
9
-
10
- import * as data from "./data";
11
- import * as diagnostic from "./diagnostic";
12
- import * as interaction from "./interaction";
13
- import * as layout from "./layout";
14
- import * as performance from "./performance";
15
-
16
- export function decode(input: string): DecodedPayload {
17
- let json: Data.Payload = JSON.parse(input);
18
- let envelope = data.envelope(json.e);
19
- let timestamp = Date.now();
20
- let payload: DecodedPayload = { timestamp, envelope };
21
-
22
- // Sort encoded events by time to simplify summary computation
23
- // It's possible for individual events to be out of order, dependent on how they are buffered on the client
24
- // E.g. scroll events are queued internally before they are sent over the wire.
25
- // By comparison, events like resize & click are sent out immediately.
26
- let encoded: Data.Token[][] = json.p ? json.a.concat(json.p) : json.a;
27
- encoded = encoded.sort((a: Data.Token[], b: Data.Token[]): number => (a[0] as number) - (b[0] as number));
28
-
29
- // Check if the incoming version is compatible with the current running code
30
- // We do an exact match for the major version and minor version.
31
- // For patch, we are backward and forward compatible with up to version change.
32
- let jsonVersion = parseVersion(payload.envelope.version);
33
- let codeVersion = parseVersion(version);
34
-
35
- if (jsonVersion.major !== codeVersion.major ||
36
- Math.abs(jsonVersion.minor - codeVersion.minor) > 1) {
37
- throw new Error(`Invalid version. Actual: ${payload.envelope.version} | Expected: ${version} (+/- 1) | ${input.substr(0, 250)}`);
38
- }
39
-
40
- for (let entry of encoded) {
41
- switch (entry[1]) {
42
- case Data.Event.Baseline:
43
- if (payload.baseline === undefined) { payload.baseline = []; }
44
- payload.baseline.push(data.decode(entry) as BaselineEvent);
45
- break;
46
- case Data.Event.Ping:
47
- if (payload.ping === undefined) { payload.ping = []; }
48
- payload.ping.push(data.decode(entry) as PingEvent);
49
- break;
50
- case Data.Event.Limit:
51
- if (payload.limit === undefined) { payload.limit = []; }
52
- payload.limit.push(data.decode(entry) as LimitEvent);
53
- break;
54
- case Data.Event.Upgrade:
55
- if (payload.upgrade === undefined) { payload.upgrade = []; }
56
- payload.upgrade.push(data.decode(entry) as UpgradeEvent);
57
- break;
58
- case Data.Event.Metric:
59
- if (payload.metric === undefined) { payload.metric = []; }
60
- let metric = data.decode(entry) as MetricEvent;
61
- // It's not possible to accurately include the byte count of the payload within the same payload
62
- // The value we get from clarity-js lags behind by a payload. To work around that,
63
- // we increment the bytes from the incoming payload at decode time.
64
- metric.data[Data.Metric.TotalBytes] = input.length;
65
- payload.metric.push(metric);
66
- break;
67
- case Data.Event.Dimension:
68
- if (payload.dimension === undefined) { payload.dimension = []; }
69
- payload.dimension.push(data.decode(entry) as DimensionEvent);
70
- break;
71
- case Data.Event.Summary:
72
- if (payload.summary === undefined) { payload.summary = []; }
73
- payload.summary.push(data.decode(entry) as SummaryEvent);
74
- break;
75
- case Data.Event.Custom:
76
- if (payload.custom === undefined) { payload.custom = []; }
77
- payload.custom.push(data.decode(entry) as CustomEvent);
78
- break;
79
- case Data.Event.Variable:
80
- if (payload.variable === undefined) { payload.variable = []; }
81
- payload.variable.push(data.decode(entry) as VariableEvent);
82
- break;
83
- case Data.Event.Upload:
84
- if (payload.upload === undefined) { payload.upload = []; }
85
- payload.upload.push(data.decode(entry) as UploadEvent);
86
- break;
87
- case Data.Event.MouseDown:
88
- case Data.Event.MouseUp:
89
- case Data.Event.MouseMove:
90
- case Data.Event.MouseWheel:
91
- case Data.Event.DoubleClick:
92
- case Data.Event.TouchStart:
93
- case Data.Event.TouchCancel:
94
- case Data.Event.TouchEnd:
95
- case Data.Event.TouchMove:
96
- if (payload.pointer === undefined) { payload.pointer = []; }
97
- payload.pointer.push(interaction.decode(entry) as PointerEvent);
98
- break;
99
- case Data.Event.Click:
100
- if (payload.click === undefined) { payload.click = []; }
101
- let clickEntry = interaction.decode(entry) as ClickEvent;
102
- payload.click.push(clickEntry);
103
- break;
104
- case Data.Event.ContextMenu:
105
- if (payload.contextMenu === undefined) { payload.contextMenu = []; }
106
- let contextMenuEntry = interaction.decode(entry) as ContextMenuEvent;
107
- payload.contextMenu.push(contextMenuEntry);
108
- break;
109
- case Data.Event.Clipboard:
110
- if (payload.clipboard === undefined) { payload.clipboard = []; }
111
- let clipEntry = interaction.decode(entry) as ClipboardEvent;
112
- payload.clipboard.push(clipEntry);
113
- break;
114
- case Data.Event.Scroll:
115
- if (payload.scroll === undefined) { payload.scroll = []; }
116
- payload.scroll.push(interaction.decode(entry) as ScrollEvent);
117
- break;
118
- case Data.Event.Resize:
119
- if (payload.resize === undefined) { payload.resize = []; }
120
- payload.resize.push(interaction.decode(entry) as ResizeEvent);
121
- break;
122
- case Data.Event.Selection:
123
- if (payload.selection === undefined) { payload.selection = []; }
124
- payload.selection.push(interaction.decode(entry) as SelectionEvent);
125
- break;
126
- case Data.Event.Change:
127
- if (payload.change === undefined) { payload.change = []; }
128
- let changeEntry = interaction.decode(entry) as ChangeEvent;
129
- payload.change.push(changeEntry);
130
- break;
131
- case Data.Event.Submit:
132
- if (payload.submit === undefined) { payload.submit = []; }
133
- let submitEntry = interaction.decode(entry) as SubmitEvent;
134
- payload.submit.push(submitEntry);
135
- break;
136
- case Data.Event.Timeline:
137
- if (payload.timeline === undefined) { payload.timeline = []; }
138
- payload.timeline.push(interaction.decode(entry) as TimelineEvent);
139
- break;
140
- case Data.Event.Input:
141
- if (payload.input === undefined) { payload.input = []; }
142
- payload.input.push(interaction.decode(entry) as InputEvent);
143
- break;
144
- case Data.Event.Unload:
145
- if (payload.unload === undefined) { payload.unload = []; }
146
- payload.unload.push(interaction.decode(entry) as UnloadEvent);
147
- break;
148
- case Data.Event.Visibility:
149
- if (payload.visibility === undefined) { payload.visibility = []; }
150
- payload.visibility.push(interaction.decode(entry) as VisibilityEvent);
151
- break;
152
- case Data.Event.Focus:
153
- if (payload.focus === undefined) { payload.focus = []; }
154
- payload.focus.push(interaction.decode(entry) as FocusEvent);
155
- break;
156
- case Data.Event.Box:
157
- /* Deprecated - Intentionally, no-op. For backward compatibility. */
158
- break;
159
- case Data.Event.Region:
160
- if (payload.region === undefined) { payload.region = []; }
161
- payload.region.push(layout.decode(entry) as RegionEvent);
162
- break;
163
- case Data.Event.Discover:
164
- case Data.Event.Mutation:
165
- case Data.Event.Snapshot:
166
- case Data.Event.StyleSheetAdoption:
167
- case Data.Event.StyleSheetUpdate:
168
- case Data.Event.Animation:
169
- if (payload.dom === undefined) { payload.dom = []; }
170
- payload.dom.push(layout.decode(entry) as DomEvent);
171
- break;
172
- case Data.Event.Document:
173
- if (payload.doc === undefined) { payload.doc = []; }
174
- payload.doc.push(layout.decode(entry) as DocumentEvent);
175
- break;
176
- case Data.Event.ScriptError:
177
- if (payload.script === undefined) { payload.script = []; }
178
- payload.script.push(diagnostic.decode(entry) as ScriptErrorEvent);
179
- break;
180
- case Data.Event.Log:
181
- if (payload.log === undefined) { payload.log = []; }
182
- payload.log.push(diagnostic.decode(entry) as LogEvent);
183
- break;
184
- case Data.Event.Fraud:
185
- if (payload.fraud === undefined) { payload.fraud = []; }
186
- payload.fraud.push(diagnostic.decode(entry) as FraudEvent);
187
- break;
188
- case Data.Event.Navigation:
189
- if (payload.navigation === undefined) { payload.navigation = []; }
190
- payload.navigation.push(performance.decode(entry) as NavigationEvent);
191
- break;
192
- case Data.Event.Connection:
193
- case Data.Event.ImageError:
194
- /* Deprecated - Intentionally, no-op. For backward compatibility. */
195
- break;
196
- case Data.Event.Extract:
197
- if (payload.extract === undefined) { payload.extract = []; }
198
- payload.extract.push(data.decode(entry) as ExtractEvent);
199
- break;
200
- case Data.Event.Consent:
201
- if (payload.consent === undefined) { payload.consent = []; }
202
- payload.consent.push(data.decode(entry) as ConsentEvent);
203
- break;
204
- case Data.Event.CustomElement:
205
- if (payload.customElement === undefined) { payload.customElement = []; }
206
- payload.customElement.push(layout.decode(entry) as CustomElementEvent);
207
- break;
208
- default:
209
- if (typeof entry[1] === "number" && entry[1] < 200) {
210
- console.error(`No handler for Event: ${JSON.stringify(entry)}`);
211
- }
212
- break;
213
- }
214
- }
215
-
216
- return payload;
217
- }
218
-
219
-
220
- function parseVersion(ver: string): DecodedVersion {
221
- let output: DecodedVersion = { major: 0, minor: 0, patch: 0, beta: 0 };
222
- let parts = ver.split(".");
223
- if (parts.length === 3) {
224
- let subparts = parts[2].split("-b");
225
- output.major = parseInt(parts[0], 10);
226
- output.minor = parseInt(parts[1], 10);
227
- if (subparts.length === 2) {
228
- output.patch = parseInt(subparts[0], 10);
229
- output.beta = parseInt(subparts[1], 10);
230
- } else { output.patch = parseInt(parts[2], 10); }
231
- }
232
- return output;
233
- }
1
+ import { Data, version } from "clarity-js";
2
+ import { BaselineEvent, CustomEvent, DecodedPayload, DecodedVersion, DimensionEvent } from "../types/data";
3
+ import { LimitEvent, MetricEvent, PingEvent, SummaryEvent, UpgradeEvent, UploadEvent, VariableEvent, ExtractEvent, ConsentEvent } from "../types/data";
4
+ import { FraudEvent, LogEvent, ScriptErrorEvent } from "../types/diagnostic";
5
+ import { ChangeEvent, ClickEvent, ContextMenuEvent, ClipboardEvent, InputEvent, PointerEvent, ResizeEvent, ScrollEvent } from "../types/interaction";
6
+ import { SelectionEvent, SubmitEvent, TimelineEvent, UnloadEvent, VisibilityEvent, FocusEvent } from "../types/interaction";
7
+ import { CustomElementEvent, DocumentEvent, DomEvent, RegionEvent } from "../types/layout";
8
+ import { NavigationEvent } from "../types/performance";
9
+
10
+ import * as data from "./data";
11
+ import * as diagnostic from "./diagnostic";
12
+ import * as interaction from "./interaction";
13
+ import * as layout from "./layout";
14
+ import * as performance from "./performance";
15
+
16
+ export function decode(input: string): DecodedPayload {
17
+ let json: Data.Payload = JSON.parse(input);
18
+ let envelope = data.envelope(json.e);
19
+ let timestamp = Date.now();
20
+ let payload: DecodedPayload = { timestamp, envelope };
21
+
22
+ // Sort encoded events by time to simplify summary computation
23
+ // It's possible for individual events to be out of order, dependent on how they are buffered on the client
24
+ // E.g. scroll events are queued internally before they are sent over the wire.
25
+ // By comparison, events like resize & click are sent out immediately.
26
+ let encoded: Data.Token[][] = json.p ? json.a.concat(json.p) : json.a;
27
+ encoded = encoded.sort((a: Data.Token[], b: Data.Token[]): number => (a[0] as number) - (b[0] as number));
28
+
29
+ // Check if the incoming version is compatible with the current running code
30
+ // We do an exact match for the major version and minor version.
31
+ // For patch, we are backward and forward compatible with up to version change.
32
+ let jsonVersion = parseVersion(payload.envelope.version);
33
+ let codeVersion = parseVersion(version);
34
+
35
+ if (jsonVersion.major !== codeVersion.major ||
36
+ Math.abs(jsonVersion.minor - codeVersion.minor) > 1) {
37
+ throw new Error(`Invalid version. Actual: ${payload.envelope.version} | Expected: ${version} (+/- 1) | ${input.substr(0, 250)}`);
38
+ }
39
+
40
+ for (let entry of encoded) {
41
+ switch (entry[1]) {
42
+ case Data.Event.Baseline:
43
+ if (payload.baseline === undefined) { payload.baseline = []; }
44
+ payload.baseline.push(data.decode(entry) as BaselineEvent);
45
+ break;
46
+ case Data.Event.Ping:
47
+ if (payload.ping === undefined) { payload.ping = []; }
48
+ payload.ping.push(data.decode(entry) as PingEvent);
49
+ break;
50
+ case Data.Event.Limit:
51
+ if (payload.limit === undefined) { payload.limit = []; }
52
+ payload.limit.push(data.decode(entry) as LimitEvent);
53
+ break;
54
+ case Data.Event.Upgrade:
55
+ if (payload.upgrade === undefined) { payload.upgrade = []; }
56
+ payload.upgrade.push(data.decode(entry) as UpgradeEvent);
57
+ break;
58
+ case Data.Event.Metric:
59
+ if (payload.metric === undefined) { payload.metric = []; }
60
+ let metric = data.decode(entry) as MetricEvent;
61
+ // It's not possible to accurately include the byte count of the payload within the same payload
62
+ // The value we get from clarity-js lags behind by a payload. To work around that,
63
+ // we increment the bytes from the incoming payload at decode time.
64
+ metric.data[Data.Metric.TotalBytes] = input.length;
65
+ payload.metric.push(metric);
66
+ break;
67
+ case Data.Event.Dimension:
68
+ if (payload.dimension === undefined) { payload.dimension = []; }
69
+ payload.dimension.push(data.decode(entry) as DimensionEvent);
70
+ break;
71
+ case Data.Event.Summary:
72
+ if (payload.summary === undefined) { payload.summary = []; }
73
+ payload.summary.push(data.decode(entry) as SummaryEvent);
74
+ break;
75
+ case Data.Event.Custom:
76
+ if (payload.custom === undefined) { payload.custom = []; }
77
+ payload.custom.push(data.decode(entry) as CustomEvent);
78
+ break;
79
+ case Data.Event.Variable:
80
+ if (payload.variable === undefined) { payload.variable = []; }
81
+ payload.variable.push(data.decode(entry) as VariableEvent);
82
+ break;
83
+ case Data.Event.Upload:
84
+ if (payload.upload === undefined) { payload.upload = []; }
85
+ payload.upload.push(data.decode(entry) as UploadEvent);
86
+ break;
87
+ case Data.Event.MouseDown:
88
+ case Data.Event.MouseUp:
89
+ case Data.Event.MouseMove:
90
+ case Data.Event.MouseWheel:
91
+ case Data.Event.DoubleClick:
92
+ case Data.Event.TouchStart:
93
+ case Data.Event.TouchCancel:
94
+ case Data.Event.TouchEnd:
95
+ case Data.Event.TouchMove:
96
+ if (payload.pointer === undefined) { payload.pointer = []; }
97
+ payload.pointer.push(interaction.decode(entry) as PointerEvent);
98
+ break;
99
+ case Data.Event.Click:
100
+ if (payload.click === undefined) { payload.click = []; }
101
+ let clickEntry = interaction.decode(entry) as ClickEvent;
102
+ payload.click.push(clickEntry);
103
+ break;
104
+ case Data.Event.ContextMenu:
105
+ if (payload.contextMenu === undefined) { payload.contextMenu = []; }
106
+ let contextMenuEntry = interaction.decode(entry) as ContextMenuEvent;
107
+ payload.contextMenu.push(contextMenuEntry);
108
+ break;
109
+ case Data.Event.Clipboard:
110
+ if (payload.clipboard === undefined) { payload.clipboard = []; }
111
+ let clipEntry = interaction.decode(entry) as ClipboardEvent;
112
+ payload.clipboard.push(clipEntry);
113
+ break;
114
+ case Data.Event.Scroll:
115
+ if (payload.scroll === undefined) { payload.scroll = []; }
116
+ payload.scroll.push(interaction.decode(entry) as ScrollEvent);
117
+ break;
118
+ case Data.Event.Resize:
119
+ if (payload.resize === undefined) { payload.resize = []; }
120
+ payload.resize.push(interaction.decode(entry) as ResizeEvent);
121
+ break;
122
+ case Data.Event.Selection:
123
+ if (payload.selection === undefined) { payload.selection = []; }
124
+ payload.selection.push(interaction.decode(entry) as SelectionEvent);
125
+ break;
126
+ case Data.Event.Change:
127
+ if (payload.change === undefined) { payload.change = []; }
128
+ let changeEntry = interaction.decode(entry) as ChangeEvent;
129
+ payload.change.push(changeEntry);
130
+ break;
131
+ case Data.Event.Submit:
132
+ if (payload.submit === undefined) { payload.submit = []; }
133
+ let submitEntry = interaction.decode(entry) as SubmitEvent;
134
+ payload.submit.push(submitEntry);
135
+ break;
136
+ case Data.Event.Timeline:
137
+ if (payload.timeline === undefined) { payload.timeline = []; }
138
+ payload.timeline.push(interaction.decode(entry) as TimelineEvent);
139
+ break;
140
+ case Data.Event.Input:
141
+ if (payload.input === undefined) { payload.input = []; }
142
+ payload.input.push(interaction.decode(entry) as InputEvent);
143
+ break;
144
+ case Data.Event.Unload:
145
+ if (payload.unload === undefined) { payload.unload = []; }
146
+ payload.unload.push(interaction.decode(entry) as UnloadEvent);
147
+ break;
148
+ case Data.Event.Visibility:
149
+ if (payload.visibility === undefined) { payload.visibility = []; }
150
+ payload.visibility.push(interaction.decode(entry) as VisibilityEvent);
151
+ break;
152
+ case Data.Event.Focus:
153
+ if (payload.focus === undefined) { payload.focus = []; }
154
+ payload.focus.push(interaction.decode(entry) as FocusEvent);
155
+ break;
156
+ case Data.Event.Box:
157
+ /* Deprecated - Intentionally, no-op. For backward compatibility. */
158
+ break;
159
+ case Data.Event.Region:
160
+ if (payload.region === undefined) { payload.region = []; }
161
+ payload.region.push(layout.decode(entry) as RegionEvent);
162
+ break;
163
+ case Data.Event.Discover:
164
+ case Data.Event.Mutation:
165
+ case Data.Event.Snapshot:
166
+ case Data.Event.StyleSheetAdoption:
167
+ case Data.Event.StyleSheetUpdate:
168
+ case Data.Event.Animation:
169
+ if (payload.dom === undefined) { payload.dom = []; }
170
+ payload.dom.push(layout.decode(entry) as DomEvent);
171
+ break;
172
+ case Data.Event.Document:
173
+ if (payload.doc === undefined) { payload.doc = []; }
174
+ payload.doc.push(layout.decode(entry) as DocumentEvent);
175
+ break;
176
+ case Data.Event.ScriptError:
177
+ if (payload.script === undefined) { payload.script = []; }
178
+ payload.script.push(diagnostic.decode(entry) as ScriptErrorEvent);
179
+ break;
180
+ case Data.Event.Log:
181
+ if (payload.log === undefined) { payload.log = []; }
182
+ payload.log.push(diagnostic.decode(entry) as LogEvent);
183
+ break;
184
+ case Data.Event.Fraud:
185
+ if (payload.fraud === undefined) { payload.fraud = []; }
186
+ payload.fraud.push(diagnostic.decode(entry) as FraudEvent);
187
+ break;
188
+ case Data.Event.Navigation:
189
+ if (payload.navigation === undefined) { payload.navigation = []; }
190
+ payload.navigation.push(performance.decode(entry) as NavigationEvent);
191
+ break;
192
+ case Data.Event.Connection:
193
+ case Data.Event.ImageError:
194
+ /* Deprecated - Intentionally, no-op. For backward compatibility. */
195
+ break;
196
+ case Data.Event.Extract:
197
+ if (payload.extract === undefined) { payload.extract = []; }
198
+ payload.extract.push(data.decode(entry) as ExtractEvent);
199
+ break;
200
+ case Data.Event.Consent:
201
+ if (payload.consent === undefined) { payload.consent = []; }
202
+ payload.consent.push(data.decode(entry) as ConsentEvent);
203
+ break;
204
+ case Data.Event.CustomElement:
205
+ if (payload.customElement === undefined) { payload.customElement = []; }
206
+ payload.customElement.push(layout.decode(entry) as CustomElementEvent);
207
+ break;
208
+ default:
209
+ if (typeof entry[1] === "number" && entry[1] < 200) {
210
+ console.error(`No handler for Event: ${JSON.stringify(entry)}`);
211
+ }
212
+ break;
213
+ }
214
+ }
215
+
216
+ return payload;
217
+ }
218
+
219
+
220
+ function parseVersion(ver: string): DecodedVersion {
221
+ let output: DecodedVersion = { major: 0, minor: 0, patch: 0, beta: 0 };
222
+ let parts = ver.split(".");
223
+ if (parts.length === 3) {
224
+ let subparts = parts[2].split("-b");
225
+ output.major = parseInt(parts[0], 10);
226
+ output.minor = parseInt(parts[1], 10);
227
+ if (subparts.length === 2) {
228
+ output.patch = parseInt(subparts[0], 10);
229
+ output.beta = parseInt(subparts[1], 10);
230
+ } else { output.patch = parseInt(parts[2], 10); }
231
+ }
232
+ return output;
233
+ }