react-native-debug-toolkit 3.2.5 → 3.2.7

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.
@@ -17,6 +17,7 @@ import com.facebook.react.bridge.UiThreadUtil;
17
17
  import com.facebook.react.bridge.WritableMap;
18
18
 
19
19
  import java.lang.reflect.Method;
20
+ import java.lang.reflect.Proxy;
20
21
  import java.net.Inet4Address;
21
22
  import java.net.InetAddress;
22
23
  import java.net.NetworkInterface;
@@ -24,7 +25,9 @@ import java.util.Enumeration;
24
25
 
25
26
  public class DebugToolkitDevConnectModule extends ReactContextBaseJavaModule {
26
27
  private static final String MODULE_NAME = "DebugToolkitDevConnect";
28
+ private static final String BUNDLE_ROOT = "index";
27
29
  private static final String DEBUG_SERVER_HOST_KEY = "debug_http_host";
30
+ private static final String KOTLIN_FUNCTION1_CLASS = "kotlin.jvm.functions.Function1";
28
31
  private static final String APPLY_RELOAD_REASON = "DebugToolkit DevConnect Metro host changed";
29
32
  private static final String RESET_RELOAD_REASON = "DebugToolkit DevConnect Metro host reset";
30
33
 
@@ -69,6 +72,46 @@ public class DebugToolkitDevConnectModule extends ReactContextBaseJavaModule {
69
72
  setter.invoke(packagerConnectionSettings, hostPort);
70
73
  }
71
74
 
75
+ private boolean setReactHostBundleSource(Object reactHost, String hostPort) throws Exception {
76
+ if (hostPort.length() == 0) {
77
+ return false;
78
+ }
79
+
80
+ try {
81
+ Class<?> function1Class = Class.forName(KOTLIN_FUNCTION1_CLASS);
82
+ Method setBundleSourceMethod = reactHost.getClass().getMethod(
83
+ "setBundleSource",
84
+ String.class,
85
+ String.class,
86
+ function1Class
87
+ );
88
+ Object queryMapper = Proxy.newProxyInstance(
89
+ function1Class.getClassLoader(),
90
+ new Class<?>[] { function1Class },
91
+ (proxy, method, args) -> {
92
+ String methodName = method.getName();
93
+ if ("invoke".equals(methodName)) {
94
+ return args != null && args.length > 0 ? args[0] : null;
95
+ }
96
+ if ("toString".equals(methodName)) {
97
+ return "DebugToolkitIdentityQueryMapper";
98
+ }
99
+ if ("hashCode".equals(methodName)) {
100
+ return System.identityHashCode(proxy);
101
+ }
102
+ if ("equals".equals(methodName)) {
103
+ return proxy == (args != null && args.length > 0 ? args[0] : null);
104
+ }
105
+ return null;
106
+ }
107
+ );
108
+ setBundleSourceMethod.invoke(reactHost, hostPort, BUNDLE_ROOT, queryMapper);
109
+ return true;
110
+ } catch (ClassNotFoundException | NoSuchMethodException ignored) {
111
+ return false;
112
+ }
113
+ }
114
+
72
115
  private boolean triggerDevSupportReload(
73
116
  @Nullable Object devSupportManager,
74
117
  String hostPort
@@ -98,6 +141,10 @@ public class DebugToolkitDevConnectModule extends ReactContextBaseJavaModule {
98
141
  return false;
99
142
  }
100
143
 
144
+ if (setReactHostBundleSource(reactHost, hostPort)) {
145
+ return true;
146
+ }
147
+
101
148
  if (triggerDevSupportReload(callGetter(reactHost, "getDevSupportManager"), hostPort)) {
102
149
  return true;
103
150
  }
@@ -2,6 +2,7 @@
2
2
  #import <React/RCTBundleManager.h>
3
3
  #import <React/RCTBridgeModule.h>
4
4
  #import <React/RCTBundleURLProvider.h>
5
+ #import <React/RCTDefines.h>
5
6
  #import <React/RCTReloadCommand.h>
6
7
  #include <ifaddrs.h>
7
8
  #include <arpa/inet.h>
@@ -23,21 +24,9 @@ RCT_EXPORT_MODULE(DebugToolkitDevConnect)
23
24
  return NO;
24
25
  }
25
26
 
26
- - (void)applyBundleURL:(NSURL *)bundleURL
27
- reason:(NSString *)reason
28
- result:(id)result
29
- resolve:(RCTPromiseResolveBlock)resolve
27
+ - (dispatch_queue_t)methodQueue
30
28
  {
31
- dispatch_async(dispatch_get_main_queue(), ^{
32
- if (bundleURL) {
33
- if (self->_bundleManager) {
34
- self->_bundleManager.bundleURL = bundleURL;
35
- }
36
- RCTReloadCommandSetBundleURL(bundleURL);
37
- }
38
- resolve(result ?: [NSNull null]);
39
- RCTTriggerReloadCommandListeners(reason);
40
- });
29
+ return dispatch_get_main_queue();
41
30
  }
42
31
 
43
32
  RCT_EXPORT_METHOD(getMetroHost:(RCTPromiseResolveBlock)resolve
@@ -56,12 +45,46 @@ RCT_EXPORT_METHOD(applyMetroHost:(NSString *)hostPort
56
45
  return;
57
46
  }
58
47
 
59
- [RCTBundleURLProvider sharedSettings].jsLocation = hostPort;
60
- NSURL *bundleURL = [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:DebugToolkitBundleRoot];
61
- [self applyBundleURL:bundleURL
62
- reason:@"DebugToolkit DevConnect Metro host changed"
63
- result:@{ @"hostPort" : hostPort }
64
- resolve:resolve];
48
+ RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
49
+ NSRange separator = [hostPort rangeOfString:@":" options:NSBackwardsSearch];
50
+ NSString *host = separator.location == NSNotFound ? hostPort : [hostPort substringToIndex:separator.location];
51
+ NSString *port = separator.location == NSNotFound ? @"" : [hostPort substringFromIndex:separator.location + 1];
52
+
53
+ if (host.length == 0 && port.length == 0) {
54
+ [self resetMetroHost:resolve rejecter:reject];
55
+ return;
56
+ }
57
+
58
+ NSNumberFormatter *formatter = [NSNumberFormatter new];
59
+ formatter.numberStyle = NSNumberFormatterDecimalStyle;
60
+ NSNumber *portNumber = [formatter numberFromString:port];
61
+ if (portNumber == nil) {
62
+ portNumber = [NSNumber numberWithInt:RCT_METRO_PORT];
63
+ }
64
+
65
+ NSString *normalizedHostPort = [NSString stringWithFormat:@"%@:%d", host, portNumber.intValue];
66
+ settings.jsLocation = normalizedHostPort;
67
+
68
+ if (DebugToolkitBundleRoot.length == 0) {
69
+ if (_bundleManager) {
70
+ [_bundleManager resetBundleURL];
71
+ }
72
+ } else {
73
+ NSURL *bundleURL = [settings jsBundleURLForBundleRoot:DebugToolkitBundleRoot];
74
+ if (_bundleManager) {
75
+ _bundleManager.bundleURL = bundleURL;
76
+ } else {
77
+ RCTReloadCommandSetBundleURL(bundleURL);
78
+ }
79
+ }
80
+
81
+ NSMutableDictionary *result = [@{@"hostPort" : normalizedHostPort} mutableCopy];
82
+ if (_bundleManager && _bundleManager.bundleURL.absoluteString) {
83
+ result[@"bundleURL"] = _bundleManager.bundleURL.absoluteString;
84
+ }
85
+
86
+ RCTTriggerReloadCommandListeners(@"DevConnect - apply changes");
87
+ resolve(result);
65
88
  }
66
89
 
67
90
  RCT_EXPORT_METHOD(resetMetroHost:(RCTPromiseResolveBlock)resolve
@@ -69,10 +92,13 @@ RCT_EXPORT_METHOD(resetMetroHost:(RCTPromiseResolveBlock)resolve
69
92
  {
70
93
  [[RCTBundleURLProvider sharedSettings] resetToDefaults];
71
94
  NSURL *bundleURL = [[RCTBundleURLProvider sharedSettings] jsBundleURLForFallbackExtension:nil];
72
- [self applyBundleURL:bundleURL
73
- reason:@"DebugToolkit DevConnect Metro host reset"
74
- result:[NSNull null]
75
- resolve:resolve];
95
+ if (_bundleManager) {
96
+ _bundleManager.bundleURL = bundleURL;
97
+ } else {
98
+ RCTReloadCommandSetBundleURL(bundleURL);
99
+ }
100
+ RCTTriggerReloadCommandListeners(@"DevConnect - reset to default");
101
+ resolve([NSNull null]);
76
102
  }
77
103
 
78
104
  RCT_EXPORT_METHOD(getPreference:(NSString *)key
@@ -108,7 +134,6 @@ RCT_EXPORT_METHOD(getLocalIp:(RCTPromiseResolveBlock)resolve
108
134
  {
109
135
  struct ifaddrs *interfaces = NULL;
110
136
  if (getifaddrs(&interfaces) == 0) {
111
- // First pass: prefer Wi-Fi interface (en0)
112
137
  struct ifaddrs *iface = interfaces;
113
138
  while (iface != NULL) {
114
139
  if (iface->ifa_addr->sa_family == AF_INET && !(iface->ifa_flags & IFF_LOOPBACK)) {
@@ -124,7 +149,6 @@ RCT_EXPORT_METHOD(getLocalIp:(RCTPromiseResolveBlock)resolve
124
149
  }
125
150
  iface = iface->ifa_next;
126
151
  }
127
- // Second pass: any non-loopback IPv4
128
152
  iface = interfaces;
129
153
  while (iface != NULL) {
130
154
  if (iface->ifa_addr->sa_family == AF_INET && !(iface->ifa_flags & IFF_LOOPBACK)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-debug-toolkit",
3
- "version": "3.2.5",
3
+ "version": "3.2.7",
4
4
  "description": "A local-first React Native debug toolkit with Web Console, HTTP API, and MCP support for AI-readable app logs",
5
5
  "main": "lib/commonjs/index.js",
6
6
  "module": "lib/module/index.js",