@semacode/cli 1.5.17 → 1.5.18

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 (66) hide show
  1. package/README.md +104 -112
  2. package/SEMA_BRIEF.curto.txt +6 -6
  3. package/SEMA_BRIEF.md +17 -24
  4. package/SEMA_BRIEF.micro.txt +5 -5
  5. package/SEMA_INDEX.json +86 -224
  6. package/dist/drift.d.ts +3 -3
  7. package/dist/drift.js +5 -111
  8. package/dist/drift.js.map +1 -1
  9. package/dist/importador.d.ts +1 -1
  10. package/dist/importador.js +1 -200
  11. package/dist/importador.js.map +1 -1
  12. package/dist/index.js +59 -479
  13. package/dist/index.js.map +1 -1
  14. package/dist/projeto.js +0 -20
  15. package/dist/projeto.js.map +1 -1
  16. package/dist/tipos.d.ts +1 -1
  17. package/docs/AGENT_STARTER.md +9 -8
  18. package/docs/cli.md +106 -119
  19. package/docs/como-ensinar-a-sema-para-ia.md +4 -4
  20. package/docs/env.md +56 -56
  21. package/docs/fluxo-pratico-ia-sema.md +171 -167
  22. package/docs/integracao-com-ia.md +98 -96
  23. package/docs/mcp.md +51 -53
  24. package/docs/pagamento-ponta-a-ponta.md +11 -1
  25. package/docs/persistencia-vendor-first.md +1 -1
  26. package/docs/prompt-base-ia-sema.md +6 -5
  27. package/docs/rollback.md +1 -1
  28. package/docs/sintaxe.md +196 -394
  29. package/exemplos/agendamento.sema +0 -1
  30. package/exemplos/assinatura.sema +0 -3
  31. package/exemplos/auditoria.sema +2 -1
  32. package/exemplos/estoque.sema +2 -1
  33. package/exemplos/fila.sema +2 -3
  34. package/exemplos/multi_tenant.sema +2 -2
  35. package/exemplos/notificacao.sema +53 -2
  36. package/exemplos/operacao_estrategia.sema +231 -0
  37. package/exemplos/pagamento.sema +214 -2
  38. package/exemplos/pedido.sema +156 -20
  39. package/exemplos/replica_analitica_erp.sema +160 -0
  40. package/exemplos/webhook.sema +2 -4
  41. package/node_modules/@sema/gerador-css/package.json +1 -1
  42. package/node_modules/@sema/gerador-dart/package.json +1 -1
  43. package/node_modules/@sema/gerador-html/package.json +1 -1
  44. package/node_modules/@sema/gerador-javascript/package.json +1 -1
  45. package/node_modules/@sema/gerador-lua/package.json +1 -1
  46. package/node_modules/@sema/gerador-python/package.json +1 -1
  47. package/node_modules/@sema/gerador-typescript/package.json +1 -1
  48. package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +2 -4
  49. package/node_modules/@sema/nucleo/dist/formatador/index.js +14 -42
  50. package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
  51. package/node_modules/@sema/nucleo/dist/ir/conversor.js +9 -204
  52. package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
  53. package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +3 -35
  54. package/node_modules/@sema/nucleo/dist/lexer/tokens.js +0 -21
  55. package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
  56. package/node_modules/@sema/nucleo/dist/parser/parser.js +0 -40
  57. package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
  58. package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +6 -5
  59. package/node_modules/@sema/nucleo/dist/semantico/analisador.js +76 -307
  60. package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
  61. package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +2 -0
  62. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +32 -2
  63. package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -1
  64. package/node_modules/@sema/nucleo/package.json +1 -1
  65. package/node_modules/@sema/padroes/package.json +1 -1
  66. package/package.json +14 -14
@@ -1,5 +1,5 @@
1
1
  import { type Diagnostico } from "@sema/nucleo";
