noibu-react-native 0.1.1 → 0.1.3

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 (35) hide show
  1. package/dist/api/clientConfig.d.ts +4 -5
  2. package/dist/api/clientConfig.js +21 -15
  3. package/dist/api/inputManager.js +1 -1
  4. package/dist/api/metroplexSocket.d.ts +155 -0
  5. package/dist/api/metroplexSocket.js +667 -804
  6. package/dist/api/storedMetrics.js +2 -1
  7. package/dist/constants.d.ts +11 -0
  8. package/dist/constants.js +15 -2
  9. package/dist/entry/index.js +2 -0
  10. package/dist/entry/init.d.ts +1 -1
  11. package/dist/entry/init.js +9 -2
  12. package/dist/monitors/appNavigationMonitor.js +3 -2
  13. package/dist/monitors/clickMonitor.js +1 -1
  14. package/dist/monitors/errorMonitor.js +2 -2
  15. package/dist/monitors/httpDataBundler.js +62 -15
  16. package/dist/monitors/inputMonitor.js +5 -0
  17. package/dist/monitors/integrations/react-native-navigation-integration.d.ts +1 -2
  18. package/dist/monitors/keyboardInputMonitor.js +1 -1
  19. package/dist/monitors/requestMonitor.js +47 -310
  20. package/dist/pageVisit/pageVisit.js +5 -0
  21. package/dist/pageVisit/{pageVisitEventError/pageVisitEventError.js → pageVisitEventError.js} +18 -19
  22. package/dist/pageVisit/{pageVisitEventHTTP/pageVisitEventHTTP.js → pageVisitEventHTTP.js} +15 -7
  23. package/dist/pageVisit/{userStep/userStep.js → userStep.js} +2 -2
  24. package/dist/types/NavigationIntegration.d.ts +1 -2
  25. package/dist/types/globals.d.ts +6 -3
  26. package/dist/utils/function.d.ts +2 -3
  27. package/dist/utils/function.js +15 -10
  28. package/dist/utils/log.d.ts +5 -0
  29. package/dist/utils/log.js +17 -0
  30. package/dist/utils/object.d.ts +41 -0
  31. package/dist/utils/object.js +85 -108
  32. package/dist/utils/performance.d.ts +6 -0
  33. package/dist/utils/performance.js +1 -2
  34. package/package.json +5 -4
  35. package/dist/pageVisit/pageVisitEventError/blacklistedDomains.js +0 -9
@@ -1,8 +1,9 @@
1
- import DeviceInfo from 'react-native-device-info';
1
+ import { Platform } from 'react-native';
2
2
  import { parseStack } from './stacktrace-parser.js';
