diff --git a/src/app.ts b/src/app.ts index e7b19d2..2d500f5 100644 --- a/src/app.ts +++ b/src/app.ts @@ -20,6 +20,14 @@ const APP_PORT = +(process.env.APP_PORT || 3000); RegisterRoutes(app); + app.get("*", (_, res) => + res.status(404).send({ + status: 404, + message: "Route not found.", + devMessage: "unknown_url", + }), + ); + app.use(error); app.listen(APP_PORT, APP_HOST, () => console.log(`Listening on: http://localhost:${APP_PORT}`)); diff --git a/src/controllers/branch/branch-controller.ts b/src/controllers/branch/branch-controller.ts index 20828b1..21c1bac 100644 --- a/src/controllers/branch/branch-controller.ts +++ b/src/controllers/branch/branch-controller.ts @@ -95,7 +95,7 @@ export class BranchController extends Controller { @Get("{branchId}") async getBranchById(@Path() branchId: string) { - return await prisma.branch.findFirst({ + const record = await prisma.branch.findFirst({ include: { province: true, district: true, @@ -103,6 +103,12 @@ export class BranchController extends Controller { }, where: { id: branchId }, }); + + if (!record) { + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + } + + return record; } @Post() @@ -115,13 +121,29 @@ export class BranchController extends Controller { prisma.branch.findFirst({ where: { id: body.headOfficeId || undefined } }), ]); if (body.provinceId && !province) - throw new HttpError(HttpStatus.BAD_REQUEST, "Province cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "missing_or_invalid_parameter", + ); if (body.districtId && !district) - throw new HttpError(HttpStatus.BAD_REQUEST, "District cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "missing_or_invalid_parameter", + ); if (body.subDistrictId && !subDistrict) - throw new HttpError(HttpStatus.BAD_REQUEST, "Sub-district cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "missing_or_invalid_parameter", + ); if (body.headOfficeId && !branch) - throw new HttpError(HttpStatus.BAD_REQUEST, "Head branch cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Head branch cannot be found.", + "missing_or_invalid_parameter", + ); } const { provinceId, districtId, subDistrictId, headOfficeId, ...rest } = body; @@ -159,13 +181,29 @@ export class BranchController extends Controller { prisma.branch.findFirst({ where: { id: body.headOfficeId || undefined } }), ]); if (body.provinceId && !province) - throw new HttpError(HttpStatus.BAD_REQUEST, "Province cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Province cannot be found.", + "missing_or_invalid_parameter", + ); if (body.districtId && !district) - throw new HttpError(HttpStatus.BAD_REQUEST, "District cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "District cannot be found.", + "missing_or_invalid_parameter", + ); if (body.subDistrictId && !subDistrict) - throw new HttpError(HttpStatus.BAD_REQUEST, "Sub-district cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Sub-district cannot be found.", + "missing_or_invalid_parameter", + ); if (body.headOfficeId && !branch) - throw new HttpError(HttpStatus.BAD_REQUEST, "Head branch cannot be found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Head branch cannot be found.", + "missing_or_invalid_parameter", + ); } const { provinceId, districtId, subDistrictId, headOfficeId, ...rest } = body; @@ -196,7 +234,7 @@ export class BranchController extends Controller { where: { id: branchId }, }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found."); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); } return record; } @@ -213,11 +251,11 @@ export class BranchController extends Controller { }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found."); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); } if (record.status === Status.USED) { - throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used."); + throw new HttpError(HttpStatus.FORBIDDEN, "Branch is in used.", "data_exists"); } return await prisma.branch.delete({ where: { id: branchId } }); diff --git a/src/controllers/branch/contact-controller.ts b/src/controllers/branch/contact-controller.ts index a673f2d..70d10a5 100644 --- a/src/controllers/branch/contact-controller.ts +++ b/src/controllers/branch/contact-controller.ts @@ -65,7 +65,13 @@ export class BranchContactController extends Controller { async getBranchContactById(@Path() branchId: string, @Path() contactId: string) { const record = await prisma.branchContact.findFirst({ where: { id: contactId, branchId } }); - if (!record) throw new HttpError(HttpStatus.NOT_FOUND, "User cannot be found."); + if (!record) { + throw new HttpError( + HttpStatus.NOT_FOUND, + "Branch contact cannot be found.", + "data_not_found", + ); + } return Object.assign(record, { qrCodeImageUrl: await minio.presignedGetObject(MINIO_BUCKET, imageLocation(record.id)), @@ -79,7 +85,11 @@ export class BranchContactController extends Controller { @Body() body: BranchContactCreate, ) { if (!(await prisma.branch.findFirst({ where: { id: branchId } }))) { - throw new HttpError(HttpStatus.BAD_REQUEST, "Branch not found."); + throw new HttpError( + HttpStatus.BAD_REQUEST, + "Branch not found.", + "missing_or_invalid_parameter", + ); } const record = await prisma.branchContact.create({ include: { branch: true }, @@ -112,7 +122,7 @@ export class BranchContactController extends Controller { where: { id: contactId, branchId }, }); if (!record) { - throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found."); + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); } return Object.assign(record, { qrCodeImageUrl: await minio.presignedGetObject( @@ -131,6 +141,8 @@ export class BranchContactController extends Controller { @Delete("{contactId}") async deleteBranchContact(@Path() branchId: string, @Path() contactId: string) { const result = await prisma.branchContact.deleteMany({ where: { id: contactId, branchId } }); - if (result.count <= 0) throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found."); + if (result.count <= 0) { + throw new HttpError(HttpStatus.NOT_FOUND, "Branch cannot be found.", "data_not_found"); + } } } diff --git a/src/interfaces/http-error.ts b/src/interfaces/http-error.ts index 5d396e2..8abe48b 100644 --- a/src/interfaces/http-error.ts +++ b/src/interfaces/http-error.ts @@ -6,13 +6,15 @@ class HttpError extends Error { */ status: HttpStatus; message: string; + devMessage?: string; - constructor(status: HttpStatus, message: string) { + constructor(status: HttpStatus, message: string, devMessage?: string) { super(message); this.name = "HttpError"; this.status = status; this.message = message; + this.devMessage = devMessage; } } diff --git a/src/middlewares/error.ts b/src/middlewares/error.ts index b010f0a..d80ceb3 100644 --- a/src/middlewares/error.ts +++ b/src/middlewares/error.ts @@ -8,6 +8,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(error.status).json({ status: error.status, message: error.message, + devMessage: error.devMessage, }); } @@ -16,6 +17,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) status: HttpStatus.UNPROCESSABLE_ENTITY, message: "Validation error(s).", detail: error.fields, + devMessage: "missing_or_invalid_parameter", }); } @@ -24,6 +26,7 @@ function error(error: Error, _req: Request, res: Response, _next: NextFunction) return res.status(HttpStatus.INTERNAL_SERVER_ERROR).json({ status: HttpStatus.INTERNAL_SERVER_ERROR, message: error.message, + devMessage: "system_error", }); }