@semacode/cli 3.0.0 → 3.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (46) hide show
  1. package/dist/agentEntryPoints.js +78 -64
  2. package/dist/cliGrammar.js +4 -4
  3. package/dist/cliHelpTexto.js +6 -6
  4. package/dist/docs.part01.d.ts +4 -1
  5. package/dist/docs.part01.js +8 -0
  6. package/dist/docs.part02.js +9 -1
  7. package/dist/drift.part01.d.ts +7 -1
  8. package/dist/drift.part04.d.ts +14 -2
  9. package/dist/drift.part04.js +35 -2
  10. package/dist/drift.part09.d.ts +2 -2
  11. package/dist/drift.part09.js +10 -3
  12. package/dist/drift.part11.js +24 -3
  13. package/dist/drift.part14.js +2 -0
  14. package/dist/exemplosOficiais.d.ts +2 -1
  15. package/dist/exemplosOficiais.js +9 -3
  16. package/dist/geracaoCore.d.ts +1 -0
  17. package/dist/geracaoCore.js +2 -0
  18. package/dist/importador.part01.d.ts +1 -1
  19. package/dist/importador.part06.d.ts +2 -0
  20. package/dist/importador.part06.js +87 -1
  21. package/dist/importador.part09.js +7 -1
  22. package/dist/index.part04.js +13 -6
  23. package/dist/index.part07.d.ts +8 -2
  24. package/dist/index.part07.js +146 -4
  25. package/dist/index.part08.js +3 -3
  26. package/dist/initCommand.d.ts +1 -0
  27. package/dist/initCommand.js +15 -3
  28. package/dist/initTemplatesBase.js +78 -78
  29. package/dist/projetoConfig.js +2 -0
  30. package/dist/projetoLegado.js +18 -0
  31. package/dist/tipos.d.ts +1 -1
  32. package/dist/typescript-http-modelos.d.ts +1 -1
  33. package/dist/typescript-http-rotas.d.ts +1 -0
  34. package/dist/typescript-http-rotas.js +93 -0
  35. package/dist/typescript-http.d.ts +1 -1
  36. package/dist/typescript-http.js +1 -1
  37. package/dist/verificacaoCache.d.ts +25 -0
  38. package/dist/verificacaoCache.js +80 -0
  39. package/docs/syntax.md +14 -0
  40. package/exemplos/express_crud.sema +139 -0
  41. package/exemplos/fastify_crud.sema +146 -0
  42. package/node_modules/@sema/nucleo/dist/ir/conversor.part01.js +37 -38
  43. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +1 -0
  44. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.d.ts +7 -0
  45. package/node_modules/@sema/nucleo/dist/semantico/analisador.part01.js +33 -10
  46. package/package.json +1 -1