3
3
  import { MAX_STRING_LENGTH, MAX_BEACON_PAYLOAD_SIZE, REQUIRED_DATA_PROCESSING_URLS, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
4
+ import { noibuLog } from './log.js';
5
+ import { unwrapNoibuWrapped } from './object.js';
4
6
 
5
- /** @module Functions */
6
7
  /**
7
8
  * Returns a stack trace frame with default filed values
8
9
  */
@@ -139,7 +140,7 @@ async function makeRequest(method, url, data, headers, timeout, sendAndForget) {
139
140
  if (currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
140
141
  return Promise.resolve();
141
142
  }
142
- return fetch(url, {
143
+ return unwrapNoibuWrapped(fetch)(url, {
143
144
  method: 'POST',
144
145
  headers: headersWithUa,
145
146
  body: stringifyJSON(data),
@@ -186,20 +187,22 @@ function isValidURL(str) {
186
187
  }
187
188
  let userAgentCache = '';
188
189
  /**
189
- * Because of the nature of user agent in react native, we have to make this async.
190
- * But I promise, this is really fast, since we memoize the result for the whole session :)
191
- * @returns {Promise<string>}
190
+ * Fakes the user agent retrieval, since there are no good libraries that support both expo and plain RN
191
+ * caches the result for the session
192
192
  */
193
193
  async function getUserAgent() {
194
194
  if (userAgentCache) {
195
195
  return userAgentCache;
196
196
  }
197
- try {
198
- userAgentCache = await DeviceInfo.getUserAgent();
197
+ noibuLog('getUserAgent start');
198
+ if (Platform.OS === 'android') {
199
+ const { Brand, Model, Release } = Platform.constants;
200
+ userAgentCache = `Mozilla/5.0 (Linux; Android ${Release}; ${Brand} ${Model}; React Native ${Platform.Version}) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Mobile Safari/537.36`;
199
201
  }
200
- catch (e) {
201
- userAgentCache = '';
202
+ else if (Platform.OS === 'ios') {
203
+ userAgentCache = `Mozilla/5.0 (iPhone; CPU iPhone OS ${Platform.constants.osVersion} like Mac OS X; React Native ${Platform.Version}) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.1 Mobile/15E148 Safari/604.1`;
202
204
  }
205
+ noibuLog('getUserAgent end', { userAgentCache });
203
206
  return userAgentCache;
204
207
  }
205
208
  /**
@@ -210,6 +213,7 @@ function isInvalidURLConfig(urls) {
210
213
  for (let i = 0; i < REQUIRED_DATA_PROCESSING_URLS.length; i += 1) {
211
214
  const u = REQUIRED_DATA_PROCESSING_URLS[i];
212
215
  if (!urls[u]) {
216
+ noibuLog('urlConfig invalid, reason', u);
213
217
  return true;
214
218
  }
215
219
  }
@@ -224,6 +228,7 @@ function isNoibuJSAlreadyLoaded() {
224
228
  const loaded = window.noibuJSLoaded !== undefined;
225
229
  // set the variable so future copies of the script
226
230
  // will know this instance is running
231
+ noibuLog('is already loaded? -', loaded);
227
232
  window.noibuJSLoaded = true;
228
233
  return loaded;
229
234
  }
@@ -0,0 +1,5 @@
1
+ /// <reference types="react-native" />
2
+ /**
3
+ * log with level = info
4
+ */
5
+ export declare const noibuLog: Console['log'];
@@ -0,0 +1,17 @@
1
+ /* eslint-disable no-console,@typescript-eslint/no-empty-function */
2
+ /** no operation */
3
+ const noop = () => { };
4
+ /**
5
+ * checks if was overridden and calls original console function
6
+ */
7
+ const getConsoleMethod = (ogProp) => {
8
+ {
9
+ return noop;
10
+ }
11
+ };
12
+ /**
13
+ * log with level = info
14
+ */
15
+ const noibuLog = (...msgs) => getConsoleMethod()('Noibu', ...msgs);
16
+
17
+ export { noibuLog };
@@ -0,0 +1,41 @@
1
+ /** @module Object */
2
+ type Func = (...args: any[]) => any;
3
+ /**
4
+ * Replaces an attribute value found in an object with another value
5
+ * sourceObject: source object whose attribute will get replaced
6
+ * attributeName: the attribute key whose value will be replace
7
+ * processingFunction: function that accepts the original value
8
+ * and returns the newValue
9
+ * @param {} sourceObject
10
+ * @param {} attributeName
11
+ * @param {} processingFunction
12
+ */
13
+ export declare const replace: <A extends { [k in K]: Func; }, K extends keyof A>(sourceObject: A, attributeName: K, processingFunction: (arg: A[K]) => A[K]) => void;
14
+ /**
15
+ * unwraps wrapped property, so we can use it without side effects
16
+ * @param anything
17
+ */
18
+ export declare function unwrapNoibuWrapped<T>(anything: {
19
+ __noibu_original__?: T;
20
+ } & T): NonNullable<T>;
21
+ /**
22
+ * Checks whether the prototype's property is writeable. If it is not,
23
+ * checks whether the property can be made writeable. If it can, it is
24
+ * set to writeable.
25
+ * @param {object} proto
26
+ * @param {string} property
27
+ * @returns {boolean} Whether the property on the prototype is (or is now) writeable
28
+ */
29
+ export declare const propWriteableOrMadeWriteable: (proto: object, property: never) => boolean;
30
+ /**
31
+ * Iterates object recursively and calls visit function
32
+ * for each property allowing to override its value
33
+ * @param {Object} instance An object to iterate through
34
+ * @param {Function} visit A callback function that is called for each property
35
+ * There are 3 arguments: current object, current property and its value
36
+ * @param {{depth: number}} limit Use limit config object to set depth of the recursion
37
+ */
38
+ export declare const iterateObjectRecursively: (instance: Record<any, any>, visit: (i: Record<any, any>, p: any, v: any) => any, limit?: {
39
+ depth: number;
40
+ }) => void;
41
+ export {};
@@ -10,39 +10,43 @@
10
10
  * @param {} processingFunction
11
11
  */
12
12
  const replace = (sourceObject, attributeName, processingFunction) => {
13
- if (!(attributeName in sourceObject)) {
14
- return;
15
- }
16
-
17
- const originalAttribute = sourceObject[attributeName];
18
- const newValue = processingFunction(originalAttribute);
19
-
20
- if (typeof newValue === 'function') {
21
- try {
22
- newValue.prototype = newValue.prototype || {};
23
- Object.defineProperties(newValue, {
24
- __noibu__: {
25
- enumerable: false,
26
- value: true,
27
- },
28
- __noibu_original__: {
29
- enumerable: false,
30
- value: originalAttribute,
31
- },
32
- __noibu_wrapped__: {
33
- enumerable: false,
34
- value: newValue,
35
- },
36
- });
37
- } catch (err) {
38
- // silent fail
13
+ if (!(attributeName in sourceObject)) {
14
+ return;
39
15
  }
40
- }
41
-
42
- // eslint-disable-next-line no-param-reassign
43
- sourceObject[attributeName] = newValue;
16
+ const originalAttribute = sourceObject[attributeName];
17
+ const newValue = processingFunction(originalAttribute);
18
+ if (typeof newValue === 'function') {
19
+ try {
20
+ newValue.prototype = newValue.prototype || {};
21
+ Object.defineProperties(newValue, {
22
+ __noibu__: {
23
+ enumerable: false,
24
+ value: true,
25
+ },
26
+ __noibu_original__: {
27
+ enumerable: false,
28
+ value: originalAttribute,
29
+ },
30
+ __noibu_wrapped__: {
31
+ enumerable: false,
32
+ value: newValue,
33
+ },
34
+ });
35
+ }
36
+ catch (err) {
37
+ // silent fail
38
+ }
39
+ }
40
+ // eslint-disable-next-line no-param-reassign
41
+ sourceObject[attributeName] = newValue;
44
42
  };
45
-
43
+ /**
44
+ * unwraps wrapped property, so we can use it without side effects
45
+ * @param anything
46
+ */
47
+ function unwrapNoibuWrapped(anything) {
48
+ return anything.__noibu_original__ || anything;
49
+ }
46
50
  /**
47
51
  * Checks whether the prototype's property is writeable. If it is not,
48
52
  * checks whether the property can be made writeable. If it can, it is
@@ -52,50 +56,29 @@ const replace = (sourceObject, attributeName, processingFunction) => {
52
56
  * @returns {boolean} Whether the property on the prototype is (or is now) writeable
53
57
  */
54
58
  const propWriteableOrMadeWriteable = (proto, property) => {
55
- if (
56
- !proto ||
57
- !proto.hasOwnProperty ||
58
- !Object.prototype.hasOwnProperty.call(proto, property)
59
- ) {
60
- return false;
61
- }
62
-
63
- // Getting the properties that this the prototype
64
- // has under the open property
65
- const propDescriptor = Object.getOwnPropertyDescriptor(proto, property);
66
-
67
- // Checking if the open property is read-only
68
- if (!propDescriptor.writable) {
69
- // Checking if we can write to it
70
- if (propDescriptor.configurable) {
71
- // Making it writable to wrap it
72
- Object.defineProperty(proto, property, {
73
- writable: true,
74
- });
75
- } else {
76
- return false;
59
+ if (!proto ||
60
+ !proto.hasOwnProperty ||
61
+ !Object.prototype.hasOwnProperty.call(proto, property)) {
62
+ return false;
77
63
  }
78
- }
79
- return true;
80
- };
81
-
82
- /**
83
- * Replaces the behaviour of Object.fromEntries() as it is not supported on all browsers
84
- * @param {Iterable} entries The iterable to parse into an object
85
- * @returns An object containing the same key/values as the iterable passed
86
- */
87
- const safeFromEntries = entries => {
88
- if (!entries || !entries[Symbol.iterator]) {
89
- throw new Error('Object.fromEntries() requires a single iterable argument');
90
- }
91
- const obj = {};
92
- // eslint-disable-next-line no-restricted-syntax
93
- for (const [key, value] of entries) {
94
- obj[key] = value;
95
- }
96
- return obj;
64
+ // Getting the properties that this the prototype
65
+ // has under the open property
66
+ const propDescriptor = Object.getOwnPropertyDescriptor(proto, property);
67
+ // Checking if the open property is read-only
68
+ if (!propDescriptor?.writable) {
69
+ // Checking if we can write to it
70
+ if (propDescriptor?.configurable) {
71
+ // Making it writable to wrap it
72
+ Object.defineProperty(proto, property, {
73
+ writable: true,
74
+ });
75
+ }
76
+ else {
77
+ return false;
78
+ }
79
+ }
80
+ return true;
97
81
  };
98
-
99
82
  /**
100
83
  * Iterates object recursively and calls visit function
101
84
  * for each property allowing to override its value
@@ -104,41 +87,35 @@ const safeFromEntries = entries => {
104
87
  * There are 3 arguments: current object, current property and its value
105
88
  * @param {{depth: number}} limit Use limit config object to set depth of the recursion
106
89
  */
107
- const iterateObjectRecursively = (
108
- instance,
109
- visit,
110
- limit = { depth: 5 },
111
- ) => {
112
- /* eslint-disable no-shadow, no-restricted-syntax, no-param-reassign, guard-for-in */
113
- /**
114
- * internal recursive function
115
- * @param {Object} instance Current object
116
- * @param {Number} depth Current depth
117
- */
118
- const iterate = (instance, depth) => {
119
- // stop to go deeper if it is deep enough already
120
- if (depth > limit.depth) return;
121
- for (const property in instance) {
122
- try {
123
- // call visit function and assign its result if not undefined
124
- const newValue = visit(instance, property, instance[property]);
125
- if (newValue !== undefined) {
126
- instance[property] = newValue;
127
- }
128
- // go one level deeper if it is an object
129
- if (
130
- instance[property] !== null &&
131
- typeof instance[property] === 'object'
132
- ) {
133
- iterate(instance[property], depth + 1);
90
+ const iterateObjectRecursively = (instance, visit, limit = { depth: 5 }) => {
91
+ /* eslint-disable no-shadow, no-restricted-syntax, no-param-reassign, guard-for-in */
92
+ /**
93
+ * internal recursive function
94
+ * @param {Object} inst Current object
95
+ * @param {Number} depth Current depth
96
+ */
97
+ const iterate = (inst, depth) => {
98
+ // stop to go deeper if it is deep enough already
99
+ if (depth > limit.depth)
100
+ return;
101
+ for (const property in inst) {
102
+ try {
103
+ // call visit function and assign its result if not undefined
104
+ const newValue = visit(inst, property, inst[property]);
105
+ if (newValue !== undefined) {
106
+ inst[property] = newValue;
107
+ }
108
+ // go one level deeper if it is an object
109
+ if (inst[property] !== null && typeof inst[property] === 'object') {
110
+ iterate(inst[property], depth + 1);
111
+ }
112
+ }
113
+ catch (e) {
114
+ // just continue to the next property
115
+ }
134
116
  }
135
- } catch (e) {
136
- // just continue to the next property
137
- }
138
- }
139
- };
140
-
141
- iterate(instance, 1);
117
+ };
118
+ iterate(instance, 1);
142
119
  };
143
120
 
144
- export { iterateObjectRecursively, propWriteableOrMadeWriteable, replace, safeFromEntries };
121
+ export { iterateObjectRecursively, propWriteableOrMadeWriteable, replace, unwrapNoibuWrapped };
@@ -0,0 +1,6 @@
1
+ /**
2
+ * Wrapper function for window.performance.now() to ensure
3
+ * it's available before calling it. If it's not available,
4
+ * we return Date.now() instead.
5
+ */
6
+ export declare function safePerformanceNow(): any;
@@ -1,14 +1,13 @@
1
1
  import { timestampWrapper } from './date.js';
2
2
 
3
3
  /** @module Performance */
4
-
5
4
  /**
6
5
  * Wrapper function for window.performance.now() to ensure
7
6
  * it's available before calling it. If it's not available,
8
7
  * we return Date.now() instead.
9
8
  */
10
9
  function safePerformanceNow() {
11
- return timestampWrapper(Date.now());
10
+ return timestampWrapper(Date.now());
12
11
  }
13
12
 
14
13
  export { safePerformanceNow };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noibu-react-native",
3
- "version": "0.1.1",
3
+ "version": "0.1.3",
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",
@@ -21,14 +21,15 @@
21
21
  "lint_output": "eslint src -c .eslintrc.json --ext js,ts,jsx,tsx -f json > eslint_report.json",
22
22
  "codecov": "codecov"
23
23
  },
24
- "optionalDependencies": {
25
- "react-native-navigation": "7"
24
+ "peerDependenciesMeta": {
25
+ "react-native-navigation": {
26
+ "optional": true
27
+ }
26
28
  },
27
29
  "dependencies": {
28
30
  "@react-native-async-storage/async-storage": "^1.19.0",
29
31
  "react": ">=16.11.0",
30
32
  "react-native": ">=0.63.0",
31
- "react-native-device-info": "^10.6.0",
32
33
  "react-native-url-polyfill": "^1.3.0",
33
34
  "react-native-uuid": "^2.0.1"
34
35
  },
@@ -1,9 +0,0 @@
1
- var blacklisedDomains = {
2
- 'input.noibu.com': true,
3
- 'input.staging.noibu.com': true,
4
- 'vf.noibu.com': true,
5
- 'vf.staging.noibu.com': true,
6
- 'cdn.noibu.com': true,
7
- };
8
-
9
- export { blacklisedDomains as default };