@semacode/cli 1.5.14 → 1.5.16

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.
Files changed (177) hide show
  1. package/README.md +2 -1
  2. package/dist/index.js +76 -43
  3. package/package.json +26 -35
  4. package/semacode-cli-1.3.1.tgz +0 -0
  5. package/src/angular-consumer-standalone.ts +312 -0
  6. package/src/cpp-symbols.ts +82 -0
  7. package/src/docs.ts +535 -0
  8. package/src/dotnet-http.ts +355 -0
  9. package/src/drift.ts +4933 -0
  10. package/src/go-http.ts +118 -0
  11. package/src/importador.ts +3891 -0
  12. package/src/index.ts +5641 -0
  13. package/src/java-http.ts +247 -0
  14. package/src/lua-symbols.ts +114 -0
  15. package/src/php-symbols.ts +462 -0
  16. package/src/projeto.ts +862 -0
  17. package/src/python-http.ts +258 -0
  18. package/src/rust-http.ts +125 -0
  19. package/src/tipos.ts +24 -0
  20. package/src/typescript-http.ts +1076 -0
  21. package/tsconfig.json +20 -0
  22. package/AGENTS.md +0 -272
  23. package/LICENSE +0 -22
  24. package/SEMA_BRIEF.curto.txt +0 -9
  25. package/SEMA_BRIEF.md +0 -63
  26. package/SEMA_BRIEF.micro.txt +0 -7
  27. package/SEMA_INDEX.json +0 -799
  28. package/dist/angular-consumer-standalone.d.ts +0 -6
  29. package/dist/angular-consumer-standalone.js.map +0 -1
  30. package/dist/cpp-symbols.d.ts +0 -10
  31. package/dist/cpp-symbols.js.map +0 -1
  32. package/dist/docs.d.ts +0 -56
  33. package/dist/docs.js.map +0 -1
  34. package/dist/dotnet-http.d.ts +0 -23
  35. package/dist/dotnet-http.js.map +0 -1
  36. package/dist/drift.d.ts +0 -225
  37. package/dist/drift.js.map +0 -1
  38. package/dist/go-http.d.ts +0 -23
  39. package/dist/go-http.js.map +0 -1
  40. package/dist/importador.d.ts +0 -31
  41. package/dist/importador.js.map +0 -1
  42. package/dist/index.d.ts +0 -2
  43. package/dist/index.js.map +0 -1
  44. package/dist/java-http.d.ts +0 -23
  45. package/dist/java-http.js.map +0 -1
  46. package/dist/lua-symbols.d.ts +0 -10
  47. package/dist/lua-symbols.js.map +0 -1
  48. package/dist/php-symbols.d.ts +0 -24
  49. package/dist/php-symbols.js.map +0 -1
  50. package/dist/projeto.d.ts +0 -53
  51. package/dist/projeto.js.map +0 -1
  52. package/dist/python-http.d.ts +0 -23
  53. package/dist/python-http.js.map +0 -1
  54. package/dist/rust-http.d.ts +0 -23
  55. package/dist/rust-http.js.map +0 -1
  56. package/dist/tipos.d.ts +0 -3
  57. package/dist/tipos.js.map +0 -1
  58. package/dist/typescript-http.d.ts +0 -35
  59. package/dist/typescript-http.js.map +0 -1
  60. package/docs/AGENT_STARTER.md +0 -102
  61. package/docs/cli.md +0 -117
  62. package/docs/como-ensinar-a-sema-para-ia.md +0 -149
  63. package/docs/deploy.md +0 -70
  64. package/docs/documentacao.md +0 -63
  65. package/docs/env.md +0 -56
  66. package/docs/extensao-vscode.md +0 -45
  67. package/docs/fluxo-pratico-ia-sema.md +0 -177
  68. package/docs/instalacao-e-primeiro-uso.md +0 -112
  69. package/docs/integracao-com-ia.md +0 -101
  70. package/docs/mcp.md +0 -53
  71. package/docs/pagamento-ponta-a-ponta.md +0 -155
  72. package/docs/persistencia-vendor-first.md +0 -145
  73. package/docs/prompt-base-ia-sema.md +0 -104
  74. package/docs/rollback.md +0 -47
  75. package/docs/sintaxe.md +0 -410
  76. package/exemplos/agendamento.sema +0 -106
  77. package/exemplos/assinatura.sema +0 -136
  78. package/exemplos/auditoria.sema +0 -88
  79. package/exemplos/autenticacao.sema +0 -125
  80. package/exemplos/automacao.sema +0 -107
  81. package/exemplos/cadastro_usuario.sema +0 -54
  82. package/exemplos/calculadora.sema +0 -78
  83. package/exemplos/crud_simples.sema +0 -89
  84. package/exemplos/estoque.sema +0 -126
  85. package/exemplos/exportacao.sema +0 -94
  86. package/exemplos/fila.sema +0 -131
  87. package/exemplos/integracao_externa.sema +0 -94
  88. package/exemplos/multi_tenant.sema +0 -140
  89. package/exemplos/notificacao.sema +0 -98
  90. package/exemplos/operacao_estrategia.sema +0 -402
  91. package/exemplos/pagamento.sema +0 -222
  92. package/exemplos/pagamento_dominio.sema +0 -35
  93. package/exemplos/pedido.sema +0 -119
  94. package/exemplos/permissao.sema +0 -121
  95. package/exemplos/persistencia_vendor_first.sema +0 -86
  96. package/exemplos/relatorio.sema +0 -93
  97. package/exemplos/testes_embutidos.sema +0 -45
  98. package/exemplos/tratamento_erro.sema +0 -157
  99. package/exemplos/upload_arquivo.sema +0 -93
  100. package/exemplos/webhook.sema +0 -96
  101. package/llms-full.txt +0 -34
  102. package/llms.txt +0 -17
  103. package/node_modules/@sema/gerador-css/dist/index.d.ts +0 -3
  104. package/node_modules/@sema/gerador-css/dist/index.js +0 -592
  105. package/node_modules/@sema/gerador-css/dist/index.js.map +0 -1
  106. package/node_modules/@sema/gerador-css/package.json +0 -7
  107. package/node_modules/@sema/gerador-dart/dist/index.d.ts +0 -3
  108. package/node_modules/@sema/gerador-dart/dist/index.js +0 -44
  109. package/node_modules/@sema/gerador-dart/dist/index.js.map +0 -1
  110. package/node_modules/@sema/gerador-dart/package.json +0 -7
  111. package/node_modules/@sema/gerador-html/dist/index.d.ts +0 -3
  112. package/node_modules/@sema/gerador-html/dist/index.js +0 -163
  113. package/node_modules/@sema/gerador-html/dist/index.js.map +0 -1
  114. package/node_modules/@sema/gerador-html/package.json +0 -7
  115. package/node_modules/@sema/gerador-javascript/dist/index.d.ts +0 -3
  116. package/node_modules/@sema/gerador-javascript/dist/index.js +0 -421
  117. package/node_modules/@sema/gerador-javascript/dist/index.js.map +0 -1
  118. package/node_modules/@sema/gerador-javascript/package.json +0 -7
  119. package/node_modules/@sema/gerador-lua/dist/index.d.ts +0 -3
  120. package/node_modules/@sema/gerador-lua/dist/index.js +0 -328
  121. package/node_modules/@sema/gerador-lua/dist/index.js.map +0 -1
  122. package/node_modules/@sema/gerador-lua/package.json +0 -7
  123. package/node_modules/@sema/gerador-python/dist/index.d.ts +0 -6
  124. package/node_modules/@sema/gerador-python/dist/index.js +0 -729
  125. package/node_modules/@sema/gerador-python/dist/index.js.map +0 -1
  126. package/node_modules/@sema/gerador-python/package.json +0 -7
  127. package/node_modules/@sema/gerador-typescript/dist/index.d.ts +0 -6
  128. package/node_modules/@sema/gerador-typescript/dist/index.js +0 -793
  129. package/node_modules/@sema/gerador-typescript/dist/index.js.map +0 -1
  130. package/node_modules/@sema/gerador-typescript/package.json +0 -7
  131. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +0 -125
  132. package/node_modules/@sema/nucleo/dist/ast/tipos.js +0 -2
  133. package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +0 -1
  134. package/node_modules/@sema/nucleo/dist/diagnosticos/index.d.ts +0 -21
  135. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js +0 -12
  136. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +0 -1
  137. package/node_modules/@sema/nucleo/dist/formatador/index.d.ts +0 -9
  138. package/node_modules/@sema/nucleo/dist/formatador/index.js +0 -487
  139. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +0 -1
  140. package/node_modules/@sema/nucleo/dist/index.d.ts +0 -35
  141. package/node_modules/@sema/nucleo/dist/index.js +0 -96
  142. package/node_modules/@sema/nucleo/dist/index.js.map +0 -1
  143. package/node_modules/@sema/nucleo/dist/ir/conversor.d.ts +0 -5
  144. package/node_modules/@sema/nucleo/dist/ir/conversor.js +0 -1058
  145. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +0 -1
  146. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +0 -377
  147. package/node_modules/@sema/nucleo/dist/ir/modelos.js +0 -2
  148. package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +0 -1
  149. package/node_modules/@sema/nucleo/dist/lexer/lexer.d.ts +0 -7
  150. package/node_modules/@sema/nucleo/dist/lexer/lexer.js +0 -122
  151. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +0 -1
  152. package/node_modules/@sema/nucleo/dist/lexer/tokens.d.ts +0 -8
  153. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +0 -82
  154. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +0 -1
  155. package/node_modules/@sema/nucleo/dist/parser/parser.d.ts +0 -9
  156. package/node_modules/@sema/nucleo/dist/parser/parser.js +0 -807
  157. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +0 -1
  158. package/node_modules/@sema/nucleo/dist/persistencia/contratos.d.ts +0 -39
  159. package/node_modules/@sema/nucleo/dist/persistencia/contratos.js +0 -294
  160. package/node_modules/@sema/nucleo/dist/persistencia/contratos.js.map +0 -1
  161. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +0 -58
  162. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +0 -1912
  163. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +0 -1
  164. package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +0 -104
  165. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +0 -445
  166. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +0 -1
  167. package/node_modules/@sema/nucleo/dist/semantico/seguranca.d.ts +0 -91
  168. package/node_modules/@sema/nucleo/dist/semantico/seguranca.js +0 -258
  169. package/node_modules/@sema/nucleo/dist/semantico/seguranca.js.map +0 -1
  170. package/node_modules/@sema/nucleo/dist/util/arquivos.d.ts +0 -2
  171. package/node_modules/@sema/nucleo/dist/util/arquivos.js +0 -25
  172. package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +0 -1
  173. package/node_modules/@sema/nucleo/package.json +0 -7
  174. package/node_modules/@sema/padroes/dist/index.d.ts +0 -25
  175. package/node_modules/@sema/padroes/dist/index.js +0 -316
  176. package/node_modules/@sema/padroes/dist/index.js.map +0 -1
  177. package/node_modules/@sema/padroes/package.json +0 -7
