noibu-react-native 0.2.5 → 0.2.7

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 (98) hide show
  1. package/README.md +15 -15
  2. package/android/build.gradle +1 -1
  3. package/dist/api/{clientConfig.js → ClientConfig.js} +69 -52
  4. package/dist/api/{helpCode.js → HelpCode.js} +6 -13
  5. package/dist/api/InputManager.js +156 -0
  6. package/dist/api/{metroplexSocket.js → MetroplexSocket.js} +189 -178
  7. package/dist/api/StoredMetrics.js +158 -0
  8. package/dist/api/{storedPageVisit.js → StoredPageVisit.js} +61 -48
  9. package/dist/const_matchers.js +1 -5
  10. package/dist/constants.js +15 -390
  11. package/dist/entry/index.js +3 -4
  12. package/dist/entry/init.js +33 -19
  13. package/dist/monitors/AppNavigationMonitor.js +19 -19
  14. package/dist/monitors/BaseMonitor.js +9 -4
  15. package/dist/monitors/ClickMonitor.js +72 -76
  16. package/dist/monitors/ErrorMonitor.js +45 -55
  17. package/dist/monitors/KeyboardInputMonitor.js +13 -11
  18. package/dist/monitors/PageMonitor.js +25 -2
  19. package/dist/monitors/RequestMonitor.js +46 -57
  20. package/dist/monitors/http-tools/GqlErrorValidator.js +39 -69
  21. package/dist/monitors/http-tools/HTTPDataBundler.js +71 -66
  22. package/dist/monitors/integrations/{react-native-navigation-integration.js → ReactNativeNavigationIntegration.js} +15 -12
  23. package/dist/pageVisit/EventDebouncer.js +43 -74
  24. package/dist/pageVisit/HttpEventManager.js +88 -0
  25. package/dist/pageVisit/PageVisitManager.js +99 -0
  26. package/dist/pageVisit/pageVisitEventError.js +170 -280
  27. package/dist/react/ErrorBoundary.js +3 -6
  28. package/dist/sessionRecorder/{sessionRecorder.js → SessionRecorder.js} +58 -70
  29. package/dist/sessionRecorder/nativeSessionRecorderSubscription.js +3 -5
  30. package/dist/storage/{rnStorageProvider.js → RNStorageProvider.js} +3 -7
  31. package/dist/storage/{storage.js → Storage.js} +17 -30
  32. package/dist/storage/{storageProvider.js → StorageProvider.js} +7 -8
  33. package/dist/utils/date.js +39 -50
  34. package/dist/utils/eventlistener.js +5 -12
  35. package/dist/utils/function.js +42 -113
  36. package/dist/utils/log.js +5 -5
  37. package/dist/utils/object.js +12 -12
  38. package/dist/utils/piiRedactor.js +31 -3
  39. package/dist/utils/stacktrace-parser.js +29 -21
  40. package/package.json +14 -14
  41. package/dist/api/inputManager.js +0 -227
  42. package/dist/api/storedMetrics.js +0 -198
  43. package/dist/pageVisit/pageVisit.js +0 -181
  44. package/dist/pageVisit/pageVisitEventHTTP.js +0 -98
  45. package/dist/pageVisit/userStep.js +0 -20
  46. package/dist/src/api/clientConfig.d.ts +0 -100
  47. package/dist/src/api/clientConfig.test.d.ts +0 -1
  48. package/dist/src/api/helpCode.d.ts +0 -23
  49. package/dist/src/api/inputManager.d.ts +0 -87
  50. package/dist/src/api/metroplexSocket.d.ts +0 -137
  51. package/dist/src/api/storedMetrics.d.ts +0 -73
  52. package/dist/src/api/storedPageVisit.d.ts +0 -40
  53. package/dist/src/const_matchers.d.ts +0 -1
  54. package/dist/src/constants.d.ts +0 -290
  55. package/dist/src/entry/index.d.ts +0 -14
  56. package/dist/src/entry/init.d.ts +0 -5
  57. package/dist/src/monitors/AppNavigationMonitor.d.ts +0 -18
  58. package/dist/src/monitors/BaseMonitor.d.ts +0 -13
  59. package/dist/src/monitors/BaseMonitor.test.d.ts +0 -1
  60. package/dist/src/monitors/ClickMonitor.d.ts +0 -31
  61. package/dist/src/monitors/ErrorMonitor.d.ts +0 -63
  62. package/dist/src/monitors/KeyboardInputMonitor.d.ts +0 -20
  63. package/dist/src/monitors/PageMonitor.d.ts +0 -20
  64. package/dist/src/monitors/RequestMonitor.d.ts +0 -94
  65. package/dist/src/monitors/http-tools/GqlErrorValidator.d.ts +0 -59
  66. package/dist/src/monitors/http-tools/HTTPDataBundler.d.ts +0 -112
  67. package/dist/src/monitors/integrations/react-native-navigation-integration.d.ts +0 -20
  68. package/dist/src/pageVisit/EventDebouncer.d.ts +0 -24
  69. package/dist/src/pageVisit/pageVisit.d.ts +0 -52
  70. package/dist/src/pageVisit/pageVisitEventError.d.ts +0 -15
  71. package/dist/src/pageVisit/pageVisitEventHTTP.d.ts +0 -25
  72. package/dist/src/pageVisit/userStep.d.ts +0 -5
  73. package/dist/src/react/ErrorBoundary.d.ts +0 -72
  74. package/dist/src/sessionRecorder/nativeSessionRecorderSubscription.d.ts +0 -79
  75. package/dist/src/sessionRecorder/sessionRecorder.d.ts +0 -60
  76. package/dist/src/sessionRecorder/types.d.ts +0 -91
  77. package/dist/src/storage/rnStorageProvider.d.ts +0 -23
  78. package/dist/src/storage/storage.d.ts +0 -39
  79. package/dist/src/storage/storageProvider.d.ts +0 -26
  80. package/dist/src/utils/date.d.ts +0 -6
  81. package/dist/src/utils/eventlistener.d.ts +0 -8
  82. package/dist/src/utils/function.d.ts +0 -102
  83. package/dist/src/utils/log.d.ts +0 -4
  84. package/dist/src/utils/object.d.ts +0 -44
  85. package/dist/src/utils/performance.d.ts +0 -6
  86. package/dist/src/utils/piiRedactor.d.ts +0 -11
  87. package/dist/src/utils/polyfills.d.ts +0 -4
  88. package/dist/src/utils/stacktrace-parser.d.ts +0 -7
  89. package/dist/types/Config.d.ts +0 -31
  90. package/dist/types/Metroplex.types.d.ts +0 -73
  91. package/dist/types/NavigationIntegration.d.ts +0 -6
  92. package/dist/types/PageVisit.types.d.ts +0 -8
  93. package/dist/types/PageVisitErrors.types.d.ts +0 -114
  94. package/dist/types/PageVisitEvents.types.d.ts +0 -91
  95. package/dist/types/PageVisitMetrics.types.d.ts +0 -27
  96. package/dist/types/Storage.d.ts +0 -14
  97. package/dist/types/StoredPageVisit.types.d.ts +0 -11
  98. package/dist/types/WrappedObjects.d.ts +0 -6
