// ── Client → Server messages ── export interface HelloMessage { type: "hello"; joinCode?: string; } export interface CreatePublicRoomMessage { type: "create-public-room"; } export interface SignalMessage { type: "signal"; to: string; data: unknown; } export interface LeaveMessage { type: "leave"; } export type ClientMessage = | HelloMessage | CreatePublicRoomMessage | SignalMessage | LeaveMessage; // ── Server → Client messages ── export interface PeerInfo { peerId: string; displayName: string; } export interface WelcomeMessage { type: "welcome"; peerId: string; displayName: string; roomId: string; peers: PeerInfo[]; } export interface PublicRoomCreatedMessage { type: "public-room-created"; code: string; url: string; expiresAt: string; } export interface PeerJoinedMessage { type: "peer-joined"; peerId: string; displayName: string; } export interface PeerLeftMessage { type: "peer-left"; peerId: string; } export interface SignalRelayMessage { type: "signal"; from: string; data: unknown; } export type ErrorCode = "room-not-found" | "room-expired" | "rate-limit"; export interface ErrorMessage { type: "error"; code: ErrorCode; message: string; } export type ServerMessage = | WelcomeMessage | PublicRoomCreatedMessage | PeerJoinedMessage | PeerLeftMessage | SignalRelayMessage | ErrorMessage; // ── Data channel messages (peer-to-peer) ── export interface FileMetaMessage { type: "file-meta"; id: string; name: string; size: number; mime: string; } export interface FileEndMessage { type: "file-end"; id: string; } export interface TextMessage { type: "text"; id: string; content: string; } export interface TransferRequestMessage { type: "transfer-request"; files: { id: string; name: string; size: number; mime: string }[]; text?: string; } export interface TransferResponseMessage { type: "transfer-response"; accepted: boolean; } export type DataChannelMessage = | FileMetaMessage | FileEndMessage | TextMessage | TransferRequestMessage | TransferResponseMessage; // ── Constants ── export const CHUNK_SIZE = 16 * 1024; // 16 KB export const MAX_BUFFER = 1024 * 1024; // 1 MB backpressure threshold export const SHORT_CODE_ALPHABET = "abcdefghjkmnpqrstuvwxyz23456789"; export const SHORT_CODE_LENGTH = 3; export const SHORT_CODE_MAX_LENGTH = 4; export const SHORT_CODE_MAX_RETRIES = 5; export const PUBLIC_ROOM_TTL_MS = 10 * 60 * 1000; // 10 minutes export const ICE_SERVERS: RTCIceServer[] = [ { urls: "stun:stun.l.google.com:19302" }, { urls: "stun:stun1.l.google.com:19302" }, ];