noibu-react-native 0.2.6 → 0.2.8

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.
Files changed (114) hide show
  1. package/README.md +15 -15
  2. package/android/build.gradle +1 -1
  3. package/dist/{src/api/clientConfig.d.ts → api/ClientConfig.d.ts} +19 -20
  4. package/dist/api/{clientConfig.js → ClientConfig.js} +82 -63
  5. package/dist/{src/api/helpCode.d.ts → api/HelpCode.d.ts} +3 -10
  6. package/dist/api/{helpCode.js → HelpCode.js} +8 -14
  7. package/dist/api/InputManager.d.ts +39 -0
  8. package/dist/api/InputManager.js +156 -0
  9. package/dist/{src/api/metroplexSocket.d.ts → api/MetroplexSocket.d.ts} +33 -38
  10. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +190 -178
  11. package/dist/{src/api/storedMetrics.d.ts → api/StoredMetrics.d.ts} +10 -20
  12. package/dist/api/StoredMetrics.js +158 -0
  13. package/dist/{src/api/storedPageVisit.d.ts → api/StoredPageVisit.d.ts} +11 -8
  14. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +62 -48
  15. package/dist/const_matchers.js +1 -5
  16. package/dist/constants.d.ts +48 -0
  17. package/dist/constants.js +15 -397
  18. package/dist/{src/entry → entry}/index.d.ts +5 -6
  19. package/dist/entry/index.js +3 -4
  20. package/dist/entry/init.d.ts +8 -0
  21. package/dist/entry/init.js +34 -19
  22. package/dist/monitors/AppNavigationMonitor.d.ts +10 -0
  23. package/dist/monitors/AppNavigationMonitor.js +19 -19
  24. package/dist/monitors/AppNavigationMonitor.test.d.ts +1 -0
  25. package/dist/{src/monitors → monitors}/BaseMonitor.d.ts +5 -5
  26. package/dist/monitors/BaseMonitor.js +9 -4
  27. package/dist/monitors/BaseMonitor.test.d.ts +1 -0
  28. package/dist/{src/monitors → monitors}/ClickMonitor.d.ts +10 -13
  29. package/dist/monitors/ClickMonitor.js +72 -76
  30. package/dist/monitors/ClickMonitor.test.d.ts +1 -0
  31. package/dist/{src/monitors → monitors}/ErrorMonitor.d.ts +4 -28
  32. package/dist/monitors/ErrorMonitor.js +45 -55
  33. package/dist/{src/monitors → monitors}/KeyboardInputMonitor.d.ts +1 -3
  34. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  35. package/dist/{src/monitors → monitors}/PageMonitor.d.ts +1 -1
  36. package/dist/monitors/PageMonitor.js +25 -2
  37. package/dist/{src/monitors → monitors}/RequestMonitor.d.ts +9 -29
  38. package/dist/monitors/RequestMonitor.js +46 -57
  39. package/dist/monitors/http-tools/GqlErrorValidator.d.ts +35 -0
  40. package/dist/monitors/http-tools/GqlErrorValidator.js +42 -70
  41. package/dist/{src/monitors → monitors}/http-tools/HTTPDataBundler.d.ts +9 -15
  42. package/dist/monitors/http-tools/HTTPDataBundler.js +74 -67
  43. package/dist/monitors/integrations/ReactNativeNavigationIntegration.d.ts +17 -0
  44. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  45. package/dist/{src/pageVisit → pageVisit}/EventDebouncer.d.ts +9 -10
  46. package/dist/pageVisit/EventDebouncer.js +43 -74
  47. package/dist/pageVisit/HttpEventManager.d.ts +14 -0
  48. package/dist/pageVisit/HttpEventManager.js +88 -0
  49. package/dist/pageVisit/PageVisitManager.d.ts +31 -0
  50. package/dist/pageVisit/PageVisitManager.js +99 -0
  51. package/dist/pageVisit/pageVisitEventError.d.ts +12 -0
  52. package/dist/pageVisit/pageVisitEventError.js +170 -280
  53. package/dist/{src/react → react}/ErrorBoundary.d.ts +4 -9
  54. package/dist/react/ErrorBoundary.js +3 -6
  55. package/dist/{src/sessionRecorder/sessionRecorder.d.ts → sessionRecorder/SessionRecorder.d.ts} +7 -17
  56. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +60 -71
  57. package/dist/{src/sessionRecorder → sessionRecorder}/nativeSessionRecorderSubscription.d.ts +4 -6
  58. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  59. package/dist/{src/storage/rnStorageProvider.d.ts → storage/RNStorageProvider.d.ts} +4 -8
  60. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  61. package/dist/{src/storage/storage.d.ts → storage/Storage.d.ts} +8 -18
  62. package/dist/storage/{storage.js → Storage.js} +17 -30
  63. package/dist/{src/storage/storageProvider.d.ts → storage/StorageProvider.d.ts} +5 -8
  64. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  65. package/dist/types/NavigationIntegration.d.ts +1 -1
  66. package/dist/utils/date.d.ts +7 -0
  67. package/dist/utils/date.js +41 -51
  68. package/dist/utils/eventlistener.js +6 -14
  69. package/dist/{src/utils → utils}/function.d.ts +13 -43
  70. package/dist/utils/function.js +42 -113
  71. package/dist/utils/log.d.ts +4 -0
  72. package/dist/utils/log.js +2 -4
  73. package/dist/{src/utils → utils}/object.d.ts +10 -8
  74. package/dist/utils/object.js +12 -12
  75. package/dist/{src/utils → utils}/performance.d.ts +1 -1
  76. package/dist/utils/piiRedactor.js +31 -3
  77. package/dist/utils/stacktrace-parser.d.ts +8 -0
  78. package/dist/utils/stacktrace-parser.js +29 -21
  79. package/dist/utils/stacktrace-parser.test.d.ts +1 -0
  80. package/package.json +14 -14
  81. package/dist/api/inputManager.js +0 -227
  82. package/dist/api/storedMetrics.js +0 -198
  83. package/dist/pageVisit/pageVisit.js +0 -181
  84. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  85. package/dist/pageVisit/userStep.js +0 -20
  86. package/dist/src/api/inputManager.d.ts +0 -87
  87. package/dist/src/constants.d.ts +0 -290
  88. package/dist/src/entry/init.d.ts +0 -5
  89. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  90. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  91. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  92. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  93. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  94. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  95. package/dist/src/pageVisit/userStep.d.ts +0 -5
  96. package/dist/src/utils/date.d.ts +0 -6
  97. package/dist/src/utils/log.d.ts +0 -4
  98. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  99. package/dist/types/Config.d.ts +0 -31
  100. package/dist/types/Metroplex.types.d.ts +0 -73
  101. package/dist/types/PageVisit.types.d.ts +0 -8
  102. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  103. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  104. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  105. package/dist/types/Storage.d.ts +0 -14
  106. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  107. package/dist/types/WrappedObjects.d.ts +0 -6
  108. /package/dist/{src/api/clientConfig.test.d.ts → api/ClientConfig.test.d.ts} +0 -0
  109. /package/dist/{src/monitors/BaseMonitor.test.d.ts → api/MetroplexSocket.test.d.ts} +0 -0
  110. /package/dist/{src/const_matchers.d.ts → const_matchers.d.ts} +0 -0
  111. /package/dist/{src/sessionRecorder → sessionRecorder}/types.d.ts +0 -0
  112. /package/dist/{src/utils → utils}/eventlistener.d.ts +0 -0
  113. /package/dist/{src/utils → utils}/piiRedactor.d.ts +0 -0
  114. /package/dist/{src/utils → utils}/polyfills.d.ts +0 -0
