From 75e685d4185be91a49891bbbe6905676f21c6e7b Mon Sep 17 00:00:00 2001 From: chenhang Date: Mon, 8 Jun 2026 19:14:40 +0800 Subject: [PATCH] refactor(data): split models into separate dto and schema modules 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. --- src/data/api/auth_api.ts | 32 ++++---- src/data/api/chat_api.ts | 22 +++--- src/data/api/metrics_api.ts | 3 +- src/data/api/user_api.ts | 14 ++-- .../auth/apple_login_request.ts | 17 ++-- .../auth/facebook_login_request.ts | 18 ++--- .../auth/fb_id_login_request.ts | 17 ++-- .../auth/google_login_request.ts | 18 ++--- .../auth/guest_login_request.ts | 16 ++-- src/data/dto/auth/guest_login_response.ts | 40 ++++++++++ .../{models => dto}/auth/login_request.ts | 20 ++--- .../{models => dto}/auth/login_response.ts | 25 +++--- .../{models => dto}/auth/logout_response.ts | 16 ++-- .../auth/refresh_token_request.ts | 16 ++-- .../auth/refresh_token_response.ts | 18 ++--- .../{models => dto}/auth/register_request.ts | 20 ++--- .../{models => dto}/auth/send_code_request.ts | 16 ++-- .../chat/chat_history_response.ts | 26 +++---- src/data/{models => dto}/chat/chat_message.ts | 19 ++--- .../chat/chat_send_response.ts | 28 ++----- .../{models => dto}/chat/chat_sync_data.ts | 17 ++-- .../{models => dto}/chat/chat_sync_request.ts | 23 +++--- .../{models => dto}/chat/guest_chat_quota.ts | 40 ++++------ .../chat/image_upload_response.ts | 23 ++---- .../chat/send_message_request.ts | 24 ++---- src/data/{models => dto}/chat/stt_data.ts | 16 ++-- src/data/{models => dto}/chat/sync_message.ts | 18 ++--- src/data/{models => dto}/index.ts | 9 ++- src/data/{models => dto}/metrics/app_event.ts | 18 ++--- src/data/{models => dto}/metrics/pwa_event.ts | 20 ++--- src/data/dto/user/avatar_data.ts | 31 ++++++++ src/data/dto/user/credits_data.ts | 31 ++++++++ src/data/dto/user/credits_history_data.ts | 33 ++++++++ src/data/dto/user/personality_traits.ts | 34 ++++++++ src/data/dto/user/recent_memory.ts | 33 ++++++++ src/data/dto/user/update_profile_request.ts | 33 ++++++++ src/data/dto/user/user.ts | 59 ++++++++++++++ src/data/dto/user/user_stats_response.ts | 51 ++++++++++++ src/data/models/auth/guest_login_response.ts | 52 ------------- src/data/models/auth/index.ts | 17 ---- src/data/models/chat/index.ts | 14 ---- src/data/models/metrics/index.ts | 6 -- src/data/models/user/avatar_data.ts | 35 --------- src/data/models/user/credits_data.ts | 35 --------- src/data/models/user/credits_history_data.ts | 39 ---------- src/data/models/user/index.ts | 12 --- src/data/models/user/personality_traits.ts | 49 ------------ src/data/models/user/recent_memory.ts | 39 ---------- .../models/user/update_profile_request.ts | 39 ---------- src/data/models/user/user.ts | 77 ------------------- src/data/models/user/user_stats_response.ts | 71 ----------------- src/data/schemas/auth/apple_login_request.ts | 13 ++++ .../schemas/auth/facebook_login_request.ts | 14 ++++ src/data/schemas/auth/fb_id_login_request.ts | 13 ++++ src/data/schemas/auth/google_login_request.ts | 14 ++++ src/data/schemas/auth/guest_login_request.ts | 12 +++ src/data/schemas/auth/guest_login_response.ts | 18 +++++ src/data/schemas/auth/login_request.ts | 16 ++++ src/data/schemas/auth/login_response.ts | 15 ++++ src/data/schemas/auth/logout_response.ts | 12 +++ .../schemas/auth/refresh_token_request.ts | 12 +++ .../schemas/auth/refresh_token_response.ts | 14 ++++ src/data/schemas/auth/register_request.ts | 16 ++++ src/data/schemas/auth/send_code_request.ts | 12 +++ .../schemas/chat/chat_history_response.ts | 16 ++++ src/data/schemas/chat/chat_message.ts | 15 ++++ src/data/schemas/chat/chat_send_response.ts | 22 ++++++ src/data/schemas/chat/chat_sync_data.ts | 13 ++++ src/data/schemas/chat/chat_sync_request.ts | 13 ++++ src/data/schemas/chat/guest_chat_quota.ts | 13 ++++ .../schemas/chat/image_upload_response.ts | 19 +++++ src/data/schemas/chat/send_message_request.ts | 20 +++++ src/data/schemas/chat/stt_data.ts | 12 +++ src/data/schemas/chat/sync_message.ts | 14 ++++ src/data/schemas/index.ts | 42 ++++++++++ src/data/schemas/metrics/app_event.ts | 14 ++++ src/data/schemas/metrics/pwa_event.ts | 16 ++++ src/data/schemas/user/avatar_data.ts | 13 ++++ src/data/schemas/user/credits_data.ts | 13 ++++ src/data/schemas/user/credits_history_data.ts | 15 ++++ src/data/schemas/user/personality_traits.ts | 24 ++++++ src/data/schemas/user/recent_memory.ts | 15 ++++ .../schemas/user/update_profile_request.ts | 15 ++++ src/data/schemas/user/user.ts | 27 +++++++ src/data/schemas/user/user_stats_response.ts | 29 +++++++ src/data/storage/chat/chat_storage.ts | 2 +- src/data/storage/chat/ichat_storage.ts | 4 +- src/data/storage/user/iuser_storage.ts | 4 +- src/data/storage/user/user_storage.ts | 2 +- 89 files changed, 1119 insertions(+), 853 deletions(-) rename src/data/{models => dto}/auth/apple_login_request.ts (61%) rename src/data/{models => dto}/auth/facebook_login_request.ts (60%) rename src/data/{models => dto}/auth/fb_id_login_request.ts (60%) rename src/data/{models => dto}/auth/google_login_request.ts (61%) rename src/data/{models => dto}/auth/guest_login_request.ts (61%) create mode 100644 src/data/dto/auth/guest_login_response.ts rename src/data/{models => dto}/auth/login_request.ts (58%) rename src/data/{models => dto}/auth/login_response.ts (55%) rename src/data/{models => dto}/auth/logout_response.ts (60%) rename src/data/{models => dto}/auth/refresh_token_request.ts (61%) rename src/data/{models => dto}/auth/refresh_token_response.ts (61%) rename src/data/{models => dto}/auth/register_request.ts (61%) rename src/data/{models => dto}/auth/send_code_request.ts (61%) rename src/data/{models => dto}/chat/chat_history_response.ts (54%) rename src/data/{models => dto}/chat/chat_message.ts (59%) rename src/data/{models => dto}/chat/chat_send_response.ts (54%) rename src/data/{models => dto}/chat/chat_sync_data.ts (61%) rename src/data/{models => dto}/chat/chat_sync_request.ts (53%) rename src/data/{models => dto}/chat/guest_chat_quota.ts (70%) rename src/data/{models => dto}/chat/image_upload_response.ts (60%) rename src/data/{models => dto}/chat/send_message_request.ts (55%) rename src/data/{models => dto}/chat/stt_data.ts (60%) rename src/data/{models => dto}/chat/sync_message.ts (61%) rename src/data/{models => dto}/index.ts (92%) rename src/data/{models => dto}/metrics/app_event.ts (58%) rename src/data/{models => dto}/metrics/pwa_event.ts (56%) create mode 100644 src/data/dto/user/avatar_data.ts create mode 100644 src/data/dto/user/credits_data.ts create mode 100644 src/data/dto/user/credits_history_data.ts create mode 100644 src/data/dto/user/personality_traits.ts create mode 100644 src/data/dto/user/recent_memory.ts create mode 100644 src/data/dto/user/update_profile_request.ts create mode 100644 src/data/dto/user/user.ts create mode 100644 src/data/dto/user/user_stats_response.ts delete mode 100644 src/data/models/auth/guest_login_response.ts delete mode 100644 src/data/models/auth/index.ts delete mode 100644 src/data/models/chat/index.ts delete mode 100644 src/data/models/metrics/index.ts delete mode 100644 src/data/models/user/avatar_data.ts delete mode 100644 src/data/models/user/credits_data.ts delete mode 100644 src/data/models/user/credits_history_data.ts delete mode 100644 src/data/models/user/index.ts delete mode 100644 src/data/models/user/personality_traits.ts delete mode 100644 src/data/models/user/recent_memory.ts delete mode 100644 src/data/models/user/update_profile_request.ts delete mode 100644 src/data/models/user/user.ts delete mode 100644 src/data/models/user/user_stats_response.ts create mode 100644 src/data/schemas/auth/apple_login_request.ts create mode 100644 src/data/schemas/auth/facebook_login_request.ts create mode 100644 src/data/schemas/auth/fb_id_login_request.ts create mode 100644 src/data/schemas/auth/google_login_request.ts create mode 100644 src/data/schemas/auth/guest_login_request.ts create mode 100644 src/data/schemas/auth/guest_login_response.ts create mode 100644 src/data/schemas/auth/login_request.ts create mode 100644 src/data/schemas/auth/login_response.ts create mode 100644 src/data/schemas/auth/logout_response.ts create mode 100644 src/data/schemas/auth/refresh_token_request.ts create mode 100644 src/data/schemas/auth/refresh_token_response.ts create mode 100644 src/data/schemas/auth/register_request.ts create mode 100644 src/data/schemas/auth/send_code_request.ts create mode 100644 src/data/schemas/chat/chat_history_response.ts create mode 100644 src/data/schemas/chat/chat_message.ts create mode 100644 src/data/schemas/chat/chat_send_response.ts create mode 100644 src/data/schemas/chat/chat_sync_data.ts create mode 100644 src/data/schemas/chat/chat_sync_request.ts create mode 100644 src/data/schemas/chat/guest_chat_quota.ts create mode 100644 src/data/schemas/chat/image_upload_response.ts create mode 100644 src/data/schemas/chat/send_message_request.ts create mode 100644 src/data/schemas/chat/stt_data.ts create mode 100644 src/data/schemas/chat/sync_message.ts create mode 100644 src/data/schemas/index.ts create mode 100644 src/data/schemas/metrics/app_event.ts create mode 100644 src/data/schemas/metrics/pwa_event.ts create mode 100644 src/data/schemas/user/avatar_data.ts create mode 100644 src/data/schemas/user/credits_data.ts create mode 100644 src/data/schemas/user/credits_history_data.ts create mode 100644 src/data/schemas/user/personality_traits.ts create mode 100644 src/data/schemas/user/recent_memory.ts create mode 100644 src/data/schemas/user/update_profile_request.ts create mode 100644 src/data/schemas/user/user.ts create mode 100644 src/data/schemas/user/user_stats_response.ts diff --git a/src/data/api/auth_api.ts b/src/data/api/auth_api.ts index abc809ed..f08522f0 100644 --- a/src/data/api/auth_api.ts +++ b/src/data/api/auth_api.ts @@ -6,23 +6,21 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - AppleLoginRequest, - FacebookLoginRequest, - FbIdLoginRequest, - GoogleLoginRequest, - GuestLoginRequest, - GuestLoginResponse, - LoginRequest, - LoginResponse, - LogoutResponse, - RefreshTokenRequest, - RefreshTokenResponse, - RegisterRequest, - SendCodeRequest, - User, - type UserData, -} from "@/data/models"; +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"; /** * 后端统一响应包装 diff --git a/src/data/api/chat_api.ts b/src/data/api/chat_api.ts index 3a70e985..2201047d 100644 --- a/src/data/api/chat_api.ts +++ b/src/data/api/chat_api.ts @@ -6,16 +6,14 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - ChatHistoryResponse, - ChatSendResponse, - ChatSyncData, - ChatSyncRequest, - ImageUploadResponse, - SendMessageRequest, - SttData, - SyncMessage, -} from "@/data/models"; +import { ChatHistoryResponse } from "@/data/dto/chat/chat_history_response"; +import { ChatSendResponse } from "@/data/dto/chat/chat_send_response"; +import { ChatSyncData } from "@/data/dto/chat/chat_sync_data"; +import { ChatSyncRequest } from "@/data/dto/chat/chat_sync_request"; +import { ImageUploadResponse } from "@/data/dto/chat/image_upload_response"; +import { SendMessageRequest } from "@/data/dto/chat/send_message_request"; +import { SttData } from "@/data/dto/chat/stt_data"; +import { SyncMessage } from "@/data/dto/chat/sync_message"; /** * 后端统一响应包装 @@ -74,9 +72,7 @@ export class ChatApi { /** * 同步游客消息 */ - async syncMessages( - messages: SyncMessage[] - ): Promise { + async syncMessages(messages: SyncMessage[]): Promise { const body = ChatSyncRequest.from({ messages }); const env = await httpClient>(ApiPath.chatSync, { method: "POST", diff --git a/src/data/api/metrics_api.ts b/src/data/api/metrics_api.ts index 1af9f9cd..d669d106 100644 --- a/src/data/api/metrics_api.ts +++ b/src/data/api/metrics_api.ts @@ -6,7 +6,8 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { AppEvent, PwaEvent } from "@/data/models"; +import { AppEvent } from "@/data/dto/metrics/app_event"; +import { PwaEvent } from "@/data/dto/metrics/pwa_event"; /** * 后端统一响应包装 diff --git a/src/data/api/user_api.ts b/src/data/api/user_api.ts index 4fc3a4dd..aa53066e 100644 --- a/src/data/api/user_api.ts +++ b/src/data/api/user_api.ts @@ -6,14 +6,12 @@ */ import { httpClient } from "./http_client"; import { ApiPath } from "./api_path"; -import { - CreditsData, - CreditsHistoryData, - UpdateProfileRequest, - User, - UserStatsResponse, - type UserData, -} from "@/data/models"; +import { CreditsData } from "@/data/dto/user/credits_data"; +import { CreditsHistoryData } from "@/data/dto/user/credits_history_data"; +import { UpdateProfileRequest } from "@/data/dto/user/update_profile_request"; +import { User } from "@/data/dto/user/user"; +import { UserStatsResponse } from "@/data/dto/user/user_stats_response"; +import type { UserData } from "@/data/schemas/user/user"; /** * 后端统一响应包装 diff --git a/src/data/models/auth/apple_login_request.ts b/src/data/dto/auth/apple_login_request.ts similarity index 61% rename from src/data/models/auth/apple_login_request.ts rename to src/data/dto/auth/apple_login_request.ts index 8b084f06..218a38ad 100644 --- a/src/data/models/auth/apple_login_request.ts +++ b/src/data/dto/auth/apple_login_request.ts @@ -1,16 +1,11 @@ /** - * Apple 登录请求 - * 原始 Dart: AppleLoginRequest (lib/data/models/auth/auth_request.dart) + * Apple 登录请求 DTO */ -import { z } from "zod"; - -export const AppleLoginRequestSchema = z.object({ - identityToken: z.string(), - platform: z.string(), -}); - -export type AppleLoginRequestInput = z.input; -export type AppleLoginRequestData = z.output; +import { + AppleLoginRequestSchema, + type AppleLoginRequestInput, + type AppleLoginRequestData, +} from "@/data/schemas/auth/apple_login_request"; export class AppleLoginRequest { declare readonly identityToken: string; diff --git a/src/data/models/auth/facebook_login_request.ts b/src/data/dto/auth/facebook_login_request.ts similarity index 60% rename from src/data/models/auth/facebook_login_request.ts rename to src/data/dto/auth/facebook_login_request.ts index 78617f57..2a96eb59 100644 --- a/src/data/models/auth/facebook_login_request.ts +++ b/src/data/dto/auth/facebook_login_request.ts @@ -1,17 +1,11 @@ /** - * Facebook 登录请求 - * 原始 Dart: FacebookLoginRequest (lib/data/models/auth/auth_request.dart) + * Facebook 登录请求 DTO */ -import { z } from "zod"; - -export const FacebookLoginRequestSchema = z.object({ - accessToken: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type FacebookLoginRequestInput = z.input; -export type FacebookLoginRequestData = z.output; +import { + FacebookLoginRequestSchema, + type FacebookLoginRequestInput, + type FacebookLoginRequestData, +} from "@/data/schemas/auth/facebook_login_request"; export class FacebookLoginRequest { declare readonly accessToken: string; diff --git a/src/data/models/auth/fb_id_login_request.ts b/src/data/dto/auth/fb_id_login_request.ts similarity index 60% rename from src/data/models/auth/fb_id_login_request.ts rename to src/data/dto/auth/fb_id_login_request.ts index 0925173a..f0f26430 100644 --- a/src/data/models/auth/fb_id_login_request.ts +++ b/src/data/dto/auth/fb_id_login_request.ts @@ -1,16 +1,11 @@ /** - * Facebook ID 登录请求 - * 原始 Dart: FbIdLoginRequest (lib/data/models/auth/auth_request.dart) + * Facebook ID 登录请求 DTO */ -import { z } from "zod"; - -export const FbIdLoginRequestSchema = z.object({ - fbId: z.string(), - avatarUrl: z.string().default(""), -}); - -export type FbIdLoginRequestInput = z.input; -export type FbIdLoginRequestData = z.output; +import { + FbIdLoginRequestSchema, + type FbIdLoginRequestInput, + type FbIdLoginRequestData, +} from "@/data/schemas/auth/fb_id_login_request"; export class FbIdLoginRequest { declare readonly fbId: string; diff --git a/src/data/models/auth/google_login_request.ts b/src/data/dto/auth/google_login_request.ts similarity index 61% rename from src/data/models/auth/google_login_request.ts rename to src/data/dto/auth/google_login_request.ts index 1c3eb419..0dbcba5b 100644 --- a/src/data/models/auth/google_login_request.ts +++ b/src/data/dto/auth/google_login_request.ts @@ -1,17 +1,11 @@ /** - * Google 登录请求 - * 原始 Dart: GoogleLoginRequest (lib/data/models/auth/auth_request.dart) + * Google 登录请求 DTO */ -import { z } from "zod"; - -export const GoogleLoginRequestSchema = z.object({ - idToken: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type GoogleLoginRequestInput = z.input; -export type GoogleLoginRequestData = z.output; +import { + GoogleLoginRequestSchema, + type GoogleLoginRequestInput, + type GoogleLoginRequestData, +} from "@/data/schemas/auth/google_login_request"; export class GoogleLoginRequest { declare readonly idToken: string; diff --git a/src/data/models/auth/guest_login_request.ts b/src/data/dto/auth/guest_login_request.ts similarity index 61% rename from src/data/models/auth/guest_login_request.ts rename to src/data/dto/auth/guest_login_request.ts index 4898ab33..d01274cd 100644 --- a/src/data/models/auth/guest_login_request.ts +++ b/src/data/dto/auth/guest_login_request.ts @@ -1,15 +1,11 @@ /** - * 游客登录请求 - * 原始 Dart: GuestLoginRequest (lib/data/models/auth/auth_request.dart) + * 游客登录请求 DTO */ -import { z } from "zod"; - -export const GuestLoginRequestSchema = z.object({ - deviceId: z.string(), -}); - -export type GuestLoginRequestInput = z.input; -export type GuestLoginRequestData = z.output; +import { + GuestLoginRequestSchema, + type GuestLoginRequestInput, + type GuestLoginRequestData, +} from "@/data/schemas/auth/guest_login_request"; export class GuestLoginRequest { declare readonly deviceId: string; diff --git a/src/data/dto/auth/guest_login_response.ts b/src/data/dto/auth/guest_login_response.ts new file mode 100644 index 00000000..ea9cb903 --- /dev/null +++ b/src/data/dto/auth/guest_login_response.ts @@ -0,0 +1,40 @@ +/** + * 游客登录响应 DTO + */ +import { + GuestLoginResponseSchema, + type GuestLoginResponseInput, + type GuestLoginResponseData, +} from "@/data/schemas/auth/guest_login_response"; +import { User } from "@/data/dto/user/user"; + +export class GuestLoginResponse { + declare readonly token: string; + declare readonly deviceId: string; + declare readonly userId: string; + declare readonly isDeviceUser: boolean; + declare readonly expiresIn: number; + declare readonly user: User; + + private constructor(input: GuestLoginResponseInput) { + const parsed = GuestLoginResponseSchema.parse(input); + Object.assign(this, { + ...parsed, + user: parsed.user ? User.fromJson(parsed.user) : User.empty(), + }); + Object.freeze(this); + } + + static from(input: GuestLoginResponseInput): GuestLoginResponse { + return new GuestLoginResponse(input); + } + + static fromJson(json: unknown): GuestLoginResponse { + return GuestLoginResponse.from(json as GuestLoginResponseInput); + } + + toJson(): GuestLoginResponseData { + const data = GuestLoginResponseSchema.parse(this); + return data; + } +} diff --git a/src/data/models/auth/login_request.ts b/src/data/dto/auth/login_request.ts similarity index 58% rename from src/data/models/auth/login_request.ts rename to src/data/dto/auth/login_request.ts index 8b37fff3..4c69cba4 100644 --- a/src/data/models/auth/login_request.ts +++ b/src/data/dto/auth/login_request.ts @@ -1,19 +1,11 @@ /** - * 登录请求 - 支持用户名或邮箱登录 - * 原始 Dart: LoginRequest (lib/data/models/auth/auth_request.dart) + * 登录请求 DTO */ -import { z } from "zod"; - -export const LoginRequestSchema = z.object({ - email: z.string().default(""), - username: z.string().default(""), - password: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type LoginRequestInput = z.input; -export type LoginRequestData = z.output; +import { + LoginRequestSchema, + type LoginRequestInput, + type LoginRequestData, +} from "@/data/schemas/auth/login_request"; export class LoginRequest { declare readonly email: string; diff --git a/src/data/models/auth/login_response.ts b/src/data/dto/auth/login_response.ts similarity index 55% rename from src/data/models/auth/login_response.ts rename to src/data/dto/auth/login_response.ts index 9df10d32..1cbe9fea 100644 --- a/src/data/models/auth/login_response.ts +++ b/src/data/dto/auth/login_response.ts @@ -1,18 +1,12 @@ /** - * 登录响应 - * 原始 Dart: LoginResponse (lib/data/models/auth/auth_response.dart) + * 登录响应 DTO */ -import { z } from "zod"; -import { User, UserSchema } from "../user/user"; - -export const LoginResponseSchema = z.object({ - user: UserSchema, - token: z.string(), - refreshToken: z.string().default(""), -}); - -export type LoginResponseInput = z.input; -export type LoginResponseData = z.output; +import { + LoginResponseSchema, + type LoginResponseInput, + type LoginResponseData, +} from "@/data/schemas/auth/login_response"; +import { User } from "@/data/dto/user/user"; export class LoginResponse { declare readonly user: User; @@ -21,7 +15,10 @@ export class LoginResponse { private constructor(input: LoginResponseInput) { const data = LoginResponseSchema.parse(input); - Object.assign(this, data); + Object.assign(this, { + ...data, + user: User.fromJson(data.user), + }); Object.freeze(this); } diff --git a/src/data/models/auth/logout_response.ts b/src/data/dto/auth/logout_response.ts similarity index 60% rename from src/data/models/auth/logout_response.ts rename to src/data/dto/auth/logout_response.ts index 57a943d5..53a922de 100644 --- a/src/data/models/auth/logout_response.ts +++ b/src/data/dto/auth/logout_response.ts @@ -1,15 +1,11 @@ /** - * 退出登录响应 - * 原始 Dart: LogoutResponse (lib/data/models/auth/auth_response.dart) + * 退出登录响应 DTO */ -import { z } from "zod"; - -export const LogoutResponseSchema = z.object({ - success: z.boolean().default(true), -}); - -export type LogoutResponseInput = z.input; -export type LogoutResponseData = z.output; +import { + LogoutResponseSchema, + type LogoutResponseInput, + type LogoutResponseData, +} from "@/data/schemas/auth/logout_response"; export class LogoutResponse { declare readonly success: boolean; diff --git a/src/data/models/auth/refresh_token_request.ts b/src/data/dto/auth/refresh_token_request.ts similarity index 61% rename from src/data/models/auth/refresh_token_request.ts rename to src/data/dto/auth/refresh_token_request.ts index 2fa504f7..96cd1d47 100644 --- a/src/data/models/auth/refresh_token_request.ts +++ b/src/data/dto/auth/refresh_token_request.ts @@ -1,15 +1,11 @@ /** - * 刷新 Token 请求 - * 原始 Dart: RefreshTokenRequest (lib/data/models/auth/auth_request.dart) + * 刷新 Token 请求 DTO */ -import { z } from "zod"; - -export const RefreshTokenRequestSchema = z.object({ - refreshToken: z.string(), -}); - -export type RefreshTokenRequestInput = z.input; -export type RefreshTokenRequestData = z.output; +import { + RefreshTokenRequestSchema, + type RefreshTokenRequestInput, + type RefreshTokenRequestData, +} from "@/data/schemas/auth/refresh_token_request"; export class RefreshTokenRequest { declare readonly refreshToken: string; diff --git a/src/data/models/auth/refresh_token_response.ts b/src/data/dto/auth/refresh_token_response.ts similarity index 61% rename from src/data/models/auth/refresh_token_response.ts rename to src/data/dto/auth/refresh_token_response.ts index 2e8635af..0508a305 100644 --- a/src/data/models/auth/refresh_token_response.ts +++ b/src/data/dto/auth/refresh_token_response.ts @@ -1,17 +1,11 @@ /** - * 刷新 Token 响应 - * 原始 Dart: RefreshTokenResponse (lib/data/models/auth/auth_response.dart) + * 刷新 Token 响应 DTO */ -import { z } from "zod"; - -export const RefreshTokenResponseSchema = z.object({ - token: z.string(), - refreshToken: z.string(), - userId: z.string(), -}); - -export type RefreshTokenResponseInput = z.input; -export type RefreshTokenResponseData = z.output; +import { + RefreshTokenResponseSchema, + type RefreshTokenResponseInput, + type RefreshTokenResponseData, +} from "@/data/schemas/auth/refresh_token_response"; export class RefreshTokenResponse { declare readonly token: string; diff --git a/src/data/models/auth/register_request.ts b/src/data/dto/auth/register_request.ts similarity index 61% rename from src/data/models/auth/register_request.ts rename to src/data/dto/auth/register_request.ts index 63608ee5..856ed5a3 100644 --- a/src/data/models/auth/register_request.ts +++ b/src/data/dto/auth/register_request.ts @@ -1,19 +1,11 @@ /** - * 注册请求 - * 原始 Dart: RegisterRequest (lib/data/models/auth/auth_request.dart) + * 注册请求 DTO */ -import { z } from "zod"; - -export const RegisterRequestSchema = z.object({ - username: z.string(), - email: z.string(), - password: z.string(), - platform: z.string(), - guestId: z.string().default(""), -}); - -export type RegisterRequestInput = z.input; -export type RegisterRequestData = z.output; +import { + RegisterRequestSchema, + type RegisterRequestInput, + type RegisterRequestData, +} from "@/data/schemas/auth/register_request"; export class RegisterRequest { declare readonly username: string; diff --git a/src/data/models/auth/send_code_request.ts b/src/data/dto/auth/send_code_request.ts similarity index 61% rename from src/data/models/auth/send_code_request.ts rename to src/data/dto/auth/send_code_request.ts index 454392b5..cbd0e54a 100644 --- a/src/data/models/auth/send_code_request.ts +++ b/src/data/dto/auth/send_code_request.ts @@ -1,15 +1,11 @@ /** - * 发送验证码请求 - * 原始 Dart: SendCodeRequest (lib/data/models/auth/auth_request.dart) + * 发送验证码请求 DTO */ -import { z } from "zod"; - -export const SendCodeRequestSchema = z.object({ - email: z.string(), -}); - -export type SendCodeRequestInput = z.input; -export type SendCodeRequestData = z.output; +import { + SendCodeRequestSchema, + type SendCodeRequestInput, + type SendCodeRequestData, +} from "@/data/schemas/auth/send_code_request"; export class SendCodeRequest { declare readonly email: string; diff --git a/src/data/models/chat/chat_history_response.ts b/src/data/dto/chat/chat_history_response.ts similarity index 54% rename from src/data/models/chat/chat_history_response.ts rename to src/data/dto/chat/chat_history_response.ts index 2781ab14..6b4abee6 100644 --- a/src/data/models/chat/chat_history_response.ts +++ b/src/data/dto/chat/chat_history_response.ts @@ -1,19 +1,12 @@ /** - * 聊天历史响应 - * 原始 Dart: ChatHistoryResponse (lib/data/models/chat/chat_response.dart) + * 聊天历史响应 DTO */ -import { z } from "zod"; -import { ChatMessage, ChatMessageSchema } from "./chat_message"; - -export const ChatHistoryResponseSchema = z.object({ - messages: z.array(ChatMessageSchema), - total: z.number().default(0), - limit: z.number(), - offset: z.number(), -}); - -export type ChatHistoryResponseInput = z.input; -export type ChatHistoryResponseData = z.output; +import { + ChatHistoryResponseSchema, + type ChatHistoryResponseInput, + type ChatHistoryResponseData, +} from "@/data/schemas/chat/chat_history_response"; +import { ChatMessage } from "./chat_message"; export class ChatHistoryResponse { declare readonly messages: ChatMessage[]; @@ -23,7 +16,10 @@ export class ChatHistoryResponse { private constructor(input: ChatHistoryResponseInput) { const data = ChatHistoryResponseSchema.parse(input); - Object.assign(this, data); + Object.assign(this, { + ...data, + messages: data.messages.map((m) => ChatMessage.from(m)), + }); Object.freeze(this); } diff --git a/src/data/models/chat/chat_message.ts b/src/data/dto/chat/chat_message.ts similarity index 59% rename from src/data/models/chat/chat_message.ts rename to src/data/dto/chat/chat_message.ts index ae1d440e..87dbc0e6 100644 --- a/src/data/models/chat/chat_message.ts +++ b/src/data/dto/chat/chat_message.ts @@ -1,18 +1,11 @@ /** - * 聊天历史中的单条消息 - * 原始 Dart: ChatMessage (lib/data/models/chat/chat_response.dart) + * 聊天历史中的单条消息 DTO */ -import { z } from "zod"; - -export const ChatMessageSchema = z.object({ - role: z.string(), - content: z.string(), - id: z.string().default(""), - createdAt: z.string().default(""), -}); - -export type ChatMessageInput = z.input; -export type ChatMessageData = z.output; +import { + ChatMessageSchema, + type ChatMessageInput, + type ChatMessageData, +} from "@/data/schemas/chat/chat_message"; export class ChatMessage { declare readonly role: string; diff --git a/src/data/models/chat/chat_send_response.ts b/src/data/dto/chat/chat_send_response.ts similarity index 54% rename from src/data/models/chat/chat_send_response.ts rename to src/data/dto/chat/chat_send_response.ts index 248dc684..a1523c4f 100644 --- a/src/data/models/chat/chat_send_response.ts +++ b/src/data/dto/chat/chat_send_response.ts @@ -1,32 +1,18 @@ /** - * 发送消息响应 - * 原始 Dart: ChatSendResponse (lib/data/models/chat/chat_response.dart) + * 发送消息响应 DTO */ -import { z } from "zod"; - -export const ChatSendResponseSchema = z.object({ - mode: z.string().default(""), - reply: z.string(), - voiceUrl: z.string().default(""), - audioUrl: z.string().default(""), - intimacyChange: z.number().default(0), - newIntimacy: z.number().default(0), - relationshipStage: z.string(), - currentMood: z.string().default(""), - messageId: z.string(), - isGuest: z.boolean().default(false), - timestamp: z.number().default(0), -}); - -export type ChatSendResponseInput = z.input; -export type ChatSendResponseData = z.output; +import { + ChatSendResponseSchema, + type ChatSendResponseInput, + type ChatSendResponseData, +} from "@/data/schemas/chat/chat_send_response"; export class ChatSendResponse { declare readonly mode: string; declare readonly reply: string; declare readonly voiceUrl: string; declare readonly audioUrl: string; - declare readonly intimacyChange: number; + declare readonly intimidadChange: number; declare readonly newIntimacy: number; declare readonly relationshipStage: string; declare readonly currentMood: string; diff --git a/src/data/models/chat/chat_sync_data.ts b/src/data/dto/chat/chat_sync_data.ts similarity index 61% rename from src/data/models/chat/chat_sync_data.ts rename to src/data/dto/chat/chat_sync_data.ts index 3f40e100..24b3effc 100644 --- a/src/data/models/chat/chat_sync_data.ts +++ b/src/data/dto/chat/chat_sync_data.ts @@ -1,16 +1,11 @@ /** - * 消息同步响应 - * 原始 Dart: ChatSyncData (lib/data/models/chat/chat_sync.dart) + * 消息同步响应 DTO */ -import { z } from "zod"; - -export const ChatSyncDataSchema = z.object({ - syncedCount: z.number(), - totalHistory: z.number(), -}); - -export type ChatSyncDataInput = z.input; -export type ChatSyncDataData = z.output; +import { + ChatSyncDataSchema, + type ChatSyncDataInput, + type ChatSyncDataData, +} from "@/data/schemas/chat/chat_sync_data"; export class ChatSyncData { declare readonly syncedCount: number; diff --git a/src/data/models/chat/chat_sync_request.ts b/src/data/dto/chat/chat_sync_request.ts similarity index 53% rename from src/data/models/chat/chat_sync_request.ts rename to src/data/dto/chat/chat_sync_request.ts index d4d7fc2e..9427170f 100644 --- a/src/data/models/chat/chat_sync_request.ts +++ b/src/data/dto/chat/chat_sync_request.ts @@ -1,23 +1,22 @@ /** - * 消息同步请求 - * 原始 Dart: ChatSyncRequest (lib/data/models/chat/chat_sync.dart) + * 消息同步请求 DTO */ -import { z } from "zod"; -import { SyncMessage, SyncMessageSchema } from "./sync_message"; - -export const ChatSyncRequestSchema = z.object({ - messages: z.array(SyncMessageSchema), -}); - -export type ChatSyncRequestInput = z.input; -export type ChatSyncRequestData = z.output; +import { + ChatSyncRequestSchema, + type ChatSyncRequestInput, + type ChatSyncRequestData, +} from "@/data/schemas/chat/chat_sync_request"; +import { SyncMessage } from "./sync_message"; export class ChatSyncRequest { declare readonly messages: SyncMessage[]; private constructor(input: ChatSyncRequestInput) { const data = ChatSyncRequestSchema.parse(input); - Object.assign(this, data); + Object.assign(this, { + ...data, + messages: data.messages.map((m) => SyncMessage.from(m)), + }); Object.freeze(this); } diff --git a/src/data/models/chat/guest_chat_quota.ts b/src/data/dto/chat/guest_chat_quota.ts similarity index 70% rename from src/data/models/chat/guest_chat_quota.ts rename to src/data/dto/chat/guest_chat_quota.ts index 8a16c152..ebbed3de 100644 --- a/src/data/models/chat/guest_chat_quota.ts +++ b/src/data/dto/chat/guest_chat_quota.ts @@ -1,25 +1,13 @@ /** - * 游客每日聊天配额数据 - * 原始 Dart: GuestChatQuota (lib/data/models/chat/guest_chat_quota.dart) - * - * 注:保留原始 Dart 中的静态常量与运行时环境判断方法。 - * `process.env.NODE_ENV` 替代 Dart 的 `AppEnvUtil.isDevelopment`。 - * `initial()` 工厂方法与 `needReset` 实例方法保留。 + * 游客每日聊天配额数据 DTO */ -import { z } from "zod"; - -export const GuestChatQuotaSchema = z.object({ - remaining: z.number(), - date: z.string(), -}); - -export type GuestChatQuotaInput = z.input; -export type GuestChatQuotaData = z.output; +import { + GuestChatQuotaSchema, + type GuestChatQuotaInput, + type GuestChatQuotaData, +} from "@/data/schemas/chat/guest_chat_quota"; export class GuestChatQuota { - declare readonly remaining: number; - declare readonly date: string; - // 静态常量 static readonly maxQuotaPerDay = 40; static readonly maxQuotaPerDayTest = 4; @@ -29,6 +17,9 @@ export class GuestChatQuota { static readonly defaultTotalQuotaDev = 5; static readonly quotaExhausted = 0; + declare readonly remaining: number; + declare readonly date: string; + private constructor(input: GuestChatQuotaInput) { const data = GuestChatQuotaSchema.parse(input); Object.assign(this, data); @@ -43,12 +34,8 @@ export class GuestChatQuota { return GuestChatQuota.from(json as GuestChatQuotaInput); } - toJson(): GuestChatQuotaData { - return GuestChatQuotaSchema.parse(this); - } - /** - * 配额耗尽状态值(便捷引用) + * 配额耗尽状态值 */ static get exhausted(): number { return GuestChatQuota.quotaExhausted; @@ -56,7 +43,6 @@ export class GuestChatQuota { /** * 是否处于开发环境 - * 通过 `process.env.NODE_ENV` 判断,替代 Dart 中的 `AppEnvUtil.isDevelopment` */ static get isDevelopment(): boolean { return process.env.NODE_ENV !== "production"; @@ -91,7 +77,6 @@ export class GuestChatQuota { /** * 创建初始配额实例 - * @param todayString 当天日期字符串(YYYY-MM-DD),由调用方提供 */ static initial(todayString: string): GuestChatQuota { return new GuestChatQuota({ @@ -102,9 +87,12 @@ export class GuestChatQuota { /** * 是否需要重置(跨天) - * @param todayString 当天日期字符串(YYYY-MM-DD),由调用方提供 */ needsReset(todayString: string): boolean { return this.date !== todayString; } + + toJson(): GuestChatQuotaData { + return GuestChatQuotaSchema.parse(this); + } } diff --git a/src/data/models/chat/image_upload_response.ts b/src/data/dto/chat/image_upload_response.ts similarity index 60% rename from src/data/models/chat/image_upload_response.ts rename to src/data/dto/chat/image_upload_response.ts index 221919f8..edbebbef 100644 --- a/src/data/models/chat/image_upload_response.ts +++ b/src/data/dto/chat/image_upload_response.ts @@ -1,22 +1,11 @@ /** - * 图片上传响应 - * 原始 Dart: ImageUploadResponse (lib/data/models/chat/image_upload_response.dart) + * 图片上传响应 DTO */ -import { z } from "zod"; - -export const ImageUploadResponseSchema = z.object({ - success: z.boolean().default(true), - imageId: z.string(), - thumbUrl: z.string(), - mediumUrl: z.string(), - originalUrl: z.string(), - width: z.number(), - height: z.number(), - bytes: z.number(), -}); - -export type ImageUploadResponseInput = z.input; -export type ImageUploadResponseData = z.output; +import { + ImageUploadResponseSchema, + type ImageUploadResponseInput, + type ImageUploadResponseData, +} from "@/data/schemas/chat/image_upload_response"; export class ImageUploadResponse { declare readonly success: boolean; diff --git a/src/data/models/chat/send_message_request.ts b/src/data/dto/chat/send_message_request.ts similarity index 55% rename from src/data/models/chat/send_message_request.ts rename to src/data/dto/chat/send_message_request.ts index 436f0e3b..41ad8f04 100644 --- a/src/data/models/chat/send_message_request.ts +++ b/src/data/dto/chat/send_message_request.ts @@ -1,23 +1,11 @@ /** - * 发送消息请求 - 用于 /api/chat/send 接口 - * 原始 Dart: SendMessageRequest (lib/data/models/chat/send_message_request.dart) + * 发送消息请求 DTO */ -import { z } from "zod"; - -export const SendMessageRequestSchema = z.object({ - message: z.string().default(""), - image: z.string().default(""), - imageId: z.string().default(""), - imageThumbUrl: z.string().default(""), - imageMediumUrl: z.string().default(""), - imageOriginalUrl: z.string().default(""), - imageWidth: z.number().default(0), - imageHeight: z.number().default(0), - useWebSocket: z.boolean().default(false), -}); - -export type SendMessageRequestInput = z.input; -export type SendMessageRequestData = z.output; +import { + SendMessageRequestSchema, + type SendMessageRequestInput, + type SendMessageRequestData, +} from "@/data/schemas/chat/send_message_request"; export class SendMessageRequest { declare readonly message: string; diff --git a/src/data/models/chat/stt_data.ts b/src/data/dto/chat/stt_data.ts similarity index 60% rename from src/data/models/chat/stt_data.ts rename to src/data/dto/chat/stt_data.ts index 7f1f23f8..a54d47e5 100644 --- a/src/data/models/chat/stt_data.ts +++ b/src/data/dto/chat/stt_data.ts @@ -1,15 +1,11 @@ /** - * STT(语音转文字)响应 - * 原始 Dart: SttData (lib/data/models/chat/stt_response.dart) + * STT(语音转文字)响应 DTO */ -import { z } from "zod"; - -export const SttDataSchema = z.object({ - text: z.string(), -}); - -export type SttDataInput = z.input; -export type SttDataData = z.output; +import { + SttDataSchema, + type SttDataInput, + type SttDataData, +} from "@/data/schemas/chat/stt_data"; export class SttData { declare readonly text: string; diff --git a/src/data/models/chat/sync_message.ts b/src/data/dto/chat/sync_message.ts similarity index 61% rename from src/data/models/chat/sync_message.ts rename to src/data/dto/chat/sync_message.ts index 8cd5dccf..e037a5a8 100644 --- a/src/data/models/chat/sync_message.ts +++ b/src/data/dto/chat/sync_message.ts @@ -1,17 +1,11 @@ /** - * 待同步的单条消息 - * 原始 Dart: SyncMessage (lib/data/models/chat/chat_sync.dart) + * 待同步的单条消息 DTO */ -import { z } from "zod"; - -export const SyncMessageSchema = z.object({ - role: z.string(), - content: z.string(), - timestamp: z.string(), -}); - -export type SyncMessageInput = z.input; -export type SyncMessageData = z.output; +import { + SyncMessageSchema, + type SyncMessageInput, + type SyncMessageData, +} from "@/data/schemas/chat/sync_message"; export class SyncMessage { declare readonly role: string; diff --git a/src/data/models/index.ts b/src/data/dto/index.ts similarity index 92% rename from src/data/models/index.ts rename to src/data/dto/index.ts index 98d8c74a..bf51c511 100644 --- a/src/data/models/index.ts +++ b/src/data/dto/index.ts @@ -1,7 +1,9 @@ /** - * @file Automatically generated by barrelsby. + * DTO - 集中导出 + * + * 不可变运行时类(API 层使用) + * 原始 Dart: lib/data/models/ */ - export * from "./auth/apple_login_request"; export * from "./auth/facebook_login_request"; export * from "./auth/fb_id_login_request"; @@ -15,6 +17,7 @@ export * from "./auth/refresh_token_request"; export * from "./auth/refresh_token_response"; export * from "./auth/register_request"; export * from "./auth/send_code_request"; + export * from "./chat/chat_history_response"; export * from "./chat/chat_message"; export * from "./chat/chat_send_response"; @@ -25,8 +28,10 @@ export * from "./chat/image_upload_response"; export * from "./chat/send_message_request"; export * from "./chat/stt_data"; export * from "./chat/sync_message"; + export * from "./metrics/app_event"; export * from "./metrics/pwa_event"; + export * from "./user/avatar_data"; export * from "./user/credits_data"; export * from "./user/credits_history_data"; diff --git a/src/data/models/metrics/app_event.ts b/src/data/dto/metrics/app_event.ts similarity index 58% rename from src/data/models/metrics/app_event.ts rename to src/data/dto/metrics/app_event.ts index 61c4dd17..daacdd83 100644 --- a/src/data/models/metrics/app_event.ts +++ b/src/data/dto/metrics/app_event.ts @@ -1,17 +1,11 @@ /** - * 应用事件上报请求 - 用于 /api/data/report-user-info 接口 - * 原始 Dart: AppEvent (lib/data/models/metrics/app_event.dart) + * 应用事件上报请求 DTO */ -import { z } from "zod"; - -export const AppEventSchema = z.object({ - userId: z.string(), - browser: z.string(), - userAgent: z.string(), -}); - -export type AppEventInput = z.input; -export type AppEventData = z.output; +import { + AppEventSchema, + type AppEventInput, + type AppEventData, +} from "@/data/schemas/metrics/app_event"; export class AppEvent { declare readonly userId: string; diff --git a/src/data/models/metrics/pwa_event.ts b/src/data/dto/metrics/pwa_event.ts similarity index 56% rename from src/data/models/metrics/pwa_event.ts rename to src/data/dto/metrics/pwa_event.ts index 13656969..95e33720 100644 --- a/src/data/models/metrics/pwa_event.ts +++ b/src/data/dto/metrics/pwa_event.ts @@ -1,19 +1,11 @@ /** - * PWA 事件上报请求 - 用于 /api/metrics/pwa/event 接口 - * 原始 Dart: PwaEvent (lib/data/models/metrics/pwa_event.dart) + * PWA 事件上报请求 DTO */ -import { z } from "zod"; - -export const PwaEventSchema = z.object({ - deviceId: z.string(), - deviceType: z.string(), - timestamp: z.number(), - pwaInstalled: z.boolean().default(false), - pwaSupported: z.boolean().default(false), -}); - -export type PwaEventInput = z.input; -export type PwaEventData = z.output; +import { + PwaEventSchema, + type PwaEventInput, + type PwaEventData, +} from "@/data/schemas/metrics/pwa_event"; export class PwaEvent { declare readonly deviceId: string; diff --git a/src/data/dto/user/avatar_data.ts b/src/data/dto/user/avatar_data.ts new file mode 100644 index 00000000..edb2dcc8 --- /dev/null +++ b/src/data/dto/user/avatar_data.ts @@ -0,0 +1,31 @@ +/** + * 头像数据 DTO + */ +import { + AvatarDataSchema, + type AvatarDataInput, + type AvatarDataData, +} from "@/data/schemas/user/avatar_data"; + +export class AvatarData { + declare readonly avatarUrl: string; + declare readonly userId: string; + + private constructor(input: AvatarDataInput) { + const data = AvatarDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: AvatarDataInput): AvatarData { + return new AvatarData(input); + } + + static fromJson(json: unknown): AvatarData { + return AvatarData.from(json as AvatarDataInput); + } + + toJson(): AvatarDataData { + return AvatarDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/credits_data.ts b/src/data/dto/user/credits_data.ts new file mode 100644 index 00000000..095c3dfd --- /dev/null +++ b/src/data/dto/user/credits_data.ts @@ -0,0 +1,31 @@ +/** + * 积分数据 DTO + */ +import { + CreditsDataSchema, + type CreditsDataInput, + type CreditsDataData, +} from "@/data/schemas/user/credits_data"; + +export class CreditsData { + declare readonly userId: string; + declare readonly dolBalance: number; + + private constructor(input: CreditsDataInput) { + const data = CreditsDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: CreditsDataInput): CreditsData { + return new CreditsData(input); + } + + static fromJson(json: unknown): CreditsData { + return CreditsData.from(json as CreditsDataInput); + } + + toJson(): CreditsDataData { + return CreditsDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/credits_history_data.ts b/src/data/dto/user/credits_history_data.ts new file mode 100644 index 00000000..6fcec0bb --- /dev/null +++ b/src/data/dto/user/credits_history_data.ts @@ -0,0 +1,33 @@ +/** + * 积分历史记录 DTO + */ +import { + CreditsHistoryDataSchema, + type CreditsHistoryDataInput, + type CreditsHistoryDataData, +} from "@/data/schemas/user/credits_history_data"; + +export class CreditsHistoryData { + declare readonly records: Record[]; + declare readonly total: number; + declare readonly limit: number; + declare readonly offset: number; + + private constructor(input: CreditsHistoryDataInput) { + const data = CreditsHistoryDataSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: CreditsHistoryDataInput): CreditsHistoryData { + return new CreditsHistoryData(input); + } + + static fromJson(json: unknown): CreditsHistoryData { + return CreditsHistoryData.from(json as CreditsHistoryDataInput); + } + + toJson(): CreditsHistoryDataData { + return CreditsHistoryDataSchema.parse(this); + } +} diff --git a/src/data/dto/user/personality_traits.ts b/src/data/dto/user/personality_traits.ts new file mode 100644 index 00000000..8802a2c7 --- /dev/null +++ b/src/data/dto/user/personality_traits.ts @@ -0,0 +1,34 @@ +/** + * 个性特征 DTO + */ +import { + PersonalityTraitsSchema, + type PersonalityTraitsInput, + type PersonalityTraitsData, +} from "@/data/schemas/user/personality_traits"; + +export class PersonalityTraits { + declare readonly cheerful: number; + declare readonly caring: number; + declare readonly playful: number; + declare readonly serious: number; + declare readonly romantic: number; + + private constructor(input: PersonalityTraitsInput) { + const data = PersonalityTraitsSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: PersonalityTraitsInput): PersonalityTraits { + return new PersonalityTraits(input); + } + + static fromJson(json: unknown): PersonalityTraits { + return PersonalityTraits.from(json as PersonalityTraitsInput); + } + + toJson(): PersonalityTraitsData { + return PersonalityTraitsSchema.parse(this); + } +} diff --git a/src/data/dto/user/recent_memory.ts b/src/data/dto/user/recent_memory.ts new file mode 100644 index 00000000..8d363810 --- /dev/null +++ b/src/data/dto/user/recent_memory.ts @@ -0,0 +1,33 @@ +/** + * 最近记忆 DTO + */ +import { + RecentMemorySchema, + type RecentMemoryInput, + type RecentMemoryData, +} from "@/data/schemas/user/recent_memory"; + +export class RecentMemory { + declare readonly type: string; + declare readonly content: string; + declare readonly importance: number; + declare readonly createdAt: string; + + private constructor(input: RecentMemoryInput) { + const data = RecentMemorySchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: RecentMemoryInput): RecentMemory { + return new RecentMemory(input); + } + + static fromJson(json: unknown): RecentMemory { + return RecentMemory.from(json as RecentMemoryInput); + } + + toJson(): RecentMemoryData { + return RecentMemorySchema.parse(this); + } +} diff --git a/src/data/dto/user/update_profile_request.ts b/src/data/dto/user/update_profile_request.ts new file mode 100644 index 00000000..deb3f0df --- /dev/null +++ b/src/data/dto/user/update_profile_request.ts @@ -0,0 +1,33 @@ +/** + * 更新个人资料请求 DTO + */ +import { + UpdateProfileRequestSchema, + type UpdateProfileRequestInput, + type UpdateProfileRequestData, +} from "@/data/schemas/user/update_profile_request"; + +export class UpdateProfileRequest { + declare readonly username: string; + declare readonly nickname: string; + declare readonly preferredLanguage: string; + declare readonly currentMood: string; + + private constructor(input: UpdateProfileRequestInput) { + const data = UpdateProfileRequestSchema.parse(input); + Object.assign(this, data); + Object.freeze(this); + } + + static from(input: UpdateProfileRequestInput): UpdateProfileRequest { + return new UpdateProfileRequest(input); + } + + static fromJson(json: unknown): UpdateProfileRequest { + return UpdateProfileRequest.from(json as UpdateProfileRequestInput); + } + + toJson(): UpdateProfileRequestData { + return UpdateProfileRequestSchema.parse(this); + } +} diff --git a/src/data/dto/user/user.ts b/src/data/dto/user/user.ts new file mode 100644 index 00000000..b3c13e90 --- /dev/null +++ b/src/data/dto/user/user.ts @@ -0,0 +1,59 @@ +/** + * 用户 DTO + */ +import { + UserSchema, + type UserInput, + type UserData, +} from "@/data/schemas/user/user"; +import { PersonalityTraits } from "./personality_traits"; + +export class User { + declare readonly id: string; + declare readonly username: string; + declare readonly email: string; + declare readonly platform: string; + declare readonly intimacy: number; + declare readonly dolBalance: number; + declare readonly relationshipStage: string; + declare readonly currentMood: string; + declare readonly personalityTraits: PersonalityTraits; + declare readonly preferredLanguage: string; + declare readonly createdAt: string; + declare readonly lastMessageAt: string; + declare readonly avatarUrl: string; + declare readonly loginProvider: string; + declare readonly isGuest: boolean; + + private constructor(input: UserInput) { + const data = UserSchema.parse(input); + Object.assign(this, { + ...data, + personalityTraits: PersonalityTraits.from(data.personalityTraits), + }); + Object.freeze(this); + } + + static from(input: UserInput): User { + return new User(input); + } + + static fromJson(json: unknown): User { + return User.from(json as UserInput); + } + + /** + * 创建一个具有空 id/username 的 User 实例(用于可选 user 字段的默认占位) + */ + static empty(): User { + return new User({ id: "", username: "" }); + } + + toJson(): UserData { + const { personalityTraits, ...rest } = this; + return { + ...rest, + personalityTraits: personalityTraits.toJson(), + }; + } +} diff --git a/src/data/dto/user/user_stats_response.ts b/src/data/dto/user/user_stats_response.ts new file mode 100644 index 00000000..fa25ebe4 --- /dev/null +++ b/src/data/dto/user/user_stats_response.ts @@ -0,0 +1,51 @@ +/** + * 用户统计响应 DTO + */ +import { + UserStatsResponseSchema, + type UserStatsResponseInput, + type UserStatsResponseData, +} from "@/data/schemas/user/user_stats_response"; +import { PersonalityTraits } from "./personality_traits"; +import { RecentMemory } from "./recent_memory"; + +export class UserStatsResponse { + declare readonly userId: string; + declare readonly username: string; + declare readonly platform: string; + declare readonly intimacy: number; + declare readonly relationshipStage: string; + declare readonly dolBalance: number; + declare readonly totalMessages: number; + declare readonly lastMessageAt: string; + declare readonly accountCreatedAt: string; + declare readonly currentMood: string; + declare readonly personalityTraits: PersonalityTraits; + declare readonly recentMemories: RecentMemory[]; + declare readonly promptTokensTotal: number; + declare readonly completionTokensTotal: number; + declare readonly cacheHitTokensTotal: number; + declare readonly tokensTotal: number; + + private constructor(input: UserStatsResponseInput) { + const data = UserStatsResponseSchema.parse(input); + Object.assign(this, { + ...data, + personalityTraits: PersonalityTraits.from(data.personalityTraits), + recentMemories: data.recentMemories.map((m) => RecentMemory.from(m)), + }); + Object.freeze(this); + } + + static from(input: UserStatsResponseInput): UserStatsResponse { + return new UserStatsResponse(input); + } + + static fromJson(json: unknown): UserStatsResponse { + return UserStatsResponse.from(json as UserStatsResponseInput); + } + + toJson(): UserStatsResponseData { + return UserStatsResponseSchema.parse(this); + } +} diff --git a/src/data/models/auth/guest_login_response.ts b/src/data/models/auth/guest_login_response.ts deleted file mode 100644 index 5081e37a..00000000 --- a/src/data/models/auth/guest_login_response.ts +++ /dev/null @@ -1,52 +0,0 @@ -/** - * 游客登录响应 - * 原始 Dart: GuestLoginResponse (lib/data/models/auth/auth_response.dart) - */ -import { z } from "zod"; -import { User, UserSchema } from "../user/user"; - -export const GuestLoginResponseSchema = z.object({ - token: z.string(), - deviceId: z.string(), - userId: z.string(), - isDeviceUser: z.boolean().default(true), - expiresIn: z.number().default(2592000), - user: UserSchema.optional(), -}); - -export type GuestLoginResponseInput = z.input; -export type GuestLoginResponseData = z.output; - -export class GuestLoginResponse { - declare readonly token: string; - declare readonly deviceId: string; - declare readonly userId: string; - declare readonly isDeviceUser: boolean; - declare readonly expiresIn: number; - declare readonly user: User; - - private constructor(data: GuestLoginResponseData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: GuestLoginResponseInput): GuestLoginResponse { - const parsed = GuestLoginResponseSchema.parse(input); - return new GuestLoginResponse({ - ...parsed, - user: parsed.user ?? User.empty(), - }); - } - - static fromJson(json: unknown): GuestLoginResponse { - return GuestLoginResponse.from(json as GuestLoginResponseInput); - } - - toJson(): GuestLoginResponseData { - const { user, ...rest } = this; - return GuestLoginResponseSchema.parse({ - ...rest, - ...(user.id !== "" ? { user } : {}), - }); - } -} diff --git a/src/data/models/auth/index.ts b/src/data/models/auth/index.ts deleted file mode 100644 index 7ef01db2..00000000 --- a/src/data/models/auth/index.ts +++ /dev/null @@ -1,17 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./apple_login_request"; -export * from "./facebook_login_request"; -export * from "./fb_id_login_request"; -export * from "./google_login_request"; -export * from "./guest_login_request"; -export * from "./guest_login_response"; -export * from "./login_request"; -export * from "./login_response"; -export * from "./logout_response"; -export * from "./refresh_token_request"; -export * from "./refresh_token_response"; -export * from "./register_request"; -export * from "./send_code_request"; diff --git a/src/data/models/chat/index.ts b/src/data/models/chat/index.ts deleted file mode 100644 index b11282a1..00000000 --- a/src/data/models/chat/index.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./chat_history_response"; -export * from "./chat_message"; -export * from "./chat_send_response"; -export * from "./chat_sync_data"; -export * from "./chat_sync_request"; -export * from "./guest_chat_quota"; -export * from "./image_upload_response"; -export * from "./send_message_request"; -export * from "./stt_data"; -export * from "./sync_message"; diff --git a/src/data/models/metrics/index.ts b/src/data/models/metrics/index.ts deleted file mode 100644 index 5213df40..00000000 --- a/src/data/models/metrics/index.ts +++ /dev/null @@ -1,6 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./app_event"; -export * from "./pwa_event"; diff --git a/src/data/models/user/avatar_data.ts b/src/data/models/user/avatar_data.ts deleted file mode 100644 index 78addf14..00000000 --- a/src/data/models/user/avatar_data.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 头像数据模型 - 对应后端 AvatarData schema - * 原始 Dart: AvatarData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const AvatarDataSchema = z.object({ - avatarUrl: z.string().default(""), - userId: z.string(), -}); - -export type AvatarDataInput = z.input; -export type AvatarDataData = z.output; - -export class AvatarData { - declare readonly avatarUrl: string; - declare readonly userId: string; - - private constructor(data: AvatarDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: AvatarDataInput): AvatarData { - return new AvatarData(AvatarDataSchema.parse(input)); - } - - static fromJson(json: unknown): AvatarData { - return AvatarData.from(json as AvatarDataInput); - } - - toJson(): AvatarDataData { - return AvatarDataSchema.parse(this); - } -} diff --git a/src/data/models/user/credits_data.ts b/src/data/models/user/credits_data.ts deleted file mode 100644 index f8e3eeee..00000000 --- a/src/data/models/user/credits_data.ts +++ /dev/null @@ -1,35 +0,0 @@ -/** - * 积分数据模型 - 对应后端 CreditsData schema - * 原始 Dart: CreditsData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const CreditsDataSchema = z.object({ - userId: z.string(), - dolBalance: z.number(), -}); - -export type CreditsDataInput = z.input; -export type CreditsDataData = z.output; - -export class CreditsData { - declare readonly userId: string; - declare readonly dolBalance: number; - - private constructor(data: CreditsDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: CreditsDataInput): CreditsData { - return new CreditsData(CreditsDataSchema.parse(input)); - } - - static fromJson(json: unknown): CreditsData { - return CreditsData.from(json as CreditsDataInput); - } - - toJson(): CreditsDataData { - return CreditsDataSchema.parse(this); - } -} diff --git a/src/data/models/user/credits_history_data.ts b/src/data/models/user/credits_history_data.ts deleted file mode 100644 index 62dba106..00000000 --- a/src/data/models/user/credits_history_data.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 积分历史记录模型 - 对应后端 CreditsHistoryData schema - * 原始 Dart: CreditsHistoryData (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const CreditsHistoryDataSchema = z.object({ - records: z.array(z.record(z.string(), z.unknown())), - total: z.number(), - limit: z.number(), - offset: z.number(), -}); - -export type CreditsHistoryDataInput = z.input; -export type CreditsHistoryDataData = z.output; - -export class CreditsHistoryData { - declare readonly records: Record[]; - declare readonly total: number; - declare readonly limit: number; - declare readonly offset: number; - - private constructor(data: CreditsHistoryDataData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: CreditsHistoryDataInput): CreditsHistoryData { - return new CreditsHistoryData(CreditsHistoryDataSchema.parse(input)); - } - - static fromJson(json: unknown): CreditsHistoryData { - return CreditsHistoryData.from(json as CreditsHistoryDataInput); - } - - toJson(): CreditsHistoryDataData { - return CreditsHistoryDataSchema.parse(this); - } -} diff --git a/src/data/models/user/index.ts b/src/data/models/user/index.ts deleted file mode 100644 index 287d1254..00000000 --- a/src/data/models/user/index.ts +++ /dev/null @@ -1,12 +0,0 @@ -/** - * @file Automatically generated by barrelsby. - */ - -export * from "./avatar_data"; -export * from "./credits_data"; -export * from "./credits_history_data"; -export * from "./personality_traits"; -export * from "./recent_memory"; -export * from "./update_profile_request"; -export * from "./user"; -export * from "./user_stats_response"; diff --git a/src/data/models/user/personality_traits.ts b/src/data/models/user/personality_traits.ts deleted file mode 100644 index f9bc397c..00000000 --- a/src/data/models/user/personality_traits.ts +++ /dev/null @@ -1,49 +0,0 @@ -/** - * 个性特征模型 - * 原始 Dart: PersonalityTraits (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const PERSONALITY_TRAITS_DEFAULTS: PersonalityTraitsData = { - cheerful: 0.5, - caring: 0.5, - playful: 0.5, - serious: 0.5, - romantic: 0.5, -}; - -export const PersonalityTraitsSchema = z.object({ - cheerful: z.number().default(0.5), - caring: z.number().default(0.5), - playful: z.number().default(0.5), - serious: z.number().default(0.5), - romantic: z.number().default(0.5), -}); - -export type PersonalityTraitsInput = z.input; -export type PersonalityTraitsData = z.output; - -export class PersonalityTraits { - declare readonly cheerful: number; - declare readonly caring: number; - declare readonly playful: number; - declare readonly serious: number; - declare readonly romantic: number; - - private constructor(data: PersonalityTraitsData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: PersonalityTraitsInput): PersonalityTraits { - return new PersonalityTraits(PersonalityTraitsSchema.parse(input)); - } - - static fromJson(json: unknown): PersonalityTraits { - return PersonalityTraits.from(json as PersonalityTraitsInput); - } - - toJson(): PersonalityTraitsData { - return PersonalityTraitsSchema.parse(this); - } -} diff --git a/src/data/models/user/recent_memory.ts b/src/data/models/user/recent_memory.ts deleted file mode 100644 index 46f1084b..00000000 --- a/src/data/models/user/recent_memory.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 最近记忆模型 - * 原始 Dart: RecentMemory (lib/data/models/user/recent_memory.dart) - */ -import { z } from "zod"; - -export const RecentMemorySchema = z.object({ - type: z.string(), - content: z.string(), - importance: z.number(), - createdAt: z.string().default(""), -}); - -export type RecentMemoryInput = z.input; -export type RecentMemoryData = z.output; - -export class RecentMemory { - declare readonly type: string; - declare readonly content: string; - declare readonly importance: number; - declare readonly createdAt: string; - - private constructor(data: RecentMemoryData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: RecentMemoryInput): RecentMemory { - return new RecentMemory(RecentMemorySchema.parse(input)); - } - - static fromJson(json: unknown): RecentMemory { - return RecentMemory.from(json as RecentMemoryInput); - } - - toJson(): RecentMemoryData { - return RecentMemorySchema.parse(this); - } -} diff --git a/src/data/models/user/update_profile_request.ts b/src/data/models/user/update_profile_request.ts deleted file mode 100644 index 1b6136e7..00000000 --- a/src/data/models/user/update_profile_request.ts +++ /dev/null @@ -1,39 +0,0 @@ -/** - * 更新个人资料请求 - * 原始 Dart: UpdateProfileRequest (lib/data/models/user/user.dart) - */ -import { z } from "zod"; - -export const UpdateProfileRequestSchema = z.object({ - username: z.string().default(""), - nickname: z.string().default(""), - preferredLanguage: z.string().default(""), - currentMood: z.string().default(""), -}); - -export type UpdateProfileRequestInput = z.input; -export type UpdateProfileRequestData = z.output; - -export class UpdateProfileRequest { - declare readonly username: string; - declare readonly nickname: string; - declare readonly preferredLanguage: string; - declare readonly currentMood: string; - - private constructor(data: UpdateProfileRequestData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UpdateProfileRequestInput): UpdateProfileRequest { - return new UpdateProfileRequest(UpdateProfileRequestSchema.parse(input)); - } - - static fromJson(json: unknown): UpdateProfileRequest { - return UpdateProfileRequest.from(json as UpdateProfileRequestInput); - } - - toJson(): UpdateProfileRequestData { - return UpdateProfileRequestSchema.parse(this); - } -} diff --git a/src/data/models/user/user.ts b/src/data/models/user/user.ts deleted file mode 100644 index 95066674..00000000 --- a/src/data/models/user/user.ts +++ /dev/null @@ -1,77 +0,0 @@ -/** - * 用户模型 - 对应后端 UserData schema - * 原始 Dart: User (lib/data/models/user/user.dart) - */ -import { z } from "zod"; -import { - PersonalityTraits, - PersonalityTraitsSchema, - PERSONALITY_TRAITS_DEFAULTS, -} from "./personality_traits"; - -export const UserSchema = z.object({ - id: z.string(), - username: z.string(), - email: z.string().default(""), - platform: z.string().default("web"), - intimacy: z.number().default(0), - dolBalance: z.number().default(0), - relationshipStage: z.string().default("密友"), - currentMood: z.string().default("happy"), - personalityTraits: PersonalityTraitsSchema.default( - PERSONALITY_TRAITS_DEFAULTS - ), - preferredLanguage: z.string().default(""), - createdAt: z.string().default(""), - lastMessageAt: z.string().default(""), - avatarUrl: z.string().default(""), - loginProvider: z.string().default("email"), - isGuest: z.boolean().default(false), -}); - -export type UserInput = z.input; -export type UserData = z.output; - -export class User { - declare readonly id: string; - declare readonly username: string; - declare readonly email: string; - declare readonly platform: string; - declare readonly intimacy: number; - declare readonly dolBalance: number; - declare readonly relationshipStage: string; - declare readonly currentMood: string; - declare readonly personalityTraits: PersonalityTraits; - declare readonly preferredLanguage: string; - declare readonly createdAt: string; - declare readonly lastMessageAt: string; - declare readonly avatarUrl: string; - declare readonly loginProvider: string; - declare readonly isGuest: boolean; - - private constructor(input: UserInput) { - const data = UserSchema.parse(input); - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UserInput): User { - return new User(input); - } - - static fromJson(json: unknown): User { - return User.from(json as UserInput); - } - - /** - * 创建一个具有空 id/username 的 User 实例,用于可选 user 字段的默认占位。 - * 调用方可通过 `user.id === ""` 判定"无用户数据"。 - */ - static empty(): User { - return new User({ id: "", username: "" }); - } - - toJson(): UserData { - return UserSchema.parse(this); - } -} diff --git a/src/data/models/user/user_stats_response.ts b/src/data/models/user/user_stats_response.ts deleted file mode 100644 index 93b1bb08..00000000 --- a/src/data/models/user/user_stats_response.ts +++ /dev/null @@ -1,71 +0,0 @@ -/** - * 用户统计响应 - * 原始 Dart: UserStatsResponse (lib/data/models/user/user_stats_response.dart) - */ -import { z } from "zod"; -import { - PersonalityTraits, - PERSONALITY_TRAITS_DEFAULTS, - PersonalityTraitsSchema, -} from "./personality_traits"; -import { RecentMemory, RecentMemorySchema } from "./recent_memory"; - -export const UserStatsResponseSchema = z.object({ - userId: z.string(), - username: z.string(), - platform: z.string(), - intimacy: z.number(), - relationshipStage: z.string(), - dolBalance: z.number(), - totalMessages: z.number(), - lastMessageAt: z.string().default(""), - accountCreatedAt: z.string().default(""), - currentMood: z.string().default(""), - personalityTraits: PersonalityTraitsSchema.default( - PERSONALITY_TRAITS_DEFAULTS - ), - recentMemories: z.array(RecentMemorySchema).default([]), - promptTokensTotal: z.number().default(0), - completionTokensTotal: z.number().default(0), - cacheHitTokensTotal: z.number().default(0), - tokensTotal: z.number().default(0), -}); - -export type UserStatsResponseInput = z.input; -export type UserStatsResponseData = z.output; - -export class UserStatsResponse { - declare readonly userId: string; - declare readonly username: string; - declare readonly platform: string; - declare readonly intimacy: number; - declare readonly relationshipStage: string; - declare readonly dolBalance: number; - declare readonly totalMessages: number; - declare readonly lastMessageAt: string; - declare readonly accountCreatedAt: string; - declare readonly currentMood: string; - declare readonly personalityTraits: PersonalityTraits; - declare readonly recentMemories: RecentMemory[]; - declare readonly promptTokensTotal: number; - declare readonly completionTokensTotal: number; - declare readonly cacheHitTokensTotal: number; - declare readonly tokensTotal: number; - - private constructor(data: UserStatsResponseData) { - Object.assign(this, data); - Object.freeze(this); - } - - static from(input: UserStatsResponseInput): UserStatsResponse { - return new UserStatsResponse(UserStatsResponseSchema.parse(input)); - } - - static fromJson(json: unknown): UserStatsResponse { - return UserStatsResponse.from(json as UserStatsResponseInput); - } - - toJson(): UserStatsResponseData { - return UserStatsResponseSchema.parse(this); - } -} diff --git a/src/data/schemas/auth/apple_login_request.ts b/src/data/schemas/auth/apple_login_request.ts new file mode 100644 index 00000000..09da28e1 --- /dev/null +++ b/src/data/schemas/auth/apple_login_request.ts @@ -0,0 +1,13 @@ +/** + * Apple 登录请求 + * 原始 Dart: AppleLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const AppleLoginRequestSchema = z.object({ + identityToken: z.string(), + platform: z.string(), +}); + +export type AppleLoginRequestInput = z.input; +export type AppleLoginRequestData = z.output; diff --git a/src/data/schemas/auth/facebook_login_request.ts b/src/data/schemas/auth/facebook_login_request.ts new file mode 100644 index 00000000..074014ac --- /dev/null +++ b/src/data/schemas/auth/facebook_login_request.ts @@ -0,0 +1,14 @@ +/** + * Facebook 登录请求 + * 原始 Dart: FacebookLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const FacebookLoginRequestSchema = z.object({ + accessToken: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type FacebookLoginRequestInput = z.input; +export type FacebookLoginRequestData = z.output; diff --git a/src/data/schemas/auth/fb_id_login_request.ts b/src/data/schemas/auth/fb_id_login_request.ts new file mode 100644 index 00000000..d9207346 --- /dev/null +++ b/src/data/schemas/auth/fb_id_login_request.ts @@ -0,0 +1,13 @@ +/** + * Facebook ID 登录请求 + * 原始 Dart: FbIdLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const FbIdLoginRequestSchema = z.object({ + fbId: z.string(), + avatarUrl: z.string().default(""), +}); + +export type FbIdLoginRequestInput = z.input; +export type FbIdLoginRequestData = z.output; diff --git a/src/data/schemas/auth/google_login_request.ts b/src/data/schemas/auth/google_login_request.ts new file mode 100644 index 00000000..d39cd0dd --- /dev/null +++ b/src/data/schemas/auth/google_login_request.ts @@ -0,0 +1,14 @@ +/** + * Google 登录请求 + * 原始 Dart: GoogleLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const GoogleLoginRequestSchema = z.object({ + idToken: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type GoogleLoginRequestInput = z.input; +export type GoogleLoginRequestData = z.output; diff --git a/src/data/schemas/auth/guest_login_request.ts b/src/data/schemas/auth/guest_login_request.ts new file mode 100644 index 00000000..09bba9d9 --- /dev/null +++ b/src/data/schemas/auth/guest_login_request.ts @@ -0,0 +1,12 @@ +/** + * 游客登录请求 + * 原始 Dart: GuestLoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const GuestLoginRequestSchema = z.object({ + deviceId: z.string(), +}); + +export type GuestLoginRequestInput = z.input; +export type GuestLoginRequestData = z.output; diff --git a/src/data/schemas/auth/guest_login_response.ts b/src/data/schemas/auth/guest_login_response.ts new file mode 100644 index 00000000..86e67eb1 --- /dev/null +++ b/src/data/schemas/auth/guest_login_response.ts @@ -0,0 +1,18 @@ +/** + * 游客登录响应 + * 原始 Dart: GuestLoginResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; +import { UserSchema } from "../user/user"; + +export const GuestLoginResponseSchema = z.object({ + token: z.string(), + deviceId: z.string(), + userId: z.string(), + isDeviceUser: z.boolean().default(true), + expiresIn: z.number().default(2592000), + user: UserSchema.optional(), +}); + +export type GuestLoginResponseInput = z.input; +export type GuestLoginResponseData = z.output; diff --git a/src/data/schemas/auth/login_request.ts b/src/data/schemas/auth/login_request.ts new file mode 100644 index 00000000..bcea9aa6 --- /dev/null +++ b/src/data/schemas/auth/login_request.ts @@ -0,0 +1,16 @@ +/** + * 登录请求 + * 原始 Dart: LoginRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const LoginRequestSchema = z.object({ + email: z.string().default(""), + username: z.string().default(""), + password: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type LoginRequestInput = z.input; +export type LoginRequestData = z.output; diff --git a/src/data/schemas/auth/login_response.ts b/src/data/schemas/auth/login_response.ts new file mode 100644 index 00000000..c7f31063 --- /dev/null +++ b/src/data/schemas/auth/login_response.ts @@ -0,0 +1,15 @@ +/** + * 登录响应 + * 原始 Dart: LoginResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; +import { UserSchema } from "../user/user"; + +export const LoginResponseSchema = z.object({ + user: UserSchema, + token: z.string(), + refreshToken: z.string().default(""), +}); + +export type LoginResponseInput = z.input; +export type LoginResponseData = z.output; diff --git a/src/data/schemas/auth/logout_response.ts b/src/data/schemas/auth/logout_response.ts new file mode 100644 index 00000000..01f4d2d6 --- /dev/null +++ b/src/data/schemas/auth/logout_response.ts @@ -0,0 +1,12 @@ +/** + * 退出登录响应 + * 原始 Dart: LogoutResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; + +export const LogoutResponseSchema = z.object({ + success: z.boolean().default(true), +}); + +export type LogoutResponseInput = z.input; +export type LogoutResponseData = z.output; diff --git a/src/data/schemas/auth/refresh_token_request.ts b/src/data/schemas/auth/refresh_token_request.ts new file mode 100644 index 00000000..4db3e522 --- /dev/null +++ b/src/data/schemas/auth/refresh_token_request.ts @@ -0,0 +1,12 @@ +/** + * 刷新 Token 请求 + * 原始 Dart: RefreshTokenRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const RefreshTokenRequestSchema = z.object({ + refreshToken: z.string(), +}); + +export type RefreshTokenRequestInput = z.input; +export type RefreshTokenRequestData = z.output; diff --git a/src/data/schemas/auth/refresh_token_response.ts b/src/data/schemas/auth/refresh_token_response.ts new file mode 100644 index 00000000..d0a6fe5c --- /dev/null +++ b/src/data/schemas/auth/refresh_token_response.ts @@ -0,0 +1,14 @@ +/** + * 刷新 Token 响应 + * 原始 Dart: RefreshTokenResponse (lib/data/models/auth/auth_response.dart) + */ +import { z } from "zod"; + +export const RefreshTokenResponseSchema = z.object({ + token: z.string(), + refreshToken: z.string(), + userId: z.string(), +}); + +export type RefreshTokenResponseInput = z.input; +export type RefreshTokenResponseData = z.output; diff --git a/src/data/schemas/auth/register_request.ts b/src/data/schemas/auth/register_request.ts new file mode 100644 index 00000000..7ed90574 --- /dev/null +++ b/src/data/schemas/auth/register_request.ts @@ -0,0 +1,16 @@ +/** + * 注册请求 + * 原始 Dart: RegisterRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const RegisterRequestSchema = z.object({ + username: z.string(), + email: z.string(), + password: z.string(), + platform: z.string(), + guestId: z.string().default(""), +}); + +export type RegisterRequestInput = z.input; +export type RegisterRequestData = z.output; diff --git a/src/data/schemas/auth/send_code_request.ts b/src/data/schemas/auth/send_code_request.ts new file mode 100644 index 00000000..9ff3b115 --- /dev/null +++ b/src/data/schemas/auth/send_code_request.ts @@ -0,0 +1,12 @@ +/** + * 发送验证码请求 + * 原始 Dart: SendCodeRequest (lib/data/models/auth/auth_request.dart) + */ +import { z } from "zod"; + +export const SendCodeRequestSchema = z.object({ + email: z.string(), +}); + +export type SendCodeRequestInput = z.input; +export type SendCodeRequestData = z.output; diff --git a/src/data/schemas/chat/chat_history_response.ts b/src/data/schemas/chat/chat_history_response.ts new file mode 100644 index 00000000..824405be --- /dev/null +++ b/src/data/schemas/chat/chat_history_response.ts @@ -0,0 +1,16 @@ +/** + * 聊天历史响应 + * 原始 Dart: ChatHistoryResponse (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; +import { ChatMessageSchema } from "./chat_message"; + +export const ChatHistoryResponseSchema = z.object({ + messages: z.array(ChatMessageSchema), + total: z.number().default(0), + limit: z.number(), + offset: z.number(), +}); + +export type ChatHistoryResponseInput = z.input; +export type ChatHistoryResponseData = z.output; diff --git a/src/data/schemas/chat/chat_message.ts b/src/data/schemas/chat/chat_message.ts new file mode 100644 index 00000000..3e4ab1b6 --- /dev/null +++ b/src/data/schemas/chat/chat_message.ts @@ -0,0 +1,15 @@ +/** + * 聊天历史中的单条消息 + * 原始 Dart: ChatMessage (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; + +export const ChatMessageSchema = z.object({ + role: z.string(), + content: z.string(), + id: z.string().default(""), + createdAt: z.string().default(""), +}); + +export type ChatMessageInput = z.input; +export type ChatMessageData = z.output; diff --git a/src/data/schemas/chat/chat_send_response.ts b/src/data/schemas/chat/chat_send_response.ts new file mode 100644 index 00000000..74dd4550 --- /dev/null +++ b/src/data/schemas/chat/chat_send_response.ts @@ -0,0 +1,22 @@ +/** + * 发送消息响应 + * 原始 Dart: ChatSendResponse (lib/data/models/chat/chat_response.dart) + */ +import { z } from "zod"; + +export const ChatSendResponseSchema = z.object({ + mode: z.string().default(""), + reply: z.string(), + voiceUrl: z.string().default(""), + audioUrl: z.string().default(""), + intimacyChange: z.number().default(0), + newIntimacy: z.number().default(0), + relationshipStage: z.string(), + currentMood: z.string().default(""), + messageId: z.string(), + isGuest: z.boolean().default(false), + timestamp: z.number().default(0), +}); + +export type ChatSendResponseInput = z.input; +export type ChatSendResponseData = z.output; diff --git a/src/data/schemas/chat/chat_sync_data.ts b/src/data/schemas/chat/chat_sync_data.ts new file mode 100644 index 00000000..a541880e --- /dev/null +++ b/src/data/schemas/chat/chat_sync_data.ts @@ -0,0 +1,13 @@ +/** + * 消息同步响应 + * 原始 Dart: ChatSyncData (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; + +export const ChatSyncDataSchema = z.object({ + syncedCount: z.number(), + totalHistory: z.number(), +}); + +export type ChatSyncDataInput = z.input; +export type ChatSyncDataData = z.output; diff --git a/src/data/schemas/chat/chat_sync_request.ts b/src/data/schemas/chat/chat_sync_request.ts new file mode 100644 index 00000000..2995a544 --- /dev/null +++ b/src/data/schemas/chat/chat_sync_request.ts @@ -0,0 +1,13 @@ +/** + * 消息同步请求 + * 原始 Dart: ChatSyncRequest (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; +import { SyncMessageSchema } from "./sync_message"; + +export const ChatSyncRequestSchema = z.object({ + messages: z.array(SyncMessageSchema), +}); + +export type ChatSyncRequestInput = z.input; +export type ChatSyncRequestData = z.output; diff --git a/src/data/schemas/chat/guest_chat_quota.ts b/src/data/schemas/chat/guest_chat_quota.ts new file mode 100644 index 00000000..0d6c4450 --- /dev/null +++ b/src/data/schemas/chat/guest_chat_quota.ts @@ -0,0 +1,13 @@ +/** + * 游客每日聊天配额数据 + * 原始 Dart: GuestChatQuota (lib/data/models/chat/guest_chat_quota.dart) + */ +import { z } from "zod"; + +export const GuestChatQuotaSchema = z.object({ + remaining: z.number(), + date: z.string(), +}); + +export type GuestChatQuotaInput = z.input; +export type GuestChatQuotaData = z.output; diff --git a/src/data/schemas/chat/image_upload_response.ts b/src/data/schemas/chat/image_upload_response.ts new file mode 100644 index 00000000..569734c7 --- /dev/null +++ b/src/data/schemas/chat/image_upload_response.ts @@ -0,0 +1,19 @@ +/** + * 图片上传响应 + * 原始 Dart: ImageUploadResponse (lib/data/models/chat/image_upload_response.dart) + */ +import { z } from "zod"; + +export const ImageUploadResponseSchema = z.object({ + success: z.boolean().default(true), + imageId: z.string(), + thumbUrl: z.string(), + mediumUrl: z.string(), + originalUrl: z.string(), + width: z.number(), + height: z.number(), + bytes: z.number(), +}); + +export type ImageUploadResponseInput = z.input; +export type ImageUploadResponseData = z.output; diff --git a/src/data/schemas/chat/send_message_request.ts b/src/data/schemas/chat/send_message_request.ts new file mode 100644 index 00000000..445f065e --- /dev/null +++ b/src/data/schemas/chat/send_message_request.ts @@ -0,0 +1,20 @@ +/** + * 发送消息请求 + * 原始 Dart: SendMessageRequest (lib/data/models/chat/send_message_request.dart) + */ +import { z } from "zod"; + +export const SendMessageRequestSchema = z.object({ + message: z.string().default(""), + image: z.string().default(""), + imageId: z.string().default(""), + imageThumbUrl: z.string().default(""), + imageMediumUrl: z.string().default(""), + imageOriginalUrl: z.string().default(""), + imageWidth: z.number().default(0), + imageHeight: z.number().default(0), + useWebSocket: z.boolean().default(false), +}); + +export type SendMessageRequestInput = z.input; +export type SendMessageRequestData = z.output; diff --git a/src/data/schemas/chat/stt_data.ts b/src/data/schemas/chat/stt_data.ts new file mode 100644 index 00000000..75a3315f --- /dev/null +++ b/src/data/schemas/chat/stt_data.ts @@ -0,0 +1,12 @@ +/** + * STT(语音转文字)响应 + * 原始 Dart: SttData (lib/data/models/chat/stt_response.dart) + */ +import { z } from "zod"; + +export const SttDataSchema = z.object({ + text: z.string(), +}); + +export type SttDataInput = z.input; +export type SttDataData = z.output; diff --git a/src/data/schemas/chat/sync_message.ts b/src/data/schemas/chat/sync_message.ts new file mode 100644 index 00000000..cd05666b --- /dev/null +++ b/src/data/schemas/chat/sync_message.ts @@ -0,0 +1,14 @@ +/** + * 待同步的单条消息 + * 原始 Dart: SyncMessage (lib/data/models/chat/chat_sync.dart) + */ +import { z } from "zod"; + +export const SyncMessageSchema = z.object({ + role: z.string(), + content: z.string(), + timestamp: z.string(), +}); + +export type SyncMessageInput = z.input; +export type SyncMessageData = z.output; diff --git a/src/data/schemas/index.ts b/src/data/schemas/index.ts new file mode 100644 index 00000000..3a07cd5d --- /dev/null +++ b/src/data/schemas/index.ts @@ -0,0 +1,42 @@ +/** + * Schemas - 集中导出 + * + * Zod schema + 类型(Source of Truth) + * 原始 Dart: lib/data/models/ + */ +export * from "./auth/apple_login_request"; +export * from "./auth/facebook_login_request"; +export * from "./auth/fb_id_login_request"; +export * from "./auth/google_login_request"; +export * from "./auth/guest_login_request"; +export * from "./auth/guest_login_response"; +export * from "./auth/login_request"; +export * from "./auth/login_response"; +export * from "./auth/logout_response"; +export * from "./auth/refresh_token_request"; +export * from "./auth/refresh_token_response"; +export * from "./auth/register_request"; +export * from "./auth/send_code_request"; + +export * from "./chat/chat_history_response"; +export * from "./chat/chat_message"; +export * from "./chat/chat_send_response"; +export * from "./chat/chat_sync_data"; +export * from "./chat/chat_sync_request"; +export * from "./chat/guest_chat_quota"; +export * from "./chat/image_upload_response"; +export * from "./chat/send_message_request"; +export * from "./chat/stt_data"; +export * from "./chat/sync_message"; + +export * from "./metrics/app_event"; +export * from "./metrics/pwa_event"; + +export * from "./user/avatar_data"; +export * from "./user/credits_data"; +export * from "./user/credits_history_data"; +export * from "./user/personality_traits"; +export * from "./user/recent_memory"; +export * from "./user/update_profile_request"; +export * from "./user/user"; +export * from "./user/user_stats_response"; diff --git a/src/data/schemas/metrics/app_event.ts b/src/data/schemas/metrics/app_event.ts new file mode 100644 index 00000000..1dd832c9 --- /dev/null +++ b/src/data/schemas/metrics/app_event.ts @@ -0,0 +1,14 @@ +/** + * 应用事件上报请求 + * 原始 Dart: AppEvent (lib/data/models/metrics/app_event.dart) + */ +import { z } from "zod"; + +export const AppEventSchema = z.object({ + userId: z.string(), + browser: z.string(), + userAgent: z.string(), +}); + +export type AppEventInput = z.input; +export type AppEventData = z.output; diff --git a/src/data/schemas/metrics/pwa_event.ts b/src/data/schemas/metrics/pwa_event.ts new file mode 100644 index 00000000..56c80d1a --- /dev/null +++ b/src/data/schemas/metrics/pwa_event.ts @@ -0,0 +1,16 @@ +/** + * PWA 事件上报请求 + * 原始 Dart: PwaEvent (lib/data/models/metrics/pwa_event.dart) + */ +import { z } from "zod"; + +export const PwaEventSchema = z.object({ + deviceId: z.string(), + deviceType: z.string(), + timestamp: z.number(), + pwaInstalled: z.boolean().default(false), + pwaSupported: z.boolean().default(false), +}); + +export type PwaEventInput = z.input; +export type PwaEventData = z.output; diff --git a/src/data/schemas/user/avatar_data.ts b/src/data/schemas/user/avatar_data.ts new file mode 100644 index 00000000..a985c8c4 --- /dev/null +++ b/src/data/schemas/user/avatar_data.ts @@ -0,0 +1,13 @@ +/** + * 头像数据模型 + * 原始 Dart: AvatarData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const AvatarDataSchema = z.object({ + avatarUrl: z.string().default(""), + userId: z.string(), +}); + +export type AvatarDataInput = z.input; +export type AvatarDataData = z.output; diff --git a/src/data/schemas/user/credits_data.ts b/src/data/schemas/user/credits_data.ts new file mode 100644 index 00000000..aae7a373 --- /dev/null +++ b/src/data/schemas/user/credits_data.ts @@ -0,0 +1,13 @@ +/** + * 积分数据模型 + * 原始 Dart: CreditsData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const CreditsDataSchema = z.object({ + userId: z.string(), + dolBalance: z.number(), +}); + +export type CreditsDataInput = z.input; +export type CreditsDataData = z.output; diff --git a/src/data/schemas/user/credits_history_data.ts b/src/data/schemas/user/credits_history_data.ts new file mode 100644 index 00000000..0b531479 --- /dev/null +++ b/src/data/schemas/user/credits_history_data.ts @@ -0,0 +1,15 @@ +/** + * 积分历史记录模型 + * 原始 Dart: CreditsHistoryData (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const CreditsHistoryDataSchema = z.object({ + records: z.array(z.record(z.string(), z.unknown())), + total: z.number(), + limit: z.number(), + offset: z.number(), +}); + +export type CreditsHistoryDataInput = z.input; +export type CreditsHistoryDataData = z.output; diff --git a/src/data/schemas/user/personality_traits.ts b/src/data/schemas/user/personality_traits.ts new file mode 100644 index 00000000..73799c35 --- /dev/null +++ b/src/data/schemas/user/personality_traits.ts @@ -0,0 +1,24 @@ +/** + * 个性特征模型 + * 原始 Dart: PersonalityTraits (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const PERSONALITY_TRAITS_DEFAULTS = { + cheerful: 0.5, + caring: 0.5, + playful: 0.5, + serious: 0.5, + romantic: 0.5, +} as const; + +export const PersonalityTraitsSchema = z.object({ + cheerful: z.number().default(0.5), + caring: z.number().default(0.5), + playful: z.number().default(0.5), + serious: z.number().default(0.5), + romantic: z.number().default(0.5), +}); + +export type PersonalityTraitsInput = z.input; +export type PersonalityTraitsData = z.output; diff --git a/src/data/schemas/user/recent_memory.ts b/src/data/schemas/user/recent_memory.ts new file mode 100644 index 00000000..2b052a1a --- /dev/null +++ b/src/data/schemas/user/recent_memory.ts @@ -0,0 +1,15 @@ +/** + * 最近记忆模型 + * 原始 Dart: RecentMemory (lib/data/models/user/recent_memory.dart) + */ +import { z } from "zod"; + +export const RecentMemorySchema = z.object({ + type: z.string(), + content: z.string(), + importance: z.number(), + createdAt: z.string().default(""), +}); + +export type RecentMemoryInput = z.input; +export type RecentMemoryData = z.output; diff --git a/src/data/schemas/user/update_profile_request.ts b/src/data/schemas/user/update_profile_request.ts new file mode 100644 index 00000000..574c55a3 --- /dev/null +++ b/src/data/schemas/user/update_profile_request.ts @@ -0,0 +1,15 @@ +/** + * 更新个人资料请求 + * 原始 Dart: UpdateProfileRequest (lib/data/models/user/user.dart) + */ +import { z } from "zod"; + +export const UpdateProfileRequestSchema = z.object({ + username: z.string().default(""), + nickname: z.string().default(""), + preferredLanguage: z.string().default(""), + currentMood: z.string().default(""), +}); + +export type UpdateProfileRequestInput = z.input; +export type UpdateProfileRequestData = z.output; diff --git a/src/data/schemas/user/user.ts b/src/data/schemas/user/user.ts new file mode 100644 index 00000000..2294cecc --- /dev/null +++ b/src/data/schemas/user/user.ts @@ -0,0 +1,27 @@ +/** + * 用户模型 + * 原始 Dart: User (lib/data/models/user/user.dart) + */ +import { z } from "zod"; +import { PersonalityTraitsSchema, PERSONALITY_TRAITS_DEFAULTS } from "./personality_traits"; + +export const UserSchema = z.object({ + id: z.string(), + username: z.string(), + email: z.string().default(""), + platform: z.string().default("web"), + intimacy: z.number().default(0), + dolBalance: z.number().default(0), + relationshipStage: z.string().default("密友"), + currentMood: z.string().default("happy"), + personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS), + preferredLanguage: z.string().default(""), + createdAt: z.string().default(""), + lastMessageAt: z.string().default(""), + avatarUrl: z.string().default(""), + loginProvider: z.string().default("email"), + isGuest: z.boolean().default(false), +}); + +export type UserInput = z.input; +export type UserData = z.output; diff --git a/src/data/schemas/user/user_stats_response.ts b/src/data/schemas/user/user_stats_response.ts new file mode 100644 index 00000000..0fb987c2 --- /dev/null +++ b/src/data/schemas/user/user_stats_response.ts @@ -0,0 +1,29 @@ +/** + * 用户统计响应 + * 原始 Dart: UserStatsResponse (lib/data/models/user/user_stats_response.dart) + */ +import { z } from "zod"; +import { PersonalityTraitsSchema, PERSONALITY_TRAITS_DEFAULTS } from "./personality_traits"; +import { RecentMemorySchema } from "./recent_memory"; + +export const UserStatsResponseSchema = z.object({ + userId: z.string(), + username: z.string(), + platform: z.string(), + intimacy: z.number(), + relationshipStage: z.string(), + dolBalance: z.number(), + totalMessages: z.number(), + lastMessageAt: z.string().default(""), + accountCreatedAt: z.string().default(""), + currentMood: z.string().default(""), + personalityTraits: PersonalityTraitsSchema.default(PERSONALITY_TRAITS_DEFAULTS), + recentMemories: z.array(RecentMemorySchema).default([]), + promptTokensTotal: z.number().default(0), + completionTokensTotal: z.number().default(0), + cacheHitTokensTotal: z.number().default(0), + tokensTotal: z.number().default(0), +}); + +export type UserStatsResponseInput = z.input; +export type UserStatsResponseData = z.output; diff --git a/src/data/storage/chat/chat_storage.ts b/src/data/storage/chat/chat_storage.ts index b908c960..11da3eed 100644 --- a/src/data/storage/chat/chat_storage.ts +++ b/src/data/storage/chat/chat_storage.ts @@ -18,7 +18,7 @@ import { GuestChatQuotaSchema, type GuestChatQuotaData, -} from "@/data/models"; +} from "@/data/schemas/chat/guest_chat_quota"; import { z } from "zod"; import { LocalStorage } from "../local_storage"; diff --git a/src/data/storage/chat/ichat_storage.ts b/src/data/storage/chat/ichat_storage.ts index 322bb906..589c2f98 100644 --- a/src/data/storage/chat/ichat_storage.ts +++ b/src/data/storage/chat/ichat_storage.ts @@ -6,13 +6,13 @@ * 对齐 Dart 端 `IChatStorage`(lib/data/services/storage/chat/ichat_storage.dart): * - 游客每日聊天配额 + 游客总配额 两个独立字段的 CRUD * - * 注:`GuestChatQuota` 模型见 `src/data/models/chat/guest_chat_quota.ts`, + * 注:`GuestChatQuota` 模型见 `src/data/dto/chat/guest_chat_quota.ts`, * 数据形态 `{ remaining: number, date: string }`。 * 跨天重置逻辑(`needsReset`)保留在 `GuestChatQuota` 类上,存储层只做读写。 */ import type { Result } from "../result"; -import type { GuestChatQuotaData } from "@/data/models"; +import type { GuestChatQuotaData } from "@/data/schemas/chat/guest_chat_quota"; export interface IChatStorage { getGuestDailyChatQuota(): Promise>; diff --git a/src/data/storage/user/iuser_storage.ts b/src/data/storage/user/iuser_storage.ts index a80ac719..2c6a1103 100644 --- a/src/data/storage/user/iuser_storage.ts +++ b/src/data/storage/user/iuser_storage.ts @@ -7,12 +7,12 @@ * - User 对象 / userId / avatarUrl 三个独立字段的 CRUD * - `clearUserData()` 批量清空 * - * 注:完整 User 模型见 `src/data/models/user/user.ts`,本接口允许存 JSON 字符串, + * 注:完整 User 模型见 `src/data/dto/user/user.ts`,本接口允许存 JSON 字符串, * 具体序列化由实现层通过 Zod schema 校验后转换为 `User` 类实例。 */ import type { Result } from "../result"; -import type { UserData } from "@/data/models"; +import type { UserData } from "@/data/schemas/user/user"; export interface IUserStorage { getUser(): Promise>; diff --git a/src/data/storage/user/user_storage.ts b/src/data/storage/user/user_storage.ts index 431c94e6..52d15558 100644 --- a/src/data/storage/user/user_storage.ts +++ b/src/data/storage/user/user_storage.ts @@ -15,7 +15,7 @@ * - 单例挂在 class 静态字段,HMR 复用安全 */ -import { UserSchema, type UserData } from "@/data/models"; +import { UserSchema, type UserData } from "@/data/schemas/user/user"; import { LocalStorage } from "../local_storage"; import { type Result as ResultT } from "../result"; import { StorageKeys } from "../storage_keys";