noibu-react-native 0.0.1 → 0.0.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 (38) hide show
  1. package/README.md +9 -7
  2. package/dist/api/clientConfig.js +50 -48
  3. package/dist/api/helpCode.js +3 -3
  4. package/dist/api/inputManager.js +5 -5
  5. package/dist/api/metroplexSocket.js +31 -43
  6. package/dist/api/storedMetrics.js +18 -22
  7. package/dist/api/storedPageVisit.js +27 -29
  8. package/dist/constants.d.ts +2 -2
  9. package/dist/constants.js +7 -48
  10. package/dist/entry/index.d.ts +8 -1
  11. package/dist/entry/index.js +8 -2
  12. package/dist/entry/init.js +6 -5
  13. package/dist/monitors/clickMonitor.js +1 -2
  14. package/dist/monitors/elementMonitor.js +4 -1
  15. package/dist/monitors/errorMonitor.d.ts +25 -0
  16. package/dist/monitors/errorMonitor.js +109 -262
  17. package/dist/monitors/httpDataBundler.js +11 -12
  18. package/dist/monitors/inputMonitor.js +4 -1
  19. package/dist/monitors/locationChangeMonitor.js +4 -16
  20. package/dist/monitors/pageMonitor.js +4 -1
  21. package/dist/monitors/requestMonitor.js +5 -19
  22. package/dist/pageVisit/pageVisit.js +3 -1
  23. package/dist/pageVisit/pageVisitEventError/blacklistedDomains.js +9 -0
  24. package/dist/pageVisit/pageVisitEventError/pageVisitEventError.js +9 -14
  25. package/dist/pageVisit/pageVisitEventHTTP/pageVisitEventHTTP.js +3 -14
  26. package/dist/storage/rnStorageProvider.d.ts +23 -0
  27. package/dist/storage/rnStorageProvider.js +23 -52
  28. package/dist/storage/storage.d.ts +38 -0
  29. package/dist/storage/storage.js +69 -104
  30. package/dist/storage/storageProvider.d.ts +25 -0
  31. package/dist/storage/storageProvider.js +38 -71
  32. package/dist/utils/function.js +80 -53
  33. package/dist/utils/performance.js +0 -7
  34. package/dist/utils/stacktrace-parser.d.ts +9 -0
  35. package/dist/utils/stacktrace-parser.js +156 -0
  36. package/package.json +4 -4
  37. package/dist/storage/localStorageProvider.js +0 -23
  38. package/dist/storage/sessionStorageProvider.js +0 -23
@@ -1,9 +1,20 @@
1
- import * as stackTraceParser from 'stacktrace-parser';
2
1
  import DeviceInfo from 'react-native-device-info';
