noibu-react-native 0.2.6 → 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 (97) hide show
  1. package/README.md +15 -15
  2. package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
  3. package/dist/api/{helpCode.js → HelpCode.js} +6 -13
  4. package/dist/api/InputManager.js +156 -0
  5. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
  6. package/dist/api/StoredMetrics.js +158 -0
  7. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
  8. package/dist/const_matchers.js +1 -5
  9. package/dist/constants.js +15 -390
  10. package/dist/entry/index.js +3 -4
  11. package/dist/entry/init.js +33 -19
  12. package/dist/monitors/AppNavigationMonitor.js +19 -19
  13. package/dist/monitors/BaseMonitor.js +9 -4
  14. package/dist/monitors/ClickMonitor.js +72 -76
  15. package/dist/monitors/ErrorMonitor.js +45 -55
  16. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  17. package/dist/monitors/PageMonitor.js +25 -2
  18. package/dist/monitors/RequestMonitor.js +46 -57
  19. package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
  20. package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
  21. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  22. package/dist/pageVisit/EventDebouncer.js +43 -74
  23. package/dist/pageVisit/HttpEventManager.js +88 -0
  24. package/dist/pageVisit/PageVisitManager.js +99 -0
  25. package/dist/pageVisit/pageVisitEventError.js +170 -280
  26. package/dist/react/ErrorBoundary.js +3 -6
  27. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
  28. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  29. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  30. package/dist/storage/{storage.js → Storage.js} +17 -30
  31. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  32. package/dist/utils/date.js +39 -50
  33. package/dist/utils/eventlistener.js +5 -12
  34. package/dist/utils/function.js +42 -113
  35. package/dist/utils/log.js +5 -5
  36. package/dist/utils/object.js +12 -12
  37. package/dist/utils/piiRedactor.js +31 -3
  38. package/dist/utils/stacktrace-parser.js +29 -21
  39. package/package.json +14 -14
  40. package/dist/api/inputManager.js +0 -227
  41. package/dist/api/storedMetrics.js +0 -198
  42. package/dist/pageVisit/pageVisit.js +0 -181
  43. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  44. package/dist/pageVisit/userStep.js +0 -20
  45. package/dist/src/api/clientConfig.d.ts +0 -100
  46. package/dist/src/api/clientConfig.test.d.ts +0 -1
  47. package/dist/src/api/helpCode.d.ts +0 -23
  48. package/dist/src/api/inputManager.d.ts +0 -87
  49. package/dist/src/api/metroplexSocket.d.ts +0 -137
  50. package/dist/src/api/storedMetrics.d.ts +0 -73
  51. package/dist/src/api/storedPageVisit.d.ts +0 -40
  52. package/dist/src/const_matchers.d.ts +0 -1
  53. package/dist/src/constants.d.ts +0 -290
  54. package/dist/src/entry/index.d.ts +0 -14
  55. package/dist/src/entry/init.d.ts +0 -5
  56. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  57. package/dist/src/monitors/BaseMonitor.d.ts +0 -13
  58. package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
  59. package/dist/src/monitors/ClickMonitor.d.ts +0 -31
  60. package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
  61. package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
  62. package/dist/src/monitors/PageMonitor.d.ts +0 -20
  63. package/dist/src/monitors/RequestMonitor.d.ts +0 -94
  64. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  65. package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
  66. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  67. package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
  68. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  69. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  70. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  71. package/dist/src/pageVisit/userStep.d.ts +0 -5
  72. package/dist/src/react/ErrorBoundary.d.ts +0 -72
  73. package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
  74. package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
  75. package/dist/src/sessionRecorder/types.d.ts +0 -91
  76. package/dist/src/storage/rnStorageProvider.d.ts +0 -23
  77. package/dist/src/storage/storage.d.ts +0 -39
  78. package/dist/src/storage/storageProvider.d.ts +0 -26
  79. package/dist/src/utils/date.d.ts +0 -6
  80. package/dist/src/utils/eventlistener.d.ts +0 -8
  81. package/dist/src/utils/function.d.ts +0 -102
  82. package/dist/src/utils/log.d.ts +0 -4
  83. package/dist/src/utils/object.d.ts +0 -44
  84. package/dist/src/utils/performance.d.ts +0 -6
  85. package/dist/src/utils/piiRedactor.d.ts +0 -11
  86. package/dist/src/utils/polyfills.d.ts +0 -4
  87. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  88. package/dist/types/Config.d.ts +0 -31
  89. package/dist/types/Metroplex.types.d.ts +0 -73
  90. package/dist/types/NavigationIntegration.d.ts +0 -6
  91. package/dist/types/PageVisit.types.d.ts +0 -8
  92. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  93. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  94. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  95. package/dist/types/Storage.d.ts +0 -14
  96. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  97. package/dist/types/WrappedObjects.d.ts +0 -6
@@ -1,17 +1,37 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import uuid from 'react-native-uuid';
3
- import { getUserAgent, stringifyJSON, getVideoRecorderType } from '../utils/function.js';
3
+ import { Platform } from 'react-native';
4
+ import { MetroplexRoute } from '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
5
+ import { getUserAgent, stringifyJSON } from '../utils/function.js';
4
6
  import { addSafeEventListener } from '../utils/eventlistener.js';
