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.
Files changed (98) hide show
  1. package/README.md +15 -15
  2. package/android/build.gradle +1 -1
  3. package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
  4. package/dist/api/{helpCode.js → HelpCode.js} +6 -13
  5. package/dist/api/InputManager.js +156 -0
  6. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
  7. package/dist/api/StoredMetrics.js +158 -0
  8. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
  9. package/dist/const_matchers.js +1 -5
  10. package/dist/constants.js +15 -390
  11. package/dist/entry/index.js +3 -4
  12. package/dist/entry/init.js +33 -19
  13. package/dist/monitors/AppNavigationMonitor.js +19 -19
  14. package/dist/monitors/BaseMonitor.js +9 -4
  15. package/dist/monitors/ClickMonitor.js +72 -76
  16. package/dist/monitors/ErrorMonitor.js +45 -55
  17. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  18. package/dist/monitors/PageMonitor.js +25 -2
  19. package/dist/monitors/RequestMonitor.js +46 -57
  20. package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
  21. package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
  22. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  23. package/dist/pageVisit/EventDebouncer.js +43 -74
  24. package/dist/pageVisit/HttpEventManager.js +88 -0
  25. package/dist/pageVisit/PageVisitManager.js +99 -0
  26. package/dist/pageVisit/pageVisitEventError.js +170 -280
  27. package/dist/react/ErrorBoundary.js +3 -6
  28. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
  29. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  30. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  31. package/dist/storage/{storage.js → Storage.js} +17 -30
  32. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  33. package/dist/utils/date.js +39 -50
  34. package/dist/utils/eventlistener.js +5 -12
  35. package/dist/utils/function.js +42 -113
  36. package/dist/utils/log.js +5 -5
  37. package/dist/utils/object.js +12 -12
  38. package/dist/utils/piiRedactor.js +31 -3
  39. package/dist/utils/stacktrace-parser.js +29 -21
  40. package/package.json +14 -14
  41. package/dist/api/inputManager.js +0 -227
  42. package/dist/api/storedMetrics.js +0 -198
  43. package/dist/pageVisit/pageVisit.js +0 -181
  44. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  45. package/dist/pageVisit/userStep.js +0 -20
  46. package/dist/src/api/clientConfig.d.ts +0 -100
  47. package/dist/src/api/clientConfig.test.d.ts +0 -1
  48. package/dist/src/api/helpCode.d.ts +0 -23
  49. package/dist/src/api/inputManager.d.ts +0 -87
  50. package/dist/src/api/metroplexSocket.d.ts +0 -137
  51. package/dist/src/api/storedMetrics.d.ts +0 -73
  52. package/dist/src/api/storedPageVisit.d.ts +0 -40
  53. package/dist/src/const_matchers.d.ts +0 -1
  54. package/dist/src/constants.d.ts +0 -290
  55. package/dist/src/entry/index.d.ts +0 -14
  56. package/dist/src/entry/init.d.ts +0 -5
  57. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  58. package/dist/src/monitors/BaseMonitor.d.ts +0 -13
  59. package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
  60. package/dist/src/monitors/ClickMonitor.d.ts +0 -31
  61. package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
  62. package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
  63. package/dist/src/monitors/PageMonitor.d.ts +0 -20
  64. package/dist/src/monitors/RequestMonitor.d.ts +0 -94
  65. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  66. package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
  67. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  68. package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
  69. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  70. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  71. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  72. package/dist/src/pageVisit/userStep.d.ts +0 -5
  73. package/dist/src/react/ErrorBoundary.d.ts +0 -72
  74. package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
  75. package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
  76. package/dist/src/sessionRecorder/types.d.ts +0 -91
  77. package/dist/src/storage/rnStorageProvider.d.ts +0 -23
  78. package/dist/src/storage/storage.d.ts +0 -39
  79. package/dist/src/storage/storageProvider.d.ts +0 -26
  80. package/dist/src/utils/date.d.ts +0 -6
  81. package/dist/src/utils/eventlistener.d.ts +0 -8
  82. package/dist/src/utils/function.d.ts +0 -102
  83. package/dist/src/utils/log.d.ts +0 -4
  84. package/dist/src/utils/object.d.ts +0 -44
  85. package/dist/src/utils/performance.d.ts +0 -6
  86. package/dist/src/utils/piiRedactor.d.ts +0 -11
  87. package/dist/src/utils/polyfills.d.ts +0 -4
  88. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  89. package/dist/types/Config.d.ts +0 -31
  90. package/dist/types/Metroplex.types.d.ts +0 -73
  91. package/dist/types/NavigationIntegration.d.ts +0 -6
  92. package/dist/types/PageVisit.types.d.ts +0 -8
  93. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  94. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  95. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  96. package/dist/types/Storage.d.ts +0 -14
  97. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  98. package/dist/types/WrappedObjects.d.ts +0 -6
