import { SERVER_URL } from '@/lib/config' import { fetchCurrentProfile } from '@/lib/profileApi' import { storage } from '@/lib/storage' import type { AccountProfile } from '@/stores/accountStore' import type { TypedSocket } from '@/lib/socket' export async function requestJson(path: string, init?: RequestInit): Promise { const response = await fetch(`${SERVER_URL}${path}`, { ...init, credentials: 'include', headers: { 'Content-Type': 'application/json', ...init?.headers }, }) if (!response.ok) { const body = (await response.json().catch(() => null)) as { error?: string } | null throw new Error(body?.error ?? `Request failed: ${response.status}`) } if (response.status === 204) return undefined as T return (await response.json()) as T } function reconnectSocket(socket: TypedSocket): Promise { return new Promise((resolve) => { let finished = false const finish = () => { if (finished) return finished = true socket.off('connect', finish) window.clearTimeout(timeout) resolve() } const timeout = window.setTimeout(finish, 3_000) socket.on('connect', finish) if (socket.connected) socket.disconnect() socket.connect() }) } function clearIdentityBoundBrowserState(): void { storage.setAuthCookies([]) storage.clearRejoinToken() } export async function setInitialPassword(password: string): Promise { await requestJson<{ accountId: string }>('/api/auth/me/password', { method: 'POST', body: JSON.stringify({ password }), }) const profile = await fetchCurrentProfile() if (!profile) throw new Error('请先设置昵称') return profile } export async function updateAccountId( socket: TypedSocket, accountId: string, currentPassword?: string, ): Promise { const result = await requestJson('/api/auth/me/account-id', { method: 'PATCH', body: JSON.stringify({ accountId: accountId.trim().toLowerCase(), currentPassword }), }) storage.setUserId(result.id) storage.clearRejoinToken() const profile = await fetchCurrentProfile() if (!profile) throw new Error('账号资料恢复失败') await reconnectSocket(socket) return profile } export async function loginIdentity(socket: TypedSocket, accountId: string, password: string): Promise { const result = await requestJson<{ userId: string; expiresAt: number }>('/api/auth/identity/recover', { method: 'POST', body: JSON.stringify({ accountId: accountId.trim(), password }), }) clearIdentityBoundBrowserState() storage.setUserId(result.userId) const profile = await fetchCurrentProfile() if (!profile) throw new Error('账号资料恢复失败') await reconnectSocket(socket) return profile } export async function logoutIdentity(socket: TypedSocket): Promise { await requestJson<{ userId: string; expiresAt: number }>('/api/auth/identity/logout', { method: 'POST', }) clearIdentityBoundBrowserState() storage.clearNickname() const profile = await fetchCurrentProfile() await reconnectSocket(socket) return profile }