Skip to content

Commit 5087dda

Browse files
committed
fix(uninit): scope import removal to exact lines, gate layout patch on ownership
- removeImport now matches the exact import string instead of any line containing 'agent-react-devtools', preventing accidental removal of unrelated comments or imports - unpatchViteConfig filters the exact import line inserted by init - unpatchNextJs only removes the layout's import './devtools' when devtools.ts was confirmed to be ours, preventing corruption of pre-existing imports with the same name - Add changeset and README entry for uninit command
1 parent 9ac010f commit 5087dda

File tree

3 files changed

+35
-13
lines changed

3 files changed

+35
-13
lines changed

.changeset/uninit-command.md

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
---
2+
"agent-react-devtools": minor
3+
---
4+
5+
Add `uninit` command to reverse framework configuration
6+
7+
`agent-react-devtools uninit` removes the changes made by `init` — restoring your config files to their original state.
8+
9+
- Supports all frameworks: Vite, Next.js (Pages Router and App Router), CRA
10+
- `--dry-run` flag previews what would be removed without writing any files
11+
- Safe to run on projects not configured by `init` (no-op)

README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -178,6 +178,12 @@ npx agent-react-devtools init
178178

179179
This detects your framework (Vite, Next.js, CRA) and patches the appropriate config file.
180180

181+
To undo these changes:
182+
183+
```sh
184+
npx agent-react-devtools uninit
185+
```
186+
181187
### One-line import
182188

183189
Add a single import as the first line of your entry point (e.g. `src/main.tsx`):

packages/agent-react-devtools/src/init.ts

Lines changed: 18 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -40,14 +40,14 @@ function prependImport(filePath: string, importLine: string, dryRun: boolean): s
4040
return filePath;
4141
}
4242

43-
function removeImport(filePath: string, dryRun: boolean): string | null {
43+
function removeImport(filePath: string, importLine: string, dryRun: boolean): string | null {
4444
const content = readFileSync(filePath, 'utf-8');
45-
if (!content.includes('agent-react-devtools')) {
45+
if (!content.includes(importLine)) {
4646
return null; // not configured
4747
}
4848
const newContent = content
4949
.split('\n')
50-
.filter((line) => !line.includes('agent-react-devtools'))
50+
.filter((line) => line !== importLine)
5151
.join('\n');
5252
if (!dryRun) {
5353
writeFileSync(filePath, newContent, 'utf-8');
@@ -207,7 +207,7 @@ function unpatchViteConfig(cwd: string, dryRun: boolean): string[] {
207207

208208
let newContent = content
209209
.split('\n')
210-
.filter((line) => !line.includes('agent-react-devtools'))
210+
.filter((line) => line !== "import { reactDevtools } from 'agent-react-devtools/vite';")
211211
.join('\n');
212212

213213
// Remove reactDevtools() call from plugins array (with optional trailing comma)
@@ -235,27 +235,32 @@ function unpatchNextJs(cwd: string, dryRun: boolean): string[] {
235235

236236
if (layoutPath) {
237237
const devtoolsPath = join(dirname(layoutPath), 'devtools.ts');
238+
let devtoolsIsOurs = false;
238239
if (existsSync(devtoolsPath)) {
239240
const content = readFileSync(devtoolsPath, 'utf-8');
240241
if (content.includes('agent-react-devtools')) {
242+
devtoolsIsOurs = true;
241243
if (!dryRun) {
242244
unlinkSync(devtoolsPath);
243245
}
244246
modified.push(devtoolsPath);
245247
}
246248
}
247249

248-
// Remove the import of ./devtools from layout
249-
const layoutContent = readFileSync(layoutPath, 'utf-8');
250-
if (layoutContent.includes("'./devtools'") || layoutContent.includes('agent-react-devtools')) {
250+
// Only remove the layout import if we confirmed devtools.ts was created by us,
251+
// to avoid corrupting a pre-existing import './devtools' that we don't own.
252+
if (devtoolsIsOurs) {
253+
const layoutContent = readFileSync(layoutPath, 'utf-8');
251254
const newContent = layoutContent
252255
.split('\n')
253-
.filter((line) => !line.includes("'./devtools'") && !line.includes('agent-react-devtools'))
256+
.filter((line) => line !== "import './devtools';")
254257
.join('\n');
255-
if (!dryRun) {
256-
writeFileSync(layoutPath, newContent, 'utf-8');
258+
if (newContent !== layoutContent) {
259+
if (!dryRun) {
260+
writeFileSync(layoutPath, newContent, 'utf-8');
261+
}
262+
modified.push(layoutPath);
257263
}
258-
modified.push(layoutPath);
259264
}
260265
}
261266

@@ -270,7 +275,7 @@ function unpatchNextJs(cwd: string, dryRun: boolean): string[] {
270275
'src/pages/_app.js',
271276
);
272277
if (pagesEntry) {
273-
const result = removeImport(pagesEntry, dryRun);
278+
const result = removeImport(pagesEntry, "import 'agent-react-devtools/connect';", dryRun);
274279
if (result) modified.push(result);
275280
}
276281

@@ -286,7 +291,7 @@ function unpatchCRA(cwd: string, dryRun: boolean): string[] {
286291
);
287292
if (!entryPath) return [];
288293

289-
const result = removeImport(entryPath, dryRun);
294+
const result = removeImport(entryPath, "import 'agent-react-devtools/connect';", dryRun);
290295
return result ? [result] : [];
291296
}
292297

0 commit comments

Comments
 (0)