react-native-inapp-inspector 1.1.23 → 1.1.24

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.
@@ -762,6 +762,21 @@ const BundleTab = react_1.default.memo(() => {
762
762
  </react_native_1.View>
763
763
  </react_native_1.View>
764
764
 
765
+ {/* Live analysis unavailable warning */}
766
+ {analysis && !analysis.isLive && (<react_native_1.View style={bundleStyles.liveWarningCard}>
767
+ <react_native_1.View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
768
+ <NetworkIcons_1.CircleAlertIcon color={AppColors_1.AppColors.amber700} size={16}/>
769
+ <react_native_1.View style={{ flex: 1 }}>
770
+ <react_native_1.Text style={bundleStyles.liveWarningTitle}>
771
+ {t('bundle.liveAnalysisUnavailable')}
772
+ </react_native_1.Text>
773
+ <react_native_1.Text style={bundleStyles.liveWarningDesc}>
774
+ {t('bundle.liveAnalysisUnavailableSub')}
775
+ </react_native_1.Text>
776
+ </react_native_1.View>
777
+ </react_native_1.View>
778
+ </react_native_1.View>)}
779
+
765
780
  {/* Development Bundle Split-Up (derived from the real running bundle) */}
766
781
  {analysis && (<react_native_1.View style={bundleStyles.sectionCard}>
767
782
  <react_native_1.View style={bundleStyles.sectionHeaderRow}>
@@ -2233,6 +2248,28 @@ const bundleStyles = react_native_1.StyleSheet.create({
2233
2248
  borderWidth: 1,
2234
2249
  borderColor: AppColors_1.AppColors.errorBorder,
2235
2250
  },
2251
+ liveWarningCard: {
2252
+ flexDirection: 'row',
2253
+ alignItems: 'center',
2254
+ backgroundColor: AppColors_1.AppColors.amber100,
2255
+ borderWidth: 1,
2256
+ borderColor: AppColors_1.AppColors.amber200,
2257
+ borderRadius: 10,
2258
+ padding: 12,
2259
+ marginBottom: 12,
2260
+ },
2261
+ liveWarningTitle: {
2262
+ fontFamily: AppFonts_1.AppFonts.interBold,
2263
+ fontSize: 12,
2264
+ color: AppColors_1.AppColors.amber800Warm,
2265
+ marginBottom: 2,
2266
+ },
2267
+ liveWarningDesc: {
2268
+ fontFamily: AppFonts_1.AppFonts.interRegular,
2269
+ fontSize: 10.5,
2270
+ lineHeight: 14,
2271
+ color: AppColors_1.AppColors.amber800Warm,
2272
+ },
2236
2273
  adviceBadge: {
2237
2274
  paddingHorizontal: 8,
2238
2275
  paddingVertical: 4,
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.1.23";
1
+ export declare const LIB_VERSION = "1.1.24";
@@ -3,4 +3,4 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.LIB_VERSION = void 0;
4
4
  // AUTO-GENERATED FILE — do not edit by hand.
5
5
  // Regenerated from package.json on every build by scripts/gen-version.js.
6
- exports.LIB_VERSION = '1.1.23';
6
+ exports.LIB_VERSION = '1.1.24';
@@ -107,7 +107,7 @@ export declare const getHostScriptURL: () => string;
107
107
  /**
108
108
  * Parses raw Metro bundle source code to discover real modules and packages in the host app.
109
109
  */
110
- export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string) => HostBundleAnalysisResult;
110
+ export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string, isLive?: boolean) => HostBundleAnalysisResult;
111
111
  /**
112
112
  * Automatically fetch and analyze the real running bundle for the host app.
113
113
  */
@@ -15,20 +15,88 @@ const react_native_1 = require("react-native");
15
15
  let cachedAnalysis = null;
16
16
  let isAnalyzing = false;
17
17
  const subscribers = [];
18
+ const getSourceCodeModule = () => {
19
+ try {
20
+ const legacy = react_native_1.NativeModules?.SourceCode;
21
+ if (legacy && typeof legacy.scriptURL === 'string' && legacy.scriptURL.length > 0) {
22
+ return legacy;
23
+ }
24
+ }
25
+ catch { }
26
+ try {
27
+ const turbo = react_native_1.TurboModuleRegistry?.get?.('SourceCode');
28
+ const constants = turbo?.getConstants?.();
29
+ const scriptURL = turbo?.scriptURL || constants?.scriptURL;
30
+ if (typeof scriptURL === 'string' && scriptURL.length > 0) {
31
+ return { scriptURL };
32
+ }
33
+ }
34
+ catch { }
35
+ return null;
36
+ };
18
37
  const getHostScriptURL = () => {
19
- const SourceCode = react_native_1.NativeModules?.SourceCode;
20
- if (SourceCode && typeof SourceCode.scriptURL === 'string' && SourceCode.scriptURL.length > 0) {
21
- return SourceCode.scriptURL;
38
+ // 1. NativeModules.SourceCode (bridged) or SourceCode TurboModule (bridgeless / new arch)
39
+ const scriptURL = getSourceCodeModule()?.scriptURL;
40
+ if (typeof scriptURL === 'string' && scriptURL.length > 0) {
41
+ return scriptURL;
22
42
  }
23
- return react_native_1.Platform.OS === 'ios'
24
- ? 'http://localhost:8081/index.bundle?platform=ios&dev=true'
25
- : 'http://10.0.2.2:8081/index.bundle?platform=android&dev=true';
43
+ // 2. Android legacy: PlatformConstants.serverHost -> "localhost:8082"
44
+ try {
45
+ const serverHost = react_native_1.NativeModules?.PlatformConstants?.serverHost;
46
+ if (typeof serverHost === 'string' && serverHost.length > 0) {
47
+ return `http://${serverHost}/index.bundle?platform=${react_native_1.Platform.OS}&dev=true`;
48
+ }
49
+ }
50
+ catch { }
51
+ return '';
26
52
  };
27
53
  exports.getHostScriptURL = getHostScriptURL;
54
+ const DEV_SERVER_PORTS = [8081, 8082, 8083, 8084, 8090, 8080, 19000];
55
+ const buildProbeUrls = (scriptURL) => {
56
+ const urls = [];
57
+ if (typeof scriptURL === 'string' && scriptURL.startsWith('http')) {
58
+ urls.push(scriptURL);
59
+ }
60
+ const portMatch = typeof scriptURL === 'string' ? scriptURL.match(/:(\d{2,5})/) : null;
61
+ const ports = portMatch ? [parseInt(portMatch[1], 10)] : DEV_SERVER_PORTS;
62
+ const hosts = react_native_1.Platform.OS === 'android'
63
+ ? ['localhost', '127.0.0.1', '10.0.2.2']
64
+ : ['localhost', '127.0.0.1'];
65
+ for (const host of hosts) {
66
+ for (const port of ports) {
67
+ urls.push(`http://${host}:${port}/index.bundle?platform=${react_native_1.Platform.OS}&dev=true`);
68
+ }
69
+ }
70
+ return Array.from(new Set(urls));
71
+ };
72
+ const fetchWithTimeout = async (url, timeoutMs) => {
73
+ try {
74
+ const controller = new AbortController();
75
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
76
+ try {
77
+ const res = await fetch(url, { signal: controller.signal });
78
+ if (!res.ok)
79
+ return { ok: false };
80
+ const contentLength = res.headers.get('content-length');
81
+ const text = await res.text();
82
+ return {
83
+ ok: true,
84
+ text,
85
+ bytes: contentLength ? parseInt(contentLength, 10) || text.length : text.length,
86
+ };
87
+ }
88
+ finally {
89
+ clearTimeout(timer);
90
+ }
91
+ }
92
+ catch {
93
+ return { ok: false };
94
+ }
95
+ };
28
96
  /**
29
97
  * Parses raw Metro bundle source code to discover real modules and packages in the host app.
30
98
  */
31
- const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
99
+ const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) => {
32
100
  const isHermes = Boolean(globalThis.HermesInternal);
33
101
  const totalDevMb = Number((totalBytes / (1024 * 1024)).toFixed(2));
34
102
  const totalDevKb = Math.round(totalBytes / 1024);
@@ -451,7 +519,7 @@ const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
451
519
  },
452
520
  ];
453
521
  return {
454
- isLive: true,
522
+ isLive,
455
523
  scriptURL,
456
524
  totalDevBytes: totalBytes,
457
525
  totalDevMb,
@@ -526,30 +594,29 @@ const analyzeHostAppBundle = async () => {
526
594
  }
527
595
  isAnalyzing = true;
528
596
  const scriptURL = (0, exports.getHostScriptURL)();
529
- try {
530
- if (scriptURL && scriptURL.startsWith('http')) {
531
- // 1. Try HEAD request first for fast content-length
532
- const headRes = await fetch(scriptURL, { method: 'HEAD' });
533
- const cl = headRes.headers.get('content-length');
534
- let byteLength = cl ? parseInt(cl, 10) : 0;
535
- // 2. Fetch partial text to discover real modules
536
- const getRes = await fetch(scriptURL);
537
- const bundleText = await getRes.text();
538
- byteLength = byteLength || bundleText.length;
539
- const result = (0, exports.parseBundleSource)(bundleText, byteLength, scriptURL);
540
- cachedAnalysis = result;
541
- isAnalyzing = false;
542
- subscribers.forEach(cb => cb(result));
543
- subscribers.length = 0;
544
- return result;
597
+ // Probe candidate dev-server URLs until one serves the JS bundle
598
+ let fetched = null;
599
+ let fetchedUrl = '';
600
+ for (const url of buildProbeUrls(scriptURL)) {
601
+ const probe = await fetchWithTimeout(url, 3000);
602
+ if (probe.ok && probe.text && probe.text.length > 0) {
603
+ fetched = { text: probe.text, bytes: probe.bytes ?? probe.text.length };
604
+ fetchedUrl = url;
605
+ break;
545
606
  }
546
607
  }
547
- catch (err) {
548
- // If fetch failed (e.g. standalone production build or offline)
608
+ if (fetched) {
609
+ const result = (0, exports.parseBundleSource)(fetched.text, fetched.bytes, fetchedUrl);
610
+ cachedAnalysis = result;
611
+ isAnalyzing = false;
612
+ subscribers.forEach(cb => cb(result));
613
+ subscribers.length = 0;
614
+ return result;
549
615
  }
550
- // Fallback to runtime memory estimation
616
+ // Fallback: could not reach a Metro dev server (release build, offline, or
617
+ // custom dev-server host). Return estimated values so the UI never crashes.
551
618
  const fallbackBytes = 6840000; // ~6.8MB standard RN dev bundle
552
- const result = (0, exports.parseBundleSource)('', fallbackBytes, scriptURL);
619
+ const result = (0, exports.parseBundleSource)('', fallbackBytes, scriptURL || 'unknown', false);
553
620
  cachedAnalysis = result;
554
621
  isAnalyzing = false;
555
622
  subscribers.forEach(cb => cb(result));
@@ -355,6 +355,8 @@
355
355
  "heroTitle": "Bundle & Asset Architecture",
356
356
  "heroSubtitle": "Real-time size breakdown across all assets, code, and dependencies",
357
357
  "heroSubtitleLive": "Live analysis of {{scriptUrl}}",
358
+ "liveAnalysisUnavailable": "Live bundle analysis unavailable",
359
+ "liveAnalysisUnavailableSub": "Could not reach the Metro dev server, so values are estimates. Make sure the app runs in development via `npx react-native start` and the Inspector can reach your Metro port (8081, 8082, ...).",
358
360
  "bundleOverviewJson": "Bundle Overview JSON",
359
361
  "devBundleSize": "DEV BUNDLE SIZE",
360
362
  "devBundleHint": "{{kb}} KB • {{modules}} modules",
@@ -724,6 +724,21 @@ const BundleTab = React.memo(() => {
724
724
  </View>
725
725
  </View>
726
726
 
727
+ {/* Live analysis unavailable warning */}
728
+ {analysis && !analysis.isLive && (<View style={bundleStyles.liveWarningCard}>
729
+ <View style={{ flexDirection: 'row', alignItems: 'center', gap: 6, flex: 1 }}>
730
+ <CircleAlertIcon color={AppColors.amber700} size={16}/>
731
+ <View style={{ flex: 1 }}>
732
+ <Text style={bundleStyles.liveWarningTitle}>
733
+ {t('bundle.liveAnalysisUnavailable')}
734
+ </Text>
735
+ <Text style={bundleStyles.liveWarningDesc}>
736
+ {t('bundle.liveAnalysisUnavailableSub')}
737
+ </Text>
738
+ </View>
739
+ </View>
740
+ </View>)}
741
+
727
742
  {/* Development Bundle Split-Up (derived from the real running bundle) */}
728
743
  {analysis && (<View style={bundleStyles.sectionCard}>
729
744
  <View style={bundleStyles.sectionHeaderRow}>
@@ -2195,6 +2210,28 @@ const bundleStyles = StyleSheet.create({
2195
2210
  borderWidth: 1,
2196
2211
  borderColor: AppColors.errorBorder,
2197
2212
  },
2213
+ liveWarningCard: {
2214
+ flexDirection: 'row',
2215
+ alignItems: 'center',
2216
+ backgroundColor: AppColors.amber100,
2217
+ borderWidth: 1,
2218
+ borderColor: AppColors.amber200,
2219
+ borderRadius: 10,
2220
+ padding: 12,
2221
+ marginBottom: 12,
2222
+ },
2223
+ liveWarningTitle: {
2224
+ fontFamily: AppFonts.interBold,
2225
+ fontSize: 12,
2226
+ color: AppColors.amber800Warm,
2227
+ marginBottom: 2,
2228
+ },
2229
+ liveWarningDesc: {
2230
+ fontFamily: AppFonts.interRegular,
2231
+ fontSize: 10.5,
2232
+ lineHeight: 14,
2233
+ color: AppColors.amber800Warm,
2234
+ },
2198
2235
  adviceBadge: {
2199
2236
  paddingHorizontal: 8,
2200
2237
  paddingVertical: 4,
@@ -1 +1 @@
1
- export declare const LIB_VERSION = "1.1.23";
1
+ export declare const LIB_VERSION = "1.1.24";
@@ -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 = '1.1.23';
3
+ export const LIB_VERSION = '1.1.24';
@@ -107,7 +107,7 @@ export declare const getHostScriptURL: () => string;
107
107
  /**
108
108
  * Parses raw Metro bundle source code to discover real modules and packages in the host app.
109
109
  */
110
- export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string) => HostBundleAnalysisResult;
110
+ export declare const parseBundleSource: (bundleText: string, totalBytes: number, scriptURL: string, isLive?: boolean) => HostBundleAnalysisResult;
111
111
  /**
112
112
  * Automatically fetch and analyze the real running bundle for the host app.
113
113
  */
@@ -8,23 +8,91 @@ import { AppColors } from '../styles/AppColors';
8
8
  // 3. Extracting real module paths (project files vs node_modules dependencies).
9
9
  // 4. Computing real Development and Production Binary (.ipa / .aab / .apk) sizes.
10
10
  // ─────────────────────────────────────────────────────────────────────────────
11
- import { NativeModules, Platform } from 'react-native';
11
+ import { NativeModules, Platform, TurboModuleRegistry } from 'react-native';
12
12
  let cachedAnalysis = null;
13
13
  let isAnalyzing = false;
14
14
  const subscribers = [];
15
+ const getSourceCodeModule = () => {
16
+ try {
17
+ const legacy = NativeModules?.SourceCode;
18
+ if (legacy && typeof legacy.scriptURL === 'string' && legacy.scriptURL.length > 0) {
19
+ return legacy;
20
+ }
21
+ }
22
+ catch { }
23
+ try {
24
+ const turbo = TurboModuleRegistry?.get?.('SourceCode');
25
+ const constants = turbo?.getConstants?.();
26
+ const scriptURL = turbo?.scriptURL || constants?.scriptURL;
27
+ if (typeof scriptURL === 'string' && scriptURL.length > 0) {
28
+ return { scriptURL };
29
+ }
30
+ }
31
+ catch { }
32
+ return null;
33
+ };
15
34
  export const getHostScriptURL = () => {
16
- const SourceCode = NativeModules?.SourceCode;
17
- if (SourceCode && typeof SourceCode.scriptURL === 'string' && SourceCode.scriptURL.length > 0) {
18
- return SourceCode.scriptURL;
35
+ // 1. NativeModules.SourceCode (bridged) or SourceCode TurboModule (bridgeless / new arch)
36
+ const scriptURL = getSourceCodeModule()?.scriptURL;
37
+ if (typeof scriptURL === 'string' && scriptURL.length > 0) {
38
+ return scriptURL;
39
+ }
40
+ // 2. Android legacy: PlatformConstants.serverHost -> "localhost:8082"
41
+ try {
42
+ const serverHost = NativeModules?.PlatformConstants?.serverHost;
43
+ if (typeof serverHost === 'string' && serverHost.length > 0) {
44
+ return `http://${serverHost}/index.bundle?platform=${Platform.OS}&dev=true`;
45
+ }
46
+ }
47
+ catch { }
48
+ return '';
49
+ };
50
+ const DEV_SERVER_PORTS = [8081, 8082, 8083, 8084, 8090, 8080, 19000];
51
+ const buildProbeUrls = (scriptURL) => {
52
+ const urls = [];
53
+ if (typeof scriptURL === 'string' && scriptURL.startsWith('http')) {
54
+ urls.push(scriptURL);
55
+ }
56
+ const portMatch = typeof scriptURL === 'string' ? scriptURL.match(/:(\d{2,5})/) : null;
57
+ const ports = portMatch ? [parseInt(portMatch[1], 10)] : DEV_SERVER_PORTS;
58
+ const hosts = Platform.OS === 'android'
59
+ ? ['localhost', '127.0.0.1', '10.0.2.2']
60
+ : ['localhost', '127.0.0.1'];
61
+ for (const host of hosts) {
62
+ for (const port of ports) {
63
+ urls.push(`http://${host}:${port}/index.bundle?platform=${Platform.OS}&dev=true`);
64
+ }
65
+ }
66
+ return Array.from(new Set(urls));
67
+ };
68
+ const fetchWithTimeout = async (url, timeoutMs) => {
69
+ try {
70
+ const controller = new AbortController();
71
+ const timer = setTimeout(() => controller.abort(), timeoutMs);
72
+ try {
73
+ const res = await fetch(url, { signal: controller.signal });
74
+ if (!res.ok)
75
+ return { ok: false };
76
+ const contentLength = res.headers.get('content-length');
77
+ const text = await res.text();
78
+ return {
79
+ ok: true,
80
+ text,
81
+ bytes: contentLength ? parseInt(contentLength, 10) || text.length : text.length,
82
+ };
83
+ }
84
+ finally {
85
+ clearTimeout(timer);
86
+ }
87
+ }
88
+ catch {
89
+ return { ok: false };
19
90
  }
20
- return Platform.OS === 'ios'
21
- ? 'http://localhost:8081/index.bundle?platform=ios&dev=true'
22
- : 'http://10.0.2.2:8081/index.bundle?platform=android&dev=true';
23
91
  };
24
92
  /**
25
93
  * Parses raw Metro bundle source code to discover real modules and packages in the host app.
26
94
  */
27
- export const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
95
+ export const parseBundleSource = (bundleText, totalBytes, scriptURL, isLive = true) => {
28
96
  const isHermes = Boolean(globalThis.HermesInternal);
29
97
  const totalDevMb = Number((totalBytes / (1024 * 1024)).toFixed(2));
30
98
  const totalDevKb = Math.round(totalBytes / 1024);
@@ -447,7 +515,7 @@ export const parseBundleSource = (bundleText, totalBytes, scriptURL) => {
447
515
  },
448
516
  ];
449
517
  return {
450
- isLive: true,
518
+ isLive,
451
519
  scriptURL,
452
520
  totalDevBytes: totalBytes,
453
521
  totalDevMb,
@@ -521,30 +589,29 @@ export const analyzeHostAppBundle = async () => {
521
589
  }
522
590
  isAnalyzing = true;
523
591
  const scriptURL = getHostScriptURL();
524
- try {
525
- if (scriptURL && scriptURL.startsWith('http')) {
526
- // 1. Try HEAD request first for fast content-length
527
- const headRes = await fetch(scriptURL, { method: 'HEAD' });
528
- const cl = headRes.headers.get('content-length');
529
- let byteLength = cl ? parseInt(cl, 10) : 0;
530
- // 2. Fetch partial text to discover real modules
531
- const getRes = await fetch(scriptURL);
532
- const bundleText = await getRes.text();
533
- byteLength = byteLength || bundleText.length;
534
- const result = parseBundleSource(bundleText, byteLength, scriptURL);
535
- cachedAnalysis = result;
536
- isAnalyzing = false;
537
- subscribers.forEach(cb => cb(result));
538
- subscribers.length = 0;
539
- return result;
592
+ // Probe candidate dev-server URLs until one serves the JS bundle
593
+ let fetched = null;
594
+ let fetchedUrl = '';
595
+ for (const url of buildProbeUrls(scriptURL)) {
596
+ const probe = await fetchWithTimeout(url, 3000);
597
+ if (probe.ok && probe.text && probe.text.length > 0) {
598
+ fetched = { text: probe.text, bytes: probe.bytes ?? probe.text.length };
599
+ fetchedUrl = url;
600
+ break;
540
601
  }
541
602
  }
542
- catch (err) {
543
- // If fetch failed (e.g. standalone production build or offline)
603
+ if (fetched) {
604
+ const result = parseBundleSource(fetched.text, fetched.bytes, fetchedUrl);
605
+ cachedAnalysis = result;
606
+ isAnalyzing = false;
607
+ subscribers.forEach(cb => cb(result));
608
+ subscribers.length = 0;
609
+ return result;
544
610
  }
545
- // Fallback to runtime memory estimation
611
+ // Fallback: could not reach a Metro dev server (release build, offline, or
612
+ // custom dev-server host). Return estimated values so the UI never crashes.
546
613
  const fallbackBytes = 6840000; // ~6.8MB standard RN dev bundle
547
- const result = parseBundleSource('', fallbackBytes, scriptURL);
614
+ const result = parseBundleSource('', fallbackBytes, scriptURL || 'unknown', false);
548
615
  cachedAnalysis = result;
549
616
  isAnalyzing = false;
550
617
  subscribers.forEach(cb => cb(result));
@@ -355,6 +355,8 @@
355
355
  "heroTitle": "Bundle & Asset Architecture",
356
356
  "heroSubtitle": "Real-time size breakdown across all assets, code, and dependencies",
357
357
  "heroSubtitleLive": "Live analysis of {{scriptUrl}}",
358
+ "liveAnalysisUnavailable": "Live bundle analysis unavailable",
359
+ "liveAnalysisUnavailableSub": "Could not reach the Metro dev server, so values are estimates. Make sure the app runs in development via `npx react-native start` and the Inspector can reach your Metro port (8081, 8082, ...).",
358
360
  "bundleOverviewJson": "Bundle Overview JSON",
359
361
  "devBundleSize": "DEV BUNDLE SIZE",
360
362
  "devBundleHint": "{{kb}} KB • {{modules}} modules",
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-inapp-inspector",
3
- "version": "1.1.23",
3
+ "version": "1.1.24",
4
4
  "description": "The zero-config, all-in-one in-app debugger for React Native & Expo. Inspect Network (fetch/axios), Console logs, Stack Traces, Redux State, Firebase Analytics, and JS Bundle size directly on device.",
5
5
  "repository": {
6
6
  "type": "git",