@semacode/cli 1.5.11 → 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 +6 -1
  2. package/dist/index.js +446 -32
  3. package/package.json +23 -32
  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 -110
  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 -244
  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 -123
  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 -460
  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 -883
  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 -345
  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 -61
  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 -771
  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 -57
  162. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +0 -1617
  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
@@ -1,793 +0,0 @@
1
- import path from "node:path";
2
- import { descreverEstruturaModulo, extrairTiposNomeados, mapearTipoParaTypeScript, normalizarNomeModulo, normalizarNomeParaSimbolo, } from "@sema/padroes";
3
- function gerarInterface(nome, campos) {
4
- const propriedades = campos.length === 0
5
- ? " // Sem campos declarados.\n"
6
- : campos.map((campo) => ` ${campo.nome}${campo.modificadores.includes("required") ? "" : "?"}: ${mapearTipoParaTypeScript(campo.tipo)};`).join("\n");
7
- return `export interface ${nome} {\n${propriedades}\n}\n`;
8
- }
9
- function gerarComentarioInvariantesTypeScript(invariantes) {
10
- if (invariantes.length === 0) {
11
- return "";
12
- }
13
- return `${invariantes.map((invariante) => `// Invariante: ${invariante.textoOriginal}`).join("\n")}\n`;
14
- }
15
- function gerarLiteralCamposTypeScript(campos) {
16
- if (campos.length === 0) {
17
- return "[]";
18
- }
19
- return `[\n${campos.map((campo) => ` { nome: "${campo.nome}", tipo: "${campo.tipo}", obrigatorio: ${campo.modificadores.includes("required") ? "true" : "false"} },`).join("\n")}\n]`;
20
- }
21
- function coletarTiposExternos(modulo) {
22
- const locais = new Set([
23
- ...modulo.types.map((item) => item.nome),
24
- ...modulo.entities.map((item) => item.nome),
25
- ...modulo.enums.map((item) => item.nome),
26
- ]);
27
- const referenciados = new Set();
28
- const campos = [
29
- ...modulo.entities.flatMap((entity) => entity.campos),
30
- ...modulo.tasks.flatMap((task) => [...task.input, ...task.output]),
31
- ...modulo.routes.flatMap((route) => [...route.inputPublico, ...route.outputPublico]),
32
- ...modulo.states.flatMap((state) => state.campos),
33
- ];
34
- for (const campo of campos) {
35
- for (const tipo of extrairTiposNomeados(campo.tipo)) {
36
- if (!locais.has(tipo)) {
37
- referenciados.add(tipo);
38
- }
39
- }
40
- }
41
- return [...referenciados].sort((a, b) => a.localeCompare(b, "pt-BR"));
42
- }
43
- function gerarLiteralErrosTypeScript(erros) {
44
- const entradas = Object.entries(erros);
45
- if (entradas.length === 0) {
46
- return "{}";
47
- }
48
- return `{\n${entradas.map(([nome, mensagem]) => ` ${JSON.stringify(nome)}: ${JSON.stringify(mensagem)},`).join("\n")}\n}`;
49
- }
50
- function formatarValorTypeScript(valor, camposConhecidos, variavel) {
51
- const texto = valor.trim();
52
- if (/^-?\d+(?:\.\d+)?$/.test(texto)) {
53
- return texto;
54
- }
55
- if (texto === "verdadeiro") {
56
- return "true";
57
- }
58
- if (texto === "falso") {
59
- return "false";
60
- }
61
- if (texto === "nulo") {
62
- return "null";
63
- }
64
- if (camposConhecidos.has(texto.split(".")[0] ?? texto)) {
65
- return `${variavel}.${texto}`;
66
- }
67
- return JSON.stringify(texto);
68
- }
69
- function resolverReferenciaTypeScript(referencia, variavel) {
70
- return `${variavel}.${referencia}`;
71
- }
72
- function gerarExpressaoTypeScript(expressao, camposConhecidos, variavel) {
73
- switch (expressao.tipo) {
74
- case "existe":
75
- return `(${resolverReferenciaTypeScript(expressao.alvo, variavel)} !== undefined && ${resolverReferenciaTypeScript(expressao.alvo, variavel)} !== null)`;
76
- case "comparacao":
77
- return `(${resolverReferenciaTypeScript(expressao.alvo, variavel)} ${expressao.operador} ${formatarValorTypeScript(expressao.valor, camposConhecidos, variavel)})`;
78
- case "pertencimento":
79
- return `([${(expressao.valores ?? []).map((valor) => formatarValorTypeScript(valor, camposConhecidos, variavel)).join(", ")}].includes(${resolverReferenciaTypeScript(expressao.alvo, variavel)}))`;
80
- case "predicado":
81
- return "true";
82
- case "composta":
83
- return `(${expressao.termos.map((termo) => gerarExpressaoTypeScript(termo, camposConhecidos, variavel)).join(expressao.operadorLogico === "e" ? " && " : " || ")})`;
84
- case "negacao":
85
- return `(!${gerarExpressaoTypeScript(expressao.termo, camposConhecidos, variavel)})`;
86
- }
87
- }
88
- function valorPadraoTypeScript(tipo, nomeCampo) {
89
- switch (tipo) {
90
- case "Texto":
91
- case "Id":
92
- case "Email":
93
- case "Url":
94
- return JSON.stringify(`${nomeCampo}_exemplo`);
95
- case "Numero":
96
- case "Inteiro":
97
- case "Decimal":
98
- return "1";
99
- case "Booleano":
100
- return "false";
101
- case "Json":
102
- return "{}";
103
- default:
104
- return "{} as any";
105
- }
106
- }
107
- function removerAspasExternas(valor) {
108
- const texto = valor.trim();
109
- if ((texto.startsWith("\"") && texto.endsWith("\""))
110
- || (texto.startsWith("'") && texto.endsWith("'"))) {
111
- return texto.slice(1, -1);
112
- }
113
- return texto;
114
- }
115
- function dividirLiteralNoNivelRaiz(valor, separador) {
116
- const partes = [];
117
- let atual = "";
118
- let profundidadeAngular = 0;
119
- let profundidadeLista = 0;
120
- let profundidadeMapa = 0;
121
- let aspas = null;
122
- for (let indice = 0; indice < valor.length; indice += 1) {
123
- const caractere = valor[indice];
124
- const anterior = indice > 0 ? valor[indice - 1] : "";
125
- if (aspas) {
126
- atual += caractere;
127
- if (caractere === aspas && anterior !== "\\") {
128
- aspas = null;
129
- }
130
- continue;
131
- }
132
- if (caractere === "\"" || caractere === "'") {
133
- aspas = caractere;
134
- atual += caractere;
135
- continue;
136
- }
137
- if (caractere === "<") {
138
- profundidadeAngular += 1;
139
- atual += caractere;
140
- continue;
141
- }
142
- if (caractere === ">") {
143
- profundidadeAngular = Math.max(0, profundidadeAngular - 1);
144
- atual += caractere;
145
- continue;
146
- }
147
- if (caractere === "[") {
148
- profundidadeLista += 1;
149
- atual += caractere;
150
- continue;
151
- }
152
- if (caractere === "]") {
153
- profundidadeLista = Math.max(0, profundidadeLista - 1);
154
- atual += caractere;
155
- continue;
156
- }
157
- if (caractere === "{") {
158
- profundidadeMapa += 1;
159
- atual += caractere;
160
- continue;
161
- }
162
- if (caractere === "}") {
163
- profundidadeMapa = Math.max(0, profundidadeMapa - 1);
164
- atual += caractere;
165
- continue;
166
- }
167
- if (caractere === separador
168
- && profundidadeAngular === 0
169
- && profundidadeLista === 0
170
- && profundidadeMapa === 0) {
171
- if (atual.trim()) {
172
- partes.push(atual.trim());
173
- }
174
- atual = "";
175
- continue;
176
- }
177
- atual += caractere;
178
- }
179
- if (atual.trim()) {
180
- partes.push(atual.trim());
181
- }
182
- return partes;
183
- }
184
- function resolverTipoItemTeste(tipoDeclarado) {
185
- const tipo = (tipoDeclarado ?? "").trim();
186
- if (!tipo) {
187
- return undefined;
188
- }
189
- if (tipo.endsWith("[]")) {
190
- return tipo.slice(0, -2).trim();
191
- }
192
- const lista = tipo.match(/^Lista<(.+)>$/);
193
- if (lista?.[1]) {
194
- return lista[1].trim();
195
- }
196
- return undefined;
197
- }
198
- function formatarLiteralTesteTypeScript(valor, tipoDeclarado) {
199
- const bruto = valor.trim();
200
- if (bruto.startsWith("[") && bruto.endsWith("]")) {
201
- const interior = bruto.slice(1, -1).trim();
202
- const tipoItem = resolverTipoItemTeste(tipoDeclarado);
203
- if (!interior) {
204
- return [];
205
- }
206
- return dividirLiteralNoNivelRaiz(interior, ",").map((item) => formatarLiteralTesteTypeScript(item, tipoItem));
207
- }
208
- if (bruto.startsWith("{") && bruto.endsWith("}")) {
209
- const interior = bruto.slice(1, -1).trim();
210
- if (!interior) {
211
- return {};
212
- }
213
- const literal = {};
214
- for (const par of dividirLiteralNoNivelRaiz(interior, ",")) {
215
- const [chaveBruta, ...valorBruto] = dividirLiteralNoNivelRaiz(par, ":");
216
- if (!chaveBruta || valorBruto.length === 0) {
217
- continue;
218
- }
219
- literal[removerAspasExternas(chaveBruta)] = formatarLiteralTesteTypeScript(valorBruto.join(":"));
220
- }
221
- return literal;
222
- }
223
- const texto = removerAspasExternas(bruto);
224
- if (["Texto", "Id", "Email", "Url"].includes(tipoDeclarado ?? "")) {
225
- return texto;
226
- }
227
- if (["Numero", "Inteiro", "Decimal"].includes(tipoDeclarado ?? "") && /^-?\d+(?:\.\d+)?$/.test(texto)) {
228
- return Number(texto);
229
- }
230
- if ((tipoDeclarado ?? "") === "Booleano") {
231
- if (texto === "verdadeiro") {
232
- return true;
233
- }
234
- if (texto === "falso") {
235
- return false;
236
- }
237
- }
238
- if (/^-?\d+(?:\.\d+)?$/.test(texto)) {
239
- return Number(texto);
240
- }
241
- if (texto === "verdadeiro") {
242
- return true;
243
- }
244
- if (texto === "falso") {
245
- return false;
246
- }
247
- if (texto === "nulo") {
248
- return null;
249
- }
250
- return texto;
251
- }
252
- function converterBlocoTesteParaValorTypeScript(bloco, tiposDeclarados) {
253
- const literal = {};
254
- for (const campo of bloco.campos) {
255
- literal[campo.nome] = formatarLiteralTesteTypeScript(campo.tipo, tiposDeclarados?.get(campo.nome));
256
- }
257
- for (const subbloco of bloco.blocos) {
258
- literal[subbloco.nome] = converterBlocoTesteParaValorTypeScript(subbloco.conteudo);
259
- }
260
- return literal;
261
- }
262
- function gerarPreparacaoSaida(task) {
263
- const camposSaida = new Set(task.output.map((campo) => campo.nome));
264
- const linhas = [];
265
- for (const campo of task.output) {
266
- linhas.push(` ${campo.nome}: ${valorPadraoTypeScript(campo.tipo, campo.nome)},`);
267
- }
268
- const ajustes = [];
269
- for (const garantia of task.garantiasEstruturadas) {
270
- if (garantia.tipo === "pertencimento" && garantia.valores && camposSaida.has(garantia.alvo)) {
271
- ajustes.push(` saida.${garantia.alvo} = ${formatarValorTypeScript(garantia.valores[0] ?? "", camposSaida, "saida")} as any;`);
272
- }
273
- if (garantia.tipo === "comparacao" && garantia.valor && camposSaida.has(garantia.alvo.split(".")[0] ?? garantia.alvo)) {
274
- ajustes.push(` ${resolverReferenciaTypeScript(garantia.alvo, "saida")} = ${formatarValorTypeScript(garantia.valor, camposSaida, "saida")} as any;`);
275
- }
276
- if (garantia.tipo === "existe" && garantia.alvo.includes(".")) {
277
- const [raiz, filho] = garantia.alvo.split(".", 2);
278
- if (raiz && filho && camposSaida.has(raiz)) {
279
- ajustes.push(` saida.${raiz} = (saida.${raiz} ?? {}) as any;`);
280
- ajustes.push(` (saida.${raiz} as any).${filho} = (saida.${raiz} as any).${filho} ?? "valor_garantido";`);
281
- }
282
- }
283
- }
284
- return ` const saida = {\n${linhas.join("\n")}\n } as ${task.nome}Saida;\n${ajustes.join("\n")}`;
285
- }
286
- function gerarValidacoes(task) {
287
- const linhas = [];
288
- const camposEntrada = new Set(task.input.map((campo) => campo.nome));
289
- for (const campo of task.input) {
290
- if (campo.modificadores.includes("required")) {
291
- linhas.push(` if (entrada.${campo.nome} === undefined || entrada.${campo.nome} === null) throw new Error("Campo obrigatorio ausente: ${campo.nome}");`);
292
- }
293
- }
294
- for (const regra of task.regrasEstruturadas) {
295
- switch (regra.tipo) {
296
- case "predicado":
297
- linhas.push(` // Predicado declarado em Sema: ${regra.textoOriginal}`);
298
- break;
299
- default:
300
- linhas.push(` if (!${gerarExpressaoTypeScript(regra, camposEntrada, "entrada")}) throw new Error("Regra violada: ${regra.textoOriginal}");`);
301
- break;
302
- }
303
- }
304
- for (const regra of task.rules.filter((regra) => !task.regrasEstruturadas.some((estruturada) => estruturada.textoOriginal === regra))) {
305
- linhas.push(` // Regra declarada em Sema: ${regra}`);
306
- }
307
- return linhas.join("\n");
308
- }
309
- function gerarGarantias(task) {
310
- return ` verificar_garantias_${normalizarNomeParaSimbolo(task.nome)}(saida);\n return saida;`;
311
- }
312
- function gerarFuncaoGarantias(task) {
313
- const camposSaida = new Set(task.output.map((campo) => campo.nome));
314
- const linhas = [];
315
- for (const garantia of task.garantiasEstruturadas) {
316
- switch (garantia.tipo) {
317
- case "predicado":
318
- linhas.push(` // Predicado de garantia declarado em Sema: ${garantia.textoOriginal}`);
319
- break;
320
- default:
321
- linhas.push(` if (!${gerarExpressaoTypeScript(garantia, camposSaida, "saida")}) throw new Error("Garantia violada: ${garantia.textoOriginal}");`);
322
- break;
323
- }
324
- }
325
- for (const garantia of task.guarantees.filter((texto) => !task.garantiasEstruturadas.some((estruturada) => estruturada.textoOriginal === texto))) {
326
- linhas.push(` // Garantia declarada em Sema: ${garantia}`);
327
- }
328
- if (linhas.length === 0) {
329
- linhas.push(" // Nenhuma garantia declarada.");
330
- }
331
- return `export function verificar_garantias_${normalizarNomeParaSimbolo(task.nome)}(saida: ${task.nome}Saida): void {\n${linhas.join("\n")}\n}\n`;
332
- }
333
- function gerarMetadadosTask(task) {
334
- const efeitos = task.efeitosEstruturados.length === 0
335
- ? "[]"
336
- : `[\n${task.efeitosEstruturados.map((efeito) => ` { categoria: "${efeito.categoria}", alvo: "${efeito.alvo}"${efeito.detalhe ? `, detalhe: ${JSON.stringify(efeito.detalhe)}` : ""}${efeito.criticidade ? `, criticidade: "${efeito.criticidade}"` : ""} },`).join("\n")}\n]`;
337
- const implementacoes = task.implementacoesExternas.length === 0
338
- ? "[]"
339
- : `[\n${task.implementacoesExternas.map((impl) => ` { origem: "${impl.origem}", caminho: "${impl.caminho}", resolucaoImpl: "${impl.resolucaoImpl ?? impl.caminho}", statusImpl: "${impl.statusImpl ?? "nao_verificado"}" },`).join("\n")}\n]`;
340
- return `export const contrato_${normalizarNomeParaSimbolo(task.nome)} = {
341
- nome: "${task.nome}",
342
- input: ${gerarLiteralCamposTypeScript(task.input)},
343
- output: ${gerarLiteralCamposTypeScript(task.output)},
344
- effects: ${efeitos},
345
- impl: ${implementacoes},
346
- errors: ${gerarLiteralErrosTypeScript(task.errors)},
347
- guarantees: ${JSON.stringify(task.guarantees, null, 2)},
348
- } as const;
349
- `;
350
- }
351
- function gerarMapeamentoSaidaPublicaTypeScript(nomeVariavel, campos) {
352
- if (campos.length === 0) {
353
- return "{}";
354
- }
355
- return `{\n${campos.map((campo) => ` ${campo.nome}: ${nomeVariavel}.${campo.nome},`).join("\n")}\n }`;
356
- }
357
- function gerarRotas(modulo) {
358
- const rotasComTask = modulo.routes.filter((route) => route.task);
359
- if (rotasComTask.length === 0) {
360
- return "";
361
- }
362
- return rotasComTask.map((route) => {
363
- const taskAssociada = modulo.tasks.find((task) => task.nome === route.task);
364
- if (!taskAssociada) {
365
- return "";
366
- }
367
- const nomeSimboloRoute = normalizarNomeParaSimbolo(route.nome);
368
- const nomeSimboloTask = normalizarNomeParaSimbolo(taskAssociada.nome);
369
- const uniaoErros = route.errosPublicos.length === 0
370
- ? "never"
371
- : route.errosPublicos.map((erro) => JSON.stringify(erro.nome)).join(" | ");
372
- const efeitosPublicos = route.efeitosPublicos.length === 0
373
- ? "[]"
374
- : `[\n${route.efeitosPublicos.map((efeito) => ` { categoria: "${efeito.categoria}", alvo: "${efeito.alvo}"${efeito.detalhe ? `, detalhe: ${JSON.stringify(efeito.detalhe)}` : ""}${efeito.criticidade ? `, criticidade: "${efeito.criticidade}"` : ""} },`).join("\n")}\n]`;
375
- const verificacoesErro = route.errosPublicos.map((erro) => ` if (erro instanceof ${taskAssociada.nome}_${erro.nome}Erro) {
376
- return { sucesso: false, erro: { codigo: "${erro.nome}" as ${route.nome}ErroPublico, mensagem: ${JSON.stringify(erro.mensagem ?? taskAssociada.errors[erro.nome] ?? `Erro publico ${erro.nome}`)} } };
377
- }`).join("\n");
378
- return `
379
- ${gerarInterface(`${route.nome}EntradaPublica`, route.inputPublico)}
380
- ${gerarInterface(`${route.nome}SaidaPublica`, route.outputPublico)}
381
- export type ${route.nome}ErroPublico = ${uniaoErros};
382
- export type ${route.nome}RespostaPublica =
383
- | { sucesso: true; dados: ${route.nome}SaidaPublica }
384
- | { sucesso: false; erro: { codigo: ${route.nome}ErroPublico; mensagem: string } };
385
-
386
- export const contrato_publico_${nomeSimboloRoute} = {
387
- nome: "${route.nome}",
388
- metodo: ${JSON.stringify(route.metodo ?? null)},
389
- caminho: ${JSON.stringify(route.caminho ?? null)},
390
- task: ${JSON.stringify(route.task ?? null)},
391
- input: ${gerarLiteralCamposTypeScript(route.inputPublico)},
392
- output: ${gerarLiteralCamposTypeScript(route.outputPublico)},
393
- effects: ${efeitosPublicos},
394
- guarantees: ${JSON.stringify(route.garantiasPublicasMinimas, null, 2)},
395
- errors: ${route.errosPublicos.length === 0 ? "[]" : `[\n${route.errosPublicos.map((erro) => ` { nome: "${erro.nome}", mensagem: ${JSON.stringify(erro.mensagem ?? taskAssociada.errors[erro.nome] ?? "")} },`).join("\n")}\n]`},
396
- } as const;
397
-
398
- export function verificar_resposta_publica_${nomeSimboloRoute}(dados: ${route.nome}SaidaPublica): void {
399
- ${route.outputPublico.length === 0
400
- ? " // Route sem campos publicos obrigatorios."
401
- : route.outputPublico.map((campo) => campo.modificadores.includes("required")
402
- ? ` if (dados.${campo.nome} === undefined || dados.${campo.nome} === null) throw new Error("Resposta publica invalida: campo obrigatorio ausente ${campo.nome}");`
403
- : ` // Campo publico opcional: ${campo.nome}`).join("\n")}
404
- }
405
-
406
- export async function adaptar_${nomeSimboloRoute}(requisicao: ${route.nome}EntradaPublica): Promise<${route.nome}RespostaPublica> {
407
- try {
408
- const saida = await executar_${nomeSimboloTask}(requisicao as ${taskAssociada.nome}Entrada);
409
- const dados = ${gerarMapeamentoSaidaPublicaTypeScript("saida", route.outputPublico)} as ${route.nome}SaidaPublica;
410
- verificar_resposta_publica_${nomeSimboloRoute}(dados);
411
- return {
412
- sucesso: true,
413
- dados,
414
- };
415
- } catch (erro) {
416
- ${verificacoesErro || " throw erro;"}
417
- throw erro;
418
- }
419
- }
420
- `;
421
- }).join("\n");
422
- }
423
- function gerarTask(task) {
424
- const nomeSimbolo = normalizarNomeParaSimbolo(task.nome);
425
- const entradaNome = `${nomeSimbolo}_entrada`;
426
- const saidaNome = `${nomeSimbolo}_saida`;
427
- const errosMapeados = new Map(Object.entries(task.errors));
428
- for (const caso of task.tests) {
429
- const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
430
- if (tipoErro && !errosMapeados.has(tipoErro)) {
431
- errosMapeados.set(tipoErro, `Erro sintetico gerado a partir do caso de teste "${caso.nome}".`);
432
- }
433
- }
434
- const erros = [...errosMapeados.entries()];
435
- const erroAutenticacao = erros.find(([nomeErro]) => nomeErro.includes("autentic"))?.[0];
436
- const erroAutorizacao = erros.find(([nomeErro]) => nomeErro.includes("acesso_negado") || nomeErro.includes("autoriz"))?.[0];
437
- return `
438
- ${gerarInterface(`${task.nome}Entrada`, task.input)}
439
- ${gerarInterface(`${task.nome}Saida`, task.output)}
440
- export type ${task.nome}Erro = ${erros.length === 0 ? "never" : erros.map(([erro]) => `"${erro}"`).join(" | ")};
441
- ${erros.map(([nomeErro, mensagem]) => `export class ${task.nome}_${nomeErro}Erro extends Error {\n readonly codigo = "${nomeErro}";\n constructor() {\n super(${JSON.stringify(mensagem)});\n this.name = "${task.nome}_${nomeErro}Erro";\n }\n}\n`).join("\n")}
442
- export interface ${task.nome}ContextoExecucao {
443
- autenticado?: boolean;
444
- autorizado?: boolean;
445
- erroEsperado?: ${task.nome}Erro | null;
446
- }
447
-
448
- function normalizar_contexto_${nomeSimbolo}(contexto: ${task.nome}ContextoExecucao = {}): Required<${task.nome}ContextoExecucao> {
449
- return {
450
- autenticado: contexto.autenticado ?? true,
451
- autorizado: contexto.autorizado ?? true,
452
- erroEsperado: contexto.erroEsperado ?? null,
453
- };
454
- }
455
-
456
- function criar_erro_${nomeSimbolo}(codigo: ${task.nome}Erro): Error {
457
- switch (codigo) {
458
- ${erros.map(([nomeErro]) => ` case "${nomeErro}":\n return new ${task.nome}_${nomeErro}Erro();`).join("\n")}
459
- default:
460
- return new Error(\`Erro sintetico nao mapeado para ${task.nome}: \${codigo as string}\`);
461
- }
462
- }
463
-
464
- ${gerarMetadadosTask(task)}
465
-
466
- export function validar_${nomeSimbolo}(entrada: ${task.nome}Entrada): void {
467
- ${gerarValidacoes(task)}
468
- }
469
-
470
- ${gerarFuncaoGarantias(task)}
471
-
472
- export async function executar_${nomeSimbolo}(entrada: ${task.nome}Entrada, contexto: ${task.nome}ContextoExecucao = {}): Promise<${task.nome}Saida> {
473
- const contextoExecucao = normalizar_contexto_${nomeSimbolo}(contexto);
474
- const erroEsperado = contextoExecucao.erroEsperado as ${task.nome}Erro | null;
475
- ${erroAutenticacao ? ` if (contextoExecucao.erroEsperado === "${erroAutenticacao}" || (${JSON.stringify(task.auth.modo ?? "")} === "obrigatorio" && !contextoExecucao.autenticado)) {\n throw new ${task.nome}_${erroAutenticacao}Erro();\n }` : ""}
476
- ${erroAutorizacao ? ` if (contextoExecucao.erroEsperado === "${erroAutorizacao}" || (${task.authz.explicita ? "!contextoExecucao.autorizado" : "false"})) {\n throw new ${task.nome}_${erroAutorizacao}Erro();\n }` : ""}
477
- if (erroEsperado${erroAutenticacao || erroAutorizacao ? ` && ![${[erroAutenticacao, erroAutorizacao].filter(Boolean).map((erro) => JSON.stringify(erro)).join(", ")}].includes(erroEsperado)` : ""}) {
478
- throw criar_erro_${nomeSimbolo}(erroEsperado);
479
- }
480
- validar_${nomeSimbolo}(entrada);
481
- ${task.stateContract ? ` // Vinculo de estado: ${task.stateContract.nomeEstado ?? "nao_definido"}\n // Transicoes declaradas pela task: ${task.stateContract.transicoes.map((transicao) => `${transicao.origem}->${transicao.destino}`).join(", ") || "nenhuma"}` : ""}
482
- ${task.implementacoesExternas.length > 0 ? ` // Implementacoes externas vinculadas:\n${task.implementacoesExternas.map((impl) => ` // - ${impl.origem}: ${impl.caminho} [${impl.statusImpl ?? "nao_verificado"}]`).join("\n")}` : ""}
483
- // Efeitos declarados:
484
- ${task.efeitosEstruturados.map((efeito) => ` // - categoria=${efeito.categoria} alvo=${efeito.alvo}${efeito.detalhe ? ` detalhe=${efeito.detalhe}` : ""}${efeito.criticidade ? ` criticidade=${efeito.criticidade}` : ""}`).join("\n") || task.effects.map((efeito) => ` // - ${efeito}`).join("\n") || " // - Nenhum efeito declarado."}
485
- ${gerarPreparacaoSaida(task)}
486
- ${gerarGarantias(task)}
487
- }
488
-
489
- export const ${entradaNome} = {} as ${task.nome}Entrada;
490
- export const ${saidaNome} = {} as ${task.nome}Saida;
491
- `;
492
- }
493
- function gerarTestes(modulo) {
494
- const classesErro = modulo.tasks.flatMap((task) => {
495
- const nomes = new Set(Object.keys(task.errors));
496
- for (const caso of task.tests) {
497
- const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
498
- if (tipoErro) {
499
- nomes.add(tipoErro);
500
- }
501
- }
502
- return [...nomes].map((nomeErro) => `${task.nome}_${nomeErro}Erro`);
503
- });
504
- const linhas = [
505
- 'import test from "node:test";',
506
- 'import assert from "node:assert/strict";',
507
- `import { ${[...modulo.tasks.map((task) => `executar_${normalizarNomeParaSimbolo(task.nome)}`), ...classesErro].join(", ")} } from "./${normalizarNomeModulo(modulo.nome).replace(/\./g, "_")}.ts";`,
508
- ];
509
- for (const task of modulo.tasks) {
510
- const nomeFuncao = `executar_${normalizarNomeParaSimbolo(task.nome)}`;
511
- const tiposEntrada = new Map(task.input.map((campo) => [campo.nome, campo.tipo]));
512
- for (const caso of task.tests) {
513
- const entrada = converterBlocoTesteParaValorTypeScript(caso.given, tiposEntrada);
514
- const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
515
- if (tipoErro) {
516
- const contextoLinhas = [`erroEsperado: ${JSON.stringify(tipoErro)}`];
517
- if (tipoErro.includes("autentic")) {
518
- contextoLinhas.push("autenticado: false", "autorizado: false");
519
- }
520
- else if (tipoErro.includes("acesso_negado") || tipoErro.includes("autoriz")) {
521
- contextoLinhas.push("autenticado: true", "autorizado: false");
522
- }
523
- linhas.push(`
524
- test("${task.nome} :: ${caso.nome}", async () => {
525
- const entrada = ${JSON.stringify(entrada, null, 2)};
526
- const contexto = {
527
- ${contextoLinhas.join(",\n ")}
528
- } as const;
529
- await assert.rejects(() => ${nomeFuncao}(entrada as any, contexto), ${task.nome}_${tipoErro}Erro);
530
- });
531
- `);
532
- continue;
533
- }
534
- linhas.push(`
535
- test("${task.nome} :: ${caso.nome}", async () => {
536
- const entrada = ${JSON.stringify(entrada, null, 2)};
537
- const resultado = await ${nomeFuncao}(entrada as any);
538
- assert.ok(resultado !== undefined);
539
- });
540
- `);
541
- }
542
- }
543
- return linhas.join("\n");
544
- }
545
- function gerarTypeScriptBase(modulo) {
546
- const nomeBase = normalizarNomeModulo(modulo.nome).replace(/\./g, "_");
547
- const interoperabilidades = modulo.interoperabilidades
548
- .map((interop) => `// Interop externo ${interop.origem}: ${interop.caminho}`)
549
- .join("\n");
550
- const tiposExternos = coletarTiposExternos(modulo)
551
- .map((tipo) => `export type ${tipo} = any; // Tipo externo referenciado por use ou por contrato compartilhado.\n`)
552
- .join("\n");
553
- const entidades = modulo.entities
554
- .map((entity) => `${gerarComentarioInvariantesTypeScript(entity.invariantes)}${gerarInterface(entity.nome, entity.campos)}`)
555
- .join("\n");
556
- const tipos = modulo.types
557
- .map((type) => `${gerarComentarioInvariantesTypeScript(type.invariantes)}${gerarInterface(type.nome, type.definicao.campos)}`)
558
- .join("\n");
559
- const enums = modulo.enums
560
- .map((enumeracao) => `export type ${enumeracao.nome} = ${enumeracao.valores.map((valor) => `"${valor}"`).join(" | ")};\n`)
561
- .join("\n");
562
- const states = modulo.states
563
- .map((state) => `// State${state.nome ? ` ${state.nome}` : ""}: campos=${state.campos.length} invariantes=${state.invariantes.length} transicoes=${state.transicoes.length}`)
564
- .join("\n");
565
- const flows = modulo.flows
566
- .map((flow) => `// Flow ${flow.nome}: etapas=${flow.linhas.length} estruturadas=${flow.etapasEstruturadas.length} tasks=${flow.tasksReferenciadas.join(", ") || flow.etapasEstruturadas.map((etapa) => etapa.task).filter(Boolean).join(", ") || "nenhuma"} ramificacoes=${flow.etapasEstruturadas.filter((etapa) => etapa.emSucesso || etapa.emErro).length} mapeamentos=${flow.etapasEstruturadas.reduce((total, etapa) => total + etapa.mapeamentos.length, 0)} rotas_erro=${flow.etapasEstruturadas.reduce((total, etapa) => total + etapa.porErro.length, 0)} efeitos=${flow.efeitosEstruturados.map((efeito) => `${efeito.categoria}:${efeito.alvo}`).join(", ") || "nenhum"}`)
567
- .join("\n");
568
- const routes = modulo.routes
569
- .map((route) => `// Route ${route.nome}: metodo=${route.metodo ?? "nao_definido"} caminho=${route.caminho ?? "nao_definido"} task=${route.task ?? "nao_definida"} input_publico=${route.inputPublico.map((campo) => campo.nome).join(", ") || "padrao_task"} output_publico=${route.outputPublico.map((campo) => campo.nome).join(", ") || "padrao_task"} erros_publicos=${route.errosPublicos.map((erro) => erro.nome).join(", ") || "padrao_task"} effects_publicos=${route.efeitosPublicos.map((efeito) => `${efeito.categoria}:${efeito.alvo}`).join(", ") || "nenhum"} garantias_publicas=${route.garantiasPublicasMinimas.length}`)
570
- .join("\n");
571
- const tasks = modulo.tasks.map(gerarTask).join("\n");
572
- const contratosPublicos = gerarRotas(modulo);
573
- const codigo = `// Arquivo gerado automaticamente pela Sema.\n// Modulo de origem: ${modulo.nome}\n${interoperabilidades ? `${interoperabilidades}\n` : ""}\n${tiposExternos}\n${tipos}\n${entidades}\n${enums}\n${states}\n${flows}\n${routes}\n${tasks}\n${contratosPublicos}\n`;
574
- const testes = gerarTestes(modulo);
575
- return [
576
- { caminhoRelativo: `${nomeBase}.ts`, conteudo: codigo },
577
- { caminhoRelativo: `${nomeBase}.test.ts`, conteudo: testes },
578
- ];
579
- }
580
- function paraPascalCase(valor) {
581
- return valor
582
- .split(/[^A-Za-z0-9]+/)
583
- .filter(Boolean)
584
- .map((parte) => parte[0].toUpperCase() + parte.slice(1))
585
- .join("");
586
- }
587
- function limparPrefixoRota(caminho) {
588
- return (caminho ?? "/").replace(/^\/+/, "").replace(/\/+$/, "");
589
- }
590
- function gerarNestJsDtos(modulo, caminhoContrato) {
591
- const tiposReferenciados = new Set();
592
- const registrarTipos = (campos) => {
593
- for (const campo of campos) {
594
- for (const tipo of extrairTiposNomeados(campo.tipo)) {
595
- tiposReferenciados.add(tipo);
596
- }
597
- }
598
- };
599
- for (const task of modulo.tasks) {
600
- registrarTipos(task.input);
601
- registrarTipos(task.output);
602
- }
603
- for (const route of modulo.routes) {
604
- registrarTipos(route.inputPublico);
605
- registrarTipos(route.outputPublico);
606
- }
607
- const linhas = [];
608
- if (tiposReferenciados.size > 0) {
609
- linhas.push(`import type { ${[...tiposReferenciados].sort((a, b) => a.localeCompare(b, "pt-BR")).join(", ")} } from "${caminhoContrato}";`);
610
- linhas.push("");
611
- }
612
- const gerarClasseDto = (nomeClasse, campos) => {
613
- linhas.push(`export class ${nomeClasse} {`);
614
- if (campos.length === 0) {
615
- linhas.push(" // Sem campos declarados.");
616
- }
617
- else {
618
- for (const campo of campos) {
619
- linhas.push(` ${campo.nome}${campo.modificadores.includes("required") ? "!" : "?"}: ${mapearTipoParaTypeScript(campo.tipo)};`);
620
- }
621
- }
622
- linhas.push("}");
623
- linhas.push("");
624
- };
625
- for (const task of modulo.tasks) {
626
- gerarClasseDto(`${paraPascalCase(task.nome)}EntradaDto`, task.input);
627
- gerarClasseDto(`${paraPascalCase(task.nome)}SaidaDto`, task.output);
628
- }
629
- for (const route of modulo.routes) {
630
- gerarClasseDto(`${paraPascalCase(route.nome)}EntradaPublicaDto`, route.inputPublico);
631
- gerarClasseDto(`${paraPascalCase(route.nome)}SaidaPublicaDto`, route.outputPublico);
632
- }
633
- return `${linhas.join("\n").trim()}\n`;
634
- }
635
- function gerarNestJsService(modulo, caminhoContrato) {
636
- const nomeClasse = `${paraPascalCase(descreverEstruturaModulo(modulo.nome).nomeArquivo)}Service`;
637
- const imports = [
638
- `import { Injectable } from "@nestjs/common";`,
639
- `import {`,
640
- ...modulo.tasks.flatMap((task) => [` executar_${normalizarNomeParaSimbolo(task.nome)},`, ` type ${task.nome}Entrada,`, ` type ${task.nome}Saida,`]),
641
- ...modulo.routes.flatMap((route) => route.task ? [
642
- ` adaptar_${normalizarNomeParaSimbolo(route.nome)},`,
643
- ` type ${route.nome}EntradaPublica,`,
644
- ` type ${route.nome}RespostaPublica,`,
645
- ] : []),
646
- `} from "${caminhoContrato}";`,
647
- ];
648
- const metodosTask = modulo.tasks.map((task) => ` async ${normalizarNomeParaSimbolo(task.nome)}(entrada: ${task.nome}Entrada): Promise<${task.nome}Saida> {
649
- ${task.implementacoesExternas.length > 0 ? task.implementacoesExternas.map((impl) => ` // impl ${impl.origem}: ${impl.caminho}`).join("\n") : " // TODO: ajustar a implementacao real e preencher dependencias do framework."}
650
- return executar_${normalizarNomeParaSimbolo(task.nome)}(entrada);
651
- }`).join("\n\n");
652
- const metodosRota = modulo.routes
653
- .filter((route) => route.task)
654
- .map((route) => ` async ${normalizarNomeParaSimbolo(route.nome)}(entrada: ${route.nome}EntradaPublica): Promise<${route.nome}RespostaPublica> {
655
- return adaptar_${normalizarNomeParaSimbolo(route.nome)}(entrada);
656
- }`).join("\n\n");
657
- return `${imports.join("\n")}
658
-
659
- @Injectable()
660
- export class ${nomeClasse} {
661
- ${metodosTask}${metodosTask && metodosRota ? "\n\n" : ""}${metodosRota}
662
- }
663
- `;
664
- }
665
- function gerarNestJsController(modulo, caminhoDto, caminhoService) {
666
- const nomeArquivo = descreverEstruturaModulo(modulo.nome).nomeArquivo;
667
- const nomeClasse = `${paraPascalCase(nomeArquivo)}Controller`;
668
- const nomeService = `${paraPascalCase(nomeArquivo)}Service`;
669
- const decoratorsImport = new Set(["Controller"]);
670
- const metodos = modulo.routes
671
- .filter((route) => route.task)
672
- .map((route) => {
673
- const metodo = (route.metodo ?? "POST").toUpperCase();
674
- if (metodo === "GET") {
675
- decoratorsImport.add("Get");
676
- }
677
- else if (metodo === "PUT") {
678
- decoratorsImport.add("Put");
679
- }
680
- else if (metodo === "PATCH") {
681
- decoratorsImport.add("Patch");
682
- }
683
- else if (metodo === "DELETE") {
684
- decoratorsImport.add("Delete");
685
- }
686
- else {
687
- decoratorsImport.add("Post");
688
- }
689
- if ((route.inputPublico ?? []).length > 0) {
690
- decoratorsImport.add("Body");
691
- }
692
- const decorator = metodo === "GET" ? "Get" : metodo === "PUT" ? "Put" : metodo === "PATCH" ? "Patch" : metodo === "DELETE" ? "Delete" : "Post";
693
- const caminhoDecorador = limparPrefixoRota(route.caminho);
694
- const bodyArg = route.inputPublico.length > 0
695
- ? `@Body() entrada: ${paraPascalCase(route.nome)}EntradaPublicaDto`
696
- : "";
697
- const tipoResposta = `${route.nome}RespostaPublica`;
698
- return ` @${decorator}(${JSON.stringify(caminhoDecorador)})
699
- async ${normalizarNomeParaSimbolo(route.nome)}(${bodyArg}): Promise<${tipoResposta}> {
700
- return this.service.${normalizarNomeParaSimbolo(route.nome)}(${route.inputPublico.length > 0 ? "entrada" : "{}"});
701
- }`;
702
- }).join("\n\n");
703
- const dtosImportados = [...new Set(modulo.routes
704
- .filter((route) => route.task && route.inputPublico.length > 0)
705
- .map((route) => `${paraPascalCase(route.nome)}EntradaPublicaDto`))];
706
- const contratosImportados = [...new Set(modulo.routes
707
- .filter((route) => route.task)
708
- .map((route) => `type ${route.nome}RespostaPublica`))];
709
- return `import { ${[...decoratorsImport].join(", ")} } from "@nestjs/common";
710
- import { ${nomeService} } from "${caminhoService}";
711
- ${dtosImportados.length > 0 ? `import { ${dtosImportados.join(", ")} } from "${caminhoDto}";` : ""}
712
- ${contratosImportados.length > 0 ? `import { ${contratosImportados.join(", ")} } from "./${descreverEstruturaModulo(modulo.nome).nomeArquivo}.contract";` : ""}
713
-
714
- @Controller()
715
- export class ${nomeClasse} {
716
- constructor(private readonly service: ${nomeService}) {}
717
-
718
- ${metodos || " // Nenhuma route publica declarada no modulo."}
719
- }
720
- `;
721
- }
722
- function gerarNestJsSpec(modulo, caminhoService, caminhoController) {
723
- const nomeArquivo = descreverEstruturaModulo(modulo.nome).nomeArquivo;
724
- const nomeService = `${paraPascalCase(nomeArquivo)}Service`;
725
- const nomeController = `${paraPascalCase(nomeArquivo)}Controller`;
726
- return `import { describe, it } from "@jest/globals";
727
- import { ${nomeService} } from "${caminhoService}";
728
- import { ${nomeController} } from "${caminhoController}";
729
-
730
- describe("${nomeController}", () => {
731
- it("mantem o scaffold inicial em pe", () => {
732
- const service = new ${nomeService}();
733
- const controller = new ${nomeController}(service);
734
- expect(controller).toBeDefined();
735
- });
736
- });
737
- `;
738
- }
739
- function gerarTypeScriptNestJs(modulo) {
740
- const base = gerarTypeScriptBase(modulo);
741
- const contrato = base.find((arquivo) => arquivo.caminhoRelativo.endsWith(".ts") && !arquivo.caminhoRelativo.endsWith(".test.ts"));
742
- const testeContrato = base.find((arquivo) => arquivo.caminhoRelativo.endsWith(".test.ts"));
743
- const estrutura = descreverEstruturaModulo(modulo.nome);
744
- const contexto = estrutura.contextoRelativo;
745
- const contratoPath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.contract.ts`;
746
- const dtoPath = `${contexto ? `${contexto}/` : ""}dto/${estrutura.nomeArquivo}.dto.ts`;
747
- const servicePath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.service.ts`;
748
- const controllerPath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.controller.ts`;
749
- const caminhoImportDto = `./dto/${estrutura.nomeArquivo}.dto`;
750
- const caminhoImportContrato = `./${estrutura.nomeArquivo}.contract`;
751
- const caminhoImportService = `./${estrutura.nomeArquivo}.service`;
752
- const caminhoContratoTeste = path.posix.join("test", `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.contract.test.ts`);
753
- const caminhoControllerSpec = path.posix.join("test", `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.controller.spec.ts`);
754
- const relativoContratoDoTeste = path.posix.relative(path.posix.dirname(caminhoContratoTeste), path.posix.join("src", contratoPath).replace(/\.ts$/, ""));
755
- const relativoServiceDoSpec = path.posix.relative(path.posix.dirname(caminhoControllerSpec), path.posix.join("src", servicePath).replace(/\.ts$/, ""));
756
- const relativoControllerDoSpec = path.posix.relative(path.posix.dirname(caminhoControllerSpec), path.posix.join("src", controllerPath).replace(/\.ts$/, ""));
757
- const arquivos = [
758
- {
759
- caminhoRelativo: path.posix.join("src", contratoPath),
760
- conteudo: contrato?.conteudo ?? "// Nenhum contrato base gerado.\n",
761
- },
762
- {
763
- caminhoRelativo: path.posix.join("src", dtoPath),
764
- conteudo: gerarNestJsDtos(modulo, `../${path.posix.basename(contratoPath, ".ts")}`),
765
- },
766
- {
767
- caminhoRelativo: path.posix.join("src", servicePath),
768
- conteudo: gerarNestJsService(modulo, caminhoImportContrato),
769
- },
770
- {
771
- caminhoRelativo: path.posix.join("src", controllerPath),
772
- conteudo: gerarNestJsController(modulo, caminhoImportDto, caminhoImportService),
773
- },
774
- {
775
- caminhoRelativo: caminhoContratoTeste,
776
- conteudo: (testeContrato?.conteudo ?? "")
777
- .replace(`./${estrutura.nomeBase}.ts`, relativoContratoDoTeste)
778
- .replace(`./${estrutura.nomeArquivo}.ts`, relativoContratoDoTeste),
779
- },
780
- {
781
- caminhoRelativo: caminhoControllerSpec,
782
- conteudo: gerarNestJsSpec(modulo, relativoServiceDoSpec, relativoControllerDoSpec),
783
- },
784
- ];
785
- return arquivos;
786
- }
787
- export function gerarTypeScript(modulo, opcoes = {}) {
788
- if (opcoes.framework === "nestjs") {
789
- return gerarTypeScriptNestJs(modulo);
790
- }
791
- return gerarTypeScriptBase(modulo);
792
- }
793
- //# sourceMappingURL=index.js.map