react-native-qalink 0.1.1 → 0.1.2
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.
- package/dist/interceptors/runtime.js +60 -118
- package/package.json +4 -17
|
@@ -1,141 +1,83 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.setupRuntimeErrorHandler =
|
|
3
|
+
exports.setupRuntimeErrorHandler = void 0;
|
|
4
4
|
const session_1 = require("../core/session");
|
|
5
|
-
|
|
6
|
-
* Captura los errores del runtime de React Native:
|
|
7
|
-
*
|
|
8
|
-
* 1. ErrorUtils.setGlobalHandler → captura la PANTALLA ROJA (errores fatales)
|
|
9
|
-
* Son los errores que crashean la app completamente. React Native los
|
|
10
|
-
* intercepta antes de mostrar el red screen y nosotros nos enganchamos ahí.
|
|
11
|
-
*
|
|
12
|
-
* 2. LogBox.ignoreLogs / console.error → captura las CAJAS AMARILLAS (warnings)
|
|
13
|
-
* Son los warnings que RN muestra en desarrollo. Se generan a través de
|
|
14
|
-
* console.error internamente, así que el interceptor de consola los captura,
|
|
15
|
-
* pero aquí los marcamos también con el handler de RN para mayor precisión.
|
|
16
|
-
*
|
|
17
|
-
* 3. NativeModules errors → errores del bridge JS<->Native
|
|
18
|
-
* Ocurren cuando un módulo nativo falla o no está disponible.
|
|
19
|
-
*/
|
|
5
|
+
|
|
20
6
|
function classifyRuntimeError(message, isFatal) {
|
|
21
|
-
if (isFatal)
|
|
22
|
-
|
|
23
|
-
if (message.includes('
|
|
24
|
-
|
|
25
|
-
message.includes('TurboModule') ||
|
|
26
|
-
message.includes('requireNativeComponent')) {
|
|
27
|
-
return 'native_module';
|
|
28
|
-
}
|
|
29
|
-
if (message.includes('bridge') ||
|
|
30
|
-
message.includes('JSContext') ||
|
|
31
|
-
message.includes('RCTBridge') ||
|
|
32
|
-
message.includes('JavaScriptCore')) {
|
|
33
|
-
return 'bridge';
|
|
34
|
-
}
|
|
35
|
-
if (message.startsWith('Warning:') || message.includes('deprecated')) {
|
|
36
|
-
return 'yellow_box';
|
|
37
|
-
}
|
|
7
|
+
if (isFatal) return 'red_screen';
|
|
8
|
+
if (message.includes('NativeModule') || message.includes('Native module') || message.includes('TurboModule') || message.includes('requireNativeComponent')) return 'native_module';
|
|
9
|
+
if (message.includes('bridge') || message.includes('JSContext') || message.includes('RCTBridge') || message.includes('JavaScriptCore')) return 'bridge';
|
|
10
|
+
if (message.startsWith('Warning:') || message.includes('deprecated')) return 'yellow_box';
|
|
38
11
|
return 'unknown';
|
|
39
12
|
}
|
|
13
|
+
|
|
40
14
|
function setupRuntimeErrorHandler(transport, config, getCurrentScreen) {
|
|
41
|
-
var _a, _b;
|
|
42
15
|
const cleanups = [];
|
|
43
|
-
|
|
44
|
-
//
|
|
45
|
-
// la app crashee y muestre el red screen.
|
|
16
|
+
|
|
17
|
+
// ── 1. Handler global de errores fatales ──────────────────────────────────
|
|
46
18
|
try {
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
catch
|
|
75
|
-
|
|
76
|
-
}
|
|
19
|
+
if (typeof ErrorUtils !== 'undefined' && ErrorUtils.getGlobalHandler) {
|
|
20
|
+
const originalGlobalHandler = ErrorUtils.getGlobalHandler();
|
|
21
|
+
ErrorUtils.setGlobalHandler((error, isFatal) => {
|
|
22
|
+
try {
|
|
23
|
+
const fatal = isFatal ?? false;
|
|
24
|
+
const category = classifyRuntimeError(error?.message ?? '', fatal);
|
|
25
|
+
const event = {
|
|
26
|
+
id: (0, session_1.generateId)(),
|
|
27
|
+
type: 'runtime_error',
|
|
28
|
+
level: fatal ? 'fatal' : 'error',
|
|
29
|
+
message: error?.message ?? String(error),
|
|
30
|
+
stack: error?.stack,
|
|
31
|
+
isFatal: fatal,
|
|
32
|
+
category,
|
|
33
|
+
timestamp: Date.now(),
|
|
34
|
+
screen: getCurrentScreen(),
|
|
35
|
+
sessionId: (0, session_1.getSessionId)(),
|
|
36
|
+
};
|
|
37
|
+
transport.send(event);
|
|
38
|
+
config.onEvent?.(event);
|
|
39
|
+
} catch {}
|
|
40
|
+
originalGlobalHandler(error, isFatal);
|
|
41
|
+
});
|
|
42
|
+
cleanups.push(() => {
|
|
43
|
+
try { ErrorUtils.setGlobalHandler(originalGlobalHandler); } catch {}
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
} catch {}
|
|
47
|
+
|
|
77
48
|
// ── 2. Promesas rechazadas no manejadas ───────────────────────────────────
|
|
78
|
-
// Cuando un Promise.reject() no tiene .catch(), RN lo captura aquí.
|
|
79
|
-
// Ejemplo típico: llamada a API sin try/catch
|
|
80
|
-
const unhandledRejectionHandler = (event) => {
|
|
81
|
-
var _a, _b, _c;
|
|
82
|
-
const error = event === null || event === void 0 ? void 0 : event.reason;
|
|
83
|
-
const message = (_b = (_a = error === null || error === void 0 ? void 0 : error.message) !== null && _a !== void 0 ? _a : String(error)) !== null && _b !== void 0 ? _b : 'Unhandled Promise Rejection';
|
|
84
|
-
const runtimeEvent = {
|
|
85
|
-
id: (0, session_1.generateId)(),
|
|
86
|
-
type: 'runtime_error',
|
|
87
|
-
level: 'error',
|
|
88
|
-
message,
|
|
89
|
-
stack: error === null || error === void 0 ? void 0 : error.stack,
|
|
90
|
-
isFatal: false,
|
|
91
|
-
category: 'unknown',
|
|
92
|
-
timestamp: Date.now(),
|
|
93
|
-
screen: getCurrentScreen(),
|
|
94
|
-
sessionId: (0, session_1.getSessionId)(),
|
|
95
|
-
};
|
|
96
|
-
transport.send(runtimeEvent);
|
|
97
|
-
(_c = config.onEvent) === null || _c === void 0 ? void 0 : _c.call(config, runtimeEvent);
|
|
98
|
-
};
|
|
99
|
-
if (typeof global !== 'undefined') {
|
|
100
|
-
(_b = (_a = global).addEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'unhandledrejection', unhandledRejectionHandler);
|
|
101
|
-
cleanups.push(() => {
|
|
102
|
-
var _a, _b;
|
|
103
|
-
(_b = (_a = global).removeEventListener) === null || _b === void 0 ? void 0 : _b.call(_a, 'unhandledrejection', unhandledRejectionHandler);
|
|
104
|
-
});
|
|
105
|
-
}
|
|
106
|
-
// ── 3. Warnings de LogBox (cajas amarillas) ───────────────────────────────
|
|
107
|
-
// En RN >= 0.64 los warnings se manejan via LogBox.
|
|
108
|
-
// Nos enganchamos al método interno que registra los warnings.
|
|
109
49
|
try {
|
|
110
|
-
const
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
const event = {
|
|
50
|
+
const unhandledRejectionHandler = (event) => {
|
|
51
|
+
try {
|
|
52
|
+
const error = event?.reason;
|
|
53
|
+
const message = error?.message ?? String(error) ?? 'Unhandled Promise Rejection';
|
|
54
|
+
const runtimeEvent = {
|
|
116
55
|
id: (0, session_1.generateId)(),
|
|
117
56
|
type: 'runtime_error',
|
|
118
|
-
level: '
|
|
57
|
+
level: 'error',
|
|
119
58
|
message,
|
|
120
|
-
stack,
|
|
59
|
+
stack: error?.stack,
|
|
121
60
|
isFatal: false,
|
|
122
|
-
category: '
|
|
61
|
+
category: 'unknown',
|
|
123
62
|
timestamp: Date.now(),
|
|
124
63
|
screen: getCurrentScreen(),
|
|
125
64
|
sessionId: (0, session_1.getSessionId)(),
|
|
126
65
|
};
|
|
127
|
-
transport.send(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
66
|
+
transport.send(runtimeEvent);
|
|
67
|
+
config.onEvent?.(runtimeEvent);
|
|
68
|
+
} catch {}
|
|
69
|
+
};
|
|
70
|
+
if (typeof global !== 'undefined' && global.addEventListener) {
|
|
71
|
+
global.addEventListener('unhandledrejection', unhandledRejectionHandler);
|
|
131
72
|
cleanups.push(() => {
|
|
132
|
-
|
|
73
|
+
try { global.removeEventListener('unhandledrejection', unhandledRejectionHandler); } catch {}
|
|
133
74
|
});
|
|
134
75
|
}
|
|
135
|
-
}
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
76
|
+
} catch {}
|
|
77
|
+
|
|
78
|
+
// NOTE: LogBox.__warn removido — causa crash en bridge nativo C++
|
|
79
|
+
// Los warnings ya son capturados por el interceptor de console.warn
|
|
80
|
+
|
|
81
|
+
return () => cleanups.forEach(fn => { try { fn(); } catch {} });
|
|
140
82
|
}
|
|
141
|
-
|
|
83
|
+
exports.setupRuntimeErrorHandler = setupRuntimeErrorHandler;
|
package/package.json
CHANGED
|
@@ -1,29 +1,16 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-qalink",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.2",
|
|
4
4
|
"description": "Real-time error capture SDK for React Native — helps QA teams identify if bugs are frontend or backend",
|
|
5
5
|
"main": "dist/index.js",
|
|
6
6
|
"types": "dist/index.d.ts",
|
|
7
|
-
"files": [
|
|
8
|
-
|
|
9
|
-
"README.md"
|
|
10
|
-
],
|
|
11
|
-
"keywords": [
|
|
12
|
-
"react-native",
|
|
13
|
-
"debugging",
|
|
14
|
-
"qa",
|
|
15
|
-
"error-tracking",
|
|
16
|
-
"network-interceptor"
|
|
17
|
-
],
|
|
7
|
+
"files": ["dist", "README.md"],
|
|
8
|
+
"keywords": ["react-native", "debugging", "qa", "error-tracking", "network-interceptor"],
|
|
18
9
|
"peerDependencies": {
|
|
19
10
|
"react-native": ">=0.70.0",
|
|
20
11
|
"axios": ">=1.0.0"
|
|
21
12
|
},
|
|
22
|
-
"peerDependenciesMeta": {
|
|
23
|
-
"axios": {
|
|
24
|
-
"optional": true
|
|
25
|
-
}
|
|
26
|
-
},
|
|
13
|
+
"peerDependenciesMeta": { "axios": { "optional": true } },
|
|
27
14
|
"devDependencies": {
|
|
28
15
|
"typescript": "^5.0.0",
|
|
29
16
|
"@types/react-native": "^0.72.0"
|