@nimbuslab/cli 0.16.3 → 0.16.4

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.
package/dist/index.js CHANGED
@@ -150,7 +150,7 @@ var require_src = __commonJS((exports, module) => {
150
150
  var require_package = __commonJS((exports, module) => {
151
151
  module.exports = {
152
152
  name: "@nimbuslab/cli",
153
- version: "0.16.3",
153
+ version: "0.16.4",
154
154
  description: "CLI para criar projetos nimbuslab",
155
155
  type: "module",
156
156
  bin: {
@@ -161,7 +161,14 @@ var require_package = __commonJS((exports, module) => {
161
161
  build: "bun build src/index.ts --outdir dist --target bun",
162
162
  typecheck: "tsc --noEmit"
163
163
  },
164
- keywords: ["nimbuslab", "cli", "nextjs", "fast", "landing-page", "saas"],
164
+ keywords: [
165
+ "nimbuslab",
166
+ "cli",
167
+ "nextjs",
168
+ "fast",
169
+ "landing-page",
170
+ "saas"
171
+ ],
165
172
  author: {
166
173
  name: "nimbuslab",
167
174
  email: "contato@nimbuslab.com.br",
@@ -2360,9 +2367,55 @@ function printUpgradePlan(name, plan) {
2360
2367
  var import_picocolors6 = __toESM(require_picocolors(), 1);
2361
2368
  import { execSync, spawnSync } from "child_process";
2362
2369
  var PACKAGE_NAME = "@nimbuslab/cli";
2370
+ function hasBunInstall() {
2371
+ try {
2372
+ const result = spawnSync("bun", ["pm", "ls", "-g"], {
2373
+ encoding: "utf-8",
2374
+ shell: true,
2375
+ timeout: 5000
2376
+ });
2377
+ return !!(result.stdout && result.stdout.includes(PACKAGE_NAME));
2378
+ } catch {
2379
+ return false;
2380
+ }
2381
+ }
2382
+ function hasNpmInstall() {
2383
+ try {
2384
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
2385
+ encoding: "utf-8",
2386
+ shell: true,
2387
+ timeout: 5000
2388
+ });
2389
+ if (result.stdout) {
2390
+ const data = JSON.parse(result.stdout);
2391
+ return !!data.dependencies?.[PACKAGE_NAME];
2392
+ }
2393
+ } catch {}
2394
+ return false;
2395
+ }
2396
+ function cleanupDuplicateInstalls() {
2397
+ const hasNpm = hasNpmInstall();
2398
+ const hasBun = hasBunInstall();
2399
+ if (hasNpm && hasBun) {
2400
+ try {
2401
+ execSync("bun remove -g @nimbuslab/cli", { stdio: "pipe", encoding: "utf-8" });
2402
+ return {
2403
+ cleaned: true,
2404
+ message: "Instalacao duplicada removida do bun (usando npm)"
2405
+ };
2406
+ } catch {
2407
+ return {
2408
+ cleaned: false,
2409
+ message: "Falha ao remover instalacao duplicada do bun"
2410
+ };
2411
+ }
2412
+ }
2413
+ return { cleaned: false, message: "" };
2414
+ }
2363
2415
  function isUsingFnm() {
2364
2416
  const fnmDir = process.env.FNM_DIR || process.env.FNM_MULTISHELL_PATH;
2365
- const whichNode = spawnSync("which", ["node"], { encoding: "utf-8", shell: true });
2417
+ const checkCmd = process.platform === "win32" ? "where" : "which";
2418
+ const whichNode = spawnSync(checkCmd, ["node"], { encoding: "utf-8", shell: true });
2366
2419
  return !!(fnmDir || whichNode.stdout && whichNode.stdout.includes("fnm"));
2367
2420
  }
2368
2421
  async function getAvailableVersions() {
@@ -2478,6 +2531,13 @@ async function update(args) {
2478
2531
  const isSpecificVersion = flag && flag !== "latest" && !flag.startsWith("-");
2479
2532
  Ie(import_picocolors6.default.cyan(`Atualizando ${PACKAGE_NAME}`));
2480
2533
  const spinner = Y2();
2534
+ spinner.start("Verificando instalacoes...");
2535
+ const cleanup = cleanupDuplicateInstalls();
2536
+ if (cleanup.cleaned) {
2537
+ spinner.stop(import_picocolors6.default.yellow(cleanup.message));
2538
+ } else {
2539
+ spinner.stop("OK");
2540
+ }
2481
2541
  spinner.start("Detectando package manager...");
2482
2542
  const detectedPm = detectPackageManager2();
2483
2543
  const pm = detectedPm === "unknown" ? "npm" : detectedPm;
@@ -2564,18 +2624,19 @@ var LOLA_MEMORY_URL = "https://lola.nimbuslab.com.br/sse";
2564
2624
  var LOLA_MEMORY_NAME = "lola-memory";
2565
2625
  var GEMINI_DIR = join3(HOME, ".gemini");
2566
2626
  var GEMINI_SETTINGS = join3(GEMINI_DIR, "GEMINI.md");
2627
+ var CHECK_CMD = process.platform === "win32" ? "where" : "which";
2567
2628
  function hasClaudeCLI() {
2568
- const result = Bun.spawnSync(["which", "claude"], { stdout: "pipe" });
2629
+ const result = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2569
2630
  return result.exitCode === 0;
2570
2631
  }
2571
2632
  function hasGeminiCLI() {
2572
- const result = Bun.spawnSync(["which", "gemini"], { stdout: "pipe" });
2633
+ const result = Bun.spawnSync([CHECK_CMD, "gemini"], { stdout: "pipe", stderr: "pipe" });
2573
2634
  return result.exitCode === 0;
2574
2635
  }
2575
2636
  async function installLolaMemoryMCP() {
2576
2637
  console.log();
2577
2638
  console.log(import_picocolors7.default.cyan(" Configurando lola-memory MCP..."));
2578
- const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" });
2639
+ const claudeCheck = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" });
2579
2640
  if (claudeCheck.exitCode !== 0) {
2580
2641
  console.log(import_picocolors7.default.yellow(" Claude CLI nao encontrado, pulando MCP"));
2581
2642
  console.log(import_picocolors7.default.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"));
@@ -2765,7 +2826,7 @@ async function suggestImprovement(message) {
2765
2826
  console.log(import_picocolors7.default.dim(' Uso: nimbus lola suggest "sua sugestao aqui"'));
2766
2827
  process.exit(1);
2767
2828
  }
2768
- const ghCheck = Bun.spawnSync(["which", "gh"]);
2829
+ const ghCheck = Bun.spawnSync([CHECK_CMD, "gh"], { stderr: "pipe" });
2769
2830
  if (ghCheck.exitCode !== 0) {
2770
2831
  console.log(import_picocolors7.default.red(" Erro: GitHub CLI (gh) nao encontrado"));
2771
2832
  console.log(import_picocolors7.default.dim(" Instale: https://cli.github.com"));
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@nimbuslab/cli",
3
- "version": "0.16.3",
3
+ "version": "0.16.4",
4
4
  "description": "CLI para criar projetos nimbuslab",
5
5
  "type": "module",
6
6
  "bin": {
@@ -11,7 +11,14 @@
11
11
  "build": "bun build src/index.ts --outdir dist --target bun",
12
12
  "typecheck": "tsc --noEmit"
13
13
  },
14
- "keywords": ["nimbuslab", "cli", "nextjs", "fast", "landing-page", "saas"],
14
+ "keywords": [
15
+ "nimbuslab",
16
+ "cli",
17
+ "nextjs",
18
+ "fast",
19
+ "landing-page",
20
+ "saas"
21
+ ],
15
22
  "author": {
16
23
  "name": "nimbuslab",
17
24
  "email": "contato@nimbuslab.com.br",
@@ -18,14 +18,17 @@ const GEMINI_SETTINGS = join(GEMINI_DIR, "GEMINI.md")
18
18
  // Tipos de agent
19
19
  type AgentType = "claude" | "gemini" | "all"
20
20
 
21
+ // Comando para verificar executavel (which no Unix, where no Windows)
22
+ const CHECK_CMD = process.platform === "win32" ? "where" : "which"
23
+
21
24
  // Helpers de detecção
22
25
  function hasClaudeCLI(): boolean {
23
- const result = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
26
+ const result = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" })
24
27
  return result.exitCode === 0
25
28
  }
26
29
 
27
30
  function hasGeminiCLI(): boolean {
28
- const result = Bun.spawnSync(["which", "gemini"], { stdout: "pipe" })
31
+ const result = Bun.spawnSync([CHECK_CMD, "gemini"], { stdout: "pipe", stderr: "pipe" })
29
32
  return result.exitCode === 0
30
33
  }
31
34
 
@@ -34,7 +37,7 @@ async function installLolaMemoryMCP(): Promise<void> {
34
37
  console.log(pc.cyan(" Configurando lola-memory MCP..."))
35
38
 
36
39
  // Verificar se claude CLI existe
37
- const claudeCheck = Bun.spawnSync(["which", "claude"], { stdout: "pipe" })
40
+ const claudeCheck = Bun.spawnSync([CHECK_CMD, "claude"], { stdout: "pipe", stderr: "pipe" })
38
41
  if (claudeCheck.exitCode !== 0) {
39
42
  console.log(pc.yellow(" Claude CLI nao encontrado, pulando MCP"))
40
43
  console.log(pc.dim(" Instale o Claude CLI e rode 'nimbus lola install' novamente"))
@@ -287,7 +290,7 @@ async function suggestImprovement(message: string): Promise<void> {
287
290
  }
288
291
 
289
292
  // Verificar gh cli
290
- const ghCheck = Bun.spawnSync(["which", "gh"])
293
+ const ghCheck = Bun.spawnSync([CHECK_CMD, "gh"], { stderr: "pipe" })
291
294
  if (ghCheck.exitCode !== 0) {
292
295
  console.log(pc.red(" Erro: GitHub CLI (gh) nao encontrado"))
293
296
  console.log(pc.dim(" Instale: https://cli.github.com"))
@@ -6,10 +6,68 @@ const PACKAGE_NAME = "@nimbuslab/cli"
6
6
 
7
7
  type PackageManager = "bun" | "npm" | "unknown"
8
8
 
9
+ // Verifica se existe instalacao no bun global
10
+ function hasBunInstall(): boolean {
11
+ try {
12
+ const result = spawnSync("bun", ["pm", "ls", "-g"], {
13
+ encoding: "utf-8",
14
+ shell: true,
15
+ timeout: 5000,
16
+ })
17
+ return !!(result.stdout && result.stdout.includes(PACKAGE_NAME))
18
+ } catch {
19
+ return false
20
+ }
21
+ }
22
+
23
+ // Verifica se existe instalacao no npm global
24
+ function hasNpmInstall(): boolean {
25
+ try {
26
+ const result = spawnSync("npm", ["ls", "-g", PACKAGE_NAME, "--json"], {
27
+ encoding: "utf-8",
28
+ shell: true,
29
+ timeout: 5000,
30
+ })
31
+ if (result.stdout) {
32
+ const data = JSON.parse(result.stdout)
33
+ return !!data.dependencies?.[PACKAGE_NAME]
34
+ }
35
+ } catch {
36
+ // ignore
37
+ }
38
+ return false
39
+ }
40
+
41
+ // Remove instalacao duplicada para evitar conflitos
42
+ // Prioriza npm (fnm/nvm), remove bun se tiver npm
43
+ function cleanupDuplicateInstalls(): { cleaned: boolean; message: string } {
44
+ const hasNpm = hasNpmInstall()
45
+ const hasBun = hasBunInstall()
46
+
47
+ if (hasNpm && hasBun) {
48
+ // Tem nos dois - remover do bun (prioriza npm)
49
+ try {
50
+ execSync("bun remove -g @nimbuslab/cli", { stdio: "pipe", encoding: "utf-8" })
51
+ return {
52
+ cleaned: true,
53
+ message: "Instalacao duplicada removida do bun (usando npm)",
54
+ }
55
+ } catch {
56
+ return {
57
+ cleaned: false,
58
+ message: "Falha ao remover instalacao duplicada do bun",
59
+ }
60
+ }
61
+ }
62
+
63
+ return { cleaned: false, message: "" }
64
+ }
65
+
9
66
  // Detecta se está usando fnm (Fast Node Manager)
10
67
  function isUsingFnm(): boolean {
11
68
  const fnmDir = process.env.FNM_DIR || process.env.FNM_MULTISHELL_PATH
12
- const whichNode = spawnSync("which", ["node"], { encoding: "utf-8", shell: true })
69
+ const checkCmd = process.platform === "win32" ? "where" : "which"
70
+ const whichNode = spawnSync(checkCmd, ["node"], { encoding: "utf-8", shell: true })
13
71
  return !!(fnmDir || (whichNode.stdout && whichNode.stdout.includes("fnm")))
14
72
  }
15
73
 
@@ -160,6 +218,15 @@ export async function update(args: string[]) {
160
218
 
161
219
  const spinner = p.spinner()
162
220
 
221
+ // Limpar instalacoes duplicadas automaticamente
222
+ spinner.start("Verificando instalacoes...")
223
+ const cleanup = cleanupDuplicateInstalls()
224
+ if (cleanup.cleaned) {
225
+ spinner.stop(pc.yellow(cleanup.message))
226
+ } else {
227
+ spinner.stop("OK")
228
+ }
229
+
163
230
  // Detectar package manager
164
231
  spinner.start("Detectando package manager...")
165
232
  const detectedPm = detectPackageManager()