noibu-react-native 0.0.8 → 0.1.1
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 +0 -4
- 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 +2 -4
- package/dist/constants.js +4 -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/errorMonitor.d.ts +5 -2
- package/dist/monitors/errorMonitor.js +53 -17
- 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 +18 -7
- package/dist/react/ErrorBoundary.js +1 -1
- package/dist/types/globals.d.ts +11 -2
- package/dist/utils/function.d.ts +0 -12
- package/dist/utils/function.js +6 -40
- package/dist/utils/stacktrace-parser.js +1 -49
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -164,10 +164,6 @@ import { NoibuJS } from 'noibu-react-native';
|
|
|
164
164
|
NoibuJS.addJsSdkError(new Error('My Error'), 'myModule.js');
|
|
165
165
|
```
|
|
166
166
|
|
|
167
|
-
## Contributing
|
|
168
|
-
|
|
169
|
-
You can contribute by checking out the project page and open issues. https://linear.app/noibu/project/react-native-sdk-5ccd19a3343a
|
|
170
|
-
|
|
171
167
|
## License
|
|
172
168
|
|
|
173
169
|
Copyright 2023 Noibu.com
|
|
@@ -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,4 @@ 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
|
|
229
|
+
export declare const STACK_TRACE_SANITIZE_REGEXP: 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.1.1" ;
|
|
321
319
|
}
|
|
322
320
|
/**
|
|
323
321
|
*
|
|
@@ -425,5 +423,6 @@ function JS_ENV() {
|
|
|
425
423
|
}
|
|
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;
|
|
426
|
+
const STACK_TRACE_SANITIZE_REGEXP = /(nbuGlobalPromiseRejectWrapper|(hermes.*InternalBytecode\/InternalBytecode))/gi;
|
|
428
427
|
|
|
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,
|
|
428
|
+
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, STACK_TRACE_SANITIZE_REGEXP, 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
|
|
@@ -15,9 +15,12 @@ export declare function wrap(functionToWrap: WrappedFunction): Function;
|
|
|
15
15
|
export declare function processErrorLogArguments(argsFromErrorLog: any[]): void;
|
|
16
16
|
/**
|
|
17
17
|
* handler for promise rejection failures
|
|
18
|
-
* @param
|
|
18
|
+
* @param error
|
|
19
19
|
*/
|
|
20
|
-
export declare function onPromiseRejectionHandler(
|
|
20
|
+
export declare function onPromiseRejectionHandler(error: {
|
|
21
|
+
message: string;
|
|
22
|
+
stack?: string;
|
|
23
|
+
}): void;
|
|
21
24
|
/**
|
|
22
25
|
* Monitors the errors happening on the window
|
|
23
26
|
*/
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { replace } from '../utils/object.js';
|
|
2
|
-
import { isStackTrace } from '../utils/function.js';
|
|
3
|
-
import { ERROR_EVENT_ERROR_TYPE,
|
|
2
|
+
import { asString, isStackTrace } from '../utils/function.js';
|
|
3
|
+
import { CONSOLE_FUNCTION_OVERRIDES, ERROR_EVENT_ERROR_TYPE, STACK_TRACE_SANITIZE_REGEXP, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, ERROR_LOG_EVENT_ERROR_TYPE } from '../constants.js';
|
|
4
4
|
import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError/pageVisitEventError.js';
|
|
5
5
|
|
|
6
6
|
/* eslint-disable @typescript-eslint/ban-types,prefer-arrow-callback */
|
|
@@ -117,11 +117,49 @@ function configureEventListeners() {
|
|
|
117
117
|
});
|
|
118
118
|
}
|
|
119
119
|
/**
|
|
120
|
-
*
|
|
120
|
+
* handler for promise rejection failures
|
|
121
|
+
* @param error
|
|
121
122
|
*/
|
|
122
|
-
function
|
|
123
|
-
|
|
124
|
-
|
|
123
|
+
function onPromiseRejectionHandler(error) {
|
|
124
|
+
if (!error || !error.message || !error.stack) {
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const sanitizedStack = error.stack
|
|
128
|
+
.split('\n')
|
|
129
|
+
.filter(line => !line.match(STACK_TRACE_SANITIZE_REGEXP))
|
|
130
|
+
.join('\n');
|
|
131
|
+
const payload = {
|
|
132
|
+
error: {
|
|
133
|
+
message: error.message,
|
|
134
|
+
stack: sanitizedStack,
|
|
135
|
+
},
|
|
136
|
+
};
|
|
137
|
+
saveErrorToPagevisit(ERROR_EVENT_UNHANDLED_REJECTION_TYPE, payload);
|
|
138
|
+
}
|
|
139
|
+
function configureHermesHooks() {
|
|
140
|
+
if (global.HermesInternal) {
|
|
141
|
+
global.HermesInternal.enablePromiseRejectionTracker?.({
|
|
142
|
+
allRejections: true,
|
|
143
|
+
});
|
|
144
|
+
/**
|
|
145
|
+
* This internal promise implementation method is populated only after enabling the promise tracker.
|
|
146
|
+
* It represents an improvement over the previous approach,
|
|
147
|
+
* which would lose stack context regarding the rejection because it ran asynchronously through setTimeout.
|
|
148
|
+
*
|
|
149
|
+
* This updated method ensures synchronous error capturing and retrieves the correct stack frames.
|
|
150
|
+
*/
|
|
151
|
+
replace(Promise, '_m', (originalFunction) => function nbuGlobalPromiseRejectWrapper(promise, error) {
|
|
152
|
+
if (error.message && error.stack) {
|
|
153
|
+
onPromiseRejectionHandler(error);
|
|
154
|
+
}
|
|
155
|
+
else {
|
|
156
|
+
onPromiseRejectionHandler(new Error(asString(error)));
|
|
157
|
+
}
|
|
158
|
+
return originalFunction?.(promise, error);
|
|
159
|
+
});
|
|
160
|
+
}
|
|
161
|
+
}
|
|
162
|
+
function configureErrorUtilsHandler() {
|
|
125
163
|
const existingHandler = global.ErrorUtils.getGlobalHandler() || (() => { });
|
|
126
164
|
global.ErrorUtils.setGlobalHandler((error, ...rest) => {
|
|
127
165
|
saveErrorToPagevisit(ERROR_EVENT_ERROR_TYPE, {
|
|
@@ -129,16 +167,14 @@ function monitorErrors() {
|
|
|
129
167
|
});
|
|
130
168
|
return existingHandler(error, ...rest);
|
|
131
169
|
});
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
});
|
|
141
|
-
}
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Monitors the errors happening on the window
|
|
173
|
+
*/
|
|
174
|
+
function monitorErrors() {
|
|
175
|
+
configureEventListeners();
|
|
176
|
+
configureHermesHooks();
|
|
177
|
+
configureErrorUtilsHandler();
|
|
142
178
|
}
|
|
143
179
|
|
|
144
|
-
export { monitorErrors, processErrorLogArguments };
|
|
180
|
+
export { monitorErrors, onPromiseRejectionHandler, processErrorLogArguments };
|
|
@@ -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
|
};
|
|
@@ -200,7 +210,7 @@ function createPageVisitEventError(type, errPayload, httpDataSeqNum) {
|
|
|
200
210
|
* determines if an error is a collect error
|
|
201
211
|
* @param {} pvError
|
|
202
212
|
*/
|
|
203
|
-
function
|
|
213
|
+
function isErrorCollectedByNoibu(pvError) {
|
|
204
214
|
// checking if this error originated from the Noibu script
|
|
205
215
|
if (pvError[TYPE_ATT_NAME] === JS_EVENT_TYPE) {
|
|
206
216
|
if (pvError[JS_ERROR_ATT_NAME]) {
|
|
@@ -212,6 +222,7 @@ function isCollectError(pvError) {
|
|
|
212
222
|
|
|
213
223
|
if (
|
|
214
224
|
lowerCapFile.includes('noibu') &&
|
|
225
|
+
!lowerCapFile.includes('examplenoibureactnativeapp') &&
|
|
215
226
|
!lowerCapMethod.includes('nbuwrapper')
|
|
216
227
|
) {
|
|
217
228
|
// if the first file in the stack is Noibu then we do not
|
|
@@ -297,7 +308,7 @@ function saveErrorToPagevisit(type, payload, httpDataSeqNum) {
|
|
|
297
308
|
}
|
|
298
309
|
}
|
|
299
310
|
|
|
300
|
-
if (
|
|
311
|
+
if (isErrorCollectedByNoibu(pvError)) {
|
|
301
312
|
return;
|
|
302
313
|
}
|
|
303
314
|
|
|
@@ -307,4 +318,4 @@ function saveErrorToPagevisit(type, payload, httpDataSeqNum) {
|
|
|
307
318
|
InputMonitor.getInstance().addEvent(pvError, ERROR_EVENT_TYPE);
|
|
308
319
|
}
|
|
309
320
|
|
|
310
|
-
export {
|
|
321
|
+
export { getOnURL, isErrorCollectedByNoibu, saveErrorToPagevisit };
|
package/dist/types/globals.d.ts
CHANGED
|
@@ -17,14 +17,23 @@ declare global {
|
|
|
17
17
|
type Window = {
|
|
18
18
|
noibuJSLoaded?: boolean;
|
|
19
19
|
};
|
|
20
|
+
type PromiseRejectionTrackerOptions = Partial<{
|
|
21
|
+
allRejections: boolean;
|
|
22
|
+
whitelist: (typeof Error)[];
|
|
23
|
+
onUnhandled: (id: number, reason: any) => void;
|
|
24
|
+
onHandled: (id: number, reason: any) => void;
|
|
25
|
+
}>;
|
|
20
26
|
type global = {
|
|
21
27
|
window: Window;
|
|
22
28
|
console: Console;
|
|
23
29
|
noibuJSLoaded?: boolean;
|
|
24
30
|
ErrorUtils: any;
|
|
25
31
|
HermesInternal: null | {
|
|
26
|
-
enablePromiseRejectionTracker?:
|
|
27
|
-
setPromiseRejectionTrackingHook?:
|
|
32
|
+
enablePromiseRejectionTracker?: (options: PromiseRejectionTrackerOptions) => void;
|
|
33
|
+
setPromiseRejectionTrackingHook?: (enable: (options: PromiseRejectionTrackerOptions) => void) => void;
|
|
34
|
+
};
|
|
35
|
+
Promise: {
|
|
36
|
+
_m: () => void;
|
|
28
37
|
};
|
|
29
38
|
};
|
|
30
39
|
const global: global;
|
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
|
/**
|
|
@@ -43,6 +41,10 @@ function processFrames(rawFrames) {
|
|
|
43
41
|
}
|
|
44
42
|
if (frame.file && frame.file !== '<unknown>') {
|
|
45
43
|
processedFrame.file = String(frame.file);
|
|
44
|
+
if (isValidURL(processedFrame.file)) {
|
|
45
|
+
// todo remove comment if assumption that react native only has local urls in filenames is correct
|
|
46
|
+
processedFrame.file = new URL(processedFrame.file).pathname;
|
|
47
|
+
}
|
|
46
48
|
}
|
|
47
49
|
if (frame.column) {
|
|
48
50
|
if (Number.isInteger(frame.column)) {
|
|
@@ -66,7 +68,7 @@ function getJSStack(errObj) {
|
|
|
66
68
|
];
|
|
67
69
|
// if the errObj type is not an object or null
|
|
68
70
|
// return a default frame
|
|
69
|
-
if (typeof errObj !== 'object' || !errObj) {
|
|
71
|
+
if (typeof errObj !== 'object' || !errObj || !errObj.stack) {
|
|
70
72
|
return {
|
|
71
73
|
frames,
|
|
72
74
|
msg: '',
|
|
@@ -171,33 +173,6 @@ async function makeRequest(method, url, data, headers, timeout, sendAndForget) {
|
|
|
171
173
|
}
|
|
172
174
|
});
|
|
173
175
|
}
|
|
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
176
|
/**
|
|
202
177
|
* makes sure the url sent is a valid URL
|
|
203
178
|
*/
|
|
@@ -276,15 +251,6 @@ function maskTextInput(text) {
|
|
|
276
251
|
.replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING)
|
|
277
252
|
.replace(PII_DIGIT_PATTERN, '*');
|
|
278
253
|
}
|
|
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
254
|
/**
|
|
289
255
|
* Checks if the provided object is an instance of the specified type.
|
|
290
256
|
* It's safer than `instanceof` operator as it handles cases
|
|
@@ -299,4 +265,4 @@ function isInstanceOf(instance, type) {
|
|
|
299
265
|
}
|
|
300
266
|
}
|
|
301
267
|
|
|
302
|
-
export { asString,
|
|
268
|
+
export { asString, getJSStack, getMaxSubstringAllowed, getUserAgent, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
|
|
@@ -88,50 +88,6 @@ const chrome = (line) => {
|
|
|
88
88
|
}
|
|
89
89
|
return undefined;
|
|
90
90
|
};
|
|
91
|
-
const geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
|
|
92
|
-
const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
|
|
93
|
-
const gecko = (line) => {
|
|
94
|
-
const parts = geckoREgex.exec(line);
|
|
95
|
-
if (parts) {
|
|
96
|
-
const isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
|
|
97
|
-
if (isEval) {
|
|
98
|
-
const subMatch = geckoEvalRegex.exec(parts[3]);
|
|
99
|
-
if (subMatch) {
|
|
100
|
-
// throw out eval line/column and use top-most line number
|
|
101
|
-
parts[1] = parts[1] || 'eval';
|
|
102
|
-
parts[3] = subMatch[1];
|
|
103
|
-
parts[4] = subMatch[2];
|
|
104
|
-
parts[5] = ''; // no column when eval
|
|
105
|
-
}
|
|
106
|
-
}
|
|
107
|
-
let filename = parts[3];
|
|
108
|
-
let func = parts[1] || UNKNOWN_FUNCTION;
|
|
109
|
-
[func, filename] = extractSafariExtensionDetails(func, filename);
|
|
110
|
-
return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined);
|
|
111
|
-
}
|
|
112
|
-
return undefined;
|
|
113
|
-
};
|
|
114
|
-
const winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
|
|
115
|
-
const winjs = (line) => {
|
|
116
|
-
const parts = winjsRegex.exec(line);
|
|
117
|
-
return parts
|
|
118
|
-
? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined)
|
|
119
|
-
: undefined;
|
|
120
|
-
};
|
|
121
|
-
const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
|
|
122
|
-
const opera10 = (line) => {
|
|
123
|
-
const parts = opera10Regex.exec(line);
|
|
124
|
-
return parts
|
|
125
|
-
? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1])
|
|
126
|
-
: undefined;
|
|
127
|
-
};
|
|
128
|
-
const opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
|
|
129
|
-
const opera11 = (line) => {
|
|
130
|
-
const parts = opera11Regex.exec(line);
|
|
131
|
-
return parts
|
|
132
|
-
? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2])
|
|
133
|
-
: undefined;
|
|
134
|
-
};
|
|
135
91
|
function parseStack(stackString) {
|
|
136
92
|
const lines = stackString.split('\n');
|
|
137
93
|
if (lines.length > MAX_FRAMES_IN_ARRAY) {
|
|
@@ -141,11 +97,7 @@ function parseStack(stackString) {
|
|
|
141
97
|
if (line.length > MAX_STRING_LENGTH) {
|
|
142
98
|
return stack;
|
|
143
99
|
}
|
|
144
|
-
const parseResult =
|
|
145
|
-
chrome(line) ||
|
|
146
|
-
winjs(line) ||
|
|
147
|
-
opera11(line) ||
|
|
148
|
-
opera10(line);
|
|
100
|
+
const parseResult = chrome(line);
|
|
149
101
|
if (parseResult) {
|
|
150
102
|
stack.push(parseResult);
|
|
151
103
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "noibu-react-native",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.1.1",
|
|
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"
|