Overview
Wrappers give every endpoint the same shape: payload plus status, message, and a referenceId for tracing. Controllers read body.payload and return ResponseDto.ok / okWithEmpty / error.
- Import from @quan-erp/shared-backend-core on the backend
- Frontend uses the simplified types from @quan-erp/shared-frontend-core
- Never return raw entities or accept bare DTOs on @Body()
1. ResponseDto<T>
Successful and error responses share one envelope.
- ResponseDto.ok(data, options?) — success with payload
- ResponseDto.okWithEmpty() — success with null payload (delete / no-content updates)
- ResponseDto.error(message, code?, referenceId?, payload?) — error envelope
| Field | Type | Notes |
|---|---|---|
| timestamp | string | ISO time |
| status | "success" | "error" | Outcome flag |
| message | string? | User-facing message (localize when possible) |
| code | HttpStatus? | Optional HTTP status for errors |
| referenceId | string | UUID for log / support tracing |
| payload | T | Actual data (or null for empty success) |
TSXcontroller responses
1import {
2 Delete,
3 Get,
4 HttpStatus,
5 Post,
6 ResponseDto,
7} from "@quan-erp/shared-backend-core";
8
9@Get("/profile")
10async getProfile() {
11 const profile = await this.service.getProfile();
12 return ResponseDto.ok(profile);
13}
14
15@Delete("/history/:id")
16async deleteHistory() {
17 await this.service.delete(/* … */);
18 return ResponseDto.okWithEmpty();
19}
20
21@Post("/update")
22async update() {
23 try {
24 return ResponseDto.ok(
25 { success: true },
26 { message: "Profile updated successfully" },
27 );
28 } catch {
29 return ResponseDto.error(
30 "Failed to update profile",
31 HttpStatus.INTERNAL_SERVER_ERROR,
32 );
33 }
34}2. RequestDto<T>
@Body() expects RequestDto<T>. Client JSON wraps the real DTO; read it from body.payload.
TSXrequest body
1import { Body, Post, RequestDto } from "@quan-erp/shared-backend-core";
2
3@Post("/calculate")
4async calculate(@Body() body: RequestDto<LoanCalculationDto>) {
5 const data = body.payload;
6 return ResponseDto.ok(await this.service.calculate(data));
7}3. Frontend pairing
On the client, wrap POST/PUT with new RequestDto(dto), cast response.data as ResponseDto<T>, check status, then return payload. Prefer shared-frontend-core helpers and Admin Axios & Query patterns.
- new RequestDto(dto) before post/put
- if (data.status === "error") throw …
- GET fetchFn should return payload, not the full ResponseDto
- See Frontend → Platform APIs → RequestDto & ResponseDto