noibu-react-native 0.0.4 → 0.0.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 (42) hide show
  1. package/README.md +22 -7
  2. package/dist/api/clientConfig.d.ts +101 -0
  3. package/dist/api/clientConfig.js +317 -388
  4. package/dist/api/helpCode.js +2 -2
  5. package/dist/api/inputManager.js +3 -9
  6. package/dist/api/metroplexSocket.js +10 -34
  7. package/dist/api/storedMetrics.js +3 -2
  8. package/dist/api/storedPageVisit.js +3 -3
  9. package/dist/constants.d.ts +7 -40
  10. package/dist/constants.js +8 -65
  11. package/dist/entry/index.d.ts +2 -3
  12. package/dist/entry/index.js +1 -9
  13. package/dist/entry/init.d.ts +5 -0
  14. package/dist/entry/init.js +60 -75
  15. package/dist/monitors/AppNavigationMonitor.d.ts +23 -0
  16. package/dist/monitors/AppNavigationMonitor.js +63 -0
  17. package/dist/monitors/clickMonitor.js +10 -57
  18. package/dist/monitors/errorMonitor.js +1 -1
  19. package/dist/monitors/gqlErrorValidator.js +3 -3
  20. package/dist/monitors/httpDataBundler.js +13 -12
  21. package/dist/monitors/integrations/react-native-navigation-integration.d.ts +19 -0
  22. package/dist/monitors/integrations/react-native-navigation-integration.js +38 -0
  23. package/dist/monitors/keyboardInputMonitor.js +0 -1
  24. package/dist/monitors/requestMonitor.js +10 -8
  25. package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +10 -8
  26. package/dist/storage/storage.d.ts +3 -2
  27. package/dist/storage/storageProvider.d.ts +6 -5
  28. package/dist/types/Config.d.ts +27 -0
  29. package/dist/types/NavigationIntegration.d.ts +7 -0
  30. package/dist/types/PageVisit.d.ts +22 -0
  31. package/dist/types/ReactNative.d.ts +4 -0
  32. package/dist/types/Storage.d.ts +14 -0
  33. package/dist/types/globals.d.ts +34 -0
  34. package/dist/utils/date.js +2 -2
  35. package/dist/utils/eventlistener.js +3 -3
  36. package/dist/utils/function.d.ts +93 -0
  37. package/dist/utils/function.js +210 -320
  38. package/dist/utils/stacktrace-parser.d.ts +6 -8
  39. package/dist/utils/stacktrace-parser.js +5 -5
  40. package/package.json +5 -1
  41. package/dist/monitors/elementMonitor.js +0 -177
  42. package/dist/monitors/locationChangeMonitor.js +0 -18
@@ -1,10 +1,10 @@
1
1
  import uuid from 'react-native-uuid';
2
- import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, DISABLED_STATUS_KEY, CLIENT_UNLOCK_TIME_KEY, SEVERITY_WARN, LAST_ACTIVE_TIME_KEY, CURRENT_PAGE_VISIT_COUNT_KEY, NOIBU_BROWSER_ID_KYWRD, BROWSER_ID_KEY, PV_SEQ_NUM_RESET_TIME_MINUTES, SEVERITY_ERROR, JS_ENV, PAGE_VISIT_ID_KEY, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
3
- import { stringifyJSON, getUserAgent, asString, getProperGlobalUrl, makeRequest } from '../utils/function.js';
2
+ import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, SEVERITY, NOIBU_BROWSER_ID_KYWRD, PV_SEQ_NUM_RESET_TIME_MINUTES, JS_ENV, MAX_PAGEVISIT_VISITED, CLIENT_LOCK_TIME_MINUTES, GET_SCRIPT_ID, MAX_COLLECT_ERROR_LOG } from '../constants.js';
3
+ import { stringifyJSON, getUserAgent, asString, makeRequest } from '../utils/function.js';
4
4
  import Storage from '../storage/storage.js';
5
+ import { AppNavigationMonitor } from '../monitors/AppNavigationMonitor.js';
5
6
 
6
7
  /** @module ClientConfig */
7
-
8
8
  /**
9
9
  * Singleton class to manage the client configuration
10
10
  * this class will be responsible for controlling the disabled
@@ -12,407 +12,336 @@ import Storage from '../storage/storage.js';
12
12
  * storing and retrieval.
13
13
  */