@@ -1,42 +1,42 @@
1
- import { SEVERITY, APP_NAVIGATION_EVENT_TYPE } from '../constants.js';
2
- import { ReactNativeNavigationIntegration } from './integrations/react-native-navigation-integration.js';
3
- import ClientConfig from '../api/clientConfig.js';
1
+ import { ReactNativeNavigationIntegration } from './integrations/ReactNativeNavigationIntegration.js';
2
+ import ClientConfig from '../api/ClientConfig.js';
4
3
  import { EventDebouncer } from '../pageVisit/EventDebouncer.js';
5
4
  import { Singleton } from './BaseMonitor.js';
5
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
6
+ import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
7
+ import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
6
8
 
7
- /**
8
- * Attaches corresponding listener to the passed navigation integration
9
- */
9
+ /** Attaches corresponding listener to the passed navigation integration */
10
10
  class AppNavigationMonitor extends Singleton {
11
- /**
12
- * Main method for starting the monitoring
13
- */
11
+ /** Main method for starting the monitoring */
14
12
  monitor() {
15
13
  try {
16
14
  // eslint-disable-next-line @typescript-eslint/no-var-requires
17
15
  const Navigation = require('react-native-navigation');
18
16
  const rnNavigation = Navigation === null || Navigation === void 0 ? void 0 : Navigation.Navigation;
19
17
  if (rnNavigation) {
20
- new ReactNativeNavigationIntegration().register(rnNavigation, AppNavigationMonitor.onNavigation);
18
+ ReactNativeNavigationIntegration.getInstance().register(rnNavigation, AppNavigationMonitor.onNavigation);
21
19
  }
22
20
  }
23
21
  catch (e) {
24
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`AppNavigationMonitor: ${e}`, false, SEVERITY.error);
22
+ ClientConfig.getInstance().postInternalError({
23
+ msg: `Error while trying to attach to navigation events`,
24
+ error: e,
25
+ }, false, Severity.ERROR);
25
26
  }
26
27
  }
