This repository was archived by the owner on Apr 8, 2021. It is now read-only.
forked from snowplow/snowplow-javascript-tracker
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathpayload.ts
More file actions
145 lines (129 loc) · 3.94 KB
/
Copy pathpayload.ts
File metadata and controls
145 lines (129 loc) · 3.94 KB
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
139
140
141
142
143
144
145
/*
* JavaScript tracker core for Snowplow: payload.ts
*
* Copyright (c) 2014-2020 Snowplow Analytics Ltd. All rights reserved.
*
* This program is licensed to you under the Apache License Version 2.0,
* and you may not use this file except in compliance with the Apache License Version 2.0.
* You may obtain a copy of the Apache License Version 2.0 at http://www.apache.org/licenses/LICENSE-2.0.
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the Apache License Version 2.0 is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the Apache License Version 2.0 for the specific language governing permissions and limitations there under.
*/
import * as base64 from './base64';
/**
* Interface for a Payload dictionary
*/
export interface PayloadDictionary {
[key: string]: unknown;
}
/**
* Interface for mutable object encapsulating tracker payload
*/
export interface PayloadData {
/**
* Adds an entry to the Payload
* @param key Key for Payload dictionary entry
* @param value Value for Payload dictionaty entry
*/
add: (key: string, value?: string) => void;
/**
* Merges a payload into the existing payload
* @param dict The payload to merge
*/
addDict: (dict: PayloadDictionary) => void;
/**
* Adds a JSON object to the payload - will stringify the JSON object
* @param keyIfEncoded key if base64 encoding is enabled
* @param keyIfNotEncoded key if base64 encoding is disabled
* @param json The json to be stringified and added to the payload
*/
addJson: (keyIfEncoded: string, keyIfNotEncoded: string, json: Record<string, unknown>) => void;
/**
* Builds and returns the Payload
*/
build: () => PayloadDictionary;
}
/**
* Base64 encode data with URL and Filename Safe Alphabet (base64url)
*
* See: http://tools.ietf.org/html/rfc4648#page-7
*/
function base64urlencode(data: string): string {
if (!data) {
return data;
}
const enc = base64.base64encode(data);
return enc.replace(/=/g, '').replace(/\+/g, '-').replace(/\//g, '_');
}
/**
* Is property a non-empty JSON?
*/
export function isNonEmptyJson(property: Record<string, unknown>): boolean {
if (!isJson(property)) {
return false;
}
for (const key in property) {
if (Object.prototype.hasOwnProperty.call(property, key)) {
return true;
}
}
return false;
}
/**
* Is property a JSON?
*/
export function isJson(property: unknown): boolean {
const record = property as Record<string, unknown> | null | undefined;
return (
typeof record !== 'undefined' &&
record !== null &&
(record.constructor === {}.constructor || record.constructor === [].constructor)
);
}
/**
* A helper to build a Snowplow request string from an
* an optional initial value plus a set of individual
* name-value pairs, provided using the add method.
*
* @param base64Encode Whether or not JSONs should be Base64-URL-safe-encoded
*
* @return The request string builder, with add, addRaw and build methods
*/
export function payloadBuilder(base64Encode: boolean): PayloadData {
const dict: PayloadDictionary = {};
const add = (key: string, value?: unknown): void => {
if (value != null && value !== '') {
// null also checks undefined
dict[key] = value;
}
};
const addDict = (dict: PayloadDictionary): void => {
for (const key in dict) {
if (Object.prototype.hasOwnProperty.call(dict, key)) {
add(key, dict[key]);
}
}
};
const addJson = (keyIfEncoded: string, keyIfNotEncoded: string, json?: Record<string, unknown>): void => {
if (json && isNonEmptyJson(json)) {
const str = JSON.stringify(json);
if (base64Encode) {
add(keyIfEncoded, base64urlencode(str));
} else {
add(keyIfNotEncoded, str);
}
}
};
const build = (): PayloadDictionary => {
return dict;
};
return {
add,
addDict,
addJson,
build,
};
}