noibu-react-native 0.2.5 → 0.2.7

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (98) hide show
  1. package/README.md +15 -15
  2. package/android/build.gradle +1 -1
  3. package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
  4. package/dist/api/{helpCode.js → HelpCode.js} +6 -13
  5. package/dist/api/InputManager.js +156 -0
  6. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
  7. package/dist/api/StoredMetrics.js +158 -0
  8. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
  9. package/dist/const_matchers.js +1 -5
  10. package/dist/constants.js +15 -390
  11. package/dist/entry/index.js +3 -4
  12. package/dist/entry/init.js +33 -19
  13. package/dist/monitors/AppNavigationMonitor.js +19 -19
  14. package/dist/monitors/BaseMonitor.js +9 -4
  15. package/dist/monitors/ClickMonitor.js +72 -76
  16. package/dist/monitors/ErrorMonitor.js +45 -55
  17. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  18. package/dist/monitors/PageMonitor.js +25 -2
  19. package/dist/monitors/RequestMonitor.js +46 -57
  20. package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
  21. package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
  22. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  23. package/dist/pageVisit/EventDebouncer.js +43 -74
  24. package/dist/pageVisit/HttpEventManager.js +88 -0
  25. package/dist/pageVisit/PageVisitManager.js +99 -0
  26. package/dist/pageVisit/pageVisitEventError.js +170 -280
  27. package/dist/react/ErrorBoundary.js +3 -6
  28. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
  29. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  30. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  31. package/dist/storage/{storage.js → Storage.js} +17 -30
  32. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  33. package/dist/utils/date.js +39 -50
  34. package/dist/utils/eventlistener.js +5 -12
  35. package/dist/utils/function.js +42 -113
  36. package/dist/utils/log.js +5 -5
  37. package/dist/utils/object.js +12 -12
  38. package/dist/utils/piiRedactor.js +31 -3
  39. package/dist/utils/stacktrace-parser.js +29 -21
  40. package/package.json +14 -14
  41. package/dist/api/inputManager.js +0 -227
  42. package/dist/api/storedMetrics.js +0 -198
  43. package/dist/pageVisit/pageVisit.js +0 -181
  44. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  45. package/dist/pageVisit/userStep.js +0 -20
  46. package/dist/src/api/clientConfig.d.ts +0 -100
  47. package/dist/src/api/clientConfig.test.d.ts +0 -1
  48. package/dist/src/api/helpCode.d.ts +0 -23
  49. package/dist/src/api/inputManager.d.ts +0 -87
  50. package/dist/src/api/metroplexSocket.d.ts +0 -137
  51. package/dist/src/api/storedMetrics.d.ts +0 -73
  52. package/dist/src/api/storedPageVisit.d.ts +0 -40
  53. package/dist/src/const_matchers.d.ts +0 -1
  54. package/dist/src/constants.d.ts +0 -290
  55. package/dist/src/entry/index.d.ts +0 -14
  56. package/dist/src/entry/init.d.ts +0 -5
  57. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  58. package/dist/src/monitors/BaseMonitor.d.ts +0 -13
  59. package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
  60. package/dist/src/monitors/ClickMonitor.d.ts +0 -31
  61. package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
  62. package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
  63. package/dist/src/monitors/PageMonitor.d.ts +0 -20
  64. package/dist/src/monitors/RequestMonitor.d.ts +0 -94
  65. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  66. package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
  67. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  68. package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
  69. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  70. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  71. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  72. package/dist/src/pageVisit/userStep.d.ts +0 -5
  73. package/dist/src/react/ErrorBoundary.d.ts +0 -72
  74. package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
  75. package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
  76. package/dist/src/sessionRecorder/types.d.ts +0 -91
  77. package/dist/src/storage/rnStorageProvider.d.ts +0 -23
  78. package/dist/src/storage/storage.d.ts +0 -39
  79. package/dist/src/storage/storageProvider.d.ts +0 -26
  80. package/dist/src/utils/date.d.ts +0 -6
  81. package/dist/src/utils/eventlistener.d.ts +0 -8
  82. package/dist/src/utils/function.d.ts +0 -102
  83. package/dist/src/utils/log.d.ts +0 -4
  84. package/dist/src/utils/object.d.ts +0 -44
  85. package/dist/src/utils/performance.d.ts +0 -6
  86. package/dist/src/utils/piiRedactor.d.ts +0 -11
  87. package/dist/src/utils/polyfills.d.ts +0 -4
  88. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  89. package/dist/types/Config.d.ts +0 -31
  90. package/dist/types/Metroplex.types.d.ts +0 -73
  91. package/dist/types/NavigationIntegration.d.ts +0 -6
  92. package/dist/types/PageVisit.types.d.ts +0 -8
  93. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  94. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  95. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  96. package/dist/types/Storage.d.ts +0 -14
  97. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  98. package/dist/types/WrappedObjects.d.ts +0 -6