27
- /**
28
- * handler for updating navigation breadcrumbs and notifying metro of location change
29
- */
28
+ /** handler for updating navigation breadcrumbs and notifying metro of location change */
30
29
  static onNavigation(breadcrumbs) {
31
30
  ClientConfig.getInstance().currentLocationBreadcrumbs = breadcrumbs;
32
31
  AppNavigationMonitor.reportLocationChange(breadcrumbs.pop());
33
32
  }
34
- /**
35
- * Called when the event needs to be emitted
36
- */
33
+ /** Called when the event needs to be emitted */
37
34
  static reportLocationChange(currentLocation) {
38
- const payload = { location: currentLocation || '' };
39
- EventDebouncer.getInstance().addEvent(payload, APP_NAVIGATION_EVENT_TYPE);
35
+ const event = {
36
+ app_nav: { location: currentLocation || '' },
37
+ type: EventType.ApplicationNavigation,
38
+ };
39
+ EventDebouncer.getInstance().debounce(event);
40
40
  }
41
41
  }
42
42
 
@@ -0,0 +1 @@
1
+ export {};
@@ -1,13 +1,13 @@
1
1
  export interface Monitor {
2
2
  monitor(): void;
3
3
  }
4
- /**
5
- * Singleton pattern with our flavor
6
- */
4
+ /** Singleton pattern with our flavor */
7
5
  export declare abstract class Singleton {
8
6
  private static instances;
9
7
  /** returns singleton instance */
10
- static getInstance<T extends Singleton, A extends any[]>(this: new (...args: A) => T, ...args: A): T;
8
+ static getInstance<T extends Singleton, A extends any[]>(this: new (...args: A) => T, ...args: ConstructorParameters<new (...args: A) => T>): T;
9
+ /** Destructor */
10
+ protected destroy(): void;
11
11
  /** used for testing only */
12
- protected resetInstances(): void;
12
+ private static resetInstances;
13
13
  }
@@ -1,8 +1,6 @@
1
1
  import { noibuLog } from '../utils/log.js';
2
2
 
