noibu-react-native 0.0.7 → 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.
@@ -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
- private static noibuErrorURL;
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
@@ -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, getUserAgent, asString, makeRequest } from '../utils/function.js';
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
- this.noibuErrorURL = noibuErrorURL;
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
- let errMsg = `Noibu Browser ID(${this.browserId ? this.browserId : ''}), PV ID ${this.pageVisitId}, Script ID ${GET_SCRIPT_ID()}, and User Agent ${await getUserAgent()} error: ${asString(errorMsg)}`;
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
- errMsg =
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: AppNavigationMonitor.getInstance().globalUrl,
311
- err_msg: errMsg,
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;
@@ -1,5 +1,5 @@
1
1
  import MetroplexSocket from './metroplexSocket.js';
2
- import { SEVERITY, WORK_REQUEST_ATT_NAME, HELP_CODE_ATT_NAME } from '../constants.js';
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 this._sendRequest();
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
- import { getUserAgent, stringifyJSON, getUserLanguage } from '../utils/function.js';
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, LANG_ATT_NAME, HELP_CODE_ATT_NAME } from '../constants.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, 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 = AppNavigationMonitor.getInstance().globalUrl;
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.
@@ -814,12 +820,6 @@ class MetroplexSocket {
814
820
  [SOCKET_INSTANCE_ID_ATT_NAME]: this.socketInstanceId,
815
821
  };
816
822
 
817
- // only setting the user language if we can safely access it
818
- const userLang = getUserLanguage();
819
- if (userLang) {
820
- pvi[LANG_ATT_NAME] = userLang;
821
- }
822
-
823
823
  return pvi;
824
824
  }
825
825
 
@@ -837,7 +837,7 @@ class MetroplexSocket {
837
837
  const data = response.substring(prefix.length);
838
838
  const success = /^\d{6}$/.test(data);
839
839
 
840
- HelpCode.getInstance().receiveHelpCode({ detail: { success, data } });
840
+ this.helpCodeCb({ detail: { success, data } });
841
841
 
842
842
  return true;
843
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]: AppNavigationMonitor.getInstance().globalUrl,
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, LOCATION_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';
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
@@ -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
@@ -195,7 +195,6 @@ const CSS_CLASS_ATT_NAME = 'class';
195
195
  const SEQ_NUM_ATT_NAME = 'seq_num';
196
196
  const HELP_CODE_ATT_NAME = 'hc';
197
197
  const WORK_REQUEST_ATT_NAME = 'wr';
198
- const LANG_ATT_NAME = 'lang';
199
198
  const SCRIPT_ID_ATT_NAME = 'script_id';
200
199
  const SCRIPT_INSTANCE_ID_ATT_NAME = 'script_inst_id';
201
200
  const METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME = 'mp_sock_inst_id';
@@ -224,9 +223,9 @@ const GQL_EVENT_TYPE = 'gql';
224
223
  const USERSTEP_EVENT_TYPE = 'userstep';
225
224
  const CLICK_EVENT_TYPE = 'click';
226
225
  const KEYBOARD_EVENT_TYPE = 'kbd';
227
- const LOCATION_EVENT_TYPE = 'loc';
228
226
  const ERROR_EVENT_TYPE = 'err';
229
227
  const PAGE_EVENT_TYPE = 'page';
228
+ const APP_NAVIGATION_EVENT_TYPE = 'app_nav';
230
229
  // complete page visit attributes
231
230
  const PAGE_VISIT_INFORMATION_ATT_NAME = 'pvi';
232
231
  const PAGE_VISIT_PART_ATT_NAME = 'pvp';
@@ -288,12 +287,10 @@ const PAGE_EVENTS_WINDOW = [
288
287
  'pageshow',
289
288
  'focus',
290
289
  'blur',
291
- // 'storage', // Disabled until compression is supported NOI-3998
292
290
  'popstate',
293
291
  'online',
294
292
  'offline',
295
293
  'messageerror',
296
- // 'message', // Disabled until compression is supported NOI-3998
297
294
  'languagechange',
298
295
  'hashchange',
299
296
  'beforeprint',
@@ -318,7 +315,7 @@ const CONTENT_LENGTH = 'content-length';
318
315
  * Gets the script id from the cookie object, returns default if cannot be found
319
316
  */
320
317
  function GET_SCRIPT_ID() {
321
- return "1.0.104" ;
318
+ return "1.0.104-rn-sdk-0.0.9" ;
322
319
  }
323
320
  /**
324
321
  *
@@ -427,4 +424,4 @@ function JS_ENV() {
427
424
  // gets the frequency at which the client resends the message that were not confirmed by metroplex
428
425
  const METROPLEX_RETRY_FREQUENCY = 30000;
429
426
 
430
- 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, LANG_ATT_NAME, LOCATION_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 };
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 };
@@ -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/AppNavigationMonitor.js';
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
- * Gets the singleton instance
11
+ * handler for updating navigation breadcrumbs and notifying metro of location change
13
12
  */
14
- static getInstance(): AppNavigationMonitor;
13
+ onNavigation(breadcrumbs: string[]): void;
15
14
  /**
16
- * gets current global url
15
+ * Gets the singleton instance
17
16
  */
18
- get globalUrl(): string;
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, URL_ATT_NAME, LOCATION_EVENT_TYPE } from '../constants.js';
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, breadcrumbs => {
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
- [URL_ATT_NAME]: this.globalUrl,
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, getBlockedElements } from '../utils/function.js';
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 (getBlockedElements().includes(element.memoizedProps.testID)) {
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 { checkHttpDataCollectionEnabled, getHttpPayloadAllowedURLs } from '../utils/function.js';
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 = AppNavigationMonitor.getInstance().globalUrl;
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 = checkHttpDataCollectionEnabled();
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 { LOCATION_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';
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(LOCATION_EVENT_TYPE, 0);
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
- onNavigation(this.stack.slice(1)); // slice 1 to skip root component
34
+ // shallow copy is returned
35
+ onNavigation(this.stack.slice());
34
36
  };
35
37
  }
