owner-handles.js 1.43 KB
const TABLE = 'vk_owner_handles'

/** 主人 id 的格式:小写字母、数字、下划线、连字符,2–32 位,字母或数字开头。与 DB CHECK 一致。 */
export const HANDLE_PATTERN = /^[a-z0-9][a-z0-9_-]{1,31}$/

/**
 * 主人的 id(handle)。Agent 的全名是「名字@主人 id」,如 小火子@yibo。
 * @param {{ db: import('knex').Knex }} deps
 */
export function createOwnerHandles({ db }) {
  if (typeof db !== 'function') throw new Error('createOwnerHandles: db is required')

  /**
   * @param {object} _ctx
   * @param {{ handle: string }} input
   * @returns {Promise<boolean>}
   */
  async function isTaken(_ctx, { handle }) {
    return (await db(TABLE).where({ handle }).first('user_id')) !== undefined
  }

  /**
   * 注册时在同一事务里登记;handle 被占用由 UNIQUE 裁决(调用方应先用 isTaken 给出友好提示)。
   * @param {object} _ctx
   * @param {import('knex').Knex} trx
   * @param {{ user_id: string, handle: string }} input
   */
  async function assign(_ctx, trx, { user_id, handle }) {
    await trx(TABLE).insert({ user_id, handle, created_at: new Date() })
  }

  /**
   * @param {object} _ctx
   * @param {{ user_id: string }} input
   * @returns {Promise<string|null>}
   */
  async function get(_ctx, { user_id }) {
    const row = await db(TABLE).where({ user_id }).first('handle')
    return row === undefined ? null : row.handle
  }

  return { isTaken, assign, get }
}