114 lines
6.4 KiB
Markdown
114 lines
6.4 KiB
Markdown
# CLAUDE.md
|
|
|
|
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
|
|
|
|
## Project Overview
|
|
|
|
FurryPlace is an unofficial open-source backend for wplace (a collaborative pixel art canvas), built with TypeScript, tinyhttp, Prisma, and MySQL. The system manages user authentication, pixel painting with charge-based rate limiting, alliances, leaderboards, and moderation features.
|
|
|
|
## Development Commands
|
|
|
|
### Essential Commands
|
|
- `pnpm dev` - Run development server with hot reload (watches src/ directory)
|
|
- `pnpm build` - Compile TypeScript to dist/
|
|
- `pnpm start` - Run production build from dist/
|
|
- `pnpm test` - Run tests once
|
|
- `pnpm test:watch` - Run tests in watch mode
|
|
- `pnpm lint` - Check for linting issues
|
|
- `pnpm lint:fix` - Auto-fix linting issues
|
|
|
|
### Database Commands
|
|
- `pnpm db:push` - Push schema changes to database and regenerate Prisma client
|
|
- `pnpm db:generate` - Regenerate Prisma client only
|
|
- `pnpm db:migrate` - Create and run a new migration
|
|
- `pnpm seed` - Seed database with initial data
|
|
|
|
### Requirements
|
|
- Node.js >= 24
|
|
- pnpm >= 10
|
|
- MySQL/MariaDB
|
|
|
|
## Architecture
|
|
|
|
### Backend Structure
|
|
|
|
**Entry Point**: [src/index.ts](src/index.ts) - Sets up tinyhttp app with middleware (CORS, cookie parser, JSON body parsing, logging) and registers all route modules.
|
|
|
|
**Authentication Flow**: JWT tokens stored in `j` cookie → validated by [src/middleware/auth.ts](src/middleware/auth.ts) → checks session validity in database → attaches `req.user` with `{ id, sessionId }`
|
|
|
|
**Database**: Prisma ORM with MySQL. Global instance exported from [src/config/database.ts](src/config/database.ts) and injected into request via middleware.
|
|
|
|
**Route Organization**: Each feature module exports a function that registers routes on the tinyhttp app:
|
|
- [src/routes/auth.ts](src/routes/auth.ts) - Registration, login, logout
|
|
- [src/routes/pixel.ts](src/routes/pixel.ts) - Pixel painting, tile generation, pixel info
|
|
- [src/routes/alliance.ts](src/routes/alliance.ts) - Alliance CRUD, invites, bans, leaderboards
|
|
- [src/routes/me.ts](src/routes/me.ts) - User profile, favorite locations, settings
|
|
- [src/routes/admin.ts](src/routes/admin.ts) - User management, bans, timeouts, tickets
|
|
- [src/routes/moderator.ts](src/routes/moderator.ts) - Moderation actions
|
|
- [src/routes/leaderboard.ts](src/routes/leaderboard.ts) - Global leaderboards
|
|
- [src/routes/store.ts](src/routes/store.ts) - Purchase colors and flags
|
|
|
|
**Service Layer**: Business logic isolated in service classes:
|
|
- [src/services/pixel.ts](src/services/pixel.ts) - `PixelService` handles pixel painting with charge validation, color unlocking checks, tile image generation using @napi-rs/canvas, and level calculation
|
|
- [src/services/alliance.ts](src/services/alliance.ts) - `AllianceService` handles alliance creation, member management, bans
|
|
- [src/services/user.ts](src/services/user.ts) - `UserService` handles user profile updates, favorites
|
|
|
|
**Core Systems**:
|
|
|
|
1. **Charge System** ([src/utils/charges.ts](src/utils/charges.ts)): Rate-limiting mechanism where users have `maxCharges` (default 20) that regenerate every `chargesCooldownMs` (default 30s). Painting consumes charges. Function `calculateChargeRecharge()` computes current charge based on time elapsed.
|
|
|
|
2. **Bitmap System** ([src/utils/bitmap.ts](src/utils/bitmap.ts)): `WplaceBitMap` class stores boolean flags as packed bytes for efficient storage (used for unlocked colors, flags). Stored in database as Bytes, converted to base64 for API responses.
|
|
|
|
3. **Color Palette** ([src/utils/colors.ts](src/utils/colors.ts)): Defines available colors with RGB values and whether they're paid. `checkColorUnlocked()` validates if user has purchased a color by checking bitmap.
|
|
|
|
4. **Tile System**: Canvas divided into 1000x1000 tiles. Each pixel has coordinates `(tileX, tileY, x, y)`. Tile images dynamically generated on-demand from pixel data.
|
|
|
|
5. **Regions** ([src/config/regions.ts](src/config/regions.ts)): Maps coordinates to geographic regions/countries. Users get 10% charge discount when painting in their equipped flag's region. **Currently returns placeholder data - implementation needed.**
|
|
|
|
### Database Schema
|
|
|
|
Key models in [prisma/schema.prisma](prisma/schema.prisma):
|
|
|
|
- **User**: Core user data, charge state, pixels painted, level, alliance membership, equipped flag, unlocked colors bitmap
|
|
- **Pixel**: Individual pixel with coordinates (tileX, tileY, x, y), colorId, paintedBy userId, timestamp
|
|
- **Tile**: Metadata for 1000x1000 tile regions, has many Pixels
|
|
- **Alliance**: Groups with members, bans, invites, HQ coordinates, total pixels painted
|
|
- **Session**: JWT session tracking with expiration
|
|
- **Ticket**: Moderation reports with evidence
|
|
- **UserNote**: Moderator notes on users
|
|
|
|
### Frontend
|
|
|
|
Pre-built SvelteKit frontend in [frontend/](frontend/) directory (served as static files, not part of development workflow). Backend serves 404.html for unmatched routes.
|
|
|
|
## Key Implementation Patterns
|
|
|
|
1. **Route Pattern**: Routes validate input → call service method → return JSON or handle service errors via `handleServiceError()`
|
|
|
|
2. **Service Pattern**: Services receive Prisma client in constructor, contain business logic, throw descriptive errors that are caught by error handler middleware
|
|
|
|
3. **Bulk Pixel Insert**: Painting uses raw SQL `INSERT ... ON DUPLICATE KEY UPDATE` for performance when updating multiple pixels
|
|
|
|
4. **Level Calculation**: `Math.floor(Math.sqrt(pixelsPainted / 100)) + 1`
|
|
|
|
5. **Validation**: Separate validator functions in [src/validators/](src/validators/) for common input patterns (seasons, coordinates, pagination)
|
|
|
|
6. **Error Responses**: Standardized via `createErrorResponse()` and HTTP_STATUS constants in [src/utils/response.ts](src/utils/response.ts)
|
|
|
|
## Environment Setup
|
|
|
|
Copy `.env.example` to `.env` and configure:
|
|
- `DATABASE_URL` - MySQL connection string (format: `mysql://user:password@host/database`)
|
|
- `JWT_SECRET` - Secret key for JWT signing
|
|
- `PORT` - Server port (default 3000)
|
|
|
|
## Important Notes
|
|
|
|
- The project is a work-in-progress with incomplete features (see README.md warnings)
|
|
- Region lookup system is stubbed and returns placeholder data - needs implementation
|
|
- Authentication uses JWT cookies named `j`
|
|
- All API responses use JSON format
|
|
- The backend is designed to work with the wplace.live frontend protocol
|
|
- Production deployment requires SSL/HTTPS (enforced by design)
|
|
- Use `pnpm` as package manager (not npm)
|