devlens-mcp 0.3.0
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/.claude/settings.json +12 -0
- package/.claude/settings.local.json +17 -0
- package/INSTALLATION_GUIDE.md +354 -0
- package/QUICK_START.md +153 -0
- package/README.md +354 -0
- package/bin/cli.ts +22 -0
- package/bin/register.ts +96 -0
- package/dist/bin/cli.d.ts +3 -0
- package/dist/bin/cli.d.ts.map +1 -0
- package/dist/bin/cli.js +20 -0
- package/dist/bin/cli.js.map +1 -0
- package/dist/bin/register.d.ts +10 -0
- package/dist/bin/register.d.ts.map +1 -0
- package/dist/bin/register.js +92 -0
- package/dist/bin/register.js.map +1 -0
- package/dist/src/config/devlens-config.d.ts +92 -0
- package/dist/src/config/devlens-config.d.ts.map +1 -0
- package/dist/src/config/devlens-config.js +70 -0
- package/dist/src/config/devlens-config.js.map +1 -0
- package/dist/src/index.d.ts +35 -0
- package/dist/src/index.d.ts.map +1 -0
- package/dist/src/index.js +8 -0
- package/dist/src/index.js.map +1 -0
- package/dist/src/metro/cdp-client.d.ts +48 -0
- package/dist/src/metro/cdp-client.d.ts.map +1 -0
- package/dist/src/metro/cdp-client.js +127 -0
- package/dist/src/metro/cdp-client.js.map +1 -0
- package/dist/src/metro/log-collector.d.ts +30 -0
- package/dist/src/metro/log-collector.d.ts.map +1 -0
- package/dist/src/metro/log-collector.js +114 -0
- package/dist/src/metro/log-collector.js.map +1 -0
- package/dist/src/metro/metro-bridge.d.ts +56 -0
- package/dist/src/metro/metro-bridge.d.ts.map +1 -0
- package/dist/src/metro/metro-bridge.js +255 -0
- package/dist/src/metro/metro-bridge.js.map +1 -0
- package/dist/src/metro/network-inspector.d.ts +34 -0
- package/dist/src/metro/network-inspector.d.ts.map +1 -0
- package/dist/src/metro/network-inspector.js +100 -0
- package/dist/src/metro/network-inspector.js.map +1 -0
- package/dist/src/platform/android/adb.d.ts +50 -0
- package/dist/src/platform/android/adb.d.ts.map +1 -0
- package/dist/src/platform/android/adb.js +137 -0
- package/dist/src/platform/android/adb.js.map +1 -0
- package/dist/src/platform/android/android-device.d.ts +21 -0
- package/dist/src/platform/android/android-device.d.ts.map +1 -0
- package/dist/src/platform/android/android-device.js +94 -0
- package/dist/src/platform/android/android-device.js.map +1 -0
- package/dist/src/platform/android/ui-automator.d.ts +17 -0
- package/dist/src/platform/android/ui-automator.d.ts.map +1 -0
- package/dist/src/platform/android/ui-automator.js +126 -0
- package/dist/src/platform/android/ui-automator.js.map +1 -0
- package/dist/src/platform/device-manager.d.ts +28 -0
- package/dist/src/platform/device-manager.d.ts.map +1 -0
- package/dist/src/platform/device-manager.js +185 -0
- package/dist/src/platform/device-manager.js.map +1 -0
- package/dist/src/platform/device.d.ts +86 -0
- package/dist/src/platform/device.d.ts.map +1 -0
- package/dist/src/platform/device.js +7 -0
- package/dist/src/platform/device.js.map +1 -0
- package/dist/src/platform/ios/accessibility.d.ts +17 -0
- package/dist/src/platform/ios/accessibility.d.ts.map +1 -0
- package/dist/src/platform/ios/accessibility.js +159 -0
- package/dist/src/platform/ios/accessibility.js.map +1 -0
- package/dist/src/platform/ios/ios-device.d.ts +22 -0
- package/dist/src/platform/ios/ios-device.d.ts.map +1 -0
- package/dist/src/platform/ios/ios-device.js +97 -0
- package/dist/src/platform/ios/ios-device.js.map +1 -0
- package/dist/src/platform/ios/simctl.d.ts +54 -0
- package/dist/src/platform/ios/simctl.d.ts.map +1 -0
- package/dist/src/platform/ios/simctl.js +192 -0
- package/dist/src/platform/ios/simctl.js.map +1 -0
- package/dist/src/server.d.ts +3 -0
- package/dist/src/server.d.ts.map +1 -0
- package/dist/src/server.js +176 -0
- package/dist/src/server.js.map +1 -0
- package/dist/src/snapshot/formatter.d.ts +18 -0
- package/dist/src/snapshot/formatter.d.ts.map +1 -0
- package/dist/src/snapshot/formatter.js +86 -0
- package/dist/src/snapshot/formatter.js.map +1 -0
- package/dist/src/snapshot/ref-registry.d.ts +67 -0
- package/dist/src/snapshot/ref-registry.d.ts.map +1 -0
- package/dist/src/snapshot/ref-registry.js +169 -0
- package/dist/src/snapshot/ref-registry.js.map +1 -0
- package/dist/src/snapshot/snapshot-differ.d.ts +57 -0
- package/dist/src/snapshot/snapshot-differ.d.ts.map +1 -0
- package/dist/src/snapshot/snapshot-differ.js +153 -0
- package/dist/src/snapshot/snapshot-differ.js.map +1 -0
- package/dist/src/tools/app-tools.d.ts +71 -0
- package/dist/src/tools/app-tools.d.ts.map +1 -0
- package/dist/src/tools/app-tools.js +97 -0
- package/dist/src/tools/app-tools.js.map +1 -0
- package/dist/src/tools/device-tools.d.ts +53 -0
- package/dist/src/tools/device-tools.d.ts.map +1 -0
- package/dist/src/tools/device-tools.js +86 -0
- package/dist/src/tools/device-tools.js.map +1 -0
- package/dist/src/tools/ds-tools.d.ts +65 -0
- package/dist/src/tools/ds-tools.d.ts.map +1 -0
- package/dist/src/tools/ds-tools.js +314 -0
- package/dist/src/tools/ds-tools.js.map +1 -0
- package/dist/src/tools/interaction-tools.d.ts +248 -0
- package/dist/src/tools/interaction-tools.d.ts.map +1 -0
- package/dist/src/tools/interaction-tools.js +391 -0
- package/dist/src/tools/interaction-tools.js.map +1 -0
- package/dist/src/tools/metro-tools.d.ts +115 -0
- package/dist/src/tools/metro-tools.d.ts.map +1 -0
- package/dist/src/tools/metro-tools.js +270 -0
- package/dist/src/tools/metro-tools.js.map +1 -0
- package/dist/src/tools/navigation-tools.d.ts +36 -0
- package/dist/src/tools/navigation-tools.d.ts.map +1 -0
- package/dist/src/tools/navigation-tools.js +60 -0
- package/dist/src/tools/navigation-tools.js.map +1 -0
- package/dist/src/tools/screenshot-tools.d.ts +298 -0
- package/dist/src/tools/screenshot-tools.d.ts.map +1 -0
- package/dist/src/tools/screenshot-tools.js +565 -0
- package/dist/src/tools/screenshot-tools.js.map +1 -0
- package/dist/src/tools/snapshot-tools.d.ts +161 -0
- package/dist/src/tools/snapshot-tools.d.ts.map +1 -0
- package/dist/src/tools/snapshot-tools.js +479 -0
- package/dist/src/tools/snapshot-tools.js.map +1 -0
- package/dist/src/utils/image-preprocess.d.ts +49 -0
- package/dist/src/utils/image-preprocess.d.ts.map +1 -0
- package/dist/src/utils/image-preprocess.js +322 -0
- package/dist/src/utils/image-preprocess.js.map +1 -0
- package/dist/src/utils/retry.d.ts +21 -0
- package/dist/src/utils/retry.d.ts.map +1 -0
- package/dist/src/utils/retry.js +33 -0
- package/dist/src/utils/retry.js.map +1 -0
- package/dist/src/visual/comparator.d.ts +51 -0
- package/dist/src/visual/comparator.d.ts.map +1 -0
- package/dist/src/visual/comparator.js +119 -0
- package/dist/src/visual/comparator.js.map +1 -0
- package/dist/src/visual/layout-analyzer.d.ts +64 -0
- package/dist/src/visual/layout-analyzer.d.ts.map +1 -0
- package/dist/src/visual/layout-analyzer.js +198 -0
- package/dist/src/visual/layout-analyzer.js.map +1 -0
- package/dist/src/visual/screenshot.d.ts +17 -0
- package/dist/src/visual/screenshot.d.ts.map +1 -0
- package/dist/src/visual/screenshot.js +39 -0
- package/dist/src/visual/screenshot.js.map +1 -0
- package/docs/figma-workflow.md +289 -0
- package/docs/setup-guide.md +360 -0
- package/docs/tool-reference.md +622 -0
- package/package.json +57 -0
- package/src/config/devlens-config.ts +76 -0
- package/src/index.ts +5 -0
- package/src/metro/cdp-client.ts +160 -0
- package/src/metro/log-collector.ts +137 -0
- package/src/metro/metro-bridge.ts +307 -0
- package/src/metro/network-inspector.ts +134 -0
- package/src/platform/android/adb.ts +200 -0
- package/src/platform/android/android-device.ts +116 -0
- package/src/platform/android/ui-automator.ts +141 -0
- package/src/platform/device-manager.ts +229 -0
- package/src/platform/device.ts +110 -0
- package/src/platform/ios/accessibility.ts +189 -0
- package/src/platform/ios/ios-device.ts +116 -0
- package/src/platform/ios/simctl.ts +244 -0
- package/src/server.ts +228 -0
- package/src/snapshot/formatter.ts +102 -0
- package/src/snapshot/ref-registry.ts +230 -0
- package/src/snapshot/snapshot-differ.ts +220 -0
- package/src/tools/app-tools.ts +111 -0
- package/src/tools/device-tools.ts +96 -0
- package/src/tools/ds-tools.ts +395 -0
- package/src/tools/interaction-tools.ts +467 -0
- package/src/tools/metro-tools.ts +320 -0
- package/src/tools/navigation-tools.ts +71 -0
- package/src/tools/screenshot-tools.ts +698 -0
- package/src/tools/snapshot-tools.ts +585 -0
- package/src/utils/image-preprocess.ts +430 -0
- package/src/utils/retry.ts +51 -0
- package/src/visual/comparator.ts +191 -0
- package/src/visual/layout-analyzer.ts +283 -0
- package/src/visual/screenshot.ts +49 -0
- package/tsconfig.json +20 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MetroBridge = void 0;
|
|
4
|
+
const cdp_client_js_1 = require("./cdp-client.js");
|
|
5
|
+
const log_collector_js_1 = require("./log-collector.js");
|
|
6
|
+
const network_inspector_js_1 = require("./network-inspector.js");
|
|
7
|
+
class MetroBridge {
|
|
8
|
+
port;
|
|
9
|
+
cdp = null;
|
|
10
|
+
_logCollector = null;
|
|
11
|
+
_networkInspector = null;
|
|
12
|
+
_connected = false;
|
|
13
|
+
constructor(port = 8081) {
|
|
14
|
+
this.port = port;
|
|
15
|
+
}
|
|
16
|
+
/** Connect to Metro bundler's debugger */
|
|
17
|
+
async connect() {
|
|
18
|
+
if (this._connected)
|
|
19
|
+
return;
|
|
20
|
+
// Try to discover the debugger endpoint
|
|
21
|
+
const endpoint = await this.discoverEndpoint();
|
|
22
|
+
this.cdp = new cdp_client_js_1.CdpClient(endpoint);
|
|
23
|
+
await this.cdp.connect();
|
|
24
|
+
// Initialize collectors
|
|
25
|
+
this._logCollector = new log_collector_js_1.LogCollector(this.cdp);
|
|
26
|
+
this._networkInspector = new network_inspector_js_1.NetworkInspector(this.cdp);
|
|
27
|
+
// Enable CDP domains
|
|
28
|
+
await this.cdp.send("Runtime.enable");
|
|
29
|
+
await this.cdp.send("Console.enable").catch(() => {
|
|
30
|
+
// Console domain might not be available in all environments
|
|
31
|
+
});
|
|
32
|
+
// Start collecting
|
|
33
|
+
this._logCollector.start();
|
|
34
|
+
this._networkInspector.start();
|
|
35
|
+
this._connected = true;
|
|
36
|
+
}
|
|
37
|
+
/** Disconnect from Metro */
|
|
38
|
+
disconnect() {
|
|
39
|
+
if (this.cdp) {
|
|
40
|
+
this.cdp.close();
|
|
41
|
+
this.cdp = null;
|
|
42
|
+
}
|
|
43
|
+
this._logCollector = null;
|
|
44
|
+
this._networkInspector = null;
|
|
45
|
+
this._connected = false;
|
|
46
|
+
}
|
|
47
|
+
/** Check if connected to Metro */
|
|
48
|
+
get connected() {
|
|
49
|
+
return this._connected && (this.cdp?.isConnected() ?? false);
|
|
50
|
+
}
|
|
51
|
+
/** Get the log collector */
|
|
52
|
+
get logCollector() {
|
|
53
|
+
if (!this._logCollector) {
|
|
54
|
+
throw new Error("Not connected to Metro. Call connect() first.");
|
|
55
|
+
}
|
|
56
|
+
return this._logCollector;
|
|
57
|
+
}
|
|
58
|
+
/** Get the network inspector */
|
|
59
|
+
get networkInspector() {
|
|
60
|
+
if (!this._networkInspector) {
|
|
61
|
+
throw new Error("Not connected to Metro. Call connect() first.");
|
|
62
|
+
}
|
|
63
|
+
return this._networkInspector;
|
|
64
|
+
}
|
|
65
|
+
/** Execute JavaScript in the React Native context */
|
|
66
|
+
async evaluate(expression) {
|
|
67
|
+
if (!this.cdp || !this._connected) {
|
|
68
|
+
throw new Error("Not connected to Metro.");
|
|
69
|
+
}
|
|
70
|
+
const result = await this.cdp.send("Runtime.evaluate", {
|
|
71
|
+
expression,
|
|
72
|
+
returnByValue: true,
|
|
73
|
+
awaitPromise: true,
|
|
74
|
+
});
|
|
75
|
+
if (result?.exceptionDetails) {
|
|
76
|
+
throw new Error(`JS Error: ${result.exceptionDetails.text || result.exceptionDetails.exception?.description}`);
|
|
77
|
+
}
|
|
78
|
+
return result?.result?.value;
|
|
79
|
+
}
|
|
80
|
+
/** Trigger a hot reload / fast refresh */
|
|
81
|
+
async hotReload() {
|
|
82
|
+
try {
|
|
83
|
+
// Method 1: Use the Metro reload endpoint
|
|
84
|
+
const http = await import("http");
|
|
85
|
+
await new Promise((resolve, reject) => {
|
|
86
|
+
const req = http.request({
|
|
87
|
+
hostname: "localhost",
|
|
88
|
+
port: this.port,
|
|
89
|
+
path: "/reload",
|
|
90
|
+
method: "POST",
|
|
91
|
+
}, (res) => {
|
|
92
|
+
res.resume();
|
|
93
|
+
resolve();
|
|
94
|
+
});
|
|
95
|
+
req.on("error", reject);
|
|
96
|
+
req.setTimeout(5000, () => {
|
|
97
|
+
req.destroy();
|
|
98
|
+
reject(new Error("Reload request timeout"));
|
|
99
|
+
});
|
|
100
|
+
req.end();
|
|
101
|
+
});
|
|
102
|
+
}
|
|
103
|
+
catch {
|
|
104
|
+
// Method 2: Fallback - evaluate reload command via CDP
|
|
105
|
+
if (this.cdp && this._connected) {
|
|
106
|
+
await this.cdp.send("Runtime.evaluate", {
|
|
107
|
+
expression: 'if (typeof __DEV__ !== "undefined" && __DEV__) { const DevSettings = require("react-native/Libraries/Utilities/DevSettings"); DevSettings.reload(); }',
|
|
108
|
+
});
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
/** Get the React component tree by evaluating JS in the RN context */
|
|
113
|
+
async getComponentTree(maxDepth = 10) {
|
|
114
|
+
if (!this.cdp || !this._connected) {
|
|
115
|
+
throw new Error("Not connected to Metro.");
|
|
116
|
+
}
|
|
117
|
+
// Inject a helper that traverses the React fiber tree
|
|
118
|
+
const script = `
|
|
119
|
+
(function() {
|
|
120
|
+
try {
|
|
121
|
+
// Find the root fiber
|
|
122
|
+
const roots = [];
|
|
123
|
+
const fiberRoots = document?.querySelectorAll?.('[data-reactroot]') || [];
|
|
124
|
+
|
|
125
|
+
// For React Native, we need to find the fiber root differently
|
|
126
|
+
// The __REACT_DEVTOOLS_GLOBAL_HOOK__ is available when DevTools is enabled
|
|
127
|
+
const hook = globalThis.__REACT_DEVTOOLS_GLOBAL_HOOK__;
|
|
128
|
+
if (!hook || !hook.renderers) {
|
|
129
|
+
return "React DevTools hook not available. Ensure the app is running in __DEV__ mode.";
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
const renderers = Array.from(hook.renderers.values());
|
|
133
|
+
if (renderers.length === 0) {
|
|
134
|
+
return "No React renderers found.";
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
// Get fiber roots from the hook
|
|
138
|
+
const fiberRootSet = hook.getFiberRoots?.(renderers[0].rendererID || 1);
|
|
139
|
+
if (!fiberRootSet || fiberRootSet.size === 0) {
|
|
140
|
+
return "No fiber roots found. Is a React Native app running?";
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
function traverseFiber(fiber, depth, maxDepth) {
|
|
144
|
+
if (!fiber || depth > maxDepth) return null;
|
|
145
|
+
|
|
146
|
+
const name = fiber.type?.displayName || fiber.type?.name || fiber.type || 'Unknown';
|
|
147
|
+
const props = {};
|
|
148
|
+
|
|
149
|
+
if (fiber.memoizedProps) {
|
|
150
|
+
for (const [key, value] of Object.entries(fiber.memoizedProps)) {
|
|
151
|
+
if (key === 'children') continue;
|
|
152
|
+
if (typeof value === 'string' || typeof value === 'number' || typeof value === 'boolean') {
|
|
153
|
+
props[key] = value;
|
|
154
|
+
} else if (typeof value === 'function') {
|
|
155
|
+
props[key] = '[function]';
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
}
|
|
159
|
+
|
|
160
|
+
const children = [];
|
|
161
|
+
let child = fiber.child;
|
|
162
|
+
while (child) {
|
|
163
|
+
const result = traverseFiber(child, depth + 1, maxDepth);
|
|
164
|
+
if (result) children.push(result);
|
|
165
|
+
child = child.sibling;
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
// Skip internal React types
|
|
169
|
+
if (typeof name === 'number' || name === 'Unknown') {
|
|
170
|
+
return children.length === 1 ? children[0] : children.length > 0 ? { type: 'Fragment', children } : null;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
return {
|
|
174
|
+
type: String(name),
|
|
175
|
+
props: Object.keys(props).length > 0 ? props : undefined,
|
|
176
|
+
children: children.length > 0 ? children : undefined,
|
|
177
|
+
};
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
const root = Array.from(fiberRootSet)[0];
|
|
181
|
+
const tree = traverseFiber(root.current, 0, ${maxDepth});
|
|
182
|
+
return JSON.stringify(tree, null, 2);
|
|
183
|
+
} catch (e) {
|
|
184
|
+
return "Error getting component tree: " + e.message;
|
|
185
|
+
}
|
|
186
|
+
})()
|
|
187
|
+
`;
|
|
188
|
+
const result = await this.cdp.send("Runtime.evaluate", {
|
|
189
|
+
expression: script,
|
|
190
|
+
returnByValue: true,
|
|
191
|
+
});
|
|
192
|
+
return result?.result?.value || "Could not retrieve component tree";
|
|
193
|
+
}
|
|
194
|
+
/** Proactively check if Metro bundler is running and healthy */
|
|
195
|
+
async getStatus() {
|
|
196
|
+
const status = {
|
|
197
|
+
running: false,
|
|
198
|
+
port: this.port,
|
|
199
|
+
packagerStatus: null,
|
|
200
|
+
cdpConnected: this.connected,
|
|
201
|
+
};
|
|
202
|
+
try {
|
|
203
|
+
const controller = new AbortController();
|
|
204
|
+
const timeout = setTimeout(() => controller.abort(), 3000);
|
|
205
|
+
const response = await fetch(`http://localhost:${this.port}/status`, {
|
|
206
|
+
signal: controller.signal,
|
|
207
|
+
});
|
|
208
|
+
clearTimeout(timeout);
|
|
209
|
+
const body = await response.text();
|
|
210
|
+
status.packagerStatus = body.trim();
|
|
211
|
+
status.running = body.includes("packager-status:running");
|
|
212
|
+
}
|
|
213
|
+
catch (err) {
|
|
214
|
+
status.error = `Cannot reach Metro on port ${this.port}: ${err.message}`;
|
|
215
|
+
}
|
|
216
|
+
return status;
|
|
217
|
+
}
|
|
218
|
+
/** Discover the debugger WebSocket endpoint */
|
|
219
|
+
async discoverEndpoint() {
|
|
220
|
+
const http = await import("http");
|
|
221
|
+
try {
|
|
222
|
+
// Query Metro's page list
|
|
223
|
+
const pages = await new Promise((resolve, reject) => {
|
|
224
|
+
http
|
|
225
|
+
.get(`http://localhost:${this.port}/json`, (res) => {
|
|
226
|
+
let data = "";
|
|
227
|
+
res.on("data", (chunk) => (data += chunk));
|
|
228
|
+
res.on("end", () => {
|
|
229
|
+
try {
|
|
230
|
+
resolve(JSON.parse(data));
|
|
231
|
+
}
|
|
232
|
+
catch {
|
|
233
|
+
resolve([]);
|
|
234
|
+
}
|
|
235
|
+
});
|
|
236
|
+
})
|
|
237
|
+
.on("error", reject);
|
|
238
|
+
});
|
|
239
|
+
// Find the best debugger page
|
|
240
|
+
const debuggerPage = pages.find((p) => p.title?.includes("Hermes") ||
|
|
241
|
+
p.title?.includes("React Native") ||
|
|
242
|
+
p.webSocketDebuggerUrl);
|
|
243
|
+
if (debuggerPage?.webSocketDebuggerUrl) {
|
|
244
|
+
return debuggerPage.webSocketDebuggerUrl;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
catch {
|
|
248
|
+
// Metro might not support /json endpoint
|
|
249
|
+
}
|
|
250
|
+
// Fallback to default endpoint
|
|
251
|
+
return `ws://localhost:${this.port}/inspector/device?device=0&page=-1`;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
exports.MetroBridge = MetroBridge;
|
|
255
|
+
//# sourceMappingURL=metro-bridge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"metro-bridge.js","sourceRoot":"","sources":["../../../src/metro/metro-bridge.ts"],"names":[],"mappings":";;;AAAA,mDAA4C;AAC5C,yDAAkD;AAClD,iEAA0D;AA6B1D,MAAa,WAAW;IAMF;IALZ,GAAG,GAAqB,IAAI,CAAC;IAC7B,aAAa,GAAwB,IAAI,CAAC;IAC1C,iBAAiB,GAA4B,IAAI,CAAC;IAClD,UAAU,GAAY,KAAK,CAAC;IAEpC,YAAoB,OAAe,IAAI;QAAnB,SAAI,GAAJ,IAAI,CAAe;IAAG,CAAC;IAE3C,0CAA0C;IAC1C,KAAK,CAAC,OAAO;QACX,IAAI,IAAI,CAAC,UAAU;YAAE,OAAO;QAE5B,wCAAwC;QACxC,MAAM,QAAQ,GAAG,MAAM,IAAI,CAAC,gBAAgB,EAAE,CAAC;QAC/C,IAAI,CAAC,GAAG,GAAG,IAAI,yBAAS,CAAC,QAAQ,CAAC,CAAC;QACnC,MAAM,IAAI,CAAC,GAAG,CAAC,OAAO,EAAE,CAAC;QAEzB,wBAAwB;QACxB,IAAI,CAAC,aAAa,GAAG,IAAI,+BAAY,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAChD,IAAI,CAAC,iBAAiB,GAAG,IAAI,uCAAgB,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAExD,qBAAqB;QACrB,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC;QACtC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,gBAAgB,CAAC,CAAC,KAAK,CAAC,GAAG,EAAE;YAC/C,4DAA4D;QAC9D,CAAC,CAAC,CAAC;QAEH,mBAAmB;QACnB,IAAI,CAAC,aAAa,CAAC,KAAK,EAAE,CAAC;QAC3B,IAAI,CAAC,iBAAiB,CAAC,KAAK,EAAE,CAAC;QAE/B,IAAI,CAAC,UAAU,GAAG,IAAI,CAAC;IACzB,CAAC;IAED,4BAA4B;IAC5B,UAAU;QACR,IAAI,IAAI,CAAC,GAAG,EAAE,CAAC;YACb,IAAI,CAAC,GAAG,CAAC,KAAK,EAAE,CAAC;YACjB,IAAI,CAAC,GAAG,GAAG,IAAI,CAAC;QAClB,CAAC;QACD,IAAI,CAAC,aAAa,GAAG,IAAI,CAAC;QAC1B,IAAI,CAAC,iBAAiB,GAAG,IAAI,CAAC;QAC9B,IAAI,CAAC,UAAU,GAAG,KAAK,CAAC;IAC1B,CAAC;IAED,kCAAkC;IAClC,IAAI,SAAS;QACX,OAAO,IAAI,CAAC,UAAU,IAAI,CAAC,IAAI,CAAC,GAAG,EAAE,WAAW,EAAE,IAAI,KAAK,CAAC,CAAC;IAC/D,CAAC;IAED,4BAA4B;IAC5B,IAAI,YAAY;QACd,IAAI,CAAC,IAAI,CAAC,aAAa,EAAE,CAAC;YACxB,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,IAAI,CAAC,aAAa,CAAC;IAC5B,CAAC;IAED,gCAAgC;IAChC,IAAI,gBAAgB;QAClB,IAAI,CAAC,IAAI,CAAC,iBAAiB,EAAE,CAAC;YAC5B,MAAM,IAAI,KAAK,CAAC,+CAA+C,CAAC,CAAC;QACnE,CAAC;QACD,OAAO,IAAI,CAAC,iBAAiB,CAAC;IAChC,CAAC;IAED,qDAAqD;IACrD,KAAK,CAAC,QAAQ,CAAC,UAAkB;QAC/B,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE;YACrD,UAAU;YACV,aAAa,EAAE,IAAI;YACnB,YAAY,EAAE,IAAI;SACnB,CAAC,CAAC;QAEH,IAAI,MAAM,EAAE,gBAAgB,EAAE,CAAC;YAC7B,MAAM,IAAI,KAAK,CACb,aAAa,MAAM,CAAC,gBAAgB,CAAC,IAAI,IAAI,MAAM,CAAC,gBAAgB,CAAC,SAAS,EAAE,WAAW,EAAE,CAC9F,CAAC;QACJ,CAAC;QAED,OAAO,MAAM,EAAE,MAAM,EAAE,KAAK,CAAC;IAC/B,CAAC;IAED,0CAA0C;IAC1C,KAAK,CAAC,SAAS;QACb,IAAI,CAAC;YACH,0CAA0C;YAC1C,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;YAClC,MAAM,IAAI,OAAO,CAAO,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBAC1C,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CACtB;oBACE,QAAQ,EAAE,WAAW;oBACrB,IAAI,EAAE,IAAI,CAAC,IAAI;oBACf,IAAI,EAAE,SAAS;oBACf,MAAM,EAAE,MAAM;iBACf,EACD,CAAC,GAAG,EAAE,EAAE;oBACN,GAAG,CAAC,MAAM,EAAE,CAAC;oBACb,OAAO,EAAE,CAAC;gBACZ,CAAC,CACF,CAAC;gBACF,GAAG,CAAC,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;gBACxB,GAAG,CAAC,UAAU,CAAC,IAAI,EAAE,GAAG,EAAE;oBACxB,GAAG,CAAC,OAAO,EAAE,CAAC;oBACd,MAAM,CAAC,IAAI,KAAK,CAAC,wBAAwB,CAAC,CAAC,CAAC;gBAC9C,CAAC,CAAC,CAAC;gBACH,GAAG,CAAC,GAAG,EAAE,CAAC;YACZ,CAAC,CAAC,CAAC;QACL,CAAC;QAAC,MAAM,CAAC;YACP,uDAAuD;YACvD,IAAI,IAAI,CAAC,GAAG,IAAI,IAAI,CAAC,UAAU,EAAE,CAAC;gBAChC,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE;oBACtC,UAAU,EACR,uJAAuJ;iBAC1J,CAAC,CAAC;YACL,CAAC;QACH,CAAC;IACH,CAAC;IAED,sEAAsE;IACtE,KAAK,CAAC,gBAAgB,CAAC,WAAmB,EAAE;QAC1C,IAAI,CAAC,IAAI,CAAC,GAAG,IAAI,CAAC,IAAI,CAAC,UAAU,EAAE,CAAC;YAClC,MAAM,IAAI,KAAK,CAAC,yBAAyB,CAAC,CAAC;QAC7C,CAAC;QAED,sDAAsD;QACtD,MAAM,MAAM,GAAG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;wDA+DqC,QAAQ;;;;;;KAM3D,CAAC;QAEF,MAAM,MAAM,GAAG,MAAM,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,kBAAkB,EAAE;YACrD,UAAU,EAAE,MAAM;YAClB,aAAa,EAAE,IAAI;SACpB,CAAC,CAAC;QAEH,OAAO,MAAM,EAAE,MAAM,EAAE,KAAK,IAAI,mCAAmC,CAAC;IACtE,CAAC;IAED,gEAAgE;IAChE,KAAK,CAAC,SAAS;QACb,MAAM,MAAM,GAAgB;YAC1B,OAAO,EAAE,KAAK;YACd,IAAI,EAAE,IAAI,CAAC,IAAI;YACf,cAAc,EAAE,IAAI;YACpB,YAAY,EAAE,IAAI,CAAC,SAAS;SAC7B,CAAC;QAEF,IAAI,CAAC;YACH,MAAM,UAAU,GAAG,IAAI,eAAe,EAAE,CAAC;YACzC,MAAM,OAAO,GAAG,UAAU,CAAC,GAAG,EAAE,CAAC,UAAU,CAAC,KAAK,EAAE,EAAE,IAAI,CAAC,CAAC;YAC3D,MAAM,QAAQ,GAAG,MAAM,KAAK,CAAC,oBAAoB,IAAI,CAAC,IAAI,SAAS,EAAE;gBACnE,MAAM,EAAE,UAAU,CAAC,MAAM;aAC1B,CAAC,CAAC;YACH,YAAY,CAAC,OAAO,CAAC,CAAC;YACtB,MAAM,IAAI,GAAG,MAAM,QAAQ,CAAC,IAAI,EAAE,CAAC;YACnC,MAAM,CAAC,cAAc,GAAG,IAAI,CAAC,IAAI,EAAE,CAAC;YACpC,MAAM,CAAC,OAAO,GAAG,IAAI,CAAC,QAAQ,CAAC,yBAAyB,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,GAAQ,EAAE,CAAC;YAClB,MAAM,CAAC,KAAK,GAAG,8BAA8B,IAAI,CAAC,IAAI,KAAK,GAAG,CAAC,OAAO,EAAE,CAAC;QAC3E,CAAC;QAED,OAAO,MAAM,CAAC;IAChB,CAAC;IAED,+CAA+C;IACvC,KAAK,CAAC,gBAAgB;QAC5B,MAAM,IAAI,GAAG,MAAM,MAAM,CAAC,MAAM,CAAC,CAAC;QAElC,IAAI,CAAC;YACH,0BAA0B;YAC1B,MAAM,KAAK,GAAG,MAAM,IAAI,OAAO,CAAQ,CAAC,OAAO,EAAE,MAAM,EAAE,EAAE;gBACzD,IAAI;qBACD,GAAG,CAAC,oBAAoB,IAAI,CAAC,IAAI,OAAO,EAAE,CAAC,GAAG,EAAE,EAAE;oBACjD,IAAI,IAAI,GAAG,EAAE,CAAC;oBACd,GAAG,CAAC,EAAE,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,IAAI,IAAI,KAAK,CAAC,CAAC,CAAC;oBAC3C,GAAG,CAAC,EAAE,CAAC,KAAK,EAAE,GAAG,EAAE;wBACjB,IAAI,CAAC;4BACH,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC,CAAC;wBAC5B,CAAC;wBAAC,MAAM,CAAC;4BACP,OAAO,CAAC,EAAE,CAAC,CAAC;wBACd,CAAC;oBACH,CAAC,CAAC,CAAC;gBACL,CAAC,CAAC;qBACD,EAAE,CAAC,OAAO,EAAE,MAAM,CAAC,CAAC;YACzB,CAAC,CAAC,CAAC;YAEH,8BAA8B;YAC9B,MAAM,YAAY,GAAG,KAAK,CAAC,IAAI,CAC7B,CAAC,CAAC,EAAE,EAAE,CACJ,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,QAAQ,CAAC;gBAC3B,CAAC,CAAC,KAAK,EAAE,QAAQ,CAAC,cAAc,CAAC;gBACjC,CAAC,CAAC,oBAAoB,CACzB,CAAC;YAEF,IAAI,YAAY,EAAE,oBAAoB,EAAE,CAAC;gBACvC,OAAO,YAAY,CAAC,oBAAoB,CAAC;YAC3C,CAAC;QACH,CAAC;QAAC,MAAM,CAAC;YACP,yCAAyC;QAC3C,CAAC;QAED,+BAA+B;QAC/B,OAAO,kBAAkB,IAAI,CAAC,IAAI,oCAAoC,CAAC;IACzE,CAAC;CACF;AAnRD,kCAmRC"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { CdpClient } from "./cdp-client.js";
|
|
2
|
+
/**
|
|
3
|
+
* Intercepts network requests from the React Native app via CDP's Network domain.
|
|
4
|
+
* Captures fetch/XHR requests, their responses, and timing information.
|
|
5
|
+
*/
|
|
6
|
+
export interface NetworkRequest {
|
|
7
|
+
id: string;
|
|
8
|
+
url: string;
|
|
9
|
+
method: string;
|
|
10
|
+
status?: number;
|
|
11
|
+
statusText?: string;
|
|
12
|
+
type?: string;
|
|
13
|
+
startTime: number;
|
|
14
|
+
endTime?: number;
|
|
15
|
+
duration?: number;
|
|
16
|
+
requestHeaders?: Record<string, string>;
|
|
17
|
+
responseHeaders?: Record<string, string>;
|
|
18
|
+
size?: number;
|
|
19
|
+
error?: string;
|
|
20
|
+
}
|
|
21
|
+
export declare class NetworkInspector {
|
|
22
|
+
private cdp;
|
|
23
|
+
private requests;
|
|
24
|
+
private maxRequests;
|
|
25
|
+
constructor(cdp: CdpClient);
|
|
26
|
+
/** Start intercepting network requests */
|
|
27
|
+
start(): void;
|
|
28
|
+
/** Get all captured network requests, optionally filtered by URL pattern */
|
|
29
|
+
getRequests(urlPattern?: string): NetworkRequest[];
|
|
30
|
+
/** Clear all captured requests */
|
|
31
|
+
clear(): void;
|
|
32
|
+
private trimRequests;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=network-inspector.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-inspector.d.ts","sourceRoot":"","sources":["../../../src/metro/network-inspector.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,SAAS,EAAc,MAAM,iBAAiB,CAAC;AAE7D;;;GAGG;AAEH,MAAM,WAAW,cAAc;IAC7B,EAAE,EAAE,MAAM,CAAC;IACX,GAAG,EAAE,MAAM,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,SAAS,EAAE,MAAM,CAAC;IAClB,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,cAAc,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACxC,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,MAAM,CAAC;CAChB;AAED,qBAAa,gBAAgB;IAIf,OAAO,CAAC,GAAG;IAHvB,OAAO,CAAC,QAAQ,CAA0C;IAC1D,OAAO,CAAC,WAAW,CAAe;gBAEd,GAAG,EAAE,SAAS;IAElC,0CAA0C;IAC1C,KAAK,IAAI,IAAI;IAoEb,4EAA4E;IAC5E,WAAW,CAAC,UAAU,CAAC,EAAE,MAAM,GAAG,cAAc,EAAE;IAclD,kCAAkC;IAClC,KAAK,IAAI,IAAI;IAIb,OAAO,CAAC,YAAY;CAerB"}
|
|
@@ -0,0 +1,100 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.NetworkInspector = void 0;
|
|
4
|
+
class NetworkInspector {
|
|
5
|
+
cdp;
|
|
6
|
+
requests = new Map();
|
|
7
|
+
maxRequests = 200;
|
|
8
|
+
constructor(cdp) {
|
|
9
|
+
this.cdp = cdp;
|
|
10
|
+
}
|
|
11
|
+
/** Start intercepting network requests */
|
|
12
|
+
start() {
|
|
13
|
+
// Enable Network domain
|
|
14
|
+
this.cdp.send("Network.enable").catch(() => {
|
|
15
|
+
// Network domain might not be available
|
|
16
|
+
});
|
|
17
|
+
// Request started
|
|
18
|
+
this.cdp.on("Network.requestWillBeSent", (msg) => {
|
|
19
|
+
const params = msg.params;
|
|
20
|
+
if (!params)
|
|
21
|
+
return;
|
|
22
|
+
const request = {
|
|
23
|
+
id: params.requestId,
|
|
24
|
+
url: params.request?.url || "",
|
|
25
|
+
method: params.request?.method || "GET",
|
|
26
|
+
type: params.type,
|
|
27
|
+
startTime: Date.now(),
|
|
28
|
+
requestHeaders: params.request?.headers,
|
|
29
|
+
};
|
|
30
|
+
this.requests.set(params.requestId, request);
|
|
31
|
+
this.trimRequests();
|
|
32
|
+
});
|
|
33
|
+
// Response received
|
|
34
|
+
this.cdp.on("Network.responseReceived", (msg) => {
|
|
35
|
+
const params = msg.params;
|
|
36
|
+
if (!params)
|
|
37
|
+
return;
|
|
38
|
+
const request = this.requests.get(params.requestId);
|
|
39
|
+
if (request) {
|
|
40
|
+
request.status = params.response?.status;
|
|
41
|
+
request.statusText = params.response?.statusText;
|
|
42
|
+
request.responseHeaders = params.response?.headers;
|
|
43
|
+
request.endTime = Date.now();
|
|
44
|
+
request.duration = request.endTime - request.startTime;
|
|
45
|
+
}
|
|
46
|
+
});
|
|
47
|
+
// Loading finished
|
|
48
|
+
this.cdp.on("Network.loadingFinished", (msg) => {
|
|
49
|
+
const params = msg.params;
|
|
50
|
+
if (!params)
|
|
51
|
+
return;
|
|
52
|
+
const request = this.requests.get(params.requestId);
|
|
53
|
+
if (request) {
|
|
54
|
+
request.size = params.encodedDataLength;
|
|
55
|
+
if (!request.endTime) {
|
|
56
|
+
request.endTime = Date.now();
|
|
57
|
+
request.duration = request.endTime - request.startTime;
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
});
|
|
61
|
+
// Loading failed
|
|
62
|
+
this.cdp.on("Network.loadingFailed", (msg) => {
|
|
63
|
+
const params = msg.params;
|
|
64
|
+
if (!params)
|
|
65
|
+
return;
|
|
66
|
+
const request = this.requests.get(params.requestId);
|
|
67
|
+
if (request) {
|
|
68
|
+
request.error = params.errorText || "Request failed";
|
|
69
|
+
request.endTime = Date.now();
|
|
70
|
+
request.duration = request.endTime - request.startTime;
|
|
71
|
+
}
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
/** Get all captured network requests, optionally filtered by URL pattern */
|
|
75
|
+
getRequests(urlPattern) {
|
|
76
|
+
let requests = Array.from(this.requests.values());
|
|
77
|
+
if (urlPattern) {
|
|
78
|
+
const pattern = urlPattern.toLowerCase();
|
|
79
|
+
requests = requests.filter((r) => r.url.toLowerCase().includes(pattern));
|
|
80
|
+
}
|
|
81
|
+
// Sort by start time (newest first)
|
|
82
|
+
return requests.sort((a, b) => b.startTime - a.startTime);
|
|
83
|
+
}
|
|
84
|
+
/** Clear all captured requests */
|
|
85
|
+
clear() {
|
|
86
|
+
this.requests.clear();
|
|
87
|
+
}
|
|
88
|
+
trimRequests() {
|
|
89
|
+
if (this.requests.size > this.maxRequests) {
|
|
90
|
+
// Remove oldest entries
|
|
91
|
+
const entries = Array.from(this.requests.entries()).sort((a, b) => a[1].startTime - b[1].startTime);
|
|
92
|
+
const toRemove = entries.slice(0, entries.length - Math.floor(this.maxRequests * 0.8));
|
|
93
|
+
for (const [id] of toRemove) {
|
|
94
|
+
this.requests.delete(id);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
exports.NetworkInspector = NetworkInspector;
|
|
100
|
+
//# sourceMappingURL=network-inspector.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"network-inspector.js","sourceRoot":"","sources":["../../../src/metro/network-inspector.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* ADB command wrapper — handles all communication with Android devices via ADB.
|
|
3
|
+
*/
|
|
4
|
+
export declare class Adb {
|
|
5
|
+
private deviceId;
|
|
6
|
+
private adbPath;
|
|
7
|
+
constructor(deviceId: string);
|
|
8
|
+
/** Execute an ADB shell command on the device (with retry for transient failures) */
|
|
9
|
+
shell(command: string): Promise<string>;
|
|
10
|
+
/** Execute an ADB command (non-shell) */
|
|
11
|
+
exec(...args: string[]): Promise<string>;
|
|
12
|
+
/** Take a screenshot and return the PNG buffer (with retry) */
|
|
13
|
+
screenshot(): Promise<Buffer>;
|
|
14
|
+
/** Dump the UI hierarchy XML (with retry) */
|
|
15
|
+
dumpUiHierarchy(): Promise<string>;
|
|
16
|
+
/** Tap at screen coordinates */
|
|
17
|
+
tap(x: number, y: number): Promise<void>;
|
|
18
|
+
/** Long press at coordinates */
|
|
19
|
+
longPress(x: number, y: number, durationMs?: number): Promise<void>;
|
|
20
|
+
/** Swipe between two points */
|
|
21
|
+
swipe(startX: number, startY: number, endX: number, endY: number, durationMs?: number): Promise<void>;
|
|
22
|
+
/** Type text using ADB input */
|
|
23
|
+
typeText(text: string): Promise<void>;
|
|
24
|
+
/** Press a key event */
|
|
25
|
+
keyEvent(keyCode: number): Promise<void>;
|
|
26
|
+
/** Get device screen size */
|
|
27
|
+
getScreenSize(): Promise<{
|
|
28
|
+
width: number;
|
|
29
|
+
height: number;
|
|
30
|
+
}>;
|
|
31
|
+
/** Get device orientation (0=portrait, 1=landscape, 2=reverse-portrait, 3=reverse-landscape) */
|
|
32
|
+
getOrientation(): Promise<number>;
|
|
33
|
+
/** Get Android version */
|
|
34
|
+
getAndroidVersion(): Promise<string>;
|
|
35
|
+
/** Get device model name */
|
|
36
|
+
getDeviceName(): Promise<string>;
|
|
37
|
+
/** Launch an app by package name */
|
|
38
|
+
launchApp(packageName: string): Promise<void>;
|
|
39
|
+
/** Force stop an app */
|
|
40
|
+
terminateApp(packageName: string): Promise<void>;
|
|
41
|
+
/** Install an APK */
|
|
42
|
+
installApp(apkPath: string): Promise<void>;
|
|
43
|
+
/** List installed packages */
|
|
44
|
+
listPackages(): Promise<string[]>;
|
|
45
|
+
/** Open a URL */
|
|
46
|
+
openUrl(url: string): Promise<void>;
|
|
47
|
+
/** Set orientation (0=auto, 1=portrait, 2=landscape) */
|
|
48
|
+
setRotation(rotation: number): Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
//# sourceMappingURL=adb.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adb.d.ts","sourceRoot":"","sources":["../../../../src/platform/android/adb.ts"],"names":[],"mappings":"AAMA;;GAEG;AACH,qBAAa,GAAG;IAGF,OAAO,CAAC,QAAQ;IAF5B,OAAO,CAAC,OAAO,CAAS;gBAEJ,QAAQ,EAAE,MAAM;IAQpC,qFAAqF;IAC/E,KAAK,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,CAAC;IAc7C,yCAAyC;IACnC,IAAI,CAAC,GAAG,IAAI,EAAE,MAAM,EAAE,GAAG,OAAO,CAAC,MAAM,CAAC;IAS9C,+DAA+D;IACzD,UAAU,IAAI,OAAO,CAAC,MAAM,CAAC;IAcnC,6CAA6C;IACvC,eAAe,IAAI,OAAO,CAAC,MAAM,CAAC;IAyBxC,gCAAgC;IAC1B,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,gCAAgC;IAC1B,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,GAAE,MAAa,GAAG,OAAO,CAAC,IAAI,CAAC;IAM/E,+BAA+B;IACzB,KAAK,CACT,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,GAAE,MAAY,GACvB,OAAO,CAAC,IAAI,CAAC;IAMhB,gCAAgC;IAC1B,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAiB3C,wBAAwB;IAClB,QAAQ,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI9C,6BAA6B;IACvB,aAAa,IAAI,OAAO,CAAC;QAAE,KAAK,EAAE,MAAM,CAAC;QAAC,MAAM,EAAE,MAAM,CAAA;KAAE,CAAC;IAOjE,gGAAgG;IAC1F,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAQvC,0BAA0B;IACpB,iBAAiB,IAAI,OAAO,CAAC,MAAM,CAAC;IAI1C,4BAA4B;IACtB,aAAa,IAAI,OAAO,CAAC,MAAM,CAAC;IAItC,oCAAoC;IAC9B,SAAS,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMnD,wBAAwB;IAClB,YAAY,CAAC,WAAW,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAItD,qBAAqB;IACf,UAAU,CAAC,OAAO,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIhD,8BAA8B;IACxB,YAAY,IAAI,OAAO,CAAC,MAAM,EAAE,CAAC;IAQvC,iBAAiB;IACX,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAMzC,wDAAwD;IAClD,WAAW,CAAC,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAInD"}
|
|
@@ -0,0 +1,137 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Adb = void 0;
|
|
4
|
+
const child_process_1 = require("child_process");
|
|
5
|
+
const util_1 = require("util");
|
|
6
|
+
const retry_js_1 = require("../../utils/retry.js");
|
|
7
|
+
const execFileAsync = (0, util_1.promisify)(child_process_1.execFile);
|
|
8
|
+
/**
|
|
9
|
+
* ADB command wrapper — handles all communication with Android devices via ADB.
|
|
10
|
+
*/
|
|
11
|
+
class Adb {
|
|
12
|
+
deviceId;
|
|
13
|
+
adbPath;
|
|
14
|
+
constructor(deviceId) {
|
|
15
|
+
this.deviceId = deviceId;
|
|
16
|
+
const androidHome = process.env.ANDROID_HOME || process.env.ANDROID_SDK_ROOT;
|
|
17
|
+
this.adbPath = androidHome
|
|
18
|
+
? `${androidHome}/platform-tools/adb`
|
|
19
|
+
: "adb";
|
|
20
|
+
}
|
|
21
|
+
/** Execute an ADB shell command on the device (with retry for transient failures) */
|
|
22
|
+
async shell(command) {
|
|
23
|
+
return (0, retry_js_1.retry)(async () => {
|
|
24
|
+
const { stdout } = await execFileAsync(this.adbPath, ["-s", this.deviceId, "shell", command], { maxBuffer: 10 * 1024 * 1024, timeout: 30000 });
|
|
25
|
+
return stdout;
|
|
26
|
+
}, { maxAttempts: 2, delayMs: 500 });
|
|
27
|
+
}
|
|
28
|
+
/** Execute an ADB command (non-shell) */
|
|
29
|
+
async exec(...args) {
|
|
30
|
+
const { stdout } = await execFileAsync(this.adbPath, ["-s", this.deviceId, ...args], { maxBuffer: 10 * 1024 * 1024, timeout: 30000 });
|
|
31
|
+
return stdout;
|
|
32
|
+
}
|
|
33
|
+
/** Take a screenshot and return the PNG buffer (with retry) */
|
|
34
|
+
async screenshot() {
|
|
35
|
+
return (0, retry_js_1.retry)(async () => {
|
|
36
|
+
const { stdout } = await execFileAsync(this.adbPath, ["-s", this.deviceId, "exec-out", "screencap", "-p"], { maxBuffer: 20 * 1024 * 1024, encoding: "buffer", timeout: 15000 });
|
|
37
|
+
return stdout;
|
|
38
|
+
}, { maxAttempts: 2, delayMs: 300 });
|
|
39
|
+
}
|
|
40
|
+
/** Dump the UI hierarchy XML (with retry) */
|
|
41
|
+
async dumpUiHierarchy() {
|
|
42
|
+
return (0, retry_js_1.retry)(async () => {
|
|
43
|
+
const dumpPath = "/sdcard/devlens-ui-dump.xml";
|
|
44
|
+
await execFileAsync(this.adbPath, ["-s", this.deviceId, "shell", `uiautomator dump ${dumpPath}`], { maxBuffer: 10 * 1024 * 1024, timeout: 30000 });
|
|
45
|
+
const { stdout: xml } = await execFileAsync(this.adbPath, ["-s", this.deviceId, "shell", `cat ${dumpPath}`], { maxBuffer: 10 * 1024 * 1024, timeout: 30000 });
|
|
46
|
+
// Clean up
|
|
47
|
+
execFileAsync(this.adbPath, ["-s", this.deviceId, "shell", `rm ${dumpPath}`]).catch(() => { });
|
|
48
|
+
return xml;
|
|
49
|
+
}, { maxAttempts: 2, delayMs: 500 });
|
|
50
|
+
}
|
|
51
|
+
/** Tap at screen coordinates */
|
|
52
|
+
async tap(x, y) {
|
|
53
|
+
await this.shell(`input tap ${Math.round(x)} ${Math.round(y)}`);
|
|
54
|
+
}
|
|
55
|
+
/** Long press at coordinates */
|
|
56
|
+
async longPress(x, y, durationMs = 1000) {
|
|
57
|
+
await this.shell(`input swipe ${Math.round(x)} ${Math.round(y)} ${Math.round(x)} ${Math.round(y)} ${durationMs}`);
|
|
58
|
+
}
|
|
59
|
+
/** Swipe between two points */
|
|
60
|
+
async swipe(startX, startY, endX, endY, durationMs = 300) {
|
|
61
|
+
await this.shell(`input swipe ${Math.round(startX)} ${Math.round(startY)} ${Math.round(endX)} ${Math.round(endY)} ${durationMs}`);
|
|
62
|
+
}
|
|
63
|
+
/** Type text using ADB input */
|
|
64
|
+
async typeText(text) {
|
|
65
|
+
// Escape special characters for ADB shell
|
|
66
|
+
const escaped = text
|
|
67
|
+
.replace(/\\/g, "\\\\")
|
|
68
|
+
.replace(/"/g, '\\"')
|
|
69
|
+
.replace(/ /g, "%s")
|
|
70
|
+
.replace(/'/g, "\\'")
|
|
71
|
+
.replace(/&/g, "\\&")
|
|
72
|
+
.replace(/</g, "\\<")
|
|
73
|
+
.replace(/>/g, "\\>")
|
|
74
|
+
.replace(/\|/g, "\\|")
|
|
75
|
+
.replace(/;/g, "\\;")
|
|
76
|
+
.replace(/\(/g, "\\(")
|
|
77
|
+
.replace(/\)/g, "\\)");
|
|
78
|
+
await this.shell(`input text "${escaped}"`);
|
|
79
|
+
}
|
|
80
|
+
/** Press a key event */
|
|
81
|
+
async keyEvent(keyCode) {
|
|
82
|
+
await this.shell(`input keyevent ${keyCode}`);
|
|
83
|
+
}
|
|
84
|
+
/** Get device screen size */
|
|
85
|
+
async getScreenSize() {
|
|
86
|
+
const output = await this.shell("wm size");
|
|
87
|
+
const match = output.match(/(\d+)x(\d+)/);
|
|
88
|
+
if (!match)
|
|
89
|
+
throw new Error("Could not determine screen size");
|
|
90
|
+
return { width: parseInt(match[1]), height: parseInt(match[2]) };
|
|
91
|
+
}
|
|
92
|
+
/** Get device orientation (0=portrait, 1=landscape, 2=reverse-portrait, 3=reverse-landscape) */
|
|
93
|
+
async getOrientation() {
|
|
94
|
+
const output = await this.shell("dumpsys input | grep 'SurfaceOrientation'");
|
|
95
|
+
const match = output.match(/SurfaceOrientation:\s*(\d)/);
|
|
96
|
+
return match ? parseInt(match[1]) : 0;
|
|
97
|
+
}
|
|
98
|
+
/** Get Android version */
|
|
99
|
+
async getAndroidVersion() {
|
|
100
|
+
return (await this.shell("getprop ro.build.version.release")).trim();
|
|
101
|
+
}
|
|
102
|
+
/** Get device model name */
|
|
103
|
+
async getDeviceName() {
|
|
104
|
+
return (await this.shell("getprop ro.product.model")).trim();
|
|
105
|
+
}
|
|
106
|
+
/** Launch an app by package name */
|
|
107
|
+
async launchApp(packageName) {
|
|
108
|
+
await this.shell(`monkey -p ${packageName} -c android.intent.category.LAUNCHER 1`);
|
|
109
|
+
}
|
|
110
|
+
/** Force stop an app */
|
|
111
|
+
async terminateApp(packageName) {
|
|
112
|
+
await this.shell(`am force-stop ${packageName}`);
|
|
113
|
+
}
|
|
114
|
+
/** Install an APK */
|
|
115
|
+
async installApp(apkPath) {
|
|
116
|
+
await this.exec("install", "-r", apkPath);
|
|
117
|
+
}
|
|
118
|
+
/** List installed packages */
|
|
119
|
+
async listPackages() {
|
|
120
|
+
const output = await this.shell("pm list packages -3");
|
|
121
|
+
return output
|
|
122
|
+
.split("\n")
|
|
123
|
+
.filter((line) => line.startsWith("package:"))
|
|
124
|
+
.map((line) => line.replace("package:", "").trim());
|
|
125
|
+
}
|
|
126
|
+
/** Open a URL */
|
|
127
|
+
async openUrl(url) {
|
|
128
|
+
await this.shell(`am start -a android.intent.action.VIEW -d "${url}"`);
|
|
129
|
+
}
|
|
130
|
+
/** Set orientation (0=auto, 1=portrait, 2=landscape) */
|
|
131
|
+
async setRotation(rotation) {
|
|
132
|
+
await this.shell("settings put system accelerometer_rotation 0");
|
|
133
|
+
await this.shell(`settings put system user_rotation ${rotation}`);
|
|
134
|
+
}
|
|
135
|
+
}
|
|
136
|
+
exports.Adb = Adb;
|
|
137
|
+
//# sourceMappingURL=adb.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"adb.js","sourceRoot":"","sources":["../../../../src/platform/android/adb.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import type { Device, DeviceInfo, AppInfo, SnapshotNode } from "../device.js";
|
|
2
|
+
export declare class AndroidDevice implements Device {
|
|
3
|
+
private adb;
|
|
4
|
+
constructor(deviceId: string);
|
|
5
|
+
getInfo(): Promise<DeviceInfo>;
|
|
6
|
+
getSnapshot(): Promise<SnapshotNode>;
|
|
7
|
+
takeScreenshot(): Promise<Buffer>;
|
|
8
|
+
tap(x: number, y: number): Promise<void>;
|
|
9
|
+
doubleTap(x: number, y: number): Promise<void>;
|
|
10
|
+
longPress(x: number, y: number, durationMs?: number): Promise<void>;
|
|
11
|
+
typeText(text: string): Promise<void>;
|
|
12
|
+
swipe(startX: number, startY: number, endX: number, endY: number, durationMs?: number): Promise<void>;
|
|
13
|
+
pressButton(button: "home" | "back" | "enter"): Promise<void>;
|
|
14
|
+
setOrientation(orientation: "portrait" | "landscape"): Promise<void>;
|
|
15
|
+
launchApp(appId: string): Promise<void>;
|
|
16
|
+
terminateApp(appId: string): Promise<void>;
|
|
17
|
+
installApp(path: string): Promise<void>;
|
|
18
|
+
listApps(): Promise<AppInfo[]>;
|
|
19
|
+
openUrl(url: string): Promise<void>;
|
|
20
|
+
}
|
|
21
|
+
//# sourceMappingURL=android-device.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"android-device.d.ts","sourceRoot":"","sources":["../../../../src/platform/android/android-device.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,MAAM,EAAE,UAAU,EAAE,OAAO,EAAE,YAAY,EAAE,MAAM,cAAc,CAAC;AAS9E,qBAAa,aAAc,YAAW,MAAM;IAC1C,OAAO,CAAC,GAAG,CAAM;gBAEL,QAAQ,EAAE,MAAM;IAItB,OAAO,IAAI,OAAO,CAAC,UAAU,CAAC;IAoB9B,WAAW,IAAI,OAAO,CAAC,YAAY,CAAC;IAKpC,cAAc,IAAI,OAAO,CAAC,MAAM,CAAC;IAIjC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIxC,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAM9C,SAAS,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,MAAM,EAAE,UAAU,SAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAIjE,QAAQ,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIrC,KAAK,CACT,MAAM,EAAE,MAAM,EACd,MAAM,EAAE,MAAM,EACd,IAAI,EAAE,MAAM,EACZ,IAAI,EAAE,MAAM,EACZ,UAAU,SAAM,GACf,OAAO,CAAC,IAAI,CAAC;IAIV,WAAW,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,GAAG,OAAO,GAAG,OAAO,CAAC,IAAI,CAAC;IAS7D,cAAc,CAAC,WAAW,EAAE,UAAU,GAAG,WAAW,GAAG,OAAO,CAAC,IAAI,CAAC;IAKpE,SAAS,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,YAAY,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAI1C,UAAU,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;IAIvC,QAAQ,IAAI,OAAO,CAAC,OAAO,EAAE,CAAC;IAS9B,OAAO,CAAC,GAAG,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC;CAG1C"}
|