@semacode/cli 0.8.2

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 (93) hide show
  1. package/LICENSE +22 -0
  2. package/README.md +52 -0
  3. package/dist/cpp-symbols.d.ts +10 -0
  4. package/dist/cpp-symbols.js +71 -0
  5. package/dist/cpp-symbols.js.map +1 -0
  6. package/dist/dotnet-http.d.ts +23 -0
  7. package/dist/dotnet-http.js +301 -0
  8. package/dist/dotnet-http.js.map +1 -0
  9. package/dist/drift.d.ts +74 -0
  10. package/dist/drift.js +878 -0
  11. package/dist/drift.js.map +1 -0
  12. package/dist/go-http.d.ts +23 -0
  13. package/dist/go-http.js +90 -0
  14. package/dist/go-http.js.map +1 -0
  15. package/dist/importador.d.ts +29 -0
  16. package/dist/importador.js +2094 -0
  17. package/dist/importador.js.map +1 -0
  18. package/dist/index.d.ts +2 -0
  19. package/dist/index.js +2150 -0
  20. package/dist/index.js.map +1 -0
  21. package/dist/java-http.d.ts +23 -0
  22. package/dist/java-http.js +204 -0
  23. package/dist/java-http.js.map +1 -0
  24. package/dist/projeto.d.ts +48 -0
  25. package/dist/projeto.js +560 -0
  26. package/dist/projeto.js.map +1 -0
  27. package/dist/python-http.d.ts +23 -0
  28. package/dist/python-http.js +200 -0
  29. package/dist/python-http.js.map +1 -0
  30. package/dist/rust-http.d.ts +23 -0
  31. package/dist/rust-http.js +95 -0
  32. package/dist/rust-http.js.map +1 -0
  33. package/dist/tipos.d.ts +3 -0
  34. package/dist/tipos.js +2 -0
  35. package/dist/tipos.js.map +1 -0
  36. package/dist/typescript-http.d.ts +35 -0
  37. package/dist/typescript-http.js +854 -0
  38. package/dist/typescript-http.js.map +1 -0
  39. package/logo.png +0 -0
  40. package/node_modules/@sema/gerador-dart/dist/index.d.ts +3 -0
  41. package/node_modules/@sema/gerador-dart/dist/index.js +44 -0
  42. package/node_modules/@sema/gerador-dart/dist/index.js.map +1 -0
  43. package/node_modules/@sema/gerador-dart/package.json +7 -0
  44. package/node_modules/@sema/gerador-python/dist/index.d.ts +6 -0
  45. package/node_modules/@sema/gerador-python/dist/index.js +510 -0
  46. package/node_modules/@sema/gerador-python/dist/index.js.map +1 -0
  47. package/node_modules/@sema/gerador-python/package.json +7 -0
  48. package/node_modules/@sema/gerador-typescript/dist/index.d.ts +6 -0
  49. package/node_modules/@sema/gerador-typescript/dist/index.js +646 -0
  50. package/node_modules/@sema/gerador-typescript/dist/index.js.map +1 -0
  51. package/node_modules/@sema/gerador-typescript/package.json +7 -0
  52. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +103 -0
  53. package/node_modules/@sema/nucleo/dist/ast/tipos.js +2 -0
  54. package/node_modules/@sema/nucleo/dist/ast/tipos.js.map +1 -0
  55. package/node_modules/@sema/nucleo/dist/diagnosticos/index.d.ts +21 -0
  56. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js +12 -0
  57. package/node_modules/@sema/nucleo/dist/diagnosticos/index.js.map +1 -0
  58. package/node_modules/@sema/nucleo/dist/formatador/index.d.ts +9 -0
  59. package/node_modules/@sema/nucleo/dist/formatador/index.js +289 -0
  60. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -0
  61. package/node_modules/@sema/nucleo/dist/index.d.ts +34 -0
  62. package/node_modules/@sema/nucleo/dist/index.js +95 -0
  63. package/node_modules/@sema/nucleo/dist/index.js.map +1 -0
  64. package/node_modules/@sema/nucleo/dist/ir/conversor.d.ts +5 -0
  65. package/node_modules/@sema/nucleo/dist/ir/conversor.js +241 -0
  66. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -0
  67. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +131 -0
  68. package/node_modules/@sema/nucleo/dist/ir/modelos.js +2 -0
  69. package/node_modules/@sema/nucleo/dist/ir/modelos.js.map +1 -0
  70. package/node_modules/@sema/nucleo/dist/lexer/lexer.d.ts +7 -0
  71. package/node_modules/@sema/nucleo/dist/lexer/lexer.js +122 -0
  72. package/node_modules/@sema/nucleo/dist/lexer/lexer.js.map +1 -0
  73. package/node_modules/@sema/nucleo/dist/lexer/tokens.d.ts +8 -0
  74. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +30 -0
  75. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -0
  76. package/node_modules/@sema/nucleo/dist/parser/parser.d.ts +9 -0
  77. package/node_modules/@sema/nucleo/dist/parser/parser.js +423 -0
  78. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -0
  79. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +52 -0
  80. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +837 -0
  81. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -0
  82. package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +99 -0
  83. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +395 -0
  84. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -0
  85. package/node_modules/@sema/nucleo/dist/util/arquivos.d.ts +2 -0
  86. package/node_modules/@sema/nucleo/dist/util/arquivos.js +25 -0
  87. package/node_modules/@sema/nucleo/dist/util/arquivos.js.map +1 -0
  88. package/node_modules/@sema/nucleo/package.json +7 -0
  89. package/node_modules/@sema/padroes/dist/index.d.ts +20 -0
  90. package/node_modules/@sema/padroes/dist/index.js +79 -0
  91. package/node_modules/@sema/padroes/dist/index.js.map +1 -0
  92. package/node_modules/@sema/padroes/package.json +7 -0
  93. package/package.json +57 -0
