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.
Files changed (64) hide show
  1. package/android/build.gradle +1 -1
  2. package/dist/api/ClientConfig.d.ts +99 -0
  3. package/dist/api/ClientConfig.js +25 -23
  4. package/dist/api/ClientConfig.test.d.ts +1 -0
  5. package/dist/api/HelpCode.d.ts +16 -0
  6. package/dist/api/HelpCode.js +3 -2
  7. package/dist/api/InputManager.d.ts +39 -0
  8. package/dist/api/MetroplexSocket.d.ts +132 -0
  9. package/dist/api/MetroplexSocket.js +4 -3
  10. package/dist/api/MetroplexSocket.test.d.ts +1 -0
  11. package/dist/api/StoredMetrics.d.ts +63 -0
  12. package/dist/api/StoredPageVisit.d.ts +43 -0
  13. package/dist/api/StoredPageVisit.js +4 -3
  14. package/dist/const_matchers.d.ts +1 -0
  15. package/dist/constants.d.ts +48 -0
  16. package/dist/constants.js +2 -9
  17. package/dist/entry/index.d.ts +13 -0
  18. package/dist/entry/init.d.ts +8 -0
  19. package/dist/entry/init.js +4 -3
  20. package/dist/monitors/AppNavigationMonitor.d.ts +10 -0
  21. package/dist/monitors/AppNavigationMonitor.js +2 -2
  22. package/dist/monitors/AppNavigationMonitor.test.d.ts +1 -0
  23. package/dist/monitors/BaseMonitor.d.ts +13 -0
  24. package/dist/monitors/BaseMonitor.test.d.ts +1 -0
  25. package/dist/monitors/ClickMonitor.d.ts +28 -0
  26. package/dist/monitors/ClickMonitor.test.d.ts +1 -0
  27. package/dist/monitors/ErrorMonitor.d.ts +39 -0
  28. package/dist/monitors/KeyboardInputMonitor.d.ts +18 -0
  29. package/dist/monitors/PageMonitor.d.ts +20 -0
  30. package/dist/monitors/RequestMonitor.d.ts +74 -0
  31. package/dist/monitors/RequestMonitor.js +8 -8
  32. package/dist/monitors/http-tools/GqlErrorValidator.d.ts +35 -0
  33. package/dist/monitors/http-tools/GqlErrorValidator.js +5 -3
  34. package/dist/monitors/http-tools/HTTPDataBundler.d.ts +106 -0
  35. package/dist/monitors/http-tools/HTTPDataBundler.js +7 -5
  36. package/dist/monitors/integrations/ReactNativeNavigationIntegration.d.ts +17 -0
  37. package/dist/pageVisit/EventDebouncer.d.ts +23 -0
  38. package/dist/pageVisit/HttpEventManager.d.ts +14 -0
  39. package/dist/pageVisit/PageVisitManager.d.ts +31 -0
  40. package/dist/pageVisit/pageVisitEventError.d.ts +12 -0
  41. package/dist/pageVisit/pageVisitEventError.js +2 -2
  42. package/dist/react/ErrorBoundary.d.ts +67 -0
  43. package/dist/sessionRecorder/SessionRecorder.d.ts +50 -0
  44. package/dist/sessionRecorder/SessionRecorder.js +7 -6
  45. package/dist/sessionRecorder/nativeSessionRecorderSubscription.d.ts +77 -0
  46. package/dist/sessionRecorder/types.d.ts +91 -0
  47. package/dist/storage/RNStorageProvider.d.ts +19 -0
  48. package/dist/storage/Storage.d.ts +29 -0
  49. package/dist/storage/StorageProvider.d.ts +23 -0
  50. package/dist/types/NavigationIntegration.d.ts +6 -0
  51. package/dist/utils/date.d.ts +7 -0
  52. package/dist/utils/date.js +3 -2
  53. package/dist/utils/eventlistener.d.ts +8 -0
  54. package/dist/utils/eventlistener.js +2 -3
  55. package/dist/utils/function.d.ts +72 -0
  56. package/dist/utils/log.d.ts +4 -0
  57. package/dist/utils/log.js +1 -3
  58. package/dist/utils/object.d.ts +46 -0
  59. package/dist/utils/performance.d.ts +6 -0
  60. package/dist/utils/piiRedactor.d.ts +11 -0
  61. package/dist/utils/polyfills.d.ts +4 -0
  62. package/dist/utils/stacktrace-parser.d.ts +8 -0
  63. package/dist/utils/stacktrace-parser.test.d.ts +1 -0
  64. package/package.json +2 -2
@@ -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.0"
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
+ }
@@ -1,11 +1,13 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import uuid from 'react-native-uuid';
3
- import { SEVERITY, MAX_METROPLEX_SOCKET_INNACTIVE_TIME, GET_SCRIPT_ID, GET_DEVICE_ENV } from '../constants.js';
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, noibuErr } from '../utils/log.js';
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, SEVERITY.error);
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, SEVERITY.warn);
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, SEVERITY.warn);
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, SEVERITY.error);
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, SEVERITY.error);
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, SEVERITY.error);
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, SEVERITY.error);
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 = SEVERITY.error, keepAlive = false) {
301
- noibuErr('postInternalError', {
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
- if (severity === SEVERITY.warn) {
314
- // don't log warning messages by default, as a cost savings
315
- return;
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 === SEVERITY.error) {
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, SEVERITY.error);
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
+ }
@@ -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, SEVERITY.error);
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, SEVERITY, MAX_BEACON_PAYLOAD_SIZE, CURRENT_NOIBUJS_VERSION, GET_SCRIPT_ID } from '../constants.js';
7
+ import { GET_METROPLEX_BASE_SOCKET_URL, GET_METROPLEX_POST_URL, GET_MAX_METROPLEX_RECONNECTION_NUMBER, GET_METROPLEX_CONSECUTIVE_CONNECTION_DELAY, MAX_BEACON_PAYLOAD_SIZE, CURRENT_NOIBUJS_VERSION, GET_SCRIPT_ID } from '../constants.js';
8
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, SEVERITY.error);
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, SEVERITY.warn);
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 { SEVERITY, MAX_METROPLEX_SOCKET_INNACTIVE_TIME, GET_METROPLEX_POST_URL } from '../constants.js';
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, SEVERITY.error);
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, SEVERITY.error);
102
+ }, false, Severity.ERROR);
102
103
  return null;
103
104
  });
104
105
  }
@@ -0,0 +1 @@
1
+ export function WHITELIST_TEXT_REGEX_STRING(): string;