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