react-native-inapp-inspector 2.2.2 → 2.2.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 (97) hide show
  1. package/dist/commonjs/constants/version.d.ts +1 -1
  2. package/dist/commonjs/constants/version.js +1 -1
  3. package/dist/esm/constants/version.d.ts +1 -1
  4. package/dist/esm/constants/version.js +1 -1
  5. package/package.json +2 -1
  6. package/src/analytics.ts +35 -0
  7. package/src/bundle.ts +25 -0
  8. package/src/components/AnalyticsDetail.tsx +865 -0
  9. package/src/components/AnalyticsEventCard.tsx +441 -0
  10. package/src/components/AnalyticsGraph.tsx +583 -0
  11. package/src/components/AnimatedEntrance.tsx +64 -0
  12. package/src/components/AppHeaderLogo.tsx +109 -0
  13. package/src/components/BrandCircleIcon.tsx +144 -0
  14. package/src/components/BrandSquareIcon.tsx +144 -0
  15. package/src/components/CodeSnippet.tsx +725 -0
  16. package/src/components/ConsoleLogCard.tsx +628 -0
  17. package/src/components/CopyButton.tsx +87 -0
  18. package/src/components/DiffViewer.tsx +82 -0
  19. package/src/components/DomainHeader.tsx +237 -0
  20. package/src/components/EmptyState.tsx +73 -0
  21. package/src/components/EndOfListFooter.tsx +100 -0
  22. package/src/components/ErrorBoundary.tsx +688 -0
  23. package/src/components/HeadersSection.tsx +192 -0
  24. package/src/components/HighlightText.tsx +100 -0
  25. package/src/components/Inspector/AnalyticsFilterModal.tsx +1250 -0
  26. package/src/components/Inspector/AnalyticsTab.tsx +1336 -0
  27. package/src/components/Inspector/BundleTab.tsx +4731 -0
  28. package/src/components/Inspector/ConsoleTab.tsx +702 -0
  29. package/src/components/Inspector/CrashDetail.tsx +941 -0
  30. package/src/components/Inspector/CrashFilterModal.tsx +721 -0
  31. package/src/components/Inspector/CrashTab.tsx +871 -0
  32. package/src/components/Inspector/FabLauncher.tsx +80 -0
  33. package/src/components/Inspector/InspectorContext.tsx +28 -0
  34. package/src/components/Inspector/InspectorHeader.tsx +973 -0
  35. package/src/components/Inspector/LogDetail.tsx +1427 -0
  36. package/src/components/Inspector/MainScreen.tsx +258 -0
  37. package/src/components/Inspector/NavigationTracker.tsx +13 -0
  38. package/src/components/Inspector/NetworkDetail.tsx +794 -0
  39. package/src/components/Inspector/NetworkTab.tsx +1095 -0
  40. package/src/components/Inspector/NpmUpdateToast.tsx +392 -0
  41. package/src/components/Inspector/PerformanceTab.tsx +1894 -0
  42. package/src/components/Inspector/ReduxDetail.tsx +1651 -0
  43. package/src/components/Inspector/ReduxTab.tsx +954 -0
  44. package/src/components/Inspector/SettingsPanel.tsx +3181 -0
  45. package/src/components/Inspector/TabBar.tsx +187 -0
  46. package/src/components/Inspector/TelemetryConsentModal.tsx +392 -0
  47. package/src/components/Inspector/UpdateAvailableModal.tsx +545 -0
  48. package/src/components/JsonViewer.tsx +486 -0
  49. package/src/components/LogCard.tsx +491 -0
  50. package/src/components/LogSyntaxHighlighter.tsx +178 -0
  51. package/src/components/MetaAccordion.tsx +340 -0
  52. package/src/components/MiniBarChart.tsx +42 -0
  53. package/src/components/MiniLineChart.tsx +33 -0
  54. package/src/components/NetworkIcons.tsx +2118 -0
  55. package/src/components/SectionHeader.tsx +113 -0
  56. package/src/components/SegmentedTabs.tsx +83 -0
  57. package/src/components/Slider.tsx +300 -0
  58. package/src/components/SourcePageCard.tsx +148 -0
  59. package/src/components/Toast.tsx +131 -0
  60. package/src/components/TouchableScale.tsx +91 -0
  61. package/src/components/TreeNode.tsx +186 -0
  62. package/src/console.ts +24 -0
  63. package/src/constants/index.ts +38 -0
  64. package/src/constants/version.ts +3 -0
  65. package/src/crash.ts +32 -0
  66. package/src/customHooks/analyticsLogger.ts +336 -0
  67. package/src/customHooks/bundleAnalyzer.ts +1231 -0
  68. package/src/customHooks/consoleLogger.ts +497 -0
  69. package/src/customHooks/crashHandler.ts +944 -0
  70. package/src/customHooks/logFilters.ts +32 -0
  71. package/src/customHooks/networkLogger.ts +419 -0
  72. package/src/customHooks/performanceTracker.ts +1014 -0
  73. package/src/customHooks/reduxLogger.ts +406 -0
  74. package/src/customHooks/useAccordion.tsx +60 -0
  75. package/src/decorators/index.ts +184 -0
  76. package/src/helpers/gaAnalyticsRegistry.ts +204 -0
  77. package/src/helpers/index.ts +860 -0
  78. package/src/helpers/memoryManager.ts +138 -0
  79. package/src/helpers/searchQueryParser.ts +283 -0
  80. package/src/helpers/settingsStore.ts +171 -0
  81. package/src/helpers/telemetry.ts +505 -0
  82. package/src/helpers/toast.ts +17 -0
  83. package/src/i18n/index.ts +69 -0
  84. package/src/i18n/locales/en.json +1052 -0
  85. package/src/index.tsx +2336 -0
  86. package/src/native/NativeInspector.ts +397 -0
  87. package/src/native/NativeNetworkInspector.ts +24 -0
  88. package/src/network.ts +22 -0
  89. package/src/performance.ts +38 -0
  90. package/src/redux.ts +23 -0
  91. package/src/styles/AppColors.ts +408 -0
  92. package/src/styles/AppFonts.ts +8 -0
  93. package/src/styles/common.ts +209 -0
  94. package/src/styles/index.ts +1570 -0
  95. package/src/types/enums.ts +194 -0
  96. package/src/types/index.ts +34 -0
  97. package/src/types/interfaces.ts +515 -0
