75e685d418
Reorganize the data layer by separating DTOs (Data Transfer Objects) from Zod validation schemas into distinct directory structures. Previously, all model types were imported from a single `@/data/models` barrel file, mixing request/response classes with validation schemas. Changes: - Update API files (auth, chat, metrics, user) to import DTOs from specific paths under `@/data/dto/*` instead of the models barrel - Move user schema to `@/data/schemas/user/user` for type-only imports - Create dedicated Zod schema files under `@/data/schemas/*` for auth and chat domain models (e.g., AppleLoginRequestSchema, SendMessageRequestSchema, SyncMessageSchema, SttDataSchema) - Improve discoverability and tree-shaking by co-locating schemas with their respective domain areas This is a non-functional refactor that lays the groundwork for clearer separation between transport-layer types and runtime validation.
169 lines
4.8 KiB
TypeScript
169 lines
4.8 KiB
TypeScript
/**
|
|
* Auth API
|
|
*
|
|
* 认证相关接口
|
|
* 原始 Dart: lib/data/services/api/auth_api_client.dart
|
|
*/
|
|
import { httpClient } from "./http_client";
|
|
import { ApiPath } from "./api_path";
|
|
import { AppleLoginRequest } from "@/data/dto/auth/apple_login_request";
|
|
import { FacebookLoginRequest } from "@/data/dto/auth/facebook_login_request";
|
|
import { FbIdLoginRequest } from "@/data/dto/auth/fb_id_login_request";
|
|
import { GoogleLoginRequest } from "@/data/dto/auth/google_login_request";
|
|
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";
|
|
import { SendCodeRequest } from "@/data/dto/auth/send_code_request";
|
|
import { User } from "@/data/dto/user/user";
|
|
import type { UserData } from "@/data/schemas/user/user";
|
|
|
|
/**
|
|
* 后端统一响应包装
|
|
*/
|
|
interface ApiEnvelope<T> {
|
|
success: boolean;
|
|
data?: T;
|
|
message?: string;
|
|
error?: string;
|
|
}
|
|
|
|
function unwrap<T>(envelope: ApiEnvelope<T>): T {
|
|
if (!envelope.success || envelope.data === undefined) {
|
|
throw new Error(envelope.message ?? envelope.error ?? "API call failed");
|
|
}
|
|
return envelope.data;
|
|
}
|
|
|
|
export class AuthApi {
|
|
/**
|
|
* 发送验证码
|
|
*/
|
|
async sendCode(body: SendCodeRequest): Promise<void> {
|
|
await httpClient<ApiEnvelope<unknown>>(ApiPath.sendCode, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* 邮箱密码登录
|
|
*/
|
|
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>);
|
|
}
|
|
|
|
/**
|
|
* 注册
|
|
*/
|
|
async register(body: RegisterRequest): Promise<void> {
|
|
await httpClient<ApiEnvelope<unknown>>(ApiPath.register, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
}
|
|
|
|
/**
|
|
* Apple 登录
|
|
*/
|
|
async appleLogin(body: AppleLoginRequest): Promise<LoginResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.appleLogin, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
|
|
}
|
|
|
|
/**
|
|
* Google 登录
|
|
*/
|
|
async googleLogin(body: GoogleLoginRequest): Promise<LoginResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.googleLogin, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
return LoginResponse.fromJson(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>);
|
|
}
|
|
|
|
/**
|
|
* Facebook ID 登录(v7.0 新增)
|
|
*/
|
|
async facebookIdLogin(body: FbIdLoginRequest): Promise<LoginResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(
|
|
ApiPath.facebookIdLogin,
|
|
{ method: "POST", body: body.toJson() }
|
|
);
|
|
return LoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
|
|
}
|
|
|
|
/**
|
|
* 退出登录
|
|
*/
|
|
async logout(): Promise<LogoutResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.logout, {
|
|
method: "POST",
|
|
});
|
|
return LogoutResponse.fromJson(unwrap(env) as Record<string, unknown>);
|
|
}
|
|
|
|
/**
|
|
* 游客登录
|
|
*/
|
|
async guestLogin(body: GuestLoginRequest): Promise<GuestLoginResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.guestLogin, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
return GuestLoginResponse.fromJson(unwrap(env) as Record<string, unknown>);
|
|
}
|
|
|
|
/**
|
|
* 刷新 Token
|
|
*/
|
|
async refreshToken(
|
|
body: RefreshTokenRequest
|
|
): Promise<RefreshTokenResponse> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.refresh, {
|
|
method: "POST",
|
|
body: body.toJson(),
|
|
});
|
|
return RefreshTokenResponse.fromJson(
|
|
unwrap(env) as Record<string, unknown>
|
|
);
|
|
}
|
|
|
|
/**
|
|
* 获取当前用户信息
|
|
*/
|
|
async getCurrentUser(): Promise<User> {
|
|
const env = await httpClient<ApiEnvelope<unknown>>(
|
|
ApiPath.getCurrentUser
|
|
);
|
|
return User.fromJson(unwrap(env) as UserData);
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 全局单例
|
|
*/
|
|
export const authApi = new AuthApi();
|