noibu-react-native 0.2.5 → 0.2.7
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 +15 -15
- package/android/build.gradle +1 -1
- package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
- package/dist/api/{helpCode.js → HelpCode.js} +6 -13
- package/dist/api/InputManager.js +156 -0
- package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
- package/dist/api/StoredMetrics.js +158 -0
- package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
- package/dist/const_matchers.js +1 -5
- package/dist/constants.js +15 -390
- package/dist/entry/index.js +3 -4
- package/dist/entry/init.js +33 -19
- package/dist/monitors/AppNavigationMonitor.js +19 -19
- package/dist/monitors/BaseMonitor.js +9 -4
- package/dist/monitors/ClickMonitor.js +72 -76
- package/dist/monitors/ErrorMonitor.js +45 -55
- package/dist/monitors/KeyboardInputMonitor.js +13 -11
- package/dist/monitors/PageMonitor.js +25 -2
- package/dist/monitors/RequestMonitor.js +46 -57
- package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
- package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
- package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
- package/dist/pageVisit/EventDebouncer.js +43 -74
- package/dist/pageVisit/HttpEventManager.js +88 -0
- package/dist/pageVisit/PageVisitManager.js +99 -0
- package/dist/pageVisit/pageVisitEventError.js +170 -280
- package/dist/react/ErrorBoundary.js +3 -6
- package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
- package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
- package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
- package/dist/storage/{storage.js → Storage.js} +17 -30
- package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
- package/dist/utils/date.js +39 -50
- package/dist/utils/eventlistener.js +5 -12
- package/dist/utils/function.js +42 -113
- package/dist/utils/log.js +5 -5
- package/dist/utils/object.js +12 -12
- package/dist/utils/piiRedactor.js +31 -3
- package/dist/utils/stacktrace-parser.js +29 -21
- package/package.json +14 -14
- package/dist/api/inputManager.js +0 -227
- package/dist/api/storedMetrics.js +0 -198
- package/dist/pageVisit/pageVisit.js +0 -181
- package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
- package/dist/pageVisit/userStep.js +0 -20
- package/dist/src/api/clientConfig.d.ts +0 -100
- package/dist/src/api/clientConfig.test.d.ts +0 -1
- package/dist/src/api/helpCode.d.ts +0 -23
- package/dist/src/api/inputManager.d.ts +0 -87
- package/dist/src/api/metroplexSocket.d.ts +0 -137
- package/dist/src/api/storedMetrics.d.ts +0 -73
- package/dist/src/api/storedPageVisit.d.ts +0 -40
- package/dist/src/const_matchers.d.ts +0 -1
- package/dist/src/constants.d.ts +0 -290
- package/dist/src/entry/index.d.ts +0 -14
- package/dist/src/entry/init.d.ts +0 -5
- package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
- package/dist/src/monitors/BaseMonitor.d.ts +0 -13
- package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
- package/dist/src/monitors/ClickMonitor.d.ts +0 -31
- package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
- package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
- package/dist/src/monitors/PageMonitor.d.ts +0 -20
- package/dist/src/monitors/RequestMonitor.d.ts +0 -94
- package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
- package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
- package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
- package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
- package/dist/src/pageVisit/pageVisit.d.ts +0 -52
- package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
- package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
- package/dist/src/pageVisit/userStep.d.ts +0 -5
- package/dist/src/react/ErrorBoundary.d.ts +0 -72
- package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
- package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
- package/dist/src/sessionRecorder/types.d.ts +0 -91
- package/dist/src/storage/rnStorageProvider.d.ts +0 -23
- package/dist/src/storage/storage.d.ts +0 -39
- package/dist/src/storage/storageProvider.d.ts +0 -26
- package/dist/src/utils/date.d.ts +0 -6
- package/dist/src/utils/eventlistener.d.ts +0 -8
- package/dist/src/utils/function.d.ts +0 -102
- package/dist/src/utils/log.d.ts +0 -4
- package/dist/src/utils/object.d.ts +0 -44
- package/dist/src/utils/performance.d.ts +0 -6
- package/dist/src/utils/piiRedactor.d.ts +0 -11
- package/dist/src/utils/polyfills.d.ts +0 -4
- package/dist/src/utils/stacktrace-parser.d.ts +0 -7
- package/dist/types/Config.d.ts +0 -31
- package/dist/types/Metroplex.types.d.ts +0 -73
- package/dist/types/NavigationIntegration.d.ts +0 -6
- package/dist/types/PageVisit.types.d.ts +0 -8
- package/dist/types/PageVisitErrors.types.d.ts +0 -114
- package/dist/types/PageVisitEvents.types.d.ts +0 -91
- package/dist/types/PageVisitMetrics.types.d.ts +0 -27
- package/dist/types/Storage.d.ts +0 -14
- package/dist/types/StoredPageVisit.types.d.ts +0 -11
- package/dist/types/WrappedObjects.d.ts +0 -6
|
@@ -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
|
}
|
|
@@ -1,95 +1,85 @@
|
|
|
1
1
|
import Pressability from 'react-native/Libraries/Pressability/Pressability';
|
|
2
|
-
import {
|
|
3
|
-
import
|
|
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
|
|
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 (
|
|
18
|
-
|
|
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
|
-
|
|
44
|
-
|
|
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 (
|
|
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 (
|
|
66
|
+
else if (tag === 'textarea') {
|
|
74
67
|
textFromElement = '*';
|
|
75
68
|
}
|
|
76
69
|
}
|
|
77
|
-
textFromElement = maskTextInput(textFromElement);
|
|
78
70
|
const tPayload = {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
71
|
+
src: '',
|
|
72
|
+
txt: maskTextInput(textFromElement),
|
|
73
|
+
tag,
|
|
74
|
+
hid,
|
|
75
|
+
type: UserStepType.Click,
|
|
76
|
+
class: '',
|
|
85
77
|
};
|
|
86
78
|
StoredMetrics.getInstance().addPvClick();
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
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
|
-
|
|
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
|
|
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');
|
|
@@ -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
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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.
|
|
36
|
+
if (!error || ErrorMonitor.preventInfiniteLoopFlag) {
|
|
38
37
|
return;
|
|
39
38
|
}
|
|
40
|
-
|
|
41
|
-
|
|
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
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
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.
|
|
76
|
+
if (!error || !error.stack || ErrorMonitor.preventInfiniteLoopFlag) {
|
|
74
77
|
return;
|
|
75
78
|
}
|
|
76
|
-
|
|
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
|
-
|
|
83
|
-
stack: sanitizedStack,
|
|
84
|
-
},
|
|
81
|
+
error,
|
|
82
|
+
type: PageVisitErrorSource.UnhandledRejectionError,
|
|
85
83
|
};
|
|
86
|
-
saveErrorToPagevisit(
|
|
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
|
-
|
|
105
|
-
|
|
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(
|
|
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 };
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { updatePayload } from '../pageVisit/userStep.js';
|
|
2
|
-
import { SOURCE_ATT_NAME, TEXT_ATT_NAME, TAGNAME_ATT_NAME, TYPE_ATT_NAME, KEYBOARD_EVENT_TYPE } from '../constants.js';
|
|
3
1
|
import { EventDebouncer } from '../pageVisit/EventDebouncer.js';
|
|
4
2
|
import { TextInput } from 'react-native';
|
|
5
3
|
import { Singleton } from './BaseMonitor.js';
|
|
4
|
+
import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
5
|
+
import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
|
|
6
|
+
import { UserStepType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/UserStepType.js';
|
|
6
7
|
|
|
7
8
|
/** @module KeyboardInputMonitor */
|
|
8
9
|
/**
|
|
@@ -37,9 +38,7 @@ class KeyboardInputMonitor extends Singleton {
|
|
|
37
38
|
};
|
|
38
39
|
}
|
|
39
40
|
}
|
|
40
|
-
/**
|
|
41
|
-
* Validates an event
|
|
42
|
-
*/
|
|
41
|
+
/** Validates an event */
|
|
43
42
|
static handle(uiViewClassName, props) {
|
|
44
43
|
if (!/(text|input)/i.test(uiViewClassName)) {
|
|
45
44
|
return;
|
|
@@ -48,12 +47,15 @@ class KeyboardInputMonitor extends Singleton {
|
|
|
48
47
|
if (!name) {
|
|
49
48
|
return;
|
|
50
49
|
}
|
|
51
|
-
EventDebouncer.getInstance().
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
50
|
+
EventDebouncer.getInstance().debounce({
|
|
51
|
+
type: EventType.UserStep,
|
|
52
|
+
userstep: {
|
|
53
|
+
src: '',
|
|
54
|
+
txt: name,
|
|
55
|
+
tag: uiViewClassName.toLowerCase(),
|
|
56
|
+
type: UserStepType.Keyboard,
|
|
57
|
+
},
|
|
58
|
+
});
|
|
57
59
|
}
|
|
58
60
|
}
|
|
59
61
|
|
|
@@ -1,9 +1,29 @@
|
|
|
1
|
-
import { PAGE_EVENTS_WINDOW, PAGE_EVENTS_DOCUMENT, PAGE_EVENT_TYPE } from '../constants.js';
|
|
2
1
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
3
2
|
import { EventDebouncer } from '../pageVisit/EventDebouncer.js';
|
|
4
3
|
import { Singleton } from './BaseMonitor.js';
|
|
4
|
+
import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
5
|
+
import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
|
|
5
6
|
|
|
6
7
|
/** @module PageMonitor */
|
|
8
|
+
const PAGE_EVENTS_DOCUMENT = ['visibilitychange', 'resume', 'freeze', 'readystatechange', 'cut', 'copy', 'paste'];
|
|
9
|
+
// page events we track in the session
|
|
10
|
+
// don't include beforeunload, it will affect bfcache
|
|
11
|
+
const PAGE_EVENTS_WINDOW = [
|
|
12
|
+
'pagehide',
|
|
13
|
+
'pageshow',
|
|
14
|
+
'focus',
|
|
15
|
+
'blur',
|
|
16
|
+
'popstate',
|
|
17
|
+
'online',
|
|
18
|
+
'offline',
|
|
19
|
+
'messageerror',
|
|
20
|
+
'languagechange',
|
|
21
|
+
'hashchange',
|
|
22
|
+
'beforeprint',
|
|
23
|
+
'afterprint',
|
|
24
|
+
'load',
|
|
25
|
+
'resize',
|
|
26
|
+
];
|
|
7
27
|
/** Monitors the page events which we capture and later process */
|
|
8
28
|
class PageMonitor extends Singleton {
|
|
9
29
|
/** Starts monitoring page events on the document */
|
|
@@ -65,7 +85,10 @@ class PageMonitor extends Singleton {
|
|
|
65
85
|
// do nothing
|
|
66
86
|
}
|
|
67
87
|
// storing the page event in the page visit queue
|
|
68
|
-
EventDebouncer.getInstance().
|
|
88
|
+
EventDebouncer.getInstance().debounce({
|
|
89
|
+
type: EventType.Page,
|
|
90
|
+
page: payload,
|
|
91
|
+
});
|
|
69
92
|
}
|
|
70
93
|
/** Returns document state */
|
|
71
94
|
getDocumentState() {
|