refactor(data): replace schema classes with readonly models

This commit is contained in:
2026-07-17 13:21:40 +08:00
parent 3437312167
commit ae97366a4a
103 changed files with 1220 additions and 2117 deletions
@@ -1,20 +1,24 @@
import { describe, expect, it } from "vitest";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { ChatSendResponse } from "@/data/schemas/chat";
import {
ChatSendResponseSchema,
type ChatSendResponse,
type ChatSendResponseInput,
} from "@/data/schemas/chat";
import type { ChatState } from "@/stores/chat/chat-state";
import {
applyNetworkHistoryLoadedOutput,
applyHttpSendOutput,
applyNetworkHistoryLoadedOutput,
countLockedHistoryMessages,
localMessagesToUi,
sendResponseToUiMessage,
} from "@/stores/chat/helper";
function makeResponse(
overrides: Partial<Parameters<typeof ChatSendResponse.from>[0]> = {},
overrides: Partial<ChatSendResponseInput> = {},
): ChatSendResponse {
return ChatSendResponse.from({
return ChatSendResponseSchema.parse({
reply: "AI reply",
messageId: "msg-1",
isGuest: false,
@@ -100,9 +104,7 @@ describe("sendResponseToUiMessage", () => {
}),
);
expect(message.audioUrl).toBe(
"https://example.com/unlocked-voice.mp3",
);
expect(message.audioUrl).toBe("https://example.com/unlocked-voice.mp3");
expect(message.locked).toBe(false);
});
@@ -1,12 +1,15 @@
import { fromCallback, fromPromise } from "xstate";
import {
ChatSendResponse,
UnlockPrivateResponse,
} from "@/data/schemas/chat";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { chatMachine } from "@/stores/chat/chat-machine";
import {
ChatSendResponseSchema,
UnlockPrivateResponseSchema,
type ChatSendResponse,
type UnlockPrivateResponse,
type UnlockPrivateResponseInput,
} from "@/data/schemas/chat";
import type { ChatEvent } from "@/stores/chat/chat-events";
import { chatMachine } from "@/stores/chat/chat-machine";
import type {
UnlockMessageOutput as MachineUnlockMessageOutput,
UnlockMessageRequest,
@@ -36,7 +39,7 @@ export const TEST_CHAT_MACHINE_INPUT = {
};
export function makeChatSendResponse(): ChatSendResponse {
return ChatSendResponse.from({
return ChatSendResponseSchema.parse({
reply: "",
audioUrl: "",
messageId: "msg-1",
@@ -51,9 +54,9 @@ export function makeChatSendResponse(): ChatSendResponse {
}
export function makeUnlockPrivateResponse(
overrides: Partial<Parameters<typeof UnlockPrivateResponse.from>[0]> = {},
overrides: Partial<UnlockPrivateResponseInput> = {},
): UnlockPrivateResponse {
return UnlockPrivateResponse.from({
return UnlockPrivateResponseSchema.parse({
unlocked: true,
content: "unlocked content",
audioUrl: "",
@@ -106,21 +109,20 @@ export function createTestChatMachine(
return () => undefined;
},
),
unlockHistory: fromPromise<
UnlockHistoryOutput,
{ characterId: string }
>(async () => {
if (options.unlockHistoryError) {
throw options.unlockHistoryError;
}
return {
unlocked: true,
reason: "ok",
shortfallCredits: 0,
messages: [],
...options.unlockHistoryOutput,
};
}),
unlockHistory: fromPromise<UnlockHistoryOutput, { characterId: string }>(
async () => {
if (options.unlockHistoryError) {
throw options.unlockHistoryError;
}
return {
unlocked: true,
reason: "ok",
shortfallCredits: 0,
messages: [],
...options.unlockHistoryOutput,
};
},
),
unlockMessage: fromPromise<
MachineUnlockMessageOutput,
UnlockMessageRequest & { characterId: string }
@@ -1,6 +1,6 @@
import { describe, expect, it } from "vitest";
import { UnlockPrivateResponse } from "@/data/schemas/chat";
import { UnlockPrivateResponseSchema } from "@/data/schemas/chat";
import type { PendingChatPromotion } from "@/data/storage/navigation";
import {
appendPromotionMessage,
@@ -50,7 +50,7 @@ describe("chat promotion", () => {
lockType: "image_paywall",
clientLockId: "promotion-1",
},
response: UnlockPrivateResponse.from({
response: UnlockPrivateResponseSchema.parse({
unlocked: true,
messageId: "backend-1",
image: {
@@ -1,7 +1,7 @@
import { describe, expect, it } from "vitest";
import { createActor, fromPromise, waitFor } from "xstate";
import { ChatSendResponse } from "@/data/schemas/chat";
import { ChatSendResponseSchema } from "@/data/schemas/chat";
import type {
UnlockMessageOutput,
UnlockMessageRequest,
@@ -666,7 +666,7 @@ describe("chat unlock flow", () => {
actor.send({
type: "ChatQueuedHttpDone",
output: {
response: ChatSendResponse.from({
response: ChatSendResponseSchema.parse({
reply: "",
audioUrl: "",
messageId: "",