next-anteater 0.2.4 → 0.2.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.
@@ -1,4 +1,4 @@
1
- #!/usr/bin/env node
1
+ #!/usr/bin/env node
2
2
  import { main } from "../lib/setup.mjs";
3
3
 
4
4
  main().catch((err) => {
package/lib/uninstall.mjs CHANGED
@@ -3,7 +3,8 @@
3
3
  */
4
4
  import { readFile, writeFile, rm, access } from "node:fs/promises";
5
5
  import { join } from "node:path";
6
- import { bold, green, red, dim, ok, fail, heading, blank } from "./ui.mjs";
6
+ import { execSync } from "node:child_process";
7
+ import { bold, green, red, dim, ok, fail, info, heading, blank } from "./ui.mjs";
7
8
 
8
9
  const cwd = process.cwd();
9
10
 
@@ -25,6 +26,9 @@ async function removeFile(path, label) {
25
26
  return false;
26
27
  }
27
28
 
29
+ /**
30
+ * Remove AnteaterBar import and component usage from the layout file.
31
+ */
28
32
  async function unpatchLayout() {
29
33
  for (const layoutFile of ["app/layout.tsx", "app/layout.js"]) {
30
34
  const fullPath = join(cwd, layoutFile);
@@ -33,11 +37,17 @@ async function unpatchLayout() {
33
37
  let content = await readFile(fullPath, "utf-8");
34
38
  if (!content.includes("AnteaterBar")) return false;
35
39
 
36
- // Remove import lines
40
+ // Remove import lines that contain AnteaterBar
37
41
  content = content.replace(/^.*AnteaterBar.*\n/gm, "");
38
- // Remove component usage
39
- content = content.replace(/^\s*<AnteaterBar[^]*?\/>\s*\n?/gm, "");
42
+
43
+ // Remove <AnteaterBar /> or <AnteaterBar ... /> on its own line
44
+ content = content.replace(/^\s*<AnteaterBar\b[^>]*\/>\s*\n?/gm, "");
45
+ // Remove inline <AnteaterBar /> (e.g., "{children} <AnteaterBar />")
46
+ content = content.replace(/\s*<AnteaterBar\b[^>]*\/>/g, "");
47
+
48
+ // Remove <AnteaterBarWrapper /> on its own line or inline
40
49
  content = content.replace(/^\s*<AnteaterBarWrapper\s*\/>\s*\n?/gm, "");
50
+ content = content.replace(/\s*<AnteaterBarWrapper\s*\/>/g, "");
41
51
 
42
52
  await writeFile(fullPath, content, "utf-8");
43
53
  ok(`Unpatched ${layoutFile}`);
@@ -46,6 +56,9 @@ async function unpatchLayout() {
46
56
  return false;
47
57
  }
48
58
 
59
+ /**
60
+ * Remove next-anteater from package.json dependencies.
61
+ */
49
62
  async function removeDependency() {
50
63
  const pkgPath = join(cwd, "package.json");
51
64
  if (!(await fileExists(pkgPath))) return false;
@@ -69,44 +82,141 @@ async function removeDependency() {
69
82
  return changed;
70
83
  }
71
84
 
85
+ /**
86
+ * Remove GITHUB_TOKEN line from .env.local if present.
87
+ */
88
+ async function cleanEnvLocal() {
89
+ const envPath = join(cwd, ".env.local");
90
+ if (!(await fileExists(envPath))) return false;
91
+
92
+ const content = await readFile(envPath, "utf-8");
93
+ if (!content.includes("GITHUB_TOKEN=")) return false;
94
+
95
+ const cleaned = content
96
+ .split("\n")
97
+ .filter((line) => !line.startsWith("GITHUB_TOKEN="))
98
+ .join("\n");
99
+
100
+ await writeFile(envPath, cleaned, "utf-8");
101
+ ok("Removed GITHUB_TOKEN from .env.local");
102
+ return true;
103
+ }
104
+
105
+ /**
106
+ * Detect the git remote (owner/repo) for secret cleanup.
107
+ */
108
+ function detectRepo() {
109
+ try {
110
+ const url = execSync("git remote get-url origin", { encoding: "utf-8" }).trim();
111
+ const match = url.match(/github\.com[/:](.+?)(?:\.git)?$/);
112
+ return match ? match[1] : null;
113
+ } catch {
114
+ return null;
115
+ }
116
+ }
117
+
118
+ /**
119
+ * Remove ANTHROPIC_API_KEY from GitHub Actions secrets.
120
+ */
121
+ async function removeGitHubSecret(repo) {
122
+ try {
123
+ execSync(`gh secret delete ANTHROPIC_API_KEY --repo ${repo}`, {
124
+ stdio: ["pipe", "ignore", "pipe"],
125
+ });
126
+ ok("Removed ANTHROPIC_API_KEY from GitHub secrets");
127
+ return true;
128
+ } catch {
129
+ return false;
130
+ }
131
+ }
132
+
133
+ /**
134
+ * Remove GITHUB_TOKEN from Vercel environment variables.
135
+ */
136
+ async function removeVercelEnv() {
137
+ try {
138
+ execSync("vercel --version", { stdio: "ignore" });
139
+ } catch {
140
+ return false; // Vercel CLI not installed
141
+ }
142
+
143
+ let removed = false;
144
+ for (const env of ["production", "preview", "development"]) {
145
+ try {
146
+ execSync(`vercel env rm GITHUB_TOKEN ${env} --yes`, {
147
+ stdio: ["pipe", "ignore", "pipe"],
148
+ });
149
+ removed = true;
150
+ } catch {
151
+ // May not exist in this environment
152
+ }
153
+ }
154
+ if (removed) ok("Removed GITHUB_TOKEN from Vercel environment variables");
155
+ return removed;
156
+ }
157
+
72
158
  export async function main() {
73
159
  console.log();
74
160
  console.log(` ${bold("\u{1F41C} Anteater Uninstall")}`);
75
161
  console.log(` ${"\u2500".repeat(20)}`);
76
162
  blank();
77
163
 
78
- heading("Removing scaffolded files");
164
+ let totalRemoved = 0;
79
165
 
80
- let removed = 0;
166
+ // ── Scaffolded files ──────────────────────────────────
167
+ heading("Removing scaffolded files");
81
168
 
82
169
  // Config file
83
- if (await removeFile(join(cwd, "anteater.config.ts"), "anteater.config.ts")) removed++;
84
- if (await removeFile(join(cwd, "anteater.config.js"), "anteater.config.js")) removed++;
170
+ if (await removeFile(join(cwd, "anteater.config.ts"), "anteater.config.ts")) totalRemoved++;
171
+ if (await removeFile(join(cwd, "anteater.config.js"), "anteater.config.js")) totalRemoved++;
85
172
 
86
173
  // API routes
87
- if (await removeFile(join(cwd, "app/api/anteater"), "app/api/anteater/")) removed++;
88
- if (await removeFile(join(cwd, "pages/api/anteater"), "pages/api/anteater/")) removed++;
174
+ if (await removeFile(join(cwd, "app/api/anteater"), "app/api/anteater/")) totalRemoved++;
175
+ if (await removeFile(join(cwd, "pages/api/anteater"), "pages/api/anteater/")) totalRemoved++;
89
176
 
90
177
  // Wrapper component
91
- if (await removeFile(join(cwd, "components/anteater-bar-wrapper.tsx"), "components/anteater-bar-wrapper.tsx")) removed++;
92
- if (await removeFile(join(cwd, "components/anteater-bar-wrapper.js"), "components/anteater-bar-wrapper.js")) removed++;
178
+ if (await removeFile(join(cwd, "components/anteater-bar-wrapper.tsx"), "components/anteater-bar-wrapper.tsx")) totalRemoved++;
179
+ if (await removeFile(join(cwd, "components/anteater-bar-wrapper.js"), "components/anteater-bar-wrapper.js")) totalRemoved++;
93
180
 
94
181
  // GitHub workflow
95
- if (await removeFile(join(cwd, ".github/workflows/anteater.yml"), ".github/workflows/anteater.yml")) removed++;
182
+ if (await removeFile(join(cwd, ".github/workflows/anteater.yml"), ".github/workflows/anteater.yml")) totalRemoved++;
183
+
184
+ // Claude Code agent settings
185
+ if (await removeFile(join(cwd, ".claude/settings.local.json"), ".claude/settings.local.json")) totalRemoved++;
96
186
 
97
- // Unpatch layout
187
+ // ── Layout cleanup ────────────────────────────────────
98
188
  heading("Cleaning up layout");
99
- await unpatchLayout();
189
+ if (await unpatchLayout()) totalRemoved++;
100
190
 
101
- // Remove dependency
191
+ // ── Package dependency ────────────────────────────────
102
192
  heading("Removing dependency");
103
- await removeDependency();
193
+ if (await removeDependency()) totalRemoved++;
194
+
195
+ // ── Environment & secrets ─────────────────────────────
196
+ heading("Cleaning up secrets & environment");
197
+
198
+ // .env.local
199
+ if (await cleanEnvLocal()) totalRemoved++;
200
+
201
+ // GitHub secret
202
+ const repo = detectRepo();
203
+ if (repo) {
204
+ if (await removeGitHubSecret(repo)) totalRemoved++;
205
+ } else {
206
+ info("Could not detect repo — skip GitHub secret cleanup");
207
+ info("Run manually: gh secret delete ANTHROPIC_API_KEY --repo <owner>/<repo>");
208
+ }
209
+
210
+ // Vercel env var
211
+ if (await removeVercelEnv()) totalRemoved++;
104
212
 
213
+ // ── Summary ───────────────────────────────────────────
105
214
  blank();
106
- if (removed > 0) {
107
- console.log(` ${green("\u2713")} Anteater uninstalled. Run ${dim("npx next-anteater setup")} to reinstall.`);
215
+ if (totalRemoved > 0) {
216
+ console.log(` ${green("\u2713")} Anteater fully uninstalled (${totalRemoved} items removed).`);
217
+ console.log(` ${dim("Run npx next-anteater setup to reinstall.")}`);
108
218
  } else {
109
- console.log(` ${dim("No Anteater files found nothing to remove.")}`);
219
+ console.log(` ${dim("No Anteater files found \u2014 nothing to remove.")}`);
110
220
  }
111
221
  console.log();
112
222
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-anteater",
3
- "version": "0.2.4",
3
+ "version": "0.2.5",
4
4
  "description": "AI-powered live editing for your Next.js app",
5
5
  "bin": {
6
6
  "anteater": "bin/setup-anteater.mjs",