@perma-tools/cli 0.0.1

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 (75) hide show
  1. package/README.md +159 -0
  2. package/dist/actions.d.ts +12 -0
  3. package/dist/actions.js +157 -0
  4. package/dist/cli-parser.d.ts +21 -0
  5. package/dist/cli-parser.js +141 -0
  6. package/dist/configs/axios.config.d.ts +2 -0
  7. package/dist/configs/axios.config.js +12 -0
  8. package/dist/configs/biome.config.d.ts +2 -0
  9. package/dist/configs/biome.config.js +12 -0
  10. package/dist/configs/cookies-next.config.d.ts +2 -0
  11. package/dist/configs/cookies-next.config.js +6 -0
  12. package/dist/configs/date-fns.config.d.ts +2 -0
  13. package/dist/configs/date-fns.config.js +6 -0
  14. package/dist/configs/eslint-prettier.config.d.ts +2 -0
  15. package/dist/configs/eslint-prettier.config.js +35 -0
  16. package/dist/configs/framer-motion.config.d.ts +2 -0
  17. package/dist/configs/framer-motion.config.js +6 -0
  18. package/dist/configs/ky.config.d.ts +2 -0
  19. package/dist/configs/ky.config.js +12 -0
  20. package/dist/configs/lucide-react.config.d.ts +2 -0
  21. package/dist/configs/lucide-react.config.js +6 -0
  22. package/dist/configs/nuqs.config.d.ts +2 -0
  23. package/dist/configs/nuqs.config.js +12 -0
  24. package/dist/configs/react-hook-form.config.d.ts +2 -0
  25. package/dist/configs/react-hook-form.config.js +6 -0
  26. package/dist/configs/recharts.config.d.ts +2 -0
  27. package/dist/configs/recharts.config.js +6 -0
  28. package/dist/configs/tanstack-query.config.d.ts +2 -0
  29. package/dist/configs/tanstack-query.config.js +19 -0
  30. package/dist/configs/zod.config.d.ts +2 -0
  31. package/dist/configs/zod.config.js +6 -0
  32. package/dist/dependency-versions.d.ts +13 -0
  33. package/dist/dependency-versions.js +50 -0
  34. package/dist/git-setup.d.ts +23 -0
  35. package/dist/git-setup.js +275 -0
  36. package/dist/index.d.ts +2 -0
  37. package/dist/index.js +537 -0
  38. package/dist/project-generator.d.ts +15 -0
  39. package/dist/project-generator.js +311 -0
  40. package/dist/snippet-manager.d.ts +11 -0
  41. package/dist/snippet-manager.js +76 -0
  42. package/dist/snippets/axios/index.ts +6 -0
  43. package/dist/snippets/biome/biome.json +93 -0
  44. package/dist/snippets/eslint-prettier/eslintignore +6 -0
  45. package/dist/snippets/eslint-prettier/eslintrc.js +3 -0
  46. package/dist/snippets/eslint-prettier/prettierignore +9 -0
  47. package/dist/snippets/eslint-prettier/prettierrc.js +9 -0
  48. package/dist/snippets/ky/index.ts +5 -0
  49. package/dist/snippets/react-query/index.tsx +53 -0
  50. package/dist/snippets/vscode/extensions.json +3 -0
  51. package/dist/snippets/vscode/settings.json +19 -0
  52. package/dist/templates/frontend/next15/base/.env.example +3 -0
  53. package/dist/templates/frontend/next15/base/README.md +50 -0
  54. package/dist/templates/frontend/next15/base/next.config.ts +7 -0
  55. package/dist/templates/frontend/next15/base/package.json +23 -0
  56. package/dist/templates/frontend/next15/base/postcss.config.mjs +8 -0
  57. package/dist/templates/frontend/next15/base/public/public.md +12 -0
  58. package/dist/templates/frontend/next15/base/src/@types/@types.md +7 -0
  59. package/dist/templates/frontend/next15/base/src/@types/types.d.ts +1 -0
  60. package/dist/templates/frontend/next15/base/src/app/(application)/page.tsx +50 -0
  61. package/dist/templates/frontend/next15/base/src/app/favicon.ico +0 -0
  62. package/dist/templates/frontend/next15/base/src/app/layout.tsx +23 -0
  63. package/dist/templates/frontend/next15/base/src/app/providers.tsx +5 -0
  64. package/dist/templates/frontend/next15/base/src/components/components.md +9 -0
  65. package/dist/templates/frontend/next15/base/src/constants/constants.md +10 -0
  66. package/dist/templates/frontend/next15/base/src/hooks/hooks.md +11 -0
  67. package/dist/templates/frontend/next15/base/src/lib/lib.md +9 -0
  68. package/dist/templates/frontend/next15/base/src/services/services.md +14 -0
  69. package/dist/templates/frontend/next15/base/src/styles/globals.css +1 -0
  70. package/dist/templates/frontend/next15/base/src/types/types.md +15 -0
  71. package/dist/templates/frontend/next15/base/src/utils/utils.md +18 -0
  72. package/dist/templates/frontend/next15/base/tsconfig.json +26 -0
  73. package/dist/types.d.ts +60 -0
  74. package/dist/types.js +1 -0
  75. package/package.json +62 -0
