vireum-spec-cli 0.2.0 → 0.2.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.
@@ -114,11 +114,11 @@ async function runRetrofit() {
114
114
  default: false,
115
115
  });
116
116
  const featuresAtivas = await (0, prompts_1.input)({
117
- message: 'Liste as funcionalidades JA implementadas (separadas por virgula):',
118
- default: analise.features.join(', '),
117
+ message: 'Liste as funcionalidades JA implementadas (separadas por virgula — Enter para pular):',
118
+ default: analise.features.length ? analise.features.join(', ') : '',
119
119
  });
120
120
  const featuresPendentes = await (0, prompts_1.input)({
121
- message: 'Liste as funcionalidades PENDENTES ou em desenvolvimento:',
121
+ message: 'Liste as funcionalidades PENDENTES (separadas por virgula — Enter para pular):',
122
122
  });
123
123
  const riscos = await (0, prompts_1.input)({
124
124
  message: 'Riscos tecnicos identificados:',
@@ -128,8 +128,8 @@ async function runRetrofit() {
128
128
  const dados = {
129
129
  projeto, cliente, objetivo, problema, prioridade,
130
130
  usuarios, regras, fase, multiTenant, lgpd,
131
- featuresAtivas: featuresAtivas.split(',').map(f => f.trim()).filter(Boolean),
132
- featuresPendentes: featuresPendentes.split(',').map(f => f.trim()).filter(Boolean),
131
+ featuresAtivas: featuresAtivas ? featuresAtivas.split(',').map(f => f.trim()).filter(Boolean) : [],
132
+ featuresPendentes: featuresPendentes ? featuresPendentes.split(',').map(f => f.trim()).filter(Boolean) : [],
133
133
  riscos, analise,
134
134
  data: new Date().toLocaleDateString('pt-BR'),
135
135
  };
@@ -154,7 +154,6 @@ async function runRetrofit() {
154
154
  fs.writeFileSync(path.join(specDir, arq.nome), arq.conteudo, 'utf-8');
155
155
  s.succeed(arq.nome);
156
156
  }
157
- // tasks
158
157
  const s1 = (0, ora_1.default)('Gerando tasks...').start();
159
158
  await sleep(400);
160
159
  fs.writeFileSync(path.join(tasksDir, 'active.md'), gerarTasksActive(dados), 'utf-8');
@@ -185,7 +184,6 @@ function analisarProjeto(cwd) {
185
184
  cache: '',
186
185
  },
187
186
  };
188
- // package.json
189
187
  const pkgPath = path.join(cwd, 'package.json');
190
188
  if (fs.existsSync(pkgPath)) {
191
189
  try {
@@ -193,7 +191,6 @@ function analisarProjeto(cwd) {
193
191
  resultado.nome = pkg.name || '';
194
192
  resultado.descricao = pkg.description || '';
195
193
  const deps = { ...pkg.dependencies, ...pkg.devDependencies };
196
- // Frontend
197
194
  if (deps['next'])
198
195
  resultado.stack.frontend = 'Next.js';
199
196
  else if (deps['react'])
@@ -202,14 +199,12 @@ function analisarProjeto(cwd) {
202
199
  resultado.stack.frontend = 'Vue';
203
200
  else if (deps['nuxt'])
204
201
  resultado.stack.frontend = 'Nuxt';
205
- // Backend
206
202
  if (deps['fastify'])
207
203
  resultado.stack.backend = 'Node.js + Fastify';
208
204
  else if (deps['express'])
209
205
  resultado.stack.backend = 'Node.js + Express';
210
206
  else if (deps['@nestjs/core'])
211
207
  resultado.stack.backend = 'NestJS';
212
- // Banco
213
208
  if (deps['pg'] || deps['postgres'])
214
209
  resultado.stack.banco = 'PostgreSQL';
215
210
  else if (deps['mysql2'])
@@ -218,29 +213,25 @@ function analisarProjeto(cwd) {
218
213
  resultado.stack.banco = 'SQLite';
219
214
  else if (deps['mongoose'])
220
215
  resultado.stack.banco = 'MongoDB';
221
- // ORM
222
216
  if (deps['prisma'] || deps['@prisma/client'])
223
217
  resultado.stack.orm = 'Prisma';
224
218
  else if (deps['typeorm'])
225
219
  resultado.stack.orm = 'TypeORM';
226
220
  else if (deps['drizzle-orm'])
227
221
  resultado.stack.orm = 'Drizzle';
228
- // Auth
229
222
  if (deps['jsonwebtoken'])
230
223
  resultado.stack.auth = 'JWT';
231
224
  else if (deps['next-auth'])
232
225
  resultado.stack.auth = 'NextAuth';
233
226
  else if (deps['@clerk/nextjs'])
234
227
  resultado.stack.auth = 'Clerk';
235
- // Cache
236
- if (deps['ioredis'] || deps['redis'])
237
- resultado.stack.cache = 'Redis';
238
228
  if (deps['bullmq'])
239
229
  resultado.stack.cache = 'Redis + BullMQ';
230
+ else if (deps['ioredis'] || deps['redis'])
231
+ resultado.stack.cache = 'Redis';
240
232
  }
241
233
  catch { }
242
234
  }
243
- // README
244
235
  const readmePath = path.join(cwd, 'README.md');
245
236
  if (fs.existsSync(readmePath)) {
246
237
  resultado.readme = true;
@@ -249,41 +240,63 @@ function analisarProjeto(cwd) {
249
240
  if (desc)
250
241
  resultado.descricao = resultado.descricao || desc.trim();
251
242
  }
252
- // Rotas procura em src/
253
- const srcDir = path.join(cwd, 'src');
254
- if (fs.existsSync(srcDir)) {
255
- resultado.features = extrairRotas(srcDir);
256
- resultado.arquivos = contarArquivos(srcDir);
243
+ const pastasCodigo = ['src', 'app', 'pages', 'components', 'server', 'api'];
244
+ let totalArquivos = 0;
245
+ const todasRotas = [];
246
+ for (const pasta of pastasCodigo) {
247
+ const dir = path.join(cwd, pasta);
248
+ if (fs.existsSync(dir)) {
249
+ todasRotas.push(...extrairRotas(dir));
250
+ totalArquivos += contarArquivos(dir);
251
+ }
257
252
  }
253
+ resultado.features = [...new Set(todasRotas)].slice(0, 20);
254
+ resultado.arquivos = totalArquivos;
258
255
  return resultado;
259
256
  }
260
257
  function extrairRotas(dir) {
261
258
  const rotas = [];
262
- const exts = ['.ts', '.js'];
259
+ const exts = ['.ts', '.tsx', '.js', '.jsx'];
263
260
  function walk(d) {
264
261
  if (!fs.existsSync(d))
265
262
  return;
266
263
  for (const entry of fs.readdirSync(d)) {
267
264
  const full = path.join(d, entry);
268
265
  const stat = fs.statSync(full);
269
- if (stat.isDirectory() && !entry.includes('node_modules')) {
266
+ if (stat.isDirectory() && !['node_modules', '.next', 'dist', '.git'].includes(entry)) {
270
267
  walk(full);
271
268
  }
272
269
  else if (exts.includes(path.extname(entry))) {
273
- const content = fs.readFileSync(full, 'utf-8');
274
- const matches = content.match(/\.(get|post|put|patch|delete|route)\(['"`]([^'"`]+)/gi);
275
- if (matches) {
276
- matches.forEach(m => {
277
- const rota = m.replace(/\.(get|post|put|patch|delete|route)\(['"`]/i, '').trim();
278
- if (rota && !rotas.includes(rota))
279
- rotas.push(rota);
280
- });
270
+ try {
271
+ const content = fs.readFileSync(full, 'utf-8');
272
+ const apiMatches = content.match(/\.(get|post|put|patch|delete|route)\(['"`]([^'"`]+)/gi);
273
+ if (apiMatches) {
274
+ apiMatches.forEach(m => {
275
+ const rota = m.replace(/\.(get|post|put|patch|delete|route)\(['"`]/i, '').trim();
276
+ if (rota && !rotas.includes(rota))
277
+ rotas.push(rota);
278
+ });
279
+ }
280
+ if (entry === 'page.tsx' || entry === 'page.ts') {
281
+ const relativo = path.relative(dir, full)
282
+ .replace(/\\/g, '/')
283
+ .replace('/page.tsx', '')
284
+ .replace('/page.ts', '');
285
+ if (relativo && !rotas.includes(relativo))
286
+ rotas.push(`page: /${relativo}`);
287
+ }
288
+ if (d.includes('pages') && (entry.endsWith('.tsx') || entry.endsWith('.ts')) && !entry.startsWith('_')) {
289
+ const pagina = entry.replace('.tsx', '').replace('.ts', '');
290
+ if (!rotas.includes(pagina))
291
+ rotas.push(`page: ${pagina}`);
292
+ }
281
293
  }
294
+ catch { }
282
295
  }
283
296
  }
284
297
  }
285
298
  walk(dir);
286
- return rotas.slice(0, 20);
299
+ return rotas;
287
300
  }
288
301
  function contarArquivos(dir) {
289
302
  let count = 0;
@@ -292,8 +305,9 @@ function contarArquivos(dir) {
292
305
  return;
293
306
  for (const entry of fs.readdirSync(d)) {
294
307
  const full = path.join(d, entry);
295
- if (fs.statSync(full).isDirectory() && !entry.includes('node_modules'))
308
+ if (fs.statSync(full).isDirectory() && !['node_modules', '.next', 'dist', '.git'].includes(entry)) {
296
309
  walk(full);
310
+ }
297
311
  else
298
312
  count++;
299
313
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "vireum-spec-cli",
3
- "version": "0.2.0",
3
+ "version": "0.2.1",
4
4
  "description": "Spec Driven Development framework by Vireum Desenvolvimento",
5
5
  "main": "dist/index.js",
6
6
  "bin": {