@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/README.md ADDED
@@ -0,0 +1,159 @@
1
+ # @perma-tools/cli
2
+
3
+ šŸš€ CLI moderna e interativa para geração rĆ”pida de projetos frontend e backend com configuraƧƵes personalizadas.
4
+
5
+ ## šŸ“¦ Instalação
6
+
7
+ ### Uso com npx (Recomendado - sem instalação)
8
+
9
+ ```bash
10
+ npx @perma-tools/cli@latest
11
+ ```
12
+
13
+ ### Instalação Global
14
+
15
+ ```bash
16
+ npm install -g @perma-tools/cli
17
+ # ou
18
+ pnpm add -g @perma-tools/cli
19
+ # ou
20
+ yarn global add @perma-tools/cli
21
+ ```
22
+
23
+ ## šŸš€ Uso RĆ”pido
24
+
25
+ ### Modo Interativo
26
+
27
+ ```bash
28
+ npx @perma-tools/cli@latest
29
+ ```
30
+
31
+ A CLI irƔ guiƔ-lo atravƩs de perguntas interativas para configurar seu projeto.
32
+
33
+ ### Modo CLI com Flags
34
+
35
+ ```bash
36
+ npx @perma-tools/cli@latest \
37
+ --name meu-app \
38
+ --type frontend \
39
+ --framework nextjs-15 \
40
+ --http-client ky \
41
+ --linter biome \
42
+ --libs tanstack-query,zod,react-hook-form \
43
+ --with-shadcn \
44
+ --shadcn-color slate \
45
+ --install
46
+ ```
47
+
48
+ ## ✨ Características
49
+
50
+ - āœ… Suporte completo para **Frontend** (NextJS 15) e **Backend** (em desenvolvimento)
51
+ - āœ… Escolha entre **ky**, **axios** ou **fetch** nativo como cliente HTTP
52
+ - āœ… Configuração automĆ”tica de **Biome** ou **ESLint + Prettier**
53
+ - āœ… Instalação e configuração de bibliotecas populares com **versƵes especĆ­ficas testadas**
54
+ - āœ… Integração completa com **shadcn/ui**
55
+ - āœ… Sistema de **providers** com injeção automĆ”tica robusta
56
+ - āœ… **Criação automĆ”tica de repositório no GitHub** com GitHub CLI
57
+ - āœ… **Deploy automĆ”tico na Vercel** para projetos frontend
58
+ - āœ… Instalação automĆ”tica de dependĆŖncias
59
+ - āœ… Validação completa de nomes de projetos (seguindo regras do npm)
60
+ - āœ… Verificação de projetos existentes para evitar sobrescritas
61
+ - āœ… Compatibilidade total com Windows, Linux e macOS
62
+
63
+ ## šŸš€ Git & Deploy AutomĆ”tico
64
+
65
+ A CLI oferece configuração automÔtica de repositório e deploy, adaptando-se automaticamente às ferramentas disponíveis no seu sistema:
66
+
67
+ ### PrƩ-requisitos
68
+
69
+ - **GitHub CLI** (`gh`): [Instalar e autenticar](https://cli.github.com/)
70
+ - **Obrigatório** para criação de repositórios
71
+ - Se não estiver instalado, a opção de Git setup serÔ ocultada
72
+ - **Vercel CLI** (opcional): `npm i -g vercel && vercel login`
73
+ - **NecessƔrio** apenas para deploy automƔtico
74
+ - Se não estiver instalado, apenas a opção "criar repo" serÔ mostrada
75
+
76
+ ### Detecção AutomÔtica de Ferramentas
77
+
78
+ A CLI detecta automaticamente quais ferramentas estão instaladas e **ajusta as opções disponíveis**:
79
+
80
+ | GitHub CLI | Vercel CLI | OpƧƵes Mostradas |
81
+ |------------|------------|------------------|
82
+ | āœ… Instalado | āœ… Instalado | Repo + Deploy, Repo only, Nenhum |
83
+ | āœ… Instalado | āŒ NĆ£o instalado | Repo only, Nenhum |
84
+ | āŒ NĆ£o instalado | āœ…/āŒ Qualquer | Nenhum (pula essa etapa) |
85
+
86
+ **Comportamento inteligente:**
87
+ - Se você **não tem GitHub CLI**, a CLI pula completamente a configuração de Git
88
+ - Se você **só tem GitHub CLI**, mostra apenas a opção de criar repositório
89
+ - Se você **tem ambas** e é um projeto **frontend**, mostra todas as opções
90
+
91
+ ### OpƧƵes Disponƭveis
92
+
93
+ 1. **Criar repo e deploy na Vercel**: Cria repositório no GitHub e configura deploy automÔtico (frontend apenas, requer ambas CLIs)
94
+ 2. **Apenas criar repo**: Cria repositório no GitHub sem deploy (requer apenas GitHub CLI)
95
+ 3. **Não configurar agora**: Pula a configuração (pode fazer manualmente depois)
96
+
97
+ ### Criação em Organizações
98
+
99
+ A CLI detecta automaticamente suas organizações do GitHub e permite escolher onde criar o repositório:
100
+
101
+ - **Perfil Pessoal**: `github.com/seu-usuario/repo`
102
+ - **Organização**: `github.com/sua-org/repo`
103
+
104
+ Se você tiver acesso a múltiplas organizações, poderÔ selecionÔ-las interativamente.
105
+
106
+ ### Como Funciona
107
+
108
+ Após criar o projeto, a CLI:
109
+ - šŸ”§ Inicializa o repositório Git local
110
+ - šŸ“ Pergunta onde criar (perfil pessoal ou organização)
111
+ - šŸ¢ Lista suas organizaƧƵes do GitHub (se aplicĆ”vel)
112
+ - šŸ“¦ Cria repositório no GitHub (pĆŗblico ou privado)
113
+ - šŸš€ Faz push do código inicial
114
+ - ā³ Aguarda o GitHub processar o repositório (3 segundos)
115
+ - ⚔ Configura deploy na Vercel (se selecionado)
116
+
117
+ ```bash
118
+ # A CLI faz tudo isso automaticamente:
119
+ git init
120
+ git add .
121
+ git commit -m "chore: initial commit from @perma-tools/cli"
122
+ gh repo create my-org/my-repo --public --source . --push # Com org
123
+ # ou
124
+ gh repo create my-repo --public --source . --push # Perfil pessoal
125
+ vercel --prod --yes # Se deploy estiver habilitado
126
+ ```
127
+
128
+ ## šŸ—ļø Estrutura do Projeto Gerado
129
+
130
+ ### Providers e Client Components
131
+
132
+ Quando vocĆŖ seleciona bibliotecas que usam Context API (TanStack Query, nuqs, etc.), a CLI:
133
+
134
+ 1. Cria um arquivo `src/app/providers.tsx` com a diretiva `'use client'`
135
+ 2. Injeta automaticamente os providers necessƔrios
136
+ 3. MantƩm a estrutura aninhada corretamente
137
+
138
+ ```tsx
139
+ 'use client';
140
+
141
+ export function Providers({ children }: { children: React.ReactNode }) {
142
+ return (
143
+ <>
144
+ <QueryClientProvider>
145
+ <NuqsAdapter>
146
+ {children}
147
+ </NuqsAdapter>
148
+ </QueryClientProvider>
149
+ </>
150
+ );
151
+ }
152
+ ```
153
+
154
+ **Por que 'use client'?**
155
+ Providers que usam hooks do React (useState, useContext, etc.) precisam ser Client Components no Next.js 15.
156
+
157
+ ## šŸ“„ LicenƧa
158
+
159
+ MIT
@@ -0,0 +1,12 @@
1
+ import type { SnippetAction } from "./types.js";
2
+ export declare class ActionExecutor {
3
+ private projectPath;
4
+ private rootPath;
5
+ private packageManager;
6
+ constructor(projectPath: string, rootPath?: string, packageManager?: string);
7
+ execute(action: SnippetAction): Promise<void>;
8
+ private executeCopyFile;
9
+ private executeInjectProvider;
10
+ private executeInstallDeps;
11
+ private executeRunCommand;
12
+ }
@@ -0,0 +1,157 @@
1
+ import { spawn } from "node:child_process";
2
+ import { copyFile, mkdir, readFile, writeFile } from "node:fs/promises";
3
+ import { dirname, join } from "node:path";
4
+ export class ActionExecutor {
5
+ projectPath;
6
+ rootPath;
7
+ packageManager;
8
+ constructor(projectPath, rootPath = process.cwd(), packageManager = "pnpm") {
9
+ this.projectPath = projectPath;
10
+ this.rootPath = rootPath;
11
+ this.packageManager = packageManager;
12
+ }
13
+ async execute(action) {
14
+ switch (action.type) {
15
+ case "copy-file":
16
+ await this.executeCopyFile(action);
17
+ break;
18
+ case "inject-provider":
19
+ await this.executeInjectProvider(action);
20
+ break;
21
+ case "modify-file":
22
+ // TODO: implementar
23
+ break;
24
+ case "install-deps":
25
+ await this.executeInstallDeps(action);
26
+ break;
27
+ case "run-command":
28
+ await this.executeRunCommand(action);
29
+ break;
30
+ }
31
+ }
32
+ async executeCopyFile(action) {
33
+ const sourcePath = join(this.rootPath, action.source);
34
+ const destPath = join(this.projectPath, action.destination);
35
+ // Criar diretório de destino se não existir
36
+ await mkdir(dirname(destPath), { recursive: true });
37
+ // Copiar arquivo
38
+ await copyFile(sourcePath, destPath);
39
+ console.log(`āœ… Arquivo copiado: ${action.destination}`);
40
+ }
41
+ async executeInjectProvider(action) {
42
+ const providersPath = join(this.projectPath, "src/app/providers.tsx");
43
+ try {
44
+ let content = await readFile(providersPath, "utf-8");
45
+ // 1. Adicionar import no topo do arquivo
46
+ if (!content.includes(action.providerImport)) {
47
+ // Encontrar a posição após o último import ou após 'use client'
48
+ const lines = content.split("\n");
49
+ let lastImportIndex = -1;
50
+ let useClientIndex = -1;
51
+ for (let i = 0; i < lines.length; i++) {
52
+ const line = lines[i].trim();
53
+ // Detectar 'use client'
54
+ if (line === "'use client';" || line === '"use client";') {
55
+ useClientIndex = i;
56
+ }
57
+ // Detectar imports
58
+ if (line.startsWith("import ") || line.startsWith("import{")) {
59
+ lastImportIndex = i;
60
+ }
61
+ }
62
+ if (lastImportIndex >= 0) {
63
+ // Inserir após o último import
64
+ lines.splice(lastImportIndex + 1, 0, action.providerImport);
65
+ }
66
+ else if (useClientIndex >= 0) {
67
+ // Se não hÔ imports mas tem 'use client', inserir após linha vazia
68
+ let insertIndex = useClientIndex + 1;
69
+ // Pular linhas vazias após 'use client'
70
+ while (insertIndex < lines.length &&
71
+ lines[insertIndex].trim() === "") {
72
+ insertIndex++;
73
+ }
74
+ lines.splice(insertIndex, 0, action.providerImport);
75
+ }
76
+ else {
77
+ // Inserir no início se não hÔ nem imports nem 'use client'
78
+ lines.unshift(action.providerImport);
79
+ }
80
+ content = lines.join("\n");
81
+ }
82
+ // 2. Envolver o children com o provider
83
+ // Verificar se jĆ” tem este provider
84
+ if (content.includes(`<${action.providerWrapper}`)) {
85
+ console.log(`āš ļø Provider ${action.providerWrapper} jĆ” existe, pulando...`);
86
+ return;
87
+ }
88
+ // Estratégia simples: encontrar {children} com sua indentação e wrappear
89
+ if (!content.includes("{children}")) {
90
+ throw new Error("NĆ£o foi possĆ­vel encontrar '{children}' no arquivo");
91
+ }
92
+ // Captura a linha inteira com {children}, incluindo indentação
93
+ const childrenLineRegex = /^(\s*)(\{children\})$/m;
94
+ const match = content.match(childrenLineRegex);
95
+ if (!match) {
96
+ throw new Error("Não foi possível encontrar {children} em sua própria linha");
97
+ }
98
+ const indent = match[1]; // indentação atual de {children}
99
+ // Substituir {children} com provider ao redor, mantendo indentação consistente
100
+ content = content.replace(childrenLineRegex, `${indent}<${action.providerWrapper}>\n${indent} {children}\n${indent}</${action.providerWrapper}>`);
101
+ await writeFile(providersPath, content, "utf-8");
102
+ console.log(`āœ… Provider injetado: ${action.providerWrapper}`);
103
+ }
104
+ catch (error) {
105
+ console.error(`āŒ Erro ao injetar provider ${action.providerWrapper}:`, error);
106
+ console.error(`šŸ’” VocĆŖ pode precisar adicionar manualmente o provider ${action.providerWrapper}`);
107
+ // NĆ£o fazer throw - continuar mesmo se falhar
108
+ }
109
+ }
110
+ async executeInstallDeps(action) {
111
+ console.log(`\nšŸ“¦ Instalando dependĆŖncias com ${this.packageManager}...`);
112
+ return new Promise((resolve, reject) => {
113
+ const command = this.packageManager;
114
+ const args = ["install"];
115
+ const child = spawn(command, args, {
116
+ cwd: this.projectPath,
117
+ stdio: "inherit",
118
+ shell: true,
119
+ });
120
+ child.on("close", (code) => {
121
+ if (code === 0) {
122
+ console.log(`āœ… DependĆŖncias instaladas com sucesso!`);
123
+ resolve();
124
+ }
125
+ else {
126
+ reject(new Error(`Erro ao instalar dependências (código ${code})`));
127
+ }
128
+ });
129
+ child.on("error", (error) => {
130
+ reject(error);
131
+ });
132
+ });
133
+ }
134
+ async executeRunCommand(action) {
135
+ console.log(`\nāš™ļø Executando: ${action.command} ${action.args?.join(" ") || ""}...`);
136
+ return new Promise((resolve, reject) => {
137
+ const args = action.args || [];
138
+ const child = spawn(action.command, args, {
139
+ cwd: this.projectPath,
140
+ stdio: "inherit",
141
+ shell: true,
142
+ });
143
+ child.on("close", (code) => {
144
+ if (code === 0) {
145
+ console.log(`āœ… Comando executado com sucesso!`);
146
+ resolve();
147
+ }
148
+ else {
149
+ reject(new Error(`Erro ao executar comando (código ${code})`));
150
+ }
151
+ });
152
+ child.on("error", (error) => {
153
+ reject(error);
154
+ });
155
+ });
156
+ }
157
+ }
@@ -0,0 +1,21 @@
1
+ import type { ProjectConfig } from "./types.js";
2
+ export interface CLIOptions {
3
+ name?: string;
4
+ packageManager?: "pnpm" | "yarn" | "npm";
5
+ type?: "frontend" | "backend";
6
+ framework?: "nextjs-15" | "vitejs-6";
7
+ httpClient?: "ky" | "axios" | "fetch";
8
+ linter?: "biome" | "eslint-prettier";
9
+ libs?: string;
10
+ install?: boolean;
11
+ withShadcn?: boolean;
12
+ shadcnColor?: "neutral" | "slate" | "gray" | "zinc" | "stone";
13
+ gitSetup?: "repo-and-deploy" | "repo-only" | "none";
14
+ repoVisibility?: "public" | "private";
15
+ repoName?: string;
16
+ repoOrg?: string;
17
+ }
18
+ export declare function parseArguments(): CLIOptions;
19
+ export declare function hasArguments(): boolean;
20
+ export declare function validateOptions(options: CLIOptions): string[];
21
+ export declare function optionsToConfig(options: CLIOptions): Partial<ProjectConfig>;
@@ -0,0 +1,141 @@
1
+ import { Command } from "commander";
2
+ import { join } from "node:path";
3
+ export function parseArguments() {
4
+ const program = new Command();
5
+ program
6
+ .name("perma-tools")
7
+ .description("CLI para geração de projetos customizados")
8
+ .version("0.0.1");
9
+ program.option("-n, --name <name>", "Nome do projeto");
10
+ program.option("--package-manager <manager>", "Package manager (pnpm, yarn, npm)");
11
+ program.option("--type <type>", "Tipo de aplicação (frontend, backend)");
12
+ program.option("--framework <framework>", "Framework (nextjs-15, vitejs-6)");
13
+ program.option("--http-client <client>", "Cliente HTTP (ky, axios, fetch)");
14
+ program.option("--linter <linter>", "Linter (biome, eslint-prettier)");
15
+ program.option("--libs <libs>", "Bibliotecas adicionais separadas por vĆ­rgula");
16
+ program.option("--install", "Instalar dependĆŖncias automaticamente");
17
+ program.option("--with-shadcn", "Configurar shadcn/ui com componentes selecionƔveis");
18
+ program.option("--shadcn-color <color>", "Cor base do shadcn/ui (neutral, slate, gray, zinc, stone)");
19
+ program.option("--git-setup <setup>", "Setup do Git (repo-and-deploy, repo-only, none)");
20
+ program.option("--repo-visibility <visibility>", "Visibilidade do repositório (public, private)");
21
+ program.option("--repo-name <name>", "Nome do repositório no GitHub");
22
+ program.option("--repo-org <org>", "Organização do GitHub para criar o repositório");
23
+ program.parse(process.argv);
24
+ const options = program.opts();
25
+ return options;
26
+ }
27
+ export function hasArguments() {
28
+ // Verifica se hƔ argumentos alƩm do comando base
29
+ return process.argv.length > 2;
30
+ }
31
+ export function validateOptions(options) {
32
+ const errors = [];
33
+ if (options.packageManager &&
34
+ !["pnpm", "yarn", "npm"].includes(options.packageManager)) {
35
+ errors.push("Package manager deve ser: pnpm, yarn ou npm");
36
+ }
37
+ if (options.type && !["frontend", "backend"].includes(options.type)) {
38
+ errors.push("Tipo deve ser: frontend ou backend");
39
+ }
40
+ if (options.framework &&
41
+ !["nextjs-15", "vitejs-6"].includes(options.framework)) {
42
+ errors.push("Framework deve ser: nextjs-15 ou vitejs-6");
43
+ }
44
+ // Validar se ViteJS foi selecionado (ainda não disponível)
45
+ if (options.framework === "vitejs-6") {
46
+ errors.push("āŒ ViteJS ainda nĆ£o estĆ” disponĆ­vel. Use nextjs-15 ou aguarde a próxima versĆ£o.");
47
+ }
48
+ if (options.httpClient &&
49
+ !["ky", "axios", "fetch"].includes(options.httpClient)) {
50
+ errors.push("HTTP Client deve ser: ky, axios ou fetch");
51
+ }
52
+ if (options.linter &&
53
+ !["biome", "eslint-prettier"].includes(options.linter)) {
54
+ errors.push("Linter deve ser: biome ou eslint-prettier");
55
+ }
56
+ if (options.shadcnColor &&
57
+ !["neutral", "slate", "gray", "zinc", "stone"].includes(options.shadcnColor)) {
58
+ errors.push("Cor do shadcn deve ser: neutral, slate, gray, zinc ou stone");
59
+ }
60
+ if (options.gitSetup &&
61
+ !["repo-and-deploy", "repo-only", "none"].includes(options.gitSetup)) {
62
+ errors.push("Git setup deve ser: repo-and-deploy, repo-only ou none");
63
+ }
64
+ if (options.repoVisibility &&
65
+ !["public", "private"].includes(options.repoVisibility)) {
66
+ errors.push("Visibilidade do repositório deve ser: public ou private");
67
+ }
68
+ // Validar conflito entre framework e tipo de aplicação
69
+ if (options.framework && options.type) {
70
+ const frontendFrameworks = ["nextjs-15", "vitejs-6"];
71
+ const backendFrameworks = ["nestjs", "honojs", "express", "fastify"];
72
+ const isFrontendFramework = frontendFrameworks.includes(options.framework);
73
+ const isBackendFramework = backendFrameworks.includes(options.framework);
74
+ if (isFrontendFramework && options.type === "backend") {
75
+ errors.push(`āŒ Conflito: ${options.framework} Ć© um framework de FRONTEND, mas vocĆŖ especificou tipo BACKEND`);
76
+ }
77
+ if (isBackendFramework && options.type === "frontend") {
78
+ errors.push(`āŒ Conflito: ${options.framework} Ć© um framework de BACKEND, mas vocĆŖ especificou tipo FRONTEND`);
79
+ }
80
+ }
81
+ return errors;
82
+ }
83
+ export function optionsToConfig(options) {
84
+ const config = {};
85
+ if (options.name) {
86
+ config.projectName = options.name;
87
+ config.projectPath = join(process.cwd(), options.name);
88
+ }
89
+ if (options.packageManager) {
90
+ config.packageManager = options.packageManager;
91
+ }
92
+ // Inferir tipo de aplicação baseado no framework se não foi explicitamente passado
93
+ if (options.framework && !options.type) {
94
+ const frontendFrameworks = ["nextjs-15", "vitejs-6"];
95
+ const backendFrameworks = ["nestjs", "honojs", "express", "fastify"]; // preparado para futuros backends
96
+ if (frontendFrameworks.includes(options.framework)) {
97
+ config.applicationType = "frontend";
98
+ }
99
+ else if (backendFrameworks.includes(options.framework)) {
100
+ config.applicationType = "backend";
101
+ }
102
+ }
103
+ // Se o tipo foi explicitamente passado, usa ele (tem prioridade sobre inferĆŖncia)
104
+ if (options.type) {
105
+ config.applicationType = options.type;
106
+ }
107
+ if (options.framework) {
108
+ config.framework = options.framework;
109
+ }
110
+ if (options.httpClient) {
111
+ config.httpClient = options.httpClient;
112
+ }
113
+ if (options.linter) {
114
+ config.linter = options.linter;
115
+ }
116
+ if (options.libs) {
117
+ config.additionalLibs = options.libs.split(",").map((lib) => lib.trim());
118
+ }
119
+ if (options.install !== undefined) {
120
+ config.shouldInstallDeps = options.install;
121
+ }
122
+ if (options.withShadcn !== undefined) {
123
+ config.withShadcn = options.withShadcn;
124
+ }
125
+ if (options.shadcnColor) {
126
+ config.shadcnColor = options.shadcnColor;
127
+ }
128
+ if (options.gitSetup) {
129
+ config.gitSetup = options.gitSetup;
130
+ }
131
+ if (options.repoVisibility) {
132
+ config.repoVisibility = options.repoVisibility;
133
+ }
134
+ if (options.repoName) {
135
+ config.repoName = options.repoName;
136
+ }
137
+ if (options.repoOrg) {
138
+ config.repoOrg = options.repoOrg;
139
+ }
140
+ return config;
141
+ }
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const axiosConfig: SnippetConfig;
@@ -0,0 +1,12 @@
1
+ export const axiosConfig = {
2
+ name: "axios",
3
+ dependencies: ["axios"],
4
+ actions: [
5
+ {
6
+ type: "copy-file",
7
+ source: "snippets/axios/index.ts",
8
+ destination: "src/lib/axios.ts",
9
+ priority: 1,
10
+ },
11
+ ],
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const biomeConfig: SnippetConfig;
@@ -0,0 +1,12 @@
1
+ export const biomeConfig = {
2
+ name: "biome",
3
+ devDependencies: ["@biomejs/biome"],
4
+ actions: [
5
+ {
6
+ type: "copy-file",
7
+ source: "snippets/biome/biome.json",
8
+ destination: "biome.json",
9
+ priority: 1,
10
+ },
11
+ ],
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const cookiesNextConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const cookiesNextConfig = {
2
+ name: "cookies-next",
3
+ dependencies: ["cookies-next"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const dateFnsConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const dateFnsConfig = {
2
+ name: "date-fns",
3
+ dependencies: ["date-fns"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const eslintPrettierConfig: SnippetConfig;
@@ -0,0 +1,35 @@
1
+ export const eslintPrettierConfig = {
2
+ name: "eslint-prettier",
3
+ devDependencies: [
4
+ "eslint",
5
+ "eslint-config-next",
6
+ "prettier",
7
+ "prettier-plugin-tailwindcss",
8
+ ],
9
+ actions: [
10
+ {
11
+ type: "copy-file",
12
+ source: "snippets/eslint-prettier/eslintrc.js",
13
+ destination: ".eslintrc.js",
14
+ priority: 1,
15
+ },
16
+ {
17
+ type: "copy-file",
18
+ source: "snippets/eslint-prettier/eslintignore",
19
+ destination: ".eslintignore",
20
+ priority: 1,
21
+ },
22
+ {
23
+ type: "copy-file",
24
+ source: "snippets/eslint-prettier/prettierrc.js",
25
+ destination: ".prettierrc.js",
26
+ priority: 1,
27
+ },
28
+ {
29
+ type: "copy-file",
30
+ source: "snippets/eslint-prettier/prettierignore",
31
+ destination: ".prettierignore",
32
+ priority: 1,
33
+ },
34
+ ],
35
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const framerMotionConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const framerMotionConfig = {
2
+ name: "framer-motion",
3
+ dependencies: ["framer-motion"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const kyConfig: SnippetConfig;
@@ -0,0 +1,12 @@
1
+ export const kyConfig = {
2
+ name: "ky",
3
+ dependencies: ["ky"],
4
+ actions: [
5
+ {
6
+ type: "copy-file",
7
+ source: "snippets/ky/index.ts",
8
+ destination: "src/lib/ky.ts",
9
+ priority: 1,
10
+ },
11
+ ],
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const lucideReactConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const lucideReactConfig = {
2
+ name: "lucide-react",
3
+ dependencies: ["lucide-react"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const nuqsConfig: SnippetConfig;
@@ -0,0 +1,12 @@
1
+ export const nuqsConfig = {
2
+ name: "nuqs",
3
+ dependencies: ["nuqs"],
4
+ actions: [
5
+ {
6
+ type: "inject-provider",
7
+ providerImport: `import { NuqsAdapter } from 'nuqs/adapters/next/app';`,
8
+ providerWrapper: "NuqsAdapter",
9
+ priority: 1,
10
+ },
11
+ ],
12
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const reactHookFormConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const reactHookFormConfig = {
2
+ name: "React Hook Form",
3
+ dependencies: ["react-hook-form", "@hookform/resolvers"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const rechartsConfig: SnippetConfig;