Visão geral
Explica o contexto e os princípios que eliminam o gargalo de escrever o mesmo contrato de API e tipos duas vezes ao desenvolver o backend e o frontend juntos, e transformam o trabalho de desenvolvimento repetitivo, como strings de campo de roteador·handler·MongoDB, em geração baseada em fonte.
História de origem
trabalho com backend e frontend juntos. Ao criar uma funcionalidade, escrevi endpoints e DTOs de request/response no Java WebFlux, e depois, no frontend, precisei escrever o mesmo URL e tipo TypeScript. Para alinhar a documentação do Swagger, precisei transferir informações já existentes no backend para outro formato, repetidamente.
o maior gargalo foi reescrever o contrato da API criado no backend para um formato utilizável pelo frontend. Se qualquer um dos parâmetros URL, método HTTP, path/query ou estrutura de request/response fosse modificado de forma diferente em ambos os lados, o problema era descoberto tarde, após a compilação. Isso não era apenas uma tarefa chata, mas a inconsistência gerada por gerenciar a mesma informação duas vezes era um problema maior.
também queria reduzir a repetição ao criar novas RouterFunction e handlers. Se eu adicionasse uma referência como ApiAccountHandler::search ao roteador, pensei que um esqueleto de classe e método de handler inexistente poderia ser criado automaticamente.
dessa forma, a geração de Swagger/OpenAPI, a criação de esqueleto de handler e a geração de enum de campo de entidade Mongo foram feitas primeiro, e depois adicionei a geração de AsyncAPI ao usar RSocket. Embora cada um pareça uma ideia separada, o ponto de partida é o mesmo: não reescrever manualmente informações já registradas no código-fonte do backend, mas permitir que ferramentas de desenvolvimento gerem partes que podem ser lidas por máquinas.
Filosofia de desenvolvimento
baseia-se no código-fonte do backend
usa informações já existentes em RouterFunction, handlers, DTOs e entidades como a fonte para a documentação da API e código gerado. O essencial é não gerenciar o mesmo contrato em arquivos separados.
prefere automação em tempo de desenvolvimento em vez de mágica em tempo de execução
não é um framework que intercepta solicitações de produção, mas analisa a fonte no ambiente de desenvolvimento local e gera arquivos reais. Os resultados podem ser verificados visualmente e versionados.
segue convenções de projeto de forma previsível
não visa ser um compilador universal que entende todo o código Java. Prioriza a análise da estrutura de endpoint funcional do WebFlux que realmente uso com regras claras.
elimina intervalos de conexão repetidos
cria Swagger a partir do endpoint do backend e conecta o gerador frontend que lê esse documento para criar serviços e tipos em uma única cadeia de automação.
O que ler no backend
código fonte da RouterFunction
Lê o método HTTP, caminho aninhado, referência do método manipulador e predicado.
Fonte do manipulador
Lê o corpo da requisição, valores de consulta/caminho e tipo do publicador de resposta.
DTO de Requisição / Resposta
Conecta o tipo Java já escrito no backend ao esquema OpenAPI.
Fonte da entidade Mongo
Lê o nome bruto de armazenamento do campo Java e @Field, e a coleção @Document.
Controlador RSocket
Lê a rota @MessageMapping e o tipo de carga útil de requisição/resposta.
O que criar em vez de escrever repetidamente
swagger.json
Transforma o endpoint REST em um contrato de API que pode ser usado pelo serviço front-end e pelo gerador de tipos TypeScript.
asyncapi-rsocket.json
Transforma a rota RSocket e a carga útil em um contrato que pode ser lido pelo gerador de cliente RSocket front-end.
Fonte do manipulador
Gera e corrige a estrutura de classe e método com base na referência do manipulador escrita primeiro na RouterFunction.
Enum {Entity}Fields
Cria um enum para os nomes dos campos Java da entidade e o nome bruto de armazenamento para evitar repetições.
Enum CollectionNames
Gera para que o nome da coleção declarado em @Document possa ser usado em vez de uma string.
Fluxo de automação no projeto atual
• Escreve RouterFunction, manipulador e DTO de requisição/resposta Java no backend.
• O watcher do perfil local detecta mudanças na fonte e atualiza swagger.json ou asyncapi-rsocket.json.
• O script de geração @byeolnaerim/typed-rx-http lê a documentação e gera funções de serviço e tipos TypeScript.
• No código da tela, não reescreve a URL e o tipo de resposta, mas importa e usa a função gerada.
• Quando a entidade muda, também atualiza o enum de campos usados na consulta e o enum de coleções.