@semacode/cli 1.5.28 → 1.5.30

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 (125) hide show
  1. package/README.md +144 -144
  2. package/dist/bridge.d.ts +52 -0
  3. package/dist/bridge.js +318 -0
  4. package/dist/bridge.js.map +1 -0
  5. package/dist/comandos.d.ts +11 -0
  6. package/dist/comandos.js +146 -0
  7. package/dist/comandos.js.map +1 -0
  8. package/dist/contexto.d.ts +34 -0
  9. package/dist/contexto.js +197 -0
  10. package/dist/contexto.js.map +1 -0
  11. package/dist/drift.d.ts +1 -1
  12. package/dist/drift.js +32 -5
  13. package/dist/drift.js.map +1 -1
  14. package/dist/guard.d.ts +35 -0
  15. package/dist/guard.js +164 -0
  16. package/dist/guard.js.map +1 -0
  17. package/dist/index.js +391 -64
  18. package/dist/index.js.map +1 -1
  19. package/dist/lua-symbols.d.ts +0 -6
  20. package/dist/lua-symbols.js +11 -78
  21. package/dist/lua-symbols.js.map +1 -1
  22. package/dist/projeto.js +6 -0
  23. package/dist/projeto.js.map +1 -1
  24. package/dist/tipos.d.ts +1 -1
  25. package/exemplos/.prepack-generated +1 -0
  26. package/exemplos/author_obra_comum.sema +294 -294
  27. package/exemplos/author_tema_sensivel.sema +264 -264
  28. package/exemplos/profile_game.sema +114 -114
  29. package/exemplos/profile_legal.sema +105 -105
  30. package/exemplos/profile_ops.sema +110 -110
  31. package/exemplos/profile_research.sema +104 -104
  32. package/exemplos/profile_software.sema +123 -123
  33. package/exemplos/profile_workflow_n8n.sema +99 -99
  34. package/node_modules/@sema/gerador-css/package.json +14 -7
  35. package/node_modules/@sema/gerador-css/src/index.ts +605 -0
  36. package/node_modules/@sema/gerador-css/tsconfig.json +13 -0
  37. package/node_modules/@sema/gerador-css/tsconfig.tsbuildinfo +1 -0
  38. package/node_modules/@sema/gerador-dart/package.json +14 -7
  39. package/node_modules/@sema/gerador-dart/src/index.ts +52 -0
  40. package/node_modules/@sema/gerador-dart/tsconfig.json +13 -0
  41. package/node_modules/@sema/gerador-dart/tsconfig.tsbuildinfo +1 -0
  42. package/node_modules/@sema/gerador-html/package.json +14 -7
  43. package/node_modules/@sema/gerador-html/src/index.ts +185 -0
  44. package/node_modules/@sema/gerador-html/tsconfig.json +13 -0
  45. package/node_modules/@sema/gerador-html/tsconfig.tsbuildinfo +1 -0
  46. package/node_modules/@sema/gerador-javascript/package.json +14 -7
  47. package/node_modules/@sema/gerador-javascript/src/index.ts +461 -0
  48. package/node_modules/@sema/gerador-javascript/tsconfig.json +13 -0
  49. package/node_modules/@sema/gerador-javascript/tsconfig.tsbuildinfo +1 -0
  50. package/node_modules/@sema/gerador-lua/package.json +14 -7
  51. package/node_modules/@sema/gerador-lua/src/index.ts +359 -0
  52. package/node_modules/@sema/gerador-lua/tsconfig.json +13 -0
  53. package/node_modules/@sema/gerador-lua/tsconfig.tsbuildinfo +1 -0
  54. package/node_modules/@sema/gerador-python/package.json +14 -7
  55. package/node_modules/@sema/gerador-python/src/index.ts +850 -0
  56. package/node_modules/@sema/gerador-python/tsconfig.json +13 -0
  57. package/node_modules/@sema/gerador-python/tsconfig.tsbuildinfo +1 -0
  58. package/node_modules/@sema/gerador-typescript/package.json +14 -7
  59. package/node_modules/@sema/gerador-typescript/src/index.ts +876 -0
  60. package/node_modules/@sema/gerador-typescript/tsconfig.json +13 -0
  61. package/node_modules/@sema/gerador-typescript/tsconfig.tsbuildinfo +1 -0
  62. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +1 -1
  63. package/node_modules/@sema/nucleo/dist/index.d.ts +17 -0
  64. package/node_modules/@sema/nucleo/dist/index.js +28 -0
  65. package/node_modules/@sema/nucleo/dist/index.js.map +1 -1
  66. package/node_modules/@sema/nucleo/dist/ir/conversor.js +4 -0
  67. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
  68. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +3 -3
  69. package/node_modules/@sema/nucleo/dist/parser/parser.js +2 -0
  70. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
  71. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +2 -2
  72. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +3 -1
  73. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
  74. package/node_modules/@sema/nucleo/package.json +10 -7
  75. package/node_modules/@sema/nucleo/src/ast/tipos.ts +207 -0
  76. package/node_modules/@sema/nucleo/src/diagnosticos/index.ts +43 -0
  77. package/node_modules/@sema/nucleo/src/formatador/index.ts +530 -0
  78. package/node_modules/@sema/nucleo/src/index.ts +183 -0
  79. package/node_modules/@sema/nucleo/src/ir/conversor.ts +1037 -0
  80. package/node_modules/@sema/nucleo/src/ir/modelos.ts +403 -0
  81. package/node_modules/@sema/nucleo/src/lexer/lexer.ts +166 -0
  82. package/node_modules/@sema/nucleo/src/lexer/tokens.ts +79 -0
  83. package/node_modules/@sema/nucleo/src/parser/gramatica.ebnf +41 -0
  84. package/node_modules/@sema/nucleo/src/parser/parser.ts +936 -0
  85. package/node_modules/@sema/nucleo/src/persistencia/contratos.ts +379 -0
  86. package/node_modules/@sema/nucleo/src/semantico/analisador.ts +3126 -0
  87. package/node_modules/@sema/nucleo/src/semantico/estruturas.ts +665 -0
  88. package/node_modules/@sema/nucleo/src/semantico/seguranca.ts +362 -0
  89. package/node_modules/@sema/nucleo/src/util/arquivos.ts +28 -0
  90. package/node_modules/@sema/nucleo/tsconfig.json +9 -0
  91. package/node_modules/@sema/nucleo/tsconfig.tsbuildinfo +1 -0
  92. package/node_modules/@sema/padroes/package.json +10 -7
  93. package/node_modules/@sema/padroes/src/index.ts +382 -0
  94. package/node_modules/@sema/padroes/tsconfig.json +9 -0
  95. package/node_modules/@sema/padroes/tsconfig.tsbuildinfo +1 -0
  96. package/package.json +74 -74
  97. package/AGENTS.md +0 -280
  98. package/LICENSE +0 -22
  99. package/SEMA_BRIEF.curto.txt +0 -11
  100. package/SEMA_BRIEF.md +0 -112
  101. package/SEMA_BRIEF.micro.txt +0 -9
  102. package/SEMA_INDEX.json +0 -1534
  103. package/dist/php-symbols.d.ts +0 -24
  104. package/dist/php-symbols.js +0 -375
  105. package/dist/php-symbols.js.map +0 -1
  106. package/docs/AGENT_STARTER.md +0 -109
  107. package/docs/cli.md +0 -175
  108. package/docs/como-ensinar-a-sema-para-ia.md +0 -155
  109. package/docs/deploy.md +0 -93
  110. package/docs/documentacao.md +0 -88
  111. package/docs/env.md +0 -105
  112. package/docs/extensao-vscode.md +0 -53
  113. package/docs/fluxo-pratico-ia-sema.md +0 -187
  114. package/docs/instalacao-e-primeiro-uso.md +0 -134
  115. package/docs/integracao-com-ia.md +0 -110
  116. package/docs/mcp.md +0 -292
  117. package/docs/pagamento-ponta-a-ponta.md +0 -171
  118. package/docs/persistencia-vendor-first.md +0 -151
  119. package/docs/prompt-base-ia-sema.md +0 -111
  120. package/docs/repositories.md +0 -54
  121. package/docs/rollback.md +0 -49
  122. package/docs/seguranca.md +0 -126
  123. package/docs/sintaxe.md +0 -218
  124. package/llms-full.txt +0 -34
  125. package/llms.txt +0 -17
