JSagon NodeJS Framework

Construa aplicações eficientes e escaláveis de maneira simples e rápida.


Rotas

Rotas são basicamente um mecanismo para definir qual funcionalidade chamar com base na URL e parâmetros fornecidos. Ou seja, o roteamento é um mapeamento entre uma URL e a sua ação.

A JSagon Framework disponibiliza duas maneiras para definição de rotas, uma definida como padrão que utiliza decorators, e a outra utilizando construtores. Abaixo se encontra a documentação de ambas.


Decorators

Digamos que gostaríamos de acessar a página de contato através da seguinte url financas.com/contato e para salvar o formulário a url financas.com/contato/cadastrar.

Um exemplo de código bem simples implementando decorators ficaria assim:

    import { ControllerBase, Request, Response, Controller, Post, Get} from '@jsagon/core'
    
    @Controller('/contato')
    class HomeController extends ControllerBase {
    
      @Get()
      public async contato(req: Request, res: Response) {
         return this.render({email: "contato@exemplo.com"})
      }}
    
      @Post('/cadastrar')
      public async salvarContato(req: Request, res: Response) {
         // código de persistência de contato
      }
    
    }
    
    export default HomeController

Para que a aplicação registre esses controladores e rotas automaticamente, é preciso que o controlador criado seja inserido no Module.ts do seu módulo que fica em Config.

O Module.ts ficará da seguinte maneira:

    import { ModuleBase } from '@jsagon/core'
    import HomeController from '../Controller/HomeController'
    
    export default class Module extends ModuleBase {
      public static controllers = [
        HomeController
      ]
    }

Devido as automatizações que a framework disponibiliza, quando se deseja renderizar uma tela com o this.render, o mecanismo interno entende o nome do método, da action, como o nome da view que se deseja renderizar. É possível alterar esse nome utilizando o decorator de View, como a seguir:

      @Get()
      @View('contato-portfolio')
      public async contato(req: Request, res: Response) {
         return this.render({email: "contato@exemplo.com"})
      }}

No exemplo anterior, o this.render passará a interpretar a view 'contato-portfolio' como a view do método 'contato'.

E caso queira definir um arquivo que se encontra em um local que não seja o padrão de mapeamento (projeto, módulo e controlador), é possível definir:

      @Get()
      @View('/novo/local/contato-portfolio', true)
      public async contato(req: Request, res: Response) {
         return this.render({email: "contato@exemplo.com"})
      }}

Decorators disponíveis:

Controller(string: opcional) Define que um controlador deve ter sua rota mapeada. E caso queira definir uma uri de prefixo, utilizar a parametrização.
Get(string: opcional) Definição da rota e método http atribuído. E caso queira definir uma uri de prefixo, utilizar a parametrização.
Post(string: opcional) Definição da rota e método http atribuído. E caso queira definir uma uri de prefixo, utilizar a parametrização.
Put(string: opcional) Definição da rota e método http atribuído. E caso queira definir uma uri de prefixo, utilizar a parametrização.
Patch(string: opcional) Definição da rota e método http atribuído. E caso queira definir uma uri de prefixo, utilizar a parametrização.
Delete(string: opcional) Definição da rota e método http atribuído. E caso queira definir uma uri de prefixo, utilizar a parametrização.
View(string, boolean): opcional Define a view de um método. Primeiro parâmetro, nome da view. Segundo parâmetro, informar true caso queria definir uma view com path completo.
Middleware(string | string[] | Function | Function[], string | string[]) Primeiro parâmetro, middlewares a serem executados na chamada da rota. Segundo parâmetro, middlewares que deverão ser pulados na execução da rota.

Construtor de Rotas

Abaixo será apresentado um exemplo de código bem simplificado.

Temos o seguinte controlador:

    import { AbstractController, Request, Response } from '@jsagon/core'
     
    class HomeController extends AbstractController {
    
        public async salvarContato(req: Request, res: Response) {
            // código de persistência de contato
        }
    
        public async contato(req: Request, res: Response) {
            return this.render({email: "contato@exemplo.com"})
        }}
    
    export default HomeController

Digamos que gostaríamos de acessar a página de contato através da url financas.com/contato e para salvar o formulário a url financas.com/contato/cadastrar.

Poderíamos conseguir o mesmo resultado de diferentes maneiras, mas por enquanto faremos da maneira mais didática. O arquivo de rota ficará da seguinte maneira:

    import { Route } from '@jsagon/core'
    import HomeController from '../Controller/HomeController'
    
    const route = Route('/contato', HomeController)
      .get({uri:'', action:'contato'})
      .post({uri:'/cadastrar', action:'salvarContato'})
    
    export default route

No exemplo anterior, primeiro importamos o construtor de rotas e logo em seguida o controlador. Utilizando o criador de rotas, passamos uma URI base e o controlador base em questão, depois definimos utilizando métodos específicos que simbolizam o modelo de requisição HTTP, e suas respectivas uri e ações a serem chamadas.

Cada ação(action) corresponde ao método implementado no controlador.

Ao iniciar a aplicação, o mecanismo interno se encarregará de ler os arquivos de rotas (Routes.ts) e registrará automaticamente as rotas criadas. Os arquivos responsáveis pelas rotas ficam armazenados dentro da pasta Config de cada módulo.


