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.
Files changed (114) hide show
  1. package/README.md +15 -15
  2. package/android/build.gradle +1 -1
  3. package/dist/{src/api/clientConfig.d.ts → api/ClientConfig.d.ts} +19 -20
  4. package/dist/api/{clientConfig.js → ClientConfig.js} +82 -63
  5. package/dist/{src/api/helpCode.d.ts → api/HelpCode.d.ts} +3 -10
  6. package/dist/api/{helpCode.js → HelpCode.js} +8 -14
  7. package/dist/api/InputManager.d.ts +39 -0
  8. package/dist/api/InputManager.js +156 -0
  9. package/dist/{src/api/metroplexSocket.d.ts → api/MetroplexSocket.d.ts} +33 -38
  10. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +190 -178
  11. package/dist/{src/api/storedMetrics.d.ts → api/StoredMetrics.d.ts} +10 -20
  12. package/dist/api/StoredMetrics.js +158 -0
  13. package/dist/{src/api/storedPageVisit.d.ts → api/StoredPageVisit.d.ts} +11 -8
  14. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +62 -48
  15. package/dist/const_matchers.js +1 -5
  16. package/dist/constants.d.ts +48 -0
  17. package/dist/constants.js +15 -397
  18. package/dist/{src/entry → entry}/index.d.ts +5 -6
  19. package/dist/entry/index.js +3 -4
  20. package/dist/entry/init.d.ts +8 -0
  21. package/dist/entry/init.js +34 -19
  22. package/dist/monitors/AppNavigationMonitor.d.ts +10 -0
  23. package/dist/monitors/AppNavigationMonitor.js +19 -19
  24. package/dist/monitors/AppNavigationMonitor.test.d.ts +1 -0
  25. package/dist/{src/monitors → monitors}/BaseMonitor.d.ts +5 -5
  26. package/dist/monitors/BaseMonitor.js +9 -4
  27. package/dist/monitors/BaseMonitor.test.d.ts +1 -0
  28. package/dist/{src/monitors → monitors}/ClickMonitor.d.ts +10 -13
  29. package/dist/monitors/ClickMonitor.js +72 -76
  30. package/dist/monitors/ClickMonitor.test.d.ts +1 -0
  31. package/dist/{src/monitors → monitors}/ErrorMonitor.d.ts +4 -28
  32. package/dist/monitors/ErrorMonitor.js +45 -55
  33. package/dist/{src/monitors → monitors}/KeyboardInputMonitor.d.ts +1 -3
  34. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  35. package/dist/{src/monitors → monitors}/PageMonitor.d.ts +1 -1
  36. package/dist/monitors/PageMonitor.js +25 -2
  37. package/dist/{src/monitors → monitors}/RequestMonitor.d.ts +9 -29
  38. package/dist/monitors/RequestMonitor.js +46 -57
  39. package/dist/monitors/http-tools/GqlErrorValidator.d.ts +35 -0
  40. package/dist/monitors/http-tools/GqlErrorValidator.js +42 -70
  41. package/dist/{src/monitors → monitors}/http-tools/HTTPDataBundler.d.ts +9 -15
  42. package/dist/monitors/http-tools/HTTPDataBundler.js +74 -67
  43. package/dist/monitors/integrations/ReactNativeNavigationIntegration.d.ts +17 -0
  44. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  45. package/dist/{src/pageVisit → pageVisit}/EventDebouncer.d.ts +9 -10
  46. package/dist/pageVisit/EventDebouncer.js +43 -74
  47. package/dist/pageVisit/HttpEventManager.d.ts +14 -0
  48. package/dist/pageVisit/HttpEventManager.js +88 -0
  49. package/dist/pageVisit/PageVisitManager.d.ts +31 -0
  50. package/dist/pageVisit/PageVisitManager.js +99 -0
  51. package/dist/pageVisit/pageVisitEventError.d.ts +12 -0
  52. package/dist/pageVisit/pageVisitEventError.js +170 -280
  53. package/dist/{src/react → react}/ErrorBoundary.d.ts +4 -9
  54. package/dist/react/ErrorBoundary.js +3 -6
  55. package/dist/{src/sessionRecorder/sessionRecorder.d.ts → sessionRecorder/SessionRecorder.d.ts} +7 -17
  56. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +60 -71
  57. package/dist/{src/sessionRecorder → sessionRecorder}/nativeSessionRecorderSubscription.d.ts +4 -6
  58. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  59. package/dist/{src/storage/rnStorageProvider.d.ts → storage/RNStorageProvider.d.ts} +4 -8
  60. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  61. package/dist/{src/storage/storage.d.ts → storage/Storage.d.ts} +8 -18
  62. package/dist/storage/{storage.js → Storage.js} +17 -30
  63. package/dist/{src/storage/storageProvider.d.ts → storage/StorageProvider.d.ts} +5 -8
  64. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  65. package/dist/types/NavigationIntegration.d.ts +1 -1
  66. package/dist/utils/date.d.ts +7 -0
  67. package/dist/utils/date.js +41 -51
  68. package/dist/utils/eventlistener.js +6 -14
  69. package/dist/{src/utils → utils}/function.d.ts +13 -43
  70. package/dist/utils/function.js +42 -113
  71. package/dist/utils/log.d.ts +4 -0
  72. package/dist/utils/log.js +2 -4
  73. package/dist/{src/utils → utils}/object.d.ts +10 -8
  74. package/dist/utils/object.js +12 -12
  75. package/dist/{src/utils → utils}/performance.d.ts +1 -1
  76. package/dist/utils/piiRedactor.js +31 -3
  77. package/dist/utils/stacktrace-parser.d.ts +8 -0
  78. package/dist/utils/stacktrace-parser.js +29 -21
  79. package/dist/utils/stacktrace-parser.test.d.ts +1 -0
  80. package/package.json +14 -14
  81. package/dist/api/inputManager.js +0 -227
  82. package/dist/api/storedMetrics.js +0 -198
  83. package/dist/pageVisit/pageVisit.js +0 -181
  84. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  85. package/dist/pageVisit/userStep.js +0 -20
  86. package/dist/src/api/inputManager.d.ts +0 -87
  87. package/dist/src/constants.d.ts +0 -290
  88. package/dist/src/entry/init.d.ts +0 -5
  89. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  90. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  91. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  92. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  93. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  94. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  95. package/dist/src/pageVisit/userStep.d.ts +0 -5
  96. package/dist/src/utils/date.d.ts +0 -6
  97. package/dist/src/utils/log.d.ts +0 -4
  98. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  99. package/dist/types/Config.d.ts +0 -31
  100. package/dist/types/Metroplex.types.d.ts +0 -73
  101. package/dist/types/PageVisit.types.d.ts +0 -8
  102. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  103. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  104. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  105. package/dist/types/Storage.d.ts +0 -14
  106. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  107. package/dist/types/WrappedObjects.d.ts +0 -6
  108. /package/dist/{src/api/clientConfig.test.d.ts → api/ClientConfig.test.d.ts} +0 -0
  109. /package/dist/{src/monitors/BaseMonitor.test.d.ts → api/MetroplexSocket.test.d.ts} +0 -0
  110. /package/dist/{src/const_matchers.d.ts → const_matchers.d.ts} +0 -0
  111. /package/dist/{src/sessionRecorder → sessionRecorder}/types.d.ts +0 -0
  112. /package/dist/{src/utils → utils}/eventlistener.d.ts +0 -0
  113. /package/dist/{src/utils → utils}/piiRedactor.d.ts +0 -0
  114. /package/dist/{src/utils → utils}/polyfills.d.ts +0 -0
