@ceraph/react-native-mcp 0.3.2 → 0.4.5

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.
Files changed (132) hide show
  1. package/README.md +335 -68
  2. package/dist/babel-plugin/index.cjs +1 -0
  3. package/dist/babel-plugin/index.js +1 -0
  4. package/dist/cli.d.ts +3 -1
  5. package/dist/cli.js +1 -47
  6. package/dist/index.d.ts +106 -1
  7. package/dist/index.js +2 -1651
  8. package/dist/shim/async-storage-ops.d.ts +26 -0
  9. package/dist/shim/async-storage-ops.js +1 -0
  10. package/dist/shim/boot.d.ts +9 -0
  11. package/dist/shim/boot.js +1 -141
  12. package/dist/shim/camera.js +1 -62
  13. package/dist/shim/command-poll.d.ts +18 -0
  14. package/dist/shim/command-poll.js +1 -0
  15. package/dist/shim/config.js +1 -56
  16. package/dist/shim/console-capture.d.ts +16 -0
  17. package/dist/shim/console-capture.js +1 -0
  18. package/dist/shim/deep-link.js +1 -25
  19. package/dist/shim/dev-guard.js +1 -3
  20. package/dist/shim/dev-host.d.ts +1 -0
  21. package/dist/shim/dev-host.js +1 -0
  22. package/dist/shim/error-handler.js +1 -66
  23. package/dist/shim/fetch-interceptor.js +1 -93
  24. package/dist/shim/index.d.ts +3 -0
  25. package/dist/shim/index.js +1 -6
  26. package/dist/shim/keep-awake.js +1 -118
  27. package/dist/shim/network-ownership.d.ts +4 -0
  28. package/dist/shim/network-ownership.js +1 -0
  29. package/dist/shim/optimistic-observer.d.ts +29 -0
  30. package/dist/shim/optimistic-observer.js +1 -0
  31. package/dist/shim/reload.js +1 -76
  32. package/dist/shim/reset.d.ts +30 -0
  33. package/dist/shim/reset.js +1 -0
  34. package/dist/shim/signal-capture.d.ts +8 -0
  35. package/dist/shim/signal-capture.js +1 -15
  36. package/dist/shim/signal-transport.d.ts +14 -1
  37. package/dist/shim/signal-transport.js +1 -43
  38. package/dist/shim/xhr-interceptor.d.ts +39 -0
  39. package/dist/shim/xhr-interceptor.js +1 -0
  40. package/package.json +41 -15
  41. package/dist/app-lifecycle.d.ts +0 -50
  42. package/dist/app-lifecycle.js +0 -487
  43. package/dist/camera-image-writer.d.ts +0 -43
  44. package/dist/camera-image-writer.js +0 -280
  45. package/dist/camera-registry-sync.d.ts +0 -18
  46. package/dist/camera-registry-sync.js +0 -117
  47. package/dist/device-autonomy.d.ts +0 -30
  48. package/dist/device-autonomy.js +0 -117
  49. package/dist/error-parser.d.ts +0 -51
  50. package/dist/error-parser.js +0 -275
  51. package/dist/expo-manager.d.ts +0 -62
  52. package/dist/expo-manager.js +0 -447
  53. package/dist/init/ast-camera.d.ts +0 -29
  54. package/dist/init/ast-camera.js +0 -267
  55. package/dist/init/ast-layout.d.ts +0 -15
  56. package/dist/init/ast-layout.js +0 -167
  57. package/dist/init/claude-hook-constants.d.ts +0 -9
  58. package/dist/init/claude-hook-constants.js +0 -91
  59. package/dist/init/lan-ip.d.ts +0 -11
  60. package/dist/init/lan-ip.js +0 -51
  61. package/dist/init/monorepo.d.ts +0 -13
  62. package/dist/init/monorepo.js +0 -185
  63. package/dist/init/oauth.d.ts +0 -52
  64. package/dist/init/oauth.js +0 -220
  65. package/dist/init/package-manager.d.ts +0 -11
  66. package/dist/init/package-manager.js +0 -60
  67. package/dist/init/prompt.d.ts +0 -12
  68. package/dist/init/prompt.js +0 -68
  69. package/dist/init/shell-profile.d.ts +0 -22
  70. package/dist/init/shell-profile.js +0 -85
  71. package/dist/init/steps.d.ts +0 -135
  72. package/dist/init/steps.js +0 -399
  73. package/dist/init/url-scheme.d.ts +0 -42
  74. package/dist/init/url-scheme.js +0 -187
  75. package/dist/init/walkthrough.d.ts +0 -76
  76. package/dist/init/walkthrough.js +0 -340
  77. package/dist/init.d.ts +0 -8
  78. package/dist/init.js +0 -395
  79. package/dist/iproxy-manager.d.ts +0 -32
  80. package/dist/iproxy-manager.js +0 -216
  81. package/dist/mac-caffeinate.d.ts +0 -10
  82. package/dist/mac-caffeinate.js +0 -56
  83. package/dist/permission-interceptor.d.ts +0 -29
  84. package/dist/permission-interceptor.js +0 -185
  85. package/dist/prebuild-detector.d.ts +0 -19
  86. package/dist/prebuild-detector.js +0 -174
  87. package/dist/preflight.d.ts +0 -34
  88. package/dist/preflight.js +0 -847
  89. package/dist/screen.d.ts +0 -184
  90. package/dist/screen.js +0 -931
  91. package/dist/signal-listener.d.ts +0 -27
  92. package/dist/signal-listener.js +0 -135
  93. package/dist/simulator-boot.d.ts +0 -52
  94. package/dist/simulator-boot.js +0 -227
  95. package/dist/target.d.ts +0 -48
  96. package/dist/target.js +0 -267
  97. package/dist/uninstall/cli-runner.d.ts +0 -32
  98. package/dist/uninstall/cli-runner.js +0 -223
  99. package/dist/uninstall/footprint.d.ts +0 -40
  100. package/dist/uninstall/footprint.js +0 -288
  101. package/dist/uninstall/mcp-tools.d.ts +0 -14
  102. package/dist/uninstall/mcp-tools.js +0 -175
  103. package/dist/uninstall/revert-auth.d.ts +0 -22
  104. package/dist/uninstall/revert-auth.js +0 -31
  105. package/dist/uninstall/revert-boot.d.ts +0 -24
  106. package/dist/uninstall/revert-boot.js +0 -242
  107. package/dist/uninstall/revert-camera.d.ts +0 -12
  108. package/dist/uninstall/revert-camera.js +0 -199
  109. package/dist/uninstall/revert-ceraph-dir.d.ts +0 -27
  110. package/dist/uninstall/revert-ceraph-dir.js +0 -38
  111. package/dist/uninstall/revert-claude-hooks.d.ts +0 -19
  112. package/dist/uninstall/revert-claude-hooks.js +0 -191
  113. package/dist/uninstall/revert-gitignore.d.ts +0 -17
  114. package/dist/uninstall/revert-gitignore.js +0 -43
  115. package/dist/uninstall/revert-mcp-clients.d.ts +0 -57
  116. package/dist/uninstall/revert-mcp-clients.js +0 -194
  117. package/dist/uninstall/revert-package.d.ts +0 -34
  118. package/dist/uninstall/revert-package.js +0 -98
  119. package/dist/uninstall/revert-scheme.d.ts +0 -36
  120. package/dist/uninstall/revert-scheme.js +0 -139
  121. package/dist/uninstall/revert-signal-host-env.d.ts +0 -31
  122. package/dist/uninstall/revert-signal-host-env.js +0 -61
  123. package/dist/uninstall/walkthrough.d.ts +0 -80
  124. package/dist/uninstall/walkthrough.js +0 -1244
  125. package/dist/utils/atomic-write.d.ts +0 -1
  126. package/dist/utils/atomic-write.js +0 -30
  127. package/dist/wait-for-device.d.ts +0 -68
  128. package/dist/wait-for-device.js +0 -368
  129. package/dist/wda-manager.d.ts +0 -38
  130. package/dist/wda-manager.js +0 -186
  131. package/dist/wda-simulator.d.ts +0 -28
  132. package/dist/wda-simulator.js +0 -257