36
38
  }
@@ -3,13 +3,10 @@ import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError/pageVisit
3
3
  import { PageVisitEventHTTP, isHttpCodeFailure } from '../pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js';
4
4
  import { propWriteableOrMadeWriteable, replace } from '../utils/object.js';
5
5
  import 'react-native-device-info';
6
- import 'react-native-localize';
7
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';
8
- import ClientConfig from '../api/clientConfig.js';
9
- import 'react-native-uuid';
10
7
  import { addSafeEventListener } from '../utils/eventlistener.js';
11
- import '@react-native-async-storage/async-storage';
12
8
  import { HTTPDataBundler } from './httpDataBundler.js';
9
+ import ClientConfig from '../api/clientConfig.js';
13
10
  import GqlErrorValidator from './gqlErrorValidator.js';
14
11
 
15
12
  /** @module RequestMonitor */
@@ -1,10 +1,9 @@
1
- import { isValidURL, getOnURL, getJSStack, stringifyJSON, getMaxSubstringAllowed } from '../../utils/function.js';
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 || AppNavigationMonitor.getInstance().globalUrl,
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(AppNavigationMonitor.getInstance().globalUrl),
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 };
@@ -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,12 +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
- /** gets the user language from the browser */
87
- export declare function getUserLanguage(): string | null;
88
74
  /**
89
75
  * Checks if the provided object is an instance of the specified type.
90
76
  * It's safer than `instanceof` operator as it handles cases
@@ -1,9 +1,6 @@
1
1
  import DeviceInfo from 'react-native-device-info';
2
- import { getLocales } from 'react-native-localize';
3
2
  import { parseStack } from './stacktrace-parser.js';
4
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';
5
- import ClientConfig from '../api/clientConfig.js';
6
- import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
7
4
 
8
5
  /** @module Functions */
9
6
  /**
@@ -67,7 +64,7 @@ function getJSStack(errObj) {
67
64
  ];
68
65
  // if the errObj type is not an object or null
69
66
  // return a default frame
70
- if (typeof errObj !== 'object' || !errObj) {
67
+ if (typeof errObj !== 'object' || !errObj || !errObj.stack) {
71
68
  return {
72
69
  frames,
73
70
  msg: '',
@@ -172,33 +169,6 @@ async function makeRequest(method, url, data, headers, timeout, sendAndForget) {
172
169
  }
173
170
  });
174
171
  }
175
- /** checks if http data collection is enabled */
176
- function checkHttpDataCollectionEnabled() {
177
- const noibuConfig = ClientConfig.getInstance();
178
- // Just a boolean, so safe to return truthiness. If undefined, will return false.
179
- return !!noibuConfig.enableHttpDataCollection;
180
- }
181
- /** gets http data payload allowed URLs */
182
- function getHttpPayloadAllowedURLs() {
183
- const noibuConfig = ClientConfig.getInstance();
184
- // return the allowed list or an empty list
185
- if (noibuConfig.listOfUrlsToCollectHttpDataFrom &&
186
- Array.isArray(noibuConfig.listOfUrlsToCollectHttpDataFrom)) {
187
- return noibuConfig.listOfUrlsToCollectHttpDataFrom;
188
- }
189
- return [];
190
- }
191
- /**
192
- * Gets selectors to prevent those elements from being recorded
193
- */
194
- function getBlockedElements() {
195
- const selectors = ClientConfig.getInstance().blockedElements;
196
- const blockedElements = ['noibu-blocked'];
197
- if (selectors && Array.isArray(selectors)) {
198
- blockedElements.push(...selectors);
199
- }
200
- return blockedElements;
201
- }
202
172
  /**
203
173
  * makes sure the url sent is a valid URL
204
174
  */
@@ -277,27 +247,6 @@ function maskTextInput(text) {
277
247
  .replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING)
278
248
  .replace(PII_DIGIT_PATTERN, '*');
279
249
  }
280
- /**
281
- * gets the onURL of a string, defaulting to the location of the webpage
282
- */
283
- function getOnURL(realOnURL) {
284
- if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
285
- return asString(getMaxSubstringAllowed(realOnURL));
286
- }
287
- return AppNavigationMonitor.getInstance().globalUrl;
288
- }
289
- /** gets the user language from the browser */
290
- function getUserLanguage() {
291
- const locales = getLocales();
292
- if (!locales.length) {
293
- return null;
294
- }
295
- const lang = locales[0].languageCode;
296
- if (lang === '' || !lang) {
297
- return null;
298
- }
299
- return lang.toLowerCase();
300
- }
301
250
  /**
302
251
  * Checks if the provided object is an instance of the specified type.
303
252
  * It's safer than `instanceof` operator as it handles cases
@@ -312,4 +261,4 @@ function isInstanceOf(instance, type) {
312
261
  }
313
262
  }
314
263
 
315
- export { asString, checkHttpDataCollectionEnabled, getBlockedElements, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
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.7",
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,13 +25,12 @@
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
- "react-native-uuid": "^2.0.1",
34
- "react-native-localize": "^3.0.1"
33
+ "react-native-uuid": "^2.0.1"
35
34
  },
36
35
  "devDependencies": {
37
36
  "@rollup/plugin-commonjs": "^25.0.0",