Add API Endpoint

Create Controller

Create a file in api/src/controllers/:

// api/src/controllers/todo.controller.ts
import { Controller, Get, Post, Body, Req, Res, UseGuards } from "@nestjs/common"
import { Response } from "express"
import { JwtAuthGuard } from "@readystart/api-core/shared/guards/jwt.auth.guard"
import { CustomRequest } from "@readystart/api-core/shared/interfaces/request.interface"
import { ResponseHandler } from "@readystart/api-core/shared/utils/response.handler"
import { PgsqlService } from "@readystart/api-core/shared/services/pgsql.service"

@UseGuards(JwtAuthGuard)
@Controller({ version: "1", path: "todos" })
export class TodoController {
  constructor(private readonly pgsqlService: PgsqlService) {}

  @Post("create")
  async create(
    @Req() req: CustomRequest,
    @Body() body: { title: string },
    @Res() res: Response
  ) {
    const tenant_id = req.tenant?.id
    const result = await this.pgsqlService.query(
      `INSERT INTO todos (tenant_id, title) VALUES ($1, $2) RETURNING *`,
      [tenant_id, body.title]
    )
    res.json({ statusCode: 200, data: result.rows[0], message: "success" })
  }

  @Post("list")
  async list(@Req() req: CustomRequest, @Res() res: Response) {
    const tenant_id = req.tenant?.id
    const result = await this.pgsqlService.query(
      `SELECT * FROM todos WHERE tenant_id = $1 ORDER BY created_at DESC`,
      [tenant_id]
    )
    res.json({ statusCode: 200, data: result.rows, message: "success" })
  }
}

Register in Module

// api/src/app.module.ts
import { TodoController } from "./controllers/todo.controller"

@Module({
  controllers: [
    // ... other controllers
    TodoController,
  ],
})
export class AppModule {}

DTO Validation

Use class-validator to validate request parameters:

// api/src/controllers/todo.dto.ts
import { IsNotEmpty, Length } from "class-validator"

export class CreateTodoDto {
  @IsNotEmpty({ message: "title is required" })
  @Length(1, 255)
  title: string
}

Usage in Controller:

@Post("create")
async create(@Body() body: CreateTodoDto, ...) {
  // body.title is already validated
}

Response Format

All endpoints return a unified format:

{
  "statusCode": 200,
  "data": {},
  "message": "success"
}

Use ResponseHandler for async responses:

await ResponseHandler.handleMicroserviceResponse(
  res,
  this.myService.doSomething()
)

Route Versioning

All endpoints have a version prefix /v1/ by default:

POST /v1/todos/create
POST /v1/todos/list