@semacode/cli 1.3.7 → 1.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +61 -41
- package/dist/drift.d.ts +5 -3
- package/dist/drift.js +532 -27
- package/dist/drift.js.map +1 -1
- package/dist/importador.d.ts +2 -0
- package/dist/importador.js +166 -7
- package/dist/importador.js.map +1 -1
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/projeto.d.ts +6 -1
- package/dist/projeto.js.map +1 -1
- package/docs/cli.md +101 -0
- package/docs/instalacao-e-primeiro-uso.md +108 -196
- package/docs/integracao-com-ia.md +43 -200
- package/docs/persistencia-vendor-first.md +145 -0
- package/docs/sintaxe.md +67 -251
- package/exemplos/persistencia_vendor_first.sema +86 -0
- package/node_modules/@sema/gerador-css/package.json +1 -1
- package/node_modules/@sema/gerador-dart/package.json +1 -1
- package/node_modules/@sema/gerador-html/package.json +1 -1
- package/node_modules/@sema/gerador-javascript/package.json +1 -1
- package/node_modules/@sema/gerador-lua/package.json +1 -1
- package/node_modules/@sema/gerador-python/package.json +1 -1
- package/node_modules/@sema/gerador-typescript/package.json +1 -1
- package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +2 -1
- package/node_modules/@sema/nucleo/dist/formatador/index.js +32 -17
- package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/index.d.ts +1 -0
- package/node_modules/@sema/nucleo/dist/index.js +1 -0
- package/node_modules/@sema/nucleo/dist/index.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.js +94 -0
- package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +60 -0
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js +15 -0
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.js +98 -3
- package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/persistencia/contratos.d.ts +39 -0
- package/node_modules/@sema/nucleo/dist/persistencia/contratos.js +294 -0
- package/node_modules/@sema/nucleo/dist/persistencia/contratos.js.map +1 -0
- package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +1 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js +118 -2
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
- package/node_modules/@sema/nucleo/package.json +1 -1
- package/node_modules/@sema/padroes/package.json +1 -1
- package/package.json +11 -11
package/dist/drift.js
CHANGED
|
@@ -28,6 +28,340 @@ const DIRETORIOS_IGNORADOS = new Set([
|
|
|
28
28
|
function normalizarFragmentoArquivo(valor) {
|
|
29
29
|
return valor.replace(/\\/g, "/").replace(/^\.?\//, "").trim().toLowerCase();
|
|
30
30
|
}
|
|
31
|
+
const NOMES_RECURSO_IGNORADOS = new Set([
|
|
32
|
+
"all",
|
|
33
|
+
"and",
|
|
34
|
+
"as",
|
|
35
|
+
"by",
|
|
36
|
+
"create",
|
|
37
|
+
"delete",
|
|
38
|
+
"from",
|
|
39
|
+
"group",
|
|
40
|
+
"inner",
|
|
41
|
+
"into",
|
|
42
|
+
"join",
|
|
43
|
+
"left",
|
|
44
|
+
"limit",
|
|
45
|
+
"offset",
|
|
46
|
+
"on",
|
|
47
|
+
"or",
|
|
48
|
+
"order",
|
|
49
|
+
"outer",
|
|
50
|
+
"returning",
|
|
51
|
+
"right",
|
|
52
|
+
"select",
|
|
53
|
+
"set",
|
|
54
|
+
"table",
|
|
55
|
+
"update",
|
|
56
|
+
"values",
|
|
57
|
+
"view",
|
|
58
|
+
"where",
|
|
59
|
+
]);
|
|
60
|
+
const OPERACOES_REDIS_KEYSPACE = [
|
|
61
|
+
"append",
|
|
62
|
+
"decr",
|
|
63
|
+
"del",
|
|
64
|
+
"expire",
|
|
65
|
+
"expireat",
|
|
66
|
+
"get",
|
|
67
|
+
"getdel",
|
|
68
|
+
"getex",
|
|
69
|
+
"getrange",
|
|
70
|
+
"hdel",
|
|
71
|
+
"hexists",
|
|
72
|
+
"hget",
|
|
73
|
+
"hgetall",
|
|
74
|
+
"hincrby",
|
|
75
|
+
"hkeys",
|
|
76
|
+
"hlen",
|
|
77
|
+
"hmget",
|
|
78
|
+
"hmset",
|
|
79
|
+
"hrandfield",
|
|
80
|
+
"hscan",
|
|
81
|
+
"hset",
|
|
82
|
+
"hsetnx",
|
|
83
|
+
"hvals",
|
|
84
|
+
"incr",
|
|
85
|
+
"incrby",
|
|
86
|
+
"lindex",
|
|
87
|
+
"llen",
|
|
88
|
+
"lpop",
|
|
89
|
+
"lpush",
|
|
90
|
+
"lrange",
|
|
91
|
+
"lrem",
|
|
92
|
+
"lset",
|
|
93
|
+
"rpop",
|
|
94
|
+
"rpush",
|
|
95
|
+
"sadd",
|
|
96
|
+
"scard",
|
|
97
|
+
"set",
|
|
98
|
+
"setex",
|
|
99
|
+
"setnx",
|
|
100
|
+
"smembers",
|
|
101
|
+
"spop",
|
|
102
|
+
"srem",
|
|
103
|
+
"ttl",
|
|
104
|
+
"type",
|
|
105
|
+
"zadd",
|
|
106
|
+
"zcard",
|
|
107
|
+
"zrange",
|
|
108
|
+
"zrem",
|
|
109
|
+
];
|
|
110
|
+
const OPERACOES_REDIS_STREAM = [
|
|
111
|
+
"xadd",
|
|
112
|
+
"xdel",
|
|
113
|
+
"xgroupcreate",
|
|
114
|
+
"xgroupdestroy",
|
|
115
|
+
"xlen",
|
|
116
|
+
"xrange",
|
|
117
|
+
"xread",
|
|
118
|
+
"xreadgroup",
|
|
119
|
+
"xrevrange",
|
|
120
|
+
"xtrim",
|
|
121
|
+
];
|
|
122
|
+
function limparLiteralRecurso(valor) {
|
|
123
|
+
return valor
|
|
124
|
+
.trim()
|
|
125
|
+
.replace(/^["'`]+|["'`]+$/g, "")
|
|
126
|
+
.replace(/\$\{[^}]+\}/g, "")
|
|
127
|
+
.replace(/\{[^}]+\}/g, "")
|
|
128
|
+
.replace(/%[sdifjo]/gi, "")
|
|
129
|
+
.trim();
|
|
130
|
+
}
|
|
131
|
+
function fecharPrefixoRecurso(valor) {
|
|
132
|
+
return valor.replace(/[:/_\-.]+$/g, "").trim();
|
|
133
|
+
}
|
|
134
|
+
function normalizarNomeRecursoDrift(valor) {
|
|
135
|
+
return fecharPrefixoRecurso(limparLiteralRecurso(valor))
|
|
136
|
+
.normalize("NFD")
|
|
137
|
+
.replace(/[\u0300-\u036f]/g, "")
|
|
138
|
+
.toLowerCase()
|
|
139
|
+
.replace(/["'`]/g, "")
|
|
140
|
+
.replace(/\s+/g, "");
|
|
141
|
+
}
|
|
142
|
+
function variantesNomeRecursoDrift(valor) {
|
|
143
|
+
const base = fecharPrefixoRecurso(limparLiteralRecurso(valor));
|
|
144
|
+
if (!base) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
147
|
+
const variantes = new Set();
|
|
148
|
+
const registrar = (candidato) => {
|
|
149
|
+
if (!candidato) {
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
const normalizado = normalizarNomeRecursoDrift(candidato);
|
|
153
|
+
if (normalizado) {
|
|
154
|
+
variantes.add(normalizado);
|
|
155
|
+
}
|
|
156
|
+
};
|
|
157
|
+
registrar(base);
|
|
158
|
+
registrar(base.replace(/[.:/_-]+/g, "_"));
|
|
159
|
+
registrar(base.replace(/[.:/_-]+/g, ""));
|
|
160
|
+
const partes = base.split(/[.:/_-]+/).filter(Boolean);
|
|
161
|
+
if (partes.length > 1) {
|
|
162
|
+
registrar(partes.join("_"));
|
|
163
|
+
registrar(partes.join(""));
|
|
164
|
+
}
|
|
165
|
+
const singular = base.replace(/s$/i, "");
|
|
166
|
+
if (singular && singular !== base) {
|
|
167
|
+
registrar(singular);
|
|
168
|
+
}
|
|
169
|
+
else if (!/s$/i.test(base)) {
|
|
170
|
+
registrar(`${base}s`);
|
|
171
|
+
}
|
|
172
|
+
return [...variantes];
|
|
173
|
+
}
|
|
174
|
+
function recursoEhIgnorado(nome) {
|
|
175
|
+
const normalizado = normalizarNomeRecursoDrift(nome);
|
|
176
|
+
if (!normalizado || normalizado.length < 2) {
|
|
177
|
+
return true;
|
|
178
|
+
}
|
|
179
|
+
return NOMES_RECURSO_IGNORADOS.has(normalizado);
|
|
180
|
+
}
|
|
181
|
+
function registrarRecursoDrift(recursos, origem, tipo, nome, arquivo, simbolo) {
|
|
182
|
+
const nomeLimpo = fecharPrefixoRecurso(limparLiteralRecurso(nome));
|
|
183
|
+
if (!nomeLimpo || recursoEhIgnorado(nomeLimpo)) {
|
|
184
|
+
return;
|
|
185
|
+
}
|
|
186
|
+
const chave = `${origem}:${tipo}:${normalizarNomeRecursoDrift(nomeLimpo)}:${arquivo}:${simbolo ?? ""}`;
|
|
187
|
+
if (!recursos.has(chave)) {
|
|
188
|
+
recursos.set(chave, {
|
|
189
|
+
origem,
|
|
190
|
+
nome: nomeLimpo,
|
|
191
|
+
arquivo,
|
|
192
|
+
simbolo,
|
|
193
|
+
tipo,
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
function inferirMotoresRelacionais(codigo, arquivo) {
|
|
198
|
+
const motores = new Set();
|
|
199
|
+
const caminho = normalizarFragmentoArquivo(arquivo);
|
|
200
|
+
if (/\b(?:from|require)\s*\(?["'`]pg["'`]/i.test(codigo)
|
|
201
|
+
|| /\bpostgres(?:ql)?\b/i.test(codigo)
|
|
202
|
+
|| /\bon\s+conflict\b/i.test(codigo)
|
|
203
|
+
|| /\breturning\b/i.test(codigo)
|
|
204
|
+
|| /\bjsonb\b/i.test(codigo)
|
|
205
|
+
|| /\bilike\b/i.test(codigo)
|
|
206
|
+
|| /(?:^|\/)(?:postgres|pgsql)(?:\/|[-_.])/i.test(caminho)) {
|
|
207
|
+
motores.add("postgres");
|
|
208
|
+
}
|
|
209
|
+
if (/\b(?:from|require)\s*\(?["'`](?:mysql2?(?:\/promise)?|mysql)["'`]/i.test(codigo)
|
|
210
|
+
|| /\bon\s+duplicate\s+key\b/i.test(codigo)
|
|
211
|
+
|| /\bauto_increment\b/i.test(codigo)
|
|
212
|
+
|| /\binnodb\b/i.test(codigo)
|
|
213
|
+
|| /\bunsigned\b/i.test(codigo)
|
|
214
|
+
|| /(?:^|\/)mysql(?:\/|[-_.])/i.test(caminho)) {
|
|
215
|
+
motores.add("mysql");
|
|
216
|
+
}
|
|
217
|
+
if (/\b(?:from|require)\s*\(?["'`](?:sqlite3|better-sqlite3|bun:sqlite|sqlite)["'`]/i.test(codigo)
|
|
218
|
+
|| /\bpragma\b/i.test(codigo)
|
|
219
|
+
|| /\bwithout\s+rowid\b/i.test(codigo)
|
|
220
|
+
|| /\bsqlite\b/i.test(codigo)
|
|
221
|
+
|| /(?:^|\/)sqlite(?:\/|[-_.])/i.test(caminho)) {
|
|
222
|
+
motores.add("sqlite");
|
|
223
|
+
}
|
|
224
|
+
const temSqlGenerico = /\b(?:select\b[\s\S]*?\bfrom\b|insert\s+into|update\s+[A-Za-z_][\w$.-]*\s+set|delete\s+from|create\s+(?:table|view)|alter\s+table|drop\s+(?:table|view)|join\s+[A-Za-z_][\w$.-]*)/i.test(codigo)
|
|
225
|
+
|| /\.(?:from|into|table)\s*\(\s*["'`]/i.test(codigo)
|
|
226
|
+
|| /\b(?:knex|db|trx)\s*\(\s*["'`][A-Za-z_][^"'`]+["'`]\s*\)/i.test(codigo)
|
|
227
|
+
|| /\bprisma\.[A-Za-z_]\w*\.(?:find\w+|create|update|delete|upsert|aggregate|count)\b/i.test(codigo);
|
|
228
|
+
if (temSqlGenerico && motores.size === 0) {
|
|
229
|
+
motores.add("postgres");
|
|
230
|
+
motores.add("mysql");
|
|
231
|
+
motores.add("sqlite");
|
|
232
|
+
}
|
|
233
|
+
return [...motores];
|
|
234
|
+
}
|
|
235
|
+
function extrairRecursosSql(arquivo, codigo) {
|
|
236
|
+
const recursos = new Map();
|
|
237
|
+
const motores = inferirMotoresRelacionais(codigo, arquivo);
|
|
238
|
+
if (motores.length === 0) {
|
|
239
|
+
return [];
|
|
240
|
+
}
|
|
241
|
+
const registrarParaMotores = (tipo, nome) => {
|
|
242
|
+
for (const motor of motores) {
|
|
243
|
+
registrarRecursoDrift(recursos, motor, tipo, nome, arquivo);
|
|
244
|
+
}
|
|
245
|
+
};
|
|
246
|
+
const registrarTextoSql = (texto) => {
|
|
247
|
+
if (!/\b(?:select\b[\s\S]*?\bfrom\b|insert\s+into|update\s+[A-Za-z_][\w$.-]*\s+set|delete\s+from|create\s+(?:table|view)|alter\s+table|drop\s+(?:table|view)|join\s+[A-Za-z_][\w$.-]*|create\s+(?:unique\s+)?index)\b/i.test(texto)) {
|
|
248
|
+
return;
|
|
249
|
+
}
|
|
250
|
+
for (const match of texto.matchAll(/\bcreate\s+(?:or\s+replace\s+)?(table|view)\s+(?:if\s+not\s+exists\s+)?["'`]?([A-Za-z_][\w$.-]*)["'`]?/gi)) {
|
|
251
|
+
registrarParaMotores(match[1].toLowerCase(), match[2]);
|
|
252
|
+
}
|
|
253
|
+
for (const match of texto.matchAll(/\bcreate\s+(?:unique\s+)?index\s+(?:if\s+not\s+exists\s+)?["'`]?([A-Za-z_][\w$.-]*)["'`]?/gi)) {
|
|
254
|
+
registrarParaMotores("index", match[1]);
|
|
255
|
+
}
|
|
256
|
+
for (const match of texto.matchAll(/\b(?:insert\s+into|update|from|join|delete\s+from|truncate\s+table)\s+["'`]?([A-Za-z_][\w$.-]*)["'`]?/gi)) {
|
|
257
|
+
registrarParaMotores("table", match[1]);
|
|
258
|
+
}
|
|
259
|
+
};
|
|
260
|
+
if (/\.(?:sql|psql|ddl)$/i.test(arquivo)) {
|
|
261
|
+
registrarTextoSql(codigo);
|
|
262
|
+
}
|
|
263
|
+
else {
|
|
264
|
+
for (const literal of codigo.matchAll(/(["'`])([\s\S]*?)\1/g)) {
|
|
265
|
+
registrarTextoSql(literal[2] ?? "");
|
|
266
|
+
}
|
|
267
|
+
}
|
|
268
|
+
for (const match of codigo.matchAll(/\.(?:from|into|table)\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi)) {
|
|
269
|
+
registrarParaMotores("table", match[1]);
|
|
270
|
+
}
|
|
271
|
+
for (const match of codigo.matchAll(/\b(?:knex|db|trx)\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi)) {
|
|
272
|
+
registrarParaMotores("table", match[1]);
|
|
273
|
+
}
|
|
274
|
+
for (const match of codigo.matchAll(/\bprisma\.([A-Za-z_]\w*)\.(?:find\w+|create|update|delete|upsert|aggregate|count)\b/gi)) {
|
|
275
|
+
registrarParaMotores("table", match[1]);
|
|
276
|
+
}
|
|
277
|
+
return [...recursos.values()];
|
|
278
|
+
}
|
|
279
|
+
function extrairRecursosMongoDb(arquivo, codigo) {
|
|
280
|
+
const recursos = new Map();
|
|
281
|
+
const contextoMongo = /\b(?:mongodb|mongoose|mongoclient|objectid)\b/i.test(codigo)
|
|
282
|
+
|| /\bdb\.collection\s*\(/i.test(codigo)
|
|
283
|
+
|| /(?:^|\/)mongo(?:db)?(?:\/|[-_.])/i.test(normalizarFragmentoArquivo(arquivo));
|
|
284
|
+
if (!contextoMongo) {
|
|
285
|
+
return [];
|
|
286
|
+
}
|
|
287
|
+
for (const match of codigo.matchAll(/\b(?:db\.)?collection\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi)) {
|
|
288
|
+
registrarRecursoDrift(recursos, "mongodb", "collection", match[1], arquivo);
|
|
289
|
+
}
|
|
290
|
+
for (const match of codigo.matchAll(/\bgetCollection\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/gi)) {
|
|
291
|
+
registrarRecursoDrift(recursos, "mongodb", "collection", match[1], arquivo);
|
|
292
|
+
}
|
|
293
|
+
for (const match of codigo.matchAll(/\bmongoose\.model\s*\(\s*["'`]([^"'`]+)["'`](?:\s*,[\s\S]*?,\s*["'`]([^"'`]+)["'`])?/gi)) {
|
|
294
|
+
registrarRecursoDrift(recursos, "mongodb", "document", match[1], arquivo);
|
|
295
|
+
if (match[2]) {
|
|
296
|
+
registrarRecursoDrift(recursos, "mongodb", "collection", match[2], arquivo);
|
|
297
|
+
}
|
|
298
|
+
}
|
|
299
|
+
for (const match of codigo.matchAll(/\bdb\.([A-Za-z_]\w*)\.(?:find|findOne|aggregate|insertOne|insertMany|updateOne|updateMany|deleteOne|deleteMany|countDocuments)\b/gi)) {
|
|
300
|
+
registrarRecursoDrift(recursos, "mongodb", "collection", match[1], arquivo);
|
|
301
|
+
}
|
|
302
|
+
return [...recursos.values()];
|
|
303
|
+
}
|
|
304
|
+
function extrairRecursosRedis(arquivo, codigo) {
|
|
305
|
+
const recursos = new Map();
|
|
306
|
+
const contextoRedis = /\b(?:from|require)\s*\(?["'`](?:redis|ioredis)["'`]/i.test(codigo)
|
|
307
|
+
|| /\bcreateClient\s*\(/i.test(codigo)
|
|
308
|
+
|| /\bx(?:add|read|readgroup|groupcreate|groupdestroy)\s*\(/i.test(codigo)
|
|
309
|
+
|| /(?:^|\/)redis(?:\/|[-_.])/i.test(normalizarFragmentoArquivo(arquivo));
|
|
310
|
+
if (!contextoRedis) {
|
|
311
|
+
return [];
|
|
312
|
+
}
|
|
313
|
+
const operacoesKeyspace = OPERACOES_REDIS_KEYSPACE.join("|");
|
|
314
|
+
const operacoesStream = OPERACOES_REDIS_STREAM.join("|");
|
|
315
|
+
const padraoKeyspace = new RegExp(`\\b(?:${operacoesKeyspace})\\s*\\(\\s*['"\\\`]([^'"\\\`]+)['"\\\`]`, "gi");
|
|
316
|
+
const padraoStream = new RegExp(`\\b(?:${operacoesStream})\\s*\\(\\s*['"\\\`]([^'"\\\`]+)['"\\\`]`, "gi");
|
|
317
|
+
for (const match of codigo.matchAll(padraoKeyspace)) {
|
|
318
|
+
registrarRecursoDrift(recursos, "redis", "keyspace", match[1], arquivo);
|
|
319
|
+
}
|
|
320
|
+
for (const match of codigo.matchAll(padraoStream)) {
|
|
321
|
+
registrarRecursoDrift(recursos, "redis", "stream", match[1], arquivo);
|
|
322
|
+
}
|
|
323
|
+
return [...recursos.values()];
|
|
324
|
+
}
|
|
325
|
+
function extrairRecursosPersistenciaCodigoVivo(arquivo, codigo) {
|
|
326
|
+
const recursos = new Map();
|
|
327
|
+
for (const recurso of extrairColecoesFirebase(arquivo, codigo)) {
|
|
328
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
329
|
+
}
|
|
330
|
+
for (const recurso of extrairRecursosSql(arquivo, codigo)) {
|
|
331
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
332
|
+
}
|
|
333
|
+
for (const recurso of extrairRecursosMongoDb(arquivo, codigo)) {
|
|
334
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
335
|
+
}
|
|
336
|
+
for (const recurso of extrairRecursosRedis(arquivo, codigo)) {
|
|
337
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
338
|
+
}
|
|
339
|
+
return [...recursos.values()];
|
|
340
|
+
}
|
|
341
|
+
function extrairRecursosPrisma(arquivo, codigo) {
|
|
342
|
+
const recursos = new Map();
|
|
343
|
+
const provider = codigo.match(/\bprovider\s*=\s*["'`](postgresql|mysql|sqlite)["'`]/i)?.[1]?.toLowerCase();
|
|
344
|
+
const origem = provider === "postgresql"
|
|
345
|
+
? "postgres"
|
|
346
|
+
: provider === "mysql"
|
|
347
|
+
? "mysql"
|
|
348
|
+
: provider === "sqlite"
|
|
349
|
+
? "sqlite"
|
|
350
|
+
: undefined;
|
|
351
|
+
if (!origem) {
|
|
352
|
+
return [];
|
|
353
|
+
}
|
|
354
|
+
for (const match of codigo.matchAll(/\bmodel\s+([A-Za-z_]\w*)\s*\{([\s\S]*?)\n\}/g)) {
|
|
355
|
+
const nomeModelo = match[1];
|
|
356
|
+
const corpo = match[2] ?? "";
|
|
357
|
+
const tabelaMapeada = corpo.match(/@@map\s*\(\s*["'`]([^"'`]+)["'`]\s*\)/)?.[1];
|
|
358
|
+
registrarRecursoDrift(recursos, origem, "table", tabelaMapeada ?? nomeModelo, arquivo);
|
|
359
|
+
if (tabelaMapeada) {
|
|
360
|
+
registrarRecursoDrift(recursos, origem, "table", nomeModelo, arquivo);
|
|
361
|
+
}
|
|
362
|
+
}
|
|
363
|
+
return [...recursos.values()];
|
|
364
|
+
}
|
|
31
365
|
function escolherArquivoPorVinculo(arquivos, valor) {
|
|
32
366
|
const normalizado = normalizarFragmentoArquivo(valor);
|
|
33
367
|
const exato = arquivos.find((arquivo) => normalizarFragmentoArquivo(arquivo) === normalizado);
|
|
@@ -701,8 +1035,8 @@ async function indexarTypeScript(diretorios) {
|
|
|
701
1035
|
const sourceFile = ts.createSourceFile(arquivo, codigo, ts.ScriptTarget.Latest, true, scriptKind);
|
|
702
1036
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
703
1037
|
const relacao = path.relative(diretorio, arquivo);
|
|
704
|
-
for (const recurso of
|
|
705
|
-
recursos.
|
|
1038
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1039
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
706
1040
|
}
|
|
707
1041
|
for (const rota of extrairRotasTypeScriptHttp(sourceFile, relacao)) {
|
|
708
1042
|
rotas.push({
|
|
@@ -889,6 +1223,7 @@ function registrarRotasPython(rotas, decoratorsPendentes, prefixo, arquivo, nome
|
|
|
889
1223
|
async function indexarPython(diretorios) {
|
|
890
1224
|
const simbolos = new Map();
|
|
891
1225
|
const rotas = [];
|
|
1226
|
+
const recursos = new Map();
|
|
892
1227
|
for (const diretorio of diretorios) {
|
|
893
1228
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".py"]))
|
|
894
1229
|
.filter((arquivo) => !arquivo.endsWith("__init__.py") && !/tests?[\\/]/i.test(arquivo));
|
|
@@ -896,6 +1231,9 @@ async function indexarPython(diretorios) {
|
|
|
896
1231
|
const texto = await readFile(arquivo, "utf8");
|
|
897
1232
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
898
1233
|
const prefixo = texto.match(/APIRouter\s*\(\s*prefix\s*=\s*["']([^"']+)["']/)?.[1];
|
|
1234
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, texto)) {
|
|
1235
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1236
|
+
}
|
|
899
1237
|
for (const rota of extrairRotasFlaskDecoradas(texto)) {
|
|
900
1238
|
rotas.push({
|
|
901
1239
|
origem: "flask",
|
|
@@ -947,11 +1285,12 @@ async function indexarPython(diretorios) {
|
|
|
947
1285
|
}
|
|
948
1286
|
}
|
|
949
1287
|
}
|
|
950
|
-
return { simbolos: [...simbolos.values()], rotas };
|
|
1288
|
+
return { simbolos: [...simbolos.values()], rotas, recursos: [...recursos.values()] };
|
|
951
1289
|
}
|
|
952
1290
|
async function indexarDart(diretorios) {
|
|
953
1291
|
const simbolos = new Map();
|
|
954
1292
|
const rotas = [];
|
|
1293
|
+
const recursos = new Map();
|
|
955
1294
|
const consumerSurfaces = new Map();
|
|
956
1295
|
for (const diretorio of diretorios) {
|
|
957
1296
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".dart"]))
|
|
@@ -960,6 +1299,9 @@ async function indexarDart(diretorios) {
|
|
|
960
1299
|
const texto = await readFile(arquivo, "utf8");
|
|
961
1300
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
962
1301
|
const relacao = path.relative(diretorio, arquivo);
|
|
1302
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, texto)) {
|
|
1303
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1304
|
+
}
|
|
963
1305
|
for (const match of texto.matchAll(/(?:Future<[^\n]+>|[\w?<>.,\s]+)\s+(\w+)\(([^)]*)\)\s*(?:async\s*)?\{/g)) {
|
|
964
1306
|
const nome = match[1];
|
|
965
1307
|
if (["build", "toString"].includes(nome)) {
|
|
@@ -1006,6 +1348,7 @@ async function indexarDart(diretorios) {
|
|
|
1006
1348
|
return {
|
|
1007
1349
|
simbolos: [...simbolos.values()],
|
|
1008
1350
|
rotas,
|
|
1351
|
+
recursos: [...recursos.values()],
|
|
1009
1352
|
consumerSurfaces: [...consumerSurfaces.values()].sort((a, b) => a.rota.localeCompare(b.rota, "pt-BR")
|
|
1010
1353
|
|| a.tipoArquivo.localeCompare(b.tipoArquivo, "pt-BR")
|
|
1011
1354
|
|| a.arquivo.localeCompare(b.arquivo, "pt-BR")),
|
|
@@ -1037,12 +1380,16 @@ function registrarSimboloGenerico(simbolos, origem, basesSimbolicas, arquivo, si
|
|
|
1037
1380
|
async function indexarDotnet(diretorios) {
|
|
1038
1381
|
const simbolos = new Map();
|
|
1039
1382
|
const rotas = [];
|
|
1383
|
+
const recursos = new Map();
|
|
1040
1384
|
for (const diretorio of diretorios) {
|
|
1041
1385
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".cs"]))
|
|
1042
1386
|
.filter((arquivo) => !/(^|[\\/])(bin|obj|Test[s]?)([\\/]|$)/i.test(arquivo));
|
|
1043
1387
|
for (const arquivo of arquivos) {
|
|
1044
1388
|
const codigo = await readFile(arquivo, "utf8");
|
|
1045
1389
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
1390
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1391
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1392
|
+
}
|
|
1046
1393
|
for (const simbolo of extrairSimbolosDotnet(codigo)) {
|
|
1047
1394
|
registrarSimboloGenerico(simbolos, "cs", basesSimbolicas, arquivo, simbolo.simbolo);
|
|
1048
1395
|
}
|
|
@@ -1057,17 +1404,21 @@ async function indexarDotnet(diretorios) {
|
|
|
1057
1404
|
}
|
|
1058
1405
|
}
|
|
1059
1406
|
}
|
|
1060
|
-
return { simbolos: [...simbolos.values()], rotas };
|
|
1407
|
+
return { simbolos: [...simbolos.values()], rotas, recursos: [...recursos.values()] };
|
|
1061
1408
|
}
|
|
1062
1409
|
async function indexarJava(diretorios) {
|
|
1063
1410
|
const simbolos = new Map();
|
|
1064
1411
|
const rotas = [];
|
|
1412
|
+
const recursos = new Map();
|
|
1065
1413
|
for (const diretorio of diretorios) {
|
|
1066
1414
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".java"]))
|
|
1067
1415
|
.filter((arquivo) => !/(^|[\\/])(target|build|out|Test[s]?)([\\/]|$)/i.test(arquivo));
|
|
1068
1416
|
for (const arquivo of arquivos) {
|
|
1069
1417
|
const codigo = await readFile(arquivo, "utf8");
|
|
1070
1418
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
1419
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1420
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1421
|
+
}
|
|
1071
1422
|
for (const simbolo of extrairSimbolosJava(codigo)) {
|
|
1072
1423
|
registrarSimboloGenerico(simbolos, "java", basesSimbolicas, arquivo, simbolo.simbolo);
|
|
1073
1424
|
}
|
|
@@ -1082,16 +1433,20 @@ async function indexarJava(diretorios) {
|
|
|
1082
1433
|
}
|
|
1083
1434
|
}
|
|
1084
1435
|
}
|
|
1085
|
-
return { simbolos: [...simbolos.values()], rotas };
|
|
1436
|
+
return { simbolos: [...simbolos.values()], rotas, recursos: [...recursos.values()] };
|
|
1086
1437
|
}
|
|
1087
1438
|
async function indexarGo(diretorios) {
|
|
1088
1439
|
const simbolos = new Map();
|
|
1089
1440
|
const rotas = [];
|
|
1441
|
+
const recursos = new Map();
|
|
1090
1442
|
for (const diretorio of diretorios) {
|
|
1091
1443
|
const arquivos = await listarArquivosRecursivos(diretorio, [".go"]);
|
|
1092
1444
|
for (const arquivo of arquivos) {
|
|
1093
1445
|
const codigo = await readFile(arquivo, "utf8");
|
|
1094
1446
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
1447
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1448
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1449
|
+
}
|
|
1095
1450
|
for (const simbolo of extrairSimbolosGo(codigo)) {
|
|
1096
1451
|
registrarSimboloGenerico(simbolos, "go", basesSimbolicas, arquivo, simbolo.simbolo);
|
|
1097
1452
|
}
|
|
@@ -1106,16 +1461,20 @@ async function indexarGo(diretorios) {
|
|
|
1106
1461
|
}
|
|
1107
1462
|
}
|
|
1108
1463
|
}
|
|
1109
|
-
return { simbolos: [...simbolos.values()], rotas };
|
|
1464
|
+
return { simbolos: [...simbolos.values()], rotas, recursos: [...recursos.values()] };
|
|
1110
1465
|
}
|
|
1111
1466
|
async function indexarRust(diretorios) {
|
|
1112
1467
|
const simbolos = new Map();
|
|
1113
1468
|
const rotas = [];
|
|
1469
|
+
const recursos = new Map();
|
|
1114
1470
|
for (const diretorio of diretorios) {
|
|
1115
1471
|
const arquivos = await listarArquivosRecursivos(diretorio, [".rs"]);
|
|
1116
1472
|
for (const arquivo of arquivos) {
|
|
1117
1473
|
const codigo = await readFile(arquivo, "utf8");
|
|
1118
1474
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
1475
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1476
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1477
|
+
}
|
|
1119
1478
|
for (const simbolo of extrairSimbolosRust(codigo)) {
|
|
1120
1479
|
registrarSimboloGenerico(simbolos, "rust", basesSimbolicas, arquivo, simbolo.simbolo);
|
|
1121
1480
|
}
|
|
@@ -1130,22 +1489,45 @@ async function indexarRust(diretorios) {
|
|
|
1130
1489
|
}
|
|
1131
1490
|
}
|
|
1132
1491
|
}
|
|
1133
|
-
return { simbolos: [...simbolos.values()], rotas };
|
|
1492
|
+
return { simbolos: [...simbolos.values()], rotas, recursos: [...recursos.values()] };
|
|
1134
1493
|
}
|
|
1135
1494
|
async function indexarCpp(diretorios) {
|
|
1136
1495
|
const simbolos = new Map();
|
|
1496
|
+
const recursos = new Map();
|
|
1137
1497
|
for (const diretorio of diretorios) {
|
|
1138
1498
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".cpp", ".cc", ".cxx", ".hpp", ".h"]))
|
|
1139
1499
|
.filter((arquivo) => !/(^|[\\/])(windows|linux|macos|runner|flutter|ephemeral|build|vendor)([\\/]|$)/i.test(arquivo));
|
|
1140
1500
|
for (const arquivo of arquivos) {
|
|
1141
1501
|
const codigo = await readFile(arquivo, "utf8");
|
|
1142
1502
|
const basesSimbolicas = caminhosSimbolicos(diretorio, arquivo);
|
|
1503
|
+
for (const recurso of extrairRecursosPersistenciaCodigoVivo(arquivo, codigo)) {
|
|
1504
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1505
|
+
}
|
|
1143
1506
|
for (const simbolo of extrairSimbolosCpp(codigo)) {
|
|
1144
1507
|
registrarSimboloGenerico(simbolos, "cpp", basesSimbolicas, arquivo, simbolo.simbolo);
|
|
1145
1508
|
}
|
|
1146
1509
|
}
|
|
1147
1510
|
}
|
|
1148
|
-
return
|
|
1511
|
+
return {
|
|
1512
|
+
simbolos: [...simbolos.values()],
|
|
1513
|
+
recursos: [...recursos.values()],
|
|
1514
|
+
};
|
|
1515
|
+
}
|
|
1516
|
+
async function indexarPersistenciaDeclarativa(diretorios) {
|
|
1517
|
+
const recursos = new Map();
|
|
1518
|
+
for (const diretorio of diretorios) {
|
|
1519
|
+
const arquivos = await listarArquivosRecursivos(diretorio, [".sql", ".psql", ".ddl", ".prisma"]);
|
|
1520
|
+
for (const arquivo of arquivos) {
|
|
1521
|
+
const codigo = await readFile(arquivo, "utf8");
|
|
1522
|
+
const extracoes = arquivo.endsWith(".prisma")
|
|
1523
|
+
? extrairRecursosPrisma(arquivo, codigo)
|
|
1524
|
+
: extrairRecursosPersistenciaCodigoVivo(arquivo, codigo);
|
|
1525
|
+
for (const recurso of extracoes) {
|
|
1526
|
+
registrarRecursoDrift(recursos, recurso.origem, recurso.tipo, recurso.nome, recurso.arquivo, recurso.simbolo);
|
|
1527
|
+
}
|
|
1528
|
+
}
|
|
1529
|
+
}
|
|
1530
|
+
return { recursos: [...recursos.values()] };
|
|
1149
1531
|
}
|
|
1150
1532
|
function normalizarCaminhoRota(caminho) {
|
|
1151
1533
|
if (!caminho) {
|
|
@@ -1337,16 +1719,121 @@ function escolherRotasEsperadas(task, fontesLegado) {
|
|
|
1337
1719
|
function taskEhBridgeFirebase(task) {
|
|
1338
1720
|
return task.implementacoesExternas.some((impl) => impl.origem === "ts" && /sema_contract_bridge|collections?|apps\.worker/i.test(impl.caminho));
|
|
1339
1721
|
}
|
|
1340
|
-
function
|
|
1341
|
-
|
|
1342
|
-
|
|
1722
|
+
function tiposAceitosParaRecursoPersistencia(recurso) {
|
|
1723
|
+
switch (recurso.resourceKind) {
|
|
1724
|
+
case "table":
|
|
1725
|
+
case "view":
|
|
1726
|
+
case "query":
|
|
1727
|
+
case "index":
|
|
1728
|
+
case "collection":
|
|
1729
|
+
case "document":
|
|
1730
|
+
case "keyspace":
|
|
1731
|
+
case "stream":
|
|
1732
|
+
return [recurso.resourceKind];
|
|
1733
|
+
default:
|
|
1734
|
+
return [];
|
|
1735
|
+
}
|
|
1736
|
+
}
|
|
1737
|
+
function nomesRecursoPersistencia(recurso) {
|
|
1738
|
+
return [...new Set([
|
|
1739
|
+
recurso.nome,
|
|
1740
|
+
recurso.table,
|
|
1741
|
+
recurso.collection,
|
|
1742
|
+
recurso.entity,
|
|
1743
|
+
recurso.path,
|
|
1744
|
+
recurso.surface,
|
|
1745
|
+
].filter((item) => Boolean(item)))];
|
|
1746
|
+
}
|
|
1747
|
+
function recursoPersistenciaCombinaAlvo(recurso, alvo) {
|
|
1748
|
+
const alvoVariantes = new Set(variantesNomeRecursoDrift(alvo));
|
|
1749
|
+
if (alvoVariantes.size === 0) {
|
|
1750
|
+
return false;
|
|
1751
|
+
}
|
|
1752
|
+
return nomesRecursoPersistencia(recurso).some((nome) => variantesNomeRecursoDrift(nome).some((variacao) => alvoVariantes.has(variacao)));
|
|
1753
|
+
}
|
|
1754
|
+
function extrairRecursosEsperados(task, ir) {
|
|
1755
|
+
const esperados = new Map();
|
|
1756
|
+
const registrar = (esperado) => {
|
|
1757
|
+
const chave = `${esperado.origem ?? "qualquer"}:${esperado.tiposAceitos.join(",")}:${esperado.nomes.join("|")}:${esperado.alvo}`;
|
|
1758
|
+
if (!esperados.has(chave)) {
|
|
1759
|
+
esperados.set(chave, esperado);
|
|
1760
|
+
}
|
|
1761
|
+
};
|
|
1762
|
+
if (taskEhBridgeFirebase(task)) {
|
|
1763
|
+
for (const efeito of task.efeitosEstruturados.filter((item) => item.categoria === "persistencia" && Boolean(item.alvo))) {
|
|
1764
|
+
registrar({
|
|
1765
|
+
categoria: "persistencia",
|
|
1766
|
+
alvo: efeito.alvo,
|
|
1767
|
+
origem: "firebase",
|
|
1768
|
+
tiposAceitos: ["colecao"],
|
|
1769
|
+
nomes: [efeito.alvo],
|
|
1770
|
+
});
|
|
1771
|
+
}
|
|
1772
|
+
}
|
|
1773
|
+
const efeitosPersistencia = task.efeitosEstruturados.filter((efeito) => ["persistencia", "db.read", "db.write"].includes(efeito.categoria) && Boolean(efeito.alvo));
|
|
1774
|
+
if (efeitosPersistencia.length === 0 || ir.databases.length === 0) {
|
|
1775
|
+
return [...esperados.values()];
|
|
1343
1776
|
}
|
|
1344
|
-
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1777
|
+
for (const efeito of efeitosPersistencia) {
|
|
1778
|
+
for (const database of ir.databases) {
|
|
1779
|
+
for (const recurso of database.resources) {
|
|
1780
|
+
const tiposAceitos = tiposAceitosParaRecursoPersistencia(recurso);
|
|
1781
|
+
if (tiposAceitos.length === 0 || !recursoPersistenciaCombinaAlvo(recurso, efeito.alvo)) {
|
|
1782
|
+
continue;
|
|
1783
|
+
}
|
|
1784
|
+
registrar({
|
|
1785
|
+
categoria: "persistencia",
|
|
1786
|
+
alvo: efeito.alvo,
|
|
1787
|
+
origem: database.engine,
|
|
1788
|
+
tiposAceitos,
|
|
1789
|
+
nomes: nomesRecursoPersistencia(recurso),
|
|
1790
|
+
});
|
|
1791
|
+
}
|
|
1792
|
+
}
|
|
1793
|
+
}
|
|
1794
|
+
return [...esperados.values()];
|
|
1795
|
+
}
|
|
1796
|
+
function construirMapaRecursos(recursos) {
|
|
1797
|
+
const mapa = new Map();
|
|
1798
|
+
for (const recurso of recursos) {
|
|
1799
|
+
for (const variante of variantesNomeRecursoDrift(recurso.nome)) {
|
|
1800
|
+
const existentes = mapa.get(variante) ?? [];
|
|
1801
|
+
if (!existentes.some((item) => item.origem === recurso.origem
|
|
1802
|
+
&& item.tipo === recurso.tipo
|
|
1803
|
+
&& item.arquivo === recurso.arquivo
|
|
1804
|
+
&& item.nome === recurso.nome
|
|
1805
|
+
&& item.simbolo === recurso.simbolo)) {
|
|
1806
|
+
existentes.push(recurso);
|
|
1807
|
+
mapa.set(variante, existentes);
|
|
1808
|
+
}
|
|
1809
|
+
}
|
|
1810
|
+
}
|
|
1811
|
+
return mapa;
|
|
1812
|
+
}
|
|
1813
|
+
function recursoResolvidoCombinaEsperado(recurso, esperado) {
|
|
1814
|
+
if (esperado.origem && recurso.origem !== esperado.origem) {
|
|
1815
|
+
return false;
|
|
1816
|
+
}
|
|
1817
|
+
if (esperado.tiposAceitos.length > 0 && !esperado.tiposAceitos.includes(recurso.tipo)) {
|
|
1818
|
+
return false;
|
|
1819
|
+
}
|
|
1820
|
+
const recursoVariantes = new Set(variantesNomeRecursoDrift(recurso.nome));
|
|
1821
|
+
return esperado.nomes.some((nome) => variantesNomeRecursoDrift(nome).some((variante) => recursoVariantes.has(variante)));
|
|
1822
|
+
}
|
|
1823
|
+
function resolverRecursoEsperado(mapaRecursos, esperado, arquivosPreferidos) {
|
|
1824
|
+
const candidatos = new Map();
|
|
1825
|
+
for (const nome of esperado.nomes) {
|
|
1826
|
+
for (const variante of variantesNomeRecursoDrift(nome)) {
|
|
1827
|
+
for (const recurso of mapaRecursos.get(variante) ?? []) {
|
|
1828
|
+
if (recursoResolvidoCombinaEsperado(recurso, esperado)) {
|
|
1829
|
+
candidatos.set(`${recurso.origem}:${recurso.tipo}:${recurso.nome}:${recurso.arquivo}:${recurso.simbolo ?? ""}`, recurso);
|
|
1830
|
+
}
|
|
1831
|
+
}
|
|
1832
|
+
}
|
|
1833
|
+
}
|
|
1834
|
+
return [...candidatos.values()].sort((a, b) => Number(Boolean(arquivosPreferidos?.has(b.arquivo))) - Number(Boolean(arquivosPreferidos?.has(a.arquivo)))
|
|
1835
|
+
|| a.arquivo.localeCompare(b.arquivo, "pt-BR")
|
|
1836
|
+
|| a.nome.localeCompare(b.nome, "pt-BR"))[0];
|
|
1350
1837
|
}
|
|
1351
1838
|
function coletarVinculosIr(ir) {
|
|
1352
1839
|
return [
|
|
@@ -1365,6 +1852,7 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1365
1852
|
const indexJava = await indexarJava(contexto.diretoriosCodigo);
|
|
1366
1853
|
const indexGo = await indexarGo(contexto.diretoriosCodigo);
|
|
1367
1854
|
const indexRust = await indexarRust(contexto.diretoriosCodigo);
|
|
1855
|
+
const indexPersistencia = await indexarPersistenciaDeclarativa(contexto.diretoriosCodigo);
|
|
1368
1856
|
const indexCpp = await indexarCpp(contexto.diretoriosCodigo);
|
|
1369
1857
|
const todosSimbolos = [
|
|
1370
1858
|
...indexTs.simbolos,
|
|
@@ -1374,7 +1862,7 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1374
1862
|
...indexJava.simbolos,
|
|
1375
1863
|
...indexGo.simbolos,
|
|
1376
1864
|
...indexRust.simbolos,
|
|
1377
|
-
...indexCpp,
|
|
1865
|
+
...indexCpp.simbolos,
|
|
1378
1866
|
];
|
|
1379
1867
|
const mapaImpl = new Map([
|
|
1380
1868
|
...indexTs.simbolos.map((item) => [item.caminho, item]),
|
|
@@ -1384,9 +1872,20 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1384
1872
|
...indexJava.simbolos.map((item) => [item.caminho, item]),
|
|
1385
1873
|
...indexGo.simbolos.map((item) => [item.caminho, item]),
|
|
1386
1874
|
...indexRust.simbolos.map((item) => [item.caminho, item]),
|
|
1387
|
-
...indexCpp.map((item) => [item.caminho, item]),
|
|
1875
|
+
...indexCpp.simbolos.map((item) => [item.caminho, item]),
|
|
1388
1876
|
]);
|
|
1389
|
-
const
|
|
1877
|
+
const todosRecursos = [
|
|
1878
|
+
...indexTs.recursos,
|
|
1879
|
+
...indexPy.recursos,
|
|
1880
|
+
...indexDart.recursos,
|
|
1881
|
+
...indexDotnet.recursos,
|
|
1882
|
+
...indexJava.recursos,
|
|
1883
|
+
...indexGo.recursos,
|
|
1884
|
+
...indexRust.recursos,
|
|
1885
|
+
...indexCpp.recursos,
|
|
1886
|
+
...indexPersistencia.recursos,
|
|
1887
|
+
];
|
|
1888
|
+
const mapaRecursos = construirMapaRecursos(todosRecursos);
|
|
1390
1889
|
const todasRotasIndexadas = [
|
|
1391
1890
|
...indexTs.rotas,
|
|
1392
1891
|
...indexPy.rotas,
|
|
@@ -1399,7 +1898,7 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1399
1898
|
const todosArquivosConhecidos = [...new Set([
|
|
1400
1899
|
...todosSimbolos.map((item) => item.arquivo),
|
|
1401
1900
|
...todasRotasIndexadas.map((item) => item.arquivo),
|
|
1402
|
-
...
|
|
1901
|
+
...todosRecursos.map((item) => item.arquivo),
|
|
1403
1902
|
])].sort((a, b) => a.localeCompare(b, "pt-BR"));
|
|
1404
1903
|
const implsValidos = [];
|
|
1405
1904
|
const implsQuebrados = [];
|
|
@@ -1550,16 +2049,16 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1550
2049
|
candidatosImpl: ordenarCandidatos([...candidatosTask.values()]).slice(0, 5),
|
|
1551
2050
|
checksSugeridos: [],
|
|
1552
2051
|
});
|
|
1553
|
-
for (const recursoEsperado of extrairRecursosEsperados(task)) {
|
|
1554
|
-
const resolvido = mapaRecursos
|
|
2052
|
+
for (const recursoEsperado of extrairRecursosEsperados(task, ir)) {
|
|
2053
|
+
const resolvido = resolverRecursoEsperado(mapaRecursos, recursoEsperado, arquivosReferenciados);
|
|
1555
2054
|
const registro = {
|
|
1556
2055
|
modulo: ir.nome,
|
|
1557
2056
|
task: task.nome,
|
|
1558
2057
|
categoria: recursoEsperado.categoria,
|
|
1559
2058
|
alvo: recursoEsperado.alvo,
|
|
1560
2059
|
arquivo: resolvido?.arquivo ?? "",
|
|
1561
|
-
origem: "firebase",
|
|
1562
|
-
tipo: "
|
|
2060
|
+
origem: resolvido?.origem ?? recursoEsperado.origem ?? "firebase",
|
|
2061
|
+
tipo: resolvido?.tipo ?? recursoEsperado.tiposAceitos[0] ?? "query",
|
|
1563
2062
|
status: resolvido ? "resolvido" : "divergente",
|
|
1564
2063
|
};
|
|
1565
2064
|
if (resolvido) {
|
|
@@ -1568,11 +2067,12 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1568
2067
|
}
|
|
1569
2068
|
else {
|
|
1570
2069
|
recursosDivergentes.push(registro);
|
|
2070
|
+
const escopo = recursoEsperado.origem ? `${recursoEsperado.origem}` : "persistencia declarada";
|
|
1571
2071
|
diagnosticos.push({
|
|
1572
2072
|
tipo: "recurso_divergente",
|
|
1573
2073
|
modulo: ir.nome,
|
|
1574
2074
|
task: task.nome,
|
|
1575
|
-
mensagem: `Recurso vivo "${recursoEsperado.alvo}" nao foi encontrado
|
|
2075
|
+
mensagem: `Recurso vivo "${recursoEsperado.alvo}" nao foi encontrado no codigo legado para ${escopo}.`,
|
|
1576
2076
|
});
|
|
1577
2077
|
}
|
|
1578
2078
|
}
|
|
@@ -1689,7 +2189,12 @@ export async function analisarDriftLegado(contexto) {
|
|
|
1689
2189
|
registro.arquivo = resolucaoArquivo.arquivo;
|
|
1690
2190
|
}
|
|
1691
2191
|
else if (recursoDeclarado) {
|
|
1692
|
-
const recurso = mapaRecursos
|
|
2192
|
+
const recurso = resolverRecursoEsperado(mapaRecursos, {
|
|
2193
|
+
categoria: "persistencia",
|
|
2194
|
+
alvo: recursoDeclarado,
|
|
2195
|
+
tiposAceitos: [],
|
|
2196
|
+
nomes: [recursoDeclarado],
|
|
2197
|
+
});
|
|
1693
2198
|
if (recurso) {
|
|
1694
2199
|
registro.status = "resolvido";
|
|
1695
2200
|
registro.confianca = "alta";
|