react-native-inapp-inspector 2.0.0 → 2.0.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/README.md +10 -0
- package/android/.gradle/8.9/checksums/checksums.lock +0 -0
- package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
- package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
- package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
- package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
- package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
- package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/8.9/gc.properties +0 -0
- package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
- package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
- package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
- package/android/.gradle/9.2.0/gc.properties +0 -0
- package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
- package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
- package/android/.gradle/vcs-1/gc.properties +0 -0
- package/android/build/reports/problems/problems-report.html +659 -0
- package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +33 -24
- package/dist/commonjs/components/ConsoleLogCard.js +5 -5
- package/dist/commonjs/components/EndOfListFooter.js +1 -1
- package/dist/commonjs/components/Inspector/AnalyticsTab.js +19 -71
- package/dist/commonjs/components/Inspector/BundleTab.js +670 -188
- package/dist/commonjs/components/Inspector/ConsoleTab.js +109 -98
- package/dist/commonjs/components/Inspector/CrashTab.js +2 -1
- package/dist/commonjs/components/Inspector/InspectorHeader.js +102 -19
- package/dist/commonjs/components/Inspector/MainScreen.js +151 -17
- package/dist/commonjs/components/Inspector/NetworkTab.js +104 -20
- package/dist/commonjs/components/Inspector/SettingsPanel.js +1111 -1385
- package/dist/commonjs/components/Inspector/TabBar.js +3 -4
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +212 -0
- package/dist/commonjs/components/JsonViewer.js +9 -4
- package/dist/commonjs/components/LogCard.js +31 -1
- package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
- package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
- package/dist/commonjs/components/NetworkIcons.js +10 -1
- package/dist/commonjs/components/Slider.d.ts +13 -0
- package/dist/commonjs/components/Slider.js +261 -0
- package/dist/commonjs/constants/version.d.ts +1 -1
- package/dist/commonjs/constants/version.js +1 -1
- package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
- package/dist/commonjs/customHooks/crashHandler.js +1 -1
- package/dist/commonjs/helpers/index.d.ts +2 -0
- package/dist/commonjs/helpers/index.js +16 -0
- package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
- package/dist/commonjs/helpers/searchQueryParser.js +236 -0
- package/dist/commonjs/helpers/settingsStore.js +13 -13
- package/dist/commonjs/helpers/telemetry.d.ts +99 -0
- package/dist/commonjs/helpers/telemetry.js +398 -0
- package/dist/commonjs/index.d.ts +2 -0
- package/dist/commonjs/index.js +30 -21
- package/dist/commonjs/native/NativeInspector.d.ts +5 -0
- package/dist/commonjs/native/NativeInspector.js +3 -2
- package/dist/commonjs/styles/index.js +35 -35
- package/dist/esm/components/ConsoleLogCard.js +5 -5
- package/dist/esm/components/EndOfListFooter.js +2 -2
- package/dist/esm/components/Inspector/AnalyticsTab.js +21 -73
- package/dist/esm/components/Inspector/BundleTab.js +670 -188
- package/dist/esm/components/Inspector/ConsoleTab.js +110 -99
- package/dist/esm/components/Inspector/CrashTab.js +2 -1
- package/dist/esm/components/Inspector/InspectorHeader.js +103 -20
- package/dist/esm/components/Inspector/MainScreen.js +119 -18
- package/dist/esm/components/Inspector/NetworkTab.js +105 -21
- package/dist/esm/components/Inspector/SettingsPanel.js +1114 -1388
- package/dist/esm/components/Inspector/TabBar.js +4 -5
- package/dist/esm/components/Inspector/TelemetryConsentModal.d.ts +3 -0
- package/dist/esm/components/Inspector/TelemetryConsentModal.js +175 -0
- package/dist/esm/components/JsonViewer.js +9 -4
- package/dist/esm/components/LogCard.js +32 -2
- package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
- package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
- package/dist/esm/components/NetworkIcons.d.ts +2 -0
- package/dist/esm/components/NetworkIcons.js +7 -0
- package/dist/esm/components/Slider.d.ts +13 -0
- package/dist/esm/components/Slider.js +222 -0
- package/dist/esm/constants/version.d.ts +1 -1
- package/dist/esm/constants/version.js +1 -1
- package/dist/esm/customHooks/analyticsLogger.js +1 -1
- package/dist/esm/customHooks/crashHandler.js +1 -1
- package/dist/esm/helpers/index.d.ts +2 -0
- package/dist/esm/helpers/index.js +2 -0
- package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
- package/dist/esm/helpers/searchQueryParser.js +233 -0
- package/dist/esm/helpers/settingsStore.js +13 -13
- package/dist/esm/helpers/telemetry.d.ts +99 -0
- package/dist/esm/helpers/telemetry.js +380 -0
- package/dist/esm/index.d.ts +2 -0
- package/dist/esm/index.js +20 -21
- package/dist/esm/native/NativeInspector.d.ts +5 -0
- package/dist/esm/native/NativeInspector.js +3 -2
- package/dist/esm/styles/index.js +35 -35
- package/ios/{NetworkInspectorModule.m → NetworkInspectorModule.mm} +193 -97
- package/package.json +2 -2
|
@@ -0,0 +1,222 @@
|
|
|
1
|
+
import React, { useRef, useState, useCallback, useMemo } from 'react';
|
|
2
|
+
import { View, Text, StyleSheet, PanResponder, } from 'react-native';
|
|
3
|
+
import { AppColors } from '../styles/AppColors';
|
|
4
|
+
import { AppFonts } from '../styles/AppFonts';
|
|
5
|
+
import TouchableScale from './TouchableScale';
|
|
6
|
+
export const Slider = React.memo(({ value, onValueChange, min = 50, max = 90, step = 5, formatLabel = val => `${Math.round(val)}%`, quickPresets = [50, 60, 70, 80, 90], disabled = false, }) => {
|
|
7
|
+
const trackWidthRef = useRef(0);
|
|
8
|
+
const [trackWidth, setTrackWidth] = useState(0);
|
|
9
|
+
const [isDragging, setIsDragging] = useState(false);
|
|
10
|
+
const clampedValue = Math.max(min, Math.min(max, value));
|
|
11
|
+
const percentage = (clampedValue - min) / (max - min || 1);
|
|
12
|
+
const updateValueFromPosition = useCallback((pageX, trackPageX) => {
|
|
13
|
+
if (trackWidthRef.current <= 0)
|
|
14
|
+
return;
|
|
15
|
+
const relativeX = Math.max(0, Math.min(trackWidthRef.current, pageX - trackPageX));
|
|
16
|
+
const rawRatio = relativeX / trackWidthRef.current;
|
|
17
|
+
let newValue = min + rawRatio * (max - min);
|
|
18
|
+
if (step > 0) {
|
|
19
|
+
newValue = Math.round(newValue / step) * step;
|
|
20
|
+
}
|
|
21
|
+
newValue = Math.max(min, Math.min(max, newValue));
|
|
22
|
+
onValueChange(newValue);
|
|
23
|
+
}, [min, max, step, onValueChange]);
|
|
24
|
+
const trackContainerRef = useRef(null);
|
|
25
|
+
const trackPageXRef = useRef(0);
|
|
26
|
+
const measureTrack = useCallback(() => {
|
|
27
|
+
if (trackContainerRef.current) {
|
|
28
|
+
trackContainerRef.current.measure((_x, _y, _width, _height, pageX) => {
|
|
29
|
+
trackPageXRef.current = pageX;
|
|
30
|
+
});
|
|
31
|
+
}
|
|
32
|
+
}, []);
|
|
33
|
+
const panResponder = useMemo(() => PanResponder.create({
|
|
34
|
+
onStartShouldSetPanResponder: () => !disabled,
|
|
35
|
+
onMoveShouldSetPanResponder: () => !disabled,
|
|
36
|
+
onPanResponderGrant: (evt) => {
|
|
37
|
+
setIsDragging(true);
|
|
38
|
+
measureTrack();
|
|
39
|
+
updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
|
|
40
|
+
},
|
|
41
|
+
onPanResponderMove: (evt, _gestureState) => {
|
|
42
|
+
updateValueFromPosition(evt.nativeEvent.pageX, trackPageXRef.current);
|
|
43
|
+
},
|
|
44
|
+
onPanResponderRelease: () => {
|
|
45
|
+
setIsDragging(false);
|
|
46
|
+
},
|
|
47
|
+
onPanResponderTerminate: () => {
|
|
48
|
+
setIsDragging(false);
|
|
49
|
+
},
|
|
50
|
+
}), [disabled, measureTrack, updateValueFromPosition]);
|
|
51
|
+
const handleLayout = (e) => {
|
|
52
|
+
const w = e.nativeEvent.layout.width;
|
|
53
|
+
trackWidthRef.current = w;
|
|
54
|
+
setTrackWidth(w);
|
|
55
|
+
measureTrack();
|
|
56
|
+
};
|
|
57
|
+
const thumbPosition = percentage * (trackWidth || 0);
|
|
58
|
+
return (<View style={styles.container}>
|
|
59
|
+
{/* Value Display Row */}
|
|
60
|
+
<View style={styles.valueRow}>
|
|
61
|
+
<Text style={styles.rangeText}>{min}%</Text>
|
|
62
|
+
<View style={[
|
|
63
|
+
styles.currentValueBadge,
|
|
64
|
+
isDragging && styles.currentValueBadgeActive,
|
|
65
|
+
]}>
|
|
66
|
+
<Text style={styles.currentValueText}>{formatLabel(clampedValue)}</Text>
|
|
67
|
+
</View>
|
|
68
|
+
<Text style={styles.rangeText}>{max}%</Text>
|
|
69
|
+
</View>
|
|
70
|
+
|
|
71
|
+
{/* Interactive Track Area */}
|
|
72
|
+
<View ref={trackContainerRef} onLayout={handleLayout} {...panResponder.panHandlers} style={styles.touchArea}>
|
|
73
|
+
{/* Background Rail */}
|
|
74
|
+
<View style={styles.rail}>
|
|
75
|
+
{/* Active Filled Bar */}
|
|
76
|
+
<View style={[
|
|
77
|
+
styles.fillBar,
|
|
78
|
+
{ width: `${Math.round(percentage * 100)}%` },
|
|
79
|
+
]}/>
|
|
80
|
+
</View>
|
|
81
|
+
|
|
82
|
+
{/* Draggable Thumb */}
|
|
83
|
+
<View style={[
|
|
84
|
+
styles.thumb,
|
|
85
|
+
{
|
|
86
|
+
left: Math.max(0, Math.min((trackWidth || 0) - 24, thumbPosition - 12)),
|
|
87
|
+
},
|
|
88
|
+
isDragging && styles.thumbActive,
|
|
89
|
+
]}>
|
|
90
|
+
<View style={styles.thumbCenterDot}/>
|
|
91
|
+
</View>
|
|
92
|
+
</View>
|
|
93
|
+
|
|
94
|
+
{/* Quick Presets */}
|
|
95
|
+
{quickPresets && quickPresets.length > 0 && (<View style={styles.presetRow}>
|
|
96
|
+
{quickPresets.map(preset => {
|
|
97
|
+
const isSelected = Math.round(clampedValue) === preset;
|
|
98
|
+
return (<TouchableScale key={preset} onPress={() => onValueChange(preset)} style={[
|
|
99
|
+
styles.presetButton,
|
|
100
|
+
isSelected && styles.presetButtonActive,
|
|
101
|
+
]}>
|
|
102
|
+
<Text style={[
|
|
103
|
+
styles.presetText,
|
|
104
|
+
isSelected && styles.presetTextActive,
|
|
105
|
+
]}>
|
|
106
|
+
{preset}%
|
|
107
|
+
</Text>
|
|
108
|
+
</TouchableScale>);
|
|
109
|
+
})}
|
|
110
|
+
</View>)}
|
|
111
|
+
</View>);
|
|
112
|
+
});
|
|
113
|
+
const styles = StyleSheet.create({
|
|
114
|
+
container: {
|
|
115
|
+
paddingVertical: 4,
|
|
116
|
+
gap: 8,
|
|
117
|
+
},
|
|
118
|
+
valueRow: {
|
|
119
|
+
flexDirection: 'row',
|
|
120
|
+
alignItems: 'center',
|
|
121
|
+
justifyContent: 'space-between',
|
|
122
|
+
paddingHorizontal: 2,
|
|
123
|
+
},
|
|
124
|
+
rangeText: {
|
|
125
|
+
fontFamily: AppFonts.interMedium,
|
|
126
|
+
fontSize: 11,
|
|
127
|
+
color: AppColors.grayText,
|
|
128
|
+
},
|
|
129
|
+
currentValueBadge: {
|
|
130
|
+
backgroundColor: `${AppColors.purple}1A`,
|
|
131
|
+
borderColor: `${AppColors.purple}33`,
|
|
132
|
+
borderWidth: 1,
|
|
133
|
+
borderRadius: 8,
|
|
134
|
+
paddingHorizontal: 10,
|
|
135
|
+
paddingVertical: 2.5,
|
|
136
|
+
},
|
|
137
|
+
currentValueBadgeActive: {
|
|
138
|
+
backgroundColor: AppColors.purple,
|
|
139
|
+
borderColor: AppColors.purple,
|
|
140
|
+
transform: [{ scale: 1.05 }],
|
|
141
|
+
},
|
|
142
|
+
currentValueText: {
|
|
143
|
+
fontFamily: AppFonts.interBold,
|
|
144
|
+
fontSize: 12,
|
|
145
|
+
color: AppColors.purple,
|
|
146
|
+
},
|
|
147
|
+
touchArea: {
|
|
148
|
+
height: 36,
|
|
149
|
+
justifyContent: 'center',
|
|
150
|
+
position: 'relative',
|
|
151
|
+
},
|
|
152
|
+
rail: {
|
|
153
|
+
height: 8,
|
|
154
|
+
backgroundColor: `${AppColors.grayTextWeak}2B`,
|
|
155
|
+
borderRadius: 4,
|
|
156
|
+
overflow: 'hidden',
|
|
157
|
+
position: 'relative',
|
|
158
|
+
},
|
|
159
|
+
fillBar: {
|
|
160
|
+
height: '100%',
|
|
161
|
+
backgroundColor: AppColors.purple,
|
|
162
|
+
borderRadius: 4,
|
|
163
|
+
},
|
|
164
|
+
thumb: {
|
|
165
|
+
position: 'absolute',
|
|
166
|
+
width: 24,
|
|
167
|
+
height: 24,
|
|
168
|
+
borderRadius: 12,
|
|
169
|
+
backgroundColor: AppColors.white,
|
|
170
|
+
borderWidth: 2.5,
|
|
171
|
+
borderColor: AppColors.purple,
|
|
172
|
+
alignItems: 'center',
|
|
173
|
+
justifyContent: 'center',
|
|
174
|
+
shadowColor: AppColors.black,
|
|
175
|
+
shadowOffset: { width: 0, height: 2 },
|
|
176
|
+
shadowOpacity: 0.18,
|
|
177
|
+
shadowRadius: 3.5,
|
|
178
|
+
elevation: 4,
|
|
179
|
+
},
|
|
180
|
+
thumbActive: {
|
|
181
|
+
transform: [{ scale: 1.15 }],
|
|
182
|
+
shadowOpacity: 0.28,
|
|
183
|
+
shadowRadius: 5,
|
|
184
|
+
elevation: 6,
|
|
185
|
+
borderColor: AppColors.purple,
|
|
186
|
+
},
|
|
187
|
+
thumbCenterDot: {
|
|
188
|
+
width: 6,
|
|
189
|
+
height: 6,
|
|
190
|
+
borderRadius: 3,
|
|
191
|
+
backgroundColor: AppColors.purple,
|
|
192
|
+
},
|
|
193
|
+
presetRow: {
|
|
194
|
+
flexDirection: 'row',
|
|
195
|
+
alignItems: 'center',
|
|
196
|
+
justifyContent: 'space-between',
|
|
197
|
+
gap: 8,
|
|
198
|
+
marginTop: 2,
|
|
199
|
+
},
|
|
200
|
+
presetButton: {
|
|
201
|
+
flex: 1,
|
|
202
|
+
paddingVertical: 5,
|
|
203
|
+
borderRadius: 7,
|
|
204
|
+
alignItems: 'center',
|
|
205
|
+
backgroundColor: AppColors.grayBackground,
|
|
206
|
+
borderWidth: 1,
|
|
207
|
+
borderColor: AppColors.dividerColor,
|
|
208
|
+
},
|
|
209
|
+
presetButtonActive: {
|
|
210
|
+
backgroundColor: `${AppColors.purple}20`,
|
|
211
|
+
borderColor: AppColors.purple,
|
|
212
|
+
},
|
|
213
|
+
presetText: {
|
|
214
|
+
fontFamily: AppFonts.interBold,
|
|
215
|
+
fontSize: 10.5,
|
|
216
|
+
color: AppColors.grayText,
|
|
217
|
+
},
|
|
218
|
+
presetTextActive: {
|
|
219
|
+
color: AppColors.purple,
|
|
220
|
+
},
|
|
221
|
+
});
|
|
222
|
+
export default Slider;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
export declare const LIB_VERSION = "2.0.
|
|
1
|
+
export declare const LIB_VERSION = "2.0.2";
|
|
@@ -43,7 +43,7 @@ const addEvent = (event) => {
|
|
|
43
43
|
if (!isAnalyticsModuleEnabled)
|
|
44
44
|
return;
|
|
45
45
|
events.unshift(event);
|
|
46
|
-
events = events.slice(0,
|
|
46
|
+
events = events.slice(0, 75);
|
|
47
47
|
notify();
|
|
48
48
|
};
|
|
49
49
|
// ─── Public subscribe / query API ────────────────────────────────────────────
|
|
@@ -10,7 +10,7 @@ let lastHandledErrorTimestamp = 0;
|
|
|
10
10
|
let crashRecordsStore = [];
|
|
11
11
|
let breadcrumbsStore = [];
|
|
12
12
|
const MAX_BREADCRUMBS = 50;
|
|
13
|
-
let maxStoredCrashes =
|
|
13
|
+
let maxStoredCrashes = 50;
|
|
14
14
|
const appStartTime = Date.now();
|
|
15
15
|
let isCrashModuleEnabled = false;
|
|
16
16
|
export const setCrashModuleEnabled = (enabled) => {
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
import { NetworkLog, RouteInfo, DiffResult, JsonContent, StackFrameType } from '../types';
|
|
2
|
+
export * from './searchQueryParser';
|
|
3
|
+
export * from './telemetry';
|
|
2
4
|
export declare const getDomainColor: (domain: string) => string;
|
|
3
5
|
export declare const formatDateTime: (timestamp: number) => string;
|
|
4
6
|
export declare const formatTimestamp: (timestamp: number) => string;
|
|
@@ -5,6 +5,8 @@ import { showToast } from './toast';
|
|
|
5
5
|
import { AppColors } from '../styles/AppColors';
|
|
6
6
|
// Constants
|
|
7
7
|
import { DOMAIN_COLORS, DURATION_FAST_MS, DURATION_SLOW_MS } from '../constants';
|
|
8
|
+
export * from './searchQueryParser';
|
|
9
|
+
export * from './telemetry';
|
|
8
10
|
export const getDomainColor = (domain) => {
|
|
9
11
|
if (!domain)
|
|
10
12
|
return DOMAIN_COLORS[0];
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { NetworkLog } from '../types';
|
|
2
|
+
/**
|
|
3
|
+
* Parses query strings like `method:POST is:error slow:>1s status:200 auth`
|
|
4
|
+
* and checks whether a given NetworkLog matches all tokens.
|
|
5
|
+
*/
|
|
6
|
+
export declare function matchNetworkLogQuery(log: NetworkLog, searchQuery: string, routePath?: string): boolean;
|
|
@@ -0,0 +1,233 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Parses query strings like `method:POST is:error slow:>1s status:200 auth`
|
|
3
|
+
* and checks whether a given NetworkLog matches all tokens.
|
|
4
|
+
*/
|
|
5
|
+
export function matchNetworkLogQuery(log, searchQuery, routePath) {
|
|
6
|
+
if (!searchQuery || searchQuery.trim().length === 0)
|
|
7
|
+
return true;
|
|
8
|
+
const rawTokens = searchQuery
|
|
9
|
+
.trim()
|
|
10
|
+
.match(/(?:[^\s"']+|"[^"]*"|'[^']*')+/g) || [];
|
|
11
|
+
if (rawTokens.length === 0)
|
|
12
|
+
return true;
|
|
13
|
+
const methodStr = (log.method || '').toLowerCase();
|
|
14
|
+
const urlStr = (log.url || '').toLowerCase();
|
|
15
|
+
const statusNum = typeof log.status === 'number' ? log.status : parseInt(String(log.status || 0), 10);
|
|
16
|
+
const statusStr = String(log.status ?? '');
|
|
17
|
+
const durationNum = log.duration || 0;
|
|
18
|
+
const clientStr = (log.client || '').toLowerCase();
|
|
19
|
+
const reqStr = typeof log.request === 'string' ? log.request : JSON.stringify(log.request || '');
|
|
20
|
+
const resStr = typeof log.response === 'string' ? log.response : JSON.stringify(log.response || '');
|
|
21
|
+
const reqHeadersStr = JSON.stringify(log.requestHeaders || '').toLowerCase();
|
|
22
|
+
const resHeadersStr = JSON.stringify(log.responseHeaders || '').toLowerCase();
|
|
23
|
+
const pathStr = routePath ? routePath.toLowerCase() : '';
|
|
24
|
+
const fullSearchCorpus = [
|
|
25
|
+
methodStr,
|
|
26
|
+
urlStr,
|
|
27
|
+
statusStr,
|
|
28
|
+
pathStr,
|
|
29
|
+
clientStr,
|
|
30
|
+
reqStr.toLowerCase(),
|
|
31
|
+
resStr.toLowerCase(),
|
|
32
|
+
reqHeadersStr,
|
|
33
|
+
resHeadersStr,
|
|
34
|
+
].join(' ');
|
|
35
|
+
for (const rawToken of rawTokens) {
|
|
36
|
+
const token = rawToken.replace(/^["']|["']$/g, '').trim();
|
|
37
|
+
if (!token)
|
|
38
|
+
continue;
|
|
39
|
+
const lowerToken = token.toLowerCase();
|
|
40
|
+
// 1. method:<VAL> or m:<VAL>
|
|
41
|
+
if (lowerToken.startsWith('method:') || lowerToken.startsWith('m:')) {
|
|
42
|
+
const targetMethod = lowerToken.replace(/^(method:|m:)/, '').trim();
|
|
43
|
+
if (targetMethod.startsWith('!')) {
|
|
44
|
+
if (methodStr === targetMethod.slice(1))
|
|
45
|
+
return false;
|
|
46
|
+
}
|
|
47
|
+
else {
|
|
48
|
+
if (methodStr !== targetMethod)
|
|
49
|
+
return false;
|
|
50
|
+
}
|
|
51
|
+
continue;
|
|
52
|
+
}
|
|
53
|
+
// 2. status:<VAL> or s:<VAL>
|
|
54
|
+
if (lowerToken.startsWith('status:') || lowerToken.startsWith('s:')) {
|
|
55
|
+
const val = lowerToken.replace(/^(status:|s:)/, '').trim();
|
|
56
|
+
if (val.startsWith('>=')) {
|
|
57
|
+
const threshold = parseInt(val.slice(2), 10);
|
|
58
|
+
if (isNaN(threshold) || statusNum < threshold)
|
|
59
|
+
return false;
|
|
60
|
+
}
|
|
61
|
+
else if (val.startsWith('>')) {
|
|
62
|
+
const threshold = parseInt(val.slice(1), 10);
|
|
63
|
+
if (isNaN(threshold) || statusNum <= threshold)
|
|
64
|
+
return false;
|
|
65
|
+
}
|
|
66
|
+
else if (val.startsWith('<=')) {
|
|
67
|
+
const threshold = parseInt(val.slice(2), 10);
|
|
68
|
+
if (isNaN(threshold) || statusNum > threshold)
|
|
69
|
+
return false;
|
|
70
|
+
}
|
|
71
|
+
else if (val.startsWith('<')) {
|
|
72
|
+
const threshold = parseInt(val.slice(1), 10);
|
|
73
|
+
if (isNaN(threshold) || statusNum >= threshold)
|
|
74
|
+
return false;
|
|
75
|
+
}
|
|
76
|
+
else if (val.endsWith('xx') || val.endsWith('x')) {
|
|
77
|
+
const prefix = val.replace(/x/g, '');
|
|
78
|
+
if (!statusStr.startsWith(prefix))
|
|
79
|
+
return false;
|
|
80
|
+
}
|
|
81
|
+
else {
|
|
82
|
+
const targetCode = parseInt(val, 10);
|
|
83
|
+
if (!isNaN(targetCode)) {
|
|
84
|
+
if (statusNum !== targetCode)
|
|
85
|
+
return false;
|
|
86
|
+
}
|
|
87
|
+
else if (!statusStr.includes(val)) {
|
|
88
|
+
return false;
|
|
89
|
+
}
|
|
90
|
+
}
|
|
91
|
+
continue;
|
|
92
|
+
}
|
|
93
|
+
// 3. is:<FLAG>
|
|
94
|
+
if (lowerToken.startsWith('is:')) {
|
|
95
|
+
const flag = lowerToken.slice(3).trim();
|
|
96
|
+
if (flag === 'error' || flag === 'failed' || flag === 'err' || flag === 'fail') {
|
|
97
|
+
const isErr = log.status === 0 || log.status == null || statusNum >= 400;
|
|
98
|
+
if (!isErr)
|
|
99
|
+
return false;
|
|
100
|
+
}
|
|
101
|
+
else if (flag === 'success' || flag === 'ok' || flag === '2xx') {
|
|
102
|
+
const isSuccess = statusNum >= 200 && statusNum < 300;
|
|
103
|
+
if (!isSuccess)
|
|
104
|
+
return false;
|
|
105
|
+
}
|
|
106
|
+
else if (flag === 'slow') {
|
|
107
|
+
if (durationNum < 1000)
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
else if (flag === 'fast') {
|
|
111
|
+
if (durationNum >= 200)
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
else if (flag === 'graphql' || flag === 'gql') {
|
|
115
|
+
const isGql = urlStr.includes('graphql') ||
|
|
116
|
+
clientStr === 'graphql' ||
|
|
117
|
+
clientStr === 'apollo';
|
|
118
|
+
if (!isGql)
|
|
119
|
+
return false;
|
|
120
|
+
}
|
|
121
|
+
else if (flag === 'https') {
|
|
122
|
+
if (!urlStr.startsWith('https'))
|
|
123
|
+
return false;
|
|
124
|
+
}
|
|
125
|
+
else if (flag === 'http') {
|
|
126
|
+
if (urlStr.startsWith('https') || !urlStr.startsWith('http'))
|
|
127
|
+
return false;
|
|
128
|
+
}
|
|
129
|
+
else if (flag === 'json') {
|
|
130
|
+
const isJson = reqHeadersStr.includes('application/json') ||
|
|
131
|
+
resHeadersStr.includes('application/json') ||
|
|
132
|
+
urlStr.includes('.json');
|
|
133
|
+
if (!isJson)
|
|
134
|
+
return false;
|
|
135
|
+
}
|
|
136
|
+
continue;
|
|
137
|
+
}
|
|
138
|
+
// 4. slow:<DURATION> or dur:<DURATION> or duration:<DURATION>
|
|
139
|
+
if (lowerToken.startsWith('slow:') ||
|
|
140
|
+
lowerToken.startsWith('dur:') ||
|
|
141
|
+
lowerToken.startsWith('duration:')) {
|
|
142
|
+
const val = lowerToken.replace(/^(slow:|dur:|duration:)/, '').trim();
|
|
143
|
+
let thresholdMs = 0;
|
|
144
|
+
let isGreater = true;
|
|
145
|
+
let cleanVal = val;
|
|
146
|
+
if (val.startsWith('>=')) {
|
|
147
|
+
isGreater = true;
|
|
148
|
+
cleanVal = val.slice(2);
|
|
149
|
+
}
|
|
150
|
+
else if (val.startsWith('>')) {
|
|
151
|
+
isGreater = true;
|
|
152
|
+
cleanVal = val.slice(1);
|
|
153
|
+
}
|
|
154
|
+
else if (val.startsWith('<=')) {
|
|
155
|
+
isGreater = false;
|
|
156
|
+
cleanVal = val.slice(2);
|
|
157
|
+
}
|
|
158
|
+
else if (val.startsWith('<')) {
|
|
159
|
+
isGreater = false;
|
|
160
|
+
cleanVal = val.slice(1);
|
|
161
|
+
}
|
|
162
|
+
if (cleanVal.endsWith('s') && !cleanVal.endsWith('ms')) {
|
|
163
|
+
thresholdMs = parseFloat(cleanVal.slice(0, -1)) * 1000;
|
|
164
|
+
}
|
|
165
|
+
else if (cleanVal.endsWith('ms')) {
|
|
166
|
+
thresholdMs = parseFloat(cleanVal.slice(0, -2));
|
|
167
|
+
}
|
|
168
|
+
else {
|
|
169
|
+
thresholdMs = parseFloat(cleanVal);
|
|
170
|
+
}
|
|
171
|
+
if (!isNaN(thresholdMs)) {
|
|
172
|
+
if (isGreater) {
|
|
173
|
+
if (durationNum < thresholdMs)
|
|
174
|
+
return false;
|
|
175
|
+
}
|
|
176
|
+
else {
|
|
177
|
+
if (durationNum > thresholdMs)
|
|
178
|
+
return false;
|
|
179
|
+
}
|
|
180
|
+
}
|
|
181
|
+
continue;
|
|
182
|
+
}
|
|
183
|
+
// 5. client:<CLIENT> or c:<CLIENT>
|
|
184
|
+
if (lowerToken.startsWith('client:') || lowerToken.startsWith('c:')) {
|
|
185
|
+
const targetClient = lowerToken.replace(/^(client:|c:)/, '').trim();
|
|
186
|
+
if (!clientStr.includes(targetClient))
|
|
187
|
+
return false;
|
|
188
|
+
continue;
|
|
189
|
+
}
|
|
190
|
+
// 6. domain:<DOMAIN> or d:<DOMAIN>
|
|
191
|
+
if (lowerToken.startsWith('domain:') || lowerToken.startsWith('d:')) {
|
|
192
|
+
const targetDomain = lowerToken.replace(/^(domain:|d:)/, '').trim();
|
|
193
|
+
if (!urlStr.includes(targetDomain))
|
|
194
|
+
return false;
|
|
195
|
+
continue;
|
|
196
|
+
}
|
|
197
|
+
// 7. path:<PATH> or p:<PATH>
|
|
198
|
+
if (lowerToken.startsWith('path:') || lowerToken.startsWith('p:')) {
|
|
199
|
+
const targetPath = lowerToken.replace(/^(path:|p:)/, '').trim();
|
|
200
|
+
if (!urlStr.includes(targetPath) && !pathStr.includes(targetPath)) {
|
|
201
|
+
return false;
|
|
202
|
+
}
|
|
203
|
+
continue;
|
|
204
|
+
}
|
|
205
|
+
// 8. req:<TERM> or body:<TERM>
|
|
206
|
+
if (lowerToken.startsWith('req:') || lowerToken.startsWith('body:')) {
|
|
207
|
+
const target = lowerToken.replace(/^(req:|body:)/, '').trim();
|
|
208
|
+
if (!reqStr.toLowerCase().includes(target))
|
|
209
|
+
return false;
|
|
210
|
+
continue;
|
|
211
|
+
}
|
|
212
|
+
// 9. res:<TERM>
|
|
213
|
+
if (lowerToken.startsWith('res:')) {
|
|
214
|
+
const target = lowerToken.slice(4).trim();
|
|
215
|
+
if (!resStr.toLowerCase().includes(target))
|
|
216
|
+
return false;
|
|
217
|
+
continue;
|
|
218
|
+
}
|
|
219
|
+
// 10. header:<TERM> or h:<TERM>
|
|
220
|
+
if (lowerToken.startsWith('header:') || lowerToken.startsWith('h:')) {
|
|
221
|
+
const target = lowerToken.replace(/^(header:|h:)/, '').trim();
|
|
222
|
+
if (!reqHeadersStr.includes(target) && !resHeadersStr.includes(target)) {
|
|
223
|
+
return false;
|
|
224
|
+
}
|
|
225
|
+
continue;
|
|
226
|
+
}
|
|
227
|
+
// 11. Generic Plain Substring Match
|
|
228
|
+
if (!fullSearchCorpus.includes(lowerToken)) {
|
|
229
|
+
return false;
|
|
230
|
+
}
|
|
231
|
+
}
|
|
232
|
+
return true;
|
|
233
|
+
}
|
|
@@ -101,19 +101,19 @@ export function getCustomStorage() {
|
|
|
101
101
|
export function calculateRamBasedLimits(freeRamMb) {
|
|
102
102
|
if (freeRamMb >= 3000) {
|
|
103
103
|
return {
|
|
104
|
-
maxNetworkLogs:
|
|
105
|
-
maxConsoleLogs:
|
|
106
|
-
maxAnalyticsEvents:
|
|
107
|
-
maxCrashRecords:
|
|
104
|
+
maxNetworkLogs: 100,
|
|
105
|
+
maxConsoleLogs: 100,
|
|
106
|
+
maxAnalyticsEvents: 75,
|
|
107
|
+
maxCrashRecords: 50,
|
|
108
108
|
profileName: 'High-End',
|
|
109
109
|
freeRamMb,
|
|
110
110
|
};
|
|
111
111
|
}
|
|
112
112
|
else if (freeRamMb >= 1500) {
|
|
113
113
|
return {
|
|
114
|
-
maxNetworkLogs:
|
|
115
|
-
maxConsoleLogs:
|
|
116
|
-
maxAnalyticsEvents:
|
|
114
|
+
maxNetworkLogs: 100,
|
|
115
|
+
maxConsoleLogs: 100,
|
|
116
|
+
maxAnalyticsEvents: 75,
|
|
117
117
|
maxCrashRecords: 50,
|
|
118
118
|
profileName: 'Standard',
|
|
119
119
|
freeRamMb,
|
|
@@ -121,9 +121,9 @@ export function calculateRamBasedLimits(freeRamMb) {
|
|
|
121
121
|
}
|
|
122
122
|
else if (freeRamMb >= 600) {
|
|
123
123
|
return {
|
|
124
|
-
maxNetworkLogs:
|
|
125
|
-
maxConsoleLogs:
|
|
126
|
-
maxAnalyticsEvents:
|
|
124
|
+
maxNetworkLogs: 100,
|
|
125
|
+
maxConsoleLogs: 100,
|
|
126
|
+
maxAnalyticsEvents: 50,
|
|
127
127
|
maxCrashRecords: 25,
|
|
128
128
|
profileName: 'Compact',
|
|
129
129
|
freeRamMb,
|
|
@@ -131,9 +131,9 @@ export function calculateRamBasedLimits(freeRamMb) {
|
|
|
131
131
|
}
|
|
132
132
|
else {
|
|
133
133
|
return {
|
|
134
|
-
maxNetworkLogs:
|
|
135
|
-
maxConsoleLogs:
|
|
136
|
-
maxAnalyticsEvents:
|
|
134
|
+
maxNetworkLogs: 50,
|
|
135
|
+
maxConsoleLogs: 50,
|
|
136
|
+
maxAnalyticsEvents: 25,
|
|
137
137
|
maxCrashRecords: 15,
|
|
138
138
|
profileName: 'Ultra-Light',
|
|
139
139
|
freeRamMb,
|
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
export declare const GA4_MEASUREMENT_ID = "G-XXXXXXXXXX";
|
|
2
|
+
export declare const GA4_API_SECRET = "YOUR_GA4_API_SECRET";
|
|
3
|
+
/**
|
|
4
|
+
* Asynchronously loads host application and device metadata (strictly non-PII/technical).
|
|
5
|
+
*/
|
|
6
|
+
export declare function loadAppDiagnosticsAsync(): Promise<Record<string, any>>;
|
|
7
|
+
/**
|
|
8
|
+
* Returns the developer's telemetry consent status.
|
|
9
|
+
*/
|
|
10
|
+
export declare function getTelemetryConsentStatus(): Promise<'granted' | 'declined' | 'undetermined'>;
|
|
11
|
+
/**
|
|
12
|
+
* Saves the developer's telemetry consent choice.
|
|
13
|
+
*/
|
|
14
|
+
export declare function setTelemetryConsent(granted: boolean): Promise<void>;
|
|
15
|
+
/**
|
|
16
|
+
* Checks if the user or environment has opted out of telemetry.
|
|
17
|
+
*/
|
|
18
|
+
export declare function isTelemetryOptedOut(explicitSetting?: boolean): boolean;
|
|
19
|
+
/**
|
|
20
|
+
* Track an anonymous event via GA4 Measurement Protocol.
|
|
21
|
+
*/
|
|
22
|
+
export declare function trackTelemetryEvent(eventName: string, params?: Record<string, any>, options?: {
|
|
23
|
+
telemetry?: boolean;
|
|
24
|
+
force?: boolean;
|
|
25
|
+
}): Promise<void>;
|
|
26
|
+
/**
|
|
27
|
+
* 1. Session initialization heartbeat ping.
|
|
28
|
+
*/
|
|
29
|
+
export declare function sendSessionTelemetryPing(options?: {
|
|
30
|
+
telemetry?: boolean;
|
|
31
|
+
environment?: string;
|
|
32
|
+
hasNavigation?: boolean;
|
|
33
|
+
hasAppIcon?: boolean;
|
|
34
|
+
force?: boolean;
|
|
35
|
+
}): Promise<void>;
|
|
36
|
+
/**
|
|
37
|
+
* 2. Track when the inspector modal is opened.
|
|
38
|
+
*/
|
|
39
|
+
export declare function trackInspectorOpen(options?: {
|
|
40
|
+
activeTab?: string;
|
|
41
|
+
openSource?: 'fab' | 'shake' | 'programmatic';
|
|
42
|
+
telemetry?: boolean;
|
|
43
|
+
}): void;
|
|
44
|
+
/**
|
|
45
|
+
* 3. Track when the inspector modal is closed.
|
|
46
|
+
*/
|
|
47
|
+
export declare function trackInspectorClose(options?: {
|
|
48
|
+
telemetry?: boolean;
|
|
49
|
+
}): void;
|
|
50
|
+
/**
|
|
51
|
+
* 4. Track tab / page view navigation inside the inspector.
|
|
52
|
+
*/
|
|
53
|
+
export declare function trackTabSwitch(tabName: string, options?: {
|
|
54
|
+
telemetry?: boolean;
|
|
55
|
+
fromTab?: string;
|
|
56
|
+
}): void;
|
|
57
|
+
/**
|
|
58
|
+
* 5. Track network API interaction (inspect details, copy cURL, retry).
|
|
59
|
+
*/
|
|
60
|
+
export declare function trackNetworkInteraction(action: 'view_detail' | 'copy_curl' | 'retry_request' | 'copy_url' | 'clear_logs' | 'export_har', options?: {
|
|
61
|
+
method?: string;
|
|
62
|
+
statusCode?: number;
|
|
63
|
+
durationMs?: number;
|
|
64
|
+
telemetry?: boolean;
|
|
65
|
+
}): void;
|
|
66
|
+
/**
|
|
67
|
+
* 6. Track Redux / State management interaction.
|
|
68
|
+
*/
|
|
69
|
+
export declare function trackReduxInteraction(action: 'view_diff' | 'view_state' | 'view_action' | 'filter_reducer', options?: {
|
|
70
|
+
reducerName?: string;
|
|
71
|
+
telemetry?: boolean;
|
|
72
|
+
}): void;
|
|
73
|
+
/**
|
|
74
|
+
* 7. Track Crash & Exception interaction.
|
|
75
|
+
*/
|
|
76
|
+
export declare function trackCrashInteraction(action: 'view_crash_detail' | 'share_crash_report' | 'copy_stacktrace' | 'clear_crashes', options?: {
|
|
77
|
+
crashType?: string;
|
|
78
|
+
telemetry?: boolean;
|
|
79
|
+
}): void;
|
|
80
|
+
/**
|
|
81
|
+
* 8. Track Performance monitoring tab interaction.
|
|
82
|
+
*/
|
|
83
|
+
export declare function trackPerformanceInteraction(subTab: 'fps' | 'memory' | 'rerenders' | 'bundles', options?: {
|
|
84
|
+
telemetry?: boolean;
|
|
85
|
+
}): void;
|
|
86
|
+
/**
|
|
87
|
+
* 9. Track search queries and filter applications.
|
|
88
|
+
*/
|
|
89
|
+
export declare function trackSearchOrFilter(target: 'apis' | 'console' | 'redux' | 'crashes' | 'analytics', actionType: 'search_query' | 'status_filter' | 'method_filter' | 'tag_filter', options?: {
|
|
90
|
+
filterValue?: string;
|
|
91
|
+
telemetry?: boolean;
|
|
92
|
+
}): void;
|
|
93
|
+
/**
|
|
94
|
+
* 10. Track when logs / reports are exported or shared.
|
|
95
|
+
*/
|
|
96
|
+
export declare function trackLogExport(exportType: 'logs_json' | 'logs_har' | 'curl' | 'crash_report', options?: {
|
|
97
|
+
telemetry?: boolean;
|
|
98
|
+
count?: number;
|
|
99
|
+
}): void;
|