package/dist/index.js ADDED
@@ -0,0 +1,537 @@
1
+ #!/usr/bin/env node
2
+ import { access, mkdir } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ import { intro, isCancel, multiselect, outro, select, text, } from "@clack/prompts";
5
+ import { optionsToConfig, parseArguments, validateOptions, } from "./cli-parser.js";
6
+ import { GitSetup } from "./git-setup.js";
7
+ import { ProjectGenerator } from "./project-generator.js";
8
+ async function runHybridMode(options) {
9
+ const config = { ...options };
10
+ // 0. Nome do projeto (obrigatΓ³rio)
11
+ if (!config.projectName) {
12
+ const projectName = await text({
13
+ message: "πŸ“ Qual o nome do projeto?",
14
+ placeholder: "meu-projeto",
15
+ validate: (value) => {
16
+ if (!value)
17
+ return "O nome do projeto Γ© obrigatΓ³rio";
18
+ // Regras do npm para nomes de pacotes
19
+ if (!/^[a-z0-9-]+$/.test(value)) {
20
+ return "Use apenas letras minΓΊsculas, nΓΊmeros e hΓ­fens";
21
+ }
22
+ if (value.startsWith("-") || value.startsWith(".")) {
23
+ return "O nome nΓ£o pode comeΓ§ar com hΓ­fen ou ponto";
24
+ }
25
+ if (value.endsWith("-") || value.endsWith(".")) {
26
+ return "O nome nΓ£o pode terminar com hΓ­fen ou ponto";
27
+ }
28
+ if (value.length > 214) {
29
+ return "O nome deve ter no mΓ‘ximo 214 caracteres";
30
+ }
31
+ if (/^[0-9]/.test(value)) {
32
+ return "O nome nΓ£o pode comeΓ§ar com nΓΊmeros";
33
+ }
34
+ // Nomes reservados do npm
35
+ const reservedNames = ["node_modules", "favicon.ico"];
36
+ if (reservedNames.includes(value.toLowerCase())) {
37
+ return "Este nome Γ© reservado e nΓ£o pode ser usado";
38
+ }
39
+ },
40
+ });
41
+ if (isCancel(projectName)) {
42
+ outro("❌ Operação cancelada");
43
+ process.exit(0);
44
+ }
45
+ config.projectName = projectName;
46
+ }
47
+ config.projectPath = join(process.cwd(), config.projectName);
48
+ // 1. Package Manager
49
+ if (!config.packageManager) {
50
+ config.packageManager = (await select({
51
+ message: "πŸ“¦ Qual package manager deseja usar?",
52
+ options: [
53
+ { value: "pnpm", label: "pnpm" },
54
+ { value: "yarn", label: "yarn" },
55
+ { value: "npm", label: "npm" },
56
+ ],
57
+ }));
58
+ }
59
+ // 2. Tipo da aplicaΓ§Γ£o
60
+ if (!config.applicationType) {
61
+ config.applicationType = (await select({
62
+ message: "πŸ—οΈ Qual tipo de aplicaΓ§Γ£o vocΓͺ quer?",
63
+ options: [
64
+ { value: "frontend", label: "Frontend" },
65
+ { value: "backend", label: "Backend" },
66
+ ],
67
+ }));
68
+ }
69
+ // Fluxo condicional baseado no tipo de aplicaΓ§Γ£o
70
+ if (config.applicationType === "frontend") {
71
+ // 3. Framework (apenas para frontend)
72
+ if (!config.framework) {
73
+ config.framework = (await select({
74
+ message: "⚑ Qual framework?",
75
+ options: [
76
+ { value: "nextjs-15", label: "NextJS 15.x" },
77
+ {
78
+ value: "vitejs-6",
79
+ label: "ViteJS 6.x (em breve)",
80
+ hint: "Ainda nΓ£o disponΓ­vel",
81
+ },
82
+ ],
83
+ }));
84
+ // Validar se ViteJS foi selecionado
85
+ if (config.framework === "vitejs-6") {
86
+ console.error("\n❌ ViteJS ainda não estÑ disponível nesta versão.");
87
+ console.error("πŸ’‘ Use NextJS 15.x ou aguarde a prΓ³xima versΓ£o.\n");
88
+ process.exit(1);
89
+ }
90
+ }
91
+ // 4. Cliente HTTP
92
+ if (!config.httpClient) {
93
+ config.httpClient = (await select({
94
+ message: "🌐 Qual cliente HTTP deseja usar?",
95
+ options: [
96
+ { value: "ky", label: "ky" },
97
+ { value: "axios", label: "axios" },
98
+ { value: "fetch", label: "none (fetch)" },
99
+ ],
100
+ }));
101
+ }
102
+ // 5. Linter
103
+ if (!config.linter) {
104
+ config.linter = (await select({
105
+ message: "✨ Qual linter deseja usar?",
106
+ options: [
107
+ { value: "biome", label: "Biome" },
108
+ { value: "eslint-prettier", label: "Eslint + Prettier" },
109
+ ],
110
+ }));
111
+ }
112
+ // 6. Libs adicionais (sΓ³ pergunta se nΓ£o foi passado)
113
+ if (!config.additionalLibs || config.additionalLibs.length === 0) {
114
+ config.additionalLibs = (await multiselect({
115
+ message: "πŸ“š Libs adicionais (pode selecionar mais de uma):",
116
+ options: [
117
+ { value: "nuqs", label: "nuqs" },
118
+ { value: "tanstack-query", label: "tanstack query" },
119
+ { value: "date-fns", label: "date-fns" },
120
+ { value: "zod", label: "zod" },
121
+ {
122
+ value: "react-hook-form",
123
+ label: "react hook form + @hookform/resolvers",
124
+ },
125
+ { value: "cookies-next", label: "cookies-next" },
126
+ { value: "framer-motion", label: "framer-motion" },
127
+ { value: "lucide-react", label: "lucide-react" },
128
+ { value: "recharts", label: "recharts" },
129
+ ],
130
+ required: false,
131
+ }));
132
+ }
133
+ // 7. shadcn/ui (sΓ³ pergunta se nΓ£o foi passado via flag)
134
+ if (config.withShadcn === undefined) {
135
+ const useShadcn = (await select({
136
+ message: "🎨 Deseja usar shadcn/ui?",
137
+ options: [
138
+ { value: true, label: "Sim, configurar shadcn/ui" },
139
+ { value: false, label: "NΓ£o" },
140
+ ],
141
+ }));
142
+ config.withShadcn = useShadcn;
143
+ }
144
+ // 7.1. Cor do shadcn (sΓ³ pergunta se withShadcn = true e nΓ£o foi passado)
145
+ if (config.withShadcn && !config.shadcnColor) {
146
+ config.shadcnColor = (await select({
147
+ message: "🎨 Qual cor base deseja usar no shadcn/ui?",
148
+ options: [
149
+ { value: "neutral", label: "Neutral (cinza neutro)" },
150
+ { value: "slate", label: "Slate (cinza azulado)" },
151
+ { value: "gray", label: "Gray (cinza mΓ©dio)" },
152
+ { value: "zinc", label: "Zinc (cinza metΓ‘lico)" },
153
+ { value: "stone", label: "Stone (cinza terroso)" },
154
+ ],
155
+ }));
156
+ }
157
+ // 7.2. Componentes shadcn (sΓ³ pergunta se withShadcn = true e nΓ£o foram passados)
158
+ if (config.withShadcn &&
159
+ (!config.shadcnComponents || config.shadcnComponents.length === 0)) {
160
+ config.shadcnComponents = (await multiselect({
161
+ message: "🧩 Quais componentes do shadcn/ui deseja adicionar?",
162
+ options: [
163
+ { value: "button", label: "button" },
164
+ { value: "input", label: "input" },
165
+ { value: "card", label: "card" },
166
+ { value: "dialog", label: "dialog" },
167
+ { value: "dropdown-menu", label: "dropdown-menu" },
168
+ { value: "label", label: "label" },
169
+ { value: "select", label: "select" },
170
+ { value: "textarea", label: "textarea" },
171
+ { value: "toast", label: "toast" },
172
+ { value: "form", label: "form" },
173
+ { value: "table", label: "table" },
174
+ { value: "tabs", label: "tabs" },
175
+ ],
176
+ required: false,
177
+ }));
178
+ }
179
+ }
180
+ // 8. Instalar dependΓͺncias automaticamente (sΓ³ pergunta se nΓ£o foi passado)
181
+ if (config.shouldInstallDeps === undefined) {
182
+ const shouldInstall = (await select({
183
+ message: "πŸ“¦ Deseja instalar as dependΓͺncias automaticamente?",
184
+ options: [
185
+ { value: true, label: "Sim, instalar agora" },
186
+ { value: false, label: "NΓ£o, vou instalar depois" },
187
+ ],
188
+ }));
189
+ config.shouldInstallDeps = shouldInstall;
190
+ }
191
+ // 9. Setup Git e Deploy (sΓ³ pergunta se nΓ£o foi passado)
192
+ if (config.gitSetup === undefined) {
193
+ // Verificar quais CLIs estΓ£o disponΓ­veis
194
+ const hasGitHubCLI = await GitSetup.isGitHubCLIAvailable();
195
+ const hasVercelCLI = await GitSetup.isVercelCLIAvailable();
196
+ // Se nΓ£o tem nenhuma CLI, pular essa etapa
197
+ if (!hasGitHubCLI) {
198
+ console.log("\nπŸ’‘ GitHub CLI (gh) nΓ£o encontrado ou nΓ£o autenticado.");
199
+ console.log(" Para habilitar criaΓ§Γ£o automΓ‘tica de repos, instale: https://cli.github.com/\n");
200
+ config.gitSetup = "none";
201
+ }
202
+ else {
203
+ // Mostrar aviso se nΓ£o tiver Vercel CLI (para projetos frontend)
204
+ if (!hasVercelCLI && config.applicationType === "frontend") {
205
+ console.log("\nπŸ’‘ Vercel CLI nΓ£o encontrado. Deploy automΓ‘tico nΓ£o estarΓ‘ disponΓ­vel.");
206
+ console.log(" Para habilitar: npm i -g vercel && vercel login\n");
207
+ }
208
+ // Montar opΓ§Γ΅es baseado nas CLIs disponΓ­veis
209
+ const options = [];
210
+ // OpΓ§Γ£o de repo + deploy (sΓ³ se tiver ambas CLIs e for frontend)
211
+ if (hasGitHubCLI &&
212
+ hasVercelCLI &&
213
+ config.applicationType === "frontend") {
214
+ options.push({
215
+ value: "repo-and-deploy",
216
+ label: "Criar repositΓ³rio no GitHub e configurar deploy na Vercel",
217
+ hint: "Recomendado para projetos frontend",
218
+ });
219
+ }
220
+ // OpΓ§Γ£o de apenas repo (sempre disponΓ­vel se tiver gh CLI)
221
+ if (hasGitHubCLI) {
222
+ options.push({
223
+ value: "repo-only",
224
+ label: "Apenas criar repositΓ³rio no GitHub",
225
+ hint: "Sem configuraΓ§Γ£o de deploy",
226
+ });
227
+ }
228
+ // OpΓ§Γ£o de nΓ£o configurar (sempre disponΓ­vel)
229
+ options.push({
230
+ value: "none",
231
+ label: "NΓ£o configurar agora",
232
+ hint: "VocΓͺ pode configurar manualmente depois",
233
+ });
234
+ const setupOption = (await select({
235
+ message: "πŸš€ Deseja configurar repositΓ³rio Git e deploy?",
236
+ options,
237
+ }));
238
+ config.gitSetup = setupOption;
239
+ }
240
+ // 9.1. Se escolheu criar repo, perguntar detalhes
241
+ if (config.gitSetup !== "none") {
242
+ // Nome do repositΓ³rio
243
+ if (!config.repoName) {
244
+ const repoName = (await text({
245
+ message: "πŸ“ Qual o nome do repositΓ³rio?",
246
+ placeholder: config.projectName,
247
+ initialValue: config.projectName,
248
+ validate: (value) => {
249
+ if (!value)
250
+ return "O nome do repositΓ³rio Γ© obrigatΓ³rio";
251
+ if (!/^[a-zA-Z0-9._-]+$/.test(value)) {
252
+ return "Use apenas letras, nΓΊmeros, pontos, hΓ­fens e underscores";
253
+ }
254
+ },
255
+ }));
256
+ if (isCancel(repoName)) {
257
+ outro("❌ Operação cancelada");
258
+ process.exit(0);
259
+ }
260
+ config.repoName = repoName;
261
+ }
262
+ // OrganizaΓ§Γ£o (se nΓ£o foi passado via flag)
263
+ if (!config.repoOrg) {
264
+ const repoLocation = (await select({
265
+ message: "πŸ“ Onde deseja criar o repositΓ³rio?",
266
+ options: [
267
+ {
268
+ value: "personal",
269
+ label: "Meu perfil pessoal",
270
+ hint: "github.com/seu-usuario",
271
+ },
272
+ {
273
+ value: "organization",
274
+ label: "Em uma organizaΓ§Γ£o",
275
+ hint: "github.com/org-name",
276
+ },
277
+ ],
278
+ }));
279
+ if (repoLocation === "organization") {
280
+ // Buscar organizaΓ§Γ΅es do usuΓ‘rio
281
+ console.log("\nπŸ” Buscando suas organizaΓ§Γ΅es...");
282
+ const orgs = await GitSetup.getGitHubOrganizations();
283
+ if (orgs.length === 0) {
284
+ console.log("⚠️ Nenhuma organização encontrada ou GitHub CLI não autenticado.");
285
+ console.log("πŸ’‘ Criando no perfil pessoal...\n");
286
+ }
287
+ else {
288
+ const selectedOrg = (await select({
289
+ message: "🏒 Selecione a organização:",
290
+ options: orgs.map((org) => ({
291
+ value: org,
292
+ label: org,
293
+ })),
294
+ }));
295
+ if (isCancel(selectedOrg)) {
296
+ outro("❌ Operação cancelada");
297
+ process.exit(0);
298
+ }
299
+ config.repoOrg = selectedOrg;
300
+ }
301
+ }
302
+ }
303
+ // Visibilidade do repositΓ³rio
304
+ if (!config.repoVisibility) {
305
+ config.repoVisibility = (await select({
306
+ message: "πŸ”’ Qual a visibilidade do repositΓ³rio?",
307
+ options: [
308
+ {
309
+ value: "public",
310
+ label: "PΓΊblico",
311
+ hint: "Qualquer pessoa pode ver",
312
+ },
313
+ {
314
+ value: "private",
315
+ label: "Privado",
316
+ hint: "Apenas vocΓͺ e colaboradores",
317
+ },
318
+ ],
319
+ }));
320
+ }
321
+ }
322
+ }
323
+ return config;
324
+ }
325
+ async function generateProject(config) {
326
+ const generator = new ProjectGenerator();
327
+ try {
328
+ // Verificar se o diretΓ³rio jΓ‘ existe
329
+ try {
330
+ await access(config.projectPath);
331
+ console.error("\n❌ Erro: O diretório jÑ existe!");
332
+ console.error(` Caminho: ${config.projectPath}`);
333
+ console.error("\nπŸ’‘ Escolha um nome diferente ou remova o diretΓ³rio existente.\n");
334
+ process.exit(1);
335
+ }
336
+ catch {
337
+ // DiretΓ³rio nΓ£o existe, podemos prosseguir
338
+ }
339
+ // Criar diretΓ³rio do projeto
340
+ await mkdir(config.projectPath, { recursive: true });
341
+ // Gerar projeto
342
+ await generator.generate(config);
343
+ // Setup Git e Deploy (se configurado)
344
+ if (config.gitSetup && config.gitSetup !== "none") {
345
+ const gitSetup = new GitSetup({
346
+ projectPath: config.projectPath,
347
+ projectName: config.projectName,
348
+ repoName: config.repoName,
349
+ repoOrg: config.repoOrg,
350
+ visibility: config.repoVisibility,
351
+ withVercel: config.gitSetup === "repo-and-deploy" &&
352
+ config.applicationType === "frontend",
353
+ });
354
+ try {
355
+ // Inicializar Git
356
+ await gitSetup.initialize();
357
+ // Criar repositΓ³rio no GitHub
358
+ const repoUrl = await gitSetup.createGitHubRepo();
359
+ console.log(`\nπŸ”— RepositΓ³rio: ${repoUrl}`);
360
+ // Configurar Vercel se necessΓ‘rio
361
+ if (config.gitSetup === "repo-and-deploy" &&
362
+ config.applicationType === "frontend") {
363
+ await gitSetup.setupVercelDeploy();
364
+ }
365
+ }
366
+ catch (error) {
367
+ console.error("\n⚠️ Aviso: Erro ao configurar Git/Deploy:");
368
+ console.error(error.message);
369
+ console.error("\nπŸ’‘ VocΓͺ pode configurar manualmente depois.");
370
+ }
371
+ }
372
+ // Sucesso!
373
+ console.log("\n");
374
+ outro("✨ Projeto criado com sucesso!");
375
+ console.log("\nπŸ“‹ PrΓ³ximos passos:\n");
376
+ console.log(` cd ${config.projectName}`);
377
+ if (!config.shouldInstallDeps) {
378
+ console.log(` ${config.packageManager} install`);
379
+ }
380
+ if (!config.gitSetup || config.gitSetup === "none") {
381
+ console.log(` git init && git add . && git commit -m "initial commit"`);
382
+ }
383
+ console.log(` ${config.packageManager} ${config.packageManager === "npm" ? "run " : ""}dev`);
384
+ console.log("");
385
+ }
386
+ catch (error) {
387
+ console.error("\n❌ Erro ao criar projeto:", error);
388
+ outro("Falha ao criar o projeto");
389
+ process.exit(1);
390
+ }
391
+ }
392
+ async function main() {
393
+ // Verificar se hΓ‘ argumentos CLI (exceto --help e --version que o commander jΓ‘ trata)
394
+ const args = process.argv.slice(2);
395
+ const hasFlags = args.length > 0 &&
396
+ !args.every((arg) => arg === "--help" || arg === "-h" || arg === "--version" || arg === "-V");
397
+ if (hasFlags) {
398
+ // Modo CLI com flags ou hΓ­brido
399
+ const options = parseArguments();
400
+ // Validar opΓ§Γ΅es antes de prosseguir
401
+ const errors = validateOptions(options);
402
+ if (errors.length > 0) {
403
+ console.error("\n");
404
+ console.error("╔═══════════════════════════════════════════════════════════╗");
405
+ console.error("β•‘ ❌ ERRO DE VALIDAÇÃO β•‘");
406
+ console.error("β•šβ•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•β•");
407
+ console.error("\n");
408
+ errors.forEach((error) => {
409
+ console.error(` ${error}`);
410
+ });
411
+ console.error("\n");
412
+ console.error("πŸ’‘ Dica: Use --help para ver as opΓ§Γ΅es disponΓ­veis");
413
+ console.error("\n");
414
+ process.exit(1);
415
+ }
416
+ // Validar disponibilidade de CLIs se Git setup foi especificado
417
+ if (options.gitSetup && options.gitSetup !== "none") {
418
+ const hasGitHubCLI = await GitSetup.isGitHubCLIAvailable();
419
+ const hasVercelCLI = await GitSetup.isVercelCLIAvailable();
420
+ if (!hasGitHubCLI) {
421
+ console.error("\n❌ Erro: GitHub CLI (gh) não encontrado ou não autenticado.");
422
+ console.error(" Instale e autentique: https://cli.github.com/");
423
+ console.error(" Ou use a CLI sem --git-setup para pular essa configuraΓ§Γ£o.\n");
424
+ process.exit(1);
425
+ }
426
+ if (options.gitSetup === "repo-and-deploy" && !hasVercelCLI) {
427
+ console.error("\n⚠️ Aviso: Vercel CLI não encontrado ou não autenticado.");
428
+ console.error(" Para deploy automΓ‘tico: npm i -g vercel && vercel login");
429
+ console.error(" Ajustando para criar apenas o repositΓ³rio...\n");
430
+ options.gitSetup = "repo-only";
431
+ }
432
+ }
433
+ console.clear();
434
+ intro("πŸš€ Bem-vindo ao Gerador de Projetos!");
435
+ // Converter options para config parcial
436
+ const partialConfig = optionsToConfig(options);
437
+ // Executar modo hΓ­brido (pergunta apenas o que falta)
438
+ const config = await runHybridMode(partialConfig);
439
+ // Exibir resumo final
440
+ console.log("\nπŸŽ‰ RESUMO DAS SUAS ESCOLHAS:\n");
441
+ console.log("═══════════════════════════════════════");
442
+ console.log(`πŸ“ Nome do Projeto: ${config.projectName}`);
443
+ console.log(`πŸ“¦ Package Manager: ${config.packageManager}`);
444
+ console.log(`πŸ—οΈ Tipo de AplicaΓ§Γ£o: ${config.applicationType}`);
445
+ if (config.applicationType === "frontend") {
446
+ console.log(`⚑ Framework: ${config.framework}`);
447
+ console.log(`🌐 Cliente HTTP: ${config.httpClient}`);
448
+ console.log(`✨ Linter: ${config.linter}`);
449
+ if (config.additionalLibs && config.additionalLibs.length > 0) {
450
+ console.log(`πŸ“š Libs Adicionais: ${config.additionalLibs.join(", ")}`);
451
+ }
452
+ else {
453
+ console.log("πŸ“š Libs Adicionais: Nenhuma selecionada");
454
+ }
455
+ if (config.withShadcn) {
456
+ if (config.shadcnComponents && config.shadcnComponents.length > 0) {
457
+ console.log(`🎨 shadcn/ui: Sim (${config.shadcnColor || "neutral"}, ${config.shadcnComponents.length} componente(s))`);
458
+ }
459
+ else {
460
+ console.log(`🎨 shadcn/ui: Sim (${config.shadcnColor || "neutral"}, apenas init)`);
461
+ }
462
+ }
463
+ else {
464
+ console.log("🎨 shadcn/ui: Não");
465
+ }
466
+ }
467
+ // Git Setup
468
+ if (config.gitSetup && config.gitSetup !== "none") {
469
+ const setupLabel = config.gitSetup === "repo-and-deploy"
470
+ ? "Repo GitHub + Deploy Vercel"
471
+ : "Apenas Repo GitHub";
472
+ const repoFullName = config.repoOrg
473
+ ? `${config.repoOrg}/${config.repoName}`
474
+ : config.repoName;
475
+ console.log(`πŸš€ Git Setup: ${setupLabel}`);
476
+ console.log(`πŸ“¦ RepositΓ³rio: ${repoFullName} (${config.repoVisibility})`);
477
+ }
478
+ else {
479
+ console.log("πŸš€ Git Setup: NΓ£o configurado");
480
+ }
481
+ console.log("═══════════════════════════════════════\n");
482
+ await generateProject(config);
483
+ }
484
+ else {
485
+ // Modo interativo puro
486
+ console.clear();
487
+ intro("πŸš€ Bem-vindo ao Gerador de Projetos!");
488
+ const config = await runHybridMode({});
489
+ // Exibir resumo final
490
+ console.log("\nπŸŽ‰ RESUMO DAS SUAS ESCOLHAS:\n");
491
+ console.log("═══════════════════════════════════════");
492
+ console.log(`πŸ“ Nome do Projeto: ${config.projectName}`);
493
+ console.log(`πŸ“¦ Package Manager: ${config.packageManager}`);
494
+ console.log(`πŸ—οΈ Tipo de AplicaΓ§Γ£o: ${config.applicationType}`);
495
+ if (config.applicationType === "frontend") {
496
+ console.log(`⚑ Framework: ${config.framework}`);
497
+ console.log(`🌐 Cliente HTTP: ${config.httpClient}`);
498
+ console.log(`✨ Linter: ${config.linter}`);
499
+ if (config.additionalLibs && config.additionalLibs.length > 0) {
500
+ console.log(`πŸ“š Libs Adicionais: ${config.additionalLibs.join(", ")}`);
501
+ }
502
+ else {
503
+ console.log("πŸ“š Libs Adicionais: Nenhuma selecionada");
504
+ }
505
+ if (config.withShadcn) {
506
+ if (config.shadcnComponents && config.shadcnComponents.length > 0) {
507
+ console.log(`🎨 shadcn/ui: Sim (${config.shadcnColor || "neutral"}, ${config.shadcnComponents.length} componente(s))`);
508
+ }
509
+ else {
510
+ console.log(`🎨 shadcn/ui: Sim (${config.shadcnColor || "neutral"}, apenas init)`);
511
+ }
512
+ }
513
+ else {
514
+ console.log("🎨 shadcn/ui: Não");
515
+ }
516
+ }
517
+ // Git Setup
518
+ if (config.gitSetup && config.gitSetup !== "none") {
519
+ const setupLabel = config.gitSetup === "repo-and-deploy"
520
+ ? "Repo GitHub + Deploy Vercel"
521
+ : "Apenas Repo GitHub";
522
+ const repoFullName = config.repoOrg
523
+ ? `${config.repoOrg}/${config.repoName}`
524
+ : config.repoName;
525
+ console.log(`πŸš€ Git Setup: ${setupLabel}`);
526
+ console.log(`πŸ“¦ RepositΓ³rio: ${repoFullName} (${config.repoVisibility})`);
527
+ }
528
+ else {
529
+ console.log("πŸš€ Git Setup: NΓ£o configurado");
530
+ }
531
+ console.log("═══════════════════════════════════════\n");
532
+ // Gerar o projeto
533
+ console.log("");
534
+ await generateProject(config);
535
+ }
536
+ }
537
+ main().catch(console.error);
@@ -0,0 +1,15 @@
1
+ import type { ProjectConfig } from "./types.js";
2
+ export declare class ProjectGenerator {
3
+ private snippetManager;
4
+ private rootPath;
5
+ constructor(rootPath?: string);
6
+ generate(config: ProjectConfig): Promise<void>;
7
+ private copyTemplate;
8
+ private getTemplatePath;
9
+ private processSnippets;
10
+ private updatePackageJson;
11
+ private createEnvFile;
12
+ private installDependencies;
13
+ private setupShadcn;
14
+ private createVscodeConfig;
15
+ }