@@ -0,0 +1,8 @@
1
+ export declare const MAX_FRAMES_IN_ARRAY = 15;
2
+ export declare interface RawStackFrame {
3
+ file: string;
4
+ line?: number;
5
+ column?: number;
6
+ mname: string;
7
+ }
8
+ export declare function parseStack(stackString: string | NativeStackAndroid): RawStackFrame[];
@@ -1,4 +1,4 @@
1
- import { MAX_FRAMES_IN_ARRAY, MAX_STRING_LENGTH } from '../constants.js';
1
+ import { MAX_STRING_LENGTH } from '../constants.js';
2
2
 
3
3
  /* eslint-disable require-jsdoc,prefer-destructuring,camelcase */
4
4
  // This is a loose copy of ravenjs code
@@ -15,13 +15,14 @@ import { MAX_FRAMES_IN_ARRAY, MAX_STRING_LENGTH } from '../constants.js';
15
15
  // or substantial portions of the Software.
16
16
  //
17
17
  // THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
18
- // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
18
+ // INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR Target
19
19
  // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
20
  // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21
21
  // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
22
  // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
23
  // global reference to slice
24
24
  const UNKNOWN_FUNCTION = '<unknown>';
25
+ const MAX_FRAMES_IN_ARRAY = 15;
25
26
  /**
26
27
  * Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
27
28
  * What it means, is that instead of format like:
@@ -48,9 +49,7 @@ const extractSafariExtensionDetails = (func, filename) => {
48
49
  return isSafariExtension || isSafariWebExtension
49
50
  ? [
50
51
  func.indexOf('@') !== -1 ? func.split('@')[0] : UNKNOWN_FUNCTION,
51
- isSafariExtension
52
- ? `safari-extension:${filename}`
53
- : `safari-web-extension:${filename}`,
52
+ isSafariExtension ? `safari-extension:${filename}` : `safari-web-extension:${filename}`,
54
53
  ]
55
54
  : [func, filename];
56
55
  };
@@ -68,8 +67,8 @@ function createFrame(filename, func, lineno, colno) {
68
67
  return frame;
69
68
  }
70
69
  // Chromium based browsers: Chrome, Brave, new Opera, new Edge
71
- const chromeRegex = /^\s*at (?:(.+?\)(?: \[.+\])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
72
- const chromeEvalRegex = /\((\S*)(?::(\d+))(?::(\d+))\)/;
70
+ const chromeRegex = /^\s*at (?:(.+?\)(?: \[.+])?|.*?) ?\((?:address at )?)?(?:async )?((?:<anonymous>|[-a-z]+:|.*bundle|\/)?.*?)(?::(\d+))?(?::(\d+))?\)?\s*$/i;
71
+ const chromeEvalRegex = /\((\S*):(\d+):(\d+)\)/;
73
72
  const chrome = (line) => {
74
73
  const parts = chromeRegex.exec(line);
75
74
  if (parts) {
@@ -89,20 +88,29 @@ const chrome = (line) => {
89
88
  return undefined;
90
89
  };
91
90
  function parseStack(stackString) {
92
- const lines = stackString.split('\n');
93
- if (lines.length > MAX_FRAMES_IN_ARRAY) {
94
- return [];
95
- }
96
- return lines.reduce((stack, line) => {
97
- if (line.length > MAX_STRING_LENGTH) {
91
+ if (typeof stackString === 'string') {
92
+ return stackString
93
+ .split('\n')
94
+ .slice(0, MAX_FRAMES_IN_ARRAY + 1)
95
+ .reduce((stack, line) => {
96
+ if (line.length > MAX_STRING_LENGTH) {
97
+ return stack;
98
+ }
99
+ const parseResult = chrome(line);
100
+ if (parseResult) {
101
+ stack.push(parseResult);
102
+ }
98
103
  return stack;
99
- }
100
- const parseResult = chrome(line);
101
- if (parseResult) {
102
- stack.push(parseResult);
103
- }
104
- return stack;
105
- }, []);
104
+ }, []);
105
+ }
106
+ if (stackString.length && stackString[0].file) {
107
+ return stackString.map(frame => ({
108
+ file: frame.file || '<unknown>',
109
+ line: frame.lineNumber,
110
+ mname: `${frame.class}.${frame.methodName}`,
111
+ }));
112
+ }
113
+ return [];
106
114
  }
107
115
 
108
- export { parseStack };
116
+ export { MAX_FRAMES_IN_ARRAY, parseStack };
@@ -0,0 +1 @@
1
+ export {};
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noibu-react-native",
3
- "version": "0.2.6",
3
+ "version": "0.2.8",
4
4
  "targetNjsVersion": "1.0.104",
5
5
  "description": "React-Native SDK for NoibuJS to collect errors in React-Native applications",
6
6
  "main": "dist/entry/index.js",
@@ -16,12 +16,10 @@
16
16
  "clean": "rimraf ./dist/*",
17
17
  "build": "node ./build.js",
18
18
  "build:dev": "node ./build.watch.js",
19
- "prepare": "npm run clean; npm run build;",
19
+ "prepack": "npm run clean; npm run build;",
20
20
  "test": "jest --coverage",
21
21
  "tsc": "tsc",
22
- "lint": "eslint src -c .eslintrc.json --ext js,ts,jsx,tsx",
23
- "lint_output": "eslint src -c .eslintrc.json --ext js,ts,jsx,tsx -f json > eslint_report.json",
24
- "codecov": "codecov"
22
+ "lint": "tsc eslint.config.ts && eslint ."
25
23
  },
26
24
  "peerDependenciesMeta": {
27
25
  "react-native-navigation": {
@@ -42,13 +40,16 @@
42
40
  "react-native": ">=0.63.0",
43
41
  "react-native-navigation": ">=2.29.0",
44
42
  "react-native-url-polyfill": "^1.3.0",
45
- "react-native-uuid": "^2.0.1"
43
+ "react-native-uuid": "^2.0.1",
44
+ "whatwg-fetch": "^3.6.20"
46
45
  },
47
46
  "devDependencies": {
48
47
  "@babel/core": "^7.26.0",
49
48
  "@babel/preset-env": "^7.26.0",
50
49
  "@babel/preset-typescript": "^7.26.0",
50
+ "@eslint/eslintrc": "^3.2.0",
51
51
  "@jest/globals": "^29.7.0",
52
+ "@noibu/metroplex-ts-bindings": "1.0.25",
52
53
  "@react-native-async-storage/async-storage": "^1.19.0",
53
54
  "@rollup/plugin-commonjs": "^25.0.0",
54
55
  "@rollup/plugin-json": "^6.0.0",
@@ -60,20 +61,19 @@
60
61
  "@types/node": "^20.2.3",
61
62
  "@types/react": "16.14.62",
62
63
  "@types/react-test-renderer": "^18.0.0",
63
- "@typescript-eslint/eslint-plugin": "^6.21.0",
64
- "@typescript-eslint/parser": "^6.21.0",
64
+ "@typescript-eslint/eslint-plugin": "^8.19.1",
65
+ "@typescript-eslint/parser": "^8.19.1",
65
66
  "babel-jest": "^29.7.0",
66
67
  "babel-plugin-transform-flow-strip-types": "^6.22.0",
67
68
  "codecov": "^3.8.3",
68
69
  "dotenv": "^16.1.3",
69
- "eslint": "^8.41.0",
70
- "eslint-config-airbnb": "^19.0.4",
71
- "eslint-config-prettier": "^8.8.0",
72
- "eslint-plugin-jsdoc": "^44.2.4",
73
- "eslint-plugin-prettier": "^4.2.1",
70
+ "eslint": "^9.17.0",
71
+ "eslint-plugin-jsdoc": "^50.6.1",
72
+ "eslint-plugin-prettier": "^5.2.1",
73
+ "eslint-plugin-react": "^7.37.3",
74
74
  "fflate": "0.8.2",
75
75
  "jest": "^29.7.0",
76
- "prettier": "^2.8.8",
76
+ "prettier": "^3.4.2",
77
77
  "react": "16.13.1",
78
78
  "react-native": "0.63.0",
79
79
  "react-native-navigation": "^7.40.3",
@@ -1,227 +0,0 @@
1
- import { NOIBUJS_SDK_REQUEST_HELP_CODE, NOIBUJS_SDK_ADD_ID_FUNCTION, NOIBUJS_SDK_ADD_ERROR_FUNCTION, NOIBUJS_SDK_ADD_ERROR_FROM_JS_FMW_FUNCTION, MAX_CUSTOM_ERRORS_PER_PAGEVISIT, MAX_CUSTOM_IDS_PER_PAGEVISIT, META_DATA_METROPLEX_TYPE, PAGE_VISIT_META_DATA_ATT_NAME, CUSTOM_ID_NAME_TYPE, CUSTOM_ID_VALUE_TYPE, CUSTOM_ERROR_EVENT_TYPE } from '../constants.js';
2
- import MetroplexSocket from './metroplexSocket.js';
3
- import { saveErrorToPagevisit } from '../pageVisit/pageVisitEventError.js';
4
- import HelpCode from './helpCode.js';
5
-
6
- /** @module InputManager */
7
-
8
- /** this class controls the input that customers can inject into
9
- * our script via the NoibuJS SDK
10
- */
11
- class InputManager {
12
- /**
13
- * Creates a new InputManager
14
- */
15
- constructor() {
16
- this.customIDs = {};
17
- this.customErrorsCount = 0;
18
-
19
- this.TOO_MANY_IDS_ADDED_MSG = 'TOO_MANY_IDS_ADDED';
20
- this.ID_NAME_ALREADY_ADDED_MSG = 'ID_NAME_ALREADY_ADDED';
21
- this.NAME_TOO_LONG_MSG = 'NAME_TOO_LONG';
22
- this.VALUE_TOO_LONG_MSG = 'VALUE_TOO_LONG';
23
- this.INVALID_NAME_TYPE_MSG = 'INVALID_NAME_TYPE';
24
- this.INVALID_VALUE_TYPE_MSG = 'INVALID_VALUE_TYPE';
25
- this.NAME_HAS_NO_LENGTH_MSG = 'NAME_HAS_NO_LENGTH';
26
- this.VALUE_HAS_NO_LENGTH_MSG = 'VALUE_HAS_NO_LENGTH';
27
- this.SUCCESS_MSG = 'SUCCESS';
28
- this.ERROR_HAS_NO_MSG_MSG = 'ERROR_HAS_NO_MSG';
29
- this.ERROR_HAS_NO_STACK_MSG = 'ERROR_HAS_NO_STACK';
30
- this.NULL_CUSTOM_ERR_MSG = 'NULL_CUSTOM_ERROR';
31
- this.ERROR_ALREADY_RECEIVED_MSG = 'ERROR_ALREADY_RECEIVED';
32
- this.INVALID_ERROR_SOURCE_MSG = 'INVALID_ERROR_SOURCE_MSG';
33
- this.TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT_MSG =
34
- 'TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT';
35
- }
36
-
37
- /** gets the singleton instance */
38
- static getInstance() {
39
- if (!this.instance) {
40
- this.instance = new InputManager();
41
- }
42
-
43
- return this.instance;
44
- }
45
-
46
- /** exposes functions to the window of the browser for the clients
47
- * to interact with on their end
48
- */
49
- exposeFunctions() {
50
- return this._getSDKWindowObject();
51
- }
52
-
53
- /**
54
- * gets the sdk object that will be assigned to a window variable
55
- * @returns {{
56
- * requestHelpCode: (alert?: boolean) => Promise<string>,
57
- * addCustomAttribute: (name: string, value: string) => Promise<string>,
58
- * addError: (customError: Error) => string,
59
- * addJsSdkError: (customError: string, errorSource: string) => string
60
- * }}
61
- */
62
- _getSDKWindowObject() {
63
- return {
64
- // adding all the functions and binding the current context
65
- // so that we can use the exposed function as if they are running`
66
- // in the noibujs script
67
- [NOIBUJS_SDK_REQUEST_HELP_CODE]: this._requestHelpCode.bind(this),
68
- [NOIBUJS_SDK_ADD_ID_FUNCTION]: this._addCustomAttribute.bind(this),
69
- [NOIBUJS_SDK_ADD_ERROR_FUNCTION]: this._addCustomError.bind(this),
70
- [NOIBUJS_SDK_ADD_ERROR_FROM_JS_FMW_FUNCTION]:
71
- this._addErrorFromJSSdk.bind(this),
72
- };
73
- }
74
-
75
- /**
76
- * validates the custom error that was passed
77
- * @param {} customError
78
- */
79
- _validateCustomError(customError) {
80
- // customError cannot be null
81
- if (!customError) {
82
- return this.NULL_CUSTOM_ERR_MSG;
83
- }
84
-
85
- // making sure we have the message and stack to create an error signature
86
- if (!customError.message) {
87
- return this.ERROR_HAS_NO_MSG_MSG;
88
- }
89
-
90
- if (!customError.stack) {
91
- return this.ERROR_HAS_NO_STACK_MSG;
92
- }
93
-
94
- return this.SUCCESS_MSG;
95
- }
96
-
97
- /**
98
- * Validates and sets the custom error to our internal trackers
99
- * @param {} customError
100
- */
101
- _validateAndSetCustomError(customError) {
102
- // we cap the number of errors allowed to be sent
103
- if (this.customErrorsCount >= MAX_CUSTOM_ERRORS_PER_PAGEVISIT) {
104
- return this.TOO_MANY_ERRORS_RECEIVED_PER_PAGEVISIT_MSG;
105
- }
106
-
107
- // need to validate first before we start operating with the received
108
- // data
109
- const validationResult = this._validateCustomError(customError);
110
- if (validationResult !== this.SUCCESS_MSG) {
111
- return validationResult;
112
- }
113
-
114
- this.customErrorsCount += 1;
115
- return this.SUCCESS_MSG;
116
- }
117
-
118
- /**
119
- * adds an error from a JS Sdk to the session
120
- * @param {} customError
121
- * @param {string} errorSource
122
- */
123
- _addErrorFromJSSdk(customError, errorSource) {
124
- const validationAndSettingResult =
125
- this._validateAndSetCustomError(customError);
126
-
127
- if (validationAndSettingResult !== this.SUCCESS_MSG) {
128
- return validationAndSettingResult;
129
- }
130
-
131
- saveErrorToPagevisit(errorSource, { error: customError });
132
- return validationAndSettingResult;
133
- }
134
-
135
- /**
136
- * adds a custom Error to the session
137
- * @param {} customError
138
- */
139
- _addCustomError(customError) {
140
- const validationAndSettingResult =
141
- this._validateAndSetCustomError(customError);
142
- if (validationAndSettingResult !== this.SUCCESS_MSG) {
143
- return validationAndSettingResult;
144
- }
145
- saveErrorToPagevisit(CUSTOM_ERROR_EVENT_TYPE, { error: customError });
146
- return validationAndSettingResult;
147
- }
148
-
149
- /**
150
- * adds a custom id to the session
151
- * @param {} name
152
- * @param {} value
153
- */
154
- async _addCustomAttribute(name, value) {
155
- // we return if we are over the limit of ids
156
- if (Object.keys(this.customIDs).length >= MAX_CUSTOM_IDS_PER_PAGEVISIT) {
157
- return this.TOO_MANY_IDS_ADDED_MSG;
158
- }
159
-
160
- // need to validate first before we start operating with the received
161
- // data
162
- const validationResult = this._validateCustomIDInput(name, value);
163
- if (validationResult !== this.SUCCESS_MSG) {
164
- return validationResult;
165
- }
166
-
167
- // we do not want to keep sending something that was already sent
168
- if (name in this.customIDs) {
169
- return this.ID_NAME_ALREADY_ADDED_MSG;
170
- }
171
-
172
- this.customIDs[name] = value;
173
- await MetroplexSocket.getInstance().sendMessage(META_DATA_METROPLEX_TYPE, {
174
- [PAGE_VISIT_META_DATA_ATT_NAME]: {
175
- [CUSTOM_ID_NAME_TYPE]: name,
176
- [CUSTOM_ID_VALUE_TYPE]: value,
177
- },
178
- });
179
-
180
- return this.SUCCESS_MSG;
181
- }
182
-
183
- /**
184
- * validation function for customer input
185
- * @param {} name
186
- * @param {} value
187
- */
188
- _validateCustomIDInput(name, value) {
189
- // all ids need to be strings and less than 50 chars and more than 0 chars
190
- if (typeof name !== 'string') {
191
- return this.INVALID_NAME_TYPE_MSG;
192
- }
193
-
194
- if (typeof value !== 'string') {
195
- return this.INVALID_VALUE_TYPE_MSG;
196
- }
197
-
198
- if (value.length > 50) {
199
- return this.VALUE_TOO_LONG_MSG;
200
- }
201
-
202
- if (name.length > 50) {
203
- return this.NAME_TOO_LONG_MSG;
204
- }
205
-
206
- if (value.length === 0) {
207
- return this.VALUE_HAS_NO_LENGTH_MSG;
208
- }
209
-
210
- if (name.length === 0) {
211
- return this.NAME_HAS_NO_LENGTH_MSG;
212
- }
213
-
214
- return this.SUCCESS_MSG;
215
- }
216
-
217
- /**
218
- * Requests a help code from the HelpCode instance.
219
- * @param {boolean} [alertUser=true] - Whether to alert the user about the help code request.
220
- * @returns {Promise<string>} A promise that resolves with the requested help code.
221
- */
222
- _requestHelpCode() {
223
- return HelpCode.getInstance().requestHelpCode();
224
- }
225
- }
226
-
227
- export { InputManager as default };
@@ -1,198 +0,0 @@
1
- import { BROWSER_ID_ATT_NAME, PV_ID_ATT_NAME, COLLECT_VER_ATT_NAME, CURRENT_NOIBUJS_VERSION, VER_ATT_NAME, CURRENT_METRICS_VERSION, EXP_VIDEO_LENGTH_ATT_NAME, PV_EXP_VF_SEQ_ATT_NAME, PV_EXP_PART_COUNTER_ATT_NAME, PV_EXP_HTTP_DATA_SEQ_ATT_NAME, PV_HTTP_PAYLOADS_COLLECTED_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_OVERSIZE_ATT_NAME, PV_HTTP_PAYLOADS_DROPPED_TYPE_ATT_NAME, PV_HTTP_REQUESTS_DROPPED_OVER_LIMIT, VIDEO_CLICKS_ATT_NAME, PV_CLICKS_ATT_NAME, DID_CUT_PV_ATT_NAME, DID_CUT_VID_ATT_NAME, DID_START_VID_ATT_NAME, HTTP_COUNT_EXPECTED_ATT_NAME, ERR_COUNT_EXPECTED_ATT_NAME, ON_URL_ATT_NAME, GET_METROPLEX_METRICS_URL } from '../constants.js';
2
- import ClientConfig from './clientConfig.js';
3
- import { getUserAgent, stringifyJSON } from '../utils/function.js';
4
- import { addSafeEventListener } from '../utils/eventlistener.js';
5
- import { unwrapNoibuWrapped } from '../utils/object.js';
6
-
7
- /** @module StoredMetrics */
8
-
9
- /**
10
- * This class holds the final page visit and video frag metrics. It flushes
11
- * them to storage and then finally sends them to Metroplex via the post
12
- * route when the next page is loaded
13
- */
14
- class StoredMetrics {
15
- /**
16
- * Creates a new StoredMetrics instance
17
- */
18
- constructor() {
19
- this.expectedVideoLength = 0;
20
- this.expectedVfSeq = 0;
21
- this.httpSequenceNumber = 0;
22
- this.httpOverLimitCount = 0;
23
- this.httpDroppedPayloadByTypeCount = 0;
24
- this.httpDroppedPayloadByLengthCount = 0;
25
- this.httpPayloadCount = 0;
26
- this.expectedPvPart = 0;
27
- this.videoClicks = 0;
28
- this.pvClicks = 0;
29
- this.errCount = 0;
30
- this.httpCount = 0;
31
- this.didCutPv = false;
32
- this.didCutVideo = false;
33
- this.writeTimeout = null;
34
- this.didStartVideo = false;
35
-
36
- this._setupListeners();
37
- }
38
-
39
- /**
40
- * gets the singleton instance
41
- * @returns {StoredMetrics}
42
- */
43
- static getInstance() {
44
- if (!this.instance) {
45
- this.instance = new StoredMetrics();
46
- }
47
-
48
- return this.instance;
49
- }
50
-
51
- /** Add video frag payload data to the stored metrics
52
- * @param {} expectedVfSeq
53
- * @param {} expectedVideoLength
54
- */
55
- addVideoFragData(expectedVfSeq, expectedVideoLength) {
56
- this.expectedVfSeq = expectedVfSeq;
57
- this.expectedVideoLength = expectedVideoLength;
58
- }
59
-
60
- /** Set the amount of page visit parts
61
- * @param {} expectedPvPart
62
- */
63
- setPvPart(expectedPvPart) {
64
- this.expectedPvPart = expectedPvPart;
65
- }
66
-
67
- /** Increase the amount of video clicks seen in the session */
68
- addVideoClick() {
69
- this.videoClicks += 1;
70
- }
71
-
72
- /** Increase the amount of page visit clicks */
73
- addPvClick() {
74
- this.pvClicks += 1;
75
- }
76
-
77
- /** Increments the error count by 1 */
78
- addError() {
79
- this.errCount += 1;
80
- }
81
-
82
- /** Increments the http count by 1 */
83
- addHttpEvent() {
84
- this.httpCount += 1;
85
- }
86
-
87
- /** Increments the http data sequence count by 1 */
88
- addHttpData() {
89
- this.httpSequenceNumber += 1;
90
- }
91
-
92
- /** Increments the http data over limit count by 1 */
93
- addHttpDataOverLimit() {
94
- this.httpOverLimitCount += 1;
95
- }
96
-
97
- /** Increments the http data drop count by content type */
98
- addHttpDataDropByType() {
99
- this.httpDroppedPayloadByTypeCount += 1;
100
- }
101
-
102
- /** Increments the http data drop count by content length */
103
- addHttpDataDropByLength() {
104
- this.httpDroppedPayloadByLengthCount += 1;
105
- }
106
-
107
- /** Increments the http data payload collected count */
108
- addHttpDataPayloadCount() {
109
- this.httpPayloadCount += 1;
110
- }
111
-
112
- /** Set that the video was cut/blocked due to size constraints */
113
- setDidCutVideo() {
114
- this.didCutVideo = true;
115
- }
116
-
117
- /** Set that the video was started */
118
- setDidStartVideo() {
119
- this.didStartVideo = true;
120
- }
121
-
122
- /** Set that the page visit was cut/blocked due to size constraints */
123
- setDidCutPv() {
124
- this.didCutPv = true;
125
- }
126
-
127
- /**
128
- * Sets up all the listeners that noibujs should listen to before storing
129
- * our metrics to localstorage
130
- */
131
- _setupListeners() {
132
- // Add the window event handlers to post the data to the metrics endpoint
133
- const evt = 'pagehide';
134
- addSafeEventListener(window, evt, () => {
135
- this._postMetricsIfActive(evt);
136
- });
137
- }
138
-
139
- /** posts the metrics to metroplex if client is active
140
- * @param {} eventName
141
- */
142
- _postMetricsIfActive(eventName) {
143
- if (ClientConfig.getInstance().isClientDisabled) {
144
- return;
145
- }
146
- // Don't send the metrics if the session has become inactive
147
- // already sent when went inactive
148
- if (ClientConfig.getInstance().isInactive()) {
149
- return;
150
- }
151
- this.postMetrics(eventName);
152
- }
153
-
154
- /** posts the metrics to metroplex using the beacon API
155
- */
156
- async postMetrics() {
157
- // Create a new object to write to local storage that doesnt have the timeout and flush members.
158
- const lsMetrics = {
159
- // metadata
160
- [BROWSER_ID_ATT_NAME]: ClientConfig.getInstance().browserId,
161
- [PV_ID_ATT_NAME]: ClientConfig.getInstance().pageVisitId,
162
- [COLLECT_VER_ATT_NAME]: CURRENT_NOIBUJS_VERSION,
163
- [VER_ATT_NAME]: CURRENT_METRICS_VERSION,
164
-
165
- // metrics
166
- [EXP_VIDEO_LENGTH_ATT_NAME]: this.expectedVideoLength,
167
- [PV_EXP_VF_SEQ_ATT_NAME]: this.expectedVfSeq,
168
- [PV_EXP_PART_COUNTER_ATT_NAME]: this.expectedPvPart,
169
- [PV_EXP_HTTP_DATA_SEQ_ATT_NAME]: this.httpSequenceNumber,
170
- [PV_HTTP_PAYLOADS_COLLECTED_ATT_NAME]: this.httpPayloadCount,
171
- [PV_HTTP_PAYLOADS_DROPPED_OVERSIZE_ATT_NAME]:
172
- this.httpDroppedPayloadByLengthCount,
173
- [PV_HTTP_PAYLOADS_DROPPED_TYPE_ATT_NAME]:
174
- this.httpDroppedPayloadByTypeCount,
175
- [PV_HTTP_REQUESTS_DROPPED_OVER_LIMIT]: this.httpOverLimitCount,
176
- [VIDEO_CLICKS_ATT_NAME]: this.videoClicks,
177
- [PV_CLICKS_ATT_NAME]: this.pvClicks,
178
- [DID_CUT_PV_ATT_NAME]: this.didCutPv,
179
- [DID_CUT_VID_ATT_NAME]: this.didCutVideo,
180
- [DID_START_VID_ATT_NAME]: this.didStartVideo,
181
- [HTTP_COUNT_EXPECTED_ATT_NAME]: this.httpCount,
182
- [ERR_COUNT_EXPECTED_ATT_NAME]: this.errCount,
183
- [ON_URL_ATT_NAME]: ClientConfig.getInstance().globalUrl,
184
- };
185
- unwrapNoibuWrapped(fetch)(GET_METROPLEX_METRICS_URL(), {
186
- method: 'POST',
187
- headers: {
188
- 'content-type': 'application/json',
189
- 'User-Agent': await getUserAgent(),
190
- },
191
- body: stringifyJSON(lsMetrics),
192
- // keep alive outlives the current page, its the same as beacon
193
- keepalive: true,
194
- });
195
- }
196
- }
197
-
198
- export { StoredMetrics as default };