refactor(data): replace schema classes with readonly models

This commit is contained in:
2026-07-17 13:21:40 +08:00
parent 3437312167
commit ae97366a4a
103 changed files with 1220 additions and 2117 deletions
+40 -38
View File
@@ -2,32 +2,37 @@
* Auth API
*
* 认证相关接口
*
*
*/
import { z } from "zod";
import { httpClient } from "./http_client";
import { ApiPath } from "./api_path";
import { ApiEnvelope, unwrap } from "./response_helper";
import {
FacebookIdentityRequest,
FacebookIdentityResponse,
FacebookIdentityResponseSchema,
FacebookLoginRequest,
FacebookPsidLoginRequest,
FacebookPsidLoginResponse,
FacebookPsidLoginResponseSchema,
FbIdLoginRequest,
GoogleLoginRequest,
GuestLoginRequest,
GuestLoginResponse,
GuestLoginResponseSchema,
LoginRequest,
LoginResponse,
LoginResponseSchema,
RefreshTokenRequest,
RefreshTokenResponse,
RefreshTokenResponseSchema,
RegisterRequest,
} from "@/data/schemas/auth";
import { User } from "@/data/schemas/user";
import { User, UserSchema } from "@/data/schemas/user";
import type { UserData } from "@/data/schemas/user/user";
import { Logger } from "@/utils/logger";
import { ApiPath } from "./api_path";
import { httpClient } from "./http_client";
import { ApiEnvelope, unwrap } from "./response_helper";
const log = new Logger("DataServicesApiAuthApi");
@@ -36,11 +41,11 @@ export class AuthApi {
* 邮箱密码登录
*/
async emailLogin(body: LoginRequest): Promise<LoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.emailLogin,
{ method: "POST", body: body.toJson() }
);
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.emailLogin, {
method: "POST",
body,
});
return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
}
/**
@@ -49,7 +54,7 @@ export class AuthApi {
async register(body: RegisterRequest): Promise<void> {
await httpClient<ApiEnvelope<unknown>>(ApiPath.register, {
method: "POST",
body: body.toJson(),
body,
});
}
@@ -59,20 +64,20 @@ export class AuthApi {
async googleLogin(body: GoogleLoginRequest): Promise<LoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.googleLogin, {
method: "POST",
body: body.toJson(),
body,
});
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
}
/**
* Facebook 登录
*/
async facebookLogin(body: FacebookLoginRequest): Promise<LoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.facebookLogin,
{ method: "POST", body: body.toJson() }
);
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.facebookLogin, {
method: "POST",
body,
});
return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
}
/**
@@ -81,9 +86,9 @@ export class AuthApi {
async facebookIdLogin(body: FbIdLoginRequest): Promise<LoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.facebookIdLogin,
{ method: "POST", body: body.toJson() }
{ method: "POST", body },
);
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
return LoginResponseSchema.parse(unwrap(env) as Record<string, unknown>);
}
/**
@@ -94,9 +99,9 @@ export class AuthApi {
): Promise<FacebookPsidLoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.facebookPsidLogin,
{ method: "POST", body: body.toJson() },
{ method: "POST", body },
);
return FacebookPsidLoginResponse.fromJson(
return FacebookPsidLoginResponseSchema.parse(
unwrap(env) as Record<string, unknown>,
);
}
@@ -109,9 +114,9 @@ export class AuthApi {
): Promise<FacebookIdentityResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.userFacebookIdentity,
{ method: "POST", body: body.toJson() },
{ method: "POST", body },
);
return FacebookIdentityResponse.fromJson(
return FacebookIdentityResponseSchema.parse(
unwrap(env) as Record<string, unknown>,
);
}
@@ -120,7 +125,7 @@ export class AuthApi {
* 退出登录(fire-and-forget
*
* 后端 logout 端点的 envelope `data` 字段常为 `null`(登出端点没有业务数据),
* 不要再用 `unwrap` + `LogoutResponse.fromJson` 解析 —— Zod schema 是 z.object
* 不要再用 `unwrap` + `LogoutResponseSchema.parse` 解析 —— Zod schema 是 z.object
* 对 null 会抛 ZodError "Invalid input: expected object, received null"。
*
* 对齐 `register` 的写法:调通就完事,不解析响应体。
@@ -137,19 +142,20 @@ export class AuthApi {
async guestLogin(body: GuestLoginRequest): Promise<GuestLoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.guestLogin, {
method: "POST",
body: body.toJson(),
body,
});
log.debug("[AuthApi.guestLogin] raw envelope from backend", env);
const unwrapped = unwrap(env) as Record<string, unknown>;
const userObj = unwrapped.user as { lastMessageAt?: unknown } | undefined;
log.debug("[AuthApi.guestLogin] unwrapped data (pre-parse)", {
hasUser: "user" in unwrapped,
userKeys: userObj && typeof userObj === "object" ? Object.keys(userObj) : null,
userKeys:
userObj && typeof userObj === "object" ? Object.keys(userObj) : null,
lastMessageAt: userObj?.lastMessageAt,
lastMessageAtType: typeof userObj?.lastMessageAt,
});
try {
return GuestLoginResponse.fromJson(unwrapped);
return GuestLoginResponseSchema.parse(unwrapped);
} catch (e) {
if (e instanceof z.ZodError) {
log.error("[AuthApi.guestLogin] ZodError parsing response", {
@@ -167,15 +173,13 @@ export class AuthApi {
/**
* 刷新 Token
*/
async refreshToken(
body: RefreshTokenRequest
): Promise<RefreshTokenResponse> {
async refreshToken(body: RefreshTokenRequest): Promise<RefreshTokenResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.refresh, {
method: "POST",
body: body.toJson(),
body,
});
return RefreshTokenResponse.fromJson(
unwrap(env) as Record<string, unknown>
return RefreshTokenResponseSchema.parse(
unwrap(env) as Record<string, unknown>,
);
}
@@ -183,10 +187,8 @@ export class AuthApi {
* 获取当前用户信息
*/
async getCurrentUser(): Promise<User> {
const env = await httpClient<ApiEnvelope<unknown>>(
ApiPath.getCurrentUser
);
return User.fromJson(unwrap(env) as UserData);
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.getCurrentUser);
return UserSchema.parse(unwrap(env) as UserData);
}
}