react-native-inapp-inspector 1.0.2 → 1.0.4
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/commonjs/components/TouchableScale.d.ts +1 -1
- package/dist/commonjs/customHooks/consoleLogger.js +2 -2
- package/dist/commonjs/customHooks/networkLogger.js +5 -5
- package/dist/commonjs/index.js +14 -2
- package/dist/esm/components/TouchableScale.d.ts +1 -1
- package/dist/esm/customHooks/consoleLogger.js +2 -2
- package/dist/esm/customHooks/networkLogger.js +5 -5
- package/dist/esm/index.js +15 -3
- package/example/App.tsx +117 -32
- package/example/ios/Podfile.lock +2277 -0
- package/example/ios/example/Info.plist +2 -1
- package/example/ios/example.xcodeproj/project.pbxproj +21 -0
- package/example/ios/example.xcworkspace/contents.xcworkspacedata +10 -0
- package/example/metro.config.js +35 -1
- package/example/package-lock.json +124 -1
- package/example/package.json +3 -1
- package/example/polyfill.js +13 -0
- package/package.json +1 -1
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
declare const TouchableScale: ({ onPress, style, children, hitSlop, disabled, }: {
|
|
3
3
|
onPress?: () => void;
|
|
4
4
|
style?: any;
|
|
5
|
-
children
|
|
5
|
+
children?: React.ReactNode;
|
|
6
6
|
hitSlop?: any;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
}) => React.JSX.Element;
|
|
@@ -108,7 +108,7 @@ exports.clearConsoleLogs = clearConsoleLogs;
|
|
|
108
108
|
const getConsoleLogs = () => [...logs];
|
|
109
109
|
exports.getConsoleLogs = getConsoleLogs;
|
|
110
110
|
const setupConsoleLogger = () => {
|
|
111
|
-
if (
|
|
111
|
+
if (globalThis.__CONSOLE_LOGGER_INITIALIZED__)
|
|
112
112
|
return;
|
|
113
113
|
const originalConsole = {
|
|
114
114
|
log: console.log,
|
|
@@ -136,6 +136,6 @@ const setupConsoleLogger = () => {
|
|
|
136
136
|
addLog('error', args, 'error');
|
|
137
137
|
originalConsole.error(...args);
|
|
138
138
|
};
|
|
139
|
-
|
|
139
|
+
globalThis.__CONSOLE_LOGGER_INITIALIZED__ = true;
|
|
140
140
|
};
|
|
141
141
|
exports.setupConsoleLogger = setupConsoleLogger;
|
|
@@ -117,12 +117,12 @@ const addOrUpdateLog = (log) => {
|
|
|
117
117
|
};
|
|
118
118
|
// ─── Setup ────────────────────────────────────────────────────────────────────
|
|
119
119
|
const setupNetworkLogger = () => {
|
|
120
|
-
if (
|
|
120
|
+
if (globalThis.__NETWORK_LOGGER_INITIALIZED__)
|
|
121
121
|
return;
|
|
122
|
-
|
|
123
|
-
const originalFetch =
|
|
122
|
+
globalThis.__NETWORK_LOGGER__ = addOrUpdateLog;
|
|
123
|
+
const originalFetch = globalThis.fetch;
|
|
124
124
|
if (originalFetch) {
|
|
125
|
-
|
|
125
|
+
globalThis.fetch = async (url, options = {}) => {
|
|
126
126
|
const method = (options?.method || 'GET').toUpperCase();
|
|
127
127
|
if (!ALLOWED_METHODS.includes(method))
|
|
128
128
|
return originalFetch(url, options);
|
|
@@ -192,7 +192,7 @@ const setupNetworkLogger = () => {
|
|
|
192
192
|
}
|
|
193
193
|
};
|
|
194
194
|
}
|
|
195
|
-
|
|
195
|
+
globalThis.__NETWORK_LOGGER_INITIALIZED__ = true;
|
|
196
196
|
};
|
|
197
197
|
exports.setupNetworkLogger = setupNetworkLogger;
|
|
198
198
|
// ─── Axios interceptor helper ─────────────────────────────────────────────────
|
package/dist/commonjs/index.js
CHANGED
|
@@ -79,6 +79,13 @@ const AnalyticsDetail_1 = __importDefault(require("./components/AnalyticsDetail"
|
|
|
79
79
|
// WebView
|
|
80
80
|
const webViewLogger_1 = require("./customHooks/webViewLogger");
|
|
81
81
|
const constants_1 = require("./constants");
|
|
82
|
+
const NavigationTracker = ({ onStateChange }) => {
|
|
83
|
+
const navState = (0, native_1.useNavigationState)(state => state);
|
|
84
|
+
(0, react_1.useEffect)(() => {
|
|
85
|
+
onStateChange(navState);
|
|
86
|
+
}, [navState, onStateChange]);
|
|
87
|
+
return null;
|
|
88
|
+
};
|
|
82
89
|
const NetworkInspector = () => {
|
|
83
90
|
const [logs, setLogs] = (0, react_1.useState)([]);
|
|
84
91
|
const [visible, setVisible] = (0, react_1.useState)(false);
|
|
@@ -145,13 +152,17 @@ const NetworkInspector = () => {
|
|
|
145
152
|
const [topEventsExpanded, setTopEventsExpanded] = (0, react_1.useState)(true);
|
|
146
153
|
const [newEventIds, setNewEventIds] = (0, react_1.useState)(new Set());
|
|
147
154
|
const prevEventIdsRef = (0, react_1.useRef)(new Set());
|
|
148
|
-
const navState = (0,
|
|
155
|
+
const [navState, setNavState] = (0, react_1.useState)(null);
|
|
156
|
+
const navigationContext = react_1.default.useContext(native_1.NavigationContext);
|
|
157
|
+
const hasNavigationContext = navigationContext !== undefined;
|
|
149
158
|
const currentRouteRef = (0, react_1.useRef)({
|
|
150
159
|
path: 'Navigators',
|
|
151
160
|
params: null,
|
|
152
161
|
});
|
|
153
162
|
(0, react_1.useEffect)(() => {
|
|
154
|
-
|
|
163
|
+
if (navState) {
|
|
164
|
+
currentRouteRef.current = (0, helpers_1.getNavigationInfo)(navState);
|
|
165
|
+
}
|
|
155
166
|
}, [navState]);
|
|
156
167
|
const logRouteMapRef = (0, react_1.useRef)(new Map());
|
|
157
168
|
const prevLogIdsRef = (0, react_1.useRef)(new Set());
|
|
@@ -804,6 +815,7 @@ const NetworkInspector = () => {
|
|
|
804
815
|
toggleSectionCollapse,
|
|
805
816
|
]);
|
|
806
817
|
return (<>
|
|
818
|
+
{hasNavigationContext && (<NavigationTracker onStateChange={setNavState}/>)}
|
|
807
819
|
<TouchableScale_1.default style={styles_1.default.fabWrapper} onPress={() => setVisible(true)} hitSlop={10}>
|
|
808
820
|
<react_native_1.Animated.View style={[styles_1.default.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
|
|
809
821
|
<react_native_linear_gradient_1.default colors={[AppColors_1.AppColors.purple, '#8F6EFF']} style={styles_1.default.fab}>
|
|
@@ -2,7 +2,7 @@ import React from 'react';
|
|
|
2
2
|
declare const TouchableScale: ({ onPress, style, children, hitSlop, disabled, }: {
|
|
3
3
|
onPress?: () => void;
|
|
4
4
|
style?: any;
|
|
5
|
-
children
|
|
5
|
+
children?: React.ReactNode;
|
|
6
6
|
hitSlop?: any;
|
|
7
7
|
disabled?: boolean;
|
|
8
8
|
}) => React.JSX.Element;
|
|
@@ -102,7 +102,7 @@ export const clearConsoleLogs = () => {
|
|
|
102
102
|
};
|
|
103
103
|
export const getConsoleLogs = () => [...logs];
|
|
104
104
|
export const setupConsoleLogger = () => {
|
|
105
|
-
if (
|
|
105
|
+
if (globalThis.__CONSOLE_LOGGER_INITIALIZED__)
|
|
106
106
|
return;
|
|
107
107
|
const originalConsole = {
|
|
108
108
|
log: console.log,
|
|
@@ -130,5 +130,5 @@ export const setupConsoleLogger = () => {
|
|
|
130
130
|
addLog('error', args, 'error');
|
|
131
131
|
originalConsole.error(...args);
|
|
132
132
|
};
|
|
133
|
-
|
|
133
|
+
globalThis.__CONSOLE_LOGGER_INITIALIZED__ = true;
|
|
134
134
|
};
|
|
@@ -111,12 +111,12 @@ const addOrUpdateLog = (log) => {
|
|
|
111
111
|
};
|
|
112
112
|
// ─── Setup ────────────────────────────────────────────────────────────────────
|
|
113
113
|
export const setupNetworkLogger = () => {
|
|
114
|
-
if (
|
|
114
|
+
if (globalThis.__NETWORK_LOGGER_INITIALIZED__)
|
|
115
115
|
return;
|
|
116
|
-
|
|
117
|
-
const originalFetch =
|
|
116
|
+
globalThis.__NETWORK_LOGGER__ = addOrUpdateLog;
|
|
117
|
+
const originalFetch = globalThis.fetch;
|
|
118
118
|
if (originalFetch) {
|
|
119
|
-
|
|
119
|
+
globalThis.fetch = async (url, options = {}) => {
|
|
120
120
|
const method = (options?.method || 'GET').toUpperCase();
|
|
121
121
|
if (!ALLOWED_METHODS.includes(method))
|
|
122
122
|
return originalFetch(url, options);
|
|
@@ -186,7 +186,7 @@ export const setupNetworkLogger = () => {
|
|
|
186
186
|
}
|
|
187
187
|
};
|
|
188
188
|
}
|
|
189
|
-
|
|
189
|
+
globalThis.__NETWORK_LOGGER_INITIALIZED__ = true;
|
|
190
190
|
};
|
|
191
191
|
// ─── Axios interceptor helper ─────────────────────────────────────────────────
|
|
192
192
|
export const addAxiosInterceptors = (axiosInstance) => {
|
package/dist/esm/index.js
CHANGED
|
@@ -2,7 +2,7 @@ import React, { useEffect, useMemo, useRef, useState, useCallback } from 'react'
|
|
|
2
2
|
import { Alert, Animated, StyleSheet, FlatList, SectionList, Modal, Platform, Pressable, ScrollView, Text, TextInput, View, Linking, Image, InteractionManager, ActivityIndicator, StatusBar, } from 'react-native';
|
|
3
3
|
import Svg, { Circle, Path } from 'react-native-svg';
|
|
4
4
|
import LinearGradient from 'react-native-linear-gradient';
|
|
5
|
-
import { useNavigationState } from '@react-navigation/native';
|
|
5
|
+
import { useNavigationState, NavigationContext } from '@react-navigation/native';
|
|
6
6
|
// Components
|
|
7
7
|
import TouchableScale from './components/TouchableScale';
|
|
8
8
|
import useAccordion from './customHooks/useAccordion';
|
|
@@ -40,6 +40,13 @@ import AnalyticsDetail from './components/AnalyticsDetail';
|
|
|
40
40
|
// WebView
|
|
41
41
|
import { getWebViewLogs, getWebViewNavHistory, getWebViewHtml, getWebViewCss, getWebViewJs, getWebViewHtmlUrl, clearWebViewData, subscribeWebView, } from './customHooks/webViewLogger';
|
|
42
42
|
import { METHOD_COLORS, STATUS_FILTERS } from './constants';
|
|
43
|
+
const NavigationTracker = ({ onStateChange }) => {
|
|
44
|
+
const navState = useNavigationState(state => state);
|
|
45
|
+
useEffect(() => {
|
|
46
|
+
onStateChange(navState);
|
|
47
|
+
}, [navState, onStateChange]);
|
|
48
|
+
return null;
|
|
49
|
+
};
|
|
43
50
|
const NetworkInspector = () => {
|
|
44
51
|
const [logs, setLogs] = useState([]);
|
|
45
52
|
const [visible, setVisible] = useState(false);
|
|
@@ -106,13 +113,17 @@ const NetworkInspector = () => {
|
|
|
106
113
|
const [topEventsExpanded, setTopEventsExpanded] = useState(true);
|
|
107
114
|
const [newEventIds, setNewEventIds] = useState(new Set());
|
|
108
115
|
const prevEventIdsRef = useRef(new Set());
|
|
109
|
-
const navState =
|
|
116
|
+
const [navState, setNavState] = useState(null);
|
|
117
|
+
const navigationContext = React.useContext(NavigationContext);
|
|
118
|
+
const hasNavigationContext = navigationContext !== undefined;
|
|
110
119
|
const currentRouteRef = useRef({
|
|
111
120
|
path: 'Navigators',
|
|
112
121
|
params: null,
|
|
113
122
|
});
|
|
114
123
|
useEffect(() => {
|
|
115
|
-
|
|
124
|
+
if (navState) {
|
|
125
|
+
currentRouteRef.current = getNavigationInfo(navState);
|
|
126
|
+
}
|
|
116
127
|
}, [navState]);
|
|
117
128
|
const logRouteMapRef = useRef(new Map());
|
|
118
129
|
const prevLogIdsRef = useRef(new Set());
|
|
@@ -765,6 +776,7 @@ const NetworkInspector = () => {
|
|
|
765
776
|
toggleSectionCollapse,
|
|
766
777
|
]);
|
|
767
778
|
return (<>
|
|
779
|
+
{hasNavigationContext && (<NavigationTracker onStateChange={setNavState}/>)}
|
|
768
780
|
<TouchableScale style={styles.fabWrapper} onPress={() => setVisible(true)} hitSlop={10}>
|
|
769
781
|
<Animated.View style={[styles.fabPulseRing, { transform: [{ scale: pulseAnim }] }]}/>
|
|
770
782
|
<LinearGradient colors={[AppColors.purple, '#8F6EFF']} style={styles.fab}>
|
package/example/App.tsx
CHANGED
|
@@ -8,12 +8,12 @@ import {
|
|
|
8
8
|
ScrollView,
|
|
9
9
|
useColorScheme,
|
|
10
10
|
} from 'react-native';
|
|
11
|
-
import { SafeAreaProvider
|
|
11
|
+
import { SafeAreaProvider } from 'react-native-safe-area-context';
|
|
12
|
+
import { NavigationContainer } from '@react-navigation/native';
|
|
13
|
+
import { createNativeStackNavigator } from '@react-navigation/native-stack';
|
|
12
14
|
import NetworkInspector from 'react-native-inapp-inspector';
|
|
13
15
|
|
|
14
|
-
function
|
|
15
|
-
const isDarkMode = useColorScheme() === 'dark';
|
|
16
|
-
|
|
16
|
+
function HomeScreen({ navigation }: any) {
|
|
17
17
|
const triggerNetworkRequest = async () => {
|
|
18
18
|
try {
|
|
19
19
|
console.log('[API] Triggering network request...');
|
|
@@ -40,37 +40,116 @@ function App() {
|
|
|
40
40
|
console.error('[App] Error log triggered! Simulated critical error.');
|
|
41
41
|
};
|
|
42
42
|
|
|
43
|
+
React.useEffect(() => {
|
|
44
|
+
console.log('[Test] HomeScreen mounted, triggering automated tests...');
|
|
45
|
+
triggerNetworkRequest();
|
|
46
|
+
triggerConsoleLogs();
|
|
47
|
+
|
|
48
|
+
const timer = setTimeout(() => {
|
|
49
|
+
console.log('[Test] Navigating to Details screen...');
|
|
50
|
+
navigation.navigate('Details');
|
|
51
|
+
}, 2500);
|
|
52
|
+
|
|
53
|
+
return () => clearTimeout(timer);
|
|
54
|
+
}, []);
|
|
55
|
+
|
|
56
|
+
return (
|
|
57
|
+
<View style={styles.container}>
|
|
58
|
+
<ScrollView contentContainerStyle={styles.content}>
|
|
59
|
+
<Text style={styles.title}>RN In-App Inspector</Text>
|
|
60
|
+
<Text style={styles.subtitle}>Reference Implementation</Text>
|
|
61
|
+
|
|
62
|
+
<View style={styles.card}>
|
|
63
|
+
<Text style={styles.cardTitle}>Inspect Network & Console Logs</Text>
|
|
64
|
+
<Text style={styles.cardDesc}>
|
|
65
|
+
Tap the buttons below to trigger simulated background events, then click the floating inspector badge to open the inspector overlay.
|
|
66
|
+
</Text>
|
|
67
|
+
|
|
68
|
+
<TouchableOpacity style={styles.button} onPress={triggerNetworkRequest}>
|
|
69
|
+
<Text style={styles.buttonText}>Trigger Fetch (200 OK)</Text>
|
|
70
|
+
</TouchableOpacity>
|
|
71
|
+
|
|
72
|
+
<TouchableOpacity style={[styles.button, styles.dangerButton]} onPress={triggerFailedNetworkRequest}>
|
|
73
|
+
<Text style={styles.buttonText}>Trigger Fetch (404 Error)</Text>
|
|
74
|
+
</TouchableOpacity>
|
|
75
|
+
|
|
76
|
+
<TouchableOpacity style={[styles.button, styles.infoButton]} onPress={triggerConsoleLogs}>
|
|
77
|
+
<Text style={styles.buttonText}>Trigger Console Logs</Text>
|
|
78
|
+
</TouchableOpacity>
|
|
79
|
+
|
|
80
|
+
<TouchableOpacity style={[styles.button, styles.successButton]} onPress={() => navigation.navigate('Details')}>
|
|
81
|
+
<Text style={styles.buttonText}>Go to Details Screen</Text>
|
|
82
|
+
</TouchableOpacity>
|
|
83
|
+
</View>
|
|
84
|
+
</ScrollView>
|
|
85
|
+
<NetworkInspector />
|
|
86
|
+
</View>
|
|
87
|
+
);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
function DetailsScreen({ navigation }: any) {
|
|
91
|
+
const triggerDetailLogs = () => {
|
|
92
|
+
console.log('[Details] User navigated to details screen and triggered a log.');
|
|
93
|
+
};
|
|
94
|
+
|
|
95
|
+
React.useEffect(() => {
|
|
96
|
+
console.log('[Test] DetailsScreen mounted!');
|
|
97
|
+
triggerDetailLogs();
|
|
98
|
+
}, []);
|
|
99
|
+
|
|
100
|
+
return (
|
|
101
|
+
<View style={styles.container}>
|
|
102
|
+
<ScrollView contentContainerStyle={styles.content}>
|
|
103
|
+
<Text style={styles.title}>Details Screen</Text>
|
|
104
|
+
<Text style={styles.subtitle}>Navigation State Verification</Text>
|
|
105
|
+
|
|
106
|
+
<View style={styles.card}>
|
|
107
|
+
<Text style={styles.cardTitle}>Verify Navigation Routing</Text>
|
|
108
|
+
<Text style={styles.cardDesc}>
|
|
109
|
+
The inspector tracks your current navigation route. Open the inspector overlay and check the 'route' metadata on new network/console logs.
|
|
110
|
+
</Text>
|
|
111
|
+
|
|
112
|
+
<TouchableOpacity style={styles.button} onPress={triggerDetailLogs}>
|
|
113
|
+
<Text style={styles.buttonText}>Trigger Log from Details</Text>
|
|
114
|
+
</TouchableOpacity>
|
|
115
|
+
|
|
116
|
+
<TouchableOpacity style={[styles.button, styles.secondaryButton]} onPress={() => navigation.goBack()}>
|
|
117
|
+
<Text style={styles.buttonText}>Go Back Home</Text>
|
|
118
|
+
</TouchableOpacity>
|
|
119
|
+
</View>
|
|
120
|
+
</ScrollView>
|
|
121
|
+
<NetworkInspector />
|
|
122
|
+
</View>
|
|
123
|
+
);
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const Stack = createNativeStackNavigator();
|
|
127
|
+
|
|
128
|
+
function App() {
|
|
129
|
+
const isDarkMode = useColorScheme() === 'dark';
|
|
130
|
+
|
|
43
131
|
return (
|
|
44
132
|
<SafeAreaProvider>
|
|
45
133
|
<StatusBar barStyle={isDarkMode ? 'light-content' : 'dark-content'} />
|
|
46
|
-
<
|
|
47
|
-
<
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
<TouchableOpacity style={[styles.button, styles.infoButton]} onPress={triggerConsoleLogs}>
|
|
66
|
-
<Text style={styles.buttonText}>Trigger Console Logs</Text>
|
|
67
|
-
</TouchableOpacity>
|
|
68
|
-
</View>
|
|
69
|
-
</ScrollView>
|
|
70
|
-
|
|
71
|
-
{/* Floating In-App Debug Inspector */}
|
|
72
|
-
<NetworkInspector />
|
|
73
|
-
</SafeAreaView>
|
|
134
|
+
<NavigationContainer>
|
|
135
|
+
<Stack.Navigator
|
|
136
|
+
screenOptions={{
|
|
137
|
+
headerStyle: {
|
|
138
|
+
backgroundColor: '#1E1E24',
|
|
139
|
+
},
|
|
140
|
+
headerTintColor: '#FFFFFF',
|
|
141
|
+
headerTitleStyle: {
|
|
142
|
+
fontWeight: 'bold',
|
|
143
|
+
},
|
|
144
|
+
contentStyle: {
|
|
145
|
+
backgroundColor: '#121214',
|
|
146
|
+
},
|
|
147
|
+
}}
|
|
148
|
+
>
|
|
149
|
+
<Stack.Screen name="Home" component={HomeScreen} options={{ title: 'Dashboard' }} />
|
|
150
|
+
<Stack.Screen name="Details" component={DetailsScreen} options={{ title: 'Details' }} />
|
|
151
|
+
</Stack.Navigator>
|
|
152
|
+
</NavigationContainer>
|
|
74
153
|
</SafeAreaProvider>
|
|
75
154
|
);
|
|
76
155
|
}
|
|
@@ -133,6 +212,12 @@ const styles = StyleSheet.create({
|
|
|
133
212
|
infoButton: {
|
|
134
213
|
backgroundColor: '#5856D6',
|
|
135
214
|
},
|
|
215
|
+
successButton: {
|
|
216
|
+
backgroundColor: '#34C759',
|
|
217
|
+
},
|
|
218
|
+
secondaryButton: {
|
|
219
|
+
backgroundColor: '#8E8E93',
|
|
220
|
+
},
|
|
136
221
|
buttonText: {
|
|
137
222
|
fontSize: 15,
|
|
138
223
|
fontWeight: '600',
|