noibu-react-native 0.0.8 → 0.0.9
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/dist/api/clientConfig.d.ts +7 -2
- package/dist/api/clientConfig.js +35 -17
- package/dist/api/helpCode.js +5 -11
- package/dist/api/metroplexSocket.js +11 -5
- package/dist/api/storedMetrics.js +1 -2
- package/dist/api/storedPageVisit.js +2 -3
- package/dist/constants.d.ts +1 -4
- package/dist/constants.js +3 -5
- package/dist/entry/init.js +5 -5
- package/dist/monitors/{AppNavigationMonitor.d.ts → appNavigationMonitor.d.ts} +4 -5
- package/dist/monitors/{AppNavigationMonitor.js → appNavigationMonitor.js} +13 -24
- package/dist/monitors/clickMonitor.js +17 -2
- package/dist/monitors/httpDataBundler.js +18 -5
- package/dist/monitors/inputMonitor.js +2 -2
- package/dist/monitors/integrations/react-native-navigation-integration.d.ts +2 -1
- package/dist/monitors/integrations/react-native-navigation-integration.js +4 -2
- package/dist/monitors/requestMonitor.js +1 -3
- package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +15 -5
- package/dist/utils/function.d.ts +0 -12
- package/dist/utils/function.js +2 -40
- package/package.json +2 -2
|
@@ -11,11 +11,12 @@ export default class ClientConfig {
|
|
|
11
11
|
private browserId;
|
|
12
12
|
private pageVisitSeq;
|
|
13
13
|
private lastActiveTime;
|
|
14
|
-
private noibuErrorURL;
|
|
14
|
+
private readonly noibuErrorURL;
|
|
15
15
|
private cltErrorPostCounter;
|
|
16
16
|
private readonly maxSocketInactiveTime;
|
|
17
|
+
private locationBreadcrumbs;
|
|
17
18
|
private static instance;
|
|
18
|
-
|
|
19
|
+
static noibuErrorURL: string;
|
|
19
20
|
customerDomain: string;
|
|
20
21
|
isClientDisabled: boolean;
|
|
21
22
|
readonly listOfUrlsToCollectHttpDataFrom: CustomerConfig['listOfUrlsToCollectHttpDataFrom'];
|
|
@@ -88,6 +89,10 @@ export default class ClientConfig {
|
|
|
88
89
|
* @param {} data the data to be stored
|
|
89
90
|
*/
|
|
90
91
|
_storeBrowserData(data: StoredConfig): Promise<StoredConfig>;
|
|
92
|
+
/** sets current breadcrumbs to be reconstructed into global url */
|
|
93
|
+
set currentLocationBreadcrumbs(newValue: typeof this.locationBreadcrumbs);
|
|
94
|
+
/** gets current global url */
|
|
95
|
+
get globalUrl(): string;
|
|
91
96
|
/**
|
|
92
97
|
* postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
|
|
93
98
|
* and disable the client if required
|
package/dist/api/clientConfig.js
CHANGED
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
2
|
import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, SEVERITY, NOIBU_BROWSER_ID_KYWRD, PV_SEQ_NUM_RESET_TIME_MINUTES, JS_ENV, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
|
|
3
|
-
import { stringifyJSON,
|
|
3
|
+
import { stringifyJSON, getMaxSubstringAllowed, getUserAgent, makeRequest } from '../utils/function.js';
|
|
4
4
|
import Storage from '../storage/storage.js';
|
|
5
|
-
import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
|
|
6
5
|
|
|
7
6
|
/** @module ClientConfig */
|
|
8
7
|
/**
|
|
@@ -19,6 +18,7 @@ class ClientConfig {
|
|
|
19
18
|
noibuErrorURL;
|
|
20
19
|
cltErrorPostCounter;
|
|
21
20
|
maxSocketInactiveTime;
|
|
21
|
+
locationBreadcrumbs = [];
|
|
22
22
|
static instance;
|
|
23
23
|
static noibuErrorURL;
|
|
24
24
|
customerDomain;
|
|
@@ -61,9 +61,8 @@ class ClientConfig {
|
|
|
61
61
|
// Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
|
|
62
62
|
// configured properly and throws an error.
|
|
63
63
|
// This will ensure we get the expected error POST request at the correct URL.
|
|
64
|
-
|
|
64
|
+
ClientConfig.noibuErrorURL = noibuErrorURL;
|
|
65
65
|
this.instance = new ClientConfig(noibuErrorURL, customerConfig);
|
|
66
|
-
this.instance.noibuErrorURL = noibuErrorURL;
|
|
67
66
|
}
|
|
68
67
|
}
|
|
69
68
|
/**
|
|
@@ -271,6 +270,22 @@ class ClientConfig {
|
|
|
271
270
|
return this._generateNewBrowserData();
|
|
272
271
|
}
|
|
273
272
|
}
|
|
273
|
+
/** sets current breadcrumbs to be reconstructed into global url */
|
|
274
|
+
set currentLocationBreadcrumbs(newValue) {
|
|
275
|
+
if (!Array.isArray(newValue)) {
|
|
276
|
+
return;
|
|
277
|
+
}
|
|
278
|
+
this.locationBreadcrumbs = newValue.slice();
|
|
279
|
+
}
|
|
280
|
+
/** gets current global url */
|
|
281
|
+
get globalUrl() {
|
|
282
|
+
const globalUrl = new URL('https://localhost');
|
|
283
|
+
globalUrl.hostname = ClientConfig.getInstance().customerDomain;
|
|
284
|
+
if (this.locationBreadcrumbs.length) {
|
|
285
|
+
globalUrl.pathname = this.locationBreadcrumbs.join('/');
|
|
286
|
+
}
|
|
287
|
+
return getMaxSubstringAllowed(globalUrl.toString());
|
|
288
|
+
}
|
|
274
289
|
/**
|
|
275
290
|
* postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
|
|
276
291
|
* and disable the client if required
|
|
@@ -287,7 +302,13 @@ class ClientConfig {
|
|
|
287
302
|
// don't log warning messages by default, as a cost savings
|
|
288
303
|
return;
|
|
289
304
|
}
|
|
290
|
-
|
|
305
|
+
const collectError = {
|
|
306
|
+
browserId: this.browserId || '',
|
|
307
|
+
pageVisitId: this.pageVisitId,
|
|
308
|
+
scriptId: GET_SCRIPT_ID(),
|
|
309
|
+
ua: await getUserAgent(),
|
|
310
|
+
error: errorMsg,
|
|
311
|
+
};
|
|
291
312
|
// if the page visits sends more errors than the
|
|
292
313
|
// allowed threshold we disable the client
|
|
293
314
|
if (this.cltErrorPostCounter >= MAX_COLLECT_ERROR_LOG) {
|
|
@@ -302,20 +323,22 @@ class ClientConfig {
|
|
|
302
323
|
this.isClientDisabled = true;
|
|
303
324
|
// end of lock
|
|
304
325
|
// overriding the message to be an alert that we are shutting collect off.
|
|
305
|
-
|
|
306
|
-
'Shutting collect off, we reached the ' +
|
|
307
|
-
'maximum limit of collect errors sent.';
|
|
326
|
+
collectError.error = `Shutting collect off, we reached the maximum limit of collect errors sent.`;
|
|
308
327
|
}
|
|
309
328
|
const errorContent = {
|
|
310
|
-
url:
|
|
311
|
-
err_msg:
|
|
329
|
+
url: this.globalUrl,
|
|
330
|
+
err_msg: collectError,
|
|
312
331
|
sev: severity,
|
|
313
332
|
};
|
|
314
333
|
const headers = {
|
|
315
334
|
'content-type': 'application/json',
|
|
316
|
-
'User-Agent': await getUserAgent(),
|
|
317
335
|
};
|
|
318
|
-
if (keepAlive) {
|
|
336
|
+
if (!keepAlive) {
|
|
337
|
+
makeRequest('POST', this.noibuErrorURL, errorContent, headers, 2000, false).catch(() => {
|
|
338
|
+
// we do nothing and let this error silently fail
|
|
339
|
+
});
|
|
340
|
+
}
|
|
341
|
+
else {
|
|
319
342
|
fetch(this.noibuErrorURL, {
|
|
320
343
|
method: 'POST',
|
|
321
344
|
headers,
|
|
@@ -324,11 +347,6 @@ class ClientConfig {
|
|
|
324
347
|
keepalive: true,
|
|
325
348
|
});
|
|
326
349
|
}
|
|
327
|
-
else {
|
|
328
|
-
makeRequest('POST', this.noibuErrorURL, errorContent, headers, 2000, false).catch(() => {
|
|
329
|
-
// we do nothing and let this error silently fail
|
|
330
|
-
});
|
|
331
|
-
}
|
|
332
350
|
// only increment if this was an actual error, not a warning or otherwise
|
|
333
351
|
if (severity === SEVERITY.error) {
|
|
334
352
|
this.cltErrorPostCounter += 1;
|
package/dist/api/helpCode.js
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import MetroplexSocket from './metroplexSocket.js';
|
|
2
|
-
import { SEVERITY
|
|
2
|
+
import { SEVERITY } from '../constants.js';
|
|
3
3
|
import ClientConfig from './clientConfig.js';
|
|
4
4
|
|
|
5
5
|
/**
|
|
@@ -23,6 +23,7 @@ class HelpCode {
|
|
|
23
23
|
*/
|
|
24
24
|
constructor() {
|
|
25
25
|
this.requestContext = null;
|
|
26
|
+
this.receiveHelpCode = this.receiveHelpCode.bind(this);
|
|
26
27
|
}
|
|
27
28
|
|
|
28
29
|
/**
|
|
@@ -50,7 +51,9 @@ class HelpCode {
|
|
|
50
51
|
|
|
51
52
|
this.requestContext = context;
|
|
52
53
|
|
|
53
|
-
const result = await
|
|
54
|
+
const result = await MetroplexSocket.getInstance().requestHelpCode(
|
|
55
|
+
this.receiveHelpCode,
|
|
56
|
+
);
|
|
54
57
|
|
|
55
58
|
if (result === false) {
|
|
56
59
|
this.requestContext = null;
|
|
@@ -92,15 +95,6 @@ class HelpCode {
|
|
|
92
95
|
context.reject(new Error(data));
|
|
93
96
|
}
|
|
94
97
|
}
|
|
95
|
-
|
|
96
|
-
/**
|
|
97
|
-
* Sends metroplex request
|
|
98
|
-
*/
|
|
99
|
-
_sendRequest() {
|
|
100
|
-
return MetroplexSocket.getInstance().sendMessage(WORK_REQUEST_ATT_NAME, {
|
|
101
|
-
[WORK_REQUEST_ATT_NAME]: HELP_CODE_ATT_NAME,
|
|
102
|
-
});
|
|
103
|
-
}
|
|
104
98
|
}
|
|
105
99
|
|
|
106
100
|
export { HelpCode as default };
|
|
@@ -1,14 +1,12 @@
|
|
|
1
1
|
import uuid from 'react-native-uuid';
|
|
2
2
|
import { getUserAgent, stringifyJSON } from '../utils/function.js';
|
|
3
3
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
4
|
-
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, SEQ_NUM_ATT_NAME, WORK_REQUEST_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, MAX_METROPLEX_CONNECTION_COUNT, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, END_AT_ATT_NAME, SEVERITY, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, VER_ATT_NAME, CURRENT_PV_VERSION, PV_SEQ_ATT_NAME, ON_URL_ATT_NAME, REF_URL_ATT_NAME, STARTED_AT_ATT_NAME, CONN_COUNT_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, SCRIPT_ID_ATT_NAME, GET_SCRIPT_ID, SCRIPT_INSTANCE_ID_ATT_NAME, METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME, SOCKET_INSTANCE_ID_ATT_NAME
|
|
4
|
+
import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, SEQ_NUM_ATT_NAME, WORK_REQUEST_ATT_NAME, HELP_CODE_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, MAX_METROPLEX_CONNECTION_COUNT, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, END_AT_ATT_NAME, SEVERITY, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, VER_ATT_NAME, CURRENT_PV_VERSION, PV_SEQ_ATT_NAME, ON_URL_ATT_NAME, REF_URL_ATT_NAME, STARTED_AT_ATT_NAME, CONN_COUNT_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, SCRIPT_ID_ATT_NAME, GET_SCRIPT_ID, SCRIPT_INSTANCE_ID_ATT_NAME, METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME, SOCKET_INSTANCE_ID_ATT_NAME } from '../constants.js';
|
|
5
5
|
import ClientConfig from './clientConfig.js';
|
|
6
6
|
import StoredMetrics from './storedMetrics.js';
|
|
7
7
|
import StoredPageVisit from './storedPageVisit.js';
|
|
8
8
|
import { safePerformanceNow } from '../utils/performance.js';
|
|
9
9
|
import { isDateOverwritten } from '../utils/date.js';
|
|
10
|
-
import HelpCode from './helpCode.js';
|
|
11
|
-
import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
|
|
12
10
|
|
|
13
11
|
/** @module MetroplexSocket */
|
|
14
12
|
|
|
@@ -62,7 +60,7 @@ class MetroplexSocket {
|
|
|
62
60
|
// setting initial URL at the start in order to guarentee that the
|
|
63
61
|
// current page visit has the real initial onURL. Fragments and SPA's
|
|
64
62
|
// can change the URL without reloading the page.
|
|
65
|
-
this._initialURL =
|
|
63
|
+
this._initialURL = ClientConfig.getInstance().globalUrl;
|
|
66
64
|
this.initialReferingURL = '';
|
|
67
65
|
this.sessionTimestamp = new Date();
|
|
68
66
|
|
|
@@ -160,6 +158,14 @@ class MetroplexSocket {
|
|
|
160
158
|
this.messageSequenceNum += 1;
|
|
161
159
|
}
|
|
162
160
|
|
|
161
|
+
/** requests help code and saves a callback to be called on response */
|
|
162
|
+
requestHelpCode(cb) {
|
|
163
|
+
this.helpCodeCb = cb;
|
|
164
|
+
return MetroplexSocket.getInstance().sendMessage(WORK_REQUEST_ATT_NAME, {
|
|
165
|
+
[WORK_REQUEST_ATT_NAME]: HELP_CODE_ATT_NAME,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
|
|
163
169
|
/**
|
|
164
170
|
* Immediately sends a message to Metroplex over the web socket
|
|
165
171
|
* Queues the message if the connection isn't open yet.
|
|
@@ -831,7 +837,7 @@ class MetroplexSocket {
|
|
|
831
837
|
const data = response.substring(prefix.length);
|
|
832
838
|
const success = /^\d{6}$/.test(data);
|
|
833
839
|
|
|
834
|
-
|
|
840
|
+
this.helpCodeCb({ detail: { success, data } });
|
|
835
841
|
|
|
836
842
|
return true;
|
|
837
843
|
}
|
|
@@ -2,7 +2,6 @@ import { BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIB
|
|
|
2
2
|
import ClientConfig from './clientConfig.js';
|
|
3
3
|
import { getUserAgent, stringifyJSON } from '../utils/function.js';
|
|
4
4
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
5
|
-
import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
|
|
6
5
|
|
|
7
6
|
/** @module StoredMetrics */
|
|
8
7
|
|
|
@@ -180,7 +179,7 @@ class StoredMetrics {
|
|
|
180
179
|
[DID_START_VID_ATT_NAME]: this.didStartVideo,
|
|
181
180
|
[HTTP_COUNT_EXPECTED_ATT_NAME]: this.httpCount,
|
|
182
181
|
[ERR_COUNT_EXPECTED_ATT_NAME]: this.errCount,
|
|
183
|
-
[ON_URL_ATT_NAME]:
|
|
182
|
+
[ON_URL_ATT_NAME]: ClientConfig.getInstance().globalUrl,
|
|
184
183
|
};
|
|
185
184
|
global.fetch(GET_METROPLEX_METRICS_URL(), {
|
|
186
185
|
method: 'POST',
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, ERROR_EVENT_TYPE,
|
|
1
|
+
import { PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, ERROR_EVENT_TYPE, NOIBU_STORED_PAGE_VISIT, SEVERITY, MAX_METROPLEX_SOCKET_INNACTIVE_TIME, PAGE_VISIT_INFORMATION_ATT_NAME, PAGE_VISIT_VID_FRAG_ATT_NAME, IS_LAST_ATT_NAME, GET_METROPLEX_POST_URL } from '../constants.js';
|
|
2
2
|
import ClientConfig from './clientConfig.js';
|
|
3
3
|
import { stringifyJSON, makeRequest } from '../utils/function.js';
|
|
4
4
|
import Storage from '../storage/storage.js';
|
|
@@ -57,8 +57,7 @@ class StoredPageVisit {
|
|
|
57
57
|
// Any userstep is used rather than just mouse clicks because we shouldn't
|
|
58
58
|
// assume mouse clicks are the only way for any activity to happen
|
|
59
59
|
event[TYPE_ATT_NAME] === USERSTEP_EVENT_TYPE ||
|
|
60
|
-
event[TYPE_ATT_NAME] === ERROR_EVENT_TYPE
|
|
61
|
-
event[TYPE_ATT_NAME] === LOCATION_EVENT_TYPE,
|
|
60
|
+
event[TYPE_ATT_NAME] === ERROR_EVENT_TYPE,
|
|
62
61
|
);
|
|
63
62
|
|
|
64
63
|
// Only write the retry queue if it contains a user step or location change
|
package/dist/constants.d.ts
CHANGED
|
@@ -125,13 +125,11 @@ export declare const HTTP_EVENT_TYPE: "http";
|
|
|
125
125
|
export declare const JS_EVENT_TYPE: "js";
|
|
126
126
|
export declare const GQL_EVENT_TYPE: "gql";
|
|
127
127
|
export declare const USERSTEP_EVENT_TYPE: "userstep";
|
|
128
|
-
export declare const WEBVITAL_EVENT_TYPE: "wv";
|
|
129
128
|
export declare const CLICK_EVENT_TYPE: "click";
|
|
130
129
|
export declare const KEYBOARD_EVENT_TYPE: "kbd";
|
|
131
|
-
export declare const NAVIGATION_EVENT_TYPE: "navigation";
|
|
132
|
-
export declare const LOCATION_EVENT_TYPE: "loc";
|
|
133
130
|
export declare const ERROR_EVENT_TYPE: "err";
|
|
134
131
|
export declare const PAGE_EVENT_TYPE: "page";
|
|
132
|
+
export declare const APP_NAVIGATION_EVENT_TYPE = "app_nav";
|
|
135
133
|
export declare const PAGE_VISIT_INFORMATION_ATT_NAME: "pvi";
|
|
136
134
|
export declare const PAGE_VISIT_PART_ATT_NAME: "pvp";
|
|
137
135
|
export declare const PAGE_VISIT_VID_FRAG_ATT_NAME: "pvvf";
|
|
@@ -228,4 +226,3 @@ export declare function GET_METROPLEX_METRICS_URL(): string;
|
|
|
228
226
|
*/
|
|
229
227
|
export declare function JS_ENV(): string;
|
|
230
228
|
export declare const METROPLEX_RETRY_FREQUENCY: 30000;
|
|
231
|
-
export declare const CSS_URL_REGEX_STR: RegExp;
|
package/dist/constants.js
CHANGED
|
@@ -223,9 +223,9 @@ const GQL_EVENT_TYPE = 'gql';
|
|
|
223
223
|
const USERSTEP_EVENT_TYPE = 'userstep';
|
|
224
224
|
const CLICK_EVENT_TYPE = 'click';
|
|
225
225
|
const KEYBOARD_EVENT_TYPE = 'kbd';
|
|
226
|
-
const LOCATION_EVENT_TYPE = 'loc';
|
|
227
226
|
const ERROR_EVENT_TYPE = 'err';
|
|
228
227
|
const PAGE_EVENT_TYPE = 'page';
|
|
228
|
+
const APP_NAVIGATION_EVENT_TYPE = 'app_nav';
|
|
229
229
|
// complete page visit attributes
|
|
230
230
|
const PAGE_VISIT_INFORMATION_ATT_NAME = 'pvi';
|
|
231
231
|
const PAGE_VISIT_PART_ATT_NAME = 'pvp';
|
|
@@ -287,12 +287,10 @@ const PAGE_EVENTS_WINDOW = [
|
|
|
287
287
|
'pageshow',
|
|
288
288
|
'focus',
|
|
289
289
|
'blur',
|
|
290
|
-
// 'storage', // Disabled until compression is supported NOI-3998
|
|
291
290
|
'popstate',
|
|
292
291
|
'online',
|
|
293
292
|
'offline',
|
|
294
293
|
'messageerror',
|
|
295
|
-
// 'message', // Disabled until compression is supported NOI-3998
|
|
296
294
|
'languagechange',
|
|
297
295
|
'hashchange',
|
|
298
296
|
'beforeprint',
|
|
@@ -317,7 +315,7 @@ const CONTENT_LENGTH = 'content-length';
|
|
|
317
315
|
* Gets the script id from the cookie object, returns default if cannot be found
|
|
318
316
|
*/
|
|
319
317
|
function GET_SCRIPT_ID() {
|
|
320
|
-
return "1.0.104" ;
|
|
318
|
+
return "1.0.104-rn-sdk-0.0.9" ;
|
|
321
319
|
}
|
|
322
320
|
/**
|
|
323
321
|
*
|
|
@@ -426,4 +424,4 @@ function JS_ENV() {
|
|
|
426
424
|
// gets the frequency at which the client resends the message that were not confirmed by metroplex
|
|
427
425
|
const METROPLEX_RETRY_FREQUENCY = 30000;
|
|
428
426
|
|
|
429
|
-
export { BLOCKED_HTTP_HEADER_KEYS, BLOCK_SOCKET_MESSAGE, BROWSER_ID_ATT_NAME, CLICK_EVENT_TYPE, CLIENT_LOCK_TIME_MINUTES, CLOSE_CONNECTION_FORCEFULLY, COLLECT_VER_ATT_NAME, CONN_COUNT_ATT_NAME, CONSOLE_FUNCTION_OVERRIDES, CONTENT_LENGTH, CONTENT_TYPE, CSS_CLASS_ATT_NAME, CURRENT_METRICS_VERSION, CURRENT_NOIBUJS_VERSION, CURRENT_PV_VERSION, CUSTOM_ERROR_EVENT_TYPE, CUSTOM_ID_NAME_TYPE, CUSTOM_ID_VALUE_TYPE, DEFAULT_STACK_FRAME_FIELD_VALUE, DEFAULT_WEBSITE_SUBDOMAIN_PATTERN, DID_CUT_PV_ATT_NAME, DID_CUT_VID_ATT_NAME, DID_START_VID_ATT_NAME, END_AT_ATT_NAME, ERROR_EVENT_ERROR_TYPE, ERROR_EVENT_TYPE, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, ERROR_LOG_EVENT_ERROR_TYPE, ERROR_SOURCE_ATT_NAME, ERR_COUNT_EXPECTED_ATT_NAME, EVENT_ERROR_TYPE, EXP_VIDEO_LENGTH_ATT_NAME, FETCH_EXCEPTION_ERROR_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_BASE_HTTP_URL, GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, GET_METROPLEX_METRICS_URL, GET_METROPLEX_POST_URL, GET_SCRIPT_ID, GQL_ERROR_ATT_NAME, GQL_ERROR_TYPE, GQL_EVENT_TYPE, HELP_CODE_ATT_NAME, HTMLID_ATT_NAME, HTTP_BODY_DROPPED_LENGTH_MSG, HTTP_BODY_DROPPED_TYPE_MSG, HTTP_BODY_NULL_STRING, HTTP_CODE_ATT_NAME, HTTP_COUNT_EXPECTED_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, HTTP_DATA_PAYLOAD_ATT_NAME, HTTP_DATA_REQ_HEADERS_ATT_NAME, HTTP_DATA_RESP_HEADERS_ATT_NAME, HTTP_DATA_RESP_PAYLOAD_ATT_NAME, HTTP_EVENT_TYPE, HTTP_METHOD_ATT_NAME, HTTP_PII_BLOCKING_PATTERNS, HTTP_RESP_CODE_ATT_NAME, HTTP_RESP_LENGTH_ATT_NAME, HTTP_RESP_TIME_ATT_NAME, HUMAN_READABLE_CONTENT_TYPE_REGEX, IS_LAST_ATT_NAME, IS_NJS_VERSION_BETA, JS_ENV, JS_ERROR_ATT_NAME, JS_EVENT_TYPE, JS_STACK_FILE_ATT_NAME, JS_STACK_FRAMES_ATT_NAME, JS_STACK_MESSAGE_ATT_NAME, JS_STACK_METHOD_ATT_NAME, KEYBOARD_EVENT_TYPE,
|
|
427
|
+
export { APP_NAVIGATION_EVENT_TYPE, BLOCKED_HTTP_HEADER_KEYS, BLOCK_SOCKET_MESSAGE, BROWSER_ID_ATT_NAME, CLICK_EVENT_TYPE, CLIENT_LOCK_TIME_MINUTES, CLOSE_CONNECTION_FORCEFULLY, COLLECT_VER_ATT_NAME, CONN_COUNT_ATT_NAME, CONSOLE_FUNCTION_OVERRIDES, CONTENT_LENGTH, CONTENT_TYPE, CSS_CLASS_ATT_NAME, CURRENT_METRICS_VERSION, CURRENT_NOIBUJS_VERSION, CURRENT_PV_VERSION, CUSTOM_ERROR_EVENT_TYPE, CUSTOM_ID_NAME_TYPE, CUSTOM_ID_VALUE_TYPE, DEFAULT_STACK_FRAME_FIELD_VALUE, DEFAULT_WEBSITE_SUBDOMAIN_PATTERN, DID_CUT_PV_ATT_NAME, DID_CUT_VID_ATT_NAME, DID_START_VID_ATT_NAME, END_AT_ATT_NAME, ERROR_EVENT_ERROR_TYPE, ERROR_EVENT_TYPE, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, ERROR_LOG_EVENT_ERROR_TYPE, ERROR_SOURCE_ATT_NAME, ERR_COUNT_EXPECTED_ATT_NAME, EVENT_ERROR_TYPE, EXP_VIDEO_LENGTH_ATT_NAME, FETCH_EXCEPTION_ERROR_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_BASE_HTTP_URL, GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, GET_METROPLEX_METRICS_URL, GET_METROPLEX_POST_URL, GET_SCRIPT_ID, GQL_ERROR_ATT_NAME, GQL_ERROR_TYPE, GQL_EVENT_TYPE, HELP_CODE_ATT_NAME, HTMLID_ATT_NAME, HTTP_BODY_DROPPED_LENGTH_MSG, HTTP_BODY_DROPPED_TYPE_MSG, HTTP_BODY_NULL_STRING, HTTP_CODE_ATT_NAME, HTTP_COUNT_EXPECTED_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, HTTP_DATA_PAYLOAD_ATT_NAME, HTTP_DATA_REQ_HEADERS_ATT_NAME, HTTP_DATA_RESP_HEADERS_ATT_NAME, HTTP_DATA_RESP_PAYLOAD_ATT_NAME, HTTP_EVENT_TYPE, HTTP_METHOD_ATT_NAME, HTTP_PII_BLOCKING_PATTERNS, HTTP_RESP_CODE_ATT_NAME, HTTP_RESP_LENGTH_ATT_NAME, HTTP_RESP_TIME_ATT_NAME, HUMAN_READABLE_CONTENT_TYPE_REGEX, IS_LAST_ATT_NAME, IS_NJS_VERSION_BETA, JS_ENV, JS_ERROR_ATT_NAME, JS_EVENT_TYPE, JS_STACK_FILE_ATT_NAME, JS_STACK_FRAMES_ATT_NAME, JS_STACK_MESSAGE_ATT_NAME, JS_STACK_METHOD_ATT_NAME, KEYBOARD_EVENT_TYPE, MAX_BEACON_PAYLOAD_SIZE, MAX_COLLECT_ERROR_LOG, MAX_CUSTOM_ERRORS_PER_PAGEVISIT, MAX_CUSTOM_IDS_PER_PAGEVISIT, MAX_FRAMES_IN_ARRAY, MAX_HTTP_DATA_EVENT_COUNT, MAX_HTTP_DATA_PAYLOAD_LENGTH, MAX_METROPLEX_CONNECTION_COUNT, MAX_METROPLEX_SOCKET_INNACTIVE_TIME, MAX_PAGEVISIT_EVENTS, MAX_PAGEVISIT_PARTS, MAX_PAGEVISIT_VISITED, MAX_STRING_LENGTH, MAX_TIME_FOR_UNSENT_DATA_MILLIS, META_DATA_METROPLEX_TYPE, METROPLEX_ERROR_ROUTE, METROPLEX_FRAG_ROUTE, METROPLEX_FULL_PV_ROUTE, METROPLEX_METRICS_ROUTE, METROPLEX_RETRY_FREQUENCY, METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME, NOIBUJS_SDK_ADD_ERROR_FROM_JS_FMW_FUNCTION, NOIBUJS_SDK_ADD_ERROR_FUNCTION, NOIBUJS_SDK_ADD_ID_FUNCTION, NOIBUJS_SDK_REQUEST_HELP_CODE, NOIBU_BROWSER_ID_KYWRD, NOIBU_INPUT_URLS, NOIBU_LOCAL_STORAGE_TEST_KEY, NOIBU_STORED_PAGE_VISIT, OCCURRED_AT_ATT_NAME, OK_SOCKET_MESSAGE, ON_URL_ATT_NAME, PAGE_EVENTS_DOCUMENT, PAGE_EVENTS_WINDOW, PAGE_EVENT_TYPE, PAGE_VISIT_HTTP_DATA_ATT_NAME, PAGE_VISIT_INFORMATION_ATT_NAME, PAGE_VISIT_META_DATA_ATT_NAME, PAGE_VISIT_PART_ATT_NAME, PAGE_VISIT_VID_FRAG_ATT_NAME, PII_DIGIT_PATTERN, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PV_CLICKS_ATT_NAME, PV_EVENTS_ATT_NAME, PV_EXP_HTTP_DATA_SEQ_ATT_NAME, PV_EXP_PART_COUNTER_ATT_NAME, PV_EXP_VF_SEQ_ATT_NAME, PV_HTTP_PAYLOADS_COLLECTED_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_OVERSIZE_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_TYPE_ATT_NAME, PV_HTTP_REQUESTS_DROPPED_OVER_LIMIT, PV_ID_ATT_NAME, PV_METROPLEX_TYPE, PV_PART_COUNTER_ATT_NAME, PV_SEQ_ATT_NAME, PV_SEQ_NUM_RESET_TIME_MINUTES, REF_URL_ATT_NAME, REQUIRED_DATA_PROCESSING_URLS, RESPONSE_ERROR_TYPE, SCRIPT_ID_ATT_NAME, SCRIPT_INSTANCE_ID_ATT_NAME, SEQ_NUM_ATT_NAME, SEVERITY, SOCKET_INSTANCE_ID_ATT_NAME, SOURCE_ATT_NAME, STARTED_AT_ATT_NAME, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, TAGNAME_ATT_NAME, TEXT_ATT_NAME, TYPE_ATT_NAME, URL_ATT_NAME, USERSTEP_EVENT_TYPE, VER_ATT_NAME, VIDEO_CLICKS_ATT_NAME, VIDEO_METROPLEX_TYPE, VIDEO_PART_COUNT_ATT_NAME, WHITELIST_HTML_ID_TEXT_REGEX, WORK_REQUEST_ATT_NAME, WRAPPED_EXCEPTION_ERROR_TYPE, XML_HTTP_REQUEST_ERROR_TYPE };
|
package/dist/entry/init.js
CHANGED
|
@@ -12,7 +12,7 @@ import { PageVisit } from '../pageVisit/pageVisit.js';
|
|
|
12
12
|
import MetroplexSocket from '../api/metroplexSocket.js';
|
|
13
13
|
import StoredPageVisit from '../api/storedPageVisit.js';
|
|
14
14
|
import HelpCode from '../api/helpCode.js';
|
|
15
|
-
import { AppNavigationMonitor } from '../monitors/
|
|
15
|
+
import { AppNavigationMonitor } from '../monitors/appNavigationMonitor.js';
|
|
16
16
|
|
|
17
17
|
/** @module Init */
|
|
18
18
|
// these are set via rollup
|
|
@@ -33,12 +33,12 @@ function globalInit(customerConfig) {
|
|
|
33
33
|
return;
|
|
34
34
|
}
|
|
35
35
|
const noibuErrorURL = `${urlConfig.metroplexHTTPBase}/${METROPLEX_ERROR_ROUTE}`;
|
|
36
|
-
ClientConfig.configureInstance({
|
|
37
|
-
noibuErrorURL,
|
|
38
|
-
customerConfig,
|
|
39
|
-
});
|
|
40
36
|
// catch any errors that happened during initialization and send collect error
|
|
41
37
|
try {
|
|
38
|
+
ClientConfig.configureInstance({
|
|
39
|
+
noibuErrorURL,
|
|
40
|
+
customerConfig,
|
|
41
|
+
});
|
|
42
42
|
// create an instance ID for this script
|
|
43
43
|
const instanceId = uuid.v4();
|
|
44
44
|
// verifying if collect was disabled by other microservices
|
|
@@ -3,19 +3,18 @@
|
|
|
3
3
|
*/
|
|
4
4
|
export declare class AppNavigationMonitor {
|
|
5
5
|
private static instance;
|
|
6
|
-
private breadcrumbs;
|
|
7
6
|
/**
|
|
8
7
|
* guesses which navigation is used in app, and registers a listener if found
|
|
9
8
|
*/
|
|
10
9
|
constructor();
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
11
|
+
* handler for updating navigation breadcrumbs and notifying metro of location change
|
|
13
12
|
*/
|
|
14
|
-
|
|
13
|
+
onNavigation(breadcrumbs: string[]): void;
|
|
15
14
|
/**
|
|
16
|
-
*
|
|
15
|
+
* Gets the singleton instance
|
|
17
16
|
*/
|
|
18
|
-
|
|
17
|
+
static getInstance(): AppNavigationMonitor;
|
|
19
18
|
/**
|
|
20
19
|
* Called when the event needs to be emitted
|
|
21
20
|
*/
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import { SEVERITY,
|
|
2
|
-
import { getMaxSubstringAllowed } from '../utils/function.js';
|
|
1
|
+
import { SEVERITY, APP_NAVIGATION_EVENT_TYPE } from '../constants.js';
|
|
3
2
|
import { InputMonitor } from './inputMonitor.js';
|
|
4
3
|
import { ReactNativeNavigationIntegration } from './integrations/react-native-navigation-integration.js';
|
|
5
4
|
import ClientConfig from '../api/clientConfig.js';
|
|
@@ -9,25 +8,29 @@ import ClientConfig from '../api/clientConfig.js';
|
|
|
9
8
|
*/
|
|
10
9
|
class AppNavigationMonitor {
|
|
11
10
|
static instance;
|
|
12
|
-
breadcrumbs = [];
|
|
13
11
|
/**
|
|
14
12
|
* guesses which navigation is used in app, and registers a listener if found
|
|
15
13
|
*/
|
|
16
14
|
constructor() {
|
|
15
|
+
this.onNavigation = this.onNavigation.bind(this);
|
|
17
16
|
try {
|
|
18
17
|
// eslint-disable-next-line global-require,@typescript-eslint/no-var-requires,import/no-extraneous-dependencies
|
|
19
18
|
const rnNavigation = require('react-native-navigation')?.Navigation;
|
|
20
19
|
if (rnNavigation) {
|
|
21
|
-
new ReactNativeNavigationIntegration().register(rnNavigation,
|
|
22
|
-
this.breadcrumbs = breadcrumbs;
|
|
23
|
-
this.reportLocationChange();
|
|
24
|
-
});
|
|
20
|
+
new ReactNativeNavigationIntegration().register(rnNavigation, this.onNavigation);
|
|
25
21
|
}
|
|
26
22
|
}
|
|
27
23
|
catch (e) {
|
|
28
24
|
ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`AppNavigationMonitor: ${e}`, false, SEVERITY.error);
|
|
29
25
|
}
|
|
30
26
|
}
|
|
27
|
+
/**
|
|
28
|
+
* handler for updating navigation breadcrumbs and notifying metro of location change
|
|
29
|
+
*/
|
|
30
|
+
onNavigation(breadcrumbs) {
|
|
31
|
+
ClientConfig.getInstance().currentLocationBreadcrumbs = breadcrumbs;
|
|
32
|
+
this.reportLocationChange(breadcrumbs.pop());
|
|
33
|
+
}
|
|
31
34
|
/**
|
|
32
35
|
* Gets the singleton instance
|
|
33
36
|
*/
|
|
@@ -37,26 +40,12 @@ class AppNavigationMonitor {
|
|
|
37
40
|
}
|
|
38
41
|
return AppNavigationMonitor.instance;
|
|
39
42
|
}
|
|
40
|
-
/**
|
|
41
|
-
* gets current global url
|
|
42
|
-
*/
|
|
43
|
-
get globalUrl() {
|
|
44
|
-
const globalUrl = new URL('https://localhost');
|
|
45
|
-
globalUrl.hostname = ClientConfig.getInstance().customerDomain;
|
|
46
|
-
if (this.breadcrumbs.length) {
|
|
47
|
-
globalUrl.pathname = this.breadcrumbs.join('/');
|
|
48
|
-
}
|
|
49
|
-
return getMaxSubstringAllowed(globalUrl.toString());
|
|
50
|
-
}
|
|
51
43
|
/**
|
|
52
44
|
* Called when the event needs to be emitted
|
|
53
45
|
*/
|
|
54
|
-
reportLocationChange() {
|
|
55
|
-
const payload = {
|
|
56
|
-
|
|
57
|
-
};
|
|
58
|
-
// storing the location change in the page visit queue
|
|
59
|
-
InputMonitor.getInstance().addEvent(payload, LOCATION_EVENT_TYPE);
|
|
46
|
+
reportLocationChange(currentLocation) {
|
|
47
|
+
const payload = { location: currentLocation || '' };
|
|
48
|
+
InputMonitor.getInstance().addEvent(payload, APP_NAVIGATION_EVENT_TYPE);
|
|
60
49
|
}
|
|
61
50
|
}
|
|
62
51
|
|
|
@@ -4,8 +4,9 @@ import { PageVisit } from '../pageVisit/pageVisit.js';
|
|
|
4
4
|
import { updatePayload } from '../pageVisit/userStep/userStep.js';
|
|
5
5
|
import StoredMetrics from '../api/storedMetrics.js';
|
|
6
6
|
import { WHITELIST_TEXT_REGEX_STRING } from '../const_matchers.js';
|
|
7
|
-
import { maskTextInput
|
|
7
|
+
import { maskTextInput } from '../utils/function.js';
|
|
8
8
|
import { timestampWrapper } from '../utils/date.js';
|
|
9
|
+
import ClientConfig from '../api/clientConfig.js';
|
|
9
10
|
|
|
10
11
|
/** @module ClickMonitor */
|
|
11
12
|
|
|
@@ -190,7 +191,9 @@ class ClickMonitor {
|
|
|
190
191
|
|
|
191
192
|
counter.value += 1;
|
|
192
193
|
|
|
193
|
-
if (
|
|
194
|
+
if (
|
|
195
|
+
ClickMonitor.getBlockedElements().includes(element.memoizedProps.testID)
|
|
196
|
+
) {
|
|
194
197
|
return `${text}${text ? ' ' : ''}*`;
|
|
195
198
|
}
|
|
196
199
|
|
|
@@ -210,6 +213,18 @@ class ClickMonitor {
|
|
|
210
213
|
return text;
|
|
211
214
|
}
|
|
212
215
|
|
|
216
|
+
/**
|
|
217
|
+
* Gets selectors to prevent those elements from being recorded
|
|
218
|
+
*/
|
|
219
|
+
static getBlockedElements() {
|
|
220
|
+
const selectors = ClientConfig.getInstance().blockedElements;
|
|
221
|
+
const blockedElements = ['noibu-blocked'];
|
|
222
|
+
if (selectors && Array.isArray(selectors)) {
|
|
223
|
+
blockedElements.push(...selectors);
|
|
224
|
+
}
|
|
225
|
+
return blockedElements;
|
|
226
|
+
}
|
|
227
|
+
|
|
213
228
|
/**
|
|
214
229
|
* normalize value and append to the resulting text if not empty
|
|
215
230
|
* @param {String} text
|
|
@@ -2,8 +2,7 @@ import { HUMAN_READABLE_CONTENT_TYPE_REGEX, DEFAULT_WEBSITE_SUBDOMAIN_PATTERN, S
|
|
|
2
2
|
import ClientConfig from '../api/clientConfig.js';
|
|
3
3
|
import StoredMetrics from '../api/storedMetrics.js';
|
|
4
4
|
import { safeFromEntries, iterateObjectRecursively } from '../utils/object.js';
|
|
5
|
-
import
|
|
6
|
-
import { AppNavigationMonitor } from './AppNavigationMonitor.js';
|
|
5
|
+
import 'react-native-device-info';
|
|
7
6
|
|
|
8
7
|
/** @module HTTPDataBundler */
|
|
9
8
|
|
|
@@ -20,7 +19,7 @@ class HTTPDataBundler {
|
|
|
20
19
|
);
|
|
21
20
|
|
|
22
21
|
// pull out the domain hostname
|
|
23
|
-
const initialURL =
|
|
22
|
+
const initialURL = ClientConfig.getInstance().globalUrl;
|
|
24
23
|
this.initialURLPartsReversed = [];
|
|
25
24
|
if (initialURL && initialURL.length > 0) {
|
|
26
25
|
try {
|
|
@@ -45,10 +44,11 @@ class HTTPDataBundler {
|
|
|
45
44
|
}
|
|
46
45
|
}
|
|
47
46
|
|
|
48
|
-
this.httpDataCollectionEnabled =
|
|
47
|
+
this.httpDataCollectionEnabled =
|
|
48
|
+
!!ClientConfig.getInstance().enableHttpDataCollection;
|
|
49
49
|
|
|
50
50
|
// compile the relative and full HTTP URL regexes
|
|
51
|
-
const allowedURLs = getHttpPayloadAllowedURLs();
|
|
51
|
+
const allowedURLs = HTTPDataBundler.getHttpPayloadAllowedURLs();
|
|
52
52
|
this.httpDataAllowedAbsoluteRegex = HTTPDataBundler.buildAllowedRegex(
|
|
53
53
|
allowedURLs,
|
|
54
54
|
'absolute',
|
|
@@ -86,6 +86,19 @@ class HTTPDataBundler {
|
|
|
86
86
|
];
|
|
87
87
|
}
|
|
88
88
|
|
|
89
|
+
/** gets http data payload allowed URLs */
|
|
90
|
+
static getHttpPayloadAllowedURLs() {
|
|
91
|
+
const noibuConfig = ClientConfig.getInstance();
|
|
92
|
+
// return the allowed list or an empty list
|
|
93
|
+
if (
|
|
94
|
+
noibuConfig.listOfUrlsToCollectHttpDataFrom &&
|
|
95
|
+
Array.isArray(noibuConfig.listOfUrlsToCollectHttpDataFrom)
|
|
96
|
+
) {
|
|
97
|
+
return noibuConfig.listOfUrlsToCollectHttpDataFrom;
|
|
98
|
+
}
|
|
99
|
+
return [];
|
|
100
|
+
}
|
|
101
|
+
|
|
89
102
|
/**
|
|
90
103
|
* gets the singleton instance
|
|
91
104
|
* @returns {HTTPDataBundler}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { PageVisit } from '../pageVisit/pageVisit.js';
|
|
2
|
-
import {
|
|
2
|
+
import { APP_NAVIGATION_EVENT_TYPE, PAGE_EVENT_TYPE, MAX_TIME_FOR_UNSENT_DATA_MILLIS, ERROR_EVENT_TYPE, HTTP_EVENT_TYPE, KEYBOARD_EVENT_TYPE, USERSTEP_EVENT_TYPE } from '../constants.js';
|
|
3
3
|
import { timestampWrapper } from '../utils/date.js';
|
|
4
4
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
5
5
|
|
|
@@ -29,7 +29,7 @@ class InputMonitor {
|
|
|
29
29
|
// setting up debouncers for all events
|
|
30
30
|
// we send clicks directly to the socket so they aren't registered here
|
|
31
31
|
// we dont wait to send location changes, they happen at most once per second.
|
|
32
|
-
this.registerInputType(
|
|
32
|
+
this.registerInputType(APP_NAVIGATION_EVENT_TYPE, 0);
|
|
33
33
|
this.registerInputType(PAGE_EVENT_TYPE, MAX_TIME_FOR_UNSENT_DATA_MILLIS);
|
|
34
34
|
this.registerInputType(ERROR_EVENT_TYPE, MAX_TIME_FOR_UNSENT_DATA_MILLIS);
|
|
35
35
|
this.registerInputType(HTTP_EVENT_TYPE, MAX_TIME_FOR_UNSENT_DATA_MILLIS);
|
|
@@ -11,7 +11,8 @@ export declare class ReactNativeNavigationIntegration implements NavigationInteg
|
|
|
11
11
|
*/
|
|
12
12
|
register(navigation: NavigationDelegate, onNavigation: (breadcrumbs: string[]) => void): void;
|
|
13
13
|
/**
|
|
14
|
-
* Listens to ComponentWillAppear events
|
|
14
|
+
* Listens to ComponentWillAppear events, keeps track of visited screens and
|
|
15
|
+
* pops them if the same page is visited to prevent cycles
|
|
15
16
|
* @param onNavigation
|
|
16
17
|
* @private
|
|
17
18
|
*/
|
|
@@ -13,7 +13,8 @@ class ReactNativeNavigationIntegration {
|
|
|
13
13
|
.registerComponentWillAppearListener(this.getListener(onNavigation));
|
|
14
14
|
}
|
|
15
15
|
/**
|
|
16
|
-
* Listens to ComponentWillAppear events
|
|
16
|
+
* Listens to ComponentWillAppear events, keeps track of visited screens and
|
|
17
|
+
* pops them if the same page is visited to prevent cycles
|
|
17
18
|
* @param onNavigation
|
|
18
19
|
* @private
|
|
19
20
|
*/
|
|
@@ -30,7 +31,8 @@ class ReactNativeNavigationIntegration {
|
|
|
30
31
|
});
|
|
31
32
|
this.stack.length = this.stackPointers[event.componentName];
|
|
32
33
|
}
|
|
33
|
-
|
|
34
|
+
// shallow copy is returned
|
|
35
|
+
onNavigation(this.stack.slice());
|
|
34
36
|
};
|
|
35
37
|
}
|
|
36
38
|
}
|
|
@@ -4,11 +4,9 @@ import { PageVisitEventHTTP, isHttpCodeFailure } from '../pageVisit/pageVisitEve
|
|
|
4
4
|
import { propWriteableOrMadeWriteable, replace } from '../utils/object.js';
|
|
5
5
|
import 'react-native-device-info';
|
|
6
6
|
import { PV_SEQ_ATT_NAME, XML_HTTP_REQUEST_ERROR_TYPE, GQL_ERROR_TYPE, SEVERITY, RESPONSE_ERROR_TYPE, HTTP_METHOD_ATT_NAME, HTTP_RESP_CODE_ATT_NAME, URL_ATT_NAME, HTTP_RESP_TIME_ATT_NAME, HTTP_RESP_LENGTH_ATT_NAME, FETCH_EXCEPTION_ERROR_TYPE } from '../constants.js';
|
|
7
|
-
import ClientConfig from '../api/clientConfig.js';
|
|
8
|
-
import 'react-native-uuid';
|
|
9
7
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
10
|
-
import '@react-native-async-storage/async-storage';
|
|
11
8
|
import { HTTPDataBundler } from './httpDataBundler.js';
|
|
9
|
+
import ClientConfig from '../api/clientConfig.js';
|
|
12
10
|
import GqlErrorValidator from './gqlErrorValidator.js';
|
|
13
11
|
|
|
14
12
|
/** @module RequestMonitor */
|
|
@@ -1,10 +1,9 @@
|
|
|
1
|
-
import { isValidURL,
|
|
1
|
+
import { isValidURL, asString, getMaxSubstringAllowed, getJSStack, stringifyJSON } from '../../utils/function.js';
|
|
2
2
|
import { EVENT_ERROR_TYPE, URL_ATT_NAME, ERROR_EVENT_TYPE, ERROR_EVENT_ERROR_TYPE, CUSTOM_ERROR_EVENT_TYPE, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, ERROR_LOG_EVENT_ERROR_TYPE, FETCH_EXCEPTION_ERROR_TYPE, WRAPPED_EXCEPTION_ERROR_TYPE, GQL_ERROR_TYPE, RESPONSE_ERROR_TYPE, XML_HTTP_REQUEST_ERROR_TYPE, ERROR_SOURCE_ATT_NAME, TYPE_ATT_NAME, JS_EVENT_TYPE, JS_ERROR_ATT_NAME, JS_STACK_FRAMES_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_METHOD_ATT_NAME, SEVERITY, JS_STACK_MESSAGE_ATT_NAME, HTTP_EVENT_TYPE, NOIBU_INPUT_URLS, HTTP_CODE_ATT_NAME, PV_SEQ_ATT_NAME, GQL_EVENT_TYPE, GQL_ERROR_ATT_NAME } from '../../constants.js';
|
|
3
3
|
import blacklisedDomains from './blacklistedDomains.js';
|
|
4
4
|
import ClientConfig from '../../api/clientConfig.js';
|
|
5
5
|
import { InputMonitor } from '../../monitors/inputMonitor.js';
|
|
6
6
|
import StoredMetrics from '../../api/storedMetrics.js';
|
|
7
|
-
import { AppNavigationMonitor } from '../../monitors/AppNavigationMonitor.js';
|
|
8
7
|
|
|
9
8
|
/** @module PageVisitEventError */
|
|
10
9
|
|
|
@@ -26,6 +25,17 @@ function getPVErrorFromResponse(errPayload, httpDataSeqNum) {
|
|
|
26
25
|
return errorObject;
|
|
27
26
|
}
|
|
28
27
|
|
|
28
|
+
/**
|
|
29
|
+
* gets the onURL of a string, defaulting to the location of the webpage
|
|
30
|
+
*/
|
|
31
|
+
function getOnURL(realOnURL) {
|
|
32
|
+
if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
|
|
33
|
+
return asString(getMaxSubstringAllowed(realOnURL));
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
return ClientConfig.getInstance().globalUrl;
|
|
37
|
+
}
|
|
38
|
+
|
|
29
39
|
/**
|
|
30
40
|
* getPVErrorFromGqlError will create the error information from an
|
|
31
41
|
* GraphQL error payload.
|
|
@@ -71,7 +81,7 @@ function getPVErrorFromXMLHttpRequest(errPayload, httpDataSeqNum) {
|
|
|
71
81
|
function getPVErrorFromErrorEvent(errPayload) {
|
|
72
82
|
return {
|
|
73
83
|
[URL_ATT_NAME]: getOnURL(
|
|
74
|
-
errPayload.filename ||
|
|
84
|
+
errPayload.filename || ClientConfig.getInstance().globalUrl,
|
|
75
85
|
),
|
|
76
86
|
[TYPE_ATT_NAME]: JS_EVENT_TYPE,
|
|
77
87
|
[JS_ERROR_ATT_NAME]: getJSStack(errPayload.error),
|
|
@@ -83,7 +93,7 @@ function getPVErrorFromErrorEvent(errPayload) {
|
|
|
83
93
|
*/
|
|
84
94
|
function getPVErrorFromErrorLog(errPayload) {
|
|
85
95
|
return {
|
|
86
|
-
[URL_ATT_NAME]: getOnURL(
|
|
96
|
+
[URL_ATT_NAME]: getOnURL(ClientConfig.getInstance().globalUrl),
|
|
87
97
|
[TYPE_ATT_NAME]: JS_EVENT_TYPE,
|
|
88
98
|
[JS_ERROR_ATT_NAME]: getJSStack(errPayload),
|
|
89
99
|
};
|
|
@@ -307,4 +317,4 @@ function saveErrorToPagevisit(type, payload, httpDataSeqNum) {
|
|
|
307
317
|
InputMonitor.getInstance().addEvent(pvError, ERROR_EVENT_TYPE);
|
|
308
318
|
}
|
|
309
319
|
|
|
310
|
-
export { isCollectError, saveErrorToPagevisit };
|
|
320
|
+
export { getOnURL, isCollectError, saveErrorToPagevisit };
|
package/dist/utils/function.d.ts
CHANGED
|
@@ -43,14 +43,6 @@ export declare function stringifyJSON(jsonObject: unknown): string;
|
|
|
43
43
|
* @param sendAndForget
|
|
44
44
|
*/
|
|
45
45
|
export declare function makeRequest(method: string, url: string, data: unknown, headers: Record<string, string>, timeout: number, sendAndForget: boolean): Promise<unknown>;
|
|
46
|
-
/** checks if http data collection is enabled */
|
|
47
|
-
export declare function checkHttpDataCollectionEnabled(): boolean;
|
|
48
|
-
/** gets http data payload allowed URLs */
|
|
49
|
-
export declare function getHttpPayloadAllowedURLs(): string[];
|
|
50
|
-
/**
|
|
51
|
-
* Gets selectors to prevent those elements from being recorded
|
|
52
|
-
*/
|
|
53
|
-
export declare function getBlockedElements(): string[];
|
|
54
46
|
/**
|
|
55
47
|
* makes sure the url sent is a valid URL
|
|
56
48
|
*/
|
|
@@ -79,10 +71,6 @@ export declare function asString(obj: unknown): string;
|
|
|
79
71
|
* masks textual content if it ressembles something sensitive
|
|
80
72
|
*/
|
|
81
73
|
export declare function maskTextInput(text: string): string;
|
|
82
|
-
/**
|
|
83
|
-
* gets the onURL of a string, defaulting to the location of the webpage
|
|
84
|
-
*/
|
|
85
|
-
export declare function getOnURL(realOnURL: string): string;
|
|
86
74
|
/**
|
|
87
75
|
* Checks if the provided object is an instance of the specified type.
|
|
88
76
|
* It's safer than `instanceof` operator as it handles cases
|
package/dist/utils/function.js
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
import DeviceInfo from 'react-native-device-info';
|
|
2
2
|
import { parseStack } from './stacktrace-parser.js';
|
|
3
3
|
import { MAX_STRING_LENGTH, MAX_BEACON_PAYLOAD_SIZE, REQUIRED_DATA_PROCESSING_URLS, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
|
|
4
|
-
import ClientConfig from '../api/clientConfig.js';
|
|
5
|
-
import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
|
|
6
4
|
|
|
7
5
|
/** @module Functions */
|
|
8
6
|
/**
|
|
@@ -66,7 +64,7 @@ function getJSStack(errObj) {
|
|
|
66
64
|
];
|
|
67
65
|
// if the errObj type is not an object or null
|
|
68
66
|
// return a default frame
|
|
69
|
-
if (typeof errObj !== 'object' || !errObj) {
|
|
67
|
+
if (typeof errObj !== 'object' || !errObj || !errObj.stack) {
|
|
70
68
|
return {
|
|
71
69
|
frames,
|
|
72
70
|
msg: '',
|
|
@@ -171,33 +169,6 @@ async function makeRequest(method, url, data, headers, timeout, sendAndForget) {
|
|
|
171
169
|
}
|
|
172
170
|
});
|
|
173
171
|
}
|
|
174
|
-
/** checks if http data collection is enabled */
|
|
175
|
-
function checkHttpDataCollectionEnabled() {
|
|
176
|
-
const noibuConfig = ClientConfig.getInstance();
|
|
177
|
-
// Just a boolean, so safe to return truthiness. If undefined, will return false.
|
|
178
|
-
return !!noibuConfig.enableHttpDataCollection;
|
|
179
|
-
}
|
|
180
|
-
/** gets http data payload allowed URLs */
|
|
181
|
-
function getHttpPayloadAllowedURLs() {
|
|
182
|
-
const noibuConfig = ClientConfig.getInstance();
|
|
183
|
-
// return the allowed list or an empty list
|
|
184
|
-
if (noibuConfig.listOfUrlsToCollectHttpDataFrom &&
|
|
185
|
-
Array.isArray(noibuConfig.listOfUrlsToCollectHttpDataFrom)) {
|
|
186
|
-
return noibuConfig.listOfUrlsToCollectHttpDataFrom;
|
|
187
|
-
}
|
|
188
|
-
return [];
|
|
189
|
-
}
|
|
190
|
-
/**
|
|
191
|
-
* Gets selectors to prevent those elements from being recorded
|
|
192
|
-
*/
|
|
193
|
-
function getBlockedElements() {
|
|
194
|
-
const selectors = ClientConfig.getInstance().blockedElements;
|
|
195
|
-
const blockedElements = ['noibu-blocked'];
|
|
196
|
-
if (selectors && Array.isArray(selectors)) {
|
|
197
|
-
blockedElements.push(...selectors);
|
|
198
|
-
}
|
|
199
|
-
return blockedElements;
|
|
200
|
-
}
|
|
201
172
|
/**
|
|
202
173
|
* makes sure the url sent is a valid URL
|
|
203
174
|
*/
|
|
@@ -276,15 +247,6 @@ function maskTextInput(text) {
|
|
|
276
247
|
.replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING)
|
|
277
248
|
.replace(PII_DIGIT_PATTERN, '*');
|
|
278
249
|
}
|
|
279
|
-
/**
|
|
280
|
-
* gets the onURL of a string, defaulting to the location of the webpage
|
|
281
|
-
*/
|
|
282
|
-
function getOnURL(realOnURL) {
|
|
283
|
-
if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
|
|
284
|
-
return asString(getMaxSubstringAllowed(realOnURL));
|
|
285
|
-
}
|
|
286
|
-
return AppNavigationMonitor.getInstance().globalUrl;
|
|
287
|
-
}
|
|
288
250
|
/**
|
|
289
251
|
* Checks if the provided object is an instance of the specified type.
|
|
290
252
|
* It's safer than `instanceof` operator as it handles cases
|
|
@@ -299,4 +261,4 @@ function isInstanceOf(instance, type) {
|
|
|
299
261
|
}
|
|
300
262
|
}
|
|
301
263
|
|
|
302
|
-
export { asString,
|
|
264
|
+
export { asString, getJSStack, getMaxSubstringAllowed, getUserAgent, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noibu-react-native",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"targetNjsVersion": "1.0.104",
|
|
5
5
|
"description": "React-Native SDK for NoibuJS to collect errors in React-Native applications",
|
|
6
6
|
"main": "dist/entry/index.js",
|
|
@@ -25,9 +25,9 @@
|
|
|
25
25
|
"react-native-navigation": "7"
|
|
26
26
|
},
|
|
27
27
|
"dependencies": {
|
|
28
|
+
"@react-native-async-storage/async-storage": "^1.19.0",
|
|
28
29
|
"react": ">=16.11.0",
|
|
29
30
|
"react-native": ">=0.63.0",
|
|
30
|
-
"@react-native-async-storage/async-storage": "^1.19.0",
|
|
31
31
|
"react-native-device-info": "^10.6.0",
|
|
32
32
|
"react-native-url-polyfill": "^1.3.0",
|
|
33
33
|
"react-native-uuid": "^2.0.1"
|