@@ -0,0 +1,355 @@
1
+ export interface ParametroRotaBackend {
2
+ nome: string;
3
+ tipoSema: "Texto" | "Inteiro" | "Decimal" | "Id";
4
+ }
5
+
6
+ export interface SimboloDotnetExtraido {
7
+ simbolo: string;
8
+ retorno?: string;
9
+ parametros: Array<{ nome: string; tipoTexto?: string; obrigatorio: boolean }>;
10
+ }
11
+
12
+ export interface RotaDotnetExtraida {
13
+ origem: "dotnet";
14
+ metodo: string;
15
+ caminho: string;
16
+ simbolo: string;
17
+ parametros: ParametroRotaBackend[];
18
+ retorno?: string;
19
+ }
20
+
21
+ const METODOS_HTTP = new Set(["GET", "POST", "PUT", "PATCH", "DELETE"]);
22
+
23
+ function normalizarCaminhoBase(caminho?: string): string | undefined {
24
+ if (!caminho) {
25
+ return undefined;
26
+ }
27
+ return caminho.replace(/^\/+|\/+$/g, "");
28
+ }
29
+
30
+ function juntarCaminho(base: string | undefined, sufixo: string | undefined): string {
31
+ const partes = [base, sufixo]
32
+ .map((parte) => normalizarCaminhoBase(parte))
33
+ .filter((parte): parte is string => Boolean(parte));
34
+ return `/${partes.join("/")}`.replace(/\/+/g, "/");
35
+ }
36
+
37
+ function normalizarCaminhoAspNet(caminho: string, classe?: string, metodo?: string): string {
38
+ const controller = (classe ?? "").replace(/Controller$/i, "");
39
+ const action = metodo ?? "";
40
+ return caminho
41
+ .replace(/\[controller\]/gi, controller ? controller.toLowerCase() : "controller")
42
+ .replace(/\[action\]/gi, action ? action.toLowerCase() : "action")
43
+ .replace(/\{([^}:]+):[^}]+\}/g, "{$1}")
44
+ .replace(/\/+/g, "/");
45
+ }
46
+
47
+ function mapearTipoRotaDotnet(tipo?: string): ParametroRotaBackend["tipoSema"] {
48
+ const normalizado = (tipo ?? "").toLowerCase();
49
+ if (/(^|\.)(int|int32|int64|long|short)$/.test(normalizado)) {
50
+ return "Inteiro";
51
+ }
52
+ if (/(^|\.)(float|double|decimal)$/.test(normalizado)) {
53
+ return "Decimal";
54
+ }
55
+ if (/guid|uuid|id$/i.test(normalizado)) {
56
+ return "Id";
57
+ }
58
+ return "Texto";
59
+ }
60
+
61
+ function extrairParametrosRota(caminho: string, assinatura: string): ParametroRotaBackend[] {
62
+ const tiposAssinatura = new Map<string, string>();
63
+ for (const parametroBruto of assinatura.split(",")) {
64
+ const parametro = parametroBruto.trim();
65
+ if (!parametro) {
66
+ continue;
67
+ }
68
+ const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
69
+ const partes = semPadrao.split(/\s+/).filter(Boolean);
70
+ if (partes.length < 2) {
71
+ continue;
72
+ }
73
+ const nome = partes.at(-1)!;
74
+ const tipo = partes.slice(0, -1).join(" ");
75
+ tiposAssinatura.set(nome, tipo);
76
+ }
77
+
78
+ return [...caminho.matchAll(/\{([^}:]+)(?::[^}]+)?\}/g)].map((match) => {
79
+ const nome = match[1]!;
80
+ return {
81
+ nome,
82
+ tipoSema: mapearTipoRotaDotnet(tiposAssinatura.get(nome)),
83
+ };
84
+ });
85
+ }
86
+
87
+ function extrairTextoAtributo(atributo: string): string | undefined {
88
+ return atributo.match(/"([^"]+)"/)?.[1];
89
+ }
90
+
91
+ function extrairMetodosAtributo(atributo: string): string[] {
92
+ const direto = atributo.match(/\[\s*Http(Get|Post|Put|Patch|Delete)\b/i)?.[1]?.toUpperCase();
93
+ if (direto && METODOS_HTTP.has(direto)) {
94
+ return [direto];
95
+ }
96
+
97
+ const bloco = atributo.match(/\bHttpMethods\.(Get|Post|Put|Patch|Delete)\b/gi)
98
+ ?.map((item) => item.split(".").pop()?.toUpperCase() ?? "")
99
+ .filter((item) => METODOS_HTTP.has(item));
100
+ if (bloco && bloco.length > 0) {
101
+ return [...new Set(bloco)];
102
+ }
103
+
104
+ const requestMapping = atributo.match(/\[\s*AcceptVerbs\(([^)]*)\)\s*\]/i)?.[1];
105
+ if (requestMapping) {
106
+ const encontrados = [...requestMapping.matchAll(/"([A-Za-z]+)"/g)]
107
+ .map((match) => match[1]!.toUpperCase())
108
+ .filter((item) => METODOS_HTTP.has(item));
109
+ if (encontrados.length > 0) {
110
+ return [...new Set(encontrados)];
111
+ }
112
+ }
113
+
114
+ return [];
115
+ }
116
+
117
+ function contarChar(texto: string, alvo: string): number {
118
+ return [...texto].filter((char) => char === alvo).length;
119
+ }
120
+
121
+ function atualizarPilhaClasses<T extends { profundidade: number }>(pilha: T[], profundidade: number): void {
122
+ while (pilha.length > 0 && profundidade < pilha[pilha.length - 1]!.profundidade) {
123
+ pilha.pop();
124
+ }
125
+ }
126
+
127
+ function extrairAtributos(linhas: string[], inicio: number): { atributos: string[]; proximoIndice: number } {
128
+ const atributos: string[] = [];
129
+ let indice = inicio;
130
+
131
+ while (indice < linhas.length) {
132
+ const linha = linhas[indice]!.trim();
133
+ if (!linha.startsWith("[")) {
134
+ break;
135
+ }
136
+ let atual = linha;
137
+ let saldo = contarChar(linha, "[") - contarChar(linha, "]");
138
+ while (saldo > 0 && indice + 1 < linhas.length) {
139
+ indice += 1;
140
+ const complemento = linhas[indice]!.trim();
141
+ atual += ` ${complemento}`;
142
+ saldo += contarChar(complemento, "[") - contarChar(complemento, "]");
143
+ }
144
+ atributos.push(atual);
145
+ indice += 1;
146
+ }
147
+
148
+ return { atributos, proximoIndice: indice };
149
+ }
150
+
151
+ export function extrairSimbolosDotnet(codigo: string): SimboloDotnetExtraido[] {
152
+ const simbolos = new Map<string, SimboloDotnetExtraido>();
153
+ const linhas = codigo.split(/\r?\n/);
154
+ const pilhaClasses: Array<{ nome: string; profundidade: number }> = [];
155
+ let classePendente: { nome: string; profundidade: number } | undefined;
156
+ let profundidade = 0;
157
+
158
+ for (let indice = 0; indice < linhas.length; indice += 1) {
159
+ const linhaOriginal = linhas[indice]!;
160
+ const linha = linhaOriginal.trim();
161
+ if (classePendente && linha.startsWith("{")) {
162
+ pilhaClasses.push(classePendente);
163
+ classePendente = undefined;
164
+ }
165
+ if (!linha || linha.startsWith("//")) {
166
+ profundidade += contarChar(linhaOriginal, "{") - contarChar(linhaOriginal, "}");
167
+ atualizarPilhaClasses(pilhaClasses, profundidade);
168
+ continue;
169
+ }
170
+
171
+ const { atributos, proximoIndice } = extrairAtributos(linhas, indice);
172
+ if (atributos.length > 0) {
173
+ indice = proximoIndice;
174
+ }
175
+
176
+ const linhaEfetiva = (linhas[indice] ?? "").trim();
177
+ const classe = linhaEfetiva.match(/\bclass\s+([A-Za-z_]\w*)/);
178
+ if (classe) {
179
+ const entrada = { nome: classe[1]!, profundidade: profundidade + 1 };
180
+ if (linhaEfetiva.includes("{")) {
181
+ pilhaClasses.push(entrada);
182
+ } else {
183
+ classePendente = entrada;
184
+ }
185
+ profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
186
+ atualizarPilhaClasses(pilhaClasses, profundidade);
187
+ continue;
188
+ }
189
+
190
+ const metodo = linhaEfetiva.match(/\b(?:public|internal|protected|private)\s+(?:static\s+|async\s+|virtual\s+|override\s+|sealed\s+|partial\s+)*([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/);
191
+ if (metodo) {
192
+ const classeAtual = pilhaClasses[pilhaClasses.length - 1];
193
+ const simbolo = classeAtual ? `${classeAtual.nome}.${metodo[2]!}` : metodo[2]!;
194
+ simbolos.set(simbolo, {
195
+ simbolo,
196
+ retorno: metodo[1]!.trim(),
197
+ parametros: metodo[3]!.split(",").flatMap((parametroBruto) => {
198
+ const parametro = parametroBruto.trim();
199
+ if (!parametro) {
200
+ return [];
201
+ }
202
+ const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
203
+ const partes = semPadrao.split(/\s+/).filter(Boolean);
204
+ if (partes.length < 2) {
205
+ return [];
206
+ }
207
+ return [{
208
+ nome: partes.at(-1)!,
209
+ tipoTexto: partes.slice(0, -1).join(" "),
210
+ obrigatorio: !parametro.includes("="),
211
+ }];
212
+ }),
213
+ });
214
+ profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
215
+ atualizarPilhaClasses(pilhaClasses, profundidade);
216
+ continue;
217
+ }
218
+
219
+ const funcaoLocal = linhaEfetiva.match(/\b([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*=>/);
220
+ if (funcaoLocal && atributos.length === 0 && pilhaClasses.length === 0) {
221
+ const simbolo = funcaoLocal[2]!;
222
+ simbolos.set(simbolo, {
223
+ simbolo,
224
+ retorno: funcaoLocal[1]!.trim(),
225
+ parametros: [],
226
+ });
227
+ }
228
+
229
+ const funcaoTopo = linhaEfetiva.match(/\b(?:static\s+)?([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)\s*(?:\{|$)/);
230
+ if (funcaoTopo && atributos.length === 0 && pilhaClasses.length === 0 && !["if", "for", "while", "switch"].includes(funcaoTopo[2]!)) {
231
+ const simbolo = funcaoTopo[2]!;
232
+ if (!simbolos.has(simbolo)) {
233
+ simbolos.set(simbolo, {
234
+ simbolo,
235
+ retorno: funcaoTopo[1]!.trim(),
236
+ parametros: funcaoTopo[3]!.split(",").flatMap((parametroBruto) => {
237
+ const parametro = parametroBruto.trim();
238
+ if (!parametro) {
239
+ return [];
240
+ }
241
+ const semPadrao = parametro.split("=")[0]?.trim() ?? parametro;
242
+ const partes = semPadrao.split(/\s+/).filter(Boolean);
243
+ if (partes.length < 2) {
244
+ return [];
245
+ }
246
+ return [{
247
+ nome: partes.at(-1)!,
248
+ tipoTexto: partes.slice(0, -1).join(" "),
249
+ obrigatorio: !parametro.includes("="),
250
+ }];
251
+ }),
252
+ });
253
+ }
254
+ }
255
+
256
+ profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
257
+ atualizarPilhaClasses(pilhaClasses, profundidade);
258
+ }
259
+
260
+ return [...simbolos.values()];
261
+ }
262
+
263
+ export function extrairRotasDotnet(codigo: string): RotaDotnetExtraida[] {
264
+ const rotas = new Map<string, RotaDotnetExtraida>();
265
+ const linhas = codigo.split(/\r?\n/);
266
+ const pilhaClasses: Array<{ nome: string; profundidade: number; rotaBase?: string; apiController: boolean }> = [];
267
+ let classePendente: { nome: string; profundidade: number; rotaBase?: string; apiController: boolean } | undefined;
268
+ let profundidade = 0;
269
+
270
+ for (let indice = 0; indice < linhas.length; indice += 1) {
271
+ const linhaOriginal = linhas[indice]!;
272
+ const linha = linhaOriginal.trim();
273
+ if (classePendente && linha.startsWith("{")) {
274
+ pilhaClasses.push(classePendente);
275
+ classePendente = undefined;
276
+ }
277
+ if (!linha || linha.startsWith("//")) {
278
+ profundidade += contarChar(linhaOriginal, "{") - contarChar(linhaOriginal, "}");
279
+ atualizarPilhaClasses(pilhaClasses, profundidade);
280
+ continue;
281
+ }
282
+
283
+ const { atributos, proximoIndice } = extrairAtributos(linhas, indice);
284
+ if (atributos.length > 0) {
285
+ indice = proximoIndice;
286
+ }
287
+
288
+ const linhaEfetiva = (linhas[indice] ?? "").trim();
289
+ const classe = linhaEfetiva.match(/\bclass\s+([A-Za-z_]\w*)/);
290
+ if (classe) {
291
+ const rotaBase = atributos
292
+ .map((atributo) => extrairTextoAtributo(atributo))
293
+ .find(Boolean);
294
+ const entrada = {
295
+ nome: classe[1]!,
296
+ profundidade: profundidade + 1,
297
+ rotaBase,
298
+ apiController: atributos.some((atributo) => /\[\s*ApiController\s*\]/i.test(atributo)),
299
+ };
300
+ if (linhaEfetiva.includes("{")) {
301
+ pilhaClasses.push(entrada);
302
+ } else {
303
+ classePendente = entrada;
304
+ }
305
+ profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
306
+ atualizarPilhaClasses(pilhaClasses, profundidade);
307
+ continue;
308
+ }
309
+
310
+ const classeAtual = pilhaClasses[pilhaClasses.length - 1];
311
+ const metodo = linhaEfetiva.match(/\b(?:public|internal|protected)\s+(?:async\s+|virtual\s+|override\s+|static\s+)*([A-Za-z0-9_<>,.?[\]\s]+)\s+([A-Za-z_]\w*)\s*\(([^)]*)\)/);
312
+ if (metodo && classeAtual) {
313
+ const atributosMetodo = atributos.filter((atributo) => /\[\s*(?:Http|AcceptVerbs)/i.test(atributo));
314
+ for (const atributo of atributosMetodo) {
315
+ const metodos = extrairMetodosAtributo(atributo);
316
+ const rotaMetodo = extrairTextoAtributo(atributo);
317
+ for (const httpMetodo of metodos) {
318
+ const caminho = normalizarCaminhoAspNet(
319
+ juntarCaminho(classeAtual.rotaBase, rotaMetodo),
320
+ classeAtual.nome,
321
+ metodo[2]!,
322
+ );
323
+ const registro: RotaDotnetExtraida = {
324
+ origem: "dotnet",
325
+ metodo: httpMetodo,
326
+ caminho,
327
+ simbolo: `${classeAtual.nome}.${metodo[2]!}`,
328
+ parametros: extrairParametrosRota(caminho, metodo[3] ?? ""),
329
+ retorno: metodo[1]!.trim(),
330
+ };
331
+ rotas.set(`${registro.metodo}:${registro.caminho}:${registro.simbolo}`, registro);
332
+ }
333
+ }
334
+ }
335
+
336
+ for (const match of linhaEfetiva.matchAll(/\b\w+\.Map(Get|Post|Put|Patch|Delete)\(\s*"([^"]+)"\s*,\s*([A-Za-z_][\w.]*)/g)) {
337
+ const httpMetodo = match[1]!.toUpperCase();
338
+ const caminho = normalizarCaminhoAspNet(match[2]!);
339
+ const simbolo = match[3]!;
340
+ const registro: RotaDotnetExtraida = {
341
+ origem: "dotnet",
342
+ metodo: httpMetodo,
343
+ caminho,
344
+ simbolo,
345
+ parametros: extrairParametrosRota(caminho, ""),
346
+ };
347
+ rotas.set(`${registro.metodo}:${registro.caminho}:${registro.simbolo}`, registro);
348
+ }
349
+
350
+ profundidade += contarChar(linhaEfetiva, "{") - contarChar(linhaEfetiva, "}");
351
+ atualizarPilhaClasses(pilhaClasses, profundidade);
352
+ }
353
+
354
+ return [...rotas.values()];
355
+ }