3
- import { MAX_STRING_LENGTH, MAX_BEACON_PAYLOAD_SIZE, REQUIRED_DATA_PROCESSING_URLS, HTTP_DATA_COLLECTION_FLAG_NAME, HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME, WIN_BLOCKED_SELECTOR_ATT_NAME, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, NOIBUJS_CONFIG, JS_STACK_FRAMES_ATT_NAME, JS_STACK_MESSAGE_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_LINE_ATT_NAME, JS_STACK_COL_ATT_NAME, MAX_FRAMES_IN_ARRAY, JS_STACK_METHOD_ATT_NAME, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
2
+ import { getLocales } from 'react-native-localize';
3
+ import { parseStack } from './stacktrace-parser.js';
4
+ import { MAX_BEACON_PAYLOAD_SIZE, MAX_STRING_LENGTH, REQUIRED_DATA_PROCESSING_URLS, HTTP_DATA_COLLECTION_FLAG_NAME, HTTP_DATA_PAYLOAD_URL_REGEXES_FLAG_NAME, WIN_BLOCKED_SELECTOR_ATT_NAME, PII_EMAIL_PATTERN, PII_REDACTION_REPLACEMENT_STRING, PII_DIGIT_PATTERN, JS_STACK_FRAMES_ATT_NAME, JS_STACK_MESSAGE_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_LINE_ATT_NAME, JS_STACK_COL_ATT_NAME, MAX_FRAMES_IN_ARRAY, NOIBUJS_CONFIG, JS_STACK_METHOD_ATT_NAME, DEFAULT_STACK_FRAME_FIELD_VALUE } from '../constants.js';
5
+ import ClientConfig from '../api/clientConfig.js';
4
6
 
5
7
  /** @module Functions */
6
8
 
9
+ /**
10
+ * Returns a stack trace frame with default filed values
11
+ */
12
+ const getDefaultFrame = () => ({
13
+ [JS_STACK_LINE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
14
+ [JS_STACK_METHOD_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
15
+ [JS_STACK_FILE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
16
+ });
17
+
7
18
  /**
8
19
  *
9
20
  * returns a string that satisfies a max length
@@ -25,61 +36,54 @@ function getMaxSubstringAllowed(
25
36
 
26
37
  /**
27
38
  *
39
+ * todo implement navigation
28
40
  * getProperGlobalUrl gets the proper global url from the window
41
+ * @returns {string}
29
42
  */
30
43
  function getProperGlobalUrl() {
31
- let globalUrl =
32
- (window.location && window.location.href) || 'http://localhost';
33
- // first we try to get the location
34
- // if it does not follow the http protocol,
35
- // then we check the parent frame and if that
36
- // fails then we return what we have without
37
- // trying anything else
38
- if (
39
- (
40
- (window.location && window.location.href) ||
41
- 'http://localhost'
42
- ).startsWith('http')
43
- ) {
44
- globalUrl = (window.location && window.location.href) || 'http://localhost';
45
- } else if (
46
- window.parent &&
47
- window.parent.location &&
48
- window.parent.location.href.startsWith('http')
49
- ) {
50
- globalUrl = window.parent.location.href;
51
- }
52
-
53
- return getMaxSubstringAllowed(globalUrl);
44
+ const globalUrl = new URL('https://localhost');
45
+ globalUrl.hostname = ClientConfig.getInstance().customerDomain;
46
+ return getMaxSubstringAllowed(globalUrl.toString());
54
47
  }
55
48
 
56
49
  /**
57
50
  * Processes the raw stack frames and creates a readable stack in a safe manner
58
- * @param rawFrames
51
+ * @param {StackFrame[]} rawFrames
59
52
  */
60
53
  function processFrames(rawFrames) {
61
54
  return rawFrames.map(frame => {
62
- const processedFrame = {
63
- [JS_STACK_LINE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
64
- [JS_STACK_METHOD_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
65
- [JS_STACK_FILE_ATT_NAME]: DEFAULT_STACK_FRAME_FIELD_VALUE,
66
- };
55
+ const processedFrame = getDefaultFrame();
67
56
 
68
- // stringification
69
- if (frame.lineNumber && frame.lineNumber !== '<unknown>') {
70
- processedFrame[JS_STACK_LINE_ATT_NAME] = String(frame.lineNumber);
57
+ if (frame[JS_STACK_LINE_ATT_NAME]) {
58
+ if (Number.isInteger(frame[JS_STACK_LINE_ATT_NAME])) {
59
+ processedFrame[JS_STACK_LINE_ATT_NAME] = String(
60
+ frame[JS_STACK_LINE_ATT_NAME],
61
+ );
62
+ }
71
63
  }
72
64
 
73
- if (frame.methodName && frame.methodName !== '<unknown>') {
74
- processedFrame[JS_STACK_METHOD_ATT_NAME] = String(frame.methodName);
65
+ if (
66
+ frame[JS_STACK_METHOD_ATT_NAME] &&
67
+ frame[JS_STACK_METHOD_ATT_NAME] !== '<unknown>'
68
+ ) {
69
+ processedFrame[JS_STACK_METHOD_ATT_NAME] = String(
70
+ frame[JS_STACK_METHOD_ATT_NAME],
71
+ );
75
72
  }
76
73
 
77
- if (frame.file && frame.file !== '<unknown>') {
78
- processedFrame[JS_STACK_FILE_ATT_NAME] = String(frame.file);
74
+ if (
75
+ frame[JS_STACK_FILE_ATT_NAME] &&
76
+ frame[JS_STACK_FILE_ATT_NAME] !== '<unknown>'
77
+ ) {
78
+ processedFrame[JS_STACK_FILE_ATT_NAME] = String(
79
+ frame[JS_STACK_FILE_ATT_NAME],
80
+ );
79
81
  }
80
82
 
81
- if (frame.column && typeof frame.column === 'number') {
82
- processedFrame[JS_STACK_COL_ATT_NAME] = frame.column;
83
+ if (frame[JS_STACK_COL_ATT_NAME]) {
84
+ if (Number.isInteger(frame[JS_STACK_COL_ATT_NAME])) {
85
+ processedFrame[JS_STACK_COL_ATT_NAME] = frame[JS_STACK_COL_ATT_NAME];
86
+ }
83
87
  }
84
88
 
85
89
  return processedFrame;
@@ -120,7 +124,7 @@ function getJSStack(errObj) {
120
124
  frames[0][JS_STACK_COL_ATT_NAME] = errObj.columnNumber;
121
125
  }
122
126
  } else {
123
- frames = processFrames(stackTraceParser.parse(errObj.stack));
127
+ frames = processFrames(parseStack(errObj.stack));
124
128
  }
125
129
 
126
130
  if (frames.length >= MAX_FRAMES_IN_ARRAY) {
@@ -134,6 +138,18 @@ function getJSStack(errObj) {
134
138
  };
135
139
  }
136
140
 
141
+ /**
142
+ * @param {string} possiblyStacktrace
143
+ * @returns {boolean}
144
+ */
145
+ function isStackTrace(possiblyStacktrace) {
146
+ try {
147
+ return parseStack(possiblyStacktrace).length > 0;
148
+ } catch (e) {
149
+ return false;
150
+ }
151
+ }
152
+
137
153
  /**
138
154
  * safely stringifies an object
139
155
  * @param jsonObject
@@ -166,7 +182,7 @@ function stringifyJSON(jsonObject) {
166
182
  * @param timeout
167
183
  * @param sendAndForget
168
184
  */
169
- function makeRequest(
185
+ async function makeRequest(
170
186
  method,
171
187
  url,
172
188
  data,
@@ -174,12 +190,20 @@ function makeRequest(
174
190
  timeout,
175
191
  sendAndForget,
176
192
  ) {
177
- // a send and forget request is made by using the beacon API (fetch + keepalive)
193
+ const ua = Object.keys(headers).findLast(
194
+ k => k.toLowerCase() === 'user-agent',
195
+ );
196
+ const headersWithUa = { ...headers };
197
+ if (!headers[ua]) {
198
+ headersWithUa['User-Agent'] = await getUserAgent();
199
+ }
200
+
201
+ // a send-and-forget request is made by using the beacon API (fetch + keepalive)
178
202
  if (sendAndForget) {
179
203
  const stringData = stringifyJSON(data);
180
204
  const currentPayloadSize = new Blob([stringData]).size;
181
205
  // if we have a large object or fetch is not available, we skip sending the message
182
- if (!window.fetch || currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
206
+ if (!global.fetch || currentPayloadSize > MAX_BEACON_PAYLOAD_SIZE) {
183
207
  return new Promise(resolve => {
184
208
  resolve();
185
209
  });
@@ -187,7 +211,7 @@ function makeRequest(
187
211
 
188
212
  return fetch(url, {
189
213
  method: 'POST',
190
- headers,
214
+ headers: headersWithUa,
191
215
  body: stringifyJSON(data),
192
216
  // keep alive outlives the current page, its the same as beacon
193
217
  keepalive: true,
@@ -195,10 +219,10 @@ function makeRequest(
195
219
  }
196
220
 
197
221
  return new Promise((resolve, reject) => {
198
- const xhr = new XMLHttpRequest();
222
+ const xhr = new global.XMLHttpRequest();
199
223
  xhr.open(method, url);
200
224
  xhr.timeout = timeout;
201
- Object.keys(headers).forEach(header => {
225
+ Object.keys(headersWithUa).forEach(header => {
202
226
  xhr.setRequestHeader(header, headers[header]);
203
227
  });
204
228
 
@@ -302,7 +326,7 @@ async function getUserAgent() {
302
326
  /**
303
327
  * isInvalidURLConfig will verify that Collect is being initializes with
304
328
  * the correct env vars.
305
- * @param {} urlConfig
329
+ * @param {Noibu.UrlConfig} urlConfig
306
330
  */
307
331
  function isInvalidURLConfig(urlConfig) {
308
332
  for (let i = 0; i < REQUIRED_DATA_PROCESSING_URLS.length; i += 1) {
@@ -359,9 +383,8 @@ function maskTextInput(text) {
359
383
  * @param {} realOnURL
360
384
  */
361
385
  function getOnURL(realOnURL) {
362
- let onURL = getMaxSubstringAllowed(
363
- (window.location && window.location.href) || 'http://localhost',
364
- );
386
+ let onURL = getProperGlobalUrl();
387
+
365
388
  if (realOnURL && realOnURL.trim() !== '' && realOnURL !== 'undefined') {
366
389
  onURL = asString(getMaxSubstringAllowed(realOnURL));
367
390
  }
@@ -371,7 +394,11 @@ function getOnURL(realOnURL) {
371
394
 
372
395
  /** gets the user language from the browser */
373
396
  function getUserLanguage() {
374
- const lang = window.navigator.userLanguage || window.navigator.language;
397
+ const locales = getLocales();
398
+ if (!locales.length) {
399
+ return null;
400
+ }
401
+ const lang = locales[0].languageCode;
375
402
 
376
403
  if (lang === '' || !lang) {
377
404
  return null;
@@ -395,4 +422,4 @@ function isInstanceOf(instance, type) {
395
422
  }
396
423
  }
397
424
 
398
- export { asString, checkHttpDataCollectionEnabled, getBlockedCSSForCurrentDomain, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getProperGlobalUrl, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
425
+ export { asString, checkHttpDataCollectionEnabled, getBlockedCSSForCurrentDomain, getHttpPayloadAllowedURLs, getJSStack, getMaxSubstringAllowed, getOnURL, getProperGlobalUrl, getUserAgent, getUserLanguage, isInstanceOf, isInvalidURLConfig, isNoibuJSAlreadyLoaded, isStackTrace, isValidURL, makeRequest, maskTextInput, processFrames, stringifyJSON };
@@ -8,13 +8,6 @@ import { timestampWrapper } from './date.js';
8
8
  * we return Date.now() instead.
9
9
  */
10
10
  function safePerformanceNow() {
11
- if (window.performance && window.performance.now) {
12
- // There is a 70% hit with using this
13
- // https://jsperf.com/perf-vs-date/1
14
- // performance.now is for relative time measurement
15
- // cannot be used instead of Date.getTime() on it's own
16
- return window.performance.now();
17
- }
18
11
  return timestampWrapper(Date.now());
19
12
  }
20
13
 
@@ -0,0 +1,9 @@
1
+ import { JS_STACK_COL_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_LINE_ATT_NAME, JS_STACK_METHOD_ATT_NAME } from '../constants';
2
+ declare interface StackFrame {
3
+ [JS_STACK_FILE_ATT_NAME]: string;
4
+ [JS_STACK_LINE_ATT_NAME]?: number;
5
+ [JS_STACK_COL_ATT_NAME]?: number;
6
+ [JS_STACK_METHOD_ATT_NAME]: string;
7
+ }
8
+ export declare function parseStack(stackString: string): StackFrame[];
9
+ export {};
@@ -0,0 +1,156 @@
1
+ import { MAX_FRAMES_IN_ARRAY, MAX_STRING_LENGTH, JS_STACK_LINE_ATT_NAME, JS_STACK_COL_ATT_NAME, JS_STACK_FILE_ATT_NAME, JS_STACK_METHOD_ATT_NAME } from '../constants.js';
2
+
3
+ /* eslint-disable require-jsdoc,prefer-destructuring,camelcase */
4
+ // This is a loose copy of ravenjs code
5
+ // Copyright (c) 2013 Onur Can Cakmak onur.cakmak@gmail.com and all TraceKit contributors.
6
+ //
7
+ // Permission is hereby granted, free of charge, to any person obtaining a copy of this
8
+ // software and associated documentation files(the 'Software'), to deal in the Software
9
+ // without restriction, including without limitation the rights to use, copy, modify,
10
+ // merge, publish, distribute, sublicense, and / or sell copies of the Software, and to
11
+ // permit persons to whom the Software is furnished to do so, subject to the following
12
+ // conditions:
13
+ //
14
+ // The above copyright notice and this permission notice shall be included in all copies
15
+ // or substantial portions of the Software.
16
+ //
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
19
+ // PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
20
+ // HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF
21
+ // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
22
+ // OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
+ // global reference to slice
24
+ const UNKNOWN_FUNCTION = '<unknown>';
25
+ /**
26
+ * Safari web extensions, starting version unknown, can produce "frames-only" stacktraces.
27
+ * What it means, is that instead of format like:
28
+ *
29
+ * Error: wat
30
+ * at function@url:row:col
31
+ * at function@url:row:col
32
+ * at function@url:row:col
33
+ *
34
+ * it produces something like:
35
+ *
36
+ * function@url:row:col
37
+ * function@url:row:col
38
+ * function@url:row:col
39
+ *
40
+ * Because of that, it won't be captured by `chrome` RegExp and will fall into `Gecko` branch.
41
+ * This function is extracted so that we can use it in both places without duplicating the logic.
42
+ * Unfortunately "just" changing RegExp is too complicated now and making it pass all tests
43
+ * and fix this case seems like an impossible, or at least way too time-consuming task.
44
+ */
45
+ const extractSafariExtensionDetails = (func, filename) => {
46
+ const isSafariExtension = func.indexOf('safari-extension') !== -1;
47
+ const isSafariWebExtension = func.indexOf('safari-web-extension') !== -1;
48
+ return isSafariExtension || isSafariWebExtension
49
+ ? [
50
+ func.indexOf('@') !== -1 ? func.split('@')[0] : UNKNOWN_FUNCTION,
51
+ isSafariExtension
52
+ ? `safari-extension:${filename}`
53
+ : `safari-web-extension:${filename}`,
54
+ ]
55
+ : [func, filename];
56
+ };
57
+ function createFrame(filename, func, lineno, colno) {
58
+ const frame = {
59
+ [JS_STACK_FILE_ATT_NAME]: filename,
60
+ [JS_STACK_METHOD_ATT_NAME]: func,
61
+ };
62
+ if (lineno !== undefined) {
63
+ frame[JS_STACK_LINE_ATT_NAME] = lineno;
64
+ }
65
+ if (colno !== undefined) {
66
+ frame[JS_STACK_COL_ATT_NAME] = colno;
67
+ }
68
+ return frame;
69
+ }
70
+ // 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+))\)/;
73
+ const chrome = (line) => {
74
+ const parts = chromeRegex.exec(line);
75
+ if (parts) {
76
+ const isEval = parts[2] && parts[2].indexOf('eval') === 0; // start of line
77
+ if (isEval) {
78
+ const subMatch = chromeEvalRegex.exec(parts[2]);
79
+ if (subMatch) {
80
+ // throw out eval line/column and use top-most line/column number
81
+ parts[2] = subMatch[1]; // url
82
+ parts[3] = subMatch[2]; // line
83
+ parts[4] = subMatch[3]; // column
84
+ }
85
+ }
86
+ const [func, filename] = extractSafariExtensionDetails(parts[1] || UNKNOWN_FUNCTION, parts[2]);
87
+ return createFrame(filename, func, parts[3] ? +parts[3] : undefined, parts[4] ? +parts[4] : undefined);
88
+ }
89
+ return undefined;
90
+ };
91
+ const geckoREgex = /^\s*(.*?)(?:\((.*?)\))?(?:^|@)?((?:[-a-z]+)?:\/.*?|\[native code\]|[^@]*(?:bundle|\d+\.js)|\/[\w\-. /=]+)(?::(\d+))?(?::(\d+))?\s*$/i;
92
+ const geckoEvalRegex = /(\S+) line (\d+)(?: > eval line \d+)* > eval/i;
93
+ const gecko = (line) => {
94
+ const parts = geckoREgex.exec(line);
95
+ if (parts) {
96
+ const isEval = parts[3] && parts[3].indexOf(' > eval') > -1;
97
+ if (isEval) {
98
+ const subMatch = geckoEvalRegex.exec(parts[3]);
99
+ if (subMatch) {
100
+ // throw out eval line/column and use top-most line number
101
+ parts[1] = parts[1] || 'eval';
102
+ parts[3] = subMatch[1];
103
+ parts[4] = subMatch[2];
104
+ parts[5] = ''; // no column when eval
105
+ }
106
+ }
107
+ let filename = parts[3];
108
+ let func = parts[1] || UNKNOWN_FUNCTION;
109
+ [func, filename] = extractSafariExtensionDetails(func, filename);
110
+ return createFrame(filename, func, parts[4] ? +parts[4] : undefined, parts[5] ? +parts[5] : undefined);
111
+ }
112
+ return undefined;
113
+ };
114
+ const winjsRegex = /^\s*at (?:((?:\[object object\])?.+) )?\(?((?:[-a-z]+):.*?):(\d+)(?::(\d+))?\)?\s*$/i;
115
+ const winjs = (line) => {
116
+ const parts = winjsRegex.exec(line);
117
+ return parts
118
+ ? createFrame(parts[2], parts[1] || UNKNOWN_FUNCTION, +parts[3], parts[4] ? +parts[4] : undefined)
119
+ : undefined;
120
+ };
121
+ const opera10Regex = / line (\d+).*script (?:in )?(\S+)(?:: in function (\S+))?$/i;
122
+ const opera10 = (line) => {
123
+ const parts = opera10Regex.exec(line);
124
+ return parts
125
+ ? createFrame(parts[2], parts[3] || UNKNOWN_FUNCTION, +parts[1])
126
+ : undefined;
127
+ };
128
+ const opera11Regex = / line (\d+), column (\d+)\s*(?:in (?:<anonymous function: ([^>]+)>|([^)]+))\(.*\))? in (.*):\s*$/i;
129
+ const opera11 = (line) => {
130
+ const parts = opera11Regex.exec(line);
131
+ return parts
132
+ ? createFrame(parts[5], parts[3] || parts[4] || UNKNOWN_FUNCTION, +parts[1], +parts[2])
133
+ : undefined;
134
+ };
135
+ function parseStack(stackString) {
136
+ const lines = stackString.split('\n');
137
+ if (lines.length > MAX_FRAMES_IN_ARRAY) {
138
+ return [];
139
+ }
140
+ return lines.reduce((stack, line) => {
141
+ if (line.length > MAX_STRING_LENGTH) {
142
+ return stack;
143
+ }
144
+ const parseResult = gecko(line) ||
145
+ chrome(line) ||
146
+ winjs(line) ||
147
+ opera11(line) ||
148
+ opera10(line);
149
+ if (parseResult) {
150
+ stack.push(parseResult);
151
+ }
152
+ return stack;
153
+ }, []);
154
+ }
155
+
156
+ export { parseStack };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "noibu-react-native",
3
- "version": "0.0.1",
3
+ "version": "0.0.3",
4
4
  "description": "React-Native SDK for NoibuJS to collect errors in React-Native applications",
5
5
  "main": "dist/entry/index.js",
6
6
  "types": "dist/entry/index.d.ts",
@@ -10,7 +10,6 @@
10
10
  ],
11
11
  "author": "Noibu Inc",
12
12
  "license": "ISC",
13
-
14
13
  "scripts": {
15
14
  "clean": "rimraf ./dist/*",
16
15
  "build": "node ./build.js",
@@ -21,13 +20,14 @@
21
20
  "lint_output": "eslint src -c .eslintrc.json --ext js,ts,jsx,tsx -f json > eslint_report.json",
22
21
  "codecov": "codecov"
23
22
  },
24
- "peerDependencies": {
23
+ "dependencies": {
25
24
  "react": ">=16.11.0",
26
25
  "react-native": ">=0.63.0",
26
+ "@react-native-async-storage/async-storage": "^1.19.0",
27
27
  "react-native-device-info": "^10.6.0",
28
28
  "react-native-url-polyfill": "^1.3.0",
29
29
  "react-native-uuid": "^2.0.1",
30
- "stacktrace-parser": "^0.1.10"
30
+ "react-native-localize": "^3.0.1"
31
31
  },
32
32
  "devDependencies": {
33
33
  "@rollup/plugin-commonjs": "^25.0.0",
@@ -1,23 +0,0 @@
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 };
@@ -1,23 +0,0 @@
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 };