react-native-debug-toolkit 3.2.6 → 3.2.8
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/ios/DebugToolkitDevConnect.mm +137 -88
- package/package.json +1 -1
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
#import <Foundation/Foundation.h>
|
|
2
|
+
#import <React/RCTBridge.h>
|
|
2
3
|
#import <React/RCTBundleManager.h>
|
|
3
4
|
#import <React/RCTBridgeModule.h>
|
|
4
5
|
#import <React/RCTBundleURLProvider.h>
|
|
@@ -17,6 +18,7 @@ static NSString *const DebugToolkitBundleRoot = @"index";
|
|
|
17
18
|
|
|
18
19
|
RCT_EXPORT_MODULE(DebugToolkitDevConnect)
|
|
19
20
|
|
|
21
|
+
@synthesize bridge = _bridge;
|
|
20
22
|
@synthesize bundleManager = _bundleManager;
|
|
21
23
|
|
|
22
24
|
+ (BOOL)requiresMainQueueSetup
|
|
@@ -24,100 +26,141 @@ RCT_EXPORT_MODULE(DebugToolkitDevConnect)
|
|
|
24
26
|
return NO;
|
|
25
27
|
}
|
|
26
28
|
|
|
27
|
-
- (
|
|
28
|
-
reason:(NSString *)reason
|
|
29
|
-
result:(id)result
|
|
30
|
-
resolve:(RCTPromiseResolveBlock)resolve
|
|
29
|
+
- (dispatch_queue_t)methodQueue
|
|
31
30
|
{
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
31
|
+
return dispatch_get_main_queue();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
#pragma mark - Bundle Manager Resolution
|
|
35
|
+
|
|
36
|
+
- (RCTBundleManager *)resolveBundleManager
|
|
37
|
+
{
|
|
38
|
+
if (_bundleManager) {
|
|
39
|
+
return _bundleManager;
|
|
40
|
+
}
|
|
41
|
+
if (_bridge) {
|
|
42
|
+
return [_bridge moduleForClass:[RCTBundleManager class]];
|
|
43
|
+
}
|
|
44
|
+
return nil;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
#pragma mark - Apply Bundle URL (multi-strategy)
|
|
48
|
+
|
|
49
|
+
- (BOOL)applyBundleURL:(NSURL *)bundleURL
|
|
50
|
+
{
|
|
51
|
+
RCTBundleManager *bm = [self resolveBundleManager];
|
|
52
|
+
if (bm) {
|
|
53
|
+
if (bundleURL) {
|
|
54
|
+
bm.bundleURL = bundleURL;
|
|
39
55
|
} else {
|
|
40
|
-
|
|
56
|
+
[bm resetBundleURL];
|
|
41
57
|
}
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
58
|
+
return YES;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
if (bundleURL) {
|
|
62
|
+
RCTReloadCommandSetBundleURL(bundleURL);
|
|
63
|
+
return YES;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
return NO;
|
|
45
67
|
}
|
|
46
68
|
|
|
69
|
+
#pragma mark - Exported Methods
|
|
70
|
+
|
|
47
71
|
RCT_EXPORT_METHOD(getMetroHost:(RCTPromiseResolveBlock)resolve
|
|
48
72
|
rejecter:(__unused RCTPromiseRejectBlock)reject)
|
|
49
73
|
{
|
|
50
|
-
|
|
51
|
-
|
|
74
|
+
@try {
|
|
75
|
+
NSString *host = [RCTBundleURLProvider sharedSettings].jsLocation;
|
|
76
|
+
resolve(host ?: [NSNull null]);
|
|
77
|
+
} @catch (NSException *exception) {
|
|
78
|
+
reject(@"native_error", exception.reason, nil);
|
|
79
|
+
}
|
|
52
80
|
}
|
|
53
81
|
|
|
54
82
|
RCT_EXPORT_METHOD(applyMetroHost:(NSString *)hostPort
|
|
55
83
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
56
84
|
rejecter:(RCTPromiseRejectBlock)reject)
|
|
57
85
|
{
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
86
|
+
@try {
|
|
87
|
+
if (hostPort.length == 0) {
|
|
88
|
+
reject(@"invalid_host", @"Metro host cannot be empty.", nil);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
62
91
|
|
|
63
|
-
|
|
64
|
-
NSRange separator = [hostPort rangeOfString:@":" options:NSBackwardsSearch];
|
|
65
|
-
NSString *host = separator.location == NSNotFound ? hostPort : [hostPort substringToIndex:separator.location];
|
|
66
|
-
NSString *port = separator.location == NSNotFound ? @"" : [hostPort substringFromIndex:separator.location + 1];
|
|
92
|
+
RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
|
|
67
93
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
94
|
+
NSRange separator = [hostPort rangeOfString:@":" options:NSBackwardsSearch];
|
|
95
|
+
NSString *host = separator.location == NSNotFound
|
|
96
|
+
? hostPort
|
|
97
|
+
: [hostPort substringToIndex:separator.location];
|
|
98
|
+
NSString *port = separator.location == NSNotFound
|
|
99
|
+
? @""
|
|
100
|
+
: [hostPort substringFromIndex:separator.location + 1];
|
|
72
101
|
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
102
|
+
if (host.length == 0 && port.length == 0) {
|
|
103
|
+
[self resetMetroHost:resolve rejecter:reject];
|
|
104
|
+
return;
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
NSNumberFormatter *formatter = [NSNumberFormatter new];
|
|
108
|
+
formatter.numberStyle = NSNumberFormatterDecimalStyle;
|
|
109
|
+
NSNumber *portNumber = [formatter numberFromString:port];
|
|
110
|
+
if (portNumber == nil) {
|
|
111
|
+
portNumber = [NSNumber numberWithInt:RCT_METRO_PORT];
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
NSString *normalizedHostPort = [NSString stringWithFormat:@"%@:%d", host, portNumber.intValue];
|
|
79
115
|
|
|
80
|
-
|
|
81
|
-
settings.jsLocation = normalizedHostPort;
|
|
116
|
+
settings.jsLocation = normalizedHostPort;
|
|
82
117
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
[_bundleManager resetBundleURL];
|
|
87
|
-
bundleURL = _bundleManager.bundleURL;
|
|
118
|
+
NSURL *bundleURL = nil;
|
|
119
|
+
if (DebugToolkitBundleRoot.length > 0) {
|
|
120
|
+
bundleURL = [settings jsBundleURLForBundleRoot:DebugToolkitBundleRoot];
|
|
88
121
|
}
|
|
89
|
-
} else {
|
|
90
|
-
bundleURL = [settings jsBundleURLForBundleRoot:DebugToolkitBundleRoot];
|
|
91
|
-
}
|
|
92
122
|
|
|
93
|
-
|
|
94
|
-
if (bundleURL.absoluteString) {
|
|
95
|
-
result[@"bundleURL"] = bundleURL.absoluteString;
|
|
96
|
-
}
|
|
123
|
+
[self applyBundleURL:bundleURL];
|
|
97
124
|
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
125
|
+
NSMutableDictionary *result = [@{@"hostPort" : normalizedHostPort} mutableCopy];
|
|
126
|
+
RCTBundleManager *bm = [self resolveBundleManager];
|
|
127
|
+
if (bm && bm.bundleURL.absoluteString) {
|
|
128
|
+
result[@"bundleURL"] = bm.bundleURL.absoluteString;
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
RCTTriggerReloadCommandListeners(@"Dev menu - apply changes");
|
|
132
|
+
resolve(result);
|
|
133
|
+
} @catch (NSException *exception) {
|
|
134
|
+
reject(@"native_error", exception.reason, nil);
|
|
135
|
+
}
|
|
102
136
|
}
|
|
103
137
|
|
|
104
138
|
RCT_EXPORT_METHOD(resetMetroHost:(RCTPromiseResolveBlock)resolve
|
|
105
139
|
rejecter:(__unused RCTPromiseRejectBlock)reject)
|
|
106
140
|
{
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
141
|
+
@try {
|
|
142
|
+
RCTBundleURLProvider *settings = [RCTBundleURLProvider sharedSettings];
|
|
143
|
+
[settings resetToDefaults];
|
|
144
|
+
NSURL *bundleURL = [settings jsBundleURLForFallbackExtension:nil];
|
|
145
|
+
|
|
146
|
+
[self applyBundleURL:bundleURL];
|
|
147
|
+
RCTTriggerReloadCommandListeners(@"Dev menu - reset to default");
|
|
148
|
+
resolve([NSNull null]);
|
|
149
|
+
} @catch (NSException *exception) {
|
|
150
|
+
reject(@"native_error", exception.reason, nil);
|
|
151
|
+
}
|
|
113
152
|
}
|
|
114
153
|
|
|
115
154
|
RCT_EXPORT_METHOD(getPreference:(NSString *)key
|
|
116
155
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
117
156
|
rejecter:(__unused RCTPromiseRejectBlock)reject)
|
|
118
157
|
{
|
|
119
|
-
|
|
120
|
-
|
|
158
|
+
@try {
|
|
159
|
+
NSString *value = [[NSUserDefaults standardUserDefaults] stringForKey:key];
|
|
160
|
+
resolve(value ?: [NSNull null]);
|
|
161
|
+
} @catch (NSException *exception) {
|
|
162
|
+
reject(@"native_error", exception.reason, nil);
|
|
163
|
+
}
|
|
121
164
|
}
|
|
122
165
|
|
|
123
166
|
RCT_EXPORT_METHOD(setPreference:(NSString *)key
|
|
@@ -125,9 +168,13 @@ RCT_EXPORT_METHOD(setPreference:(NSString *)key
|
|
|
125
168
|
resolver:(RCTPromiseResolveBlock)resolve
|
|
126
169
|
rejecter:(__unused RCTPromiseRejectBlock)reject)
|
|
127
170
|
{
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
171
|
+
@try {
|
|
172
|
+
[[NSUserDefaults standardUserDefaults] setObject:value forKey:key];
|
|
173
|
+
[[NSUserDefaults standardUserDefaults] synchronize];
|
|
174
|
+
resolve([NSNull null]);
|
|
175
|
+
} @catch (NSException *exception) {
|
|
176
|
+
reject(@"native_error", exception.reason, nil);
|
|
177
|
+
}
|
|
131
178
|
}
|
|
132
179
|
|
|
133
180
|
RCT_EXPORT_METHOD(isDebugBuild:(RCTPromiseResolveBlock)resolve
|
|
@@ -143,13 +190,27 @@ RCT_EXPORT_METHOD(isDebugBuild:(RCTPromiseResolveBlock)resolve
|
|
|
143
190
|
RCT_EXPORT_METHOD(getLocalIp:(RCTPromiseResolveBlock)resolve
|
|
144
191
|
rejecter:(__unused RCTPromiseRejectBlock)reject)
|
|
145
192
|
{
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
193
|
+
@try {
|
|
194
|
+
struct ifaddrs *interfaces = NULL;
|
|
195
|
+
if (getifaddrs(&interfaces) == 0) {
|
|
196
|
+
struct ifaddrs *iface = interfaces;
|
|
197
|
+
while (iface != NULL) {
|
|
198
|
+
if (iface->ifa_addr != NULL && iface->ifa_addr->sa_family == AF_INET && !(iface->ifa_flags & IFF_LOOPBACK)) {
|
|
199
|
+
if (strcmp(iface->ifa_name, "en0") == 0) {
|
|
200
|
+
char addrStr[INET_ADDRSTRLEN];
|
|
201
|
+
struct sockaddr_in *sin = (struct sockaddr_in *)iface->ifa_addr;
|
|
202
|
+
inet_ntop(AF_INET, &sin->sin_addr, addrStr, sizeof(addrStr));
|
|
203
|
+
NSString *ip = [NSString stringWithUTF8String:addrStr];
|
|
204
|
+
freeifaddrs(interfaces);
|
|
205
|
+
resolve(ip);
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
iface = iface->ifa_next;
|
|
210
|
+
}
|
|
211
|
+
iface = interfaces;
|
|
212
|
+
while (iface != NULL) {
|
|
213
|
+
if (iface->ifa_addr != NULL && iface->ifa_addr->sa_family == AF_INET && !(iface->ifa_flags & IFF_LOOPBACK)) {
|
|
153
214
|
char addrStr[INET_ADDRSTRLEN];
|
|
154
215
|
struct sockaddr_in *sin = (struct sockaddr_in *)iface->ifa_addr;
|
|
155
216
|
inet_ntop(AF_INET, &sin->sin_addr, addrStr, sizeof(addrStr));
|
|
@@ -158,26 +219,14 @@ RCT_EXPORT_METHOD(getLocalIp:(RCTPromiseResolveBlock)resolve
|
|
|
158
219
|
resolve(ip);
|
|
159
220
|
return;
|
|
160
221
|
}
|
|
222
|
+
iface = iface->ifa_next;
|
|
161
223
|
}
|
|
162
|
-
iface = iface->ifa_next;
|
|
163
|
-
}
|
|
164
|
-
// Second pass: any non-loopback IPv4
|
|
165
|
-
iface = interfaces;
|
|
166
|
-
while (iface != NULL) {
|
|
167
|
-
if (iface->ifa_addr->sa_family == AF_INET && !(iface->ifa_flags & IFF_LOOPBACK)) {
|
|
168
|
-
char addrStr[INET_ADDRSTRLEN];
|
|
169
|
-
struct sockaddr_in *sin = (struct sockaddr_in *)iface->ifa_addr;
|
|
170
|
-
inet_ntop(AF_INET, &sin->sin_addr, addrStr, sizeof(addrStr));
|
|
171
|
-
NSString *ip = [NSString stringWithUTF8String:addrStr];
|
|
172
|
-
freeifaddrs(interfaces);
|
|
173
|
-
resolve(ip);
|
|
174
|
-
return;
|
|
175
|
-
}
|
|
176
|
-
iface = iface->ifa_next;
|
|
177
224
|
}
|
|
225
|
+
freeifaddrs(interfaces);
|
|
226
|
+
resolve([NSNull null]);
|
|
227
|
+
} @catch (NSException *exception) {
|
|
228
|
+
reject(@"native_error", exception.reason, nil);
|
|
178
229
|
}
|
|
179
|
-
freeifaddrs(interfaces);
|
|
180
|
-
resolve([NSNull null]);
|
|
181
230
|
}
|
|
182
231
|
|
|
183
232
|
@end
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-debug-toolkit",
|
|
3
|
-
"version": "3.2.
|
|
3
|
+
"version": "3.2.8",
|
|
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",
|