3
- /**
4
- * Singleton pattern with our flavor
5
- */
3
+ /** Singleton pattern with our flavor */
6
4
  class Singleton {
7
5
  /** returns singleton instance */
8
6
  static getInstance(...args) {
@@ -13,8 +11,15 @@ class Singleton {
13
11
  }
14
12
  return Singleton.instances.get(this);
15
13
  }
14
+ /** Destructor */
15
+ destroy() {
16
+ // implement in subclasses if needed
17
+ }
16
18
  /** used for testing only */
17
- resetInstances() {
19
+ static resetInstances() {
20
+ Singleton.instances.forEach(instance => {
21
+ instance.destroy();
22
+ });
18
23
  Singleton.instances.clear();
19
24
  }
20
25
  }
@@ -0,0 +1 @@
1
+ export {};
@@ -4,28 +4,25 @@ import { Monitor, Singleton } from './BaseMonitor';
4
4
  export declare class ClickMonitor extends Singleton implements Monitor {
5
5
  private static textCapturedWhiteListRegex;
6
6
  private static htmlIDAllowListRegex;
7
- private static originalCreateEventHandlers;
8
7
  /** Starts monitoring clicks on every Press-able component */
9
8
  monitor(): void;
10
- /**
11
- * Handles a single click event
12
- */
9
+ /** Handles a single click event */
13
10
  private static onClickHandle;
14
11
  /** Gets the textual content from an element, if any
15
12
  */
16
13
  private static getTextualContentFromEl;
17
14
  /** Parse and trim text */
18
15
  private static trimText;
19
- /**
20
- * Recursively parses element's inner content and masks blocked css classes
21
- */
16
+ /** gets id */
17
+ private static getHid;
18
+ /** gets tag name */
19
+ private static getTagName;
20
+ /** Recursively parses element's inner content and masks blocked css classes */
22
21
  private static parseInnerContent;
23
- /**
24
- * Gets selectors to prevent those elements from being recorded
25
- */
22
+ /** Gets selectors to prevent those elements from being recorded */
26
23
  private static getBlockedElements;
27
- /**
28
- * normalize value and append to the resulting text if not empty
29
- */
24
+ /** normalize value and append to the resulting text if not empty */
30
25
  private static parseAndAppendText;
26
+ /** Destructs instance */
27
+ destroy(this: Singleton): void;
31
28
  }
@@ -1,95 +1,85 @@
1
1
  import Pressability from 'react-native/Libraries/Pressability/Pressability';
2
- import { WHITELIST_HTML_ID_TEXT_REGEX, USERSTEP_EVENT_TYPE, SOURCE_ATT_NAME, TEXT_ATT_NAME, TAGNAME_ATT_NAME, HTMLID_ATT_NAME, TYPE_ATT_NAME, CLICK_EVENT_TYPE, CSS_CLASS_ATT_NAME } from '../constants.js';
3
- import { PageVisit } from '../pageVisit/pageVisit.js';
4
- import { updatePayload } from '../pageVisit/userStep.js';
5
- import StoredMetrics from '../api/storedMetrics.js';
2
+ import { PageVisitManager } from '../pageVisit/PageVisitManager.js';
3
+ import StoredMetrics from '../api/StoredMetrics.js';
6
4
  import { WHITELIST_TEXT_REGEX_STRING } from '../const_matchers.js';
7
5
  import { maskTextInput } from '../utils/function.js';
8
- import { timestampWrapper } from '../utils/date.js';
9
- import ClientConfig from '../api/clientConfig.js';
6
+ import ClientConfig from '../api/ClientConfig.js';
10
7
  import { Singleton } from './BaseMonitor.js';
8
+ import { isNoibuWrapped, replace, unwrapNoibuWrapped } from '../utils/object.js';
9
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
10
+ import { UserStepType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/UserStepType.js';
11
+ import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
11
12
 
12
13
  /** @module ClickMonitor */
14
+ /**
15
+ * will return a regex that will match
16
+ * any keywords that may indicate that users are moving
17
+ * forward in the sales funnel. It will match add to cart, checkout,
18
+ * and any other relevant text.
19
+ * INFO: WHEN ARCEE CHANGES THE REGEX PATTERN, THIS NEEDS TO CHANGE TOO
20
+ * will return a regex that will match
21
+ * any keywords that may indicate that users are moving
22
+ * forward in the sales funnel. It will match add to cart, checkout,
23
+ * and any other relevant text.
24
+ * INFO: WHEN ARCEE CHANGES THE REGEX PATERN, THIS NEEDS TO CHANGE TOO
25
+ * text that have this id will not be masked, change arcee/src/models/websessions/pv_event.rs
26
+ */
27
+ const WHITELIST_HTML_ID_TEXT_REGEX = 'method|finance|sagepay|cart|bag|coupon|affirm|karna|sezzle|button';
13
28
  /** Monitors the clicks which we capture and later process */
14
29
  class ClickMonitor extends Singleton {
15
30
  /** Starts monitoring clicks on every Press-able component */
16
31
  monitor() {
17
- if (!ClickMonitor.originalCreateEventHandlers) {
18
- ClickMonitor.originalCreateEventHandlers =
19
- Pressability.prototype.getEventHandlers;
20
- /**
21
- * Proxies prototype method
22
- */
23
- Pressability.prototype.getEventHandlers = function () {
24
- const ehs = ClickMonitor.originalCreateEventHandlers.call(this);
25
- return Object.fromEntries(Object.entries(ehs).map(([key, handler]) => [
26
- key,
27
- (event) => {
28
- if (key === 'onResponderRelease') {
29
- ClickMonitor.onClickHandle(event);
30
- }
31
- return handler(event);
32
- },
33
- ]));
34
- };
32
+ if (isNoibuWrapped(Pressability.prototype.getEventHandlers)) {
33
+ return;
35
34
  }
35
+ replace(Pressability.prototype, 'getEventHandlers', function (original) {
36
+ return function nbuWrapper() {
37
+ const ehs = original.call(this);
38
+ return Object.assign(Object.assign({}, ehs), { onResponderRelease: function nbuWrapper(event) {
39
+ ClientConfig.getInstance().wrapInternal('ClickMonitor.onClickHandle', () => ClickMonitor.onClickHandle(event));
40
+ return ehs.onResponderRelease(event);
41
+ } });
42
+ };
43
+ });
36
44
  }
37
- /**
38
- * Handles a single click event
39
- */
45
+ /** Handles a single click event */
40
46
  static onClickHandle(event) {
41
47
  if (event) {
42
48
  const { _targetInst: target } = event;
43
- const targetClassName = target.elementType;
44
- // if the tag name of the src element is image, then we need
45
- // to process the image name, else we need to get the textual content
46
- // todo process images
47
- const text = ClickMonitor.getTextualContentFromEl(target);
48
- let textFromElement = ClickMonitor.trimText(text);
49
- let tagName = '';
50
- if (typeof targetClassName === 'string') {
51
- tagName = targetClassName.toLowerCase();
52
- }
53
- // id of element
54
- let hid = target.memoizedProps.testID || '';
55
- // in some bizarre cases, the html id of an element gets overriden
56
- // to contain jquery objects. If the hid is an object, it's of no
57
- // use to us.
58
- if (typeof hid !== 'string') {
59
- hid = '';
49
+ if (!target) {
50
+ return;
60
51
  }
52
+ const tag = this.getTagName(target);
53
+ const hid = this.getHid(target);
54
+ let textFromElement = ClickMonitor.trimText(ClickMonitor.getTextualContentFromEl(target));
61
55
  // if we find that the text matches analytic data used
62
56
  // to find checkout starts, add to cart clicks, etc.
63
57
  // we do not mask it.
64
58
  if (!ClickMonitor.textCapturedWhiteListRegex.test(textFromElement) &&
65
59
  !ClickMonitor.htmlIDAllowListRegex.test(hid)) {
66
- if (tagName === 'input') {
67
- if (event.type &&
68
- (event.type === 'button' || event.type === 'submit')) ;
60
+ if (tag === 'input') {
61
+ if (event.type && (event.type === 'button' || event.type === 'submit')) ;
69
62
  else {
70
63
  textFromElement = '*';
71
64
  }
72
65
  }
73
- else if (tagName === 'textarea') {
66
+ else if (tag === 'textarea') {
74
67
  textFromElement = '*';
75
68
  }
76
69
  }
77
- textFromElement = maskTextInput(textFromElement);
78
70
  const tPayload = {
79
- [SOURCE_ATT_NAME]: '',
80
- [TEXT_ATT_NAME]: textFromElement,
81
- [TAGNAME_ATT_NAME]: tagName,
82
- [HTMLID_ATT_NAME]: hid,
83
- [TYPE_ATT_NAME]: CLICK_EVENT_TYPE,
84
- [CSS_CLASS_ATT_NAME]: '',
71
+ src: '',
72
+ txt: maskTextInput(textFromElement),
73
+ tag,
74
+ hid,
75
+ type: UserStepType.Click,
76
+ class: '',
85
77
  };
86
78
  StoredMetrics.getInstance().addPvClick();
87
- PageVisit.getInstance().addPageVisitEvents([
88
- {
89
- event: updatePayload(tPayload),
90
- occurredAt: new Date(timestampWrapper(Date.now())).toISOString(),
91
- },
92
- ], USERSTEP_EVENT_TYPE);
79
+ PageVisitManager.getInstance().addPageVisitEvent({
80
+ type: EventType.UserStep,
81
+ userstep: tPayload,
82
+ });
93
83
  }
94
84
  }
95
85
  /** Gets the textual content from an element, if any
@@ -122,12 +112,18 @@ class ClickMonitor extends Singleton {
122
112
  }
123
113
  return parsedText;
124
114
  }
125
- /**
126
- * Recursively parses element's inner content and masks blocked css classes
127
- */
115
+ /** gets id */
116
+ static getHid(element) {
117
+ var _a;
118
+ const hid = (_a = element.memoizedProps) === null || _a === void 0 ? void 0 : _a.testID;
119
+ return typeof hid === 'string' ? hid : '';
120
+ }
121
+ /** gets tag name */
122
+ static getTagName(element) {
123
+ return typeof element.elementType === 'string' ? element.elementType.toLowerCase() : '';
124
+ }
125
+ /** Recursively parses element's inner content and masks blocked css classes */
128
126
  static parseInnerContent(element, text, textLimit, counter) {
129
- /* eslint-disable no-restricted-syntax */
130
- /* eslint-disable no-param-reassign */
131
127
  if (text.length >= textLimit) {
132
128
  return text;
133
129
  }
@@ -135,7 +131,7 @@ class ClickMonitor extends Singleton {
135
131
  return text;
136
132
  }
137
133
  counter.value += 1;
138
- if (ClickMonitor.getBlockedElements().includes(element.memoizedProps.testID)) {
134
+ if (ClickMonitor.getBlockedElements().includes(this.getHid(element))) {
139
135
  return `${text}${text ? ' ' : ''}*`;
140
136
  }
141
137
  // eslint-disable-next-line require-jsdoc
@@ -146,9 +142,7 @@ class ClickMonitor extends Singleton {
146
142
  ((_a = node.elementType) === null || _a === void 0 ? void 0 : _a.displayName) === 'Text' &&
147
143
  node.memoizedProps &&
148
144
  typeof node.memoizedProps.children === 'string') {
149
- text = ClickMonitor.parseAndAppendText(text, [
150
- node.memoizedProps.children,
151
- ]);
145
+ text = ClickMonitor.parseAndAppendText(text, [node.memoizedProps.children]);
152
146
  if (text.length >= textLimit)
153
147
  return;
154
148
  }
@@ -162,9 +156,7 @@ class ClickMonitor extends Singleton {
162
156
  walk(element);
163
157
  return text;
164
158
  }
165
- /**
166
- * Gets selectors to prevent those elements from being recorded
167
- */
159
+ /** Gets selectors to prevent those elements from being recorded */
168
160
  static getBlockedElements() {
169
161
  const selectors = ClientConfig.getInstance().blockedElements;
170
162
  const blockedElements = ['noibu-blocked'];
@@ -173,9 +165,7 @@ class ClickMonitor extends Singleton {
173
165
  }
174
166
  return blockedElements;
175
167
  }
176
- /**
177
- * normalize value and append to the resulting text if not empty
178
- */
168
+ /** normalize value and append to the resulting text if not empty */
179
169
  static parseAndAppendText(text, values) {
180
170
  const goodValues = [];
181
171
  for (const v of values) {
@@ -191,6 +181,12 @@ class ClickMonitor extends Singleton {
191
181
  }
192
182
  return text;
193
183
  }
184
+ /** Destructs instance */
185
+ destroy() {
186
+ if (isNoibuWrapped(Pressability.prototype.getEventHandlers)) {
187
+ Pressability.prototype.getEventHandlers = unwrapNoibuWrapped(Pressability.prototype.getEventHandlers);
188
+ }
189
+ }
194
190
  }
195
191
  ClickMonitor.textCapturedWhiteListRegex = new RegExp(WHITELIST_TEXT_REGEX_STRING(), 'i');
196
192
  ClickMonitor.htmlIDAllowListRegex = new RegExp(WHITELIST_HTML_ID_TEXT_REGEX, 'i');
@@ -0,0 +1 @@
1
+ export {};
@@ -1,32 +1,16 @@
1
1
  import { Monitor, Singleton } from './BaseMonitor';
2
- type WrappedFunction<T extends Function = Function> = T & Partial<{
3
- __noibu__: boolean;
4
- __noibu_wrapped__: T;
5
- }>;
6
- /**
7
- * wraps a provided function into a function that try and catches
8
- * the original function, doing so allows us to catch errors
9
- * functionToWrap: function to be wrapped
10
- * @param {} functionToWrap
11
- */
12
- export declare function wrap(functionToWrap: WrappedFunction): Function;
13
- /**
14
- * Monitors the errors happening on the window
15
- */
2
+ /** Monitors the errors happening on the window */
16
3
  export declare class ErrorMonitor extends Singleton implements Monitor {
4
+ static preventInfiniteLoopFlag: boolean;
17
5
  /** base method */
18
6
  monitor(): void;
19
7
  /** proxy error utils */
20
8
  private static configureErrorUtilsHandler;
21
- /**
22
- * Handles a single error event
23
- */
9
+ /** Handles a single error event */
24
10
  private static onErrorHandler;
25
11
  /** proxy hermes engine */
26
12
  private static configureHermesHooks;
27
- /**
28
- * handler for promise rejection failures
29
- */
13
+ /** handler for promise rejection failures */
30
14
  private static onPromiseRejectionHandler;
31
15
  /**
32
16
  * wraps and replaces the addEventListener property
@@ -45,19 +29,11 @@ export declare class ErrorMonitor extends Singleton implements Monitor {
45
29
  * it maps the stack traces to objects with their respective first lines as messages.
46
30
  * Otherwise, if there is exactly one stack trace and one error message,
47
31
  * it constructs an array with a single object containing the first stack trace and the first error message.
48
- * @param {Array<string>} args
49
32
  */
50
33
  private static constructErrors;
51
- /**
52
- * returns boolean that indicates wether we should
53
- * ignore the next error event caught by the error event
54
- * listener.
55
- */
56
- private static shouldIgnoreError;
57
34
  /**
58
35
  * transform a log into an error since React hides component errors
59
36
  * https://reactjs.org/docs/error-boundaries.html
60
37
  */
61
38
  private static processErrorLog;
62
39
  }
63
- export {};
@@ -1,15 +1,16 @@
1
1
  import { asString, isStackTrace } from '../utils/function.js';
2
- import { ERROR_EVENT_ERROR_TYPE, STACK_TRACE_SANITIZE_REGEXP, ERROR_EVENT_UNHANDLED_REJECTION_TYPE, CONSOLE_FUNCTION_OVERRIDES, ERROR_LOG_EVENT_ERROR_TYPE } from '../constants.js';
3
2
  import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError.js';
4
3
  import { replace } from '../utils/object.js';
5
4
  import { Singleton } from './BaseMonitor.js';
5
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
6
+ import ClientConfig from '../api/ClientConfig.js';
7
+ import { PageVisitErrorSource } from '../node_modules/@noibu/metroplex-ts-bindings/dist/PageVisitErrorSource.js';
6
8
 
7
9
  /* eslint-disable @typescript-eslint/ban-types,prefer-arrow-callback */
8
10
  /** @module ErrorMonitor */
9
- let ignoreError = 0;
10
- /**
11
- * Monitors the errors happening on the window
12
- */
11
+ // console functions that we override to capture errors
12
+ const CONSOLE_FUNCTION_OVERRIDES = ['error', 'warn', 'log'];
13
+ /** Monitors the errors happening on the window */
13
14
  class ErrorMonitor extends Singleton {
14
15
  /** base method */
15
16
  monitor() {
@@ -30,16 +31,14 @@ class ErrorMonitor extends Singleton {
30
31
  }
31
32
  });
32
33
  }
33
- /**
34
- * Handles a single error event
35
- */
34
+ /** Handles a single error event */
36
35
  static onErrorHandler(error) {
37
- if (!error || ErrorMonitor.shouldIgnoreError()) {
36
+ if (!error || ErrorMonitor.preventInfiniteLoopFlag) {
38
37
  return;
39
38
  }
40
- saveErrorToPagevisit(ERROR_EVENT_ERROR_TYPE, {
41
- error,
42
- });
39
+ ErrorMonitor.preventInfiniteLoopFlag = true;
40
+ saveErrorToPagevisit({ error, type: PageVisitErrorSource.ErrorEvent });
41
+ ErrorMonitor.preventInfiniteLoopFlag = false;
43
42
  }
44
43
  /** proxy hermes engine */
45
44
  static configureHermesHooks() {
@@ -48,42 +47,42 @@ class ErrorMonitor extends Singleton {
48
47
  (_a = HermesInternal.enablePromiseRejectionTracker) === null || _a === void 0 ? void 0 : _a.call(HermesInternal, {
49
48
  allRejections: true,
50
49
  });
51
- /**
52
- * This internal promise implementation method is populated only after enabling the promise tracker.
53
- * It represents an improvement over the previous approach,
54
- * which would lose stack context regarding the rejection because it ran asynchronously through setTimeout.
55
- *
56
- * This updated method ensures synchronous error capturing and retrieves the correct stack frames.
57
- */
58
- replace(Promise, '_m', (originalFunction) => function nbuGlobalPromiseRejectWrapper(promise, error) {
59
- if (error.message && error.stack) {
60
- ErrorMonitor.onPromiseRejectionHandler(error);
61
- }
62
- else {
63
- ErrorMonitor.onPromiseRejectionHandler(new Error(asString(error)));
50
+ }
51
+ /**
52
+ * This internal promise implementation method is populated only after enabling the promise tracker.
53
+ * It represents an improvement over the previous approach,
54
+ * which would lose stack context regarding the rejection because it ran asynchronously through setTimeout.
55
+ *
56
+ * This updated method ensures synchronous error capturing and retrieves the correct stack frames.
57
+ */
58
+ replace(Promise, '_m', (originalFunction) => function nbuGlobalPromiseRejectWrapper(promise, error) {
59
+ ClientConfig.getInstance().wrapInternal('ErrorMonitor.configureHermesHooks', () => {
60
+ switch (true) {
61
+ case !!(error.message && error.stack): {
62
+ ErrorMonitor.onPromiseRejectionHandler(error);
63
+ break;
64
+ }
65
+ default: {
66
+ ErrorMonitor.onPromiseRejectionHandler(new Error(asString(error)));
67
+ break;
68
+ }
64
69
  }
65
- return originalFunction === null || originalFunction === void 0 ? void 0 : originalFunction(promise, error);
66
70
  });
67
- }
71
+ return originalFunction === null || originalFunction === void 0 ? void 0 : originalFunction(promise, error);
72
+ });
68
73
  }
69
- /**
70
- * handler for promise rejection failures
71
- */
74
+ /** handler for promise rejection failures */
72
75
  static onPromiseRejectionHandler(error) {
73
- if (!error || !error.message || !error.stack) {
76
+ if (!error || !error.stack || ErrorMonitor.preventInfiniteLoopFlag) {
74
77
  return;
75
78
  }
76
- const sanitizedStack = error.stack
77
- .split('\n')
78
- .filter(line => !line.match(STACK_TRACE_SANITIZE_REGEXP))
79
- .join('\n');
79
+ ErrorMonitor.preventInfiniteLoopFlag = true;
80
80
  const payload = {
81
- error: {
82
- message: error.message,
83
- stack: sanitizedStack,
84
- },
81
+ error,
82
+ type: PageVisitErrorSource.UnhandledRejectionError,
85
83
  };
86
- saveErrorToPagevisit(ERROR_EVENT_UNHANDLED_REJECTION_TYPE, payload);
84
+ saveErrorToPagevisit(payload);
85
+ ErrorMonitor.preventInfiniteLoopFlag = false;
87
86
  }
88
87
  /**
89
88
  * wraps and replaces the addEventListener property
@@ -101,13 +100,12 @@ class ErrorMonitor extends Singleton {
101
100
  // the trace message will start with nbuWrapper which would allow us to
102
101
  // detect that this is a wrapped function and not a NoibuJS error
103
102
  return function nbuWrapper() {
104
- // ignoring this linting error since we don't want
105
- // potentially overide the actual functioning of console.error
103
+ ClientConfig.getInstance().wrapInternal('ErrorMonitor.configureEventListeners', () => {
104
+ // eslint-disable-next-line prefer-rest-params
105
+ ErrorMonitor.processErrorLogArguments(Array.from(arguments));
106
+ });
106
107
  // eslint-disable-next-line prefer-rest-params
107
108
  originalFunction.call(window.console, ...arguments);
108
- // converting the arguments to an array so that we do not nest argument objects
109
- // eslint-disable-next-line prefer-rest-params
110
- ErrorMonitor.processErrorLogArguments(Array.from(arguments));
111
109
  };
112
110
  });
113
111
  });
@@ -144,7 +142,6 @@ class ErrorMonitor extends Singleton {
144
142
  * it maps the stack traces to objects with their respective first lines as messages.
145
143
  * Otherwise, if there is exactly one stack trace and one error message,
146
144
  * it constructs an array with a single object containing the first stack trace and the first error message.
147
- * @param {Array<string>} args
148
145
  */
149
146
  static constructErrors(args) {
150
147
  if (args.length === 0) {
@@ -176,14 +173,6 @@ class ErrorMonitor extends Singleton {
176
173
  });
177
174
  return stacks.map((stack, i) => ({ stack, message: messages[i] }));
178
175
  }
179
- /**
180
- * returns boolean that indicates wether we should
181
- * ignore the next error event caught by the error event
182
- * listener.
183
- */
184
- static shouldIgnoreError() {
185
- return ignoreError > 0;
186
- }
187
176
  /**
188
177
  * transform a log into an error since React hides component errors
189
178
  * https://reactjs.org/docs/error-boundaries.html
@@ -198,9 +187,10 @@ class ErrorMonitor extends Singleton {
198
187
  if (!stack || !message) {
199
188
  return false;
200
189
  }
201
- saveErrorToPagevisit(ERROR_LOG_EVENT_ERROR_TYPE, { message, stack });
190
+ saveErrorToPagevisit({ message, stack, type: PageVisitErrorSource.ErrorLogEvent });
202
191
  return true;
203
192
  }
204
193
  }
194
+ ErrorMonitor.preventInfiniteLoopFlag = false;
205
195
 
206
196
  export { ErrorMonitor };
@@ -10,9 +10,7 @@ export declare class KeyboardInputMonitor extends Singleton implements Monitor {
10
10
  * we currently only monitor two input locations: textarea and input
11
11
  */
12
12
  monitor(): void;
13
- /**
14
- * Validates an event
15
- */
13
+ /** Validates an event */
16
14
  static handle(uiViewClassName: string, props: {
17
15
  placeholder?: string;
18
16
  testID?: string;