@@ -0,0 +1,131 @@
1
+ import React, {useState, useEffect, useRef} from 'react';
2
+ import {Animated, StyleSheet, Text, View, Platform} from 'react-native';
3
+ import {subscribeToast} from '../helpers/toast';
4
+ import {CheckIcon} from './NetworkIcons';
5
+ import {AppColors} from '../styles/AppColors';
6
+ import {AppFonts} from '../styles/AppFonts';
7
+
8
+ const Toast = React.memo(() => {
9
+ const [toastMessage, setToastMessage] = useState<string | null>(null);
10
+ const opacityAnim = useRef(new Animated.Value(0)).current;
11
+ const translateYAnim = useRef(new Animated.Value(20)).current;
12
+ const hideTimerRef = useRef<NodeJS.Timeout | null>(null);
13
+
14
+ useEffect(() => {
15
+ const unsubscribe = subscribeToast((message: string) => {
16
+ if (hideTimerRef.current) {
17
+ clearTimeout(hideTimerRef.current);
18
+ }
19
+
20
+ setToastMessage(message);
21
+
22
+ Animated.parallel([
23
+ Animated.timing(opacityAnim, {
24
+ toValue: 1,
25
+ duration: 180,
26
+ useNativeDriver: true,
27
+ }),
28
+ Animated.spring(translateYAnim, {
29
+ toValue: 0,
30
+ tension: 80,
31
+ friction: 8,
32
+ useNativeDriver: true,
33
+ }),
34
+ ]).start();
35
+
36
+ hideTimerRef.current = setTimeout(() => {
37
+ Animated.parallel([
38
+ Animated.timing(opacityAnim, {
39
+ toValue: 0,
40
+ duration: 200,
41
+ useNativeDriver: true,
42
+ }),
43
+ Animated.timing(translateYAnim, {
44
+ toValue: 20,
45
+ duration: 200,
46
+ useNativeDriver: true,
47
+ }),
48
+ ]).start(() => {
49
+ setToastMessage(null);
50
+ });
51
+ }, 2000);
52
+ });
53
+
54
+ return () => {
55
+ unsubscribe();
56
+ if (hideTimerRef.current) {
57
+ clearTimeout(hideTimerRef.current);
58
+ }
59
+ };
60
+ }, [opacityAnim, translateYAnim]);
61
+
62
+ if (!toastMessage) {
63
+ return null;
64
+ }
65
+
66
+ return (
67
+ <Animated.View
68
+ pointerEvents="none"
69
+ style={[
70
+ styles.toastContainer,
71
+ {
72
+ opacity: opacityAnim,
73
+ transform: [{translateY: translateYAnim}],
74
+ },
75
+ ]}>
76
+ <View style={styles.toastCard}>
77
+ <View style={styles.iconCircle}>
78
+ <CheckIcon color={AppColors.white} size={11} />
79
+ </View>
80
+ <Text style={styles.toastText} numberOfLines={2}>
81
+ {toastMessage}
82
+ </Text>
83
+ </View>
84
+ </Animated.View>
85
+ );
86
+ });
87
+
88
+ const styles = StyleSheet.create({
89
+ toastContainer: {
90
+ position: 'absolute',
91
+ bottom: Platform.OS === 'ios' ? 44 : 28,
92
+ left: 20,
93
+ right: 20,
94
+ alignItems: 'center',
95
+ justifyContent: 'center',
96
+ zIndex: 999999,
97
+ },
98
+ toastCard: {
99
+ flexDirection: 'row',
100
+ alignItems: 'center',
101
+ backgroundColor: AppColors.toastBg,
102
+ paddingVertical: 10,
103
+ paddingHorizontal: 16,
104
+ borderRadius: 24,
105
+ shadowColor: AppColors.black,
106
+ shadowOffset: {width: 0, height: 6},
107
+ shadowOpacity: 0.28,
108
+ shadowRadius: 10,
109
+ elevation: 8,
110
+ borderWidth: 1,
111
+ borderColor: AppColors.toastBorder,
112
+ maxWidth: '90%',
113
+ gap: 9,
114
+ },
115
+ iconCircle: {
116
+ width: 18,
117
+ height: 18,
118
+ borderRadius: 9,
119
+ backgroundColor: AppColors.greenColor,
120
+ alignItems: 'center',
121
+ justifyContent: 'center',
122
+ },
123
+ toastText: {
124
+ color: AppColors.white,
125
+ fontFamily: AppFonts.interBold,
126
+ fontSize: 12.5,
127
+ letterSpacing: -0.1,
128
+ },
129
+ });
130
+
131
+ export default Toast;
@@ -0,0 +1,91 @@
1
+ import React, {useRef} from 'react';
2
+ import {Animated, Pressable, PressableProps} from 'react-native';
3
+ import {triggerNativeHaptic} from '../native/NativeInspector';
4
+
5
+ const AnimatedPressable = Animated.createAnimatedComponent(Pressable);
6
+
7
+ export interface TouchableScaleProps extends PressableProps {
8
+ onPress?: () => void;
9
+ onLongPress?: () => void;
10
+ style?: any;
11
+ children?: React.ReactNode;
12
+ hitSlop?: any;
13
+ disabled?: boolean;
14
+ enableHaptics?: boolean;
15
+ }
16
+
17
+ const TouchableScale = React.memo(function TouchableScale({
18
+ onPress,
19
+ onLongPress,
20
+ style,
21
+ children,
22
+ hitSlop,
23
+ disabled,
24
+ enableHaptics = true,
25
+ accessible,
26
+ accessibilityRole,
27
+ accessibilityLabel,
28
+ accessibilityHint,
29
+ accessibilityState,
30
+ accessibilityValue,
31
+ ...rest
32
+ }: TouchableScaleProps) {
33
+ const scale = useRef(new Animated.Value(1)).current;
34
+ const opacity = useRef(new Animated.Value(1)).current;
35
+
36
+ const handlePressIn = () => {
37
+ if (disabled) return;
38
+ if (enableHaptics) {
39
+ triggerNativeHaptic('light');
40
+ }
41
+ Animated.parallel([
42
+ Animated.timing(scale, {
43
+ toValue: 0.94,
44
+ duration: 50,
45
+ useNativeDriver: true,
46
+ }),
47
+ Animated.timing(opacity, {
48
+ toValue: 0.85,
49
+ duration: 50,
50
+ useNativeDriver: true,
51
+ }),
52
+ ]).start();
53
+ };
54
+
55
+ const handlePressOut = () => {
56
+ Animated.parallel([
57
+ Animated.timing(scale, {
58
+ toValue: 1,
59
+ duration: 100,
60
+ useNativeDriver: true,
61
+ }),
62
+ Animated.timing(opacity, {
63
+ toValue: 1,
64
+ duration: 100,
65
+ useNativeDriver: true,
66
+ }),
67
+ ]).start();
68
+ };
69
+
70
+ return (
71
+ <AnimatedPressable
72
+ accessible={accessible}
73
+ accessibilityRole={accessibilityRole}
74
+ accessibilityLabel={accessibilityLabel}
75
+ accessibilityHint={accessibilityHint}
76
+ accessibilityState={accessibilityState}
77
+ accessibilityValue={accessibilityValue}
78
+ disabled={disabled}
79
+ style={[style, {opacity, transform: [{scale}]}]}
80
+ onPressIn={handlePressIn}
81
+ onPressOut={handlePressOut}
82
+ onPress={onPress}
83
+ onLongPress={onLongPress}
84
+ hitSlop={hitSlop}
85
+ {...rest}>
86
+ {children}
87
+ </AnimatedPressable>
88
+ );
89
+ });
90
+
91
+ export default TouchableScale;
@@ -0,0 +1,186 @@
1
+ import React, {useState, useRef, useEffect} from 'react';
2
+ import {Text, View, Image, Animated, Pressable} from 'react-native';
3
+
4
+ // Helpers
5
+ import {escapeRegex} from '../helpers';
6
+
7
+ // Assets
8
+ import {ChevronIcon, DocIcon} from './NetworkIcons';
9
+
10
+ // Stylesheet
11
+ import {AppColors} from '../styles/AppColors';
12
+ import styles from '../styles';
13
+
14
+ // Type Definition
15
+ import {TreeNodeProps} from '../types';
16
+
17
+ const TreeNode = React.memo(function TreeNode({
18
+ data,
19
+ name,
20
+ level = 0,
21
+ search,
22
+ forceOpen,
23
+ defaultExpandDepth = 1,
24
+ }: TreeNodeProps) {
25
+ const [localOpen, setLocalOpen] = useState<boolean>(() => {
26
+ if (forceOpen !== undefined) {
27
+ return forceOpen;
28
+ }
29
+ return defaultExpandDepth !== undefined ? level < defaultExpandDepth : level < 1;
30
+ });
31
+ const open = localOpen;
32
+
33
+ useEffect(() => {
34
+ if (forceOpen !== undefined) {
35
+ setLocalOpen(forceOpen);
36
+ }
37
+ }, [forceOpen]);
38
+
39
+ const isObject = typeof data === 'object' && data !== null;
40
+ const isArray = Array.isArray(data);
41
+
42
+ // Declare all hooks at the top unconditionally (prevents "Rendered fewer hooks than expected" error)
43
+ const treeChevronAnim = useRef(new Animated.Value(open ? 1 : 0)).current;
44
+ useEffect(() => {
45
+ Animated.timing(treeChevronAnim, {
46
+ toValue: open ? 1 : 0,
47
+ duration: 160,
48
+ useNativeDriver: true,
49
+ }).start();
50
+ }, [open]);
51
+
52
+ const treeChevronRotate = treeChevronAnim.interpolate({
53
+ inputRange: [0, 1],
54
+ outputRange: ['0deg', '180deg'],
55
+ });
56
+
57
+ function renderHighlighted(text: string): React.ReactNode[] {
58
+ if (text === 'null' || text === 'undefined') {
59
+ return [
60
+ <Text key="nil" style={styles.codeTextNil}>
61
+ {text}
62
+ </Text>,
63
+ ];
64
+ }
65
+ if (!search) {
66
+ return [
67
+ <Text key="plain" style={styles.codeText}>
68
+ {text}
69
+ </Text>,
70
+ ];
71
+ }
72
+ const regex = new RegExp(`(${escapeRegex(search)})`, 'gi');
73
+ const parts = text.split(regex);
74
+ return parts.map((part, i) =>
75
+ part.toLowerCase() === search.toLowerCase() ? (
76
+ <Text key={i} style={styles.highlight}>
77
+ {part}
78
+ </Text>
79
+ ) : (
80
+ <Text key={i} style={styles.codeText}>
81
+ {part}
82
+ </Text>
83
+ ),
84
+ );
85
+ }
86
+
87
+ const indentStyle = {paddingLeft: level * 12};
88
+
89
+ if (isObject && (data as any)._isFile) {
90
+ const file = data as any;
91
+ const isImage = file.type?.includes('image');
92
+
93
+ return (
94
+ <View style={[indentStyle, styles.filePreviewNode]}>
95
+ {name !== undefined && (
96
+ <Text style={[styles.codeKey, {marginBottom: 4}]}>{`"${String(
97
+ name,
98
+ )}": `}</Text>
99
+ )}
100
+ <View style={styles.filePreviewCard}>
101
+ {isImage ? (
102
+ <Image
103
+ source={{uri: file.uri}}
104
+ style={styles.filePreviewThumb}
105
+ resizeMode="cover"
106
+ />
107
+ ) : (
108
+ <View style={styles.filePreviewDoc}>
109
+ <DocIcon color={AppColors.grayTextWeak} size={20} />
110
+ </View>
111
+ )}
112
+ <View style={{flex: 1}}>
113
+ <Text style={styles.filePreviewName} numberOfLines={1}>
114
+ {file.name}
115
+ </Text>
116
+ <Text style={styles.filePreviewType}>{file.type}</Text>
117
+ </View>
118
+ </View>
119
+ </View>
120
+ );
121
+ }
122
+
123
+ if (!isObject) {
124
+ const serialized = JSON.stringify(data) ?? String(data);
125
+ const prefix = name !== undefined ? `"${String(name)}": ` : null;
126
+ return (
127
+ <View style={indentStyle}>
128
+ <Text selectable={true} style={styles.codeText}>
129
+ <Text style={styles.codeKey}>{prefix}</Text>
130
+ {renderHighlighted(serialized)}
131
+ </Text>
132
+ </View>
133
+ );
134
+ }
135
+
136
+ const entries: [string | number, unknown][] = isArray
137
+ ? (data as unknown[]).map((v, i) => [i, v])
138
+ : Object.entries(data as Record<string, unknown>);
139
+
140
+ const countLabel = isArray ? `[${entries.length}]` : `{${entries.length}}`;
141
+
142
+ return (
143
+ <View style={indentStyle}>
144
+ <Pressable
145
+ style={styles.treeRow}
146
+ onPress={() => setLocalOpen(v => !v)}
147
+ hitSlop={{top: 10, bottom: 10, left: 10, right: 10}}>
148
+ <Animated.View
149
+ style={{transform: [{rotate: treeChevronRotate}], marginRight: 6}}>
150
+ <ChevronIcon color={AppColors.grayTextWeak} size={12} />
151
+ </Animated.View>
152
+ {name !== undefined && (
153
+ <Text style={[styles.codeKey, styles.treeKeyMargin]}>{`"${String(
154
+ name,
155
+ )}"`}</Text>
156
+ )}
157
+ {isArray ? (
158
+ <View style={styles.arrayBadge}>
159
+ <Text style={styles.arrayBadgeText}>{countLabel}</Text>
160
+ </View>
161
+ ) : (
162
+ <View style={styles.objectBadge}>
163
+ <Text style={styles.objectBadgeText}>{countLabel}</Text>
164
+ </View>
165
+ )}
166
+ </Pressable>
167
+
168
+ {open &&
169
+ entries.map(([k, v]) => (
170
+ <TreeNode
171
+ key={String(k)}
172
+ name={k}
173
+ data={v}
174
+ level={level + 1}
175
+ search={search}
176
+ forceOpen={forceOpen}
177
+ defaultExpandDepth={defaultExpandDepth}
178
+ />
179
+ ))}
180
+
181
+ {open && <Text style={styles.codeSyntax}>{isArray ? ']' : '}'}</Text>}
182
+ </View>
183
+ );
184
+ });
185
+
186
+ export default TreeNode;
package/src/console.ts ADDED
@@ -0,0 +1,24 @@
1
+ /**
2
+ * Sub-module entry point: react-native-inapp-inspector/console
3
+ * Clean tree-shaking & isolated console logger.
4
+ */
5
+ export {
6
+ setupConsoleLogger,
7
+ clearConsoleLogs,
8
+ subscribeConsoleLogs,
9
+ getConsoleLogs,
10
+ setConsoleModuleEnabled,
11
+ getConsoleModuleEnabled,
12
+ setMaxConsoleLogsLimit,
13
+ getMaxConsoleLogsLimit,
14
+ pruneConsoleLogs,
15
+ } from './customHooks/consoleLogger';
16
+
17
+ export type {
18
+ ConsoleLog,
19
+ } from './types';
20
+
21
+ export {
22
+ ConsoleLogType,
23
+ LogFilter,
24
+ } from './types';
@@ -0,0 +1,38 @@
1
+ import {Method} from '../types';
2
+
3
+ // Styles
4
+ import {AppColors} from '../styles/AppColors';
5
+
6
+ // Type Definition
7
+ import {StatusFilter} from '../types';
8
+
9
+ export const STATUS_FILTERS: string[] = [
10
+ 'ALL',
11
+ '2xx',
12
+ '200',
13
+ '3xx',
14
+ '4xx',
15
+ '400',
16
+ '404',
17
+ '5xx',
18
+ '500',
19
+ 'Failed',
20
+ ];
21
+
22
+ export const METHOD_COLORS: Record<Method, string> = {
23
+ ALL: '#64748B', // Slate
24
+ GET: '#059669', // Emerald
25
+ POST: '#2563EB', // Royal Blue
26
+ PUT: '#D97706', // Amber Gold
27
+ PATCH: '#7C3AED', // Rich Violet
28
+ DELETE: '#DC2626', // Crimson Red
29
+ };
30
+
31
+ export const DOMAIN_COLORS: string[] = AppColors.domainColors;
32
+
33
+ export const DURATION_FAST_MS = 200;
34
+ export const DURATION_SLOW_MS = 800;
35
+
36
+ // Package version — auto-generated from package.json at build time.
37
+ // See scripts/gen-version.js (wired to the "prebuild" npm script).
38
+ export {LIB_VERSION} from './version';
@@ -0,0 +1,3 @@
1
+ // AUTO-GENERATED FILE — do not edit by hand.
2
+ // Regenerated from package.json on every build by scripts/gen-version.js.
3
+ export const LIB_VERSION = '2.2.3';
package/src/crash.ts ADDED
@@ -0,0 +1,32 @@
1
+ /**
2
+ * Sub-module entry point: react-native-inapp-inspector/crash
3
+ * Clean tree-shaking & isolated global crash handler and reporting.
4
+ */
5
+ export {
6
+ setupGlobalCrashHandler,
7
+ subscribeCrashEvents,
8
+ emitCrashEvent,
9
+ getCrashRecords,
10
+ clearCrashRecords,
11
+ simulateTestCrash,
12
+ exportCrashReport,
13
+ parseCrashStackTrace,
14
+ setMaxCrashLogsLimit,
15
+ getMaxCrashLogsLimit,
16
+ pruneCrashRecords,
17
+ setCrashModuleEnabled,
18
+ getCrashModuleEnabled,
19
+ } from './customHooks/crashHandler';
20
+
21
+ export type {
22
+ CrashRecord,
23
+ CrashBreadcrumb,
24
+ } from './types';
25
+
26
+ export {
27
+ CrashType,
28
+ CrashExportFormat,
29
+ CrashDetailSubTab,
30
+ CrashFilterType,
31
+ BreadcrumbType,
32
+ } from './types';