@@ -1,17 +1,21 @@
1
1
  import { __awaiter } from 'tslib';
2
2
  import { Platform } from 'react-native';
3
3
  import { parseStack } from './stacktrace-parser.js';
4
- import { MAX_STRING_LENGTH, MAX_BEACON_PAYLOAD_SIZE, REQUIRED_DATA_PROCESSING_URLS, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, JS_STACK_LINE_ATT_NAME, DEFAULT_STACK_FRAME_FIELD_VALUE, JS_STACK_METHOD_ATT_NAME, JS_STACK_FILE_ATT_NAME } from '../constants.js';
4
+ import { MAX_STRING_LENGTH, MAX_BEACON_PAYLOAD_SIZE, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING } from '../constants.js';
5
5
  import { noibuLog } from './log.js';
6
6
  import { unwrapNoibuWrapped } from './object.js';
7
7
 
8
+ // default string for stack frame fields
9
+ const DEFAULT_STACK_FRAME_FIELD_VALUE = '_';
10
+ const PII_DIGIT_PATTERN = /[0-9]+/g;
11
+ const STACK_TRACE_SANITIZE_REGEXP = /(nbuGlobalPromiseRejectWrapper|InternalBytecode)/gi;
8
12
  /**
9
13
  * Returns a stack trace frame with default filed values
10
14
  */
