visual-game-admin-users.js 6.08 KB
import * as v from 'valibot'

export const VisualGameAdminUserAccountType = v.picklist(['registered', 'guest'])

export const VisualGameAdminUserSubscriptionStatus = v.picklist([
  'none',
  'active',
  'expired',
  'canceled',
])

export const VisualGameAdminUserSubscription = v.object({
  level: v.string(),
  status: VisualGameAdminUserSubscriptionStatus,
  expires_at: v.nullable(v.string()),
  provider: v.nullable(v.string()),
  source: v.nullable(v.string()),
})

export const VisualGameAdminUserListStats = v.object({
  runs: v.number(),
  turns: v.number(),
  endings: v.number(),
  orders: v.number(),
})

export const VisualGameAdminUserInteractionStats = v.object({
  credits_spent: v.number(),
  credits_granted: v.number(),
  say_turns: v.number(),
  act_turns: v.number(),
  interactions: v.number(),
  completed_runs: v.number(),
  completed_seasons: v.number(),
})

export const VisualGameAdminUserListItem = v.object({
  id: v.string(),
  account_type: VisualGameAdminUserAccountType,
  email: v.nullable(v.string()),
  display_name: v.nullable(v.string()),
  locale: v.nullable(v.string()),
  created_at: v.string(),
  last_active_at: v.nullable(v.string()),
  credits: v.number(),
  subscription: VisualGameAdminUserSubscription,
  stats: VisualGameAdminUserListStats,
  interaction_stats: VisualGameAdminUserInteractionStats,
})

export const VisualGameAdminUserSummary = v.object({
  total_users: v.number(),
  registered_users: v.number(),
  guest_users: v.number(),
  players: v.number(),
  paying_users: v.number(),
})

export const VisualGameAdminUserListResponse = v.object({
  items: v.array(VisualGameAdminUserListItem),
  next_cursor: v.nullable(v.string()),
  total: v.number(),
})

export const VisualGameAdminGuestDevice = v.object({
  status: v.picklist(['active', 'merged']),
  last_seen_at: v.nullable(v.string()),
  merged_user_id: v.nullable(v.string()),
})

export const VisualGameAdminLedgerEntry = v.object({
  id: v.string(),
  type: v.picklist(['grant', 'deduct']),
  amount: v.number(),
  balance_after: v.number(),
  reason: v.nullable(v.string()),
  ref_type: v.nullable(v.string()),
  ref_id: v.nullable(v.string()),
  created_at: v.string(),
})

export const VisualGameAdminPaymentOrder = v.object({
  id: v.string(),
  product_id: v.string(),
  mode: v.picklist(['payment', 'subscription']),
  provider: v.picklist(['stripe', 'apple', 'google']),
  status: v.picklist(['pending', 'paid', 'canceled', 'failed', 'refunded', 'disputed']),
  amount_cents: v.nullable(v.number()),
  refund_amount: v.nullable(v.number()),
  currency: v.nullable(v.string()),
  created_at: v.string(),
  updated_at: v.nullable(v.string()),
})

export const VisualGameAdminRun = v.object({
  id: v.string(),
  scenario_id: v.string(),
  scenario_title: v.nullable(v.string()),
  status: v.picklist(['active', 'completed']),
  turn_count: v.number(),
  current_location_id: v.nullable(v.string()),
  phase: v.nullable(v.string()),
  created_at: v.string(),
  updated_at: v.nullable(v.string()),
  completed_at: v.nullable(v.string()),
})

export const VisualGameAdminPlaySummary = v.object({
  runs: v.number(),
  active_runs: v.number(),
  completed_runs: v.number(),
  turns: v.number(),
  scenarios: v.number(),
  progress_records: v.number(),
  save_slots: v.number(),
  endings: v.number(),
  last_active_at: v.nullable(v.string()),
  say_turns: v.number(),
  act_turns: v.number(),
  credits_spent: v.number(),
  credits_granted: v.number(),
  completed_seasons: v.number(),
})

export const VisualGameAdminUserAuditAction = v.picklist([
  'account_provisioned',
  'profile_updated',
  'credits_granted',
  'credits_deducted',
  'subscription_updated',
])

export const VisualGameAdminUserProvisionRequest = v.strictObject({
  mutation_id: v.pipe(v.string(), v.regex(/^[0-9a-f]{8}-[0-9a-f]{4}-[1-8][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i)),
  email: v.pipe(v.string(), v.trim(), v.toLowerCase(), v.email(), v.maxLength(254)),
  password: v.pipe(v.string(), v.minLength(8), v.maxLength(256)),
  locale: v.picklist(['zh', 'en', 'ja', 'ko', 'es', 'pt']),
  initial_credits: v.pipe(v.number(), v.integer(), v.minValue(0), v.maxValue(10000000)),
  reason: v.pipe(v.string(), v.trim(), v.minLength(3), v.maxLength(500)),
})

export const VisualGameAdminUserAuditEntry = v.object({
  id: v.string(),
  operator_id: v.string(),
  action: VisualGameAdminUserAuditAction,
  reason: v.string(),
  created_at: v.string(),
})

export const VisualGameAdminUserDetail = v.object({
  user: v.object({
    id: v.string(),
    account_type: VisualGameAdminUserAccountType,
    email: v.nullable(v.string()),
    display_name: v.nullable(v.string()),
    nickname: v.nullable(v.string()),
    avatar_url: v.nullable(v.string()),
    account_locale: v.nullable(v.string()),
    profile_locale: v.nullable(v.string()),
    email_verified_at: v.nullable(v.string()),
    created_at: v.string(),
  }),
  guest_devices: v.array(VisualGameAdminGuestDevice),
  subscription: VisualGameAdminUserSubscription,
  credits: v.object({
    balance: v.number(),
    ledger: v.array(VisualGameAdminLedgerEntry),
  }),
  orders: v.array(VisualGameAdminPaymentOrder),
  audit_logs: v.array(VisualGameAdminUserAuditEntry),
  play: v.object({
    summary: VisualGameAdminPlaySummary,
    recent_runs: v.array(VisualGameAdminRun),
  }),
})

export const VisualGameAdminUserDetailResponse = v.object({
  detail: VisualGameAdminUserDetail,
})

export const VisualGameAdminUserProfileUpdateRequest = v.object({
  mutation_id: v.string(),
  nickname: v.nullable(v.string()),
  avatar_url: v.nullable(v.string()),
  locale: v.picklist(['zh', 'en', 'ja', 'ko', 'es', 'pt']),
  reason: v.string(),
})

export const VisualGameAdminUserCreditsAdjustRequest = v.object({
  mutation_id: v.string(),
  type: v.picklist(['grant', 'deduct']),
  amount: v.number(),
  reason: v.string(),
})

export const VisualGameAdminUserSubscriptionUpdateRequest = v.object({
  mutation_id: v.string(),
  level: v.string(),
  status: VisualGameAdminUserSubscriptionStatus,
  expires_at: v.nullable(v.string()),
  reason: v.string(),
})

export const VisualGameAdminUserActionResponse = v.object({
  detail: VisualGameAdminUserDetail,
  audit_id: v.string(),
})