107 lines
3.0 KiB
TypeScript
107 lines
3.0 KiB
TypeScript
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<string>();
|
|
const seenNames = new Set<string>();
|
|
|
|
return parsed
|
|
.filter((channel): channel is Record<string, unknown> => !!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
|
|
};
|
|
}
|