serverIdentity.ts 2.0 KB

12345678910111213141516171819202122232425262728293031323334
  1. import { hostname } from 'node:os'
  2. import type { WorkspaceStore } from './workspaceStore.js'
  3. import type { ServerIdentity } from '../shared/serverIdentity.js'
  4. import { HttpError } from './errors.js'
  5. export function readServerIdentity(store: WorkspaceStore): ServerIdentity {
  6. const row = store.db.prepare('SELECT * FROM server_identity WHERE singleton=1').get()!
  7. const name = String(row.name)
  8. return { serverId: String(row.server_id), name, displayName: name || hostname(), revision: Number(row.revision) }
  9. }
  10. export function updateServerIdentity(store: WorkspaceStore, input: Record<string, unknown>): ServerIdentity {
  11. if (typeof input.name !== 'string' || Object.keys(input).some(key => !['name', 'expectedRevision', 'expectedServerId'].includes(key))) {
  12. throw new HttpError(400, '请输入服务器名称', 'invalid_server_name')
  13. }
  14. const name = input.name.trim()
  15. if (name.length > 100 || /[\u0000-\u001f\u007f]/.test(name)) {
  16. throw new HttpError(400, '服务器名称最多 100 个字符,不能包含换行或控制字符', 'invalid_server_name')
  17. }
  18. if (input.expectedRevision !== undefined && (!Number.isSafeInteger(input.expectedRevision) || Number(input.expectedRevision) < 0)) {
  19. throw new HttpError(400, '服务器配置版本无效', 'invalid_server_revision')
  20. }
  21. return store.atomic(() => {
  22. const current = readServerIdentity(store)
  23. if (input.expectedServerId !== undefined && input.expectedServerId !== current.serverId) {
  24. throw new HttpError(409, '服务器连接已切换,请重新载入后再保存', 'server_identity_target_changed')
  25. }
  26. if (input.expectedRevision !== undefined && input.expectedRevision !== current.revision) {
  27. throw new HttpError(409, '服务器名称已在其他端更新,请重新载入后再保存', 'server_identity_conflict')
  28. }
  29. if (name !== current.name) store.db.prepare('UPDATE server_identity SET name=?,revision=revision+1 WHERE singleton=1').run(name)
  30. return readServerIdentity(store)
  31. })
  32. }