Contributing Guidelines
Welcome to the Football Booking Backend project! This guide will help you get started with contributing.
Table of Contents
- Getting Started
- Development Workflow
- Code Standards
- Testing
- Pull Request Process
- Commit Message Guidelines
Getting Started
Prerequisites
- Node.js 20+
- npm 9+
- Docker & Docker Compose
- Git
Installation
- Clone the repository:
git clone <repository-url>
cd football-booking-backend
- Install dependencies:
npm install
- Setup Git hooks:
npm run prepare
- Install recommended VS Code extensions (if using VS Code):
- Open VS Code
- Press
Cmd+Shift+P(Mac) orCtrl+Shift+P(Windows/Linux) - Type "Show Recommended Extensions"
- Install all recommended extensions
First Time Setup
Run the code quality setup script:
chmod +x scripts/setup-code-quality.sh
./scripts/setup-code-quality.sh
Development Workflow
1. Create a Branch
Always create a new branch for your work:
git checkout -b <type>/<scope>/<short-description>
Branch naming conventions:
feat/booking/add-conflict-detectionfix/payment/stripe-webhook-timeoutrefactor/user/extract-keycloak-syncdocs/readme/update-setup-instructionstest/field/add-search-integration-testschore/deps/update-nestjs
2. Make Changes
- Write clean, self-documenting code
- Add comments for complex logic
- Follow the code standards (see below)
- Write tests for new features
- Update documentation if needed
3. Before Committing
Run these commands to ensure code quality:
# Format code
npm run format
# Fix linting issues
npm run lint:fix
# Run type checking
npm run typecheck
# Run tests
npm test
Or run all checks at once:
npm run check:all
4. Commit Your Changes
We use Conventional Commits:
git commit -m "feat(booking): add double booking prevention
- Add distributed lock with Redis
- Implement conflict detection service
- Add integration tests
Closes #123"
Commit message format:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, missing semi-colons, etc.)refactor: Code refactoringperf: Performance improvementstest: Adding or updating testschore: Maintenance tasksci: CI/CD changesbuild: Build system changes
Scopes:
- Service names:
api-gateway,user-service,field-service,booking-service,payment-service,notification-service - Library names:
shared,database,messaging,cache,observability - Other:
docker,ci,deps,config
5. Push and Create PR
git push origin <your-branch-name>
Then create a Pull Request on GitHub.
Code Standards
TypeScript
Type Safety
✅ DO: Use explicit types
function calculateTotal(price: number, quantity: number): number {
return price * quantity;
}
❌ DON'T: Use any
function calculateTotal(price: any, quantity: any) {
// ❌ Avoid any
return price * quantity;
}
Null Safety
✅ DO: Handle null/undefined cases
function getUserName(user?: User): string {
return user?.name ?? 'Anonymous';
}
❌ DON'T: Assume values exist
function getUserName(user: User): string {
return user.name; // ❌ May crash if user is undefined
}
Async/Await
✅ DO: Always await promises
async function getUser(id: string): Promise<User> {
return await this.userRepository.findById(id);
}
❌ DON'T: Forget to await
async function getUser(id: string) {
return this.userRepository.findById(id); // ❌ Returns Promise<Promise<User>>
}
Naming Conventions
| Type | Convention | Example |
|---|---|---|
| Files | kebab-case | user-service.ts |
| Classes | PascalCase | UserService |
| Interfaces | PascalCase (no I prefix) | User (not IUser) |
| Type Aliases | PascalCase | UserId |
| Enums | PascalCase | UserRole |
| Enum Members | UPPER_CASE | ADMIN, CUSTOMER |
| Variables | camelCase | userName |
| Constants | UPPER_SNAKE_CASE | MAX_RETRY_COUNT |
| Functions | camelCase | calculateTotal |
| Methods | camelCase | findById |
Import Organization
Imports should be organized in this order:
- Node.js built-in modules
- External dependencies
- Internal packages (
@football-booking/*) - Relative imports (parent/sibling)
- Type imports
Example:
import { Injectable } from '@nestjs/common';
import { InjectRepository } from '@nestjs/typeorm';
import { Repository } from 'typeorm';
import { KafkaProducerService } from '@football-booking/messaging';
import { CacheService } from '@football-booking/cache';
import { BookingRepository } from './booking.repository';
import { CreateBookingDto } from './dto/create-booking.dto';
import type { Booking } from './entities/booking.entity';
This is enforced automatically by ESLint and Prettier.
Documentation
Add JSDoc comments for:
- All public classes
- All public methods
- Complex functions
- All interfaces and type aliases
Example:
/**
* Service for managing football field bookings
*/
@Injectable()
export class BookingService {
/**
* Creates a new booking with conflict detection
*
* @param userId - The ID of the user making the booking
* @param createDto - Booking details
* @returns The created booking
* @throws ConflictException if time slot is already booked
*/
async create(userId: string, createDto: CreateBookingDto): Promise<Booking> {
// Implementation
}
}
Error Handling
✅ DO: Use specific exception types
if (!field) {
throw new NotFoundException(`Field ${id} not found`);
}
❌ DON'T: Use generic errors
if (!field) {
throw new Error('Field not found'); // ❌ Too generic
}
Logging
✅ DO: Use appropriate log levels
this.logger.log('Booking created successfully', { bookingId });
this.logger.warn('Payment timeout, will retry', { paymentId });
this.logger.error('Failed to send notification', error);
❌ DON'T: Use console.log (will fail pre-commit hook)
console.log('Debug info'); // ❌ Will be rejected
Testing
Unit Tests
Write unit tests for:
- Services (business logic)
- Utilities
- Complex functions
Example:
describe('BookingService', () => {
it('should create a booking', async () => {
const result = await service.create(userId, createDto);
expect(result).toBeDefined();
expect(result.status).toBe(BookingStatus.PENDING);
});
it('should throw ConflictException for double booking', async () => {
await expect(service.create(userId, createDto)).rejects.toThrow(ConflictException);
});
});
Integration Tests
Write integration tests for:
- Controllers (API endpoints)
- Database operations
- External service integrations
Running Tests
# Run all tests
npm test
# Run tests for a specific service
nx test booking-service
# Run tests with coverage
npm run test:cov
# Run tests in watch mode
npm run test:watch
Pull Request Process
Before Creating PR
- ✅ All tests pass
- ✅ Code is formatted (
npm run format) - ✅ No linting errors (
npm run lint) - ✅ No TypeScript errors (
npm run typecheck) - ✅ Added tests for new features
- ✅ Updated documentation
PR Title
Use the same format as commit messages:
feat(booking): add conflict detection for double booking
PR Description Template
## Description
Brief description of changes
## Type of Change
- [ ] Bug fix
- [ ] New feature
- [ ] Breaking change
- [ ] Documentation update
## Changes Made
- Change 1
- Change 2
## Testing
- [ ] Unit tests added/updated
- [ ] Integration tests added/updated
- [ ] Manual testing completed
## Screenshots (if applicable)
## Checklist
- [ ] Code follows style guidelines
- [ ] Self-review completed
- [ ] Comments added for complex code
- [ ] Documentation updated
- [ ] No new warnings
- [ ] Tests pass locally
Code Review Guidelines
As a reviewer:
- Be respectful and constructive
- Ask questions to understand intent
- Suggest improvements, don't demand
- Approve if changes meet standards
As an author:
- Respond to all comments
- Ask for clarification if needed
- Make requested changes or explain why not
- Thank reviewers for their time
Commit Message Guidelines
Examples of Good Commits
✅ Good:
feat(booking): add conflict detection for double booking
- Implement distributed lock using Redis
- Add conflict detection service
- Add integration tests
- Update booking controller
Closes #123
✅ Good:
fix(payment): handle Stripe webhook timeout
The webhook handler was timing out for large payments.
Added timeout configuration and retry logic.
Fixes #456
✅ Good:
docs(readme): update installation instructions
- Add Docker prerequisite
- Update environment variables section
- Fix broken links
Examples of Bad Commits
❌ Bad:
Update stuff
Problem: Too vague, no type, no scope
❌ Bad:
feat: new feature
Problem: No scope, unclear what feature
❌ Bad:
Fix bug.
Problem: Has period at end, no scope, too vague
❌ Bad:
This is a really long commit message that exceeds the maximum allowed length of one hundred characters
Problem: Exceeds 100 character limit
Questions?
If you have questions about contributing, please:
- Check existing documentation
- Search closed issues/PRs
- Ask in team chat
- Create a discussion on GitHub
Thank you for contributing! 🎉