@ceraph/react-native-mcp 0.3.3 → 0.4.6

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 +40 -11
  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,191 +0,0 @@
1
- import { access, readFile, unlink } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { CLAUDE_SETTINGS_REL_PATHS, ERROR_HOOK_COMMAND, ERROR_HOOK_MATCHER, ERROR_HOOK_REL_PATH, FLOW_PROGRESS_HOOK_COMMAND, FLOW_PROGRESS_HOOK_MATCHER, FLOW_PROGRESS_HOOK_REL_PATH, HOOK_SCRIPT, FLOW_PROGRESS_HOOK_SCRIPT, } from "../init/claude-hook-constants.js";
4
- import { writeFileAtomic } from "../utils/atomic-write.js";
5
- async function defaultExists(p) {
6
- try {
7
- await access(p);
8
- return true;
9
- }
10
- catch {
11
- return false;
12
- }
13
- }
14
- export async function revertClaudeHooks(input, deps = {}) {
15
- const read = deps.readFile ?? ((p) => readFile(p, "utf-8"));
16
- const write = deps.writeFile ?? writeFileAtomic;
17
- const unlinkFn = deps.unlink ?? ((p) => unlink(p));
18
- const exists = deps.fileExists ?? defaultExists;
19
- const hooks = [
20
- {
21
- scriptAbsPath: join(input.projectDir, ...ERROR_HOOK_REL_PATH),
22
- canonicalScript: HOOK_SCRIPT,
23
- matcher: ERROR_HOOK_MATCHER,
24
- command: ERROR_HOOK_COMMAND,
25
- },
26
- {
27
- scriptAbsPath: join(input.projectDir, ...FLOW_PROGRESS_HOOK_REL_PATH),
28
- canonicalScript: FLOW_PROGRESS_HOOK_SCRIPT,
29
- matcher: FLOW_PROGRESS_HOOK_MATCHER,
30
- command: FLOW_PROGRESS_HOOK_COMMAND,
31
- },
32
- ];
33
- const scriptsDeleted = [];
34
- const scriptsLeftAlone = [];
35
- for (const h of hooks) {
36
- if (!(await exists(h.scriptAbsPath)))
37
- continue;
38
- let onDisk;
39
- try {
40
- onDisk = await read(h.scriptAbsPath);
41
- }
42
- catch {
43
- scriptsLeftAlone.push(h.scriptAbsPath);
44
- continue;
45
- }
46
- if (onDisk === h.canonicalScript) {
47
- await unlinkFn(h.scriptAbsPath);
48
- scriptsDeleted.push(h.scriptAbsPath);
49
- }
50
- else {
51
- scriptsLeftAlone.push(h.scriptAbsPath);
52
- }
53
- }
54
- const settingsFilesModified = [];
55
- const settingsFilesUntouched = [];
56
- for (const relParts of CLAUDE_SETTINGS_REL_PATHS) {
57
- const abs = join(input.projectDir, ...relParts);
58
- if (!(await exists(abs)))
59
- continue;
60
- let raw;
61
- try {
62
- raw = await read(abs);
63
- }
64
- catch {
65
- settingsFilesUntouched.push(abs);
66
- continue;
67
- }
68
- let parsed;
69
- try {
70
- parsed = JSON.parse(raw);
71
- }
72
- catch {
73
- settingsFilesUntouched.push(abs);
74
- continue;
75
- }
76
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
77
- settingsFilesUntouched.push(abs);
78
- continue;
79
- }
80
- const result = stripHooksFromSettings(parsed, hooks);
81
- if (!result.mutated) {
82
- settingsFilesUntouched.push(abs);
83
- continue;
84
- }
85
- const indentMatch = raw.match(/\n(\s+)"/);
86
- const indent = indentMatch?.[1] ?? " ";
87
- const hadTrailingNewline = raw.endsWith("\n");
88
- const out = JSON.stringify(result.next, null, indent);
89
- await write(abs, hadTrailingNewline ? out + "\n" : out);
90
- settingsFilesModified.push(abs);
91
- }
92
- const anyAction = scriptsDeleted.length > 0 || settingsFilesModified.length > 0;
93
- let status;
94
- if (scriptsLeftAlone.length > 0) {
95
- status = "manual";
96
- }
97
- else if (anyAction) {
98
- status = "reverted";
99
- }
100
- else {
101
- status = "already-reverted";
102
- }
103
- return {
104
- status,
105
- details: {
106
- scriptsDeleted,
107
- scriptsLeftAlone,
108
- settingsFilesModified,
109
- settingsFilesUntouched,
110
- },
111
- };
112
- }
113
- function stripHooksFromSettings(obj, managed) {
114
- const hooksVal = obj.hooks;
115
- if (!hooksVal || typeof hooksVal !== "object" || Array.isArray(hooksVal)) {
116
- return { mutated: false, next: obj };
117
- }
118
- const hooks = hooksVal;
119
- const fileChanged = hooks.FileChanged;
120
- if (!Array.isArray(fileChanged)) {
121
- return { mutated: false, next: obj };
122
- }
123
- const managedByMatcher = new Map();
124
- for (const m of managed)
125
- managedByMatcher.set(m.matcher, m);
126
- const keptEntries = [];
127
- let mutated = false;
128
- for (const raw of fileChanged) {
129
- if (!raw || typeof raw !== "object" || Array.isArray(raw)) {
130
- keptEntries.push(raw);
131
- continue;
132
- }
133
- const entry = raw;
134
- const matcher = entry.matcher;
135
- if (typeof matcher !== "string") {
136
- keptEntries.push(raw);
137
- continue;
138
- }
139
- const managedHook = managedByMatcher.get(matcher);
140
- if (!managedHook) {
141
- keptEntries.push(raw);
142
- continue;
143
- }
144
- const innerList = entry.hooks;
145
- if (!Array.isArray(innerList)) {
146
- keptEntries.push(raw);
147
- continue;
148
- }
149
- const keptInner = [];
150
- let droppedAny = false;
151
- for (const innerRaw of innerList) {
152
- if (!innerRaw || typeof innerRaw !== "object" || Array.isArray(innerRaw)) {
153
- keptInner.push(innerRaw);
154
- continue;
155
- }
156
- const innerObj = innerRaw;
157
- const cmd = innerObj.command;
158
- if (typeof cmd === "string" && cmd === managedHook.command) {
159
- droppedAny = true;
160
- continue;
161
- }
162
- keptInner.push(innerRaw);
163
- }
164
- if (!droppedAny) {
165
- keptEntries.push(raw);
166
- continue;
167
- }
168
- mutated = true;
169
- if (keptInner.length === 0) {
170
- continue;
171
- }
172
- keptEntries.push({ ...entry, hooks: keptInner });
173
- }
174
- if (!mutated)
175
- return { mutated: false, next: obj };
176
- const nextHooks = { ...hooks };
177
- if (keptEntries.length === 0) {
178
- delete nextHooks.FileChanged;
179
- }
180
- else {
181
- nextHooks.FileChanged = keptEntries;
182
- }
183
- const next = { ...obj };
184
- if (Object.keys(nextHooks).length === 0) {
185
- delete next.hooks;
186
- }
187
- else {
188
- next.hooks = nextHooks;
189
- }
190
- return { mutated: true, next };
191
- }
@@ -1,17 +0,0 @@
1
- export declare const GITIGNORE_ENTRIES: readonly [".rn-errors.json", ".rn-flow-progress.json", ".rn-mcp-cache/", ".rn-mcp-cache"];
2
- export type RevertGitignoreResult = {
3
- status: "reverted";
4
- path: string;
5
- removedLines: string[];
6
- } | {
7
- status: "already-reverted";
8
- path: string;
9
- } | {
10
- status: "no-gitignore";
11
- path: string;
12
- };
13
- export interface RevertGitignoreDeps {
14
- readFile?: (p: string) => Promise<string>;
15
- writeFile?: (p: string, c: string) => Promise<void>;
16
- }
17
- export declare function revertGitignore(projectDir: string, deps?: RevertGitignoreDeps): Promise<RevertGitignoreResult>;
@@ -1,43 +0,0 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- export const GITIGNORE_ENTRIES = [
4
- ".rn-errors.json",
5
- ".rn-flow-progress.json",
6
- ".rn-mcp-cache/",
7
- ".rn-mcp-cache",
8
- ];
9
- export async function revertGitignore(projectDir, deps = {}) {
10
- const path = join(projectDir, ".gitignore");
11
- const read = deps.readFile ?? ((p) => readFile(p, "utf-8"));
12
- const write = deps.writeFile ?? ((p, c) => writeFile(p, c, "utf-8"));
13
- let content;
14
- try {
15
- content = await read(path);
16
- }
17
- catch {
18
- return { status: "no-gitignore", path };
19
- }
20
- const hadTrailingNewline = content.endsWith("\n");
21
- const lines = content.split(/\r?\n/);
22
- if (hadTrailingNewline && lines.length > 0 && lines[lines.length - 1] === "") {
23
- lines.pop();
24
- }
25
- const targets = new Set(GITIGNORE_ENTRIES);
26
- const removedLines = [];
27
- const kept = [];
28
- for (const line of lines) {
29
- if (targets.has(line.trim())) {
30
- removedLines.push(line);
31
- continue;
32
- }
33
- kept.push(line);
34
- }
35
- if (removedLines.length === 0) {
36
- return { status: "already-reverted", path };
37
- }
38
- const nextContent = hadTrailingNewline
39
- ? kept.join("\n") + "\n"
40
- : kept.join("\n");
41
- await write(path, nextContent);
42
- return { status: "reverted", path, removedLines };
43
- }
@@ -1,57 +0,0 @@
1
- export declare const JSON_CLIENT_PATHS: readonly [".mcp.json", string, string];
2
- export declare const TOML_CLIENT_PATHS: readonly [string];
3
- export interface UserGlobalMcpClient {
4
- label: string;
5
- dir: readonly string[];
6
- file: readonly string[];
7
- }
8
- export declare const USER_GLOBAL_MCP_CLIENTS: readonly UserGlobalMcpClient[];
9
- export declare function userGlobalMcpClientPaths(home?: string): Array<{
10
- label: string;
11
- path: string;
12
- }>;
13
- export declare const SERVER_KEYS: readonly ["mobile-mcp", "react-native-mcp"];
14
- export type RevertMcpClientFileResult = {
15
- path: string;
16
- status: "removed-entries";
17
- removedKeys: string[];
18
- } | {
19
- path: string;
20
- status: "deleted-file";
21
- removedKeys: string[];
22
- } | {
23
- path: string;
24
- status: "no-changes";
25
- } | {
26
- path: string;
27
- status: "not-found";
28
- } | {
29
- path: string;
30
- status: "malformed";
31
- };
32
- export interface RevertMcpClientsResult {
33
- files: RevertMcpClientFileResult[];
34
- }
35
- export interface RevertMcpClientsDeps {
36
- readFile?: (p: string) => Promise<string>;
37
- writeFile?: (p: string, c: string) => Promise<void>;
38
- unlink?: (p: string) => Promise<void>;
39
- fileExists?: (p: string) => Promise<boolean>;
40
- }
41
- export declare function revertMcpClients(projectDir: string, deps?: RevertMcpClientsDeps): Promise<RevertMcpClientsResult>;
42
- declare function stripTomlSections(raw: string, sectionHeadings: ReadonlySet<string>): {
43
- next: string;
44
- removedKeys: string[];
45
- };
46
- export { stripTomlSections };
47
- export interface RevertUserGlobalMcpClientsResult {
48
- files: RevertMcpClientFileResult[];
49
- }
50
- export interface RevertUserGlobalMcpClientsDeps {
51
- readFile?: (p: string) => Promise<string>;
52
- writeFile?: (p: string, c: string) => Promise<void>;
53
- unlink?: (p: string) => Promise<void>;
54
- fileExists?: (p: string) => Promise<boolean>;
55
- home?: string;
56
- }
57
- export declare function revertUserGlobalMcpClients(deps?: RevertUserGlobalMcpClientsDeps): Promise<RevertUserGlobalMcpClientsResult>;
@@ -1,194 +0,0 @@
1
- import { readFile, unlink, access } from "node:fs/promises";
2
- import { homedir } from "node:os";
3
- import { join } from "node:path";
4
- import { writeFileAtomic } from "../utils/atomic-write.js";
5
- export const JSON_CLIENT_PATHS = [
6
- ".mcp.json",
7
- join(".cursor", "mcp.json"),
8
- join(".vscode", "mcp.json"),
9
- ];
10
- export const TOML_CLIENT_PATHS = [join(".codex", "config.toml")];
11
- export const USER_GLOBAL_MCP_CLIENTS = [
12
- {
13
- label: "Windsurf",
14
- dir: [".codeium", "windsurf"],
15
- file: [".codeium", "windsurf", "mcp_config.json"],
16
- },
17
- {
18
- label: "Antigravity",
19
- dir: [".gemini", "antigravity"],
20
- file: [".gemini", "antigravity", "mcp_config.json"],
21
- },
22
- ];
23
- export function userGlobalMcpClientPaths(home) {
24
- const h = home ?? homedir();
25
- return USER_GLOBAL_MCP_CLIENTS.map((c) => ({
26
- label: c.label,
27
- path: join(h, ...c.file),
28
- }));
29
- }
30
- export const SERVER_KEYS = ["mobile-mcp", "react-native-mcp"];
31
- async function defaultExists(p) {
32
- try {
33
- await access(p);
34
- return true;
35
- }
36
- catch {
37
- return false;
38
- }
39
- }
40
- export async function revertMcpClients(projectDir, deps = {}) {
41
- const read = deps.readFile ?? ((p) => readFile(p, "utf-8"));
42
- const write = deps.writeFile ?? writeFileAtomic;
43
- const unlinkFn = deps.unlink ?? ((p) => unlink(p));
44
- const exists = deps.fileExists ?? defaultExists;
45
- const files = [];
46
- for (const rel of JSON_CLIENT_PATHS) {
47
- const abs = join(projectDir, rel);
48
- if (!(await exists(abs))) {
49
- files.push({ path: abs, status: "not-found" });
50
- continue;
51
- }
52
- files.push(await revertJsonClient(abs, { read, write, unlink: unlinkFn }));
53
- }
54
- for (const rel of TOML_CLIENT_PATHS) {
55
- const abs = join(projectDir, rel);
56
- if (!(await exists(abs))) {
57
- files.push({ path: abs, status: "not-found" });
58
- continue;
59
- }
60
- files.push(await revertTomlClient(abs, { read, write, unlink: unlinkFn }));
61
- }
62
- return { files };
63
- }
64
- async function revertJsonClient(abs, io) {
65
- const raw = await io.read(abs);
66
- let parsed;
67
- try {
68
- parsed = JSON.parse(raw);
69
- }
70
- catch {
71
- return { path: abs, status: "malformed" };
72
- }
73
- if (!parsed || typeof parsed !== "object" || Array.isArray(parsed)) {
74
- return { path: abs, status: "malformed" };
75
- }
76
- const obj = parsed;
77
- const servers = obj.mcpServers;
78
- if (!servers || typeof servers !== "object" || Array.isArray(servers)) {
79
- return { path: abs, status: "no-changes" };
80
- }
81
- const map = servers;
82
- const removedKeys = [];
83
- for (const key of SERVER_KEYS) {
84
- if (key in map) {
85
- delete map[key];
86
- removedKeys.push(key);
87
- }
88
- }
89
- if (removedKeys.length === 0) {
90
- return { path: abs, status: "no-changes" };
91
- }
92
- const otherTopKeys = Object.keys(obj).filter((k) => k !== "mcpServers");
93
- const mcpEmpty = Object.keys(map).length === 0;
94
- if (mcpEmpty && otherTopKeys.length === 0) {
95
- await io.unlink(abs);
96
- return { path: abs, status: "deleted-file", removedKeys };
97
- }
98
- const indentMatch = raw.match(/\n(\s+)"/);
99
- const indent = indentMatch?.[1] ?? " ";
100
- const hadTrailingNewline = raw.endsWith("\n");
101
- const out = JSON.stringify(obj, null, indent);
102
- await io.write(abs, hadTrailingNewline ? out + "\n" : out);
103
- return { path: abs, status: "removed-entries", removedKeys };
104
- }
105
- function stripTomlSections(raw, sectionHeadings) {
106
- const lines = raw.split(/\r?\n/);
107
- const hadTrailingNewline = raw.endsWith("\n");
108
- if (hadTrailingNewline && lines.length > 0 && lines[lines.length - 1] === "") {
109
- lines.pop();
110
- }
111
- const out = [];
112
- const removedKeys = [];
113
- let inDropSection = false;
114
- let justExitedDrop = false;
115
- for (let i = 0; i < lines.length; i++) {
116
- const line = lines[i];
117
- const trimmed = line.trim();
118
- const isHeading = trimmed.startsWith("[") && trimmed.endsWith("]");
119
- if (isHeading) {
120
- const heading = trimmed.slice(1, -1).trim();
121
- const isDropHeading = sectionHeadings.has(heading);
122
- if (isDropHeading) {
123
- if (out.length > 0 && out[out.length - 1] === "") {
124
- out.pop();
125
- }
126
- const key = heading.startsWith("mcp_servers.")
127
- ? heading.slice("mcp_servers.".length)
128
- : heading;
129
- removedKeys.push(key);
130
- inDropSection = true;
131
- justExitedDrop = false;
132
- continue;
133
- }
134
- if ((inDropSection || justExitedDrop) && out.length > 0 && out[out.length - 1] !== "") {
135
- out.push("");
136
- }
137
- inDropSection = false;
138
- justExitedDrop = false;
139
- out.push(line);
140
- continue;
141
- }
142
- if (inDropSection) {
143
- justExitedDrop = true;
144
- continue;
145
- }
146
- if (justExitedDrop) {
147
- if (trimmed === "")
148
- continue;
149
- if (out.length > 0 && out[out.length - 1] !== "") {
150
- out.push("");
151
- }
152
- justExitedDrop = false;
153
- out.push(line);
154
- continue;
155
- }
156
- out.push(line);
157
- }
158
- while (out.length > 0 && out[out.length - 1] === "") {
159
- out.pop();
160
- }
161
- const joined = out.join("\n");
162
- const next = hadTrailingNewline && joined.length > 0 ? joined + "\n" : joined;
163
- return { next, removedKeys };
164
- }
165
- async function revertTomlClient(abs, io) {
166
- const raw = await io.read(abs);
167
- const headings = new Set(SERVER_KEYS.map((k) => `mcp_servers.${k}`));
168
- const { next, removedKeys } = stripTomlSections(raw, headings);
169
- if (removedKeys.length === 0) {
170
- return { path: abs, status: "no-changes" };
171
- }
172
- if (next.trim().length === 0) {
173
- await io.unlink(abs);
174
- return { path: abs, status: "deleted-file", removedKeys };
175
- }
176
- await io.write(abs, next);
177
- return { path: abs, status: "removed-entries", removedKeys };
178
- }
179
- export { stripTomlSections };
180
- export async function revertUserGlobalMcpClients(deps = {}) {
181
- const read = deps.readFile ?? ((p) => readFile(p, "utf-8"));
182
- const write = deps.writeFile ?? writeFileAtomic;
183
- const unlinkFn = deps.unlink ?? ((p) => unlink(p));
184
- const exists = deps.fileExists ?? defaultExists;
185
- const files = [];
186
- for (const { path } of userGlobalMcpClientPaths(deps.home)) {
187
- if (!(await exists(path))) {
188
- files.push({ path, status: "not-found" });
189
- continue;
190
- }
191
- files.push(await revertJsonClient(path, { read, write, unlink: unlinkFn }));
192
- }
193
- return { files };
194
- }
@@ -1,34 +0,0 @@
1
- export type PackageManager = "pnpm" | "yarn" | "bun" | "npm";
2
- export declare const LOCKFILES: ReadonlyArray<{
3
- file: string;
4
- pm: PackageManager;
5
- }>;
6
- export declare const CERAPH_PKG = "@ceraph/react-native-mcp";
7
- export declare const APPIUM_PKG = "appium-webdriveragent";
8
- export declare function detectPackageManager(projectDir: string): Promise<PackageManager>;
9
- export declare function removeArgv(pm: PackageManager, pkgs: string[]): {
10
- bin: string;
11
- args: string[];
12
- };
13
- export declare function listInstalledPackages(projectDir: string, pkgs: string[]): Promise<string[]>;
14
- export type RevertPackageStatus = "removed" | "nothing-to-remove" | "command-failed";
15
- export interface RevertPackageResult {
16
- status: RevertPackageStatus;
17
- pm: PackageManager;
18
- removedPackages: string[];
19
- command?: {
20
- bin: string;
21
- args: string[];
22
- };
23
- exitCode?: number;
24
- }
25
- export interface RevertPackageDeps {
26
- spawnRemove?: (input: {
27
- bin: string;
28
- args: string[];
29
- cwd: string;
30
- }) => Promise<{
31
- exitCode: number;
32
- }>;
33
- }
34
- export declare function revertPackage(projectDir: string, deps?: RevertPackageDeps): Promise<RevertPackageResult>;
@@ -1,98 +0,0 @@
1
- import { spawn } from "node:child_process";
2
- import { readFile, access } from "node:fs/promises";
3
- import { join } from "node:path";
4
- export const LOCKFILES = [
5
- { file: "pnpm-lock.yaml", pm: "pnpm" },
6
- { file: "yarn.lock", pm: "yarn" },
7
- { file: "bun.lockb", pm: "bun" },
8
- { file: "bun.lock", pm: "bun" },
9
- { file: "package-lock.json", pm: "npm" },
10
- ];
11
- export const CERAPH_PKG = "@ceraph/react-native-mcp";
12
- export const APPIUM_PKG = "appium-webdriveragent";
13
- async function fileExists(path) {
14
- try {
15
- await access(path);
16
- return true;
17
- }
18
- catch {
19
- return false;
20
- }
21
- }
22
- export async function detectPackageManager(projectDir) {
23
- for (const { file, pm } of LOCKFILES) {
24
- if (await fileExists(join(projectDir, file))) {
25
- return pm;
26
- }
27
- }
28
- return "npm";
29
- }
30
- export function removeArgv(pm, pkgs) {
31
- switch (pm) {
32
- case "pnpm":
33
- return { bin: "pnpm", args: ["remove", ...pkgs] };
34
- case "yarn":
35
- return { bin: "yarn", args: ["remove", ...pkgs] };
36
- case "bun":
37
- return { bin: "bun", args: ["remove", ...pkgs] };
38
- case "npm":
39
- return { bin: "npm", args: ["uninstall", ...pkgs] };
40
- }
41
- }
42
- export async function listInstalledPackages(projectDir, pkgs) {
43
- let raw;
44
- try {
45
- raw = await readFile(join(projectDir, "package.json"), "utf-8");
46
- }
47
- catch {
48
- return [];
49
- }
50
- let parsed;
51
- try {
52
- parsed = JSON.parse(raw);
53
- }
54
- catch {
55
- return [];
56
- }
57
- if (!parsed || typeof parsed !== "object")
58
- return [];
59
- const dep = parsed.dependencies ?? {};
60
- const dev = parsed.devDependencies ?? {};
61
- return pkgs.filter((p) => Boolean(dep[p] || dev[p]));
62
- }
63
- export async function revertPackage(projectDir, deps = {}) {
64
- const pm = await detectPackageManager(projectDir);
65
- const candidates = [CERAPH_PKG];
66
- const listed = await listInstalledPackages(projectDir, candidates);
67
- if (listed.length === 0) {
68
- return { status: "nothing-to-remove", pm, removedPackages: [] };
69
- }
70
- const argv = removeArgv(pm, listed);
71
- const runner = deps.spawnRemove ?? defaultSpawnRemove;
72
- const result = await runner({ bin: argv.bin, args: argv.args, cwd: projectDir });
73
- if (result.exitCode !== 0) {
74
- return {
75
- status: "command-failed",
76
- pm,
77
- removedPackages: [],
78
- command: argv,
79
- exitCode: result.exitCode,
80
- };
81
- }
82
- return {
83
- status: "removed",
84
- pm,
85
- removedPackages: listed,
86
- command: argv,
87
- };
88
- }
89
- function defaultSpawnRemove(input) {
90
- return new Promise((resolve) => {
91
- const child = spawn(input.bin, input.args, {
92
- cwd: input.cwd,
93
- stdio: "inherit",
94
- });
95
- child.on("error", () => resolve({ exitCode: 127 }));
96
- child.on("exit", (code) => resolve({ exitCode: code ?? 1 }));
97
- });
98
- }
@@ -1,36 +0,0 @@
1
- export declare const CERAPH_SCHEME = "ceraph";
2
- export type RevertSchemeResult = {
3
- status: "reverted";
4
- path: string;
5
- previousScheme: string | string[];
6
- nextScheme: string | string[] | undefined;
7
- } | {
8
- status: "already-reverted";
9
- path: string;
10
- } | {
11
- status: "manual";
12
- kind: "expo-dynamic" | "bare-rn";
13
- path?: string;
14
- remediation: string;
15
- } | {
16
- status: "no-rn-project";
17
- };
18
- export interface RevertSchemeDeps {
19
- readFile?: (p: string) => Promise<string>;
20
- writeFile?: (p: string, c: string) => Promise<void>;
21
- fileExists?: (p: string) => Promise<boolean>;
22
- }
23
- interface ParsedAppJson {
24
- expo?: {
25
- scheme?: string | string[] | unknown;
26
- [k: string]: unknown;
27
- };
28
- [k: string]: unknown;
29
- }
30
- export declare function stripCeraphSchemeFromAppJson(parsed: ParsedAppJson): {
31
- changed: boolean;
32
- previousScheme: string | string[] | undefined;
33
- nextScheme: string | string[] | undefined;
34
- };
35
- export declare function revertCeraphUrlScheme(projectDir: string, deps?: RevertSchemeDeps): Promise<RevertSchemeResult>;
36
- export {};