برنامه نویسی

خطای zod را به پاسخ خطای قابل خواندن تبدیل کنید

خطای اعتبار سنجی zod را به شیء پیام کلیدی قابل خواندن FE در NestJS تبدیل کنید

نسخه اندونزیایی

https://abdulghofurme.github.io/posts/transform-zod-error-into-readable-error-response

چشم انداز

به عنوان یک مهندس فرانت اند،
من گهگاه با خطاهای اعتبارسنجی مواجه شده ام که چنین هستند کمتر آسان برای پردازش

خب من متخصص نیستم
اما به نظر من، اگر خطاهای اعتبار سنجی دریافتی راحت تر قابل رسیدگی باشد، بهتر است.

هدف

برای تبدیل خطاهای اعتبار سنجی Zod به این صورت:

{
    "issues": [
        {
            "code": "too_small",
            "minimum": 3,
            "type": "string",
            "inclusive": true,
            "exact": false,
            "message": "The category name must be at least 3 characters long",
            "path": ["name"]
        }
    ],
    "name": "ZodError"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

به یک پاسخ خطا در فرمت پیام key: مانند این:

{
    "name": "The category name must be at least 3 characters long"
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

با key: message فرمت بالا،
فکر می کنم خواندن و پردازش آن آسان تر است.

بار دیگر،
این بدان معنا نیست که قالب اول دشوار است. البته، می توان آن را پردازش کرد، اما نیاز به یک مرحله اضافی برای استخراج پیام های خطا از هر فیلد ورودی دارد.

کد

ما از یک استفاده خواهیم کرد فیلتر خطا/استثنا،
یک رویکرد استاندارد برای رسیدگی به خطاها مرکزی.

با این دستور می توانید فیلتر را ایجاد کنید:

nest g f error
# nest generate filter [filter_name]
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

در اینجا پیاده سازی است:

// ./error/error.filter.ts

import { ArgumentsHost, Catch, ExceptionFilter, HttpException, HttpStatus } from "@nestjs/common";
import { Response } from "express";
import { TWebResponse } from "src/model/web.model";
import { ZodError, ZodIssue } from "zod";

@Catch()
export class ErrorFilter<T> implements ExceptionFilter {
    zodErrorToKeyedObject(error: ZodError): Record<string, string> {
        return error.errors.reduce(
            (acc, issue) => {
                const key = issue.path.join(".");
                acc[key] = issue.message;
                return acc;
            },
            {} as Record<string, string>,
        );
    }

    catch(exception: any, host: ArgumentsHost) {
        const response: Response = host.switchToHttp().getResponse();
        let result: {
            status: HttpStatus;
            json: TWebResponse;
        };

        if (exception instanceof HttpException) {
            result = {
                status: exception.getStatus(),
                json: {
                    message: exception?.message,
                },
            };
        } else if (exception instanceof ZodError) {
            result = {
                status: HttpStatus.BAD_REQUEST,
                json: {
                    message: "Validation error",
                    errors: this.zodErrorToKeyedObject(exception),
                },
            };
        } else {
            result = {
                status: HttpStatus.INTERNAL_SERVER_ERROR,
                json: {
                    message: exception?.message,
                },
            };
        }

        response.status(result.status).json(result.json);
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

سپس فیلتر را روی برنامه خود اعمال کنید:

// app/global module
...
import { APP_FILTER } from '@nestjs/core';
import { ErrorFilter } from './error/error.filter';
...
@Module({
...
  providers: [
    ...
    {
      provide: APP_FILTER,
      useClass: ErrorFilter,
    },
  ],
  ...
})
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

توضیح

HTTPEexception

...
if (exception instanceof HttpException) {
    result = {
        status: exception.getStatus(),
        json: {
            message: exception?.message,
        },
    };
}
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

HttpException را مدیریت می کند و آن را فوروارد می کند، به طوری که:

...
throw new HttpException(
  'Category not found',
  HttpStatus.NOT_FOUND,
);
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

این پاسخ را برمی گرداند:

{
    "status": 404,
    "data": {
        "message": "Category not found"
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ZodError

...
else if (exception instanceof ZodError) {
    result = {
        status: HttpStatus.BAD_REQUEST,
        json: {
            message: 'Validation error',
            errors: this.zodErrorToKeyedObject(exception),
        },
    };
}
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ZodError را می گیرد و روش:

...
zodErrorToKeyedObject(error: ZodError): Record<string, string> {
    return error.errors.reduce(
        (acc, issue) => {
            const key = issue.path.join('.');
            acc[key] = issue.message;
            return acc;
        },
        {} as Record<string, string>,
    );
}
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

ZodError را مطابق هدف ما به یک شیء خطای پیام تبدیل می کند.

این منجر به پاسخی مانند این می شود:

{
    "status": 400,
    "data": {
        "message": "Validation error",
        "errors": {
            "name": "Field-specific error message"
        }
    }
}
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

دیگر

...
else {
    result = {
        status: HttpStatus.INTERNAL_SERVER_ERROR,
        json: {
            message: exception?.message,
        },
    };
}
...
وارد حالت تمام صفحه شوید

از حالت تمام صفحه خارج شوید

هر گونه خطای دیگر را کنترل می کند و یک خطای سرور داخلی (500) را برمی گرداند.

نتیجه گیری

من معتقدم هر کسی نظرات و معیارهای خود را دارد.

با این حال، از دیدگاه noob FE،
خطاهای اعتبارسنجی اگر در کلید باشند راحت تر قابل رسیدگی هستند: قالب شیء پیام،
به آنها اجازه می دهد مستقیماً برای هر فیلد ورودی استخراج و نمایش داده شوند.

گفته می شود، اگر تیم از قبل استاندارد متفاوتی داشته باشد،
حتما بپذیرید، سوال بپرسید و به خوبی درباره آن بحث کنید.
شاید دلایل بهتری پشت آن باشد.

با خیال راحت سایر ملاحظات را به اشتراک بگذارید. 😉

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا