refactor(data): merge DTO models into schemas

This commit is contained in:
2026-07-17 12:47:18 +08:00
parent 2796010971
commit eac3d8f0a7
274 changed files with 1466 additions and 1956 deletions
@@ -5,7 +5,8 @@ import { hydrateRoot, type Root } from "react-dom/client";
import { renderToString } from "react-dom/server";
import { afterEach, describe, expect, it, vi } from "vitest";
import type { AuthPanelMode, LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import type { AuthPanelMode } from "@/stores/auth/auth-panel-mode";
vi.mock("@/stores/auth/auth-machine", async () => {
const { setup } = await import("xstate");
@@ -1,7 +1,7 @@
import { vi } from "vitest";
import { fromPromise } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import type { AuthProvider } from "@/lib/auth/auth_platform";
import { authMachine } from "@/stores/auth/auth-machine";
import type { BindFacebookIdentityInput } from "@/stores/auth/auth-events";
+1 -1
View File
@@ -4,7 +4,7 @@
* 事件名与原 Dart AuthEvent 对齐。
*/
import type { AuthProvider } from "@/lib/auth/auth_platform";
import type { AuthPanelMode } from "@/data/dto/auth";
import type { AuthPanelMode } from "@/stores/auth/auth-panel-mode";
export interface BindFacebookIdentityInput {
asid?: string;
+7
View File
@@ -0,0 +1,7 @@
export const AuthPanelMode = {
Facebook: "facebook",
Email: "email",
} as const;
export type AuthPanelMode =
(typeof AuthPanelMode)[keyof typeof AuthPanelMode];
+3 -1
View File
@@ -1,7 +1,9 @@
/**
* Auth 状态机:State 形状 + 初始值
*/
import type { AuthPanelMode, LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import type { AuthPanelMode } from "./auth-panel-mode";
export interface AuthState {
/** 当前面板模式(Facebook / Email */
+1
View File
@@ -2,6 +2,7 @@
export * from "./auth-context";
export * from "./auth-events";
export * from "./auth-panel-mode";
export * from "./helper";
export * from "./auth-machine";
export * from "./auth-state";
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import { getAuthRepository } from "@/data/repositories/auth_repository";
import { Logger } from "@/utils/logger";
import { Result } from "@/utils/result";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import { getAuthRepository } from "@/data/repositories/auth_repository";
import { fetchFacebookUserData } from "@/data/services";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import { getAuthRepository } from "@/data/repositories/auth_repository";
import { AuthStorage } from "@/data/storage/auth/auth_storage";
import { UserStorage } from "@/data/storage/user/user_storage";
+1 -1
View File
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import { toAuthErrorMessage } from "../helper/error";
import {
+1 -1
View File
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import type { AuthProvider } from "@/lib/auth/auth_platform";
import { toAuthErrorMessage } from "../helper/error";
+1 -1
View File
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import { toAuthErrorMessage } from "../helper/error";
import {
@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { ChatSendResponse } from "@/data/dto/chat";
import { ChatSendResponse } from "@/data/schemas/chat";
import type { ChatState } from "@/stores/chat/chat-state";
import {
applyNetworkHistoryLoadedOutput,
@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import { createActor, fromCallback, waitFor } from "xstate";
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import type { ChatEvent } from "@/stores/chat/chat-events";
import { chatMachine } from "@/stores/chat/chat-machine";
import type { LoadMoreHistoryActorEvent } from "@/stores/chat/machine/actors/history";
@@ -3,8 +3,7 @@ import { fromCallback, fromPromise } from "xstate";
import {
ChatSendResponse,
UnlockPrivateResponse,
type UiMessage,
} from "@/data/dto/chat";
} from "@/data/schemas/chat";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { chatMachine } from "@/stores/chat/chat-machine";
import type { ChatEvent } from "@/stores/chat/chat-events";
@@ -13,6 +12,7 @@ import type {
UnlockMessageRequest,
} from "@/stores/chat/helper/unlock";
import type { ChatHistoryActorInput } from "@/stores/chat/machine/actors/history";
import type { UiMessage } from "@/stores/chat/ui-message";
export interface SendMessageHttpOutput {
response: ChatSendResponse;
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { UnlockPrivateResponse } from "@/data/dto/chat";
import { UnlockPrivateResponse } from "@/data/schemas/chat";
import type { PendingChatPromotion } from "@/data/storage/navigation";
import {
appendPromotionMessage,
@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import { createActor, fromPromise, waitFor } from "xstate";
import { ChatSendResponse } from "@/data/dto/chat";
import { ChatSendResponse } from "@/data/schemas/chat";
import type {
UnlockMessageOutput,
UnlockMessageRequest,
+1 -1
View File
@@ -1,4 +1,4 @@
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import { resolveChatConversationKey } from "@/data/repositories/chat_cache_identity";
import { loadChatRepository } from "@/data/repositories/chat_repository_loader";
import { Logger } from "@/utils/logger";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import type { PendingChatUnlockKind } from "@/lib/navigation/chat_unlock_session";
import type { ChatLockType } from "@/data/schemas/chat";
import type { PendingChatPromotion } from "@/data/storage/navigation";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import type { ChatState } from "../chat-state";
+5 -2
View File
@@ -1,5 +1,8 @@
import { type ChatSendResponse, type UiMessage } from "@/data/dto/chat";
import type { ChatLockDetailData } from "@/data/schemas/chat";
import type {
ChatLockDetailData,
ChatSendResponse,
} from "@/data/schemas/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import { todayString } from "@/utils/date";
/**
+1 -1
View File
@@ -1,4 +1,4 @@
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import type { PendingChatPromotion } from "@/data/storage/navigation";
import { todayString } from "@/utils/date";
+2 -1
View File
@@ -1,4 +1,5 @@
import { type ChatSendResponse, type UiMessage } from "@/data/dto/chat";
import type { ChatSendResponse } from "@/data/schemas/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import type { ChatState, ChatUpgradeReason } from "../chat-state";
+5 -2
View File
@@ -1,5 +1,8 @@
import type { UiMessage, UnlockPrivateResponse } from "@/data/dto/chat";
import type { ChatLockType } from "@/data/schemas/chat";
import type {
ChatLockType,
UnlockPrivateResponse,
} from "@/data/schemas/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
export interface UnlockMessageRequest {
displayMessageId: string;
+1
View File
@@ -5,3 +5,4 @@ export * from "./chat-events";
export * from "./helper";
export * from "./chat-machine";
export * from "./chat-state";
export * from "./ui-message";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromCallback } from "xstate";
import type { UiMessage } from "@/data/dto/chat";
import type { UiMessage } from "@/stores/chat/ui-message";
import { loadChatRepository } from "@/data/repositories/chat_repository_loader";
import { Logger } from "@/utils/logger";
import { Result } from "@/utils/result";
+2 -2
View File
@@ -2,7 +2,7 @@ import { fromCallback, fromPromise } from "xstate";
import { ExceptionHandler } from "@/core/errors";
import { MessageQueue } from "@/core/net/message-queue";
import type { ChatSendResponse } from "@/data/dto/chat";
import type { ChatSendResponse } from "@/data/schemas/chat";
import { loadChatRepository } from "@/data/repositories/chat_repository_loader";
import { resolveChatConversationKey } from "@/data/repositories/chat_cache_identity";
import { Logger } from "@/utils/logger";
@@ -13,7 +13,7 @@ import { sendResponseToUiMessage } from "../../helper/message-mappers";
const log = new Logger("StoresChatChatSendFlow");
type UiMessage = import("@/data/dto/chat").UiMessage;
type UiMessage = import("@/stores/chat/ui-message").UiMessage;
export const sendMessageHttpActor = fromPromise<
{ response: ChatSendResponse; reply: UiMessage | null },
+1 -1
View File
@@ -13,7 +13,7 @@ import {
const log = new Logger("StoresChatChatUnlockFlow");
type UiMessage = import("@/data/dto/chat").UiMessage;
type UiMessage = import("@/stores/chat/ui-message").UiMessage;
export interface UnlockHistoryOutput {
unlocked: boolean;
+33
View File
@@ -0,0 +1,33 @@
import { z } from "zod";
export const UiMessageSchema = z.object({
id: z.string().optional(),
content: z.string(),
isFromAI: z.boolean(),
date: z.string(),
isSynthetic: z.boolean().optional(),
imageUrl: z.string().optional(),
imagePaywalled: z.boolean().optional(),
audioUrl: z.string().optional(),
locked: z.boolean().nullable().optional(),
lockReason: z.string().nullable().optional(),
isPrivate: z.boolean().nullable().optional(),
lockedPrivate: z.boolean().nullable().optional(),
privateMessageHint: z.string().nullable().optional(),
});
export type UiMessage = z.infer<typeof UiMessageSchema>;
export const UiMessage = {
create(input: Omit<UiMessage, "date"> & { date?: string }): UiMessage {
return UiMessageSchema.parse({
...input,
date:
input.date ??
new Date().toLocaleTimeString([], {
hour: "2-digit",
minute: "2-digit",
}),
});
},
};
@@ -1,7 +1,7 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import { createActor, waitFor } from "xstate";
import { PaymentPlansResponse } from "@/data/dto/payment";
import { PaymentPlansResponse } from "@/data/schemas/payment";
import {
createTestPaymentMachine,
@@ -6,7 +6,7 @@ import {
type PayChannel,
PaymentOrderStatusResponse,
PaymentPlansResponse,
} from "@/data/dto/payment";
} from "@/data/schemas/payment";
import { paymentMachine } from "@/stores/payment/payment-machine";
import type { PaymentPlanCatalog } from "@/stores/payment/payment-state";
+1 -1
View File
@@ -1,4 +1,4 @@
import { PaymentPlan, type PaymentPlansResponse } from "@/data/dto/payment";
import { PaymentPlan, type PaymentPlansResponse } from "@/data/schemas/payment";
import type { PaymentState } from "../payment-state";
import { resetOrderState } from "./order";
+1 -1
View File
@@ -1,5 +1,5 @@
import { ExceptionHandler } from "@/core/errors";
import type { PaymentPlan } from "@/data/dto/payment";
import type { PaymentPlan } from "@/data/schemas/payment";
import type { PaymentState } from "../payment-state";
+1 -1
View File
@@ -4,7 +4,7 @@ import {
CreatePaymentOrderResponse,
PayChannel,
PaymentOrderStatusResponse,
} from "@/data/dto/payment";
} from "@/data/schemas/payment";
import { getPaymentRepository } from "@/data/repositories/payment_repository";
import { Result } from "@/utils/result";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import { PaymentPlansResponse } from "@/data/dto/payment";
import { PaymentPlansResponse } from "@/data/schemas/payment";
import { getPaymentRepository } from "@/data/repositories/payment_repository";
import { Result } from "@/utils/result";
+1 -1
View File
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { PaymentPlansResponse } from "@/data/dto/payment";
import type { PaymentPlansResponse } from "@/data/schemas/payment";
import {
consumeFirstRechargeState,
+1 -1
View File
@@ -3,7 +3,7 @@ import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type {
CreatePaymentOrderResponse,
PaymentOrderStatusResponse,
} from "@/data/dto/payment";
} from "@/data/schemas/payment";
import { behaviorAnalytics } from "@/lib/analytics";
import {
+1 -1
View File
@@ -1,7 +1,7 @@
/**
* Payment 状态机:事件联合
*/
import type { PayChannel } from "@/data/dto/payment";
import type { PayChannel } from "@/data/schemas/payment";
import type { PaymentPlanCatalog } from "./payment-state";
export type PaymentEvent =
+1 -1
View File
@@ -5,7 +5,7 @@ import type {
PayChannel,
PaymentOrderStatus,
PaymentPlan,
} from "@/data/dto/payment";
} from "@/data/schemas/payment";
export type PaymentPlanCatalog = "default" | "tip";
@@ -3,7 +3,7 @@ import { createActor, fromPromise, waitFor } from "xstate";
import {
PrivateAlbumsResponse,
PrivateAlbumUnlockResponse,
} from "@/data/dto/private-room";
} from "@/data/schemas/private-room";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { privateRoomMachine } from "@/stores/private-room/private-room-machine";
+1 -1
View File
@@ -2,7 +2,7 @@ import {
PrivateAlbum,
type PrivateAlbumsResponse,
type PrivateAlbumUnlockResponse,
} from "@/data/dto/private-room";
} from "@/data/schemas/private-room";
import type { PrivateRoomState } from "../private-room-state";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { PrivateAlbumUnlockResponse } from "@/data/dto/private-room";
import type { PrivateAlbumUnlockResponse } from "@/data/schemas/private-room";
import type { PrivateRoomUnlockPaywallRequest } from "../private-room-state";
@@ -3,7 +3,7 @@ import { fromPromise } from "xstate";
import type {
PrivateAlbumsResponse,
PrivateAlbumUnlockResponse,
} from "@/data/dto/private-room";
} from "@/data/schemas/private-room";
import { getPrivateRoomRepository } from "@/data/repositories/private_room_repository";
import { Result } from "@/utils/result";
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { PrivateAlbumsResponse } from "@/data/dto/private-room";
import type { PrivateAlbumsResponse } from "@/data/schemas/private-room";
import { applyAlbumsResponse } from "../helper/albums";
import { toPrivateRoomErrorMessage } from "../helper/unlock";
@@ -1,6 +1,6 @@
import type { DoneActorEvent, ErrorActorEvent } from "xstate";
import type { PrivateAlbumUnlockResponse } from "@/data/dto/private-room";
import type { PrivateAlbumUnlockResponse } from "@/data/schemas/private-room";
import {
getPendingAlbum,
@@ -1,4 +1,4 @@
import type { PrivateAlbum } from "@/data/dto/private-room";
import type { PrivateAlbum } from "@/data/schemas/private-room";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
export interface PrivateRoomUnlockPaywallRequest {
+1 -1
View File
@@ -11,7 +11,7 @@
import { useEffect, useRef } from "react";
import { shallowEqual } from "@xstate/react";
import type { LoginStatus } from "@/data/dto/auth";
import type { LoginStatus } from "@/data/schemas/auth";
import {
selectAuthIsLoading,
useAuthSelector,
@@ -1,7 +1,7 @@
import { vi } from "vitest";
import { fromPromise } from "xstate";
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
import { userMachine } from "@/stores/user/user-machine";
import type { UserFetchData } from "@/stores/user/machine/actors/profile";
import type { InitData } from "@/stores/user/machine/actors/session";
+1 -1
View File
@@ -1,4 +1,4 @@
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
import type { UserEntitlementSnapshotData } from "@/data/schemas/user";
export function toView(u: {
+1
View File
@@ -5,3 +5,4 @@ export * from "./user-events";
export * from "./helper";
export * from "./user-machine";
export * from "./user-state";
export * from "./user-view";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
import { getUserRepository } from "@/data/repositories/user_repository";
import type { UserEntitlementSnapshotData } from "@/data/schemas/user";
import { UserStorage } from "@/data/storage/user/user_storage";
+1 -1
View File
@@ -1,6 +1,6 @@
import { fromPromise } from "xstate";
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
import { getAuthRepository } from "@/data/repositories/auth_repository";
import type { UserEntitlementSnapshotData } from "@/data/schemas/user";
import { UserStorage } from "@/data/storage/user/user_storage";
+1 -1
View File
@@ -1,7 +1,7 @@
/**
* User 状态机:事件联合
*/
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
export type UserEvent =
| { type: "UserInit" }
+1 -1
View File
@@ -1,7 +1,7 @@
/**
* User 状态机:State 形状 + 初始值
*/
import type { UserView } from "@/data/dto/user";
import type { UserView } from "@/stores/user/user-view";
export interface UserState {
currentUser: UserView | null;
+15
View File
@@ -0,0 +1,15 @@
import { z } from "zod";
export const UserViewSchema = z.object({
id: z.string(),
username: z.string(),
countryCode: z.string(),
creditBalance: z.number(),
dailyFreeChatLimit: z.number(),
dailyFreeChatRemaining: z.number(),
dailyFreePrivateLimit: z.number(),
dailyFreePrivateRemaining: z.number(),
isVip: z.boolean(),
});
export type UserView = z.infer<typeof UserViewSchema>;