@ceraph/react-native-mcp 0.3.3 → 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 +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,242 +0,0 @@
1
- import { readFile, writeFile } from "node:fs/promises";
2
- import { join } from "node:path";
3
- import { IndentationText, Node, Project, SyntaxKind, } from "ts-morph";
4
- const SHIM_MODULE = "@ceraph/react-native-mcp/shim";
5
- const INSTALL_CALL = "installCeraph";
6
- async function fileExists(path) {
7
- try {
8
- await readFile(path, "utf-8");
9
- return true;
10
- }
11
- catch {
12
- return false;
13
- }
14
- }
15
- export async function detectRevertTarget(projectDir) {
16
- const expo = join(projectDir, "app", "_layout.tsx");
17
- if (await fileExists(expo)) {
18
- return { kind: "expo-router", filePath: expo };
19
- }
20
- const expoJsx = join(projectDir, "app", "_layout.jsx");
21
- if (await fileExists(expoJsx)) {
22
- return { kind: "expo-router", filePath: expoJsx };
23
- }
24
- for (const name of ["App.tsx", "App.jsx"]) {
25
- const p = join(projectDir, name);
26
- if (await fileExists(p)) {
27
- return { kind: "bare-rn", filePath: p };
28
- }
29
- }
30
- return null;
31
- }
32
- function findDefaultExportFunction(source) {
33
- for (const fn of source.getFunctions()) {
34
- if (fn.isDefaultExport())
35
- return fn;
36
- }
37
- const exportAssignment = source
38
- .getStatements()
39
- .find((s) => Node.isExportAssignment(s));
40
- if (exportAssignment && Node.isExportAssignment(exportAssignment)) {
41
- const expr = exportAssignment.getExpression();
42
- if (Node.isIdentifier(expr)) {
43
- const symbol = expr.getSymbol();
44
- if (symbol) {
45
- const decl = symbol.getDeclarations()[0];
46
- if (decl && Node.isVariableDeclaration(decl)) {
47
- const init = decl.getInitializer();
48
- if (init && Node.isArrowFunction(init))
49
- return init;
50
- if (init && Node.isFunctionExpression(init))
51
- return init;
52
- }
53
- }
54
- }
55
- if (Node.isArrowFunction(expr))
56
- return expr;
57
- if (Node.isFunctionExpression(expr))
58
- return expr;
59
- }
60
- return null;
61
- }
62
- function isSoloInstallCeraphStatement(stmt) {
63
- if (Node.isExpressionStatement(stmt)) {
64
- const expr = stmt.getExpression();
65
- if (Node.isCallExpression(expr)) {
66
- const callee = expr.getExpression();
67
- if (Node.isIdentifier(callee) && callee.getText() === INSTALL_CALL) {
68
- return true;
69
- }
70
- }
71
- }
72
- return false;
73
- }
74
- function classifyUseEffect(call) {
75
- const args = call.getArguments();
76
- if (args.length === 0)
77
- return "unrelated";
78
- const callback = args[0];
79
- let body = null;
80
- if (Node.isArrowFunction(callback) || Node.isFunctionExpression(callback)) {
81
- const b = callback.getBody();
82
- if (Node.isBlock(b))
83
- body = b;
84
- else {
85
- if (Node.isCallExpression(b)) {
86
- const callee = b.getExpression();
87
- if (Node.isIdentifier(callee) && callee.getText() === INSTALL_CALL) {
88
- return "installCeraph-only";
89
- }
90
- }
91
- return "unrelated";
92
- }
93
- }
94
- else {
95
- return "unrelated";
96
- }
97
- if (!body)
98
- return "unrelated";
99
- const statements = body.getStatements();
100
- if (statements.length === 0)
101
- return "unrelated";
102
- let hasInstallCeraph = false;
103
- let hasOthers = false;
104
- for (const s of statements) {
105
- if (isSoloInstallCeraphStatement(s)) {
106
- hasInstallCeraph = true;
107
- }
108
- else {
109
- hasOthers = true;
110
- }
111
- }
112
- if (!hasInstallCeraph)
113
- return "unrelated";
114
- return hasOthers ? "installCeraph-with-others" : "installCeraph-only";
115
- }
116
- function listUseEffectsInBody(fn) {
117
- const block = fn.getBody();
118
- if (!block || !Node.isBlock(block))
119
- return [];
120
- const out = [];
121
- block.forEachDescendant((node) => {
122
- if (Node.isCallExpression(node)) {
123
- const callee = node.getExpression();
124
- if (Node.isIdentifier(callee) && callee.getText() === "useEffect") {
125
- out.push(node);
126
- }
127
- }
128
- });
129
- return out;
130
- }
131
- function dropUseEffectImportIfOrphan(source) {
132
- const decl = source.getImportDeclaration("react");
133
- if (!decl)
134
- return false;
135
- const named = decl.getNamedImports();
136
- const target = named.find((n) => n.getName() === "useEffect");
137
- if (!target)
138
- return false;
139
- const aliasNode = target.getAliasNode();
140
- if (aliasNode)
141
- return false;
142
- let stillReferenced = false;
143
- source.forEachDescendant((node) => {
144
- if (stillReferenced)
145
- return;
146
- if (Node.isIdentifier(node) && node.getText() === "useEffect") {
147
- const parent = node.getParent();
148
- if (parent && (Node.isImportSpecifier(parent) || Node.isImportClause(parent))) {
149
- return;
150
- }
151
- stillReferenced = true;
152
- }
153
- });
154
- if (stillReferenced)
155
- return false;
156
- target.remove();
157
- const remaining = decl.getNamedImports();
158
- const hasDefault = decl.getDefaultImport() != null;
159
- const hasNamespace = decl.getNamespaceImport() != null;
160
- if (remaining.length === 0 && !hasDefault && !hasNamespace) {
161
- decl.remove();
162
- }
163
- return true;
164
- }
165
- function removeInstallCeraphImport(source) {
166
- const decl = source.getImportDeclaration(SHIM_MODULE);
167
- if (!decl)
168
- return false;
169
- const named = decl.getNamedImports();
170
- const target = named.find((n) => n.getName() === INSTALL_CALL);
171
- if (!target)
172
- return false;
173
- target.remove();
174
- const remaining = decl.getNamedImports();
175
- const hasDefault = decl.getDefaultImport() != null;
176
- if (remaining.length === 0 && !hasDefault) {
177
- decl.remove();
178
- }
179
- return true;
180
- }
181
- export async function revertBoot(projectDir) {
182
- const target = await detectRevertTarget(projectDir);
183
- if (!target) {
184
- return { status: "no-layout-found" };
185
- }
186
- const project = new Project({
187
- useInMemoryFileSystem: false,
188
- skipAddingFilesFromTsConfig: true,
189
- skipFileDependencyResolution: true,
190
- skipLoadingLibFiles: true,
191
- compilerOptions: { allowJs: true, jsx: 1 },
192
- manipulationSettings: { indentationText: IndentationText.TwoSpaces },
193
- });
194
- const source = project.addSourceFileAtPath(target.filePath);
195
- const fn = findDefaultExportFunction(source);
196
- if (!fn) {
197
- const removedImport = removeInstallCeraphImport(source);
198
- if (removedImport) {
199
- await writeFile(target.filePath, source.getFullText(), "utf-8");
200
- return {
201
- status: "reverted",
202
- target,
203
- removedUseEffect: false,
204
- removedImport: true,
205
- };
206
- }
207
- return { status: "already-reverted", target };
208
- }
209
- const useEffects = listUseEffectsInBody(fn);
210
- const candidates = useEffects.map((u) => ({ call: u, kind: classifyUseEffect(u) }));
211
- const soloCandidates = candidates.filter((c) => c.kind === "installCeraph-only");
212
- const mixedCandidates = candidates.filter((c) => c.kind === "installCeraph-with-others");
213
- if (mixedCandidates.length > 0) {
214
- return {
215
- status: "skipped",
216
- target,
217
- reason: "useEffect contains other statements",
218
- };
219
- }
220
- let removedUseEffect = false;
221
- for (const c of soloCandidates) {
222
- const stmt = c.call.getFirstAncestorByKind(SyntaxKind.ExpressionStatement);
223
- if (stmt) {
224
- stmt.remove();
225
- removedUseEffect = true;
226
- }
227
- }
228
- const removedImport = removeInstallCeraphImport(source);
229
- if (removedUseEffect) {
230
- dropUseEffectImportIfOrphan(source);
231
- }
232
- if (!removedUseEffect && !removedImport) {
233
- return { status: "already-reverted", target };
234
- }
235
- await writeFile(target.filePath, source.getFullText(), "utf-8");
236
- return {
237
- status: "reverted",
238
- target,
239
- removedUseEffect,
240
- removedImport,
241
- };
242
- }
@@ -1,12 +0,0 @@
1
- export interface CameraFileRevertResult {
2
- path: string;
3
- relPath: string;
4
- ceraphCamerasRemoved: number;
5
- importDropped: boolean;
6
- importRestored: boolean;
7
- }
8
- export interface RevertCameraResult {
9
- files: CameraFileRevertResult[];
10
- filesScanned: number;
11
- }
12
- export declare function revertCamera(projectDir: string): Promise<RevertCameraResult>;
@@ -1,199 +0,0 @@
1
- import { writeFile, readdir } from "node:fs/promises";
2
- import { join, relative, sep } from "node:path";
3
- import { IndentationText, Node, Project, SyntaxKind, } from "ts-morph";
4
- const SHIM_MODULE = "@ceraph/react-native-mcp/shim";
5
- const SHIM_NAMED = "CeraphCamera";
6
- const EXPO_MODULE = "expo-camera";
7
- const EXPO_NAMED = "CameraView";
8
- const SCAN_ROOTS = ["app", "src", "screens"];
9
- const SCAN_EXTENSIONS = new Set([".tsx", ".jsx"]);
10
- const SKIP_DIRS = new Set([
11
- "node_modules",
12
- "dist",
13
- "build",
14
- ".git",
15
- ".ceraph",
16
- ".rn-mcp-cache",
17
- ".expo",
18
- ".next",
19
- "ios",
20
- "android",
21
- ]);
22
- async function listCandidateFiles(projectDir) {
23
- const out = [];
24
- async function walk(dir) {
25
- let entries;
26
- try {
27
- entries = await readdir(dir, { withFileTypes: true });
28
- }
29
- catch {
30
- return;
31
- }
32
- for (const entry of entries) {
33
- const abs = join(dir, entry.name);
34
- if (entry.isDirectory()) {
35
- if (SKIP_DIRS.has(entry.name))
36
- continue;
37
- await walk(abs);
38
- continue;
39
- }
40
- if (!entry.isFile())
41
- continue;
42
- const dot = entry.name.lastIndexOf(".");
43
- if (dot < 0)
44
- continue;
45
- const ext = entry.name.slice(dot).toLowerCase();
46
- if (!SCAN_EXTENSIONS.has(ext))
47
- continue;
48
- out.push(abs);
49
- }
50
- }
51
- for (const sub of SCAN_ROOTS) {
52
- await walk(join(projectDir, sub));
53
- }
54
- for (const candidate of ["App.tsx", "App.jsx"]) {
55
- out.push(join(projectDir, candidate));
56
- }
57
- return out;
58
- }
59
- function buildProject(filePaths) {
60
- const project = new Project({
61
- useInMemoryFileSystem: false,
62
- skipAddingFilesFromTsConfig: true,
63
- skipFileDependencyResolution: true,
64
- skipLoadingLibFiles: true,
65
- compilerOptions: { allowJs: true, jsx: 1 },
66
- manipulationSettings: { indentationText: IndentationText.TwoSpaces },
67
- });
68
- for (const path of filePaths) {
69
- try {
70
- project.addSourceFileAtPath(path);
71
- }
72
- catch {
73
- }
74
- }
75
- return project;
76
- }
77
- function listJsxByName(source, name) {
78
- const out = [];
79
- source.forEachDescendant((node) => {
80
- if (Node.isJsxOpeningElement(node) || Node.isJsxSelfClosingElement(node)) {
81
- const tag = node.getTagNameNode();
82
- if (tag.getText() === name) {
83
- out.push(node);
84
- }
85
- }
86
- });
87
- return out;
88
- }
89
- function removeImageKeyAttribute(node) {
90
- const attrs = node.getAttributes();
91
- for (const attr of attrs) {
92
- if (Node.isJsxAttribute(attr)) {
93
- const nameNode = attr.getNameNode();
94
- if (nameNode.getText() === "imageKey") {
95
- attr.remove();
96
- }
97
- }
98
- }
99
- }
100
- function renameCeraphCamerasToCameraView(source) {
101
- let count = 0;
102
- for (let safety = 0; safety < 10_000; safety++) {
103
- const tags = listJsxByName(source, SHIM_NAMED);
104
- if (tags.length === 0)
105
- break;
106
- const target = tags[0];
107
- target.getTagNameNode().replaceWithText(EXPO_NAMED);
108
- if (Node.isJsxOpeningElement(target)) {
109
- const parent = target.getParentIfKind(SyntaxKind.JsxElement);
110
- if (parent) {
111
- const closing = parent.getClosingElement();
112
- closing.getTagNameNode().replaceWithText(EXPO_NAMED);
113
- }
114
- }
115
- removeImageKeyAttribute(target);
116
- count++;
117
- }
118
- return count;
119
- }
120
- function dropCeraphCameraFromShimImport(source) {
121
- const decl = source.getImportDeclaration(SHIM_MODULE);
122
- if (!decl)
123
- return false;
124
- const named = decl.getNamedImports();
125
- const target = named.find((n) => n.getName() === SHIM_NAMED);
126
- if (!target)
127
- return false;
128
- target.remove();
129
- const remaining = decl.getNamedImports();
130
- const hasDefault = decl.getDefaultImport() != null;
131
- if (remaining.length === 0 && !hasDefault) {
132
- decl.remove();
133
- }
134
- return true;
135
- }
136
- function ensureCameraViewImport(source) {
137
- const decl = source.getImportDeclaration(EXPO_MODULE);
138
- if (decl) {
139
- const named = decl.getNamedImports();
140
- if (named.some((n) => n.getName() === EXPO_NAMED))
141
- return false;
142
- decl.addNamedImport(EXPO_NAMED);
143
- return true;
144
- }
145
- source.addImportDeclaration({
146
- moduleSpecifier: EXPO_MODULE,
147
- namedImports: [EXPO_NAMED],
148
- });
149
- return true;
150
- }
151
- export async function revertCamera(projectDir) {
152
- const candidates = await listCandidateFiles(projectDir);
153
- const project = buildProject(candidates);
154
- const files = [];
155
- let filesScanned = 0;
156
- for (const source of project.getSourceFiles()) {
157
- filesScanned++;
158
- const tags = listJsxByName(source, SHIM_NAMED);
159
- if (tags.length === 0) {
160
- const importDecl = source.getImportDeclaration(SHIM_MODULE);
161
- const hasOrphanImport = importDecl != null &&
162
- importDecl.getNamedImports().some((n) => n.getName() === SHIM_NAMED);
163
- if (!hasOrphanImport)
164
- continue;
165
- const dropped = dropCeraphCameraFromShimImport(source);
166
- if (!dropped)
167
- continue;
168
- const filePath = source.getFilePath();
169
- await writeFile(filePath, source.getFullText(), "utf-8");
170
- files.push({
171
- path: filePath,
172
- relPath: relative(projectDir, filePath).split(sep).join("/"),
173
- ceraphCamerasRemoved: 0,
174
- importDropped: true,
175
- importRestored: false,
176
- });
177
- continue;
178
- }
179
- const ceraphCamerasRemoved = renameCeraphCamerasToCameraView(source);
180
- const remainingShimTags = listJsxByName(source, SHIM_NAMED);
181
- const importDropped = remainingShimTags.length === 0
182
- ? dropCeraphCameraFromShimImport(source)
183
- : false;
184
- const hasCameraViewJsx = listJsxByName(source, EXPO_NAMED).length > 0;
185
- const importRestored = hasCameraViewJsx
186
- ? ensureCameraViewImport(source)
187
- : false;
188
- const filePath = source.getFilePath();
189
- await writeFile(filePath, source.getFullText(), "utf-8");
190
- files.push({
191
- path: filePath,
192
- relPath: relative(projectDir, filePath).split(sep).join("/"),
193
- ceraphCamerasRemoved,
194
- importDropped,
195
- importRestored,
196
- });
197
- }
198
- return { files, filesScanned };
199
- }
@@ -1,27 +0,0 @@
1
- export type RevertCeraphDirResult = {
2
- status: "skipped-needs-confirmation";
3
- path: string;
4
- paths: string[];
5
- } | {
6
- status: "deleted";
7
- path: string;
8
- deletedEntries: string[];
9
- } | {
10
- status: "already-reverted";
11
- path: string;
12
- };
13
- export interface RevertCeraphDirInput {
14
- projectDir: string;
15
- confirm: boolean;
16
- }
17
- export interface RevertCeraphDirDeps {
18
- rm?: (p: string, opts: {
19
- recursive: true;
20
- force: true;
21
- }) => Promise<void>;
22
- readdir?: (p: string) => Promise<string[]>;
23
- stat?: (p: string) => Promise<{
24
- isDirectory: () => boolean;
25
- }>;
26
- }
27
- export declare function revertCeraphDir(input: RevertCeraphDirInput, deps?: RevertCeraphDirDeps): Promise<RevertCeraphDirResult>;
@@ -1,38 +0,0 @@
1
- import { rm, readdir, stat } from "node:fs/promises";
2
- import { join } from "node:path";
3
- async function dirExists(path, statFn) {
4
- try {
5
- const s = await statFn(path);
6
- return s.isDirectory();
7
- }
8
- catch {
9
- return false;
10
- }
11
- }
12
- export async function revertCeraphDir(input, deps = {}) {
13
- const ceraphPath = join(input.projectDir, ".ceraph");
14
- const rmFn = deps.rm ?? ((p, o) => rm(p, o));
15
- const readdirFn = deps.readdir ?? ((p) => readdir(p));
16
- const statFn = deps.stat ?? ((p) => stat(p));
17
- const exists = await dirExists(ceraphPath, statFn);
18
- if (!exists) {
19
- return { status: "already-reverted", path: ceraphPath };
20
- }
21
- let entries = [];
22
- try {
23
- entries = await readdirFn(ceraphPath);
24
- }
25
- catch {
26
- entries = [];
27
- }
28
- entries.sort();
29
- if (!input.confirm) {
30
- return {
31
- status: "skipped-needs-confirmation",
32
- path: ceraphPath,
33
- paths: entries.map((e) => join(ceraphPath, e)),
34
- };
35
- }
36
- await rmFn(ceraphPath, { recursive: true, force: true });
37
- return { status: "deleted", path: ceraphPath, deletedEntries: entries };
38
- }
@@ -1,19 +0,0 @@
1
- export type RevertClaudeHooksStatus = "reverted" | "already-reverted" | "manual" | "skipped";
2
- export interface RevertClaudeHooksResult {
3
- status: RevertClaudeHooksStatus;
4
- details: {
5
- scriptsDeleted: string[];
6
- scriptsLeftAlone: string[];
7
- settingsFilesModified: string[];
8
- settingsFilesUntouched: string[];
9
- };
10
- }
11
- export interface RevertClaudeHooksDeps {
12
- readFile?: (p: string) => Promise<string>;
13
- writeFile?: (p: string, c: string) => Promise<void>;
14
- unlink?: (p: string) => Promise<void>;
15
- fileExists?: (p: string) => Promise<boolean>;
16
- }
17
- export declare function revertClaudeHooks(input: {
18
- projectDir: string;
19
- }, deps?: RevertClaudeHooksDeps): Promise<RevertClaudeHooksResult>;