Files
chad/server/CLAUDE.md
2026-04-12 22:35:47 +06:00

74 lines
3.7 KiB
Markdown

# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## Project Overview
Chad is a real-time voice/video chat server (think Discord-like) built with Fastify, Socket.IO, and mediasoup for WebRTC media handling. It uses SQLite via Prisma ORM and Lucia for session-based authentication. The client is a Tauri desktop app (separate repo).
## Commands
- **Start server:** `yarn start` (runs `ts-node --transpile-only server.ts`)
- **Deploy DB (migrate + seed + generate):** `yarn db:deploy`
- **Generate Prisma client after schema changes:** `npx prisma generate`
- **Create a migration:** `npx prisma migrate dev --name <name>`
- **Lint:** `npx eslint .`
- **Package manager:** Yarn 4 (corepack). Do not use npm.
## Architecture
### Entry Point & Plugin System
`server.ts` creates a Fastify instance and uses `@fastify/autoload` to auto-register everything in `plugins/` and `routes/` (prefixed under `/chad`). Plugins use `fastify-plugin` (`fp`) with named dependencies to control load order.
### Plugin Load Order (dependency chain)
1. `plugins/auth.ts` — Adds `req.user` / `req.session` via Lucia cookie validation on every request (preHandler hook)
2. `plugins/mediasoup-worker.ts` — Creates a mediasoup Worker, decorates `fastify.mediasoupWorker`
3. `plugins/mediasoup-router.ts` — Creates a mediasoup Router (depends on worker), decorates `fastify.mediasoupRouter`. Configures supported audio/video codecs (Opus, VP8, VP9, H.264, AV1)
4. `plugins/socket.ts` — Creates Socket.IO server at `/chad/ws` (depends on worker + router), decorates `fastify.io`. Registers socket handlers on `fastify.ready()`
### Socket Handlers (`socket/`)
- `socket/webrtc.ts` — Main WebRTC signaling: join/leave, transport creation, producer/consumer lifecycle, audio level observation, active speaker detection
- `socket/channel.ts` — Channel-based socket logic (in development on `channels` branch)
Both handlers authenticate by looking up `socket.handshake.auth.userId` against the DB.
### REST Routes (`routes/`)
All routes are prefixed with `/chad` via autoload config.
- `routes/auth.ts``/register`, `/login`, `/logout`, `/me`
- `routes/user.ts``/preferences` (GET/PATCH), `/profile` (PATCH). Profile changes broadcast to connected socket peers via `clientChanged` event.
### Type System (`types/socket.ts`)
Fully typed Socket.IO events: `ClientToServerEvents`, `ServerToClientEvents`, `SocketData`. The `SomeSocket` union type covers both live `Socket` and `RemoteSocket` (from `fetchSockets()`).
### Database
- SQLite with Prisma 7 + `@prisma/adapter-better-sqlite3`
- Schema at `prisma/schema.prisma`, generated client at `prisma/generated/client/`
- Models: `User`, `Session` (Lucia), `UserPreferences`, `Channel`
- Seed creates a persistent "Default" channel
- Config in `prisma.config.ts` using `dotenv` for `DATABASE_URL`
### Key Patterns
- Request validation uses Zod schemas defined inline in route handlers
- DTOs in `dto/` define Prisma select objects with `satisfies Prisma.*Select` for type-safe projections
- `utils/socket-to-client.ts` maps socket data to the `ChadClient` interface sent to clients
- ESLint uses `@antfu/eslint-config` (flat config) with `no-console` and `n/prefer-global/process` disabled
### Environment Variables
- `PORT` — Server port (default: 4000, Docker: 80)
- `DATABASE_URL` — SQLite path (e.g., `file:../data/database.db`)
- `ANNOUNCED_ADDRESS` — Public IP for WebRTC ICE candidates (default: `127.0.0.1`)
- `CORS_ORIGIN` — Socket.IO CORS origin (default: `*`)
### Docker
`Dockerfile` requires python3 and build-essential for mediasoup native compilation. Runs `yarn db:deploy && yarn start`.