Construtores

Atualmente existem dois tipos de construtores de rotas que é possível importar de @jsagon/core, Route e RestRoute.

Ambos compartilham a mesma interface de Route. São elas:

construtor(uri, controller, middleware(s)) uri string: nome da uri base, será usado para concatenação com todas as uris posteriores definidas; controller: controlador base das ações; middleware(s): função única ou um array de funções a serem executados antes da execução das rotas. Será melhor explicado em Middlewares)
setBaseUri(string) Seta e altera a uri base definida no construtor.
setBaseController(Controller) Seta e altera o controlador base definido no construtor.
setBaseMiddleware(function | [functions]) Seta e altera o(s) middleware(s) base definido no construtor.
addBaseMiddleware(function) Adicionar um novo middleware a lista de middlewares.
get({uri, action}) uri específica da rota, action específica da rota. Método http GET.
post({uri, action}) uri específica da rota, action específica da rota. Método http POST.
patch({uri, action}) uri específica da rota, action específica da rota. Método http PATCH.
put({uri, action}) uri específica da rota, action específica da rota. Método http PUT.
del({uri, action}) uri específica da rota, action específica da rota. Método http DELETE.

Métodos padrões de acordo com convenções MVC.

Obs.: as URIs padrões serão adicionadas àquela URI definida como base.

Exemplo: uri base = /produto, ao chamar método list. A rota gerada será "/produto/list"

index parametrização opcional, mas idêntica a anterior. uri padrão: '/', action padrão 'index'
list uri padrão: '/list', action padrão 'list'
show uri padrão: '/show/:id', action padrão 'show'
detail uri padrão: '/detail/:id', action padrão 'detail'
create uri padrão: '/create', action padrão 'create'
edit uri padrão: '/edit:id', action padrão 'edit'
store uri padrão: '/store', action padrão 'store'
allDefaults Registra todas as rotas padrões: index, list, create, store, edit, patch, detail, del.

Comportamento específico para RestRoute.

Ao utilizar o RestRoute teremos métodos padrões de acordo com convenções Restful.

Obs.: as URIs padrões serão adicionadas àquela URI definida como base.

Exemplo: uri base = /produto, ao chamar método edit, a rota gerada será "/produto/:id/edit". E o método list neste caso será '/produto'.

index parametrização opcional, mas idêntica a anterior. uri padrão: '/', action padrão 'index'
list uri padrão: '/', action padrão 'list'
show uri padrão: '/:id', action padrão 'show'
detail uri padrão: '/:id', action padrão 'detail'
create uri padrão: '/', action padrão 'create'
edit uri padrão: '/:id/edit', action padrão 'edit'
put | patch uri padrão: '/:id', action padrão 'update'
allDefaults Registra todas as rotas padrões: store, patch, del, show, edit, index.

Um exemplo mais elaborado de criação de rotas
    import { RestRoute, Route } from '@jsagon/core'
    import HomeController from '../Controller/HomeController'
    import ProdutoController from '../Controller/ProdutoController'
    import { authMiddleware } from '../Middlewares'
    
    const route = Route('/', HomeController)
      .index()
      .get({uri: '/login', action: 'viewLogin'})
      .post({uri: '/login/entrar', action: 'logar'}) 
      .setBaseMiddleware(authMiddleware)
      .post({uri:'/sair', action: 'logout'})
    
    const restRoute = RestRoute('/produto', ProdutoController, authMiddleware)
      .allDefaults()
      .get({uri: '/:id/photos', action: 'recuperarFotos'})
    
    export default [ route, restRoute ]

Descrição comportamental do código anterior:

URIs criadas Route

  • financas.com/ ⇒ rota da página inicial
  • financas.com/login ⇒ rota da tela de login
  • financas.com/login/entrar ⇒ post de login
  • Definido middleware de autenticação. Em todas as rotas posteriores o usuário deverá estar logado para executar a ação.
  • financas.com/sair ⇒ rota de logout do sistema

URIs criadas RestRoute

  • Como definido o authMiddleware todas as rotas precisarão de acesso
  • get financas.com/produto
  • get financas.com/produto/:id
  • post financas.com/produto
  • patch financas.com/produto/:id
  • delete financas.com/produto/:id
  • get financas.com/produtos/:id/photos

Definindo rota base por aplicação

No arquivo de configuração específico do projeto por aplicação (app/WebApp/app.config.ts), é possível definir uma URI base. Ou seja, todas as rotas da aplicação em questão automaticamente terão a URI inserida.

    // ...
    module.exports = {
      // App's uri base. Example if uri: "test", example.com/test root url for all routes
      // Uri base da aplicação. Se uri: "test", example.com/test será a url base para todas as rotas definidas
      uri: '/app'
      // ...
    }

Digamos que no arquivo app.config.ts definimos a uri base como "/app". Se internamente criarmos uma rota para listar produtos. Automaticamente, a rota ficará como website.com/app/produto/list.


Tendo entendido e implementado o Controlador e a Rota, agora caso esteja implementado MVC, é preciso entender View.