32 KiB
SerpentRace Backend API Documentation for Frontend Developers
Complete API Reference with All Endpoints
Table of Contents
- Test User Credentials
- Data Structures & Entities
- Base URL & Service Info
- Authentication Endpoints
- User Management
- Deck Management
- Organization Management
- Chat System
- Contact Management
- Import/Export Functionality
- Admin Endpoints
- Error Handling
- WebSocket Real-Time Communication
Test User Credentials
For development and testing, use these pre-configured user accounts:
Regular User (Verified)
- Username:
john_doe - Password:
password123 - Email:
john.doe@email.com - Type: Regular user (state: 1 - VERIFIED_REGULAR)
- Organization: None
Premium User (Organization Member)
- Username:
jane_premium - Password:
password123 - Email:
jane.smith@email.com - Type: Premium user (state: 2 - VERIFIED_PREMIUM)
- Organization: Tech Solutions Inc
Teacher (Premium Organization Member)
- Username:
teacher_bob - Password:
password123 - Email:
bob.teacher@eduinst.edu - Type: Premium user (state: 2 - VERIFIED_PREMIUM)
- Organization: Educational Institute
Admin User
- Username:
admin_user - Password:
password123 - Email:
admin@serpentrace.com - Type: Admin (state: 5 - ADMIN)
- Organization: None
Unverified User
- Username:
new_user - Password:
password123 - Email:
newuser@email.com - Type: Unverified (state: 0 - REGISTERED_NOT_VERIFIED)
- Organization: None
Data Structures & Entities
User DTOs
interface ShortUserDto {
id: string; // UUID
username: string; // Username
state: number; // UserState enum
authLevel: 0 | 1; // 0 = regular, 1 = admin
}
interface DetailUserDto {
id: string; // UUID
orgid: string | null; // Organization ID (if member)
username: string; // Unique username
email: string; // Email address
fname: string; // First name
lname: string; // Last name
code: string | null; // Verification code
type: string; // 'personal' | 'premium' | 'admin'
phone: string | null; // Phone number
state: number; // UserState enum value
}
enum UserState {
REGISTERED_NOT_VERIFIED = 0, // Email not verified
VERIFIED_REGULAR = 1, // Regular verified user
VERIFIED_PREMIUM = 2, // Premium verified user
SOFT_DELETE = 3, // Soft deleted
DEACTIVATED = 4, // Account deactivated
ADMIN = 5 // Admin user
}
Deck DTOs
interface ShortDeckDto {
id: string; // UUID
name: string; // Deck name
type: number; // DeckType enum value
playedNumber: number; // Times played
ctype: number; // DeckVisibility enum value
}
interface DetailDeckDto {
id: string; // UUID
name: string; // Deck name
type: number; // DeckType enum value
userid: string; // Owner's user ID
creationdate: Date; // Creation timestamp
cards: Card[]; // Array of cards
playedNumber: number; // Times played
ctype: number; // DeckVisibility enum value
}
interface Card {
text: string; // Question/prompt text
type?: number; // CardType enum (optional)
answer?: string | null; // Answer (varies by type)
}
enum DeckType {
LUCK = 0, // Luck-based cards
JOKER = 1, // Joker/wild cards
QUESTION = 2 // Question-based cards
}
enum DeckVisibility {
PUBLIC = 0, // Public to all
PRIVATE = 1, // Private to owner
ORGANIZATION = 2 // Shared within organization
}
enum DeckState {
ACTIVE = 0, // Active deck
SOFT_DELETE = 1 // Soft deleted
}
enum CardType {
QUIZ = 0, // Multiple choice question
SENTENCE_PAIRING = 1, // Sentence completion
OWN_ANSWER = 2, // Custom answer
TRUE_FALSE = 3, // True/False question
CLOSER = 4 // Closer to answer
}
Organization DTOs
interface ShortOrganizationDto {
id: string; // UUID
name: string; // Organization name
contactfname: string; // Contact first name
contactlname: string; // Contact last name
contactemail: string; // Contact email
state: number; // OrganizationState enum
regdate: Date; // Registration date
maxOrganizationalDecks: number | null; // Max org decks allowed
}
enum OrganizationState {
REGISTERED = 0, // Just registered
ACTIVE = 1, // Active organization
SOFT_DELETE = 2 // Soft deleted
}
Chat DTOs
interface ShortChatDto {
id: string; // UUID
userCount: number; // Number of participants
state: number; // ChatState enum value
}
interface DetailChatDto {
id: string; // UUID
users: string[]; // Participant user IDs
messages: Message[]; // Message history
updateDate: Date; // Last update
state: number; // ChatState enum value
}
interface Message {
id: string; // Message UUID
date: Date; // Message timestamp
userid: string; // Sender user ID
text: string; // Message content
}
enum ChatType {
DIRECT = 'direct', // Direct message
GROUP = 'group', // Group chat
GAME = 'game' // Game-specific chat
}
enum ChatState {
ACTIVE = 0, // Active chat
ARCHIVE = 1, // Archived chat
SOFT_DELETE = 2 // Soft deleted
}
Contact DTOs
interface ContactDto {
id: string; // UUID
name: string; // Contact name
email: string; // Contact email
userid: string | null; // User ID if logged in
type: number; // ContactType enum
txt: string; // Message content
state: number; // ContactState enum
createDate: Date; // Creation date
updateDate: Date; // Last update
adminResponse: string | null; // Admin response
responseDate: Date | null; // Response date
respondedBy: string | null; // Responding admin ID
}
enum ContactType {
BUG = 0, // Bug report
PROBLEM = 1, // Problem report
QUESTION = 2, // General question
SALES = 3, // Sales inquiry
OTHER = 4 // Other type
}
enum ContactState {
ACTIVE = 0, // Active/unresolved
RESOLVED = 1, // Resolved
SOFT_DELETE = 2 // Soft deleted
}
Base URL & Service Info
Base URL: http://localhost:3000 (development)
Service Information
Endpoint: GET /
Authentication: None required
Response Data:
{
service: "SerpentRace Backend API";
status: "running";
version: "1.0.0";
endpoints: {
swagger: "/api-docs";
users: "/api/users";
organizations: "/api/organizations";
decks: "/api/decks";
chats: "/api/chats";
contacts: "/api/contacts";
admin: "/api/admin";
deckImportExport: "/api/deck-import-export";
health: "/health";
};
websocket: {
enabled: true;
events: string[]; // WebSocket event names
};
}
Health Check
Endpoint: GET /health
Authentication: None required
Response Data:
{
status: "healthy" | "unhealthy";
timestamp: string; // ISO timestamp
service: "SerpentRace Backend API";
version: "1.0.0";
environment: string; // "development" | "production"
database: {
connected: boolean; // Database connection status
type: string; // Database type
};
websocket: {
enabled: boolean; // WebSocket status
};
uptime: number; // Process uptime in seconds
}
Authentication Endpoints
User Login
Endpoint: POST /api/users/login
Authentication: None required
Validation Rules:
username: 3-50 characterspassword: 6-100 characters
Request Data:
{
username: string; // Username or email
password: string; // Password
}
Response Data (Success):
{
token: string; // JWT token (also set as cookie)
user: ShortUserDto; // User information
organizationName?: string; // Organization name (if member)
}
Error Responses:
400: Validation error401: Invalid credentials, unverified email, or account restrictions500: Internal server error
User Registration
Endpoint: POST /api/users/create
Authentication: None required
Validation Rules:
username: 3-50 characters, uniqueemail: valid email format, uniquepassword: 6-100 characters
Request Data:
{
username: string; // Unique username
email: string; // Valid email
password: string; // Password
fname?: string; // First name (optional)
lname?: string; // Last name (optional)
phone?: string; // Phone number (optional)
type?: string; // User type (optional)
}
Response Data (Success):
{
id: string; // User UUID
username: string; // Username
email: string; // Email
regdate: Date; // Registration date
}
Error Responses:
400: Validation error409: Username or email already exists500: Internal server error
User Management
Get User Profile
Endpoint: GET /api/users/profile
Authentication: Required
Response Data: DetailUserDto
Update User Profile
Endpoint: PATCH /api/users/profile
Authentication: Required
Request Data: Partial DetailUserDto fields to update
Response Data: Updated DetailUserDto
Error Responses:
400: Validation error404: User not found409: Email already exists500: Internal server error
Deck Management
Get Decks (Paginated) - RECOMMENDED
Endpoint: GET /api/decks/page/{from}/{to}
Authentication: Required
URL Parameters:
from: Start index (0-based, ≥ 0)to: End index (inclusive, ≥ from)
Response Data:
{
decks: ShortDeckDto[]; // Array of deck summaries
totalCount: number; // Total available decks
}
Create Deck
Endpoint: POST /api/decks
Authentication: Required
Request Data:
{
name: string; // Deck name (required)
type?: number; // DeckType enum (optional)
cards?: Card[]; // Initial cards (optional)
ctype?: number; // DeckVisibility enum (optional)
}
Response Data: ShortDeckDto
Search Decks
Endpoint: GET /api/decks/search
Authentication: Required
Query Parameters:
query: Search query (required, non-empty)limit: Results limit (1-100, default: 20)offset: Results offset (≥ 0, default: 0)
Response Data: Array of matching ShortDeckDto
Get Deck by ID
Endpoint: GET /api/decks/{id}
Authentication: Required
URL Parameters:
id: Deck UUID
Response Data: DetailDeckDto
Update Deck
Endpoint: PUT /api/decks/{id}
Authentication: Required (owner only)
URL Parameters:
id: Deck UUID
Request Data: Partial DetailDeckDto fields to update
Response Data: Updated ShortDeckDto
Delete Deck (Soft Delete)
Endpoint: DELETE /api/decks/{id}
Authentication: Required (owner only)
URL Parameters:
id: Deck UUID
Response Data:
{
success: boolean; // Deletion success status
}
Organization Management
Get Organizations (Paginated) - RECOMMENDED
Endpoint: GET /api/organizations/page/{from}/{to}
Authentication: Required
URL Parameters:
from: Start index (0-based, ≥ 0)to: End index (inclusive, ≥ from)
Response Data:
{
organizations: ShortOrganizationDto[];
totalCount: number;
}
Search Organizations
Endpoint: GET /api/organizations/search
Authentication: Required
Query Parameters:
query: Search query (required, non-empty)limit: Results limit (1-100, default: 20)offset: Results offset (≥ 0, default: 0)
Response Data: Array of matching organizations
Get Organization Login URL
Endpoint: GET /api/organizations/{orgId}/login-url
Authentication: Required
URL Parameters:
orgId: Organization UUID
Response Data:
{
loginUrl: string; // Organization login URL
organizationName: string; // Organization name
}
Process Organization Auth Callback
Endpoint: POST /api/organizations/auth-callback
Authentication: Required
Request Data:
{
organizationId: string; // Organization UUID
status: "ok" | "not_ok"; // Authentication status
authToken?: string; // Authentication token (optional)
}
Response Data:
{
success: boolean; // Processing success
message: string; // Result message
updatedFields?: string[]; // Fields that were updated
}
Chat System
Get User Chats
Endpoint: GET /api/chats/user-chats
Authentication: Required
Query Parameters:
includeArchived: boolean (default: false)
Response Data: Array of ShortChatDto
Get Chat History
Endpoint: GET /api/chats/history/{chatId}
Authentication: Required
URL Parameters:
chatId: Chat UUID (validated)
Response Data:
{
id: string; // Chat UUID
users: string[]; // Participants
messages: Message[]; // Message history
isArchived: boolean; // Archive status
state: number; // Chat state
}
Create Chat
Endpoint: POST /api/chats/create
Authentication: Required
Validation Rules:
type: must be 'direct' or 'group'userIds: non-empty arrayname: required for groups
Request Data:
{
type: 'direct' | 'group'; // Chat type
userIds: string[]; // Participant user IDs
name?: string; // Group name (required for groups)
}
Response Data:
{
id: string; // Chat UUID
type: ChatType; // Chat type
name: string | null; // Chat name
users: string[]; // Participants
messages: Message[]; // Empty initially
}
Send Message (REST - for testing)
Endpoint: POST /api/chats/message
Authentication: Required
Validation Rules:
chatId: valid UUIDmessage: 1-2000 characters
Request Data:
{
chatId: string; // Chat UUID
message: string; // Message content
}
Response Data: Message object
Archive Chat
Endpoint: POST /api/chats/archive/{chatId}
Authentication: Required
URL Parameters:
chatId: Chat UUID (validated)
Response Data:
{
success: boolean;
message: string;
}
Restore Chat from Archive
Endpoint: POST /api/chats/restore/{chatId}
Authentication: Required
URL Parameters:
chatId: Chat UUID (validated)
Response Data:
{
success: boolean;
message: string;
}
Get Archived Game Chats
Endpoint: GET /api/chats/archived/game/{gameId}
Authentication: Required
URL Parameters:
gameId: Game UUID (validated)
Response Data: Array of archived chat objects
Contact Management
Create Contact
Endpoint: POST /api/contact
Authentication: Optional
Validation Rules:
name,email,type,txt: required fieldstype: must be 0-4 (ContactType enum)
Request Data:
{
name: string; // Contact name (required)
email: string; // Contact email (required)
type: ContactType; // Contact type (0-4)
txt: string; // Message content (required)
}
Response Data: ContactDto
Error Responses:
400: Missing fields or invalid contact type500: Internal server error
Import/Export Functionality
Export Deck
Endpoint: GET /api/deck-import-export/export/{deckId}
Authentication: Required (deck owner only)
URL Parameters:
deckId: Deck UUID
Response: Binary .spr file download
Headers:
Content-Type:application/octet-streamContent-Disposition:attachment; filename="deckname.spr"
Import Deck
Endpoint: POST /api/deck-import-export/import
Authentication: Required
Request: Multipart form data
file: .spr or JSON file (max 10MB)
Response Data:
{
success: boolean;
message: string;
deckId: string; // Created deck ID
}
Admin Endpoints
All admin endpoints require authentication with admin role (UserState.ADMIN = 5).
User Management (Admin)
Get Users (Paginated) - RECOMMENDED
Endpoint: GET /api/admin/users/page/{from}/{to}
Query Parameters:
includeDeleted: boolean (default: false)
URL Parameters:
from: Start index (0-based)to: End index (inclusive, max page size: 100)
Response Data:
{
users: DetailUserDto[]; // Array of detailed user objects
pagination: {
from: number; // Start index
to: number; // End index
returned: number; // Actual returned count
totalCount: number; // Total user count
includeDeleted: boolean; // Include deleted flag
};
}
Get User by ID (Admin)
Endpoint: GET /api/admin/users/{userId}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: DetailUserDto or null
Search Users (Admin)
Endpoint: GET /api/admin/users/search/{searchTerm}
URL Parameters:
searchTerm: Search term (2-100 characters)
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Array of matching users
Update User (Admin)
Endpoint: PATCH /api/admin/users/{userId}
Request Data: Partial user fields to update
Response Data: Updated DetailUserDto
Deactivate User (Admin)
Endpoint: POST /api/admin/users/{userId}/deactivate
Response Data:
{
message: string;
user: DetailUserDto;
}
Delete User (Admin)
Endpoint: DELETE /api/admin/users/{userId}
Response Data:
{
message: string;
}
Deck Management (Admin)
Get Decks (Paginated, Admin)
Endpoint: GET /api/admin/decks/page/{from}/{to}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Same as regular deck pagination but unrestricted
Get Deck by ID (Admin)
Endpoint: GET /api/admin/decks/{id}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: DetailDeckDto
Search Decks (Admin)
Endpoint: GET /api/admin/decks/search/{searchTerm}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Array of matching decks
Hard Delete Deck (Admin)
Endpoint: DELETE /api/admin/decks/{id}/hard
Response Data:
{
success: boolean;
}
Organization Management (Admin)
Create Organization (Admin)
Endpoint: POST /api/admin/organizations
Request Data: Organization creation data
Response Data: Created organization object
Update Organization (Admin)
Endpoint: PATCH /api/admin/organizations/{id}
Request Data: Partial organization fields to update
Response Data: Updated organization object
Get Organizations (Paginated, Admin)
Endpoint: GET /api/admin/organizations/page/{from}/{to}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Organization pagination with unrestricted access
Get Organization by ID (Admin)
Endpoint: GET /api/admin/organizations/{id}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Organization object
Search Organizations (Admin)
Endpoint: GET /api/admin/organizations/search/{searchTerm}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Array of matching organizations
Soft Delete Organization (Admin)
Endpoint: DELETE /api/admin/organizations/{id}
Response Data:
{
success: boolean;
}
Hard Delete Organization (Admin)
Endpoint: DELETE /api/admin/organizations/{id}/hard
Response Data:
{
success: boolean;
}
Chat Management (Admin)
Get Chats (Paginated, Admin)
Endpoint: GET /api/admin/chats/page/{from}/{to}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data:
{
chats: DetailChatDto[];
pagination: {
from: number;
to: number;
returned: number;
totalCount: number;
includeDeleted: boolean;
};
}
Get Chat by ID (Admin)
Endpoint: GET /api/admin/chats/{id}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: DetailChatDto
Contact Management (Admin)
Get Contacts (Paginated, Admin)
Endpoint: GET /api/admin/contacts/page/{from}/{to}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Contact pagination with full access
Get Contact by ID (Admin)
Endpoint: GET /api/admin/contacts/{id}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: ContactDto
Search Contacts (Admin)
Endpoint: GET /api/admin/contacts/search/{searchTerm}
Query Parameters:
includeDeleted: boolean (default: false)
Response Data: Array of matching contacts
Respond to Contact (Admin)
Endpoint: PUT /api/admin/contacts/{id}/respond
Request Data:
{
adminResponse: string; // Admin response (required)
sendEmail?: boolean; // Send email to contact (optional)
language?: string; // Response language (optional)
}
Response Data:
{
success: boolean;
message: string;
contact: ContactDto;
emailSent: boolean;
emailError: string | null;
}
Resend Contact Email (Admin)
Endpoint: POST /api/admin/contacts/{id}/resend-email
Request Data:
{
language?: string; // Email language (optional)
}
Response Data:
{
success: boolean;
message: string;
}
Soft Delete Contact (Admin)
Endpoint: DELETE /api/admin/contacts/{id}
Response Data:
{
success: boolean;
}
Hard Delete Contact (Admin)
Endpoint: DELETE /api/admin/contacts/{id}/hard
Response Data:
{
success: boolean;
}
Import/Export (Admin)
Import Deck from JSON (Admin)
Endpoint: POST /api/admin/decks/import
Request: Multipart form data
file: JSON file (max 10MB)
Response Data:
{
success: boolean;
message: string;
deckId: string;
}
Export Deck as JSON (Admin)
Endpoint: GET /api/admin/decks/{deckId}/export
Response: JSON file download
Headers:
Content-Type:application/jsonContent-Disposition:attachment; filename="deckname.json"
Error Handling
Standard Error Response Format
{
error: string; // Error message
details?: string; // Additional details (development only)
timestamp?: string; // Error timestamp
}
HTTP Status Codes
200- Success201- Created204- No Content400- Bad Request (validation error)401- Unauthorized (authentication required)403- Forbidden (insufficient permissions)404- Not Found409- Conflict (duplicate data)500- Internal Server Error503- Service Unavailable
Common Error Scenarios
Authentication Errors:
// Missing or invalid token
{ error: "Authentication required" }
// Account state restrictions
{ error: "Please verify your email address" }
{ error: "Account has been deactivated" }
// Admin access required
{ error: "Admin access required" }
Validation Errors:
// Missing required fields
{ error: "Missing required fields: username, password" }
// Invalid field length
{ error: "Username must be between 3 and 50 characters" }
// Invalid parameters
{ error: "Invalid page parameters. \"from\" and \"to\" must be valid numbers with to >= from >= 0" }
// Invalid file type
{ error: "Only JSON and .spr files are allowed" }
Business Logic Errors:
// Ownership restrictions
{ error: "Access denied - you can only export your own decks" }
// Feature restrictions
{ error: "Premium subscription required to create groups" }
// Duplicate data
{ error: "Deck with this name already exists" }
{ error: "Username or email already exists" }
WebSocket Real-Time Communication
Connection & Authentication
Connect to WebSocket server with JWT authentication:
import io from 'socket.io-client';
// Option 1: JWT token in auth
const socket = io('http://localhost:3000', {
auth: {
token: 'your-jwt-token'
}
});
// Option 2: Cookie authentication
const socket = io('http://localhost:3000', {
withCredentials: true
});
Connection Events
// Connection successful
socket.on('connect', () => {
console.log('Connected to WebSocket server');
});
// Authentication failed
socket.on('connect_error', (error) => {
console.error('Connection failed:', error.message);
});
// Disconnected
socket.on('disconnect', (reason) => {
console.log('Disconnected:', reason);
});
// General errors
socket.on('error', (error: { message: string }) => {
console.error('WebSocket error:', error.message);
});
Chat Management Events
Initial Chat List:
// Automatically sent on connection
socket.on('chats:list', (chats: Array<{
id: string;
type: ChatType;
name: string | null;
users: string[];
lastActivity: Date | null;
isArchived: boolean;
}>) => {
// Update chat list in UI
});
Join/Leave Chat:
// Join a chat room
socket.emit('chat:join', { chatId: 'chat-uuid' });
// Confirmation of joining
socket.on('chat:joined', (data: {
chatId: string;
messages: Message[];
users: string[];
}) => {
// Load chat messages
});
// Leave a chat room
socket.emit('chat:leave', { chatId: 'chat-uuid' });
// Confirmation of leaving
socket.on('chat:left', (data: { chatId: string }) => {
// Update UI
});
Real-time Messaging
Send/Receive Messages:
// Send message
socket.emit('message:send', {
chatId: 'chat-uuid',
message: 'Hello everyone!'
});
// Receive message
socket.on('message:received', (data: {
chatId: string;
message: Message;
senderInfo?: {
username: string;
fname: string;
lname: string;
};
}) => {
// Add message to chat UI
});
// Message sent confirmation
socket.on('message:sent', (data: {
chatId: string;
messageId: string;
timestamp: Date;
}) => {
// Update UI
});
Rate Limiting: 100 messages per user per minute
Chat Creation Events
Create Group Chat (Premium Only):
// Create group
socket.emit('group:create', {
name: 'Study Group',
userIds: ['user-uuid-1', 'user-uuid-2']
});
// Group created
socket.on('group:created', (data: {
chat: {
id: string;
type: 'group';
name: string;
users: string[];
createdBy: string;
};
}) => {
// Add to chat list
});
// Creation failed
socket.on('group:creation:failed', (data: {
error: string;
}) => {
// Show error
});
Create Direct Chat:
// Create or get direct chat
socket.emit('chat:direct', {
targetUserId: 'user-uuid'
});
// Chat created
socket.on('chat:direct:created', (data: {
chat: {
id: string;
type: 'direct';
users: string[];
};
}) => {
// Add to list
});
// Chat already exists
socket.on('chat:direct:exists', (data: {
chatId: string;
}) => {
// Navigate to existing chat
});
Create Game Chat:
// Create game chat
socket.emit('game:chat:create', {
gameId: 'game-uuid',
gameName: 'Quiz Game #123',
playerIds: ['player-uuid-1', 'player-uuid-2']
});
// Game chat created
socket.on('game:chat:created', (data: {
chat: {
id: string;
type: 'game';
name: string;
gameId: string;
users: string[];
};
}) => {
// Show game chat
});
Chat History Management
Get Chat History:
// Request full history
socket.emit('chat:history', { chatId: 'chat-uuid' });
// Receive active chat history
socket.on('chat:history', (data: {
chatId: string;
messages: Message[];
users: string[];
type: ChatType;
name: string | null;
}) => {
// Display full history
});
// Receive archived chat history
socket.on('chat:history:archived', (data: {
chatId: string;
messages: Message[];
isGameChat: boolean;
archiveDate: Date;
}) => {
// Display as read-only
});
Message Retention Rules
- All chats: Messages older than 2 weeks are deleted
- Direct & Game chats: Max 10 messages per user (FIFO)
- Group chats: Time limit only (no per-user limit)
- Archive: Inactive chats (30 minutes) are archived
- Cleanup: Archived messages cleaned after 4 weeks
Complete Implementation Example
// hooks/useWebSocket.ts
import { useEffect, useRef, useState } from 'react';
import io, { Socket } from 'socket.io-client';
export const useWebSocket = (token: string | null) => {
const socketRef = useRef<Socket | null>(null);
const [isConnected, setIsConnected] = useState(false);
const [chats, setChats] = useState<any[]>([]);
useEffect(() => {
if (!token) return;
socketRef.current = io('http://localhost:3000', {
auth: { token },
withCredentials: true
});
const socket = socketRef.current;
socket.on('connect', () => setIsConnected(true));
socket.on('connect_error', () => setIsConnected(false));
socket.on('disconnect', () => setIsConnected(false));
socket.on('chats:list', (chatList) => {
setChats(chatList);
});
socket.on('message:received', (data) => {
setChats(prev => prev.map(chat =>
chat.id === data.chatId
? { ...chat, messages: [...chat.messages, data.message] }
: chat
));
});
return () => {
socket.disconnect();
};
}, [token]);
const sendMessage = (chatId: string, message: string) => {
socketRef.current?.emit('message:send', { chatId, message });
};
const joinChat = (chatId: string) => {
socketRef.current?.emit('chat:join', { chatId });
};
const createDirectChat = (targetUserId: string) => {
socketRef.current?.emit('chat:direct', { targetUserId });
};
const createGroup = (name: string, userIds: string[]) => {
socketRef.current?.emit('group:create', { name, userIds });
};
return {
socket: socketRef.current,
isConnected,
chats,
sendMessage,
joinChat,
createDirectChat,
createGroup
};
};
This documentation provides a complete reference for all 50+ endpoints available in the SerpentRace backend API, with accurate data structures, validation rules, and implementation examples derived directly from the TypeScript source code.