@@ -1,52 +1,49 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import { strToU8, zlibSync, strFromU8 } from 'fflate';
3
3
  import { LogLevel, initialize, subscribeToNativeEvent } from './nativeSessionRecorderSubscription.js';
4
- import StoredMetrics from '../api/storedMetrics.js';
5
- import ClientConfig from '../api/clientConfig.js';
4
+ import StoredMetrics from '../api/StoredMetrics.js';
5
+ import ClientConfig from '../api/ClientConfig.js';
6
6
  import { stringifyJSON } from '../utils/function.js';
7
- import { MAX_TIME_FOR_RECORDER_USER_EVENTS, SEVERITY, MAX_RECORDER_EVENT_BUFFER, MAX_TIME_FOR_UNSENT_DATA_MILLIS, VIDEO_FRAG_ATT_NAME, PV_SEQ_ATT_NAME, LENGTH_ATT_NAME, CSS_URLS_ATT_NAME, VIDEO_METROPLEX_TYPE, PAGE_VISIT_VID_FRAG_ATT_NAME, POST_METRICS_EVENT_NAME } from '../constants.js';
8
- import MetroplexSocket from '../api/metroplexSocket.js';
7
+ import { SEVERITY, MAX_TIME_FOR_UNSENT_DATA_MILLIS } from '../constants.js';
8
+ import MetroplexSocket from '../api/MetroplexSocket.js';
9
9
  import { addSafeEventListener } from '../utils/eventlistener.js';
10
10
  import { noibuLog } from '../utils/log.js';
11
11
  import { Platform } from 'react-native';
12
+ import { Singleton } from '../monitors/BaseMonitor.js';
13
+ import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
14
+ import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
12
15
 
16
+ // custom event name for posting metrics
17
+ const POST_METRICS_EVENT_NAME = 'noibuPostMetrics';
18
+ // the max amount of time to wait for user events until freezing rrweb mutation events
19
+ const MAX_TIME_FOR_RECORDER_USER_EVENTS = 2000;
20
+ // Maximum number of events in the RRWEB session recorder buffer
21
+ // before sending to Metroplex
22
+ const MAX_RECORDER_EVENT_BUFFER = 10;
13
23
  /** Singleton class to record user sessions */
