noibu-react-native 0.0.1

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 (40) hide show
  1. package/README.md +155 -0
  2. package/dist/api/clientConfig.js +416 -0
  3. package/dist/api/helpCode.js +106 -0
  4. package/dist/api/inputManager.js +233 -0
  5. package/dist/api/metroplexSocket.js +882 -0
  6. package/dist/api/storedMetrics.js +201 -0
  7. package/dist/api/storedPageVisit.js +235 -0
  8. package/dist/const_matchers.js +260 -0
  9. package/dist/constants.d.ts +264 -0
  10. package/dist/constants.js +528 -0
  11. package/dist/entry/index.d.ts +8 -0
  12. package/dist/entry/index.js +15 -0
  13. package/dist/entry/init.js +91 -0
  14. package/dist/monitors/clickMonitor.js +284 -0
  15. package/dist/monitors/elementMonitor.js +174 -0
  16. package/dist/monitors/errorMonitor.js +295 -0
  17. package/dist/monitors/gqlErrorValidator.js +306 -0
  18. package/dist/monitors/httpDataBundler.js +665 -0
  19. package/dist/monitors/inputMonitor.js +130 -0
  20. package/dist/monitors/keyboardInputMonitor.js +67 -0
  21. package/dist/monitors/locationChangeMonitor.js +30 -0
  22. package/dist/monitors/pageMonitor.js +119 -0
  23. package/dist/monitors/requestMonitor.js +679 -0
  24. package/dist/pageVisit/pageVisit.js +172 -0
  25. package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +313 -0
  26. package/dist/pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js +115 -0
  27. package/dist/pageVisit/userStep/userStep.js +20 -0
  28. package/dist/react/ErrorBoundary.d.ts +72 -0
  29. package/dist/react/ErrorBoundary.js +102 -0
  30. package/dist/storage/localStorageProvider.js +23 -0
  31. package/dist/storage/rnStorageProvider.js +62 -0
  32. package/dist/storage/sessionStorageProvider.js +23 -0
  33. package/dist/storage/storage.js +119 -0
  34. package/dist/storage/storageProvider.js +83 -0
  35. package/dist/utils/date.js +62 -0
  36. package/dist/utils/eventlistener.js +67 -0
  37. package/dist/utils/function.js +398 -0
  38. package/dist/utils/object.js +144 -0
  39. package/dist/utils/performance.js +21 -0
  40. package/package.json +57 -0
