computerNames.ts 1.5 KB

1234567891011121314151617181920212223242526272829303132333435
  1. import { existsSync, mkdirSync, readFileSync, renameSync, writeFileSync } from 'node:fs'
  2. import { join } from 'node:path'
  3. import { randomUUID } from 'node:crypto'
  4. import { HttpError } from './errors.js'
  5. const pathOf = (home: string) => join(home, 'computer-names.json')
  6. const idOk = (id: string) => id === 'local' || /^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$/.test(id)
  7. export function readComputerNames(home: string): Record<string, string> {
  8. const path = pathOf(home)
  9. if (!existsSync(path)) return {}
  10. try {
  11. const value = JSON.parse(readFileSync(path, 'utf8')) as { names?: Record<string, unknown> }
  12. const names: Record<string, string> = {}
  13. for (const [id, name] of Object.entries(value?.names ?? {})) {
  14. if (idOk(id) && typeof name === 'string' && name.trim()) names[id] = name.trim().slice(0, 64)
  15. }
  16. return names
  17. } catch { return {} }
  18. }
  19. export function saveComputerName(home: string, id: string, name: string): Record<string, string> {
  20. if (!idOk(id)) throw new HttpError(400, '这台电脑不能改名', 'computer_unknown')
  21. const trimmed = name.trim()
  22. if (trimmed.length > 64) throw new HttpError(400, '名字最长 64 个字', 'computer_name_invalid')
  23. const names = readComputerNames(home)
  24. if (trimmed) names[id] = trimmed
  25. else delete names[id]
  26. mkdirSync(home, { recursive: true, mode: 0o700 })
  27. const path = pathOf(home)
  28. const temporary = path + '.' + randomUUID()
  29. writeFileSync(temporary, JSON.stringify({ names }, null, 2) + '\n', { mode: 0o600 })
  30. renameSync(temporary, path)
  31. return names
  32. }