@mocoto/mahoraga 0.14.1 → 0.14.3
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 +0 -34
- package/dist/analysts/architects/analyst-structure.js +20 -20
- package/dist/analysts/architects/archetypes-custom.js +16 -19
- package/dist/analysts/architects/detector-archetypes.js +43 -36
- package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
- package/dist/analysts/architects/signals-project-advanced.js +26 -28
- package/dist/analysts/architects/signals-project.js +2 -2
- package/dist/analysts/architects/strategist-structure.js +47 -66
- package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +41 -35
- package/dist/analysts/azure-pipelines/corrections/correction-azure.js +22 -19
- package/dist/analysts/azure-pipelines/detectors/detector-azure-performance.js +21 -18
- package/dist/analysts/azure-pipelines/detectors/detector-azure-security.js +25 -20
- package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +39 -40
- package/dist/analysts/azure-pipelines/scorers/scorer-azure.js +10 -7
- package/dist/analysts/circleci/analysts/analyst-circleci.js +33 -27
- package/dist/analysts/circleci/corrections/correction-circleci.js +22 -20
- package/dist/analysts/circleci/detectors/detector-circleci-performance.js +23 -19
- package/dist/analysts/circleci/detectors/detector-circleci-security.js +78 -82
- package/dist/analysts/circleci/detectors/detector-circleci-structure.js +22 -22
- package/dist/analysts/converters/convert-registry.js +1 -1
- package/dist/analysts/converters/engines/converter-gha-to-gitlab.js +17 -15
- package/dist/analysts/converters/index.js +1 -1
- package/dist/analysts/corrections/analyst-quick-fixes.js +25 -28
- package/dist/analysts/corrections/analyst-scoring.js +24 -21
- package/dist/analysts/corrections/auto-fix-engine.js +1 -1
- package/dist/analysts/corrections/corrector-structure.js +43 -42
- package/dist/analysts/corrections/fix-alias-imports.js +10 -6
- package/dist/analysts/corrections/fix-md-fences.js +23 -23
- package/dist/analysts/corrections/map-reversion.js +56 -53
- package/dist/analysts/corrections/pruning.js +19 -16
- package/dist/analysts/corrections/quick-fixes/fix-any-to-proper-type.js +57 -61
- package/dist/analysts/corrections/quick-fixes/fix-unknown-to-specific-type.js +30 -30
- package/dist/analysts/corrections/reorganize-barrels.js +13 -13
- package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
- package/dist/analysts/corrections/scoring-shared.js +19 -18
- package/dist/analysts/corrections/type-safety/context-analyzer.js +15 -10
- package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
- package/dist/analysts/corrections/type-safety/type-validator.js +4 -3
- package/dist/analysts/corrections/type-safety/usage-analyzer.js +39 -42
- package/dist/analysts/css/analysts/analyst-css.js +42 -42
- package/dist/analysts/css/corrections/correction-css.js +19 -11
- package/dist/analysts/css/detectors/detector-css-best-practices.js +129 -118
- package/dist/analysts/css/scorers/scorer-css.js +23 -18
- package/dist/analysts/css-in-js/analysts/analyst-css-in-js.js +24 -17
- package/dist/analysts/css-in-js/corrections/correction-css-in-js.js +31 -16
- package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +28 -30
- package/dist/analysts/css-in-js/scorers/scorer-css-in-js.js +79 -54
- package/dist/analysts/css-in-js/shared.js +7 -0
- package/dist/analysts/detectors/detector-architecture.js +91 -85
- package/dist/analysts/detectors/detector-bugs-ml.js +29 -27
- package/dist/analysts/detectors/detector-code-fragile.js +41 -36
- package/dist/analysts/detectors/detector-dependencies.js +5 -5
- package/dist/analysts/detectors/detector-duplications.js +26 -26
- package/dist/analysts/detectors/detector-monorepo.js +51 -45
- package/dist/analysts/detectors/detector-performance.js +24 -17
- package/dist/analysts/detectors/detector-recommendation-architecture.js +40 -36
- package/dist/analysts/detectors/detector-security.js +43 -42
- package/dist/analysts/detectors/detector-structure.js +31 -28
- package/dist/analysts/github-actions/analysts/analyst-github-actions.js +5 -8
- package/dist/analysts/github-actions/detectors/detector-workflow-accessibility.js +1 -9
- package/dist/analysts/github-actions/detectors/detector-workflow-structure.js +1 -4
- package/dist/analysts/github-actions/detectors/detector-workflow-trigger-unsafe.js +6 -5
- package/dist/analysts/gitlab-ci/analysts/analyst-gitlab-ci.js +2 -2
- package/dist/analysts/gitlab-ci/detectors/detector-gitlab-ci-structure.js +0 -3
- package/dist/analysts/go/analysts/analyst-best-practices.js +2 -2
- package/dist/analysts/go/analysts/analyst-concurrency.js +1 -1
- package/dist/analysts/go/analysts/analyst-security.js +1 -1
- package/dist/analysts/go/detectors/detector-conventions.js +1 -1
- package/dist/analysts/html/analysts/analyst-html.js +10 -12
- package/dist/analysts/html/detectors/detector-html.js +3 -3
- package/dist/analysts/js-ts/analysts/analyst-commands-cli.js +22 -22
- package/dist/analysts/js-ts/analysts/analyst-functions-long.js +5 -5
- package/dist/analysts/js-ts/analysts/analyst-patterns-usage.js +6 -2
- package/dist/analysts/js-ts/detectors/detector-anti-patterns-async.js +84 -9
- package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +33 -10
- package/dist/analysts/js-ts/detectors/detector-context-smart.js +6 -6
- package/dist/analysts/js-ts/detectors/detector-leaks-memory.js +1 -1
- package/dist/analysts/js-ts/detectors/detector-types-unsafe.js +33 -2
- package/dist/analysts/php/analysts/analyst-php.js +3 -3
- package/dist/analysts/php/detectors/detector-php-best-practices.js +5 -5
- package/dist/analysts/php/detectors/detector-php-security.js +5 -5
- package/dist/analysts/php/scorers/scorer-php.js +2 -2
- package/dist/analysts/plugins/detector-documentation.js +6 -6
- package/dist/analysts/plugins/detector-markdown.js +7 -7
- package/dist/analysts/python/analysts/analyst-python.js +2 -5
- package/dist/analysts/react/analysts/analyst-react-hooks.js +66 -9
- package/dist/analysts/react/analysts/analyst-react.js +46 -2
- package/dist/analysts/react/corrections/correction-react.js +41 -1
- package/dist/analysts/react/detectors/detector-react-best-practices.js +5 -5
- package/dist/analysts/react/scorers/scorer-react.js +36 -1
- package/dist/analysts/registry/autodiscovery.js +2 -2
- package/dist/analysts/rust/analysts/analyst-best-practices.js +42 -3
- package/dist/analysts/rust/analysts/analyst-memory.js +2 -2
- package/dist/analysts/rust/analysts/analyst-rust.js +52 -5
- package/dist/analysts/rust/analysts/analyst-security.js +29 -1
- package/dist/analysts/scorers/scorer.js +5 -5
- package/dist/analysts/shell/analysts/analyst-shell.js +81 -5
- package/dist/analysts/shell/corrections/correction-shell.js +34 -1
- package/dist/analysts/shell/detectors/detector-shell-security.js +88 -0
- package/dist/analysts/shell/scorers/scorer-shell.js +58 -1
- package/dist/analysts/strategists/operator-structure.js +5 -7
- package/dist/analysts/strategists/suggestions-contextuais.js +5 -2
- package/dist/analysts/svg/analysts/analyst-svg.js +1 -0
- package/dist/analysts/tailwind/analysts/analyst-tailwind.js +79 -55
- package/dist/analysts/tailwind/corrections/correction-tailwind.js +108 -9
- package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
- package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -11
- package/dist/analysts/xml/analysts/analyst-xml.js +2 -2
- package/dist/app/index.js +1 -0
- package/dist/bin/cli-bootstrap.js +6 -4
- package/dist/bin/index.js +6 -4
- package/dist/caretakers/scoring.js +1 -0
- package/dist/cli/commands/command-analysts.js +4 -3
- package/dist/cli/commands/command-azure.js +1 -1
- package/dist/cli/commands/command-circleci.js +1 -1
- package/dist/cli/commands/command-compliance.js +1 -1
- package/dist/cli/commands/command-diagnose.js +10 -13
- package/dist/cli/commands/command-fix-types.js +9 -32
- package/dist/cli/commands/command-formatters.js +2 -2
- package/dist/cli/commands/command-github-actions.js +1 -1
- package/dist/cli/commands/command-gitlab-ci.js +1 -1
- package/dist/cli/commands/command-guardian.js +1 -1
- package/dist/cli/commands/command-imports.js +6 -6
- package/dist/cli/commands/command-jenkins.js +1 -1
- package/dist/cli/commands/command-licenses.js +1 -1
- package/dist/cli/commands/command-marketplace.js +7 -7
- package/dist/cli/commands/command-names.js +3 -8
- package/dist/cli/commands/command-perf.js +7 -9
- package/dist/cli/commands/command-plugins.js +4 -4
- package/dist/cli/diagnostic/auto-fix.js +2 -2
- package/dist/cli/diagnostic/exporters/json-exporter.js +1 -1
- package/dist/cli/diagnostic/exporters/sharded-exporter.js +0 -3
- package/dist/cli/diagnostic/exporters/svg-optimization-exporter.js +1 -1
- package/dist/cli/diagnostic/filters.js +9 -9
- package/dist/cli/diagnostic/handlers/archetype-handler.js +3 -6
- package/dist/cli/diagnostic/handlers/auto-fix-handler.js +4 -4
- package/dist/cli/diagnostic/handlers/guardian-handler.js +1 -1
- package/dist/cli/diagnostic/processing-diagnostic.js +31 -35
- package/dist/cli/diagnostic/processing-helpers.js +2 -2
- package/dist/cli/handlers/fix-types-exporter.js +1 -4
- package/dist/cli/helpers/display-frame.js +5 -5
- package/dist/core/config/auto/auto-fix-config.js +0 -6
- package/dist/core/config/chalk-safe.js +6 -6
- package/dist/core/config/config.js +11 -13
- package/dist/core/config/conventions.js +1 -1
- package/dist/core/config/security.js +2 -2
- package/dist/core/execution/analysis-cache.js +5 -8
- package/dist/core/execution/ast-cache.js +1 -3
- package/dist/core/execution/executor.js +8 -21
- package/dist/core/execution/inquisitor.js +24 -21
- package/dist/core/execution/results.js +1 -0
- package/dist/core/execution/scanner.js +4 -4
- package/dist/core/messages/en/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/en/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/en/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/en/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/en/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/en/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/en/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/en/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/en/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/en/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/en/core/plugin-messages.js +31 -3
- package/dist/core/messages/en/log/log.js +4 -4
- package/dist/core/messages/en/ui/filter-config.js +1 -5
- package/dist/core/messages/i18n-system.js +3 -3
- package/dist/core/messages/index.js +3 -3
- package/dist/core/messages/ja/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/ja/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/ja/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/ja/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/ja/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/ja/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/ja/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/ja/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/ja/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/ja/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/ja/core/plugin-messages.js +31 -3
- package/dist/core/messages/ja/log/log.js +4 -4
- package/dist/core/messages/ja/ui/filter-config.js +1 -1
- package/dist/core/messages/pt/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/pt/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/pt/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/pt/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/pt/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/pt/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/pt/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/pt/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/pt/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/pt/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/pt/core/plugin-messages.js +31 -3
- package/dist/core/messages/pt/log/log-engine.js +6 -6
- package/dist/core/messages/pt/log/log.js +3 -3
- package/dist/core/messages/pt/ui/filter-config.js +1 -1
- package/dist/core/messages/shared/icons.js +3 -3
- package/dist/core/messages/zh/analysts/analyst-github-actions-messages.js +1 -1
- package/dist/core/messages/zh/analysts/analyst-patterns-usage-messages.js +1 -0
- package/dist/core/messages/zh/analysts/analyst-shell-messages.js +15 -0
- package/dist/core/messages/zh/analysts/detector-constructions-syntactic-messages.js +6 -0
- package/dist/core/messages/zh/analysts/detector-js-ts-messages.js +27 -0
- package/dist/core/messages/zh/analysts/detector-react-messages.js +8 -0
- package/dist/core/messages/zh/analysts/detector-shell-messages.js +17 -0
- package/dist/core/messages/zh/analysts/detector-tailwind-messages.js +3 -3
- package/dist/core/messages/zh/analysts/report-circleci-messages.js +7 -7
- package/dist/core/messages/zh/caretakers/caretaker-messages.js +1 -7
- package/dist/core/messages/zh/core/plugin-messages.js +31 -3
- package/dist/core/messages/zh/log/log.js +3 -3
- package/dist/core/messages/zh/ui/filter-config.js +1 -5
- package/dist/core/parsing/filters.js +3 -3
- package/dist/core/parsing/langs/json.js +1 -1
- package/dist/core/parsing/langs/python.js +1 -1
- package/dist/core/parsing/langs/typescript.js +1 -1
- package/dist/core/parsing/parser.js +3 -4
- package/dist/core/parsing/utils.js +1 -0
- package/dist/core/registry/file-registry.js +3 -2
- package/dist/core/registry/paths.js +3 -3
- package/dist/core/reporting/default-reporter.js +2 -2
- package/dist/core/schema/version.js +6 -6
- package/dist/core/workers/worker-executor.js +3 -3
- package/dist/core/workers/worker-pool.js +0 -0
- package/dist/guardian/baseline.js +1 -1
- package/dist/guardian/gpg.js +3 -1
- package/dist/guardian/integrity.js +2 -7
- package/dist/guardian/records.js +7 -1
- package/dist/guardian/result.js +1 -1
- package/dist/guardian/sentinel.js +7 -1
- package/dist/guardian/watcher-hidden.js +6 -1
- package/dist/licenses/fs-utils.js +5 -1
- package/dist/licenses/generate-notices.js +1 -1
- package/dist/licenses/index.js +1 -0
- package/dist/licenses/normalizer.js +10 -9
- package/dist/node.loader.js +224 -4
- package/dist/reports/analise-async-patterns.js +1 -1
- package/dist/reports/filter-smart.js +2 -5
- package/dist/reports/generator-report.js +7 -7
- package/dist/reports/report-archetypes.js +10 -10
- package/dist/reports/report-caretaker-health.js +2 -1
- package/dist/reports/report-patterns-usage.js +1 -1
- package/dist/sdk/analyzer.js +1 -1
- package/dist/shared/data-processing/fragment-report.js +11 -11
- package/dist/shared/data-processing/json.js +1 -1
- package/dist/shared/data-processing/occurrences.js +3 -2
- package/dist/shared/formatters/code-min-formatter.js +1 -1
- package/dist/shared/formatters/engines/prettier.js +1 -1
- package/dist/shared/formatters/engines/stylelint.js +43 -40
- package/dist/shared/formatters/formatter.js +8 -8
- package/dist/shared/formatters/formatters/code.js +3 -3
- package/dist/shared/formatters/formatters/css.js +2 -10
- package/dist/shared/formatters/formatters/dotfiles.js +1 -1
- package/dist/shared/formatters/formatters/html.js +1 -5
- package/dist/shared/formatters/formatters/json.js +0 -3
- package/dist/shared/formatters/formatters/markdown.js +19 -24
- package/dist/shared/formatters/formatters/properties.js +2 -2
- package/dist/shared/formatters/formatters/shell.js +1 -4
- package/dist/shared/formatters/formatters/sql.js +0 -3
- package/dist/shared/formatters/formatters/xml.js +5 -7
- package/dist/shared/formatters/formatters/yaml.js +2 -7
- package/dist/shared/formatters/index.js +1 -1
- package/dist/shared/helpers/framework-detector.js +6 -2
- package/dist/shared/helpers/json.js +1 -1
- package/dist/shared/helpers/magic-constants-whitelist.js +1 -1
- package/dist/shared/helpers/masking.js +17 -17
- package/dist/shared/helpers/reader-report.js +0 -12
- package/dist/shared/helpers/structural-hash.js +3 -2
- package/dist/shared/helpers/structure.js +1 -1
- package/dist/shared/marketplace/registry.js +1 -1
- package/dist/shared/marketplace/remote.js +4 -4
- package/dist/shared/persistence/persistence.js +13 -6
- package/dist/shared/plugins/core-plugin.js +5 -1
- package/dist/shared/plugins/registry.js +3 -2
- package/dist/types/analysts/tailwind-correction.js +2 -0
- package/dist/types/caretakers/imports-barrel.js +1 -0
- package/dist/types/caretakers/index.js +4 -0
- package/dist/types/caretakers/map-reversion.js +1 -0
- package/dist/types/caretakers/pruning.js +1 -0
- package/dist/types/caretakers/scoring.js +1 -0
- package/dist/types/common/analysts.js +1 -1
- package/dist/types/core/config/filters.js +1 -0
- package/dist/types/core/config/index.js +2 -0
- package/dist/types/core/execution/ambiente.js +1 -0
- package/dist/types/core/execution/linguagens.js +1 -0
- package/dist/types/core/execution/parse-errors.js +1 -0
- package/dist/types/core/execution/results.js +1 -0
- package/dist/types/core/execution/structure-json.js +1 -0
- package/dist/types/core/index.js +1 -0
- package/dist/types/core/messages/index.js +1 -0
- package/dist/types/core/messages/log.js +1 -0
- package/dist/types/core/parsing/babel-narrow.js +1 -0
- package/dist/types/core/parsing/index.js +1 -0
- package/dist/types/core/runtime.js +1 -0
- package/dist/types/guardian/index.js +2 -0
- package/dist/types/guardian/integrity.js +7 -0
- package/dist/types/guardian/snapshot.js +1 -0
- package/dist/types/index.js +4 -4
- package/dist/types/licenses/index.js +2 -0
- package/dist/types/processing/display.js +16 -13
- package/dist/types/processing/filters.js +8 -11
- package/dist/types/reports/compliance.js +1 -0
- package/dist/types/reports/streaming.js +1 -0
- package/dist/types/scripts/index.js +1 -0
- package/dist/types/scripts/migrar-aliases.js +1 -0
- package/dist/types/sdk/index.js +1 -0
- package/dist/types/shared/index.js +2 -0
- package/dist/types/vulnerabilities/index.js +2 -0
- package/dist/vulnerabilities/scanner.js +3 -2
- package/package.json +14 -20
package/README.md
CHANGED
|
@@ -2,46 +2,12 @@
|
|
|
2
2
|
Proveniência e Autoria: Este documento integra o projeto Mahoraga (licença MIT-0).
|
|
3
3
|
---
|
|
4
4
|
|
|
5
|
-
<img src="./svg/banner-mahoraga.svg" width="100%">
|
|
6
|
-
|
|
7
|
-
---
|
|
8
|
-
|
|
9
5
|
<div align="center">
|
|
10
6
|
|
|
11
|
-

