๐Ÿ“„ auth.ts  โ€ข  4656 bytes
import { t } from '../i18n.js'
import { login, register, validateToken, loadUserCache, clearUserCache, type UserInfo } from '../user.js'
import { existsSync, mkdirSync } from 'node:fs'

/**
 * ็”จๆˆท่ฎค่ฏๆต็จ‹ - ็™ปๅฝ•/ๆณจๅ†Œไบคไบ’
 * 
 * ไปŽ cli.ts ๆๅ–๏ผŒๆŽฅๆ”ถๆ‰€ๆœ‰ไพ่ต–ไฝœไธบๅ‚ๆ•ฐไปฅ้ฟๅ…้—ญๅŒ…่€ฆๅˆ
 */
export async function userAuthFlow(
  VERSION: string,
  color: { bold: string; reset: string; brightGreen: string; brightRed: string; brightYellow: string; [key: string]: string },
  BRAND: string,
  ACCENT: string,
  MUTED: string,
  SUCCESS: string,
  ERROR: string,
  WARN: string,
  askQuestion: (query: string) => Promise<string>,
  askPassword: (query: string) => Promise<string>
): Promise<UserInfo> {
  console.log('')
  console.log(`  ${color.bold}${BRAND}CmdCode${color.reset} ${MUTED}v${VERSION}${color.reset}  ${ACCENT}${t('app.subtitle')}${color.reset}`)
  console.log('')

  // 1. ๆฃ€ๆŸฅๆœฌๅœฐ็ผ“ๅญ˜token
  const cached = loadUserCache()
  if (cached) {
    process.stdout.write(`  ${ACCENT}${t('auth.verify')}${color.reset}`)
    const valid = await validateToken(cached)
    // ๆธ…้™คๅฝ“ๅ‰่กŒ
    process.stdout.write('\r' + ' '.repeat(40) + '\r')
    if (valid) {
      // ้™้ป˜่ฟ”ๅ›ž๏ผŒ็Šถๆ€ไฟกๆฏๅœจ printBanner ็ปŸไธ€ๆ˜พ็คบ
      if (!existsSync(cached.workspaceDir)) {
        mkdirSync(cached.workspaceDir, { recursive: true })
      }
      return cached
    } else {
      console.log(`  ${WARN}${t('auth.expired')}${color.reset}`)
      clearUserCache()
    }
  }

  // 2. ไบคไบ’ๅผ็™ปๅฝ•/ๆณจๅ†Œ
  while (true) {
    console.log('')
    console.log(`  ${MUTED}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
    console.log(`    ${BRAND}${color.bold}1${color.reset}  ${t('auth.login')}`)
    console.log(`    ${BRAND}${color.bold}2${color.reset}  ${t('auth.register')}`)
    console.log(`  ${MUTED}โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€${color.reset}`)
    console.log('')

    const choice = await askQuestion(`  ${MUTED}โ€บ${color.reset} `)

    if (choice === '1') {
      const username = await askQuestion(`  ${MUTED}โ€บ${color.reset} ${t('auth.username')}: `)
      if (!username) { console.log(`  ${ERROR}${t('auth.username_empty')}${color.reset}`); continue }
      const password = await askPassword(`  ${MUTED}โ€บ${color.reset} ${t('auth.password')}: `)
      if (!password) { console.log(`  ${ERROR}${t('auth.password_empty')}${color.reset}`); continue }

      process.stdout.write(`  ${ACCENT}${t('auth.logging_in')}${color.reset}`)
      try {
        const userInfo = await login(username, password)
        process.stdout.write('\r' + ' '.repeat(20) + '\r')
        console.log(`  ${SUCCESS}${t('auth.login_success')}${color.reset}`)
        return userInfo
      } catch (e: any) {
        process.stdout.write('\r' + ' '.repeat(20) + '\r')
        console.log(`  ${ERROR}${e.message}${color.reset}`)
        continue
      }
    } else if (choice === '2') {
      const username = await askQuestion(`  ${MUTED}โ€บ${color.reset} ${t('auth.username')} ${MUTED}${t('auth.username_hint')}${color.reset}: `)
      if (!username) { console.log(`  ${ERROR}${t('auth.username_empty')}${color.reset}`); continue }
      if (!/^[a-zA-Z0-9_]{3,32}$/.test(username)) {
        console.log(`  ${ERROR}${t('auth.username_invalid')}${color.reset}`)
        continue
      }
      const password = await askPassword(`  ${MUTED}โ€บ${color.reset} ${t('auth.password')} ${MUTED}${t('auth.password_hint')}${color.reset}: `)
      if (!password || password.length < 6) {
        console.log(`  ${ERROR}${t('auth.password_short')}${color.reset}`)
        continue
      }
      const password2 = await askPassword(`  ${MUTED}โ€บ${color.reset} ${t('auth.confirm_password')}: `)
      if (password !== password2) {
        console.log(`  ${ERROR}Passwords do not match${color.reset}`)
        continue
      }

      process.stdout.write(`  ${ACCENT}${t('auth.registering')}${color.reset}`)
      try {
        const userInfo = await register(username, password)
        process.stdout.write('\r' + ' '.repeat(20) + '\r')
        console.log(`  ${SUCCESS}${t('auth.register_success')}${color.reset}`)
        console.log(`  ${ACCENT}Workspace created${color.reset}`)
        return userInfo
      } catch (e: any) {
        process.stdout.write('\r' + ' '.repeat(20) + '\r')
        console.log(`  ${ERROR}${e.message}${color.reset}`)
        continue
      }
    } else {
      console.log(`  ${ERROR}${t('auth.choose_option')}${color.reset}`)
    }
  }
}