Files
cozsweet-frontend-nextjs/src/data/services/api/auth_api.ts
T

186 lines
5.1 KiB
TypeScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
/**
* Auth API
*
* 认证相关接口
* 原始 Dart: lib/data/services/api/auth_api_client.dart
*/
import { z } from "zod";
import { httpClient } from "./http_client";
import { ApiPath } from "./api_path";
import { ApiEnvelope, unwrap } from "./response_helper";
import {
AppleLoginRequest,
FacebookLoginRequest,
FbIdLoginRequest,
GoogleLoginRequest,
GuestLoginRequest,
GuestLoginResponse,
LoginRequest,
LoginResponse,
RefreshTokenRequest,
RefreshTokenResponse,
RegisterRequest,
SendCodeRequest,
} from "@/data/dto/auth";
import { User } from "@/data/dto/user";
import type { UserData } from "@/data/schemas/user/user";
import { Logger } from "@/utils";
const log = new Logger("DataServicesApiAuthApi");
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>);
}
/**
* 退出登录(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<void> {
await httpClient<ApiEnvelope<unknown>>(ApiPath.logout, {
method: "POST",
});
}
/**
* 游客登录
*/
async guestLogin(body: GuestLoginRequest): Promise<GuestLoginResponse> {
const env = await httpClient<ApiEnvelope<unknown>>(ApiPath.guestLogin, {
method: "POST",
body: body.toJson(),
});
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,
lastMessageAt: userObj?.lastMessageAt,
lastMessageAtType: typeof userObj?.lastMessageAt,
});
try {
return GuestLoginResponse.fromJson(unwrapped);
} catch (e) {
if (e instanceof z.ZodError) {
log.error("[AuthApi.guestLogin] ZodError parsing response", {
issueCount: e.issues.length,
firstIssue: e.issues[0],
allPaths: e.issues.map((i) => i.path),
});
} else {
log.error("[AuthApi.guestLogin] unexpected error", e);
}
throw e;
}
}
/**
* 刷新 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();