File size: 3,160 Bytes
00a912e | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 | 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<T>(path: string, init?: RequestInit): Promise<T> {
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<void> {
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<AccountProfile> {
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<AccountProfile> {
const result = await requestJson<AccountProfile>('/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<AccountProfile> {
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<AccountProfile | null> {
await requestJson<{ userId: string; expiresAt: number }>('/api/auth/identity/logout', {
method: 'POST',
})
clearIdentityBoundBrowserState()
storage.clearNickname()
const profile = await fetchCurrentProfile()
await reconnectSocket(socket)
return profile
}
|