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