129 lines
3.6 KiB
TypeScript
Executable File
129 lines
3.6 KiB
TypeScript
Executable File
import {
|
|
Get,
|
|
Post,
|
|
Put,
|
|
Delete,
|
|
Param,
|
|
Query,
|
|
Body,
|
|
HttpCode,
|
|
ParseUUIDPipe,
|
|
} from "@nestjs/common";
|
|
import {
|
|
ApiOperation,
|
|
ApiOkResponse,
|
|
ApiNotFoundResponse,
|
|
ApiBadRequestResponse,
|
|
} from "@nestjs/swagger";
|
|
import { BaseService } from "./base.service";
|
|
import { PaginationDto } from "../dto/pagination.dto";
|
|
import {
|
|
ApiResponse,
|
|
createSuccessResponse,
|
|
createPaginatedResponse,
|
|
} from "../types/api-response.type";
|
|
|
|
/**
|
|
* Generic base controller with common CRUD endpoints
|
|
* Extend this class for entity-specific controllers
|
|
*
|
|
* Note: Use decorators like @Controller() on the child class
|
|
*/
|
|
export abstract class BaseController<T, CreateDto, UpdateDto> {
|
|
constructor(
|
|
protected readonly service: BaseService<T, CreateDto, UpdateDto>,
|
|
protected readonly entityName: string,
|
|
) {}
|
|
|
|
@Get()
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Get all records with pagination" })
|
|
@ApiOkResponse({ description: "Records retrieved successfully" })
|
|
async findAll(
|
|
@Query() pagination: PaginationDto,
|
|
): Promise<ApiResponse<{ items: T[]; meta: any }>> {
|
|
const result = await this.service.findAll(pagination);
|
|
return createPaginatedResponse(
|
|
result.items,
|
|
result.meta.total,
|
|
result.meta.page,
|
|
result.meta.limit,
|
|
`${this.entityName} list retrieved successfully`,
|
|
);
|
|
}
|
|
|
|
@Get(":id")
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Get a record by ID" })
|
|
@ApiOkResponse({ description: "Record retrieved successfully" })
|
|
@ApiNotFoundResponse({ description: "Record not found" })
|
|
async findOne(
|
|
@Param("id", ParseUUIDPipe) id: string,
|
|
): Promise<ApiResponse<T>> {
|
|
const result = await this.service.findOne(id);
|
|
return createSuccessResponse(
|
|
result,
|
|
`${this.entityName} retrieved successfully`,
|
|
);
|
|
}
|
|
|
|
@Post()
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Create a new record" })
|
|
@ApiOkResponse({ description: "Record created successfully" })
|
|
@ApiBadRequestResponse({ description: "Validation failed" })
|
|
async create(@Body() createDto: CreateDto): Promise<ApiResponse<T>> {
|
|
const result = await this.service.create(createDto);
|
|
return createSuccessResponse(
|
|
result,
|
|
`${this.entityName} created successfully`,
|
|
201,
|
|
);
|
|
}
|
|
|
|
@Put(":id")
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Update an existing record" })
|
|
@ApiOkResponse({ description: "Record updated successfully" })
|
|
@ApiNotFoundResponse({ description: "Record not found" })
|
|
async update(
|
|
@Param("id", ParseUUIDPipe) id: string,
|
|
@Body() updateDto: UpdateDto,
|
|
): Promise<ApiResponse<T>> {
|
|
const result = await this.service.update(id, updateDto);
|
|
return createSuccessResponse(
|
|
result,
|
|
`${this.entityName} updated successfully`,
|
|
);
|
|
}
|
|
|
|
@Delete(":id")
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Delete a record (soft delete)" })
|
|
@ApiOkResponse({ description: "Record deleted successfully" })
|
|
@ApiNotFoundResponse({ description: "Record not found" })
|
|
async delete(
|
|
@Param("id", ParseUUIDPipe) id: string,
|
|
): Promise<ApiResponse<T>> {
|
|
const result = await this.service.delete(id);
|
|
return createSuccessResponse(
|
|
result,
|
|
`${this.entityName} deleted successfully`,
|
|
);
|
|
}
|
|
|
|
@Post(":id/restore")
|
|
@HttpCode(200)
|
|
@ApiOperation({ summary: "Restore a soft-deleted record" })
|
|
@ApiOkResponse({ description: "Record restored successfully" })
|
|
async restore(
|
|
@Param("id", ParseUUIDPipe) id: string,
|
|
): Promise<ApiResponse<T>> {
|
|
const result = await this.service.restore(id);
|
|
return createSuccessResponse(
|
|
result,
|
|
`${this.entityName} restored successfully`,
|
|
);
|
|
}
|
|
}
|