Files
FrenoCorp/server/websocket/index.ts
Michael Freno ef1b15c9ea FRE-600: Implement Phase 1 WebSocket + Yjs CRDT foundation
- Create TypeScript and Vite configuration for SolidJS
- Implement Yjs document structure for screenplay collaboration
- Build WebSocket connection manager with exponential backoff reconnection
- Create CRDT document manager with undo/redo support
- Set up WebSocket sync server with JWT authentication
- Add SolidJS reactive bindings for Yjs shared types
- Build collaborative editor component
- Write unit tests for CRDT operations
- Document implementation in analysis/fre600_websocket_foundation.md

Architecture: Yjs chosen over Automerge for better ecosystem and
Tauri compatibility. WebSocket for sync, WebRTC for video.

Co-Authored-By: Paperclip <noreply@paperclip.ing>
2026-04-22 23:08:27 -04:00

77 lines
2.0 KiB
TypeScript

/**
* WebSocket Server Entry Point
* Starts the Yjs sync server with JWT authentication
*/
import { createWebSocketServer } from './websocket/server';
interface ServerConfig {
port: number;
jwtSecret: string;
enableAuth: boolean;
}
/**
* Start the WebSocket sync server
*/
export async function startServer(config: ServerConfig) {
const { port, jwtSecret, enableAuth } = config;
// Auth middleware for JWT token validation
const authMiddleware = async (token: string) => {
if (!enableAuth) {
return { userId: 'anonymous', projectId: 'default' };
}
// Simple JWT verification (in production, use jsonwebtoken library)
try {
const decoded = JSON.parse(Buffer.from(token.split('.')[1], 'base64').toString());
return {
userId: decoded.userId,
projectId: decoded.projectId,
};
} catch (error) {
throw new Error('Invalid JWT token');
}
};
const server = createWebSocketServer(port, {
authMiddleware: enableAuth ? authMiddleware : undefined,
});
server.on('listening', () => {
console.log(`WebSocket sync server listening on port ${port}`);
console.log(`Authentication ${enableAuth ? 'enabled' : 'disabled'}`);
});
server.on('error', (error) => {
console.error('WebSocket server error:', error);
});
// Graceful shutdown
process.on('SIGINT', () => {
console.log('\nShutting down WebSocket server...');
server.clients.forEach((client) => client.close());
server.close(() => {
console.log('WebSocket server closed');
process.exit(0);
});
});
return server;
}
// If run directly, start the server
if (require.main === module) {
const config: ServerConfig = {
port: parseInt(process.env.WS_PORT || '8080', 10),
jwtSecret: process.env.JWT_SECRET || 'dev-secret',
enableAuth: process.env.ENABLE_AUTH === 'true',
};
startServer(config).catch((error) => {
console.error('Failed to start server:', error);
process.exit(1);
});
}