/** * Auth 状态机(XState v5) * * 原始 Dart: lib/ui/auth/bloc/auth_bloc.dart + auth_state.dart + auth_event.dart * * 本轮迁移:社交登录改由 NextAuth 处理(`@/lib/auth/nextauth`),状态机仅保留 * 邮箱注册/登录 + 通用 reset 事件。社交登录走 `new AuthPlatform("google").signIn()` / * `new AuthPlatform("facebook").signIn()`。 */ import { setup, fromPromise, assign } from "xstate"; import type { LoginType } from "@/models/auth/login-type"; import { authRepository } from "@/data/repositories/auth_repository"; import { AuthStorage } from "@/data/storage/auth/auth_storage"; import { Result } from "@/utils/result"; import { AuthState, initialState } from "./auth-state"; import type { AuthEvent } from "./auth-events"; // 重新导出 State / Event 类型,保持 machine 文件的公共 API 不变 export type { AuthState } from "./auth-state"; export { initialState } from "./auth-state"; export type { AuthEvent } from "./auth-events"; // ============================================================ // Helpers // ============================================================ async function readGuestId(): Promise { const r = await AuthStorage.getInstance().getDeviceId(); if (r.success && r.data != null) { return r.data; } return undefined; } // ============================================================ // Actors(异步服务) // ============================================================ // 邮箱登录 actor 仅调 authRepository.emailLogin 拿业务 token。 // 本轮起不再调 /api/auth/marker 写 cookie(统一迁到 NextAuth session // cookie 检测,邮箱登录 proxy 行为在后续轮恢复)。 const emailLoginActor = fromPromise( async ({ input }) => { const guestId = await readGuestId(); const result = await authRepository.emailLogin({ ...input, guestId }); if (Result.isErr(result)) throw result.error; return "email" as LoginType; }, ); const emailRegisterThenLoginActor = fromPromise< LoginType, { email: string; password: string; username: string; confirmPassword: string } >(async ({ input }) => { const guestId = await readGuestId(); const registerResult = await authRepository.register({ ...input, guestId }); if (Result.isErr(registerResult)) throw registerResult.error; // 注册后自动登录(对齐 Dart 行为) const loginResult = await authRepository.emailLogin({ email: input.email, password: input.password, guestId, }); if (Result.isErr(loginResult)) throw loginResult.error; return "email" as LoginType; }); // ============================================================ // Machine // ============================================================ export const authMachine = setup({ types: { context: {} as AuthState, events: {} as AuthEvent, }, actors: { emailLogin: emailLoginActor, emailRegisterThenLogin: emailRegisterThenLoginActor, }, }).createMachine({ id: "auth", initial: "idle", context: initialState, states: { idle: { on: { AuthPanelModeChanged: { actions: assign({ authPanelMode: ({ event }) => event.mode, errorMessage: null, }), }, AuthModeChanged: { actions: assign({ authMode: ({ event }) => event.mode, errorMessage: null, }), }, AuthFormCleared: { actions: assign({ email: "", password: "", username: "", confirmPassword: "", errorMessage: null, }), }, AuthReset: { actions: assign(() => initialState), }, AuthEmailLoginSubmitted: "loadingEmailLogin", AuthEmailRegisterSubmitted: "loadingEmailRegister", // 社交登录已迁移到 NextAuth + AuthPlatform 类 // 状态机保留事件以兼容旧调用方(实际不再触发) AuthGoogleLoginSubmitted: {}, AuthFacebookLoginSubmitted: {}, AuthAppleLoginSubmitted: { actions: assign({ errorMessage: "Apple login not implemented", }), }, }, }, loadingEmailLogin: { invoke: { src: "emailLogin", input: ({ event }) => { if (event.type !== "AuthEmailLoginSubmitted") return { email: "", password: "" }; return { email: event.email, password: event.password }; }, onDone: { target: "success", actions: assign({ loginType: ({ event }) => event.output, errorMessage: null, }), }, onError: { target: "idle", actions: assign({ errorMessage: ({ event }) => event.error instanceof Error ? event.error.message : String(event.error), }), }, }, }, loadingEmailRegister: { invoke: { src: "emailRegisterThenLogin", input: ({ event }) => { if (event.type !== "AuthEmailRegisterSubmitted") return { email: "", password: "", username: "", confirmPassword: "" }; return { email: event.email, password: event.password, username: event.username, confirmPassword: event.confirmPassword, }; }, onDone: { target: "success", actions: assign({ loginType: ({ event }) => event.output, errorMessage: null, }), }, onError: { target: "idle", actions: assign({ errorMessage: ({ event }) => event.error instanceof Error ? event.error.message : String(event.error), }), }, }, }, success: { // 终态:业务层通过 state.matches("success") 判断 }, }, }); export type AuthMachine = typeof authMachine;