11
15
  const getDefaultFrame = () => ({
12
- [JS_STACK_LINE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
13
- [JS_STACK_METHOD_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
14
- [JS_STACK_FILE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
16
+ line: DEFAULT_STACK_FRAME_FIELD_VALUE,
17
+ mname: DEFAULT_STACK_FRAME_FIELD_VALUE,
18
+ file: DEFAULT_STACK_FRAME_FIELD_VALUE,
15
19
  });
16
20
  /**
17
21
  * returns a string that satisfies a max length
@@ -55,22 +59,15 @@ function processFrames(rawFrames) {
55
59
  return processedFrame;
56
60
  });
57
61
  }
58
- /**
59
- * Retrieves the javascript stack and message from an error event object
60
- * @param errObj error to extract stack from
61
- */
62
+ /** Retrieves the javascript stack and message from an error event object */
62
63
  function getJSStack(errObj) {
63
- let frames = [getDefaultFrame()];
64
64
  // if the errObj type is not an object or null
65
65
  // return a default frame
66
66
  if (typeof errObj !== 'object' || !errObj || !errObj.stack) {
67
- return {
68
- frames,
69
- msg: '',
70
- };
67
+ return { frames: [getDefaultFrame()], msg: '' };
71
68
  }
72
- frames = processFrames(parseStack(errObj.stack));
73
69
  const msg = errObj.message ? getMaxSubstringAllowed(errObj.message) : '';
70
+ const frames = processFrames(parseStack(errObj.stack)).filter(line => !`${line.file}|${line.mname}`.match(STACK_TRACE_SANITIZE_REGEXP));
74
71
  return {
75
72
  frames,
76
73
  msg,
@@ -111,63 +108,36 @@ function stringifyJSON(jsonObject) {
111
108
  });
112
109
  }
113
110
  /**
114
- * Wrapper for a request, since we have to do some special handling
115
- * @param method
116
- * @param url
117
- * @param data
118
- * @param headers
119
- * @param timeout
120
- * @param sendAndForget
111
+ * Wrapper for a request with an ability to send-and-forget
112
+ * a send-and-forget request can outlive the page
121
113
  */
122
- function makeRequest(method, url, data, headers, timeout, sendAndForget) {
123
- return __awaiter(this, void 0, void 0, function* () {
124
- const ua = Object.keys(headers).findLast(k => k.toLowerCase() === 'user-agent');
125
- const headersWithUa = Object.assign({}, headers);
126
- if (!headers[ua]) {
127
- headersWithUa['User-Agent'] = yield getUserAgent();
128
- }
129
- // a send-and-forget request is made by using the beacon API (fetch + keepalive)
130
- if (sendAndForget) {
131
- const stringData = stringifyJSON(data);
132
- const currentPayloadSize = new Blob([stringData]).size;
133
- // if we have a large object or fetch is not available, we skip sending the message
134
- if (currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
135
- return Promise.resolve();
136
- }
137
- return unwrapNoibuWrapped(fetch)(url, {
138
- method: 'POST',
139
- headers: headersWithUa,
140
- body: stringifyJSON(data),
141
- // keep alive outlives the current page, its the same as beacon
142
- keepalive: true,
143
- });
144
- }
145
- return new Promise((resolve, reject) => {
146
- const xhr = new XMLHttpRequest();
147
- xhr.open(method, url);
148
- xhr.timeout = timeout;
149
- Object.keys(headersWithUa).forEach(header => {
150
- xhr.setRequestHeader(header, headers[header]);
151
- });
152
- xhr.onload = () => {
153
- if (xhr.status >= 200 && xhr.status < 300) {
154
- resolve(xhr.response);
155
- }
156
- else {
157
- reject(new Error(`Custom Request failed: ${xhr.statusText}`));
158
- }
159
- };
160
- xhr.onerror = () => {
161
- reject(new Error(`Custom Request failed: ${xhr.statusText}`));
162
- };
163
- if (data) {
164
- xhr.send(stringifyJSON(data));
165
- }
166
- else {
167
- xhr.send();
168
- }
169
- });
170
- });
114
+ function postRequest(url, data, headers, sendAndForget = false, timeout = 2000) {
115
+ if (typeof fetch !== 'function') {
116
+ return Promise.resolve();
117
+ }
118
+ const body = asString(data);
119
+ const currentPayloadSize = new Blob([body]).size;
120
+ if (sendAndForget && currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
121
+ return Promise.reject("Can't queue data for transfer due to it's size.");
122
+ }
123
+ const init = {
124
+ method: 'POST',
125
+ headers,
126
+ body,
127
+ keepalive: sendAndForget,
128
+ };
129
+ let timer;
130
+ if (typeof AbortController !== 'undefined') {
131
+ const controller = new AbortController();
132
+ init.signal = controller.signal;
133
+ timer = setTimeout(() => controller.abort('Timeout exceeded'), timeout);
134
+ }
135
+ const originalFetch = unwrapNoibuWrapped(fetch);
136
+ const promise = originalFetch(url, init).then(() => { });
137
+ if (typeof AbortController !== 'undefined') {
138
+ promise.finally(() => clearTimeout(timer));
139
+ }
140
+ return promise;
171
141
  }
172
142
  /**
173
143
  * makes sure the url sent is a valid URL
@@ -202,20 +172,6 @@ function getUserAgent() {
202
172
  return userAgentCache;
203
173
  });
204
174
  }
205
- /**
206
- * isInvalidURLConfig will verify that Collect is being initializes with
207
- * the correct env vars.
208
- */
209
- function isInvalidURLConfig(urls) {
210
- for (let i = 0; i < REQUIRED_DATA_PROCESSING_URLS.length; i += 1) {
211
- const u = REQUIRED_DATA_PROCESSING_URLS[i];
212
- if (!urls[u]) {
213
- noibuLog('urlConfig invalid, reason', u);
214
- return true;
215
- }
216
- }
217
- return false;
218
- }
219
175
  /**
220
176
  * isNoibuJSAlreadyLoaded will verify if there are already other
221
177
  * copies of NoibuJS runnung
@@ -249,9 +205,7 @@ function asString(obj) {
249
205
  */
250
206
  function maskTextInput(text) {
251
207
  // if it has an email or digit(s), we mask the text
252
- return text
253
- .replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING)
254
- .replace(PII_DIGIT_PATTERN, '*');
208
+ return text.replace(PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING).replace(PII_DIGIT_PATTERN, '*');
255
209
  }
256
210
  /**
257
211
  * Checks if the provided object is an instance of the specified type.
@@ -266,20 +220,6 @@ function isInstanceOf(instance, type) {
266
220
  return false;
267
221
  }
268
222
  }
269
- /**
270
- * To grab the video recorder type based on the device we run the app on.
271
- */
272
- function getVideoRecorderType() {
273
- return __awaiter(this, void 0, void 0, function* () {
274
- if (Platform.OS === 'android') {
275
- return 'AndroidNative';
276
- }
277
- if (Platform.OS === 'ios') {
278
- return 'IOSNative';
279
- }
280
- return '';
281
- });
282
- }
283
223
  /** String.trim, but safe */
284
224
  function safeTrim(text) {
285
225
  if (typeof text !== 'string') {
@@ -290,9 +230,6 @@ function safeTrim(text) {
290
230
  /**
291
231
  * Tries to get the stack trace from the given error object and returns it.
292
232
  * If the error object does not have a stack trace, an empty string is returned.
293
- *
294
- * @param {Error} error - The error object from which to retrieve the stack trace.
295
- * @returns {string} The stack trace of the error, if available. Otherwise, an empty string is returned.
296
233
  */
297
234
  function tryGetStackTrace(error) {
298
235
  let result = '';
@@ -306,13 +243,5 @@ function tryGetStackTrace(error) {
306
243
  }
307
244
  return result;
308
245
  }
309
- /**
310
- * Checks whether the given value is a string or an instance of String.
311
- * @param {*} value - The value to be checked.
312
- * @returns {boolean} Returns true if the value is a string or an instance of String, otherwise returns false.
313
- */
314
- function isString(value) {
315
- return typeof value === 'string' || value instanceof String;
316
- }
317
246
 
318
- export { asString, getJSStack, getMaxSubstringAllowed, getUserAgent, getVideoRecorderType, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isString, isValidURL, makeRequest, maskTextInput, processFrames, safeTrim, stringifyJSON, tryGetStackTrace };
247
+ export { asString, getJSStack, getMaxSubstringAllowed, getUserAgent, isInstanceOf, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, maskTextInput, postRequest, processFrames, safeTrim, stringifyJSON, tryGetStackTrace };
package/dist/utils/log.js CHANGED
@@ -4,12 +4,12 @@
4
4
  * checks if was overridden and calls original console function
5
5
  */
6
6
  const getConsoleMethod = (ogProp) => {
7
- // @ts-ignore
7
+ // @ts-expect-error __noibu_original__ is not a standard property
8
8
  return console[ogProp].__noibu_original__ || console[ogProp];
9
9
  };
10
- /**
11
- * log with level = info
12
- */
10
+ /**log with level = info */
13
11
  const noibuLog = (...msgs) => getConsoleMethod('log')('Noibu', ...msgs);
12
+ /**log with level = error */
13
+ const noibuErr = (...msgs) => getConsoleMethod('error')('Noibu', ...msgs);
14
14
 
15
- export { noibuLog };
15
+ export { noibuErr, noibuLog };
@@ -6,16 +6,13 @@
6
6
  * attributeName: the attribute key whose value will be replace
7
7
  * processingFunction: function that accepts the original value
8
8
  * and returns the newValue
9
- * @param {} sourceObject
10
- * @param {} attributeName
11
- * @param {} processingFunction
12
9
  */
13
- const replace = (sourceObject, attributeName, processingFunction) => {
10
+ function replace(sourceObject, attributeName, processingFunction) {
14
11
  if (!(attributeName in sourceObject)) {
15
12
  return;
16
13
  }
17
14
  const originalAttribute = sourceObject[attributeName];
18
- const newValue = processingFunction(originalAttribute);
15
+ const newValue = processingFunction.call(sourceObject, originalAttribute);
19
16
  if (typeof newValue === 'function') {
20
17
  try {
21
18
  newValue.prototype = newValue.prototype || {};
@@ -40,14 +37,19 @@ const replace = (sourceObject, attributeName, processingFunction) => {
40
37
  }
41
38
  // eslint-disable-next-line no-param-reassign
42
39
  sourceObject[attributeName] = newValue;
43
- };
40
+ }
44
41
  /**
45
42
  * unwraps wrapped property, so we can use it without side effects
46
- * @param anything
47
43
  */
48
44
  function unwrapNoibuWrapped(anything) {
49
45
  return anything.__noibu_original__ || anything;
50
46
  }
47
+ /**
48
+ * Checks if the given object is wrapped
49
+ */
50
+ function isNoibuWrapped(anything) {
51
+ return '__noibu_original__' in anything;
52
+ }
51
53
  /**
52
54
  * Checks whether the prototype's property is writeable. If it is not,
53
55
  * checks whether the property can be made writeable. If it can, it is
@@ -55,9 +57,7 @@ function unwrapNoibuWrapped(anything) {
55
57
  * returns Whether the property on the prototype is (or is now) writeable
56
58
  */
57
59
  const propWriteableOrMadeWriteable = (proto, property) => {
58
- if (!proto ||
59
- !proto.hasOwnProperty ||
60
- !Object.prototype.hasOwnProperty.call(proto, property)) {
60
+ if (!proto || !proto.hasOwnProperty || !Object.prototype.hasOwnProperty.call(proto, property)) {
61
61
  return false;
62
62
  }
63
63
  // Getting the properties that this the prototype
@@ -82,7 +82,7 @@ const propWriteableOrMadeWriteable = (proto, property) => {
82
82
  * Iterates object recursively and calls visit function
83
83
  * for each property allowing to override its value
84
84
  * @param {Object} instance An object to iterate through
85
- * @param {Function} visit A callback function that is called for each property
85
+ * @param {Function} visit Target callback function that is called for each property
86
86
  * There are 3 arguments: current object, current property and its value
87
87
  * @param {{depth: number}} limit Use limit config object to set depth of the recursion
88
88
  */
@@ -171,4 +171,4 @@ const safeFromEntries = (entries) => {
171
171
  return obj;
172
172
  };
173
173
 
174
- export { iterateObjectRecursively, propWriteableOrMadeWriteable, replace, safeEntries, safeFromEntries, unwrapNoibuWrapped };
174
+ export { isNoibuWrapped, iterateObjectRecursively, propWriteableOrMadeWriteable, replace, safeEntries, safeFromEntries, unwrapNoibuWrapped };
@@ -1,7 +1,36 @@
1
1
  import { iterateObjectRecursively } from './object.js';
2
- import { HTTP_PII_BLOCKING_PATTERNS, PII_REDACTION_REPLACEMENT_STRING } from '../constants.js';
2
+ import { PII_REDACTION_REPLACEMENT_STRING, PII_EMAIL_PATTERN } from '../constants.js';
3
3
  import { stringifyJSON } from './function.js';
4
4
 
5
+ // Regex patterns for a best-effort attempt at blocking PII in HTTP requests
6
+ const HTTP_PII_BLOCKING_PATTERNS = [
7
+ // Match credit cards [https://www.regular-expressions.info/creditcard.html]
8
+ // Visa
9
+ /\b4\d{12}(?:\d{3})?\b/g,
10
+ // MasterCard
11
+ /\b(?:5[1-5]\d{2}|222[1-9]|22[3-9]\d|2[3-6]\d{2}|27[01]\d|2720)\d{12}\b/g,
12
+ // Amex
13
+ /\b3[47]\d{13}\b/g,
14
+ // Diners Club
15
+ /\b3(?:0[0-5]|[68]\d)\d{11}\b/g,
16
+ // Discover
17
+ /\b6(?:011|5\d{2})\d{12}\b/g,
18
+ // JCB
19
+ /\b(?:2131|1800|35\d{3})\d{11}\b/g,
20
+ // Emails [https://www.regular-expressions.info/email.html]
21
+ PII_EMAIL_PATTERN,
22
+ // US SSN with or without dashes
23
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s12.html]
24
+ /\b(?!000|666)[0-8]\d{2}[-.● ]?(?!00)\d{2}[-.● ]?(?!0000)\d{4}\b/g,
25
+ // Canadian SIN with or without dashes [https://regexpattern.com/social-insurance-number-ca]
26
+ /\b(\d{3}[-.● ]?\d{3}[-.● ]?\d{3})\b/g,
27
+ // International phone numbers
28
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s03.html]
29
+ /\+(?:\d●?){6,14}\d\b/g,
30
+ // US/Canada phone numbers
31
+ // [https://www.oreilly.com/library/view/regular-expressions-cookbook/9781449327453/ch04s02.html]
32
+ /(\b|\+)?(1[-.● ]?)?\(?(\d{3})\)?[-.● ]?(\d{3})[-.● ]?(\d{4})\b/g,
33
+ ];
5
34
  const fuzzyFieldsToRedact = [
6
35
  'password',
7
36
  'address',
@@ -35,8 +64,7 @@ const exactFieldsToRedact = [
35
64
  */
36
65
  function shouldRedact(field) {
37
66
  // check for exact and fuzzy matches
38
- return (exactFieldsToRedact.some(v => field === v) ||
39
- fuzzyFieldsToRedact.some(v => field.indexOf(v) >= 0));
67
+ return exactFieldsToRedact.some(v => field === v) || fuzzyFieldsToRedact.some(v => field.indexOf(v) >= 0);
40
68
  }
41
69
  /**
42
70
  * Try to parse content as a JSON object and
@@ -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 };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noibu-react-native",
3
- "version": "0.2.5",
3
+ "version": "0.2.7",
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.24",
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",