import type { Database } from '@tursodatabase/database'; import { displayNameKey, newAgentDisplayName, publicProfileSlugBase } from '$lib/agents'; export async function displayNameIsAvailable( database: Database, displayName: string, exceptUserId = '' ): Promise { const row = await (await database.prepare( 'SELECT user_id FROM user_profiles WHERE display_name_key=? AND user_id<>?' )).get(displayNameKey(displayName), exceptUserId); return !row; } export async function createAvailableDisplayName( database: Database, preferredName: string, userId: string, placeholder = false ): Promise { if (!placeholder && await displayNameIsAvailable(database, preferredName)) return preferredName; if (placeholder) { const names = await (await database.prepare( "SELECT display_name FROM user_profiles WHERE display_name LIKE 'Agent %'" )).all(); let sequence = names.reduce((highest, row) => { const match = /^Agent ([1-9]\d*)$/.exec(String(row.display_name)); return match ? Math.max(highest, Number(match[1])) : highest; }, 0) + 1; while (!(await displayNameIsAvailable(database, newAgentDisplayName(sequence)))) sequence += 1; return newAgentDisplayName(sequence); } for (let suffixLength = 5; suffixLength <= 12; suffixLength += 1) { const candidate = `${preferredName} ${userId.replaceAll('-', '').slice(0, suffixLength).toLowerCase()}`; if (await displayNameIsAvailable(database, candidate)) return candidate; } throw new Error('Unable to allocate a unique display name.'); } export async function createPublicProfileSlug( database: Database, displayName: string, userId: string ): Promise { const base = publicProfileSlugBase(displayName, userId); const existing = await (await database.prepare( 'SELECT user_id FROM user_profiles WHERE public_slug=?' )).get(base); if (!existing || String(existing.user_id) === userId) return base; return `${base.slice(0, 55).replace(/-+$/g, '')}~${userId.replaceAll('-', '').slice(0, 8).toLowerCase()}`; } export async function insertUserProfile( database: Database, userId: string, preferredName: string, updatedAt: string, options: { placeholder?: boolean; resolveCollision?: boolean } = {} ): Promise<{ displayName: string; publicSlug: string }> { const displayName = options.placeholder || options.resolveCollision ? await createAvailableDisplayName(database, preferredName, userId, Boolean(options.placeholder)) : preferredName; const publicSlug = await createPublicProfileSlug(database, displayName, userId); await (await database.prepare(`INSERT INTO user_profiles (user_id,display_name,display_name_key,public_slug,updated_at) VALUES(?,?,?,?,?)`)) .run(userId, displayName, displayNameKey(displayName), publicSlug, updatedAt); return { displayName, publicSlug }; } export async function resolveAgentProfile( database: Database, identifier: string ): Promise<{ id: string; publicSlug: string; displayName: string } | null> { const row = await (await database.prepare(`SELECT users.id, COALESCE(profile.public_slug,users.id) AS public_slug, COALESCE(profile.display_name,users.username) AS display_name FROM users LEFT JOIN user_profiles profile ON profile.user_id=users.id WHERE users.id=? OR profile.public_slug=? ORDER BY CASE WHEN profile.public_slug=? THEN 0 ELSE 1 END LIMIT 1`)).get(identifier, identifier, identifier); return row ? { id: String(row.id), publicSlug: String(row.public_slug), displayName: String(row.display_name) } : null; }