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,11 +1,11 @@
import { describe, expect, it, vi } from "vitest";
import { AuthRepository } from "@/data/repositories/auth_repository";
import {
FacebookIdentityResponse,
FacebookPsidLoginResponse,
FacebookIdentityResponseSchema,
FacebookPsidLoginResponseSchema,
LoginStatus,
} from "@/data/schemas/auth";
import { AuthRepository } from "@/data/repositories/auth_repository";
import type { AuthApi } from "@/data/services/api";
import type { IAuthStorage } from "@/data/storage/auth";
import type { IUserStorage } from "@/data/storage/user";
@@ -36,7 +36,7 @@ function createRepository(overrides: Partial<AuthApi>) {
describe("AuthRepository facebook identity", () => {
it("binds facebook identity and stores returned ids", async () => {
const bindFacebookIdentity = vi.fn(async () =>
FacebookIdentityResponse.fromJson({
FacebookIdentityResponseSchema.parse({
fbAsid: "asid-1",
fbPsid: "psid-1",
facebookBinding: { conflicts: [], bound: [] },
@@ -57,7 +57,7 @@ describe("AuthRepository facebook identity", () => {
it("saves real login data from complete psid login responses", async () => {
const facebookPsidLogin = vi.fn(async () =>
FacebookPsidLoginResponse.fromJson({
FacebookPsidLoginResponseSchema.parse({
token: "login-token",
refreshToken: "refresh-token",
matchedBy: "psid",
@@ -88,7 +88,7 @@ describe("AuthRepository facebook identity", () => {
it("saves guest data from incomplete psid login responses", async () => {
const facebookPsidLogin = vi.fn(async () =>
FacebookPsidLoginResponse.fromJson({
FacebookPsidLoginResponseSchema.parse({
token: "guest-token",
matchedBy: "psid_incomplete",
fbPsid: "psid-1",
@@ -116,7 +116,7 @@ describe("AuthRepository facebook identity", () => {
it("does not report guest psid login success when session persistence fails", async () => {
const storageError = new Error("guest token write failed");
const facebookPsidLogin = vi.fn(async () =>
FacebookPsidLoginResponse.fromJson({
FacebookPsidLoginResponseSchema.parse({
token: "guest-token",
matchedBy: "psid_incomplete",
fbPsid: "psid-1",
@@ -1,22 +1,24 @@
import { afterEach, describe, expect, it, vi } from "vitest";
import {
GuestLoginResponse,
LoginResponse,
LoginStatus,
RefreshTokenResponse,
} from "@/data/schemas/auth";
import { AuthRepository } from "@/data/repositories/auth_repository";
import {
GuestLoginResponseSchema,
LoginResponseSchema,
LoginStatus,
RefreshTokenResponseSchema,
} from "@/data/schemas/auth";
import type { AuthApi } from "@/data/services/api";
import type { IAuthStorage } from "@/data/storage/auth";
import type { IUserStorage } from "@/data/storage/user";
import { Result } from "@/utils/result";
function createRepository(input: {
api?: Partial<AuthApi>;
storage?: Partial<IAuthStorage>;
userStorage?: Partial<IUserStorage>;
} = {}) {
function createRepository(
input: {
api?: Partial<AuthApi>;
storage?: Partial<IAuthStorage>;
userStorage?: Partial<IUserStorage>;
} = {},
) {
const storage = {
getRefreshToken: vi.fn(async () => Result.ok("refresh-token")),
setLoginToken: vi.fn(async () => Result.ok(undefined)),
@@ -52,7 +54,7 @@ afterEach(() => {
});
describe("AuthRepository session Result handling", () => {
const loginResponse = LoginResponse.from({
const loginResponse = LoginResponseSchema.parse({
token: "login-token",
refreshToken: "refresh-token",
user: { id: "user-1", username: "Elio" },
@@ -112,7 +114,7 @@ describe("AuthRepository session Result handling", () => {
it("does not report refresh success when a new token cannot be stored", async () => {
const storageError = new Error("login token write failed");
const response = RefreshTokenResponse.from({
const response = RefreshTokenResponseSchema.parse({
token: "new-login-token",
refreshToken: "new-refresh-token",
userId: "user-1",
@@ -135,7 +137,7 @@ describe("AuthRepository session Result handling", () => {
it("does not report guest login success when session persistence fails", async () => {
const storageError = new Error("guest token write failed");
const response = GuestLoginResponse.from({
const response = GuestLoginResponseSchema.parse({
token: "guest-token",
deviceId: "device-1",
userId: "guest-1",
@@ -1,13 +1,13 @@
import { describe, expect, it, vi } from "vitest";
import { ChatMessage } from "@/data/schemas/chat";
import { ChatMessage, ChatMessageSchema } from "@/data/schemas/chat";
import { LocalMessage } from "@/data/storage/chat";
import { Result } from "@/utils/result";
import { ChatLocalMessageStore } from "../chat_local_message_store";
function makeMessage(id: string, content: string): ChatMessage {
return ChatMessage.from({
return ChatMessageSchema.parse({
id,
role: "assistant",
type: "text",
@@ -53,9 +53,8 @@ describe("ChatLocalMessageStore identity isolation", () => {
it("reads, replaces, and clears only the current identity", async () => {
const memory = createMemoryStorage();
let identity = "user:account-a";
const store = new ChatLocalMessageStore(
memory.storage,
async () => Result.ok(identity),
const store = new ChatLocalMessageStore(memory.storage, async () =>
Result.ok(identity),
);
await store.saveMessages([makeMessage("a-1", "account A")]);
@@ -1,7 +1,14 @@
import { describe, expect, it } from "vitest";
import { DEFAULT_CHARACTER_ID } from "@/data/constants/character";
import { ChatMessage, ChatSendResponse } from "@/data/schemas/chat";
import {
ChatMessageSchema,
ChatSendResponseSchema,
type ChatMessage,
type ChatMessageInput,
type ChatSendResponse,
type ChatSendResponseInput,
} from "@/data/schemas/chat";
import {
buildChatMediaCacheKey,
@@ -11,10 +18,8 @@ import {
uniqueMediaTargets,
} from "../chat_media_cache_helpers";
function makeMessage(
overrides: Partial<Parameters<typeof ChatMessage.from>[0]> = {},
): ChatMessage {
return ChatMessage.from({
function makeMessage(overrides: Partial<ChatMessageInput> = {}): ChatMessage {
return ChatMessageSchema.parse({
id: "msg-1",
role: "assistant",
type: "image",
@@ -31,9 +36,9 @@ function makeMessage(
}
function makeResponse(
overrides: Partial<Parameters<typeof ChatSendResponse.from>[0]> = {},
overrides: Partial<ChatSendResponseInput> = {},
): ChatSendResponse {
return ChatSendResponse.from({
return ChatSendResponseSchema.parse({
reply: "",
messageId: "msg-1",
isGuest: false,
@@ -1,14 +1,14 @@
import { describe, expect, it, vi } from "vitest";
import { TipPaymentPlansResponse } from "@/data/schemas/payment";
import { PaymentRepository } from "@/data/repositories/payment_repository";
import { TipPaymentPlansResponseSchema } from "@/data/schemas/payment";
import type { PaymentApi } from "@/data/services/api";
import { Result } from "@/utils/result";
describe("PaymentRepository", () => {
it("adapts tip plans without caching them as subscription plans", async () => {
const getTipPlans = vi.fn().mockResolvedValue(
TipPaymentPlansResponse.from({
TipPaymentPlansResponseSchema.parse({
plans: [
{
planId: "tip_coffee_usd_9_99",
+31 -30
View File
@@ -1,30 +1,31 @@
import { ExceptionHandler } from "@/core/errors";
import { ApiError, AuthApi, authApi, ErrorCode } from "@/data/services/api";
import type { IAuthRepository } from "@/data/repositories/interfaces";
import {
FacebookIdentityRequest,
FacebookPsidLoginRequest,
FacebookLoginRequest,
FbIdLoginRequest,
GoogleLoginRequest,
GuestLoginRequest,
FacebookIdentityRequestSchema,
FacebookLoginRequestSchema,
FacebookPsidLoginRequestSchema,
FbIdLoginRequestSchema,
GoogleLoginRequestSchema,
GuestLoginRequestSchema,
GuestLoginResponse,
LoginRequest,
LoginRequestSchema,
LoginResponse,
LoginResponseSchema,
LoginStatus,
type LoginStatus as LoginStatusT,
RefreshTokenRequest,
RefreshTokenRequestSchema,
RefreshTokenResponse,
RegisterRequest,
RegisterRequestSchema,
type LoginStatus as LoginStatusT,
} from "@/data/schemas/auth";
import { User } from "@/data/schemas/user";
import { AppEnvUtil } from "@/utils/app-env";
import { PlatformDetector } from "@/utils/platform-detect";
import { Result } from "@/utils/result";
import { Logger } from "@/utils/logger";
import { deviceIdentifier } from "@/utils/device_identifier";
import type { IAuthRepository } from "@/data/repositories/interfaces";
import { ApiError, AuthApi, authApi, ErrorCode } from "@/data/services/api";
import { AuthStorage, type IAuthStorage } from "@/data/storage/auth";
import { UserStorage, type IUserStorage } from "@/data/storage/user";
import { AppEnvUtil } from "@/utils/app-env";
import { deviceIdentifier } from "@/utils/device_identifier";
import { Logger } from "@/utils/logger";
import { PlatformDetector } from "@/utils/platform-detect";
import { Result } from "@/utils/result";
import { createLazySingleton } from "./lazy_singleton";
const log = new Logger("DataRepositoriesAuthRepository");
@@ -52,7 +53,7 @@ export class AuthRepository implements IAuthRepository {
}): Promise<Result<void>> {
return Result.wrap(async () => {
await this.api.register(
RegisterRequest.from(
RegisterRequestSchema.parse(
withTestAccountFlag({
username: input.username,
email: input.email,
@@ -76,7 +77,7 @@ export class AuthRepository implements IAuthRepository {
return Result.wrap(async () => {
const email = input.email?.trim() ?? "";
const response = await this.api.emailLogin(
LoginRequest.from(
LoginRequestSchema.parse(
withTestAccountFlag({
email,
username: input.username,
@@ -152,7 +153,7 @@ export class AuthRepository implements IAuthRepository {
});
return Result.wrap(async () => {
const response = await this.api.guestLogin(
GuestLoginRequest.from(withTestAccountFlag({ deviceId })),
GuestLoginRequestSchema.parse(withTestAccountFlag({ deviceId })),
);
log.debug("[AuthRepository.guestLogin] API call SUCCESS (Zod parsed)", {
hasToken: !!response.token,
@@ -190,7 +191,7 @@ export class AuthRepository implements IAuthRepository {
}): Promise<Result<LoginResponse>> {
return this._socialLogin(LoginStatus.Google, () =>
this.api.googleLogin(
GoogleLoginRequest.from(
GoogleLoginRequestSchema.parse(
withTestAccountFlag({
idToken: input.idToken,
platform: getAuthPlatform(),
@@ -210,7 +211,7 @@ export class AuthRepository implements IAuthRepository {
}): Promise<Result<LoginResponse>> {
return this._socialLogin(LoginStatus.Facebook, () =>
this.api.facebookLogin(
FacebookLoginRequest.from(
FacebookLoginRequestSchema.parse(
withTestAccountFlag({
accessToken: input.accessToken,
platform: getAuthPlatform(),
@@ -230,7 +231,7 @@ export class AuthRepository implements IAuthRepository {
}): Promise<Result<LoginResponse>> {
return this._socialLogin(LoginStatus.Facebook, () =>
this.api.facebookIdLogin(
FbIdLoginRequest.from(
FbIdLoginRequestSchema.parse(
withTestAccountFlag({
fbId: input.asid,
avatarUrl: input.avatarUrl ?? "",
@@ -250,12 +251,12 @@ export class AuthRepository implements IAuthRepository {
return Result.wrap(async () => {
const response = await this.api.bindFacebookIdentity(
FacebookIdentityRequest.from({
FacebookIdentityRequestSchema.parse({
asid: input.asid ?? "",
psid: input.psid ?? "",
}),
);
const data = response.toJson();
const data = response;
await this._saveFacebookIdentity({
asid: data.fbAsid,
psid: data.fbPsid,
@@ -271,13 +272,13 @@ export class AuthRepository implements IAuthRepository {
}): Promise<Result<LoginStatusT>> {
return Result.wrap(async () => {
const response = await this.api.facebookPsidLogin(
FacebookPsidLoginRequest.from({
FacebookPsidLoginRequestSchema.parse({
psid: input.psid,
deviceId: input.deviceId ?? "",
bindToGuest: input.bindToGuest ?? true,
}),
);
const data = response.toJson();
const data = response;
await this._saveFacebookIdentity({
asid: data.fbAsid,
psid: data.fbPsid,
@@ -303,7 +304,7 @@ export class AuthRepository implements IAuthRepository {
}
await this._saveLoginData(
LoginResponse.from({
LoginResponseSchema.parse({
token: data.token,
refreshToken: data.refreshToken,
user: data.user ?? { id: data.userId },
@@ -330,7 +331,7 @@ export class AuthRepository implements IAuthRepository {
);
}
const response = await this.api.refreshToken(
RefreshTokenRequest.from({ refreshToken: existing.data }),
RefreshTokenRequestSchema.parse({ refreshToken: existing.data }),
);
const tokenResult = await this.storage.setLoginToken(response.token);
if (Result.isErr(tokenResult)) throw tokenResult.error;
@@ -404,7 +405,7 @@ export class AuthRepository implements IAuthRepository {
private async _cacheUser(user: User): Promise<void> {
try {
const userResult = await this.userStorage.setUser(user.toJson());
const userResult = await this.userStorage.setUser(user);
if (Result.isErr(userResult)) {
log.warn("[AuthRepository] setUser failed", userResult.error);
}
@@ -1,5 +1,5 @@
import { ChatMessage } from "@/data/schemas/chat";
import type { UnlockedPrivateMessageLocalPatch } from "@/data/repositories/interfaces";
import { ChatMessage, ChatMessageSchema } from "@/data/schemas/chat";
import { LocalChatStorage, LocalMessage } from "@/data/storage/chat";
import { Result } from "@/utils/result";
@@ -20,8 +20,7 @@ type LocalMessageStorage = Pick<
export class ChatLocalMessageStore {
constructor(
private readonly localStorage: LocalMessageStorage,
private readonly resolveIdentity: ChatCacheIdentityResolver =
resolveChatCacheOwnerKey,
private readonly resolveIdentity: ChatCacheIdentityResolver = resolveChatCacheOwnerKey,
) {}
async markMessageUnlocked(
@@ -40,8 +39,8 @@ export class ChatLocalMessageStore {
const updatedMessages = localResult.data.map((message) => {
if (!shouldMarkMessageUnlocked(message, messageId)) return message;
changed = true;
return ChatMessage.from({
...message.toJson(),
return ChatMessageSchema.parse({
...message,
content: normalizeUnlockedContent(patch.content, message.content),
audioUrl: normalizeUnlockedAudioUrl(patch.audioUrl, message.audioUrl),
image: patch.image ?? message.image,
@@ -85,7 +84,9 @@ export class ChatLocalMessageStore {
});
}
async getMessages(identity?: string): Promise<Result<ChatMessage[]>> {
async getMessages(
identity?: string,
): Promise<Result<readonly ChatMessage[]>> {
return Result.wrap(async () => {
const ownerKey = await this._requireIdentity(identity);
const result = await this._getMessages(ownerKey);
@@ -128,12 +129,10 @@ export class ChatLocalMessageStore {
private async _getMessages(
identity: string,
): Promise<Result<ChatMessage[]>> {
): Promise<Result<readonly ChatMessage[]>> {
const result = await this.localStorage.getAllMessagesBySession(identity);
if (Result.isErr(result)) return result;
return Result.ok(
result.data.map((message) => this._localToChat(message)),
);
return Result.ok(result.data.map((message) => this._localToChat(message)));
}
private _saveMessages(
@@ -161,7 +160,7 @@ export class ChatLocalMessageStore {
}
private _localToChat(local: LocalMessage): ChatMessage {
return ChatMessage.from({
return ChatMessageSchema.parse({
id: local.id,
role: local.role,
type: local.type,
@@ -1,14 +1,14 @@
import type { UnlockPrivateMessageInput } from "@/data/repositories/interfaces";
import {
ChatHistoryResponse,
ChatSendResponse,
SendMessageRequest,
UnlockHistoryRequest,
SendMessageRequestSchema,
UnlockHistoryRequestSchema,
UnlockHistoryResponse,
UnlockPrivateRequest,
UnlockPrivateRequestSchema,
UnlockPrivateResponse,
} from "@/data/schemas/chat";
import type { ChatApi } from "@/data/services/api";
import type { UnlockPrivateMessageInput } from "@/data/repositories/interfaces";
import { Result } from "@/utils/result";
export class ChatRemoteDataSource {
@@ -20,7 +20,7 @@ export class ChatRemoteDataSource {
options?: { image?: string; useWebSocket?: boolean },
): Promise<Result<ChatSendResponse>> {
return Result.wrap(async () => {
const request = SendMessageRequest.from({
const request = SendMessageRequestSchema.parse({
characterId,
message,
image: options?.image ?? "",
@@ -42,7 +42,7 @@ export class ChatRemoteDataSource {
input: UnlockPrivateMessageInput,
): Promise<Result<UnlockPrivateResponse>> {
return Result.wrap(() =>
this.api.unlockPrivateMessage(UnlockPrivateRequest.from(input)),
this.api.unlockPrivateMessage(UnlockPrivateRequestSchema.parse(input)),
);
}
@@ -50,7 +50,7 @@ export class ChatRemoteDataSource {
characterId: string,
): Promise<Result<UnlockHistoryResponse>> {
return Result.wrap(() =>
this.api.unlockHistory(UnlockHistoryRequest.from({ characterId })),
this.api.unlockHistory(UnlockHistoryRequestSchema.parse({ characterId })),
);
}
}
+11 -9
View File
@@ -1,3 +1,10 @@
import type {
CacheRemoteChatMediaInput,
ChatMediaLookupInput,
IChatRepository,
UnlockPrivateMessageInput,
UnlockedPrivateMessageLocalPatch,
} from "@/data/repositories/interfaces";
import type {
ChatHistoryResponse,
ChatMessage,
@@ -11,13 +18,6 @@ import {
LocalChatStorage,
type LocalChatMediaRow,
} from "@/data/storage/chat";
import type {
CacheRemoteChatMediaInput,
ChatMediaLookupInput,
IChatRepository,
UnlockPrivateMessageInput,
UnlockedPrivateMessageLocalPatch,
} from "@/data/repositories/interfaces";
import type { Result } from "@/utils/result";
import { ChatLocalMessageStore } from "./chat_local_message_store";
@@ -60,7 +60,9 @@ export class ChatRepository implements IChatRepository {
}
/** 一键解锁历史锁定消息。 */
async unlockHistory(characterId: string): Promise<Result<UnlockHistoryResponse>> {
async unlockHistory(
characterId: string,
): Promise<Result<UnlockHistoryResponse>> {
return this.remote.unlockHistory(characterId);
}
@@ -101,7 +103,7 @@ export class ChatRepository implements IChatRepository {
/** 读取所有本地消息,按 dbId 升序。 */
async getLocalMessages(
cacheIdentity?: string,
): Promise<Result<ChatMessage[]>> {
): Promise<Result<readonly ChatMessage[]>> {
return this.localMessages.getMessages(cacheIdentity);
}
@@ -4,18 +4,19 @@
* 聚合聊天远程操作、身份隔离的本地历史,以及媒体缓存能力。
*/
import type { Result } from "@/utils/result";
import type {
ChatHistoryResponse,
ChatImageData,
ChatLockDetailData,
ChatLockType,
ChatMediaKind,
ChatMessage,
ChatSendResponse,
UnlockHistoryResponse,
UnlockPrivateResponse,
} from "@/data/schemas/chat";
import type { ChatLockDetailData } from "@/data/schemas/chat";
import type { ChatImageData, ChatLockType } from "@/data/schemas/chat";
import type { LocalChatMediaRow } from "@/data/storage/chat";
import type { Result } from "@/utils/result";
export interface ChatMediaLookupInput {
characterId: string;
@@ -84,7 +85,9 @@ export interface IChatRepository {
): Promise<Result<void>>;
/** 读取所有本地消息,按 dbId 升序。 */
getLocalMessages(cacheIdentity?: string): Promise<Result<ChatMessage[]>>;
getLocalMessages(
cacheIdentity?: string,
): Promise<Result<readonly ChatMessage[]>>;
/** 清空本地消息。 */
clearLocalMessages(cacheIdentity?: string): Promise<Result<void>>;
+5 -5
View File
@@ -3,10 +3,10 @@
*
* 指标/埋点仓库:纯远程 fire-and-forget 上报,无本地状态。
*/
import { MetricsApi, metricsApi } from "@/data/services/api";
import { AppEvent, PwaEvent } from "@/data/schemas/metrics";
import { Result } from "@/utils/result";
import type { IMetricsRepository } from "@/data/repositories/interfaces";
import { AppEventSchema, PwaEventSchema } from "@/data/schemas/metrics";
import { MetricsApi, metricsApi } from "@/data/services/api";
import { Result } from "@/utils/result";
import { createLazySingleton } from "./lazy_singleton";
export class MetricsRepository implements IMetricsRepository {
@@ -24,7 +24,7 @@ export class MetricsRepository implements IMetricsRepository {
}): Promise<Result<void>> {
return Result.wrap(async () => {
await this.api.reportPwaEvent(
PwaEvent.from({
PwaEventSchema.parse({
deviceId: input.deviceId,
deviceType: input.deviceType,
timestamp: Math.floor(Date.now() / 1000),
@@ -45,7 +45,7 @@ export class MetricsRepository implements IMetricsRepository {
}): Promise<Result<void>> {
return Result.wrap(async () => {
await this.api.reportUserInfo(
AppEvent.from({
AppEventSchema.parse({
userId: input.userId,
browser: input.browser,
userAgent: input.userAgent,
+8 -8
View File
@@ -3,16 +3,17 @@
*
* 支付 / 付费墙相关远程调用。
*/
import type { IPaymentRepository } from "@/data/repositories/interfaces";
import {
CreatePaymentOrderRequest,
CreatePaymentOrderRequestSchema,
CreatePaymentOrderResponse,
PayChannel,
PaymentOrderStatusResponse,
PaymentPlansResponse,
PaymentPlansResponseSchema,
} from "@/data/schemas/payment";
import { PaymentApi, paymentApi } from "@/data/services/api";
import { PaymentPlansStorage } from "@/data/storage/payment";
import type { IPaymentRepository } from "@/data/repositories/interfaces";
import { Result } from "@/utils/result";
import { createLazySingleton } from "./lazy_singleton";
@@ -23,7 +24,7 @@ export class PaymentRepository implements IPaymentRepository {
async getPlans(): Promise<Result<PaymentPlansResponse>> {
return Result.wrap(async () => {
const response = await this.api.getPlans();
await PaymentPlansStorage.setPlans(response.toJson());
await PaymentPlansStorage.setPlans(response);
return response;
});
}
@@ -33,7 +34,7 @@ export class PaymentRepository implements IPaymentRepository {
return Result.wrap(async () => {
const result = await PaymentPlansStorage.getPlans();
if (Result.isErr(result)) throw result.error;
return result.data ? PaymentPlansResponse.from(result.data) : null;
return result.data ? PaymentPlansResponseSchema.parse(result.data) : null;
});
}
@@ -41,9 +42,9 @@ export class PaymentRepository implements IPaymentRepository {
async getTipPlans(): Promise<Result<PaymentPlansResponse>> {
return Result.wrap(async () => {
const response = await this.api.getTipPlans();
return PaymentPlansResponse.from({
return PaymentPlansResponseSchema.parse({
plans: response.plans.map((plan) => ({
...plan.toJson(),
...plan,
orderType: "tip",
vipDays: null,
dolAmount: null,
@@ -72,7 +73,7 @@ export class PaymentRepository implements IPaymentRepository {
payChannel: PayChannel,
autoRenew: boolean,
): Promise<Result<CreatePaymentOrderResponse>> {
const request = CreatePaymentOrderRequest.from({
const request = CreatePaymentOrderRequestSchema.parse({
planId,
payChannel,
autoRenew,
@@ -86,7 +87,6 @@ export class PaymentRepository implements IPaymentRepository {
): Promise<Result<PaymentOrderStatusResponse>> {
return Result.wrap(() => this.api.getOrderStatus(orderId));
}
}
/** 全局懒单例。 */
@@ -1,16 +1,16 @@
import type {
GetPrivateAlbumsInput,
IPrivateRoomRepository,
} from "@/data/repositories/interfaces";
import {
UnlockPrivateAlbumRequest,
type PrivateAlbumsResponse,
type PrivateAlbumUnlockResponse,
UnlockPrivateAlbumRequestSchema,
} from "@/data/schemas/private-room";
import {
PrivateRoomApi,
privateRoomApi,
} from "@/data/services/api/private_room_api";
import type {
GetPrivateAlbumsInput,
IPrivateRoomRepository,
} from "@/data/repositories/interfaces";
import { Result } from "@/utils/result";
import { createLazySingleton } from "./lazy_singleton";
@@ -31,7 +31,7 @@ export class PrivateRoomRepository implements IPrivateRoomRepository {
return Result.wrap(() =>
this.api.unlockAlbum(
albumId,
UnlockPrivateAlbumRequest.from({ expectedCost }),
UnlockPrivateAlbumRequestSchema.parse({ expectedCost }),
),
);
}