14
- class SessionRecorder {
15
- /**
16
- * Creates an instance of the session recorder
17
- */
24
+ class SessionRecorder extends Singleton {
25
+ /** Setups the SessionRecorder instance for usage */
18
26
  constructor() {
19
- this.freezingEvents = false;
27
+ super();
20
28
  this.eventBuffer = [];
21
29
  this.vfCounter = 0;
22
30
  this.didSetupRecorder = false;
23
- this.recordStopper = null;
24
- this.firstRecordedTimestamp = null;
25
- this.lastRecordedTimestamp = null;
26
31
  this.isVideoLengthNegativeInvalid = false;
27
32
  this.lastFragPostTimestamp = Date.now();
28
33
  this.pauseTimeout = null;
34
+ this.lastRecordedTimestamp = null;
35
+ this.firstRecordedTimestamp = null;
36
+ this.recordStopper = null;
37
+ this.freezingEvents = false;
29
38
  this.setupUnloadHandler();
30
39
  this.setupPostMetricsHandler();
31
- }
32
- /**
33
- * Setups the SessionRecorder instance for usage
34
- */
35
- static getInstance() {
36
- if (!this.instance) {
37
- const nativeSessionRecorderConfig = {
38
- logLevel: LogLevel.Verbose,
39
- };
40
- if (Platform.OS === 'android') {
41
- initialize('abc1234', nativeSessionRecorderConfig);
42
- }
43
- this.instance = new SessionRecorder();
44
- // todo handle RN clicks
45
- addSafeEventListener(window, 'click', () => {
46
- this.instance.handleFragPost();
47
- });
40
+ const nativeSessionRecorderConfig = {
41
+ logLevel: LogLevel.Verbose,
42
+ };
43
+ if (Platform.OS === 'android') {
44
+ initialize('abc1234', nativeSessionRecorderConfig);
48
45
  }
49
- return this.instance;
46
+ addSafeEventListener(window, 'click', () => this.handleFragPost());
50
47
  }
51
48
  /** Sets up the page hide handler to try to push remaining video events */
52
49
  setupUnloadHandler() {
@@ -64,8 +61,7 @@ class SessionRecorder {
64
61
  // Get the event name that triggered postMetrics from the custom event
65
62
  const eventName = e.detail;
66
63
  // Calculate the total expected video length
67
- const totalVideoTime = this.lastRecordedTimestamp === null ||
68
- this.firstRecordedTimestamp === null
64
+ const totalVideoTime = this.lastRecordedTimestamp === null || this.firstRecordedTimestamp === null
69
65
  ? 0
70
66
  : this.lastRecordedTimestamp - this.firstRecordedTimestamp;
71
67
  const sessionLength = MetroplexSocket.getInstance().sessionLength
@@ -77,7 +73,8 @@ class SessionRecorder {
77
73
  // debug message gets through
78
74
  const clientDisabled = ClientConfig.getInstance().isClientDisabled;
79
75
  ClientConfig.getInstance().isClientDisabled = false;
80
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient({
76
+ ClientConfig.getInstance().postInternalError({
77
+ msg: 'large retry message queue',
81
78
  eventName,
82
79
  totalVideoTime,
83
80
  sessionLength,
@@ -85,15 +82,12 @@ class SessionRecorder {
85
82
  }
86
83
  });
87
84
  }
88
- /**
89
- * Starts recording the user session
90
- */
85
+ /** Starts recording the user session */
91
86
  recordUserSession() {
92
87
  return __awaiter(this, void 0, void 0, function* () {
93
88
  // check if inactive before starting any recording
94
89
  noibuLog('recordUserSession');
95
- if ((yield MetroplexSocket.getInstance().closeIfInactive()) ||
96
- StoredMetrics.getInstance().didCutVideo) {
90
+ if ((yield MetroplexSocket.getInstance().closeIfInactive()) || StoredMetrics.getInstance().didCutVideo) {
97
91
  return;
98
92
  }
99
93
  // making sure we are not attempting to call this method
@@ -116,8 +110,7 @@ class SessionRecorder {
116
110
  return __awaiter(this, void 0, void 0, function* () {
117
111
  const timestamp = Date.now();
118
112
  // check if inactive before any processing
119
- if ((yield MetroplexSocket.getInstance().closeIfInactive()) ||
120
- StoredMetrics.getInstance().didCutVideo) {
113
+ if ((yield MetroplexSocket.getInstance().closeIfInactive()) || StoredMetrics.getInstance().didCutVideo) {
121
114
  this.freeze();
122
115
  return;
123
116
  }
@@ -153,9 +146,8 @@ class SessionRecorder {
153
146
  // the metrics 'exp_vid_len' data.
154
147
  // If we don't adjust for time, we assume that the expected video length is
155
148
  // the difference between the first recorded timestamp and the last recorded timestamp.
156
- if (this.firstRecordedTimestamp &&
157
- timestamp < this.firstRecordedTimestamp) {
158
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Detected time rewind. Client has been disabled.`, true, SEVERITY.error, true);
149
+ if (this.firstRecordedTimestamp && timestamp < this.firstRecordedTimestamp) {
150
+ ClientConfig.getInstance().postInternalError({ msg: `Detected time rewind. Client has been disabled.` }, true, SEVERITY.error, true);
159
151
  return;
160
152
  }
161
153
  const packedEvent = yield this.pack(recorderEvent.message);
@@ -167,30 +159,26 @@ class SessionRecorder {
167
159
  // todo if there are clicks, call StoredMetrics.getInstance().addVideoClick(); for each click
168
160
  const now = Date.now();
169
161
  const delta = now - this.lastFragPostTimestamp;
170
- if (this.eventBuffer.length >= MAX_RECORDER_EVENT_BUFFER ||
171
- delta > MAX_TIME_FOR_UNSENT_DATA_MILLIS) {
162
+ if (this.eventBuffer.length >= MAX_RECORDER_EVENT_BUFFER || delta > MAX_TIME_FOR_UNSENT_DATA_MILLIS) {
172
163
  this.handleFragPost();
173
164
  }
174
165
  });
175
166
  }
176
- /**
177
- * Compress event
178
- */
167
+ /** Compress event */
179
168
  pack(recorderEvent) {
180
169
  return __awaiter(this, void 0, void 0, function* () {
181
170
  // return JSON.stringify(recorderEvent);
182
171
  return SessionRecorder.compress(recorderEvent);
183
172
  });
184
173
  }
174
+ /** Compresses the snapshot */
185
175
  static compress(snapshot) {
186
176
  const uncompressedString = stringifyJSON(snapshot);
187
177
  const uncompressedData = strToU8(uncompressedString);
188
178
  const compressedData = zlibSync(uncompressedData, { level: 1 });
189
- const compressedString = strFromU8(compressedData, true);
190
- return compressedString;
179
+ return strFromU8(compressedData, true);
191
180
  }
192
- /** builds a log message with debug info
193
- */
181
+ /** builds a log message with debug info */
194
182
  buildDebugMessage(eventName, totalVideoTime, sessionLength) {
195
183
  return JSON.stringify({ eventName, totalVideoTime, sessionLength });
196
184
  }
@@ -215,21 +203,20 @@ class SessionRecorder {
215
203
  try {
216
204
  let totalVideoTime = 0;
217
205
  // checking if we have those values set in the first place
218
- if (this.firstRecordedTimestamp &&
219
- this.lastRecordedTimestamp &&
220
- !this.isVideoLengthNegativeInvalid) {
221
- totalVideoTime =
222
- this.lastRecordedTimestamp - this.firstRecordedTimestamp;
206
+ if (this.firstRecordedTimestamp && this.lastRecordedTimestamp && !this.isVideoLengthNegativeInvalid) {
207
+ totalVideoTime = this.lastRecordedTimestamp - this.firstRecordedTimestamp;
223
208
  }
224
209
  // In the past we have seen the video LengthMS field to be negative
225
210
  // and bigger than the long limit of scala. Which is less than the
226
211
  // safe integer limit of js.
227
- if (!this.isVideoLengthNegativeInvalid &&
228
- (totalVideoTime < 0 || totalVideoTime >= Number.MAX_SAFE_INTEGER)) {
212
+ if (!this.isVideoLengthNegativeInvalid && (totalVideoTime < 0 || totalVideoTime >= Number.MAX_SAFE_INTEGER)) {
229
213
  // we log an error to know if this is still happening
230
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`video lengthMS is invalid: ${totalVideoTime}, ` +
231
- `start time: ${this.firstRecordedTimestamp}, ` +
232
- `end time: ${this.lastRecordedTimestamp}`, false, SEVERITY.error);
214
+ ClientConfig.getInstance().postInternalError({
215
+ msg: 'video length MS is invalid',
216
+ totalVideoTime,
217
+ 'start time': this.firstRecordedTimestamp,
218
+ 'end time': this.lastRecordedTimestamp,
219
+ }, false, SEVERITY.error);
233
220
  this.isVideoLengthNegativeInvalid = true;
234
221
  totalVideoTime = 0;
235
222
  }
@@ -239,23 +226,24 @@ class SessionRecorder {
239
226
  // when being sent to metroplex which we will then unmarshall into
240
227
  // a struct to parse it's inner urls
241
228
  // If stringifying this event buffer takes too long consider using a service worker
242
- [VIDEO_FRAG_ATT_NAME]: stringifyJSON(this.eventBuffer),
229
+ vid: stringifyJSON(this.eventBuffer),
243
230
  // Send the sequence number but don't send the expected length since that is sent as
244
231
  // part of the last stored metrics data
245
- [PV_SEQ_ATT_NAME]: this.vfCounter,
246
- [LENGTH_ATT_NAME]: totalVideoTime,
247
- [CSS_URLS_ATT_NAME]: [],
232
+ seq: this.vfCounter,
233
+ len: totalVideoTime,
234
+ css_urls: [],
248
235
  }, false);
249
236
  StoredMetrics.getInstance().addVideoFragData(this.vfCounter, totalVideoTime);
250
237
  // constructing a client message that metroplex knows how to handle.
251
- yield MetroplexSocket.getInstance().sendMessage(VIDEO_METROPLEX_TYPE, {
252
- [PAGE_VISIT_VID_FRAG_ATT_NAME]: videoFragment,
238
+ yield MetroplexSocket.getInstance().sendMessage({
239
+ type: WebsocketMessageType.PageVisitVideoFile,
240
+ payload: videoFragment,
253
241
  });
254
242
  this.lastFragPostTimestamp = Date.now();
255
243
  }
256
244
  catch (err) {
257
245
  // letting collect know we are closing the rrweb listener
258
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`video frag socket closed with err: ${err.message}`, false, SEVERITY.error);
246
+ ClientConfig.getInstance().postInternalError({ msg: `video frag socket closed with err: ${err.message}` }, false, SEVERITY.error);
259
247
  // if we detect an error in the frag posting, we stop recording
260
248
  // the video
261
249
  this.freeze();
@@ -282,7 +270,7 @@ class SessionRecorder {
282
270
  this.recordStopper();
283
271
  }
284
272
  catch (e) {
285
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(`Error during handleFragPost in recordStopper: ${e}`, false, SEVERITY.error);
273
+ ClientConfig.getInstance().postInternalError({ msg: `Error during handleFragPost in recordStopper: ${e}` }, false, SEVERITY.error);
286
274
  }
287
275
  }
288
276
  }
@@ -8,9 +8,7 @@ const LINKING_ERROR = `The package 'noibu-session-replay' doesn't seem to be lin
8
8
  const { NativeSessionRecorder } = NativeModules;
9
9
  let nativeModuleEmitter;
10
10
  const SupportedPlatforms = ['android'];
11
- /**
12
- * The level of logging to show in the device logcat stream.
13
- */
11
+ /** The level of logging to show in the device logcat stream. */
14
12
  // eslint-disable-next-line no-shadow
15
13
  var LogLevel;
16
14
  (function (LogLevel) {
@@ -53,10 +51,10 @@ function initialize(projectId, config) {
53
51
  * and invokes the provided callback whenever the event occurs. If the platform is not Android,
54
52
  * the function will do nothing and return a no-op unsubscribe function.
55
53
  *
56
- * @param {function(RecorderEvent): void} callback - A callback function that will be invoked with
54
+ * @param {function(RecorderEvent): void} callback - Target callback function that will be invoked with
57
55
  * the event data whenever the `noibuRecordingEvent` is emitted.
58
56
  *
59
- * @returns {UnsubscribeFn} A function to unsubscribe from the event. On Android, this will remove
57
+ * @returns {UnsubscribeFn} Target function to unsubscribe from the event. On Android, this will remove
60
58
  * the event listener. On other platforms, it will be a no-op.
61
59
  *
62
60
  * @throws {Error} If the Noibu Session Recorder is not initialized before calling this function.
@@ -1,14 +1,10 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import AsyncStorage from '@react-native-async-storage/async-storage';
3
- import StorageProvider from './storageProvider.js';
3
+ import StorageProvider from './StorageProvider.js';
4
4
 
5
- /**
6
- * React native storage provider implementation
7
- */
5
+ /** React native storage provider implementation */
8
6
  class RNStorageProvider extends StorageProvider {
9
- /**
10
- * Creates new instance
11
- */
7
+ /** Creates new instance */
12
8
  constructor() {
13
9
  super(AsyncStorage);
14
10
  }
@@ -1,41 +1,29 @@
1
1
  import { __awaiter } from 'tslib';
2
- import RNStorageProvider from './rnStorageProvider.js';
2
+ import RNStorageProvider from './RNStorageProvider.js';
3
+ import { Singleton } from '../monitors/BaseMonitor.js';
3
4
 
4
- /**
5
- * Encapsulates storage api
6
- */
7
- class Storage {
8
- /**
9
- * Creates new instance assessing available options
10
- */
5
+ /** Encapsulates storage api */
6
+ class Storage extends Singleton {
7
+ /** Creates new instance assessing available options */
11
8
  constructor() {
9
+ super();
12
10
  // todo replace with promise all if more storage available
13
11
  const rnStorageAvailability = RNStorageProvider.isAvailable();
14
- this._provider = rnStorageAvailability.then(({ result }) => result ? new RNStorageProvider() : null);
15
- this._type = rnStorageAvailability.then(({ result }) => result ? 'RNStorage' : 'unavailable');
16
- this._isRNStorageAvailable = rnStorageAvailability.then(({ result }) => result);
17
- this._rnStorageError = rnStorageAvailability.then(({ error }) => error);
18
- }
19
- /**
20
- * Singleton
21
- * @returns {Storage}
22
- */
23
- static getInstance() {
24
- if (!this._instance) {
25
- this._instance = new Storage();
26
- }
27
- return this._instance;
12
+ this.provider = rnStorageAvailability.then(({ result }) => (result ? new RNStorageProvider() : null));
13
+ this.type = rnStorageAvailability.then(({ result }) => (result ? 'RNStorage' : 'unavailable'));
14
+ this.isRNStorageAvailable = rnStorageAvailability.then(({ result }) => result);
15
+ this.rnStorageError = rnStorageAvailability.then(({ error }) => error);
28
16
  }
29
17
  /** Checks if storage is available */
30
18
  isAvailable() {
31
19
  return __awaiter(this, void 0, void 0, function* () {
32
- return (yield this._provider) !== null;
20
+ return (yield this.provider) !== null;
33
21
  });
34
22
  }
35
23
  /** Loads value from storage */
36
24
  load(key) {
37
25
  return __awaiter(this, void 0, void 0, function* () {
38
- const provider = yield this._provider;
26
+ const provider = yield this.provider;
39
27
  if (provider !== null) {
40
28
  return provider.load(key);
41
29
  }
@@ -45,7 +33,7 @@ class Storage {
45
33
  /** Saves value to storage */
46
34
  save(key, value) {
47
35
  return __awaiter(this, void 0, void 0, function* () {
48
- const provider = yield this._provider;
36
+ const provider = yield this.provider;
49
37
  if (provider !== null) {
50
38
  return provider.save(key, value);
51
39
  }
@@ -58,7 +46,7 @@ class Storage {
58
46
  */
59
47
  remove(key) {
60
48
  return __awaiter(this, void 0, void 0, function* () {
61
- const provider = yield this._provider;
49
+ const provider = yield this.provider;
62
50
  if (provider !== null) {
63
51
  return provider.remove(key);
64
52
  }
@@ -68,7 +56,7 @@ class Storage {
68
56
  /** Calculates used scape */
69
57
  calculateUsedSize() {
70
58
  return __awaiter(this, void 0, void 0, function* () {
71
- const provider = yield this._provider;
59
+ const provider = yield this.provider;
72
60
  if (provider !== null) {
73
61
  return provider.calculateUsedSize();
74
62
  }
@@ -82,9 +70,8 @@ class Storage {
82
70
  */
83
71
  getDiagnoseInfo() {
84
72
  return __awaiter(this, void 0, void 0, function* () {
85
- return `storage provider: ${yield this
86
- ._type} (rnStorage available: ${yield this
87
- ._isRNStorageAvailable}, error: ${yield this._rnStorageError})`;
73
+ return `storage provider: ${yield this.type} (rnStorage available: ${yield this
74
+ .isRNStorageAvailable}, error: ${yield this.rnStorageError})`;
88
75
  });
89
76
  }
90
77
  }
@@ -1,13 +1,14 @@
1
1
  import { __awaiter } from 'tslib';
2
- import { NOIBU_LOCAL_STORAGE_TEST_KEY } from '../constants.js';
3
2
 
3
+ // The local storage key used to test whether writing to local storage is supported
4
+ const NOIBU_LOCAL_STORAGE_TEST_KEY = 'n_key';
4
5
  /**
5
6
  * Base implementation for LocalStorage and SessionStorage
6
7
  */
7
8
  class StorageProvider {
8
9
  /** Creates new instance based on provided provider type */
9
10
  constructor(provider) {
10
- this._provider = provider;
11
+ this.provider = provider;
11
12
  }
12
13
  /** Checks if provider is available */
13
14
  static isAvailable(resolver) {
@@ -26,12 +27,10 @@ class StorageProvider {
26
27
  return { result, error };
27
28
  });
28
29
  }
29
- /**
30
- * Loads value from storage
31
- */
30
+ /** Loads value from storage */
32
31
  load(key) {
33
32
  return __awaiter(this, void 0, void 0, function* () {
34
- const value = yield this._provider.getItem(key);
33
+ const value = yield this.provider.getItem(key);
35
34
  if (value !== null) {
36
35
  return value;
37
36
  }
@@ -40,14 +39,14 @@ class StorageProvider {
40
39
  }
41
40
  /** Saves value to storage */
42
41
  save(key, value) {
43
- return this._provider.setItem(key, `${value}`);
42
+ return this.provider.setItem(key, `${value}`);
44
43
  }
45
44
  /**
46
45
  * Removes value from storage
47
46
  * @param {String} key
48
47
  */
49
48
  remove(key) {
50
- return this._provider.removeItem(key);
49
+ return this.provider.removeItem(key);
51
50
  }
52
51
  }
53
52
 
@@ -1,62 +1,51 @@
1
- import ClientConfig from '../api/clientConfig.js';
1
+ import ClientConfig from '../api/ClientConfig.js';
2
2
  import { SEVERITY } from '../constants.js';
3
3
 
4
4
  /** @module Date */
5
-
6
5
  /** Checks to see if the necessary Date functions that we use have been overwritten */
7
6
  function isDateOverwritten() {
8
- // Check to see if Date.now() exists
9
- if (!('now' in Date)) {
10
- return true;
11
- }
12
-
13
- // Check to ensure that Date.now() returns a number
14
- if (typeof Date.now() !== 'number') {
15
- return true;
16
- }
17
-
18
- // Check to see if new Date().toISOString() exists
19
- if (!('toISOString' in new Date())) {
20
- return true;
21
- }
22
-
23
- // Check to ensure new Date().toISOString() returns a string
24
- if (typeof new Date().toISOString() !== 'string') {
25
- return true;
26
- }
27
-
28
- // If none of the above checks return true, we assume that the Date function
29
- // has not been overwritten
30
- return false;
7
+ // Check to see if Date.now() exists
8
+ if (!('now' in Date)) {
9
+ return true;
10
+ }
11
+ // Check to ensure that Date.now() returns a number
12
+ if (typeof Date.now() !== 'number') {
13
+ return true;
14
+ }
15
+ // Check to see if new Date().toISOString() exists
16
+ if (!('toISOString' in new Date())) {
17
+ return true;
18
+ }
19
+ // Check to ensure new Date().toISOString() returns a string
20
+ if (typeof new Date().toISOString() !== 'string') {
21
+ return true;
22
+ }
23
+ // If none of the above checks return true, we assume that the Date function
24
+ // has not been overwritten
25
+ return false;
31
26
  }
32
-
33
27
  /** Timestamp wrapper to properly handle timestamps
34
- * @param {} timestamp
35
28
  */
36
29
  function timestampWrapper(timestamp) {
37
- // If the Date object has been overwritten and the timestamp is not a number,
38
- // we use the valueOf property to try to retrieve the actual timestamp.
39
- // If valueOf is not available, we disable client and log the error.
40
- if (typeof timestamp !== 'number' && isDateOverwritten()) {
41
- if (
42
- // eslint-disable-next-line no-prototype-builtins
43
- Date.prototype.hasOwnProperty('valueOf') &&
44
- typeof timestamp.valueOf === 'function' &&
45
- typeof timestamp.valueOf() === 'number'
46
- ) {
47
- return timestamp.valueOf();
48
- }
49
-
50
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
51
- `The date object has been overwritten and can't be processed properly.
30
+ var _a;
31
+ // If the Date object has been overwritten and the timestamp is not a number,
32
+ // we use the valueOf property to try to retrieve the actual timestamp.
33
+ // If valueOf is not available, we disable client and log the error.
34
+ if (typeof timestamp === 'object' && isDateOverwritten()) {
35
+ const value = (_a = timestamp === null || timestamp === void 0 ? void 0 : timestamp.valueOf) === null || _a === void 0 ? void 0 : _a.call(timestamp);
36
+ if (typeof value === 'number') {
37
+ return value;
38
+ }
39
+ ClientConfig.getInstance().postInternalError({
40
+ msg: `The date object has been overwritten and can't be processed properly.
52
41
  Client has been disabled.`,
53
- true,
54
- SEVERITY.error,
55
- true,
56
- );
57
- }
58
-
59
- return timestamp;
42
+ }, true, SEVERITY.error, true);
43
+ }
44
+ return timestamp;
45
+ }
46
+ /** Get the current time in ISO format */
47
+ function getOccurredNow() {
48
+ return new Date(timestampWrapper(Date.now())).toISOString();
60
49
  }
61
50
 
62
- export { isDateOverwritten, timestampWrapper };
51
+ export { getOccurredNow, isDateOverwritten, timestampWrapper };
@@ -1,5 +1,5 @@
1
1
  import { SEVERITY } from '../constants.js';
2
- import ClientConfig from '../api/clientConfig.js';
2
+ import ClientConfig from '../api/ClientConfig.js';
3
3
 
4
4
  /** addSafeEventListener will add an event listener for the specified event
5
5
  * but will catch and log any errors encountered
@@ -21,7 +21,7 @@ function addSafeEventListener(object, event, callback, capture = false) {
21
21
  try {
22
22
  callback(eventReceived);
23
23
  } catch (e) {
24
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
24
+ ClientConfig.getInstance().postInternalError(
25
25
  `addEventListener callback error: ${e.message}`,
26
26
  false,
27
27
  SEVERITY.error,
@@ -29,17 +29,14 @@ function addSafeEventListener(object, event, callback, capture = false) {
29
29
  }
30
30
  };
31
31
 
32
- /**
33
- * tries to add an event listener to a Proxy object
34
- */
32
+ /** tries to add an event listener to a Proxy object */
35
33
  const tryAddEventListenerForProxy = () => {
36
34
  if (!Reflect) {
37
35
  return false;
38
36
  }
39
37
 
40
38
  try {
41
- const addEventListener =
42
- Reflect.get(object, 'addEventListener') || (() => {});
39
+ const addEventListener = Reflect.get(object, 'addEventListener') || (() => {});
43
40
  addEventListener(event, safeCallback, capture);
44
41
  } catch (e) {
45
42
  return false;
@@ -56,11 +53,7 @@ function addSafeEventListener(object, event, callback, capture = false) {
56
53
  return;
57
54
  }
58
55
  }
59
- ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
60
- `addEventListener error: ${e.message}`,
61
- false,
62
- SEVERITY.error,
63
- );
56
+ ClientConfig.getInstance().postInternalError(`addEventListener error: ${e.message}`, false, SEVERITY.error);
64
57
  }
65
58
  }
66
59