AzuraJS Logo
AzuraJSFramework
v2.2 Beta

Decorators

Complete guide to all AzuraJS decorators

Decorators 🏷️

AzuraJS provides a rich set of TypeScript decorators for building elegant and type-safe APIs.

Class Decorators 🎯

@Controller

Defines a controller class with an optional base path.

@Controller(prefix?: string)

Examples:

import { Controller } from "azurajs/decorators";

// With prefix
@Controller("/api/users")
export class UserController {}

// Without prefix
@Controller()
export class RootController {}

// Nested path
@Controller("/api/v1/admin/users")
export class AdminUserController {}

Method Decorators 🛣️

Method decorators define HTTP routes for controller methods.

@Get

Define a GET route.

@Get(path?: string)

Examples:

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

@Controller("/api/users")
export class UserController {
  @Get()  // GET /api/users
  getAll() {}

  @Get("/:id")  // GET /api/users/:id
  getOne() {}

  @Get("/search")  // GET /api/users/search
  search() {}
}

@Post

Define a POST route.

@Post(path?: string)

Example:

import { Post, Body } from "azurajs/decorators";

@Post()  // POST /api/users
createUser(@Body() data: any) {
  return { id: Date.now(), ...data };
}

@Put

Define a PUT route for full updates.

@Put(path?: string)

Example:

import { Put, Param, Body } from "azurajs/decorators";

@Put("/:id")  // PUT /api/users/:id
updateUser(@Param("id") id: string, @Body() data: any) {
  return { id, ...data };
}

@Patch

Define a PATCH route for partial updates.

@Patch(path?: string)

Example:

@Patch("/:id")  // PATCH /api/users/:id
patchUser(@Param("id") id: string, @Body() data: Partial<User>) {
  return { id, ...data };
}

@Delete

Define a DELETE route.

@Delete(path?: string)

Example:

@Delete("/:id")  // DELETE /api/users/:id
deleteUser(@Param("id") id: string) {
  return { message: "User deleted" };
}

Define a HEAD route (for checking resource existence).

@Head(path?: string)

Example:

@Head("/:id")  // HEAD /api/users/:id
checkExists(@Param("id") id: string, @Res() res: ResponseServer) {
  const exists = users.some(u => u.id === id);
  res.status(exists ? 200 : 404).end();
}

@Options

Define an OPTIONS route (typically for CORS preflight).

@Options(path?: string)

Example:

@Options()  // OPTIONS /api/users
handleOptions(@Res() res: ResponseServer) {
  res.set("Allow", "GET, POST, PUT, DELETE").end();
}

Parameter Decorators 🔖

Parameter decorators inject data into controller method parameters.

@Req

Inject the full request object.

@Req() req: RequestServer

Example:

@Get("/info")
getInfo(@Req() req: RequestServer) {
  return {
    method: req.method,
    url: req.url,
    headers: req.headers
  };
}

@Res

Inject the response object for manual control.

@Res() res: ResponseServer

Example:

@Get("/download")
download(@Res() res: ResponseServer) {
  res.setHeader("Content-Type", "application/octet-stream");
  res.setHeader("Content-Disposition", "attachment; filename=file.zip");
  res.send(fileBuffer);
}

@Body

Extract the request body (automatically parsed for JSON and form data).

@Body() body: any

Examples:

// Entire body
@Post()
create(@Body() data: CreateUserDto) {
  return { id: Date.now(), ...data };
}

// Access body properties directly
@Post()
create(@Body() { name, email }: { name: string; email: string }) {
  return { name, email };
}

@Param

Extract route parameters from the URL path.

@Param(name?: string) param: string

Examples:

// Single parameter
@Get("/:id")
getUser(@Param("id") id: string) {
  return { id };
}

// Multiple parameters
@Get("/:userId/posts/:postId")
getPost(
  @Param("userId") userId: string,
  @Param("postId") postId: string
) {
  return { userId, postId };
}

// All parameters
@Get("/:userId/posts/:postId")
getPost(@Param() params: Record<string, string>) {
  return params;  // { userId: "1", postId: "2" }
}

@Query

Extract query string parameters.

@Query(name?: string) query: string

Examples:

