import { AuthUserEntity } from '../entities/AuthUserEntity'; import { ServerEntity } from '../entities/ServerEntity'; import { JoinRequestEntity } from '../entities/JoinRequestEntity'; import { AuthUserPayload, ServerChannelPayload, ServerPayload, JoinRequestPayload } from './types'; function channelNameKey(type: ServerChannelPayload['type'], name: string): string { return `${type}:${name.toLocaleLowerCase()}`; } function parseStringArray(raw: string | null | undefined): string[] { try { const parsed = JSON.parse(raw || '[]'); return Array.isArray(parsed) ? parsed.filter((value): value is string => typeof value === 'string') : []; } catch { return []; } } function parseServerChannels(raw: string | null | undefined): ServerChannelPayload[] { try { const parsed = JSON.parse(raw || '[]'); if (!Array.isArray(parsed)) { return []; } const seenIds = new Set(); const seenNames = new Set(); return parsed .filter((channel): channel is Record => !!channel && typeof channel === 'object') .map((channel, index) => { const id = typeof channel.id === 'string' ? channel.id.trim() : ''; const name = typeof channel.name === 'string' ? channel.name.trim().replace(/\s+/g, ' ') : ''; const type = channel.type === 'text' || channel.type === 'voice' ? channel.type : null; const position = typeof channel.position === 'number' ? channel.position : index; const nameKey = type ? channelNameKey(type, name) : ''; if (!id || !name || !type || seenIds.has(id) || seenNames.has(nameKey)) { return null; } seenIds.add(id); seenNames.add(nameKey); return { id, name, type, position } satisfies ServerChannelPayload; }) .filter((channel): channel is ServerChannelPayload => !!channel); } catch { return []; } } export function rowToAuthUser(row: AuthUserEntity): AuthUserPayload { return { id: row.id, username: row.username, passwordHash: row.passwordHash, displayName: row.displayName, createdAt: row.createdAt }; } export function rowToServer(row: ServerEntity): ServerPayload { return { id: row.id, name: row.name, description: row.description ?? undefined, ownerId: row.ownerId, ownerPublicKey: row.ownerPublicKey, hasPassword: !!row.passwordHash, passwordHash: row.passwordHash ?? undefined, isPrivate: !!row.isPrivate, maxUsers: row.maxUsers, currentUsers: row.currentUsers, tags: parseStringArray(row.tags), channels: parseServerChannels(row.channels), createdAt: row.createdAt, lastSeen: row.lastSeen }; } export function rowToJoinRequest(row: JoinRequestEntity): JoinRequestPayload { return { id: row.id, serverId: row.serverId, userId: row.userId, userPublicKey: row.userPublicKey, displayName: row.displayName, status: row.status as JoinRequestPayload['status'], createdAt: row.createdAt }; }