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.
Files changed (95) hide show
  1. package/README.md +10 -0
  2. package/android/.gradle/8.9/checksums/checksums.lock +0 -0
  3. package/android/.gradle/8.9/checksums/md5-checksums.bin +0 -0
  4. package/android/.gradle/8.9/checksums/sha1-checksums.bin +0 -0
  5. package/android/.gradle/8.9/dependencies-accessors/gc.properties +0 -0
  6. package/android/.gradle/8.9/executionHistory/executionHistory.lock +0 -0
  7. package/android/.gradle/8.9/fileChanges/last-build.bin +0 -0
  8. package/android/.gradle/8.9/fileHashes/fileHashes.lock +0 -0
  9. package/android/.gradle/8.9/gc.properties +0 -0
  10. package/android/.gradle/9.2.0/checksums/checksums.lock +0 -0
  11. package/android/.gradle/9.2.0/fileChanges/last-build.bin +0 -0
  12. package/android/.gradle/9.2.0/fileHashes/fileHashes.bin +0 -0
  13. package/android/.gradle/9.2.0/fileHashes/fileHashes.lock +0 -0
  14. package/android/.gradle/9.2.0/gc.properties +0 -0
  15. package/android/.gradle/buildOutputCleanup/buildOutputCleanup.lock +0 -0
  16. package/android/.gradle/buildOutputCleanup/cache.properties +2 -0
  17. package/android/.gradle/vcs-1/gc.properties +0 -0
  18. package/android/build/reports/problems/problems-report.html +659 -0
  19. package/android/src/main/java/com/inappinspector/NetworkInspectorModule.kt +33 -24
  20. package/dist/commonjs/components/ConsoleLogCard.js +5 -5
  21. package/dist/commonjs/components/EndOfListFooter.js +1 -1
  22. package/dist/commonjs/components/Inspector/AnalyticsTab.js +19 -71
  23. package/dist/commonjs/components/Inspector/BundleTab.js +670 -188
  24. package/dist/commonjs/components/Inspector/ConsoleTab.js +109 -98
  25. package/dist/commonjs/components/Inspector/CrashTab.js +2 -1
  26. package/dist/commonjs/components/Inspector/InspectorHeader.js +102 -19
  27. package/dist/commonjs/components/Inspector/MainScreen.js +151 -17
  28. package/dist/commonjs/components/Inspector/NetworkTab.js +104 -20
  29. package/dist/commonjs/components/Inspector/SettingsPanel.js +1111 -1385
  30. package/dist/commonjs/components/Inspector/TabBar.js +3 -4
  31. package/dist/commonjs/components/Inspector/TelemetryConsentModal.d.ts +3 -0
  32. package/dist/commonjs/components/Inspector/TelemetryConsentModal.js +212 -0
  33. package/dist/commonjs/components/JsonViewer.js +9 -4
  34. package/dist/commonjs/components/LogCard.js +31 -1
  35. package/dist/commonjs/components/LogSyntaxHighlighter.d.ts +16 -0
  36. package/dist/commonjs/components/LogSyntaxHighlighter.js +130 -0
  37. package/dist/commonjs/components/NetworkIcons.d.ts +2 -0
  38. package/dist/commonjs/components/NetworkIcons.js +10 -1
  39. package/dist/commonjs/components/Slider.d.ts +13 -0
  40. package/dist/commonjs/components/Slider.js +261 -0
  41. package/dist/commonjs/constants/version.d.ts +1 -1
  42. package/dist/commonjs/constants/version.js +1 -1
  43. package/dist/commonjs/customHooks/analyticsLogger.js +1 -1
  44. package/dist/commonjs/customHooks/crashHandler.js +1 -1
  45. package/dist/commonjs/helpers/index.d.ts +2 -0
  46. package/dist/commonjs/helpers/index.js +16 -0
  47. package/dist/commonjs/helpers/searchQueryParser.d.ts +6 -0
  48. package/dist/commonjs/helpers/searchQueryParser.js +236 -0
  49. package/dist/commonjs/helpers/settingsStore.js +13 -13
  50. package/dist/commonjs/helpers/telemetry.d.ts +99 -0
  51. package/dist/commonjs/helpers/telemetry.js +398 -0
  52. package/dist/commonjs/index.d.ts +2 -0
  53. package/dist/commonjs/index.js +30 -21
  54. package/dist/commonjs/native/NativeInspector.d.ts +5 -0
  55. package/dist/commonjs/native/NativeInspector.js +3 -2
  56. package/dist/commonjs/styles/index.js +35 -35
  57. package/dist/esm/components/ConsoleLogCard.js +5 -5
  58. package/dist/esm/components/EndOfListFooter.js +2 -2
  59. package/dist/esm/components/Inspector/AnalyticsTab.js +21 -73
  60. package/dist/esm/components/Inspector/BundleTab.js +670 -188
  61. package/dist/esm/components/Inspector/ConsoleTab.js +110 -99
  62. package/dist/esm/components/Inspector/CrashTab.js +2 -1
  63. package/dist/esm/components/Inspector/InspectorHeader.js +103 -20
  64. package/dist/esm/components/Inspector/MainScreen.js +119 -18
  65. package/dist/esm/components/Inspector/NetworkTab.js +105 -21
  66. package/dist/esm/components/Inspector/SettingsPanel.js +1114 -1388
  67. package/dist/esm/components/Inspector/TabBar.js +4 -5
  68. package/dist/esm/components/Inspector/TelemetryConsentModal.d.ts +3 -0
  69. package/dist/esm/components/Inspector/TelemetryConsentModal.js +175 -0
  70. package/dist/esm/components/JsonViewer.js +9 -4
  71. package/dist/esm/components/LogCard.js +32 -2
  72. package/dist/esm/components/LogSyntaxHighlighter.d.ts +16 -0
  73. package/dist/esm/components/LogSyntaxHighlighter.js +123 -0
  74. package/dist/esm/components/NetworkIcons.d.ts +2 -0
  75. package/dist/esm/components/NetworkIcons.js +7 -0
  76. package/dist/esm/components/Slider.d.ts +13 -0
  77. package/dist/esm/components/Slider.js +222 -0
  78. package/dist/esm/constants/version.d.ts +1 -1
  79. package/dist/esm/constants/version.js +1 -1
  80. package/dist/esm/customHooks/analyticsLogger.js +1 -1
  81. package/dist/esm/customHooks/crashHandler.js +1 -1
  82. package/dist/esm/helpers/index.d.ts +2 -0
  83. package/dist/esm/helpers/index.js +2 -0
  84. package/dist/esm/helpers/searchQueryParser.d.ts +6 -0
  85. package/dist/esm/helpers/searchQueryParser.js +233 -0
  86. package/dist/esm/helpers/settingsStore.js +13 -13
  87. package/dist/esm/helpers/telemetry.d.ts +99 -0
  88. package/dist/esm/helpers/telemetry.js +380 -0
  89. package/dist/esm/index.d.ts +2 -0
  90. package/dist/esm/index.js +20 -21
  91. package/dist/esm/native/NativeInspector.d.ts +5 -0
  92. package/dist/esm/native/NativeInspector.js +3 -2
  93. package/dist/esm/styles/index.js +35 -35
  94. package/ios/{NetworkInspectorModule.m → NetworkInspectorModule.mm} +193 -97
  95. 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.0";
1
+ export declare const LIB_VERSION = "2.0.2";
@@ -1,3 +1,3 @@
1
1
  // AUTO-GENERATED FILE — do not edit by hand.
2
2
  // Regenerated from package.json on every build by scripts/gen-version.js.
3
- export const LIB_VERSION = '2.0.0';
3
+ export 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, 200);
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 = 100;
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: 1000,
105
- maxConsoleLogs: 1500,
106
- maxAnalyticsEvents: 500,
107
- maxCrashRecords: 100,
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: 500,
115
- maxConsoleLogs: 750,
116
- maxAnalyticsEvents: 250,
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: 200,
125
- maxConsoleLogs: 300,
126
- maxAnalyticsEvents: 100,
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: 100,
135
- maxConsoleLogs: 150,
136
- maxAnalyticsEvents: 50,
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;