- 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>
77 lines
2.0 KiB
TypeScript
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);
|
|
});
|
|
}
|