fix(auth): stop parsing logout response body (avoids ZodError on null data)

Root cause: backend `/auth/logout` returns `{ success: true, data: null }`
(no business payload for a fire-and-forget endpoint). The previous
`AuthApi.logout` ran `unwrap(env)` (which passes null through, since
null is defined) and then `LogoutResponse.fromJson(null)`, which
Zod-parses as `z.object(...)` and throws "Invalid input: expected
object, received null".

The error was caught in `AuthRepository.logout` with
`console.warn(... clearing local anyway)` — logout actually still
worked (local clear ran), but a noisy red ZodError hit the console on
every logout click.

Fix: align `AuthApi.logout` with the existing fire-and-forget pattern
used by `register` and `sendCode` — call `httpClient` and ignore the
response body. Drop the now-unused `LogoutResponse` import.

`AuthRepository.logout` already discards the return value, so the
`Promise<LogoutResponse> → Promise<void>` signature change is safe.

Bundled in this commit (unrelated):
- chat-machine.actors.ts / user-machine.ts: removed stale design-doc
  comment blocks (IDE/linter cleanup)
- user-machine.actors.ts: removed redundant `userStorage.clearUserData()`
  from `userLogoutActor` — `authRepo.logout` already clears local
  user data, so this was a no-op duplicate.
- sidebar-screen.tsx: removed one stale comment line.
This commit is contained in:
2026-06-16 18:34:55 +08:00
parent 8832552321
commit 0a9abc2502
5 changed files with 9 additions and 34 deletions
+9 -5
View File
@@ -17,7 +17,6 @@ import { GuestLoginRequest } from "@/data/dto/auth/guest_login_request";
import { GuestLoginResponse } from "@/data/dto/auth/guest_login_response";
import { LoginRequest } from "@/data/dto/auth/login_request";
import { LoginResponse } from "@/data/dto/auth/login_response";
import { LogoutResponse } from "@/data/dto/auth/logout_response";
import { RefreshTokenRequest } from "@/data/dto/auth/refresh_token_request";
import { RefreshTokenResponse } from "@/data/dto/auth/refresh_token_response";
import { RegisterRequest } from "@/data/dto/auth/register_request";
@@ -102,13 +101,18 @@ export class AuthApi {
}
/**
* 退出登录
* 退出登录fire-and-forget
*
* 后端 logout 端点的 envelope `data` 字段常为 `null`(登出端点没有业务数据),
* 不要再用 `unwrap` + `LogoutResponse.fromJson` 解析 —— Zod schema 是 z.object
* 对 null 会抛 ZodError "Invalid input: expected object, received null"。
*
* 对齐 `register` / `sendCode` 的写法:调通就完事,不解析响应体。
*/
async logout(): Promise<LogoutResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.logout, {
async logout(): Promise<void> {
await httpClient<ApiEnvelope<unknown>>(ApiPath.logout, {
method: "POST",
});
return LogoutResponse.fromJson(unwrap(env) as Record<string, unknown>);
}
/**