@@ -0,0 +1,102 @@
1
+ import * as React from 'react';
2
+ import uuid from 'react-native-uuid';
3
+ import InputManager from '../api/inputManager.js';
4
+
5
+ // initial state variables
6
+ const INITIAL_STATE = {
7
+ componentStack: null,
8
+ error: null,
9
+ eventId: null,
10
+ };
11
+ /**
12
+ * @description A ErrorBoundary component that logs errors to Noibu. Requires React >= 16.
13
+ * @extends {Component<ErrorBoundaryProps, ErrorBoundaryState>}
14
+ */
15
+ class ErrorBoundary extends React.Component {
16
+ state = INITIAL_STATE;
17
+ /**
18
+ * Lifecycle hook on mount
19
+ * @returns void
20
+ */
21
+ componentDidMount() {
22
+ const { onMount } = this.props;
23
+ if (onMount) {
24
+ onMount();
25
+ }
26
+ }
27
+ /**
28
+ *
29
+ * Handler for all errors that happen in a wrapped component
30
+ * @param {Error&{cause?:Error}} error
31
+ * @param {React.ErrorInfo} {componentStack}
32
+ * @returns void
33
+ */
34
+ componentDidCatch(error, { componentStack }) {
35
+ const { onError } = this.props;
36
+ InputManager.getInstance()._addErrorFromJSSdk(error, 'ReactError');
37
+ const eventId = uuid.v4();
38
+ if (onError) {
39
+ onError(error, componentStack, eventId);
40
+ }
41
+ // componentDidCatch is used over getDerivedStateFromError
42
+ // so that componentStack is accessible through state.
43
+ this.setState({ error, componentStack, eventId });
44
+ }
45
+ /**
46
+ * * Lifecycle hook on unmount
47
+ * @returns void
48
+ */
49
+ componentWillUnmount() {
50
+ const { error, componentStack, eventId } = this.state;
51
+ const { onUnmount } = this.props;
52
+ if (onUnmount) {
53
+ onUnmount(error, componentStack, eventId);
54
+ }
55
+ }
56
+ /**
57
+ * Callback from fallback to reset the error boundary
58
+ * @param {} =>void=(
59
+ */
60
+ resetErrorBoundary = () => {
61
+ const { onReset } = this.props;
62
+ const { error, componentStack, eventId } = this.state;
63
+ if (onReset) {
64
+ onReset(error, componentStack, eventId);
65
+ }
66
+ this.setState(INITIAL_STATE);
67
+ };
68
+ /**
69
+ *
70
+ * Renders the fallback ui
71
+ * @returns {React.ReactNode}
72
+ */
73
+ render() {
74
+ const { fallback, children } = this.props;
75
+ const { error, componentStack, eventId } = this.state;
76
+ if (error) {
77
+ let element;
78
+ if (typeof fallback === 'function') {
79
+ element = fallback({
80
+ error,
81
+ componentStack,
82
+ resetError: this.resetErrorBoundary,
83
+ eventId,
84
+ });
85
+ }
86
+ else {
87
+ element = fallback;
88
+ }
89
+ if (React.isValidElement(element)) {
90
+ return element;
91
+ }
92
+ // Fail gracefully if no fallback provided or is not valid
93
+ return null;
94
+ }
95
+ if (typeof children === 'function') {
96
+ return children();
97
+ }
98
+ return children;
99
+ }
100
+ }
101
+
102
+ export { ErrorBoundary };
@@ -0,0 +1,23 @@
1
+ import StorageProvider from './storageProvider.js';
2
+
3
+ /**
4
+ * Local storage provider implementation
5
+ */
6
+ class LocalStorageProvider extends StorageProvider {
7
+ /**
8
+ * Creates new instance
9
+ */
10
+ constructor() {
11
+ super(window.localStorage);
12
+ }
13
+
14
+ /**
15
+ * Checks if storage is available
16
+ * @returns {Object}
17
+ */
18
+ static isAvailable() {
19
+ return StorageProvider.isAvailable(() => window.localStorage);
20
+ }
21
+ }
22
+
23
+ export { LocalStorageProvider as default };
@@ -0,0 +1,62 @@
1
+ import StorageProvider from './storageProvider.js';
2
+
3
+ // eslint-disable-next-line max-classes-per-file
4
+
5
+ /**
6
+ * React native storage implementation: temporary
7
+ */
8
+ class RNStorageTmp {
9
+ /** */
10
+ constructor() {
11
+ this._map = new Map();
12
+ }
13
+
14
+ /**
15
+ * @param key
16
+ * @returns {string}
17
+ */
18
+ getItem(key) {
19
+ return this._map.get(key);
20
+ }
21
+
22
+ /**
23
+ * @param key
24
+ * @param value
25
+ * @returns {Map<string, string>}
26
+ */
27
+ setItem(key, value) {
28
+ return this._map.set(key, value);
29
+ }
30
+
31
+ /**
32
+ * @param key
33
+ * @returns {boolean}
34
+ */
35
+ removeItem(key) {
36
+ return this._map.delete(key);
37
+ }
38
+ }
39
+
40
+ /**
41
+ * React native storage provider implementation
42
+ */
43
+ class RNStorageProvider extends StorageProvider {
44
+ static storage = new RNStorageTmp();
45
+
46
+ /**
47
+ * Creates new instance
48
+ */
49
+ constructor() {
50
+ super(RNStorageProvider.storage);
51
+ }
52
+
53
+ /**
54
+ * Checks if storage is available
55
+ * @returns {Object}
56
+ */
57
+ static isAvailable() {
58
+ return StorageProvider.isAvailable(() => RNStorageProvider.storage);
59
+ }
60
+ }
61
+
62
+ export { RNStorageProvider as default };
@@ -0,0 +1,23 @@
1
+ import StorageProvider from './storageProvider.js';
2
+
3
+ /**
4
+ * Session storage provider implementation
5
+ */
6
+ class SessionStorageProvider extends StorageProvider {
7
+ /**
8
+ * Creates new instance
9
+ */
10
+ constructor() {
11
+ super(window.sessionStorage);
12
+ }
13
+
14
+ /**
15
+ * Checks if storage is available
16
+ * @returns {Object}
17
+ */
18
+ static isAvailable() {
19
+ return StorageProvider.isAvailable(() => window.sessionStorage);
20
+ }
21
+ }
22
+
23
+ export { SessionStorageProvider as default };
@@ -0,0 +1,119 @@
1
+ import LocalStorageProvider from './localStorageProvider.js';
2
+ import SessionStorageProvider from './sessionStorageProvider.js';
3
+ import RNStorageProvider from './rnStorageProvider.js';
4
+
5
+ /**
6
+ * Encapsulates storage api
7
+ */
8
+ class Storage {
9
+ /**
10
+ * Creates new instance assessing available options
11
+ */
12
+ constructor() {
13
+ const localStorageAvailability = LocalStorageProvider.isAvailable();
14
+ const sessionStorageAvailability = SessionStorageProvider.isAvailable();
15
+ const rnStorageAvailability = RNStorageProvider.isAvailable();
16
+ this._isLocalStorageAvailable = localStorageAvailability.result;
17
+ this._isSessionStorageAvailable = sessionStorageAvailability.result;
18
+ this._isRNStorageAvailable = rnStorageAvailability.result;
19
+ this._localStorageError = localStorageAvailability.error;
20
+ this._sessionStorageError = sessionStorageAvailability.error;
21
+ this._rnStorageError = rnStorageAvailability.error;
22
+ this._provider = null;
23
+ this._type = 'unavailable';
24
+
25
+ if (this._isLocalStorageAvailable) {
26
+ this._provider = new LocalStorageProvider();
27
+ this._type = 'LocalStorage';
28
+ } else if (this._isSessionStorageAvailable) {
29
+ this._provider = new SessionStorageProvider();
30
+ this._type = 'SessionStorage';
31
+ } else if (this._isRNStorageAvailable) {
32
+ console.log('_isRNStorageAvailable');
33
+ this._provider = new RNStorageProvider();
34
+ this._type = 'RNStorage';
35
+ }
36
+ }
37
+
38
+ /**
39
+ * Singleton
40
+ * @returns {Storage}
41
+ */
42
+ static getInstance() {
43
+ if (!this._instance) {
44
+ this._instance = new Storage();
45
+ }
46
+ return this._instance;
47
+ }
48
+
49
+ /**
50
+ * Checks if storage is available
51
+ * @returns {Boolean}
52
+ */
53
+ isAvailable() {
54
+ return this._provider != null;
55
+ }
56
+
57
+ /**
58
+ * Loads value from storage
59
+ * @param {String} key
60
+ * @returns {String}
61
+ */
62
+ load(key) {
63
+ if (this.isAvailable()) {
64
+ return this._provider.load(key);
65
+ }
66
+ return null;
67
+ }
68
+
69
+ /**
70
+ * Saves value to storage
71
+ * @param {String} key
72
+ * @param {String} value
73
+ */
74
+ save(key, value) {
75
+ if (this.isAvailable()) {
76
+ this._provider.save(key, value);
77
+ }
78
+ }
79
+
80
+ /**
81
+ * Removes value from storage
82
+ * @param {String} key
83
+ */
84
+ remove(key) {
85
+ if (this.isAvailable()) {
86
+ this._provider.remove(key);
87
+ }
88
+ }
89
+
90
+ /**
91
+ * Calculates used scape
92
+ * @returns {Number}
93
+ */
94
+ calculateUsedSize() {
95
+ if (this.isAvailable()) {
96
+ return this._provider.calculateUsedSize();
97
+ }
98
+ return 0;
99
+ }
100
+
101
+ /**
102
+ * Returns string indicating current provider type
103
+ * and availability for other storage types
104
+ * @returns {String}
105
+ */
106
+ getDiagnoseInfo() {
107
+ return (
108
+ `storage provider: ${this._type} ` +
109
+ `(localStorage available: ${this._isLocalStorageAvailable}, ` +
110
+ `error: ${this._localStorageError}) ` +
111
+ `(sessionStorage available: ${this._isSessionStorageAvailable}, ` +
112
+ `error: ${this._sessionStorageError})` +
113
+ `(rnStorage available: ${this._isRNStorageAvailable}, ` +
114
+ `error: ${this._rnStorageError})`
115
+ );
116
+ }
117
+ }
118
+
119
+ export { Storage as default };
@@ -0,0 +1,83 @@
1
+ import { NOIBU_LOCAL_STORAGE_TEST_KEY } from '../constants.js';
2
+
3
+ /**
4
+ * Base implementation for LocalStorage and SessionStorage
5
+ */
6
+ class StorageProvider {
7
+ /**
8
+ * Creates new instance based on provided provider type
9
+ * @param {WindowLocalStorage|WindowSessionStorage|RNStorageTmp} provider
10
+ */
11
+ constructor(provider) {
12
+ this._provider = provider;
13
+ }
14
+
15
+ /**
16
+ * Checks if provider is available
17
+ * @param {Function} function that returns storage instance
18
+ * @return {Object} { result: true|false, error: null|Error }
19
+ */
20
+ static isAvailable(resolver) {
21
+ let result = true;
22
+ let error = null;
23
+ try {
24
+ // access to localStorage/sessionStorage may throw an error
25
+ // so use function to resolve it wrapped with try/catch
26
+ const provider = resolver();
27
+ console.log({ provider, providerset: provider.setItem });
28
+ provider.setItem(NOIBU_LOCAL_STORAGE_TEST_KEY, 0);
29
+ provider.removeItem(NOIBU_LOCAL_STORAGE_TEST_KEY);
30
+ } catch (e) {
31
+ result = false;
32
+ error = e;
33
+ }
34
+ return { result, error };
35
+ }
36
+
37
+ /**
38
+ * Loads value from storage
39
+ * @param {String} key
40
+ * @returns {String}
41
+ */
42
+ load(key) {
43
+ return this._provider.getItem(key);
44
+ }
45
+
46
+ /**
47
+ * Saves value to storage
48
+ * @param {String} key
49
+ * @param {String} value
50
+ */
51
+ save(key, value) {
52
+ this._provider.setItem(key, value);
53
+ }
54
+
55
+ /**
56
+ * Removes value from storage
57
+ * @param {String} key
58
+ */
59
+ remove(key) {
60
+ this._provider.removeItem(key);
61
+ }
62
+
63
+ /**
64
+ * Calculates used scape
65
+ * @returns {Number}
66
+ */
67
+ calculateUsedSize() {
68
+ let size = 0;
69
+ for (let i = 0; i < this._provider.length; i++) {
70
+ const key = this._provider.key(i);
71
+ if (key) {
72
+ size += key.length;
73
+ const value = this._provider.getItem(key);
74
+ if (value) {
75
+ size += value.length;
76
+ }
77
+ }
78
+ }
79
+ return size;
80
+ }
81
+ }
82
+
83
+ export { StorageProvider as default };
@@ -0,0 +1,62 @@
1
+ import ClientConfig from '../api/clientConfig.js';
2
+ import { SEVERITY_ERROR } from '../constants.js';
3
+
4
+ /** @module Date */
5
+
6
+ /** Checks to see if the necessary Date functions that we use have been overwritten */
7
+ function isDateOverwritten() {
8
+ // Check to see if Date.now() exists
9
+ if (!('now' in Date)) {
10
+ return true;
11
+ }
12
+
13
+ // Check to ensure that Date.now() returns a number
14
+ if (typeof Date.now() !== 'number') {
15
+ return true;
16
+ }
17
+
18
+ // Check to see if new Date().toISOString() exists
19
+ if (!('toISOString' in new Date())) {
20
+ return true;
21
+ }
22
+
23
+ // Check to ensure new Date().toISOString() returns a string
24
+ if (typeof new Date().toISOString() !== 'string') {
25
+ return true;
26
+ }
27
+
28
+ // If none of the above checks return true, we assume that the Date function
29
+ // has not been overwritten
30
+ return false;
31
+ }
32
+
33
+ /** Timestamp wrapper to properly handle timestamps
34
+ * @param {} timestamp
35
+ */
36
+ function timestampWrapper(timestamp) {
37
+ // If the Date object has been overwritten and the timestamp is not a number,
38
+ // we use the valueOf property to try to retrieve the actual timestamp.
39
+ // If valueOf is not available, we disable client and log the error.
40
+ if (typeof timestamp !== 'number' && isDateOverwritten()) {
41
+ if (
42
+ // eslint-disable-next-line no-prototype-builtins
43
+ Date.prototype.hasOwnProperty('valueOf') &&
44
+ typeof timestamp.valueOf === 'function' &&
45
+ typeof timestamp.valueOf() === 'number'
46
+ ) {
47
+ return timestamp.valueOf();
48
+ }
49
+
50
+ ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
51
+ `The date object has been overwritten and can't be processed properly.
52
+ Client has been disabled.`,
53
+ true,
54
+ SEVERITY_ERROR,
55
+ true,
56
+ );
57
+ }
58
+
59
+ return timestamp;
60
+ }
61
+
62
+ export { isDateOverwritten, timestampWrapper };
@@ -0,0 +1,67 @@
1
+ import { SEVERITY_ERROR } from '../constants.js';
2
+ import ClientConfig from '../api/clientConfig.js';
3
+
4
+ /** addSafeEventListener will add an event listener for the specified event
5
+ * but will catch and log any errors encountered
6
+ * @param {} object to attach the listener to
7
+ * @param {} event to listen to
8
+ * @param {} callback function to call
9
+ * @param {} capture additional arguments
10
+ */
11
+ function addSafeEventListener(object, event, callback, capture) {
12
+ if (!object || !event || !callback) {
13
+ // nothing to do if these don't exist
14
+ return;
15
+ }
16
+
17
+ /** safeCallback will catch and log any errors encountered on the callback
18
+ * @param {} eventReceived for the callback
19
+ */
20
+ const safeCallback = eventReceived => {
21
+ try {
22
+ callback(eventReceived);
23
+ } catch (e) {
24
+ ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
25
+ `addEventListener callback error: ${e.message}`,
26
+ false,
27
+ SEVERITY_ERROR,
28
+ );
29
+ }
30
+ };
31
+
32
+ /**
33
+ * tries to add an event listener to a Proxy object
34
+ */
35
+ const tryAddEventListenerForProxy = () => {
36
+ if (!Reflect) {
37
+ return false;
38
+ }
39
+
40
+ try {
41
+ const addEventListener =
42
+ Reflect.get(object, 'addEventListener') || (() => {});
43
+ addEventListener(event, safeCallback, capture);
44
+ } catch (e) {
45
+ return false;
46
+ }
47
+
48
+ return true;
49
+ };
50
+
51
+ try {
52
+ object.addEventListener(event, safeCallback, capture);
53
+ } catch (e) {
54
+ if (e instanceof TypeError) {
55
+ if (tryAddEventListenerForProxy()) {
56
+ return;
57
+ }
58
+ }
59
+ ClientConfig.getInstance().postNoibuErrorAndOptionallyDisableClient(
60
+ `addEventListener error: ${e.message}`,
61
+ false,
62
+ SEVERITY_ERROR,
63
+ );
64
+ }
65
+ }
66
+
67
+ export { addSafeEventListener };