1// src/server.ts - Basic Implementation
2import { createApp, z, validate, SocketIOAdapter } from '@morojs/moro';
3
4// Create app with WebSocket support
5const app = await createApp({
6 server: { port: 3000, host: '0.0.0.0' },
7 websocket: { enabled: true, adapter: new SocketIOAdapter() },
8});
9
10// Simple in-memory storage for demo
11const users: any[] = [];
12const rooms: any[] = [
13 { id: 'general', name: 'General Chat', description: 'Main chat room' },
14 { id: 'random', name: 'Random', description: 'Random discussions' }
15];
16const messages: any[] = [];
17
18// Basic welcome endpoint
19app.get('/', (req, res) => {
20 return {
21 message: 'Real-time Chat API - Simple Demo',
22 status: 'running',
23 version: '1.0.0',
24 note: 'This is a simplified demo without database dependencies',
25 endpoints: [
26 'GET / - This message',
27 'GET /health - Health check',
28 'GET /rooms - Get available rooms',
29 'GET /test - WebSocket test client (open in browser)',
30 'POST /auth/register - Simple user registration (no persistence)',
31 'POST /auth/login - Simple user login (no persistence)',
32 'WebSocket /chat - Real-time chat functionality'
33 ],
34 websocket: {
35 url: 'ws://localhost:3000/chat',
36 events: ['join', 'message', 'leave']
37 }
38 };
39});
40
41// Simple authentication endpoints (no database)
42app.post('/auth/register',
43 validate({
44 body: z.object({
45 username: z.string().min(3).max(20),
46 email: z.string().email(),
47 password: z.string().min(6)
48 })
49 }, async (req, res) => {
50 // Check if user already exists
51 const existingUser = users.find(u => u.email === req.body.email || u.username === req.body.username);
52 if (existingUser) {
53 res.status(400);
54 return { error: 'User already exists with this email or username' };
55 }
56
57 // Create user (in memory)
58 const user = {
59 id: Date.now().toString(),
60 username: req.body.username,
61 email: req.body.email,
62 createdAt: new Date().toISOString()
63 };
64
65 users.push(user);
66
67 return {
68 user,
69 token: `demo-token-${user.id}`,
70 message: 'User registered successfully (demo mode - no persistence)'
71 };
72 })
73);
74
75// Basic WebSocket handler
76app.websocket('/chat', {
77 connect: (socket: any) => {
78 console.log(`🔗 WebSocket client connected: ${socket.id}`);
79 },
80
81 disconnect: (socket: any) => {
82 console.log(`❌ WebSocket client disconnected: ${socket.id}`);
83 },
84
85 join: (socket: any, data: any) => {
86 console.log(`📝 Join event received:`, data);
87 const roomId = data.roomId || 'general';
88 const username = data.username || 'Anonymous';
89
90 console.log(`👥 ${username} joined room ${roomId}`);
91
92 return {
93 success: true,
94 message: `Joined room ${roomId}`,
95 room: rooms.find(r => r.id === roomId) || { id: roomId, name: roomId }
96 };
97 },
98
99 message: (socket: any, data: any) => {
100 console.log(`💬 Message event received:`, data);
101 const roomId = data.roomId || 'general';
102 const username = data.username || 'Anonymous';
103
104 const message = {
105 id: Date.now(),
106 content: data.message,
107 sender: username,
108 roomId,
109 timestamp: new Date().toISOString()
110 };
111
112 // Store message in memory
113 messages.push(message);
114 console.log(`📨 Broadcasting message to room ${roomId}:`, message);
115
116 return { success: true, message: 'Message sent' };
117 }
118});
119
120// REST API endpoints
121app.get('/rooms', (req, res) => {
122 return {
123 rooms,
124 message: 'Available chat rooms'
125 };
126});
127
128app.get('/rooms/:roomId/messages', (req, res) => {
129 const roomMessages = messages
130 .filter(m => m.roomId === req.params.roomId)
131 .slice(-50); // Last 50 messages
132
133 return {
134 messages: roomMessages,
135 roomId: req.params.roomId,
136 count: roomMessages.length
137 };
138});
139
140app.listen(() => {
141 const config = app.getConfig();
142 console.log(`Real-time Chat Server running on port ${config.server.port}`);
143 console.log(`WebSocket endpoint: ws://localhost:${config.server.port}/chat`);
144 console.log(`Test client: http://localhost:${config.server.port}/test`);
145});