Some checks failed
Build & Deploy / build-and-deploy (push) Failing after 8s
Includes React PWA frontend, WebSocket signaling server, shared types, K8s manifests, Gitea CI/CD workflow, nginx config, and Dockerfiles. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
138 lines
2.6 KiB
TypeScript
138 lines
2.6 KiB
TypeScript
// ── 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" },
|
|
];
|