@@ -0,0 +1,646 @@
1
+ import path from "node:path";
2
+ import { descreverEstruturaModulo, mapearTipoParaTypeScript, normalizarNomeModulo, normalizarNomeParaSimbolo, } from "@sema/padroes";
3
+ const TIPOS_PRIMITIVOS_SEMA = new Set(["Texto", "Numero", "Inteiro", "Decimal", "Booleano", "Data", "DataHora", "Id", "Email", "Url", "Json", "Vazio"]);
4
+ const TIPOS_TYPESCRIPT_NATIVOS = new Set([
5
+ "string",
6
+ "number",
7
+ "boolean",
8
+ "Date",
9
+ "unknown",
10
+ "void",
11
+ "null",
12
+ "undefined",
13
+ "any",
14
+ "Record<string, unknown>",
15
+ ]);
16
+ function gerarInterface(nome, campos) {
17
+ const propriedades = campos.length === 0
18
+ ? " // Sem campos declarados.\n"
19
+ : campos.map((campo) => ` ${campo.nome}${campo.modificadores.includes("required") ? "" : "?"}: ${mapearTipoParaTypeScript(campo.tipo)};`).join("\n");
20
+ return `export interface ${nome} {\n${propriedades}\n}\n`;
21
+ }
22
+ function gerarComentarioInvariantesTypeScript(invariantes) {
23
+ if (invariantes.length === 0) {
24
+ return "";
25
+ }
26
+ return `${invariantes.map((invariante) => `// Invariante: ${invariante.textoOriginal}`).join("\n")}\n`;
27
+ }
28
+ function gerarLiteralCamposTypeScript(campos) {
29
+ if (campos.length === 0) {
30
+ return "[]";
31
+ }
32
+ return `[\n${campos.map((campo) => ` { nome: "${campo.nome}", tipo: "${campo.tipo}", obrigatorio: ${campo.modificadores.includes("required") ? "true" : "false"} },`).join("\n")}\n]`;
33
+ }
34
+ function coletarTiposExternos(modulo) {
35
+ const locais = new Set([
36
+ ...modulo.types.map((item) => item.nome),
37
+ ...modulo.entities.map((item) => item.nome),
38
+ ...modulo.enums.map((item) => item.nome),
39
+ ]);
40
+ const referenciados = new Set();
41
+ const campos = [
42
+ ...modulo.entities.flatMap((entity) => entity.campos),
43
+ ...modulo.tasks.flatMap((task) => [...task.input, ...task.output]),
44
+ ...modulo.routes.flatMap((route) => [...route.inputPublico, ...route.outputPublico]),
45
+ ...modulo.states.flatMap((state) => state.campos),
46
+ ];
47
+ for (const campo of campos) {
48
+ if (!TIPOS_PRIMITIVOS_SEMA.has(campo.tipo) && !locais.has(campo.tipo)) {
49
+ referenciados.add(campo.tipo);
50
+ }
51
+ }
52
+ return [...referenciados].sort((a, b) => a.localeCompare(b, "pt-BR"));
53
+ }
54
+ function gerarLiteralErrosTypeScript(erros) {
55
+ const entradas = Object.entries(erros);
56
+ if (entradas.length === 0) {
57
+ return "{}";
58
+ }
59
+ return `{\n${entradas.map(([nome, mensagem]) => ` ${JSON.stringify(nome)}: ${JSON.stringify(mensagem)},`).join("\n")}\n}`;
60
+ }
61
+ function formatarValorTypeScript(valor, camposConhecidos, variavel) {
62
+ const texto = valor.trim();
63
+ if (/^-?\d+(?:\.\d+)?$/.test(texto)) {
64
+ return texto;
65
+ }
66
+ if (texto === "verdadeiro") {
67
+ return "true";
68
+ }
69
+ if (texto === "falso") {
70
+ return "false";
71
+ }
72
+ if (texto === "nulo") {
73
+ return "null";
74
+ }
75
+ if (camposConhecidos.has(texto.split(".")[0] ?? texto)) {
76
+ return `${variavel}.${texto}`;
77
+ }
78
+ return JSON.stringify(texto);
79
+ }
80
+ function resolverReferenciaTypeScript(referencia, variavel) {
81
+ return `${variavel}.${referencia}`;
82
+ }
83
+ function gerarExpressaoTypeScript(expressao, camposConhecidos, variavel) {
84
+ switch (expressao.tipo) {
85
+ case "existe":
86
+ return `(${resolverReferenciaTypeScript(expressao.alvo, variavel)} !== undefined && ${resolverReferenciaTypeScript(expressao.alvo, variavel)} !== null)`;
87
+ case "comparacao":
88
+ return `(${resolverReferenciaTypeScript(expressao.alvo, variavel)} ${expressao.operador} ${formatarValorTypeScript(expressao.valor, camposConhecidos, variavel)})`;
89
+ case "pertencimento":
90
+ return `([${(expressao.valores ?? []).map((valor) => formatarValorTypeScript(valor, camposConhecidos, variavel)).join(", ")}].includes(${resolverReferenciaTypeScript(expressao.alvo, variavel)}))`;
91
+ case "predicado":
92
+ return "true";
93
+ case "composta":
94
+ return `(${expressao.termos.map((termo) => gerarExpressaoTypeScript(termo, camposConhecidos, variavel)).join(expressao.operadorLogico === "e" ? " && " : " || ")})`;
95
+ case "negacao":
96
+ return `(!${gerarExpressaoTypeScript(expressao.termo, camposConhecidos, variavel)})`;
97
+ }
98
+ }
99
+ function valorPadraoTypeScript(tipo, nomeCampo) {
100
+ switch (tipo) {
101
+ case "Texto":
102
+ case "Id":
103
+ case "Email":
104
+ case "Url":
105
+ return JSON.stringify(`${nomeCampo}_exemplo`);
106
+ case "Numero":
107
+ case "Inteiro":
108
+ case "Decimal":
109
+ return "1";
110
+ case "Booleano":
111
+ return "false";
112
+ case "Json":
113
+ return "{}";
114
+ default:
115
+ return "{} as any";
116
+ }
117
+ }
118
+ function formatarLiteralTesteTypeScript(valor, tipoDeclarado) {
119
+ if (["Texto", "Id", "Email", "Url"].includes(tipoDeclarado ?? "")) {
120
+ return valor;
121
+ }
122
+ if (["Numero", "Inteiro", "Decimal"].includes(tipoDeclarado ?? "") && /^-?\d+(?:\.\d+)?$/.test(valor)) {
123
+ return Number(valor);
124
+ }
125
+ if ((tipoDeclarado ?? "") === "Booleano") {
126
+ if (valor === "verdadeiro") {
127
+ return true;
128
+ }
129
+ if (valor === "falso") {
130
+ return false;
131
+ }
132
+ }
133
+ if (/^-?\d+(?:\.\d+)?$/.test(valor)) {
134
+ return Number(valor);
135
+ }
136
+ if (valor === "verdadeiro") {
137
+ return true;
138
+ }
139
+ if (valor === "falso") {
140
+ return false;
141
+ }
142
+ return valor;
143
+ }
144
+ function gerarPreparacaoSaida(task) {
145
+ const camposSaida = new Set(task.output.map((campo) => campo.nome));
146
+ const linhas = [];
147
+ for (const campo of task.output) {
148
+ linhas.push(` ${campo.nome}: ${valorPadraoTypeScript(campo.tipo, campo.nome)},`);
149
+ }
150
+ const ajustes = [];
151
+ for (const garantia of task.garantiasEstruturadas) {
152
+ if (garantia.tipo === "pertencimento" && garantia.valores && camposSaida.has(garantia.alvo)) {
153
+ ajustes.push(` saida.${garantia.alvo} = ${formatarValorTypeScript(garantia.valores[0] ?? "", camposSaida, "saida")} as any;`);
154
+ }
155
+ if (garantia.tipo === "comparacao" && garantia.valor && camposSaida.has(garantia.alvo.split(".")[0] ?? garantia.alvo)) {
156
+ ajustes.push(` ${resolverReferenciaTypeScript(garantia.alvo, "saida")} = ${formatarValorTypeScript(garantia.valor, camposSaida, "saida")} as any;`);
157
+ }
158
+ if (garantia.tipo === "existe" && garantia.alvo.includes(".")) {
159
+ const [raiz, filho] = garantia.alvo.split(".", 2);
160
+ if (raiz && filho && camposSaida.has(raiz)) {
161
+ ajustes.push(` saida.${raiz} = (saida.${raiz} ?? {}) as any;`);
162
+ ajustes.push(` (saida.${raiz} as any).${filho} = (saida.${raiz} as any).${filho} ?? "valor_garantido";`);
163
+ }
164
+ }
165
+ }
166
+ return ` const saida = {\n${linhas.join("\n")}\n } as ${task.nome}Saida;\n${ajustes.join("\n")}`;
167
+ }
168
+ function gerarValidacoes(task) {
169
+ const linhas = [];
170
+ const camposEntrada = new Set(task.input.map((campo) => campo.nome));
171
+ for (const campo of task.input) {
172
+ if (campo.modificadores.includes("required")) {
173
+ linhas.push(` if (entrada.${campo.nome} === undefined || entrada.${campo.nome} === null) throw new Error("Campo obrigatorio ausente: ${campo.nome}");`);
174
+ }
175
+ }
176
+ for (const regra of task.regrasEstruturadas) {
177
+ switch (regra.tipo) {
178
+ case "predicado":
179
+ linhas.push(` // Predicado declarado em Sema: ${regra.textoOriginal}`);
180
+ break;
181
+ default:
182
+ linhas.push(` if (!${gerarExpressaoTypeScript(regra, camposEntrada, "entrada")}) throw new Error("Regra violada: ${regra.textoOriginal}");`);
183
+ break;
184
+ }
185
+ }
186
+ for (const regra of task.rules.filter((regra) => !task.regrasEstruturadas.some((estruturada) => estruturada.textoOriginal === regra))) {
187
+ linhas.push(` // Regra declarada em Sema: ${regra}`);
188
+ }
189
+ return linhas.join("\n");
190
+ }
191
+ function gerarGarantias(task) {
192
+ return ` verificar_garantias_${normalizarNomeParaSimbolo(task.nome)}(saida);\n return saida;`;
193
+ }
194
+ function gerarFuncaoGarantias(task) {
195
+ const camposSaida = new Set(task.output.map((campo) => campo.nome));
196
+ const linhas = [];
197
+ for (const garantia of task.garantiasEstruturadas) {
198
+ switch (garantia.tipo) {
199
+ case "predicado":
200
+ linhas.push(` // Predicado de garantia declarado em Sema: ${garantia.textoOriginal}`);
201
+ break;
202
+ default:
203
+ linhas.push(` if (!${gerarExpressaoTypeScript(garantia, camposSaida, "saida")}) throw new Error("Garantia violada: ${garantia.textoOriginal}");`);
204
+ break;
205
+ }
206
+ }
207
+ for (const garantia of task.guarantees.filter((texto) => !task.garantiasEstruturadas.some((estruturada) => estruturada.textoOriginal === texto))) {
208
+ linhas.push(` // Garantia declarada em Sema: ${garantia}`);
209
+ }
210
+ if (linhas.length === 0) {
211
+ linhas.push(" // Nenhuma garantia declarada.");
212
+ }
213
+ return `export function verificar_garantias_${normalizarNomeParaSimbolo(task.nome)}(saida: ${task.nome}Saida): void {\n${linhas.join("\n")}\n}\n`;
214
+ }
215
+ function gerarMetadadosTask(task) {
216
+ const efeitos = task.efeitosEstruturados.length === 0
217
+ ? "[]"
218
+ : `[\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]`;
219
+ const implementacoes = task.implementacoesExternas.length === 0
220
+ ? "[]"
221
+ : `[\n${task.implementacoesExternas.map((impl) => ` { origem: "${impl.origem}", caminho: "${impl.caminho}", resolucaoImpl: "${impl.resolucaoImpl ?? impl.caminho}", statusImpl: "${impl.statusImpl ?? "nao_verificado"}" },`).join("\n")}\n]`;
222
+ return `export const contrato_${normalizarNomeParaSimbolo(task.nome)} = {
223
+ nome: "${task.nome}",
224
+ input: ${gerarLiteralCamposTypeScript(task.input)},
225
+ output: ${gerarLiteralCamposTypeScript(task.output)},
226
+ effects: ${efeitos},
227
+ impl: ${implementacoes},
228
+ errors: ${gerarLiteralErrosTypeScript(task.errors)},
229
+ guarantees: ${JSON.stringify(task.guarantees, null, 2)},
230
+ } as const;
231
+ `;
232
+ }
233
+ function gerarMapeamentoSaidaPublicaTypeScript(nomeVariavel, campos) {
234
+ if (campos.length === 0) {
235
+ return "{}";
236
+ }
237
+ return `{\n${campos.map((campo) => ` ${campo.nome}: ${nomeVariavel}.${campo.nome},`).join("\n")}\n }`;
238
+ }
239
+ function gerarRotas(modulo) {
240
+ const rotasComTask = modulo.routes.filter((route) => route.task);
241
+ if (rotasComTask.length === 0) {
242
+ return "";
243
+ }
244
+ return rotasComTask.map((route) => {
245
+ const taskAssociada = modulo.tasks.find((task) => task.nome === route.task);
246
+ if (!taskAssociada) {
247
+ return "";
248
+ }
249
+ const nomeSimboloRoute = normalizarNomeParaSimbolo(route.nome);
250
+ const nomeSimboloTask = normalizarNomeParaSimbolo(taskAssociada.nome);
251
+ const uniaoErros = route.errosPublicos.length === 0
252
+ ? "never"
253
+ : route.errosPublicos.map((erro) => JSON.stringify(erro.nome)).join(" | ");
254
+ const efeitosPublicos = route.efeitosPublicos.length === 0
255
+ ? "[]"
256
+ : `[\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]`;
257
+ const verificacoesErro = route.errosPublicos.map((erro) => ` if (erro instanceof ${taskAssociada.nome}_${erro.nome}Erro) {
258
+ return { sucesso: false, erro: { codigo: "${erro.nome}" as ${route.nome}ErroPublico, mensagem: ${JSON.stringify(erro.mensagem ?? taskAssociada.errors[erro.nome] ?? `Erro publico ${erro.nome}`)} } };
259
+ }`).join("\n");
260
+ return `
261
+ ${gerarInterface(`${route.nome}EntradaPublica`, route.inputPublico)}
262
+ ${gerarInterface(`${route.nome}SaidaPublica`, route.outputPublico)}
263
+ export type ${route.nome}ErroPublico = ${uniaoErros};
264
+ export type ${route.nome}RespostaPublica =
265
+ | { sucesso: true; dados: ${route.nome}SaidaPublica }
266
+ | { sucesso: false; erro: { codigo: ${route.nome}ErroPublico; mensagem: string } };
267
+
268
+ export const contrato_publico_${nomeSimboloRoute} = {
269
+ nome: "${route.nome}",
270
+ metodo: ${JSON.stringify(route.metodo ?? null)},
271
+ caminho: ${JSON.stringify(route.caminho ?? null)},
272
+ task: ${JSON.stringify(route.task ?? null)},
273
+ input: ${gerarLiteralCamposTypeScript(route.inputPublico)},
274
+ output: ${gerarLiteralCamposTypeScript(route.outputPublico)},
275
+ effects: ${efeitosPublicos},
276
+ guarantees: ${JSON.stringify(route.garantiasPublicasMinimas, null, 2)},
277
+ 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]`},
278
+ } as const;
279
+
280
+ export function verificar_resposta_publica_${nomeSimboloRoute}(dados: ${route.nome}SaidaPublica): void {
281
+ ${route.outputPublico.length === 0
282
+ ? " // Route sem campos publicos obrigatorios."
283
+ : route.outputPublico.map((campo) => campo.modificadores.includes("required")
284
+ ? ` if (dados.${campo.nome} === undefined || dados.${campo.nome} === null) throw new Error("Resposta publica invalida: campo obrigatorio ausente ${campo.nome}");`
285
+ : ` // Campo publico opcional: ${campo.nome}`).join("\n")}
286
+ }
287
+
288
+ export async function adaptar_${nomeSimboloRoute}(requisicao: ${route.nome}EntradaPublica): Promise<${route.nome}RespostaPublica> {
289
+ try {
290
+ const saida = await executar_${nomeSimboloTask}(requisicao as ${taskAssociada.nome}Entrada);
291
+ const dados = ${gerarMapeamentoSaidaPublicaTypeScript("saida", route.outputPublico)} as ${route.nome}SaidaPublica;
292
+ verificar_resposta_publica_${nomeSimboloRoute}(dados);
293
+ return {
294
+ sucesso: true,
295
+ dados,
296
+ };
297
+ } catch (erro) {
298
+ ${verificacoesErro || " throw erro;"}
299
+ throw erro;
300
+ }
301
+ }
302
+ `;
303
+ }).join("\n");
304
+ }
305
+ function gerarTask(task) {
306
+ const nomeSimbolo = normalizarNomeParaSimbolo(task.nome);
307
+ const entradaNome = `${nomeSimbolo}_entrada`;
308
+ const saidaNome = `${nomeSimbolo}_saida`;
309
+ const errosMapeados = new Map(Object.entries(task.errors));
310
+ for (const caso of task.tests) {
311
+ const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
312
+ if (tipoErro && !errosMapeados.has(tipoErro)) {
313
+ errosMapeados.set(tipoErro, `Erro sintetico gerado a partir do caso de teste "${caso.nome}".`);
314
+ }
315
+ }
316
+ const erros = [...errosMapeados.entries()];
317
+ const tiposEntrada = new Map(task.input.map((campo) => [campo.nome, campo.tipo]));
318
+ const cenariosErro = task.tests
319
+ .filter((caso) => caso.error && caso.error.campos.length > 0)
320
+ .map((caso) => ({
321
+ nome: caso.nome,
322
+ entrada: Object.fromEntries(caso.given.campos.map((campo) => [campo.nome, formatarLiteralTesteTypeScript(campo.tipo, tiposEntrada.get(campo.nome))])),
323
+ tipoErro: caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo,
324
+ }))
325
+ .filter((caso) => caso.tipoErro);
326
+ return `
327
+ ${gerarInterface(`${task.nome}Entrada`, task.input)}
328
+ ${gerarInterface(`${task.nome}Saida`, task.output)}
329
+ export type ${task.nome}Erro = ${erros.length === 0 ? "never" : erros.map(([erro]) => `"${erro}"`).join(" | ")};
330
+ ${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")}
331
+ ${gerarMetadadosTask(task)}
332
+
333
+ export function validar_${nomeSimbolo}(entrada: ${task.nome}Entrada): void {
334
+ ${gerarValidacoes(task)}
335
+ }
336
+
337
+ ${gerarFuncaoGarantias(task)}
338
+
339
+ export async function executar_${nomeSimbolo}(entrada: ${task.nome}Entrada): Promise<${task.nome}Saida> {
340
+ validar_${nomeSimbolo}(entrada);
341
+ ${cenariosErro.map((caso) => ` if (JSON.stringify(entrada) === JSON.stringify(${JSON.stringify(caso.entrada)})) throw new ${task.nome}_${caso.tipoErro}Erro();`).join("\n")}
342
+ ${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"}` : ""}
343
+ ${task.implementacoesExternas.length > 0 ? ` // Implementacoes externas vinculadas:\n${task.implementacoesExternas.map((impl) => ` // - ${impl.origem}: ${impl.caminho} [${impl.statusImpl ?? "nao_verificado"}]`).join("\n")}` : ""}
344
+ // Efeitos declarados:
345
+ ${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."}
346
+ ${gerarPreparacaoSaida(task)}
347
+ ${gerarGarantias(task)}
348
+ }
349
+
350
+ export const ${entradaNome} = {} as ${task.nome}Entrada;
351
+ export const ${saidaNome} = {} as ${task.nome}Saida;
352
+ `;
353
+ }
354
+ function gerarTestes(modulo) {
355
+ const classesErro = modulo.tasks.flatMap((task) => {
356
+ const nomes = new Set(Object.keys(task.errors));
357
+ for (const caso of task.tests) {
358
+ const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
359
+ if (tipoErro) {
360
+ nomes.add(tipoErro);
361
+ }
362
+ }
363
+ return [...nomes].map((nomeErro) => `${task.nome}_${nomeErro}Erro`);
364
+ });
365
+ const linhas = [
366
+ 'import test from "node:test";',
367
+ 'import assert from "node:assert/strict";',
368
+ `import { ${[...modulo.tasks.map((task) => `executar_${normalizarNomeParaSimbolo(task.nome)}`), ...classesErro].join(", ")} } from "./${normalizarNomeModulo(modulo.nome).replace(/\./g, "_")}.ts";`,
369
+ ];
370
+ for (const task of modulo.tasks) {
371
+ const nomeFuncao = `executar_${normalizarNomeParaSimbolo(task.nome)}`;
372
+ const tiposEntrada = new Map(task.input.map((campo) => [campo.nome, campo.tipo]));
373
+ for (const caso of task.tests) {
374
+ const entrada = Object.fromEntries(caso.given.campos.map((campo) => [campo.nome, formatarLiteralTesteTypeScript(campo.tipo, tiposEntrada.get(campo.nome))]));
375
+ const tipoErro = caso.error?.campos.find((campo) => campo.nome === "tipo")?.tipo ?? caso.error?.campos[0]?.tipo;
376
+ if (tipoErro) {
377
+ linhas.push(`
378
+ test("${task.nome} :: ${caso.nome}", async () => {
379
+ const entrada = ${JSON.stringify(entrada, null, 2)};
380
+ await assert.rejects(() => ${nomeFuncao}(entrada as any), ${task.nome}_${tipoErro}Erro);
381
+ });
382
+ `);
383
+ continue;
384
+ }
385
+ linhas.push(`
386
+ test("${task.nome} :: ${caso.nome}", async () => {
387
+ const entrada = ${JSON.stringify(entrada, null, 2)};
388
+ const resultado = await ${nomeFuncao}(entrada as any);
389
+ assert.ok(resultado !== undefined);
390
+ });
391
+ `);
392
+ }
393
+ }
394
+ return linhas.join("\n");
395
+ }
396
+ function gerarTypeScriptBase(modulo) {
397
+ const nomeBase = normalizarNomeModulo(modulo.nome).replace(/\./g, "_");
398
+ const interoperabilidades = modulo.interoperabilidades
399
+ .map((interop) => `// Interop externo ${interop.origem}: ${interop.caminho}`)
400
+ .join("\n");
401
+ const tiposExternos = coletarTiposExternos(modulo)
402
+ .map((tipo) => `export type ${tipo} = any; // Tipo externo referenciado por use ou por contrato compartilhado.\n`)
403
+ .join("\n");
404
+ const entidades = modulo.entities
405
+ .map((entity) => `${gerarComentarioInvariantesTypeScript(entity.invariantes)}${gerarInterface(entity.nome, entity.campos)}`)
406
+ .join("\n");
407
+ const tipos = modulo.types
408
+ .map((type) => `${gerarComentarioInvariantesTypeScript(type.invariantes)}${gerarInterface(type.nome, type.definicao.campos)}`)
409
+ .join("\n");
410
+ const enums = modulo.enums
411
+ .map((enumeracao) => `export type ${enumeracao.nome} = ${enumeracao.valores.map((valor) => `"${valor}"`).join(" | ")};\n`)
412
+ .join("\n");
413
+ const states = modulo.states
414
+ .map((state) => `// State${state.nome ? ` ${state.nome}` : ""}: campos=${state.campos.length} invariantes=${state.invariantes.length} transicoes=${state.transicoes.length}`)
415
+ .join("\n");
416
+ const flows = modulo.flows
417
+ .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"}`)
418
+ .join("\n");
419
+ const routes = modulo.routes
420
+ .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}`)
421
+ .join("\n");
422
+ const tasks = modulo.tasks.map(gerarTask).join("\n");
423
+ const contratosPublicos = gerarRotas(modulo);
424
+ 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`;
425
+ const testes = gerarTestes(modulo);
426
+ return [
427
+ { caminhoRelativo: `${nomeBase}.ts`, conteudo: codigo },
428
+ { caminhoRelativo: `${nomeBase}.test.ts`, conteudo: testes },
429
+ ];
430
+ }
431
+ function paraPascalCase(valor) {
432
+ return valor
433
+ .split(/[^A-Za-z0-9]+/)
434
+ .filter(Boolean)
435
+ .map((parte) => parte[0].toUpperCase() + parte.slice(1))
436
+ .join("");
437
+ }
438
+ function limparPrefixoRota(caminho) {
439
+ return (caminho ?? "/").replace(/^\/+/, "").replace(/\/+$/, "");
440
+ }
441
+ function gerarNestJsDtos(modulo, caminhoContrato) {
442
+ const tiposReferenciados = new Set();
443
+ const registrarTipos = (campos) => {
444
+ for (const campo of campos) {
445
+ const tipoMapeado = mapearTipoParaTypeScript(campo.tipo);
446
+ if (!TIPOS_TYPESCRIPT_NATIVOS.has(tipoMapeado)
447
+ && /^[A-Za-z_][A-Za-z0-9_]*$/.test(tipoMapeado)) {
448
+ tiposReferenciados.add(tipoMapeado);
449
+ }
450
+ }
451
+ };
452
+ for (const task of modulo.tasks) {
453
+ registrarTipos(task.input);
454
+ registrarTipos(task.output);
455
+ }
456
+ for (const route of modulo.routes) {
457
+ registrarTipos(route.inputPublico);
458
+ registrarTipos(route.outputPublico);
459
+ }
460
+ const linhas = [];
461
+ if (tiposReferenciados.size > 0) {
462
+ linhas.push(`import type { ${[...tiposReferenciados].sort((a, b) => a.localeCompare(b, "pt-BR")).join(", ")} } from "${caminhoContrato}";`);
463
+ linhas.push("");
464
+ }
465
+ const gerarClasseDto = (nomeClasse, campos) => {
466
+ linhas.push(`export class ${nomeClasse} {`);
467
+ if (campos.length === 0) {
468
+ linhas.push(" // Sem campos declarados.");
469
+ }
470
+ else {
471
+ for (const campo of campos) {
472
+ linhas.push(` ${campo.nome}${campo.modificadores.includes("required") ? "!" : "?"}: ${mapearTipoParaTypeScript(campo.tipo)};`);
473
+ }
474
+ }
475
+ linhas.push("}");
476
+ linhas.push("");
477
+ };
478
+ for (const task of modulo.tasks) {
479
+ gerarClasseDto(`${paraPascalCase(task.nome)}EntradaDto`, task.input);
480
+ gerarClasseDto(`${paraPascalCase(task.nome)}SaidaDto`, task.output);
481
+ }
482
+ for (const route of modulo.routes) {
483
+ gerarClasseDto(`${paraPascalCase(route.nome)}EntradaPublicaDto`, route.inputPublico);
484
+ gerarClasseDto(`${paraPascalCase(route.nome)}SaidaPublicaDto`, route.outputPublico);
485
+ }
486
+ return `${linhas.join("\n").trim()}\n`;
487
+ }
488
+ function gerarNestJsService(modulo, caminhoContrato) {
489
+ const nomeClasse = `${paraPascalCase(descreverEstruturaModulo(modulo.nome).nomeArquivo)}Service`;
490
+ const imports = [
491
+ `import { Injectable } from "@nestjs/common";`,
492
+ `import {`,
493
+ ...modulo.tasks.flatMap((task) => [` executar_${normalizarNomeParaSimbolo(task.nome)},`, ` type ${task.nome}Entrada,`, ` type ${task.nome}Saida,`]),
494
+ ...modulo.routes.flatMap((route) => route.task ? [
495
+ ` adaptar_${normalizarNomeParaSimbolo(route.nome)},`,
496
+ ` type ${route.nome}EntradaPublica,`,
497
+ ` type ${route.nome}RespostaPublica,`,
498
+ ] : []),
499
+ `} from "${caminhoContrato}";`,
500
+ ];
501
+ const metodosTask = modulo.tasks.map((task) => ` async ${normalizarNomeParaSimbolo(task.nome)}(entrada: ${task.nome}Entrada): Promise<${task.nome}Saida> {
502
+ ${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."}
503
+ return executar_${normalizarNomeParaSimbolo(task.nome)}(entrada);
504
+ }`).join("\n\n");
505
+ const metodosRota = modulo.routes
506
+ .filter((route) => route.task)
507
+ .map((route) => ` async ${normalizarNomeParaSimbolo(route.nome)}(entrada: ${route.nome}EntradaPublica): Promise<${route.nome}RespostaPublica> {
508
+ return adaptar_${normalizarNomeParaSimbolo(route.nome)}(entrada);
509
+ }`).join("\n\n");
510
+ return `${imports.join("\n")}
511
+
512
+ @Injectable()
513
+ export class ${nomeClasse} {
514
+ ${metodosTask}${metodosTask && metodosRota ? "\n\n" : ""}${metodosRota}
515
+ }
516
+ `;
517
+ }
518
+ function gerarNestJsController(modulo, caminhoDto, caminhoService) {
519
+ const nomeArquivo = descreverEstruturaModulo(modulo.nome).nomeArquivo;
520
+ const nomeClasse = `${paraPascalCase(nomeArquivo)}Controller`;
521
+ const nomeService = `${paraPascalCase(nomeArquivo)}Service`;
522
+ const decoratorsImport = new Set(["Controller"]);
523
+ const metodos = modulo.routes
524
+ .filter((route) => route.task)
525
+ .map((route) => {
526
+ const metodo = (route.metodo ?? "POST").toUpperCase();
527
+ if (metodo === "GET") {
528
+ decoratorsImport.add("Get");
529
+ }
530
+ else if (metodo === "PUT") {
531
+ decoratorsImport.add("Put");
532
+ }
533
+ else if (metodo === "PATCH") {
534
+ decoratorsImport.add("Patch");
535
+ }
536
+ else if (metodo === "DELETE") {
537
+ decoratorsImport.add("Delete");
538
+ }
539
+ else {
540
+ decoratorsImport.add("Post");
541
+ }
542
+ if ((route.inputPublico ?? []).length > 0) {
543
+ decoratorsImport.add("Body");
544
+ }
545
+ const decorator = metodo === "GET" ? "Get" : metodo === "PUT" ? "Put" : metodo === "PATCH" ? "Patch" : metodo === "DELETE" ? "Delete" : "Post";
546
+ const caminhoDecorador = limparPrefixoRota(route.caminho);
547
+ const bodyArg = route.inputPublico.length > 0
548
+ ? `@Body() entrada: ${paraPascalCase(route.nome)}EntradaPublicaDto`
549
+ : "";
550
+ const tipoResposta = `${route.nome}RespostaPublica`;
551
+ return ` @${decorator}(${JSON.stringify(caminhoDecorador)})
552
+ async ${normalizarNomeParaSimbolo(route.nome)}(${bodyArg}): Promise<${tipoResposta}> {
553
+ return this.service.${normalizarNomeParaSimbolo(route.nome)}(${route.inputPublico.length > 0 ? "entrada" : "{}"});
554
+ }`;
555
+ }).join("\n\n");
556
+ const dtosImportados = [...new Set(modulo.routes
557
+ .filter((route) => route.task && route.inputPublico.length > 0)
558
+ .map((route) => `${paraPascalCase(route.nome)}EntradaPublicaDto`))];
559
+ const contratosImportados = [...new Set(modulo.routes
560
+ .filter((route) => route.task)
561
+ .map((route) => `type ${route.nome}RespostaPublica`))];
562
+ return `import { ${[...decoratorsImport].join(", ")} } from "@nestjs/common";
563
+ import { ${nomeService} } from "${caminhoService}";
564
+ ${dtosImportados.length > 0 ? `import { ${dtosImportados.join(", ")} } from "${caminhoDto}";` : ""}
565
+ ${contratosImportados.length > 0 ? `import { ${contratosImportados.join(", ")} } from "./${descreverEstruturaModulo(modulo.nome).nomeArquivo}.contract";` : ""}
566
+
567
+ @Controller()
568
+ export class ${nomeClasse} {
569
+ constructor(private readonly service: ${nomeService}) {}
570
+
571
+ ${metodos || " // Nenhuma route publica declarada no modulo."}
572
+ }
573
+ `;
574
+ }
575
+ function gerarNestJsSpec(modulo, caminhoService, caminhoController) {
576
+ const nomeArquivo = descreverEstruturaModulo(modulo.nome).nomeArquivo;
577
+ const nomeService = `${paraPascalCase(nomeArquivo)}Service`;
578
+ const nomeController = `${paraPascalCase(nomeArquivo)}Controller`;
579
+ return `import { describe, it } from "@jest/globals";
580
+ import { ${nomeService} } from "${caminhoService}";
581
+ import { ${nomeController} } from "${caminhoController}";
582
+
583
+ describe("${nomeController}", () => {
584
+ it("mantem o scaffold inicial em pe", () => {
585
+ const service = new ${nomeService}();
586
+ const controller = new ${nomeController}(service);
587
+ expect(controller).toBeDefined();
588
+ });
589
+ });
590
+ `;
591
+ }
592
+ function gerarTypeScriptNestJs(modulo) {
593
+ const base = gerarTypeScriptBase(modulo);
594
+ const contrato = base.find((arquivo) => arquivo.caminhoRelativo.endsWith(".ts") && !arquivo.caminhoRelativo.endsWith(".test.ts"));
595
+ const testeContrato = base.find((arquivo) => arquivo.caminhoRelativo.endsWith(".test.ts"));
596
+ const estrutura = descreverEstruturaModulo(modulo.nome);
597
+ const contexto = estrutura.contextoRelativo;
598
+ const contratoPath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.contract.ts`;
599
+ const dtoPath = `${contexto ? `${contexto}/` : ""}dto/${estrutura.nomeArquivo}.dto.ts`;
600
+ const servicePath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.service.ts`;
601
+ const controllerPath = `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.controller.ts`;
602
+ const caminhoImportDto = `./dto/${estrutura.nomeArquivo}.dto`;
603
+ const caminhoImportContrato = `./${estrutura.nomeArquivo}.contract`;
604
+ const caminhoImportService = `./${estrutura.nomeArquivo}.service`;
605
+ const caminhoContratoTeste = path.posix.join("test", `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.contract.test.ts`);
606
+ const caminhoControllerSpec = path.posix.join("test", `${contexto ? `${contexto}/` : ""}${estrutura.nomeArquivo}.controller.spec.ts`);
607
+ const relativoContratoDoTeste = path.posix.relative(path.posix.dirname(caminhoContratoTeste), path.posix.join("src", contratoPath).replace(/\.ts$/, ""));
608
+ const relativoServiceDoSpec = path.posix.relative(path.posix.dirname(caminhoControllerSpec), path.posix.join("src", servicePath).replace(/\.ts$/, ""));
609
+ const relativoControllerDoSpec = path.posix.relative(path.posix.dirname(caminhoControllerSpec), path.posix.join("src", controllerPath).replace(/\.ts$/, ""));
610
+ const arquivos = [
611
+ {
612
+ caminhoRelativo: path.posix.join("src", contratoPath),
613
+ conteudo: contrato?.conteudo ?? "// Nenhum contrato base gerado.\n",
614
+ },
615
+ {
616
+ caminhoRelativo: path.posix.join("src", dtoPath),
617
+ conteudo: gerarNestJsDtos(modulo, `../${path.posix.basename(contratoPath, ".ts")}`),
618
+ },
619
+ {
620
+ caminhoRelativo: path.posix.join("src", servicePath),
621
+ conteudo: gerarNestJsService(modulo, caminhoImportContrato),
622
+ },
623
+ {
624
+ caminhoRelativo: path.posix.join("src", controllerPath),
625
+ conteudo: gerarNestJsController(modulo, caminhoImportDto, caminhoImportService),
626
+ },
627
+ {
628
+ caminhoRelativo: caminhoContratoTeste,
629
+ conteudo: (testeContrato?.conteudo ?? "")
630
+ .replace(`./${estrutura.nomeBase}.ts`, relativoContratoDoTeste)
631
+ .replace(`./${estrutura.nomeArquivo}.ts`, relativoContratoDoTeste),
632
+ },
633
+ {
634
+ caminhoRelativo: caminhoControllerSpec,
635
+ conteudo: gerarNestJsSpec(modulo, relativoServiceDoSpec, relativoControllerDoSpec),
636
+ },
637
+ ];
638
+ return arquivos;
639
+ }
640
+ export function gerarTypeScript(modulo, opcoes = {}) {
641
+ if (opcoes.framework === "nestjs") {
642
+ return gerarTypeScriptNestJs(modulo);
643
+ }
644
+ return gerarTypeScriptBase(modulo);
645
+ }
646
+ //# sourceMappingURL=index.js.map