@nimbuslab/cli 0.16.3 → 0.16.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.
- package/README.md +41 -75
- package/dist/index.js +72 -10
- package/package.json +12 -2
- package/.github/workflows/publish.yml +0 -67
- package/CLAUDE.md +0 -106
- package/MIGRATION-ROADMAP.md +0 -201
- package/bun.lock +0 -36
- package/docs/CI-CD.md +0 -181
- package/docs/analyze.md +0 -148
- package/docs/create.md +0 -219
- package/docs/migrate.md +0 -177
- package/docs/package.md +0 -229
- package/docs/upgrade.md +0 -152
- package/src/commands/analyze.ts +0 -210
- package/src/commands/create.ts +0 -1323
- package/src/commands/lola.ts +0 -1026
- package/src/commands/update.ts +0 -267
- package/src/commands/upgrade.ts +0 -251
- package/src/index.ts +0 -161
- package/tsconfig.json +0 -29
package/docs/upgrade.md
DELETED
|
@@ -1,152 +0,0 @@
|
|
|
1
|
-
# nimbus upgrade
|
|
2
|
-
|
|
3
|
-
Planeja e executa upgrades de dependencias para a stack nimbuslab.
|
|
4
|
-
|
|
5
|
-
## Uso
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
# Ver plano completo de upgrades
|
|
9
|
-
nimbus upgrade --plan
|
|
10
|
-
|
|
11
|
-
# Upgrade especifico (em desenvolvimento)
|
|
12
|
-
nimbus upgrade next
|
|
13
|
-
nimbus upgrade react
|
|
14
|
-
nimbus upgrade tailwind
|
|
15
|
-
nimbus upgrade bun
|
|
16
|
-
```
|
|
17
|
-
|
|
18
|
-
## Upgrades Suportados
|
|
19
|
-
|
|
20
|
-
### Next.js 14/15 -> 16
|
|
21
|
-
|
|
22
|
-
| Aspecto | Detalhes |
|
|
23
|
-
|---------|----------|
|
|
24
|
-
| Complexidade | Media |
|
|
25
|
-
| Breaking Changes | next/image API, middleware, turbopack |
|
|
26
|
-
| Tempo Estimado | 1-2 horas |
|
|
27
|
-
|
|
28
|
-
**Passos:**
|
|
29
|
-
1. Atualizar next para ^16.0.0
|
|
30
|
-
2. Atualizar react para ^19.0.0
|
|
31
|
-
3. Atualizar react-dom para ^19.0.0
|
|
32
|
-
4. Revisar next.config.ts
|
|
33
|
-
5. Testar build e dev
|
|
34
|
-
|
|
35
|
-
### React 18 -> 19
|
|
36
|
-
|
|
37
|
-
| Aspecto | Detalhes |
|
|
38
|
-
|---------|----------|
|
|
39
|
-
| Complexidade | Media |
|
|
40
|
-
| Breaking Changes | forwardRef, Suspense, async components |
|
|
41
|
-
| Tempo Estimado | 1-2 horas |
|
|
42
|
-
|
|
43
|
-
**Passos:**
|
|
44
|
-
1. Atualizar react e react-dom para ^19.0.0
|
|
45
|
-
2. Remover forwardRef (ref agora e prop regular)
|
|
46
|
-
3. Atualizar @types/react
|
|
47
|
-
4. Revisar Suspense boundaries
|
|
48
|
-
|
|
49
|
-
### Tailwind 3 -> 4
|
|
50
|
-
|
|
51
|
-
| Aspecto | Detalhes |
|
|
52
|
-
|---------|----------|
|
|
53
|
-
| Complexidade | Media |
|
|
54
|
-
| Breaking Changes | Config em CSS, @apply syntax |
|
|
55
|
-
| Tempo Estimado | 2-4 horas |
|
|
56
|
-
|
|
57
|
-
**Passos:**
|
|
58
|
-
1. Atualizar tailwindcss para ^4.0.0
|
|
59
|
-
2. Converter tailwind.config.js para CSS
|
|
60
|
-
3. Atualizar globals.css com @import 'tailwindcss'
|
|
61
|
-
4. Revisar @apply usages
|
|
62
|
-
5. Atualizar plugins
|
|
63
|
-
|
|
64
|
-
### pnpm/npm/yarn -> bun
|
|
65
|
-
|
|
66
|
-
| Aspecto | Detalhes |
|
|
67
|
-
|---------|----------|
|
|
68
|
-
| Complexidade | Baixa |
|
|
69
|
-
| Breaking Changes | Lockfile, alguns scripts |
|
|
70
|
-
| Tempo Estimado | 30 min |
|
|
71
|
-
|
|
72
|
-
**Passos:**
|
|
73
|
-
1. Remover node_modules
|
|
74
|
-
2. Remover lockfile antigo
|
|
75
|
-
3. Executar bun install
|
|
76
|
-
4. Atualizar scripts (npx -> bunx)
|
|
77
|
-
5. Atualizar CI/CD
|
|
78
|
-
|
|
79
|
-
### Prisma -> Drizzle
|
|
80
|
-
|
|
81
|
-
| Aspecto | Detalhes |
|
|
82
|
-
|---------|----------|
|
|
83
|
-
| Complexidade | Alta |
|
|
84
|
-
| Breaking Changes | Schema, queries, migrations |
|
|
85
|
-
| Tempo Estimado | 4-8 horas |
|
|
86
|
-
|
|
87
|
-
**Passos:**
|
|
88
|
-
1. Instalar drizzle-orm e drizzle-kit
|
|
89
|
-
2. Converter schema.prisma para drizzle
|
|
90
|
-
3. Configurar drizzle.config.ts
|
|
91
|
-
4. Gerar migrations
|
|
92
|
-
5. Atualizar todas as queries
|
|
93
|
-
6. Atualizar auth config
|
|
94
|
-
|
|
95
|
-
## Exemplo de Output
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
Upgrades Disponiveis:
|
|
99
|
-
|
|
100
|
-
Next.js
|
|
101
|
-
Atual: 15.0.2 -> 16.x
|
|
102
|
-
Complexidade: media
|
|
103
|
-
|
|
104
|
-
Breaking Changes:
|
|
105
|
-
! next/image: Mudancas na API de otimizacao
|
|
106
|
-
! Middleware: Novo formato de config
|
|
107
|
-
! Turbopack: Agora e o bundler padrao
|
|
108
|
-
|
|
109
|
-
Passos:
|
|
110
|
-
1. Atualizar next para ^16.0.0
|
|
111
|
-
2. Atualizar react para ^19.0.0
|
|
112
|
-
3. Revisar next.config.ts
|
|
113
|
-
4. Testar build: bun run build
|
|
114
|
-
|
|
115
|
-
React
|
|
116
|
-
Atual: 18.2.0 -> 19.x
|
|
117
|
-
Complexidade: media
|
|
118
|
-
|
|
119
|
-
Breaking Changes:
|
|
120
|
-
! forwardRef: Nao mais necessario
|
|
121
|
-
! Suspense: Mudancas em fallback
|
|
122
|
-
! Async components: Novo suporte
|
|
123
|
-
|
|
124
|
-
Passos:
|
|
125
|
-
1. Atualizar react para ^19.0.0
|
|
126
|
-
2. Remover forwardRef
|
|
127
|
-
3. Revisar Suspense boundaries
|
|
128
|
-
```
|
|
129
|
-
|
|
130
|
-
## Codemods (Em Desenvolvimento)
|
|
131
|
-
|
|
132
|
-
Codemods sao transformacoes automaticas de codigo usando AST:
|
|
133
|
-
|
|
134
|
-
```bash
|
|
135
|
-
# Futuros comandos
|
|
136
|
-
nimbus codemod tailwind-v4 # Transforma Tailwind 3 -> 4
|
|
137
|
-
nimbus codemod react-19 # Transforma React 18 -> 19
|
|
138
|
-
nimbus codemod drizzle # Transforma Prisma -> Drizzle
|
|
139
|
-
nimbus codemod bun # Transforma para Bun
|
|
140
|
-
```
|
|
141
|
-
|
|
142
|
-
## Estrategia de Upgrade
|
|
143
|
-
|
|
144
|
-
1. **Sempre** fazer backup/branch antes
|
|
145
|
-
2. **Sempre** rodar `nimbus analyze` primeiro
|
|
146
|
-
3. **Sempre** testar apos cada upgrade
|
|
147
|
-
4. **Nunca** fazer todos os upgrades de uma vez
|
|
148
|
-
5. **Preferir** ordem: bun -> tailwind -> react -> next
|
|
149
|
-
|
|
150
|
-
---
|
|
151
|
-
|
|
152
|
-
[Voltar ao README](../README.md) | [create](./create.md) | [analyze](./analyze.md) | [migrate](./migrate.md)
|
package/src/commands/analyze.ts
DELETED
|
@@ -1,210 +0,0 @@
|
|
|
1
|
-
import * as p from "@clack/prompts"
|
|
2
|
-
import pc from "picocolors"
|
|
3
|
-
import { existsSync, readFileSync } from "node:fs"
|
|
4
|
-
import { join } from "node:path"
|
|
5
|
-
|
|
6
|
-
interface AnalysisResult {
|
|
7
|
-
name: string
|
|
8
|
-
version: string
|
|
9
|
-
framework: string | null
|
|
10
|
-
frameworkVersion: string | null
|
|
11
|
-
styling: string[]
|
|
12
|
-
packageManager: string
|
|
13
|
-
monorepo: string | null
|
|
14
|
-
auth: string | null
|
|
15
|
-
database: string | null
|
|
16
|
-
typescript: boolean
|
|
17
|
-
dependencies: Record<string, string>
|
|
18
|
-
devDependencies: Record<string, string>
|
|
19
|
-
recommendations: string[]
|
|
20
|
-
}
|
|
21
|
-
|
|
22
|
-
function detectPackageManager(dir: string): string {
|
|
23
|
-
if (existsSync(join(dir, "bun.lockb"))) return "bun"
|
|
24
|
-
if (existsSync(join(dir, "pnpm-lock.yaml"))) return "pnpm"
|
|
25
|
-
if (existsSync(join(dir, "yarn.lock"))) return "yarn"
|
|
26
|
-
if (existsSync(join(dir, "package-lock.json"))) return "npm"
|
|
27
|
-
return "unknown"
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
function detectMonorepo(dir: string, pkg: any): string | null {
|
|
31
|
-
if (existsSync(join(dir, "turbo.json"))) return "turborepo"
|
|
32
|
-
if (existsSync(join(dir, "nx.json"))) return "nx"
|
|
33
|
-
if (existsSync(join(dir, "lerna.json"))) return "lerna"
|
|
34
|
-
if (pkg.workspaces) return "workspaces"
|
|
35
|
-
return null
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
function detectFramework(deps: Record<string, string>): { name: string | null; version: string | null } {
|
|
39
|
-
if (deps["next"]) return { name: "nextjs", version: deps["next"] }
|
|
40
|
-
if (deps["@angular/core"]) return { name: "angular", version: deps["@angular/core"] }
|
|
41
|
-
if (deps["vue"]) return { name: "vue", version: deps["vue"] }
|
|
42
|
-
if (deps["svelte"]) return { name: "svelte", version: deps["svelte"] }
|
|
43
|
-
if (deps["react"] && !deps["next"]) return { name: "react", version: deps["react"] }
|
|
44
|
-
return { name: null, version: null }
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
function detectStyling(deps: Record<string, string>, devDeps: Record<string, string>): string[] {
|
|
48
|
-
const styling: string[] = []
|
|
49
|
-
const allDeps = { ...deps, ...devDeps }
|
|
50
|
-
|
|
51
|
-
if (allDeps["tailwindcss"]) styling.push(`tailwind@${allDeps["tailwindcss"]}`)
|
|
52
|
-
if (allDeps["styled-components"]) styling.push("styled-components")
|
|
53
|
-
if (allDeps["@emotion/react"]) styling.push("emotion")
|
|
54
|
-
if (allDeps["sass"]) styling.push("sass")
|
|
55
|
-
if (allDeps["less"]) styling.push("less")
|
|
56
|
-
|
|
57
|
-
return styling.length > 0 ? styling : ["css"]
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
function detectAuth(deps: Record<string, string>): string | null {
|
|
61
|
-
if (deps["better-auth"]) return "better-auth"
|
|
62
|
-
if (deps["next-auth"]) return "next-auth"
|
|
63
|
-
if (deps["@clerk/nextjs"]) return "clerk"
|
|
64
|
-
if (deps["@auth0/nextjs-auth0"]) return "auth0"
|
|
65
|
-
if (deps["@supabase/supabase-js"]) return "supabase"
|
|
66
|
-
return null
|
|
67
|
-
}
|
|
68
|
-
|
|
69
|
-
function detectDatabase(deps: Record<string, string>): string | null {
|
|
70
|
-
if (deps["drizzle-orm"]) return "drizzle"
|
|
71
|
-
if (deps["@prisma/client"]) return "prisma"
|
|
72
|
-
if (deps["typeorm"]) return "typeorm"
|
|
73
|
-
if (deps["mongoose"]) return "mongoose"
|
|
74
|
-
if (deps["pg"]) return "pg"
|
|
75
|
-
if (deps["mysql2"]) return "mysql"
|
|
76
|
-
return null
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
function generateRecommendations(result: AnalysisResult): string[] {
|
|
80
|
-
const recs: string[] = []
|
|
81
|
-
|
|
82
|
-
// Package manager
|
|
83
|
-
if (result.packageManager !== "bun") {
|
|
84
|
-
recs.push(`Migrar ${result.packageManager} -> bun (nimbus codemod bun)`)
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Framework version
|
|
88
|
-
if (result.framework === "nextjs" && result.frameworkVersion) {
|
|
89
|
-
const majorVersion = parseInt(result.frameworkVersion.replace(/[^0-9]/g, "").slice(0, 2))
|
|
90
|
-
if (majorVersion < 16) {
|
|
91
|
-
recs.push(`Atualizar Next.js ${result.frameworkVersion} -> 16 (nimbus upgrade next)`)
|
|
92
|
-
}
|
|
93
|
-
}
|
|
94
|
-
|
|
95
|
-
// Tailwind
|
|
96
|
-
const tailwind = result.styling.find(s => s.startsWith("tailwind"))
|
|
97
|
-
if (tailwind) {
|
|
98
|
-
const version = tailwind.split("@")[1] || ""
|
|
99
|
-
if (version.startsWith("3")) {
|
|
100
|
-
recs.push(`Atualizar Tailwind 3 -> 4 (nimbus upgrade tailwind)`)
|
|
101
|
-
}
|
|
102
|
-
} else if (!result.styling.includes("tailwind")) {
|
|
103
|
-
recs.push(`Considerar adicionar Tailwind CSS (nimbus add tailwind)`)
|
|
104
|
-
}
|
|
105
|
-
|
|
106
|
-
// React version
|
|
107
|
-
if (result.dependencies["react"]) {
|
|
108
|
-
const reactVersion = result.dependencies["react"]
|
|
109
|
-
if (reactVersion.startsWith("18") || reactVersion.startsWith("^18")) {
|
|
110
|
-
recs.push(`Atualizar React 18 -> 19 (nimbus upgrade react)`)
|
|
111
|
-
}
|
|
112
|
-
}
|
|
113
|
-
|
|
114
|
-
// Database
|
|
115
|
-
if (result.database === "prisma") {
|
|
116
|
-
recs.push(`Considerar migrar Prisma -> Drizzle (nimbus codemod drizzle)`)
|
|
117
|
-
} else if (!result.database && result.framework === "nextjs") {
|
|
118
|
-
recs.push(`Considerar adicionar banco de dados (nimbus add db)`)
|
|
119
|
-
}
|
|
120
|
-
|
|
121
|
-
// Auth
|
|
122
|
-
if (!result.auth && result.framework === "nextjs") {
|
|
123
|
-
recs.push(`Considerar adicionar autenticacao (nimbus add auth)`)
|
|
124
|
-
} else if (result.auth === "next-auth") {
|
|
125
|
-
recs.push(`Considerar migrar NextAuth -> Better Auth`)
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Monorepo
|
|
129
|
-
if (result.monorepo === "workspaces" && !result.monorepo) {
|
|
130
|
-
recs.push(`Considerar usar Turborepo para monorepo (nimbus add monorepo)`)
|
|
131
|
-
}
|
|
132
|
-
|
|
133
|
-
return recs
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
export async function analyze(args: string[]) {
|
|
137
|
-
const targetDir = args[0] || "."
|
|
138
|
-
const absoluteDir = targetDir.startsWith("/") ? targetDir : join(process.cwd(), targetDir)
|
|
139
|
-
|
|
140
|
-
console.log()
|
|
141
|
-
console.log(pc.cyan(" Analisando projeto..."))
|
|
142
|
-
console.log()
|
|
143
|
-
|
|
144
|
-
// Check if package.json exists
|
|
145
|
-
const pkgPath = join(absoluteDir, "package.json")
|
|
146
|
-
if (!existsSync(pkgPath)) {
|
|
147
|
-
console.log(pc.red(" Erro: package.json nao encontrado"))
|
|
148
|
-
console.log(pc.dim(` Diretorio: ${absoluteDir}`))
|
|
149
|
-
process.exit(1)
|
|
150
|
-
}
|
|
151
|
-
|
|
152
|
-
// Read package.json
|
|
153
|
-
const pkg = JSON.parse(readFileSync(pkgPath, "utf-8"))
|
|
154
|
-
const deps = pkg.dependencies || {}
|
|
155
|
-
const devDeps = pkg.devDependencies || {}
|
|
156
|
-
|
|
157
|
-
// Detect everything
|
|
158
|
-
const framework = detectFramework(deps)
|
|
159
|
-
const result: AnalysisResult = {
|
|
160
|
-
name: pkg.name || "unknown",
|
|
161
|
-
version: pkg.version || "0.0.0",
|
|
162
|
-
framework: framework.name,
|
|
163
|
-
frameworkVersion: framework.version,
|
|
164
|
-
styling: detectStyling(deps, devDeps),
|
|
165
|
-
packageManager: detectPackageManager(absoluteDir),
|
|
166
|
-
monorepo: detectMonorepo(absoluteDir, pkg),
|
|
167
|
-
auth: detectAuth(deps),
|
|
168
|
-
database: detectDatabase(deps),
|
|
169
|
-
typescript: existsSync(join(absoluteDir, "tsconfig.json")),
|
|
170
|
-
dependencies: deps,
|
|
171
|
-
devDependencies: devDeps,
|
|
172
|
-
recommendations: [],
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
// Generate recommendations
|
|
176
|
-
result.recommendations = generateRecommendations(result)
|
|
177
|
-
|
|
178
|
-
// Display results
|
|
179
|
-
console.log(pc.bold(" Projeto: ") + pc.cyan(result.name) + pc.dim(` v${result.version}`))
|
|
180
|
-
console.log()
|
|
181
|
-
|
|
182
|
-
console.log(pc.bold(" Stack Detectada:"))
|
|
183
|
-
console.log(` Framework: ${result.framework ? pc.green(result.framework + "@" + result.frameworkVersion) : pc.dim("nenhum")}`)
|
|
184
|
-
console.log(` Styling: ${result.styling.map(s => pc.green(s)).join(", ")}`)
|
|
185
|
-
console.log(` Package Manager: ${result.packageManager === "bun" ? pc.green(result.packageManager) : pc.yellow(result.packageManager)}`)
|
|
186
|
-
console.log(` TypeScript: ${result.typescript ? pc.green("sim") : pc.dim("nao")}`)
|
|
187
|
-
console.log(` Monorepo: ${result.monorepo ? pc.green(result.monorepo) : pc.dim("nao")}`)
|
|
188
|
-
console.log(` Auth: ${result.auth ? pc.green(result.auth) : pc.dim("nenhum")}`)
|
|
189
|
-
console.log(` Database: ${result.database ? pc.green(result.database) : pc.dim("nenhum")}`)
|
|
190
|
-
console.log()
|
|
191
|
-
|
|
192
|
-
if (result.recommendations.length > 0) {
|
|
193
|
-
console.log(pc.bold(" Recomendacoes:"))
|
|
194
|
-
result.recommendations.forEach((rec, i) => {
|
|
195
|
-
console.log(pc.yellow(` ${i + 1}. ${rec}`))
|
|
196
|
-
})
|
|
197
|
-
console.log()
|
|
198
|
-
} else {
|
|
199
|
-
console.log(pc.green(" Projeto ja esta na stack recomendada!"))
|
|
200
|
-
console.log()
|
|
201
|
-
}
|
|
202
|
-
|
|
203
|
-
// JSON output option
|
|
204
|
-
if (args.includes("--json")) {
|
|
205
|
-
console.log(pc.dim(" JSON:"))
|
|
206
|
-
console.log(JSON.stringify(result, null, 2))
|
|
207
|
-
}
|
|
208
|
-
|
|
209
|
-
return result
|
|
210
|
-
}
|