// Single query parameter
@Get("/search")
search(@Query("q") searchTerm: string) {
  return { results: [], query: searchTerm };
}

// Multiple query parameters
@Get("/filter")
filter(
  @Query("status") status: string,
  @Query("limit") limit: string
) {
  return { status, limit };
}

// All query parameters
@Get("/search")
search(@Query() query: Record<string, string>) {
  // GET /api/users/search?q=john&limit=10
  return query;  // { q: "john", limit: "10" }
}

@Headers

Extract request headers.

@Headers(name?: string) header: string | undefined

Examples:

// Single header
@Get("/protected")
getData(@Headers("authorization") auth: string) {
  if (!auth) {
    throw new HttpError(401, "Unauthorized");
  }
  return { data: "secret" };
}

// Multiple headers
@Get("/info")
getInfo(
  @Headers("user-agent") ua: string,
  @Headers("accept-language") lang: string
) {
  return { userAgent: ua, language: lang };
}

// All headers
@Get("/headers")
getAllHeaders(@Headers() headers: Record<string, string>) {
  return { headers };
}

@Ip

Extract the client IP address.

@Ip() ip: string

Example:

@Post("/login")
login(@Body() credentials: any, @Ip() ip: string) {
  console.log(`Login attempt from ${ip}`);
  // Authenticate user
  return { success: true };
}

@UserAgent

Extract the User-Agent header.

@UserAgent() userAgent: string

Example:

@Get("/stats")
trackVisit(@UserAgent() ua: string, @Ip() ip: string) {
  console.log(`Visit from ${ip} using ${ua}`);
  return { message: "Visit tracked" };
}

@Next

Inject the next function for middleware chains.

@Next() next: (err?: unknown) => void

Example:

@Get("/async")
async handleAsync(
  @Req() req: RequestServer,
  @Res() res: ResponseServer,
  @Next() next: () => void
) {
  try {
    const data = await fetchData();
    res.json({ data });
  } catch (error) {
    next(error);
  }
}

Combining Decorators 🔗

You can combine multiple parameter decorators in one method:

@Controller("/api/posts")
export class PostController {
  @Get("/:id/comments")
  getComments(
    @Param("id") postId: string,
    @Query("limit") limit: string,
    @Query("offset") offset: string,
    @Headers("authorization") auth: string,
    @Ip() ip: string,
    @Res() res: ResponseServer
  ) {
    // Verify auth
    if (!auth) {
      return res.status(401).json({ error: "Unauthorized" });
    }

    // Log request
    console.log(`${ip} requested comments for post ${postId}`);

    // Return comments
    const comments = getCommentsFromDB(postId, Number(limit), Number(offset));
    res.json({ comments });
  }

  @Post("/:id/comments")
  createComment(
    @Param("id") postId: string,
    @Body() data: CreateCommentDto,
    @Ip() ip: string,
    @UserAgent() ua: string,
    @Res() res: ResponseServer
  ) {
    const comment = {
      id: Date.now(),
      postId,
      ...data,
      metadata: { ip, userAgent: ua }
    };

    res.status(201).json({ comment });
  }
}

Decorator Execution Order ⚡

Decorators are executed in this order:

  1. Class Decorator (@Controller) - Registers the controller
  2. Method Decorators (@Get, @Post, etc.) - Registers routes
  3. Parameter Decorators (@Body, @Param, etc.) - Executed at runtime when the route is called

Type Safety with Decorators 🔒

Use TypeScript interfaces for better type safety:

interface CreatePostDto {
  title: string;
  content: string;
  tags: string[];
}

interface UpdatePostDto {
  title?: string;
  content?: string;
  tags?: string[];
}

@Controller("/api/posts")
export class PostController {
  @Post()
  create(@Body() data: CreatePostDto, @Res() res: ResponseServer) {
    // data is fully typed
    const post = {
      id: Date.now(),
      title: data.title,
      content: data.content,
      tags: data.tags
    };
    res.status(201).json({ post });
  }

  @Patch("/:id")
  update(
    @Param("id") id: string,
    @Body() data: UpdatePostDto,
    @Res() res: ResponseServer
  ) {
    // TypeScript knows all fields are optional
    res.json({ id, ...data });
  }
}

Next Steps 📖

On this page