-
Notifications
You must be signed in to change notification settings - Fork 1
/
utils.ts
138 lines (131 loc) · 3.34 KB
/
utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
/**
* Contains utility methods that may be useful for
* consumers of the patch collector.
*
* ## esm
*
* ```js
* import { utils } from '@paychex/collector-batch';
* ```
*
* ## cjs
*
* ```js
* const { utils } = require('@paychex/collector-batch');
* ```
*
* ## amd
*
* ```js
* define(['@paychex/collector-batch'], function({ utils }) { ... });
* require(['@paychex/collector-batch'], function({ utils }) { ... });
* ```
*
* ## iife
*
* ```js
* const { utils } = window['@paychex/collector-batch'];
* ```
*
* @module utils
*/
import { isEmpty } from 'lodash';
import { compare, Operation } from 'fast-json-patch';
import type { TrackingInfo } from '@paychex/core/types/trackers';
export type PatchResult = [TrackingInfo?, ...Operation[][]];
type PatchPair = [TrackingInfo | void, TrackingInfo];
function isNotEmpty(patches: TrackingInfo|Operation[]): boolean {
return !isEmpty(patches);
}
function asPatch(arr: PatchResult, [prev, curr]: PatchPair): PatchResult {
arr.push(prev ? compare(prev, curr) : curr);
return arr;
}
function toPairs(item: TrackingInfo, index: number, arr: TrackingInfo[]): PatchPair {
const prev = arr[index - 1];
return [prev, item];
}
/**
* Converts an Array of TrackingInfo instances into an array whose first item is a TrackingInfo
* instance, and whose subsequent items are arrays of JSON-Patch operations.
*
* For example, if you set up your collector like this:
*
* ```js
* import { batch, utils } from '@paychex/collector-batch';
*
* async function send(payload) {
* // payload will either be empty,
* // have a single TrackingInfo entry,
* // or have a TrackingInfo entry followed
* // by 1 or more arrays of JSON-Patch
* // operations describing the differences
* // from the previous payload entry
* }
*
* const collector = batch(send, utils.toPatch);
* ```
*
* And you sent the following events:
*
* ```js
* tracker.event('click', { category: 'ux' });
* tracker.event('click', { category: 'menu', text: 'log out' });
* ```
*
* Then the payload provided to your send method would look like this:
*
* ```json
* [
* {
* "id": "a0ed9697-1e38-4bca-b17b-5c79b9f028e2",
* "type": "event",
* "label": "click",
* "start": 1611604974339,
* "stop": 1611604974339,
* "duration": 0,
* "count": 1,
* "data": {
* "category": "ux"
* }
* },
* [
* {
* "op": "replace",
* "path": "/data/category",
* "value": "menu"
* },
* {
* "op": "add",
* "path": "/data/text",
* "value": "log out"
* },
* {
* "op": "replace",
* "path": "/stop",
* "value": 1611604974340
* },
* {
* "op": "replace",
* "path": "/start",
* "value": 1611604974340
* },
* {
* "op": "replace",
* "path": "/id",
* "value": "b387d125-1910-45ff-a346-cd17e35c9e94"
* }
* ]
* ]
* ```
*
* @param entries The array of TrackingInfo instances to convert.
* @returns An array of entries, where the first item is an unmodified TrackingInfo
* instance, and each subsequent item in the array is an Array of JSON-Patch operations.
*/
export function toPatch(entries: TrackingInfo[]): PatchResult {
return entries
.map(toPairs)
.reduce(asPatch, [])
.filter(isNotEmpty) as PatchResult;
}