|
|
12
|
-

|
|
13
|
-

|
|
14
|
-

|
|
15
|
-

|
|
16
|
-
---
|
|
17
|
-
|
|
18
7
|
<p><b>CLI modular para análise, diagnóstico e manutenção de projetos JavaScript/TypeScript com suporte multi-linguagem</b><p>
|
|
19
8
|
|
|
20
9
|
</div>
|
|
21
10
|
|
|
22
|
-
---
|
|
23
|
-
|
|
24
|
-
## Índice
|
|
25
|
-
|
|
26
|
-
- [Começar Rápido (30 segundos)](#começar-rápido-30-segundos)
|
|
27
|
-
- [Fluxo Passo a Passo](#fluxo-passo-a-passo)
|
|
28
|
-
- [Funcionalidades](#funcionalidades)
|
|
29
|
-
- [Instalação](#instalação)
|
|
30
|
-
- [Configuração](#configuração)
|
|
31
|
-
- [Comandos da CLI](#comandos-da-cli)
|
|
32
|
-
- [REST API](#rest-api)
|
|
33
|
-
- [SDK Programático](#sdk-programático)
|
|
34
|
-
- [GitHub App](#github-app)
|
|
35
|
-
- [Editor (LSP / VSCode)](#editor-lsp--vscode)
|
|
36
|
-
- [CI/CD](#cicd)
|
|
37
|
-
- [Linguagens Suportadas](#linguagens-suportadas)
|
|
38
|
-
- [Documentação Completa](#documentação-completa)
|
|
39
|
-
- [Desenvolvimento](#desenvolvimento)
|
|
40
|
-
- [Contribuir](#contribuir)
|
|
41
|
-
- [Licença](#licença)
|
|
42
|
-
|
|
43
|
-
---
|
|
44
|
-
|
|
45
11
|
## Começar Rápido (30 segundos)
|
|
46
12
|
|
|
47
13
|
```bash
|
|
@@ -3,7 +3,7 @@ import path from 'node:path';
|
|
|
3
3
|
import pLimit from 'p-limit';
|
|
4
4
|
import { config } from '../../core/config/index.js';
|
|
5
5
|
// Constantes para análise estrutural
|
|
6
|
-
export const CONCORRENCIA =
|
|
6
|
+
export const CONCORRENCIA = config.STRUCTURE_CONCURRENCY;
|
|
7
7
|
export const CAMADAS = {
|
|
8
8
|
ts: 'src',
|
|
9
9
|
js: 'src',
|
|
@@ -17,27 +17,27 @@ export const CAMADAS = {
|
|
|
17
17
|
yaml: 'config',
|
|
18
18
|
// Adicione mais mapeamentos conforme necessário
|
|
19
19
|
};
|
|
20
|
+
function determinarCamadaIdeal(entry) {
|
|
21
|
+
const rel = entry.relPath;
|
|
22
|
+
const normalizado = rel.replace(/\\/g, '/');
|
|
23
|
+
const atual = normalizado.split('/')[0] || '';
|
|
24
|
+
let ideal = null;
|
|
25
|
+
const matchDireta = Object.entries(CAMADAS).find(([, dir]) => normalizado.startsWith(`${dir.replace(/\\/g, '/')}/`));
|
|
26
|
+
if (matchDireta) {
|
|
27
|
+
ideal = matchDireta[1];
|
|
28
|
+
}
|
|
29
|
+
else {
|
|
30
|
+
const nome = path.basename(rel);
|
|
31
|
+
const [, tipo] = /\.([^.]+)\.[^.]+$/.exec(nome) ?? [];
|
|
32
|
+
if (tipo && CAMADAS[tipo]) {
|
|
33
|
+
ideal = CAMADAS[tipo];
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return { arquivo: rel, atual, ideal };
|
|
37
|
+
}
|
|
20
38
|
export async function analisarEstrutura(fileEntries, _baseDir = process.cwd()) {
|
|
21
39
|
const limit = pLimit(CONCORRENCIA);
|
|
22
|
-
const resultados = await Promise.all(fileEntries.map((entry) => limit(() =>
|
|
23
|
-
const rel = entry.relPath;
|
|
24
|
-
// Normaliza para separador POSIX para evitar dependência de platform e necessidade de mock em testes
|
|
25
|
-
const normalizado = rel.replace(/\\/g, '/');
|
|
26
|
-
const atual = normalizado.split('/')[0] || '';
|
|
27
|
-
let ideal = null;
|
|
28
|
-
const matchDireta = Object.entries(CAMADAS).find(([, dir]) => normalizado.startsWith(`${dir.replace(/\\/g, '/')}/`));
|
|
29
|
-
if (matchDireta) {
|
|
30
|
-
ideal = matchDireta[1];
|
|
31
|
-
}
|
|
32
|
-
else {
|
|
33
|
-
const nome = path.basename(rel);
|
|
34
|
-
const [, tipo] = /\.([^.]+)\.[^.]+$/.exec(nome) ?? [];
|
|
35
|
-
if (tipo && CAMADAS[tipo]) {
|
|
36
|
-
ideal = CAMADAS[tipo];
|
|
37
|
-
}
|
|
38
|
-
}
|
|
39
|
-
return { arquivo: rel, atual, ideal };
|
|
40
|
-
})));
|
|
40
|
+
const resultados = await Promise.all(fileEntries.map((entry) => limit(() => determinarCamadaIdeal(entry))));
|
|
41
41
|
return resultados;
|
|
42
42
|
}
|
|
43
43
|
export { analisarEstrutura as alinhamentoEstrutural };
|
|
@@ -19,6 +19,13 @@ import { lerEstado, salvarEstado } from '../../shared/persistence/index.js';
|
|
|
19
19
|
const { log, ArquetiposExtraMensagens } = getMessages();
|
|
20
20
|
// Nome do arquivo legado (para compatibilidade)
|
|
21
21
|
const ARQUETIPO_PERSONALIZADO_FILENAME = 'mahoraga.repo.arquetipo.json';
|
|
22
|
+
function logVerbose(fn) {
|
|
23
|
+
const isTest = (process.env.VITEST ?? '') !== '';
|
|
24
|
+
const isVerbose = log.verbose ?? false;
|
|
25
|
+
if (!isTest && isVerbose) {
|
|
26
|
+
fn();
|
|
27
|
+
}
|
|
28
|
+
}
|
|
22
29
|
/**
|
|
23
30
|
* Carrega o arquétipo personalizado do projeto atual
|
|
24
31
|
* Tenta primeiro o novo caminho (.mahoraga/estrutura.arquetipo.json),
|
|
@@ -38,12 +45,7 @@ export async function carregarArquetipoPersonalizado(baseDir = process.cwd()) {
|
|
|
38
45
|
const arquetipoLegado = await lerEstado(caminhoLegado, null);
|
|
39
46
|
// Validação básica
|
|
40
47
|
if (!arquetipoLegado?.nome || !arquetipoLegado.arquetipoOficial) {
|
|
41
|
-
|
|
42
|
-
const isTest = (process.env.VITEST ?? '') !== '';
|
|
43
|
-
const isVerbose = log.verbose ?? false;
|
|
44
|
-
if (!isTest && isVerbose) {
|
|
45
|
-
log.aviso(ArquetiposExtraMensagens.naoEncontrado.replace('{novo}', novoCaminho).replace('{legado}', caminhoLegado));
|
|
46
|
-
}
|
|
48
|
+
logVerbose(() => { log.aviso(ArquetiposExtraMensagens.naoEncontrado.replace('{novo}', novoCaminho).replace('{legado}', caminhoLegado)); });
|
|
47
49
|
return null;
|
|
48
50
|
}
|
|
49
51
|
return arquetipoLegado;
|
|
@@ -105,8 +107,8 @@ export async function existeArquetipoPersonalizado(baseDir = process.cwd()) {
|
|
|
105
107
|
* Obtém o arquétipo oficial base para um arquétipo personalizado
|
|
106
108
|
*/
|
|
107
109
|
export function obterArquetipoOficial(arquetipoPersonalizado) {
|
|
108
|
-
const nomeOficial = arquetipoPersonalizado.arquetipoOficial
|
|
109
|
-
const encontrado = ARQUETIPOS
|
|
110
|
+
const nomeOficial = arquetipoPersonalizado.arquetipoOficial;
|
|
111
|
+
const encontrado = ARQUETIPOS?.find((arq) => arq.nome === nomeOficial);
|
|
110
112
|
return encontrado ?? null;
|
|
111
113
|
}
|
|
112
114
|
/**
|
|
@@ -209,21 +211,16 @@ export function validarArquetipoPersonalizado(arquetipo) {
|
|
|
209
211
|
}
|
|
210
212
|
else {
|
|
211
213
|
// Verifica se o arquétipo oficial existe
|
|
212
|
-
const arquetipoOficial = ARQUETIPOS
|
|
214
|
+
const arquetipoOficial = ARQUETIPOS?.find((arq) => arq.nome === arquetipo.arquetipoOficial);
|
|
213
215
|
if (!arquetipoOficial) {
|
|
214
|
-
erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}',
|
|
216
|
+
erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}', ARQUETIPOS.map(arquivo => (arquivo).nome).join(', ')));
|
|
215
217
|
}
|
|
216
218
|
}
|
|
217
|
-
if (!arquetipo.estruturaPersonalizada) {
|
|
218
|
-
erros.push(ArquetiposExtraMensagens.validacao.
|
|
219
|
+
if (!Array.isArray(arquetipo.estruturaPersonalizada.diretorios)) {
|
|
220
|
+
erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
|
|
219
221
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
|
|
223
|
-
}
|
|
224
|
-
if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
|
|
225
|
-
erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
|
|
226
|
-
}
|
|
222
|
+
if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
|
|
223
|
+
erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
|
|
227
224
|
}
|
|
228
225
|
return {
|
|
229
226
|
valido: erros.length === 0,
|
|
@@ -41,6 +41,34 @@ if (process.env.VITEST) {
|
|
|
41
41
|
scoreArquetipo
|
|
42
42
|
};
|
|
43
43
|
}
|
|
44
|
+
function aplicarBoostConfianca(candidato, arquetiposCandidatos, melhorDeteccao) {
|
|
45
|
+
if (arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome))) {
|
|
46
|
+
const boostConfianca = Math.min(melhorDeteccao.confiancaTotal * 100 * 0.8, 60);
|
|
47
|
+
return {
|
|
48
|
+
...candidato,
|
|
49
|
+
confidence: Math.max(candidato.confidence + boostConfianca, 70),
|
|
50
|
+
explicacaoSimilaridade: `[Boost contextual: ${melhorDeteccao.tecnologia} detectado com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança] ${candidato.explicacaoSimilaridade ?? ''}`
|
|
51
|
+
};
|
|
52
|
+
}
|
|
53
|
+
return candidato;
|
|
54
|
+
}
|
|
55
|
+
function criarArquetipoVirtual(melhorDeteccao, tecnologiaDetectada) {
|
|
56
|
+
return {
|
|
57
|
+
nome: tecnologiaDetectada,
|
|
58
|
+
score: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
59
|
+
confidence: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
60
|
+
matchedRequired: [],
|
|
61
|
+
missingRequired: [],
|
|
62
|
+
matchedOptional: [],
|
|
63
|
+
dependencyMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'dependencia').map(erro => erro.valor),
|
|
64
|
+
filePadraoMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'estrutura').map(erro => erro.valor),
|
|
65
|
+
forbiddenPresent: [],
|
|
66
|
+
anomalias: [],
|
|
67
|
+
sugestaoPadronizacao: (melhorDeteccao.sugestoesMelhoria ?? []).join('; '),
|
|
68
|
+
explicacaoSimilaridade: `Detectado via sistema inteligente contextual com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança`,
|
|
69
|
+
descricao: `Projeto ${melhorDeteccao.tecnologia} identificado por análise contextual`
|
|
70
|
+
};
|
|
71
|
+
}
|
|
44
72
|
export async function detectarArquetipos(contexto, baseDir, options) {
|
|
45
73
|
if (!options?.quiet && config.VERBOSE) {
|
|
46
74
|
console.log(DetectorArquetiposExtraMensagens.debugChamado, contexto.arquivos.length, 'arquivos');
|
|
@@ -91,7 +119,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
91
119
|
const melhorDeteccao = resultadosContextuais.reduce((melhor, atual) => atual.confiancaTotal > melhor.confiancaTotal ? atual : melhor, {
|
|
92
120
|
confiancaTotal: 0
|
|
93
121
|
});
|
|
94
|
-
if (melhorDeteccao
|
|
122
|
+
if (melhorDeteccao.confiancaTotal > 0.6) {
|
|
95
123
|
// Escala 0-1, não 0-100
|
|
96
124
|
// Mapear tecnologias detectadas para arquétipos conhecidos
|
|
97
125
|
const mapeamentoTecnologia = {
|
|
@@ -106,40 +134,19 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
106
134
|
'react-spa': ['react-spa', 'react', 'spa']
|
|
107
135
|
};
|
|
108
136
|
const tecnologiaDetectada = melhorDeteccao.tecnologia ?? 'desconhecido';
|
|
109
|
-
const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
};
|
|
137
|
+
const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada];
|
|
138
|
+
if (!arquetiposCandidatos) {
|
|
139
|
+
if (!options?.quiet && config.VERBOSE) {
|
|
140
|
+
console.log(`[AVISO] Tecnologia detectada "${tecnologiaDetectada}" não mapeada para nenhum arquétipo.`);
|
|
141
|
+
}
|
|
142
|
+
}
|
|
143
|
+
else {
|
|
144
|
+
// Aplicar boost de confiança para arquétipos relacionados
|
|
145
|
+
const boostAplicado = candidatos.some((candidato) => arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome)));
|
|
146
|
+
candidatos = candidatos.map((candidato) => aplicarBoostConfianca(candidato, arquetiposCandidatos, melhorDeteccao));
|
|
147
|
+
if (!boostAplicado) {
|
|
148
|
+
candidatos.unshift(criarArquetipoVirtual(melhorDeteccao, tecnologiaDetectada));
|
|
122
149
|
}
|
|
123
|
-
return candidato;
|
|
124
|
-
});
|
|
125
|
-
// Se não encontrou arquétipo compatível, criar um virtual baseado na detecção
|
|
126
|
-
if (!boostAplicado) {
|
|
127
|
-
const arquetipoVirtual = {
|
|
128
|
-
nome: tecnologiaDetectada,
|
|
129
|
-
score: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
130
|
-
confidence: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
131
|
-
matchedRequired: [],
|
|
132
|
-
missingRequired: [],
|
|
133
|
-
matchedOptional: [],
|
|
134
|
-
dependencyMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'dependencia').map(erro => erro.valor),
|
|
135
|
-
filePadraoMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'estrutura').map(erro => erro.valor),
|
|
136
|
-
forbiddenPresent: [],
|
|
137
|
-
anomalias: [],
|
|
138
|
-
sugestaoPadronizacao: (melhorDeteccao.sugestoesMelhoria ?? []).join('; '),
|
|
139
|
-
explicacaoSimilaridade: `Detectado via sistema inteligente contextual com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança`,
|
|
140
|
-
descricao: `Projeto ${melhorDeteccao.tecnologia} identificado por análise contextual`
|
|
141
|
-
};
|
|
142
|
-
candidatos.unshift(arquetipoVirtual); // Adiciona no início
|
|
143
150
|
}
|
|
144
151
|
}
|
|
145
152
|
}
|
|
@@ -211,7 +218,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
211
218
|
const baselineCaminho = path.join(baseDir, '.mahoraga', 'baseline-estrutura.json');
|
|
212
219
|
let baseline;
|
|
213
220
|
const existente = await lerEstado(baselineCaminho);
|
|
214
|
-
if (
|
|
221
|
+
if (!Array.isArray(existente) && typeof existente === 'object' && 'arquetipo' in existente) {
|
|
215
222
|
baseline = existente;
|
|
216
223
|
}
|
|
217
224
|
if (!baseline && candidatos[0]) {
|
|
@@ -227,7 +234,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
227
234
|
// Prioriza baseline apenas se o candidato principal for 'desconhecido' ou confiança baixa
|
|
228
235
|
if (baseline && baseline.arquetipo !== 'desconhecido') {
|
|
229
236
|
const arquivosRaizAtuais = arquivos.filter(caminho => !caminho.includes('/'));
|
|
230
|
-
const setBase = new Set(baseline.arquivosRaiz
|
|
237
|
+
const setBase = new Set(baseline.arquivosRaiz);
|
|
231
238
|
const temIntersecao = arquivosRaizAtuais.some(arquivo => setBase.has(arquivo));
|
|
232
239
|
const candidatoTop = candidatos[0];
|
|
233
240
|
if (temIntersecao && (candidatoTop.nome === 'desconhecido' || candidatoTop.confidence < 50)) {
|
|
@@ -94,7 +94,7 @@ export function detectarArquetipo(arquivos) {
|
|
|
94
94
|
const filtrados = apenasPenalidades.filter(elem => {
|
|
95
95
|
// Regra específica: se o candidato for 'monorepo-packages' e o único forbidden detectado for 'src', descartamos
|
|
96
96
|
if (elem.nome === 'monorepo-packages') {
|
|
97
|
-
const forb = elem.forbiddenPresent
|
|
97
|
+
const forb = elem.forbiddenPresent;
|
|
98
98
|
if (forb.length === 1 && forb[0] === 'src') {
|
|
99
99
|
return false;
|
|
100
100
|
}
|
|
@@ -110,8 +110,8 @@ export function detectarArquetipo(arquivos) {
|
|
|
110
110
|
const forbA = arquivo.forbiddenPresent.length || 0;
|
|
111
111
|
const forbB = base.forbiddenPresent.length || 0;
|
|
112
112
|
// Usa somente o total de diretórios proibidos definidos no alvo para o ratio
|
|
113
|
-
const defA = ARQUETIPOS
|
|
114
|
-
const defB = ARQUETIPOS
|
|
113
|
+
const defA = ARQUETIPOS?.find((diretorio) => diretorio.nome === arquivo.nome);
|
|
114
|
+
const defB = ARQUETIPOS?.find((diretorio) => diretorio.nome === base.nome);
|
|
115
115
|
const totA = defA?.forbiddenDirs?.length ?? 0;
|
|
116
116
|
const totB = defB?.forbiddenDirs?.length ?? 0;
|
|
117
117
|
const ratioA = totA > 0 ? forbA / totA : 0;
|
|
@@ -5,7 +5,7 @@ _sinaisAvancados // prefixo _ para ignorar warning de unused
|
|
|
5
5
|
// Implementação fictícia para evitar erro de compilação
|
|
6
6
|
return {
|
|
7
7
|
nome: def.nome,
|
|
8
|
-
descricao: def.descricao
|
|
8
|
+
descricao: def.descricao,
|
|
9
9
|
score: 0,
|
|
10
10
|
confidence: 0,
|
|
11
11
|
matchedRequired: [],
|
|
@@ -17,6 +17,28 @@ _sinaisAvancados // prefixo _ para ignorar warning de unused
|
|
|
17
17
|
anomalias: []
|
|
18
18
|
};
|
|
19
19
|
}
|
|
20
|
+
function processarImportsFramework(imports, tecnologias, sinais) {
|
|
21
|
+
for (const indice of imports) {
|
|
22
|
+
if (typeof indice.source.value === 'string') {
|
|
23
|
+
const importSource = indice.source.value.toLowerCase();
|
|
24
|
+
if (importSource.includes('react') || importSource.includes('vue') || importSource.includes('angular')) {
|
|
25
|
+
tecnologias.set('frontend-framework', (tecnologias.get('frontend-framework') ?? 0) + 1);
|
|
26
|
+
}
|
|
27
|
+
if (importSource.includes('express') || importSource.includes('fastify') || importSource.includes('nestjs')) {
|
|
28
|
+
tecnologias.set('backend-framework', (tecnologias.get('backend-framework') ?? 0) + 1);
|
|
29
|
+
}
|
|
30
|
+
if (importSource.includes('prisma') || importSource.includes('mongoose') || importSource.includes('typeorm')) {
|
|
31
|
+
tecnologias.set('orm', (tecnologias.get('orm') ?? 0) + 1);
|
|
32
|
+
}
|
|
33
|
+
if (importSource.includes('jest') || importSource.includes('vitest') || importSource.includes('mocha')) {
|
|
34
|
+
tecnologias.set('testing-framework', (tecnologias.get('testing-framework') ?? 0) + 1);
|
|
35
|
+
}
|
|
36
|
+
if (/express|react|next|electron|discord\.js|telegraf/.test(importSource)) {
|
|
37
|
+
sinais.frameworksDetectados.push(indice.source.value);
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
}
|
|
20
42
|
export function extrairSinaisAvancados(fileEntries, packageJson, _p0, _baseDir, _arquivos) {
|
|
21
43
|
// Auxiliar para checar se o nó possui id.name string
|
|
22
44
|
const hasIdNome = (node) => {
|
|
@@ -45,8 +67,8 @@ export function extrairSinaisAvancados(fileEntries, packageJson, _p0, _baseDir,
|
|
|
45
67
|
const tecnologias = new Map();
|
|
46
68
|
for (const fe of fileEntries) {
|
|
47
69
|
let body = [];
|
|
48
|
-
if (fe.ast && 'node' in fe.ast &&
|
|
49
|
-
body = fe.ast.node.body;
|
|
70
|
+
if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
|
|
71
|
+
body = (fe.ast.node).body;
|
|
50
72
|
}
|
|
51
73
|
// Análise inteligente de padrões
|
|
52
74
|
const conteudo = fe.content ?? '';
|
|
@@ -134,31 +156,7 @@ export function extrairSinaisAvancados(fileEntries, packageJson, _p0, _baseDir,
|
|
|
134
156
|
// Classes
|
|
135
157
|
sinais.classes += body.filter((node) => node.type === 'ClassDeclaration').length;
|
|
136
158
|
// Frameworks por import (expandido)
|
|
137
|
-
|
|
138
|
-
if (typeof indice.source.value === 'string') {
|
|
139
|
-
const importSource = indice.source.value.toLowerCase();
|
|
140
|
-
// Frameworks web
|
|
141
|
-
if (importSource.includes('react') || importSource.includes('vue') || importSource.includes('angular')) {
|
|
142
|
-
tecnologias.set('frontend-framework', (tecnologias.get('frontend-framework') ?? 0) + 1);
|
|
143
|
-
}
|
|
144
|
-
// Frameworks backend
|
|
145
|
-
if (importSource.includes('express') || importSource.includes('fastify') || importSource.includes('nestjs')) {
|
|
146
|
-
tecnologias.set('backend-framework', (tecnologias.get('backend-framework') ?? 0) + 1);
|
|
147
|
-
}
|
|
148
|
-
// ORMs
|
|
149
|
-
if (importSource.includes('prisma') || importSource.includes('mongoose') || importSource.includes('typeorm')) {
|
|
150
|
-
tecnologias.set('orm', (tecnologias.get('orm') ?? 0) + 1);
|
|
151
|
-
}
|
|
152
|
-
// Testing
|
|
153
|
-
if (importSource.includes('jest') || importSource.includes('vitest') || importSource.includes('mocha')) {
|
|
154
|
-
tecnologias.set('testing-framework', (tecnologias.get('testing-framework') ?? 0) + 1);
|
|
155
|
-
}
|
|
156
|
-
// Lista original mantida
|
|
157
|
-
if (/express|react|next|electron|discord\.js|telegraf/.test(importSource)) {
|
|
158
|
-
sinais.frameworksDetectados.push(indice.source.value);
|
|
159
|
-
}
|
|
160
|
-
}
|
|
161
|
-
}
|
|
159
|
+
processarImportsFramework(imports, tecnologias, sinais);
|
|
162
160
|
// Padrões de pastas/arquivos (expandido)
|
|
163
161
|
const rel = fe.relPath.replace(/\\/g, '/');
|
|
164
162
|
if (/src\/controllers|pages|api|prisma|packages|apps|src\/routes|src\/services|src\/repositories/.test(rel)) {
|
|
@@ -22,8 +22,8 @@ export function extrairSinaisProjeto(fileEntries, packageJson) {
|
|
|
22
22
|
};
|
|
23
23
|
for (const fe of fileEntries) {
|
|
24
24
|
let body = [];
|
|
25
|
-
if (fe.ast && 'node' in fe.ast &&
|
|
26
|
-
body = fe.ast.node.body;
|
|
25
|
+
if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
|
|
26
|
+
body = (fe.ast.node).body;
|
|
27
27
|
}
|
|
28
28
|
// Funções
|
|
29
29
|
sinais.funcoes += body.filter((node) => node.type === 'FunctionDeclaration').length;
|
|
@@ -3,15 +3,52 @@ import { statSync } from 'node:fs';
|
|
|
3
3
|
import path from 'node:path';
|
|
4
4
|
import { getTypesDirectoryRelPosix } from '../../core/config/index.js';
|
|
5
5
|
import { carregarConfigEstrategia, destinoPara, deveIgnorar, normalizarRel } from '../../shared/helpers/index.js';
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
6
|
+
function processarArquivoParaMovimento(rel, cfg, baseDir, sinaisAvancados, rels, mover, conflitos) {
|
|
7
|
+
if (deveIgnorar(rel, cfg.ignorarPastas)) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
if (/__(tests|mocks)__/.test(rel) || /\.(test|spec)\.[jt]sx?$/.test(rel) || /fixtures\//.test(rel)) {
|
|
11
|
+
return;
|
|
12
|
+
}
|
|
13
|
+
if (!rel.endsWith('.ts') && !rel.endsWith('.js')) {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
const base = path.posix.basename(rel);
|
|
17
|
+
if (/^(eslint|vitest|next|tailwind|postcss|prettier|jest)\.config\.[jt]s$/i.test(base)) {
|
|
18
|
+
return;
|
|
19
|
+
}
|
|
20
|
+
const res = destinoPara(rel, cfg.raizCodigo, cfg.criarSubpastasPorEntidade, cfg.apenasCategoriasConfiguradas, cfg.categoriasMapa);
|
|
21
|
+
if (!res.destinoDir) {
|
|
22
|
+
return;
|
|
23
|
+
}
|
|
24
|
+
const currentDir = path.posix.dirname(rel);
|
|
25
|
+
const alreadyInTarget = currentDir === res.destinoDir || currentDir.startsWith(`${res.destinoDir}/`);
|
|
26
|
+
if (alreadyInTarget) {
|
|
27
|
+
return;
|
|
28
|
+
}
|
|
29
|
+
let destinoDirAjustado = res.destinoDir;
|
|
30
|
+
const motivoAjustado = res.motivo ?? 'Reorganização padrão';
|
|
31
|
+
if (sinaisAvancados) {
|
|
32
|
+
destinoDirAjustado = ajustarDestinoPorSinais(rel, res.destinoDir, sinaisAvancados, motivoAjustado);
|
|
33
|
+
}
|
|
34
|
+
const destino = path.posix.join(destinoDirAjustado, path.posix.basename(rel));
|
|
35
|
+
let destinoExiste = rels.includes(destino);
|
|
36
|
+
if (!destinoExiste) {
|
|
37
|
+
try {
|
|
38
|
+
const abs = path.join(baseDir, destino.replace(/\\/g, '/'));
|
|
39
|
+
statSync(abs);
|
|
40
|
+
destinoExiste = true;
|
|
41
|
+
}
|
|
42
|
+
catch {
|
|
43
|
+
destinoExiste = false;
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
if (destinoExiste) {
|
|
47
|
+
conflitos.push({ alvo: destino, motivo: 'destino já existe' });
|
|
48
|
+
return;
|
|
49
|
+
}
|
|
50
|
+
mover.push({ de: rel, para: destino, motivo: motivoAjustado });
|
|
51
|
+
}
|
|
15
52
|
export async function gerarPlanoEstrategico(contexto, opcoes = {}, sinaisAvancados) {
|
|
16
53
|
const typesDir = getTypesDirectoryRelPosix();
|
|
17
54
|
const cfg = await carregarConfigEstrategia(contexto.baseDir, {
|
|
@@ -24,63 +61,7 @@ export async function gerarPlanoEstrategico(contexto, opcoes = {}, sinaisAvancad
|
|
|
24
61
|
const rels = contexto.arquivos.map(arquivo => normalizarRel(arquivo.relPath));
|
|
25
62
|
const isTestLike = (caminho) => /__(tests|mocks)__/.test(caminho) || /\.(test|spec)\.[jt]sx?$/.test(caminho) || /fixtures\//.test(caminho);
|
|
26
63
|
for (const rel of rels) {
|
|
27
|
-
|
|
28
|
-
continue;
|
|
29
|
-
}
|
|
30
|
-
if (isTestLike(rel)) {
|
|
31
|
-
continue;
|
|
32
|
-
} // não mover testes/fixtures
|
|
33
|
-
// Evitar mexer em arquivos fora do escopo de código (por agora)
|
|
34
|
-
if (!rel.endsWith('.ts') && !rel.endsWith('.js')) {
|
|
35
|
-
continue;
|
|
36
|
-
}
|
|
37
|
-
// Respeita convenções de ferramentas no root: não mover configs globais
|
|
38
|
-
const base = path.posix.basename(rel);
|
|
39
|
-
if (/^(eslint|vitest|next|tailwind|postcss|prettier|jest)\.config\.[jt]s$/i.test(base)) {
|
|
40
|
-
continue;
|
|
41
|
-
}
|
|
42
|
-
const res = destinoPara(rel, cfg.raizCodigo, cfg.criarSubpastasPorEntidade, cfg.apenasCategoriasConfiguradas, cfg.categoriasMapa);
|
|
43
|
-
if (!res.destinoDir) {
|
|
44
|
-
continue;
|
|
45
|
-
}
|
|
46
|
-
const currentDir = path.posix.dirname(rel);
|
|
47
|
-
const alreadyInTarget = currentDir === res.destinoDir || currentDir.startsWith(`${res.destinoDir}/`);
|
|
48
|
-
if (alreadyInTarget) {
|
|
49
|
-
continue;
|
|
50
|
-
}
|
|
51
|
-
// [LANCAMENTO] INTELIGÊNCIA CONTEXTUAL: Ajustar destino baseado em sinais avançados
|
|
52
|
-
let destinoDirAjustado = res.destinoDir;
|
|
53
|
-
const motivoAjustado = res.motivo ?? 'Reorganização padrão';
|
|
54
|
-
if (sinaisAvancados) {
|
|
55
|
-
destinoDirAjustado = ajustarDestinoPorSinais(rel, res.destinoDir, sinaisAvancados, motivoAjustado);
|
|
56
|
-
}
|
|
57
|
-
// Mantém o mesmo nome do arquivo; apenas move para pasta de destino
|
|
58
|
-
const destino = path.posix.join(destinoDirAjustado, path.posix.basename(rel));
|
|
59
|
-
// Conflito se já existe arquivo listado ou presente no filesystem
|
|
60
|
-
let destinoExiste = rels.includes(destino);
|
|
61
|
-
if (!destinoExiste) {
|
|
62
|
-
try {
|
|
63
|
-
const abs = path.join(contexto.baseDir, destino.replace(/\\/g, '/'));
|
|
64
|
-
// fs.statSync usado de forma segura; se falhar, considera inexistente
|
|
65
|
-
statSync(abs);
|
|
66
|
-
destinoExiste = true;
|
|
67
|
-
}
|
|
68
|
-
catch {
|
|
69
|
-
destinoExiste = false;
|
|
70
|
-
}
|
|
71
|
-
}
|
|
72
|
-
if (destinoExiste) {
|
|
73
|
-
conflitos.push({
|
|
74
|
-
alvo: destino,
|
|
75
|
-
motivo: 'destino já existe'
|
|
76
|
-
});
|
|
77
|
-
continue;
|
|
78
|
-
}
|
|
79
|
-
mover.push({
|
|
80
|
-
de: rel,
|
|
81
|
-
para: destino,
|
|
82
|
-
motivo: motivoAjustado
|
|
83
|
-
});
|
|
64
|
+
processarArquivoParaMovimento(rel, cfg, contexto.baseDir, sinaisAvancados, rels, mover, conflitos);
|
|
84
65
|
}
|
|
85
66
|
// Deduplicação simples
|
|
86
67
|
const seen = new Set();
|
|
@@ -11,6 +11,21 @@ export function registrarDetectorAzure(detector) {
|
|
|
11
11
|
export function obterDetectoresAzure() {
|
|
12
12
|
return [...detectoresRegistrados];
|
|
13
13
|
}
|
|
14
|
+
function processarResultadosPlugins(plugResults, ocorrencias, relPath) {
|
|
15
|
+
for (const results of plugResults) {
|
|
16
|
+
for (const item of results) {
|
|
17
|
+
ocorrencias.push({
|
|
18
|
+
tipo: `AZURE_${item.tipo.toUpperCase().replace(/-/g, '_')}`,
|
|
19
|
+
mensagem: item.descricao,
|
|
20
|
+
relPath,
|
|
21
|
+
linha: item.linha ?? 1,
|
|
22
|
+
coluna: 1,
|
|
23
|
+
sugestao: item.sugestao ?? '',
|
|
24
|
+
nivel: item.severidade === 'critica' || item.severidade === 'alta' ? 'erro' : item.severidade === 'media' ? 'aviso' : 'info',
|
|
25
|
+
});
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
}
|
|
14
29
|
export const analistaAzurePipelines = {
|
|
15
30
|
nome: 'azure-pipelines',
|
|
16
31
|
categoria: 'workflows',
|
|
@@ -23,53 +38,44 @@ export const analistaAzurePipelines = {
|
|
|
23
38
|
const securityResults = await Promise.resolve(detectorAzureSecurity.aplicar(conteudo, relPath, null, _fc, contexto));
|
|
24
39
|
const performanceResults = await Promise.resolve(detectorAzurePerformance.aplicar(conteudo, relPath, null, _fc, contexto));
|
|
25
40
|
const estruturaResults = await Promise.resolve(detectorAzureEstrutura.aplicar(conteudo, relPath, null, _fc, contexto));
|
|
26
|
-
|
|
41
|
+
for (const r of [securityResults, performanceResults, estruturaResults]) {
|
|
42
|
+
if (r) {
|
|
43
|
+
ocorrencias.push(...(Array.isArray(r) ? r : [r]));
|
|
44
|
+
}
|
|
45
|
+
}
|
|
27
46
|
// 2. Análise Estrutural básica
|
|
28
47
|
const doc = parseDocument(conteudo);
|
|
29
48
|
const configData = doc.toJS();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
49
|
+
// Verificar versão antiga (v0.x)
|
|
50
|
+
const version = configData.version;
|
|
51
|
+
if ((typeof version === 'string' || typeof version === 'number') && parseFloat(String(version)) < 1.0) {
|
|
52
|
+
ocorrencias.push({
|
|
53
|
+
tipo: 'AZURE_OBSOLETE_VERSION',
|
|
54
|
+
mensagem: 'Versão do schema do Azure Pipelines está obsoleta',
|
|
55
|
+
relPath,
|
|
56
|
+
linha: 1,
|
|
57
|
+
nivel: 'aviso',
|
|
58
|
+
sugestao: 'Remova o campo "version" para usar o schema YAML moderno',
|
|
59
|
+
});
|
|
60
|
+
}
|
|
61
|
+
// Detectar excesso de variáveis globais
|
|
62
|
+
if (configData.variables && typeof configData.variables === 'object') {
|
|
63
|
+
const varCount = Object.keys(configData.variables).length;
|
|
64
|
+
if (varCount > 20) {
|
|
33
65
|
ocorrencias.push({
|
|
34
|
-
tipo: '
|
|
35
|
-
mensagem:
|
|
66
|
+
tipo: 'AZURE_TOO_MANY_VARIABLES',
|
|
67
|
+
mensagem: messages.RelatorioAzureMensagens.tooManyVariables,
|
|
36
68
|
relPath,
|
|
37
69
|
linha: 1,
|
|
38
|
-
nivel: '
|
|
39
|
-
sugestao:
|
|
70
|
+
nivel: 'info',
|
|
71
|
+
sugestao: messages.RelatorioAzureMensagens.tooManyVariablesSugestao,
|
|
40
72
|
});
|
|
41
73
|
}
|
|
42
|
-
// Detectar excesso de variáveis globais
|
|
43
|
-
if (configData.variables && typeof configData.variables === 'object') {
|
|
44
|
-
const varCount = Object.keys(configData.variables).length;
|
|
45
|
-
if (varCount > 20) {
|
|
46
|
-
ocorrencias.push({
|
|
47
|
-
tipo: 'AZURE_TOO_MANY_VARIABLES',
|
|
48
|
-
mensagem: messages.RelatorioAzureMensagens.tooManyVariables,
|
|
49
|
-
relPath,
|
|
50
|
-
linha: 1,
|
|
51
|
-
nivel: 'info',
|
|
52
|
-
sugestao: messages.RelatorioAzureMensagens.tooManyVariablesSugestao,
|
|
53
|
-
});
|
|
54
|
-
}
|
|
55
|
-
}
|
|
56
74
|
}
|
|
57
75
|
// 3. Plugins registrados
|
|
58
76
|
const caminhos = contexto?.arquivos.map(arquivo => arquivo.relPath) ?? [];
|
|
59
77
|
const plugResults = await Promise.all(detectoresRegistrados.map(detector => Promise.resolve(detector.testar(configData, { conteudo, caminhos })).catch(() => [])));
|
|
60
|
-
|
|
61
|
-
for (const item of results) {
|
|
62
|
-
ocorrencias.push({
|
|
63
|
-
tipo: `AZURE_${item.tipo.toUpperCase().replace(/-/g, '_')}`,
|
|
64
|
-
mensagem: item.descricao,
|
|
65
|
-
relPath,
|
|
66
|
-
linha: item.linha ?? 1,
|
|
67
|
-
coluna: 1,
|
|
68
|
-
sugestao: item.sugestao ?? '',
|
|
69
|
-
nivel: item.severidade === 'critica' || item.severidade === 'alta' ? 'erro' : item.severidade === 'media' ? 'aviso' : 'info',
|
|
70
|
-
});
|
|
71
|
-
}
|
|
72
|
-
}
|
|
78
|
+
processarResultadosPlugins(plugResults, ocorrencias, relPath);
|
|
73
79
|
}
|
|
74
80
|
catch {
|
|
75
81
|
// Falha silenciosa no parse
|