auth.js 1.96 KB
import * as v from 'valibot'
import { Account } from './account.js'

/**
 * 登录请求:provider(oauth 厂商 / 匿名)+ 凭据 + 可选设备标识(匿名身份合并用)。
 * @typedef {{ provider: string, credential: string, oauth_flow?: 'access_token'|'authorization_code', redirect_uri?: string, device_id?: string }} LoginRequestT
 */
export const LoginRequest = v.object({
  provider: v.string(),
  credential: v.string(),
  oauth_flow: v.optional(v.picklist(['access_token', 'authorization_code'])),
  redirect_uri: v.optional(v.string()),
  device_id: v.optional(v.string()),
})

/**
 * 登录响应:访问 / 刷新 token 对 + 账户资料。
 * @typedef {{ access_token: string, refresh_token: string, account: import('./account.js').AccountT }} LoginResponseT
 */
export const LoginResponse = v.object({
  access_token: v.string(),
  refresh_token: v.string(),
  account: Account,
})

/**
 * 开放注册请求:验证码只用于本次邮箱注册,邀请码不属于该契约。
 * @typedef {{ email: string, password: string, verification_code: string, locale: 'en'|'zh'|'ja'|'ko'|'es'|'pt', device_id?: string }} RegisterRequestT
 */
export const RegisterRequest = v.strictObject({
  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)),
  verification_code: v.pipe(v.string(), v.regex(/^\d{6}$/)),
  locale: v.picklist(['en', 'zh', 'ja', 'ko', 'es', 'pt']),
  device_id: v.optional(v.pipe(v.string(), v.trim(), v.minLength(1), v.maxLength(255))),
})

/** @typedef {{ channel: 'email', target: string, purpose: 'register', locale?: 'en'|'zh'|'ja'|'ko'|'es'|'pt' }} SendRegistrationCodeRequestT */
export const SendRegistrationCodeRequest = v.strictObject({
  channel: v.literal('email'),
  target: v.pipe(v.string(), v.trim(), v.toLowerCase(), v.email(), v.maxLength(254)),
  purpose: v.literal('register'),
  locale: v.optional(v.picklist(['en', 'zh', 'ja', 'ko', 'es', 'pt'])),
})