tumemo 1.0.5 → 1.1.0

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 (2) hide show
  1. package/index.js +122 -32
  2. package/package.json +1 -1
package/index.js CHANGED
@@ -19,7 +19,7 @@ async function runCommand(command, args, options = {}) {
19
19
  try {
20
20
  await execa(command, args, {
21
21
  stdio: 'inherit',
22
- shell: true,
22
+ shell: true,
23
23
  env: { ...process.env, FORCE_COLOR: "1" },
24
24
  ...options
25
25
  });
@@ -31,8 +31,7 @@ async function runCommand(command, args, options = {}) {
31
31
 
32
32
  program
33
33
  .name('Tumemo')
34
- .description('O setup mais rápido para React + TS')
35
- .version('1.1.1')
34
+ .version('1.1.9')
36
35
  .option('-t, --tailwind', 'Instalar Tailwind v4')
37
36
  .option('-s, --shadcn', 'Instalar Shadcn')
38
37
  .action(async (options) => {
@@ -45,16 +44,19 @@ program
45
44
  log.info('Baixando template React + TS...');
46
45
  await runCommand('npx', ['--yes', 'degit', 'vitejs/vite/packages/create-vite/template-react-ts', '.']);
47
46
 
48
- const oldGit = path.join(root, '_gitignore');
49
- if (fs.existsSync(oldGit)) fs.renameSync(oldGit, path.join(root, '.gitignore'));
47
+ if (fs.existsSync(path.join(root, '_gitignore'))) {
48
+ fs.renameSync(path.join(root, '_gitignore'), path.join(root, '.gitignore'));
49
+ }
50
50
 
51
51
  const pkgPath = path.join(root, 'package.json');
52
52
  const pkg = await fs.readJson(pkgPath);
53
53
  pkg.name = projectName;
54
54
  await fs.writeJson(pkgPath, pkg, { spaces: 2 });
55
55
 
56
- log.info('Instalando dependências base...');
56
+ log.info('Instalando dependências...');
57
57
  await runCommand('npm', ['install']);
58
+ await runCommand('npm', ['install', '-D', '@types/node', '@vitejs/plugin-react-swc']);
59
+ await runCommand('npm', ['install', 'axios', 'react-router-dom', 'tailwind-merge', 'clsx']);
58
60
 
59
61
  log.info('Limpando boilerplate...');
60
62
  ['src/assets', 'src/App.css', 'src/index.css', 'public/vite.svg'].forEach(item => {
@@ -62,16 +64,7 @@ program
62
64
  if (fs.existsSync(fullPath)) fs.removeSync(fullPath);
63
65
  });
64
66
 
65
- const htmlPath = path.join(root, 'index.html');
66
- let htmlContent = fs.readFileSync(htmlPath, 'utf8');
67
- htmlContent = htmlContent.replace('</head>', ' <style>body { margin: 0; padding: 0; box-sizing: border-box; }</style>\n </head>');
68
- fs.writeFileSync(htmlPath, htmlContent);
69
-
70
- await runCommand('npm', ['install', 'axios', 'react-router-dom', 'tailwind-merge', 'clsx']);
71
- await runCommand('npm', ['install', '-D', '@types/node']);
72
-
73
67
  const useTailwind = options.tailwind || options.shadcn;
74
- const useShadcn = options.shadcn;
75
68
 
76
69
  if (useTailwind) {
77
70
  log.info('Configurando Tailwind v4...');
@@ -80,34 +73,131 @@ program
80
73
  fs.writeFileSync(path.join(root, 'src/shared/tailwind.css'), `@import "tailwindcss";`);
81
74
  }
82
75
 
83
- if (useShadcn) {
84
- log.info('Configurando Shadcn UI...');
85
- await runCommand('npx', ['--yes', 'shadcn@latest', 'init', '-y']);
86
- }
87
-
88
- const viteConfig = `import path from "path"\nimport react from "@vitejs/plugin-react"\nimport { defineConfig } from "vite"\n${useTailwind ? 'import tailwindcss from "@tailwindcss/vite"' : ''}\n\nexport default defineConfig({\n plugins: [react(), ${useTailwind ? 'tailwindcss()' : ''}],\n resolve: { alias: { "@": path.resolve(__dirname, "./src") } },\n})`;
76
+ // --- 1. SEU VITE CONFIG ---
77
+ const viteConfig = `
78
+ import { defineConfig } from 'vite'
79
+ import react from '@vitejs/plugin-react-swc'
80
+ import path from "path"
81
+ import tailwindcss from "@tailwindcss/vite"
82
+
83
+ export default defineConfig({
84
+ plugins: [react(), tailwindcss()],
85
+ resolve: {
86
+ alias: {
87
+ "@": path.resolve(__dirname, "./src"),
88
+ },
89
+ },
90
+ })`;
89
91
  fs.writeFileSync(path.join(root, 'vite.config.ts'), viteConfig.trim());
90
92
 
91
- const tsAppPath = path.join(root, 'tsconfig.app.json');
92
- const fallbackTs = { compilerOptions: { target: "ESNext", lib: ["DOM", "DOM.Iterable", "ESNext"], module: "ESNext", skipLibCheck: true, moduleResolution: "Node", resolveJsonModule: true, isolatedModules: true, noEmit: true, jsx: "react-jsx", strict: true, baseUrl: ".", paths: { "@/*": ["./src/*"] } } };
93
- fs.writeJsonSync(tsAppPath, fallbackTs, { spaces: 2 });
93
+ // --- 2. SEU TSCONFIG APP ---
94
+ const tsConfigApp = {
95
+ "compilerOptions": {
96
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
97
+ "target": "ES2022",
98
+ "useDefineForClassFields": true,
99
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
100
+ "module": "ESNext",
101
+ "types": ["vite/client", "node"],
102
+ "skipLibCheck": true,
103
+ "moduleResolution": "bundler",
104
+ "allowImportingTsExtensions": true,
105
+ "verbatimModuleSyntax": true,
106
+ "moduleDetection": "force",
107
+ "noEmit": true,
108
+ "jsx": "react-jsx",
109
+ "strict": true,
110
+ "noUnusedLocals": true,
111
+ "noUnusedParameters": true,
112
+ "erasableSyntaxOnly": true,
113
+ "noFallthroughCasesInSwitch": true,
114
+ "noUncheckedSideEffectImports": true,
115
+ "baseUrl": ".",
116
+ "paths": { "@/*": ["./src/*"] }
117
+ },
118
+ "include": ["src"]
119
+ };
120
+ fs.writeJsonSync(path.join(root, 'tsconfig.app.json'), tsConfigApp, { spaces: 2 });
121
+
122
+ // --- 3. SEU TSCONFIG RAIZ ---
123
+ const tsConfig = {
124
+ "files": [],
125
+ "references": [
126
+ { "path": "./tsconfig.app.json" },
127
+ { "path": "./tsconfig.node.json" }
128
+ ],
129
+ "compilerOptions": {
130
+ "baseUrl": ".",
131
+ "paths": { "@/*": ["./src/*"] }
132
+ }
133
+ };
134
+ fs.writeJsonSync(path.join(root, 'tsconfig.json'), tsConfig, { spaces: 2 });
135
+
136
+ if (options.shadcn) {
137
+ log.info('Configurando Shadcn UI');
138
+ await runCommand('npx', ['shadcn@latest', 'init']);
139
+ }
94
140
 
141
+ // --- 4. APP.TSX COM VISUAL CAPRICHADO ---
95
142
  let techStack = "React + TS";
96
- if (useShadcn) techStack += " + Shadcn UI";
143
+ if (options.shadcn) techStack += " + Shadcn UI";
97
144
  else if (useTailwind) techStack += " + Tailwind v4";
98
145
 
99
- const appContent = `export default function App() {\n return (\n <div style={{ display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center', minHeight: '100vh', width: '100%', fontFamily: 'system-ui, sans-serif', backgroundColor: '#0f172a', color: '#f8fafc', margin: 0 }}>\n <h1 style={{ fontSize: '3.5rem', marginBottom: '0.5rem' }}>Tumemo CLI</h1>\n <p style={{ fontSize: '1.25rem', color: '#94a3b8' }}>Projeto: <strong style={{ color: '#38bdf8' }}>${projectName}</strong></p>\n <div style={{ marginTop: '2.5rem', padding: '1.5rem 3rem', borderRadius: '12px', backgroundColor: '#1e293b', border: '1px solid #334155' }}>\n <p>Stack: <strong>${techStack}</strong></p>\n </div>\n </div>\n )\n}`;
146
+ const appContent = `
147
+ export default function App() {
148
+ return (
149
+ <div style={{
150
+ display: 'flex',
151
+ flexDirection: 'column',
152
+ alignItems: 'center',
153
+ justifyContent: 'center',
154
+ minHeight: '100vh',
155
+ width: '100%',
156
+ fontFamily: 'system-ui, sans-serif',
157
+ backgroundColor: '#0f172a',
158
+ color: '#f8fafc',
159
+ textAlign: 'center',
160
+ margin: 0,
161
+ padding: 0
162
+ }}>
163
+ <h1 style={{ fontSize: '3.5rem', marginBottom: '0.5rem', letterSpacing: '-0.025em' }}>Tumemo CLI</h1>
164
+ <p style={{ fontSize: '1.25rem', color: '#94a3b8' }}>
165
+ Projeto: <strong style={{ color: '#38bdf8' }}>${projectName}</strong>
166
+ </p>
167
+ <div style={{
168
+ marginTop: '2.5rem',
169
+ padding: '1.5rem 3rem',
170
+ borderRadius: '12px',
171
+ backgroundColor: '#1e293b',
172
+ border: '1px solid #334155',
173
+ boxShadow: '0 10px 15px -3px rgba(0, 0, 0, 0.1)'
174
+ }}>
175
+ <p style={{ margin: 0 }}>Stack: <span style={{ color: '#60a5fa', fontWeight: 'bold' }}>${techStack}</span></p>
176
+ </div>
177
+ <footer style={{ marginTop: '3rem', fontSize: '0.875rem', color: '#475569' }}>
178
+ Edite o <code>src/App.tsx</code> para começar.
179
+ </footer>
180
+ </div>
181
+ )
182
+ }`;
100
183
  fs.writeFileSync(path.join(root, 'src/App.tsx'), appContent.trim());
101
184
 
102
- const mainContent = `import React from 'react'\nimport ReactDOM from 'react-dom/client'\nimport App from './App.tsx'\n${useTailwind ? "import '@/shared/tailwind.css'\n" : ""}ReactDOM.createRoot(document.getElementById('root')!).render(<App />)`;
103
- fs.writeFileSync(path.join(root, 'src/main.tsx'), mainContent);
185
+ const mainContent = `
186
+ import React from 'react'
187
+ import ReactDOM from 'react-dom/client'
188
+ import App from './App.tsx'
189
+ ${useTailwind ? "import '@/shared/tailwind.css'" : ""}
104
190
 
105
- ['src/components', 'src/pages'].forEach(dir => fs.ensureDirSync(path.join(root, dir)));
191
+ ReactDOM.createRoot(document.getElementById('root')!).render(
192
+ <React.StrictMode>
193
+ <App />
194
+ </React.StrictMode>
195
+ )`;
196
+ fs.writeFileSync(path.join(root, 'src/main.tsx'), mainContent.trim());
106
197
 
107
- log.success(`\nTumemo v1.0.5 finalizado!`);
108
- log.info('Iniciando servidor de desenvolvimento...\n');
198
+ ['src/components', 'src/pages'].forEach(dir => fs.ensureDirSync(path.join(root, dir)));
109
199
 
110
- // COMANDO PARA RODAR O SERVIDOR AUTOMATICAMENTE
200
+ log.success(`\nTumemo v1.1.0 finalizado!`);
111
201
  await runCommand('npm', ['run', 'dev']);
112
202
 
113
203
  } catch (err) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "tumemo",
3
- "version": "1.0.5",
3
+ "version": "1.1.0",
4
4
  "type": "module",
5
5
  "description": "CLI para automação de projetos React",
6
6
  "main": "index.js",