noibu-react-native 0.0.3 → 0.0.6
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 +27 -7
- package/dist/api/clientConfig.d.ts +101 -0
- package/dist/api/clientConfig.js +315 -387
- package/dist/api/helpCode.js +2 -2
- package/dist/api/inputManager.js +3 -9
- package/dist/api/metroplexSocket.js +6 -31
- package/dist/api/storedPageVisit.js +3 -3
- package/dist/constants.d.ts +7 -40
- package/dist/constants.js +8 -65
- package/dist/entry/index.d.ts +2 -3
- package/dist/entry/index.js +1 -9
- package/dist/entry/init.d.ts +5 -0
- package/dist/entry/init.js +54 -69
- package/dist/monitors/clickMonitor.js +9 -56
- package/dist/monitors/errorMonitor.js +4 -2
- package/dist/monitors/gqlErrorValidator.js +3 -3
- package/dist/monitors/httpDataBundler.js +10 -10
- package/dist/monitors/requestMonitor.js +8 -8
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +4 -4
- package/dist/storage/storage.d.ts +3 -2
- package/dist/storage/storageProvider.d.ts +6 -5
- package/dist/types/Config.d.ts +27 -0
- package/dist/types/PageVisit.d.ts +22 -0
- package/dist/types/ReactNative.d.ts +3 -0
- package/dist/types/Storage.d.ts +14 -0
- package/dist/types/globals.d.ts +34 -0
- package/dist/utils/date.js +2 -2
- package/dist/utils/eventlistener.js +3 -3
- package/dist/utils/function.d.ts +100 -0
- package/dist/utils/function.js +208 -312
- package/dist/utils/stacktrace-parser.d.ts +6 -8
- package/dist/utils/stacktrace-parser.js +5 -5
- package/package.json +2 -1
- package/dist/monitors/elementMonitor.js +0 -177
package/dist/utils/function.js
CHANGED
|
@@ -1,39 +1,31 @@
|
|
|
1
1
|
import DeviceInfo from 'react-native-device-info';
|
|
2
2
|
import { getLocales } from 'react-native-localize';
|
|
3
3
|
import { parseStack } from './stacktrace-parser.js';
|
|
4
|
-
import { MAX_BEACON_PAYLOAD_SIZE, MAX_STRING_LENGTH, REQUIRED_DATA_PROCESSING_URLS,
|
|
4
|
+
import { MAX_BEACON_PAYLOAD_SIZE, MAX_STRING_LENGTH, REQUIRED_DATA_PROCESSING_URLS, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
|
|
5
5
|
import ClientConfig from '../api/clientConfig.js';
|
|
6
6
|
|
|
7
7
|
/** @module Functions */
|
|
8
|
-
|
|
9
8
|
/**
|
|
10
9
|
* Returns a stack trace frame with default filed values
|
|
11
10
|
*/
|
|
12
11
|
const getDefaultFrame = () => ({
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
12
|
+
line: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
13
|
+
mname: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
14
|
+
file: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
16
15
|
});
|
|
17
|
-
|
|
18
16
|
/**
|
|
19
|
-
*
|
|
20
17
|
* returns a string that satisfies a max length
|
|
21
18
|
* stringToVerify: string that needs to be verified
|
|
22
19
|
* length :optional, max length that stringToVerify can be
|
|
23
|
-
* @param stringToVerify
|
|
24
|
-
* @param length
|
|
25
20
|
*/
|
|
26
|
-
function getMaxSubstringAllowed(
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
if (stringToVerify.length < length) return stringToVerify;
|
|
34
|
-
return stringToVerify.substring(0, length);
|
|
21
|
+
function getMaxSubstringAllowed(stringToVerify, length = MAX_STRING_LENGTH) {
|
|
22
|
+
if (!stringToVerify) {
|
|
23
|
+
return stringToVerify;
|
|
24
|
+
}
|
|
25
|
+
if (stringToVerify.length < length)
|
|
26
|
+
return stringToVerify;
|
|
27
|
+
return stringToVerify.substring(0, length);
|
|
35
28
|
}
|
|
36
|
-
|
|
37
29
|
/**
|
|
38
30
|
*
|
|
39
31
|
* todo implement navigation
|
|
@@ -41,138 +33,98 @@ function getMaxSubstringAllowed(
|
|
|
41
33
|
* @returns {string}
|
|
42
34
|
*/
|
|
43
35
|
function getProperGlobalUrl() {
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
36
|
+
const globalUrl = new URL('https://localhost');
|
|
37
|
+
globalUrl.hostname = ClientConfig.getInstance().customerDomain;
|
|
38
|
+
return getMaxSubstringAllowed(globalUrl.toString());
|
|
47
39
|
}
|
|
48
|
-
|
|
49
40
|
/**
|
|
50
41
|
* Processes the raw stack frames and creates a readable stack in a safe manner
|
|
51
42
|
* @param {StackFrame[]} rawFrames
|
|
52
43
|
*/
|
|
53
44
|
function processFrames(rawFrames) {
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
)
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
if (
|
|
75
|
-
frame[JS_STACK_FILE_ATT_NAME] &&
|
|
76
|
-
frame[JS_STACK_FILE_ATT_NAME] !== '<unknown>'
|
|
77
|
-
) {
|
|
78
|
-
processedFrame[JS_STACK_FILE_ATT_NAME] = String(
|
|
79
|
-
frame[JS_STACK_FILE_ATT_NAME],
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
if (frame[JS_STACK_COL_ATT_NAME]) {
|
|
84
|
-
if (Number.isInteger(frame[JS_STACK_COL_ATT_NAME])) {
|
|
85
|
-
processedFrame[JS_STACK_COL_ATT_NAME] = frame[JS_STACK_COL_ATT_NAME];
|
|
86
|
-
}
|
|
87
|
-
}
|
|
88
|
-
|
|
89
|
-
return processedFrame;
|
|
90
|
-
});
|
|
45
|
+
return rawFrames.map(frame => {
|
|
46
|
+
const processedFrame = getDefaultFrame();
|
|
47
|
+
if (frame.line) {
|
|
48
|
+
if (Number.isInteger(frame.line)) {
|
|
49
|
+
processedFrame.line = String(frame.line);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
52
|
+
if (frame.mname && frame.mname !== '<unknown>') {
|
|
53
|
+
processedFrame.mname = String(frame.mname);
|
|
54
|
+
}
|
|
55
|
+
if (frame.file && frame.file !== '<unknown>') {
|
|
56
|
+
processedFrame.file = String(frame.file);
|
|
57
|
+
}
|
|
58
|
+
if (frame.column) {
|
|
59
|
+
if (Number.isInteger(frame.column)) {
|
|
60
|
+
processedFrame.column = frame.column;
|
|
61
|
+
}
|
|
62
|
+
}
|
|
63
|
+
return processedFrame;
|
|
64
|
+
});
|
|
91
65
|
}
|
|
92
|
-
|
|
93
66
|
/**
|
|
94
67
|
* Retrieves the javascript stack and message from an error event object
|
|
95
68
|
* @param errObj error to extract stack from
|
|
96
69
|
*/
|
|
97
70
|
function getJSStack(errObj) {
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
};
|
|
113
|
-
}
|
|
114
|
-
|
|
115
|
-
// If there is no stack field present then try to read the single file/line/column values
|
|
116
|
-
if (!errObj.stack) {
|
|
117
|
-
if (errObj.fileName && typeof errObj.fileName === 'string') {
|
|
118
|
-
frames[0][JS_STACK_FILE_ATT_NAME] = errObj.fileName;
|
|
71
|
+
let frames = [
|
|
72
|
+
{
|
|
73
|
+
line: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
74
|
+
mname: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
75
|
+
file: DEFAULT_STACK_FRAME_FIELD_VALUE,
|
|
76
|
+
},
|
|
77
|
+
];
|
|
78
|
+
// if the errObj type is not an object or null
|
|
79
|
+
// return a default frame
|
|
80
|
+
if (typeof errObj !== 'object' || !errObj) {
|
|
81
|
+
return {
|
|
82
|
+
frames,
|
|
83
|
+
msg: '',
|
|
84
|
+
};
|
|
119
85
|
}
|
|
120
|
-
if (errObj.lineNumber) {
|
|
121
|
-
frames[0][JS_STACK_LINE_ATT_NAME] = String(errObj.lineNumber);
|
|
122
|
-
}
|
|
123
|
-
if (errObj.columnNumber && Number.isInteger(errObj.columnNumber)) {
|
|
124
|
-
frames[0][JS_STACK_COL_ATT_NAME] = errObj.columnNumber;
|
|
125
|
-
}
|
|
126
|
-
} else {
|
|
127
86
|
frames = processFrames(parseStack(errObj.stack));
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
const msg = errObj.message ? getMaxSubstringAllowed(errObj.message) : '';
|
|
135
|
-
return {
|
|
136
|
-
[JS_STACK_FRAMES_ATT_NAME]: frames,
|
|
137
|
-
[JS_STACK_MESSAGE_ATT_NAME]: msg,
|
|
138
|
-
};
|
|
87
|
+
const msg = errObj.message ? getMaxSubstringAllowed(errObj.message) : '';
|
|
88
|
+
return {
|
|
89
|
+
frames,
|
|
90
|
+
msg,
|
|
91
|
+
};
|
|
139
92
|
}
|
|
140
|
-
|
|
141
93
|
/**
|
|
142
|
-
*
|
|
143
|
-
* @returns {boolean}
|
|
94
|
+
* Checks if possiblyStacktrace has any stack frames present
|
|
144
95
|
*/
|
|
145
96
|
function isStackTrace(possiblyStacktrace) {
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
97
|
+
try {
|
|
98
|
+
// todo disable temporary
|
|
99
|
+
// return parseStack(possiblyStacktrace).length > 0;
|
|
100
|
+
return false;
|
|
101
|
+
}
|
|
102
|
+
catch (e) {
|
|
103
|
+
return false;
|
|
104
|
+
}
|
|
151
105
|
}
|
|
152
|
-
|
|
153
106
|
/**
|
|
154
|
-
*
|
|
155
|
-
*
|
|
107
|
+
* Stringify function that is aware of inner circular references and handles them by replacing with {} (empty object)
|
|
108
|
+
* taken from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Errors/Cyclic_object_value
|
|
156
109
|
*/
|
|
157
110
|
function stringifyJSON(jsonObject) {
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
111
|
+
const ancestors = [];
|
|
112
|
+
return JSON.stringify(jsonObject, function (k, v) {
|
|
113
|
+
if (typeof v !== 'object' || v === null) {
|
|
114
|
+
return v;
|
|
115
|
+
}
|
|
116
|
+
// `this` is the object that value is contained in,
|
|
117
|
+
// i.e., its direct parent.
|
|
118
|
+
while (ancestors.length > 0 && ancestors[ancestors.length - 1] !== this) {
|
|
119
|
+
ancestors.pop();
|
|
120
|
+
}
|
|
121
|
+
if (ancestors.includes(v)) {
|
|
122
|
+
return {};
|
|
123
|
+
}
|
|
124
|
+
ancestors.push(v);
|
|
125
|
+
return v;
|
|
126
|
+
});
|
|
174
127
|
}
|
|
175
|
-
|
|
176
128
|
/**
|
|
177
129
|
* Wrapper for a request, since we have to do some special handling
|
|
178
130
|
* @param method
|
|
@@ -182,244 +134,188 @@ function stringifyJSON(jsonObject) {
|
|
|
182
134
|
* @param timeout
|
|
183
135
|
* @param sendAndForget
|
|
184
136
|
*/
|
|
185
|
-
async function makeRequest(
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
timeout,
|
|
191
|
-
sendAndForget,
|
|
192
|
-
) {
|
|
193
|
-
const ua = Object.keys(headers).findLast(
|
|
194
|
-
k => k.toLowerCase() === 'user-agent',
|
|
195
|
-
);
|
|
196
|
-
const headersWithUa = { ...headers };
|
|
197
|
-
if (!headers[ua]) {
|
|
198
|
-
headersWithUa['User-Agent'] = await getUserAgent();
|
|
199
|
-
}
|
|
200
|
-
|
|
201
|
-
// a send-and-forget request is made by using the beacon API (fetch + keepalive)
|
|
202
|
-
if (sendAndForget) {
|
|
203
|
-
const stringData = stringifyJSON(data);
|
|
204
|
-
const currentPayloadSize = new Blob([stringData]).size;
|
|
205
|
-
// if we have a large object or fetch is not available, we skip sending the message
|
|
206
|
-
if (!global.fetch || currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
|
|
207
|
-
return new Promise(resolve => {
|
|
208
|
-
resolve();
|
|
209
|
-
});
|
|
137
|
+
async function makeRequest(method, url, data, headers, timeout, sendAndForget) {
|
|
138
|
+
const ua = Object.keys(headers).findLast(k => k.toLowerCase() === 'user-agent');
|
|
139
|
+
const headersWithUa = { ...headers };
|
|
140
|
+
if (!headers[ua]) {
|
|
141
|
+
headersWithUa['User-Agent'] = await getUserAgent();
|
|
210
142
|
}
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
xhr.setRequestHeader(header, headers[header]);
|
|
227
|
-
});
|
|
228
|
-
|
|
229
|
-
xhr.onload = () => {
|
|
230
|
-
if (xhr.status >= 200 && xhr.status < 300) {
|
|
231
|
-
resolve(xhr.response);
|
|
232
|
-
} else {
|
|
233
|
-
reject(new Error(`Custom Request failed: ${xhr.statusText}`));
|
|
234
|
-
}
|
|
235
|
-
};
|
|
236
|
-
xhr.onerror = () => {
|
|
237
|
-
reject(new Error(`Custom Request failed: ${xhr.statusText}`));
|
|
238
|
-
};
|
|
239
|
-
if (data) {
|
|
240
|
-
xhr.send(stringifyJSON(data));
|
|
241
|
-
} else {
|
|
242
|
-
xhr.send();
|
|
143
|
+
// a send-and-forget request is made by using the beacon API (fetch + keepalive)
|
|
144
|
+
if (sendAndForget) {
|
|
145
|
+
const stringData = stringifyJSON(data);
|
|
146
|
+
const currentPayloadSize = new Blob([stringData]).size;
|
|
147
|
+
// if we have a large object or fetch is not available, we skip sending the message
|
|
148
|
+
if (currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
|
|
149
|
+
return Promise.resolve();
|
|
150
|
+
}
|
|
151
|
+
return fetch(url, {
|
|
152
|
+
method: 'POST',
|
|
153
|
+
headers: headersWithUa,
|
|
154
|
+
body: stringifyJSON(data),
|
|
155
|
+
// keep alive outlives the current page, its the same as beacon
|
|
156
|
+
keepalive: true,
|
|
157
|
+
});
|
|
243
158
|
}
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
159
|
+
return new Promise((resolve, reject) => {
|
|
160
|
+
const xhr = new XMLHttpRequest();
|
|
161
|
+
xhr.open(method, url);
|
|
162
|
+
xhr.timeout = timeout;
|
|
163
|
+
Object.keys(headersWithUa).forEach(header => {
|
|
164
|
+
xhr.setRequestHeader(header, headers[header]);
|
|
165
|
+
});
|
|
166
|
+
xhr.onload = () => {
|
|
167
|
+
if (xhr.status >= 200 && xhr.status < 300) {
|
|
168
|
+
resolve(xhr.response);
|
|
169
|
+
}
|
|
170
|
+
else {
|
|
171
|
+
reject(new Error(`Custom Request failed: ${xhr.statusText}`));
|
|
172
|
+
}
|
|
173
|
+
};
|
|
174
|
+
xhr.onerror = () => {
|
|
175
|
+
reject(new Error(`Custom Request failed: ${xhr.statusText}`));
|
|
176
|
+
};
|
|
177
|
+
if (data) {
|
|
178
|
+
xhr.send(stringifyJSON(data));
|
|
179
|
+
}
|
|
180
|
+
else {
|
|
181
|
+
xhr.send();
|
|
182
|
+
}
|
|
183
|
+
});
|
|
254
184
|
}
|
|
255
|
-
|
|
256
185
|
/** checks if http data collection is enabled */
|
|
257
186
|
function checkHttpDataCollectionEnabled() {
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
}
|
|
262
|
-
|
|
263
|
-
/** determines if we have received the http allowed urls */
|
|
264
|
-
function checkHttpPayloadAllowedURLsExistence() {
|
|
265
|
-
const noibuConfig = NOIBUJS_CONFIG();
|
|
266
|
-
return (
|
|
267
|
-
noibuConfig[HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME] &&
|
|
268
|
-
Array.isArray(noibuConfig[HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME])
|
|
269
|
-
);
|
|
187
|
+
const noibuConfig = ClientConfig.getInstance();
|
|
188
|
+
// Just a boolean, so safe to return truthiness. If undefined, will return false.
|
|
189
|
+
return !!noibuConfig.enableHttpDataCollection;
|
|
270
190
|
}
|
|
271
|
-
|
|
272
191
|
/** gets http data payload allowed URLs */
|
|
273
192
|
function getHttpPayloadAllowedURLs() {
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
193
|
+
const noibuConfig = ClientConfig.getInstance();
|
|
194
|
+
// return the allowed list or an empty list
|
|
195
|
+
if (noibuConfig.listOfUrlsToCollectHttpDataFrom &&
|
|
196
|
+
Array.isArray(noibuConfig.listOfUrlsToCollectHttpDataFrom)) {
|
|
197
|
+
return noibuConfig.listOfUrlsToCollectHttpDataFrom;
|
|
198
|
+
}
|
|
199
|
+
return [];
|
|
280
200
|
}
|
|
281
201
|
/**
|
|
282
|
-
* Gets
|
|
202
|
+
* Gets selectors to prevent those elements from being recorded
|
|
283
203
|
*/
|
|
284
|
-
function
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
// selecting everything after and including the element at index 1
|
|
292
|
-
blockedCSS.push(sel.substring(1));
|
|
293
|
-
}
|
|
294
|
-
});
|
|
295
|
-
}
|
|
296
|
-
return blockedCSS;
|
|
204
|
+
function getBlockedElements() {
|
|
205
|
+
const selectors = ClientConfig.getInstance().blockedElements;
|
|
206
|
+
const blockedElements = ['noibu-blocked'];
|
|
207
|
+
if (selectors && Array.isArray(selectors)) {
|
|
208
|
+
blockedElements.push(...selectors);
|
|
209
|
+
}
|
|
210
|
+
return blockedElements;
|
|
297
211
|
}
|
|
298
212
|
/**
|
|
299
213
|
* makes sure the url sent is a valid URL
|
|
300
|
-
* @param {} string url to be validated
|
|
301
214
|
*/
|
|
302
|
-
function isValidURL(
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
215
|
+
function isValidURL(str) {
|
|
216
|
+
try {
|
|
217
|
+
return !!new URL(str);
|
|
218
|
+
}
|
|
219
|
+
catch (_) {
|
|
220
|
+
return false;
|
|
221
|
+
}
|
|
309
222
|
}
|
|
310
|
-
|
|
311
223
|
let userAgentCache = '';
|
|
312
|
-
|
|
313
224
|
/**
|
|
314
225
|
* Because of the nature of user agent in react native, we have to make this async.
|
|
315
226
|
* But I promise, this is really fast, since we memoize the result for the whole session :)
|
|
316
227
|
* @returns {Promise<string>}
|
|
317
228
|
*/
|
|
318
229
|
async function getUserAgent() {
|
|
319
|
-
|
|
230
|
+
if (userAgentCache) {
|
|
231
|
+
return userAgentCache;
|
|
232
|
+
}
|
|
233
|
+
userAgentCache = await DeviceInfo.getUserAgent();
|
|
320
234
|
return userAgentCache;
|
|
321
|
-
}
|
|
322
|
-
userAgentCache = await DeviceInfo.getUserAgent();
|
|
323
|
-
return userAgentCache;
|
|
324
235
|
}
|
|
325
|
-
|
|
326
236
|
/**
|
|
327
237
|
* isInvalidURLConfig will verify that Collect is being initializes with
|
|
328
238
|
* the correct env vars.
|
|
329
|
-
* @param {Noibu.UrlConfig} urlConfig
|
|
330
239
|
*/
|
|
331
|
-
function isInvalidURLConfig(
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
240
|
+
function isInvalidURLConfig(urls) {
|
|
241
|
+
for (let i = 0; i < REQUIRED_DATA_PROCESSING_URLS.length; i += 1) {
|
|
242
|
+
const u = REQUIRED_DATA_PROCESSING_URLS[i];
|
|
243
|
+
if (!urls[u]) {
|
|
244
|
+
return true;
|
|
245
|
+
}
|
|
336
246
|
}
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
return false;
|
|
247
|
+
return false;
|
|
340
248
|
}
|
|
341
|
-
|
|
342
249
|
/**
|
|
343
250
|
* isNoibuJSAlreadyLoaded will verify if there are already other
|
|
344
251
|
* copies of NoibuJS runnung
|
|
345
252
|
*/
|
|
346
253
|
function isNoibuJSAlreadyLoaded() {
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
254
|
+
// check if the global variable exists and its value
|
|
255
|
+
const loaded = window.noibuJSLoaded !== undefined;
|
|
256
|
+
// set the variable so future copies of the script
|
|
257
|
+
// will know this instance is running
|
|
258
|
+
window.noibuJSLoaded = true;
|
|
259
|
+
return loaded;
|
|
353
260
|
}
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
* @param {} obj
|
|
261
|
+
/**
|
|
262
|
+
* asString will create a string out of anything passed to it.
|
|
357
263
|
*/
|
|
358
264
|
function asString(obj) {
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
return String(obj);
|
|
265
|
+
if (!obj) {
|
|
266
|
+
return '';
|
|
267
|
+
}
|
|
268
|
+
// we've seen the url be an object in some cases
|
|
269
|
+
// we would still like to send those to our backend in the case
|
|
270
|
+
// that this is an issue and needs to be queried
|
|
271
|
+
if (typeof obj === 'object') {
|
|
272
|
+
return stringifyJSON(obj);
|
|
273
|
+
}
|
|
274
|
+
return String(obj);
|
|
370
275
|
}
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
* @param {} text
|
|
276
|
+
/**
|
|
277
|
+
* masks textual content if it ressembles something sensitive
|
|
374
278
|
*/
|
|
375
279
|
function maskTextInput(text) {
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
280
|
+
// if it has an email or digit(s), we mask the text
|
|
281
|
+
return text
|
|
282
|
+
.replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING)
|
|
283
|
+
.replace(PII_DIGIT_PATTERN, '*');
|
|
380
284
|
}
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
* @param {} realOnURL
|
|
285
|
+
/**
|
|
286
|
+
* gets the onURL of a string, defaulting to the location of the webpage
|
|
384
287
|
*/
|
|
385
288
|
function getOnURL(realOnURL) {
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
return onURL;
|
|
289
|
+
let onURL = getProperGlobalUrl();
|
|
290
|
+
if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
|
|
291
|
+
onURL = asString(getMaxSubstringAllowed(realOnURL));
|
|
292
|
+
}
|
|
293
|
+
return onURL;
|
|
393
294
|
}
|
|
394
|
-
|
|
395
295
|
/** gets the user language from the browser */
|
|
396
296
|
function getUserLanguage() {
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
return lang.toLowerCase();
|
|
297
|
+
const locales = getLocales();
|
|
298
|
+
if (!locales.length) {
|
|
299
|
+
return null;
|
|
300
|
+
}
|
|
301
|
+
const lang = locales[0].languageCode;
|
|
302
|
+
if (lang === '' || !lang) {
|
|
303
|
+
return null;
|
|
304
|
+
}
|
|
305
|
+
return lang.toLowerCase();
|
|
408
306
|
}
|
|
409
|
-
|
|
410
307
|
/**
|
|
411
308
|
* Checks if the provided object is an instance of the specified type.
|
|
412
309
|
* It's safer than `instanceof` operator as it handles cases
|
|
413
310
|
* where type is not actually a type but an object.
|
|
414
|
-
* @param {any} instance
|
|
415
|
-
* @param {any} type
|
|
416
311
|
*/
|
|
417
312
|
function isInstanceOf(instance, type) {
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
313
|
+
try {
|
|
314
|
+
return typeof type === 'function' && instance instanceof type;
|
|
315
|
+
}
|
|
316
|
+
catch (e) {
|
|
317
|
+
return false;
|
|
318
|
+
}
|
|
423
319
|
}
|
|
424
320
|
|
|
425
|
-
export { asString, checkHttpDataCollectionEnabled,
|
|
321
|
+
export { asString, checkHttpDataCollectionEnabled, getBlockedElements, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getProperGlobalUrl, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
|
|
@@ -1,9 +1,7 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
[JS_STACK_METHOD_ATT_NAME]: string;
|
|
1
|
+
export declare interface RawStackFrame {
|
|
2
|
+
file: string;
|
|
3
|
+
line?: number;
|
|
4
|
+
column?: number;
|
|
5
|
+
mname: string;
|
|
7
6
|
}
|
|
8
|
-
export declare function parseStack(stackString: string):
|
|
9
|
-
export {};
|
|
7
|
+
export declare function parseStack(stackString: string): RawStackFrame[];
|