feat: implement lazy singleton pattern for repository instances and update related imports
This commit is contained in:
@@ -5,8 +5,7 @@ import { fromPromise } from "xstate";
|
||||
|
||||
import { AuthPlatform, type AuthProvider } from "@/lib/auth/auth_platform";
|
||||
import type { LoginStatus } from "@/data/dto/auth";
|
||||
import { authRepository } from "@/data/repositories/auth_repository";
|
||||
import type { IAuthRepository } from "@/data/repositories/interfaces";
|
||||
import { getAuthRepository } from "@/data/repositories/auth_repository";
|
||||
import { fetchFacebookUserData } from "@/data/services";
|
||||
import { AuthStorage } from "@/data/storage/auth/auth_storage";
|
||||
import { UserStorage } from "@/data/storage/user/user_storage";
|
||||
@@ -16,11 +15,9 @@ import { readGuestId } from "./auth-helpers";
|
||||
|
||||
const log = new Logger("AuthActors");
|
||||
|
||||
// 仓库以接口类型注入:调用面只看接口,运行时仍是同一单例
|
||||
const authRepo: IAuthRepository = authRepository;
|
||||
|
||||
export const emailLoginActor = fromPromise<LoginStatus, { email: string; password: string }>(
|
||||
async ({ input }) => {
|
||||
const authRepo = getAuthRepository();
|
||||
log.debug("[auth-machine] emailLoginActor ENTRY", {
|
||||
emailLength: input.email.length,
|
||||
emailPreview: input.email.slice(0, 8),
|
||||
@@ -46,6 +43,7 @@ export const emailRegisterThenLoginActor = fromPromise<
|
||||
LoginStatus,
|
||||
{ email: string; password: string; username: string; confirmPassword: string }
|
||||
>(async ({ input }) => {
|
||||
const authRepo = getAuthRepository();
|
||||
log.debug("[auth-machine] emailRegisterThenLoginActor ENTRY", {
|
||||
emailLength: input.email.length,
|
||||
usernameLength: input.username.length,
|
||||
@@ -96,6 +94,7 @@ export const oauthSignInActor = fromPromise<void, AuthProvider>(async ({ input }
|
||||
});
|
||||
|
||||
export const logoutActor = fromPromise<void>(async () => {
|
||||
const authRepo = getAuthRepository();
|
||||
const result = await authRepo.logout();
|
||||
if (Result.isErr(result)) throw result.error;
|
||||
});
|
||||
@@ -103,10 +102,11 @@ export const logoutActor = fromPromise<void>(async () => {
|
||||
// ========== OAuth token → 后端业务 token sync actors ==========
|
||||
// 由 <OAuthSessionSync /> 在 NextAuth 回调后派发(监听 useSession())。
|
||||
// 用 OAuth provider 的 idToken / accessToken 调后端换业务 token + user。
|
||||
// 后端返回的 LoginResponse 已经被 authRepository._saveLoginData 持久化。
|
||||
// 后端返回的 LoginResponse 已经被 AuthRepository._saveLoginData 持久化。
|
||||
|
||||
export const syncGoogleBackendActor = fromPromise<LoginStatus, { idToken: string }>(
|
||||
async ({ input }) => {
|
||||
const authRepo = getAuthRepository();
|
||||
const guestId = await readGuestId();
|
||||
const result = await authRepo.googleLogin({
|
||||
idToken: input.idToken,
|
||||
@@ -121,6 +121,7 @@ export const syncFacebookBackendActor = fromPromise<
|
||||
LoginStatus,
|
||||
{ accessToken: string }
|
||||
>(async ({ input }) => {
|
||||
const authRepo = getAuthRepository();
|
||||
const guestId = await readGuestId();
|
||||
const result = await authRepo.facebookLogin({
|
||||
accessToken: input.accessToken,
|
||||
@@ -193,13 +194,6 @@ async function persistFacebookProfile(accessToken: string): Promise<void> {
|
||||
|
||||
// ========== 显式游客登录 actor(opt-in) ==========
|
||||
// 由 splash UI 派发 `AuthGuestLoginSubmitted` 触发,不自动跑。
|
||||
// 取代了之前 checkAuthStatusActor 的 auto-guest-login 行为 —— 避免每次
|
||||
// 访 splash 都自动创建游客账号污染后端。
|
||||
//
|
||||
// 短路优化:本地已有 guestToken 时直接 return "guest",跳过 deviceId
|
||||
// 探测 + 后端 round-trip(splash 每打开一次就可能点一次 Skip,命中率高)。
|
||||
// 已知 trade-off:若后端已吊销该 token,actor 仍返回 "guest" —— 任何后续
|
||||
// 受保护 API 401 会由 HTTP 层清掉 token 回到 splash,无需在此处主动校验。
|
||||
|
||||
export const guestLoginActor = fromPromise<LoginStatus, void>(async () => {
|
||||
log.debug("[auth-machine] guestLoginActor ENTRY");
|
||||
@@ -223,9 +217,9 @@ export const guestLoginActor = fromPromise<LoginStatus, void>(async () => {
|
||||
prefix: deviceId.slice(0, 8),
|
||||
});
|
||||
|
||||
log.debug("[auth-machine] guestLoginActor calling authRepository.guestLogin");
|
||||
const result = await authRepository.guestLogin(deviceId);
|
||||
log.debug("[auth-machine] guestLoginActor authRepository.guestLogin DONE", {
|
||||
log.debug("[auth-machine] guestLoginActor calling authRepo.guestLogin");
|
||||
const result = await getAuthRepository().guestLogin(deviceId);
|
||||
log.debug("[auth-machine] guestLoginActor authRepo.guestLogin DONE", {
|
||||
success: result.success,
|
||||
hasData: result.success ? !!result.data : null,
|
||||
errorName: result.success ? null : result.error?.name,
|
||||
@@ -260,6 +254,7 @@ export const checkAuthStatusActor = fromPromise<LoginStatus, void>(async () => {
|
||||
// 3. 外部浏览器深链同步:仅 fbid 落地时,用它换业务 token。
|
||||
const facebookIdR = await storage.getFacebookId();
|
||||
if (facebookIdR.success && facebookIdR.data) {
|
||||
const authRepo = getAuthRepository();
|
||||
const avatarUrlR = await UserStorage.getInstance().getAvatarUrl();
|
||||
const result = await authRepo.facebookIdLogin({
|
||||
fbId: facebookIdR.data,
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
* - 有 NextAuth OAuth session(provider + token)
|
||||
* - 且 auth machine 还没有该 provider 的业务 token
|
||||
* → 派发 `AuthGoogleSyncSubmitted` / `AuthFacebookSyncSubmitted` 事件
|
||||
* → auth machine 调 `authRepository.googleLogin/facebookLogin` 换业务 token
|
||||
* → auth machine 调 `AuthRepository.googleLogin/facebookLogin` 换业务 token
|
||||
* → 业务 token 写入本地 storage
|
||||
* → **清掉 NextAuth session**(`signOut({ redirect: false })`):
|
||||
* idToken / accessToken 已交给后端换业务 token,浏览器侧不再需要保留 OAuth 凭证
|
||||
|
||||
Reference in New Issue
Block a user