@@ -0,0 +1,139 @@
1
+ module exemplos.express.crud {
2
+ entity Monitor {
3
+ fields {
4
+ id: Id
5
+ nome: Texto
6
+ url: Texto
7
+ ativo: Booleano
8
+ }
9
+ }
10
+
11
+ task criar_monitor {
12
+ input {
13
+ nome: Texto required
14
+ url: Texto required
15
+ }
16
+ output {
17
+ monitor: Monitor
18
+ }
19
+ rules {
20
+ nome deve_ser preenchido
21
+ url deve_ser preenchido
22
+ }
23
+ effects {
24
+ persistencia Monitor
25
+ auditoria monitor_criado
26
+ }
27
+ guarantees {
28
+ monitor existe
29
+ }
30
+ tests {
31
+ caso "cria monitor" {
32
+ given {
33
+ nome: "API Pagamentos"
34
+ url: "https://api.exemplo.dev/status"
35
+ }
36
+
37
+ expect {
38
+ sucesso: verdadeiro
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ task listar_monitores {
45
+ input {
46
+ ativo: Booleano
47
+ }
48
+ output {
49
+ monitores: Lista
50
+ }
51
+ effects {
52
+ consulta Monitor
53
+ }
54
+ guarantees {
55
+ monitores existe
56
+ }
57
+ tests {
58
+ caso "lista monitores" {
59
+ given {
60
+ ativo: verdadeiro
61
+ }
62
+
63
+ expect {
64
+ sucesso: verdadeiro
65
+ }
66
+ }
67
+ }
68
+ }
69
+
70
+ task remover_monitor {
71
+ input {
72
+ id: Id required
73
+ }
74
+ output {
75
+ removido: Booleano
76
+ }
77
+ rules {
78
+ id deve_ser valido
79
+ }
80
+ effects {
81
+ persistencia Monitor
82
+ auditoria monitor_removido
83
+ }
84
+ guarantees {
85
+ removido == verdadeiro
86
+ }
87
+ tests {
88
+ caso "remove monitor por id" {
89
+ given {
90
+ id: "mon_1"
91
+ }
92
+
93
+ expect {
94
+ sucesso: verdadeiro
95
+ }
96
+ }
97
+ }
98
+ }
99
+
100
+ route monitores_criar {
101
+ metodo: POST
102
+ caminho: /monitores
103
+ task: criar_monitor
104
+ finalidade: cadastro_monitor
105
+ input {
106
+ nome: Texto
107
+ url: Texto
108
+ }
109
+ output {
110
+ monitor: Monitor
111
+ }
112
+ }
113
+
114
+ route monitores_listar {
115
+ metodo: GET
116
+ caminho: /monitores
117
+ task: listar_monitores
118
+ finalidade: consulta_monitores
119
+ input {
120
+ ativo: Booleano
121
+ }
122
+ output {
123
+ monitores: Lista
124
+ }
125
+ }
126
+
127
+ route monitores_remover {
128
+ metodo: DELETE
129
+ caminho: "/monitores/{id}"
130
+ task: remover_monitor
131
+ finalidade: exclusao_monitor
132
+ input {
133
+ id: Id
134
+ }
135
+ output {
136
+ removido: Booleano
137
+ }
138
+ }
139
+ }
@@ -0,0 +1,146 @@
1
+ module exemplos.fastify.crud {
2
+ entity Pedido {
3
+ fields {
4
+ id: Id
5
+ cliente: Texto
6
+ total: Decimal
7
+ status: Texto
8
+ }
9
+ }
10
+
11
+ task criar_pedido {
12
+ input {
13
+ cliente: Texto required
14
+ total: Decimal required
15
+ }
16
+ output {
17
+ pedido: Pedido
18
+ }
19
+ rules {
20
+ cliente deve_ser preenchido
21
+ total deve_ser positivo
22
+ }
23
+ effects {
24
+ persistencia Pedido
25
+ auditoria pedido_criado
26
+ }
27
+ guarantees {
28
+ pedido existe
29
+ }
30
+ tests {
31
+ caso "cria pedido" {
32
+ given {
33
+ cliente: "Ana"
34
+ total: 149.9
35
+ }
36
+
37
+ expect {
38
+ sucesso: verdadeiro
39
+ }
40
+ }
41
+ }
42
+ }
43
+
44
+ task obter_pedido {
45
+ input {
46
+ id: Id required
47
+ }
48
+ output {
49
+ pedido: Pedido
50
+ }
51
+ rules {
52
+ id deve_ser valido
53
+ }
54
+ effects {
55
+ consulta Pedido
56
+ }
57
+ guarantees {
58
+ pedido existe
59
+ }
60
+ tests {
61
+ caso "obtem pedido por id" {
62
+ given {
63
+ id: "ped_1"
64
+ }
65
+
66
+ expect {
67
+ sucesso: verdadeiro
68
+ }
69
+ }
70
+ }
71
+ }
72
+
73
+ task atualizar_pedido {
74
+ input {
75
+ id: Id required
76
+ status: Texto required
77
+ }
78
+ output {
79
+ pedido: Pedido
80
+ }
81
+ rules {
82
+ id deve_ser valido
83
+ status deve_ser preenchido
84
+ }
85
+ effects {
86
+ persistencia Pedido
87
+ auditoria pedido_atualizado
88
+ }
89
+ guarantees {
90
+ pedido existe
91
+ }
92
+ tests {
93
+ caso "atualiza status do pedido" {
94
+ given {
95
+ id: "ped_1"
96
+ status: "pago"
97
+ }
98
+
99
+ expect {
100
+ sucesso: verdadeiro
101
+ }
102
+ }
103
+ }
104
+ }
105
+
106
+ route pedidos_criar {
107
+ metodo: POST
108
+ caminho: /pedidos
109
+ task: criar_pedido
110
+ finalidade: cadastro_pedido
111
+ input {
112
+ cliente: Texto
113
+ total: Decimal
114
+ }
115
+ output {
116
+ pedido: Pedido
117
+ }
118
+ }
119
+
120
+ route pedidos_obter {
121
+ metodo: GET
122
+ caminho: "/pedidos/{id}"
123
+ task: obter_pedido
124
+ finalidade: consulta_pedido
125
+ input {
126
+ id: Id
127
+ }
128
+ output {
129
+ pedido: Pedido
130
+ }
131
+ }
132
+
133
+ route pedidos_atualizar {
134
+ metodo: PATCH
135
+ caminho: "/pedidos/{id}"
136
+ task: atualizar_pedido
137
+ finalidade: alteracao_pedido
138
+ input {
139
+ id: Id
140
+ status: Texto
141
+ }
142
+ output {
143
+ pedido: Pedido
144
+ }
145
+ }
146
+ }
@@ -242,53 +242,52 @@ export function converterDatabase(database) {
242
242
  .filter((item) => Boolean(item)),
243
243
  };
244
244
  }
245
+ const ORIGENS_INTEROP_IMPLEMENTACAO = {
246
+ ts: "ts",
247
+ typescript: "ts",
248
+ js: "js",
249
+ javascript: "js",
250
+ py: "py",
251
+ python: "py",
252
+ dart: "dart",
253
+ lua: "lua",
254
+ cs: "cs",
255
+ csharp: "cs",
256
+ dotnet: "cs",
257
+ java: "java",
258
+ go: "go",
259
+ golang: "go",
260
+ rust: "rust",
261
+ rs: "rust",
262
+ cpp: "cpp",
263
+ cxx: "cpp",
264
+ cc: "cpp",
265
+ "c++": "cpp",
266
+ php: "php",
267
+ };
268
+ const PAPEIS_IMPLEMENTACAO_IR = new Set(["rota", "servico", "persistencia", "repositorio"]);
245
269
  export function converterImplementacoes(bloco) {
246
270
  const implementacoes = [];
247
271
  for (const campo of bloco?.campos ?? []) {
248
- const origem = campo.nome.toLowerCase();
249
- if (origem === "ts" || origem === "typescript") {
250
- implementacoes.push({ origem: "ts", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
272
+ const segmentos = campo.nome.toLowerCase().split("_");
273
+ if (segmentos.length > 2) {
251
274
  continue;
252
275
  }
253
- if (origem === "js" || origem === "javascript") {
254
- implementacoes.push({ origem: "js", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
276
+ const origem = ORIGENS_INTEROP_IMPLEMENTACAO[segmentos[0] ?? ""];
277
+ if (!origem) {
255
278
  continue;
256
279
  }
257
- if (origem === "py" || origem === "python") {
258
- implementacoes.push({ origem: "py", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
280
+ const papel = segmentos[1];
281
+ if (papel !== undefined && !PAPEIS_IMPLEMENTACAO_IR.has(papel)) {
259
282
  continue;
260
283
  }
261
- if (origem === "dart") {
262
- implementacoes.push({ origem: "dart", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
263
- continue;
264
- }
265
- if (origem === "lua") {
266
- implementacoes.push({ origem: "lua", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
267
- continue;
268
- }
269
- if (origem === "cs" || origem === "csharp" || origem === "dotnet") {
270
- implementacoes.push({ origem: "cs", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
271
- continue;
272
- }
273
- if (origem === "java") {
274
- implementacoes.push({ origem: "java", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
275
- continue;
276
- }
277
- if (origem === "go" || origem === "golang") {
278
- implementacoes.push({ origem: "go", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
279
- continue;
280
- }
281
- if (origem === "rust" || origem === "rs") {
282
- implementacoes.push({ origem: "rust", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
283
- continue;
284
- }
285
- if (origem === "cpp" || origem === "cxx" || origem === "cc" || origem === "c++") {
286
- implementacoes.push({ origem: "cpp", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
287
- continue;
288
- }
289
- if (origem === "php") {
290
- implementacoes.push({ origem: "php", caminho: campo.valor, resolucaoImpl: campo.valor, statusImpl: "nao_verificado" });
291
- }
284
+ implementacoes.push({
285
+ origem,
286
+ papel: papel,
287
+ caminho: campo.valor,
288
+ resolucaoImpl: campo.valor,
289
+ statusImpl: "nao_verificado",
290
+ });
292
291
  }
293
292
  return implementacoes;
294
293
  }
@@ -24,6 +24,7 @@ export interface IrCampo {
24
24
  export interface IrImplementacaoTask {
25
25
  origem: "ts" | "js" | "py" | "dart" | "lua" | "cs" | "java" | "go" | "rust" | "cpp" | "php";
26
26
  caminho: string;
27
+ papel?: "rota" | "servico" | "persistencia" | "repositorio";
27
28
  origemArquivo?: string;
28
29
  origemSimbolo?: string;
29
30
  resolucaoImpl?: string;
@@ -32,6 +32,7 @@ export interface InteropSemantico {
32
32
  export interface ImplementacaoTaskSemantica {
33
33
  origem: "ts" | "js" | "py" | "dart" | "lua" | "cs" | "java" | "go" | "rust" | "cpp" | "php";
34
34
  caminho: string;
35
+ papel?: "rota" | "servico" | "persistencia" | "repositorio";
35
36
  }
36
37
  export interface ContextoSemantico {
37
38
  modulo: string;
@@ -83,6 +84,12 @@ export declare function converterCampoSemantico(campo: CampoAst): CampoSemantico
83
84
  export declare function indicesCampos(campos: CampoSemantico[]): Map<string, CampoSemantico>;
84
85
  export declare function indiceErros(erros: ErroSemanticoTask[]): Map<string, ErroSemanticoTask>;
85
86
  export declare function coletarErrosTask(task: TaskAst): ErroSemanticoTask[];
87
+ export declare const PAPEIS_IMPLEMENTACAO_SUPORTADOS: Set<"servico" | "persistencia" | "rota" | "repositorio">;
88
+ export interface NomeCampoImplementacao {
89
+ origem: ImplementacaoTaskSemantica["origem"];
90
+ papel?: ImplementacaoTaskSemantica["papel"];
91
+ }
92
+ export declare function normalizarNomeCampoImplementacao(valor: string): NomeCampoImplementacao | undefined;
86
93
  export declare function coletarResumoTask(task: TaskAst): ResumoTaskSemantico;
87
94
  export declare function validarImplementacoesTask(task: TaskAst, diagnosticos: Diagnostico[]): void;
88
95
  export declare function validarVinculos(bloco: BlocoGenericoAst | undefined, diagnosticos: Diagnostico[], contexto: string): void;
@@ -236,6 +236,25 @@ export function coletarErrosTask(task) {
236
236
  }
237
237
  return [...erros.values()];
238
238
  }
239
+ export const PAPEIS_IMPLEMENTACAO_SUPORTADOS = new Set(["rota", "servico", "persistencia", "repositorio"]);
240
+ export function normalizarNomeCampoImplementacao(valor) {
241
+ const segmentos = valor.toLowerCase().split("_");
242
+ if (segmentos.length > 2) {
243
+ return undefined;
244
+ }
245
+ const origem = normalizarOrigemImplementacao(segmentos[0] ?? "");
246
+ if (!origem) {
247
+ return undefined;
248
+ }
249
+ const papel = segmentos[1];
250
+ if (papel === undefined) {
251
+ return { origem };
252
+ }
253
+ if (!PAPEIS_IMPLEMENTACAO_SUPORTADOS.has(papel)) {
254
+ return undefined;
255
+ }
256
+ return { origem, papel: papel };
257
+ }
239
258
  export function coletarResumoTask(task) {
240
259
  return {
241
260
  input: (task.input?.campos ?? []).map(converterCampoSemantico),
@@ -244,8 +263,10 @@ export function coletarResumoTask(task) {
244
263
  guarantees: (task.guarantees?.linhas ?? []).map((linha) => linha.conteudo),
245
264
  implementacoes: (task.impl?.campos ?? [])
246
265
  .map((campo) => {
247
- const origem = normalizarOrigemImplementacao(campo.nome);
248
- return origem ? { origem, caminho: campo.valor } : undefined;
266
+ const nome = normalizarNomeCampoImplementacao(campo.nome);
267
+ return nome
268
+ ? { origem: nome.origem, ...(nome.papel ? { papel: nome.papel } : {}), caminho: campo.valor }
269
+ : undefined;
249
270
  })
250
271
  .filter((item) => Boolean(item)),
251
272
  };
@@ -254,20 +275,22 @@ export function validarImplementacoesTask(task, diagnosticos) {
254
275
  if (!task.impl) {
255
276
  return;
256
277
  }
257
- const origens = new Set();
278
+ const chaves = new Set();
258
279
  for (const campo of task.impl.campos) {
259
- const origem = normalizarOrigemImplementacao(campo.nome);
260
- if (!origem) {
261
- diagnosticos.push(criarDiagnostico("SEM059", `Task "${task.nome}" declarou implementacao externa invalida em impl: "${campo.nome}".`, "erro", campo.intervalo, "Use apenas ts, js, py, dart, lua, cs, java, go, rust, cpp ou php dentro do bloco impl."));
280
+ const nome = normalizarNomeCampoImplementacao(campo.nome);
281
+ if (!nome) {
282
+ diagnosticos.push(criarDiagnostico("SEM059", `Task "${task.nome}" declarou implementacao externa invalida em impl: "${campo.nome}".`, "erro", campo.intervalo, "Use ts, js, py, dart, lua, cs, java, go, rust, cpp ou php, opcionalmente com papel: ts_rota, ts_servico, ts_persistencia ou ts_repositorio."));
262
283
  continue;
263
284
  }
264
- if (origens.has(origem)) {
265
- diagnosticos.push(criarDiagnostico("SEM060", `Task "${task.nome}" declarou mais de uma implementacao ${origem} no bloco impl.`, "erro", campo.intervalo, "Cada origem externa deve aparecer no maximo uma vez dentro de impl."));
285
+ const rotulo = nome.papel ? `${nome.origem}_${nome.papel}` : nome.origem;
286
+ const chave = `${nome.origem}:${nome.papel ?? "-"}`;
287
+ if (chaves.has(chave)) {
288
+ diagnosticos.push(criarDiagnostico("SEM060", `Task "${task.nome}" declarou mais de uma implementacao ${rotulo} no bloco impl.`, "erro", campo.intervalo, "Cada combinacao de origem e papel deve aparecer no maximo uma vez; use papeis distintos como ts_rota e ts_servico para camadas diferentes."));
266
289
  continue;
267
290
  }
268
- origens.add(origem);
291
+ chaves.add(chave);
269
292
  if (!PADRAO_CAMINHO_INTEROP.test(campo.valor)) {
270
- diagnosticos.push(criarDiagnostico("SEM061", `Task "${task.nome}" declarou caminho invalido para impl ${origem}: "${campo.valor}".`, "erro", campo.intervalo, "Use um identificador de implementacao como pacote.modulo.funcao ou app.servico.metodo."));
293
+ diagnosticos.push(criarDiagnostico("SEM061", `Task "${task.nome}" declarou caminho invalido para impl ${rotulo}: "${campo.valor}".`, "erro", campo.intervalo, "Use um identificador de implementacao como pacote.modulo.funcao ou app.servico.metodo."));
271
294
  }
272
295
  }
273
296
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@semacode/cli",
3
- "version": "3.0.0",
3
+ "version": "3.5.0",
4
4
  "description": "Codex-native local semantic governance CLI for contracts, drift, impact, documentation gates, and code generation.",
5
5
  "type": "module",
6
6
  "icon": "logo.png",