AzuraJS Logo
AzuraJSFramework
v2.2 Beta

Routing

Aprenda sobre padrões de rota, parâmetros e correspondência

Routing 🛣️

AzuraJS fornece um sistema de roteamento poderoso e flexível baseado em decorators e correspondência de padrões.

Básico de Rotas 📍

Rotas são definidas usando decorators de método HTTP em métodos de controller.

import { Controller, Get, Param } from "azurajs/decorators";

@Controller("/api/users")
export class UserController {
  @Get()  // Corresponde: GET /api/users
  getAllUsers() {}

  @Get("/:id")  // Corresponde: GET /api/users/123
  getUser(@Param("id") id: string) {}
}

Caminhos de Rota 🗺️

Caminhos Estáticos

@Get("/users")  // Correspondência exata apenas
getUsers() {}

@Get("/users/active")  // Correspondência exata
getActiveUsers() {}

Parâmetros Dinâmicos

Use :paramName para parâmetros de rota:

@Get("/:id")  // Corresponde /123, /abc, etc.
getOne(@Param("id") id: string) {}

@Get("/:userId/posts/:postId")  // Múltiplos parâmetros
getPost(
  @Param("userId") userId: string,
  @Param("postId") postId: string
) {}

Parâmetros de Query

Parâmetros de query não fazem parte do caminho da rota:

TypeScript

import { Get, Query } from "azurajs/decorators";

// Rota: GET /search
// URL: GET /search?q=john&limit=10
@Get("/search")
search(@Query("q") query: string, @Query("limit") limit: string) {
  return { query, limit };
}

JavaScript

const { AzuraClient } = require("azurajs");

const app = new AzuraClient();

// Rota: GET /search
// URL: GET /search?q=john&limit=10
app.get("/search", (req, res) => {
  const query = req.query.q;
  const limit = req.query.limit;
  
  res.json({ query, limit });
});

Padrões de Rota 🎨

Combinando Estático e Dinâmico

import { Controller, Get, Param } from "azurajs/decorators";

@Controller("/api")
export class ApiController {
  @Get("/users/:id/profile")  // GET /api/users/123/profile
  getProfile(@Param("id") id: string) {}

  @Get("/posts/:id/comments/:commentId")  // Múltiplos params
  getComment(
    @Param("id") postId: string,
    @Param("commentId") commentId: string
  ) {}
}

Rotas Aninhadas

@Controller("/api/organizations")
export class OrgController {
  @Get("/:orgId/teams/:teamId/members")
  getMembers(
    @Param("orgId") orgId: string,
    @Param("teamId") teamId: string
  ) {
    return { orgId, teamId };
  }
}

Prioridade de Rotas ⚡

Rotas são correspondidas na ordem em que são registradas. Rotas mais específicas devem ser definidas primeiro:

@Controller("/api/users")
export class UserController {
  // ✅ Ordem correta
  @Get("/me")  // Rota específica primeiro
  getCurrentUser() {}

  @Get("/:id")  // Rota genérica depois
  getUser(@Param("id") id: string) {}

  // ❌ Ordem errada
  @Get("/:id")  // Isso corresponderia /me
  getUser2(@Param("id") id: string) {}

  @Get("/me")  // Nunca alcançado!
  getCurrentUser2() {}
}

Métodos HTTP 🔧

Todos os métodos HTTP padrão são suportados:

@Controller("/api/posts")
export class PostController {
  @Get()  // Ler todos
  getAll() {}

  @Get("/:id")  // Ler um
  getOne(@Param("id") id: string) {}

  @Post()  // Criar
  create(@Body() data: any) {}

  @Put("/:id")  // Atualizar (completo)
  update(@Param("id") id: string, @Body() data: any) {}

  @Patch("/:id")  // Atualizar (parcial)
  patch(@Param("id") id: string, @Body() data: any) {}

  @Delete("/:id")  // Deletar
  remove(@Param("id") id: string) {}

  @Head("/:id")  // Verificar existência
  exists(@Param("id") id: string, @Res() res: ResponseServer) {
    res.status(200).end();
  }

  @Options()  // Preflight CORS
  options(@Res() res: ResponseServer) {
    res.set("Allow", "GET, POST").end();
  }
}

Rotas Programáticas 🔨

Você também pode definir rotas programaticamente sem decorators:

const app = new AzuraClient();

app.get("/api/health", (req, res) => {
  res.json({ status: "ok" });
});

app.post("/api/webhook", (req, res) => {
  console.log("Webhook recebido:", req.body);
  res.status(200).send("OK");
});

app.put("/api/items/:id", (req, res) => {
  res.json({ id: req.params.id });
});

Helpers de Rota 🛠️

Múltiplas Rotas por Método

// Não suportado diretamente, mas você pode criar um wrapper
@Controller("/api/posts")
export class PostController {
  private getPostsLogic() {
    return { posts: [] };
  }

  @Get()
  getPosts() {
    return this.getPostsLogic();
  }

  @Get("/all")
  getAllPosts() {
    return this.getPostsLogic();
  }
}

Grupos de Rotas

Use controllers para agrupar rotas relacionadas:

// Rotas de autenticação
@Controller("/auth")
export class AuthController {
  @Post("/login")
  login() {}

  @Post("/register")
  register() {}

  @Post("/logout")
  logout() {}
}

// Rotas de API pública
@Controller("/api/public")
export class PublicController {}

// Rotas de admin
@Controller("/api/admin")
export class AdminController {}

Roteamento RESTful 🎯

Siga convenções REST para APIs baseadas em recursos:

@Controller("/api/users")
export class UserController {
  @Get()  // GET /api/users - Listar todos os usuários
  index() {}

  @Post()  // POST /api/users - Criar usuário
  store(@Body() data: any) {}

  @Get("/:id")  // GET /api/users/:id - Obter um usuário
  show(@Param("id") id: string) {}

  @Put("/:id")  // PUT /api/users/:id - Atualizar usuário
  update(@Param("id") id: string, @Body() data: any) {}

  @Delete("/:id")  // DELETE /api/users/:id - Deletar usuário
  destroy(@Param("id") id: string) {}
}

Testando Rotas 🧪

Teste suas rotas:

import { AzuraClient, applyDecorators } from "azurajs";
import { UserController } from "./controllers/UserController";

const app = new AzuraClient();
applyDecorators(app, [UserController]);

// Iniciar servidor
await app.listen(3000);

// Testar endpoints
const response = await fetch("http://localhost:3000/api/users/123");
const data = await response.json();
console.log(data);

Melhores Práticas ✨

Use nomes consistentes: Siga convenções REST (index, show, store, update, destroy)

Mantenha rotas planas: Evite rotas profundamente aninhadas (máximo 2-3 níveis)

Use substantivos no plural: /users em vez de /user, /posts em vez de /post

Observe a ordem das rotas: Rotas específicas antes das genéricas

Próximos Passos 📖

On this page