@semacode/cli 2.3.0 → 2.3.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +39 -39
- package/README.md +251 -228
- package/dist/agentEntryPoints.js +551 -550
- package/dist/angular-consumer-standalone.d.ts +3 -1
- package/dist/angular-consumer-standalone.js +12 -8
- package/dist/drift.part01.d.ts +32 -2
- package/dist/drift.part01.js +2 -0
- package/dist/drift.part04.d.ts +3 -2
- package/dist/drift.part04.js +6 -3
- package/dist/drift.part05.d.ts +2 -1
- package/dist/drift.part05.js +4 -3
- package/dist/drift.part06.d.ts +2 -1
- package/dist/drift.part06.js +9 -5
- package/dist/drift.part07.d.ts +11 -10
- package/dist/drift.part07.js +40 -30
- package/dist/drift.part08.d.ts +2 -1
- package/dist/drift.part08.js +4 -3
- package/dist/drift.part11.js +71 -6
- package/dist/drift.part12.js +14 -1
- package/dist/drift.part13.d.ts +42 -7
- package/dist/drift.part13.js +660 -36
- package/dist/driftCache.d.ts +49 -0
- package/dist/driftCache.js +311 -0
- package/dist/driftCacheIncremental.d.ts +98 -0
- package/dist/driftCacheIncremental.js +596 -0
- package/dist/driftCatalogo.d.ts +91 -0
- package/dist/driftCatalogo.js +657 -0
- package/dist/driftCatalogoPersistente.d.ts +8 -0
- package/dist/driftCatalogoPersistente.js +77 -0
- package/dist/driftEscopo.d.ts +23 -0
- package/dist/driftEscopo.js +563 -0
- package/dist/driftEscopoReferencias.d.ts +4 -0
- package/dist/driftEscopoReferencias.js +265 -0
- package/dist/driftOrcamento.d.ts +12 -0
- package/dist/driftOrcamento.js +19 -3
- package/dist/execucoesExternas.js +5 -19
- package/dist/iaPrompts.js +310 -310
- package/dist/index.part01.d.ts +16 -1
- package/dist/index.part01.js +80 -4
- package/dist/index.part02.js +21 -21
- package/dist/index.part03.d.ts +2 -2
- package/dist/index.part03.js +14 -3
- package/dist/index.part04.d.ts +2 -2
- package/dist/index.part04.js +113 -101
- package/dist/index.part05.d.ts +1 -1
- package/dist/index.part05.js +99 -22
- package/dist/index.part06.js +3 -2
- package/dist/index.part07.js +24 -24
- package/dist/index.part08.js +1 -1
- package/dist/init/templates.part01.js +393 -393
- package/dist/init/templates.part02.js +189 -189
- package/dist/initTemplatesBackend.js +73 -73
- package/dist/initTemplatesBase.js +81 -81
- package/dist/initTemplatesFlutter.js +137 -137
- package/dist/initTemplatesRuntime.js +350 -350
- package/dist/initTemplatesWeb.js +309 -309
- package/dist/pipelineConteudo/command.js +1 -36
- package/dist/projeto.d.ts +1 -1
- package/dist/projetoCarregar.d.ts +2 -2
- package/dist/projetoCarregar.js +47 -24
- package/dist/projetoCatalogo.d.ts +7 -0
- package/dist/projetoCatalogo.js +125 -0
- package/dist/projetoTipos.d.ts +14 -5
- package/dist/sync/index.js +35 -35
- package/docs/README.md +34 -34
- package/docs/ai-integration.md +1 -7
- package/docs/ai-onboarding.md +62 -62
- package/docs/ai-workflow.md +4 -0
- package/docs/auth.md +26 -26
- package/docs/cli.md +79 -79
- package/docs/commands.md +16 -13
- package/docs/database.md +15 -15
- package/docs/deploy.md +41 -41
- package/docs/descoberta-capacidades.md +106 -106
- package/docs/documentation.md +37 -46
- package/docs/env.md +16 -16
- package/docs/frontend.md +41 -41
- package/docs/getting-started.md +57 -57
- package/docs/i18n.md +15 -15
- package/docs/pipeline-conteudo.md +246 -246
- package/docs/profiles.md +54 -54
- package/docs/repositories.md +43 -43
- package/docs/rollback.md +31 -31
- package/docs/security.md +32 -32
- package/docs/sistemas-interativos.md +373 -378
- package/docs/support.md +8 -8
- package/docs/testing.md +51 -44
- package/docs/vocabulary.md +29 -29
- package/exemplos/agendamento.sema +1 -1
- package/exemplos/assinatura.sema +1 -1
- package/exemplos/auditoria.sema +1 -1
- package/exemplos/autenticacao.sema +1 -1
- package/exemplos/author_obra_comum.sema +1 -1
- package/exemplos/author_tema_sensivel.sema +1 -1
- package/exemplos/automacao.sema +1 -1
- package/exemplos/cadastro_usuario.sema +1 -1
- package/exemplos/calculadora.sema +1 -1
- package/exemplos/crud_simples.sema +1 -1
- package/exemplos/estoque.sema +1 -1
- package/exemplos/exportacao.sema +1 -1
- package/exemplos/fila.sema +1 -1
- package/exemplos/integracao_externa.sema +1 -1
- package/exemplos/multi_tenant.sema +1 -1
- package/exemplos/notificacao.sema +1 -1
- package/exemplos/operacao_estrategia.sema +132 -132
- package/exemplos/operacao_estrategia_discovery.sema +220 -220
- package/exemplos/operacao_estrategia_fluxo.sema +114 -114
- package/exemplos/operacao_estrategia_gates.sema +106 -106
- package/exemplos/operacao_estrategia_quarentena.sema +133 -133
- package/exemplos/operacao_estrategia_rollout.sema +124 -124
- package/exemplos/pagamento.sema +1 -1
- package/exemplos/pagamento_dominio.sema +1 -1
- package/exemplos/pedido.sema +1 -1
- package/exemplos/permissao.sema +1 -1
- package/exemplos/persistencia_vendor_first.sema +1 -1
- package/exemplos/pipeline-conteudo/README.md +44 -44
- package/exemplos/pipeline-conteudo/alvos.json +23 -23
- package/exemplos/pipeline-conteudo/definicao.json +136 -136
- package/exemplos/profile_conversas.sema +165 -165
- package/exemplos/profile_game.sema +1 -1
- package/exemplos/profile_legal.sema +1 -1
- package/exemplos/profile_ops.sema +1 -1
- package/exemplos/profile_research.sema +1 -1
- package/exemplos/profile_simulation.sema +211 -211
- package/exemplos/profile_software.sema +1 -1
- package/exemplos/profile_workflow_n8n.sema +1 -1
- package/exemplos/relatorio.sema +1 -1
- package/exemplos/replica_analitica_erp.sema +1 -1
- package/exemplos/sistemas-interativos/README.md +100 -100
- package/exemplos/sistemas-interativos/advanced/acceptance-context-evaluate-valid.json +5 -5
- package/exemplos/sistemas-interativos/advanced/acceptance-lock-valid.json +16 -16
- package/exemplos/sistemas-interativos/advanced/asset-provenance-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/autonomy-repair-valid.json +93 -93
- package/exemplos/sistemas-interativos/advanced/control-run-definition-valid.json +78 -78
- package/exemplos/sistemas-interativos/advanced/control-run-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/distributed-workers-valid.json +79 -79
- package/exemplos/sistemas-interativos/advanced/editor-state-valid.json +42 -42
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-after-valid.json +32 -32
- package/exemplos/sistemas-interativos/advanced/engine-snapshot-before-valid.json +23 -23
- package/exemplos/sistemas-interativos/advanced/job-orchestration-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/multimodal-evidence-valid.json +46 -46
- package/exemplos/sistemas-interativos/advanced/multiplayer-authority-valid.json +39 -39
- package/exemplos/sistemas-interativos/advanced/playtest-fuzz-valid.json +37 -37
- package/exemplos/sistemas-interativos/advanced/portability-valid.json +104 -104
- package/exemplos/sistemas-interativos/advanced/temporal-evidence-valid.json +27 -27
- package/exemplos/sistemas-interativos/advanced/temporal-valid.json +118 -118
- package/exemplos/sistemas-interativos/experience-ir-valid.json +459 -459
- package/exemplos/sistemas-interativos/game-2d.json +83 -83
- package/exemplos/sistemas-interativos/game-3d-human.json +81 -81
- package/exemplos/sistemas-interativos/game-pixel-16-bit.json +97 -97
- package/exemplos/sistemas-interativos/game-pixel-8-bit.json +94 -94
- package/exemplos/sistemas-interativos/game-xr-human.json +80 -80
- package/exemplos/sistemas-interativos/hybrid-2-5d.json +108 -108
- package/exemplos/sistemas-interativos/protocol-mutating-rollback-valid.json +75 -75
- package/exemplos/sistemas-interativos/protocol-read-only-valid.json +58 -58
- package/exemplos/sistemas-interativos/simulation-2d-controlled.json +97 -97
- package/exemplos/sistemas-interativos/simulation-3d-calibrated-autonomous.json +141 -141
- package/exemplos/sistemas-interativos/simulation-headless-autonomous-batch.json +112 -112
- package/exemplos/sistemas-interativos/simulation-pixel-16-bit.json +103 -103
- package/exemplos/sistemas-interativos/simulation-text-controlled.json +95 -95
- package/exemplos/testes_embutidos.sema +1 -1
- package/exemplos/tratamento_erro.sema +1 -1
- package/exemplos/upload_arquivo.sema +1 -1
- package/exemplos/webhook.sema +1 -1
- package/node_modules/@sema/gerador-cpp/dist/index.js +176 -176
- package/node_modules/@sema/gerador-cpp/package.json +1 -1
- package/node_modules/@sema/gerador-css/dist/index.part01.js +10 -10
- package/node_modules/@sema/gerador-css/dist/index.part02.js +460 -460
- package/node_modules/@sema/gerador-dotnet/dist/index.js +169 -169
- package/node_modules/@sema/gerador-dotnet/package.json +1 -1
- package/node_modules/@sema/gerador-html/dist/index.js +17 -17
- package/node_modules/@sema/gerador-lua/dist/index.js +51 -51
- package/node_modules/@sema/gerador-php/dist/index.js +113 -113
- package/node_modules/@sema/gerador-python/dist/index.part02.js +3 -3
- package/node_modules/@sema/gerador-typescript/dist/index.part02.js +11 -11
- package/node_modules/@sema/nucleo/dist/diagnosticos/melhorador.js +42 -42
- package/package.json +3 -3
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
// SEMA-GOVERNED: sema.produto.governanca_ia.drift
|
|
2
|
+
// Descricao: reutiliza um snapshot validado do catalogo global sem transformar escopo estreito em varredura ampla.
|
|
3
|
+
import path from "node:path";
|
|
4
|
+
import { criarCacheDrift, digestJsonCanonicoCacheDrift, } from "./driftCache.js";
|
|
5
|
+
import { criarCatalogoDrift, } from "./driftCatalogo.js";
|
|
6
|
+
export const SCHEMA_CACHE_CATALOGO_DRIFT = "sema.drift-catalog-cache/v1";
|
|
7
|
+
function chaveRelativa(base, alvo) {
|
|
8
|
+
const relativo = path.relative(base, path.resolve(base, alvo)).replace(/\\/g, "/");
|
|
9
|
+
return relativo || ".";
|
|
10
|
+
}
|
|
11
|
+
function identidadePlanoCatalogo(opcoes) {
|
|
12
|
+
const base = path.resolve(opcoes.baseDiretorio ?? process.cwd());
|
|
13
|
+
const ignorados = [...(opcoes.diretoriosIgnorados ?? [])]
|
|
14
|
+
.map((item) => item.trim().toLowerCase())
|
|
15
|
+
.filter(Boolean)
|
|
16
|
+
.sort((a, b) => a.localeCompare(b, "en"));
|
|
17
|
+
return {
|
|
18
|
+
schema: SCHEMA_CACHE_CATALOGO_DRIFT,
|
|
19
|
+
arquivos: [...(opcoes.arquivos ?? [])]
|
|
20
|
+
.map((arquivo) => chaveRelativa(base, arquivo))
|
|
21
|
+
.sort((a, b) => a.localeCompare(b, "en")),
|
|
22
|
+
raizes: [...(opcoes.raizes ?? [])]
|
|
23
|
+
.map((raiz) => chaveRelativa(base, raiz))
|
|
24
|
+
.sort((a, b) => a.localeCompare(b, "en")),
|
|
25
|
+
extensoes: opcoes.extensoes
|
|
26
|
+
? [...opcoes.extensoes].map((item) => item.toLowerCase()).sort((a, b) => a.localeCompare(b, "en"))
|
|
27
|
+
: null,
|
|
28
|
+
diretoriosIgnorados: ignorados,
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
export async function criarCatalogoPersistenteDrift(opcoes, opcoesCache) {
|
|
32
|
+
const baseProjeto = path.resolve(opcoes.baseDiretorio ?? process.cwd());
|
|
33
|
+
if (opcoesCache.politica === "off" || (opcoes.raizes?.length ?? 0) === 0) {
|
|
34
|
+
return criarCatalogoDrift(opcoes);
|
|
35
|
+
}
|
|
36
|
+
const plano = identidadePlanoCatalogo(opcoes);
|
|
37
|
+
const entrada = {
|
|
38
|
+
fingerprintConteudo: digestJsonCanonicoCacheDrift(plano),
|
|
39
|
+
identidade: {
|
|
40
|
+
schema: SCHEMA_CACHE_CATALOGO_DRIFT,
|
|
41
|
+
executor: opcoesCache.identidade,
|
|
42
|
+
plano,
|
|
43
|
+
},
|
|
44
|
+
};
|
|
45
|
+
let catalogoCalculado;
|
|
46
|
+
const cache = criarCacheDrift({
|
|
47
|
+
baseProjeto,
|
|
48
|
+
politica: opcoesCache.politica,
|
|
49
|
+
observador: opcoes.observador,
|
|
50
|
+
});
|
|
51
|
+
const resultado = await cache.obterOuCalcular(entrada, async () => {
|
|
52
|
+
catalogoCalculado = await criarCatalogoDrift(opcoes);
|
|
53
|
+
return catalogoCalculado.snapshot();
|
|
54
|
+
});
|
|
55
|
+
if (catalogoCalculado) {
|
|
56
|
+
return catalogoCalculado;
|
|
57
|
+
}
|
|
58
|
+
const restauradoOuRecalculado = await criarCatalogoDrift({
|
|
59
|
+
...opcoes,
|
|
60
|
+
snapshot: resultado.valor,
|
|
61
|
+
});
|
|
62
|
+
if (restauradoOuRecalculado.metricas().origem === "snapshot") {
|
|
63
|
+
return restauradoOuRecalculado;
|
|
64
|
+
}
|
|
65
|
+
// O envelope estava integro, mas o snapshot ficou obsoleto ou falhou na
|
|
66
|
+
// validacao runtime. A caminhada ja executada acima e reaproveitada; apenas
|
|
67
|
+
// substituimos atomicamente a entrada persistente.
|
|
68
|
+
const refresh = criarCacheDrift({
|
|
69
|
+
baseProjeto,
|
|
70
|
+
politica: "refresh",
|
|
71
|
+
observador: opcoes.observador,
|
|
72
|
+
});
|
|
73
|
+
const snapshotAtual = restauradoOuRecalculado.snapshot();
|
|
74
|
+
await refresh.obterOuCalcular(entrada, async () => snapshotAtual);
|
|
75
|
+
return restauradoOuRecalculado;
|
|
76
|
+
}
|
|
77
|
+
//# sourceMappingURL=driftCatalogoPersistente.js.map
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { ContextoProjetoCarregado } from "./projeto.js";
|
|
2
|
+
import type { ConfiguracaoEscopoDriftAplicada, EscopoDriftReal } from "./drift.part01.js";
|
|
3
|
+
import type { CatalogoDrift } from "./driftCatalogo.js";
|
|
4
|
+
import type { CacheIncrementalDrift } from "./driftCacheIncremental.js";
|
|
5
|
+
export { extrairReferenciasLocaisDrift } from "./driftEscopoReferencias.js";
|
|
6
|
+
export type EstrategiaEscopoDrift = "arquivos_vinculados" | "projeto";
|
|
7
|
+
export type CoberturaEscopoDrift = "completa" | "parcial";
|
|
8
|
+
export interface PlanoEscopoDrift {
|
|
9
|
+
escopo: EscopoDriftReal;
|
|
10
|
+
estrategia: EstrategiaEscopoDrift;
|
|
11
|
+
arquivos: string[];
|
|
12
|
+
arquivosDeclarados: string[];
|
|
13
|
+
arquivosInferidos: string[];
|
|
14
|
+
arquivosAusentes: string[];
|
|
15
|
+
diretorios: string[];
|
|
16
|
+
modulos: string[];
|
|
17
|
+
cobertura: CoberturaEscopoDrift;
|
|
18
|
+
bloqueios: string[];
|
|
19
|
+
dependencias: Record<string, string[]>;
|
|
20
|
+
}
|
|
21
|
+
export declare function planejarEscopoDrift(contexto: ContextoProjetoCarregado, configuracao: ConfiguracaoEscopoDriftAplicada): Promise<PlanoEscopoDrift>;
|
|
22
|
+
export declare function expandirDependenciasPlanoDrift(contexto: ContextoProjetoCarregado, plano: PlanoEscopoDrift, catalogo: CatalogoDrift, cache?: CacheIncrementalDrift): Promise<PlanoEscopoDrift>;
|
|
23
|
+
export declare function mapearDependenciasCatalogadasDrift(contexto: ContextoProjetoCarregado, catalogo: CatalogoDrift, cache: CacheIncrementalDrift, arquivos?: readonly string[]): Promise<Record<string, string[]>>;
|
|
@@ -0,0 +1,563 @@
|
|
|
1
|
+
// SEMA-GOVERNED: sema.produto.governanca_ia.drift
|
|
2
|
+
// Descricao: planeja o conjunto fisico minimo que pode ser indexado antes de qualquer caminhada de drift.
|
|
3
|
+
import { lstat, realpath } from "node:fs/promises";
|
|
4
|
+
import path from "node:path";
|
|
5
|
+
import { resolverDiretoriosCodigoEscopoReal } from "./drift.part02.js";
|
|
6
|
+
import { candidatosReferenciaLocalDrift, extrairReferenciasLocaisDrift, raizesCodigoLogicasDrift, } from "./driftEscopoReferencias.js";
|
|
7
|
+
export { extrairReferenciasLocaisDrift } from "./driftEscopoReferencias.js";
|
|
8
|
+
const CONCORRENCIA_SONDAGENS_DRIFT = 16;
|
|
9
|
+
const CONCORRENCIA_MAPEAMENTO_DEPENDENCIAS_DRIFT = 8;
|
|
10
|
+
const EXTENSAO_POR_ORIGEM = {
|
|
11
|
+
// O indexador TypeScript tambem cobre JavaScript legado. Essa compatibilidade
|
|
12
|
+
// e necessaria para contratos antigos que usam `ts:` para simbolos browser-side.
|
|
13
|
+
ts: [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"],
|
|
14
|
+
// O resolvedor semantico trata JS/TS como a mesma familia. O planejamento
|
|
15
|
+
// precisa sondar a mesma familia para nao descartar uma implementacao `js:`
|
|
16
|
+
// escrita fisicamente em TypeScript antes de o resolvedor poder avalia-la.
|
|
17
|
+
js: [".js", ".jsx", ".mjs", ".cjs", ".ts", ".tsx"],
|
|
18
|
+
py: [".py"],
|
|
19
|
+
dart: [".dart"],
|
|
20
|
+
lua: [".lua"],
|
|
21
|
+
cs: [".cs"],
|
|
22
|
+
java: [".java"],
|
|
23
|
+
go: [".go"],
|
|
24
|
+
rust: [".rs"],
|
|
25
|
+
cpp: [".cpp", ".cc", ".cxx", ".hpp", ".h"],
|
|
26
|
+
php: [".php"],
|
|
27
|
+
};
|
|
28
|
+
function chaveCaminho(caminho) {
|
|
29
|
+
const absoluto = path.normalize(path.resolve(caminho));
|
|
30
|
+
return process.platform === "win32" ? absoluto.toLowerCase() : absoluto;
|
|
31
|
+
}
|
|
32
|
+
function caminhoEstaDentro(raiz, alvo) {
|
|
33
|
+
const relativo = path.relative(path.resolve(raiz), path.resolve(alvo));
|
|
34
|
+
return relativo === "" || (relativo !== ".."
|
|
35
|
+
&& !relativo.startsWith(`..${path.sep}`)
|
|
36
|
+
&& !path.isAbsolute(relativo));
|
|
37
|
+
}
|
|
38
|
+
async function mapearComLimite(itens, limite, executar) {
|
|
39
|
+
if (itens.length === 0) {
|
|
40
|
+
return [];
|
|
41
|
+
}
|
|
42
|
+
const resultados = new Array(itens.length);
|
|
43
|
+
let proximoIndice = 0;
|
|
44
|
+
const trabalhador = async () => {
|
|
45
|
+
for (;;) {
|
|
46
|
+
const indice = proximoIndice;
|
|
47
|
+
proximoIndice += 1;
|
|
48
|
+
if (indice >= itens.length) {
|
|
49
|
+
return;
|
|
50
|
+
}
|
|
51
|
+
resultados[indice] = await executar(itens[indice]);
|
|
52
|
+
}
|
|
53
|
+
};
|
|
54
|
+
await Promise.all(Array.from({ length: Math.min(Math.max(1, limite), itens.length) }, () => trabalhador()));
|
|
55
|
+
return resultados;
|
|
56
|
+
}
|
|
57
|
+
async function arquivoRegularContido(caminho, raizReal) {
|
|
58
|
+
try {
|
|
59
|
+
const informacao = await lstat(caminho);
|
|
60
|
+
if (!informacao.isFile() || informacao.isSymbolicLink()) {
|
|
61
|
+
return false;
|
|
62
|
+
}
|
|
63
|
+
const caminhoReal = await realpath(caminho);
|
|
64
|
+
return caminhoEstaDentro(raizReal, caminhoReal);
|
|
65
|
+
}
|
|
66
|
+
catch {
|
|
67
|
+
return false;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
async function sondarArquivosRegularesContidos(caminhos, raizReal) {
|
|
71
|
+
const unicos = [...new Map(caminhos.map((caminho) => [chaveCaminho(caminho), caminho])).entries()];
|
|
72
|
+
const resultados = await mapearComLimite(unicos, CONCORRENCIA_SONDAGENS_DRIFT, async ([chave, caminho]) => [chave, await arquivoRegularContido(caminho, raizReal)]);
|
|
73
|
+
return new Map(resultados);
|
|
74
|
+
}
|
|
75
|
+
function vinculosModulo(ir) {
|
|
76
|
+
return [
|
|
77
|
+
...ir.vinculos,
|
|
78
|
+
...ir.tasks.flatMap((task) => task.vinculos),
|
|
79
|
+
...ir.flows.flatMap((flow) => flow.vinculos),
|
|
80
|
+
...ir.routes.flatMap((route) => route.vinculos),
|
|
81
|
+
...ir.superficies.flatMap((superficie) => superficie.vinculos),
|
|
82
|
+
];
|
|
83
|
+
}
|
|
84
|
+
function implementacoesModulo(ir) {
|
|
85
|
+
return [
|
|
86
|
+
...ir.tasks.flatMap((task) => task.implementacoesExternas),
|
|
87
|
+
...ir.superficies.flatMap((superficie) => superficie.implementacoesExternas),
|
|
88
|
+
];
|
|
89
|
+
}
|
|
90
|
+
function resolverArquivoWorkspace(baseProjeto, valor) {
|
|
91
|
+
const absoluto = path.isAbsolute(valor)
|
|
92
|
+
? path.resolve(valor)
|
|
93
|
+
: path.resolve(baseProjeto, valor);
|
|
94
|
+
return caminhoEstaDentro(baseProjeto, absoluto) ? absoluto : undefined;
|
|
95
|
+
}
|
|
96
|
+
function variantesSegmentoDiretorio(segmento) {
|
|
97
|
+
const camel = segmento.replace(/_([a-z0-9])/gi, (_ocorrencia, caractere) => caractere.toUpperCase());
|
|
98
|
+
return [...new Set([
|
|
99
|
+
segmento,
|
|
100
|
+
segmento.includes("_") ? segmento.replace(/_/g, "-") : undefined,
|
|
101
|
+
/(?:^|_)id$/i.test(segmento) ? `[${segmento}]` : undefined,
|
|
102
|
+
/(?:^|_)id$/i.test(segmento) && camel !== segmento ? `[${camel}]` : undefined,
|
|
103
|
+
].filter((item) => Boolean(item)))];
|
|
104
|
+
}
|
|
105
|
+
function adicionarCandidatoPreservandoForma(candidatos, baseProjeto, caminho) {
|
|
106
|
+
const absoluto = path.resolve(caminho);
|
|
107
|
+
if (!caminhoEstaDentro(baseProjeto, absoluto)) {
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
const chave = chaveCaminho(absoluto);
|
|
111
|
+
if (!candidatos.has(chave)) {
|
|
112
|
+
candidatos.set(chave, absoluto);
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
function variantesNomeArquivo(segmento) {
|
|
116
|
+
const pascal = segmento
|
|
117
|
+
.split(/[_-]+/)
|
|
118
|
+
.filter(Boolean)
|
|
119
|
+
.map((parte) => `${parte[0]?.toUpperCase() ?? ""}${parte.slice(1)}`)
|
|
120
|
+
.join("");
|
|
121
|
+
return [...new Set([
|
|
122
|
+
segmento,
|
|
123
|
+
segmento.includes("_") ? segmento.replace(/_/g, "-") : undefined,
|
|
124
|
+
segmento.includes("_") ? segmento.replace(/_/g, ".") : undefined,
|
|
125
|
+
pascal && pascal !== segmento ? pascal : undefined,
|
|
126
|
+
].filter((item) => Boolean(item)))];
|
|
127
|
+
}
|
|
128
|
+
function variantesCaminhoSegmentos(segmentos) {
|
|
129
|
+
let variantes = [[]];
|
|
130
|
+
for (const segmento of segmentos) {
|
|
131
|
+
const opcoes = variantesSegmentoDiretorio(segmento);
|
|
132
|
+
variantes = variantes.flatMap((prefixo) => opcoes.map((opcao) => [...prefixo, opcao]));
|
|
133
|
+
}
|
|
134
|
+
return variantes.slice(0, 16);
|
|
135
|
+
}
|
|
136
|
+
function candidatosArquivoImpl(contexto, impl) {
|
|
137
|
+
const candidatos = new Map();
|
|
138
|
+
const adicionar = (caminho) => {
|
|
139
|
+
adicionarCandidatoPreservandoForma(candidatos, contexto.baseProjeto, caminho);
|
|
140
|
+
};
|
|
141
|
+
if (impl.origemArquivo) {
|
|
142
|
+
const declarado = resolverArquivoWorkspace(contexto.baseProjeto, impl.origemArquivo);
|
|
143
|
+
if (declarado) {
|
|
144
|
+
adicionar(declarado);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
const partes = impl.caminho.split(".").map((parte) => parte.trim()).filter(Boolean);
|
|
148
|
+
if (partes.length < 2) {
|
|
149
|
+
return [...candidatos.values()];
|
|
150
|
+
}
|
|
151
|
+
const bases = [contexto.baseProjeto, ...contexto.diretoriosCodigo];
|
|
152
|
+
const extensoes = EXTENSAO_POR_ORIGEM[impl.origem] ?? [];
|
|
153
|
+
for (const removerCauda of [1, 2]) {
|
|
154
|
+
const segmentosOriginais = partes.slice(0, Math.max(1, partes.length - removerCauda));
|
|
155
|
+
for (const base of bases) {
|
|
156
|
+
const nomeBase = path.basename(base).toLowerCase();
|
|
157
|
+
const segmentos = segmentosOriginais[0]?.toLowerCase() === nomeBase
|
|
158
|
+
? segmentosOriginais.slice(1)
|
|
159
|
+
: segmentosOriginais;
|
|
160
|
+
if (segmentos.length === 0) {
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
for (const diretorios of variantesCaminhoSegmentos(segmentos.slice(0, -1))) {
|
|
164
|
+
for (const nomeArquivo of variantesNomeArquivo(segmentos.at(-1))) {
|
|
165
|
+
for (const extensao of extensoes) {
|
|
166
|
+
adicionar(path.join(base, ...diretorios, `${nomeArquivo}${extensao}`));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
for (const caminhoDiretorio of variantesCaminhoSegmentos(segmentos)) {
|
|
171
|
+
for (const extensao of extensoes) {
|
|
172
|
+
adicionar(path.join(base, ...caminhoDiretorio, `index${extensao}`));
|
|
173
|
+
}
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return [...candidatos.values()];
|
|
178
|
+
}
|
|
179
|
+
function candidatosConsumerDeterministicos(contexto, irs, termosEscopo) {
|
|
180
|
+
const segmentos = new Set();
|
|
181
|
+
for (const termo of termosEscopo) {
|
|
182
|
+
segmentos.add(termo);
|
|
183
|
+
segmentos.add(termo.replace(/_/g, "-"));
|
|
184
|
+
}
|
|
185
|
+
for (const ir of irs) {
|
|
186
|
+
for (const rota of ir.routes) {
|
|
187
|
+
for (const segmento of (rota.caminho ?? "").split("/").filter((item) => item && !item.startsWith(":"))) {
|
|
188
|
+
segmentos.add(segmento);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
const candidatos = new Map();
|
|
193
|
+
const extensoes = [".ts", ".tsx", ".js", ".jsx"];
|
|
194
|
+
for (const raiz of contexto.diretoriosCodigo) {
|
|
195
|
+
for (const segmento of segmentos) {
|
|
196
|
+
for (const extensao of extensoes) {
|
|
197
|
+
for (const relativo of [
|
|
198
|
+
["src", "app", segmento, `page${extensao}`],
|
|
199
|
+
["app", segmento, `page${extensao}`],
|
|
200
|
+
["src", "pages", `${segmento}${extensao}`],
|
|
201
|
+
["pages", `${segmento}${extensao}`],
|
|
202
|
+
]) {
|
|
203
|
+
const absoluto = path.resolve(raiz, ...relativo);
|
|
204
|
+
adicionarCandidatoPreservandoForma(candidatos, contexto.baseProjeto, absoluto);
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
return [...candidatos.values()];
|
|
210
|
+
}
|
|
211
|
+
function candidatosRotasDeterministicos(contexto, irs) {
|
|
212
|
+
const candidatos = new Map();
|
|
213
|
+
const extensoes = [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".py"];
|
|
214
|
+
const segmentos = new Set();
|
|
215
|
+
for (const ir of irs) {
|
|
216
|
+
for (const rota of ir.routes) {
|
|
217
|
+
for (const segmento of (rota.caminho ?? "").split("/").filter((item) => item && !item.startsWith(":") && !item.startsWith("{"))) {
|
|
218
|
+
segmentos.add(segmento);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
for (const raiz of contexto.diretoriosCodigo) {
|
|
223
|
+
for (const segmento of segmentos) {
|
|
224
|
+
const nomes = variantesNomeArquivo(segmento);
|
|
225
|
+
for (const nome of nomes) {
|
|
226
|
+
for (const extensao of extensoes) {
|
|
227
|
+
for (const relativo of [
|
|
228
|
+
[segmento, `${nome}.controller${extensao}`],
|
|
229
|
+
[`${nome}.controller${extensao}`],
|
|
230
|
+
["controllers", `${nome}.controller${extensao}`],
|
|
231
|
+
["routes", `${nome}${extensao}`],
|
|
232
|
+
]) {
|
|
233
|
+
adicionarCandidatoPreservandoForma(candidatos, contexto.baseProjeto, path.resolve(raiz, ...relativo));
|
|
234
|
+
}
|
|
235
|
+
}
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
}
|
|
239
|
+
return [...candidatos.values()];
|
|
240
|
+
}
|
|
241
|
+
function candidatosConvencionaisEscopo(contexto, irs) {
|
|
242
|
+
const candidatos = new Map();
|
|
243
|
+
const adicionar = (caminho) => {
|
|
244
|
+
adicionarCandidatoPreservandoForma(candidatos, contexto.baseProjeto, caminho);
|
|
245
|
+
};
|
|
246
|
+
const origens = new Set(irs.flatMap((ir) => implementacoesModulo(ir).map((impl) => impl.origem)));
|
|
247
|
+
const possuiRotas = irs.some((ir) => ir.routes.length > 0);
|
|
248
|
+
const possuiPersistencia = irs.some((ir) => ir.databases.length > 0
|
|
249
|
+
|| ir.tasks.some((task) => task.effects.some((efeito) => /\b(?:db|database|persist|storage)\b/i.test(efeito))));
|
|
250
|
+
const bases = [contexto.baseProjeto, ...contexto.diretoriosCodigo];
|
|
251
|
+
if (possuiRotas && origens.has("rust")) {
|
|
252
|
+
for (const base of bases) {
|
|
253
|
+
adicionar(path.join(base, "main.rs"));
|
|
254
|
+
adicionar(path.join(base, "src", "main.rs"));
|
|
255
|
+
adicionar(path.join(base, "lib.rs"));
|
|
256
|
+
adicionar(path.join(base, "src", "lib.rs"));
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
if (possuiPersistencia) {
|
|
260
|
+
for (const base of bases) {
|
|
261
|
+
adicionar(path.join(base, "schema.sql"));
|
|
262
|
+
adicionar(path.join(base, "schema.prisma"));
|
|
263
|
+
adicionar(path.join(base, "db", "schema.sql"));
|
|
264
|
+
adicionar(path.join(base, "prisma", "schema.prisma"));
|
|
265
|
+
}
|
|
266
|
+
}
|
|
267
|
+
return [...candidatos.values()];
|
|
268
|
+
}
|
|
269
|
+
function escolherDiretoriosLogicos(contexto, arquivos) {
|
|
270
|
+
const candidatos = [...new Map(contexto.diretoriosCodigo
|
|
271
|
+
.map((diretorio) => path.resolve(diretorio))
|
|
272
|
+
.map((diretorio) => [chaveCaminho(diretorio), diretorio])).values()]
|
|
273
|
+
.sort((a, b) => b.length - a.length || a.localeCompare(b, "pt-BR"));
|
|
274
|
+
const escolhidos = new Map();
|
|
275
|
+
for (const arquivo of arquivos) {
|
|
276
|
+
const raiz = candidatos.find((diretorio) => caminhoEstaDentro(diretorio, arquivo))
|
|
277
|
+
?? path.dirname(arquivo);
|
|
278
|
+
escolhidos.set(chaveCaminho(raiz), raiz);
|
|
279
|
+
}
|
|
280
|
+
return [...escolhidos.values()]
|
|
281
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
282
|
+
}
|
|
283
|
+
export async function planejarEscopoDrift(contexto, configuracao) {
|
|
284
|
+
if (configuracao.escopo === "projeto") {
|
|
285
|
+
const diretorios = resolverDiretoriosCodigoEscopoReal(contexto, configuracao);
|
|
286
|
+
return {
|
|
287
|
+
escopo: configuracao.escopo,
|
|
288
|
+
estrategia: "projeto",
|
|
289
|
+
arquivos: [],
|
|
290
|
+
arquivosDeclarados: [],
|
|
291
|
+
arquivosInferidos: [],
|
|
292
|
+
arquivosAusentes: [],
|
|
293
|
+
diretorios,
|
|
294
|
+
modulos: contexto.modulosSelecionados
|
|
295
|
+
.map((modulo) => modulo.resultado.ir?.nome)
|
|
296
|
+
.filter((nome) => Boolean(nome)),
|
|
297
|
+
cobertura: "completa",
|
|
298
|
+
bloqueios: [],
|
|
299
|
+
dependencias: {},
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
const modulosFonte = configuracao.escopo === "arquivo"
|
|
303
|
+
? contexto.modulosSelecionados
|
|
304
|
+
: contexto.modulosCarregados;
|
|
305
|
+
const irs = modulosFonte
|
|
306
|
+
.map((modulo) => modulo.resultado.ir)
|
|
307
|
+
.filter((ir) => Boolean(ir));
|
|
308
|
+
const declarados = new Map();
|
|
309
|
+
const ausentes = new Map();
|
|
310
|
+
const inferidos = new Map();
|
|
311
|
+
const raizReal = await realpath(contexto.baseProjeto);
|
|
312
|
+
const vinculosPlanejados = irs.flatMap((ir) => vinculosModulo(ir))
|
|
313
|
+
.map((vinculo) => vinculo.arquivo ?? (vinculo.tipo === "arquivo" ? vinculo.valor : undefined))
|
|
314
|
+
.filter((valor) => Boolean(valor))
|
|
315
|
+
.map((valor) => ({
|
|
316
|
+
valor,
|
|
317
|
+
absoluto: resolverArquivoWorkspace(contexto.baseProjeto, valor),
|
|
318
|
+
}));
|
|
319
|
+
const implementacoesPlanejadas = irs
|
|
320
|
+
.flatMap((ir) => implementacoesModulo(ir))
|
|
321
|
+
.map((impl) => candidatosArquivoImpl(contexto, impl));
|
|
322
|
+
const candidatosDeterministicos = [
|
|
323
|
+
...candidatosConsumerDeterministicos(contexto, irs, configuracao.termosEscopo),
|
|
324
|
+
...candidatosRotasDeterministicos(contexto, irs),
|
|
325
|
+
...candidatosConvencionaisEscopo(contexto, irs),
|
|
326
|
+
];
|
|
327
|
+
const resultadoSondagens = await sondarArquivosRegularesContidos([
|
|
328
|
+
...vinculosPlanejados.flatMap((vinculo) => vinculo.absoluto ? [vinculo.absoluto] : []),
|
|
329
|
+
...implementacoesPlanejadas.flat(),
|
|
330
|
+
...candidatosDeterministicos,
|
|
331
|
+
], raizReal);
|
|
332
|
+
const arquivoExiste = (arquivo) => resultadoSondagens.get(chaveCaminho(arquivo)) === true;
|
|
333
|
+
for (const vinculo of vinculosPlanejados) {
|
|
334
|
+
if (!vinculo.absoluto) {
|
|
335
|
+
ausentes.set(`fora:${vinculo.valor}`, vinculo.valor);
|
|
336
|
+
continue;
|
|
337
|
+
}
|
|
338
|
+
if (arquivoExiste(vinculo.absoluto)) {
|
|
339
|
+
const chave = chaveCaminho(vinculo.absoluto);
|
|
340
|
+
if (!declarados.has(chave)) {
|
|
341
|
+
declarados.set(chave, vinculo.absoluto);
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
else {
|
|
345
|
+
ausentes.set(chaveCaminho(vinculo.absoluto), vinculo.absoluto);
|
|
346
|
+
}
|
|
347
|
+
}
|
|
348
|
+
for (const candidatos of implementacoesPlanejadas) {
|
|
349
|
+
const encontrados = candidatos.filter(arquivoExiste);
|
|
350
|
+
for (const candidato of encontrados) {
|
|
351
|
+
const chave = chaveCaminho(candidato);
|
|
352
|
+
if (!declarados.has(chave) && !inferidos.has(chave)) {
|
|
353
|
+
inferidos.set(chave, candidato);
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
if (encontrados.length === 0 && candidatos[0]) {
|
|
357
|
+
ausentes.set(chaveCaminho(candidatos[0]), candidatos[0]);
|
|
358
|
+
}
|
|
359
|
+
}
|
|
360
|
+
for (const candidato of candidatosDeterministicos.filter(arquivoExiste)) {
|
|
361
|
+
const chave = chaveCaminho(candidato);
|
|
362
|
+
if (!declarados.has(chave) && !inferidos.has(chave)) {
|
|
363
|
+
inferidos.set(chave, candidato);
|
|
364
|
+
}
|
|
365
|
+
}
|
|
366
|
+
const arquivosMesclados = new Map(declarados);
|
|
367
|
+
for (const [chave, arquivo] of inferidos) {
|
|
368
|
+
if (!arquivosMesclados.has(chave)) {
|
|
369
|
+
arquivosMesclados.set(chave, arquivo);
|
|
370
|
+
}
|
|
371
|
+
}
|
|
372
|
+
const arquivos = [...arquivosMesclados.values()]
|
|
373
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
374
|
+
const arquivosAusentes = [...ausentes.values()]
|
|
375
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
376
|
+
const bloqueios = arquivos.length === 0
|
|
377
|
+
? ["escopo_estreito_sem_vinculos"]
|
|
378
|
+
: [];
|
|
379
|
+
return {
|
|
380
|
+
escopo: configuracao.escopo,
|
|
381
|
+
estrategia: "arquivos_vinculados",
|
|
382
|
+
arquivos,
|
|
383
|
+
arquivosDeclarados: [...declarados.values()].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
384
|
+
arquivosInferidos: [...inferidos.values()].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
385
|
+
arquivosAusentes,
|
|
386
|
+
diretorios: escolherDiretoriosLogicos(contexto, arquivos),
|
|
387
|
+
modulos: irs.map((ir) => ir.nome),
|
|
388
|
+
cobertura: arquivosAusentes.length === 0 && bloqueios.length === 0 ? "completa" : "parcial",
|
|
389
|
+
bloqueios,
|
|
390
|
+
dependencias: {},
|
|
391
|
+
};
|
|
392
|
+
}
|
|
393
|
+
async function construirConfinamentoDependencias(contexto) {
|
|
394
|
+
const raizWorkspaceReal = await realpath(contexto.baseProjeto);
|
|
395
|
+
const logicas = raizesCodigoLogicasDrift(contexto);
|
|
396
|
+
const reaisPossiveis = await mapearComLimite(logicas, CONCORRENCIA_SONDAGENS_DRIFT, async (raiz) => {
|
|
397
|
+
try {
|
|
398
|
+
const raizReal = await realpath(raiz);
|
|
399
|
+
return caminhoEstaDentro(raizWorkspaceReal, raizReal) ? raizReal : undefined;
|
|
400
|
+
}
|
|
401
|
+
catch {
|
|
402
|
+
return undefined;
|
|
403
|
+
}
|
|
404
|
+
});
|
|
405
|
+
const raizesCodigoReais = [...new Map(reaisPossiveis
|
|
406
|
+
.filter((raiz) => Boolean(raiz))
|
|
407
|
+
.map((raiz) => [chaveCaminho(raiz), raiz])).values()];
|
|
408
|
+
return {
|
|
409
|
+
raizWorkspaceReal,
|
|
410
|
+
raizesCodigoLogicas: logicas,
|
|
411
|
+
raizesCodigoReais,
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
async function arquivoRegularConfinadoDependencias(caminho, confinamento) {
|
|
415
|
+
const absoluto = path.resolve(caminho);
|
|
416
|
+
if (!confinamento.raizesCodigoLogicas.some((raiz) => caminhoEstaDentro(raiz, absoluto))) {
|
|
417
|
+
return false;
|
|
418
|
+
}
|
|
419
|
+
try {
|
|
420
|
+
const informacao = await lstat(absoluto);
|
|
421
|
+
if (!informacao.isFile() || informacao.isSymbolicLink()) {
|
|
422
|
+
return false;
|
|
423
|
+
}
|
|
424
|
+
const caminhoReal = await realpath(absoluto);
|
|
425
|
+
return caminhoEstaDentro(confinamento.raizWorkspaceReal, caminhoReal)
|
|
426
|
+
&& confinamento.raizesCodigoReais.some((raiz) => caminhoEstaDentro(raiz, caminhoReal));
|
|
427
|
+
}
|
|
428
|
+
catch {
|
|
429
|
+
return false;
|
|
430
|
+
}
|
|
431
|
+
}
|
|
432
|
+
async function resolverReferenciaLocalExistente(contexto, arquivoOrigem, referencia, confinamento, catalogados) {
|
|
433
|
+
for (const candidatoBruto of candidatosReferenciaLocalDrift(contexto, arquivoOrigem, referencia)) {
|
|
434
|
+
const candidato = catalogados?.get(chaveCaminho(candidatoBruto)) ?? candidatoBruto;
|
|
435
|
+
if (catalogados && !catalogados.has(chaveCaminho(candidatoBruto))) {
|
|
436
|
+
continue;
|
|
437
|
+
}
|
|
438
|
+
if (await arquivoRegularConfinadoDependencias(candidato, confinamento)) {
|
|
439
|
+
return candidato;
|
|
440
|
+
}
|
|
441
|
+
}
|
|
442
|
+
return undefined;
|
|
443
|
+
}
|
|
444
|
+
export async function expandirDependenciasPlanoDrift(contexto, plano, catalogo, cache) {
|
|
445
|
+
if (plano.estrategia !== "arquivos_vinculados" || plano.arquivos.length === 0) {
|
|
446
|
+
return plano;
|
|
447
|
+
}
|
|
448
|
+
const arquivos = new Map(plano.arquivos.map((arquivo) => [chaveCaminho(arquivo), arquivo]));
|
|
449
|
+
const inferidos = new Map(plano.arquivosInferidos.map((arquivo) => [chaveCaminho(arquivo), arquivo]));
|
|
450
|
+
const visitados = new Set();
|
|
451
|
+
const fila = [...plano.arquivos];
|
|
452
|
+
const confinamento = await construirConfinamentoDependencias(contexto);
|
|
453
|
+
const dependencias = new Map(Object.entries(plano.dependencias).map(([arquivo, itens]) => [arquivo, new Set(itens)]));
|
|
454
|
+
while (fila.length > 0) {
|
|
455
|
+
const lote = fila.splice(0)
|
|
456
|
+
.filter((arquivo) => {
|
|
457
|
+
const chave = chaveCaminho(arquivo);
|
|
458
|
+
if (visitados.has(chave)) {
|
|
459
|
+
return false;
|
|
460
|
+
}
|
|
461
|
+
visitados.add(chave);
|
|
462
|
+
return true;
|
|
463
|
+
});
|
|
464
|
+
const resultadosLote = await mapearComLimite(lote, CONCORRENCIA_MAPEAMENTO_DEPENDENCIAS_DRIFT, async (arquivo) => {
|
|
465
|
+
let referencias;
|
|
466
|
+
try {
|
|
467
|
+
if (cache) {
|
|
468
|
+
const estado = await cache.resolverArquivo({
|
|
469
|
+
arquivo,
|
|
470
|
+
analise: "dependencias-v4",
|
|
471
|
+
ler: () => catalogo.ler(arquivo),
|
|
472
|
+
extrair: (conteudo) => extrairReferenciasLocaisDrift(conteudo.texto),
|
|
473
|
+
validar: (valor) => Array.isArray(valor) && valor.every((item) => typeof item === "string"),
|
|
474
|
+
});
|
|
475
|
+
referencias = estado.valor;
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
referencias = extrairReferenciasLocaisDrift(await catalogo.lerTexto(arquivo));
|
|
479
|
+
}
|
|
480
|
+
}
|
|
481
|
+
catch {
|
|
482
|
+
return { arquivo, resolvidas: [] };
|
|
483
|
+
}
|
|
484
|
+
const resolvidas = new Map();
|
|
485
|
+
for (const referencia of referencias) {
|
|
486
|
+
const candidato = await resolverReferenciaLocalExistente(contexto, arquivo, referencia, confinamento);
|
|
487
|
+
if (candidato) {
|
|
488
|
+
resolvidas.set(chaveCaminho(candidato), candidato);
|
|
489
|
+
}
|
|
490
|
+
}
|
|
491
|
+
return { arquivo, resolvidas: [...resolvidas.values()] };
|
|
492
|
+
});
|
|
493
|
+
const novos = new Map();
|
|
494
|
+
for (const { arquivo, resolvidas } of resultadosLote) {
|
|
495
|
+
if (resolvidas.length > 0) {
|
|
496
|
+
const lista = dependencias.get(arquivo) ?? new Set();
|
|
497
|
+
for (const candidato of resolvidas) {
|
|
498
|
+
lista.add(candidato);
|
|
499
|
+
const chave = chaveCaminho(candidato);
|
|
500
|
+
if (!arquivos.has(chave)) {
|
|
501
|
+
novos.set(chave, candidato);
|
|
502
|
+
}
|
|
503
|
+
}
|
|
504
|
+
dependencias.set(arquivo, lista);
|
|
505
|
+
}
|
|
506
|
+
}
|
|
507
|
+
if (novos.size > 0) {
|
|
508
|
+
const novosOrdenados = [...novos.values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
509
|
+
await catalogo.incluir(novosOrdenados);
|
|
510
|
+
for (const candidato of novosOrdenados) {
|
|
511
|
+
const chave = chaveCaminho(candidato);
|
|
512
|
+
arquivos.set(chave, candidato);
|
|
513
|
+
inferidos.set(chave, candidato);
|
|
514
|
+
fila.push(candidato);
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
518
|
+
const arquivosExpandidos = [...arquivos.values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
519
|
+
return {
|
|
520
|
+
...plano,
|
|
521
|
+
arquivos: arquivosExpandidos,
|
|
522
|
+
arquivosInferidos: [...inferidos.values()].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
523
|
+
diretorios: escolherDiretoriosLogicos(contexto, arquivosExpandidos),
|
|
524
|
+
dependencias: Object.fromEntries([...dependencias.entries()]
|
|
525
|
+
.sort(([a], [b]) => a.localeCompare(b, "pt-BR"))
|
|
526
|
+
.map(([arquivo, itens]) => [arquivo, [...itens].sort((a, b) => a.localeCompare(b, "pt-BR"))])),
|
|
527
|
+
};
|
|
528
|
+
}
|
|
529
|
+
export async function mapearDependenciasCatalogadasDrift(contexto, catalogo, cache, arquivos = catalogo.arquivosCatalogados()) {
|
|
530
|
+
const confinamento = await construirConfinamentoDependencias(contexto);
|
|
531
|
+
const catalogados = new Map(catalogo.arquivosCatalogados().map((arquivo) => [chaveCaminho(arquivo), arquivo]));
|
|
532
|
+
const arquivosOrdenados = [...arquivos].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
533
|
+
const resultados = await mapearComLimite(arquivosOrdenados, CONCORRENCIA_MAPEAMENTO_DEPENDENCIAS_DRIFT, async (arquivo) => {
|
|
534
|
+
let referencias;
|
|
535
|
+
try {
|
|
536
|
+
const estado = await cache.resolverArquivo({
|
|
537
|
+
arquivo,
|
|
538
|
+
analise: "dependencias-v4",
|
|
539
|
+
ler: () => catalogo.ler(arquivo),
|
|
540
|
+
extrair: (conteudo) => extrairReferenciasLocaisDrift(conteudo.texto),
|
|
541
|
+
validar: (valor) => Array.isArray(valor) && valor.every((item) => typeof item === "string"),
|
|
542
|
+
});
|
|
543
|
+
referencias = estado.valor;
|
|
544
|
+
}
|
|
545
|
+
catch {
|
|
546
|
+
return undefined;
|
|
547
|
+
}
|
|
548
|
+
const resolvidas = new Map();
|
|
549
|
+
for (const referencia of referencias) {
|
|
550
|
+
const existente = await resolverReferenciaLocalExistente(contexto, arquivo, referencia, confinamento, catalogados);
|
|
551
|
+
if (existente) {
|
|
552
|
+
resolvidas.set(chaveCaminho(existente), existente);
|
|
553
|
+
}
|
|
554
|
+
}
|
|
555
|
+
return [
|
|
556
|
+
arquivo,
|
|
557
|
+
[...resolvidas.values()].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
558
|
+
];
|
|
559
|
+
});
|
|
560
|
+
const dependencias = new Map(resultados.filter((item) => Boolean(item)));
|
|
561
|
+
return Object.fromEntries([...dependencias.entries()].sort(([a], [b]) => a.localeCompare(b, "pt-BR")));
|
|
562
|
+
}
|
|
563
|
+
//# sourceMappingURL=driftEscopo.js.map
|
|
@@ -0,0 +1,4 @@
|
|
|
1
|
+
import type { ContextoProjetoCarregado } from "./projeto.js";
|
|
2
|
+
export declare function extrairReferenciasLocaisDrift(codigo: string): string[];
|
|
3
|
+
export declare function raizesCodigoLogicasDrift(contexto: ContextoProjetoCarregado): string[];
|
|
4
|
+
export declare function candidatosReferenciaLocalDrift(contexto: ContextoProjetoCarregado, arquivoOrigem: string, referencia: string): string[];
|