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,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().addEvent(updatePayload({
52
- [SOURCE_ATT_NAME]: '',
53
- [TEXT_ATT_NAME]: name,
54
- [TAGNAME_ATT_NAME]: uiViewClassName.toLowerCase(),
55
- [TYPE_ATT_NAME]: KEYBOARD_EVENT_TYPE,
56
- }), KEYBOARD_EVENT_TYPE);
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
 
@@ -10,7 +10,7 @@ export declare class PageMonitor extends Singleton implements Monitor {
10
10
  */
11
11
  _onPageEventHandle(event: Event): void;
12
12
  /** Returns document state */
13
- getDocumentState(): "hidden" | "active" | "passive";
13
+ getDocumentState(): "passive" | "hidden" | "active";
14
14
  /**
15
15
  * Returns object size in bytes
16
16
  * @param {} obj
@@ -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().addEvent(payload, PAGE_EVENT_TYPE);
88
+ EventDebouncer.getInstance().debounce({
89
+ type: EventType.Page,
90
+ page: payload,
91
+ });
69
92
  }
70
93
  /** Returns document state */
71
94
  getDocumentState() {
@@ -1,9 +1,5 @@
1
- /** @module RequestMonitor */
2
- import 'react-native/Libraries/Network/fetch';
3
1
  import { Monitor, Singleton } from './BaseMonitor';
4
- /**
5
- * Monitors all requests
6
- */
2
+ /** Monitors all requests */
7
3
  export default class RequestMonitor extends Singleton implements Monitor {
8
4
  /** main method */
9
5
  monitor(): void;
@@ -15,54 +11,38 @@ export default class RequestMonitor extends Singleton implements Monitor {
15
11
  * thus client code may throw an error.
16
12
  */
17
13
  private static consumeResponseAndGetBodyText;
18
- /**
19
- * Generates new PVEventHTTP
20
- */
14
+ /** Generates new PVEventHTTP */
21
15
  private static getPvEventHttp;
22
- /**
23
- * Gets headers from request or request options. Handles different scenarios where simple conversion is not possible
24
- */
16
+ /** Gets headers from request or request options. Handles different scenarios where simple conversion is not possible */
25
17
  private static getRequestHeaders;
26
18
  /**
27
19
  * Gets response headers.
28
20
  * It is always a Headers object.
29
21
  */
30
22
  private static getResponseHeaders;
31
- /**
32
- * Gets request body from body strings or Request options
33
- */
23
+ /** Gets request body from body strings or Request options */
34
24
  private static getRequestBody;
35
- /**
36
- * Returns the parameters to pass the PageVisitEventHTTP constructor. Specific to the fetch wrapper.
37
- */
25
+ /** Returns the parameters to pass the HttpEventManager constructor. Specific to the fetch wrapper. */
38
26
  private static getHttpDataFromFetch;
39
27
  /** Clones Response / Request or returns original object if cloning is not possible */
40
28
  private static cloneResponse;
41
- /**
42
- * Handles fetch response safely. Reports PageVisitEventHTTP and error to Pagevisit if needed.
43
- */
29
+ /** Handles fetch response safely. Reports HttpEventManager and error to Pagevisit if needed. */
44
30
  private static safeHandleFetchResponse;
45
- /**
46
- * Safe function to get method and url from fetch args
47
- */
31
+ /** Safe function to get method and url from fetch args */
48
32
  private static getMethodUrlFromFetchArgs;
49
33
  /**
50
34
  * Setting up the wrapper around fetch functions to try and
51
35
  * catch http errors
52
36
  */
53
37
  private static setupGlobalFetchWrapper;
54
- /**
55
- * Does a check if data collection is enabled and combines it into HttpDataBundle
56
- */
38
+ /** Does a check if data collection is enabled and combines it into HttpDataBundle */
57
39
  private static getHttpDataFromXhr;
58
40
  /**
59
41
  * on loadend we catch the event and
60
42
  * make sure it was correct
61
43
  */
62
44
  private static loadendHandler;
63
- /**
64
- * Handles fetch failure
65
- */
45
+ /** Handles fetch failure */
66
46
  private static handleFetchFailure;
67
47
  /** gets method from xhr */
68
48
  private static getMethodFromXHR;
@@ -1,10 +1,8 @@
1
1
  import { __awaiter } from 'tslib';
2
- import 'react-native/Libraries/Network/fetch';
3
2
  import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError.js';
4
- import { isHttpCodeFailure, PageVisitEventHTTP } from '../pageVisit/pageVisitEventHTTP.js';
3
+ import { isHttpCodeFailure, saveHTTPEvent } from '../pageVisit/HttpEventManager.js';
5
4
  import { safeEntries, propWriteableOrMadeWriteable, replace } from '../utils/object.js';
6
- import { BODY_USED_ERROR, HTTP_RESP_LENGTH_ATT_NAME, SEVERITY, PV_SEQ_ATT_NAME, RESPONSE_ERROR_TYPE, GQL_ERROR_TYPE, XML_HTTP_REQUEST_ERROR_TYPE, FETCH_EXCEPTION_ERROR_TYPE, HTTP_METHOD_ATT_NAME, HTTP_RESP_CODE_ATT_NAME, URL_ATT_NAME, HTTP_RESP_TIME_ATT_NAME } from '../constants.js';
7
- import ClientConfig from '../api/clientConfig.js';
5
+ import ClientConfig from '../api/ClientConfig.js';
8
6
  import { noibuLog } from '../utils/log.js';
9
7
  import { tryGetStackTrace, safeTrim } from '../utils/function.js';
10
8
  import { promiseAll } from '../utils/polyfills.js';
@@ -12,10 +10,13 @@ import { addSafeEventListener } from '../utils/eventlistener.js';
12
10
  import { HTTPDataBundler } from './http-tools/HTTPDataBundler.js';
13
11
  import GqlErrorValidator from './http-tools/GqlErrorValidator.js';
14
12
  import { Singleton } from './BaseMonitor.js';
13
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
14
+ import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
15
+ import { PageVisitErrorSource } from '../node_modules/@noibu/metroplex-ts-bindings/dist/PageVisitErrorSource.js';
15
16
 
16
- /**
17
- * Monitors all requests
18
- */
17
+ /** request monitor */
18
+ const BODY_USED_ERROR = 'Response data unavailable due to an improperly wrapped fetch call';
19
+ /** Monitors all requests */
19
20
  class RequestMonitor extends Singleton {
20
21
  /** main method */
21
22
  monitor() {
@@ -42,27 +43,23 @@ class RequestMonitor extends Singleton {
42
43
  return response.text();
43
44
  });
44
45
  }
45
- /**
46
- * Generates new PVEventHTTP
47
- */
46
+ /** Generates new PVEventHTTP */
48
47
  static getPvEventHttp(status, responseHeaders, method, url, responseTime) {
49
48
  const httpEvent = {
50
- [HTTP_METHOD_ATT_NAME]: method,
51
- [HTTP_RESP_CODE_ATT_NAME]: status,
52
- [URL_ATT_NAME]: url,
53
- [HTTP_RESP_TIME_ATT_NAME]: responseTime,
49
+ mtd: method,
50
+ code: status,
51
+ url,
52
+ r_time: responseTime,
54
53
  };
55
54
  const bundler = HTTPDataBundler.getInstance();
56
55
  // add response payload length, if any
57
56
  const contentLength = bundler.contentLength(responseHeaders);
58
57
  if (contentLength > 0 && bundler.shouldContinueForURL(url)) {
59
- httpEvent[HTTP_RESP_LENGTH_ATT_NAME] = contentLength;
58
+ httpEvent.resp_len = contentLength;
60
59
  }
61
60
  return httpEvent;
62
61
  }
63
- /**
64
- * Gets headers from request or request options. Handles different scenarios where simple conversion is not possible
65
- */
62
+ /** Gets headers from request or request options. Handles different scenarios where simple conversion is not possible */
66
63
  static getRequestHeaders(request, options) {
67
64
  const headers = safeEntries((request === null || request === void 0 ? void 0 : request.headers) || (options === null || options === void 0 ? void 0 : options.headers));
68
65
  return HTTPDataBundler.headersMapFromIterable(headers);
@@ -75,9 +72,7 @@ class RequestMonitor extends Singleton {
75
72
  const headers = safeEntries(response === null || response === void 0 ? void 0 : response.headers);
76
73
  return HTTPDataBundler.headersMapFromIterable(headers);
77
74
  }
78
- /**
79
- * Gets request body from body strings or Request options
80
- */
75
+ /** Gets request body from body strings or Request options */
81
76
  static getRequestBody(requestText, options) {
82
77
  if (typeof requestText === 'string') {
83
78
  return requestText;
@@ -85,9 +80,7 @@ class RequestMonitor extends Singleton {
85
80
  // it's fine if it's falsy or an empty string, we catch that in HTTPDataBundler.getInstance().bundleHTTPData
86
81
  return options === null || options === void 0 ? void 0 : options.body;
87
82
  }
88
- /**
89
- * Returns the parameters to pass the PageVisitEventHTTP constructor. Specific to the fetch wrapper.
90
- */
83
+ /** Returns the parameters to pass the HttpEventManager constructor. Specific to the fetch wrapper. */
91
84
  static getHttpDataFromFetch(request, response, method, url, options, isError, requestText, responseText) {
92
85
  return __awaiter(this, void 0, void 0, function* () {
93
86
  if (!HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
@@ -103,17 +96,15 @@ class RequestMonitor extends Singleton {
103
96
  }
104
97
  return ogResponse; // body consumed already, no http response body for us
105
98
  }
106
- /**
107
- * Handles fetch response safely. Reports PageVisitEventHTTP and error to Pagevisit if needed.
108
- */
99
+ /** Handles fetch response safely. Reports HttpEventManager and error to Pagevisit if needed. */
109
100
  static safeHandleFetchResponse(startTime, url, method, options, request) {
110
101
  return (ogResponse) => __awaiter(this, void 0, void 0, function* () {
111
- var _a, _b;
102
+ var _a;
112
103
  try {
113
104
  if (!ogResponse) {
114
105
  // no idea how, but this happens sometimes, esp if other libs override fetch
115
106
  // logging to track the issue if it becomes widespread
116
- return ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in custom fetch() callback: no response received`, false, SEVERITY.error);
107
+ return ClientConfig.getInstance().postInternalError({ msg: 'No response object in fetch callback', url, method, options, request }, false, Severity.ERROR);
117
108
  }
118
109
  const clonedResponse = RequestMonitor.cloneResponse(ogResponse); // have to do it as early as possible
119
110
  const graphqlResponse = RequestMonitor.cloneResponse(clonedResponse); // and two times more for each consumption
@@ -129,15 +120,17 @@ class RequestMonitor extends Singleton {
129
120
  ]);
130
121
  const httpEvent = RequestMonitor.getPvEventHttp(status, headers, method, url, respTime);
131
122
  const httpData = yield RequestMonitor.getHttpDataFromFetch(request, httpEventDataResponse, method, url, options, isHttpError || !!gqlError, maybeRequestText, responseText);
132
- const pageVisitEventHTTP = new PageVisitEventHTTP(httpEvent, httpData, !!gqlError);
133
- pageVisitEventHTTP.saveHTTPEvent();
134
- const seq = (_b = pageVisitEventHTTP.httpData) === null || _b === void 0 ? void 0 : _b[PV_SEQ_ATT_NAME];
123
+ const seq = saveHTTPEvent(httpEvent, httpData, !!gqlError);
135
124
  if (isHttpError) {
136
125
  // this does not consume response body so no need to clone it
137
- saveErrorToPagevisit(RESPONSE_ERROR_TYPE, clonedResponse, seq);
126
+ saveErrorToPagevisit(Object.assign(Object.assign({}, clonedResponse), { type: PageVisitErrorSource.Response }), seq);
138
127
  }
139
128
  if (gqlError) {
140
- gqlError.forEach(error => saveErrorToPagevisit(GQL_ERROR_TYPE, error, seq));
129
+ gqlError.forEach(error => saveErrorToPagevisit({
130
+ url: ClientConfig.getInstance().globalUrl,
131
+ gql_err: error,
132
+ type: PageVisitErrorSource.Response,
133
+ }, seq));
141
134
  }
142
135
  }
143
136
  catch (e) {
@@ -146,13 +139,11 @@ class RequestMonitor extends Singleton {
146
139
  return;
147
140
  }
148
141
  const stack = tryGetStackTrace(e);
149
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in custom fetch() callback: ${e}${stack}`, false, SEVERITY.error);
142
+ ClientConfig.getInstance().postInternalError({ msg: `Error in custom fetch() callback`, error: e, stack }, false, Severity.ERROR);
150
143
  }
151
144
  });
152
145
  }
153
- /**
154
- * Safe function to get method and url from fetch args
155
- */
146
+ /** Safe function to get method and url from fetch args */
156
147
  static getMethodUrlFromFetchArgs(resource, options) {
157
148
  const defaultResource = { method: 'GET', url: '' };
158
149
  try {
@@ -170,7 +161,7 @@ class RequestMonitor extends Singleton {
170
161
  };
171
162
  }
172
163
  catch (e) {
173
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in fetch() wrapper: ${e}`, false, SEVERITY.error);
164
+ ClientConfig.getInstance().postInternalError({ msg: `Error in fetch() wrapper`, error: e }, false, Severity.ERROR);
174
165
  }
175
166
  return defaultResource;
176
167
  }
@@ -206,9 +197,7 @@ class RequestMonitor extends Singleton {
206
197
  };
207
198
  });
208
199
  }
209
- /**
210
- * Does a check if data collection is enabled and combines it into HttpDataBundle
211
- */
200
+ /** Does a check if data collection is enabled and combines it into HttpDataBundle */
212
201
  static getHttpDataFromXhr(xhrObj_1, method_1, url_1, isError_1) {
213
202
  return __awaiter(this, arguments, void 0, function* (xhrObj, method, url, isError, requestPayload = null, responseText) {
214
203
  if (!HTTPDataBundler.getInstance().shouldContinueForURL(url)) {
@@ -224,28 +213,27 @@ class RequestMonitor extends Singleton {
224
213
  */
225
214
  static loadendHandler(xhr, startTime, url, method, requestPayload) {
226
215
  return __awaiter(this, void 0, void 0, function* () {
227
- var _a;
228
216
  const respTime = Date.now() - startTime;
229
217
  const gqlError = yield GqlErrorValidator.fromXhr(url, xhr);
230
218
  const httpError = isHttpCodeFailure(xhr.status);
231
219
  const responseText = yield HTTPDataBundler.getResponseStringFromXHR(xhr);
232
220
  const httpEvent = RequestMonitor.getPvEventHttp(xhr.status, HTTPDataBundler.headersMapFromString(xhr.getAllResponseHeaders()), method, url, respTime);
233
221
  const httpData = yield RequestMonitor.getHttpDataFromXhr(xhr, method, url, httpError || !!gqlError, requestPayload, responseText);
234
- const pageVisitEventHTTP = new PageVisitEventHTTP(httpEvent, httpData, !!gqlError);
235
222
  // Save HTTP Info
236
- pageVisitEventHTTP.saveHTTPEvent();
237
- const seq = (_a = pageVisitEventHTTP.httpData) === null || _a === void 0 ? void 0 : _a[PV_SEQ_ATT_NAME];
223
+ const seq = saveHTTPEvent(httpEvent, httpData, !!gqlError);
238
224
  if (httpError) {
239
- saveErrorToPagevisit(XML_HTTP_REQUEST_ERROR_TYPE, xhr, seq);
225
+ saveErrorToPagevisit({ url: xhr.responseURL, status: xhr.status, type: PageVisitErrorSource.XMLHttpRequest }, seq);
240
226
  }
241
227
  if (gqlError) {
242
- gqlError.forEach(error => saveErrorToPagevisit(GQL_ERROR_TYPE, error, seq));
228
+ gqlError.forEach(error => saveErrorToPagevisit({
229
+ url: ClientConfig.getInstance().globalUrl,
230
+ gql_err: error,
231
+ type: PageVisitErrorSource.Response,
232
+ }, seq));
243
233
  }
244
234
  });
245
235
  }
246
- /**
247
- * Handles fetch failure
248
- */
236
+ /** Handles fetch failure */
249
237
  static handleFetchFailure(maybeErr, url) {
250
238
  if (!maybeErr || typeof maybeErr !== 'object') {
251
239
  return;
@@ -263,8 +251,9 @@ class RequestMonitor extends Singleton {
263
251
  errorFromFetch.message = `${err.message}${urlMessage}`;
264
252
  const errorPayload = {
265
253
  error: errorFromFetch,
254
+ type: PageVisitErrorSource.FetchException,
266
255
  };
267
- saveErrorToPagevisit(FETCH_EXCEPTION_ERROR_TYPE, errorPayload);
256
+ saveErrorToPagevisit(errorPayload);
268
257
  }
269
258
  /** gets method from xhr */
270
259
  static getMethodFromXHR(xhr, payload) {
@@ -292,7 +281,7 @@ class RequestMonitor extends Singleton {
292
281
  }
293
282
  catch (e) {
294
283
  const stack = tryGetStackTrace(e);
295
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in XHR.send() wrapper: ${e}${stack}`, false, SEVERITY.error);
284
+ ClientConfig.getInstance().postInternalError({ msg: `Error in XHR.send() wrapper`, error: e, stack }, false, Severity.ERROR);
296
285
  }
297
286
  return originalFunction.call(this, payload);
298
287
  };
@@ -310,14 +299,14 @@ class RequestMonitor extends Singleton {
310
299
  try {
311
300
  /**
312
301
  * We wrap assignment of the .noibu[...] variables in a try/catch, as we're assigning
313
- * properties to a built-in object type, and have no guarantee of success.
302
+ * properties to a built-in object source, and have no guarantee of success.
314
303
  */
315
304
  try {
316
305
  this.noibuHttpMethod = method;
317
306
  this.noibuHttpUrl = url;
318
307
  }
319
308
  catch (error) {
320
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Unable to set custom properties on XHR object: ${error}`, false, SEVERITY.warn);
309
+ ClientConfig.getInstance().postInternalError({ msg: `Unable to set custom properties on XHR object`, error }, false, Severity.WARN);
321
310
  }
322
311
  if (shouldHandleLoadend) {
323
312
  const startTime = Date.now();
@@ -326,7 +315,7 @@ class RequestMonitor extends Singleton {
326
315
  }
327
316
  catch (e) {
328
317
  const stack = tryGetStackTrace(e);
329
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in XHR.open() wrapper: ${e}${stack}`, false, SEVERITY.error);
318
+ ClientConfig.getInstance().postInternalError({ msg: `Error in XHR.open() wrapper`, error: e, stack }, false, Severity.ERROR);
330
319
  }
331
320
  return originalFunction.call(this, method, url, async, user, password);
332
321
  };
@@ -353,7 +342,7 @@ class RequestMonitor extends Singleton {
353
342
  }
354
343
  }
355
344
  catch (error) {
356
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error in XHR.setRequestHeader() wrapper: ${error}`, false, SEVERITY.error);
345
+ ClientConfig.getInstance().postInternalError({ msg: `Error in XHR.setRequestHeader() wrapper`, error }, false, Severity.ERROR);
357
346
  }
358
347
  return originalFunction.call(this, header, value);
359
348
  };
@@ -0,0 +1,35 @@
1
+ import { GQLError } from '@noibu/metroplex-ts-bindings';
2
+ /** Try detecting GraphQL errors from http response */
3
+ export default class GqlErrorValidator {
4
+ /** Retrieves GQL error object based on fetch request/response */
5
+ static fromFetch(url: string, options: RequestInit | undefined, request: Request | undefined, response: Response): Promise<GQLError[] | null>;
6
+ /** Retrieves GQL error object based on XHR object */
7
+ static fromXhr(url: string, xhr: unknown): Promise<GQLError[] | null>;
8
+ /** Try safely parse a string and return null if fails */
9
+ static _parseJsonSafely(content: string): any;
10
+ /** Try to get content type for fetch arguments */
11
+ static _getContentTypeFromFetchArguments(options?: RequestInit, request?: Request): string | null;
12
+ /**
13
+ * Checks if request is aborted
14
+ * If it has been aborted we are not able to consume the response
15
+ */
16
+ static _isRequestAborted(options?: RequestInit, request?: RequestInit): boolean | null | undefined;
17
+ /** Determines if request should be processed */
18
+ static _shouldHandleRequest(url: string, contentType?: string | null): boolean;
19
+ /** Sanitizes payload object */
20
+ static _validate(data: unknown, validationIssues: string[]): GQLError[] | null;
21
+ /** Sanitizes message object */
22
+ static _validateMessage(error: GQLError): void;
23
+ /**
24
+ * Sanitizes extensions object
25
+ */
26
+ static _validateExtensions(error: GQLError): void;
27
+ /** Sanitizes locations object */
28
+ static _validateLocations(error: GQLError, validationIssues: string[]): void;
29
+ /** Sanitizes path object */
30
+ static _validatePath(error: object, validationIssues: string[]): void;
31
+ /** Posts error */
32
+ static _postError(message: unknown): void;
33
+ /** Posts issue found during object sanitization */
34
+ static _postValidationIssues(validationIssues: string[]): void;
35
+ }