@asapjs/error
v1.0.0-alpha.13
Published
Error handling utilities for ASAP.js with Effect integration
Downloads
575
Readme
@asapjs/error
TypeScript 기반 ASAP.js 프레임워크를 위한 Effect 통합 에러 처리 패키지
주요 기능
- TypeIs 기반 에러 정의: 간단하고 타입 안전한 에러 생성
- 자동 Swagger 문서화: TypeIs 스키마로부터 OpenAPI 스펙 자동 생성
- Effect 라이브러리 통합: stack-safe 로깅 및 구조화된 에러 처리
- 레거시 호환성: 기존
HttpException지원
설치
yarn add @asapjs/error effect기본 사용법
1. 에러 정의 (새로운 방식)
import { error, TypeIs } from '@asapjs/error';
export class UserErrors {
static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자를 찾을 수 없습니다. ID: {userId}", {
userId: TypeIs.INT({ comment: "사용자 ID" }),
});
static EMAIL_DUPLICATE = error(409, "USER_EMAIL_DUPLICATE", "이미 사용 중인 이메일입니다: {email}", {
email: TypeIs.STRING({ comment: "중복된 이메일" }),
existingUserId: TypeIs.INT({ comment: "기존 사용자 ID", optional: true }),
});
static INVALID_DATA = error(400, "USER_INVALID_DATA", "잘못된 사용자 데이터입니다", {
invalidFields: TypeIs.ARRAY({
type: () => TypeIs.STRING(),
comment: "유효하지 않은 필드 목록"
}),
details: TypeIs.JSON({
comment: "상세 오류 정보",
optional: true
}),
});
}2. 컨트롤러에서 사용
import { Get, Post, RouterController } from '@asapjs/router';
import { wrapWithEffect } from '@asapjs/error';
import { UserErrors } from './errors/UserErrors';
export default class UserController extends RouterController {
@Get('/:id', {
title: '사용자 조회',
errors: [UserErrors.NOT_FOUND], // Swagger에 자동으로 문서화
})
public getUser = wrapWithEffect(async ({ path }) => {
const user = await findUser(path.id);
if (!user) {
throw UserErrors.NOT_FOUND({ userId: path.id });
}
return { result: user };
});
@Post('/', {
title: '사용자 생성',
body: CreateUserDto,
errors: [UserErrors.EMAIL_DUPLICATE, UserErrors.INVALID_DATA],
})
public createUser = wrapWithEffect(async ({ body }) => {
// 이메일 검증
if (!isValidEmail(body.email)) {
throw UserErrors.INVALID_DATA({
invalidFields: ['email'],
details: { email: 'Invalid email format' }
});
}
// 중복 체크
const existing = await findUserByEmail(body.email);
if (existing) {
throw UserErrors.EMAIL_DUPLICATE({
email: body.email,
existingUserId: existing.id
});
}
const user = await createUser(body);
return { result: user };
});
}3. Express 앱에 미들웨어 적용
import { effectErrorHandler } from '@asapjs/error';
app.use(effectErrorHandler);HTTP 에러 응답 포맷
모든 에러는 다음과 같은 통일된 포맷으로 응답됩니다:
{
"status": 404,
"errorCode": "USER_NOT_FOUND",
"message": "사용자를 찾을 수 없습니다. ID: 123",
"data": {
"userId": 123
}
}주요 특징
1. TypeIs를 활용한 타입 안전성
// 컴파일 타임에 타입 체크
throw UserErrors.NOT_FOUND({ userId: "123" }); // ❌ Error: userId must be number
throw UserErrors.NOT_FOUND({ userId: 123 }); // ✅ OK2. 메시지 템플릿
에러 메시지에 {fieldName} 형식으로 데이터를 삽입할 수 있습니다:
static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자 {userId}를 찾을 수 없습니다", {
userId: TypeIs.INT(),
});
// 사용 시: "사용자 123를 찾을 수 없습니다"
throw UserErrors.NOT_FOUND({ userId: 123 });3. 자동 Swagger 문서화
TypeIs 스키마가 자동으로 OpenAPI 스펙으로 변환됩니다:
components:
schemas:
USER_NOT_FOUND:
type: object
properties:
status:
type: number
example: 404
errorCode:
type: string
example: USER_NOT_FOUND
message:
type: string
data:
type: object
properties:
userId:
type: integer
description: 사용자 IDTypeIs 지원 타입
TypeIs.INT() // 정수
TypeIs.STRING() // 문자열
TypeIs.BOOLEAN() // 불린
TypeIs.FLOAT() // 실수
TypeIs.JSON() // JSON 객체
TypeIs.ARRAY() // 배열
TypeIs.DATETIME() // 날짜/시간
TypeIs.ENUM() // 열거형모든 타입은 optional: true 옵션을 지원합니다.
고급 기능
Effect 래핑
wrapWithEffect는 다음 기능을 제공합니다:
- 자동 스팬 트레이싱
- 구조화된 로깅 (요청 ID, 파일, 라인, 함수명 포함)
- Effect Exit 처리
레거시 호환성
기존 HttpException을 사용하는 코드도 자동으로 처리됩니다:
throw new HttpException(400, '잘못된 요청입니다');
// 자동으로 { status: 400, errorCode: 'LEGACY_HTTP_EXCEPTION', message: '...' } 로 변환마이그레이션 가이드
기존 방식
export class UserNotFoundError extends NotFoundError {
constructor(userId: number) {
super('USER_NOT_FOUND', `사용자를 찾을 수 없습니다. ID: ${userId}`, { userId });
}
}
throw new UserNotFoundError(123);새로운 방식
export class UserErrors {
static NOT_FOUND = error(404, "USER_NOT_FOUND", "사용자를 찾을 수 없습니다. ID: {userId}", {
userId: TypeIs.INT(),
});
}
throw UserErrors.NOT_FOUND({ userId: 123 });새로운 방식은 더 간결하고, 타입 안전하며, 자동 문서화를 지원합니다.
