48 lines
2 KiB
Markdown
48 lines
2 KiB
Markdown
|
|
# Architecture
|
||
|
|
|
||
|
|
## Server
|
||
|
|
|
||
|
|
Dual-server setup:
|
||
|
|
|
||
|
|
- **server.ts** — HTTP server entry point, initializes Socket.IO
|
||
|
|
- **server/app.ts** — Express app with React Router SSR handler and database context
|
||
|
|
- **server/socket.ts** — Socket.IO server for real-time draft updates
|
||
|
|
- **server/timer.ts** — Runs every second via `setInterval` to advance draft timers. Uses a dedicated DB connection. **Must be started** for draft functionality to work.
|
||
|
|
|
||
|
|
## Database Layer
|
||
|
|
|
||
|
|
- **Schema**: `database/schema.ts`
|
||
|
|
- **Context**: `database/context.ts` — DB connection injected via `AsyncLocalStorage`
|
||
|
|
- **Models**: `app/models/` — all DB queries live here, organized by domain (e.g. `league.ts`, `season.ts`, `draft-pick.ts`)
|
||
|
|
|
||
|
|
Always query through the model layer — never write Drizzle queries directly in route files.
|
||
|
|
|
||
|
|
## Frontend
|
||
|
|
|
||
|
|
- **Routes config**: `app/routes.ts` — all routes must be explicitly registered here (React Router 7 does not auto-discover files)
|
||
|
|
- **Route files**: `app/routes/` — file naming uses `.` as path separator; `$param` for dynamic segments; `_index.tsx` for index routes
|
||
|
|
- **Components**: `app/components/` — UI primitives in `app/components/ui/` (ShadCN)
|
||
|
|
- **Hooks**: `app/hooks/` — custom React hooks
|
||
|
|
- **Lib**: `app/lib/` — pure utility functions
|
||
|
|
|
||
|
|
## Real-time (Socket.IO)
|
||
|
|
|
||
|
|
Clients join a room per season. Key events:
|
||
|
|
|
||
|
|
| Event | Direction | Trigger |
|
||
|
|
|---|---|---|
|
||
|
|
| `join-draft` | client → server | on draft page load |
|
||
|
|
| `timer-update` | server → client | every second during active draft |
|
||
|
|
| `pick-made` | server → client | participant drafted |
|
||
|
|
| `autodraft-updated` | server → client | team enables/disables autodraft |
|
||
|
|
| `team-connected` / `team-disconnected` | server → client | presence |
|
||
|
|
|
||
|
|
Server emits via `getSocketIO()` from `server/socket.ts`. Clients consume via `useDraftSocket()` hook at `app/hooks/useDraftSocket.ts`.
|
||
|
|
|
||
|
|
### Adding a Socket Event
|
||
|
|
|
||
|
|
1. Define types in `server/socket.d.ts`
|
||
|
|
2. Add handler in `server/socket.ts`
|
||
|
|
3. Emit from server: `getSocketIO().to(room).emit(...)`
|
||
|
|
4. Listen in client component or hook
|