import * as v from 'valibot' /** * 订阅状态:账户当前订阅档位与状态。 * @typedef {{ tier: string, status: 'active' | 'inactive' | 'past_due', renews_at?: string }} SubscriptionT */ export const Subscription = v.object({ tier: v.string(), status: v.picklist(['active', 'inactive', 'past_due']), renews_at: v.optional(v.string()), }) /** /** * 库目条目:个人中心「继续观看 / 已保存」列表项。 * @typedef {{ id?: string, drama_id?: string, title?: string, cover?: string, progress?: number }} LibraryItemT */ export const LibraryItem = v.object({ id: v.optional(v.string()), drama_id: v.optional(v.string()), title: v.optional(v.string()), cover: v.optional(v.string()), progress: v.optional(v.number()), }) /** * 账户行为统计:观看 / 改写计数(个人中心头部指标,缺失项前端不渲染)。 * @typedef {{ watched?: number, rewritten?: number }} AccountStatsT */ export const AccountStats = v.object({ watched: v.optional(v.number()), rewritten: v.optional(v.number()), }) /** * 账户资料:跨端共享的用户资料 / 积分 / 订阅状态 / 语言。 * 个人中心扩展字段(history/favorites/stats/member_since)为可选:仅在 server 携带时渲染, * 不携带时前端给真实空态。声明在 schema 内以免 valibot 静默 strip 掉这些字段。 * @typedef {{ * id: string, * email?: string, * display_name: string, * credits: number, * subscription: SubscriptionT, * locale: string, * member_since?: string, * stats?: AccountStatsT, * history?: LibraryItemT[], * favorites?: LibraryItemT[] * }} AccountT */ export const Account = v.object({ id: v.string(), email: v.optional(v.string()), display_name: v.string(), credits: v.number(), subscription: Subscription, locale: v.string(), role: v.optional(v.picklist(['user', 'operator', 'admin'])), member_since: v.optional(v.string()), stats: v.optional(AccountStats), history: v.optional(v.array(LibraryItem)), favorites: v.optional(v.array(LibraryItem)), })