Clean rules database and add documentation
- Remove OCR noise, credits, and duplicates from rules-database.json (288→255 rules) - Add clean_rules.py script for rule cleanup - Add CLAUDE.md, docs/, and update README with documentation links Co-Authored-By: Claude Opus 4.7 <[email protected]>
This commit is contained in:
@@ -0,0 +1,439 @@
|
||||
# Developer Guide
|
||||
|
||||
## Project Structure
|
||||
|
||||
```
|
||||
dwroller/
|
||||
├── backend/
|
||||
│ ├── src/
|
||||
│ │ ├── routes/ # API routes
|
||||
│ │ ├── models/ # Data models
|
||||
│ │ ├── controllers/ # Route controllers
|
||||
│ │ ├── middleware/ # Auth, validation
|
||||
│ │ └── utils/ # Helper functions
|
||||
│ ├── server.js # Entry point
|
||||
│ └── package.json
|
||||
├── frontend/
|
||||
│ ├── src/
|
||||
│ │ ├── components/ # React components
|
||||
│ │ ├── pages/ # Route pages
|
||||
│ │ ├── hooks/ # Custom hooks
|
||||
│ │ └── store/ # State management
|
||||
│ ├── public/ # Static assets
|
||||
│ ├── package.json
|
||||
│ └── vite.config.js
|
||||
├── data/ # Static data files
|
||||
├── database/ # Database files
|
||||
└── docs/ # Documentation
|
||||
```
|
||||
|
||||
## Development Setup
|
||||
|
||||
### Backend
|
||||
|
||||
```bash
|
||||
cd backend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The backend starts on port 5000.
|
||||
|
||||
### Frontend
|
||||
|
||||
```bash
|
||||
cd frontend
|
||||
npm install
|
||||
npm run dev
|
||||
```
|
||||
|
||||
The frontend starts on port 3000.
|
||||
|
||||
## Code Style
|
||||
|
||||
### JavaScript/TypeScript
|
||||
|
||||
- Use TypeScript for new code
|
||||
- Follow Airbnb JavaScript style guide
|
||||
- Maximum 100 character line length
|
||||
- Use ESLint for linting
|
||||
|
||||
```typescript
|
||||
// Example code style
|
||||
interface Player {
|
||||
id: number;
|
||||
name: string;
|
||||
xp: number;
|
||||
rp: number;
|
||||
}
|
||||
|
||||
export class PlayerService {
|
||||
async getPlayer(id: number): Promise<Player> {
|
||||
const player = await this.repository.findById(id);
|
||||
return this.transform(player);
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### React
|
||||
|
||||
- Functional components with hooks
|
||||
- Use TypeScript for props
|
||||
- Follow React best practices
|
||||
- Use Context for global state
|
||||
|
||||
```typescript
|
||||
// Example React component
|
||||
interface ShopItemProps {
|
||||
item: ShopItem;
|
||||
onPurchase: (itemId: number) => void;
|
||||
}
|
||||
|
||||
const ShopItem: React.FC<ShopItemProps> = ({ item, onPurchase }) => {
|
||||
return (
|
||||
<div className="shop-item">
|
||||
<h3>{item.name}</h3>
|
||||
<p>Cost: {item.cost} RP</p>
|
||||
<button onClick={() => onPurchase(item.id)}>
|
||||
Purchase
|
||||
</button>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Database
|
||||
|
||||
### Schema
|
||||
|
||||
The database uses SQLite by default. The schema is created automatically on first run.
|
||||
|
||||
Main tables:
|
||||
- `players` - Player accounts
|
||||
- `items` - Shop inventory
|
||||
- `inventory` - Player item ownership
|
||||
- `sessions` - Game session tracking
|
||||
- `webhooks` - Webhook configurations
|
||||
|
||||
### Migrations
|
||||
|
||||
Migrations are stored in `backend/migrations/`.
|
||||
|
||||
```bash
|
||||
# Run migrations
|
||||
npm run migrate
|
||||
|
||||
# Create new migration
|
||||
npx knex migrate:make create_new_table
|
||||
```
|
||||
|
||||
## API Development
|
||||
|
||||
### Creating a New Endpoint
|
||||
|
||||
```bash
|
||||
backend/src/routes/new-endpoints.ts
|
||||
```
|
||||
|
||||
```typescript
|
||||
import express, { Request, Response } from 'express';
|
||||
|
||||
const router = express.Router();
|
||||
|
||||
// GET /new-endpoint
|
||||
router.get('/', async (req: Request, res: Response) => {
|
||||
const data = await getNewData();
|
||||
res.json({ success: true, data });
|
||||
});
|
||||
|
||||
export default router;
|
||||
```
|
||||
|
||||
Add to `server.js`:
|
||||
|
||||
```typescript
|
||||
import newEndpoints from './src/routes/new-endpoints';
|
||||
|
||||
app.use('/api/new', newEndpoints);
|
||||
```
|
||||
|
||||
### Adding Authentication
|
||||
|
||||
```typescript
|
||||
import { requireAuth } from '../middleware/auth';
|
||||
|
||||
router.get(protectedRoute, requireAuth, async (req, res) => {
|
||||
// Protected route logic
|
||||
});
|
||||
```
|
||||
|
||||
## Frontend Development
|
||||
|
||||
### Creating a New Component
|
||||
|
||||
```bash
|
||||
frontend/src/components/NewComponent.tsx
|
||||
```
|
||||
|
||||
```typescript
|
||||
import React from 'react';
|
||||
|
||||
interface NewComponentProps {
|
||||
data: any;
|
||||
onAction: (action: string) => void;
|
||||
}
|
||||
|
||||
export const NewComponent: React.FC<NewComponentProps> = ({
|
||||
data,
|
||||
onAction,
|
||||
}) => {
|
||||
const handleClick = () => {
|
||||
onAction('click');
|
||||
};
|
||||
|
||||
return <div className="new-component">{data.title}</div>;
|
||||
};
|
||||
```
|
||||
|
||||
### State Management
|
||||
|
||||
Use React Context for global state:
|
||||
|
||||
```typescript
|
||||
// frontend/src/store/PlayerContext.tsx
|
||||
import React, { createContext, useContext, useState } from 'react';
|
||||
|
||||
interface PlayerState {
|
||||
players: Player[];
|
||||
addPlayer: (player: Player) => void;
|
||||
}
|
||||
|
||||
const PlayerContext = createContext<PlayerState | undefined>(undefined);
|
||||
|
||||
export const PlayerProvider: React.FC<{ children: React.ReactNode }> = ({
|
||||
children,
|
||||
}) => {
|
||||
const [players, setPlayers] = useState<Player[]>([]);
|
||||
|
||||
const addPlayer = (player: Player) => {
|
||||
setPlayers((prev) => [...prev, player]);
|
||||
};
|
||||
|
||||
return (
|
||||
<PlayerContext.Provider value={{ players, addPlayer }}>
|
||||
{children}
|
||||
</PlayerContext.Provider>
|
||||
);
|
||||
};
|
||||
```
|
||||
|
||||
## Testing
|
||||
|
||||
### Backend Tests
|
||||
|
||||
```bash
|
||||
backend/src/routes/__tests__/new-endpoints.test.ts
|
||||
```
|
||||
|
||||
```typescript
|
||||
import request from 'supertest';
|
||||
import app from '../../../server';
|
||||
|
||||
describe('New Endpoint', () => {
|
||||
it('should return 200 for GET', async () => {
|
||||
const res = await request(app).get('/new-endpoint');
|
||||
|
||||
expect(res.statusCode).toBe(200);
|
||||
expect(res.body.success).toBe(true);
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Run tests:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
### Frontend Tests
|
||||
|
||||
```bash
|
||||
frontend/src/components/__tests__/NewComponent.test.tsx
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { render, screen } from '@testing-library/react';
|
||||
import NewComponent from '../NewComponent';
|
||||
|
||||
describe('NewComponent', () => {
|
||||
it('renders the title', () => {
|
||||
render(<NewComponent data={{ title: 'Test' }} />);
|
||||
|
||||
expect(screen.getByText('Test')).toBeInTheDocument();
|
||||
});
|
||||
});
|
||||
```
|
||||
|
||||
Run tests:
|
||||
|
||||
```bash
|
||||
npm test
|
||||
```
|
||||
|
||||
## Debugging
|
||||
|
||||
### Backend Debugging
|
||||
|
||||
```bash
|
||||
# Enable verbose logging
|
||||
NODE_ENV=development npm run server
|
||||
|
||||
# View logs
|
||||
tail -f backend.log
|
||||
```
|
||||
|
||||
### Frontend Debugging
|
||||
|
||||
```bash
|
||||
# Open DevTools
|
||||
npm run dev
|
||||
|
||||
# Check browser console
|
||||
# Network tab for API calls
|
||||
```
|
||||
|
||||
## Deployment
|
||||
|
||||
### Build
|
||||
|
||||
```bash
|
||||
# Build frontend
|
||||
npm run build
|
||||
|
||||
# Build backend
|
||||
cd backend
|
||||
npm run build
|
||||
```
|
||||
|
||||
### PM2 Setup
|
||||
|
||||
```bash
|
||||
# Start with PM2
|
||||
npm run pm2:start
|
||||
|
||||
# View logs
|
||||
pm2 logs
|
||||
|
||||
# Stop
|
||||
npm run pm2:stop
|
||||
```
|
||||
|
||||
### Production Environment Variables
|
||||
|
||||
```bash
|
||||
# Create production env
|
||||
cp .env.example .env.production
|
||||
|
||||
# Set required variables:
|
||||
# - NODE_ENV=production
|
||||
# - SESSION_SECRET
|
||||
# - X_GM_SECRET
|
||||
# - PORT
|
||||
```
|
||||
|
||||
## Performance
|
||||
|
||||
### Optimization Tips
|
||||
|
||||
1. **Database**: Use indexes for frequent queries
|
||||
2. **Frontend**: Enable code splitting
|
||||
3. **API**: Implement caching for static data
|
||||
4. **Images**: Use lazy loading
|
||||
|
||||
### Caching
|
||||
|
||||
```typescript
|
||||
// Example: Cache shop data
|
||||
const CACHE_DURATION = 5 * 60 * 1000; // 5 minutes
|
||||
|
||||
async function getShop() {
|
||||
const cached = getFromCache('shop');
|
||||
if (cached) return cached;
|
||||
|
||||
const shop = await db.items.findAll();
|
||||
setCache('shop', shop, CACHE_DURATION);
|
||||
return shop;
|
||||
}
|
||||
```
|
||||
|
||||
## Security
|
||||
|
||||
### Authentication
|
||||
|
||||
All API endpoints use session-based authentication. Implement proper session management:
|
||||
|
||||
```typescript
|
||||
// Session middleware
|
||||
import { verifyToken } from '../utils/auth';
|
||||
|
||||
export const requireAuth = async (req: Request, res: Response, next: NextFunction) => {
|
||||
const session = req.headers['cookie'];
|
||||
|
||||
if (!session) {
|
||||
return res.status(401).json({ error: 'Unauthorized' });
|
||||
}
|
||||
|
||||
try {
|
||||
req.user = await verifyToken(session);
|
||||
next();
|
||||
} catch (error) {
|
||||
return res.status(401).json({ error: 'Invalid session' });
|
||||
}
|
||||
};
|
||||
```
|
||||
|
||||
### API Security
|
||||
|
||||
1. Use HTTPS in production
|
||||
2. Rate limit API requests
|
||||
3. Validate all inputs
|
||||
4. Use prepared statements for SQL
|
||||
5. Never expose sensitive data
|
||||
|
||||
## Contributing
|
||||
|
||||
### Pull Request Process
|
||||
|
||||
1. Fork the repository
|
||||
2. Create a feature branch
|
||||
3. Make your changes
|
||||
4. Add tests for new functionality
|
||||
5. Update documentation
|
||||
6. Submit a pull request
|
||||
|
||||
### Code Review
|
||||
|
||||
All PRs will be reviewed for:
|
||||
- Code quality
|
||||
- Test coverage
|
||||
- Documentation
|
||||
- Security
|
||||
- Performance
|
||||
|
||||
### Commit Messages
|
||||
|
||||
Use conventional commits:
|
||||
|
||||
```bash
|
||||
feat: add new shop item filter
|
||||
fix: resolve authentication issue
|
||||
docs: update API documentation
|
||||
chore: update dependencies
|
||||
```
|
||||
|
||||
## Resources
|
||||
|
||||
- [React Documentation](https://react.dev/)
|
||||
- [Express.js Documentation](https://expressjs.com/)
|
||||
- [TypeScript Handbook](https://www.typescriptlang.org/docs/)
|
||||
- [SQLite Documentation](https://www.sqlite.org/docs.html)
|
||||
Reference in New Issue
Block a user