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" };
}@Head
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: RequestServerExample:
@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: ResponseServerExample:
@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: anyExamples:
// 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: stringExamples:
// 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: stringExamples:
// 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 | undefinedExamples:
// 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: stringExample:
@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: stringExample:
@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) => voidExample:
@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:
- Class Decorator (
@Controller) - Registers the controller - Method Decorators (
@Get,@Post, etc.) - Registers routes - 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 });
}
}