@ceraph/react-native-mcp 0.2.2 → 0.3.1
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/LICENSE +116 -15
- package/README.md +79 -77
- package/assets/default.png +0 -0
- package/dist/app-lifecycle.d.ts +50 -0
- package/dist/app-lifecycle.js +487 -0
- package/dist/camera-image-writer.d.ts +43 -0
- package/dist/camera-image-writer.js +280 -0
- package/dist/camera-registry-sync.d.ts +18 -0
- package/dist/camera-registry-sync.js +117 -0
- package/dist/cli.d.ts +0 -7
- package/dist/cli.js +41 -9
- package/dist/device-autonomy.d.ts +30 -0
- package/dist/device-autonomy.js +117 -0
- package/dist/error-parser.d.ts +6 -26
- package/dist/error-parser.js +4 -74
- package/dist/expo-manager.d.ts +2 -74
- package/dist/expo-manager.js +11 -125
- package/dist/index.d.ts +0 -7
- package/dist/index.js +1266 -56
- package/dist/init/ast-camera.d.ts +29 -0
- package/dist/init/ast-camera.js +267 -0
- package/dist/init/ast-layout.d.ts +15 -0
- package/dist/init/ast-layout.js +167 -0
- package/dist/init/claude-hook-constants.d.ts +9 -0
- package/dist/init/claude-hook-constants.js +91 -0
- package/dist/init/lan-ip.d.ts +11 -0
- package/dist/init/lan-ip.js +51 -0
- package/dist/init/monorepo.d.ts +13 -0
- package/dist/init/monorepo.js +185 -0
- package/dist/init/oauth.d.ts +52 -0
- package/dist/init/oauth.js +220 -0
- package/dist/init/package-manager.d.ts +11 -0
- package/dist/init/package-manager.js +60 -0
- package/dist/init/prompt.d.ts +12 -0
- package/dist/init/prompt.js +68 -0
- package/dist/init/shell-profile.d.ts +22 -0
- package/dist/init/shell-profile.js +85 -0
- package/dist/init/steps.d.ts +135 -0
- package/dist/init/steps.js +399 -0
- package/dist/init/url-scheme.d.ts +42 -0
- package/dist/init/url-scheme.js +187 -0
- package/dist/init/walkthrough.d.ts +76 -0
- package/dist/init/walkthrough.js +340 -0
- package/dist/init.d.ts +7 -7
- package/dist/init.js +280 -120
- package/dist/iproxy-manager.d.ts +32 -0
- package/dist/iproxy-manager.js +216 -0
- package/dist/mac-caffeinate.d.ts +10 -0
- package/dist/mac-caffeinate.js +56 -0
- package/dist/permission-interceptor.d.ts +29 -0
- package/dist/permission-interceptor.js +185 -0
- package/dist/prebuild-detector.d.ts +0 -30
- package/dist/prebuild-detector.js +1 -42
- package/dist/preflight.d.ts +34 -0
- package/dist/preflight.js +847 -0
- package/dist/screen.d.ts +132 -43
- package/dist/screen.js +668 -94
- package/dist/shim/boot.d.ts +41 -0
- package/dist/shim/boot.js +141 -0
- package/dist/shim/camera.d.ts +22 -0
- package/dist/shim/camera.js +62 -0
- package/dist/shim/config.d.ts +6 -0
- package/dist/shim/config.js +56 -0
- package/dist/shim/deep-link.d.ts +1 -0
- package/dist/shim/deep-link.js +25 -0
- package/dist/shim/dev-guard.d.ts +1 -0
- package/dist/shim/dev-guard.js +3 -0
- package/dist/shim/error-handler.d.ts +20 -0
- package/dist/shim/error-handler.js +66 -0
- package/dist/shim/fetch-interceptor.d.ts +13 -0
- package/dist/shim/fetch-interceptor.js +93 -0
- package/dist/shim/index.d.ts +6 -0
- package/dist/shim/index.js +6 -0
- package/dist/shim/keep-awake.d.ts +13 -0
- package/dist/shim/keep-awake.js +118 -0
- package/dist/shim/reload.d.ts +23 -0
- package/dist/shim/reload.js +76 -0
- package/dist/shim/signal-capture.d.ts +11 -0
- package/dist/shim/signal-capture.js +15 -0
- package/dist/shim/signal-transport.d.ts +17 -0
- package/dist/shim/signal-transport.js +43 -0
- package/dist/signal-listener.d.ts +27 -0
- package/dist/signal-listener.js +135 -0
- package/dist/simulator-boot.d.ts +52 -0
- package/dist/simulator-boot.js +227 -0
- package/dist/target.d.ts +48 -0
- package/dist/target.js +267 -0
- package/dist/uninstall/cli-runner.d.ts +32 -0
- package/dist/uninstall/cli-runner.js +223 -0
- package/dist/uninstall/footprint.d.ts +40 -0
- package/dist/uninstall/footprint.js +288 -0
- package/dist/uninstall/mcp-tools.d.ts +14 -0
- package/dist/uninstall/mcp-tools.js +175 -0
- package/dist/uninstall/revert-auth.d.ts +22 -0
- package/dist/uninstall/revert-auth.js +31 -0
- package/dist/uninstall/revert-boot.d.ts +24 -0
- package/dist/uninstall/revert-boot.js +242 -0
- package/dist/uninstall/revert-camera.d.ts +12 -0
- package/dist/uninstall/revert-camera.js +199 -0
- package/dist/uninstall/revert-ceraph-dir.d.ts +27 -0
- package/dist/uninstall/revert-ceraph-dir.js +38 -0
- package/dist/uninstall/revert-claude-hooks.d.ts +19 -0
- package/dist/uninstall/revert-claude-hooks.js +191 -0
- package/dist/uninstall/revert-gitignore.d.ts +17 -0
- package/dist/uninstall/revert-gitignore.js +43 -0
- package/dist/uninstall/revert-mcp-clients.d.ts +57 -0
- package/dist/uninstall/revert-mcp-clients.js +194 -0
- package/dist/uninstall/revert-package.d.ts +34 -0
- package/dist/uninstall/revert-package.js +98 -0
- package/dist/uninstall/revert-scheme.d.ts +36 -0
- package/dist/uninstall/revert-scheme.js +139 -0
- package/dist/uninstall/revert-signal-host-env.d.ts +31 -0
- package/dist/uninstall/revert-signal-host-env.js +61 -0
- package/dist/uninstall/walkthrough.d.ts +80 -0
- package/dist/uninstall/walkthrough.js +1244 -0
- package/dist/utils/atomic-write.d.ts +1 -0
- package/dist/utils/atomic-write.js +30 -0
- package/dist/wait-for-device.d.ts +68 -0
- package/dist/wait-for-device.js +368 -0
- package/dist/wda-manager.d.ts +38 -0
- package/dist/wda-manager.js +186 -0
- package/dist/wda-simulator.d.ts +28 -0
- package/dist/wda-simulator.js +257 -0
- package/package.json +38 -5
package/dist/expo-manager.js
CHANGED
|
@@ -1,9 +1,3 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Manages React Native / Expo child processes (build and Metro dev server).
|
|
3
|
-
* Auto-detects whether the project uses Expo or bare React Native
|
|
4
|
-
* and runs the appropriate commands.
|
|
5
|
-
* Captures stdout/stderr into rolling buffers and parses errors.
|
|
6
|
-
*/
|
|
7
1
|
import { spawn } from "node:child_process";
|
|
8
2
|
import { writeFile, access } from "node:fs/promises";
|
|
9
3
|
import { join } from "node:path";
|
|
@@ -19,30 +13,18 @@ export class RNManager {
|
|
|
19
13
|
runtimeErrors = [];
|
|
20
14
|
buildWarnings = [];
|
|
21
15
|
metroWarnings = [];
|
|
22
|
-
// Parser state must persist across `onData` chunks so that an error
|
|
23
|
-
// whose message and stack trace arrive in separate chunks is still
|
|
24
|
-
// assembled into a single RuntimeError. Resetting on every chunk
|
|
25
|
-
// (the previous bug) caused the .rn-errors.json hook to fire with
|
|
26
|
-
// the message but no stack, or to drop multi-line errors entirely.
|
|
27
16
|
metroParser = new MetroErrorParser();
|
|
28
17
|
MAX_BUILD_LINES = 1000;
|
|
29
18
|
MAX_METRO_LINES = 500;
|
|
30
19
|
MAX_ERRORS = 100;
|
|
31
|
-
/** The working directory for commands. */
|
|
32
20
|
cwd;
|
|
33
|
-
/** Path to the error file that triggers the Claude Code hook. */
|
|
34
21
|
errorFilePath;
|
|
35
22
|
constructor(cwd) {
|
|
36
23
|
this.cwd = cwd;
|
|
37
24
|
this.errorFilePath = join(cwd, ".rn-errors.json");
|
|
38
25
|
}
|
|
39
|
-
/**
|
|
40
|
-
* Detect whether this is an Expo or bare React Native project.
|
|
41
|
-
* Checks for app.json with expo config or expo package in dependencies.
|
|
42
|
-
*/
|
|
43
26
|
async detectProjectType() {
|
|
44
27
|
try {
|
|
45
|
-
// Check for app.json with expo key
|
|
46
28
|
const appJsonPath = join(this.cwd, "app.json");
|
|
47
29
|
await access(appJsonPath);
|
|
48
30
|
const appJson = JSON.parse(await (await import("node:fs/promises")).readFile(appJsonPath, "utf-8"));
|
|
@@ -51,10 +33,8 @@ export class RNManager {
|
|
|
51
33
|
}
|
|
52
34
|
}
|
|
53
35
|
catch {
|
|
54
|
-
// No app.json or no expo key
|
|
55
36
|
}
|
|
56
37
|
try {
|
|
57
|
-
// Check for expo in package.json dependencies
|
|
58
38
|
const pkgPath = join(this.cwd, "package.json");
|
|
59
39
|
const pkg = JSON.parse(await (await import("node:fs/promises")).readFile(pkgPath, "utf-8"));
|
|
60
40
|
if (pkg.dependencies?.expo) {
|
|
@@ -62,14 +42,9 @@ export class RNManager {
|
|
|
62
42
|
}
|
|
63
43
|
}
|
|
64
44
|
catch {
|
|
65
|
-
// No package.json
|
|
66
45
|
}
|
|
67
46
|
return false;
|
|
68
47
|
}
|
|
69
|
-
/**
|
|
70
|
-
* Write errors to .rn-errors.json so the Claude Code hook can detect them.
|
|
71
|
-
* Overwrites the file each time — the hook fires on any write.
|
|
72
|
-
*/
|
|
73
48
|
async writeErrorFile(errors) {
|
|
74
49
|
try {
|
|
75
50
|
await writeFile(this.errorFilePath, JSON.stringify({
|
|
@@ -78,54 +53,40 @@ export class RNManager {
|
|
|
78
53
|
message: e.message,
|
|
79
54
|
stack: e.stack,
|
|
80
55
|
timestamp: e.timestamp,
|
|
56
|
+
kind: e.kind ?? "metro-error",
|
|
57
|
+
...(e.url !== undefined ? { url: e.url } : {}),
|
|
58
|
+
...(e.status !== undefined ? { status: e.status } : {}),
|
|
59
|
+
...(e.method !== undefined ? { method: e.method } : {}),
|
|
60
|
+
...(e.durationMs !== undefined ? { durationMs: e.durationMs } : {}),
|
|
81
61
|
})),
|
|
82
62
|
}, null, 2), "utf-8");
|
|
83
63
|
}
|
|
84
64
|
catch {
|
|
85
|
-
// Non-critical — don't break the process over a file write
|
|
86
65
|
}
|
|
87
66
|
}
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
67
|
+
async appendShimSignal(entry) {
|
|
68
|
+
this.runtimeErrors.push(entry);
|
|
69
|
+
this.capErrors(this.runtimeErrors);
|
|
70
|
+
await this.writeErrorFile(this.runtimeErrors);
|
|
71
|
+
}
|
|
91
72
|
async clearErrorFile() {
|
|
92
73
|
try {
|
|
93
74
|
await writeFile(this.errorFilePath, JSON.stringify({ timestamp: new Date().toISOString(), errors: [] }), "utf-8");
|
|
94
75
|
}
|
|
95
76
|
catch {
|
|
96
|
-
// Non-critical
|
|
97
77
|
}
|
|
98
78
|
}
|
|
99
|
-
/**
|
|
100
|
-
* Append a line to a rolling buffer, evicting oldest entries when full.
|
|
101
|
-
*/
|
|
102
79
|
pushLine(buffer, line, max) {
|
|
103
80
|
buffer.push(line);
|
|
104
81
|
if (buffer.length > max) {
|
|
105
82
|
buffer.splice(0, buffer.length - max);
|
|
106
83
|
}
|
|
107
84
|
}
|
|
108
|
-
/**
|
|
109
|
-
* Cap an error array at MAX_ERRORS, dropping oldest entries.
|
|
110
|
-
*/
|
|
111
85
|
capErrors(arr) {
|
|
112
86
|
if (arr.length > this.MAX_ERRORS) {
|
|
113
87
|
arr.splice(0, arr.length - this.MAX_ERRORS);
|
|
114
88
|
}
|
|
115
89
|
}
|
|
116
|
-
/**
|
|
117
|
-
* Kill a child process gracefully (SIGTERM, then SIGKILL after timeout).
|
|
118
|
-
*
|
|
119
|
-
* The promise resolves only when the process actually exits, not when
|
|
120
|
-
* SIGKILL is sent. Resolving on the SIGKILL timer was a race: callers
|
|
121
|
-
* (e.g. `runBuild`) would spawn a new build while the old Xcode process
|
|
122
|
-
* was still releasing DerivedData / build locks, causing cryptic
|
|
123
|
-
* SIGABRT or "file locked" errors on the new build.
|
|
124
|
-
*
|
|
125
|
-
* A hard upper-bound timer (2s after SIGKILL) guards against the
|
|
126
|
-
* pathological case where a process refuses to die at all, so callers
|
|
127
|
-
* never hang forever.
|
|
128
|
-
*/
|
|
129
90
|
async killProcess(proc) {
|
|
130
91
|
return new Promise((resolve) => {
|
|
131
92
|
if (!proc.pid || proc.exitCode !== null) {
|
|
@@ -138,10 +99,7 @@ export class RNManager {
|
|
|
138
99
|
proc.kill("SIGKILL");
|
|
139
100
|
}
|
|
140
101
|
catch {
|
|
141
|
-
// Process may have already exited between checks.
|
|
142
102
|
}
|
|
143
|
-
// Wait for `exit` to fire after SIGKILL, but bound the wait so
|
|
144
|
-
// callers don't hang on a process that refuses to die.
|
|
145
103
|
hardTimer = setTimeout(() => {
|
|
146
104
|
proc.off("exit", onExit);
|
|
147
105
|
resolve();
|
|
@@ -158,18 +116,11 @@ export class RNManager {
|
|
|
158
116
|
proc.kill("SIGTERM");
|
|
159
117
|
}
|
|
160
118
|
catch {
|
|
161
|
-
// Process already exited or PID is gone — treat as done. Detach
|
|
162
|
-
// the exit listener so it doesn't fire stale on a stop/start cycle.
|
|
163
119
|
proc.off("exit", onExit);
|
|
164
120
|
clearTimeout(softTimer);
|
|
165
121
|
resolve();
|
|
166
122
|
return;
|
|
167
123
|
}
|
|
168
|
-
// TOCTOU recovery: if the process exited between the entry guard
|
|
169
|
-
// and the `once("exit")` registration above, `kill()` returns false
|
|
170
|
-
// (no throw) and our listener never fires for the already-emitted
|
|
171
|
-
// exit. Re-check `exitCode` here so we don't wait the full 7s on
|
|
172
|
-
// the hard timer.
|
|
173
124
|
if (proc.exitCode !== null) {
|
|
174
125
|
proc.off("exit", onExit);
|
|
175
126
|
clearTimeout(softTimer);
|
|
@@ -177,9 +128,6 @@ export class RNManager {
|
|
|
177
128
|
}
|
|
178
129
|
});
|
|
179
130
|
}
|
|
180
|
-
/**
|
|
181
|
-
* Run `npx expo prebuild --clean` synchronously (waits for exit).
|
|
182
|
-
*/
|
|
183
131
|
runPrebuildClean() {
|
|
184
132
|
return new Promise((resolve) => {
|
|
185
133
|
const lines = [];
|
|
@@ -196,8 +144,6 @@ export class RNManager {
|
|
|
196
144
|
};
|
|
197
145
|
proc.stdout?.on("data", onData);
|
|
198
146
|
proc.stderr?.on("data", onData);
|
|
199
|
-
// Node fires both `error` and `exit` on a failed spawn. Guard so
|
|
200
|
-
// the second handler doesn't run a stale resolve / output dump.
|
|
201
147
|
let resolved = false;
|
|
202
148
|
proc.on("error", (err) => {
|
|
203
149
|
if (resolved)
|
|
@@ -219,28 +165,17 @@ export class RNManager {
|
|
|
219
165
|
});
|
|
220
166
|
});
|
|
221
167
|
}
|
|
222
|
-
/**
|
|
223
|
-
* Build and run the app on an iOS device or simulator.
|
|
224
|
-
* Auto-detects Expo vs bare React Native and uses the appropriate command:
|
|
225
|
-
* - Expo: `npx expo run:ios`
|
|
226
|
-
* - Bare RN: `npx react-native run-ios`
|
|
227
|
-
*
|
|
228
|
-
* Optionally runs `npx expo prebuild --clean` first (Expo only).
|
|
229
|
-
*/
|
|
230
168
|
async runBuild(options = {}) {
|
|
231
169
|
const isExpo = await this.detectProjectType();
|
|
232
|
-
// Kill any existing build process
|
|
233
170
|
if (this.buildProcess) {
|
|
234
171
|
this.buildKilled = true;
|
|
235
172
|
await this.killProcess(this.buildProcess);
|
|
236
173
|
this.buildProcess = null;
|
|
237
174
|
}
|
|
238
|
-
// Reset state
|
|
239
175
|
this.buildKilled = false;
|
|
240
176
|
this.buildOutput = [];
|
|
241
177
|
this.buildErrors = [];
|
|
242
178
|
this.buildWarnings = [];
|
|
243
|
-
// Run prebuild --clean if requested (Expo only)
|
|
244
179
|
if (options.clean) {
|
|
245
180
|
if (!isExpo) {
|
|
246
181
|
return {
|
|
@@ -273,12 +208,10 @@ export class RNManager {
|
|
|
273
208
|
output: prebuildResult.output,
|
|
274
209
|
};
|
|
275
210
|
}
|
|
276
|
-
// Add prebuild output to build output
|
|
277
211
|
for (const line of prebuildResult.output.split("\n")) {
|
|
278
212
|
this.pushLine(this.buildOutput, line, this.MAX_BUILD_LINES);
|
|
279
213
|
}
|
|
280
214
|
}
|
|
281
|
-
// Construct the build command based on project type
|
|
282
215
|
const args = isExpo ? ["expo", "run:ios"] : ["react-native", "run-ios"];
|
|
283
216
|
if (options.device) {
|
|
284
217
|
args.push(isExpo ? "--device" : "--udid", options.device);
|
|
@@ -299,10 +232,6 @@ export class RNManager {
|
|
|
299
232
|
};
|
|
300
233
|
proc.stdout?.on("data", onData);
|
|
301
234
|
proc.stderr?.on("data", onData);
|
|
302
|
-
// Node fires both `error` and `exit` on a spawn failure. Guard so
|
|
303
|
-
// the `exit` handler doesn't re-parse the (likely empty) output
|
|
304
|
-
// and overwrite `this.buildErrors` / `this.buildWarnings` after
|
|
305
|
-
// the caller has already received the failure result.
|
|
306
235
|
let resolved = false;
|
|
307
236
|
proc.on("error", (err) => {
|
|
308
237
|
if (resolved)
|
|
@@ -337,7 +266,6 @@ export class RNManager {
|
|
|
337
266
|
});
|
|
338
267
|
return;
|
|
339
268
|
}
|
|
340
|
-
// Parse all captured output
|
|
341
269
|
const parsed = parseBuildOutput(this.buildOutput);
|
|
342
270
|
this.buildErrors = parsed.errors;
|
|
343
271
|
this.buildWarnings = parsed.warnings;
|
|
@@ -352,29 +280,18 @@ export class RNManager {
|
|
|
352
280
|
type: e.type,
|
|
353
281
|
})),
|
|
354
282
|
warnings: parsed.warnings,
|
|
355
|
-
output: this.buildOutput.slice(-100).join("\n"),
|
|
283
|
+
output: this.buildOutput.slice(-100).join("\n"),
|
|
356
284
|
});
|
|
357
285
|
});
|
|
358
286
|
});
|
|
359
287
|
}
|
|
360
|
-
/**
|
|
361
|
-
* Start the Metro dev server.
|
|
362
|
-
* Auto-detects Expo vs bare React Native:
|
|
363
|
-
* - Expo: `npx expo start --dev-client`
|
|
364
|
-
* - Bare RN: `npx react-native start`
|
|
365
|
-
*
|
|
366
|
-
* Spawns Metro in the background and continuously captures output.
|
|
367
|
-
* Returns quickly once Metro shows signs of being ready (or after a timeout).
|
|
368
|
-
*/
|
|
369
288
|
async startMetro(options = {}) {
|
|
370
289
|
const isExpo = await this.detectProjectType();
|
|
371
|
-
// Kill existing Metro process
|
|
372
290
|
if (this.metroProcess) {
|
|
373
291
|
this.metroKilled = true;
|
|
374
292
|
await this.killProcess(this.metroProcess);
|
|
375
293
|
this.metroProcess = null;
|
|
376
294
|
}
|
|
377
|
-
// Reset state
|
|
378
295
|
this.metroKilled = false;
|
|
379
296
|
this.metroOutput = [];
|
|
380
297
|
this.runtimeErrors = [];
|
|
@@ -399,9 +316,6 @@ export class RNManager {
|
|
|
399
316
|
let resolved = false;
|
|
400
317
|
const onData = (data) => {
|
|
401
318
|
const text = data.toString();
|
|
402
|
-
// Collect lines from this chunk and parse them as a batch.
|
|
403
|
-
// The parser is stateful, so an error whose message and stack
|
|
404
|
-
// straddle chunk boundaries is still assembled correctly.
|
|
405
319
|
const chunkLines = [];
|
|
406
320
|
for (const line of text.split("\n")) {
|
|
407
321
|
if (line.trim()) {
|
|
@@ -420,7 +334,6 @@ export class RNManager {
|
|
|
420
334
|
this.metroWarnings.push(...parsed.warnings);
|
|
421
335
|
}
|
|
422
336
|
}
|
|
423
|
-
// Detect Metro ready
|
|
424
337
|
if (!resolved && text.includes("Metro waiting on")) {
|
|
425
338
|
resolved = true;
|
|
426
339
|
resolve({
|
|
@@ -443,8 +356,6 @@ export class RNManager {
|
|
|
443
356
|
});
|
|
444
357
|
proc.on("exit", (code) => {
|
|
445
358
|
this.metroProcess = null;
|
|
446
|
-
// Flush any error still being assembled in the streaming parser
|
|
447
|
-
// so it surfaces in `.rn-errors.json` for the Claude Code hook.
|
|
448
359
|
const flushed = this.metroParser.flush();
|
|
449
360
|
if (flushed.runtimeErrors.length > 0) {
|
|
450
361
|
this.runtimeErrors.push(...flushed.runtimeErrors);
|
|
@@ -469,8 +380,6 @@ export class RNManager {
|
|
|
469
380
|
});
|
|
470
381
|
}
|
|
471
382
|
});
|
|
472
|
-
// If Metro doesn't show "ready" within 30s, resolve anyway
|
|
473
|
-
// -- it may still be starting up (pod install, etc.)
|
|
474
383
|
setTimeout(() => {
|
|
475
384
|
if (!resolved) {
|
|
476
385
|
resolved = true;
|
|
@@ -483,17 +392,7 @@ export class RNManager {
|
|
|
483
392
|
}, 30_000);
|
|
484
393
|
});
|
|
485
394
|
}
|
|
486
|
-
/**
|
|
487
|
-
* Return all captured errors from both build and runtime contexts.
|
|
488
|
-
*/
|
|
489
395
|
getErrors() {
|
|
490
|
-
// Only re-parse the buffer when Metro is NOT running. While the
|
|
491
|
-
// streaming parser holds in-progress state (header received, stack
|
|
492
|
-
// not yet), an independent re-parse would `flush()` a stackless
|
|
493
|
-
// copy of that same error and surface it as a duplicate-without-stack.
|
|
494
|
-
// Once Metro exits, the streaming parser has already been flushed
|
|
495
|
-
// in the `proc.on("exit")` handler, and re-parsing the buffer is a
|
|
496
|
-
// safe fallback for anything still missing.
|
|
497
396
|
const metroParsed = this.metroProcess === null
|
|
498
397
|
? parseMetroOutput(this.metroOutput)
|
|
499
398
|
: { runtimeErrors: [], warnings: [] };
|
|
@@ -512,9 +411,6 @@ export class RNManager {
|
|
|
512
411
|
warnings: [...this.buildWarnings, ...this.metroWarnings],
|
|
513
412
|
};
|
|
514
413
|
}
|
|
515
|
-
/**
|
|
516
|
-
* Return recent console output from Metro, optionally filtered by level.
|
|
517
|
-
*/
|
|
518
414
|
getConsole(options = {}) {
|
|
519
415
|
const { lines = 50, level = "all" } = options;
|
|
520
416
|
let output = this.metroOutput;
|
|
@@ -524,12 +420,8 @@ export class RNManager {
|
|
|
524
420
|
return classified === level;
|
|
525
421
|
});
|
|
526
422
|
}
|
|
527
|
-
// Return the last N lines
|
|
528
423
|
return output.slice(-lines);
|
|
529
424
|
}
|
|
530
|
-
/**
|
|
531
|
-
* Stop all managed Expo processes.
|
|
532
|
-
*/
|
|
533
425
|
async stopAll() {
|
|
534
426
|
const stopped = [];
|
|
535
427
|
if (this.buildProcess) {
|
|
@@ -546,15 +438,9 @@ export class RNManager {
|
|
|
546
438
|
}
|
|
547
439
|
return stopped;
|
|
548
440
|
}
|
|
549
|
-
/**
|
|
550
|
-
* Get the raw build output buffer (for diagnostics).
|
|
551
|
-
*/
|
|
552
441
|
getBuildOutput() {
|
|
553
442
|
return [...this.buildOutput];
|
|
554
443
|
}
|
|
555
|
-
/**
|
|
556
|
-
* Get the raw metro output buffer (for diagnostics).
|
|
557
|
-
*/
|
|
558
444
|
getMetroOutput() {
|
|
559
445
|
return [...this.metroOutput];
|
|
560
446
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -1,9 +1,2 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
|
-
/**
|
|
3
|
-
* @ceraph/react-native-mcp — MCP server for React Native / Expo development workflow.
|
|
4
|
-
*
|
|
5
|
-
* Auto-detects Expo vs bare React Native projects and uses the appropriate
|
|
6
|
-
* commands. Provides tools for building, running, error capture, screen
|
|
7
|
-
* interaction, and prebuild detection.
|
|
8
|
-
*/
|
|
9
2
|
export {};
|