@mocoto/mahoraga 0.14.1 → 0.14.2
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/dist/analysts/architects/analyst-structure.js +1 -1
- package/dist/analysts/architects/archetypes-custom.js +8 -13
- package/dist/analysts/architects/detector-archetypes.js +39 -35
- package/dist/analysts/architects/orchestrator-archetypes.js +3 -3
- package/dist/analysts/architects/signals-project-advanced.js +2 -2
- package/dist/analysts/architects/signals-project.js +1 -1
- package/dist/analysts/azure-pipelines/analysts/analyst-azure.js +20 -21
- package/dist/analysts/azure-pipelines/detectors/detector-azure-structure.js +0 -3
- package/dist/analysts/circleci/analysts/analyst-circleci.js +22 -24
- package/dist/analysts/circleci/detectors/detector-circleci-structure.js +4 -7
- package/dist/analysts/converters/convert-registry.js +1 -1
- package/dist/analysts/converters/index.js +1 -1
- package/dist/analysts/corrections/auto-fix-engine.js +1 -1
- package/dist/analysts/corrections/corrector-structure.js +8 -7
- package/dist/analysts/corrections/map-reversion.js +2 -2
- package/dist/analysts/corrections/reorganize-barrels.js +3 -3
- package/dist/analysts/corrections/rewrite-testes-aliases.js +23 -22
- package/dist/analysts/corrections/type-safety/type-analyzer.js +3 -3
- package/dist/analysts/corrections/type-safety/type-validator.js +2 -2
- package/dist/analysts/corrections/type-safety/usage-analyzer.js +3 -3
- package/dist/analysts/css/analysts/analyst-css.js +27 -28
- package/dist/analysts/css-in-js/detectors/detector-css-in-js-best-practices.js +8 -15
- package/dist/analysts/detectors/detector-architecture.js +2 -2
- package/dist/analysts/detectors/detector-bugs-ml.js +8 -8
- package/dist/analysts/detectors/detector-code-fragile.js +11 -10
- package/dist/analysts/detectors/detector-dependencies.js +5 -5
- package/dist/analysts/detectors/detector-duplications.js +5 -8
- package/dist/analysts/detectors/detector-monorepo.js +10 -9
- package/dist/analysts/detectors/detector-performance.js +2 -1
- package/dist/analysts/detectors/detector-recommendation-architecture.js +1 -1
- package/dist/analysts/detectors/detector-security.js +1 -1
- package/dist/analysts/detectors/detector-structure.js +3 -3
- 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 +81 -9
- package/dist/analysts/js-ts/detectors/detector-constructions-syntactic.js +35 -6
- 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 +5 -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 +63 -8
- package/dist/analysts/react/analysts/analyst-react.js +45 -1
- package/dist/analysts/react/corrections/correction-react.js +40 -0
- package/dist/analysts/react/detectors/detector-react-best-practices.js +4 -4
- package/dist/analysts/react/scorers/scorer-react.js +36 -1
- 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 +116 -9
- package/dist/analysts/tailwind/detectors/detector-tailwind-best-practices.js +122 -7
- package/dist/analysts/tailwind/scorers/scorer-tailwind.js +62 -10
- 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 +1 -1
- 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-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 +3 -3
- 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/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 +2 -2
- package/dist/core/config/config.js +6 -8
- 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/executor.js +8 -19
- package/dist/core/execution/inquisitor.js +24 -21
- package/dist/core/execution/results.js +1 -0
- package/dist/core/execution/scanner.js +3 -3
- 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/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/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/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/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 +2 -2
- 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 +6 -1
- package/dist/guardian/result.js +1 -1
- package/dist/guardian/sentinel.js +6 -1
- package/dist/guardian/watcher-hidden.js +5 -1
- package/dist/licenses/fs-utils.js +4 -1
- package/dist/licenses/generate-notices.js +1 -1
- package/dist/licenses/header-options.js +0 -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 +4 -4
- package/dist/reports/report-archetypes.js +10 -10
- package/dist/reports/report-caretaker-health.js +2 -1
- package/dist/sdk/analyzer.js +1 -1
- package/dist/shared/data-processing/fragment-report.js +10 -10
- 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 +6 -9
- 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 +18 -23
- 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 +1 -1
- 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 +0 -1
- package/dist/shared/plugins/core-plugin.js +3 -1
- package/dist/shared/plugins/registry.js +3 -2
- 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 +3 -7
- 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/npm-audit.js +0 -1
- package/dist/vulnerabilities/scanner.js +2 -1
- package/dist/vulnerabilities/vulnerabilities.js +0 -1
- package/package.json +11 -12
|
@@ -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',
|
|
@@ -105,8 +105,8 @@ export async function existeArquetipoPersonalizado(baseDir = process.cwd()) {
|
|
|
105
105
|
* Obtém o arquétipo oficial base para um arquétipo personalizado
|
|
106
106
|
*/
|
|
107
107
|
export function obterArquetipoOficial(arquetipoPersonalizado) {
|
|
108
|
-
const nomeOficial = arquetipoPersonalizado.arquetipoOficial
|
|
109
|
-
const encontrado = ARQUETIPOS
|
|
108
|
+
const nomeOficial = arquetipoPersonalizado.arquetipoOficial;
|
|
109
|
+
const encontrado = ARQUETIPOS?.find((arq) => arq.nome === nomeOficial);
|
|
110
110
|
return encontrado ?? null;
|
|
111
111
|
}
|
|
112
112
|
/**
|
|
@@ -209,21 +209,16 @@ export function validarArquetipoPersonalizado(arquetipo) {
|
|
|
209
209
|
}
|
|
210
210
|
else {
|
|
211
211
|
// Verifica se o arquétipo oficial existe
|
|
212
|
-
const arquetipoOficial = ARQUETIPOS
|
|
212
|
+
const arquetipoOficial = ARQUETIPOS?.find((arq) => arq.nome === arquetipo.arquetipoOficial);
|
|
213
213
|
if (!arquetipoOficial) {
|
|
214
|
-
erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}',
|
|
214
|
+
erros.push(ArquetiposExtraMensagens.validacao.arquetipoNaoEncontrado.replace('{arquetipo}', arquetipo.arquetipoOficial).replace('{disponiveis}', ARQUETIPOS.map(arquivo => (arquivo).nome).join(', ')));
|
|
215
215
|
}
|
|
216
216
|
}
|
|
217
|
-
if (!arquetipo.estruturaPersonalizada) {
|
|
218
|
-
erros.push(ArquetiposExtraMensagens.validacao.
|
|
217
|
+
if (!Array.isArray(arquetipo.estruturaPersonalizada.diretorios)) {
|
|
218
|
+
erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
|
|
219
219
|
}
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
erros.push(ArquetiposExtraMensagens.validacao.diretoriosArray);
|
|
223
|
-
}
|
|
224
|
-
if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
|
|
225
|
-
erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
|
|
226
|
-
}
|
|
220
|
+
if (!Array.isArray(arquetipo.estruturaPersonalizada.arquivosChave)) {
|
|
221
|
+
erros.push(ArquetiposExtraMensagens.validacao.arquivosChaveArray);
|
|
227
222
|
}
|
|
228
223
|
return {
|
|
229
224
|
valido: erros.length === 0,
|
|
@@ -91,7 +91,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
91
91
|
const melhorDeteccao = resultadosContextuais.reduce((melhor, atual) => atual.confiancaTotal > melhor.confiancaTotal ? atual : melhor, {
|
|
92
92
|
confiancaTotal: 0
|
|
93
93
|
});
|
|
94
|
-
if (melhorDeteccao
|
|
94
|
+
if (melhorDeteccao.confiancaTotal > 0.6) {
|
|
95
95
|
// Escala 0-1, não 0-100
|
|
96
96
|
// Mapear tecnologias detectadas para arquétipos conhecidos
|
|
97
97
|
const mapeamentoTecnologia = {
|
|
@@ -106,40 +106,44 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
106
106
|
'react-spa': ['react-spa', 'react', 'spa']
|
|
107
107
|
};
|
|
108
108
|
const tecnologiaDetectada = melhorDeteccao.tecnologia ?? 'desconhecido';
|
|
109
|
-
const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada]
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
109
|
+
const arquetiposCandidatos = mapeamentoTecnologia[tecnologiaDetectada];
|
|
110
|
+
if (!arquetiposCandidatos) {
|
|
111
|
+
if (!options?.quiet && config.VERBOSE) {
|
|
112
|
+
console.log(`[AVISO] Tecnologia detectada "${tecnologiaDetectada}" não mapeada para nenhum arquétipo.`);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
else {
|
|
116
|
+
// Aplicar boost de confiança para arquétipos relacionados
|
|
117
|
+
const boostAplicado = candidatos.some((candidato) => arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome)));
|
|
118
|
+
candidatos = candidatos.map((candidato) => {
|
|
119
|
+
if (arquetiposCandidatos.some((arq) => candidato.nome.includes(arq) || arq.includes(candidato.nome))) {
|
|
120
|
+
const boostConfianca = Math.min(melhorDeteccao.confiancaTotal * 100 * 0.8, 60);
|
|
121
|
+
return {
|
|
122
|
+
...candidato,
|
|
123
|
+
confidence: Math.max(candidato.confidence + boostConfianca, 70),
|
|
124
|
+
explicacaoSimilaridade: `[Boost contextual: ${melhorDeteccao.tecnologia} detectado com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança] ${candidato.explicacaoSimilaridade ?? ''}`
|
|
125
|
+
};
|
|
126
|
+
}
|
|
127
|
+
return candidato;
|
|
128
|
+
});
|
|
129
|
+
if (!boostAplicado) {
|
|
130
|
+
const arquetipoVirtual = {
|
|
131
|
+
nome: tecnologiaDetectada,
|
|
132
|
+
score: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
133
|
+
confidence: Math.round(melhorDeteccao.confiancaTotal * 100),
|
|
134
|
+
matchedRequired: [],
|
|
135
|
+
missingRequired: [],
|
|
136
|
+
matchedOptional: [],
|
|
137
|
+
dependencyMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'dependencia').map(erro => erro.valor),
|
|
138
|
+
filePadraoMatches: (melhorDeteccao.evidencias ?? []).filter(erro => erro.tipo === 'estrutura').map(erro => erro.valor),
|
|
139
|
+
forbiddenPresent: [],
|
|
140
|
+
anomalias: [],
|
|
141
|
+
sugestaoPadronizacao: (melhorDeteccao.sugestoesMelhoria ?? []).join('; '),
|
|
142
|
+
explicacaoSimilaridade: `Detectado via sistema inteligente contextual com ${(melhorDeteccao.confiancaTotal * 100).toFixed(0)}% confiança`,
|
|
143
|
+
descricao: `Projeto ${melhorDeteccao.tecnologia} identificado por análise contextual`
|
|
121
144
|
};
|
|
145
|
+
candidatos.unshift(arquetipoVirtual);
|
|
122
146
|
}
|
|
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
147
|
}
|
|
144
148
|
}
|
|
145
149
|
}
|
|
@@ -211,7 +215,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
211
215
|
const baselineCaminho = path.join(baseDir, '.mahoraga', 'baseline-estrutura.json');
|
|
212
216
|
let baseline;
|
|
213
217
|
const existente = await lerEstado(baselineCaminho);
|
|
214
|
-
if (
|
|
218
|
+
if (!Array.isArray(existente) && typeof existente === 'object' && 'arquetipo' in existente) {
|
|
215
219
|
baseline = existente;
|
|
216
220
|
}
|
|
217
221
|
if (!baseline && candidatos[0]) {
|
|
@@ -227,7 +231,7 @@ export async function detectarArquetipos(contexto, baseDir, options) {
|
|
|
227
231
|
// Prioriza baseline apenas se o candidato principal for 'desconhecido' ou confiança baixa
|
|
228
232
|
if (baseline && baseline.arquetipo !== 'desconhecido') {
|
|
229
233
|
const arquivosRaizAtuais = arquivos.filter(caminho => !caminho.includes('/'));
|
|
230
|
-
const setBase = new Set(baseline.arquivosRaiz
|
|
234
|
+
const setBase = new Set(baseline.arquivosRaiz);
|
|
231
235
|
const temIntersecao = arquivosRaizAtuais.some(arquivo => setBase.has(arquivo));
|
|
232
236
|
const candidatoTop = candidatos[0];
|
|
233
237
|
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: [],
|
|
@@ -45,7 +45,7 @@ export function extrairSinaisAvancados(fileEntries, packageJson, _p0, _baseDir,
|
|
|
45
45
|
const tecnologias = new Map();
|
|
46
46
|
for (const fe of fileEntries) {
|
|
47
47
|
let body = [];
|
|
48
|
-
if (fe.ast && 'node' in fe.ast &&
|
|
48
|
+
if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
|
|
49
49
|
body = fe.ast.node.body;
|
|
50
50
|
}
|
|
51
51
|
// Análise inteligente de padrões
|
|
@@ -22,7 +22,7 @@ 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 &&
|
|
25
|
+
if (fe.ast && 'node' in fe.ast && Array.isArray(fe.ast.node.body)) {
|
|
26
26
|
body = fe.ast.node.body;
|
|
27
27
|
}
|
|
28
28
|
// Funções
|
|
@@ -27,32 +27,31 @@ export const analistaAzurePipelines = {
|
|
|
27
27
|
// 2. Análise Estrutural básica
|
|
28
28
|
const doc = parseDocument(conteudo);
|
|
29
29
|
const configData = doc.toJS();
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
30
|
+
// Verificar versão antiga (v0.x)
|
|
31
|
+
const version = configData.version;
|
|
32
|
+
if ((typeof version === 'string' || typeof version === 'number') && parseFloat(String(version)) < 1.0) {
|
|
33
|
+
ocorrencias.push({
|
|
34
|
+
tipo: 'AZURE_OBSOLETE_VERSION',
|
|
35
|
+
mensagem: 'Versão do schema do Azure Pipelines está obsoleta',
|
|
36
|
+
relPath,
|
|
37
|
+
linha: 1,
|
|
38
|
+
nivel: 'aviso',
|
|
39
|
+
sugestao: 'Remova o campo "version" para usar o schema YAML moderno',
|
|
40
|
+
});
|
|
41
|
+
}
|
|
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) {
|
|
33
46
|
ocorrencias.push({
|
|
34
|
-
tipo: '
|
|
35
|
-
mensagem:
|
|
47
|
+
tipo: 'AZURE_TOO_MANY_VARIABLES',
|
|
48
|
+
mensagem: messages.RelatorioAzureMensagens.tooManyVariables,
|
|
36
49
|
relPath,
|
|
37
50
|
linha: 1,
|
|
38
|
-
nivel: '
|
|
39
|
-
sugestao:
|
|
51
|
+
nivel: 'info',
|
|
52
|
+
sugestao: messages.RelatorioAzureMensagens.tooManyVariablesSugestao,
|
|
40
53
|
});
|
|
41
54
|
}
|
|
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
55
|
}
|
|
57
56
|
// 3. Plugins registrados
|
|
58
57
|
const caminhos = contexto?.arquivos.map(arquivo => arquivo.relPath) ?? [];
|
|
@@ -15,9 +15,6 @@ export const detectorAzureEstrutura = {
|
|
|
15
15
|
try {
|
|
16
16
|
const doc = parseDocument(src);
|
|
17
17
|
const pipeline = doc.toJS();
|
|
18
|
-
if (!pipeline) {
|
|
19
|
-
return ocorrencias;
|
|
20
|
-
}
|
|
21
18
|
const jobs = pipeline.jobs;
|
|
22
19
|
if (jobs && Array.isArray(jobs)) {
|
|
23
20
|
const jobNames = jobs.map(j => j.job ?? '').filter(Boolean);
|
|
@@ -32,30 +32,28 @@ export const analistaCircleCI = {
|
|
|
32
32
|
}
|
|
33
33
|
const doc = parseDocument(conteudo);
|
|
34
34
|
const config = doc.toJS();
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
});
|
|
58
|
-
}
|
|
35
|
+
const configData = config;
|
|
36
|
+
if (configData.version && parseFloat(String(configData.version)) < 2.1) {
|
|
37
|
+
ocorrencias.push({
|
|
38
|
+
tipo: 'CIRCLECI_OBSOLETE_VERSION',
|
|
39
|
+
mensagem: `Versão do CircleCI (${configData.version}) está obsoleta`,
|
|
40
|
+
relPath,
|
|
41
|
+
linha: 1,
|
|
42
|
+
nivel: 'aviso',
|
|
43
|
+
sugestao: 'Atualize para a versão 2.1 para usar Orbs, Commands e outras melhorias modernas'
|
|
44
|
+
});
|
|
45
|
+
}
|
|
46
|
+
if (configData.jobs) {
|
|
47
|
+
for (const [jobName, job] of Object.entries(configData.jobs)) {
|
|
48
|
+
if (job.steps && job.steps.length > 20) {
|
|
49
|
+
ocorrencias.push({
|
|
50
|
+
tipo: 'CIRCLECI_JOB_TOO_MANY_STEPS',
|
|
51
|
+
mensagem: `Job '${jobName}' possui muitos steps (${job.steps.length})`,
|
|
52
|
+
relPath,
|
|
53
|
+
linha: 1,
|
|
54
|
+
nivel: 'info',
|
|
55
|
+
sugestao: 'Agrupe steps repetitivos em "commands" para maior legibilidade'
|
|
56
|
+
});
|
|
59
57
|
}
|
|
60
58
|
}
|
|
61
59
|
}
|
|
@@ -16,9 +16,6 @@ export const detectorCircleCIEstrutura = {
|
|
|
16
16
|
try {
|
|
17
17
|
const doc = parseDocument(src);
|
|
18
18
|
const config = doc.toJS();
|
|
19
|
-
if (!config) {
|
|
20
|
-
return ocorrencias;
|
|
21
|
-
}
|
|
22
19
|
const jobs = config;
|
|
23
20
|
if (jobs.jobs) {
|
|
24
21
|
for (const [jobName, job] of Object.entries(jobs.jobs)) {
|
|
@@ -91,7 +88,7 @@ export const detectorCircleCIEstrutura = {
|
|
|
91
88
|
const commands = config.commands;
|
|
92
89
|
if (commands) {
|
|
93
90
|
for (const [_cmdName, cmdDef] of Object.entries(commands)) {
|
|
94
|
-
if (
|
|
91
|
+
if (!('parameters' in cmdDef)) {
|
|
95
92
|
ocorrencias.push(criarOcorrencia({
|
|
96
93
|
tipo: 'circleci-command-no-parameters',
|
|
97
94
|
nivel: 'info',
|
|
@@ -133,14 +130,14 @@ export const detectorCircleCIEstrutura = {
|
|
|
133
130
|
const wfValues = Object.values(workflows);
|
|
134
131
|
const usedJobs = new Set();
|
|
135
132
|
for (const wf of wfValues) {
|
|
136
|
-
if (
|
|
133
|
+
if (typeof wf === 'object') {
|
|
137
134
|
const wfJobs = wf.jobs;
|
|
138
135
|
if (Array.isArray(wfJobs)) {
|
|
139
136
|
for (const wfJob of wfJobs) {
|
|
140
137
|
if (typeof wfJob === 'string') {
|
|
141
138
|
usedJobs.add(wfJob);
|
|
142
139
|
}
|
|
143
|
-
else if (
|
|
140
|
+
else if (typeof wfJob === 'object') {
|
|
144
141
|
Object.keys(wfJob).forEach(k => usedJobs.add(k));
|
|
145
142
|
}
|
|
146
143
|
}
|
|
@@ -162,7 +159,7 @@ export const detectorCircleCIEstrutura = {
|
|
|
162
159
|
// Resource class pricing consideration
|
|
163
160
|
if (jobs.jobs) {
|
|
164
161
|
for (const [, job] of Object.entries(jobs.jobs)) {
|
|
165
|
-
if (
|
|
162
|
+
if (!('resource_class' in job) && job.steps && job.steps.length > 5) {
|
|
166
163
|
ocorrencias.push(criarOcorrencia({
|
|
167
164
|
tipo: 'circleci-resource-class-pricing',
|
|
168
165
|
nivel: 'info',
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { ConversorGhaToGitlab } from './engines/converter-gha-to-gitlab.js';
|
|
2
2
|
export const registroConversores = [new ConversorGhaToGitlab()];
|
|
3
3
|
export function obterConversor(de, para) {
|
|
4
|
-
return registroConversores
|
|
4
|
+
return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
|
|
5
5
|
}
|
|
@@ -10,5 +10,5 @@ export const registroConversores = [new ConversorGhaToGitlab()];
|
|
|
10
10
|
* Busca um conversor compatível com as plataformas de origem e destino.
|
|
11
11
|
*/
|
|
12
12
|
export function obterConversor(de, para) {
|
|
13
|
-
return registroConversores
|
|
13
|
+
return registroConversores?.find(elem => elem.de.toLowerCase() === de.toLowerCase() && elem.para.toLowerCase() === para.toLowerCase());
|
|
14
14
|
}
|
|
@@ -83,7 +83,7 @@ export function aplicarCorrecaoArquivo(arquivo, ocorrencias, config) {
|
|
|
83
83
|
/**
|
|
84
84
|
* Aplica correções em múltiplos arquivos
|
|
85
85
|
*/
|
|
86
|
-
export
|
|
86
|
+
export function aplicarCorrecoesEmLote(porArquivo, config) {
|
|
87
87
|
const resultados = [];
|
|
88
88
|
let sucesso = 0;
|
|
89
89
|
let falhas = 0;
|
|
@@ -12,9 +12,10 @@ import { mapaReversao } from './map-reversion.js';
|
|
|
12
12
|
const { log, logAuto, CorretorEstruturaExtraMensagens } = getMessages();
|
|
13
13
|
export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd()) {
|
|
14
14
|
// Captura dinâmica das configs (evita congelar valores em tempo de import)
|
|
15
|
-
const CONCORRENCIA =
|
|
15
|
+
const CONCORRENCIA = config.STRUCTURE_CONCURRENCY;
|
|
16
16
|
const AUTO_CORRECAO = config.STRUCTURE_AUTO_FIX;
|
|
17
|
-
const
|
|
17
|
+
const rawPlugins = config.STRUCTURE_PLUGINS ?? [];
|
|
18
|
+
const PLUGINS = Array.isArray(rawPlugins) ? rawPlugins.filter((p) => typeof p === 'string') : [];
|
|
18
19
|
const ESTRUTURA_CAMADAS = config.ESTRUTURA_CAMADAS;
|
|
19
20
|
const limit = pLimit(CONCORRENCIA);
|
|
20
21
|
await Promise.all(mapa.map(entry => limit(async () => {
|
|
@@ -68,17 +69,17 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
|
|
|
68
69
|
})));
|
|
69
70
|
for (const pluginRel of PLUGINS) {
|
|
70
71
|
try {
|
|
71
|
-
const resolvido = resolverPluginSeguro(baseDir,
|
|
72
|
+
const resolvido = resolverPluginSeguro(baseDir, pluginRel);
|
|
72
73
|
if (resolvido.erro) {
|
|
73
|
-
logAuto.pluginIgnorado(
|
|
74
|
+
logAuto.pluginIgnorado(pluginRel, resolvido.erro);
|
|
74
75
|
continue;
|
|
75
76
|
}
|
|
76
77
|
const caminhoPlugin = resolvido.caminho;
|
|
77
78
|
if (!caminhoPlugin) {
|
|
78
|
-
logAuto.caminhoNaoResolvido(
|
|
79
|
+
logAuto.caminhoNaoResolvido(pluginRel);
|
|
79
80
|
continue;
|
|
80
81
|
}
|
|
81
|
-
const pluginModule = await importarModuloSeguro(baseDir,
|
|
82
|
+
const pluginModule = await importarModuloSeguro(baseDir, pluginRel);
|
|
82
83
|
let pluginFn;
|
|
83
84
|
if (pluginModule && typeof pluginModule === 'object' && 'default' in pluginModule && typeof pluginModule.default === 'function') {
|
|
84
85
|
pluginFn = pluginModule.default;
|
|
@@ -103,7 +104,7 @@ export async function corrigirEstrutura(mapa, fileEntries, baseDir = process.cwd
|
|
|
103
104
|
else if (typeof err === 'string') {
|
|
104
105
|
msg = err;
|
|
105
106
|
}
|
|
106
|
-
logAuto.pluginFalhou(
|
|
107
|
+
logAuto.pluginFalhou(pluginRel, msg);
|
|
107
108
|
}
|
|
108
109
|
}
|
|
109
110
|
}
|
|
@@ -41,7 +41,7 @@ export class GerenciadorMapaReversao {
|
|
|
41
41
|
}
|
|
42
42
|
};
|
|
43
43
|
// Validação básica
|
|
44
|
-
if (!
|
|
44
|
+
if (!Array.isArray(this.mapa.moves)) {
|
|
45
45
|
throw new Error(messages.ExcecoesMensagens.mapaReversaoCorrompido);
|
|
46
46
|
}
|
|
47
47
|
logAuto.mapaReversaoCarregado(this.mapa.moves.length);
|
|
@@ -89,7 +89,7 @@ export class GerenciadorMapaReversao {
|
|
|
89
89
|
// quando true, evita persistir o mapa no disco imediatamente (útil para chamadas em massa/tests)
|
|
90
90
|
skipSalvar) {
|
|
91
91
|
try {
|
|
92
|
-
const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).
|
|
92
|
+
const id = `move_${Date.now()}_${Math.random().toString(CONSTANTES_MAPA.RADIX_36).slice(CONSTANTES_MAPA.ID_OFFSET, CONSTANTES_MAPA.ID_OFFSET + CONSTANTES_MAPA.ID_LENGTH)}`;
|
|
93
93
|
const move = {
|
|
94
94
|
id,
|
|
95
95
|
timestamp: new Date().toISOString(),
|
|
@@ -301,9 +301,9 @@ async function extrairNomesExportados(srcDir, relPath, visitados = new Set(), pr
|
|
|
301
301
|
nomes.add(exportDecl[1]);
|
|
302
302
|
}
|
|
303
303
|
// export { name1, name2 as alias, ... }
|
|
304
|
-
const exportList = trimmed.match(/^export\s+type\s
|
|
304
|
+
const exportList = trimmed.match(/^export\s+(?:type\s+)?\s*\{([^}]+)\}/);
|
|
305
305
|
if (exportList) {
|
|
306
|
-
const body = exportList[1]
|
|
306
|
+
const body = exportList[1];
|
|
307
307
|
if (body) {
|
|
308
308
|
body.split(',').forEach(part => {
|
|
309
309
|
const m = part.trim().match(/^(\w+)(?:\s+as\s+\w+)?$/);
|
|
@@ -469,7 +469,7 @@ async function repararImportsBarrelPerdidos(srcDir, barrelsPerdidos, _movimentos
|
|
|
469
469
|
if (!match) {
|
|
470
470
|
return null;
|
|
471
471
|
}
|
|
472
|
-
return { imported: match[1], local: match[2]
|
|
472
|
+
return { imported: match[1], local: match[2] || match[1] };
|
|
473
473
|
}).filter((n) => n !== null);
|
|
474
474
|
const nomesQueFicam = [];
|
|
475
475
|
const nomesQueMoveram = [];
|
|
@@ -19,7 +19,7 @@ function exists(caminho) {
|
|
|
19
19
|
function pathFromAlias(aliasSpec, srcRoot) {
|
|
20
20
|
const spec = aliasSpec.replace(/^@/, '');
|
|
21
21
|
const parts = spec.split('/');
|
|
22
|
-
const top = parts
|
|
22
|
+
const top = parts?.shift();
|
|
23
23
|
return path.join(srcRoot, top ?? '', parts.join('/'));
|
|
24
24
|
}
|
|
25
25
|
export function pickExtForAlias(aliasBase, srcRoot) {
|
|
@@ -67,40 +67,41 @@ export function rewriteToAlias(spec, ctx) {
|
|
|
67
67
|
export function transformCodeForTests(code, ctx) {
|
|
68
68
|
let changed = false;
|
|
69
69
|
const rewrite = (spec) => rewriteToAlias(spec, ctx);
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
70
|
+
let result = code;
|
|
71
|
+
result = result.replace(/(import\s+[^'"\n]+?from\s+)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
|
|
72
|
+
const res = rewrite(spec);
|
|
73
|
+
if (!res.changed) {
|
|
74
|
+
return substring;
|
|
74
75
|
}
|
|
75
76
|
changed = true;
|
|
76
|
-
return `${p1}${delimitadorString}${
|
|
77
|
+
return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
|
|
77
78
|
});
|
|
78
|
-
|
|
79
|
-
const
|
|
80
|
-
if (!
|
|
81
|
-
return
|
|
79
|
+
result = result.replace(/(import\s*)(["'])([^"']+?)\2/g, (substring, p1, delimitadorString, spec) => {
|
|
80
|
+
const res = rewrite(spec);
|
|
81
|
+
if (!res.changed) {
|
|
82
|
+
return substring;
|
|
82
83
|
}
|
|
83
84
|
changed = true;
|
|
84
|
-
return `${p1}${delimitadorString}${
|
|
85
|
+
return `${p1}${delimitadorString}${res.value}${delimitadorString}`;
|
|
85
86
|
});
|
|
86
|
-
|
|
87
|
-
const
|
|
88
|
-
if (!
|
|
89
|
-
return
|
|
87
|
+
result = result.replace(/(import\s*\()(\s*["'])([^"']+?)(["']\s*\))/g, (substring, p1, q1, spec, q2) => {
|
|
88
|
+
const res = rewrite(spec);
|
|
89
|
+
if (!res.changed) {
|
|
90
|
+
return substring;
|
|
90
91
|
}
|
|
91
92
|
changed = true;
|
|
92
|
-
return `${p1}${q1}${
|
|
93
|
+
return `${p1}${q1}${res.value}${q2}`;
|
|
93
94
|
});
|
|
94
|
-
|
|
95
|
-
const
|
|
96
|
-
if (!
|
|
97
|
-
return
|
|
95
|
+
result = result.replace(/(vi\.(?:do)?mock\s*\()(\s*["'])([^"']+?)(["'])(\s*,?)/g, (substring, p1, q1, spec, q2, comma = '') => {
|
|
96
|
+
const res = rewrite(spec);
|
|
97
|
+
if (!res.changed) {
|
|
98
|
+
return substring;
|
|
98
99
|
}
|
|
99
100
|
changed = true;
|
|
100
|
-
return `${p1}${q1}${
|
|
101
|
+
return `${p1}${q1}${res.value}${q2}${comma}`;
|
|
101
102
|
});
|
|
102
103
|
return {
|
|
103
|
-
code,
|
|
104
|
+
code: result,
|
|
104
105
|
changed
|
|
105
106
|
};
|
|
106
107
|
}
|
|
@@ -62,14 +62,14 @@ export function analyzeTypeUsage(match, fullCode, fileCaminho, ast) {
|
|
|
62
62
|
/**
|
|
63
63
|
* Analisa uso de unknown com foco em type guards
|
|
64
64
|
*/
|
|
65
|
-
export
|
|
65
|
+
export function analyzeUnknownUsage(match, fullCode, fileCaminho, ast) {
|
|
66
66
|
// Mesma lógica de analyzeTypeUsage, mas mais conservador
|
|
67
67
|
const analysis = analyzeTypeUsage(match, fullCode, fileCaminho, ast);
|
|
68
68
|
// Penalizar confiança em 10% para unknown (mais conservador)
|
|
69
69
|
analysis.confidence = Math.max(0, analysis.confidence - 10);
|
|
70
70
|
// Se confiança ainda é baixa, sugerir manter unknown
|
|
71
71
|
if (analysis.confidence < 70) {
|
|
72
|
-
analysis.suggestion =
|
|
72
|
+
analysis.suggestion = `Confiança baixa para substituir unknown. Considere adicionar type guards ou criar tipo dedicado em ${getTypesDirectoryDisplay()}`;
|
|
73
73
|
}
|
|
74
|
-
return analysis;
|
|
74
|
+
return Promise.resolve(analysis);
|
|
75
75
|
}
|
|
@@ -18,13 +18,13 @@ export async function validateTypeReplacement(originalCode, fixedCodigo, typeAna
|
|
|
18
18
|
if (typeAnalise.createdNewType) {
|
|
19
19
|
const existingTipo = await findExistingType(typeAnalise.typeName);
|
|
20
20
|
if (existingTipo && !isSameType(existingTipo, typeAnalise.typeDefinition)) {
|
|
21
|
-
result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente.
|
|
21
|
+
result.warnings.push(`Tipo ${typeAnalise.typeName} já existe com definição diferente. Verifique conflito em ${existingTipo.path}`);
|
|
22
22
|
}
|
|
23
23
|
}
|
|
24
24
|
// 2. Verificar se tipo inferido é compatível com uso
|
|
25
25
|
const usageValidation = validateTypeUsageCompatibility(fixedCodigo, typeAnalise);
|
|
26
26
|
if (!usageValidation.isCompatible) {
|
|
27
|
-
result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado.
|
|
27
|
+
result.errors.push(`Tipo inferido ${typeAnalise.inferredTipo} incompatível com uso detectado. Esperado: ${usageValidation.expectedType}`);
|
|
28
28
|
result.isCompatible = false;
|
|
29
29
|
}
|
|
30
30
|
// 3. Verificar se import foi adicionado corretamente
|
|
@@ -214,7 +214,7 @@ function extractUsageFromNode(node, varNome) {
|
|
|
214
214
|
* Extrai informações de MemberExpression
|
|
215
215
|
*/
|
|
216
216
|
function extractMemberExpressionUsage(node, varNome) {
|
|
217
|
-
const property = node.property?.name ?? node.property.value;
|
|
217
|
+
const property = node.property?.name ?? String(node.property.value);
|
|
218
218
|
return {
|
|
219
219
|
name: varNome,
|
|
220
220
|
nodeType: 'MemberExpression',
|
|
@@ -222,7 +222,7 @@ function extractMemberExpressionUsage(node, varNome) {
|
|
|
222
222
|
column: node.loc?.start?.column ?? 0,
|
|
223
223
|
context: extractNodeContext(node),
|
|
224
224
|
operation: 'access',
|
|
225
|
-
property: property
|
|
225
|
+
property: property || undefined
|
|
226
226
|
};
|
|
227
227
|
}
|
|
228
228
|
/**
|
|
@@ -250,7 +250,7 @@ function extractNodeContext(node) {
|
|
|
250
250
|
}
|
|
251
251
|
if (node.type === 'MemberExpression') {
|
|
252
252
|
const obj = node.object?.name ?? extractNodeContext(node.object);
|
|
253
|
-
const prop = node.property?.name ?? node.property.value;
|
|
253
|
+
const prop = node.property?.name ?? String(node.property.value);
|
|
254
254
|
return `${obj}.${prop}`;
|
|
255
255
|
}
|
|
256
256
|
if (node.type === 'CallExpression') {
|