5
- import { GET_METROPLEX_BASE_SOCKET_URL, METROPLEX_FRAG_ROUTE, GET_METROPLEX_POST_URL, METROPLEX_RETRY_FREQUENCY, SEQ_NUM_ATT_NAME, WORK_REQUEST_ATT_NAME, HELP_CODE_ATT_NAME, PV_METROPLEX_TYPE, PAGE_VISIT_PART_ATT_NAME, PV_EVENTS_ATT_NAME, TYPE_ATT_NAME, USERSTEP_EVENT_TYPE, GET_MAX_METROPLEX_RECONNECTION_NUMBER, MAX_METROPLEX_CONNECTION_COUNT, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, END_AT_ATT_NAME, SEVERITY, OK_SOCKET_MESSAGE, CLOSE_CONNECTION_FORCEFULLY, BLOCK_SOCKET_MESSAGE, STOP_STORING_PV_SOCKET_MESSAGE, STOP_STORING_VID_SOCKET_MESSAGE, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, MAX_BEACON_PAYLOAD_SIZE, PAGE_VISIT_INFORMATION_ATT_NAME, PAGE_VISIT_HTTP_DATA_ATT_NAME, VIDEO_PART_COUNT_ATT_NAME, IS_LAST_ATT_NAME, HTTP_DATA_METROPLEX_TYPE, BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, VER_ATT_NAME, CURRENT_PV_VERSION, PV_SEQ_ATT_NAME, ON_URL_ATT_NAME, REF_URL_ATT_NAME, STARTED_AT_ATT_NAME, CONN_COUNT_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, SCRIPT_ID_ATT_NAME, GET_SCRIPT_ID, SCRIPT_INSTANCE_ID_ATT_NAME, METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME, SOCKET_INSTANCE_ID_ATT_NAME, VIDEO_RECORDER_ATT_NAME, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, MAX_RETRY_MSG_Q_SIZE } from '../constants.js';
6
- import ClientConfig from './clientConfig.js';
7
- import StoredMetrics from './storedMetrics.js';
8
- import StoredPageVisit from './storedPageVisit.js';
7
+ import { GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_POST_URL, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, SEVERITY, MAX_BEACON_PAYLOAD_SIZE, CURRENT_NOIBUJS_VERSION, GET_SCRIPT_ID } from '../constants.js';
8
+ import ClientConfig from './ClientConfig.js';
9
+ import StoredMetrics from './StoredMetrics.js';
10
+ import StoredPageVisit from './StoredPageVisit.js';
9
11
  import { safePerformanceNow } from '../utils/performance.js';
10
12
  import { isDateOverwritten } from '../utils/date.js';
11
13
  import { unwrapNoibuWrapped } from '../utils/object.js';
12
14
  import { noibuLog } from '../utils/log.js';
13
15
  import { Singleton } from '../monitors/BaseMonitor.js';
