noibu-react-native 0.2.7 → 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/android/build.gradle +1 -1
- package/dist/api/ClientConfig.d.ts +99 -0
- package/dist/api/ClientConfig.js +25 -23
- package/dist/api/ClientConfig.test.d.ts +1 -0
- package/dist/api/HelpCode.d.ts +16 -0
- package/dist/api/HelpCode.js +3 -2
- package/dist/api/InputManager.d.ts +39 -0
- package/dist/api/MetroplexSocket.d.ts +132 -0
- package/dist/api/MetroplexSocket.js +4 -3
- package/dist/api/MetroplexSocket.test.d.ts +1 -0
- package/dist/api/StoredMetrics.d.ts +63 -0
- package/dist/api/StoredPageVisit.d.ts +43 -0
- package/dist/api/StoredPageVisit.js +4 -3
- package/dist/const_matchers.d.ts +1 -0
- package/dist/constants.d.ts +48 -0
- package/dist/constants.js +2 -9
- package/dist/entry/index.d.ts +13 -0
- package/dist/entry/init.d.ts +8 -0
- package/dist/entry/init.js +4 -3
- package/dist/monitors/AppNavigationMonitor.d.ts +10 -0
- package/dist/monitors/AppNavigationMonitor.js +2 -2
- package/dist/monitors/AppNavigationMonitor.test.d.ts +1 -0
- package/dist/monitors/BaseMonitor.d.ts +13 -0
- package/dist/monitors/BaseMonitor.test.d.ts +1 -0
- package/dist/monitors/ClickMonitor.d.ts +28 -0
- package/dist/monitors/ClickMonitor.test.d.ts +1 -0
- package/dist/monitors/ErrorMonitor.d.ts +39 -0
- package/dist/monitors/KeyboardInputMonitor.d.ts +18 -0
- package/dist/monitors/PageMonitor.d.ts +20 -0
- package/dist/monitors/RequestMonitor.d.ts +74 -0
- package/dist/monitors/RequestMonitor.js +8 -8
- package/dist/monitors/http-tools/GqlErrorValidator.d.ts +35 -0
- package/dist/monitors/http-tools/GqlErrorValidator.js +5 -3
- package/dist/monitors/http-tools/HTTPDataBundler.d.ts +106 -0
- package/dist/monitors/http-tools/HTTPDataBundler.js +7 -5
- package/dist/monitors/integrations/ReactNativeNavigationIntegration.d.ts +17 -0
- package/dist/pageVisit/EventDebouncer.d.ts +23 -0
- package/dist/pageVisit/HttpEventManager.d.ts +14 -0
- package/dist/pageVisit/PageVisitManager.d.ts +31 -0
- package/dist/pageVisit/pageVisitEventError.d.ts +12 -0
- package/dist/pageVisit/pageVisitEventError.js +2 -2
- package/dist/react/ErrorBoundary.d.ts +67 -0
- package/dist/sessionRecorder/SessionRecorder.d.ts +50 -0
- package/dist/sessionRecorder/SessionRecorder.js +7 -6
- package/dist/sessionRecorder/nativeSessionRecorderSubscription.d.ts +77 -0
- package/dist/sessionRecorder/types.d.ts +91 -0
- package/dist/storage/RNStorageProvider.d.ts +19 -0
- package/dist/storage/Storage.d.ts +29 -0
- package/dist/storage/StorageProvider.d.ts +23 -0
- package/dist/types/NavigationIntegration.d.ts +6 -0
- package/dist/utils/date.d.ts +7 -0
- package/dist/utils/date.js +3 -2
- package/dist/utils/eventlistener.d.ts +8 -0
- package/dist/utils/eventlistener.js +2 -3
- package/dist/utils/function.d.ts +72 -0
- package/dist/utils/log.d.ts +4 -0
- package/dist/utils/log.js +1 -3
- package/dist/utils/object.d.ts +46 -0
- package/dist/utils/performance.d.ts +6 -0
- package/dist/utils/piiRedactor.d.ts +11 -0
- package/dist/utils/polyfills.d.ts +4 -0
- package/dist/utils/stacktrace-parser.d.ts +8 -0
- package/dist/utils/stacktrace-parser.test.d.ts +1 -0
- package/package.json +2 -2
package/android/build.gradle
CHANGED
|
@@ -67,7 +67,7 @@ def kotlin_version = getExtOrDefault("kotlinVersion")
|
|
|
67
67
|
dependencies {
|
|
68
68
|
implementation "com.facebook.react:react-native:+"
|
|
69
69
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
|
|
70
|
-
implementation "com.noibu:sessionreplay-recorder:0.2.
|
|
70
|
+
implementation "com.noibu:sessionreplay-recorder:0.2.1"
|
|
71
71
|
}
|
|
72
72
|
|
|
73
73
|
if (isNewArchitectureEnabled()) {
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
import { ErrorMessage, Severity } from '@noibu/metroplex-ts-bindings';
|
|
2
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
3
|
+
/**
|
|
4
|
+
* Singleton class to manage the client configuration
|
|
5
|
+
* this class will be responsible for controlling the disabled
|
|
6
|
+
* status of the client script as well as managing all storage
|
|
7
|
+
* storing and retrieval.
|
|
8
|
+
*/
|
|
9
|
+
export default class ClientConfig extends Singleton {
|
|
10
|
+
readonly pageVisitId: string;
|
|
11
|
+
browserId: StoredConfig['BrowserId'];
|
|
12
|
+
private pageVisitSeq;
|
|
13
|
+
private lastActiveTime;
|
|
14
|
+
private readonly noibuErrorURL;
|
|
15
|
+
private cltErrorPostCounter;
|
|
16
|
+
private readonly maxSocketInactiveTime;
|
|
17
|
+
private locationBreadcrumbs;
|
|
18
|
+
private readonly customerDomain;
|
|
19
|
+
isClientDisabled: boolean;
|
|
20
|
+
configurationPromise: Promise<void>;
|
|
21
|
+
readonly listOfUrlsToCollectHttpDataFrom: CustomerConfig['listOfUrlsToCollectHttpDataFrom'];
|
|
22
|
+
readonly enableHttpDataCollection: CustomerConfig['enableHttpDataCollection'];
|
|
23
|
+
readonly blockedElements: CustomerConfig['blockedElements'];
|
|
24
|
+
private alreadyPostingError;
|
|
25
|
+
/** Error handling for constructor */
|
|
26
|
+
handleConstructorError(noibuErrorURL?: string, customerConfig?: CustomerConfig): void;
|
|
27
|
+
/** Creates a ClientConfig singleton instance */
|
|
28
|
+
constructor(noibuErrorURL?: string, customerConfig?: CustomerConfig);
|
|
29
|
+
/** Convenience method to check correct setup */
|
|
30
|
+
private hasAllNecessaryArgs;
|
|
31
|
+
/** lockClient will disable the client script for a single pagevisit for
|
|
32
|
+
* duration given in minuntes */
|
|
33
|
+
lockClient(duration: number, msg: ErrorMessage): Promise<void>;
|
|
34
|
+
/** Locks the client until the next page loads */
|
|
35
|
+
lockClientUntilNextPage(msg: ErrorMessage): Promise<void>;
|
|
36
|
+
/** Updates the config object to store the given last active time */
|
|
37
|
+
updateLastActiveTime(lastActiveTime: Date): Promise<void>;
|
|
38
|
+
/** Gets the current page visit sequence number that should be used */
|
|
39
|
+
getPageVisitSeq(): Promise<number | null>;
|
|
40
|
+
/**
|
|
41
|
+
* Returns the client config object from storage or generates a new one
|
|
42
|
+
* What is stored in storage will look like this
|
|
43
|
+
* {
|
|
44
|
+
* BrowserId: UUIDV4
|
|
45
|
+
* ExpiryTime: DATE OBJ
|
|
46
|
+
* DisabledStatus: BOOL
|
|
47
|
+
* CurrentPageVisitCount: INT
|
|
48
|
+
* ClientUnlockTime: DATE OBJ
|
|
49
|
+
* LastActiveTime: DATE OBJ
|
|
50
|
+
* }
|
|
51
|
+
*/
|
|
52
|
+
_getLsObject(): Promise<StoredConfig>;
|
|
53
|
+
/** Check if we have surpassed the last active time and the page visit seq number needs resetting */
|
|
54
|
+
_pageVisitSeqNeedsReset(): Promise<boolean>;
|
|
55
|
+
/**
|
|
56
|
+
* _setupStorageVars will set all class variables that depend
|
|
57
|
+
* on the storage's value.
|
|
58
|
+
*/
|
|
59
|
+
_setupStorageVars(): Promise<void>;
|
|
60
|
+
/**
|
|
61
|
+
* Function will get the Noibu Storage Object
|
|
62
|
+
* 1. Generate a brand new one
|
|
63
|
+
* Get it from storage if the expiry date is not in the past
|
|
64
|
+
* Generate a brand new one if the expiry date is in the past
|
|
65
|
+
*/
|
|
66
|
+
_getClientState(): Promise<StoredConfig>;
|
|
67
|
+
/**
|
|
68
|
+
* _generateAndStoreData generates brand new data and then proceeds to store
|
|
69
|
+
* it.
|
|
70
|
+
*/
|
|
71
|
+
_generateAndStoreData(): Promise<StoredConfig>;
|
|
72
|
+
/**
|
|
73
|
+
* _generateNewBrowserData will create new data to be stored in storage
|
|
74
|
+
* and persisted throughout a session
|
|
75
|
+
*/
|
|
76
|
+
_generateNewBrowserData(): StoredConfig;
|
|
77
|
+
/**
|
|
78
|
+
* _storeBrowserData will store the passed object in storage.
|
|
79
|
+
* @param {} data the data to be stored
|
|
80
|
+
*/
|
|
81
|
+
_storeBrowserData(data: StoredConfig): Promise<StoredConfig>;
|
|
82
|
+
/** sets current breadcrumbs to be reconstructed into global url */
|
|
83
|
+
set currentLocationBreadcrumbs(newValue: typeof this.locationBreadcrumbs);
|
|
84
|
+
/** gets current global url */
|
|
85
|
+
get globalUrl(): string;
|
|
86
|
+
/**
|
|
87
|
+
* postInternalError will post errors that were thrown by collect
|
|
88
|
+
* and disable the client if required
|
|
89
|
+
* severity expects one of the SEVERITY_x level constants, or else error will be used
|
|
90
|
+
*/
|
|
91
|
+
postInternalError(errorMsg: ErrorMessage, disableClient?: boolean, severity?: Severity, keepAlive?: boolean): Promise<void>;
|
|
92
|
+
/** Returns true if the page visit is considered to be inactive */
|
|
93
|
+
isInactive(): boolean;
|
|
94
|
+
/**
|
|
95
|
+
* Wraps a function in a try catch block and posts the error if one is thrown
|
|
96
|
+
* explanation will be inserted into the error message as 'Error in {explanation}'
|
|
97
|
+
*/
|
|
98
|
+
wrapInternal(explanation: string, fun: () => void): void;
|
|
99
|
+
}
|
package/dist/api/ClientConfig.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import uuid from 'react-native-uuid';
|
|
3
|
-
import
|
|
3
|
+
import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
4
|
+
import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, GET_SCRIPT_ID, GET_DEVICE_ENV } from '../constants.js';
|
|
4
5
|
import { stringifyJSON, getMaxSubstringAllowed, getUserAgent, postRequest } from '../utils/function.js';
|
|
5
6
|
import Storage from '../storage/Storage.js';
|
|
6
|
-
import { noibuLog
|
|
7
|
+
import { noibuLog } from '../utils/log.js';
|
|
7
8
|
import { unwrapNoibuWrapped } from '../utils/object.js';
|
|
8
9
|
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
10
|
+
import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
|
|
9
11
|
|
|
10
12
|
// maximum number of page visits assigned to a single browser id
|
|
11
13
|
const MAX_PAGEVISIT_VISITED = 300;
|
|
@@ -32,7 +34,7 @@ class ClientConfig extends Singleton {
|
|
|
32
34
|
customerConfig,
|
|
33
35
|
globalUrl: this.globalUrl,
|
|
34
36
|
};
|
|
35
|
-
void this.postInternalError(reason, true,
|
|
37
|
+
void this.postInternalError(reason, true, Severity.ERROR);
|
|
36
38
|
this.configurationPromise = Promise.reject(reason);
|
|
37
39
|
}
|
|
38
40
|
/** Creates a ClientConfig singleton instance */
|
|
@@ -52,6 +54,7 @@ class ClientConfig extends Singleton {
|
|
|
52
54
|
this.maxSocketInactiveTime = MAX_METROPLEX_SOCKET_INNACTIVE_TIME;
|
|
53
55
|
this.locationBreadcrumbs = [];
|
|
54
56
|
this.isClientDisabled = false;
|
|
57
|
+
this.alreadyPostingError = false;
|
|
55
58
|
if (!noibuErrorURL || !customerConfig) {
|
|
56
59
|
this.handleConstructorError(noibuErrorURL, customerConfig);
|
|
57
60
|
return;
|
|
@@ -82,12 +85,12 @@ class ClientConfig extends Singleton {
|
|
|
82
85
|
noibuLSObject.DisabledStatus = true;
|
|
83
86
|
noibuLSObject.ClientUnlockTime = expiryTime;
|
|
84
87
|
yield this._storeBrowserData(noibuLSObject);
|
|
85
|
-
yield this.postInternalError(msg, true,
|
|
88
|
+
yield this.postInternalError(msg, true, Severity.WARN);
|
|
86
89
|
});
|
|
87
90
|
}
|
|
88
91
|
/** Locks the client until the next page loads */
|
|
89
92
|
lockClientUntilNextPage(msg) {
|
|
90
|
-
return this.postInternalError(msg, true,
|
|
93
|
+
return this.postInternalError(msg, true, Severity.WARN);
|
|
91
94
|
}
|
|
92
95
|
/** Updates the config object to store the given last active time */
|
|
93
96
|
updateLastActiveTime(lastActiveTime) {
|
|
@@ -171,7 +174,7 @@ class ClientConfig extends Singleton {
|
|
|
171
174
|
return __awaiter(this, void 0, void 0, function* () {
|
|
172
175
|
const storage = Storage.getInstance();
|
|
173
176
|
if (!(yield storage.isAvailable())) {
|
|
174
|
-
void this.postInternalError({ msg: `Storage is unavailable, disabling client.`, diagnosis: yield storage.getDiagnoseInfo() }, true,
|
|
177
|
+
void this.postInternalError({ msg: `Storage is unavailable, disabling client.`, diagnosis: yield storage.getDiagnoseInfo() }, true, Severity.ERROR);
|
|
175
178
|
return;
|
|
176
179
|
}
|
|
177
180
|
// getting the current content of the storage
|
|
@@ -201,7 +204,7 @@ class ClientConfig extends Singleton {
|
|
|
201
204
|
// setting the lock time
|
|
202
205
|
noibuLSObject.ClientUnlockTime = expiryTime;
|
|
203
206
|
noibuLSObject.DisabledStatus = true;
|
|
204
|
-
yield this.postInternalError({ msg: `Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins` }, true,
|
|
207
|
+
yield this.postInternalError({ msg: `Hit max page visits, disabling client for ${CLIENT_LOCK_TIME_MINUTES}mins` }, true, Severity.ERROR);
|
|
205
208
|
}
|
|
206
209
|
// we now check if we successfully saved the data
|
|
207
210
|
const savedData = yield this._storeBrowserData(noibuLSObject);
|
|
@@ -209,7 +212,7 @@ class ClientConfig extends Singleton {
|
|
|
209
212
|
// error happened, thus we disable collect.
|
|
210
213
|
if (!savedData.BrowserId) {
|
|
211
214
|
// we do not set a lock expiry date here since we cannot store to storage
|
|
212
|
-
void this.postInternalError({ msg: `Null browser in storage, disabling client` }, true,
|
|
215
|
+
void this.postInternalError({ msg: `Null browser in storage, disabling client` }, true, Severity.ERROR);
|
|
213
216
|
this.browserId = '';
|
|
214
217
|
}
|
|
215
218
|
});
|
|
@@ -269,7 +272,7 @@ class ClientConfig extends Singleton {
|
|
|
269
272
|
yield this.postInternalError({
|
|
270
273
|
msg: 'Error writing browser data to storage, disabling client: ' + e.message,
|
|
271
274
|
diagnosis: yield storage.getDiagnoseInfo(),
|
|
272
|
-
}, true,
|
|
275
|
+
}, true, Severity.ERROR);
|
|
273
276
|
// sending empty fields if we encountered errors while storing in the LS
|
|
274
277
|
return this._generateNewBrowserData();
|
|
275
278
|
}
|
|
@@ -297,23 +300,21 @@ class ClientConfig extends Singleton {
|
|
|
297
300
|
* severity expects one of the SEVERITY_x level constants, or else error will be used
|
|
298
301
|
*/
|
|
299
302
|
postInternalError(errorMsg_1) {
|
|
300
|
-
return __awaiter(this, arguments, void 0, function* (errorMsg, disableClient = false, severity =
|
|
301
|
-
|
|
302
|
-
errorMsg,
|
|
303
|
-
disableClient,
|
|
304
|
-
severity,
|
|
305
|
-
keepAlive,
|
|
306
|
-
});
|
|
307
|
-
if (this.isClientDisabled) {
|
|
303
|
+
return __awaiter(this, arguments, void 0, function* (errorMsg, disableClient = false, severity = Severity.ERROR, keepAlive = false) {
|
|
304
|
+
if (this.alreadyPostingError || this.isClientDisabled || severity === Severity.WARN) {
|
|
308
305
|
return;
|
|
309
306
|
}
|
|
310
307
|
if (disableClient) {
|
|
311
308
|
this.isClientDisabled = true;
|
|
312
309
|
}
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
310
|
+
this.alreadyPostingError = true;
|
|
311
|
+
/** Don't use noibuErr here since we end up in recursion due to RN log intercept in debug mode */
|
|
312
|
+
noibuLog('postInternalError', {
|
|
313
|
+
errorMsg,
|
|
314
|
+
disableClient,
|
|
315
|
+
severity,
|
|
316
|
+
keepAlive,
|
|
317
|
+
});
|
|
317
318
|
const collectError = {
|
|
318
319
|
browserId: this.browserId || '',
|
|
319
320
|
pageVisitId: this.pageVisitId,
|
|
@@ -361,9 +362,10 @@ class ClientConfig extends Singleton {
|
|
|
361
362
|
});
|
|
362
363
|
}
|
|
363
364
|
// only increment if this was an actual error, not a warning or otherwise
|
|
364
|
-
if (severity ===
|
|
365
|
+
if (severity === Severity.ERROR) {
|
|
365
366
|
this.cltErrorPostCounter += 1;
|
|
366
367
|
}
|
|
368
|
+
this.alreadyPostingError = false;
|
|
367
369
|
});
|
|
368
370
|
}
|
|
369
371
|
/** Returns true if the page visit is considered to be inactive */
|
|
@@ -381,7 +383,7 @@ class ClientConfig extends Singleton {
|
|
|
381
383
|
fun();
|
|
382
384
|
}
|
|
383
385
|
catch (error) {
|
|
384
|
-
this.postInternalError({ msg: `Error in ${explanation}`, error }, false,
|
|
386
|
+
this.postInternalError({ msg: `Error in ${explanation}`, error }, false, Severity.ERROR);
|
|
385
387
|
}
|
|
386
388
|
}
|
|
387
389
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
2
|
+
/**
|
|
3
|
+
* HelpCode class is responsible for help code feature related functionality
|
|
4
|
+
*/
|
|
5
|
+
export default class HelpCode extends Singleton {
|
|
6
|
+
private requestContext;
|
|
7
|
+
/** Constructs instance and sets up event listeners */
|
|
8
|
+
constructor();
|
|
9
|
+
/**
|
|
10
|
+
* Requests a help code and returns a Promise that resolves when the help code is obtained
|
|
11
|
+
* or rejects if the noibu connection is unavailable.
|
|
12
|
+
*/
|
|
13
|
+
requestHelpCode(): Promise<string | null>;
|
|
14
|
+
/** Handles the received help code event. */
|
|
15
|
+
receiveHelpCode(event: CustomEvent<string>): void;
|
|
16
|
+
}
|
package/dist/api/HelpCode.js
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
2
|
import MetroplexSocket from './MetroplexSocket.js';
|
|
3
|
-
import { SEVERITY } from '../constants.js';
|
|
4
3
|
import ClientConfig from './ClientConfig.js';
|
|
5
4
|
import { Singleton } from '../monitors/BaseMonitor.js';
|
|
5
|
+
import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
6
|
+
import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
|
|
6
7
|
|
|
7
8
|
/**
|
|
8
9
|
* HelpCode class is responsible for help code feature related functionality
|
|
@@ -48,7 +49,7 @@ class HelpCode extends Singleton {
|
|
|
48
49
|
const { success, data } = event.detail;
|
|
49
50
|
if (!success) {
|
|
50
51
|
const msg = `Noibu help code is not available due to ${data}`;
|
|
51
|
-
ClientConfig.getInstance().postInternalError({ msg }, false,
|
|
52
|
+
ClientConfig.getInstance().postInternalError({ msg }, false, Severity.ERROR);
|
|
52
53
|
}
|
|
53
54
|
return;
|
|
54
55
|
}
|
|
@@ -0,0 +1,39 @@
|
|
|
1
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
2
|
+
declare const NOIBUJS_SDK_REQUEST_HELP_CODE = "requestHelpCode";
|
|
3
|
+
declare const NOIBUJS_SDK_ADD_ID_FUNCTION = "addCustomAttribute";
|
|
4
|
+
declare const NOIBUJS_SDK_ADD_ERROR_FUNCTION = "addError";
|
|
5
|
+
declare const NOIBUJS_SDK_ADD_ERROR_FROM_JS_FMW_FUNCTION = "addJsSdkError";
|
|
6
|
+
/** this class controls the input that customers can inject into
|
|
7
|
+
* our script via the NoibuJS SDK
|
|
8
|
+
*/
|
|
9
|
+
export default class InputManager extends Singleton {
|
|
10
|
+
private readonly customIDs;
|
|
11
|
+
private customErrorsCount;
|
|
12
|
+
/** exposes functions to the window of the browser for the clients
|
|
13
|
+
* to interact with on their end
|
|
14
|
+
*/
|
|
15
|
+
exposeFunctions(): {
|
|
16
|
+
[NOIBUJS_SDK_REQUEST_HELP_CODE]: () => Promise<string | null>;
|
|
17
|
+
[NOIBUJS_SDK_ADD_ID_FUNCTION]: (name: string, value: string) => Promise<string>;
|
|
18
|
+
[NOIBUJS_SDK_ADD_ERROR_FUNCTION]: (customError: unknown) => string;
|
|
19
|
+
[NOIBUJS_SDK_ADD_ERROR_FROM_JS_FMW_FUNCTION]: (customError: unknown, errorSource: unknown) => string;
|
|
20
|
+
};
|
|
21
|
+
/** validates the custom error that was passed */
|
|
22
|
+
getErrorValidationError(customError: any): "SUCCESS" | "ERROR_HAS_NO_MSG" | "ERROR_HAS_NO_STACK" | "NULL_CUSTOM_ERROR";
|
|
23
|
+
/** Validates and sets the custom error to our internal trackers */
|
|
24
|
+
_validateAndSetCustomError(customError: unknown): "SUCCESS" | "ERROR_HAS_NO_MSG" | "ERROR_HAS_NO_STACK" | "NULL_CUSTOM_ERROR" | "TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT";
|
|
25
|
+
/** adds an error from a JS Sdk to the session */
|
|
26
|
+
_addErrorFromJSSdk(customError: unknown, errorSource: unknown): "SUCCESS" | "ERROR_HAS_NO_MSG" | "ERROR_HAS_NO_STACK" | "NULL_CUSTOM_ERROR" | "TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT";
|
|
27
|
+
/** adds a custom Error to the session */
|
|
28
|
+
_addCustomError(customError: unknown): "SUCCESS" | "ERROR_HAS_NO_MSG" | "ERROR_HAS_NO_STACK" | "NULL_CUSTOM_ERROR" | "TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT";
|
|
29
|
+
/**
|
|
30
|
+
* adds a custom id to the session
|
|
31
|
+
* todo wrong param types, should be unknown
|
|
32
|
+
*/
|
|
33
|
+
_addCustomAttribute(name: string, value: string): Promise<"TOO_MANY_IDS_ADDED" | "ID_NAME_ALREADY_ADDED" | "NAME_TOO_LONG" | "VALUE_TOO_LONG" | "INVALID_NAME_TYPE" | "INVALID_VALUE_TYPE" | "NAME_HAS_NO_LENGTH" | "VALUE_HAS_NO_LENGTH" | "SUCCESS">;
|
|
34
|
+
/** validation function for customer input */
|
|
35
|
+
getValidationError(name: unknown, value: unknown): "NAME_TOO_LONG" | "VALUE_TOO_LONG" | "INVALID_NAME_TYPE" | "INVALID_VALUE_TYPE" | "NAME_HAS_NO_LENGTH" | "VALUE_HAS_NO_LENGTH" | "SUCCESS";
|
|
36
|
+
/** Requests a help code from the HelpCode instance. */
|
|
37
|
+
_requestHelpCode(): Promise<string | null>;
|
|
38
|
+
}
|
|
39
|
+
export {};
|
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
import { MetroplexInputRouteMap, MetroplexRoute, PageInformation, PageVisitEvent, VideoRecorder, WebsocketMessageType } from '@noibu/metroplex-ts-bindings';
|
|
2
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
3
|
+
import { NoSeqNumSlidingMessage, RetryQueueWSMessage } from '../types/Metroplex';
|
|
4
|
+
/**
|
|
5
|
+
* Grab the video recorder type based on the device we run the app on.
|
|
6
|
+
*/
|
|
7
|
+
export declare function getVideoRecorderType(): Promise<VideoRecorder>;
|
|
8
|
+
/**
|
|
9
|
+
* Implements rolling window of specified size,
|
|
10
|
+
* but only makes a cut once array length exceeds 150%.
|
|
11
|
+
* During downsize deletes oldest (lowest indexes) elements.
|
|
12
|
+
*/
|
|
13
|
+
export declare function createSlidingArrayOfSize<T>(size: number, arraySource?: T[], downsizeThreshold?: number, downsizeFactor?: number): T[];
|
|
14
|
+
/** Manages the socket to Metroplex */
|
|
15
|
+
export default class MetroplexSocket extends Singleton {
|
|
16
|
+
forceClosed: boolean;
|
|
17
|
+
socket: WebSocket | null;
|
|
18
|
+
socketInstanceId: string | null;
|
|
19
|
+
previousMessageType: string;
|
|
20
|
+
currentConnectionAttempts: number;
|
|
21
|
+
connectionCount: number;
|
|
22
|
+
sessionStartTime: number;
|
|
23
|
+
connectionPromise: Promise<void>;
|
|
24
|
+
pageVisitInfoSent: boolean;
|
|
25
|
+
connectionURL: string;
|
|
26
|
+
postURL: string;
|
|
27
|
+
messageSequenceNum: number;
|
|
28
|
+
latestReceivedSeqNumber: number;
|
|
29
|
+
isRetryLoopDisabled: boolean;
|
|
30
|
+
/** messages that need to be resent to metroplex since they are lacking confirmation */
|
|
31
|
+
retryMessageQueue: RetryQueueWSMessage[];
|
|
32
|
+
metroplexTypeLock: Record<WebsocketMessageType, boolean>;
|
|
33
|
+
initialURL: string;
|
|
34
|
+
initialReferringURL: string;
|
|
35
|
+
sessionTimestamp: Date;
|
|
36
|
+
latestReceivedSeqNumStoredTime: Date;
|
|
37
|
+
instanceId: string;
|
|
38
|
+
scriptInstanceId?: string;
|
|
39
|
+
sessionLength: number;
|
|
40
|
+
socketCloseCodes: string[];
|
|
41
|
+
socketOpens: string[];
|
|
42
|
+
ackedOnce: boolean;
|
|
43
|
+
metroRetryFrequencyMS: number;
|
|
44
|
+
retryMetroplexInterval: ReturnType<typeof setTimeout> | null;
|
|
45
|
+
private helpCodeCb;
|
|
46
|
+
/**
|
|
47
|
+
* Creates an instance of metroplex
|
|
48
|
+
* id of script, to make sure only a single socket is open
|
|
49
|
+
*/
|
|
50
|
+
constructor(scriptInstanceId?: string);
|
|
51
|
+
/**
|
|
52
|
+
* connectSocket will establish a websocket connection to the metroplex
|
|
53
|
+
* service
|
|
54
|
+
*/
|
|
55
|
+
connectSocket(): Promise<void>;
|
|
56
|
+
/** sets up events that will trigger the event queue to be emptied */
|
|
57
|
+
_setupOffloadEvents(): void;
|
|
58
|
+
/**
|
|
59
|
+
* Adds the seq num field to the given payload depending on whether its
|
|
60
|
+
* a page visit part or video frag
|
|
61
|
+
*/
|
|
62
|
+
_addSeqNumToPayload<T extends RetryQueueWSMessage>(message: NoSeqNumSlidingMessage<T>): Promise<T>;
|
|
63
|
+
/** requests help code and saves a callback to be called on response */
|
|
64
|
+
requestHelpCode(cb: typeof this.helpCodeCb): Promise<boolean>;
|
|
65
|
+
/**
|
|
66
|
+
* Immediately sends a message to Metroplex over the web socket
|
|
67
|
+
* Queues the message if the connection isn't open yet.
|
|
68
|
+
* returns true if message was sent succefully, false otherwise
|
|
69
|
+
*/
|
|
70
|
+
sendMessage(message: NoSeqNumSlidingMessage<RetryQueueWSMessage<WebsocketMessageType>>): Promise<boolean>;
|
|
71
|
+
/** Updates the latest pv message sent timestamp if events contain any user steps
|
|
72
|
+
*/
|
|
73
|
+
_updateLatestPvTimestamp(events: PageVisitEvent[]): Promise<void>;
|
|
74
|
+
/** returns true if the socket is either connecting or connected to metroplex */
|
|
75
|
+
isConnected(): boolean;
|
|
76
|
+
/** returns true if we are connecting to the socket */
|
|
77
|
+
isConnecting(): boolean;
|
|
78
|
+
/** close will close the socket opened for video frag transmission */
|
|
79
|
+
close(): void;
|
|
80
|
+
/** Connects the web socket to metroplex and calls callback upon successfully connecting
|
|
81
|
+
*/
|
|
82
|
+
handleConnect(forceOpen: boolean): Promise<void>;
|
|
83
|
+
/** Calculates and sets the end_at field of the payload */
|
|
84
|
+
addEndTimeToPayload<T>(payload: T, isPageVisit: boolean): T & {
|
|
85
|
+
end_at: string;
|
|
86
|
+
};
|
|
87
|
+
/** open handler for socket */
|
|
88
|
+
_onSocketOpen(): Promise<void>;
|
|
89
|
+
/** message handler for socket */
|
|
90
|
+
_onSocketMessage(event: WebSocketMessageEvent): Promise<void>;
|
|
91
|
+
/**
|
|
92
|
+
* Returns true if the message's payload has the payload type given and has a sequence
|
|
93
|
+
* number higher than seqNum
|
|
94
|
+
*/
|
|
95
|
+
_messagePayloadHasLargerSeqNum(message: RetryQueueWSMessage, seqNum: number): boolean | 0;
|
|
96
|
+
/**
|
|
97
|
+
* removes messages from the retry queue that are smaller than the
|
|
98
|
+
* latest stored message in metroplex
|
|
99
|
+
*/
|
|
100
|
+
_clearRetryQueue(seqNum: number): void;
|
|
101
|
+
/** will resend everything that is in the retry queue */
|
|
102
|
+
_sendUnconfirmedMessages(socketWasAlreadyOpen: boolean): Promise<void>;
|
|
103
|
+
/** sets up the interval to empty the queue as we receive confirmation messages from metroplex */
|
|
104
|
+
setupRetryMechanism(): void;
|
|
105
|
+
/**
|
|
106
|
+
* will handle the final moments of a page being active. It
|
|
107
|
+
* will try to empty both the queues with beacons.
|
|
108
|
+
*/
|
|
109
|
+
_handleUnload(): Promise<void>;
|
|
110
|
+
/**
|
|
111
|
+
* will post full page visit to metroplex. It
|
|
112
|
+
* will try to empty both the queues with beacons.
|
|
113
|
+
*/
|
|
114
|
+
postFullPageVisit(maxMessageSize: number): Promise<void>;
|
|
115
|
+
/** will send a message to metroplex via a post request that will outlive the current page */
|
|
116
|
+
postMessage(msg: MetroplexInputRouteMap[MetroplexRoute.PageVisit]): Promise<void>;
|
|
117
|
+
/**
|
|
118
|
+
* Stringifies the payload into JSON, sends it to the back end if the session
|
|
119
|
+
* is active and returns true. If inactive the session and socket are closed
|
|
120
|
+
* and this method returns false.
|
|
121
|
+
*/
|
|
122
|
+
private sendSocketMessage;
|
|
123
|
+
/**
|
|
124
|
+
* Closes the socket connection if the session is inactive. Returns true if the
|
|
125
|
+
* session is inactive
|
|
126
|
+
*/
|
|
127
|
+
closeIfInactive(): Promise<boolean>;
|
|
128
|
+
/** will get page information, calling this will increase the connection count */
|
|
129
|
+
getPageInformation(): Promise<PageInformation>;
|
|
130
|
+
/** Try to parse help code response and fire custom event */
|
|
131
|
+
_tryProcessHelpCodeResponse(response: unknown): boolean;
|
|
132
|
+
}
|
|
@@ -4,7 +4,7 @@ import { Platform } from 'react-native';
|
|
|
4
4
|
import { MetroplexRoute } from '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
5
5
|
import { getUserAgent, stringifyJSON } from '../utils/function.js';
|
|
6
6
|
import { addSafeEventListener } from '../utils/eventlistener.js';
|
|
7
|
-
import { GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_POST_URL, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY,
|
|
7
|
+
import { GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_POST_URL, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, MAX_BEACON_PAYLOAD_SIZE, CURRENT_NOIBUJS_VERSION, GET_SCRIPT_ID } from '../constants.js';
|
|
8
8
|
import ClientConfig from './ClientConfig.js';
|
|
9
9
|
import StoredMetrics from './StoredMetrics.js';
|
|
10
10
|
import StoredPageVisit from './StoredPageVisit.js';
|
|
@@ -16,6 +16,7 @@ import { Singleton } from '../monitors/BaseMonitor.js';
|
|
|
16
16
|
import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
|
|
17
17
|
import { WorkRequestMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WorkRequestMessageType.js';
|
|
18
18
|
import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
|
|
19
|
+
import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
|
|
19
20
|
import { InboundMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/InboundMessageType.js';
|
|
20
21
|
|
|
21
22
|
/**
|
|
@@ -387,7 +388,7 @@ class MetroplexSocket extends Singleton {
|
|
|
387
388
|
if (event.data.includes('seq_num')) {
|
|
388
389
|
const seqNumSplit = event.data.split('seq_num:');
|
|
389
390
|
if (seqNumSplit.length < 2) {
|
|
390
|
-
ClientConfig.getInstance().postInternalError({ msg: `Invalid message received from metroplex while clearing retry queue`, data: event.data }, false,
|
|
391
|
+
ClientConfig.getInstance().postInternalError({ msg: `Invalid message received from metroplex while clearing retry queue`, data: event.data }, false, Severity.ERROR);
|
|
391
392
|
break;
|
|
392
393
|
}
|
|
393
394
|
// the second element in the string split is the sequence number
|
|
@@ -607,7 +608,7 @@ class MetroplexSocket extends Singleton {
|
|
|
607
608
|
// debug message gets through
|
|
608
609
|
const clientDisabled = ClientConfig.getInstance().isClientDisabled;
|
|
609
610
|
ClientConfig.getInstance().isClientDisabled = false;
|
|
610
|
-
ClientConfig.getInstance().postInternalError(message, clientDisabled,
|
|
611
|
+
ClientConfig.getInstance().postInternalError(message, clientDisabled, Severity.WARN);
|
|
611
612
|
}
|
|
612
613
|
});
|
|
613
614
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
|
@@ -0,0 +1,63 @@
|
|
|
1
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
2
|
+
/**
|
|
3
|
+
* This class holds the final page visit and video frag metrics. It flushes
|
|
4
|
+
* them to storage and then finally sends them to Metroplex via the post
|
|
5
|
+
* route when the next page is loaded
|
|
6
|
+
*/
|
|
7
|
+
export default class StoredMetrics extends Singleton {
|
|
8
|
+
expectedVideoLength: number;
|
|
9
|
+
expectedVfSeq: number;
|
|
10
|
+
httpSequenceNumber: number;
|
|
11
|
+
httpOverLimitCount: number;
|
|
12
|
+
httpDroppedPayloadByTypeCount: number;
|
|
13
|
+
httpDroppedPayloadByLengthCount: number;
|
|
14
|
+
httpPayloadCount: number;
|
|
15
|
+
expectedPvPart: number;
|
|
16
|
+
videoClicks: number;
|
|
17
|
+
pvClicks: number;
|
|
18
|
+
errCount: number;
|
|
19
|
+
httpCount: number;
|
|
20
|
+
didCutPv: boolean;
|
|
21
|
+
didCutVideo: boolean;
|
|
22
|
+
didStartVideo: boolean;
|
|
23
|
+
/** Creates a new StoredMetrics instance */
|
|
24
|
+
constructor();
|
|
25
|
+
/** Add video frag payload data to the stored metrics */
|
|
26
|
+
addVideoFragData(expectedVfSeq: number, expectedVideoLength: number): void;
|
|
27
|
+
/** Set the amount of page visit parts */
|
|
28
|
+
setPvPart(expectedPvPart: number): void;
|
|
29
|
+
/** Increase the amount of video clicks seen in the session */
|
|
30
|
+
addVideoClick(): void;
|
|
31
|
+
/** Increase the amount of page visit clicks */
|
|
32
|
+
addPvClick(): void;
|
|
33
|
+
/** Increments the error count by 1 */
|
|
34
|
+
addError(): void;
|
|
35
|
+
/** Increments the http count by 1 */
|
|
36
|
+
addHttpEvent(): void;
|
|
37
|
+
/** Increments the http data sequence count by 1 */
|
|
38
|
+
addHttpData(): void;
|
|
39
|
+
/** Increments the http data over limit count by 1 */
|
|
40
|
+
addHttpDataOverLimit(): void;
|
|
41
|
+
/** Increments the http data drop count by content type */
|
|
42
|
+
addHttpDataDropByType(): void;
|
|
43
|
+
/** Increments the http data drop count by content length */
|
|
44
|
+
addHttpDataDropByLength(): void;
|
|
45
|
+
/** Increments the http data payload collected count */
|
|
46
|
+
addHttpDataPayloadCount(): void;
|
|
47
|
+
/** Set that the video was cut/blocked due to size constraints */
|
|
48
|
+
setDidCutVideo(): void;
|
|
49
|
+
/** Set that the video was started */
|
|
50
|
+
setDidStartVideo(): void;
|
|
51
|
+
/** Set that the page visit was cut/blocked due to size constraints */
|
|
52
|
+
setDidCutPv(): void;
|
|
53
|
+
/**
|
|
54
|
+
* Sets up all the listeners that noibujs should listen to before storing
|
|
55
|
+
* our metrics to localstorage
|
|
56
|
+
*/
|
|
57
|
+
_setupListeners(): void;
|
|
58
|
+
/** posts the metrics to metroplex if client is active */
|
|
59
|
+
private postMetricsIfActive;
|
|
60
|
+
/** posts the metrics to metroplex using the beacon API
|
|
61
|
+
*/
|
|
62
|
+
postMetrics(): Promise<void>;
|
|
63
|
+
}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
import { Singleton } from '../monitors/BaseMonitor';
|
|
2
|
+
import { RetryQueueWSMessage } from '../types/Metroplex';
|
|
3
|
+
import { CompletePageVisitPart, PageInformation, PageVisitPart } from '@noibu/metroplex-ts-bindings';
|
|
4
|
+
/**
|
|
5
|
+
* This class holds the final page visit. It flushes it to storage and then
|
|
6
|
+
* finally sends it to Metroplex via the post route when the next page is loaded
|
|
7
|
+
*/
|
|
8
|
+
export default class StoredPageVisit extends Singleton {
|
|
9
|
+
/** Creates a new instance of StoredPageVisit */
|
|
10
|
+
constructor();
|
|
11
|
+
/**
|
|
12
|
+
* Check if the events contain a click or location change. If they do then write the retry
|
|
13
|
+
* queue (which contains the metroplex msg sent above) to storage
|
|
14
|
+
*/
|
|
15
|
+
checkAndStoreRetryQueue(retryMessageQueue: RetryQueueWSMessage[], pvInfo: PageInformation): void;
|
|
16
|
+
/** Writes the page visit frags in the retry queue to storage
|
|
17
|
+
*/
|
|
18
|
+
writePageVisitsFromRetryQueue(retryMessageQueue: RetryQueueWSMessage[], pvInfo: PageInformation): void;
|
|
19
|
+
/** Write the given page visit frags to storage
|
|
20
|
+
*/
|
|
21
|
+
_writePageVisitFrags(pageVisitFrags: PageVisitPart[], pvInfo: PageInformation): Promise<void>;
|
|
22
|
+
/**
|
|
23
|
+
* Handles any issues that may appear when trying to get the stored page visit data
|
|
24
|
+
*/
|
|
25
|
+
static handleGetPostDataError(data: string, error: Error): Promise<null>;
|
|
26
|
+
/**
|
|
27
|
+
* Read the stored page visit from storage, create a complete page visit object
|
|
28
|
+
* and then post that to Metroplex
|
|
29
|
+
*/
|
|
30
|
+
_getPostData(): Promise<CompletePageVisitPart | null>;
|
|
31
|
+
/**
|
|
32
|
+
* Creates and tries to resolve a promise that posts the previous page visit
|
|
33
|
+
* to Metroplex from storage
|
|
34
|
+
*/
|
|
35
|
+
_postPreviousPageVisit(): void;
|
|
36
|
+
/**
|
|
37
|
+
* Remove the storage item and set flushed to true after they have
|
|
38
|
+
* been posted to metroplex
|
|
39
|
+
*/
|
|
40
|
+
_updateStorageFlushed(): void;
|
|
41
|
+
/** Returns a promise that resolves to post the page visit in storage to Metroplex */
|
|
42
|
+
_getPostPageVisitPromise(): Promise<void>;
|
|
43
|
+
}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { __awaiter } from 'tslib';
|
|
2
|
-
import {
|
|
2
|
+
import { MAX_METROPLEX_SOCKET_INNACTIVE_TIME, GET_METROPLEX_POST_URL } from '../constants.js';
|
|
3
3
|
import ClientConfig from './ClientConfig.js';
|
|
4
4
|
import { stringifyJSON, postRequest } from '../utils/function.js';
|
|
5
5
|
import Storage from '../storage/Storage.js';
|
|
@@ -7,6 +7,7 @@ import { Singleton } from '../monitors/BaseMonitor.js';
|
|
|
7
7
|
import '../node_modules/@noibu/metroplex-ts-bindings/dist/index.js';
|
|
8
8
|
import { WebsocketMessageType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/WebsocketMessageType.js';
|
|
9
9
|
import { EventType } from '../node_modules/@noibu/metroplex-ts-bindings/dist/EventType.js';
|
|
10
|
+
import { Severity } from '../node_modules/@noibu/metroplex-ts-bindings/dist/Severity.js';
|
|
10
11
|
|
|
11
12
|
// The local storage key used to store the last page visit
|
|
12
13
|
const NOIBU_STORED_PAGE_VISIT = 'n_stored_page_visit';
|
|
@@ -83,7 +84,7 @@ class StoredPageVisit extends Singleton {
|
|
|
83
84
|
jsonSize: json.length,
|
|
84
85
|
storageSize: size,
|
|
85
86
|
diagnosis: yield storage.getDiagnoseInfo(),
|
|
86
|
-
}, false,
|
|
87
|
+
}, false, Severity.ERROR);
|
|
87
88
|
}
|
|
88
89
|
});
|
|
89
90
|
}
|
|
@@ -98,7 +99,7 @@ class StoredPageVisit extends Singleton {
|
|
|
98
99
|
msg: `Error parsing page visit string`,
|
|
99
100
|
data,
|
|
100
101
|
error,
|
|
101
|
-
}, false,
|
|
102
|
+
}, false, Severity.ERROR);
|
|
102
103
|
return null;
|
|
103
104
|
});
|
|
104
105
|
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export function WHITELIST_TEXT_REGEX_STRING(): string;
|