14
14
  class ClientConfig {
15
- /**
16
- * Creates a ClientConfig singleton instance
17
- * @param {string} noibuErrorURL
18
- * @param {string} customerDomain
19
- */
20
- constructor(noibuErrorURL, customerDomain) {
21
- // sets up this.browserId, this.disabledStatus
22
- this.pageVisitId = uuid.v4();
23
- // variables stored in storage
24
- this.isClientDisabled = null;
25
- this.browserId = null;
26
- this.pageVisitSeq = null;
27
- // This variable tracks the last time the user was active in this session.
28
- // It is also written to storage. Initialized to now so the session can be
29
- // timed out even if a PV is never sent.
30
- this.lastActiveTime = new Date();
31
- // error URL to send Noibu errors to
32
- this.noibuErrorURL = noibuErrorURL;
33
- // sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
34
- this._setupStorageVars();
35
- // error sent to backend counter
36
- this.cltErrorPostCounter = 0;
37
- // variables for checking if the socket is inactive
38
- // used a class variables in order to be changed in testing
39
- this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
40
-
41
- this.customerDomain = customerDomain;
42
- }
43
-
44
- /** Configures the singleton instance */
45
- static configureInstance({ noibuErrorURL, customerDomain }) {
46
- if (!this.instance) {
47
- // Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
48
- // configured properly and throws an error.
49
- // This will ensure we get the expected error POST request at the correct URL.
50
- this.noibuErrorURL = noibuErrorURL;
51
- this.instance = new ClientConfig(noibuErrorURL, customerDomain);
52
- this.instance.noibuErrorURL = noibuErrorURL;
15
+ pageVisitId;
16
+ browserId;
17
+ pageVisitSeq;
18
+ lastActiveTime;
19
+ noibuErrorURL;
20
+ cltErrorPostCounter;
21
+ maxSocketInactiveTime;
22
+ static instance;
23
+ static noibuErrorURL;
24
+ customerDomain;
25
+ isClientDisabled;
26
+ listOfUrlsToCollectHttpDataFrom;
27
+ enableHttpDataCollection;
28
+ blockedElements;
29
+ /**
30
+ * Creates a ClientConfig singleton instance
31
+ */
32
+ constructor(noibuErrorURL, customerConfig) {
33
+ // sets up this.browserId, this.disabledStatus
34
+ this.pageVisitId = uuid.v4();
35
+ // variables stored in storage
36
+ this.isClientDisabled = false;
37
+ this.browserId = '';
38
+ this.pageVisitSeq = null;
39
+ // This variable tracks the last time the user was active in this session.
40
+ // It is also written to storage. Initialized to now so the session can be
41
+ // timed out even if a PV is never sent.
42
+ this.lastActiveTime = new Date();
43
+ // error URL to send Noibu errors to
44
+ this.noibuErrorURL = noibuErrorURL;
45
+ // sets up this.browserId, this.isClientDisabled, this.pageVisitSeq
46
+ this._setupStorageVars();
47
+ // error sent to backend counter
48
+ this.cltErrorPostCounter = 0;
49
+ // variables for checking if the socket is inactive
50
+ // used a class variables in order to be changed in testing
51
+ this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
52
+ this.customerDomain = customerConfig.domain;
53
+ this.listOfUrlsToCollectHttpDataFrom =
54
+ customerConfig.listOfUrlsToCollectHttpDataFrom;
55
+ this.enableHttpDataCollection = customerConfig.enableHttpDataCollection;
56
+ this.blockedElements = customerConfig.blockedElements;
53
57
  }
54
- }
55
-
56
- /**
57
- * gets the singleton instance
58
- * @returns {ClientConfig}
59
- */
60
- static getInstance() {
61
- if (!this.instance) {
62
- throw new Error('ClientConfig was not configured');
58
+ /** Configures the singleton instance */
59
+ static configureInstance({ noibuErrorURL, customerConfig, }) {
60
+ if (!this.instance) {
61
+ // Set this.noibuErrorURL preemptively in case ClientConfig isn't able to be
62
+ // configured properly and throws an error.
63
+ // This will ensure we get the expected error POST request at the correct URL.
64
+ this.noibuErrorURL = noibuErrorURL;
65
+ this.instance = new ClientConfig(noibuErrorURL, customerConfig);
66
+ this.instance.noibuErrorURL = noibuErrorURL;
67
+ }
63
68
  }
64
-
65
- return this.instance;
66
- }
67
-
68
- /** lockClient will disable the client script for a single pagevisit for
69
- * duration given in minuntes */
70
- async lockClient(duration, msg) {
71
- const expiryTime = new Date();
72
- expiryTime.setMinutes(expiryTime.getMinutes() + duration);
73
-
74
- const noibuLSObject = await this._getClientState();
75
- noibuLSObject[DISABLED_STATUS_KEY] = true;
76
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
77
- await this._storeBrowserData(noibuLSObject);
78
- this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY_WARN);
79
- }
80
-
81
- /** Locks the client until the next page loads */
82
- lockClientUntilNextPage(msg) {
83
- this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY_WARN);
84
- }
85
-
86
- /** Updates the config object to store the given last active time */
87
- async updateLastActiveTime(lastActiveTime) {
88
- this.lastActiveTime = lastActiveTime;
89
- const newConfigData = await this._getLsObject();
90
- newConfigData[LAST_ACTIVE_TIME_KEY] = lastActiveTime;
91
- await this._storeBrowserData(newConfigData);
92
- }
93
-
94
- /** Gets the current page visit sequence number that should be used */
95
- async getPageVisitSeq() {
96
- if (await this._pageVisitSeqNeedsReset()) {
97
- // Reset the page visit sequence number to zero and store the next seq number in storage
98
- this.pageVisitSeq = 0;
99
- const newConfigData = await this._getLsObject();
100
- newConfigData[CURRENT_PAGE_VISIT_COUNT_KEY] = this.pageVisitSeq + 1;
101
- // Update the last active time since we are actively requesting the seq
102
- newConfigData[LAST_ACTIVE_TIME_KEY] = new Date();
103
- await this._storeBrowserData(newConfigData);
69
+ /**
70
+ * gets the singleton instance
71
+ * @returns {ClientConfig}
72
+ */
73
+ static getInstance() {
74
+ if (!this.instance) {
75
+ throw new Error('ClientConfig was not configured');
76
+ }
77
+ return this.instance;
104
78
  }
105
-
106
- return this.pageVisitSeq;
107
- }
108
-
109
- /**
110
- * Returns the client config object from storage or generates a new one
111
- * What is stored in storage will look like this
112
- * {
113
- * BrowserId: UUIDV4
114
- * ExpiryTime: DATE OBJ
115
- * DisabledStatus: BOOL
116
- * CurrentPageVisitCount: INT
117
- * ClientUnlockTime: DATE OBJ
118
- * LastActiveTime: DATE OBJ
119
- * }
120
- */
121
- async _getLsObject() {
122
- const storage = Storage.getInstance();
123
- const storedConfig = await storage.load(NOIBU_BROWSER_ID_KYWRD);
124
-
125
- // first time browsing since noibu was installed
126
- if (!storedConfig) {
127
- return this._generateAndStoreData();
79
+ /** lockClient will disable the client script for a single pagevisit for
80
+ * duration given in minuntes */
81
+ async lockClient(duration, msg) {
82
+ const expiryTime = new Date();
83
+ expiryTime.setMinutes(expiryTime.getMinutes() + duration);
84
+ const noibuLSObject = await this._getClientState();
85
+ noibuLSObject.DisabledStatus = true;
86
+ noibuLSObject.ClientUnlockTime = expiryTime;
87
+ await this._storeBrowserData(noibuLSObject);
88
+ this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY.warn);
128
89
  }
129
-
130
- let parsedConfig = {};
131
-
132
- try {
133
- parsedConfig = JSON.parse(storedConfig);
134
- } catch (e) {
135
- return this._generateAndStoreData();
90
+ /** Locks the client until the next page loads */
91
+ lockClientUntilNextPage(msg) {
92
+ this.postNoibuErrorAndOptionallyDisableClient(msg, true, SEVERITY.warn);
136
93
  }
137
-
138
- // checking if it's a valid object. The CLIENT_UNLOCK_TIME_KEY doesn't have to exist
139
- // since it's not written to the storage object when set to null.
140
- if (
141
- parsedConfig[BROWSER_ID_KEY] == null ||
142
- parsedConfig[DISABLED_STATUS_KEY] == null ||
143
- parsedConfig[CURRENT_PAGE_VISIT_COUNT_KEY] == null ||
144
- parsedConfig[LAST_ACTIVE_TIME_KEY] == null
145
- ) {
146
- return this._generateAndStoreData();
94
+ /** Updates the config object to store the given last active time */
95
+ async updateLastActiveTime(lastActiveTime) {
96
+ this.lastActiveTime = lastActiveTime;
97
+ const newConfigData = await this._getLsObject();
98
+ newConfigData.LastActive = lastActiveTime;
99
+ await this._storeBrowserData(newConfigData);
147
100
  }
148
- return parsedConfig;
149
- }
150
-
151
- /**
152
- * Check if we have surpased the last active time and the page visit seq number needs resetting
153
- */
154
- async _pageVisitSeqNeedsReset() {
155
- const noibuLSObject = await this._getClientState();
156
- const someTimeAgo = new Date();
157
- someTimeAgo.setMinutes(
158
- someTimeAgo.getMinutes() - PV_SEQ_NUM_RESET_TIME_MINUTES,
159
- );
160
- return new Date(noibuLSObject[LAST_ACTIVE_TIME_KEY]) < someTimeAgo;
161
- }
162
-
163
- /**
164
- * _setupStorageVars will set all class variables that depend
165
- * on the storage's value.
166
- */
167
- async _setupStorageVars() {
168
- const storage = Storage.getInstance();
169
- if (!(await storage.isAvailable())) {
170
- this.postNoibuErrorAndOptionallyDisableClient(
171
- `Storage is unavailable, disabling client. ${await storage.getDiagnoseInfo()}`,
172
- true,
173
- SEVERITY_ERROR,
174
- );
175
- return;
101
+ /** Gets the current page visit sequence number that should be used */
102
+ async getPageVisitSeq() {
103
+ if (await this._pageVisitSeqNeedsReset()) {
104
+ // Reset the page visit sequence number to zero and store the next seq number in storage
105
+ this.pageVisitSeq = 0;
106
+ const newConfigData = await this._getLsObject();
107
+ newConfigData.CurrentPageVisitCount = this.pageVisitSeq + 1;
108
+ // Update the last active time since we are actively requesting the seq
109
+ newConfigData.LastActive = new Date();
110
+ await this._storeBrowserData(newConfigData);
111
+ }
112
+ return this.pageVisitSeq;
176
113
  }
177
-
178
- // getting the current content of the storage
179
- const noibuLSObject = await this._getClientState();
180
-
181
- // Check if we have surpased the last active time and reset the sequence number if so
182
- if (await this._pageVisitSeqNeedsReset()) {
183
- noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] = 0;
114
+ /**
115
+ * Returns the client config object from storage or generates a new one
116
+ * What is stored in storage will look like this
117
+ * {
118
+ * BrowserId: UUIDV4
119
+ * ExpiryTime: DATE OBJ
120
+ * DisabledStatus: BOOL
121
+ * CurrentPageVisitCount: INT
122
+ * ClientUnlockTime: DATE OBJ
123
+ * LastActiveTime: DATE OBJ
124
+ * }
125
+ */
126
+ async _getLsObject() {
127
+ const storage = Storage.getInstance();
128
+ const storedConfig = await storage.load(NOIBU_BROWSER_ID_KYWRD);
129
+ // first time browsing since noibu was installed
130
+ if (!storedConfig) {
131
+ return this._generateAndStoreData();
132
+ }
133
+ let parsedConfig = {};
134
+ try {
135
+ parsedConfig = JSON.parse(storedConfig);
136
+ }
137
+ catch (e) {
138
+ return this._generateAndStoreData();
139
+ }
140
+ // checking if it's a valid object. The CLIENT_UNLOCK_TIME_KEY doesn't have to exist
141
+ // since it's not written to the storage object when set to null.
142
+ if (!(parsedConfig.BrowserId &&
143
+ Boolean(parsedConfig.DisabledStatus) === parsedConfig.DisabledStatus &&
144
+ parsedConfig.CurrentPageVisitCount &&
145
+ parsedConfig.LastActive)) {
146
+ return this._generateAndStoreData();
147
+ }
148
+ return parsedConfig;
184
149
  }
185
-
186
- this.browserId = noibuLSObject[BROWSER_ID_KEY];
187
- this.pageVisitSeq = noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY];
188
- this.isClientDisabled = noibuLSObject[DISABLED_STATUS_KEY];
189
-
190
- // If the client has been disabled just return.
191
- // Calling _getClientState() above performs the disabled expirey check
192
- if (this.isClientDisabled) return;
193
-
194
- // Update the LS object values before storing it for the next page visit
195
- noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] += 1;
196
- noibuLSObject[LAST_ACTIVE_TIME_KEY] = new Date();
197
-
198
- // Expose page visit ID in storage for use by Trailbreaker video tests
199
- // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
200
- if (JS_ENV().includes('video')) {
201
- noibuLSObject[PAGE_VISIT_ID_KEY] = this.pageVisitId;
150
+ /**
151
+ * Check if we have surpassed the last active time and the page visit seq number needs resetting
152
+ */
153
+ async _pageVisitSeqNeedsReset() {
154
+ const noibuLSObject = await this._getClientState();
155
+ const someTimeAgo = new Date();
156
+ someTimeAgo.setMinutes(someTimeAgo.getMinutes() - PV_SEQ_NUM_RESET_TIME_MINUTES);
157
+ if (!noibuLSObject.LastActive) {
158
+ return true;
159
+ }
160
+ return new Date(noibuLSObject.LastActive) < someTimeAgo;
202
161
  }
203
-
204
- // if we have reached the max page visits for a browser id then
205
- // we disabled collect for 45 minutes
206
- if (noibuLSObject[CURRENT_PAGE_VISIT_COUNT_KEY] >= MAX_PAGEVISIT_VISITED) {
207
- // if we bust the max pagevisit visited limit we lock the client for 45 minutes
208
- // since its probably a bot.
209
- const expiryTime = new Date();
210
- expiryTime.setMinutes(expiryTime.getMinutes() + CLIENT_LOCK_TIME_MINUTES);
211
- // setting the lock time
212
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
213
- noibuLSObject[DISABLED_STATUS_KEY] = true;
214
- this.postNoibuErrorAndOptionallyDisableClient(
215
- `Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins`,
216
- true,
217
- SEVERITY_ERROR,
218
- );
219
- }
220
-
221
- // we now check if we successfully saved the data
222
- const savedData = await this._storeBrowserData(noibuLSObject);
223
-
224
- // if the browser is null, we cannot access the storage or an
225
- // error happened, thus we disable collect.
226
- if (savedData[BROWSER_ID_KEY] === null) {
227
- // we do not set a lock expiry date here since we cannot store to storage
228
- this.postNoibuErrorAndOptionallyDisableClient(
229
- `Null browser in storage, disabling client`,
230
- true,
231
- SEVERITY_ERROR,
232
- );
233
- this.browserId = null;
162
+ /**
163
+ * _setupStorageVars will set all class variables that depend
164
+ * on the storage's value.
165
+ */
166
+ async _setupStorageVars() {
167
+ const storage = Storage.getInstance();
168
+ if (!(await storage.isAvailable())) {
169
+ this.postNoibuErrorAndOptionallyDisableClient(`Storage is unavailable, disabling client. ${await storage.getDiagnoseInfo()}`, true, SEVERITY.error);
170
+ return;
171
+ }
172
+ // getting the current content of the storage
173
+ const noibuLSObject = await this._getClientState();
174
+ // Check if we have surpased the last active time and reset the sequence number if so
175
+ if (await this._pageVisitSeqNeedsReset()) {
176
+ noibuLSObject.CurrentPageVisitCount = 0;
177
+ }
178
+ this.browserId = noibuLSObject.BrowserId;
179
+ this.pageVisitSeq = noibuLSObject.CurrentPageVisitCount;
180
+ this.isClientDisabled = noibuLSObject.DisabledStatus;
181
+ // If the client has been disabled just return.
182
+ // Calling _getClientState() above performs the disabled expirey check
183
+ if (this.isClientDisabled)
184
+ return;
185
+ // Update the LS object values before storing it for the next page visit
186
+ noibuLSObject.CurrentPageVisitCount += 1;
187
+ noibuLSObject.LastActive = new Date();
188
+ // Expose page visit ID in storage for use by Trailbreaker video tests
189
+ // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
190
+ if (JS_ENV().includes('video')) {
191
+ noibuLSObject.pvId = this.pageVisitId;
192
+ }
193
+ // if we have reached the max page visits for a browser id then
194
+ // we disabled collect for 45 minutes
195
+ if (noibuLSObject.CurrentPageVisitCount >= MAX_PAGEVISIT_VISITED) {
196
+ // if we bust the max pagevisit visited limit we lock the client for 45 minutes
197
+ // since its probably a bot.
198
+ const expiryTime = new Date();
199
+ expiryTime.setMinutes(expiryTime.getMinutes() + CLIENT_LOCK_TIME_MINUTES);
200
+ // setting the lock time
201
+ noibuLSObject.ClientUnlockTime = expiryTime;
202
+ noibuLSObject.DisabledStatus = true;
203
+ this.postNoibuErrorAndOptionallyDisableClient(`Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins`, true, SEVERITY.error);
204
+ }
205
+ // we now check if we successfully saved the data
206
+ const savedData = await this._storeBrowserData(noibuLSObject);
207
+ // if the browser is null, we cannot access the storage or an
208
+ // error happened, thus we disable collect.
209
+ if (!savedData.BrowserId) {
210
+ // we do not set a lock expiry date here since we cannot store to storage
211
+ this.postNoibuErrorAndOptionallyDisableClient(`Null browser in storage, disabling client`, true, SEVERITY.error);
212
+ this.browserId = '';
213
+ }
234
214
  }
235
- }
236
-
237
- /**
238
- * Function will get the Noibu Storage Object
239
- * 1. Generate a brand new one
240
- * Get it from storage if the expiry date is not in the past
241
- * Generate a brand new one if the expiry date is in the past
242
- */
243
- async _getClientState() {
244
- const newConfigData = await this._getLsObject();
245
-
246
- // if the lock expired, we remove the lock period and enable the client
247
- if (
248
- newConfigData[CLIENT_UNLOCK_TIME_KEY] &&
249
- new Date(newConfigData[CLIENT_UNLOCK_TIME_KEY]) <= new Date()
250
- ) {
251
- newConfigData[CLIENT_UNLOCK_TIME_KEY] = null;
252
- newConfigData[DISABLED_STATUS_KEY] = false;
253
- await this._storeBrowserData(newConfigData);
215
+ /**
216
+ * Function will get the Noibu Storage Object
217
+ * 1. Generate a brand new one
218
+ * Get it from storage if the expiry date is not in the past
219
+ * Generate a brand new one if the expiry date is in the past
220
+ */
221
+ async _getClientState() {
222
+ const newConfigData = await this._getLsObject();
223
+ // if the lock expired, we remove the lock period and enable the client
224
+ if (newConfigData.ClientUnlockTime &&
225
+ new Date(newConfigData.ClientUnlockTime) <= new Date()) {
226
+ newConfigData.ClientUnlockTime = undefined;
227
+ newConfigData.DisabledStatus = false;
228
+ await this._storeBrowserData(newConfigData);
229
+ }
230
+ // return the stored browserId
231
+ return newConfigData;
254
232
  }
255
- // return the stored browserId
256
- return newConfigData;
257
- }
258
-
259
- /**
260
- * _generateAndStoreData generates brand new data and then proceeds to store
261
- * it.
262
- */
263
- async _generateAndStoreData() {
264
- return this._storeBrowserData(this._generateNewBrowserData());
265
- }
266
-
267
- /**
268
- * _generateNewBrowserData will create new data to be stored in storage
269
- * and persisted throughout a session
270
- */
271
- _generateNewBrowserData() {
272
- const noibuBrowserData = {
273
- [DISABLED_STATUS_KEY]: false,
274
- [BROWSER_ID_KEY]: uuid.v4(),
275
- [CURRENT_PAGE_VISIT_COUNT_KEY]: 0,
276
- [CLIENT_UNLOCK_TIME_KEY]: null,
277
- [LAST_ACTIVE_TIME_KEY]: new Date(),
278
- };
279
-
280
- // Expose page visit ID in storage for use by Trailbreaker video tests
281
- // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
282
- if (JS_ENV().includes('video')) {
283
- noibuBrowserData[PAGE_VISIT_ID_KEY] = this.pageVisitId;
233
+ /**
234
+ * _generateAndStoreData generates brand new data and then proceeds to store
235
+ * it.
236
+ */
237
+ async _generateAndStoreData() {
238
+ return this._storeBrowserData(this._generateNewBrowserData());
284
239
  }
285
-
286
- return noibuBrowserData;
287
- }
288
-
289
- /**
290
- * _storeBrowserData will store the passed object in storage.
291
- * @param {} data the data to be stored
292
- */
293
- async _storeBrowserData(data) {
294
- const storage = Storage.getInstance();
295
- try {
296
- await storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
297
- return data;
298
- } catch (e) {
299
- this.postNoibuErrorAndOptionallyDisableClient(
300
- `Error writing browser data to storage, disabling client: ${e.message}, ` +
301
- `${await storage.getDiagnoseInfo()}`,
302
- true,
303
- SEVERITY_ERROR,
304
- );
305
- // sending empty fields if we encountered errors while storing in the LS
306
- return {
307
- [DISABLED_STATUS_KEY]: true,
308
- [BROWSER_ID_KEY]: null,
309
- [CURRENT_PAGE_VISIT_COUNT_KEY]: 0,
310
- };
240
+ /**
241
+ * _generateNewBrowserData will create new data to be stored in storage
242
+ * and persisted throughout a session
243
+ */
244
+ _generateNewBrowserData() {
245
+ const noibuBrowserData = {
246
+ DisabledStatus: false,
247
+ BrowserId: uuid.v4(),
248
+ CurrentPageVisitCount: 0,
249
+ LastActive: new Date(),
250
+ };
251
+ // Expose page visit ID in storage for use by Trailbreaker video tests
252
+ // This will be done for the testvideo and lambdavideo bundles used by Trailbreaker
253
+ if (JS_ENV().includes('video')) {
254
+ noibuBrowserData.pvId = this.pageVisitId;
255
+ }
256
+ return noibuBrowserData;
311
257
  }
312
- }
313
-
314
- /**
315
- * postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
316
- * and disable the client if required
317
- * severity expects one of the SEVERITY_x level constants, or else error will be used
318
- * @param {} error
319
- * @param {} disableClient
320
- * @param {} severity
321
- * @param {} keepAlive=false
322
- */
323
- async postNoibuErrorAndOptionallyDisableClient(
324
- error,
325
- disableClient,
326
- severity,
327
- keepAlive = false,
328
- ) {
329
- if (this.isClientDisabled) {
330
- return;
258
+ /**
259
+ * _storeBrowserData will store the passed object in storage.
260
+ * @param {} data the data to be stored
261
+ */
262
+ async _storeBrowserData(data) {
263
+ const storage = Storage.getInstance();
264
+ try {
265
+ await storage.save(NOIBU_BROWSER_ID_KYWRD, stringifyJSON(data));
266
+ return data;
267
+ }
268
+ catch (e) {
269
+ this.postNoibuErrorAndOptionallyDisableClient(`Error writing browser data to storage, disabling client: ${e.message}, ${await storage.getDiagnoseInfo()}`, true, SEVERITY.error);
270
+ // sending empty fields if we encountered errors while storing in the LS
271
+ return this._generateNewBrowserData();
272
+ }
331
273
  }
332
- if (disableClient) {
333
- this.isClientDisabled = true;
274
+ /**
275
+ * postNoibuErrorAndOptionallyDisableClient will post errors that were thrown by collect
276
+ * and disable the client if required
277
+ * severity expects one of the SEVERITY_x level constants, or else error will be used
278
+ */
279
+ async postNoibuErrorAndOptionallyDisableClient(errorMsg, disableClient, severity, keepAlive = false) {
280
+ if (this.isClientDisabled) {
281
+ return;
282
+ }
283
+ if (disableClient) {
284
+ this.isClientDisabled = true;
285
+ }
286
+ if (severity === SEVERITY.warn) {
287
+ // don't log warning messages by default, as a cost savings
288
+ return;
289
+ }
290
+ let errMsg = `Noibu Browser ID(${this.browserId ? this.browserId : ''}), PV ID ${this.pageVisitId}, Script ID ${GET_SCRIPT_ID()}, and User Agent ${await getUserAgent()} error: ${asString(errorMsg)}`;
291
+ // if the page visits sends more errors than the
292
+ // allowed threshold we disable the client
293
+ if (this.cltErrorPostCounter >= MAX_COLLECT_ERROR_LOG) {
294
+ // we disable the client for 10 minute if we sent too many logs
295
+ // we manually lock the client to not cause an infinite loop
296
+ const expiryTime = new Date();
297
+ expiryTime.setMinutes(expiryTime.getMinutes() + 10); // 10 minutes lock
298
+ const noibuLSObject = await this._getClientState();
299
+ noibuLSObject.DisabledStatus = true;
300
+ noibuLSObject.ClientUnlockTime = expiryTime;
301
+ await this._storeBrowserData(noibuLSObject);
302
+ this.isClientDisabled = true;
303
+ // end of lock
304
+ // overriding the message to be an alert that we are shutting collect off.
305
+ errMsg =
306
+ 'Shutting collect off, we reached the ' +
307
+ 'maximum limit of collect errors sent.';
308
+ }
309
+ const errorContent = {
310
+ url: AppNavigationMonitor.getInstance().globalUrl,
311
+ err_msg: errMsg,
312
+ sev: severity,
313
+ };
314
+ const headers = {
315
+ 'content-type': 'application/json',
316
+ 'User-Agent': await getUserAgent(),
317
+ };
318
+ if (keepAlive) {
319
+ fetch(this.noibuErrorURL, {
320
+ method: 'POST',
321
+ headers,
322
+ body: stringifyJSON(errorContent),
323
+ // keep alive outlives the current page, its the same as beacon
324
+ keepalive: true,
325
+ });
326
+ }
327
+ else {
328
+ makeRequest('POST', this.noibuErrorURL, errorContent, headers, 2000, false).catch(() => {
329
+ // we do nothing and let this error silently fail
330
+ });
331
+ }
332
+ // only increment if this was an actual error, not a warning or otherwise
333
+ if (severity === SEVERITY.error) {
334
+ this.cltErrorPostCounter += 1;
335
+ }
334
336
  }
335
- if (severity === SEVERITY_WARN) {
336
- // don't log warning messages by default, as a cost savings
337
- return;
337
+ /**
338
+ * Returns true if the page visit is considered to be inactive
339
+ */
340
+ isInactive() {
341
+ const someTimeAgo = new Date();
342
+ someTimeAgo.setSeconds(someTimeAgo.getSeconds() - this.maxSocketInactiveTime);
343
+ return this.lastActiveTime < someTimeAgo;
338
344
  }
339
-
340
- let errMsg = `Noibu Browser ID(${
341
- this.browserId ? this.browserId : ''
342
- }), PV ID ${
343
- this.pageVisitId
344
- }, Script ID ${GET_SCRIPT_ID()}, and User Agent ${await getUserAgent()} error: ${asString(
345
- error,
346
- )}`;
347
-
348
- // if the page visits sends more errors than the
349
- // allowed threshold we disable the client
350
- if (this.cltErrorPostCounter >= MAX_COLLECT_ERROR_LOG) {
351
- // we disable the client for 10 minute if we sent too many logs
352
- // we manually lock the client to not cause an infinite loop
353
- const expiryTime = new Date();
354
- expiryTime.setMinutes(expiryTime.getMinutes() + 10); // 10 minutes lock
355
-
356
- const noibuLSObject = await this._getClientState();
357
- noibuLSObject[DISABLED_STATUS_KEY] = true;
358
- noibuLSObject[CLIENT_UNLOCK_TIME_KEY] = expiryTime;
359
- await this._storeBrowserData(noibuLSObject);
360
- this.isClientDisabled = true;
361
- // end of lock
362
- // overriding the message to be an alert that we are shutting collect off.
363
- errMsg =
364
- 'Shutting collect off, we reached the ' +
365
- 'maximum limit of collect errors sent.';
366
- }
367
-
368
- const errorContent = {
369
- url: getProperGlobalUrl(),
370
- err_msg: errMsg,
371
- sev: severity,
372
- };
373
- const headers = {
374
- 'content-type': 'application/json',
375
- 'User-Agent': await getUserAgent(),
376
- };
377
-
378
- if (keepAlive) {
379
- global.fetch(this.noibuErrorURL, {
380
- method: 'POST',
381
- headers,
382
- body: stringifyJSON(errorContent),
383
- // keep alive outlives the current page, its the same as beacon
384
- keepalive: true,
385
- });
386
- } else {
387
- makeRequest(
388
- 'POST',
389
- this.noibuErrorURL,
390
- errorContent,
391
- headers,
392
- 2000,
393
- false,
394
- ).catch(() => {
395
- // we do nothing and let this error silently fail
396
- });
397
- }
398
-
399
- // only increment if this was an actual error, not a warning or otherwise
400
- if (severity === SEVERITY_ERROR) {
401
- this.cltErrorPostCounter += 1;
402
- }
403
- }
404
-
405
- /**
406
- * Returns true if the page visit is considered to be inactive
407
- */
408
- isInactive() {
409
- const someTimeAgo = new Date();
410
- someTimeAgo.setSeconds(
411
- someTimeAgo.getSeconds() - this.maxSocketInactiveTime,
412
- );
413
-
414
- return this.lastActiveTime < someTimeAgo;
415
- }
416
345
  }
417
346
 
418
347
  export { ClientConfig as default };