@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.
- package/README.md +104 -112
- package/SEMA_BRIEF.curto.txt +6 -6
- package/SEMA_BRIEF.md +17 -24
- package/SEMA_BRIEF.micro.txt +5 -5
- package/SEMA_INDEX.json +86 -224
- package/dist/drift.d.ts +3 -3
- package/dist/drift.js +5 -111
- package/dist/drift.js.map +1 -1
- package/dist/importador.d.ts +1 -1
- package/dist/importador.js +1 -200
- package/dist/importador.js.map +1 -1
- package/dist/index.js +59 -479
- package/dist/index.js.map +1 -1
- package/dist/projeto.js +0 -20
- package/dist/projeto.js.map +1 -1
- package/dist/tipos.d.ts +1 -1
- package/docs/AGENT_STARTER.md +9 -8
- package/docs/cli.md +106 -119
- package/docs/como-ensinar-a-sema-para-ia.md +4 -4
- package/docs/env.md +56 -56
- package/docs/fluxo-pratico-ia-sema.md +171 -167
- package/docs/integracao-com-ia.md +98 -96
- package/docs/mcp.md +51 -53
- package/docs/pagamento-ponta-a-ponta.md +11 -1
- package/docs/persistencia-vendor-first.md +1 -1
- package/docs/prompt-base-ia-sema.md +6 -5
- package/docs/rollback.md +1 -1
- package/docs/sintaxe.md +196 -394
- package/exemplos/agendamento.sema +0 -1
- package/exemplos/assinatura.sema +0 -3
- package/exemplos/auditoria.sema +2 -1
- package/exemplos/estoque.sema +2 -1
- package/exemplos/fila.sema +2 -3
- package/exemplos/multi_tenant.sema +2 -2
- package/exemplos/notificacao.sema +53 -2
- package/exemplos/operacao_estrategia.sema +231 -0
- package/exemplos/pagamento.sema +214 -2
- package/exemplos/pedido.sema +156 -20
- package/exemplos/replica_analitica_erp.sema +160 -0
- package/exemplos/webhook.sema +2 -4
- package/node_modules/@sema/gerador-css/package.json +1 -1
- package/node_modules/@sema/gerador-dart/package.json +1 -1
- package/node_modules/@sema/gerador-html/package.json +1 -1
- package/node_modules/@sema/gerador-javascript/package.json +1 -1
- package/node_modules/@sema/gerador-lua/package.json +1 -1
- package/node_modules/@sema/gerador-python/package.json +1 -1
- package/node_modules/@sema/gerador-typescript/package.json +1 -1
- package/node_modules/@sema/nucleo/dist/ast/tipos.d.ts +2 -4
- package/node_modules/@sema/nucleo/dist/formatador/index.js +14 -42
- package/node_modules/@sema/nucleo/dist/formatador/index.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/ir/conversor.js +9 -204
- package/node_modules/@sema/nucleo/dist/ir/conversor.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/ir/modelos.d.ts +3 -35
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js +0 -21
- package/node_modules/@sema/nucleo/dist/lexer/tokens.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/parser/parser.js +0 -40
- package/node_modules/@sema/nucleo/dist/parser/parser.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/semantico/analisador.d.ts +6 -5
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js +76 -307
- package/node_modules/@sema/nucleo/dist/semantico/analisador.js.map +1 -1
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.d.ts +2 -0
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js +32 -2
- package/node_modules/@sema/nucleo/dist/semantico/estruturas.js.map +1 -1
- package/node_modules/@sema/nucleo/package.json +1 -1
- package/node_modules/@sema/padroes/package.json +1 -1
- package/package.json +14 -14
package/dist/importador.d.ts
CHANGED
|
@@ -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" | "
|
|
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;
|
package/dist/importador.js
CHANGED
|
@@ -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
|
}
|