@@ -0,0 +1,158 @@
1
+ import { __awaiter } from 'tslib';
2
+ import { CURRENT_NOIBUJS_VERSION, GET_METROPLEX_METRICS_URL } from '../constants.js';
3
+ import ClientConfig from './ClientConfig.js';
4
+ import { getUserAgent, stringifyJSON } from '../utils/function.js';
5
+ import { addSafeEventListener } from '../utils/eventlistener.js';
6
+ import { unwrapNoibuWrapped } from '../utils/object.js';
7
+ import { Singleton } from '../monitors/BaseMonitor.js';
8
+
9
+ // current metrics version to be sent from front end services.
10
+ const CURRENT_METRICS_VERSION = 1;
11
+ /**
12
+ * This class holds the final page visit and video frag metrics. It flushes
13
+ * them to storage and then finally sends them to Metroplex via the post
14
+ * route when the next page is loaded
15
+ */
16
+ class StoredMetrics extends Singleton {
17
+ /** Creates a new StoredMetrics instance */
18
+ constructor() {
19
+ super();
20
+ this.expectedVideoLength = 0;
21
+ this.expectedVfSeq = 0;
22
+ this.httpSequenceNumber = 0;
23
+ this.httpOverLimitCount = 0;
24
+ this.httpDroppedPayloadByTypeCount = 0;
25
+ this.httpDroppedPayloadByLengthCount = 0;
26
+ this.httpPayloadCount = 0;
27
+ this.expectedPvPart = 0;
28
+ this.videoClicks = 0;
29
+ this.pvClicks = 0;
30
+ this.errCount = 0;
31
+ this.httpCount = 0;
32
+ this.didCutPv = false;
33
+ this.didCutVideo = false;
34
+ this.didStartVideo = false;
35
+ this._setupListeners();
36
+ }
37
+ /** Add video frag payload data to the stored metrics */
38
+ addVideoFragData(expectedVfSeq, expectedVideoLength) {
39
+ this.expectedVfSeq = expectedVfSeq;
40
+ this.expectedVideoLength = expectedVideoLength;
41
+ }
42
+ /** Set the amount of page visit parts */
43
+ setPvPart(expectedPvPart) {
44
+ this.expectedPvPart = expectedPvPart;
45
+ }
46
+ /** Increase the amount of video clicks seen in the session */
47
+ addVideoClick() {
48
+ this.videoClicks += 1;
49
+ }
50
+ /** Increase the amount of page visit clicks */
51
+ addPvClick() {
52
+ this.pvClicks += 1;
53
+ }
54
+ /** Increments the error count by 1 */
55
+ addError() {
56
+ this.errCount += 1;
57
+ }
58
+ /** Increments the http count by 1 */
59
+ addHttpEvent() {
60
+ this.httpCount += 1;
61
+ }
62
+ /** Increments the http data sequence count by 1 */
63
+ addHttpData() {
64
+ this.httpSequenceNumber += 1;
65
+ }
66
+ /** Increments the http data over limit count by 1 */
67
+ addHttpDataOverLimit() {
68
+ this.httpOverLimitCount += 1;
69
+ }
70
+ /** Increments the http data drop count by content type */
71
+ addHttpDataDropByType() {
72
+ this.httpDroppedPayloadByTypeCount += 1;
73
+ }
74
+ /** Increments the http data drop count by content length */
75
+ addHttpDataDropByLength() {
76
+ this.httpDroppedPayloadByLengthCount += 1;
77
+ }
78
+ /** Increments the http data payload collected count */
79
+ addHttpDataPayloadCount() {
80
+ this.httpPayloadCount += 1;
81
+ }
82
+ /** Set that the video was cut/blocked due to size constraints */
83
+ setDidCutVideo() {
84
+ this.didCutVideo = true;
85
+ }
86
+ /** Set that the video was started */
87
+ setDidStartVideo() {
88
+ this.didStartVideo = true;
89
+ }
90
+ /** Set that the page visit was cut/blocked due to size constraints */
91
+ setDidCutPv() {
92
+ this.didCutPv = true;
93
+ }
94
+ /**
95
+ * Sets up all the listeners that noibujs should listen to before storing
96
+ * our metrics to localstorage
97
+ */
98
+ _setupListeners() {
99
+ // Add the window event handlers to post the data to the metrics endpoint
100
+ const evt = 'pagehide';
101
+ addSafeEventListener(window, evt, () => this.postMetricsIfActive());
102
+ }
103
+ /** posts the metrics to metroplex if client is active */
104
+ postMetricsIfActive() {
105
+ if (ClientConfig.getInstance().isClientDisabled) {
106
+ return;
107
+ }
108
+ // Don't send the metrics if the session has become inactive
109
+ // already sent when went inactive
110
+ if (ClientConfig.getInstance().isInactive()) {
111
+ return;
112
+ }
113
+ return this.postMetrics();
114
+ }
115
+ /** posts the metrics to metroplex using the beacon API
116
+ */
117
+ postMetrics() {
118
+ return __awaiter(this, void 0, void 0, function* () {
119
+ // Create a new object to write to local storage that doesnt have the timeout and flush members.
120
+ const lsMetrics = {
121
+ // metadata
122
+ br_id: ClientConfig.getInstance().browserId,
123
+ pv_id: ClientConfig.getInstance().pageVisitId,
124
+ cv: CURRENT_NOIBUJS_VERSION,
125
+ v: CURRENT_METRICS_VERSION,
126
+ // metrics
127
+ exp_vid_len: this.expectedVideoLength,
128
+ exp_vf_seq: this.expectedVfSeq,
129
+ exp_pc_seq: this.expectedPvPart,
130
+ exp_http_seq: this.httpSequenceNumber,
131
+ http_payloads: this.httpPayloadCount,
132
+ http_drop_oversize: this.httpDroppedPayloadByLengthCount,
133
+ http_drop_type: this.httpDroppedPayloadByTypeCount,
134
+ http_over_limit: this.httpOverLimitCount,
135
+ vid_clicks: this.videoClicks,
136
+ pv_clicks: this.pvClicks,
137
+ did_cut_pv: this.didCutPv,
138
+ did_cut_vid: this.didCutVideo,
139
+ did_start_vid: this.didStartVideo,
140
+ exp_http: this.httpCount,
141
+ exp_err: this.errCount,
142
+ on_url: ClientConfig.getInstance().globalUrl,
143
+ };
144
+ unwrapNoibuWrapped(fetch)(GET_METROPLEX_METRICS_URL(), {
145
+ method: 'POST',
146
+ headers: {
147
+ 'content-type': 'application/json',
148
+ 'User-Agent': yield getUserAgent(),
149
+ },
150
+ body: stringifyJSON(lsMetrics),
151
+ // keep alive outlives the current page, its the same as beacon
152
+ keepalive: true,
153
+ });
154
+ });
155
+ }
156
+ }
157
+
158
+ export { StoredMetrics as default };
@@ -1,18 +1,21 @@
1
1
  import { __awaiter } from 'tslib';
