@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
@@ -0,0 +1,6 @@
1
+ export const rechartsConfig = {
2
+ name: "recharts",
3
+ dependencies: ["recharts"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const tanstackQueryConfig: SnippetConfig;
@@ -0,0 +1,19 @@
1
+ export const tanstackQueryConfig = {
2
+ name: "tanstack-query",
3
+ dependencies: ["@tanstack/react-query"],
4
+ devDependencies: ["@tanstack/react-query-devtools"],
5
+ actions: [
6
+ {
7
+ type: "copy-file",
8
+ source: "snippets/react-query/index.tsx",
9
+ destination: "src/lib/tanstack-query.tsx",
10
+ priority: 1,
11
+ },
12
+ {
13
+ type: "inject-provider",
14
+ providerImport: `import { QueryClientProvider } from '@/lib/tanstack-query';`,
15
+ providerWrapper: "QueryClientProvider",
16
+ priority: 2,
17
+ },
18
+ ],
19
+ };
@@ -0,0 +1,2 @@
1
+ import type { SnippetConfig } from "../types.js";
2
+ export declare const zodConfig: SnippetConfig;
@@ -0,0 +1,6 @@
1
+ export const zodConfig = {
2
+ name: "Zod",
3
+ dependencies: ["zod"],
4
+ devDependencies: [],
5
+ actions: [],
6
+ };
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Versões específicas e testadas das dependências
3
+ * Atualizado em: Fevereiro 2026
4
+ */
5
+ export declare const DEPENDENCY_VERSIONS: Record<string, string>;
6
+ /**
7
+ * Retorna a versão específica de uma dependência ou 'latest' como fallback
8
+ */
9
+ export declare function getDependencyVersion(packageName: string): string;
10
+ /**
11
+ * Retorna múltiplas versões de dependências
12
+ */
13
+ export declare function getDependencyVersions(packageNames: string[]): Record<string, string>;
@@ -0,0 +1,50 @@
1
+ /**
2
+ * Versões específicas e testadas das dependências
3
+ * Atualizado em: Fevereiro 2026
4
+ */
5
+ export const DEPENDENCY_VERSIONS = {
6
+ // HTTP Clients
7
+ ky: "^1.7.3",
8
+ axios: "^1.7.9",
9
+ // State Management & Data Fetching
10
+ "@tanstack/react-query": "^5.62.11",
11
+ "@tanstack/react-query-devtools": "^5.62.11",
12
+ nuqs: "^2.2.4",
13
+ // Form & Validation
14
+ zod: "^3.24.1",
15
+ "react-hook-form": "^7.54.2",
16
+ "@hookform/resolvers": "^3.10.0",
17
+ // Utilities
18
+ "date-fns": "^4.1.0",
19
+ "cookies-next": "^4.3.0",
20
+ // UI/UX
21
+ "framer-motion": "^11.15.0",
22
+ "lucide-react": "^0.468.0",
23
+ recharts: "^2.15.0",
24
+ // Linters & Formatters
25
+ "@biomejs/biome": "^1.9.4",
26
+ eslint: "^9",
27
+ "eslint-config-next": "^15.1.4",
28
+ prettier: "^3.4.2",
29
+ "prettier-plugin-tailwindcss": "^0.6.9",
30
+ // shadcn/ui dependencies (instaladas automaticamente pelo shadcn init)
31
+ "class-variance-authority": "^0.7.1",
32
+ clsx: "^2.1.1",
33
+ "tailwind-merge": "^2.6.0",
34
+ };
35
+ /**
36
+ * Retorna a versão específica de uma dependência ou 'latest' como fallback
37
+ */
38
+ export function getDependencyVersion(packageName) {
39
+ return DEPENDENCY_VERSIONS[packageName] || "latest";
40
+ }
41
+ /**
42
+ * Retorna múltiplas versões de dependências
43
+ */
44
+ export function getDependencyVersions(packageNames) {
45
+ const versions = {};
46
+ for (const packageName of packageNames) {
47
+ versions[packageName] = getDependencyVersion(packageName);
48
+ }
49
+ return versions;
50
+ }
@@ -0,0 +1,23 @@
1
+ interface GitSetupOptions {
2
+ projectPath: string;
3
+ projectName: string;
4
+ repoName: string;
5
+ repoOrg?: string;
6
+ visibility: "public" | "private";
7
+ withVercel?: boolean;
8
+ }
9
+ export declare class GitSetup {
10
+ private options;
11
+ constructor(options: GitSetupOptions);
12
+ initialize(): Promise<void>;
13
+ createGitHubRepo(): Promise<string>;
14
+ setupVercelDeploy(): Promise<void>;
15
+ private ensureGitignore;
16
+ private getRepoUrl;
17
+ private runCommand;
18
+ private runCommandWithOutput;
19
+ static getGitHubOrganizations(): Promise<string[]>;
20
+ static isGitHubCLIAvailable(): Promise<boolean>;
21
+ static isVercelCLIAvailable(): Promise<boolean>;
22
+ }
23
+ export {};
@@ -0,0 +1,275 @@
1
+ import { spawn } from "node:child_process";
2
+ import { rm, writeFile } from "node:fs/promises";
3
+ import { join } from "node:path";
4
+ export class GitSetup {
5
+ options;
6
+ constructor(options) {
7
+ this.options = options;
8
+ }
9
+ async initialize() {
10
+ console.log("\n🔧 Configurando Git...");
11
+ // 1. Inicializar repositório Git com branch main
12
+ await this.runCommand("git", ["init", "-b", "main"], this.options.projectPath);
13
+ // 2. Criar .gitignore se não existir
14
+ await this.ensureGitignore();
15
+ // 3. Adicionar todos os arquivos
16
+ await this.runCommand("git", ["add", "."], this.options.projectPath);
17
+ // 4. Fazer commit inicial
18
+ await this.runCommand("git", ["commit", "-m", "chore: initial commit from @perma-tools/cli"], this.options.projectPath);
19
+ console.log("✅ Git inicializado!");
20
+ }
21
+ async createGitHubRepo() {
22
+ console.log("\n📦 Criando repositório no GitHub...");
23
+ const visibilityFlag = this.options.visibility === "private" ? "--private" : "--public";
24
+ // Montar nome completo do repo (com org se fornecida)
25
+ const fullRepoName = this.options.repoOrg
26
+ ? `${this.options.repoOrg}/${this.options.repoName}`
27
+ : this.options.repoName;
28
+ try {
29
+ await this.runCommand("gh", [
30
+ "repo",
31
+ "create",
32
+ fullRepoName,
33
+ visibilityFlag,
34
+ "--source",
35
+ ".",
36
+ "--push",
37
+ ], this.options.projectPath);
38
+ console.log("✅ Repositório criado e código enviado!");
39
+ // Aguardar alguns segundos para o GitHub processar o repositório
40
+ console.log("⏳ Aguardando GitHub processar o repositório...");
41
+ await new Promise((resolve) => setTimeout(resolve, 60000));
42
+ // Obter URL do repositório
43
+ const repoUrl = await this.getRepoUrl();
44
+ return repoUrl;
45
+ }
46
+ catch {
47
+ throw new Error("Erro ao criar repositório. Certifique-se de que o GitHub CLI (gh) está instalado e autenticado.");
48
+ }
49
+ }
50
+ async setupVercelDeploy() {
51
+ console.log("\n🚀 Conectando projeto à Vercel...");
52
+ // Tentar até 5 vezes conectar o repositório com delay de 20 segundos entre tentativas
53
+ let linkSuccess = false;
54
+ for (let i = 0; i < 5; i++) {
55
+ try {
56
+ if (i > 0) {
57
+ console.log(`\n🔄 Tentativa ${i + 1} de 5...`);
58
+ // Deletar pasta .vercel para forçar nova criação/conexão
59
+ const vercelDir = join(this.options.projectPath, ".vercel");
60
+ try {
61
+ await rm(vercelDir, { recursive: true, force: true });
62
+ }
63
+ catch {
64
+ // Ignorar se não existir
65
+ }
66
+ }
67
+ // Primeiro, fazer o link do repositório com a Vercel
68
+ // Usar runCommandWithOutput para capturar erros no output
69
+ await this.runCommandWithOutput("vercel", ["link", "--yes"], this.options.projectPath);
70
+ console.log("✅ Repositório conectado com sucesso!");
71
+ linkSuccess = true;
72
+ break; // Sucesso! Sair do loop
73
+ }
74
+ catch (error) {
75
+ if (i === 4) {
76
+ // Última tentativa falhou
77
+ console.error("❌ Erro ao conectar repositório com a Vercel após 5 tentativas.");
78
+ console.error("💡 Certifique-se de que o Vercel CLI está instalado e autenticado.");
79
+ console.error("💡 Execute: npm i -g vercel && vercel login");
80
+ throw error;
81
+ }
82
+ // Aguardar 20 segundos antes da próxima tentativa
83
+ console.log("⏳ Aguardando 20 segundos antes da próxima tentativa...");
84
+ await new Promise((resolve) => setTimeout(resolve, 20000));
85
+ }
86
+ }
87
+ // Se conseguiu fazer o link, fazer o deploy
88
+ if (linkSuccess) {
89
+ console.log("\n🚀 Fazendo deploy na Vercel...");
90
+ try {
91
+ await this.runCommand("vercel", ["--prod", "--yes"], this.options.projectPath);
92
+ console.log("✅ Deploy realizado com sucesso!");
93
+ console.log("💡 Deploys automáticos estão configurados para cada push no repositório.");
94
+ }
95
+ catch (error) {
96
+ console.error("❌ Erro ao fazer deploy na Vercel.");
97
+ console.error("💡 O link foi criado, mas o deploy falhou. Tente: cd " +
98
+ this.options.projectName +
99
+ " && vercel --prod");
100
+ throw error;
101
+ }
102
+ }
103
+ }
104
+ async ensureGitignore() {
105
+ const gitignorePath = join(this.options.projectPath, ".gitignore");
106
+ // Já deve existir do template, mas garantir
107
+ const defaultGitignore = `# dependencies
108
+ node_modules
109
+ .pnp
110
+ .pnp.js
111
+
112
+ # testing
113
+ coverage
114
+
115
+ # next.js
116
+ .next/
117
+ out/
118
+
119
+ # production
120
+ build
121
+ dist
122
+
123
+ # misc
124
+ .DS_Store
125
+ *.pem
126
+
127
+ # debug
128
+ npm-debug.log*
129
+ yarn-debug.log*
130
+ yarn-error.log*
131
+
132
+ # local env files
133
+ .env*.local
134
+ .env
135
+
136
+ # vercel
137
+ .vercel
138
+
139
+ # typescript
140
+ *.tsbuildinfo
141
+ next-env.d.ts
142
+ `;
143
+ try {
144
+ await writeFile(gitignorePath, defaultGitignore, { flag: "wx" });
145
+ }
146
+ catch {
147
+ // Arquivo já existe, tudo bem
148
+ }
149
+ }
150
+ async getRepoUrl() {
151
+ return new Promise((resolve, reject) => {
152
+ let output = "";
153
+ const child = spawn("git", ["remote", "get-url", "origin"], {
154
+ cwd: this.options.projectPath,
155
+ });
156
+ child.stdout.on("data", (data) => {
157
+ output += data.toString();
158
+ });
159
+ child.on("close", (code) => {
160
+ if (code === 0) {
161
+ resolve(output.trim());
162
+ }
163
+ else {
164
+ reject(new Error("Erro ao obter URL do repositório"));
165
+ }
166
+ });
167
+ child.on("error", (error) => {
168
+ reject(error);
169
+ });
170
+ });
171
+ }
172
+ runCommand(command, args, cwd, options) {
173
+ return new Promise((resolve, reject) => {
174
+ const child = spawn(command, args, {
175
+ cwd,
176
+ stdio: "inherit",
177
+ ...options,
178
+ });
179
+ child.on("close", (code) => {
180
+ if (code === 0) {
181
+ resolve();
182
+ }
183
+ else {
184
+ reject(new Error(`Comando falhou com código ${code}`));
185
+ }
186
+ });
187
+ child.on("error", (error) => {
188
+ reject(error);
189
+ });
190
+ });
191
+ }
192
+ runCommandWithOutput(command, args, cwd, options) {
193
+ return new Promise((resolve, reject) => {
194
+ let stdout = "";
195
+ let stderr = "";
196
+ const child = spawn(command, args, {
197
+ cwd,
198
+ stdio: "pipe",
199
+ ...options,
200
+ });
201
+ child.stdout?.on("data", (data) => {
202
+ const text = data.toString();
203
+ stdout += text;
204
+ process.stdout.write(text); // Mostrar no terminal também
205
+ });
206
+ child.stderr?.on("data", (data) => {
207
+ const text = data.toString();
208
+ stderr += text;
209
+ process.stderr.write(text); // Mostrar no terminal também
210
+ });
211
+ child.on("close", (code) => {
212
+ // Verificar se tem erro no output, independente do exit code
213
+ const output = stdout + stderr;
214
+ if (code !== 0 ||
215
+ output.includes("Error:") ||
216
+ output.includes("Failed to connect")) {
217
+ reject(new Error(`Comando falhou: ${output.substring(output.lastIndexOf("Error:") || 0)}`));
218
+ }
219
+ else {
220
+ resolve({ stdout, stderr });
221
+ }
222
+ });
223
+ child.on("error", (error) => {
224
+ reject(error);
225
+ });
226
+ });
227
+ }
228
+ static async getGitHubOrganizations() {
229
+ return new Promise((resolve) => {
230
+ let output = "";
231
+ const child = spawn("gh", ["api", "user/orgs", "--jq", ".[].login"]);
232
+ child.stdout.on("data", (data) => {
233
+ output += data.toString();
234
+ });
235
+ child.on("close", (code) => {
236
+ if (code === 0) {
237
+ const orgs = output.trim().split("\n").filter(Boolean);
238
+ resolve(orgs);
239
+ }
240
+ else {
241
+ resolve([]); // Se falhar, retorna array vazio
242
+ }
243
+ });
244
+ child.on("error", () => {
245
+ resolve([]); // Se falhar, retorna array vazio
246
+ });
247
+ });
248
+ }
249
+ static async isGitHubCLIAvailable() {
250
+ return new Promise((resolve) => {
251
+ const child = spawn("gh", ["auth", "status"], {
252
+ stdio: "pipe",
253
+ });
254
+ child.on("close", (code) => {
255
+ resolve(code === 0);
256
+ });
257
+ child.on("error", () => {
258
+ resolve(false);
259
+ });
260
+ });
261
+ }
262
+ static async isVercelCLIAvailable() {
263
+ return new Promise((resolve) => {
264
+ const child = spawn("vercel", ["whoami"], {
265
+ stdio: "pipe",
266
+ });
267
+ child.on("close", (code) => {
268
+ resolve(code === 0);
269
+ });
270
+ child.on("error", () => {
271
+ resolve(false);
272
+ });
273
+ });
274
+ }
275
+ }
@@ -0,0 +1,2 @@
1
+ #!/usr/bin/env node
2
+ export {};