@mocoto/mahoraga 0.14.9 → 0.15.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.
- package/README.md +263 -30
- package/dist/analysts/js-ts/registrar.js +1 -1
- package/dist/analysts/react/analysts/analyst-react-hooks.js +30 -15
- package/dist/analysts/react/analysts/analyst-react.js +4 -2
- package/dist/analysts/react/detectors/detector-react-best-practices.js +7 -4
- package/dist/caretakers/caretaker-imports.js +0 -9
- package/dist/cli/commands/command-github-actions.js +0 -27
- package/dist/core/messages/en/cli/cli-command-github-actions-messages.js +0 -5
- package/dist/core/messages/en/github/index.js +0 -1
- package/dist/core/messages/ja/cli/cli-command-github-actions-messages.js +0 -5
- package/dist/core/messages/ja/github/index.js +0 -1
- package/dist/core/messages/pt/cli/cli-command-github-actions-messages.js +0 -5
- package/dist/core/messages/pt/github/index.js +0 -1
- package/dist/core/messages/zh/cli/cli-command-github-actions-messages.js +0 -5
- package/dist/core/messages/zh/github/index.js +0 -1
- package/dist/core/registry/file-registry.js +1 -1
- package/dist/node.loader.js +0 -2
- package/dist/shared/formatters/formatters/commons.js +36 -10
- package/dist/shared/formatters/formatters/shell.js +6 -3
- package/dist/types/analysts/index.js +1 -1
- package/docs/.obsidian/app.json +7 -0
- package/docs/.obsidian/appearance.json +8 -0
- package/docs/.obsidian/community-plugins.json +28 -0
- package/docs/.obsidian/core-plugins-migration.json +18 -0
- package/docs/.obsidian/core-plugins.json +73 -0
- package/docs/.obsidian/graph.json +22 -0
- package/docs/.obsidian/workspace.json +196 -0
- package/docs/01-arquitetura/ADR-001-estrutura-testes.md +31 -0
- package/docs/01-arquitetura/_index.md +152 -0
- package/docs/02-componentes/_index.md +294 -0
- package/docs/02-componentes/supressao-inline.md +88 -0
- package/docs/03-guias/_index.md +173 -0
- package/docs/03-guias/contribuindo.md +71 -0
- package/docs/03-guias/testes.md +133 -0
- package/docs/04-glossario/_index.md +29 -0
- package/docs/04-glossario/termos.md +247 -0
- package/docs/05-referencias/_index.md +87 -0
- package/docs/_home.md +140 -0
- package/docs/partials/AVISO-PROVENIENCIA.md +3 -0
- package/docs/templates/ADR.md +24 -0
- package/docs/templates/componente.md +34 -0
- package/docs/templates/guia.md +28 -0
- package/package.json +31 -32
- package/dist/app/github.js +0 -14
- package/dist/app/index.js +0 -1
- package/dist/core/messages/en/github/github-app-messages.js +0 -9
- package/dist/core/messages/ja/github/github-app-messages.js +0 -9
- package/dist/core/messages/pt/github/github-app-messages.js +0 -9
- package/dist/core/messages/zh/github/github-app-messages.js +0 -9
package/README.md
CHANGED
|
@@ -7,10 +7,11 @@ Proveniência e Autoria: Este documento integra o projeto @mocoto/mahoraga (lice
|
|
|
7
7
|
<p><b>@mocoto/mahoraga</b>: CLI modular para análise, diagnóstico e manutenção de projetos JavaScript/TypeScript com suporte multi-linguagem<p>
|
|
8
8
|
|
|
9
9
|
</div>
|
|
10
|
+
ja que temos aqui esses 60 bastiões, vou manter o projeto no ar e em evolução pra ajuda-los, no momento esta passando por ajustes, mas ja ja fica no jeito. (obrigado por usar o mahoraga).
|
|
10
11
|
|
|
11
|
-
Caso queira ajudar com
|
|
12
|
+
Caso queira ajudar com relatórios de bugs e erros ou com sugestões, entre em contato pelo e-mail abaixo.
|
|
12
13
|
|
|
13
|
-
[ProtonMail](mailto:mahoraga.
|
|
14
|
+
[ProtonMail](mailto:mahoraga.able522@passfwd.com)
|
|
14
15
|
|
|
15
16
|
---
|
|
16
17
|
|
|
@@ -43,7 +44,9 @@ mahoraga diagnosticar --json > relatorio.json
|
|
|
43
44
|
| `guardian` | Monitoramento de integridade com GPG | `mahoraga guardian --accept-baseline` |
|
|
44
45
|
| `fix-types` | Corrigir tipos inseguros (`any`/`unknown`) | `mahoraga fix-types --target src` |
|
|
45
46
|
| `formatar` | Formatação automática de código | `mahoraga formatar --write` |
|
|
47
|
+
| `formatters` | Gerenciamento de formatadores | `mahoraga formatters list` |
|
|
46
48
|
| `podar` | Remover arquivos órfãos e código morto | `mahoraga podar` |
|
|
49
|
+
| `otimizar-svg` | Otimizar arquivos SVG | `mahoraga otimizar-svg --write` |
|
|
47
50
|
| `names` | Extração e renomeação em massa de variáveis | `mahoraga names --scan` |
|
|
48
51
|
| `imports` | Gerenciar aliases de import (`@/`) | `mahoraga imports --scan` |
|
|
49
52
|
| `barrels` | Gerenciar barrels (`index.ts`) | `mahoraga barrels --generate` |
|
|
@@ -92,7 +95,6 @@ mahoraga guardian --json # saída JSON estruturada
|
|
|
92
95
|
```bash
|
|
93
96
|
mahoraga github-actions scan # GitHub Actions
|
|
94
97
|
mahoraga github-actions gate --threshold 80 # quality gate
|
|
95
|
-
mahoraga github-actions app --port 3000 # servidor GitHub App
|
|
96
98
|
mahoraga gitlab-ci scan # GitLab CI
|
|
97
99
|
mahoraga circleci scan # CircleCI
|
|
98
100
|
mahoraga jenkins scan # Jenkins
|
|
@@ -120,6 +122,7 @@ mahoraga fix-types --interactive # modo interativo
|
|
|
120
122
|
mahoraga formatar --write # formatar código
|
|
121
123
|
mahoraga formatar --check # apenas verificar
|
|
122
124
|
mahoraga podar # remover arquivos órfãos
|
|
125
|
+
mahoraga otimizar-svg --write # otimizar SVGs
|
|
123
126
|
mahoraga names --scan # extrair nomes de variáveis
|
|
124
127
|
mahoraga names --apply # aplicar renomeações
|
|
125
128
|
mahoraga reverter listar # listar reversões disponíveis
|
|
@@ -140,7 +143,6 @@ mahoraga marketplace list # listar instalados
|
|
|
140
143
|
### Utilitários
|
|
141
144
|
|
|
142
145
|
```bash
|
|
143
|
-
mahoraga otimizar-svg --write # otimizar SVGs
|
|
144
146
|
mahoraga imports --scan # escanear aliases de import
|
|
145
147
|
mahoraga imports --apply # aplicar correções de import
|
|
146
148
|
mahoraga barrels --scan # preview de barrels
|
|
@@ -158,7 +160,8 @@ mahoraga atualizar --global # auto-update
|
|
|
158
160
|
|
|
159
161
|
- **Diagnóstico completo**: qualidade, segurança e arquitetura
|
|
160
162
|
- **15+ detectores especializados**: código frágil, duplicação, complexidade, performance, vazamentos de memória, tipos inseguros
|
|
161
|
-
- **
|
|
163
|
+
- **14 analisadores de linguagem**: JS, TS, React, CSS, CSS-in-JS, HTML, SVG, XML, Tailwind, Python, Shell, SQL, Go, Rust, PHP
|
|
164
|
+
- **5 analisadores de CI/CD**: GitHub Actions, GitLab CI, CircleCI, Jenkins, Azure Pipelines
|
|
162
165
|
- **Detecção de bugs via ML**: 8 padrões com pontuação Bayesiana
|
|
163
166
|
- **Registro inteligente**: descoberta automática de analistas built-in e customizados
|
|
164
167
|
- **Análise de monorepos**: pnpm-workspace, lerna, nx, turbo
|
|
@@ -168,7 +171,7 @@ mahoraga atualizar --global # auto-update
|
|
|
168
171
|
- **Guardian**: monitoramento contínuo com assinatura GPG (Ed25519), baselines criptográficos e verificação de integridade
|
|
169
172
|
- **Fix Types**: correção automática de `any` e `unknown`
|
|
170
173
|
- **Poda inteligente**: identificação e remoção de arquivos órfãos e código morto
|
|
171
|
-
- **Formatação**: formatação automática do código
|
|
174
|
+
- **Formatação**: formatação automática do código com supressão inline via `@mahoraga-disable`
|
|
172
175
|
- **Names/Rename**: extração e renomeação em massa de variáveis
|
|
173
176
|
- **Reverter**: rollback de movimentações aplicadas
|
|
174
177
|
- **Imports**: gerenciamento de aliases de import
|
|
@@ -183,7 +186,7 @@ mahoraga atualizar --global # auto-update
|
|
|
183
186
|
|
|
184
187
|
### Integrações CI/CD
|
|
185
188
|
|
|
186
|
-
- **GitLab CI / CircleCI / Jenkins / Azure Pipelines**: análise de pipelines
|
|
189
|
+
- **GitHub Actions / GitLab CI / CircleCI / Jenkins / Azure Pipelines**: análise de pipelines com detectores e correções específicos
|
|
187
190
|
- **Conversão** entre plataformas de CI/CD
|
|
188
191
|
|
|
189
192
|
### Extensível
|
|
@@ -213,7 +216,7 @@ npx mahoraga --help
|
|
|
213
216
|
### Verificar Instalação
|
|
214
217
|
|
|
215
218
|
```bash
|
|
216
|
-
mahoraga --version # v0.
|
|
219
|
+
mahoraga --version # v0.15.1
|
|
217
220
|
mahoraga --help # lista todos os comandos
|
|
218
221
|
mahoraga analistas --json # analistas disponíveis
|
|
219
222
|
```
|
|
@@ -222,20 +225,169 @@ mahoraga analistas --json # analistas disponíveis
|
|
|
222
225
|
|
|
223
226
|
## Configuração
|
|
224
227
|
|
|
225
|
-
O Mahoraga lê um arquivo `mahoraga.config.json` na raiz do seu projeto (
|
|
228
|
+
O Mahoraga lê um arquivo `mahoraga.config.json` na raiz do seu projeto. A configuração usa **deep merge** com esta precedência (maior para menor):
|
|
229
|
+
1. CLI flags / environment variables (`MAHORAGA_*`)
|
|
230
|
+
2. `mahoraga.config.json` (ou `src/config.json` como fallback)
|
|
231
|
+
3. System defaults (hardcoded)
|
|
226
232
|
|
|
227
|
-
###
|
|
233
|
+
### Exemplo Completo
|
|
228
234
|
|
|
229
|
-
```
|
|
235
|
+
```jsonc
|
|
230
236
|
{
|
|
231
|
-
|
|
232
|
-
"
|
|
233
|
-
|
|
234
|
-
|
|
237
|
+
// === LOCALIDADE ===
|
|
238
|
+
"locale": "pt", // Idioma: pt, en, zh, ja
|
|
239
|
+
|
|
240
|
+
// === LOG E DEBUG ===
|
|
241
|
+
"verbose": false, // Saída verbosa
|
|
242
|
+
"LOG_LEVEL": "info", // Nível: erro, aviso, info, debug
|
|
243
|
+
"LOG_ESTRUTURADO": false, // Logs em JSON estruturado
|
|
244
|
+
"DEV_MODE": false, // Modo desenvolvimento
|
|
245
|
+
|
|
246
|
+
// === LINGUAGENS ===
|
|
247
|
+
"languages": { // Habilita/desabilita analisadores
|
|
235
248
|
"javascript": { "enabled": true },
|
|
236
249
|
"typescript": { "enabled": true },
|
|
250
|
+
"react": { "enabled": true },
|
|
237
251
|
"html": { "enabled": true },
|
|
238
|
-
"css": { "enabled": true }
|
|
252
|
+
"css": { "enabled": true },
|
|
253
|
+
"scss": { "enabled": false },
|
|
254
|
+
"sass": { "enabled": false },
|
|
255
|
+
"css-in-js": { "enabled": false },
|
|
256
|
+
"tailwind": { "enabled": false },
|
|
257
|
+
"xml": { "enabled": true },
|
|
258
|
+
"svg": { "enabled": false },
|
|
259
|
+
"python": { "enabled": false },
|
|
260
|
+
"shell": { "enabled": false },
|
|
261
|
+
"sql": { "enabled": false },
|
|
262
|
+
"go": { "enabled": false },
|
|
263
|
+
"rust": { "enabled": false },
|
|
264
|
+
"php": { "enabled": false },
|
|
265
|
+
"astro": { "enabled": false },
|
|
266
|
+
"gradle": { "enabled": false }
|
|
267
|
+
},
|
|
268
|
+
|
|
269
|
+
// === INCLUDE/EXCLUDE ===
|
|
270
|
+
"exclude": [ // Glob patterns para excluir do scan
|
|
271
|
+
"node_modules/**", "dist/**", "build/**", "coverage/**",
|
|
272
|
+
".git/**", ".next/**", ".turbo/**", ".vercel/**",
|
|
273
|
+
"**/*.min.js", "**/*.min.css", "**/*.log", "**/*.lock",
|
|
274
|
+
"package-lock.json", "yarn.lock", "pnpm-lock.yaml",
|
|
275
|
+
"**/.mahoraga/**"
|
|
276
|
+
],
|
|
277
|
+
|
|
278
|
+
// === SUPRESSÃO DE OCORRÊNCIAS ===
|
|
279
|
+
"suppress": {
|
|
280
|
+
"rules": ["no-console"], // Suprimir regras específicas
|
|
281
|
+
"severity": { "some-rule": "warning" }, // Override de severidade
|
|
282
|
+
"paths": ["**/test/**"], // Suprimir por caminho
|
|
283
|
+
"filePatterns": ["*.test.ts"] // Suprimir por padrão de arquivo
|
|
284
|
+
},
|
|
285
|
+
|
|
286
|
+
// === REGRAS PERSONALIZADAS ===
|
|
287
|
+
"rules": {
|
|
288
|
+
"nome-da-regra": {
|
|
289
|
+
"severity": "error", // error, warning, info, off
|
|
290
|
+
"exclude": ["**/generated/**"], // Exclusão por glob
|
|
291
|
+
"allowTestFiles": false // Permitir em testes
|
|
292
|
+
}
|
|
293
|
+
},
|
|
294
|
+
|
|
295
|
+
// === GUARDIAN (INTEGRIDADE) ===
|
|
296
|
+
"GUARDIAN_ENABLED": true, // Habilitar Guardian
|
|
297
|
+
"GUARDIAN_ENFORCE_PROTECTION": true, // Impedir alterações não autorizadas
|
|
298
|
+
"GUARDIAN_ALLOW_ADDS": false, // Permitir adição de arquivos
|
|
299
|
+
"GUARDIAN_ALLOW_CHG": false, // Permitir modificação de arquivos
|
|
300
|
+
"GUARDIAN_ALLOW_DELS": false, // Permitir deleção de arquivos
|
|
301
|
+
|
|
302
|
+
// === WORKERS (PARALELISMO) ===
|
|
303
|
+
"WORKER_POOL_ENABLED": true, // Habilitar worker pool
|
|
304
|
+
"WORKER_POOL_MAX_WORKERS": 0, // Máx workers (0 = auto)
|
|
305
|
+
"WORKER_POOL_BATCH_SIZE": 10, // Arquivos por lote
|
|
306
|
+
"WORKER_POOL_AUTO_THRESHOLD": 50, // Threshold para auto-pool
|
|
307
|
+
|
|
308
|
+
// === ANÁLISE ===
|
|
309
|
+
"ANALISE_INCREMENTAL_ENABLED": false, // Análise incremental
|
|
310
|
+
"ANALISE_CACHE_ENABLED": false, // Cache de análise
|
|
311
|
+
"ANALISE_CACHE_TTL_MS": 86400000, // TTL do cache (24h)
|
|
312
|
+
"ANALISE_METRICAS_ENABLED": true, // Coleta de métricas
|
|
313
|
+
"ANALISE_PRIORIZACAO_ENABLED": true, // Priorização de ocorrências
|
|
314
|
+
"ANALISE_TIMEOUT_POR_ANALISTA_MS": 30000, // Timeout por analista
|
|
315
|
+
"SCAN_ONLY": false, // Modo scan-only (sem correções)
|
|
316
|
+
"COMPACT_MODE": false, // Modo compacto
|
|
317
|
+
|
|
318
|
+
// === LIMITES DE ANÁLISE ===
|
|
319
|
+
"ANALISE_LIMITES": {
|
|
320
|
+
"FUNCOES_LONGAS": {
|
|
321
|
+
"MAX_LINHAS": 30, // Máx linhas por função
|
|
322
|
+
"MAX_PARAMETROS": 4, // Máx parâmetros
|
|
323
|
+
"MAX_ANINHAMENTO": 3 // Máx aninhamento if
|
|
324
|
+
},
|
|
325
|
+
"CODIGO_FRAGIL": {
|
|
326
|
+
"MAX_LINHAS_FUNCAO": 30,
|
|
327
|
+
"MAX_PARAMETROS": 4,
|
|
328
|
+
"MAX_NESTED_CALLBACKS": 2 // Máx callbacks aninhados
|
|
329
|
+
}
|
|
330
|
+
},
|
|
331
|
+
|
|
332
|
+
// === RELATÓRIOS ===
|
|
333
|
+
"REPORT_EXPORT_ENABLED": false, // Exportar relatórios
|
|
334
|
+
"REPORT_EXPORT_FULL": false, // Relatório completo (não diff)
|
|
335
|
+
"REPORT_OUTPUT_DIR": ".mahoraga/reports",
|
|
336
|
+
"REPORT_SILENCE_LOGS": false, // Silenciar logs durante geração
|
|
337
|
+
"REPORT_STREAM_ENABLED": false, // Streaming NDJSON
|
|
338
|
+
"REPORT_STREAM_AUTO_THRESHOLD": 5000, // Auto-stream para projetos grandes
|
|
339
|
+
"REPORT_FRAGMENT_OCCURRENCES": 2000, // Máx ocorrências por fragmento
|
|
340
|
+
"REPORT_FRAGMENT_FILEENTRIES": 500, // Máx entradas por fragmento
|
|
341
|
+
|
|
342
|
+
// === ESTRUTURA DO PROJETO ===
|
|
343
|
+
"STRUCTURE_AUTO_FIX": false, // Auto-fix de violações estruturais
|
|
344
|
+
"STRUCTURE_CONCURRENCY": 5, // Concorrência
|
|
345
|
+
"ESTRUTURA_ARQUIVOS_RAIZ_MAX": 10, // Máx arquivos na raiz
|
|
346
|
+
"ESTRUTURA_PLANO_MAX_FILE_SIZE": 262144, // Tam máx para plano (256KB)
|
|
347
|
+
|
|
348
|
+
// === CONVENÇÕES DE NOMES ===
|
|
349
|
+
"nameConventions": { // Personalizar nomes de diretórios
|
|
350
|
+
"typesDirectory": "types",
|
|
351
|
+
"testsDirectory": "tests",
|
|
352
|
+
"docsDirectory": "docs",
|
|
353
|
+
"srcDirectory": "src",
|
|
354
|
+
"componentsDirectory": "components",
|
|
355
|
+
"utilsDirectory": "utils",
|
|
356
|
+
"servicesDirectory": "services",
|
|
357
|
+
"stylesDirectory": "styles",
|
|
358
|
+
"assetsDirectory": "assets"
|
|
359
|
+
},
|
|
360
|
+
|
|
361
|
+
// === MARKDOWN DETECTOR ===
|
|
362
|
+
"detectorMarkdown": {
|
|
363
|
+
"checkProveniencia": true, // Verificar headers de proveniência
|
|
364
|
+
"checkLicenses": true, // Verificar compatibilidade de licença
|
|
365
|
+
"checkReferences": true, // Verificar referências externas
|
|
366
|
+
"headerLines": 30, // Linhas para scan de headers
|
|
367
|
+
"whitelist": {
|
|
368
|
+
"paths": [],
|
|
369
|
+
"patterns": [],
|
|
370
|
+
"dirs": []
|
|
371
|
+
},
|
|
372
|
+
"whitelistMode": "merge" // merge | replace
|
|
373
|
+
},
|
|
374
|
+
|
|
375
|
+
// === SEGURANÇA ===
|
|
376
|
+
"SAFE_MODE": true, // Modo seguro
|
|
377
|
+
"ALLOW_PLUGINS": false, // Permitir carregamento de plugins
|
|
378
|
+
"ALLOW_EXEC": false, // Permitir execução de código
|
|
379
|
+
"ALLOW_MUTATE_FS": true, // Permitir mutação do filesystem
|
|
380
|
+
|
|
381
|
+
// === AUTO-FIX ===
|
|
382
|
+
"autoFix": { // Configuração de correção automática
|
|
383
|
+
"mode": "balanced", // balanced | conservative | aggressive
|
|
384
|
+
"minConfidence": 75, // Confiança mínima (0-100)
|
|
385
|
+
"maxFixesPerArquivo": 5, // Máx correções por arquivo
|
|
386
|
+
"createBackup": true, // Criar backup (.local.bak)
|
|
387
|
+
"validateAfterFix": true, // Validar após correção
|
|
388
|
+
"allowedCategories": [
|
|
389
|
+
"security", "performance", "style", "documentation"
|
|
390
|
+
]
|
|
239
391
|
}
|
|
240
392
|
}
|
|
241
393
|
```
|
|
@@ -244,14 +396,76 @@ O Mahoraga lê um arquivo `mahoraga.config.json` na raiz do seu projeto (ou vari
|
|
|
244
396
|
|
|
245
397
|
| Variável | Descrição | Padrão |
|
|
246
398
|
|----------|-----------|--------|
|
|
247
|
-
| `LOG_LEVEL` | Nível de log | `info` |
|
|
248
|
-
| `LOG_ESTRUTURADO` | Logs em JSON | `false` |
|
|
249
|
-
| `MAHORAGA_DEBUG` |
|
|
399
|
+
| `LOG_LEVEL` | Nível de log (`erro`, `aviso`, `info`, `debug`) | `info` |
|
|
400
|
+
| `LOG_ESTRUTURADO` | Logs em JSON estruturado | `false` |
|
|
401
|
+
| `MAHORAGA_DEBUG` | Ativa modo debug | não definido |
|
|
250
402
|
| `MAHORAGA_STATE_DIR` | Diretório de estado | `.mahoraga` |
|
|
251
|
-
| `
|
|
252
|
-
| `
|
|
253
|
-
| `
|
|
254
|
-
| `
|
|
403
|
+
| `MAHORAGA_VERBOSE` | Saída verbosa | `false` |
|
|
404
|
+
| `MAHORAGA_SAFE_MODE` | Modo segurança (`0` desativa) | `1` |
|
|
405
|
+
| `MAHORAGA_ALLOW_PLUGINS` | Permite plugins (`1` ativa) | `0` |
|
|
406
|
+
| `MAHORAGA_ALLOW_EXEC` | Permite execução (`1` ativa) | `0` |
|
|
407
|
+
| `MAHORAGA_DEV` | Ativa modo dev | não definido |
|
|
408
|
+
|
|
409
|
+
---
|
|
410
|
+
|
|
411
|
+
## Supressão Inline (`@mahoraga-disable`)
|
|
412
|
+
|
|
413
|
+
Além da supressão por configuração, o Mahoraga suporta **supressão inline** via comentários no código fonte. Funciona tanto para analistas quanto para o formatador.
|
|
414
|
+
|
|
415
|
+
### Formatos
|
|
416
|
+
|
|
417
|
+
| Diretiva | Escopo | Exemplo |
|
|
418
|
+
|----------|--------|---------|
|
|
419
|
+
| `@mahoraga-disable-next-line <regras>` | Próxima linha | `// @mahoraga-disable-next-line pontuacao-repetida` |
|
|
420
|
+
| `@mahoraga-disable <regras>` | Bloco (até `@mahoraga-enable`) | `// @mahoraga-disable formatador` |
|
|
421
|
+
| `@mahoraga-enable <regras>` | Fim de bloco | `// @mahoraga-enable formatador` |
|
|
422
|
+
| `@mahoraga-disable-all` | Bloco total | `// @mahoraga-disable-all` |
|
|
423
|
+
| `@mahoraga-enable-all` | Fim de bloco total | `// @mahoraga-enable-all` |
|
|
424
|
+
|
|
425
|
+
### Sintaxes de comentário suportadas
|
|
426
|
+
|
|
427
|
+
| Linguagem | Sintaxe |
|
|
428
|
+
|-----------|---------|
|
|
429
|
+
| JS/TS/CSS | `// @mahoraga-disable regra` / `/* @mahoraga-disable regra */` |
|
|
430
|
+
| Python/Shell/YAML | `# @mahoraga-disable regra` |
|
|
431
|
+
| SQL | `-- @mahoraga-disable regra` |
|
|
432
|
+
| INI | `; @mahoraga-disable regra` |
|
|
433
|
+
| HTML | `<!-- @mahoraga-disable regra -->` |
|
|
434
|
+
|
|
435
|
+
### Regras do formatador
|
|
436
|
+
|
|
437
|
+
| Regra | Efeito |
|
|
438
|
+
|-------|--------|
|
|
439
|
+
| `pontuacao-repetida` | Impede colapso de pontuação repetida (`;;`, ` ...`, etc.) |
|
|
440
|
+
| `espacamento-incorreto` | Impede correção de espaçamento ao redor de pontuação |
|
|
441
|
+
| `formatador` | Desativa todas as correções do formatador na linha/bloco |
|
|
442
|
+
| `analista-formatador` | Desativa apenas o analista de verificação de formatação |
|
|
443
|
+
| `*` | Desativa regras de todos os sistemas |
|
|
444
|
+
|
|
445
|
+
### Exemplos
|
|
446
|
+
|
|
447
|
+
```typescript
|
|
448
|
+
// @mahoraga-disable-next-line pontuacao-repetida
|
|
449
|
+
const x = a;; // <-- os dois ;; serão preservados
|
|
450
|
+
|
|
451
|
+
// @mahoraga-disable formatador
|
|
452
|
+
function exemplo() {
|
|
453
|
+
const url = "https://example.com/path?v=1&x=2";
|
|
454
|
+
return url;
|
|
455
|
+
}
|
|
456
|
+
// @mahoraga-enable formatador
|
|
457
|
+
```
|
|
458
|
+
|
|
459
|
+
```bash
|
|
460
|
+
# @mahoraga-disable-next-line espacamento-incorreto
|
|
461
|
+
case $x in a) echo "a" ;; esac # <-- ;; preservado
|
|
462
|
+
```
|
|
463
|
+
|
|
464
|
+
```html
|
|
465
|
+
<!-- @mahoraga-disable formatador -->
|
|
466
|
+
<pre> texto com espaços intencionais </pre>
|
|
467
|
+
<!-- @mahoraga-enable formatador -->
|
|
468
|
+
```
|
|
255
469
|
|
|
256
470
|
---
|
|
257
471
|
|
|
@@ -274,8 +488,12 @@ npm run lint # ESLint
|
|
|
274
488
|
|-----------|--------|---------|
|
|
275
489
|
| JavaScript | Babel | Nativo |
|
|
276
490
|
| TypeScript | Babel | Nativo |
|
|
491
|
+
| React/JSX | Babel | Nativo |
|
|
277
492
|
| HTML | htmlparser2 | Nativo |
|
|
278
493
|
| CSS | postcss | Nativo |
|
|
494
|
+
| CSS-in-JS | postcss | Nativo |
|
|
495
|
+
| Tailwind CSS | Heurístico | Nativo |
|
|
496
|
+
| SVG | Heurístico | Nativo |
|
|
279
497
|
| XML | fast-xml-parser | Nativo |
|
|
280
498
|
| Python | Heurístico | Nativo |
|
|
281
499
|
| PHP | Heurístico | Nativo |
|
|
@@ -288,12 +506,27 @@ npm run lint # ESLint
|
|
|
288
506
|
|
|
289
507
|
## Qualidade
|
|
290
508
|
|
|
291
|
-
- TypeScript
|
|
292
|
-
- Testes com Vitest
|
|
293
|
-
- ESLint 10.x
|
|
294
|
-
- Worker pool
|
|
295
|
-
- i18n
|
|
296
|
-
- Schema versioning
|
|
509
|
+
- **TypeScript estrito**: `strict: true`, `verbatimModuleSyntax: true`
|
|
510
|
+
- **Testes com Vitest**: ~3200 testes em ~230 arquivos
|
|
511
|
+
- **ESLint 10.x**: configuração strict
|
|
512
|
+
- **Worker pool**: processamento paralelo
|
|
513
|
+
- **i18n**: PT, EN, ZH, JA
|
|
514
|
+
- **Schema versioning**: relatórios versionados
|
|
515
|
+
- **Documentação viva**: `Docs/` em formato Obsidian vault
|
|
516
|
+
|
|
517
|
+
---
|
|
518
|
+
|
|
519
|
+
## Documentação
|
|
520
|
+
|
|
521
|
+
A documentação completa do projeto está disponível em `Docs/` no formato **Obsidian vault**:
|
|
522
|
+
|
|
523
|
+
- **Arquitetura**: camadas, fluxos, diagramas, ADRs
|
|
524
|
+
- **Componentes**: documentação de todos os módulos
|
|
525
|
+
- **Guias**: contribuição, testes, referência de comandos
|
|
526
|
+
- **Glossário**: termos do domínio de A a Z
|
|
527
|
+
- **Referências**: links, specs, configurações
|
|
528
|
+
|
|
529
|
+
Abra `Docs/` como vault no [Obsidian](https://obsidian.md/) para navegação completa com wikilinks.
|
|
297
530
|
|
|
298
531
|
---
|
|
299
532
|
|
|
@@ -301,7 +534,7 @@ npm run lint # ESLint
|
|
|
301
534
|
|
|
302
535
|
Contribuições são bem-vindas! Como o projeto não está mais no GitHub:
|
|
303
536
|
|
|
304
|
-
1. Entre em contato pelo e-mail:
|
|
537
|
+
1. Entre em contato pelo e-mail: [ProtonMail](mailto:mahoraga.able522@passfwd.com)
|
|
305
538
|
2. Envie patches ou sugestões por e-mail
|
|
306
539
|
3. Reporte bugs com descrição detalhada e exemplo mínimo
|
|
307
540
|
|
|
@@ -40,53 +40,64 @@ function extractHookCallContent(src, startIndex) {
|
|
|
40
40
|
const char = src[i];
|
|
41
41
|
if (escaped) {
|
|
42
42
|
escaped = false;
|
|
43
|
-
if (started)
|
|
43
|
+
if (started) {
|
|
44
44
|
content += char;
|
|
45
|
+
}
|
|
45
46
|
continue;
|
|
46
47
|
}
|
|
47
48
|
if (char === '\\' && (inSingle || inDouble || inBacktick)) {
|
|
48
49
|
escaped = true;
|
|
49
|
-
if (started)
|
|
50
|
+
if (started) {
|
|
50
51
|
content += char;
|
|
52
|
+
}
|
|
51
53
|
continue;
|
|
52
54
|
}
|
|
53
55
|
if (inSingle) {
|
|
54
|
-
if (char === "'")
|
|
56
|
+
if (char === "'") {
|
|
55
57
|
inSingle = false;
|
|
56
|
-
|
|
58
|
+
}
|
|
59
|
+
if (started) {
|
|
57
60
|
content += char;
|
|
61
|
+
}
|
|
58
62
|
continue;
|
|
59
63
|
}
|
|
60
64
|
if (inDouble) {
|
|
61
|
-
if (char === '"')
|
|
65
|
+
if (char === '"') {
|
|
62
66
|
inDouble = false;
|
|
63
|
-
|
|
67
|
+
}
|
|
68
|
+
if (started) {
|
|
64
69
|
content += char;
|
|
70
|
+
}
|
|
65
71
|
continue;
|
|
66
72
|
}
|
|
67
73
|
if (inBacktick) {
|
|
68
|
-
if (char === '`')
|
|
74
|
+
if (char === '`') {
|
|
69
75
|
inBacktick = false;
|
|
70
|
-
|
|
76
|
+
}
|
|
77
|
+
if (started) {
|
|
71
78
|
content += char;
|
|
79
|
+
}
|
|
72
80
|
continue;
|
|
73
81
|
}
|
|
74
82
|
if (char === "'") {
|
|
75
83
|
inSingle = true;
|
|
76
|
-
if (started)
|
|
84
|
+
if (started) {
|
|
77
85
|
content += char;
|
|
86
|
+
}
|
|
78
87
|
continue;
|
|
79
88
|
}
|
|
80
89
|
if (char === '"') {
|
|
81
90
|
inDouble = true;
|
|
82
|
-
if (started)
|
|
91
|
+
if (started) {
|
|
83
92
|
content += char;
|
|
93
|
+
}
|
|
84
94
|
continue;
|
|
85
95
|
}
|
|
86
96
|
if (char === '`') {
|
|
87
97
|
inBacktick = true;
|
|
88
|
-
if (started)
|
|
98
|
+
if (started) {
|
|
89
99
|
content += char;
|
|
100
|
+
}
|
|
90
101
|
continue;
|
|
91
102
|
}
|
|
92
103
|
if (char === '(') {
|
|
@@ -116,15 +127,18 @@ function collectHookIssues(src, relPath, opts = {}) {
|
|
|
116
127
|
const fullCall = extractHookCallContent(src, hookInicio + m[0].length - 1);
|
|
117
128
|
const hasDepsArg = (() => {
|
|
118
129
|
const lastClosing = fullCall.lastIndexOf(')');
|
|
119
|
-
if (lastClosing === -1)
|
|
130
|
+
if (lastClosing === -1) {
|
|
120
131
|
return false;
|
|
132
|
+
}
|
|
121
133
|
const beforeClosing = fullCall.slice(0, lastClosing);
|
|
122
134
|
const arrayMatch = beforeClosing.match(/,\s*(\[[\s\S]*?\])\s*$/);
|
|
123
|
-
if (arrayMatch)
|
|
135
|
+
if (arrayMatch) {
|
|
124
136
|
return true;
|
|
137
|
+
}
|
|
125
138
|
const identMatch = beforeClosing.match(/,\s*(\w+)\s*$/);
|
|
126
|
-
if (identMatch)
|
|
139
|
+
if (identMatch) {
|
|
127
140
|
return true;
|
|
141
|
+
}
|
|
128
142
|
return false;
|
|
129
143
|
})();
|
|
130
144
|
const skip = /no-deps-ok|eslint-disable-next-line\s+react-hooks\/exhaustive-deps/i.test(fullCall);
|
|
@@ -159,8 +173,9 @@ function collectHookIssues(src, relPath, opts = {}) {
|
|
|
159
173
|
conditionalHooks.forEach(m => {
|
|
160
174
|
const line = lineOf(m.index || 0);
|
|
161
175
|
const pre = src.slice(Math.max(0, (m.index ?? 0) - 80), m.index ?? 0);
|
|
162
|
-
if (/=>\s*$|\)\s*=>\s*$|\)\s*\{[\s\S]{0,40}$/.test(pre))
|
|
176
|
+
if (/=>\s*$|\)\s*=>\s*$|\)\s*\{[\s\S]{0,40}$/.test(pre)) {
|
|
163
177
|
return;
|
|
178
|
+
}
|
|
164
179
|
ocorrencias.push(warn(messages.ReactHooksMensagens.hookInConditional, relPath, line));
|
|
165
180
|
});
|
|
166
181
|
}
|
|
@@ -34,8 +34,9 @@ function collectReactIssues(src, relPath) {
|
|
|
34
34
|
for (const match of src.matchAll(/dangerouslySetInnerHTML/gi)) {
|
|
35
35
|
const line = lineOf(match.index);
|
|
36
36
|
const lineContent = src.split('\n')[line - 1] ?? '';
|
|
37
|
-
if (/speculationrules/.test(lineContent))
|
|
37
|
+
if (/speculationrules/.test(lineContent)) {
|
|
38
38
|
continue;
|
|
39
|
+
}
|
|
39
40
|
ocorrencias.push(warn(messages.ReactMensagens.dangerouslySetInnerHTML, relPath, line));
|
|
40
41
|
}
|
|
41
42
|
for (const match of src.matchAll(/<img[^>]*>/gi)) {
|
|
@@ -214,8 +215,9 @@ function parseReactWithBabel(scan, relPath) {
|
|
|
214
215
|
if (findAttr(attrs, 'dangerouslySetInnerHTML')) {
|
|
215
216
|
if (tag.toLowerCase() === 'script') {
|
|
216
217
|
const typeAttr = findAttr(attrs, 'type');
|
|
217
|
-
if (typeAttr && /speculationrules/i.test(normalizeStringValue(typeAttr.value)))
|
|
218
|
+
if (typeAttr && /speculationrules/i.test(normalizeStringValue(typeAttr.value))) {
|
|
218
219
|
return;
|
|
220
|
+
}
|
|
219
221
|
}
|
|
220
222
|
pushOnce(warn(messages.ReactMensagens.dangerouslySetInnerHTML, relPath, locLine));
|
|
221
223
|
}
|
|
@@ -156,17 +156,20 @@ function detectWithBabel(src, relPath) {
|
|
|
156
156
|
const locLine = path.node.loc?.start.line;
|
|
157
157
|
if (isHookName(name)) {
|
|
158
158
|
const parent = (() => {
|
|
159
|
-
|
|
159
|
+
const currentPath = path;
|
|
160
160
|
while (currentPath) {
|
|
161
161
|
const found = currentPath.findParent(p => p.isIfStatement() || p.isConditionalExpression() || p.isLogicalExpression() || p.isSwitchStatement() || p.isSwitchCase() || p.isForStatement() || p.isWhileStatement() || p.isDoWhileStatement() || p.isLoop());
|
|
162
|
-
if (found)
|
|
162
|
+
if (found) {
|
|
163
163
|
return found;
|
|
164
|
+
}
|
|
164
165
|
const fnBoundary = currentPath.findParent(p => p.isFunction());
|
|
165
|
-
if (!fnBoundary)
|
|
166
|
+
if (!fnBoundary) {
|
|
166
167
|
return null;
|
|
168
|
+
}
|
|
167
169
|
const aboveFn = fnBoundary.findParent(p => p.isIfStatement() || p.isConditionalExpression() || p.isLogicalExpression() || p.isSwitchStatement() || p.isSwitchCase() || p.isForStatement() || p.isWhileStatement() || p.isDoWhileStatement() || p.isLoop());
|
|
168
|
-
if (aboveFn)
|
|
170
|
+
if (aboveFn) {
|
|
169
171
|
return aboveFn;
|
|
172
|
+
}
|
|
170
173
|
return null;
|
|
171
174
|
}
|
|
172
175
|
return null;
|
|
@@ -111,15 +111,6 @@ const PADRAO_ALIAS_CONFIGURACAO = {
|
|
|
111
111
|
"@api/routes": "./src/api/routes/index.ts",
|
|
112
112
|
"@api/server": "./src/api/server.ts",
|
|
113
113
|
"@api/services": "./src/api/services/index.ts",
|
|
114
|
-
"@app": "./src/app/index.ts",
|
|
115
|
-
"@app/changelog": "./src/app/changelog/index.ts",
|
|
116
|
-
"@app/github": "./src/app/github/app/index.ts",
|
|
117
|
-
"@app/github/app": "./src/app/github/app/index.ts",
|
|
118
|
-
"@app/github/dashboard": "./src/app/github/dashboard/index.ts",
|
|
119
|
-
"@app/github/jobs": "./src/app/github/jobs/index.ts",
|
|
120
|
-
"@app/github/push-analysis": "./src/app/github/push-analysis/index.ts",
|
|
121
|
-
"@app/privacy-policy": "./src/app/privacy-policy/index.ts",
|
|
122
|
-
"@app/terms-of-use": "./src/app/terms-of-use/index.ts",
|
|
123
114
|
"@caretakers": "./src/caretakers/index.ts",
|
|
124
115
|
"@cli": "./src/cli/index.ts",
|
|
125
116
|
"@cli/commands": "./src/cli/commands/index.ts",
|
|
@@ -7,7 +7,6 @@ import { aplicarCorrecoes, salvarArquivoCorrigido } from '../../core/execution/i
|
|
|
7
7
|
import { CliComandoGithubActionsMensagens, messages } from '../../core/messages/index.js';
|
|
8
8
|
import { analistaGithubActions, analistaGithubActionsGlobal, autofixEngine, gerarRelatorio, obterDetectoresGithubActions, pontuarWorkflow, prepararDadosRelatorio } from '../../analysts/github-actions/index.js';
|
|
9
9
|
import { ExitCode, sair } from '../helpers/index.js';
|
|
10
|
-
import { iniciarServidorApp } from '../../app/github.js';
|
|
11
10
|
const SCORE_MAX = 100;
|
|
12
11
|
const SCORE_MIN = 0;
|
|
13
12
|
const PENALTY_PER_OCCURRENCE = 5;
|
|
@@ -348,31 +347,5 @@ export function comandoGithubActions() {
|
|
|
348
347
|
sair(ExitCode.Failure);
|
|
349
348
|
}
|
|
350
349
|
});
|
|
351
|
-
cmd.command('app').description(CliComandoGithubActionsMensagens.descricaoApp)
|
|
352
|
-
.option('-p, --port <number>', 'Porta do servidor', (process.env.MAHORAGA_API_PORT ?? process.env.PORT) ?? '3000')
|
|
353
|
-
.action(async (opts) => {
|
|
354
|
-
const appId = process.env.GITHUB_APP_ID;
|
|
355
|
-
const privateKey = process.env.GITHUB_PRIVATE_KEY;
|
|
356
|
-
const webhookSecret = process.env.GITHUB_WEBHOOK_SECRET;
|
|
357
|
-
if (!appId || !privateKey || !webhookSecret) {
|
|
358
|
-
log.erro(CliComandoGithubActionsMensagens.appSetupRequired);
|
|
359
|
-
log.erro(CliComandoGithubActionsMensagens.appSetupEnvList);
|
|
360
|
-
log.info(CliComandoGithubActionsMensagens.appDicaEnv);
|
|
361
|
-
sair(ExitCode.Failure);
|
|
362
|
-
return;
|
|
363
|
-
}
|
|
364
|
-
try {
|
|
365
|
-
await iniciarServidorApp({
|
|
366
|
-
appId,
|
|
367
|
-
privateKey: privateKey.replace(/\\n/g, '\n'),
|
|
368
|
-
webhookSecret,
|
|
369
|
-
port: parseInt(opts.port, 10),
|
|
370
|
-
});
|
|
371
|
-
}
|
|
372
|
-
catch (err) {
|
|
373
|
-
log.erro(CliComandoGithubActionsMensagens.erroIniciarServidor(err instanceof Error ? err.message : String(err)));
|
|
374
|
-
sair(ExitCode.Failure);
|
|
375
|
-
}
|
|
376
|
-
});
|
|
377
350
|
return cmd;
|
|
378
351
|
}
|
|
@@ -3,7 +3,6 @@ export const CliComandoGithubActionsMensagens = {
|
|
|
3
3
|
descricaoScan: 'Analyzes GitHub Actions workflows',
|
|
4
4
|
descricaoReport: 'Generates workflow analysis report',
|
|
5
5
|
descricaoGate: 'Quality gate for CI/CD - fails if score below threshold',
|
|
6
|
-
descricaoApp: 'Starts the server to act as a GitHub App',
|
|
7
6
|
optPath: 'Path to repository',
|
|
8
7
|
optWorkflow: 'Analyze specific workflow',
|
|
9
8
|
optFix: 'Automatically applies fixes when possible',
|
|
@@ -35,8 +34,4 @@ export const CliComandoGithubActionsMensagens = {
|
|
|
35
34
|
gatePassou: (score, threshold) => `[OK] Gate passed! Score: ${score}/100 (threshold: ${threshold})`,
|
|
36
35
|
gateFalhou: (score, threshold) => `[ERR] Gate failed! Score: ${score}/100 (threshold: ${threshold})`,
|
|
37
36
|
gateFalhaMotivo: (motivo) => ` - ${motivo}`,
|
|
38
|
-
appSetupRequired: 'To start the GitHub App, you need to configure the environment variables:',
|
|
39
|
-
appSetupEnvList: ' - GITHUB_APP_ID\n - GITHUB_PRIVATE_KEY\n - GITHUB_WEBHOOK_SECRET',
|
|
40
|
-
appDicaEnv: '\nTip: Create a .env file in the root with these variables.',
|
|
41
|
-
erroIniciarServidor: (msg) => `Failed to start server: ${msg}`,
|
|
42
37
|
};
|
|
@@ -3,7 +3,6 @@ export const CliComandoGithubActionsMensagens = {
|
|
|
3
3
|
descricaoScan: 'GitHub Actions ワークフローを分析',
|
|
4
4
|
descricaoReport: 'ワークフロー分析レポートを生成',
|
|
5
5
|
descricaoGate: 'CI/CD 品質ゲート - スコアがしきい値を下回ると失敗',
|
|
6
|
-
descricaoApp: 'GitHub Appとして動作するサーバーを起動',
|
|
7
6
|
optPath: 'リポジトリへのパス',
|
|
8
7
|
optWorkflow: '特定のワークフローを分析',
|
|
9
8
|
optFix: '可能な場合に自動的に修正を適用',
|
|
@@ -35,8 +34,4 @@ export const CliComandoGithubActionsMensagens = {
|
|
|
35
34
|
gatePassou: (score, threshold) => `[OK] 品質ゲート通過! スコア: ${score}/100 (しきい値: ${threshold})`,
|
|
36
35
|
gateFalhou: (score, threshold) => `[エラー] 品質ゲート失敗! スコア: ${score}/100 (しきい値: ${threshold})`,
|
|
37
36
|
gateFalhaMotivo: (motivo) => ` - ${motivo}`,
|
|
38
|
-
appSetupRequired: 'GitHub Appを起動するには、環境変数を設定する必要があります:',
|
|
39
|
-
appSetupEnvList: ' - GITHUB_APP_ID\n - GITHUB_PRIVATE_KEY\n - GITHUB_WEBHOOK_SECRET',
|
|
40
|
-
appDicaEnv: '\nヒント: ルートに .env ファイルを作成し、これらの変数を設定してください。',
|
|
41
|
-
erroIniciarServidor: (msg) => `サーバー起動エラー: ${msg}`,
|
|
42
37
|
};
|