/* * 인증 API 래퍼 — 로그인(2FA 대응)·회원가입·비밀번호 찾기/초기화. * 근거: 01_backend_contracts.md §2 · 04_backend_public_auth.md. * 비밀번호는 요청 body로만 전송하고 어디에도 저장하지 않는다. */ import { api, ApiRequestError } from './api'; import type { LoginResponse, MessageResponse, RegisterRequest, RegisterResponse, } from './types'; export interface LoginParams { email: string; password: string; /** 2차 인증 코드 — OTP_REQUIRED 재시도 시 동봉(백엔드 TOTP 방식). */ otp?: string; } /** * 로그인. 성공 시 LoginResponse. * 2FA: 백엔드가 OTP_REQUIRED(401)를 반환하면 호출부가 OTP 입력 UI를 띄우고 * otp를 포함해 재호출한다. OTP_INVALID면 코드 오류로 재입력 유도. */ export async function login(params: LoginParams): Promise { const body: Record = { email: params.email.trim(), password: params.password, }; if (params.otp) body.otp = params.otp.trim(); return api.post('/api/auth/login', body, { anonymous: true }); } /** OTP_REQUIRED 여부 판정 헬퍼(로그인 2단계 분기용). */ export function isOtpRequired(e: unknown): boolean { return e instanceof ApiRequestError && e.code === 'OTP_REQUIRED'; } export async function register(req: RegisterRequest): Promise { return api.post('/api/auth/register', req, { anonymous: true }); } export async function forgotPassword(email: string): Promise { return api.post( '/api/auth/password/forgot', { email: email.trim() }, { anonymous: true }, ); } export async function resetPassword( email: string, code: string, newPassword: string, ): Promise { return api.post( '/api/auth/password/reset', { email: email.trim(), code: code.trim(), newPassword }, { anonymous: true }, ); }