Files
InsightRadar/frontend/src/auth.api.ts
T
2026-03-13 23:48:49 +08:00

107 lines
3.2 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* 认证 API:登录、注册、发送验证码(不走通用 client,无 Bearer
*/
import type {
AuthTokenResponse,
LoginPayload,
LoginWithCodePayload,
MessageResponse,
RegisterPayload,
} from './auth.types'
import { fetchApi } from '@/config/apiBase'
type JsonValue = object | null
const MESSAGE_MAP: Record<string, string> = {
'Email is already registered': '该邮箱已注册',
'Email is not registered': '该邮箱未注册',
'Failed to send verification code': '验证码发送失败,请稍后重试',
'Verification code sent': '验证码已发送',
'Verification code does not exist or expired': '验证码不存在或已过期',
'Invalid verification code': '验证码错误',
'Invalid email or password': '邮箱或密码错误',
'Invalid email or verification code': '邮箱或验证码错误',
}
function localizeMessage(message: string): string {
return MESSAGE_MAP[message] ?? message
}
function localizeDetail(detail: string): string {
const direct = localizeMessage(detail)
if (direct !== detail) {
return direct
}
const cooldownMatch = detail.match(/^Please wait (\d+)s before requesting another verification code$/)
if (cooldownMatch) {
return `操作过于频繁,请 ${cooldownMatch[1]} 秒后再试`
}
return detail
}
async function request<T>(path: string, payload: JsonValue): Promise<T> {
const response = await fetchApi(path, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: payload ? JSON.stringify(payload) : undefined,
})
const raw = await response.text()
let data: Record<string, unknown> = {}
if (raw) {
try {
data = JSON.parse(raw) as Record<string, unknown>
} catch {
data = {}
}
}
if (!response.ok) {
const detail = data.detail
if (typeof detail === 'string') {
const error = new Error(localizeDetail(detail)) as Error & { retryAfter?: number }
if (response.status === 429) {
const retryAfterHeader = response.headers.get('Retry-After')
if (retryAfterHeader) {
const retryAfter = Number.parseInt(retryAfterHeader, 10)
if (Number.isFinite(retryAfter) && retryAfter > 0) {
error.retryAfter = retryAfter
}
}
}
throw error
}
throw new Error('请求失败,请稍后重试')
}
if (typeof data.message === 'string') {
data.message = localizeMessage(data.message)
}
return data as T
}
export function sendRegisterCode(email: string): Promise<MessageResponse> {
return request<MessageResponse>('/auth/register/send-code', { email })
}
export function sendLoginCode(email: string): Promise<MessageResponse> {
return request<MessageResponse>('/auth/login/send-code', { email })
}
export function register(payload: RegisterPayload): Promise<AuthTokenResponse> {
return request<AuthTokenResponse>('/auth/register', payload)
}
export function login(payload: LoginPayload): Promise<AuthTokenResponse> {
return request<AuthTokenResponse>('/auth/login', payload)
}
export function loginWithCode(payload: LoginWithCodePayload): Promise<AuthTokenResponse> {
return request<AuthTokenResponse>('/auth/login/code', payload)
}