Web API for code.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

69 lines
1.6 KiB

  1. import { FastifyReply, FastifyRequest } from 'fastify'
  2. type AppErrorOptions = {
  3. cause?: Error,
  4. }
  5. export class AppError extends Error {
  6. public readonly cause?: Error
  7. constructor(message?: string, options?: AppErrorOptions) {
  8. super(message)
  9. if (typeof options === 'object') {
  10. this.cause = options.cause
  11. }
  12. }
  13. }
  14. const httpErrorClassFactory = (statusCode: number, statusMessage?: string) => class HttpError extends AppError {
  15. readonly statusCode = statusCode
  16. readonly statusMessage = statusMessage
  17. }
  18. interface CustomFastifyError extends Error {
  19. statusMessage?: string;
  20. validation: {
  21. keyword: string,
  22. instancePath: string,
  23. params: Record<string, unknown>,
  24. message: string,
  25. }[];
  26. statusCode?: number;
  27. errors: Record<string, unknown>[];
  28. detail?: string;
  29. }
  30. export const fastifyErrorHandler = (error: CustomFastifyError, _request: FastifyRequest, reply: FastifyReply) => {
  31. reply.headers({
  32. 'Content-Type': 'application/problem+json',
  33. })
  34. if (error.validation) {
  35. reply.status(400)
  36. reply.raw.statusMessage = 'Invalid Request'
  37. reply.send({
  38. title: 'There are errors in the request body.',
  39. 'invalid-params': error.validation.map(v => ({
  40. name: (
  41. v.keyword === 'required'
  42. ? `${v.instancePath}/${v.params.missingProperty}`
  43. : v.instancePath
  44. ).replaceAll('/', '.'),
  45. reason: v.message,
  46. })),
  47. })
  48. return
  49. }
  50. if (Number.isNaN(reply.raw.statusCode)) {
  51. reply.status(error?.statusCode ?? 500)
  52. }
  53. reply.raw.statusMessage = error.statusMessage ?? 'Unknown Error'
  54. reply.send({
  55. title: reply.raw.statusMessage,
  56. detail: error.message,
  57. })
  58. }
  59. export { httpErrorClassFactory as HttpError }