@@ -0,0 +1,43 @@
1
+ export type SeveridadeDiagnostico = "erro" | "aviso" | "informacao";
2
+
3
+ export interface PosicaoFonte {
4
+ indice: number;
5
+ linha: number;
6
+ coluna: number;
7
+ }
8
+
9
+ export interface IntervaloFonte {
10
+ inicio: PosicaoFonte;
11
+ fim: PosicaoFonte;
12
+ arquivo?: string;
13
+ }
14
+
15
+ export interface Diagnostico {
16
+ codigo: string;
17
+ mensagem: string;
18
+ severidade: SeveridadeDiagnostico;
19
+ intervalo?: IntervaloFonte;
20
+ dica?: string;
21
+ contexto?: string;
22
+ }
23
+
24
+ export function formatarDiagnostico(diagnostico: Diagnostico): string {
25
+ const local = diagnostico.intervalo
26
+ ? `${diagnostico.intervalo.arquivo ?? "arquivo"}:${diagnostico.intervalo.inicio.linha}:${diagnostico.intervalo.inicio.coluna}`
27
+ : "local desconhecido";
28
+ const dica = diagnostico.dica ? `\nDica: ${diagnostico.dica}` : "";
29
+ const contexto = diagnostico.contexto ? `\nContexto: ${diagnostico.contexto}` : "";
30
+ return `[${diagnostico.severidade.toUpperCase()} ${diagnostico.codigo}] ${diagnostico.mensagem} (${local})${dica}${contexto}`;
31
+ }
32
+
33
+ export function criarDiagnostico(
34
+ codigo: string,
35
+ mensagem: string,
36
+ severidade: SeveridadeDiagnostico,
37
+ intervalo?: IntervaloFonte,
38
+ dica?: string,
39
+ contexto?: string,
40
+ ): Diagnostico {
41
+ return { codigo, mensagem, severidade, intervalo, dica, contexto };
42
+ }
43
+
@@ -0,0 +1,530 @@
1
+ import type {
2
+ BlocoAst,
3
+ BlocoCasoTesteAst,
4
+ BlocoGenericoAst,
5
+ CampoAst,
6
+ EntityAst,
7
+ EnumAst,
8
+ FlowAst,
9
+ ModuloAst,
10
+ RouteAst,
11
+ StateAst,
12
+ TaskAst,
13
+ TypeAst,
14
+ UseAst,
15
+ } from "../ast/tipos.js";
16
+ import type { Diagnostico } from "../diagnosticos/index.js";
17
+ import { parsear } from "../parser/parser.js";
18
+ import { tokenizar } from "../lexer/lexer.js";
19
+
20
+ const ORDEM_BLOCOS_MODULO = new Map<string, number>([
21
+ ["docs", 0],
22
+ ["comments", 1],
23
+ ["use", 2],
24
+ ["vinculos", 3],
25
+ ["database", 4],
26
+ ["type", 5],
27
+ ["entity", 6],
28
+ ["enum", 7],
29
+ ["state", 8],
30
+ ["task", 9],
31
+ ["flow", 10],
32
+ ["route", 11],
33
+ ["worker", 12],
34
+ ["evento", 13],
35
+ ["fila", 14],
36
+ ["cron", 15],
37
+ ["webhook", 16],
38
+ ["cache", 17],
39
+ ["storage", 18],
40
+ ["policy", 19],
41
+ ["tests", 20],
42
+ ["desconhecido", 21],
43
+ ]);
44
+
45
+ const ORDEM_SUBBLOCOS_TASK = new Map<string, number>([
46
+ ["docs", 0],
47
+ ["comments", 1],
48
+ ["input", 2],
49
+ ["output", 3],
50
+ ["rules", 4],
51
+ ["effects", 5],
52
+ ["auth", 6],
53
+ ["authz", 7],
54
+ ["dados", 8],
55
+ ["audit", 9],
56
+ ["segredos", 10],
57
+ ["forbidden", 11],
58
+ ["impl", 12],
59
+ ["vinculos", 13],
60
+ ["execucao", 14],
61
+ ["state", 15],
62
+ ["guarantees", 16],
63
+ ["error", 17],
64
+ ["tests", 18],
65
+ ["desconhecido", 19],
66
+ ]);
67
+
68
+ const ORDEM_SUBBLOCOS_ROUTE = new Map<string, number>([
69
+ ["input", 0],
70
+ ["output", 1],
71
+ ["effects", 2],
72
+ ["auth", 3],
73
+ ["authz", 4],
74
+ ["dados", 5],
75
+ ["audit", 6],
76
+ ["segredos", 7],
77
+ ["forbidden", 8],
78
+ ["vinculos", 9],
79
+ ["error", 10],
80
+ ["docs", 11],
81
+ ["comments", 12],
82
+ ["desconhecido", 13],
83
+ ]);
84
+
85
+ const ORDEM_SUBBLOCOS_FLOW = new Map<string, number>([
86
+ ["effects", 0],
87
+ ["vinculos", 1],
88
+ ["docs", 2],
89
+ ["comments", 3],
90
+ ["desconhecido", 4],
91
+ ]);
92
+
93
+ const ORDEM_SUBBLOCOS_SUPERFICIE = new Map<string, number>([
94
+ ["input", 0],
95
+ ["output", 1],
96
+ ["effects", 2],
97
+ ["auth", 3],
98
+ ["authz", 4],
99
+ ["dados", 5],
100
+ ["audit", 6],
101
+ ["segredos", 7],
102
+ ["forbidden", 8],
103
+ ["impl", 9],
104
+ ["vinculos", 10],
105
+ ["execucao", 11],
106
+ ["error", 12],
107
+ ["docs", 13],
108
+ ["comments", 14],
109
+ ["desconhecido", 15],
110
+ ]);
111
+
112
+ const ORDEM_SUBBLOCOS_STATE = new Map<string, number>([
113
+ ["fields", 0],
114
+ ["invariants", 1],
115
+ ["transitions", 2],
116
+ ["docs", 3],
117
+ ["comments", 4],
118
+ ["desconhecido", 5],
119
+ ]);
120
+
121
+ const ORDEM_SUBBLOCOS_TESTE = new Map<string, number>([
122
+ ["given", 0],
123
+ ["when", 1],
124
+ ["expect", 2],
125
+ ["error", 3],
126
+ ["docs", 4],
127
+ ["comments", 5],
128
+ ["desconhecido", 6],
129
+ ]);
130
+
131
+ const ORDEM_CAMPOS_POR_BLOCO = new Map<string, Map<string, number>>([
132
+ ["vinculos", new Map<string, number>([
133
+ ["arquivo", 0],
134
+ ["simbolo", 1],
135
+ ["rota", 2],
136
+ ["superficie", 3],
137
+ ["recurso", 4],
138
+ ["tabela", 5],
139
+ ["fila", 6],
140
+ ["worker", 7],
141
+ ["evento", 8],
142
+ ["cron", 9],
143
+ ["webhook", 10],
144
+ ["cache", 11],
145
+ ["storage", 12],
146
+ ["policy", 13],
147
+ ["teste", 14],
148
+ ])],
149
+ ["execucao", new Map<string, number>([
150
+ ["idempotencia", 0],
151
+ ["timeout", 1],
152
+ ["retry", 2],
153
+ ["compensacao", 3],
154
+ ["criticidade_operacional", 4],
155
+ ])],
156
+ ["auth", new Map<string, number>([
157
+ ["modo", 0],
158
+ ["estrategia", 1],
159
+ ["principal", 2],
160
+ ["origem", 3],
161
+ ])],
162
+ ["authz", new Map<string, number>([
163
+ ["papeis", 0],
164
+ ["papel", 1],
165
+ ["escopos", 2],
166
+ ["escopo", 3],
167
+ ["politica", 4],
168
+ ["tenant", 5],
169
+ ])],
170
+ ["dados", new Map<string, number>([
171
+ ["classificacao_padrao", 0],
172
+ ["redacao_log", 1],
173
+ ["retencao", 2],
174
+ ])],
175
+ ["audit", new Map<string, number>([
176
+ ["evento", 0],
177
+ ["ator", 1],
178
+ ["correlacao", 2],
179
+ ["retencao", 3],
180
+ ["motivo", 4],
181
+ ])],
182
+ ["database", new Map<string, number>([
183
+ ["engine", 0],
184
+ ["schema", 1],
185
+ ["database", 2],
186
+ ["consistency", 3],
187
+ ["durability", 4],
188
+ ["transaction_model", 5],
189
+ ["query_model", 6],
190
+ ["portavel", 7],
191
+ ["adapter", 8],
192
+ ])],
193
+ ]);
194
+
195
+ export interface ResultadoFormatacao {
196
+ modulo?: ModuloAst;
197
+ codigoFormatado?: string;
198
+ diagnosticos: Diagnostico[];
199
+ alterado: boolean;
200
+ }
201
+
202
+ function indentacao(nivel: number): string {
203
+ return " ".repeat(nivel);
204
+ }
205
+
206
+ function ordenarPorMapa<T>(itens: T[], extrairChave: (item: T) => string, ordem: Map<string, number>): T[] {
207
+ return [...itens].sort((a, b) => {
208
+ const ordemA = ordem.get(extrairChave(a)) ?? Number.MAX_SAFE_INTEGER;
209
+ const ordemB = ordem.get(extrairChave(b)) ?? Number.MAX_SAFE_INTEGER;
210
+ if (ordemA !== ordemB) {
211
+ return ordemA - ordemB;
212
+ }
213
+ return extrairChave(a).localeCompare(extrairChave(b), "pt-BR");
214
+ });
215
+ }
216
+
217
+ function normalizarEspacos(texto: string): string {
218
+ const marcadorSeta = "__SEMA_SETA__";
219
+ const marcadorMaiorIgual = "__SEMA_MAIOR_IGUAL__";
220
+ const marcadorMenorIgual = "__SEMA_MENOR_IGUAL__";
221
+ const marcadorIgual = "__SEMA_IGUAL__";
222
+ const marcadorDiferente = "__SEMA_DIFERENTE__";
223
+ return texto
224
+ .trim()
225
+ .replace(/\s*->\s*/g, ` ${marcadorSeta} `)
226
+ .replace(/\s*-\s*>\s*/g, ` ${marcadorSeta} `)
227
+ .replace(/\s+/g, " ")
228
+ .replace(/\s*,\s*/g, ", ")
229
+ .replace(/\(\s+/g, "(")
230
+ .replace(/\s+\)/g, ")")
231
+ .replace(/\[\s+/g, "[")
232
+ .replace(/\s+\]/g, "]")
233
+ .replace(/\s*>=\s*/g, ` ${marcadorMaiorIgual} `)
234
+ .replace(/\s*<=\s*/g, ` ${marcadorMenorIgual} `)
235
+ .replace(/\s*==\s*/g, ` ${marcadorIgual} `)
236
+ .replace(/\s*!=\s*/g, ` ${marcadorDiferente} `)
237
+ .replace(/\s*>\s*/g, " > ")
238
+ .replace(/\s*<\s*/g, " < ")
239
+ .replace(new RegExp(`\\s*${marcadorMaiorIgual}\\s*`, "g"), " >= ")
240
+ .replace(new RegExp(`\\s*${marcadorMenorIgual}\\s*`, "g"), " <= ")
241
+ .replace(new RegExp(`\\s*${marcadorIgual}\\s*`, "g"), " == ")
242
+ .replace(new RegExp(`\\s*${marcadorDiferente}\\s*`, "g"), " != ")
243
+ .replace(new RegExp(`\\s*${marcadorSeta}\\s*`, "g"), " -> ");
244
+ }
245
+
246
+ function normalizarCaminho(texto: string): string {
247
+ return texto
248
+ .trim()
249
+ .replace(/\s*\/\s*/g, "/")
250
+ .replace(/\s+/g, "");
251
+ }
252
+
253
+ function eLiteralEscalar(texto: string): boolean {
254
+ const normalizado = texto.trim();
255
+ return /^-?\d+(?:\.\d+)?$/.test(normalizado) || ["verdadeiro", "falso", "nulo"].includes(normalizado);
256
+ }
257
+
258
+ function deveColocarAspas(contexto: string, campo: CampoAst, combinado: string): boolean {
259
+ if (campo.nome === "metodo") {
260
+ return false;
261
+ }
262
+ if (campo.nome === "caminho") {
263
+ return /[{}]/.test(combinado);
264
+ }
265
+ if (contexto === "vinculos" && ["arquivo", "webhook"].includes(campo.nome)) {
266
+ return true;
267
+ }
268
+ if (["timeout", "retry", "compensacao", "retencao", "rotacao"].includes(campo.nome)) {
269
+ return true;
270
+ }
271
+ if (contexto === "docs" || contexto === "comments") {
272
+ return true;
273
+ }
274
+ if (contexto === "error") {
275
+ return !eLiteralEscalar(combinado);
276
+ }
277
+ if (contexto === "given" || contexto === "when" || contexto === "expect") {
278
+ return !eLiteralEscalar(combinado);
279
+ }
280
+ return false;
281
+ }
282
+
283
+ function normalizarValorCampo(campo: CampoAst): string {
284
+ return [campo.valor, ...campo.modificadores]
285
+ .filter(Boolean)
286
+ .join(" ")
287
+ .replace(/\s+/g, " ")
288
+ .trim();
289
+ }
290
+
291
+ function ordenarCampos(bloco: BlocoGenericoAst): CampoAst[] {
292
+ const ordem = ORDEM_CAMPOS_POR_BLOCO.get(bloco.palavraChave);
293
+ if (!ordem) {
294
+ return bloco.campos;
295
+ }
296
+ return ordenarPorMapa(bloco.campos, (campo) => campo.nome, ordem);
297
+ }
298
+
299
+ function renderizarCampo(campo: CampoAst, nivel: number, contexto: string): string {
300
+ let combinado = normalizarValorCampo(campo);
301
+
302
+ if (campo.nome === "caminho") {
303
+ combinado = normalizarCaminho(combinado);
304
+ }
305
+
306
+ if (deveColocarAspas(contexto, campo, combinado)) {
307
+ combinado = JSON.stringify(combinado);
308
+ }
309
+
310
+ return `${indentacao(nivel)}${campo.nome}: ${combinado}`;
311
+ }
312
+
313
+ function renderizarLinha(linha: string, nivel: number): string {
314
+ return `${indentacao(nivel)}${normalizarEspacos(linha)}`;
315
+ }
316
+
317
+ function renderizarCasoTeste(caso: BlocoCasoTesteAst, nivel: number): string {
318
+ const partes: string[] = [];
319
+ if (caso.given) {
320
+ partes.push(renderizarBlocoGenerico(caso.given, nivel + 1));
321
+ }
322
+ if (caso.when) {
323
+ partes.push(renderizarBlocoGenerico(caso.when, nivel + 1));
324
+ }
325
+ if (caso.expect) {
326
+ partes.push(renderizarBlocoGenerico(caso.expect, nivel + 1));
327
+ }
328
+ if (caso.error) {
329
+ partes.push(renderizarBlocoGenerico(caso.error, nivel + 1));
330
+ }
331
+ if (caso.docs) {
332
+ partes.push(renderizarBlocoGenerico(caso.docs, nivel + 1));
333
+ }
334
+ if (caso.comments) {
335
+ partes.push(renderizarBlocoGenerico(caso.comments, nivel + 1));
336
+ }
337
+
338
+ return `${indentacao(nivel)}caso ${JSON.stringify(caso.nome)} {\n${partes.join("\n\n")}\n${indentacao(nivel)}}`;
339
+ }
340
+
341
+ function renderizarBlocoAst(bloco: BlocoAst, nivel: number): string {
342
+ switch (bloco.tipo) {
343
+ case "caso_teste":
344
+ return renderizarCasoTeste(bloco, nivel);
345
+ case "bloco_generico":
346
+ return renderizarBlocoGenerico(bloco, nivel);
347
+ case "use":
348
+ return `${indentacao(nivel)}use ${bloco.origem === "sema" ? "" : `${bloco.origem} `}${bloco.caminho}`.trimEnd();
349
+ case "enum":
350
+ return renderizarEnum(bloco, nivel);
351
+ case "type":
352
+ return renderizarTipo(bloco, nivel);
353
+ case "entity":
354
+ return renderizarEntity(bloco, nivel);
355
+ case "task":
356
+ return renderizarTask(bloco, nivel);
357
+ case "flow":
358
+ return renderizarFlow(bloco, nivel);
359
+ case "route":
360
+ return renderizarRoute(bloco, nivel);
361
+ case "state":
362
+ return renderizarState(bloco, nivel);
363
+ }
364
+ }
365
+
366
+ function ordenarSubblocos(bloco: BlocoGenericoAst): BlocoAst[] {
367
+ if (bloco.palavraChave === "task") {
368
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_TASK);
369
+ }
370
+ if (bloco.palavraChave === "route") {
371
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_ROUTE);
372
+ }
373
+ if (bloco.palavraChave === "flow") {
374
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_FLOW);
375
+ }
376
+ if (["worker", "evento", "fila", "cron", "webhook", "cache", "storage", "policy"].includes(bloco.palavraChave)) {
377
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_SUPERFICIE);
378
+ }
379
+ if (bloco.palavraChave === "state") {
380
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_STATE);
381
+ }
382
+ if (bloco.palavraChave === "tests") {
383
+ return ordenarPorMapa(bloco.blocos, (item) => item.tipo === "caso_teste" ? "case" : item.tipo === "bloco_generico" ? item.palavraChave : item.tipo, ORDEM_SUBBLOCOS_TESTE);
384
+ }
385
+ return bloco.blocos;
386
+ }
387
+
388
+ function renderizarBlocoGenerico(bloco: BlocoGenericoAst, nivel: number): string {
389
+ const identificadorBloco = bloco.palavraChave === "desconhecido" && bloco.nome
390
+ ? bloco.nome
391
+ : `${bloco.palavraChave}${bloco.nome ? ` ${bloco.nome}` : ""}`;
392
+ const cabecalho = `${indentacao(nivel)}${identificadorBloco} {`;
393
+ const linhasCampos = ordenarCampos(bloco).map((campo) => renderizarCampo(campo, nivel + 1, bloco.palavraChave));
394
+ const linhasDeclarativas = bloco.linhas.map((linha) => renderizarLinha(linha.conteudo, nivel + 1));
395
+ const blocosInternos = ordenarSubblocos(bloco).map((subbloco) => renderizarBlocoAst(subbloco, nivel + 1));
396
+ const corpo = [...linhasCampos, ...linhasDeclarativas, ...blocosInternos];
397
+ if (corpo.length === 0) {
398
+ return `${cabecalho}\n${indentacao(nivel)}}`;
399
+ }
400
+ return `${cabecalho}\n${corpo.join("\n")}\n${indentacao(nivel)}}`;
401
+ }
402
+
403
+ function renderizarEnum(enumeracao: EnumAst, nivel: number): string {
404
+ const corpo = enumeracao.valores.map((valor, indice) => `${indentacao(nivel + 1)}${valor}${indice < enumeracao.valores.length - 1 ? "," : ""}`);
405
+ return `${indentacao(nivel)}enum ${enumeracao.nome} {\n${corpo.join("\n")}\n${indentacao(nivel)}}`;
406
+ }
407
+
408
+ function renderizarTipo(type: TypeAst, nivel: number): string {
409
+ return `${indentacao(nivel)}type ${type.nome} {\n${renderizarCorpoSimples(type.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
410
+ }
411
+
412
+ function renderizarEntity(entity: EntityAst, nivel: number): string {
413
+ return `${indentacao(nivel)}entity ${entity.nome} {\n${renderizarCorpoSimples(entity.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
414
+ }
415
+
416
+ function renderizarTask(task: TaskAst, nivel: number): string {
417
+ return `${indentacao(nivel)}task ${task.nome} {\n${renderizarCorpoSimples(task.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
418
+ }
419
+
420
+ function renderizarFlow(flow: FlowAst, nivel: number): string {
421
+ return `${indentacao(nivel)}flow ${flow.nome} {\n${renderizarCorpoSimples(flow.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
422
+ }
423
+
424
+ function renderizarRoute(route: RouteAst, nivel: number): string {
425
+ return `${indentacao(nivel)}route ${route.nome} {\n${renderizarCorpoSimples(route.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
426
+ }
427
+
428
+ function renderizarState(state: StateAst, nivel: number): string {
429
+ return `${indentacao(nivel)}state${state.nome ? ` ${state.nome}` : ""} {\n${renderizarCorpoSimples(state.corpo, nivel + 1)}\n${indentacao(nivel)}}`;
430
+ }
431
+
432
+ function renderizarCorpoSimples(bloco: BlocoGenericoAst, nivel: number): string {
433
+ const conteudo = ordenarSubblocos(bloco).map((subbloco) => renderizarBlocoAst(subbloco, nivel));
434
+ const campos = ordenarCampos(bloco).map((campo) => renderizarCampo(campo, nivel, bloco.palavraChave));
435
+ const linhas = bloco.linhas.map((linha) => renderizarLinha(linha.conteudo, nivel));
436
+ const corpo = [...campos, ...linhas, ...conteudo];
437
+ return corpo.join("\n");
438
+ }
439
+
440
+ function renderizarModulo(modulo: ModuloAst): string {
441
+ const blocos: Array<{ chave: string; conteudo: string }> = [];
442
+
443
+ if (modulo.docs) {
444
+ blocos.push({ chave: "docs", conteudo: renderizarBlocoGenerico(modulo.docs, 1) });
445
+ }
446
+ if (modulo.comments) {
447
+ blocos.push({ chave: "comments", conteudo: renderizarBlocoGenerico(modulo.comments, 1) });
448
+ }
449
+ for (const use of modulo.uses) {
450
+ blocos.push({ chave: "use", conteudo: renderizarBlocoAst(use, 1) });
451
+ }
452
+ if (modulo.vinculos) {
453
+ blocos.push({ chave: "vinculos", conteudo: renderizarBlocoGenerico(modulo.vinculos, 1) });
454
+ }
455
+ for (const database of modulo.databases) {
456
+ blocos.push({ chave: "database", conteudo: renderizarBlocoGenerico(database, 1) });
457
+ }
458
+ for (const type of modulo.types) {
459
+ blocos.push({ chave: "type", conteudo: renderizarBlocoAst(type, 1) });
460
+ }
461
+ for (const entity of modulo.entities) {
462
+ blocos.push({ chave: "entity", conteudo: renderizarBlocoAst(entity, 1) });
463
+ }
464
+ for (const enumeracao of modulo.enums) {
465
+ blocos.push({ chave: "enum", conteudo: renderizarBlocoAst(enumeracao, 1) });
466
+ }
467
+ for (const state of modulo.states) {
468
+ blocos.push({ chave: "state", conteudo: renderizarBlocoAst(state, 1) });
469
+ }
470
+ for (const task of modulo.tasks) {
471
+ blocos.push({ chave: "task", conteudo: renderizarBlocoAst(task, 1) });
472
+ }
473
+ for (const flow of modulo.flows) {
474
+ blocos.push({ chave: "flow", conteudo: renderizarBlocoAst(flow, 1) });
475
+ }
476
+ for (const route of modulo.routes) {
477
+ blocos.push({ chave: "route", conteudo: renderizarBlocoAst(route, 1) });
478
+ }
479
+ for (const worker of modulo.workers) {
480
+ blocos.push({ chave: "worker", conteudo: renderizarBlocoGenerico(worker, 1) });
481
+ }
482
+ for (const evento of modulo.eventos) {
483
+ blocos.push({ chave: "evento", conteudo: renderizarBlocoGenerico(evento, 1) });
484
+ }
485
+ for (const fila of modulo.filas) {
486
+ blocos.push({ chave: "fila", conteudo: renderizarBlocoGenerico(fila, 1) });
487
+ }
488
+ for (const cron of modulo.crons) {
489
+ blocos.push({ chave: "cron", conteudo: renderizarBlocoGenerico(cron, 1) });
490
+ }
491
+ for (const webhook of modulo.webhooks) {
492
+ blocos.push({ chave: "webhook", conteudo: renderizarBlocoGenerico(webhook, 1) });
493
+ }
494
+ for (const cache of modulo.caches) {
495
+ blocos.push({ chave: "cache", conteudo: renderizarBlocoGenerico(cache, 1) });
496
+ }
497
+ for (const storage of modulo.storages) {
498
+ blocos.push({ chave: "storage", conteudo: renderizarBlocoGenerico(storage, 1) });
499
+ }
500
+ for (const policy of modulo.policies) {
501
+ blocos.push({ chave: "policy", conteudo: renderizarBlocoGenerico(policy, 1) });
502
+ }
503
+ if (modulo.tests) {
504
+ blocos.push({ chave: "tests", conteudo: renderizarBlocoGenerico(modulo.tests, 1) });
505
+ }
506
+ for (const extra of modulo.extras) {
507
+ blocos.push({ chave: "desconhecido", conteudo: renderizarBlocoGenerico(extra, 1) });
508
+ }
509
+
510
+ const ordenados = ordenarPorMapa(blocos, (item) => item.chave, ORDEM_BLOCOS_MODULO);
511
+ return `module ${modulo.nome} {\n${ordenados.map((item) => item.conteudo).join("\n\n")}\n}\n`;
512
+ }
513
+
514
+ export function formatarCodigo(codigo: string, arquivo?: string): ResultadoFormatacao {
515
+ const resultadoLexer = tokenizar(codigo, arquivo);
516
+ const resultadoParser = parsear(resultadoLexer.tokens);
517
+ const diagnosticos = [...resultadoLexer.diagnosticos, ...resultadoParser.diagnosticos];
518
+
519
+ if (!resultadoParser.modulo) {
520
+ return { diagnosticos, alterado: false };
521
+ }
522
+
523
+ const codigoFormatado = renderizarModulo(resultadoParser.modulo);
524
+ return {
525
+ modulo: resultadoParser.modulo,
526
+ codigoFormatado,
527
+ diagnosticos,
528
+ alterado: codigoFormatado !== codigo,
529
+ };
530
+ }