2
- 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';
3
- import ClientConfig from './clientConfig.js';
4
- import { stringifyJSON, makeRequest } from '../utils/function.js';
5
- import Storage from '../storage/storage.js';
2
+ import { SEVERITY, MAX_METROPLEX_SOCKET_INNACTIVE_TIME, GET_METROPLEX_POST_URL } from '../constants.js';
3
+ import ClientConfig from './ClientConfig.js';
4
+ import { stringifyJSON, postRequest } from '../utils/function.js';
5
+ import Storage from '../storage/Storage.js';
6
6
  import { Singleton } from '../monitors/BaseMonitor.js';
7
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
8
+ import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
9
+ import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
7
10
 
11
+ // The local storage key used to store the last page visit
12
+ const NOIBU_STORED_PAGE_VISIT = 'n_stored_page_visit';
8
13
  /**
9
14
  * This class holds the final page visit. It flushes it to storage and then
10
15
  * finally sends it to Metroplex via the post route when the next page is loaded
11
16
  */
12
17
  class StoredPageVisit extends Singleton {
13
- /**
14
- * Creates a new instance of StoredPageVisit
15
- */
18
+ /** Creates a new instance of StoredPageVisit */
16
19
  constructor() {
17
20
  super();
18
21
  const storage = Storage.getInstance();
@@ -29,18 +32,15 @@ class StoredPageVisit extends Singleton {
29
32
  // Get the events from the last message
30
33
  const { type, payload } = retryMessageQueue[retryMessageQueue.length - 1];
31
34
  // Only store page visit payloads
32
- if (type !== PV_METROPLEX_TYPE || !payload[PAGE_VISIT_PART_ATT_NAME]) {
35
+ if (type !== WebsocketMessageType.PageVisitPart || !payload) {
33
36
  return;
34
37
  }
35
- const events = payload[PAGE_VISIT_PART_ATT_NAME][PV_EVENTS_ATT_NAME]
36
- ? payload[PAGE_VISIT_PART_ATT_NAME][PV_EVENTS_ATT_NAME]
37
- : [];
38
+ const events = payload.events ? payload.events : [];
38
39
  const filteredEvents = events.filter(event =>
39
- // Return true if the event is a userstep, error, or location event
40
+ // Return true if the event is an userstep, error, or location event
40
41
  // Any userstep is used rather than just mouse clicks because we shouldn't
41
42
  // assume mouse clicks are the only way for any activity to happen
42
- event[TYPE_ATT_NAME] === USERSTEP_EVENT_TYPE ||
43
- event[TYPE_ATT_NAME] === ERROR_EVENT_TYPE);
43
+ event.type === EventType.UserStep || event.type === EventType.Error);
44
44
  // Only write the retry queue if it contains a user step or location change
45
45
  if (filteredEvents.length > 0) {
46
46
  this.writePageVisitsFromRetryQueue(retryMessageQueue, pvInfo);
@@ -52,9 +52,8 @@ class StoredPageVisit extends Singleton {
52
52
  const pageVisitFrags = [];
53
53
  for (let i = 0; i < retryMessageQueue.length; i += 1) {
54
54
  const { type, payload } = retryMessageQueue[i];
55
- if (type === PV_METROPLEX_TYPE) {
56
- const frag = payload[PAGE_VISIT_PART_ATT_NAME];
57
- pageVisitFrags.push(frag);
55
+ if (type === WebsocketMessageType.PageVisitPart) {
56
+ pageVisitFrags.push(payload);
58
57
  }
59
58
  }
60
59
  this._writePageVisitFrags(pageVisitFrags, pvInfo);
@@ -74,16 +73,35 @@ class StoredPageVisit extends Singleton {
74
73
  try {
75
74
  yield storage.save(NOIBU_STORED_PAGE_VISIT, json);
76
75
  }
77
- catch (err) {
76
+ catch (error) {
78
77
  yield storage.remove(NOIBU_STORED_PAGE_VISIT);
79
78
  // Calculate current storage size
80
79
  const size = yield storage.calculateUsedSize();
81
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error writing pv to storage: ${err}, ` +
82
- `json size: ${json.length}, storage size: ${size}, ` +
83
- `${yield storage.getDiagnoseInfo()}`, false, SEVERITY.error);
80
+ ClientConfig.getInstance().postInternalError({
81
+ msg: `Error writing pv to storage`,
82
+ error,
83
+ jsonSize: json.length,
84
+ storageSize: size,
85
+ diagnosis: yield storage.getDiagnoseInfo(),
86
+ }, false, SEVERITY.error);
84
87
  }
85
88
  });
86
89
  }
90
+ /**
91
+ * Handles any issues that may appear when trying to get the stored page visit data
92
+ */
93
+ static handleGetPostDataError(data, error) {
94
+ return __awaiter(this, void 0, void 0, function* () {
95
+ // Remove the item since there is something corrupted
96
+ yield Storage.getInstance().remove(NOIBU_STORED_PAGE_VISIT);
97
+ ClientConfig.getInstance().postInternalError({
98
+ msg: `Error parsing page visit string`,
99
+ data,
100
+ error,
101
+ }, false, SEVERITY.error);
102
+ return null;
103
+ });
104
+ }
87
105
  /**
88
106
  * Read the stored page visit from storage, create a complete page visit object
89
107
  * and then post that to Metroplex
@@ -99,12 +117,17 @@ class StoredPageVisit extends Singleton {
99
117
  let storedPageVisit = {};
100
118
  try {
101
119
  storedPageVisit = JSON.parse(data);
120
+ if (!storedPageVisit.pageVisitInfo) {
121
+ return StoredPageVisit.handleGetPostDataError(data, new TypeError('Page visit info is missing'));
122
+ }
123
+ if (!storedPageVisit.pageVisitFrags) {
124
+ return StoredPageVisit.handleGetPostDataError(data, new TypeError('Page visit frags is missing'));
125
+ }
126
+ // Set is last to be true on the page visit information
127
+ storedPageVisit.pageVisitInfo.last = true;
102
128
  }
103
129
  catch (e) {
104
- // Remove the item since there is something corrupted
105
- yield storage.remove(NOIBU_STORED_PAGE_VISIT);
106
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error parsing page visit string '${data}': ${e}`, false, SEVERITY.error);
107
- return null;
130
+ return StoredPageVisit.handleGetPostDataError(data, e);
108
131
  }
109
132
  // making sure we have the timestamp attribute since we added this logic after initially
110
133
  // releasing the storedPageVisit
@@ -120,16 +143,10 @@ class StoredPageVisit extends Singleton {
120
143
  }
121
144
  // Copy the page visit information from storage into a new complete PV
122
145
  const completePv = {
123
- [PAGE_VISIT_INFORMATION_ATT_NAME]: storedPageVisit.pageVisitInfo,
124
- [PAGE_VISIT_PART_ATT_NAME]: [],
125
- [PAGE_VISIT_VID_FRAG_ATT_NAME]: [],
146
+ pvi: storedPageVisit.pageVisitInfo,
147
+ pvp: storedPageVisit.pageVisitFrags,
148
+ pvvf: [],
126
149
  };
127
- // Set is last to be true on the page visit information
128
- completePv[PAGE_VISIT_INFORMATION_ATT_NAME][IS_LAST_ATT_NAME] = true;
129
- // Add the page visit frags to the complete PV
130
- for (let i = 0; i < storedPageVisit.pageVisitFrags.length; i += 1) {
131
- completePv[PAGE_VISIT_PART_ATT_NAME].push(storedPageVisit.pageVisitFrags[i]);
132
- }
133
150
  return completePv;
134
151
  });
135
152
  }
@@ -152,20 +169,16 @@ class StoredPageVisit extends Singleton {
152
169
  }
153
170
  /** Returns a promise that resolves to post the page visit in storage to Metroplex */
154
171
  _getPostPageVisitPromise() {
155
- return new Promise((resolve, reject) => {
156
- this._getPostData().then(data => {
157
- if (!data) {
158
- resolve();
159
- return;
160
- }
161
- const headers = {
162
- 'content-type': 'application/json',
163
- };
164
- makeRequest('POST', GET_METROPLEX_POST_URL(), data, headers, 2000, true)
165
- .then(resolve)
166
- .catch(e => {
167
- reject(new Error('Page visit post request rejected due to: ', e));
168
- });
172
+ return __awaiter(this, void 0, void 0, function* () {
173
+ const postData = yield this._getPostData();
174
+ if (!postData) {
175
+ return;
176
+ }
177
+ const headers = {
178
+ 'content-type': 'application/json',
179
+ };
180
+ return postRequest(GET_METROPLEX_POST_URL(), postData, headers, true, 2000).catch(cause => {
181
+ Promise.reject(new Error('Page visit post request rejected due to: ', { cause }));
169
182
  });
170
183
  });
171
184
  }
@@ -1,4 +1,3 @@
1
- /* eslint-disable require-jsdoc */
2
1
  // This file is generated by wsmatchers. Don't directly edit this file
3
2
  const addToCartTextRegexArray = [
4
3
  '\\b(view|add|my)\\b.*\\b(cart|bag|basket|bucket|box)\\b',
@@ -251,10 +250,7 @@ const checkoutPlaceOrderRegexArray = [
251
250
  ];
252
251
 
253
252
  function WHITELIST_TEXT_REGEX_STRING() {
254
- return addToCartTextRegexArray
255
- .concat(checkoutStartedTextRegexArray)
256
- .concat(checkoutPlaceOrderRegexArray)
257
- .join('|');
253
+ return addToCartTextRegexArray.concat(checkoutStartedTextRegexArray).concat(checkoutPlaceOrderRegexArray).join('|');
258
254
  }
259
255
 
260
256
  export { WHITELIST_TEXT_REGEX_STRING };