@@ -1,56 +0,0 @@
1
- import { spawn as nodeSpawn } from "node:child_process";
2
- let child = null;
3
- let active = false;
4
- let spawnerOverride = null;
5
- export function _resetForTesting() {
6
- child = null;
7
- active = false;
8
- spawnerOverride = null;
9
- }
10
- export function _setSpawnerForTesting(fn) {
11
- spawnerOverride = fn;
12
- }
13
- export function enableCaffeinate() {
14
- if (process.platform !== "darwin") {
15
- return { applied: false, reason: "not-darwin" };
16
- }
17
- if (active && child && !child.killed) {
18
- return { applied: true, reason: "already-active" };
19
- }
20
- try {
21
- const spawnFn = spawnerOverride ?? nodeSpawn;
22
- const proc = spawnFn("caffeinate", ["-di", "-w", String(process.pid)], {
23
- detached: true,
24
- stdio: "ignore",
25
- });
26
- if (typeof proc.unref === "function") {
27
- proc.unref();
28
- }
29
- child = proc;
30
- active = true;
31
- const thisChild = proc;
32
- proc.once("exit", () => {
33
- if (child === thisChild) {
34
- child = null;
35
- active = false;
36
- }
37
- });
38
- return { applied: true, reason: "started" };
39
- }
40
- catch {
41
- return { applied: false, reason: "spawn-failed" };
42
- }
43
- }
44
- export function disableCaffeinate() {
45
- if (!active)
46
- return;
47
- if (child) {
48
- try {
49
- child.kill("SIGTERM");
50
- }
51
- catch {
52
- }
53
- }
54
- child = null;
55
- active = false;
56
- }
@@ -1,29 +0,0 @@
1
- import type { ScreenManager } from "./screen.js";
2
- export type InterceptorMode = "auto-accept" | "ask" | "off";
3
- export interface PermissionInterceptorOpts {
4
- screen: ScreenManager;
5
- mode: InterceptorMode;
6
- onDialog?: (info: {
7
- title: string;
8
- body: string;
9
- }) => Promise<"accept" | "deny">;
10
- }
11
- export interface DialogInfo {
12
- title: string;
13
- body: string;
14
- action: "accept" | "deny";
15
- }
16
- export interface InterceptResult {
17
- handled: boolean;
18
- dialog?: DialogInfo;
19
- }
20
- export declare class PermissionInterceptor {
21
- private readonly screen;
22
- private mode;
23
- private readonly onDialog?;
24
- constructor(opts: PermissionInterceptorOpts);
25
- getMode(): InterceptorMode;
26
- setMode(mode: InterceptorMode): void;
27
- checkAndHandle(): Promise<InterceptResult>;
28
- }
29
- export declare function modeFromEnv(value: string | undefined): InterceptorMode;
@@ -1,185 +0,0 @@
1
- const KNOWN_DIALOGS = [
2
- {
3
- id: "camera",
4
- titlePattern: /Would Like to Access the Camera/i,
5
- acceptButtons: ["OK", "Allow"],
6
- },
7
- {
8
- id: "microphone",
9
- titlePattern: /Would Like to Access the Microphone/i,
10
- acceptButtons: ["OK", "Allow"],
11
- },
12
- {
13
- id: "photos",
14
- titlePattern: /Would Like to Access Your Photos/i,
15
- acceptButtons: [
16
- "Allow Access to All Photos",
17
- "Allow Full Access",
18
- "Allow",
19
- ],
20
- },
21
- {
22
- id: "location",
23
- titlePattern: /Allow .* to Use Your Location\??/i,
24
- acceptButtons: [
25
- "Allow While Using App",
26
- "Allow Once",
27
- "Allow",
28
- ],
29
- },
30
- {
31
- id: "notifications",
32
- titlePattern: /Would Like to Send You Notifications/i,
33
- acceptButtons: ["Allow"],
34
- },
35
- {
36
- id: "local-network",
37
- titlePattern: /Would Like to Find and Connect to Devices on Your Local Network/i,
38
- acceptButtons: ["Allow", "OK"],
39
- },
40
- {
41
- id: "bluetooth",
42
- titlePattern: /Would Like to Use Bluetooth/i,
43
- acceptButtons: ["OK", "Allow"],
44
- },
45
- {
46
- id: "tracking",
47
- titlePattern: /Allow .* to track your activity|would like permission to track/i,
48
- acceptButtons: ["Allow"],
49
- },
50
- {
51
- id: "faceid",
52
- titlePattern: /Would Like to Use Face ID/i,
53
- acceptButtons: ["OK", "Allow"],
54
- },
55
- ];
56
- const ALERT_TYPE_PATTERNS = [
57
- /XCUIElementTypeAlert/i,
58
- /SBAlertController/i,
59
- ];
60
- function isAlertElement(el) {
61
- const type = String(el.type ?? "");
62
- return ALERT_TYPE_PATTERNS.some((p) => p.test(type));
63
- }
64
- function findAlert(root) {
65
- if (isAlertElement(root))
66
- return root;
67
- const children = root.children;
68
- if (Array.isArray(children)) {
69
- for (const child of children) {
70
- const found = findAlert(child);
71
- if (found)
72
- return found;
73
- }
74
- }
75
- return null;
76
- }
77
- function collectAlertContents(root) {
78
- const texts = [];
79
- const buttons = [];
80
- const visit = (el) => {
81
- const type = String(el.type ?? "");
82
- const label = String(el.label ?? el.name ?? "");
83
- const value = String(el.value ?? "");
84
- if (/XCUIElementTypeStaticText/i.test(type)) {
85
- const text = label || value;
86
- if (text)
87
- texts.push(text);
88
- }
89
- else if (/XCUIElementTypeButton/i.test(type)) {
90
- if (label)
91
- buttons.push({ label, element: el });
92
- }
93
- else if (!type) {
94
- }
95
- const children = el.children;
96
- if (Array.isArray(children)) {
97
- for (const child of children)
98
- visit(child);
99
- }
100
- };
101
- visit(root);
102
- return { texts, buttons };
103
- }
104
- export class PermissionInterceptor {
105
- screen;
106
- mode;
107
- onDialog;
108
- constructor(opts) {
109
- this.screen = opts.screen;
110
- this.mode = opts.mode;
111
- this.onDialog = opts.onDialog;
112
- }
113
- getMode() {
114
- return this.mode;
115
- }
116
- setMode(mode) {
117
- this.mode = mode;
118
- }
119
- async checkAndHandle() {
120
- if (this.mode === "off") {
121
- return { handled: false };
122
- }
123
- const src = await this.screen.getSource().catch(() => undefined);
124
- if (!src?.success || !src.source) {
125
- return { handled: false };
126
- }
127
- const alert = findAlert(src.source);
128
- if (!alert)
129
- return { handled: false };
130
- const { texts, buttons } = collectAlertContents(alert);
131
- if (texts.length === 0 && buttons.length === 0) {
132
- return { handled: false };
133
- }
134
- const title = texts[0] ?? "";
135
- const body = texts.slice(1).join(" ");
136
- const pattern = KNOWN_DIALOGS.find((p) => p.titlePattern.test(title));
137
- if (!pattern) {
138
- return { handled: false };
139
- }
140
- let action = "accept";
141
- if (this.mode === "ask") {
142
- if (this.onDialog) {
143
- try {
144
- action = await this.onDialog({ title, body });
145
- }
146
- catch {
147
- action = "accept";
148
- }
149
- }
150
- }
151
- const buttonLabels = action === "accept"
152
- ? pattern.acceptButtons
153
- : pattern.denyButtons ?? ["Don't Allow", "Cancel"];
154
- const target = buttonLabels
155
- .map((preferred) => buttons.find((b) => b.label.toLowerCase() === preferred.toLowerCase()))
156
- .find((b) => !!b);
157
- if (!target) {
158
- return {
159
- handled: false,
160
- dialog: { title, body, action },
161
- };
162
- }
163
- const tap = await this.screen.findAndTap({
164
- accessibilityLabel: target.label,
165
- });
166
- if (!tap.success) {
167
- return {
168
- handled: false,
169
- dialog: { title, body, action },
170
- };
171
- }
172
- return {
173
- handled: true,
174
- dialog: { title, body, action },
175
- };
176
- }
177
- }
178
- export function modeFromEnv(value) {
179
- const v = (value ?? "").toLowerCase();
180
- if (v === "off" || v === "false" || v === "0")
181
- return "off";
182
- if (v === "ask")
183
- return "ask";
184
- return "auto-accept";
185
- }
@@ -1,19 +0,0 @@
1
- interface PrebuildCheckResult {
2
- needsClean: boolean;
3
- reasons: string[];
4
- }
5
- export declare class PrebuildDetector {
6
- private cacheDir;
7
- private projectDir;
8
- private snapshotPath;
9
- constructor(projectDir: string, cacheDir: string);
10
- private fileExists;
11
- private readJson;
12
- private hashFile;
13
- private getCurrentState;
14
- private loadSnapshot;
15
- saveSnapshot(): Promise<void>;
16
- private diffDependencies;
17
- check(): Promise<PrebuildCheckResult>;
18
- }
19
- export {};
@@ -1,174 +0,0 @@
1
- import { readFile, writeFile, mkdir, access } from "node:fs/promises";
2
- import { join } from "node:path";
3
- export class PrebuildDetector {
4
- cacheDir;
5
- projectDir;
6
- snapshotPath;
7
- constructor(projectDir, cacheDir) {
8
- this.projectDir = projectDir;
9
- this.cacheDir = cacheDir;
10
- this.snapshotPath = join(cacheDir, "last-build-snapshot.json");
11
- }
12
- async fileExists(path) {
13
- try {
14
- await access(path);
15
- return true;
16
- }
17
- catch {
18
- return false;
19
- }
20
- }
21
- async readJson(path) {
22
- try {
23
- const content = await readFile(path, "utf-8");
24
- return JSON.parse(content);
25
- }
26
- catch {
27
- return null;
28
- }
29
- }
30
- async hashFile(path) {
31
- try {
32
- const content = await readFile(path, "utf-8");
33
- let hash = 0;
34
- for (let i = 0; i < content.length; i++) {
35
- const chr = content.charCodeAt(i);
36
- hash = (hash << 5) - hash + chr;
37
- hash |= 0;
38
- }
39
- return hash.toString(36);
40
- }
41
- catch {
42
- return "missing";
43
- }
44
- }
45
- async getCurrentState() {
46
- const pkgJson = await this.readJson(join(this.projectDir, "package.json"));
47
- let appConfig = await this.readJson(join(this.projectDir, "app.json"));
48
- if (!appConfig) {
49
- const configHash = await this.hashFile(join(this.projectDir, "app.config.js"));
50
- const configTsHash = await this.hashFile(join(this.projectDir, "app.config.ts"));
51
- appConfig = {
52
- _fileHash: configHash,
53
- _tsFileHash: configTsHash,
54
- };
55
- }
56
- const podfileLockHash = await this.hashFile(join(this.projectDir, "ios", "Podfile.lock"));
57
- return {
58
- dependencies: (pkgJson?.dependencies ?? {}),
59
- devDependencies: (pkgJson?.devDependencies ?? {}),
60
- appConfig: appConfig ?? {},
61
- podfileLockHash,
62
- timestamp: new Date().toISOString(),
63
- };
64
- }
65
- async loadSnapshot() {
66
- try {
67
- const content = await readFile(this.snapshotPath, "utf-8");
68
- return JSON.parse(content);
69
- }
70
- catch {
71
- return null;
72
- }
73
- }
74
- async saveSnapshot() {
75
- const state = await this.getCurrentState();
76
- await mkdir(this.cacheDir, { recursive: true });
77
- await writeFile(this.snapshotPath, JSON.stringify(state, null, 2), "utf-8");
78
- }
79
- diffDependencies(oldDeps, newDeps) {
80
- const added = [];
81
- const removed = [];
82
- const changed = [];
83
- const allKeys = new Set([
84
- ...Object.keys(oldDeps),
85
- ...Object.keys(newDeps),
86
- ]);
87
- for (const key of allKeys) {
88
- if (!(key in oldDeps)) {
89
- added.push(key);
90
- }
91
- else if (!(key in newDeps)) {
92
- removed.push(key);
93
- }
94
- else if (oldDeps[key] !== newDeps[key]) {
95
- changed.push(key);
96
- }
97
- }
98
- return { added, removed, changed };
99
- }
100
- async check() {
101
- const reasons = [];
102
- const iosExists = await this.fileExists(join(this.projectDir, "ios"));
103
- if (!iosExists) {
104
- return {
105
- needsClean: true,
106
- reasons: [
107
- "ios/ directory does not exist. Run `npx expo prebuild` to generate native projects.",
108
- ],
109
- };
110
- }
111
- const snapshot = await this.loadSnapshot();
112
- if (!snapshot) {
113
- return {
114
- needsClean: true,
115
- reasons: [
116
- "No previous build snapshot found. Run a build to establish a baseline. " +
117
- "A clean prebuild is recommended for the first build.",
118
- ],
119
- };
120
- }
121
- const current = await this.getCurrentState();
122
- const depDiff = this.diffDependencies(snapshot.dependencies, current.dependencies);
123
- if (depDiff.added.length > 0) {
124
- reasons.push(`New dependencies added: ${depDiff.added.join(", ")}. ` +
125
- "Native modules may need linking.");
126
- }
127
- if (depDiff.removed.length > 0) {
128
- reasons.push(`Dependencies removed: ${depDiff.removed.join(", ")}. ` +
129
- "Stale native modules may cause build errors.");
130
- }
131
- if (depDiff.changed.length > 0) {
132
- const nativeIndicators = [
133
- "react-native",
134
- "expo",
135
- "@react-native",
136
- "react-native-",
137
- ];
138
- const nativeChanges = depDiff.changed.filter((dep) => nativeIndicators.some((indicator) => dep.includes(indicator)));
139
- if (nativeChanges.length > 0) {
140
- reasons.push(`Native dependency versions changed: ${nativeChanges.join(", ")}. ` +
141
- "Clean prebuild recommended.");
142
- }
143
- }
144
- const devDepDiff = this.diffDependencies(snapshot.devDependencies, current.devDependencies);
145
- if (devDepDiff.added.length > 0 || devDepDiff.removed.length > 0) {
146
- const nativeDevDeps = [
147
- ...devDepDiff.added,
148
- ...devDepDiff.removed,
149
- ].filter((dep) => dep.includes("react-native") ||
150
- dep.includes("expo") ||
151
- dep.includes("@react-native"));
152
- if (nativeDevDeps.length > 0) {
153
- reasons.push(`Native dev dependencies changed: ${nativeDevDeps.join(", ")}.`);
154
- }
155
- }
156
- const configChanged = JSON.stringify(snapshot.appConfig) !==
157
- JSON.stringify(current.appConfig);
158
- if (configChanged) {
159
- reasons.push("app.json / app.config.js has changed since last build. " +
160
- "Expo plugins or native config may have changed.");
161
- }
162
- if (current.podfileLockHash === "missing") {
163
- reasons.push("ios/Podfile.lock is missing. Pods may need to be installed.");
164
- }
165
- else if (snapshot.podfileLockHash !== current.podfileLockHash) {
166
- reasons.push("ios/Podfile.lock has changed since last build. " +
167
- "Pod dependencies may be out of sync.");
168
- }
169
- return {
170
- needsClean: reasons.length > 0,
171
- reasons,
172
- };
173
- }
174
- }
@@ -1,34 +0,0 @@
1
- import type { ScreenManager } from "./screen.js";
2
- import type { AppLifecycle } from "./app-lifecycle.js";
3
- import type { DeviceAutonomy } from "./device-autonomy.js";
4
- import type { TargetResolver } from "./target.js";
5
- import type { IproxyManager } from "./iproxy-manager.js";
6
- export interface PreflightOpts {
7
- screen: ScreenManager;
8
- apps: AppLifecycle;
9
- autonomy: DeviceAutonomy;
10
- iproxyManager?: IproxyManager | null;
11
- bundleId?: string;
12
- requiredEnv?: string[];
13
- expectedNetwork?: string;
14
- projectDir?: string;
15
- target?: TargetResolver;
16
- excludeRuntimeChecks?: boolean;
17
- }
18
- export interface PreflightCheck {
19
- name: string;
20
- ok: boolean;
21
- severity: "error" | "warning" | "info";
22
- message: string;
23
- remediation?: string;
24
- details?: Record<string, unknown>;
25
- }
26
- export interface PreflightResult {
27
- ok: boolean;
28
- checks: PreflightCheck[];
29
- }
30
- export declare function pollUntil(fn: () => Promise<boolean>, opts: {
31
- intervalMs: number;
32
- timeoutMs: number;
33
- }): Promise<boolean>;
34
- export declare function runPreflight(opts: PreflightOpts): Promise<PreflightResult>;