2
- export type FonteImportacao = "nestjs" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "firebase" | "typescript" | "python" | "dart" | "lua" | "php" | "dotnet" | "java" | "go" | "rust" | "cpp";
2
+ export type FonteImportacao = "nestjs" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "firebase" | "typescript" | "python" | "dart" | "dotnet" | "java" | "go" | "rust" | "cpp";
3
3
  export interface ArquivoImportado {
4
4
  caminhoRelativo: string;
5
5
  conteudo: string;
@@ -7,8 +7,6 @@ import { extrairSimbolosCpp } from "./cpp-symbols.js";
7
7
  import { extrairRotasDotnet, extrairSimbolosDotnet } from "./dotnet-http.js";
8
8
  import { extrairRotasGo, extrairSimbolosGo } from "./go-http.js";
9
9
  import { extrairRotasJava, extrairSimbolosJava } from "./java-http.js";
10
- import { extrairSimbolosLua } from "./lua-symbols.js";
11
- import { extrairRotasPhp, extrairSimbolosPhp } from "./php-symbols.js";
12
10
  import { extrairParametrosCaminhoFlask, extrairRotasFlaskDecoradas } from "./python-http.js";
13
11
  import { extrairRotasRust, extrairSimbolosRust } from "./rust-http.js";
14
12
  import { extrairRotasTypeScriptHttp, inferirSemanticaHandlerTypeScriptHttp, localizarExportacaoTypeScriptHttp, } from "./typescript-http.js";
@@ -247,7 +245,6 @@ function limparTipoBackend(tipo) {
247
245
  }
248
246
  return tipo
249
247
  .trim()
250
- .replace(/^\?/, "")
251
248
  .replace(/^Task<(.+)>$/i, "$1")
252
249
  .replace(/^ActionResult<(.+)>$/i, "$1")
253
250
  .replace(/^IActionResult$/i, "Json")
@@ -261,10 +258,7 @@ function limparTipoBackend(tipo) {
261
258
  .replace(/^Vec<(.+)>$/i, "Json")
262
259
  .replace(/^List<(.+)>$/i, "Json")
263
260
  .replace(/^Map<(.+)>$/i, "Json")
264
- .replace(/^Dictionary<(.+)>$/i, "Json")
265
- .replace(/\|null$/i, "")
266
- .replace(/^null\|/i, "")
267
- .replace(/^(array|mixed|object)$/i, "Json");
261
+ .replace(/^Dictionary<(.+)>$/i, "Json");
268
262
  }
269
263
  function mapearTipoBackendParaSema(tipo) {
270
264
  const limpo = limparTipoBackend(tipo);
@@ -1470,8 +1464,6 @@ function renderizarImpl(impl, indentacao = " ") {
1470
1464
  ...(impl.ts ? [`${indentacao} ts: ${impl.ts}`] : []),
1471
1465
  ...(impl.py ? [`${indentacao} py: ${impl.py}`] : []),
1472
1466
  ...(impl.dart ? [`${indentacao} dart: ${impl.dart}`] : []),
1473
- ...(impl.lua ? [`${indentacao} lua: ${impl.lua}`] : []),
1474
- ...(impl.php ? [`${indentacao} php: ${impl.php}`] : []),
1475
1467
  ...(impl.cs ? [`${indentacao} cs: ${impl.cs}`] : []),
1476
1468
  ...(impl.java ? [`${indentacao} java: ${impl.java}`] : []),
1477
1469
  ...(impl.go ? [`${indentacao} go: ${impl.go}`] : []),
@@ -2191,27 +2183,6 @@ function extrairErrosPython(texto) {
2191
2183
  }
2192
2184
  return [...erros.entries()].map(([nome, mensagem]) => ({ nome, mensagem }));
2193
2185
  }
2194
- function extrairErrosLua(texto) {
2195
- const erros = new Map();
2196
- for (const match of texto.matchAll(/\berror\s*\(\s*(?:(["'])(.*?)\1|([A-Za-z_]\w*))/g)) {
2197
- const mensagem = match[2] ?? `Erro importado automaticamente de ${match[3] ?? "error"}.`;
2198
- erros.set(normalizarNomeErroBruto(mensagem), mensagem);
2199
- }
2200
- return [...erros.entries()].map(([nome, mensagem]) => ({ nome, mensagem }));
2201
- }
2202
- function extrairErrosPhp(texto) {
2203
- const erros = new Map();
2204
- for (const match of texto.matchAll(/\bthrow\s+new\s+([A-Za-z_\\][A-Za-z0-9_\\]*)\s*\(([^)]*)\)/g)) {
2205
- const nomeBruto = match[1].split("\\").at(-1) ?? match[1];
2206
- const mensagem = (match[2] ?? "").match(/["']([^"']+)["']/)?.[1] ?? `Erro importado automaticamente de ${nomeBruto}.`;
2207
- erros.set(normalizarNomeErroBruto(nomeBruto), mensagem);
2208
- }
2209
- for (const match of texto.matchAll(/\babort\s*\(\s*(\d{3})(?:\s*,\s*["']([^"']+)["'])?/g)) {
2210
- const mensagem = match[2] ?? `Abort HTTP ${match[1]}.`;
2211
- erros.set(`http_${match[1]}`, mensagem);
2212
- }
2213
- return [...erros.entries()].map(([nome, mensagem]) => ({ nome, mensagem }));
2214
- }
2215
2186
  function caminhoImplGenerico(diretorioBase, arquivo, simbolo, opcoes) {
2216
2187
  const relativo = path.relative(diretorioBase, arquivo).replace(/\.[^.]+$/, "");
2217
2188
  const segmentos = relativo.split(path.sep).map((segmento, indice, lista) => opcoes?.snakeCaseUltimoArquivo && indice === lista.length - 1
@@ -2226,62 +2197,6 @@ function caminhoImplPython(diretorioBase, arquivo, simbolo) {
2226
2197
  function caminhoImplDart(diretorioBase, arquivo, simbolo) {
2227
2198
  return caminhoImplGenerico(diretorioBase, arquivo, simbolo);
2228
2199
  }
2229
- function caminhoImplPhp(diretorioBase, arquivo, simbolo) {
2230
- return simbolo.includes(".")
2231
- ? simbolo
2232
- : caminhoImplGenerico(diretorioBase, arquivo, simbolo);
2233
- }
2234
- const NOMES_RESERVADOS_TASK_IMPORTADA = new Set([
2235
- "database",
2236
- "table",
2237
- "view",
2238
- "query",
2239
- "transaction",
2240
- "index",
2241
- "constraint",
2242
- "relationship",
2243
- "collection",
2244
- "document",
2245
- "keyspace",
2246
- "stream",
2247
- "lock",
2248
- "retention",
2249
- "replication",
2250
- "input",
2251
- "output",
2252
- "rules",
2253
- "effects",
2254
- "impl",
2255
- "vinculos",
2256
- "execucao",
2257
- "auth",
2258
- "authz",
2259
- "dados",
2260
- "audit",
2261
- "segredos",
2262
- "forbidden",
2263
- "guarantees",
2264
- "state",
2265
- "tests",
2266
- "error",
2267
- "flow",
2268
- "route",
2269
- "worker",
2270
- "evento",
2271
- "fila",
2272
- "cron",
2273
- "webhook",
2274
- "cache",
2275
- "storage",
2276
- "policy",
2277
- "when",
2278
- "given",
2279
- "expect",
2280
- ]);
2281
- function normalizarNomeTaskImportada(valor) {
2282
- const nome = paraSnakeCase(valor) || "task_importada";
2283
- return NOMES_RESERVADOS_TASK_IMPORTADA.has(nome) ? `${nome}_task` : nome;
2284
- }
2285
2200
  function dividirParametrosPython(parametros) {
2286
2201
  const partes = [];
2287
2202
  let atual = "";
@@ -2585,114 +2500,6 @@ async function importarDartBase(diretorio, namespaceBase) {
2585
2500
  }
2586
2501
  return modulos;
2587
2502
  }
2588
- async function importarLuaBase(diretorio, namespaceBase) {
2589
- const arquivos = (await listarArquivosRecursivos(diretorio, [".lua"]))
2590
- .filter((arquivo) => !/(^|[\\/])tests?([\\/]|$)|(?:^|[\\/])spec([\\/]|$)|(?:_spec|_test)\.lua$/i.test(arquivo));
2591
- const modulos = [];
2592
- for (const arquivo of arquivos) {
2593
- const texto = await readFile(arquivo, "utf8");
2594
- const relacao = path.relative(diretorio, arquivo);
2595
- const contextoSegmentos = inferirContextoPorArquivo(relacao);
2596
- const nomeModulo = [namespaceBase, ...contextoSegmentos].join(".");
2597
- const tasks = [];
2598
- for (const simbolo of selecionarSimbolosPreferidos(extrairSimbolosLua(texto))) {
2599
- const nomeBase = simbolo.simbolo.split(".").at(-1) ?? simbolo.simbolo;
2600
- tasks.push({
2601
- nome: paraSnakeCase(nomeBase),
2602
- resumo: `Task importada automaticamente de ${relacao}#${simbolo.simbolo}.`,
2603
- input: simbolo.parametros.map((parametro) => ({
2604
- nome: normalizarNomeCampoImportado(parametro.nome),
2605
- tipo: mapearTipoPrimitivo(parametro.tipoTexto ?? "Json"),
2606
- obrigatorio: parametro.obrigatorio,
2607
- })),
2608
- output: [{ nome: "resultado", tipo: "Json", obrigatorio: false }],
2609
- errors: extrairErrosLua(texto),
2610
- effects: descreverEfeitosPorHeuristica(texto),
2611
- impl: { lua: caminhoImplGenerico(diretorio, arquivo, simbolo.simbolo) },
2612
- origemArquivo: relacao,
2613
- origemSimbolo: simbolo.simbolo,
2614
- });
2615
- }
2616
- if (tasks.length === 0) {
2617
- continue;
2618
- }
2619
- modulos.push({
2620
- nome: nomeModulo,
2621
- resumo: `Rascunho Sema importado automaticamente de ${relacao}.`,
2622
- tasks: deduplicarTarefas(tasks),
2623
- routes: [],
2624
- entities: [],
2625
- enums: [],
2626
- databases: inferirDatabasesPorHeuristica(texto, relacao),
2627
- });
2628
- }
2629
- return modulos;
2630
- }
2631
- async function importarPhpBase(diretorio, namespaceBase) {
2632
- const arquivos = (await listarArquivosRecursivos(diretorio, [".php"]))
2633
- .filter((arquivo) => !/(^|[\\/])tests?([\\/]|$)|(?:^|[\\/])spec([\\/]|$)|(?:Test|Spec)\.php$/i.test(arquivo));
2634
- const modulos = new Map();
2635
- for (const arquivo of arquivos) {
2636
- const texto = await readFile(arquivo, "utf8");
2637
- const relacao = path.relative(diretorio, arquivo);
2638
- const contextoSegmentos = inferirContextoPorArquivo(relacao);
2639
- const nomeModulo = [namespaceBase, ...contextoSegmentos].join(".");
2640
- const tasks = [];
2641
- const routes = [];
2642
- for (const simbolo of selecionarSimbolosPreferidos(extrairSimbolosPhp(texto))) {
2643
- const nomeBase = simbolo.simbolo.split(".").at(-1) ?? simbolo.simbolo;
2644
- tasks.push({
2645
- nome: normalizarNomeTaskImportada(nomeBase),
2646
- resumo: `Task importada automaticamente de ${relacao}#${simbolo.simbolo}.`,
2647
- input: simbolo.parametros.map((parametro) => ({
2648
- nome: normalizarNomeCampoImportado(parametro.nome),
2649
- tipo: mapearTipoBackendParaSema(parametro.tipoTexto),
2650
- obrigatorio: parametro.obrigatorio,
2651
- })),
2652
- output: criarCampoResultadoBackend(simbolo.retorno),
2653
- errors: extrairErrosPhp(texto),
2654
- effects: descreverEfeitosPorHeuristica(texto),
2655
- impl: { php: caminhoImplPhp(diretorio, arquivo, simbolo.simbolo) },
2656
- origemArquivo: relacao,
2657
- origemSimbolo: simbolo.simbolo,
2658
- });
2659
- }
2660
- for (const rota of extrairRotasPhp(texto)) {
2661
- const taskNome = normalizarNomeTaskImportada(rota.simbolo.split(".").at(-1) ?? rota.simbolo);
2662
- const output = rota.retorno ? criarCampoResultadoBackend(rota.retorno) : [{ nome: "resultado", tipo: "Json", obrigatorio: false }];
2663
- const nomeBase = `${taskNome}_publico`;
2664
- const nome = routes.some((route) => route.nome === nomeBase)
2665
- ? `${taskNome}_${rota.metodo.toLowerCase()}_publico`
2666
- : nomeBase;
2667
- tasks.push({
2668
- nome: taskNome,
2669
- resumo: `Task HTTP PHP importada automaticamente de ${relacao}#${rota.simbolo}.`,
2670
- input: camposDeParametrosRotaBackend(rota.parametros),
2671
- output,
2672
- errors: extrairErrosPhp(texto),
2673
- effects: [{ categoria: "consulta", alvo: "http", criticidade: "media" }],
2674
- impl: { php: caminhoImplPhp(diretorio, arquivo, rota.simbolo) },
2675
- origemArquivo: relacao,
2676
- origemSimbolo: rota.simbolo,
2677
- });
2678
- routes.push({
2679
- nome,
2680
- resumo: `Rota PHP importada automaticamente de ${relacao}#${rota.simbolo}.`,
2681
- metodo: rota.metodo,
2682
- caminho: rota.caminho,
2683
- task: taskNome,
2684
- input: camposDeParametrosRotaBackend(rota.parametros),
2685
- output,
2686
- errors: [],
2687
- });
2688
- }
2689
- if (tasks.length === 0 && routes.length === 0) {
2690
- continue;
2691
- }
2692
- acumularModuloImportado(modulos, criarModuloImportadoSimples(nomeModulo, `Rascunho Sema importado automaticamente de ${relacao}.`, tasks, routes, [], inferirDatabasesPorHeuristica(texto, relacao)));
2693
- }
2694
- return [...modulos.values()];
2695
- }
2696
2503
  function criarModuloImportadoSimples(nome, resumo, tasks, routes = [], vinculos = [], databases = []) {
2697
2504
  sincronizarRotasComTasks(routes, tasks);
2698
2505
  return {
@@ -3084,12 +2891,6 @@ export async function importarProjetoLegado(fonte, diretorio, namespaceBase) {
3084
2891
  else if (fonte === "dart") {
3085
2892
  modulos = await importarDartBase(base, namespace);
3086
2893
  }
3087
- else if (fonte === "lua") {
3088
- modulos = await importarLuaBase(base, namespace);
3089
- }
3090
- else if (fonte === "php") {
3091
- modulos = await importarPhpBase(base, namespace);
3092
- }
3093
2894
  else if (fonte === "dotnet") {
3094
2895
  modulos = await importarDotnetBase(base, namespace);
3095
2896
  }