@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,657 @@
|
|
|
1
|
+
// SEMA-GOVERNED: sema.produto.governanca_ia.drift
|
|
2
|
+
// Descrição: cataloga somente o plano explícito do drift e compartilha leituras e fingerprints de conteúdo.
|
|
3
|
+
import { createHash } from "node:crypto";
|
|
4
|
+
import { lstat, open, readdir, realpath } from "node:fs/promises";
|
|
5
|
+
import path from "node:path";
|
|
6
|
+
export const SCHEMA_SNAPSHOT_CATALOGO_DRIFT = "sema.drift-catalog/v1";
|
|
7
|
+
const CONCORRENCIA_PADRAO = 8;
|
|
8
|
+
const CONCORRENCIA_MAXIMA = 64;
|
|
9
|
+
function emitirEvento(observador, evento) {
|
|
10
|
+
try {
|
|
11
|
+
observador?.(evento);
|
|
12
|
+
}
|
|
13
|
+
catch {
|
|
14
|
+
// Observabilidade nunca altera o resultado funcional do drift.
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
function normalizarConcorrencia(valor) {
|
|
18
|
+
if (!Number.isFinite(valor)) {
|
|
19
|
+
return CONCORRENCIA_PADRAO;
|
|
20
|
+
}
|
|
21
|
+
return Math.max(1, Math.min(CONCORRENCIA_MAXIMA, Math.trunc(valor)));
|
|
22
|
+
}
|
|
23
|
+
function normalizarExtensao(extensao) {
|
|
24
|
+
const limpa = extensao.trim().toLowerCase();
|
|
25
|
+
if (!limpa) {
|
|
26
|
+
return limpa;
|
|
27
|
+
}
|
|
28
|
+
return limpa.startsWith(".") ? limpa : `.${limpa}`;
|
|
29
|
+
}
|
|
30
|
+
function ehFiltroCatalogoDrift(valor) {
|
|
31
|
+
return !Array.isArray(valor);
|
|
32
|
+
}
|
|
33
|
+
function chaveCaminho(caminho) {
|
|
34
|
+
const normalizado = path.normalize(path.resolve(caminho));
|
|
35
|
+
return process.platform === "win32" ? normalizado.toLowerCase() : normalizado;
|
|
36
|
+
}
|
|
37
|
+
function caminhoEstaDentro(raiz, alvo) {
|
|
38
|
+
const relativo = path.relative(raiz, alvo);
|
|
39
|
+
return relativo === "" || (relativo !== ".."
|
|
40
|
+
&& !relativo.startsWith(`..${path.sep}`)
|
|
41
|
+
&& !path.isAbsolute(relativo));
|
|
42
|
+
}
|
|
43
|
+
function erroEhAusencia(erro) {
|
|
44
|
+
return ["ENOENT", "ENOTDIR"].includes(erro.code ?? "");
|
|
45
|
+
}
|
|
46
|
+
function assinaturaDiretorio(info) {
|
|
47
|
+
return {
|
|
48
|
+
mtimeNs: info.mtimeNs.toString(),
|
|
49
|
+
ctimeNs: info.ctimeNs.toString(),
|
|
50
|
+
dev: info.dev.toString(),
|
|
51
|
+
ino: info.ino.toString(),
|
|
52
|
+
};
|
|
53
|
+
}
|
|
54
|
+
function assinaturasDiretorioIguais(a, b) {
|
|
55
|
+
return a.mtimeNs === b.mtimeNs
|
|
56
|
+
&& a.ctimeNs === b.ctimeNs
|
|
57
|
+
&& a.dev === b.dev
|
|
58
|
+
&& a.ino === b.ino;
|
|
59
|
+
}
|
|
60
|
+
function identidadeArquivoEstavel(a, b) {
|
|
61
|
+
return a.isFile()
|
|
62
|
+
&& b.isFile()
|
|
63
|
+
&& !a.isSymbolicLink()
|
|
64
|
+
&& !b.isSymbolicLink()
|
|
65
|
+
&& a.dev === b.dev
|
|
66
|
+
&& a.ino === b.ino
|
|
67
|
+
&& a.size === b.size
|
|
68
|
+
&& a.mtimeNs === b.mtimeNs
|
|
69
|
+
&& a.ctimeNs === b.ctimeNs;
|
|
70
|
+
}
|
|
71
|
+
function registroObjeto(valor) {
|
|
72
|
+
return typeof valor === "object" && valor !== null && !Array.isArray(valor);
|
|
73
|
+
}
|
|
74
|
+
function caminhoRelativoSeguro(valor) {
|
|
75
|
+
return typeof valor === "string"
|
|
76
|
+
&& valor.length > 0
|
|
77
|
+
&& valor !== "."
|
|
78
|
+
&& valor !== ".."
|
|
79
|
+
&& !valor.startsWith("../")
|
|
80
|
+
&& !valor.includes("\\")
|
|
81
|
+
&& !path.posix.isAbsolute(valor);
|
|
82
|
+
}
|
|
83
|
+
function diretorioRelativoSeguro(valor) {
|
|
84
|
+
return valor === "." || caminhoRelativoSeguro(valor);
|
|
85
|
+
}
|
|
86
|
+
function assinaturaDiretorioValida(valor) {
|
|
87
|
+
return registroObjeto(valor)
|
|
88
|
+
&& ["mtimeNs", "ctimeNs", "dev", "ino"]
|
|
89
|
+
.every((campo) => typeof valor[campo] === "string" && /^\d+$/u.test(valor[campo]));
|
|
90
|
+
}
|
|
91
|
+
async function mapearComLimite(itens, limite, executar) {
|
|
92
|
+
if (itens.length === 0) {
|
|
93
|
+
return [];
|
|
94
|
+
}
|
|
95
|
+
const resultados = new Array(itens.length);
|
|
96
|
+
let proximoIndice = 0;
|
|
97
|
+
const trabalhador = async () => {
|
|
98
|
+
for (;;) {
|
|
99
|
+
const indice = proximoIndice;
|
|
100
|
+
proximoIndice += 1;
|
|
101
|
+
if (indice >= itens.length) {
|
|
102
|
+
return;
|
|
103
|
+
}
|
|
104
|
+
resultados[indice] = await executar(itens[indice]);
|
|
105
|
+
}
|
|
106
|
+
};
|
|
107
|
+
await Promise.all(Array.from({ length: Math.min(limite, itens.length) }, () => trabalhador()));
|
|
108
|
+
return resultados;
|
|
109
|
+
}
|
|
110
|
+
class CatalogoDriftImplementacao {
|
|
111
|
+
baseDiretorio;
|
|
112
|
+
raizes;
|
|
113
|
+
registros = new Map();
|
|
114
|
+
conteudos = new Map();
|
|
115
|
+
extensoesPermitidas;
|
|
116
|
+
concorrencia;
|
|
117
|
+
observador;
|
|
118
|
+
baseDiretorioReal;
|
|
119
|
+
extensoesSnapshot;
|
|
120
|
+
diretoriosVisitados = new Map();
|
|
121
|
+
diretoriosIgnoradosSnapshot = [];
|
|
122
|
+
contadores = {
|
|
123
|
+
diretoriosVisitados: 0,
|
|
124
|
+
arquivosCatalogados: 0,
|
|
125
|
+
leiturasConteudo: 0,
|
|
126
|
+
bytesLidos: 0,
|
|
127
|
+
acertosMemoriaConteudo: 0,
|
|
128
|
+
origem: "plano_explicito",
|
|
129
|
+
diretoriosValidadosCache: 0,
|
|
130
|
+
};
|
|
131
|
+
constructor(opcoes) {
|
|
132
|
+
this.baseDiretorio = path.resolve(opcoes.baseDiretorio ?? process.cwd());
|
|
133
|
+
this.baseDiretorioReal = realpath(this.baseDiretorio);
|
|
134
|
+
this.raizes = [...new Map((opcoes.raizes ?? [])
|
|
135
|
+
.map((raiz) => path.resolve(this.baseDiretorio, raiz))
|
|
136
|
+
.map((raiz) => [chaveCaminho(raiz), raiz])).values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
137
|
+
const extensoes = opcoes.extensoes
|
|
138
|
+
?.map(normalizarExtensao)
|
|
139
|
+
.filter(Boolean);
|
|
140
|
+
this.extensoesPermitidas = extensoes?.length
|
|
141
|
+
? new Set(extensoes)
|
|
142
|
+
: undefined;
|
|
143
|
+
this.extensoesSnapshot = this.extensoesPermitidas
|
|
144
|
+
? [...this.extensoesPermitidas].sort((a, b) => a.localeCompare(b, "en"))
|
|
145
|
+
: null;
|
|
146
|
+
this.concorrencia = normalizarConcorrencia(opcoes.concorrencia);
|
|
147
|
+
this.observador = opcoes.observador;
|
|
148
|
+
}
|
|
149
|
+
async construir(arquivosExplicitos, diretoriosIgnorados, snapshot) {
|
|
150
|
+
await this.baseDiretorioReal;
|
|
151
|
+
this.diretoriosIgnoradosSnapshot = [...diretoriosIgnorados]
|
|
152
|
+
.sort((a, b) => a.localeCompare(b, "en"));
|
|
153
|
+
const restaurado = snapshot
|
|
154
|
+
? await this.restaurarSnapshot(snapshot, diretoriosIgnorados, arquivosExplicitos)
|
|
155
|
+
: false;
|
|
156
|
+
if (!restaurado) {
|
|
157
|
+
this.contadores.origem = this.raizes.length > 0 ? "caminhada" : "plano_explicito";
|
|
158
|
+
await this.caminharRaizes(diretoriosIgnorados);
|
|
159
|
+
}
|
|
160
|
+
await this.incluir(arquivosExplicitos);
|
|
161
|
+
}
|
|
162
|
+
async incluir(arquivosExplicitos) {
|
|
163
|
+
const explicitos = [...new Map(arquivosExplicitos
|
|
164
|
+
.map((arquivo) => path.resolve(this.baseDiretorio, arquivo))
|
|
165
|
+
.map((arquivo) => [chaveCaminho(arquivo), arquivo])).values()].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
166
|
+
await mapearComLimite(explicitos, this.concorrencia, async (arquivo) => {
|
|
167
|
+
if (!await this.caminhoPermaneceNoWorkspace(arquivo)) {
|
|
168
|
+
return;
|
|
169
|
+
}
|
|
170
|
+
let informacao;
|
|
171
|
+
try {
|
|
172
|
+
informacao = await lstat(arquivo);
|
|
173
|
+
}
|
|
174
|
+
catch (erro) {
|
|
175
|
+
if (erroEhAusencia(erro)) {
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
throw erro;
|
|
179
|
+
}
|
|
180
|
+
if (!informacao.isFile() || informacao.isSymbolicLink()) {
|
|
181
|
+
return;
|
|
182
|
+
}
|
|
183
|
+
this.adicionarArquivo(arquivo, true);
|
|
184
|
+
});
|
|
185
|
+
}
|
|
186
|
+
listar(extensoesOuFiltro = [], raizes) {
|
|
187
|
+
if (ehFiltroCatalogoDrift(extensoesOuFiltro)) {
|
|
188
|
+
return this.listarEntradas(extensoesOuFiltro).map((arquivo) => arquivo.caminho);
|
|
189
|
+
}
|
|
190
|
+
const extensoes = extensoesOuFiltro.length ? extensoesOuFiltro : undefined;
|
|
191
|
+
if (!raizes?.length) {
|
|
192
|
+
return this.listarEntradas({ extensoes }).map((arquivo) => arquivo.caminho);
|
|
193
|
+
}
|
|
194
|
+
const raizesAbsolutas = raizes.map((raiz) => path.resolve(this.baseDiretorio, raiz));
|
|
195
|
+
return this.listarEntradas({ extensoes })
|
|
196
|
+
.filter((arquivo) => raizesAbsolutas.some((raiz) => caminhoEstaDentro(raiz, arquivo.caminho)))
|
|
197
|
+
.map((arquivo) => arquivo.caminho);
|
|
198
|
+
}
|
|
199
|
+
listarEntradas(filtro = {}) {
|
|
200
|
+
const extensoes = filtro.extensoes
|
|
201
|
+
? new Set(filtro.extensoes.map(normalizarExtensao).filter(Boolean))
|
|
202
|
+
: undefined;
|
|
203
|
+
const raiz = filtro.raiz
|
|
204
|
+
? path.resolve(this.baseDiretorio, filtro.raiz)
|
|
205
|
+
: undefined;
|
|
206
|
+
return [...this.registros.values()]
|
|
207
|
+
.filter((registro) => !extensoes || extensoes.has(registro.extensao))
|
|
208
|
+
.filter((registro) => !raiz || caminhoEstaDentro(raiz, registro.caminho))
|
|
209
|
+
.map((registro) => ({
|
|
210
|
+
caminho: registro.caminho,
|
|
211
|
+
extensao: registro.extensao,
|
|
212
|
+
explicito: registro.explicito,
|
|
213
|
+
raizes: [...registro.raizes].sort((a, b) => a.localeCompare(b, "pt-BR")),
|
|
214
|
+
}))
|
|
215
|
+
.sort((a, b) => a.caminho.localeCompare(b.caminho, "pt-BR"));
|
|
216
|
+
}
|
|
217
|
+
listarPorExtensoes(extensoes, raiz) {
|
|
218
|
+
return raiz ? this.listar(extensoes, [raiz]) : this.listar(extensoes);
|
|
219
|
+
}
|
|
220
|
+
listarPorRaiz(raiz, extensoes) {
|
|
221
|
+
return this.listar(extensoes, [raiz]);
|
|
222
|
+
}
|
|
223
|
+
arquivosCatalogados() {
|
|
224
|
+
return this.listar();
|
|
225
|
+
}
|
|
226
|
+
contem(caminho) {
|
|
227
|
+
return this.registros.has(chaveCaminho(path.resolve(this.baseDiretorio, caminho)));
|
|
228
|
+
}
|
|
229
|
+
ler(caminho) {
|
|
230
|
+
const absoluto = path.resolve(this.baseDiretorio, caminho);
|
|
231
|
+
const chave = chaveCaminho(absoluto);
|
|
232
|
+
const registro = this.registros.get(chave);
|
|
233
|
+
if (!registro) {
|
|
234
|
+
return Promise.reject(new Error(`Arquivo fora do plano explicito do drift: ${absoluto}`));
|
|
235
|
+
}
|
|
236
|
+
const existente = this.conteudos.get(chave);
|
|
237
|
+
if (existente) {
|
|
238
|
+
this.contadores.acertosMemoriaConteudo += 1;
|
|
239
|
+
return existente;
|
|
240
|
+
}
|
|
241
|
+
const leitura = this.lerFisicamente(registro.caminho);
|
|
242
|
+
this.conteudos.set(chave, leitura);
|
|
243
|
+
void leitura.catch(() => {
|
|
244
|
+
if (this.conteudos.get(chave) === leitura) {
|
|
245
|
+
this.conteudos.delete(chave);
|
|
246
|
+
}
|
|
247
|
+
});
|
|
248
|
+
return leitura;
|
|
249
|
+
}
|
|
250
|
+
async lerTexto(caminho) {
|
|
251
|
+
return (await this.ler(caminho)).texto;
|
|
252
|
+
}
|
|
253
|
+
async digest(caminho) {
|
|
254
|
+
return (await this.ler(caminho)).digest;
|
|
255
|
+
}
|
|
256
|
+
async fingerprint(caminhos) {
|
|
257
|
+
const selecionados = caminhos
|
|
258
|
+
? [...new Map(caminhos.map((caminho) => {
|
|
259
|
+
const absoluto = path.resolve(this.baseDiretorio, caminho);
|
|
260
|
+
return [chaveCaminho(absoluto), absoluto];
|
|
261
|
+
})).values()]
|
|
262
|
+
: this.arquivosCatalogados();
|
|
263
|
+
selecionados.sort((a, b) => chaveCaminho(a).localeCompare(chaveCaminho(b), "en"));
|
|
264
|
+
const itens = await mapearComLimite(selecionados, this.concorrencia, async (arquivo) => ({
|
|
265
|
+
caminho: chaveCaminho(arquivo).replace(/\\/g, "/"),
|
|
266
|
+
digest: await this.digest(arquivo),
|
|
267
|
+
}));
|
|
268
|
+
return `sha256:${createHash("sha256").update(JSON.stringify(itens)).digest("hex")}`;
|
|
269
|
+
}
|
|
270
|
+
obterFingerprint(caminhos) {
|
|
271
|
+
return this.fingerprint(caminhos);
|
|
272
|
+
}
|
|
273
|
+
emitir(tipo, arquivo) {
|
|
274
|
+
emitirEvento(this.observador, {
|
|
275
|
+
tipo,
|
|
276
|
+
caminho: arquivo ? path.resolve(this.baseDiretorio, arquivo) : undefined,
|
|
277
|
+
});
|
|
278
|
+
}
|
|
279
|
+
metricas() {
|
|
280
|
+
return { ...this.contadores };
|
|
281
|
+
}
|
|
282
|
+
snapshot() {
|
|
283
|
+
return {
|
|
284
|
+
schema: SCHEMA_SNAPSHOT_CATALOGO_DRIFT,
|
|
285
|
+
raizes: this.raizes.map((raiz) => this.relativoSeguro(raiz, true)),
|
|
286
|
+
extensoes: this.extensoesSnapshot ? [...this.extensoesSnapshot] : null,
|
|
287
|
+
diretoriosIgnorados: [...this.diretoriosIgnoradosSnapshot],
|
|
288
|
+
diretorios: [...this.diretoriosVisitados.entries()]
|
|
289
|
+
.map(([caminho, assinatura]) => ({
|
|
290
|
+
caminho: this.relativoSeguro(caminho, true),
|
|
291
|
+
assinatura: { ...assinatura },
|
|
292
|
+
}))
|
|
293
|
+
.sort((a, b) => a.caminho.localeCompare(b.caminho, "en")),
|
|
294
|
+
arquivos: [...this.registros.values()]
|
|
295
|
+
.map((registro) => ({
|
|
296
|
+
caminho: this.relativoSeguro(registro.caminho),
|
|
297
|
+
explicito: registro.explicito,
|
|
298
|
+
}))
|
|
299
|
+
.sort((a, b) => a.caminho.localeCompare(b.caminho, "en")),
|
|
300
|
+
};
|
|
301
|
+
}
|
|
302
|
+
async caminharRaizes(diretoriosIgnorados) {
|
|
303
|
+
let nivel = [...this.raizes];
|
|
304
|
+
const visitados = new Set();
|
|
305
|
+
while (nivel.length > 0) {
|
|
306
|
+
const nivelUnico = [...new Map(nivel.map((diretorio) => [chaveCaminho(diretorio), diretorio])).values()]
|
|
307
|
+
.filter((diretorio) => {
|
|
308
|
+
const chave = chaveCaminho(diretorio);
|
|
309
|
+
if (visitados.has(chave)) {
|
|
310
|
+
return false;
|
|
311
|
+
}
|
|
312
|
+
visitados.add(chave);
|
|
313
|
+
return true;
|
|
314
|
+
})
|
|
315
|
+
.sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
316
|
+
const proximos = await mapearComLimite(nivelUnico, this.concorrencia, async (diretorio) => this.visitarDiretorio(diretorio, diretoriosIgnorados));
|
|
317
|
+
nivel = proximos.flat();
|
|
318
|
+
}
|
|
319
|
+
}
|
|
320
|
+
async visitarDiretorio(diretorio, diretoriosIgnorados) {
|
|
321
|
+
if (!await this.caminhoPermaneceNoWorkspace(diretorio)) {
|
|
322
|
+
return [];
|
|
323
|
+
}
|
|
324
|
+
let informacao;
|
|
325
|
+
try {
|
|
326
|
+
informacao = await lstat(diretorio, { bigint: true });
|
|
327
|
+
}
|
|
328
|
+
catch (erro) {
|
|
329
|
+
if (erroEhAusencia(erro)) {
|
|
330
|
+
return [];
|
|
331
|
+
}
|
|
332
|
+
throw erro;
|
|
333
|
+
}
|
|
334
|
+
if (informacao.isSymbolicLink()) {
|
|
335
|
+
return [];
|
|
336
|
+
}
|
|
337
|
+
if (informacao.isFile()) {
|
|
338
|
+
this.adicionarArquivo(diretorio, false);
|
|
339
|
+
return [];
|
|
340
|
+
}
|
|
341
|
+
if (!informacao.isDirectory()) {
|
|
342
|
+
return [];
|
|
343
|
+
}
|
|
344
|
+
let entradas;
|
|
345
|
+
try {
|
|
346
|
+
entradas = await readdir(diretorio, { withFileTypes: true });
|
|
347
|
+
}
|
|
348
|
+
catch (erro) {
|
|
349
|
+
if (erroEhAusencia(erro)) {
|
|
350
|
+
return [];
|
|
351
|
+
}
|
|
352
|
+
throw erro;
|
|
353
|
+
}
|
|
354
|
+
const informacaoDepois = await lstat(diretorio, { bigint: true });
|
|
355
|
+
if (!informacaoDepois.isDirectory()
|
|
356
|
+
|| informacaoDepois.isSymbolicLink()
|
|
357
|
+
|| !assinaturasDiretorioIguais(assinaturaDiretorio(informacao), assinaturaDiretorio(informacaoDepois))) {
|
|
358
|
+
throw new Error(`catalogo_diretorio_instavel:${diretorio}`);
|
|
359
|
+
}
|
|
360
|
+
this.contadores.diretoriosVisitados += 1;
|
|
361
|
+
this.diretoriosVisitados.set(path.resolve(diretorio), assinaturaDiretorio(informacaoDepois));
|
|
362
|
+
emitirEvento(this.observador, {
|
|
363
|
+
tipo: "catalog.visit",
|
|
364
|
+
caminho: diretorio,
|
|
365
|
+
categoria: "diretorio",
|
|
366
|
+
});
|
|
367
|
+
const proximos = [];
|
|
368
|
+
for (const entrada of entradas.sort((a, b) => a.name.localeCompare(b.name, "pt-BR"))) {
|
|
369
|
+
if (entrada.isSymbolicLink()) {
|
|
370
|
+
continue;
|
|
371
|
+
}
|
|
372
|
+
const caminhoAtual = path.join(diretorio, entrada.name);
|
|
373
|
+
if (entrada.isDirectory()) {
|
|
374
|
+
if (!diretoriosIgnorados.has(entrada.name.toLowerCase())) {
|
|
375
|
+
proximos.push(caminhoAtual);
|
|
376
|
+
}
|
|
377
|
+
continue;
|
|
378
|
+
}
|
|
379
|
+
if (entrada.isFile()) {
|
|
380
|
+
this.adicionarArquivo(caminhoAtual, false);
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
return proximos;
|
|
384
|
+
}
|
|
385
|
+
adicionarArquivo(caminho, explicito, emitirVisita = true) {
|
|
386
|
+
const absoluto = path.resolve(caminho);
|
|
387
|
+
const extensao = path.extname(absoluto).toLowerCase();
|
|
388
|
+
if (this.extensoesPermitidas && !this.extensoesPermitidas.has(extensao)) {
|
|
389
|
+
return;
|
|
390
|
+
}
|
|
391
|
+
const chave = chaveCaminho(absoluto);
|
|
392
|
+
const existente = this.registros.get(chave);
|
|
393
|
+
const raizes = this.raizes.filter((raiz) => caminhoEstaDentro(raiz, absoluto));
|
|
394
|
+
if (existente) {
|
|
395
|
+
existente.explicito = existente.explicito || explicito;
|
|
396
|
+
for (const raiz of raizes) {
|
|
397
|
+
existente.raizes.add(raiz);
|
|
398
|
+
}
|
|
399
|
+
return;
|
|
400
|
+
}
|
|
401
|
+
this.registros.set(chave, {
|
|
402
|
+
caminho: absoluto,
|
|
403
|
+
extensao,
|
|
404
|
+
explicito,
|
|
405
|
+
raizes: new Set(raizes),
|
|
406
|
+
});
|
|
407
|
+
this.contadores.arquivosCatalogados += 1;
|
|
408
|
+
if (emitirVisita) {
|
|
409
|
+
emitirEvento(this.observador, {
|
|
410
|
+
tipo: "catalog.visit",
|
|
411
|
+
caminho: absoluto,
|
|
412
|
+
categoria: "arquivo",
|
|
413
|
+
});
|
|
414
|
+
}
|
|
415
|
+
}
|
|
416
|
+
async restaurarSnapshot(snapshot, diretoriosIgnorados, arquivosExplicitos) {
|
|
417
|
+
if (!registroObjeto(snapshot)
|
|
418
|
+
|| snapshot.schema !== SCHEMA_SNAPSHOT_CATALOGO_DRIFT
|
|
419
|
+
|| !Array.isArray(snapshot.raizes)
|
|
420
|
+
|| !snapshot.raizes.every(diretorioRelativoSeguro)
|
|
421
|
+
|| !Array.isArray(snapshot.diretoriosIgnorados)
|
|
422
|
+
|| !snapshot.diretoriosIgnorados.every((item) => typeof item === "string")
|
|
423
|
+
|| !(snapshot.extensoes === null
|
|
424
|
+
|| (Array.isArray(snapshot.extensoes) && snapshot.extensoes.every((item) => typeof item === "string")))
|
|
425
|
+
|| !Array.isArray(snapshot.diretorios)
|
|
426
|
+
|| !Array.isArray(snapshot.arquivos)) {
|
|
427
|
+
return false;
|
|
428
|
+
}
|
|
429
|
+
const raizesAtuais = this.raizes.map((raiz) => this.relativoSeguro(raiz, true));
|
|
430
|
+
const ignoradosAtuais = [...diretoriosIgnorados].sort((a, b) => a.localeCompare(b, "en"));
|
|
431
|
+
if (JSON.stringify(snapshot.raizes) !== JSON.stringify(raizesAtuais)
|
|
432
|
+
|| JSON.stringify(snapshot.extensoes) !== JSON.stringify(this.extensoesSnapshot)
|
|
433
|
+
|| JSON.stringify(snapshot.diretoriosIgnorados) !== JSON.stringify(ignoradosAtuais)) {
|
|
434
|
+
return false;
|
|
435
|
+
}
|
|
436
|
+
const diretorios = snapshot.diretorios.map((entrada) => {
|
|
437
|
+
if (!registroObjeto(entrada)
|
|
438
|
+
|| !diretorioRelativoSeguro(entrada.caminho)
|
|
439
|
+
|| !assinaturaDiretorioValida(entrada.assinatura)) {
|
|
440
|
+
return undefined;
|
|
441
|
+
}
|
|
442
|
+
return {
|
|
443
|
+
caminho: path.resolve(this.baseDiretorio, entrada.caminho),
|
|
444
|
+
assinatura: entrada.assinatura,
|
|
445
|
+
};
|
|
446
|
+
});
|
|
447
|
+
if (diretorios.some((entrada) => !entrada)) {
|
|
448
|
+
return false;
|
|
449
|
+
}
|
|
450
|
+
if (diretorios.some((entrada) => entrada
|
|
451
|
+
&& !this.caminhoPertenceRaizCatalogavel(entrada.caminho, diretoriosIgnorados, true))) {
|
|
452
|
+
return false;
|
|
453
|
+
}
|
|
454
|
+
const estadosDiretorios = await mapearComLimite(diretorios, this.concorrencia, async (entrada) => {
|
|
455
|
+
if (!await this.caminhoPermaneceNoWorkspace(entrada.caminho)) {
|
|
456
|
+
return false;
|
|
457
|
+
}
|
|
458
|
+
try {
|
|
459
|
+
const info = await lstat(entrada.caminho, { bigint: true });
|
|
460
|
+
this.contadores.diretoriosValidadosCache += 1;
|
|
461
|
+
return info.isDirectory()
|
|
462
|
+
&& !info.isSymbolicLink()
|
|
463
|
+
&& assinaturasDiretorioIguais(entrada.assinatura, assinaturaDiretorio(info));
|
|
464
|
+
}
|
|
465
|
+
catch {
|
|
466
|
+
return false;
|
|
467
|
+
}
|
|
468
|
+
});
|
|
469
|
+
if (estadosDiretorios.some((valido) => !valido)) {
|
|
470
|
+
this.contadores.diretoriosValidadosCache = 0;
|
|
471
|
+
return false;
|
|
472
|
+
}
|
|
473
|
+
const arquivos = snapshot.arquivos.map((entrada) => {
|
|
474
|
+
if (!registroObjeto(entrada)
|
|
475
|
+
|| !caminhoRelativoSeguro(entrada.caminho)
|
|
476
|
+
|| typeof entrada.explicito !== "boolean") {
|
|
477
|
+
return undefined;
|
|
478
|
+
}
|
|
479
|
+
return {
|
|
480
|
+
caminho: path.resolve(this.baseDiretorio, entrada.caminho),
|
|
481
|
+
explicito: entrada.explicito,
|
|
482
|
+
};
|
|
483
|
+
});
|
|
484
|
+
if (arquivos.some((entrada) => !entrada)) {
|
|
485
|
+
return false;
|
|
486
|
+
}
|
|
487
|
+
const arquivosTipados = arquivos;
|
|
488
|
+
const explicitosPermitidos = new Set(arquivosExplicitos.map((arquivo) => chaveCaminho(path.resolve(this.baseDiretorio, arquivo))));
|
|
489
|
+
if (arquivosTipados.some((entrada) => entrada.explicito
|
|
490
|
+
? !explicitosPermitidos.has(chaveCaminho(entrada.caminho))
|
|
491
|
+
: !this.caminhoPertenceRaizCatalogavel(entrada.caminho, diretoriosIgnorados))) {
|
|
492
|
+
return false;
|
|
493
|
+
}
|
|
494
|
+
const caminhosRepresentados = new Set([
|
|
495
|
+
...diretorios
|
|
496
|
+
.filter((entrada) => Boolean(entrada))
|
|
497
|
+
.map((entrada) => chaveCaminho(entrada.caminho)),
|
|
498
|
+
...arquivosTipados.map((entrada) => chaveCaminho(entrada.caminho)),
|
|
499
|
+
]);
|
|
500
|
+
if (this.raizes.some((raiz) => !caminhosRepresentados.has(chaveCaminho(raiz)))) {
|
|
501
|
+
// Uma raiz ausente nao pode produzir um snapshot eterno: a criacao
|
|
502
|
+
// posterior dessa raiz precisa forcar uma nova caminhada.
|
|
503
|
+
return false;
|
|
504
|
+
}
|
|
505
|
+
const estadosArquivos = await mapearComLimite(arquivosTipados, this.concorrencia, async (entrada) => {
|
|
506
|
+
if (!caminhoEstaDentro(this.baseDiretorio, entrada.caminho)
|
|
507
|
+
|| !await this.caminhoPermaneceNoWorkspace(entrada.caminho)) {
|
|
508
|
+
return false;
|
|
509
|
+
}
|
|
510
|
+
try {
|
|
511
|
+
const info = await lstat(entrada.caminho);
|
|
512
|
+
return info.isFile()
|
|
513
|
+
&& !info.isSymbolicLink()
|
|
514
|
+
&& (!this.extensoesPermitidas
|
|
515
|
+
|| this.extensoesPermitidas.has(path.extname(entrada.caminho).toLowerCase()));
|
|
516
|
+
}
|
|
517
|
+
catch {
|
|
518
|
+
return false;
|
|
519
|
+
}
|
|
520
|
+
});
|
|
521
|
+
if (estadosArquivos.some((valido) => !valido)) {
|
|
522
|
+
return false;
|
|
523
|
+
}
|
|
524
|
+
const diretoriosTipados = diretorios;
|
|
525
|
+
const diretoriosAindaEstaveis = await mapearComLimite(diretoriosTipados, this.concorrencia, async (entrada) => {
|
|
526
|
+
try {
|
|
527
|
+
const info = await lstat(entrada.caminho, { bigint: true });
|
|
528
|
+
return info.isDirectory()
|
|
529
|
+
&& !info.isSymbolicLink()
|
|
530
|
+
&& assinaturasDiretorioIguais(entrada.assinatura, assinaturaDiretorio(info));
|
|
531
|
+
}
|
|
532
|
+
catch {
|
|
533
|
+
return false;
|
|
534
|
+
}
|
|
535
|
+
});
|
|
536
|
+
if (diretoriosAindaEstaveis.some((valido) => !valido)) {
|
|
537
|
+
return false;
|
|
538
|
+
}
|
|
539
|
+
for (const entrada of arquivosTipados) {
|
|
540
|
+
this.adicionarArquivo(entrada.caminho, entrada.explicito, false);
|
|
541
|
+
}
|
|
542
|
+
for (const entrada of diretoriosTipados) {
|
|
543
|
+
this.diretoriosVisitados.set(entrada.caminho, { ...entrada.assinatura });
|
|
544
|
+
}
|
|
545
|
+
this.contadores.origem = "snapshot";
|
|
546
|
+
return true;
|
|
547
|
+
}
|
|
548
|
+
relativoSeguro(caminho, permitirBase = false) {
|
|
549
|
+
const relativo = path.relative(this.baseDiretorio, path.resolve(caminho)).replace(/\\/g, "/");
|
|
550
|
+
if (!(permitirBase ? diretorioRelativoSeguro(relativo || ".") : caminhoRelativoSeguro(relativo))) {
|
|
551
|
+
throw new Error(`caminho_snapshot_catalogo_invalido:${caminho}`);
|
|
552
|
+
}
|
|
553
|
+
return relativo || ".";
|
|
554
|
+
}
|
|
555
|
+
caminhoPertenceRaizCatalogavel(caminho, diretoriosIgnorados, incluirUltimoSegmento = false) {
|
|
556
|
+
return this.raizes.some((raiz) => {
|
|
557
|
+
if (!caminhoEstaDentro(raiz, caminho)) {
|
|
558
|
+
return false;
|
|
559
|
+
}
|
|
560
|
+
const segmentos = path.relative(raiz, caminho)
|
|
561
|
+
.split(path.sep)
|
|
562
|
+
.filter(Boolean);
|
|
563
|
+
if (!incluirUltimoSegmento) {
|
|
564
|
+
segmentos.pop();
|
|
565
|
+
}
|
|
566
|
+
return segmentos.every((segmento) => !diretoriosIgnorados.has(segmento.toLowerCase()));
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
async lerFisicamente(caminho) {
|
|
570
|
+
if (!await this.caminhoPermaneceNoWorkspace(caminho)) {
|
|
571
|
+
throw new Error(`Arquivo catalogado saiu do workspace real: ${caminho}`);
|
|
572
|
+
}
|
|
573
|
+
const informacaoAntes = await lstat(caminho, { bigint: true });
|
|
574
|
+
if (!informacaoAntes.isFile() || informacaoAntes.isSymbolicLink()) {
|
|
575
|
+
throw new Error(`Arquivo catalogado deixou de ser arquivo regular: ${caminho}`);
|
|
576
|
+
}
|
|
577
|
+
const handle = await open(caminho, "r");
|
|
578
|
+
let bytes;
|
|
579
|
+
try {
|
|
580
|
+
const informacaoHandleAntes = await handle.stat({ bigint: true });
|
|
581
|
+
emitirEvento(this.observador, {
|
|
582
|
+
tipo: "content.open",
|
|
583
|
+
caminho,
|
|
584
|
+
categoria: "arquivo",
|
|
585
|
+
});
|
|
586
|
+
const [informacaoCaminhoAberto, caminhoRealAberto] = await Promise.all([
|
|
587
|
+
lstat(caminho, { bigint: true }),
|
|
588
|
+
realpath(caminho),
|
|
589
|
+
]);
|
|
590
|
+
const baseReal = await this.baseDiretorioReal;
|
|
591
|
+
if (!caminhoEstaDentro(baseReal, caminhoRealAberto)
|
|
592
|
+
|| !identidadeArquivoEstavel(informacaoAntes, informacaoHandleAntes)
|
|
593
|
+
|| !identidadeArquivoEstavel(informacaoHandleAntes, informacaoCaminhoAberto)) {
|
|
594
|
+
throw new Error(`Arquivo catalogado mudou durante abertura segura: ${caminho}`);
|
|
595
|
+
}
|
|
596
|
+
bytes = await handle.readFile();
|
|
597
|
+
const [informacaoHandleDepois, informacaoCaminhoDepois, caminhoRealDepois] = await Promise.all([
|
|
598
|
+
handle.stat({ bigint: true }),
|
|
599
|
+
lstat(caminho, { bigint: true }),
|
|
600
|
+
realpath(caminho),
|
|
601
|
+
]);
|
|
602
|
+
if (!caminhoEstaDentro(baseReal, caminhoRealDepois)
|
|
603
|
+
|| !identidadeArquivoEstavel(informacaoHandleAntes, informacaoHandleDepois)
|
|
604
|
+
|| !identidadeArquivoEstavel(informacaoHandleDepois, informacaoCaminhoDepois)) {
|
|
605
|
+
throw new Error(`Arquivo catalogado mudou durante leitura segura: ${caminho}`);
|
|
606
|
+
}
|
|
607
|
+
}
|
|
608
|
+
finally {
|
|
609
|
+
await handle.close().catch(() => undefined);
|
|
610
|
+
}
|
|
611
|
+
const digest = `sha256:${createHash("sha256").update(bytes).digest("hex")}`;
|
|
612
|
+
this.contadores.leiturasConteudo += 1;
|
|
613
|
+
this.contadores.bytesLidos += bytes.byteLength;
|
|
614
|
+
emitirEvento(this.observador, {
|
|
615
|
+
tipo: "content.read",
|
|
616
|
+
caminho,
|
|
617
|
+
categoria: "arquivo",
|
|
618
|
+
bytes: bytes.byteLength,
|
|
619
|
+
digest,
|
|
620
|
+
});
|
|
621
|
+
return {
|
|
622
|
+
caminho,
|
|
623
|
+
bytes,
|
|
624
|
+
texto: bytes.toString("utf8"),
|
|
625
|
+
digest,
|
|
626
|
+
};
|
|
627
|
+
}
|
|
628
|
+
async caminhoPermaneceNoWorkspace(caminho) {
|
|
629
|
+
const absoluto = path.resolve(caminho);
|
|
630
|
+
if (!caminhoEstaDentro(this.baseDiretorio, absoluto)) {
|
|
631
|
+
return false;
|
|
632
|
+
}
|
|
633
|
+
try {
|
|
634
|
+
const [baseReal, caminhoReal] = await Promise.all([
|
|
635
|
+
this.baseDiretorioReal,
|
|
636
|
+
realpath(absoluto),
|
|
637
|
+
]);
|
|
638
|
+
return caminhoEstaDentro(baseReal, caminhoReal);
|
|
639
|
+
}
|
|
640
|
+
catch (erro) {
|
|
641
|
+
if (erroEhAusencia(erro)) {
|
|
642
|
+
return false;
|
|
643
|
+
}
|
|
644
|
+
throw erro;
|
|
645
|
+
}
|
|
646
|
+
}
|
|
647
|
+
}
|
|
648
|
+
export async function criarCatalogoDrift(opcoes) {
|
|
649
|
+
const ignoradosOrigem = opcoes.diretoriosIgnorados ?? [];
|
|
650
|
+
const ignorados = new Set([...ignoradosOrigem]
|
|
651
|
+
.map((diretorio) => diretorio.trim().toLowerCase())
|
|
652
|
+
.filter(Boolean));
|
|
653
|
+
const catalogo = new CatalogoDriftImplementacao(opcoes);
|
|
654
|
+
await catalogo.construir(opcoes.arquivos ?? [], ignorados, opcoes.snapshot);
|
|
655
|
+
return catalogo;
|
|
656
|
+
}
|
|
657
|
+
//# sourceMappingURL=driftCatalogo.js.map
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type PoliticaCacheDrift, type ValorJson } from "./driftCache.js";
|
|
2
|
+
import { type CatalogoDrift, type OpcoesCatalogoDrift } from "./driftCatalogo.js";
|
|
3
|
+
export declare const SCHEMA_CACHE_CATALOGO_DRIFT: "sema.drift-catalog-cache/v1";
|
|
4
|
+
export interface OpcoesCatalogoPersistenteDrift {
|
|
5
|
+
politica: PoliticaCacheDrift;
|
|
6
|
+
identidade: ValorJson;
|
|
7
|
+
}
|
|
8
|
+
export declare function criarCatalogoPersistenteDrift(opcoes: OpcoesCatalogoDrift, opcoesCache: OpcoesCatalogoPersistenteDrift): Promise<CatalogoDrift>;
|