@semacode/cli 3.5.0 → 3.8.1
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/dist/cliGrammar.js +2 -2
- package/dist/cliHelpTexto.js +1 -1
- package/dist/drift.part01.d.ts +2 -2
- package/dist/drift.part05.d.ts +6 -0
- package/dist/drift.part05.js +68 -0
- package/dist/drift.part06.js +60 -3
- package/dist/drift.part09.d.ts +2 -2
- package/dist/drift.part09.js +5 -2
- package/dist/drift.part14.js +2 -0
- package/dist/geracaoCore.js +3 -0
- package/dist/importador.part01.d.ts +1 -1
- package/dist/importador.part04.d.ts +5 -1
- package/dist/importador.part04.js +40 -2
- package/dist/importador.part06.d.ts +2 -2
- package/dist/importador.part06.js +22 -12
- package/dist/importador.part09.js +10 -1
- package/dist/projetoConfig.js +3 -0
- package/dist/projetoLegado.js +22 -0
- package/dist/projetoOrigens.js +8 -2
- package/dist/tipos.d.ts +1 -1
- package/dist/typescript-http-body.js +9 -0
- package/dist/typescript-http-modelos.d.ts +1 -1
- package/dist/typescript-http-rotas.js +112 -7
- package/dist/typescript-http-semantica.d.ts +3 -3
- package/dist/typescript-http-semantica.js +65 -7
- package/exemplos/koa_crud.sema +95 -0
- package/package.json +1 -1
package/dist/cliGrammar.js
CHANGED
|
@@ -22,8 +22,8 @@ const TEMPLATES_INIT = new Set([
|
|
|
22
22
|
"crud-simples", "auth-completo", "api-rest", "workflow", "pedido", "usuario", "upload",
|
|
23
23
|
]);
|
|
24
24
|
const FONTES_IMPORTACAO = new Set([
|
|
25
|
-
"nestjs", "express", "fastify", "fastapi", "flask", "nextjs", "nextjs-consumer", "react-vite-consumer",
|
|
26
|
-
"angular-consumer", "flutter-consumer", "firebase", "typescript", "javascript",
|
|
25
|
+
"nestjs", "express", "fastify", "koa", "fastapi", "flask", "nextjs", "nextjs-consumer", "react-vite-consumer",
|
|
26
|
+
"angular-consumer", "flutter-consumer", "sveltekit-consumer", "nuxt-consumer", "firebase", "typescript", "javascript",
|
|
27
27
|
"python", "dart", "lua", "dotnet", "java", "go", "rust", "cpp", "php",
|
|
28
28
|
]);
|
|
29
29
|
const ALVOS_GERACAO = new Set([
|
package/dist/cliHelpTexto.js
CHANGED
|
@@ -114,7 +114,7 @@ export function criarAjudaRaiz(versao) {
|
|
|
114
114
|
"modos: drift direto usa fresh por padrão; --cache none ainda executa sem cache persistente; resumo/inspecionar usam --drift none por padrão e não fabricam evidência",
|
|
115
115
|
"impacto: sema impacto <arquivo-ou-pasta> --alvo <token> [--mudanca <descricao>] [--escopo <arquivo|modulo|projeto>] [--json]",
|
|
116
116
|
"renomeação: sema renomear-semantico <arquivo-ou-pasta> --de <nome-atual> --para <nome-novo> [--escopo <arquivo|modulo|projeto>] [--json]",
|
|
117
|
-
"importação: sema importar <nestjs|express|fastify|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|firebase|dotnet|java|go|rust|cpp|php|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]",
|
|
117
|
+
"importação: sema importar <nestjs|express|fastify|koa|fastapi|flask|nextjs|nextjs-consumer|react-vite-consumer|angular-consumer|flutter-consumer|sveltekit-consumer|nuxt-consumer|firebase|dotnet|java|go|rust|cpp|php|typescript|python|dart> <diretorio> [--saida <diretorio>] [--namespace <base>] [--json]",
|
|
118
118
|
"validação: sema validar <arquivo-ou-pasta> [--json]",
|
|
119
119
|
"diagnóstico: sema diagnosticos <arquivo.sema> [--json]",
|
|
120
120
|
"geração: sema compilar <arquivo-ou-pasta> --alvo <typescript|python|php|dart|lua|javascript|html|css|dotnet|cpp> --saida <diretorio> [--estrutura <flat|modulos|backend>] [--framework <base|nestjs|fastapi>]",
|
package/dist/drift.part01.d.ts
CHANGED
|
@@ -11,9 +11,9 @@ export interface SimboloResolvido {
|
|
|
11
11
|
arquivo: string;
|
|
12
12
|
simbolo: string;
|
|
13
13
|
}
|
|
14
|
-
export type ConsumerFramework = "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer";
|
|
14
|
+
export type ConsumerFramework = "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "sveltekit-consumer" | "nuxt-consumer";
|
|
15
15
|
export interface RotaResolvida {
|
|
16
|
-
origem: "nestjs" | "express" | "fastify" | "fastapi" | "flask" | "nextjs" | ConsumerFramework | "firebase" | "dotnet" | "java" | "go" | "rust" | "php";
|
|
16
|
+
origem: "nestjs" | "express" | "fastify" | "koa" | "fastapi" | "flask" | "nextjs" | ConsumerFramework | "firebase" | "dotnet" | "java" | "go" | "rust" | "php";
|
|
17
17
|
metodo: string;
|
|
18
18
|
caminho: string;
|
|
19
19
|
arquivo: string;
|
package/dist/drift.part05.d.ts
CHANGED
|
@@ -18,6 +18,12 @@ export declare function arquivoEhRotasAngularConsumerRaiz(relacaoArquivo: string
|
|
|
18
18
|
export declare function arquivoEhBridgeFlutterConsumer(relacaoArquivo: string): boolean;
|
|
19
19
|
export declare function arquivoEhSuperficieFlutterConsumer(relacaoArquivo: string): boolean;
|
|
20
20
|
export declare function arquivoEhRotasFlutterConsumer(relacaoArquivo: string, codigo?: string): boolean;
|
|
21
|
+
export declare function arquivoEhBridgeSvelteKitConsumer(relacaoArquivo: string): boolean;
|
|
22
|
+
export declare function arquivoEhSuperficieSvelteKitConsumer(relacaoArquivo: string): boolean;
|
|
23
|
+
export declare function inferirRotaSvelteKitConsumer(relacaoArquivo: string): RegistroConsumerSurfaceDrift | undefined;
|
|
24
|
+
export declare function arquivoEhBridgeNuxtConsumer(relacaoArquivo: string): boolean;
|
|
25
|
+
export declare function arquivoEhSuperficieNuxtConsumer(relacaoArquivo: string): boolean;
|
|
26
|
+
export declare function inferirRotaNuxtConsumer(relacaoArquivo: string): RegistroConsumerSurfaceDrift | undefined;
|
|
21
27
|
export declare function inferirRotaNextJsConsumer(relacaoArquivo: string): RegistroConsumerSurfaceDrift | undefined;
|
|
22
28
|
export declare function inferirRotaReactViteConsumer(relacaoArquivo: string): RegistroConsumerSurfaceDrift | undefined;
|
|
23
29
|
export declare function inferirRotaFlutterConsumer(relacaoArquivo: string): RegistroConsumerSurfaceDrift | undefined;
|
package/dist/drift.part05.js
CHANGED
|
@@ -120,6 +120,74 @@ export function arquivoEhRotasFlutterConsumer(relacaoArquivo, codigo) {
|
|
|
120
120
|
return /(?:^|\/)(?:lib\/)?(?:router|app_router|routes)\.dart$/i.test(relacao)
|
|
121
121
|
|| /MaterialApp(?:\.router)?\s*\(|CupertinoApp(?:\.router)?\s*\(|GoRouter\s*\(/.test(codigo ?? "");
|
|
122
122
|
}
|
|
123
|
+
export function arquivoEhBridgeSvelteKitConsumer(relacaoArquivo) {
|
|
124
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
125
|
+
return /(?:^|\/)(?:src\/)?lib\/(?:sema_consumer_bridge|sema\/.+)\.(?:ts|js)$/i.test(relacao);
|
|
126
|
+
}
|
|
127
|
+
export function arquivoEhSuperficieSvelteKitConsumer(relacaoArquivo) {
|
|
128
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
129
|
+
return /(?:^|\/)(?:src\/)?routes\/(?:[^/]+\/)*\+(?:page|layout|error|server)\.(?:svelte|ts|js)$/i.test(relacao);
|
|
130
|
+
}
|
|
131
|
+
export function inferirRotaSvelteKitConsumer(relacaoArquivo) {
|
|
132
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
133
|
+
const segmentos = relacao.split("/");
|
|
134
|
+
const indiceSrcRoutes = segmentos.findIndex((segmento, indice) => segmento === "src" && segmentos[indice + 1] === "routes");
|
|
135
|
+
const indiceRoutes = segmentos.findIndex((segmento) => segmento === "routes");
|
|
136
|
+
const inicioRoutes = indiceSrcRoutes >= 0 ? indiceSrcRoutes + 2 : indiceRoutes >= 0 ? indiceRoutes + 1 : -1;
|
|
137
|
+
if (inicioRoutes < 0) {
|
|
138
|
+
return undefined;
|
|
139
|
+
}
|
|
140
|
+
const arquivoFinal = segmentos.at(-1) ?? "";
|
|
141
|
+
const tipoArquivo = arquivoFinal.match(/^\+(page|layout|error|server)\.(?:svelte|ts|js)$/i)?.[1]?.toLowerCase();
|
|
142
|
+
if (!tipoArquivo) {
|
|
143
|
+
return undefined;
|
|
144
|
+
}
|
|
145
|
+
return {
|
|
146
|
+
rota: montarRotaConsumer(segmentos.slice(inicioRoutes, -1)),
|
|
147
|
+
arquivo: relacaoArquivo,
|
|
148
|
+
tipoArquivo,
|
|
149
|
+
};
|
|
150
|
+
}
|
|
151
|
+
export function arquivoEhBridgeNuxtConsumer(relacaoArquivo) {
|
|
152
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
153
|
+
return /(?:^|\/)(?:app\/)?composables\/(?:sema_consumer_bridge|sema\/.+)\.(?:ts|js)$/i.test(relacao);
|
|
154
|
+
}
|
|
155
|
+
export function arquivoEhSuperficieNuxtConsumer(relacaoArquivo) {
|
|
156
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
157
|
+
return /^(?:app\/)?pages\/.+\.vue$/i.test(relacao)
|
|
158
|
+
|| /(?:^|\/)server\/api\/.+\.(?:get|post|put|patch|delete|head)\.(?:ts|js)$/i.test(relacao);
|
|
159
|
+
}
|
|
160
|
+
export function inferirRotaNuxtConsumer(relacaoArquivo) {
|
|
161
|
+
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
162
|
+
const segmentos = relacao.split("/");
|
|
163
|
+
const indiceServer = segmentos.findIndex((segmento, indice) => segmento === "server" && segmentos[indice + 1] === "api");
|
|
164
|
+
if (indiceServer >= 0) {
|
|
165
|
+
const arquivoFinal = segmentos.at(-1) ?? "";
|
|
166
|
+
const metodo = arquivoFinal.match(/\.(get|post|put|patch|delete|head)\.(?:ts|js)$/i)?.[1]?.toUpperCase();
|
|
167
|
+
const nomeBase = arquivoFinal.replace(/\.(?:get|post|put|patch|delete|head)?\.(?:ts|js)$/i, "");
|
|
168
|
+
const caminhoAteArquivo = segmentos.slice(indiceServer + 1, -1);
|
|
169
|
+
return {
|
|
170
|
+
rota: montarRotaConsumer(nomeBase === "index" ? caminhoAteArquivo : [...caminhoAteArquivo, nomeBase]),
|
|
171
|
+
arquivo: relacaoArquivo,
|
|
172
|
+
tipoArquivo: metodo ?? "server",
|
|
173
|
+
};
|
|
174
|
+
}
|
|
175
|
+
const indicePages = segmentos.findIndex((segmento, indice) => segmento === "pages" && (indice === 0 || segmentos[indice - 1] === "app"));
|
|
176
|
+
if (indicePages < 0) {
|
|
177
|
+
return undefined;
|
|
178
|
+
}
|
|
179
|
+
const arquivoFinal = segmentos.at(-1) ?? "";
|
|
180
|
+
if (!arquivoFinal.endsWith(".vue")) {
|
|
181
|
+
return undefined;
|
|
182
|
+
}
|
|
183
|
+
const nomeBase = arquivoFinal.replace(/\.vue$/i, "");
|
|
184
|
+
const caminhoAteArquivo = segmentos.slice(indicePages + 1, -1);
|
|
185
|
+
return {
|
|
186
|
+
rota: montarRotaConsumer(nomeBase === "index" ? caminhoAteArquivo : [...caminhoAteArquivo, nomeBase]),
|
|
187
|
+
arquivo: relacaoArquivo,
|
|
188
|
+
tipoArquivo: "page",
|
|
189
|
+
};
|
|
190
|
+
}
|
|
123
191
|
export function inferirRotaNextJsConsumer(relacaoArquivo) {
|
|
124
192
|
const relacao = normalizarRelacaoConsumer(relacaoArquivo);
|
|
125
193
|
const segmentos = relacao.split("/");
|
package/dist/drift.part06.js
CHANGED
|
@@ -5,7 +5,7 @@ import path from "node:path";
|
|
|
5
5
|
import ts from "typescript";
|
|
6
6
|
import { coletarSuperficiesAngularStandaloneConsumer } from "./angular-consumer-standalone.js";
|
|
7
7
|
import { extrairRotasTypeScriptHttp } from "./typescript-http.js";
|
|
8
|
-
import { arquivoEhRotasAngularConsumer, arquivoEhRotasAngularConsumerRaiz, arquivoEhRotasReactViteConsumer, arquivoEhSuperficieNextJsConsumer, arquivoEhSuperficieReactViteConsumer, extrairRotasAngularConsumer, extrairRotasReactViteConsumer, inferirRotaNextJsConsumer, inferirRotaReactViteConsumer, normalizarRelacaoConsumer, registrarAtribuicaoPrototypeTypeScript, registrarMetodosObjectAssignTypeScript } from "./drift.part05.js";
|
|
8
|
+
import { arquivoEhRotasAngularConsumer, arquivoEhRotasAngularConsumerRaiz, arquivoEhRotasReactViteConsumer, arquivoEhSuperficieNextJsConsumer, arquivoEhSuperficieNuxtConsumer, arquivoEhSuperficieReactViteConsumer, arquivoEhSuperficieSvelteKitConsumer, extrairRotasAngularConsumer, extrairRotasReactViteConsumer, inferirRotaNextJsConsumer, inferirRotaNuxtConsumer, inferirRotaReactViteConsumer, inferirRotaSvelteKitConsumer, normalizarRelacaoConsumer, registrarAtribuicaoPrototypeTypeScript, registrarMetodosObjectAssignTypeScript } from "./drift.part05.js";
|
|
9
9
|
import { caminhosSimbolicos, chaveCaminhoCanonicoDrift, deduplicarRaizesSobrepostasDrift, desembrulharExpressaoTypeScript, extrairNomeClassePrototypeTypeScript, extrairTextoLiteral, juntarCaminhoHttp, lerDecorator, listarArquivosRecursivos, registrarSimboloTypeScript, } from "./drift.part04.js";
|
|
10
10
|
import { extrairRecursosPersistenciaCodigoVivo, registrarRecursoDrift } from "./drift.part03.js";
|
|
11
11
|
export function inferirConsumerFrameworkPrincipal(fontesLegado, consumerSurfaces, consumerBridges) {
|
|
@@ -31,7 +31,14 @@ export function inferirConsumerFrameworkPrincipal(fontesLegado, consumerSurfaces
|
|
|
31
31
|
|| /(?:^|\/)(?:lib\/)?(?:router|app_router|routes|main)\.dart$/i.test(arquivo))) {
|
|
32
32
|
return "flutter-consumer";
|
|
33
33
|
}
|
|
34
|
-
|
|
34
|
+
if (arquivos.some((arquivo) => /(?:^|\/)(?:src\/)?routes\/(?:[^/]+\/)*\+(?:page|layout|error|server)\.(?:svelte|ts|js)$/i.test(arquivo))) {
|
|
35
|
+
return "sveltekit-consumer";
|
|
36
|
+
}
|
|
37
|
+
if (arquivos.some((arquivo) => /^(?:app\/)?pages\/.+\.vue$/i.test(arquivo)
|
|
38
|
+
|| /(?:^|\/)server\/api\/.+\.(?:get|post|put|patch|delete|head)\.(?:ts|js)$/i.test(arquivo))) {
|
|
39
|
+
return "nuxt-consumer";
|
|
40
|
+
}
|
|
41
|
+
for (const framework of ["nextjs-consumer", "react-vite-consumer", "angular-consumer", "flutter-consumer", "sveltekit-consumer", "nuxt-consumer"]) {
|
|
35
42
|
if (fontesLegado.includes(framework)) {
|
|
36
43
|
return framework;
|
|
37
44
|
}
|
|
@@ -203,8 +210,50 @@ export async function indexarTypeScript(diretorios, adaptadorLeitura) {
|
|
|
203
210
|
const consumerSurfaces = new Map();
|
|
204
211
|
const sourceFiles = new Map();
|
|
205
212
|
const arquivosProcessados = new Set();
|
|
213
|
+
const registrarSuperficieSvelteKitDrift = (relacao, arquivo) => {
|
|
214
|
+
const superficie = arquivoEhSuperficieSvelteKitConsumer(relacao)
|
|
215
|
+
? inferirRotaSvelteKitConsumer(relacao)
|
|
216
|
+
: undefined;
|
|
217
|
+
if (!superficie) {
|
|
218
|
+
return;
|
|
219
|
+
}
|
|
220
|
+
consumerSurfaces.set(`${superficie.rota}:${arquivo}:${superficie.tipoArquivo}`, {
|
|
221
|
+
rota: superficie.rota,
|
|
222
|
+
arquivo,
|
|
223
|
+
tipoArquivo: superficie.tipoArquivo,
|
|
224
|
+
});
|
|
225
|
+
rotas.push({
|
|
226
|
+
origem: "sveltekit-consumer",
|
|
227
|
+
metodo: superficie.tipoArquivo === "server" ? "GET" : "VIEW",
|
|
228
|
+
caminho: superficie.rota,
|
|
229
|
+
arquivo,
|
|
230
|
+
simbolo: superficie.tipoArquivo,
|
|
231
|
+
});
|
|
232
|
+
};
|
|
233
|
+
const registrarSuperficieNuxtDrift = (relacao, arquivo) => {
|
|
234
|
+
const superficie = arquivoEhSuperficieNuxtConsumer(relacao)
|
|
235
|
+
? inferirRotaNuxtConsumer(relacao)
|
|
236
|
+
: undefined;
|
|
237
|
+
if (!superficie) {
|
|
238
|
+
return;
|
|
239
|
+
}
|
|
240
|
+
consumerSurfaces.set(`${superficie.rota}:${arquivo}:${superficie.tipoArquivo}`, {
|
|
241
|
+
rota: superficie.rota,
|
|
242
|
+
arquivo,
|
|
243
|
+
tipoArquivo: superficie.tipoArquivo,
|
|
244
|
+
});
|
|
245
|
+
rotas.push({
|
|
246
|
+
origem: "nuxt-consumer",
|
|
247
|
+
metodo: ["GET", "POST", "PUT", "PATCH", "DELETE", "HEAD"].includes(superficie.tipoArquivo)
|
|
248
|
+
? superficie.tipoArquivo
|
|
249
|
+
: "VIEW",
|
|
250
|
+
caminho: superficie.rota,
|
|
251
|
+
arquivo,
|
|
252
|
+
simbolo: superficie.tipoArquivo,
|
|
253
|
+
});
|
|
254
|
+
};
|
|
206
255
|
for (const diretorio of deduplicarRaizesSobrepostasDrift(diretorios)) {
|
|
207
|
-
const arquivos = (await listarArquivosRecursivos(diretorio, [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs"], adaptadorLeitura))
|
|
256
|
+
const arquivos = (await listarArquivosRecursivos(diretorio, [".ts", ".tsx", ".js", ".jsx", ".mjs", ".cjs", ".vue", ".svelte"], adaptadorLeitura))
|
|
208
257
|
.filter((arquivo) => !arquivo.endsWith(".d.ts")
|
|
209
258
|
&& !arquivo.endsWith(".spec.ts")
|
|
210
259
|
&& !arquivo.endsWith(".test.ts"))
|
|
@@ -228,6 +277,12 @@ export async function indexarTypeScript(diretorios, adaptadorLeitura) {
|
|
|
228
277
|
const codigo = adaptadorLeitura
|
|
229
278
|
? await adaptadorLeitura.lerTexto(arquivo)
|
|
230
279
|
: await readFile(arquivo, "utf8");
|
|
280
|
+
if (/\.(?:vue|svelte)$/i.test(arquivo)) {
|
|
281
|
+
const relacaoSuperficie = path.relative(diretorio, arquivo);
|
|
282
|
+
registrarSuperficieSvelteKitDrift(relacaoSuperficie, arquivo);
|
|
283
|
+
registrarSuperficieNuxtDrift(relacaoSuperficie, arquivo);
|
|
284
|
+
continue;
|
|
285
|
+
}
|
|
231
286
|
const origemArquivo = /\.(?:js|jsx|mjs|cjs)$/i.test(arquivo) ? "js" : "ts";
|
|
232
287
|
const scriptKind = arquivo.endsWith(".tsx")
|
|
233
288
|
? ts.ScriptKind.TSX
|
|
@@ -287,6 +342,8 @@ export async function indexarTypeScript(diretorios, adaptadorLeitura) {
|
|
|
287
342
|
simbolo: superficieReact.tipoArquivo,
|
|
288
343
|
});
|
|
289
344
|
}
|
|
345
|
+
registrarSuperficieSvelteKitDrift(relacao, arquivo);
|
|
346
|
+
registrarSuperficieNuxtDrift(relacao, arquivo);
|
|
290
347
|
if (fonteDeclaraRotasReactVite(relacao, sourceFile)) {
|
|
291
348
|
for (const rotaReact of extrairRotasReactViteConsumer(relacao, codigo)) {
|
|
292
349
|
consumerSurfaces.set(`${rotaReact.rota}:${arquivo}:router`, {
|
package/dist/drift.part09.d.ts
CHANGED
|
@@ -5,7 +5,7 @@ import { OpcoesDriftLegado, OrigemCodigoDrift, RecursoResolvido, RegistroPersist
|
|
|
5
5
|
import { indexarPersistenciaDetalhada } from "./drift.part08.js";
|
|
6
6
|
export declare function analisarPersistenciaReal(contexto: ContextoProjetoCarregado, mapaRecursos?: Map<string, RecursoResolvido[]>, detalhesPersistencia?: Awaited<ReturnType<typeof indexarPersistenciaDetalhada>>, opcoes?: OpcoesDriftLegado, mapaImpl?: Map<string, SimboloResolvido>): Promise<RegistroPersistenciaRealDrift[]>;
|
|
7
7
|
export declare function normalizarCaminhoRota(caminho?: string): string;
|
|
8
|
-
export declare function extrairFontesHttpTypeScript(fontesLegado: FonteLegado[]): Array<"nestjs" | "nextjs" | "firebase" | "express" | "fastify">;
|
|
8
|
+
export declare function extrairFontesHttpTypeScript(fontesLegado: FonteLegado[]): Array<"nestjs" | "nextjs" | "firebase" | "express" | "fastify" | "koa">;
|
|
9
9
|
export declare function extrairFontesHttpBackend(fontesLegado: FonteLegado[]): Array<"dotnet" | "java" | "go" | "rust" | "php">;
|
|
10
10
|
export declare function ultimoSegmentoSimbolico(caminho: string): string;
|
|
11
11
|
export declare function pontuarCandidatoDeclarado(candidato: SimboloResolvido, origem: OrigemCodigoDrift, caminhoDeclarado: string): SimboloCandidatoDrift | undefined;
|
|
@@ -14,7 +14,7 @@ export declare function deduplicarCandidatos(candidatos: SimboloCandidatoDrift[]
|
|
|
14
14
|
export declare function ordenarCandidatos(candidatos: SimboloCandidatoDrift[]): SimboloCandidatoDrift[];
|
|
15
15
|
export declare function sugerirCandidatosParaImpl(simbolos: SimboloResolvido[], origem: OrigemCodigoDrift, caminhoDeclarado: string): SimboloCandidatoDrift[];
|
|
16
16
|
export declare function sugerirCandidatosParaTaskSemImpl(simbolos: SimboloResolvido[], nomeTask: string): SimboloCandidatoDrift[];
|
|
17
|
-
export declare function escolherRotasEsperadas(task: IrTask, fontesLegado: FonteLegado[]): Array<"nestjs" | "express" | "fastify" | "fastapi" | "flask" | "nextjs" | "firebase" | "dotnet" | "java" | "go" | "rust" | "php">;
|
|
17
|
+
export declare function escolherRotasEsperadas(task: IrTask, fontesLegado: FonteLegado[]): Array<"nestjs" | "express" | "fastify" | "koa" | "fastapi" | "flask" | "nextjs" | "firebase" | "dotnet" | "java" | "go" | "rust" | "php">;
|
|
18
18
|
export declare function taskEhBridgeFirebase(task: IrTask): boolean;
|
|
19
19
|
export declare function tiposAceitosParaRecursoPersistencia(recurso: IrRecursoPersistencia): TipoRecursoDrift[];
|
|
20
20
|
export declare function nomesRecursoPersistencia(recurso: IrRecursoPersistencia): string[];
|
package/dist/drift.part09.js
CHANGED
|
@@ -87,7 +87,7 @@ export function normalizarCaminhoRota(caminho) {
|
|
|
87
87
|
return normalizado.endsWith("/") && normalizado !== "/" ? normalizado.slice(0, -1) : normalizado;
|
|
88
88
|
}
|
|
89
89
|
export function extrairFontesHttpTypeScript(fontesLegado) {
|
|
90
|
-
return fontesLegado.filter((fonte) => fonte === "nestjs" || fonte === "nextjs" || fonte === "firebase" || fonte === "express" || fonte === "fastify");
|
|
90
|
+
return fontesLegado.filter((fonte) => fonte === "nestjs" || fonte === "nextjs" || fonte === "firebase" || fonte === "express" || fonte === "fastify" || fonte === "koa");
|
|
91
91
|
}
|
|
92
92
|
export function extrairFontesHttpBackend(fontesLegado) {
|
|
93
93
|
return fontesLegado.filter((fonte) => fonte === "dotnet" || fonte === "java" || fonte === "go" || fonte === "rust" || fonte === "php");
|
|
@@ -234,13 +234,16 @@ export function escolherRotasEsperadas(task, fontesLegado) {
|
|
|
234
234
|
if (/\bfastify\b/i.test(implTsOuJs.caminho) && fontesTs.includes("fastify")) {
|
|
235
235
|
esperadas.add("fastify");
|
|
236
236
|
}
|
|
237
|
+
if (/\bkoa\b/i.test(implTsOuJs.caminho) && fontesTs.includes("koa")) {
|
|
238
|
+
esperadas.add("koa");
|
|
239
|
+
}
|
|
237
240
|
if (esperadas.size > 0) {
|
|
238
241
|
return [...esperadas];
|
|
239
242
|
}
|
|
240
243
|
if (fontesTs.length > 0) {
|
|
241
244
|
return fontesTs;
|
|
242
245
|
}
|
|
243
|
-
return ["nestjs", "nextjs", "firebase", "express", "fastify"];
|
|
246
|
+
return ["nestjs", "nextjs", "firebase", "express", "fastify", "koa"];
|
|
244
247
|
}
|
|
245
248
|
if (task.implementacoesExternas.some((impl) => impl.origem === "py")) {
|
|
246
249
|
const fontesPython = fontesLegado.filter((fonte) => fonte === "fastapi" || fonte === "flask");
|
package/dist/drift.part14.js
CHANGED
|
@@ -277,6 +277,8 @@ export function analisarModulosSelecionadosDrift(estado) {
|
|
|
277
277
|
&& rotaResolvida.origem !== "react-vite-consumer"
|
|
278
278
|
&& rotaResolvida.origem !== "angular-consumer"
|
|
279
279
|
&& rotaResolvida.origem !== "flutter-consumer"
|
|
280
|
+
&& rotaResolvida.origem !== "sveltekit-consumer"
|
|
281
|
+
&& rotaResolvida.origem !== "nuxt-consumer"
|
|
280
282
|
&& esperadas.includes(rotaResolvida.origem));
|
|
281
283
|
const combina = encontradas.some((rotaResolvida) => rotaResolvida.metodo === route.metodo
|
|
282
284
|
&& normalizarCaminhoRota(rotaResolvida.caminho) === normalizarCaminhoRota(route.caminho));
|
package/dist/geracaoCore.js
CHANGED
|
@@ -87,6 +87,7 @@ export function normalizarFonteImportacao(valor) {
|
|
|
87
87
|
if (valor === "nestjs"
|
|
88
88
|
|| valor === "express"
|
|
89
89
|
|| valor === "fastify"
|
|
90
|
+
|| valor === "koa"
|
|
90
91
|
|| valor === "fastapi"
|
|
91
92
|
|| valor === "flask"
|
|
92
93
|
|| valor === "nextjs"
|
|
@@ -94,6 +95,8 @@ export function normalizarFonteImportacao(valor) {
|
|
|
94
95
|
|| valor === "react-vite-consumer"
|
|
95
96
|
|| valor === "angular-consumer"
|
|
96
97
|
|| valor === "flutter-consumer"
|
|
98
|
+
|| valor === "sveltekit-consumer"
|
|
99
|
+
|| valor === "nuxt-consumer"
|
|
97
100
|
|| valor === "firebase"
|
|
98
101
|
|| valor === "dotnet"
|
|
99
102
|
|| valor === "java"
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { type Diagnostico } from "@sema/nucleo";
|
|
3
|
-
export type FonteImportacao = "nestjs" | "express" | "fastify" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "firebase" | "typescript" | "python" | "dart" | "dotnet" | "java" | "go" | "rust" | "cpp" | "php";
|
|
3
|
+
export type FonteImportacao = "nestjs" | "express" | "fastify" | "koa" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "sveltekit-consumer" | "nuxt-consumer" | "firebase" | "typescript" | "python" | "dart" | "dotnet" | "java" | "go" | "rust" | "cpp" | "php";
|
|
4
4
|
export type OrigemInteropImportada = "ts" | "py" | "dart" | "cs" | "java" | "go" | "rust" | "cpp" | "php";
|
|
5
5
|
export interface CampoImportado {
|
|
6
6
|
nome: string;
|
|
@@ -11,8 +11,12 @@ export declare function extrairTasksBridgeConsumer(baseProjeto: string, contexto
|
|
|
11
11
|
enums: EnumImportado[];
|
|
12
12
|
};
|
|
13
13
|
export declare function montarVinculosSuperficiesConsumer(superficies: SuperficieConsumerImportada[]): VinculoImportado[];
|
|
14
|
-
export declare function importarConsumerBase(diretorio: string, namespaceBase: string, descricaoFramework: string, ehBridge: (relacaoArquivo: string) => boolean, coletarSuperficies: (baseProjeto: string, arquivos: string[]) => Promise<SuperficieConsumerImportada[]
|
|
14
|
+
export declare function importarConsumerBase(diretorio: string, namespaceBase: string, descricaoFramework: string, ehBridge: (relacaoArquivo: string) => boolean, coletarSuperficies: (baseProjeto: string, arquivos: string[]) => Promise<SuperficieConsumerImportada[]>, extensoes?: readonly string[]): Promise<ModuloImportado[]>;
|
|
15
15
|
export declare function coletarSuperficiesNextJsConsumer(baseProjeto: string, arquivos: string[]): Promise<SuperficieConsumerImportada[]>;
|
|
16
|
+
export declare function coletarSuperficiesSvelteKitConsumer(baseProjeto: string, arquivos: string[]): Promise<SuperficieConsumerImportada[]>;
|
|
17
|
+
export declare function coletarSuperficiesNuxtConsumer(baseProjeto: string, arquivos: string[]): Promise<SuperficieConsumerImportada[]>;
|
|
18
|
+
export declare function importarSvelteKitConsumerBase(diretorio: string, namespaceBase: string): Promise<ModuloImportado[]>;
|
|
19
|
+
export declare function importarNuxtConsumerBase(diretorio: string, namespaceBase: string): Promise<ModuloImportado[]>;
|
|
16
20
|
export declare function coletarSuperficiesReactViteConsumer(baseProjeto: string, arquivos: string[]): Promise<SuperficieConsumerImportada[]>;
|
|
17
21
|
export declare function coletarSuperficiesAngularConsumer(baseProjeto: string, arquivos: string[]): Promise<SuperficieConsumerImportada[]>;
|
|
18
22
|
export declare function importarNextJsConsumerBase(diretorio: string, namespaceBase: string): Promise<ModuloImportado[]>;
|
|
@@ -146,9 +146,9 @@ export function montarVinculosSuperficiesConsumer(superficies) {
|
|
|
146
146
|
{ tipo: "arquivo", valor: normalizarCaminhoImportado(superficie.arquivo) },
|
|
147
147
|
]));
|
|
148
148
|
}
|
|
149
|
-
export async function importarConsumerBase(diretorio, namespaceBase, descricaoFramework, ehBridge, coletarSuperficies) {
|
|
149
|
+
export async function importarConsumerBase(diretorio, namespaceBase, descricaoFramework, ehBridge, coletarSuperficies, extensoes = [".ts", ".tsx", ".js", ".jsx"]) {
|
|
150
150
|
const escopo = resolverEscopoImportacaoFrontendConsumer(diretorio);
|
|
151
|
-
const arquivos = await listarArquivosRecursivos(escopo.baseProjeto, [
|
|
151
|
+
const arquivos = await listarArquivosRecursivos(escopo.baseProjeto, [...extensoes]);
|
|
152
152
|
const arquivosBridge = arquivos.filter((arquivo) => ehBridge(path.relative(escopo.baseProjeto, arquivo)));
|
|
153
153
|
const contextosBridge = await carregarContextosBridgeConsumer(escopo.baseProjeto, arquivosBridge);
|
|
154
154
|
const { tasks, entities, enums } = extrairTasksBridgeConsumer(escopo.baseProjeto, contextosBridge);
|
|
@@ -175,6 +175,44 @@ export async function coletarSuperficiesNextJsConsumer(baseProjeto, arquivos) {
|
|
|
175
175
|
.map((arquivo) => inferirCaminhoNextJsConsumer(path.relative(baseProjeto, arquivo)))
|
|
176
176
|
.filter((item) => Boolean(item));
|
|
177
177
|
}
|
|
178
|
+
export async function coletarSuperficiesSvelteKitConsumer(baseProjeto, arquivos) {
|
|
179
|
+
const { arquivoEhSuperficieSvelteKitConsumer, inferirRotaSvelteKitConsumer } = await import("./drift.part05.js");
|
|
180
|
+
return arquivos
|
|
181
|
+
.map((arquivo) => {
|
|
182
|
+
const relacao = path.relative(baseProjeto, arquivo);
|
|
183
|
+
if (!arquivoEhSuperficieSvelteKitConsumer(relacao)) {
|
|
184
|
+
return undefined;
|
|
185
|
+
}
|
|
186
|
+
const superficie = inferirRotaSvelteKitConsumer(relacao);
|
|
187
|
+
return superficie
|
|
188
|
+
? { caminho: superficie.rota, arquivo: relacao, tipoArquivo: superficie.tipoArquivo }
|
|
189
|
+
: undefined;
|
|
190
|
+
})
|
|
191
|
+
.filter((item) => Boolean(item));
|
|
192
|
+
}
|
|
193
|
+
export async function coletarSuperficiesNuxtConsumer(baseProjeto, arquivos) {
|
|
194
|
+
const { arquivoEhSuperficieNuxtConsumer, inferirRotaNuxtConsumer } = await import("./drift.part05.js");
|
|
195
|
+
return arquivos
|
|
196
|
+
.map((arquivo) => {
|
|
197
|
+
const relacao = path.relative(baseProjeto, arquivo);
|
|
198
|
+
if (!arquivoEhSuperficieNuxtConsumer(relacao)) {
|
|
199
|
+
return undefined;
|
|
200
|
+
}
|
|
201
|
+
const superficie = inferirRotaNuxtConsumer(relacao);
|
|
202
|
+
return superficie
|
|
203
|
+
? { caminho: superficie.rota, arquivo: relacao, tipoArquivo: superficie.tipoArquivo }
|
|
204
|
+
: undefined;
|
|
205
|
+
})
|
|
206
|
+
.filter((item) => Boolean(item));
|
|
207
|
+
}
|
|
208
|
+
export async function importarSvelteKitConsumerBase(diretorio, namespaceBase) {
|
|
209
|
+
const { arquivoEhBridgeSvelteKitConsumer } = await import("./drift.part05.js");
|
|
210
|
+
return importarConsumerBase(diretorio, namespaceBase, "SvelteKit", arquivoEhBridgeSvelteKitConsumer, coletarSuperficiesSvelteKitConsumer, [".ts", ".js", ".svelte"]);
|
|
211
|
+
}
|
|
212
|
+
export async function importarNuxtConsumerBase(diretorio, namespaceBase) {
|
|
213
|
+
const { arquivoEhBridgeNuxtConsumer } = await import("./drift.part05.js");
|
|
214
|
+
return importarConsumerBase(diretorio, namespaceBase, "Nuxt", arquivoEhBridgeNuxtConsumer, coletarSuperficiesNuxtConsumer, [".ts", ".js", ".vue"]);
|
|
215
|
+
}
|
|
178
216
|
export async function coletarSuperficiesReactViteConsumer(baseProjeto, arquivos) {
|
|
179
217
|
const superficies = [];
|
|
180
218
|
for (const arquivo of arquivos) {
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import { extrairRotasTypeScriptHttp } from "./typescript-http.js";
|
|
2
2
|
import { CampoImportado, ModuloImportado, TipoDescoberto } from "./importador.part01.js";
|
|
3
3
|
export declare function importarNestJsDeArquivo(diretorioBase: string, arquivo: string, namespaceBase: string, tiposGlobais: Map<string, TipoDescoberto>): ModuloImportado[];
|
|
4
|
-
export declare function importarExpressFastifyDeArquivo(diretorioBase: string, arquivo: string, namespaceBase: string, origemDesejada: "express" | "fastify"): ModuloImportado[];
|
|
5
|
-
export declare function importarExpressFastifyBase(diretorio: string, namespaceBase: string, origem: "express" | "fastify"): Promise<ModuloImportado[]>;
|
|
4
|
+
export declare function importarExpressFastifyDeArquivo(diretorioBase: string, arquivo: string, namespaceBase: string, origemDesejada: "express" | "fastify" | "koa"): ModuloImportado[];
|
|
5
|
+
export declare function importarExpressFastifyBase(diretorio: string, namespaceBase: string, origem: "express" | "fastify" | "koa"): Promise<ModuloImportado[]>;
|
|
6
6
|
export declare function importarTypeScriptBase(diretorio: string, namespaceBase: string, modoNestjs?: boolean): Promise<ModuloImportado[]>;
|
|
7
7
|
export declare function nomeTaskParaRotaTypeScript(caminho: string, metodo: string): string;
|
|
8
8
|
export declare function camposDeParametrosRotaTypeScript(parametros: ReturnType<typeof extrairRotasTypeScriptHttp>[number]["parametros"]): CampoImportado[];
|
|
@@ -132,15 +132,29 @@ export function importarExpressFastifyDeArquivo(diretorioBase, arquivo, namespac
|
|
|
132
132
|
for (const rota of rotasArquivo) {
|
|
133
133
|
const taskNome = nomearTarefaRotaChamada(rota.metodo, rota.caminho);
|
|
134
134
|
const implSimbolo = /^[A-Za-z_]\w*$/.test(rota.simbolo) ? rota.simbolo : undefined;
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
135
|
+
const semantica = implSimbolo
|
|
136
|
+
? inferirSemanticaHandlerTypeScriptHttp(sourceFile, implSimbolo, true)
|
|
137
|
+
: undefined;
|
|
138
|
+
const converterCampoInferido = (campo) => ({
|
|
139
|
+
nome: campo.nome,
|
|
140
|
+
tipo: mapearTipoPrimitivo(campo.tipoTexto ?? "string") === "Vazio" ? "Texto" : mapearTipoPrimitivo(campo.tipoTexto ?? "string"),
|
|
141
|
+
obrigatorio: campo.obrigatorio,
|
|
142
|
+
});
|
|
143
|
+
const camposInferidos = deduplicarCampos([
|
|
144
|
+
...rota.parametros.map((parametro) => ({
|
|
139
145
|
nome: parametro.nome,
|
|
140
146
|
tipo: parametro.tipoSema,
|
|
141
147
|
obrigatorio: true,
|
|
142
148
|
})),
|
|
143
|
-
|
|
149
|
+
...(semantica?.query ?? []).map(converterCampoInferido),
|
|
150
|
+
...(semantica?.body ?? []).map(converterCampoInferido),
|
|
151
|
+
]);
|
|
152
|
+
const camposResposta = deduplicarCampos((semantica?.response ?? []).map(converterCampoInferido));
|
|
153
|
+
tasks.push({
|
|
154
|
+
nome: taskNome,
|
|
155
|
+
resumo: `Task importada automaticamente da rota ${rota.metodo} ${rota.caminho} em ${relacao}.`,
|
|
156
|
+
input: camposInferidos,
|
|
157
|
+
output: camposResposta,
|
|
144
158
|
errors: [],
|
|
145
159
|
effects: [],
|
|
146
160
|
impl: implSimbolo ? { ts: caminhoImplTs(diretorioBase, arquivo, implSimbolo) } : undefined,
|
|
@@ -153,12 +167,8 @@ export function importarExpressFastifyDeArquivo(diretorioBase, arquivo, namespac
|
|
|
153
167
|
metodo: rota.metodo,
|
|
154
168
|
caminho: rota.caminho,
|
|
155
169
|
task: taskNome,
|
|
156
|
-
input:
|
|
157
|
-
|
|
158
|
-
tipo: parametro.tipoSema,
|
|
159
|
-
obrigatorio: true,
|
|
160
|
-
})),
|
|
161
|
-
output: [],
|
|
170
|
+
input: camposInferidos,
|
|
171
|
+
output: camposResposta,
|
|
162
172
|
errors: [],
|
|
163
173
|
});
|
|
164
174
|
}
|
|
@@ -166,7 +176,7 @@ export function importarExpressFastifyDeArquivo(diretorioBase, arquivo, namespac
|
|
|
166
176
|
sincronizarRotasComTasks(routes, tasks);
|
|
167
177
|
return [{
|
|
168
178
|
nome: nomeModulo,
|
|
169
|
-
resumo: `Rascunho Sema importado de um contexto ${origemDesejada === "express" ? "Express" : "Fastify"} legado em ${contextoSegmentos.join("/")}.`,
|
|
179
|
+
resumo: `Rascunho Sema importado de um contexto ${origemDesejada === "express" ? "Express" : origemDesejada === "koa" ? "Koa" : "Fastify"} legado em ${contextoSegmentos.join("/")}.`,
|
|
170
180
|
entities,
|
|
171
181
|
enums,
|
|
172
182
|
tasks: deduplicarTarefas(tasks),
|
|
@@ -13,7 +13,7 @@ import { camposDeParametrosRotaBackend, criarCampoResultadoBackend, descreverEfe
|
|
|
13
13
|
import { caminhoImplGenerico, importarFirebaseBase } from "./importador.part07.js";
|
|
14
14
|
import { acumularModuloImportado, criarModuloImportadoSimples, importarDartBase, importarDotnetBase, importarPythonBase, resolverArquivoRustParaSimbolo, selecionarSimbolosPreferidos } from "./importador.part08.js";
|
|
15
15
|
import { importarExpressFastifyBase, importarNextJsBase, importarTypeScriptBase } from "./importador.part06.js";
|
|
16
|
-
import { importarAngularConsumerBase, importarFlutterConsumerBase, importarNextJsConsumerBase, importarReactViteConsumerBase } from "./importador.part04.js";
|
|
16
|
+
import { importarAngularConsumerBase, importarFlutterConsumerBase, importarNextJsConsumerBase, importarReactViteConsumerBase, importarNuxtConsumerBase, importarSvelteKitConsumerBase } from "./importador.part04.js";
|
|
17
17
|
import { formatarModuloImportado, moduloParaCodigo, montarArquivoImportado } from "./importador.part05.js";
|
|
18
18
|
export async function importarJavaBase(diretorio, namespaceBase) {
|
|
19
19
|
const arquivos = (await listarArquivosRecursivos(diretorio, [".java"]))
|
|
@@ -306,6 +306,9 @@ export async function importarProjetoLegado(fonte, diretorio, namespaceBase) {
|
|
|
306
306
|
else if (fonte === "fastify") {
|
|
307
307
|
modulos = await importarExpressFastifyBase(base, namespace, "fastify");
|
|
308
308
|
}
|
|
309
|
+
else if (fonte === "koa") {
|
|
310
|
+
modulos = await importarExpressFastifyBase(base, namespace, "koa");
|
|
311
|
+
}
|
|
309
312
|
else if (fonte === "nextjs") {
|
|
310
313
|
modulos = await importarNextJsBase(base, namespace);
|
|
311
314
|
}
|
|
@@ -321,6 +324,12 @@ export async function importarProjetoLegado(fonte, diretorio, namespaceBase) {
|
|
|
321
324
|
else if (fonte === "flutter-consumer") {
|
|
322
325
|
modulos = await importarFlutterConsumerBase(base, namespace);
|
|
323
326
|
}
|
|
327
|
+
else if (fonte === "sveltekit-consumer") {
|
|
328
|
+
modulos = await importarSvelteKitConsumerBase(base, namespace);
|
|
329
|
+
}
|
|
330
|
+
else if (fonte === "nuxt-consumer") {
|
|
331
|
+
modulos = await importarNuxtConsumerBase(base, namespace);
|
|
332
|
+
}
|
|
324
333
|
else if (fonte === "firebase") {
|
|
325
334
|
modulos = await importarFirebaseBase(base, namespace);
|
|
326
335
|
}
|
package/dist/projetoConfig.js
CHANGED
|
@@ -76,6 +76,7 @@ export function normalizarFonteLegado(valor) {
|
|
|
76
76
|
if (valor === "nestjs"
|
|
77
77
|
|| valor === "express"
|
|
78
78
|
|| valor === "fastify"
|
|
79
|
+
|| valor === "koa"
|
|
79
80
|
|| valor === "fastapi"
|
|
80
81
|
|| valor === "flask"
|
|
81
82
|
|| valor === "nextjs"
|
|
@@ -83,6 +84,8 @@ export function normalizarFonteLegado(valor) {
|
|
|
83
84
|
|| valor === "react-vite-consumer"
|
|
84
85
|
|| valor === "angular-consumer"
|
|
85
86
|
|| valor === "flutter-consumer"
|
|
87
|
+
|| valor === "sveltekit-consumer"
|
|
88
|
+
|| valor === "nuxt-consumer"
|
|
86
89
|
|| valor === "firebase"
|
|
87
90
|
|| valor === "typescript"
|
|
88
91
|
|| valor === "javascript"
|
package/dist/projetoLegado.js
CHANGED
|
@@ -25,6 +25,10 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
25
25
|
encontrados.add("fastify");
|
|
26
26
|
encontrados.add("typescript");
|
|
27
27
|
}
|
|
28
|
+
if (/"koa"\s*:|@koa\/router|"koa-router"/.test(packageJsonRaiz)) {
|
|
29
|
+
encontrados.add("koa");
|
|
30
|
+
encontrados.add("typescript");
|
|
31
|
+
}
|
|
28
32
|
if (/typescript/.test(packageJsonRaiz)) {
|
|
29
33
|
encontrados.add("typescript");
|
|
30
34
|
}
|
|
@@ -51,6 +55,8 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
51
55
|
const arquivosJava = await listarArquivosRecursivosLimitado(diretorio, [".java"], 5, 20);
|
|
52
56
|
const arquivosGo = await listarArquivosRecursivosLimitado(diretorio, [".go"], 5, 20);
|
|
53
57
|
const arquivosRust = await listarArquivosRecursivosLimitado(diretorio, [".rs"], 5, 20);
|
|
58
|
+
const arquivosVueSvelte = await listarArquivosRecursivosLimitado(diretorio, [".vue", ".svelte"], 5, 40);
|
|
59
|
+
const relacoesVueSvelte = arquivosVueSvelte.map((arquivo) => path.relative(diretorio, arquivo).replace(/\\/g, "/"));
|
|
54
60
|
const arquivosCppBrutos = await listarArquivosRecursivosLimitado(diretorio, [".cpp", ".cc", ".cxx", ".hpp", ".h"], 5, 30);
|
|
55
61
|
const arquivosCpp = arquivosCppBrutos.filter((arquivo) => !/(^|[\\/])(windows|linux|macos|runner|flutter|ephemeral|build|vendor)([\\/]|$)/i.test(arquivo));
|
|
56
62
|
const arquivosPhp = (await listarArquivosRecursivosLimitado(diretorio, [".php"], 5, 30))
|
|
@@ -76,6 +82,8 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
76
82
|
|| amostrasTs.some((texto) => /(?:from\s+["']express["']|require\(\s*["']express["']\s*\)|\bexpress\s*\(\s*\))/.test(texto ?? ""));
|
|
77
83
|
const temFastify = textosPackage.some((texto) => /"fastify"\s*:/.test(texto ?? ""))
|
|
78
84
|
|| amostrasTs.some((texto) => /(?:from\s+["']fastify["']|require\(\s*["']fastify["']\s*\)|\bfastify\s*\(\s*\{)/.test(texto ?? ""));
|
|
85
|
+
const temKoa = textosPackage.some((texto) => /"koa"\s*:|@koa\/router|"koa-router"/.test(texto ?? ""))
|
|
86
|
+
|| amostrasTs.some((texto) => /(?:from\s+["'](?:@koa\/router|koa-router|koa)["']|require\(\s*["'](?:@koa\/router|koa-router|koa)["']\s*\)|new\s+Router\s*\()/.test(texto ?? ""));
|
|
79
87
|
const temNext = textosPackage.some((texto) => /"next"\s*:/.test(texto ?? ""))
|
|
80
88
|
|| nextConfigs.length > 0
|
|
81
89
|
|| relacoesTs.some((relacao) => /(?:^|\/)(?:src\/)?app\/api\/.+\/route\.(?:ts|tsx|js|jsx)$/.test(relacao));
|
|
@@ -89,6 +97,11 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
89
97
|
const temSuperficieAngularConsumer = relacoesTs.some((relacao) => /(?:^|\/)(?:src\/)?app\/.+\.component\.(?:ts|js)$/.test(relacao))
|
|
90
98
|
|| relacoesTs.some((relacao) => /(?:^|\/)(?:src\/)?app(?:\/.+)?\/[^/]+\.routes\.(?:ts|js)$/.test(relacao));
|
|
91
99
|
const temBridgeAngularConsumer = relacoesTs.some((relacao) => /(?:^|\/)(?:src\/)?app\/(?:sema_consumer_bridge|sema\/.+)\.(?:ts|js)$/.test(relacao));
|
|
100
|
+
const temSvelteKitConsumer = relacoesVueSvelte.some((relacao) => /(?:^|\/)(?:src\/)?routes\/(?:[^/]+\/)*\+(?:page|layout|error|server)\.svelte$/i.test(relacao))
|
|
101
|
+
|| relacoesTs.some((relacao) => /(?:^|\/)(?:src\/)?routes\/(?:[^/]+\/)*\+(?:page|server)\.(?:ts|js)$/i.test(relacao))
|
|
102
|
+
|| textosPackage.some((texto) => /@sveltejs\/kit/.test(texto ?? ""));
|
|
103
|
+
const temNuxtConsumer = relacoesVueSvelte.some((relacao) => /^(?:app\/)?pages\/.+\.vue$/i.test(relacao))
|
|
104
|
+
|| textosPackage.some((texto) => /"nuxt"\s*:/.test(texto ?? ""));
|
|
92
105
|
const temAngularConsumer = temSuperficieAngularConsumer
|
|
93
106
|
|| ((textosPackage.some((texto) => /@angular\/core|@angular\/router/.test(texto ?? "")) || angularConfigs.length > 0) && temBridgeAngularConsumer);
|
|
94
107
|
const temFirebase = marcadoresFirebaseProjeto.length > 0
|
|
@@ -104,6 +117,9 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
104
117
|
if (temFastify) {
|
|
105
118
|
encontrados.add("fastify");
|
|
106
119
|
}
|
|
120
|
+
if (temKoa) {
|
|
121
|
+
encontrados.add("koa");
|
|
122
|
+
}
|
|
107
123
|
if (temNext) {
|
|
108
124
|
encontrados.add("nextjs");
|
|
109
125
|
}
|
|
@@ -116,6 +132,12 @@ export async function inferirFontesLegado(diretoriosCodigo, baseProjeto, configC
|
|
|
116
132
|
if (temAngularConsumer) {
|
|
117
133
|
encontrados.add("angular-consumer");
|
|
118
134
|
}
|
|
135
|
+
if (temSvelteKitConsumer) {
|
|
136
|
+
encontrados.add("sveltekit-consumer");
|
|
137
|
+
}
|
|
138
|
+
if (temNuxtConsumer) {
|
|
139
|
+
encontrados.add("nuxt-consumer");
|
|
140
|
+
}
|
|
119
141
|
if (temFirebase) {
|
|
120
142
|
encontrados.add("firebase");
|
|
121
143
|
}
|
package/dist/projetoOrigens.js
CHANGED
|
@@ -52,8 +52,14 @@ async function resolverDiretoriosConfiguradosConfinados(baseProjeto, baseConfigu
|
|
|
52
52
|
let canonico = absoluto;
|
|
53
53
|
try {
|
|
54
54
|
const [real, informacao] = await Promise.all([realpath(absoluto), stat(absoluto)]);
|
|
55
|
-
|
|
56
|
-
|
|
55
|
+
const ehContratoIndividual = campo === "origens"
|
|
56
|
+
&& informacao.isFile()
|
|
57
|
+
&& absoluto.toLowerCase().endsWith(".sema");
|
|
58
|
+
if (!informacao.isDirectory() && !ehContratoIndividual) {
|
|
59
|
+
const esperado = campo === "origens"
|
|
60
|
+
? "um diretorio de contratos (ex.: ./contratos) ou um arquivo .sema individual"
|
|
61
|
+
: "um diretorio de codigo vivo";
|
|
62
|
+
throw new Error(`${identificadorSeguro} nao e ${esperado}. Corrija "${campo}" no sema.config.json; configuracoes geradas por versoes antigas da CLI podem listar arquivos direto.`);
|
|
57
63
|
}
|
|
58
64
|
if (!caminhoEstaDentro(baseReal, real)) {
|
|
59
65
|
throw new Error(`${identificadorSeguro} resolve fora da base do projeto`);
|
package/dist/tipos.d.ts
CHANGED
|
@@ -1,3 +1,3 @@
|
|
|
1
1
|
export type EstruturaSaida = "flat" | "modulos" | "backend";
|
|
2
|
-
export type FonteLegado = "nestjs" | "express" | "fastify" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "firebase" | "typescript" | "javascript" | "python" | "dart" | "lua" | "dotnet" | "java" | "go" | "rust" | "cpp" | "php";
|
|
2
|
+
export type FonteLegado = "nestjs" | "express" | "fastify" | "koa" | "fastapi" | "flask" | "nextjs" | "nextjs-consumer" | "react-vite-consumer" | "angular-consumer" | "flutter-consumer" | "sveltekit-consumer" | "nuxt-consumer" | "firebase" | "typescript" | "javascript" | "python" | "dart" | "lua" | "dotnet" | "java" | "go" | "rust" | "cpp" | "php";
|
|
3
3
|
export type ModoAdocao = "incremental";
|
|
@@ -8,6 +8,15 @@ export function resolverMetadadosOrigemBody(expr, sourceFile, requestNames, body
|
|
|
8
8
|
if (ts.isIdentifier(normalizado) && bodyAliases.has(normalizado.text)) {
|
|
9
9
|
return bodyAliases.get(normalizado.text);
|
|
10
10
|
}
|
|
11
|
+
if (ts.isPropertyAccessExpression(normalizado)
|
|
12
|
+
&& normalizado.name.text === "body"
|
|
13
|
+
&& ts.isIdentifier(normalizado.expression)
|
|
14
|
+
&& requestNames.has(normalizado.expression.text)) {
|
|
15
|
+
return {
|
|
16
|
+
tipoTexto: typeNodeDeclarado?.getText(sourceFile),
|
|
17
|
+
campos: [],
|
|
18
|
+
};
|
|
19
|
+
}
|
|
11
20
|
if (ehCallRequest(expr, requestNames, "json")) {
|
|
12
21
|
return extrairMetadadosTipoExplicito(expr, sourceFile, typeNodeDeclarado);
|
|
13
22
|
}
|
|
@@ -4,7 +4,7 @@ export interface ParametroRotaTypeScript {
|
|
|
4
4
|
tipoSema: "Texto" | "Inteiro" | "Decimal" | "Id";
|
|
5
5
|
}
|
|
6
6
|
export interface RotaTypeScriptExtraida {
|
|
7
|
-
origem: "nextjs" | "firebase" | "express" | "fastify";
|
|
7
|
+
origem: "nextjs" | "firebase" | "express" | "fastify" | "koa";
|
|
8
8
|
metodo: string;
|
|
9
9
|
caminho: string;
|
|
10
10
|
simbolo: string;
|
|
@@ -109,13 +109,114 @@ export function extrairRotasNodeWorker(sourceFile, relacaoArquivo) {
|
|
|
109
109
|
}
|
|
110
110
|
return deduplicarRotas(rotas);
|
|
111
111
|
}
|
|
112
|
+
function combinarCaminhoPrefixo(base, sufixo) {
|
|
113
|
+
const prefixo = (base ?? "").replace(/\/+$/u, "");
|
|
114
|
+
const caminho = sufixo.startsWith("/") ? sufixo : `/${sufixo}`;
|
|
115
|
+
const combinado = `${prefixo}${caminho}`.replace(/\/{2,}/gu, "/");
|
|
116
|
+
return combinado.length > 1 && combinado.endsWith("/") ? combinado.slice(0, -1) : combinado;
|
|
117
|
+
}
|
|
118
|
+
function extrairPrefixoRegister(node) {
|
|
119
|
+
const opcoes = node.arguments[1];
|
|
120
|
+
if (!opcoes || !ts.isObjectLiteralExpression(opcoes)) {
|
|
121
|
+
return undefined;
|
|
122
|
+
}
|
|
123
|
+
for (const propriedade of opcoes.properties) {
|
|
124
|
+
if (ts.isPropertyAssignment(propriedade)
|
|
125
|
+
&& ts.isIdentifier(propriedade.name)
|
|
126
|
+
&& propriedade.name.text === "prefix"
|
|
127
|
+
&& propriedade.initializer
|
|
128
|
+
&& ts.isStringLiteralLike(propriedade.initializer)) {
|
|
129
|
+
return propriedade.initializer.text;
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
return undefined;
|
|
133
|
+
}
|
|
112
134
|
export function extrairRotasExpressFastify(sourceFile) {
|
|
113
135
|
const textoArquivo = sourceFile.getFullText();
|
|
114
136
|
const importouExpress = /(?:from\s+["']express["']|require\(\s*["']express["']\s*\))/.test(textoArquivo);
|
|
115
137
|
const importouFastify = /(?:from\s+["']fastify["']|require\(\s*["']fastify["']\s*\))/.test(textoArquivo);
|
|
116
|
-
|
|
138
|
+
const importouKoa = /(?:from\s+["'](?:@koa\/router|koa-router|koa)["']|require\(\s*["'](?:@koa\/router|koa-router|koa)["']\s*\))/.test(textoArquivo);
|
|
139
|
+
if (!importouExpress && !importouFastify && !importouKoa) {
|
|
117
140
|
return [];
|
|
118
141
|
}
|
|
142
|
+
const arestasMontagem = [];
|
|
143
|
+
const prefixoDireto = new Map();
|
|
144
|
+
const prefixoPorParametro = new Map();
|
|
145
|
+
const prefixoResolvido = new Map();
|
|
146
|
+
const resolverPrefixo = (receptor, profundidade = 0) => {
|
|
147
|
+
if (prefixoResolvido.has(receptor)) {
|
|
148
|
+
return prefixoResolvido.get(receptor);
|
|
149
|
+
}
|
|
150
|
+
if (profundidade > 8) {
|
|
151
|
+
return "";
|
|
152
|
+
}
|
|
153
|
+
let prefixo = prefixoDireto.get(receptor) ?? "";
|
|
154
|
+
const aresta = arestasMontagem.find((item) => item.filho === receptor);
|
|
155
|
+
if (aresta) {
|
|
156
|
+
prefixo = combinarCaminhoPrefixo(resolverPrefixo(aresta.pai, profundidade + 1), aresta.prefixo);
|
|
157
|
+
}
|
|
158
|
+
prefixoResolvido.set(receptor, prefixo);
|
|
159
|
+
return prefixo;
|
|
160
|
+
};
|
|
161
|
+
const visitarMontagens = (node) => {
|
|
162
|
+
if (ts.isVariableStatement(node)) {
|
|
163
|
+
for (const declaracao of node.declarationList.declarations) {
|
|
164
|
+
if (!ts.isIdentifier(declaracao.name) || !declaracao.initializer) {
|
|
165
|
+
continue;
|
|
166
|
+
}
|
|
167
|
+
const init = declaracao.initializer;
|
|
168
|
+
const argumentoFastify = ts.isCallExpression(init)
|
|
169
|
+
&& ts.isIdentifier(init.expression)
|
|
170
|
+
&& /fastify/i.test(init.expression.text)
|
|
171
|
+
&& init.arguments[0]
|
|
172
|
+
&& ts.isObjectLiteralExpression(init.arguments[0])
|
|
173
|
+
? init.arguments[0]
|
|
174
|
+
: undefined;
|
|
175
|
+
if (argumentoFastify) {
|
|
176
|
+
for (const propriedade of argumentoFastify.properties) {
|
|
177
|
+
if (ts.isPropertyAssignment(propriedade)
|
|
178
|
+
&& ts.isIdentifier(propriedade.name)
|
|
179
|
+
&& propriedade.name.text === "prefix"
|
|
180
|
+
&& propriedade.initializer
|
|
181
|
+
&& ts.isStringLiteralLike(propriedade.initializer)) {
|
|
182
|
+
prefixoDireto.set(declaracao.name.text, propriedade.initializer.text);
|
|
183
|
+
}
|
|
184
|
+
}
|
|
185
|
+
}
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression)) {
|
|
189
|
+
const receptor = node.expression.expression.text;
|
|
190
|
+
const nomeMetodo = node.expression.name.text.toLowerCase();
|
|
191
|
+
if (nomeMetodo === "use"
|
|
192
|
+
&& node.arguments[0]
|
|
193
|
+
&& ts.isStringLiteralLike(node.arguments[0])
|
|
194
|
+
&& node.arguments[0].text.startsWith("/")
|
|
195
|
+
&& node.arguments[1]
|
|
196
|
+
&& ts.isIdentifier(node.arguments[1])) {
|
|
197
|
+
arestasMontagem.push({ pai: receptor, filho: node.arguments[1].text, prefixo: node.arguments[0].text });
|
|
198
|
+
}
|
|
199
|
+
else if (nomeMetodo === "prefix"
|
|
200
|
+
&& node.arguments[0]
|
|
201
|
+
&& ts.isStringLiteralLike(node.arguments[0])
|
|
202
|
+
&& node.arguments[0].text.startsWith("/")) {
|
|
203
|
+
prefixoDireto.set(receptor, combinarCaminhoPrefixo(node.arguments[0].text, prefixoDireto.get(receptor) ?? ""));
|
|
204
|
+
}
|
|
205
|
+
else if (nomeMetodo === "register" && importouFastify) {
|
|
206
|
+
const prefixo = extrairPrefixoRegister(node);
|
|
207
|
+
const alvo = node.arguments[0];
|
|
208
|
+
if (prefixo && alvo) {
|
|
209
|
+
const funcao = ts.isFunctionExpression(alvo) || ts.isArrowFunction(alvo) ? alvo : undefined;
|
|
210
|
+
const parametro = funcao?.parameters[0];
|
|
211
|
+
if (parametro && ts.isIdentifier(parametro.name)) {
|
|
212
|
+
prefixoPorParametro.set(parametro.name.text, prefixo);
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
node.forEachChild(visitarMontagens);
|
|
218
|
+
};
|
|
219
|
+
visitarMontagens(sourceFile);
|
|
119
220
|
const rotas = [];
|
|
120
221
|
const escolherOrigemChamada = (receptor) => {
|
|
121
222
|
if (/fastify/i.test(receptor)) {
|
|
@@ -124,7 +225,10 @@ export function extrairRotasExpressFastify(sourceFile) {
|
|
|
124
225
|
if (importouExpress) {
|
|
125
226
|
return "express";
|
|
126
227
|
}
|
|
127
|
-
if (
|
|
228
|
+
if (importouKoa) {
|
|
229
|
+
return "koa";
|
|
230
|
+
}
|
|
231
|
+
if (importouFastify || prefixoPorParametro.has(receptor)) {
|
|
128
232
|
return "fastify";
|
|
129
233
|
}
|
|
130
234
|
return undefined;
|
|
@@ -133,6 +237,7 @@ export function extrairRotasExpressFastify(sourceFile) {
|
|
|
133
237
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && ts.isIdentifier(node.expression.expression)) {
|
|
134
238
|
const receptor = node.expression.expression.text;
|
|
135
239
|
const nomeMetodo = node.expression.name.text.toLowerCase();
|
|
240
|
+
const prefixoReceptor = prefixoPorParametro.get(receptor) ?? resolverPrefixo(receptor);
|
|
136
241
|
if (nomeMetodo === "route" && node.arguments[0] && ts.isObjectLiteralExpression(node.arguments[0]) && importouFastify) {
|
|
137
242
|
let metodo;
|
|
138
243
|
let caminho;
|
|
@@ -154,13 +259,13 @@ export function extrairRotasExpressFastify(sourceFile) {
|
|
|
154
259
|
rotas.push({
|
|
155
260
|
origem: "fastify",
|
|
156
261
|
metodo,
|
|
157
|
-
caminho: converterCaminhoParametros(caminho),
|
|
262
|
+
caminho: converterCaminhoParametros(combinarCaminhoPrefixo(prefixoReceptor, caminho)),
|
|
158
263
|
simbolo: receptor,
|
|
159
264
|
parametros: extrairParametrosCaminhoDoisPontos(caminho),
|
|
160
265
|
});
|
|
161
266
|
}
|
|
162
267
|
}
|
|
163
|
-
else if (nomeMetodo === "all" || METODOS_HTTP.has(nomeMetodo.toUpperCase())) {
|
|
268
|
+
else if (nomeMetodo === "all" || nomeMetodo === "del" || METODOS_HTTP.has(nomeMetodo.toUpperCase())) {
|
|
164
269
|
const caminho = node.arguments[0] && ts.isStringLiteralLike(node.arguments[0])
|
|
165
270
|
? node.arguments[0].text
|
|
166
271
|
: undefined;
|
|
@@ -169,14 +274,14 @@ export function extrairRotasExpressFastify(sourceFile) {
|
|
|
169
274
|
if (caminho?.startsWith("/") && origem) {
|
|
170
275
|
const metodos = nomeMetodo === "all"
|
|
171
276
|
? ["GET", "POST", "PUT", "PATCH", "DELETE"]
|
|
172
|
-
: [nomeMetodo.toUpperCase()];
|
|
277
|
+
: [nomeMetodo === "del" ? "DELETE" : nomeMetodo.toUpperCase()];
|
|
173
278
|
for (const metodo of metodos) {
|
|
174
279
|
rotas.push({
|
|
175
280
|
origem,
|
|
176
281
|
metodo,
|
|
177
|
-
caminho: converterCaminhoParametros(caminho),
|
|
282
|
+
caminho: converterCaminhoParametros(combinarCaminhoPrefixo(prefixoReceptor, caminho)),
|
|
178
283
|
simbolo: handler ?? receptor,
|
|
179
|
-
parametros: extrairParametrosCaminhoDoisPontos(caminho),
|
|
284
|
+
parametros: extrairParametrosCaminhoDoisPontos(combinarCaminhoPrefixo(prefixoReceptor, caminho)),
|
|
180
285
|
});
|
|
181
286
|
}
|
|
182
287
|
}
|
|
@@ -1,11 +1,11 @@
|
|
|
1
1
|
import ts from "typescript";
|
|
2
2
|
import { type CampoInferidoTypeScriptHttp, type ExportacaoTypeScriptHttp, type SemanticaHandlerTypeScriptHttp, type ValorLocalTypeScriptHttp } from "./typescript-http-modelos.js";
|
|
3
|
-
export declare function localizarExportacaoEmStatement(statement: ts.Statement, nomeExportado: string, sourceFile: ts.SourceFile): ExportacaoTypeScriptHttp | undefined;
|
|
3
|
+
export declare function localizarExportacaoEmStatement(statement: ts.Statement, nomeExportado: string, sourceFile: ts.SourceFile, permitirNaoExportada?: boolean): ExportacaoTypeScriptHttp | undefined;
|
|
4
4
|
export declare function inferirTipoPorContexto(node: ts.Node, nomeCampo: string): string | undefined;
|
|
5
5
|
export declare function extrairRetornoHttp(expr: ts.Expression, sourceFile: ts.SourceFile, valoresLocais: Map<string, ValorLocalTypeScriptHttp>): {
|
|
6
6
|
campos: CampoInferidoTypeScriptHttp[];
|
|
7
7
|
tipoTexto?: string;
|
|
8
8
|
status?: number;
|
|
9
9
|
} | undefined;
|
|
10
|
-
export declare function localizarExportacaoTypeScriptHttp(sourceFile: ts.SourceFile, nomeExportado: string): ExportacaoTypeScriptHttp | undefined;
|
|
11
|
-
export declare function inferirSemanticaHandlerTypeScriptHttp(sourceFile: ts.SourceFile, nomeExportado: string): SemanticaHandlerTypeScriptHttp | undefined;
|
|
10
|
+
export declare function localizarExportacaoTypeScriptHttp(sourceFile: ts.SourceFile, nomeExportado: string, permitirNaoExportada?: boolean): ExportacaoTypeScriptHttp | undefined;
|
|
11
|
+
export declare function inferirSemanticaHandlerTypeScriptHttp(sourceFile: ts.SourceFile, nomeExportado: string, permitirNaoExportada?: boolean): SemanticaHandlerTypeScriptHttp | undefined;
|
|
@@ -4,8 +4,10 @@ import ts from "typescript";
|
|
|
4
4
|
import { deduplicarCampos, deduplicarNumeros, desembrulharExpressao, } from "./typescript-http-modelos.js";
|
|
5
5
|
import { ehCallRequest, ehNewUrl, ehSearchParamsSource, extrairCamposObjetoLiteral, extrairMetadadosTipoExplicito, extrairStatusHttp, obterNomeSchema, tipoInferidoPorNomeCampo, } from "./typescript-http-expressoes.js";
|
|
6
6
|
import { extrairCamposBindingPattern, extrairSchemasZodLocais, resolverMetadadosOrigemBody, } from "./typescript-http-body.js";
|
|
7
|
-
export function localizarExportacaoEmStatement(statement, nomeExportado, sourceFile) {
|
|
8
|
-
|
|
7
|
+
export function localizarExportacaoEmStatement(statement, nomeExportado, sourceFile, permitirNaoExportada = false) {
|
|
8
|
+
const declarada = (statement) => permitirNaoExportada
|
|
9
|
+
|| statement.modifiers?.some((modifier) => modifier.kind === ts.SyntaxKind.ExportKeyword) === true;
|
|
10
|
+
if (ts.isFunctionDeclaration(statement) && statement.name?.text === nomeExportado && declarada(statement)) {
|
|
9
11
|
return {
|
|
10
12
|
corpo: statement.body,
|
|
11
13
|
retorno: statement.type?.getText(sourceFile),
|
|
@@ -13,7 +15,7 @@ export function localizarExportacaoEmStatement(statement, nomeExportado, sourceF
|
|
|
13
15
|
declaracao: statement,
|
|
14
16
|
};
|
|
15
17
|
}
|
|
16
|
-
if (!ts.isVariableStatement(statement) || !statement
|
|
18
|
+
if (!ts.isVariableStatement(statement) || !declarada(statement)) {
|
|
17
19
|
return undefined;
|
|
18
20
|
}
|
|
19
21
|
for (const declaracao of statement.declarationList.declarations) {
|
|
@@ -110,17 +112,17 @@ export function extrairRetornoHttp(expr, sourceFile, valoresLocais) {
|
|
|
110
112
|
}
|
|
111
113
|
return undefined;
|
|
112
114
|
}
|
|
113
|
-
export function localizarExportacaoTypeScriptHttp(sourceFile, nomeExportado) {
|
|
115
|
+
export function localizarExportacaoTypeScriptHttp(sourceFile, nomeExportado, permitirNaoExportada = false) {
|
|
114
116
|
for (const node of sourceFile.statements) {
|
|
115
|
-
const localizada = localizarExportacaoEmStatement(node, nomeExportado, sourceFile);
|
|
117
|
+
const localizada = localizarExportacaoEmStatement(node, nomeExportado, sourceFile, permitirNaoExportada);
|
|
116
118
|
if (localizada) {
|
|
117
119
|
return localizada;
|
|
118
120
|
}
|
|
119
121
|
}
|
|
120
122
|
return undefined;
|
|
121
123
|
}
|
|
122
|
-
export function inferirSemanticaHandlerTypeScriptHttp(sourceFile, nomeExportado) {
|
|
123
|
-
const exportacao = localizarExportacaoTypeScriptHttp(sourceFile, nomeExportado);
|
|
124
|
+
export function inferirSemanticaHandlerTypeScriptHttp(sourceFile, nomeExportado, permitirNaoExportada = false) {
|
|
125
|
+
const exportacao = localizarExportacaoTypeScriptHttp(sourceFile, nomeExportado, permitirNaoExportada);
|
|
124
126
|
if (!exportacao?.corpo) {
|
|
125
127
|
return undefined;
|
|
126
128
|
}
|
|
@@ -139,6 +141,12 @@ export function inferirSemanticaHandlerTypeScriptHttp(sourceFile, nomeExportado)
|
|
|
139
141
|
requestNames.add(parametro.name.text);
|
|
140
142
|
}
|
|
141
143
|
}
|
|
144
|
+
const responseNames = new Set();
|
|
145
|
+
for (const [indice, parametro] of exportacao.parametros.entries()) {
|
|
146
|
+
if (indice > 0 && ts.isIdentifier(parametro.name)) {
|
|
147
|
+
responseNames.add(parametro.name.text);
|
|
148
|
+
}
|
|
149
|
+
}
|
|
142
150
|
const visitarDeclaracoes = (node) => {
|
|
143
151
|
if (ts.isVariableDeclaration(node) && node.initializer) {
|
|
144
152
|
const inicializadorNormalizado = desembrulharExpressao(node.initializer);
|
|
@@ -256,6 +264,56 @@ export function inferirSemanticaHandlerTypeScriptHttp(sourceFile, nomeExportado)
|
|
|
256
264
|
bodyTipoTexto ??= tipoTexto;
|
|
257
265
|
};
|
|
258
266
|
const visitarSemantica = (node) => {
|
|
267
|
+
if (ts.isPropertyAccessExpression(node)
|
|
268
|
+
&& ts.isPropertyAccessExpression(node.expression)
|
|
269
|
+
&& ts.isIdentifier(node.expression.expression)
|
|
270
|
+
&& requestNames.has(node.expression.expression.text)) {
|
|
271
|
+
const origemAcesso = node.expression.name.text;
|
|
272
|
+
const nomeCampo = node.name.text;
|
|
273
|
+
const ehQuery = origemAcesso === "query" || origemAcesso === "params"
|
|
274
|
+
|| (origemAcesso === "request" && (nomeCampo === "query" || nomeCampo === "searchParams"));
|
|
275
|
+
const ehBody = origemAcesso === "body" || (origemAcesso === "request" && nomeCampo === "body");
|
|
276
|
+
if (ehQuery && origemAcesso !== "params") {
|
|
277
|
+
query.push({
|
|
278
|
+
nome: nomeCampo,
|
|
279
|
+
tipoTexto: inferirTipoPorContexto(node, nomeCampo) ?? "string",
|
|
280
|
+
obrigatorio: false,
|
|
281
|
+
});
|
|
282
|
+
}
|
|
283
|
+
else if (ehBody) {
|
|
284
|
+
body.push({
|
|
285
|
+
nome: nomeCampo,
|
|
286
|
+
tipoTexto: inferirTipoPorContexto(node, nomeCampo) ?? "string",
|
|
287
|
+
obrigatorio: false,
|
|
288
|
+
});
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression) && node.expression.name.text === "json") {
|
|
292
|
+
let alvo = node.expression.expression;
|
|
293
|
+
let status;
|
|
294
|
+
if (ts.isCallExpression(alvo)
|
|
295
|
+
&& ts.isPropertyAccessExpression(alvo.expression)
|
|
296
|
+
&& alvo.expression.name.text === "status"
|
|
297
|
+
&& alvo.arguments[0]
|
|
298
|
+
&& ts.isNumericLiteral(alvo.arguments[0])) {
|
|
299
|
+
status = Number(alvo.arguments[0].text);
|
|
300
|
+
alvo = alvo.expression.expression;
|
|
301
|
+
}
|
|
302
|
+
if (ts.isIdentifier(alvo) && responseNames.has(alvo.text)) {
|
|
303
|
+
const argumento = node.arguments[0];
|
|
304
|
+
const campos = argumento && ts.isObjectLiteralExpression(argumento)
|
|
305
|
+
? extrairCamposObjetoLiteral(argumento, sourceFile)
|
|
306
|
+
: argumento && ts.isIdentifier(argumento) && valoresLocais.has(argumento.text)
|
|
307
|
+
? valoresLocais.get(argumento.text).campos
|
|
308
|
+
: [];
|
|
309
|
+
if (typeof status === "number") {
|
|
310
|
+
statuses.push(status);
|
|
311
|
+
}
|
|
312
|
+
if (status === undefined || status < 400) {
|
|
313
|
+
response.push(...campos);
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
259
317
|
if (ts.isCallExpression(node) && ts.isPropertyAccessExpression(node.expression)) {
|
|
260
318
|
const alvo = node.expression.expression;
|
|
261
319
|
const metodo = node.expression.name.text;
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
module exemplos.koa.crud {
|
|
2
|
+
entity Tarefa {
|
|
3
|
+
fields {
|
|
4
|
+
id: Id
|
|
5
|
+
titulo: Texto
|
|
6
|
+
concluida: Booleano
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
task criar_tarefa {
|
|
11
|
+
input {
|
|
12
|
+
titulo: Texto required
|
|
13
|
+
}
|
|
14
|
+
output {
|
|
15
|
+
tarefa: Tarefa
|
|
16
|
+
}
|
|
17
|
+
rules {
|
|
18
|
+
titulo deve_ser preenchido
|
|
19
|
+
}
|
|
20
|
+
effects {
|
|
21
|
+
persistencia Tarefa
|
|
22
|
+
auditoria tarefa_criada
|
|
23
|
+
}
|
|
24
|
+
guarantees {
|
|
25
|
+
tarefa existe
|
|
26
|
+
}
|
|
27
|
+
tests {
|
|
28
|
+
caso "cria tarefa" {
|
|
29
|
+
given {
|
|
30
|
+
titulo: "Revisar contrato"
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
expect {
|
|
34
|
+
sucesso: verdadeiro
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
task concluir_tarefa {
|
|
41
|
+
input {
|
|
42
|
+
id: Id required
|
|
43
|
+
}
|
|
44
|
+
output {
|
|
45
|
+
tarefa: Tarefa
|
|
46
|
+
}
|
|
47
|
+
rules {
|
|
48
|
+
id deve_ser valido
|
|
49
|
+
}
|
|
50
|
+
effects {
|
|
51
|
+
persistencia Tarefa
|
|
52
|
+
auditoria tarefa_concluida
|
|
53
|
+
}
|
|
54
|
+
guarantees {
|
|
55
|
+
tarefa existe
|
|
56
|
+
}
|
|
57
|
+
tests {
|
|
58
|
+
caso "conclui tarefa por id" {
|
|
59
|
+
given {
|
|
60
|
+
id: "tar_1"
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
expect {
|
|
64
|
+
sucesso: verdadeiro
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
route tarefas_criar {
|
|
71
|
+
metodo: POST
|
|
72
|
+
caminho: /api/tarefas
|
|
73
|
+
task: criar_tarefa
|
|
74
|
+
finalidade: cadastro_tarefa
|
|
75
|
+
input {
|
|
76
|
+
titulo: Texto
|
|
77
|
+
}
|
|
78
|
+
output {
|
|
79
|
+
tarefa: Tarefa
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
route tarefas_concluir {
|
|
84
|
+
metodo: PATCH
|
|
85
|
+
caminho: "/api/tarefas/{id}"
|
|
86
|
+
task: concluir_tarefa
|
|
87
|
+
finalidade: alteracao_tarefa
|
|
88
|
+
input {
|
|
89
|
+
id: Id
|
|
90
|
+
}
|
|
91
|
+
output {
|
|
92
|
+
tarefa: Tarefa
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
}
|
package/package.json
CHANGED