Demo

Routers

HTTP APIs via @Controller, route/method decorators, parameter decorators, and @APIInfo. Always return ResponseDto-shaped responses.

@Controller

@Controller(path) sets the base route. The plugin name is prefixed automatically (for example /reward-point becomes /<plugin>/reward-point).

TSXcontroller
1import { 2 AuthenticatedUserOnly, 3 CheckAPIPermission, 4 Controller, 5 Get, 6 ResponseDto, 7} from "@quan-erp/shared-backend-core"; 8 9@Controller("/reward-point") 10export class RewardPointController { 11 @Get("/") 12 @AuthenticatedUserOnly() 13 @CheckAPIPermission() 14 async list() { 15 return ResponseDto.ok(/* … */); 16 } 17}

HTTP methods

  • @Get / @Post / @Put / @Delete — path must begin with "/"
  • Combine with security, @APIInfo, caching, and workflow decorators as needed

Route parameters

  • @Param(name) — path param
  • @Query(name) — query param
  • @Body() — usually RequestDto<T>
  • @User() — RequestedUser
TSXparams
1import { 2 Body, 3 Controller, 4 Param, 5 Put, 6 RequestDto, 7 RequestedUser, 8 User, 9} from "@quan-erp/shared-backend-core"; 10import type { UpdateDto } from "./update.dto.js"; 11 12@Controller("/order") 13export class OrderController { 14 @Put("/:id") 15 async update( 16 @Param("id") id: number, 17 @Body() body: RequestDto<UpdateDto>, 18 @User() user: RequestedUser, 19 ) { /* … */ } 20}

@APIInfo

Metadata for docs and system integration: shortDescription, description, isPublic, contentType, requestDto, responseDto, queryParams, pathParams, headers.

TSXapi-info
1import { 2 APIInfo, 3 Controller, 4 Get, 5 JsonContentType, 6 JWTAuthorizationHeader, 7 ResponseDto, 8 SkipLimitQueryParam, 9} from "@quan-erp/shared-backend-core"; 10 11@Controller("/branch") 12export class BranchController { 13 @Get("/") 14 @APIInfo({ 15 shortDescription: "Get all branches", 16 contentType: JsonContentType, 17 responseDto: ResponseDto, 18 queryParams: SkipLimitQueryParam, 19 headers: JWTAuthorizationHeader, 20 }) 21 async list() { /* … */ } 22}

Request & response DTOs

Wrap payloads with RequestDto / ResponseDto so the frontend always receives a consistent shape (payload, errors, meta).

Service CRUD patterns

  • Create: repo.insert(...) → return { id } from identifiers (no post-insert findOne)
  • Update: repo.update({ id }, { ...data, updateDate }) and check affected
  • Delete: repo.softDelete + affected check