16
+ import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
17
+ import { WorkRequestMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WorkRequestMessageType.js';
18
+ import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
19
+ import { InboundMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/InboundMessageType.js';
14
20
 
21
+ /**
22
+ * Grab the video recorder type based on the device we run the app on.
23
+ */
24
+ function getVideoRecorderType() {
25
+ return __awaiter(this, void 0, void 0, function* () {
26
+ if (Platform.OS === 'android') {
27
+ return 'AndroidNative';
28
+ }
29
+ if (Platform.OS === 'ios') {
30
+ return 'IOSNative';
31
+ }
32
+ return 'RRWeb'; // should never happen
33
+ });
34
+ }
15
35
  /**
16
36
  * Implements rolling window of specified size,
17
37
  * but only makes a cut once array length exceeds 150%.
@@ -35,6 +55,13 @@ function createSlidingArrayOfSize(size, arraySource = [], downsizeThreshold = 1.
35
55
  },
36
56
  });
37
57
  }
58
+ // gets the frequency at which the client resends the message that were not confirmed by metroplex
59
+ const METROPLEX_RETRY_FREQUENCY = 30000;
60
+ // current PageVisitManager version to be sent from front end services
61
+ const CURRENT_PV_VERSION = 5;
62
+ // maximum number of connection a single page visit can reach
63
+ const MAX_METROPLEX_CONNECTION_COUNT = 100;
64
+ const MAX_RETRY_MSG_Q_SIZE = 500;
38
65
  /** Manages the socket to Metroplex */
39
66
  class MetroplexSocket extends Singleton {
40
67
  /**
@@ -59,11 +86,10 @@ class MetroplexSocket extends Singleton {
59
86
  this.connectionCount = 0;
60
87
  // session start time, used to calculate accurate end time
61
88
  this.sessionStartTime = safePerformanceNow();
62
- this.connectionPromise = null;
63
- // Whether or not we have sent the page visit information after connecting the socket
89
+ // Whether we have sent the page visit information after connecting the socket
64
90
  this.pageVisitInfoSent = false;
65
91
  // socket connection url
66
- this.connectionURL = `${GET_METROPLEX_BASE_SOCKET_URL()}/${METROPLEX_FRAG_ROUTE}`;
92
+ this.connectionURL = `${GET_METROPLEX_BASE_SOCKET_URL()}/${MetroplexRoute.PageVisitPart}`;
67
93
  // post endpoint for the same events we would send to the socket
68
94
  this.postURL = GET_METROPLEX_POST_URL();
69
95
  // sequence number of the message sent to metroplex
@@ -98,75 +124,91 @@ class MetroplexSocket extends Singleton {
98
124
  this.metroRetryFrequencyMS = METROPLEX_RETRY_FREQUENCY;
99
125
  this.retryMetroplexInterval = null;
100
126
  this.helpCodeCb = null;
101
- noibuLog('Metroplex constructor', {
102
- initialURL: this.initialURL,
103
- scriptInstanceId,
104
- });
127
+ noibuLog('Metroplex constructor', { initialURL: this.initialURL, scriptInstanceId });
105
128
  this.scriptInstanceId = scriptInstanceId;
106
- // Connect the WS
107
129
  this.connectionPromise = this.connectSocket();
108
130
  // Set up the offload events immediately
109
131
  this._setupOffloadEvents();
110
132
  }
133
+ /**
134
+ * connectSocket will establish a websocket connection to the metroplex
135
+ * service
136
+ */
137
+ connectSocket() {
138
+ if (this.isConnected() || this.isConnecting()) {
139
+ // self resolving promise since we are already ready to send
140
+ // requests, if we did reach state 1, we already sent initial
141
+ // request, thus not sending it again.
142
+ return this.connectionPromise;
143
+ }
144
+ // we return a promisified socket resolver to be able to chain the
145
+ // opening of the socket
146
+ return this.handleConnect(false);
147
+ }
148
+ /** sets up events that will trigger the event queue to be emptied */
149
+ _setupOffloadEvents() {
150
+ // when the page hides we try getting all the events
151
+ // and empty the event and retry queue.
152
+ addSafeEventListener(window, 'pagehide', () => this._handleUnload(), false);
153
+ }
111
154
  /**
112
155
  * Adds the seq num field to the given payload depending on whether its
113
156
  * a page visit part or video frag
114
157
  */
115
- _addSeqNumToPayload(type, payload) {
116
- const newPayload = Object.assign({}, payload);
117
- const key = MetroplexSocket.typeToPayloadPropMap[type];
118
- if (key) {
119
- newPayload[key][SEQ_NUM_ATT_NAME] = this.messageSequenceNum;
158
+ _addSeqNumToPayload(message) {
159
+ return __awaiter(this, void 0, void 0, function* () {
160
+ const { type, payload } = message;
161
+ /**
162
+ * Increasing the message sequence number for every message we send to metroplex
163
+ * and move the data to the retry queue.
164
+ */
120
165
  this.messageSequenceNum += 1;
121
- }
122
- return newPayload;
166
+ const newMessage = {
167
+ type,
168
+ payload: Object.assign(Object.assign({}, payload), { seq_num: this.messageSequenceNum }),
169
+ };
170
+ /** push the message to the retry queue immediately in case socket isnt connected */
171
+ this.retryMessageQueue.push(newMessage);
172
+ StoredPageVisit.getInstance().checkAndStoreRetryQueue(this.retryMessageQueue, yield this.getPageInformation());
173
+ return newMessage;
174
+ });
123
175
  }
124
176
  /** requests help code and saves a callback to be called on response */
125
177
  requestHelpCode(cb) {
126
178
  this.helpCodeCb = cb;
127
- return MetroplexSocket.getInstance().sendMessage(WORK_REQUEST_ATT_NAME, {
128
- [WORK_REQUEST_ATT_NAME]: HELP_CODE_ATT_NAME,
129
- });
179
+ return this.sendMessage({ type: WebsocketMessageType.WorkRequest, payload: WorkRequestMessageType.HelpCode });
130
180
  }
131
181
  /**
132
182
  * Immediately sends a message to Metroplex over the web socket
133
183
  * Queues the message if the connection isn't open yet.
134
184
  * returns true if message was sent succefully, false otherwise
135
185
  */
136
- sendMessage(type, payload) {
186
+ sendMessage(message) {
137
187
  return __awaiter(this, void 0, void 0, function* () {
188
+ const { type } = message;
138
189
  noibuLog('sendMessage start', { type });
139
190
  // if we have a lock on this specific type, we dont send it
140
- if (type in this.metroplexTypeLock ||
141
- ClientConfig.getInstance().isClientDisabled) {
191
+ if (this.metroplexTypeLock[type] || ClientConfig.getInstance().isClientDisabled) {
142
192
  noibuLog('sendMessage quitting due to', {
143
- typeInLock: type in this.metroplexTypeLock,
193
+ typeInLock: this.metroplexTypeLock[type] ? `${type} locked` : false,
144
194
  isClientDisabled: ClientConfig.getInstance().isClientDisabled,
145
195
  });
146
196
  return false;
147
197
  }
148
- if (type !== WORK_REQUEST_ATT_NAME) {
149
- // Increasing the message sequence number for every message we send to metroplex
150
- // and move the data to the retry queue.
151
- this._addSeqNumToPayload(type, payload);
152
- // push the message to the retry queue immediately in case socket isnt connected
153
- this.retryMessageQueue.push({ payload, type });
154
- StoredPageVisit.getInstance().checkAndStoreRetryQueue(this.retryMessageQueue, yield this.getPageInformation());
155
- }
198
+ const withSeqNum = type === WebsocketMessageType.WorkRequest
199
+ ? message
200
+ : yield this._addSeqNumToPayload(message);
156
201
  // send the socket message if we are connected and have sent page visit info
157
202
  if (this.isConnected() && this.pageVisitInfoSent) {
158
203
  // sending the data to metroplex
159
- yield this._sendSocketMessage(payload);
204
+ yield this.sendSocketMessage({ [withSeqNum.type]: withSeqNum.payload });
160
205
  }
161
206
  this.previousMessageType = type;
162
207
  // Only update the last message send if its a page visit with user action
163
208
  // ensure this is done regardless of whether socket is connected or not,
164
209
  // so that pagehide will post PV if user is active but socket is not
165
- if (type === PV_METROPLEX_TYPE && payload[PAGE_VISIT_PART_ATT_NAME]) {
166
- const events = payload[PAGE_VISIT_PART_ATT_NAME][PV_EVENTS_ATT_NAME]
167
- ? payload[PAGE_VISIT_PART_ATT_NAME][PV_EVENTS_ATT_NAME]
168
- : [];
169
- yield this._updateLatestPvTimestamp(events);
210
+ if (withSeqNum.type === WebsocketMessageType.PageVisitPart) {
211
+ yield this._updateLatestPvTimestamp(withSeqNum.payload.events || []);
170
212
  }
171
213
  return true;
172
214
  });
@@ -175,7 +217,7 @@ class MetroplexSocket extends Singleton {
175
217
  */
176
218
  _updateLatestPvTimestamp(events) {
177
219
  return __awaiter(this, void 0, void 0, function* () {
178
- const userstepsEvents = events.filter(ev => ev[TYPE_ATT_NAME] === USERSTEP_EVENT_TYPE);
220
+ const userstepsEvents = events.filter(ev => ev.type === EventType.UserStep);
179
221
  if (userstepsEvents.length > 0) {
180
222
  yield ClientConfig.getInstance().updateLastActiveTime(new Date());
181
223
  }
@@ -244,18 +286,21 @@ class MetroplexSocket extends Singleton {
244
286
  clearInterval(this.retryMetroplexInterval);
245
287
  }
246
288
  // if we tried reconnecting too many times we abandon
247
- if (this.currentConnectionAttempts >=
248
- GET_MAX_METROPLEX_RECONNECTION_NUMBER()) {
289
+ if (this.currentConnectionAttempts >= GET_MAX_METROPLEX_RECONNECTION_NUMBER()) {
249
290
  // if we tried beyond the threshold, we block ourselves a short
250
291
  // while fix the issue
251
- yield ClientConfig.getInstance().lockClientUntilNextPage('Too many reconnection attempts, locking until next page');
292
+ yield ClientConfig.getInstance().lockClientUntilNextPage({
293
+ msg: 'Too many reconnection attempts, locking until next page',
294
+ });
252
295
  return;
253
296
  }
254
297
  // if we tried reconnecting too many times we abandon
255
298
  if (this.connectionCount >= MAX_METROPLEX_CONNECTION_COUNT) {
256
299
  // if we tried beyond the threshold, we block ourselves a short
257
300
  // while fix the issue
258
- yield ClientConfig.getInstance().lockClientUntilNextPage('Too many connections, locking until next page');
301
+ yield ClientConfig.getInstance().lockClientUntilNextPage({
302
+ msg: 'Too many connections, locking until next page',
303
+ });
259
304
  return;
260
305
  }
261
306
  // try to reconnect on close but after a certain delay based off unsuccessful connections
@@ -265,7 +310,7 @@ class MetroplexSocket extends Singleton {
265
310
  });
266
311
  // everytime we get a message from the socket
267
312
  this.socket.onmessage = event => {
268
- noibuLog('metroplex handleConnect, onmessage', { event });
313
+ noibuLog('metroplex handleConnect, onmessage', event);
269
314
  this._onSocketMessage(event);
270
315
  };
271
316
  // the moment we open the socket
@@ -276,32 +321,14 @@ class MetroplexSocket extends Singleton {
276
321
  };
277
322
  });
278
323
  }
279
- /**
280
- * connectSocket will establish a websocket connection to the metroplex
281
- * service
282
- */
283
- connectSocket() {
284
- if (this.isConnected() || this.isConnecting()) {
285
- // self resolving promise since we are already ready to send
286
- // requests, if we did reach state 1, we already sent initial
287
- // request, thus not sending it again.
288
- return this.connectionPromise;
289
- }
290
- // we return a promisified socket resolver to be able to chain the
291
- // opening of the socket
292
- return this.handleConnect(false);
293
- }
294
- /** Calculates and sets the end_at field of the payload
295
- * @param {} payload
296
- * @param {} isPageVisit
297
- */
324
+ /** Calculates and sets the end_at field of the payload */
298
325
  addEndTimeToPayload(payload, isPageVisit) {
299
326
  const delta = Math.ceil(safePerformanceNow() - this.sessionStartTime);
300
327
  // update session length if this is a page visit event
301
328
  if (isPageVisit) {
302
329
  this.sessionLength = delta;
303
330
  }
304
- return Object.assign(Object.assign({}, payload), { [END_AT_ATT_NAME]: new Date(this.sessionTimestamp.getTime() + delta).toISOString() });
331
+ return Object.assign(Object.assign({}, payload), { end_at: new Date(this.sessionTimestamp.getTime() + delta).toISOString() });
305
332
  }
306
333
  /** open handler for socket */
307
334
  _onSocketOpen() {
@@ -310,7 +337,7 @@ class MetroplexSocket extends Singleton {
310
337
  if (!this.isConnected() || ClientConfig.getInstance().isClientDisabled) {
311
338
  return;
312
339
  }
313
- yield this._sendSocketMessage(yield this.getPageInformation());
340
+ yield this.sendSocketMessage(yield this.getPageInformation());
314
341
  // Set this to allow normal page visit and video frag messages to be sent
315
342
  this.pageVisitInfoSent = true;
316
343
  this.currentConnectionAttempts = 0;
@@ -324,32 +351,30 @@ class MetroplexSocket extends Singleton {
324
351
  this.connectionCount += 1;
325
352
  });
326
353
  }
327
- /** message handler for socket
328
- * @param {} event
329
- */
354
+ /** message handler for socket */
330
355
  _onSocketMessage(event) {
331
356
  return __awaiter(this, void 0, void 0, function* () {
332
357
  switch (event.data) {
333
- case STOP_STORING_VID_SOCKET_MESSAGE:
358
+ case InboundMessageType.VideoBlock:
334
359
  // stopping vids from being sent
335
- this.metroplexTypeLock[VIDEO_METROPLEX_TYPE] = true;
360
+ this.metroplexTypeLock.pvvf = true;
336
361
  StoredMetrics.getInstance().setDidCutVideo();
337
362
  break;
338
- case STOP_STORING_PV_SOCKET_MESSAGE:
363
+ case InboundMessageType.PageVisitBlock:
339
364
  // stopping pv from being sent
340
- this.metroplexTypeLock[PV_METROPLEX_TYPE] = true;
365
+ this.metroplexTypeLock.pvp = true;
341
366
  StoredMetrics.getInstance().setDidCutPv();
342
367
  break;
343
- case BLOCK_SOCKET_MESSAGE:
368
+ case InboundMessageType.FullBlock:
344
369
  // we are disabling collect for 1 day if we get the
345
370
  // block message from metroplex. We are probably on it
346
- yield ClientConfig.getInstance().lockClient(1440, 'Metroplex blocked script');
371
+ yield ClientConfig.getInstance().lockClient(1440, { msg: 'Metroplex blocked script' });
347
372
  this.close();
348
373
  break;
349
- case CLOSE_CONNECTION_FORCEFULLY:
374
+ case InboundMessageType.CloseConnection:
350
375
  this.close();
351
376
  break;
352
- case OK_SOCKET_MESSAGE:
377
+ case InboundMessageType.OK:
353
378
  // we do nothing on an OK
354
379
  break;
355
380
  default:
@@ -359,10 +384,10 @@ class MetroplexSocket extends Singleton {
359
384
  // we now need to check if we receive text that contains
360
385
  // the text SEQ_NUM. if that is true, then its a seq num
361
386
  // and we need to clear out the retry queue.
362
- if (event.data.includes(SEQ_NUM_ATT_NAME)) {
363
- const seqNumSplit = event.data.split(`${SEQ_NUM_ATT_NAME}:`);
387
+ if (event.data.includes('seq_num')) {
388
+ const seqNumSplit = event.data.split('seq_num:');
364
389
  if (seqNumSplit.length < 2) {
365
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Invalid message received from metroplex while clearing retry queue ${event.data}`, false, SEVERITY.error);
390
+ ClientConfig.getInstance().postInternalError({ msg: `Invalid message received from metroplex while clearing retry queue`, data: event.data }, false, SEVERITY.error);
366
391
  break;
367
392
  }
368
393
  // the second element in the string split is the sequence number
@@ -399,10 +424,8 @@ class MetroplexSocket extends Singleton {
399
424
  * Returns true if the message's payload has the payload type given and has a sequence
400
425
  * number higher than seqNum
401
426
  */
402
- _messagePayloadHasLargerSeqNum(message, payloadType, seqNum) {
403
- return (message.payload[payloadType] &&
404
- message.payload[payloadType][SEQ_NUM_ATT_NAME] &&
405
- message.payload[payloadType][SEQ_NUM_ATT_NAME] > seqNum);
427
+ _messagePayloadHasLargerSeqNum(message, seqNum) {
428
+ return message.payload && message.payload.seq_num && message.payload.seq_num > seqNum;
406
429
  }
407
430
  /**
408
431
  * removes messages from the retry queue that are smaller than the
@@ -410,8 +433,7 @@ class MetroplexSocket extends Singleton {
410
433
  */
411
434
  _clearRetryQueue(seqNum) {
412
435
  this.latestReceivedSeqNumStoredTime = new Date();
413
- const newQueue = this.retryMessageQueue.filter(message => this._messagePayloadHasLargerSeqNum(message, PAGE_VISIT_PART_ATT_NAME, seqNum) ||
414
- this._messagePayloadHasLargerSeqNum(message, PAGE_VISIT_VID_FRAG_ATT_NAME, seqNum));
436
+ const newQueue = this.retryMessageQueue.filter(message => this._messagePayloadHasLargerSeqNum(message, seqNum));
415
437
  this.retryMessageQueue = createSlidingArrayOfSize(MAX_RETRY_MSG_Q_SIZE, newQueue);
416
438
  }
417
439
  /** will resend everything that is in the retry queue */
@@ -438,13 +460,12 @@ class MetroplexSocket extends Singleton {
438
460
  }
439
461
  }
440
462
  // removing all the messages with a blocked type from the retry queue
441
- this.retryMessageQueue = this.retryMessageQueue.filter(message => !(message.type in this.metroplexTypeLock));
463
+ this.retryMessageQueue = this.retryMessageQueue.filter(message => !this.metroplexTypeLock[message.type]);
442
464
  // we dont remove any items from this queue in this function
443
465
  for (let i = 0; i < this.retryMessageQueue.length; i += 1) {
444
466
  const { type, payload } = this.retryMessageQueue[i];
445
467
  // sending the data to metroplex
446
- // eslint-disable-next-line no-await-in-loop
447
- yield this._sendSocketMessage(payload);
468
+ yield this.sendSocketMessage({ [type]: payload });
448
469
  this.previousMessageType = type;
449
470
  }
450
471
  });
@@ -455,12 +476,6 @@ class MetroplexSocket extends Singleton {
455
476
  this._sendUnconfirmedMessages(true);
456
477
  }, METROPLEX_RETRY_FREQUENCY);
457
478
  }
458
- /** sets up events that will trigger the event queue to be emptied */
459
- _setupOffloadEvents() {
460
- // when the page hides we try getting all the events
461
- // and empty the event and retry queue.
462
- addSafeEventListener(window, 'pagehide', () => this._handleUnload(), false);
463
- }
464
479
  /**
465
480
  * will handle the final moments of a page being active. It
466
481
  * will try to empty both the queues with beacons.
@@ -488,26 +503,29 @@ class MetroplexSocket extends Singleton {
488
503
  */
489
504
  postFullPageVisit(maxMessageSize) {
490
505
  return __awaiter(this, void 0, void 0, function* () {
506
+ var _a;
491
507
  if (this.retryMessageQueue.length === 0) {
492
508
  return;
493
509
  }
494
510
  // debug counters
495
511
  const postInfo = [];
496
512
  const numDropped = {
497
- [VIDEO_METROPLEX_TYPE]: 0,
498
- [PV_METROPLEX_TYPE]: 0,
513
+ pvvf: 0,
514
+ pvp: 0,
515
+ pvh: 0,
499
516
  };
500
517
  let currentMsgPayloadSize = 0;
501
518
  let currentCompletePv = {
502
- [PAGE_VISIT_INFORMATION_ATT_NAME]: yield this.getPageInformation(),
503
- [PAGE_VISIT_PART_ATT_NAME]: [],
504
- [PAGE_VISIT_VID_FRAG_ATT_NAME]: [],
505
- [PAGE_VISIT_HTTP_DATA_ATT_NAME]: [],
506
- [VIDEO_PART_COUNT_ATT_NAME]: this.connectionCount,
519
+ pvi: yield this.getPageInformation(),
520
+ pvp: [],
521
+ pvvf: [],
522
+ pvh: [],
523
+ vpnum: this.connectionCount,
507
524
  };
508
- currentCompletePv[PAGE_VISIT_INFORMATION_ATT_NAME][IS_LAST_ATT_NAME] = true;
525
+ currentCompletePv.pvi.last = true;
509
526
  const pageInfo = yield this.getPageInformation();
510
527
  this.retryMessageQueue.forEach(msg => {
528
+ var _a, _b, _c;
511
529
  // can't use two variables types in obj deconstruction
512
530
  // eslint-disable-next-line prefer-const
513
531
  let { type, payload } = msg;
@@ -522,81 +540,84 @@ class MetroplexSocket extends Singleton {
522
540
  if (currentMsgPayloadSize >= maxMessageSize) {
523
541
  this.postMessage(currentCompletePv);
524
542
  // add to post info
525
- let postInfoMessage = `Vid: ${currentCompletePv[PAGE_VISIT_VID_FRAG_ATT_NAME].length}`;
526
- postInfoMessage += ` PV: ${currentCompletePv[PAGE_VISIT_PART_ATT_NAME].length}`;
527
- postInfoMessage += ` HTTP: ${currentCompletePv[PAGE_VISIT_HTTP_DATA_ATT_NAME].length},`;
543
+ let postInfoMessage = `Vid: ${currentCompletePv.pvvf.length}`;
544
+ postInfoMessage += ` PV: ${currentCompletePv.pvp.length}`;
545
+ postInfoMessage += ` HTTP: ${(_a = currentCompletePv.pvh) === null || _a === void 0 ? void 0 : _a.length},`;
528
546
  postInfo.push(postInfoMessage);
529
547
  // resetting currentCompletePv, since we need to keep adding
530
548
  // events to a blank object to send to metroplex.
531
549
  // retain the video part count, so we don't overwrite anything
532
550
  currentCompletePv = {
533
- [PAGE_VISIT_INFORMATION_ATT_NAME]: pageInfo,
534
- [PAGE_VISIT_PART_ATT_NAME]: [],
535
- [PAGE_VISIT_VID_FRAG_ATT_NAME]: [],
536
- [PAGE_VISIT_HTTP_DATA_ATT_NAME]: [],
537
- [VIDEO_PART_COUNT_ATT_NAME]: currentCompletePv[VIDEO_PART_COUNT_ATT_NAME],
551
+ pvi: pageInfo,
552
+ pvp: [],
553
+ pvvf: [],
554
+ pvh: [],
555
+ vpnum: currentCompletePv.vpnum,
538
556
  };
539
- currentCompletePv[PAGE_VISIT_INFORMATION_ATT_NAME][IS_LAST_ATT_NAME] =
540
- true;
557
+ currentCompletePv.pvi.last = true;
541
558
  // resetting the message size based on what is being added
542
559
  currentMsgPayloadSize = currentPayloadSize;
543
560
  }
544
- switch (type) {
545
- case VIDEO_METROPLEX_TYPE:
546
- currentCompletePv[PAGE_VISIT_VID_FRAG_ATT_NAME].push(payload[PAGE_VISIT_VID_FRAG_ATT_NAME]);
561
+ switch (msg.type) {
562
+ case WebsocketMessageType.PageVisitVideoFile:
563
+ currentCompletePv.pvvf.push(msg.payload);
547
564
  break;
548
- case PV_METROPLEX_TYPE:
549
- currentCompletePv[PAGE_VISIT_PART_ATT_NAME].push(payload[PAGE_VISIT_PART_ATT_NAME]);
565
+ case WebsocketMessageType.PageVisitPart:
566
+ currentCompletePv.pvp.push(msg.payload);
550
567
  break;
551
- case HTTP_DATA_METROPLEX_TYPE:
552
- currentCompletePv[PAGE_VISIT_HTTP_DATA_ATT_NAME].push(payload[PAGE_VISIT_HTTP_DATA_ATT_NAME]);
568
+ case WebsocketMessageType.PageVisitHttp:
569
+ (_c = (_b = currentCompletePv.pvh) === null || _b === void 0 ? void 0 : _b.push) === null || _c === void 0 ? void 0 : _c.call(_b, msg.payload);
553
570
  break;
554
571
  }
555
572
  });
556
- this.postMessage(currentCompletePv);
573
+ yield this.postMessage(currentCompletePv);
557
574
  // debug log if large retry message queue
558
575
  if (this.retryMessageQueue.length > 100) {
559
- let postInfoMessage = `Vid: ${currentCompletePv[PAGE_VISIT_VID_FRAG_ATT_NAME].length}`;
560
- postInfoMessage += ` PV: ${currentCompletePv[PAGE_VISIT_PART_ATT_NAME].length}`;
561
- postInfoMessage += ` HTTP: ${currentCompletePv[PAGE_VISIT_HTTP_DATA_ATT_NAME].length},`;
576
+ let postInfoMessage = `Vid: ${currentCompletePv.pvvf.length}`;
577
+ postInfoMessage += ` PV: ${currentCompletePv.pvp.length}`;
578
+ postInfoMessage += ` HTTP: ${(_a = currentCompletePv.pvh) === null || _a === void 0 ? void 0 : _a.length},`;
562
579
  postInfo.push(postInfoMessage);
563
580
  // we completed posted the full pv, send the confirmation debug logs
564
581
  // build the debug message
565
- let message = 'POST Full PV complete';
566
- // POST counts
567
- message += `, POSTs count: ${postInfo.length}`;
568
- message += `, POSTs info: ${stringifyJSON(postInfo)}`;
569
- // Initial retry message queue size
570
- message += `, Retry message queue size: ${this.retryMessageQueue.length}`;
582
+ const message = {
583
+ msg: `POST Full PV complete`,
584
+ postsCount: postInfo.length,
585
+ postsInfo: stringifyJSON(postInfo),
586
+ retryMessageQueueSize: this.retryMessageQueue.length,
587
+ };
571
588
  // Num drops
572
- if (numDropped[VIDEO_METROPLEX_TYPE] > 0) {
573
- message += `, Video parts dropped: ${numDropped[VIDEO_METROPLEX_TYPE]}`;
589
+ if (numDropped.pvvf > 0) {
590
+ message.videoPartsDropped = numDropped.pvvf;
574
591
  }
575
- if (numDropped[PV_METROPLEX_TYPE] > 0) {
576
- message += `, Page visit parts dropped: ${numDropped[PV_METROPLEX_TYPE]}`;
592
+ if (numDropped.pvp > 0) {
593
+ message.pvpPartsDropped = numDropped.pvp;
577
594
  }
578
- if (numDropped[HTTP_DATA_METROPLEX_TYPE] > 0) {
579
- message += `, HTTP data parts dropped: ${numDropped[HTTP_DATA_METROPLEX_TYPE]}`;
595
+ if (numDropped.pvh > 0) {
596
+ message.httpPartsDropped = numDropped.pvh;
580
597
  }
581
598
  // Sequence info
582
- message += `, Sequence Info: Latest ${this.messageSequenceNum}`;
583
- message += ` Ack'd ${this.latestReceivedSeqNumStoredTime} ${this.latestReceivedSeqNumber}`;
599
+ message.sequenceInfo = {
600
+ Latest: this.messageSequenceNum,
601
+ acked: {
602
+ latestReceivedSeqNumStoredTime: this.latestReceivedSeqNumStoredTime,
603
+ latestReceivedSeqNumber: this.latestReceivedSeqNumber,
604
+ },
605
+ };
584
606
  // if client was disabled (due to inactive or otherwise) enable briefly so the
585
607
  // debug message gets through
586
608
  const clientDisabled = ClientConfig.getInstance().isClientDisabled;
587
609
  ClientConfig.getInstance().isClientDisabled = false;
588
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(message, clientDisabled, SEVERITY.warn);
610
+ ClientConfig.getInstance().postInternalError(message, clientDisabled, SEVERITY.warn);
589
611
  }
590
612
  });
591
613
  }
592
- /**
593
- * will send a message to metroplex via a post request that will outlive the current page
594
- */
614
+ /** will send a message to metroplex via a post request that will outlive the current page */
595
615
  postMessage(msg) {
596
616
  return __awaiter(this, void 0, void 0, function* () {
597
617
  const updatedMsg = msg;
618
+ updatedMsg.vpnum || (updatedMsg.vpnum = 0);
598
619
  // ensure a unique video part number each call
599
- updatedMsg[VIDEO_PART_COUNT_ATT_NAME] += 1;
620
+ updatedMsg.vpnum += 1;
600
621
  // we send the remainder elements
601
622
  unwrapNoibuWrapped(fetch)(this.postURL, {
602
623
  method: 'POST',
@@ -615,18 +636,16 @@ class MetroplexSocket extends Singleton {
615
636
  * is active and returns true. If inactive the session and socket are closed
616
637
  * and this method returns false.
617
638
  */
618
- _sendSocketMessage(payload) {
639
+ sendSocketMessage(payload) {
619
640
  return __awaiter(this, void 0, void 0, function* () {
620
- noibuLog('_sendSocketMessage');
641
+ noibuLog('sendSocketMessage');
621
642
  const closeIfInactive = yield this.closeIfInactive();
622
643
  if (closeIfInactive) {
623
- noibuLog('_sendSocketMessage dropped due to', { closeIfInactive });
644
+ noibuLog('sendSocketMessage dropped due to', { closeIfInactive });
624
645
  return;
625
646
  }
647
+ noibuLog(`_sendSocketMessage sending: `, payload);
626
648
  const payloadJson = stringifyJSON(payload);
627
- noibuLog(`_sendSocketMessage sending: ${PAGE_VISIT_VID_FRAG_ATT_NAME in payload
628
- ? PAGE_VISIT_VID_FRAG_ATT_NAME
629
- : payloadJson}`);
630
649
  if (this.socket) {
631
650
  this.socket.send(payloadJson);
632
651
  }
@@ -644,7 +663,7 @@ class MetroplexSocket extends Singleton {
644
663
  // lock the client for 1 minute, since the lock expires
645
664
  // only on new page loads this will lock the client until
646
665
  // the next page is loaded.
647
- yield ClientConfig.getInstance().lockClientUntilNextPage('Session is inactive, locking until next page');
666
+ yield ClientConfig.getInstance().lockClientUntilNextPage({ msg: 'Session is inactive, locking until next page' });
648
667
  this.close();
649
668
  // post metrics now so we don't include events after going inactive
650
669
  StoredMetrics.getInstance().postMetrics();
@@ -658,29 +677,27 @@ class MetroplexSocket extends Singleton {
658
677
  getPageInformation() {
659
678
  return __awaiter(this, void 0, void 0, function* () {
660
679
  return {
661
- [BROWSER_ID_ATT_NAME]: ClientConfig.getInstance().browserId,
662
- [PV_ID_ATT_NAME]: ClientConfig.getInstance().pageVisitId,
663
- [VER_ATT_NAME]: CURRENT_PV_VERSION,
664
- [PV_SEQ_ATT_NAME]: yield ClientConfig.getInstance().getPageVisitSeq(),
665
- [ON_URL_ATT_NAME]: this.initialURL,
666
- [REF_URL_ATT_NAME]: this.initialReferringURL,
667
- [STARTED_AT_ATT_NAME]: this.sessionTimestamp.toISOString(),
668
- [CONN_COUNT_ATT_NAME]: this.connectionCount,
669
- [COLLECT_VER_ATT_NAME]: CURRENT_NOIBUJS_VERSION,
670
- [IS_LAST_ATT_NAME]: false,
671
- [SCRIPT_ID_ATT_NAME]: GET_SCRIPT_ID(),
672
- [SCRIPT_INSTANCE_ID_ATT_NAME]: this.scriptInstanceId,
673
- [METROPLEX_SOCKET_INSTANCE_ID_ATT_NAME]: this.instanceId,
674
- [SOCKET_INSTANCE_ID_ATT_NAME]: this.socketInstanceId,
675
- [VIDEO_RECORDER_ATT_NAME]: yield getVideoRecorderType(),
680
+ br_id: ClientConfig.getInstance().browserId,
681
+ pv_id: ClientConfig.getInstance().pageVisitId,
682
+ v: CURRENT_PV_VERSION,
683
+ seq: yield ClientConfig.getInstance().getPageVisitSeq(),
684
+ on_url: this.initialURL,
685
+ ref_url: this.initialReferringURL,
686
+ start_at: this.sessionTimestamp.toISOString(),
687
+ conc: this.connectionCount,
688
+ cv: CURRENT_NOIBUJS_VERSION,
689
+ last: false,
690
+ script_id: GET_SCRIPT_ID(),
691
+ script_inst_id: this.scriptInstanceId,
692
+ mp_sock_inst_id: this.instanceId,
693
+ sock_inst_id: this.socketInstanceId,
694
+ video_recorder: yield getVideoRecorderType(),
676
695
  };
677
696
  });
678
697
  }
679
- /**
680
- * Try to parse help code response and fire custom event
681
- */
698
+ /** Try to parse help code response and fire custom event */
682
699
  _tryProcessHelpCodeResponse(response) {
683
- const prefix = `${HELP_CODE_ATT_NAME}:`;
700
+ const prefix = `${WorkRequestMessageType.HelpCode}:`;
684
701
  if (typeof response !== 'string' || !response.startsWith(prefix)) {
685
702
  return false;
686
703
  }
@@ -692,11 +709,5 @@ class MetroplexSocket extends Singleton {
692
709
  return true;
693
710
  }
694
711
  }
695
- MetroplexSocket.typeToPayloadPropMap = {
696
- [HTTP_DATA_METROPLEX_TYPE]: PAGE_VISIT_HTTP_DATA_ATT_NAME,
697
- [META_DATA_METROPLEX_TYPE]: PAGE_VISIT_META_DATA_ATT_NAME,
698
- [PV_METROPLEX_TYPE]: PAGE_VISIT_PART_ATT_NAME,
699
- [VIDEO_METROPLEX_TYPE]: PAGE_VISIT_VID_FRAG_ATT_NAME,
700
- };
701
712
 
702
- export { createSlidingArrayOfSize, MetroplexSocket as default };
713
+ export { createSlidingArrayOfSize, MetroplexSocket as default, getVideoRecorderType };