o2o-negosium-original/negodata/front/src/lib/apiError.ts
Mina Choi a40257ddc1 [feat] negodata: 회원관리 / 최고관리자(OWNER)
- OWNER 권한 신설, 최고관리자가 자기 회사 소속 직원(USER) 계정 생성·수정·삭제 관리
- 회사 사용자 API(/v1/company/user/*), 회원관리 페이지·폼
- 로그인/프로필 흐름 정비, 무인증 계정생성(/auth/create) 제거

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
2026-06-29 13:31:32 +09:00

47 lines
2.4 KiB
TypeScript

import { ApiError } from '@/api/mutator/custom-fetch';
import type { ErrorInfo } from '@/api/generated/model/errorInfo';
// 백엔드 식별자(ErrorType.name = 응답봉투 result.desc / HTTPException detail) → 사용자용 한글.
// 서버는 안정적인 코드명만 주고, 표시 문구는 여기서만 정한다(서버·프론트 메시지 단일화).
const MESSAGES: Record<string, string> = {
// HTTP 예외(라우터 단에서 raise)
HTTP_FORBIDDEN: '최고관리자 권한이 필요합니다.',
HTTP_INVALID_CLIENT_ACCESS: '인증에 실패했습니다. 다시 로그인해 주세요.',
HTTP_ACCESS_TOKEN_EXPIRED: '세션이 만료되었습니다. 다시 로그인해 주세요.',
HTTP_REFRESH_TOKEN_EXPIRED: '세션이 만료되었습니다. 다시 로그인해 주세요.',
HTTP_INVALID_TOKEN_ACCESS: '인증에 실패했습니다. 다시 로그인해 주세요.',
// 응답 봉투(result.success=false)
ACCOUNT_INVALID_INFO: '아이디 또는 비밀번호가 올바르지 않습니다.',
ACCOUNT_ALREADY_EXIST: '이미 사용 중인 로그인 ID 입니다.',
ACCOUNT_BLOCKED_USER: '비활성화된 계정입니다.',
ACCOUNT_NOT_FOUND: '대상 계정을 찾을 수 없습니다.',
ACCOUNT_FORBIDDEN: '해당 계정은 수정·삭제할 수 없습니다(최고관리자 대상).',
};
const STATUS_FALLBACK: Record<number, string> = {
401: '인증에 실패했습니다. 다시 로그인해 주세요.',
403: MESSAGES.HTTP_FORBIDDEN,
404: '대상을 찾을 수 없습니다.',
500: '서버 오류가 발생했습니다.',
};
const DEFAULT = '요청 처리 중 오류가 발생했습니다.';
const byKey = (key?: string | null): string | null => (key ? MESSAGES[key] ?? null : null);
// HTTP 에러(ApiError)/일반 에러 → 사용자용 한글. catch 블록에서 사용.
export function toMessage(err: unknown, fallback: string = DEFAULT): string {
if (err instanceof ApiError) {
const detail = (err.data as { detail?: string } | null)?.detail;
return byKey(detail) ?? STATUS_FALLBACK[err.status] ?? fallback;
}
if (err instanceof Error) return err.message;
return fallback;
}
// 응답 봉투(result.success=false) → 한글. 정상이면 null.
export function resultMessage(result?: ErrorInfo, fallback = '요청에 실패했습니다.'): string | null {
if (!result || result.success !== false) return null;
return byKey(result.desc) ?? result.desc ?? fallback;
}