diff --git a/CODING_STANDARDS.md b/CODING_STANDARDS.md new file mode 100644 index 0000000..cc6f5e9 --- /dev/null +++ b/CODING_STANDARDS.md @@ -0,0 +1,678 @@ +# Coding Standards and Guidelines + +This document outlines the coding standards, conventions, and best practices for the Bank Server project. + +## Table of Contents + +- [General Principles](#general-principles) +- [TypeScript Guidelines](#typescript-guidelines) +- [Code Formatting](#code-formatting) +- [Naming Conventions](#naming-conventions) +- [File Organization](#file-organization) +- [NestJS Specific Guidelines](#nestjs-specific-guidelines) +- [Database Guidelines](#database-guidelines) +- [Testing Standards](#testing-standards) +- [Documentation Standards](#documentation-standards) +- [Security Guidelines](#security-guidelines) + +## General Principles + +### SOLID Principles + +Follow SOLID principles in all code: + +- **Single Responsibility**: Each class should have one reason to change +- **Open/Closed**: Open for extension, closed for modification +- **Liskov Substitution**: Derived classes must be substitutable for base classes +- **Interface Segregation**: Many client-specific interfaces are better than one general-purpose interface +- **Dependency Inversion**: Depend on abstractions, not concretions + +### DRY (Don't Repeat Yourself) + +- Extract common functionality into shared utilities +- Use inheritance and composition appropriately +- Create reusable components and services + +### KISS (Keep It Simple, Stupid) + +- Write clear, readable code +- Avoid unnecessary complexity +- Prefer explicit over implicit behavior + +## TypeScript Guidelines + +### Type Safety + +Always use TypeScript's type system effectively: + +```typescript +// Good: Explicit types +interface CreateUserDto { + firstName: string; + lastName: string; + email: string; +} + +// Good: Return type annotations for public methods +async createUser(userData: CreateUserDto): Promise { + // implementation +} + +// Avoid: Using 'any' type +// Bad +function processData(data: any): any { + return data; +} +``` + +### Interface vs Type + +- Use **interfaces** for object shapes that might be extended +- Use **type aliases** for unions, primitives, and computed types + +```typescript +// Good: Interface for extensible object shapes +interface UserEntity { + id: string; + email: string; +} + +// Good: Type for unions and computed types +type UserRole = 'USER' | 'ADMIN' | 'ROOT'; +type UserWithRole = UserEntity & { role: UserRole }; +``` + +### Generics + +Use generics for reusable components: + +```typescript +// Good: Generic repository pattern +interface Repository { + findById(id: string): Promise; + create(entity: Partial): Promise; + update(id: string, updates: Partial): Promise; + delete(id: string): Promise; +} +``` + +## Code Formatting + +### Prettier Configuration + +The project uses Prettier with the following configuration (`.prettierrc`): + +```json +{ + "singleQuote": true, + "trailingComma": "all" +} +``` + +### ESLint Configuration + +ESLint is configured with TypeScript support (`.eslintrc.js`): + +```javascript +module.exports = { + parser: '@typescript-eslint/parser', + parserOptions: { + project: 'tsconfig.json', + sourceType: 'module', + }, + plugins: ['@typescript-eslint/eslint-plugin'], + extends: [ + 'plugin:@typescript-eslint/eslint-recommended', + 'plugin:@typescript-eslint/recommended', + 'prettier', + 'prettier/@typescript-eslint', + ], + rules: { + '@typescript-eslint/interface-name-prefix': 'off', + '@typescript-eslint/explicit-function-return-type': 'off', + '@typescript-eslint/no-explicit-any': 'off', + }, +}; +``` + +### Formatting Rules + +- Use single quotes for strings +- Include trailing commas in multi-line structures +- Use 2 spaces for indentation +- Maximum line length: 80 characters (when practical) + +## Naming Conventions + +### Files and Directories + +``` +kebab-case.type.ts # Files +kebab-case/ # Directories +user.entity.ts # Entity files +user.service.ts # Service files +user.controller.ts # Controller files +create-user.dto.ts # DTO files +user.service.spec.ts # Test files +``` + +### Classes and Interfaces + +```typescript +// PascalCase for classes +class UserService {} +class CreateUserDto {} + +// PascalCase for interfaces +interface UserRepository {} +interface DatabaseConfig {} + +// PascalCase for enums +enum UserRole { + USER = 'USER', + ADMIN = 'ADMIN', + ROOT = 'ROOT', +} +``` + +### Variables and Functions + +```typescript +// camelCase for variables and functions +const userName = 'john_doe'; +const isUserActive = true; + +function getUserById(id: string): Promise {} +async function createNewUser(userData: CreateUserDto): Promise {} +``` + +### Constants + +```typescript +// SCREAMING_SNAKE_CASE for constants +const MAX_LOGIN_ATTEMPTS = 5; +const DEFAULT_PAGE_SIZE = 20; +const JWT_EXPIRATION_TIME = 3600; +``` + +### Database Naming + +```typescript +// snake_case for database columns (handled by SnakeNamingStrategy) +@Entity('user_accounts') +export class UserEntity { + @Column({ name: 'first_name' }) + firstName: string; + + @Column({ name: 'created_at' }) + createdAt: Date; +} +``` + +## File Organization + +### Module Structure + +Each module should follow this structure: + +``` +modules/ +└── user/ + ├── controllers/ + │ └── user.controller.ts + ├── dtos/ + │ ├── create-user.dto.ts + │ └── update-user.dto.ts + ├── entities/ + │ └── user.entity.ts + ├── services/ + │ └── user.service.ts + ├── subscribers/ + │ └── user.subscriber.ts + ├── templates/ + │ └── welcome.template.hbs + └── user.module.ts +``` + +### Import Organization + +Organize imports in the following order: + +```typescript +// 1. Node.js built-in modules +import * as path from 'path'; + +// 2. External libraries +import { Injectable } from '@nestjs/common'; +import { Repository } from 'typeorm'; + +// 3. Internal modules (using path aliases) +import { UserEntity } from 'modules/user/entities/user.entity'; +import { CreateUserDto } from 'modules/user/dtos/create-user.dto'; +import { UtilsService } from 'utils/services/utils.service'; + +// 4. Relative imports +import './user.types'; +``` + +## NestJS Specific Guidelines + +### Controllers + +```typescript +@Controller('users') +@ApiTags('Users') +export class UserController { + constructor(private readonly userService: UserService) {} + + @Get(':id') + @ApiOperation({ summary: 'Get user by ID' }) + @ApiParam({ name: 'id', description: 'User ID' }) + @ApiResponse({ status: 200, description: 'User found', type: UserEntity }) + @ApiResponse({ status: 404, description: 'User not found' }) + async findOne(@Param('id') id: string): Promise { + return this.userService.findById(id); + } +} +``` + +### Services + +```typescript +@Injectable() +export class UserService { + constructor( + @InjectRepository(UserEntity) + private readonly userRepository: Repository, + ) {} + + async findById(id: string): Promise { + const user = await this.userRepository.findOne({ where: { id } }); + if (!user) { + throw new NotFoundException(`User with ID ${id} not found`); + } + return user; + } +} +``` + +### DTOs + +```typescript +export class CreateUserDto { + @ApiProperty({ description: 'User first name', example: 'John' }) + @IsString() + @IsNotEmpty() + @Length(1, 255) + firstName: string; + + @ApiProperty({ description: 'User email address', example: 'john@example.com' }) + @IsEmail() + @IsNotEmpty() + email: string; +} +``` + +### Entities + +```typescript +@Entity('users') +export class UserEntity extends AbstractEntity { + @Column({ type: 'varchar', length: 255 }) + @ApiProperty({ description: 'User first name' }) + firstName: string; + + @Column({ type: 'varchar', length: 255, unique: true }) + @ApiProperty({ description: 'User email address' }) + email: string; + + @OneToMany(() => BillEntity, bill => bill.user) + bills: BillEntity[]; +} +``` + +## Database Guidelines + +### Entity Design + +- Extend `AbstractEntity` for common fields (id, createdAt, updatedAt) +- Use appropriate column types and constraints +- Define relationships clearly +- Use validation decorators + +### Migrations + +```typescript +export class CreateUserTable1234567890 implements MigrationInterface { + name = 'CreateUserTable1234567890'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.createTable( + new Table({ + name: 'users', + columns: [ + { + name: 'id', + type: 'uuid', + isPrimary: true, + generationStrategy: 'uuid', + default: 'uuid_generate_v4()', + }, + // ... other columns + ], + }), + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.dropTable('users'); + } +} +``` + +### Query Optimization + +- Use proper indexes +- Implement pagination for large datasets +- Use select queries to limit returned fields +- Avoid N+1 query problems with proper joins + +## Testing Standards + +### Unit Tests + +```typescript +describe('UserService', () => { + let service: UserService; + let repository: Repository; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + UserService, + { + provide: getRepositoryToken(UserEntity), + useClass: Repository, + }, + ], + }).compile(); + + service = module.get(UserService); + repository = module.get>(getRepositoryToken(UserEntity)); + }); + + describe('findById', () => { + it('should return a user when found', async () => { + const userId = 'test-id'; + const expectedUser = new UserEntity(); + expectedUser.id = userId; + + jest.spyOn(repository, 'findOne').mockResolvedValue(expectedUser); + + const result = await service.findById(userId); + + expect(result).toEqual(expectedUser); + expect(repository.findOne).toHaveBeenCalledWith({ where: { id: userId } }); + }); + }); +}); +``` + +### Test Organization + +- One test file per source file +- Use descriptive test names +- Group related tests with `describe` blocks +- Use `beforeEach` for common setup +- Mock external dependencies + +## Documentation Standards + +### Code Comments + +```typescript +/** + * Creates a new user account with the provided information. + * Automatically generates a unique pin code and sends a welcome email. + * + * @param userData - The user information for account creation + * @returns Promise resolving to the created user entity + * @throws ConflictException when email already exists + * @throws BadRequestException when validation fails + */ +async createUser(userData: CreateUserDto): Promise { + // Implementation details that need explanation + const pinCode = await this.generateUniquePinCode(); + + // Complex business logic explanation + if (await this.isEmailTaken(userData.email)) { + throw new ConflictException('Email already exists'); + } + + return this.userRepository.save({ ...userData, pinCode }); +} +``` + +### API Documentation + +Use Swagger decorators extensively: + +```typescript +@ApiOperation({ + summary: 'Create a new user account', + description: 'Creates a new user with automatic pin code generation and welcome email' +}) +@ApiBody({ type: CreateUserDto }) +@ApiResponse({ + status: 201, + description: 'User created successfully', + type: UserEntity +}) +@ApiResponse({ + status: 409, + description: 'Email already exists' +}) +``` + +## Security Guidelines + +### Input Validation + +Always validate input data: + +```typescript +export class CreateUserDto { + @IsString() + @IsNotEmpty() + @Length(1, 255) + @Matches(/^[a-zA-Z\s]+$/, { message: 'Name can only contain letters and spaces' }) + firstName: string; + + @IsEmail() + @IsNotEmpty() + email: string; +} +``` + +### Password Handling + +```typescript +// Good: Hash passwords before storing +const hashedPassword = await UtilsService.generateHash(plainPassword); + +// Good: Compare hashed passwords +const isValid = await UtilsService.validateHash(plainPassword, hashedPassword); + +// Never: Store plain text passwords +// Bad: user.password = plainPassword; +``` + +### JWT Security + +```typescript +// Good: Use strong, configurable secrets +const jwtSecret = this.configService.get('JWT_SECRET_KEY'); + +// Good: Set appropriate expiration times +const expiresIn = this.configService.get('JWT_EXPIRATION_TIME'); + +// Good: Include necessary claims only +const payload = { sub: user.id, email: user.email, role: user.role }; +``` + +### SQL Injection Prevention + +```typescript +// Good: Use TypeORM query builder or repository methods +const user = await this.userRepository.findOne({ + where: { email: userEmail } +}); + +// Good: Parameterized queries +const users = await this.userRepository + .createQueryBuilder('user') + .where('user.email = :email', { email: userEmail }) + .getMany(); + +// Never: String concatenation in queries +// Bad: `SELECT * FROM users WHERE email = '${userEmail}'` +``` + +## Performance Guidelines + +### Database Queries + +```typescript +// Good: Use select to limit fields +const users = await this.userRepository + .createQueryBuilder('user') + .select(['user.id', 'user.email', 'user.firstName']) + .getMany(); + +// Good: Use pagination +const [users, total] = await this.userRepository.findAndCount({ + skip: (page - 1) * limit, + take: limit, +}); + +// Good: Use proper joins to avoid N+1 queries +const users = await this.userRepository + .createQueryBuilder('user') + .leftJoinAndSelect('user.bills', 'bill') + .getMany(); +``` + +### Caching Strategies + +```typescript +// Consider caching for expensive operations +@Injectable() +export class CurrencyService { + private exchangeRateCache = new Map(); + + async getExchangeRate(from: string, to: string): Promise { + const cacheKey = `${from}-${to}`; + + if (this.exchangeRateCache.has(cacheKey)) { + return this.exchangeRateCache.get(cacheKey); + } + + const rate = await this.fetchExchangeRateFromAPI(from, to); + this.exchangeRateCache.set(cacheKey, rate); + + return rate; + } +} +``` + +## Error Handling + +### Exception Handling + +```typescript +// Good: Use appropriate HTTP exceptions +if (!user) { + throw new NotFoundException(`User with ID ${id} not found`); +} + +if (await this.isEmailTaken(email)) { + throw new ConflictException('Email already exists'); +} + +if (!this.isValidInput(data)) { + throw new BadRequestException('Invalid input data'); +} + +// Good: Handle and transform errors appropriately +try { + return await this.externalApiService.fetchData(); +} catch (error) { + this.logger.error('External API call failed', error); + throw new ServiceUnavailableException('External service temporarily unavailable'); +} +``` + +### Logging + +```typescript +// Good: Use structured logging +this.logger.log('User created successfully', { + userId: user.id, + email: user.email +}); + +this.logger.error('Database operation failed', { + operation: 'createUser', + error: error.message, + stack: error.stack +}); + +// Good: Log important business events +this.logger.log('Transaction completed', { + transactionId: transaction.id, + amount: transaction.amount, + fromAccount: transaction.senderBill.accountBillNumber, + toAccount: transaction.recipientBill.accountBillNumber +}); +``` + +## Code Review Guidelines + +### Before Submitting + +- Run `yarn lint` and fix all issues +- Run `yarn test` and ensure all tests pass +- Run `yarn format` to ensure consistent formatting +- Verify all new code has appropriate test coverage +- Check that all public methods have proper documentation + +### Review Checklist + +- [ ] Code follows established patterns and conventions +- [ ] All new functionality has tests +- [ ] API endpoints have proper Swagger documentation +- [ ] Error handling is appropriate and consistent +- [ ] Security considerations have been addressed +- [ ] Performance implications have been considered +- [ ] Database migrations are safe and reversible +- [ ] No sensitive information is logged or exposed + +## Continuous Improvement + +### Refactoring Guidelines + +- Refactor when adding new features that would benefit from cleaner code +- Extract common patterns into reusable utilities +- Improve test coverage during refactoring +- Update documentation when changing public interfaces + +### Code Quality Metrics + +Monitor and improve: + +- Test coverage (aim for >80%) +- Code complexity (keep functions simple) +- Duplication (extract common code) +- Performance (monitor query times and response times) + +This document is a living guide that should be updated as the project evolves and new patterns emerge. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md new file mode 100644 index 0000000..4452b1f --- /dev/null +++ b/CONTRIBUTING.md @@ -0,0 +1,495 @@ +# Contributing Guidelines + +Thank you for your interest in contributing to the Bank Server project! This document provides guidelines and instructions for contributing to the codebase. + +## Table of Contents + +- [Code of Conduct](#code-of-conduct) +- [Getting Started](#getting-started) +- [Development Workflow](#development-workflow) +- [Pull Request Process](#pull-request-process) +- [Coding Standards](#coding-standards) +- [Testing Requirements](#testing-requirements) +- [Documentation Guidelines](#documentation-guidelines) +- [Issue Reporting](#issue-reporting) +- [Security Vulnerabilities](#security-vulnerabilities) +- [Community Guidelines](#community-guidelines) + +## Code of Conduct + +### Our Pledge + +We are committed to providing a welcoming and inclusive environment for all contributors, regardless of background, experience level, or identity. + +### Expected Behavior + +- Use welcoming and inclusive language +- Be respectful of differing viewpoints and experiences +- Gracefully accept constructive criticism +- Focus on what is best for the community +- Show empathy towards other community members + +### Unacceptable Behavior + +- Harassment, discrimination, or offensive comments +- Personal attacks or trolling +- Publishing private information without permission +- Any conduct that would be inappropriate in a professional setting + +## Getting Started + +### Prerequisites + +Before contributing, ensure you have: + +- [Node.js](https://nodejs.org/) v12.18 or higher +- [yarn](https://classic.yarnpkg.com/) v1.22 or higher +- [PostgreSQL](https://www.postgresql.org/) v10.12 or higher +- [Git](https://git-scm.com/) for version control + +### Setting Up Your Development Environment + +1. **Fork the repository** on GitHub +2. **Clone your fork** locally: + ```bash + git clone https://github.com/your-username/bank-server.git + cd bank-server + ``` + +3. **Add the upstream remote**: + ```bash + git remote add upstream https://github.com/original-owner/bank-server.git + ``` + +4. **Install dependencies**: + ```bash + yarn install + ``` + +5. **Set up environment variables**: + ```bash + cp .env.example .env + # Edit .env with your local configuration + ``` + +6. **Set up the database**: + ```bash + createdb bank + yarn migration:run + ``` + +7. **Verify your setup**: + ```bash + yarn start:dev + # Server should start on http://localhost:4000 + ``` + +## Development Workflow + +### Branch Naming Convention + +Use descriptive branch names following this pattern: + +``` +feature/add-user-authentication +bugfix/fix-transaction-validation +hotfix/security-patch +docs/update-api-documentation +refactor/improve-error-handling +``` + +### Workflow Steps + +1. **Create a feature branch**: + ```bash + git checkout -b feature/your-feature-name + ``` + +2. **Make your changes** following our [coding standards](#coding-standards) + +3. **Write or update tests** for your changes + +4. **Run the test suite**: + ```bash + yarn test + yarn test:e2e + ``` + +5. **Run linting and formatting**: + ```bash + yarn lint + yarn format + ``` + +6. **Commit your changes** with a descriptive message: + ```bash + git add . + git commit -m "feat: add user authentication middleware" + ``` + +7. **Push to your fork**: + ```bash + git push origin feature/your-feature-name + ``` + +8. **Create a Pull Request** on GitHub + +### Keeping Your Fork Updated + +Regularly sync your fork with the upstream repository: + +```bash +git checkout master +git fetch upstream +git merge upstream/master +git push origin master +``` + +## Pull Request Process + +### Before Submitting + +- [ ] Ensure all tests pass (`yarn test` and `yarn test:e2e`) +- [ ] Run linting without errors (`yarn lint`) +- [ ] Format code consistently (`yarn format`) +- [ ] Update documentation if needed +- [ ] Add or update tests for new functionality +- [ ] Verify your changes don't break existing functionality + +### Pull Request Template + +When creating a pull request, include: + +```markdown +## Description +Brief description of the changes made. + +## Type of Change +- [ ] Bug fix (non-breaking change that fixes an issue) +- [ ] New feature (non-breaking change that adds functionality) +- [ ] Breaking change (fix or feature that would cause existing functionality to not work as expected) +- [ ] Documentation update + +## Testing +- [ ] Unit tests pass +- [ ] Integration tests pass +- [ ] Manual testing completed + +## Checklist +- [ ] Code follows the project's coding standards +- [ ] Self-review of code completed +- [ ] Code is commented where necessary +- [ ] Documentation updated +- [ ] No new warnings introduced +``` + +### Review Process + +1. **Automated checks** must pass (CI/CD pipeline) +2. **Code review** by at least one maintainer +3. **Testing** in a staging environment (if applicable) +4. **Approval** from project maintainers +5. **Merge** into the main branch + +### Review Criteria + +Reviewers will check for: + +- Code quality and adherence to standards +- Test coverage and quality +- Documentation completeness +- Security considerations +- Performance implications +- Backward compatibility + +## Coding Standards + +### General Principles + +Follow the guidelines outlined in [CODING_STANDARDS.md](./CODING_STANDARDS.md): + +- Use TypeScript with strict type checking +- Follow SOLID principles +- Write clean, readable code +- Use meaningful variable and function names +- Keep functions small and focused + +### Code Style + +- Use Prettier for code formatting +- Follow ESLint rules +- Use single quotes for strings +- Include trailing commas in multi-line structures +- Use 2 spaces for indentation + +### Architecture Guidelines + +- Follow NestJS best practices +- Use dependency injection properly +- Implement proper error handling +- Use DTOs for data validation +- Follow RESTful API conventions + +## Testing Requirements + +### Test Coverage + +- Maintain minimum 80% test coverage +- Write unit tests for all business logic +- Include integration tests for API endpoints +- Add end-to-end tests for critical user flows + +### Testing Guidelines + +```typescript +// Example unit test structure +describe('UserService', () => { + let service: UserService; + let repository: Repository; + + beforeEach(async () => { + const module = await Test.createTestingModule({ + providers: [ + UserService, + { + provide: getRepositoryToken(UserEntity), + useClass: Repository, + }, + ], + }).compile(); + + service = module.get(UserService); + repository = module.get>(getRepositoryToken(UserEntity)); + }); + + describe('createUser', () => { + it('should create a user successfully', async () => { + // Test implementation + }); + + it('should throw error when email already exists', async () => { + // Test implementation + }); + }); +}); +``` + +### Running Tests + +```bash +# Run all tests +yarn test + +# Run tests in watch mode +yarn test:watch + +# Run tests with coverage +yarn test:cov + +# Run end-to-end tests +yarn test:e2e +``` + +## Documentation Guidelines + +### Code Documentation + +- Use JSDoc comments for public methods +- Document complex business logic +- Include examples in documentation +- Keep documentation up to date with code changes + +### API Documentation + +- Use Swagger decorators for all endpoints +- Include request/response examples +- Document error responses +- Provide clear descriptions for parameters + +### README Updates + +When adding new features: + +- Update installation instructions if needed +- Add new environment variables to documentation +- Update API endpoint documentation +- Include usage examples + +## Issue Reporting + +### Bug Reports + +When reporting bugs, include: + +```markdown +## Bug Description +Clear description of the issue + +## Steps to Reproduce +1. Step one +2. Step two +3. Step three + +## Expected Behavior +What should happen + +## Actual Behavior +What actually happens + +## Environment +- Node.js version: +- yarn version: +- PostgreSQL version: +- Operating System: + +## Additional Context +Any other relevant information +``` + +### Feature Requests + +When requesting features, include: + +```markdown +## Feature Description +Clear description of the proposed feature + +## Use Case +Why is this feature needed? + +## Proposed Solution +How should this feature work? + +## Alternatives Considered +Other approaches you've considered + +## Additional Context +Any other relevant information +``` + +### Issue Labels + +Use appropriate labels: + +- `bug`: Something isn't working +- `enhancement`: New feature or request +- `documentation`: Improvements or additions to documentation +- `good first issue`: Good for newcomers +- `help wanted`: Extra attention is needed +- `priority:high`: High priority issue +- `priority:low`: Low priority issue + +## Security Vulnerabilities + +### Reporting Security Issues + +**Do not report security vulnerabilities through public GitHub issues.** + +Instead: + +1. Email security concerns to: [security@example.com] +2. Include detailed information about the vulnerability +3. Provide steps to reproduce if possible +4. Allow time for the issue to be addressed before public disclosure + +### Security Best Practices + +When contributing: + +- Never commit secrets or credentials +- Use environment variables for sensitive configuration +- Validate all user inputs +- Follow OWASP security guidelines +- Use parameterized queries to prevent SQL injection +- Implement proper authentication and authorization + +## Community Guidelines + +### Communication Channels + +- **GitHub Issues**: Bug reports and feature requests +- **GitHub Discussions**: General questions and discussions +- **Pull Requests**: Code review and collaboration + +### Getting Help + +If you need help: + +1. Check existing documentation +2. Search through GitHub issues +3. Ask questions in GitHub Discussions +4. Reach out to maintainers + +### Recognition + +Contributors will be recognized: + +- In the project's README +- In release notes for significant contributions +- Through GitHub's contributor statistics + +## Development Best Practices + +### Database Changes + +When making database changes: + +1. **Create migrations** for schema changes +2. **Test migrations** on sample data +3. **Provide rollback scripts** when possible +4. **Document breaking changes** clearly + +### API Changes + +When modifying APIs: + +1. **Maintain backward compatibility** when possible +2. **Version APIs** for breaking changes +3. **Update Swagger documentation** +4. **Notify users** of deprecations + +### Performance Considerations + +- **Profile code** for performance bottlenecks +- **Optimize database queries** +- **Use appropriate caching strategies** +- **Monitor memory usage** + +### Error Handling + +- **Use appropriate HTTP status codes** +- **Provide meaningful error messages** +- **Log errors appropriately** +- **Handle edge cases gracefully** + +## Release Process + +### Versioning + +We follow [Semantic Versioning](https://semver.org/): + +- **MAJOR**: Breaking changes +- **MINOR**: New features (backward compatible) +- **PATCH**: Bug fixes (backward compatible) + +### Release Checklist + +Before releasing: + +- [ ] All tests pass +- [ ] Documentation updated +- [ ] Migration scripts tested +- [ ] Security review completed +- [ ] Performance impact assessed +- [ ] Backward compatibility verified + +## Questions? + +If you have questions about contributing: + +1. Check this document first +2. Look through existing issues and discussions +3. Create a new discussion for general questions +4. Contact maintainers directly for urgent matters + +Thank you for contributing to the Bank Server project! Your contributions help make this project better for everyone. diff --git a/DEVELOPMENT.md b/DEVELOPMENT.md new file mode 100644 index 0000000..4d6a67a --- /dev/null +++ b/DEVELOPMENT.md @@ -0,0 +1,435 @@ +# Development Guide + +This guide provides detailed instructions for setting up and developing the Bank Server application. + +## Table of Contents + +- [Prerequisites](#prerequisites) +- [Environment Setup](#environment-setup) +- [Database Setup](#database-setup) +- [Development Workflow](#development-workflow) +- [Architecture Overview](#architecture-overview) +- [API Development](#api-development) +- [Testing](#testing) +- [Database Migrations](#database-migrations) + +## Prerequisites + +Before you begin, ensure you have the following installed: + +- **Node.js** v12.18 or higher +- **yarn** v1.22 or higher +- **PostgreSQL** v10.12 or higher +- **Git** for version control + +## Environment Setup + +### 1. Clone and Install + +```bash +git clone +cd bank-server +yarn install +``` + +### 2. Environment Configuration + +Copy the example environment file and configure it: + +```bash +cp .env.example .env +``` + +Edit the `.env` file with your specific configuration: + +```env +# Server Configuration +PORT=4000 +TRANSPORT_PORT=5000 + +# JWT Configuration +JWT_SECRET_KEY=your-secret-key-here +JWT_EXPIRATION_TIME=3600 +JWT_FORGOTTEN_PASSWORD_TOKEN_SECRET=your-reset-secret-here +JWT_FORGOTTEN_PASSWORD_TOKEN_EXPIRATION_TIME=3600 + +# Database Configuration +DB_HOST=localhost +DB_PORT=5432 +DB_USERNAME=your-db-username +DB_PASSWORD=your-db-password +DB_DATABASE=bank + +# Default Admin Users +BANK_ROOT_EMAIL=root@bank.com +BANK_ROOT_PASSWORD=secure-password +BANK_AUTHOR_EMAIL=author@bank.com +BANK_AUTHOR_PASSWORD=secure-password +BANK_AUTHOR_FIRSTNAME=Your +BANK_AUTHOR_LASTNAME=Name + +# Email Configuration (for notifications) +EMAIL_HOST=gmail +EMAIL_PORT=587 +EMAIL_ADDRESS=your-email@gmail.com +EMAIL_PASSWORD=your-email-password +``` + +## Database Setup + +### 1. Create Database + +Create a PostgreSQL database: + +```bash +# Using psql +createdb bank + +# Or using SQL +psql -c "CREATE DATABASE bank;" +``` + +### 2. Run Migrations + +The application uses TypeORM for database management. Migrations will run automatically when you start the application (`migrationsRun: true` in configuration). + +To manually run migrations: + +```bash +# Generate a new migration +yarn migration:generate MigrationName + +# Run pending migrations +yarn migration:run + +# Revert the last migration +yarn migration:revert + +# Drop the entire schema (use with caution!) +yarn schema:drop +``` + +## Development Workflow + +### Development Scripts + +```bash +# Start development server with hot reload +yarn start:dev + +# Start development server with debugging +yarn start:debug + +# Build the application +yarn build + +# Start production server +yarn start:prod + +# Format code with Prettier +yarn format + +# Lint code with ESLint +yarn lint + +# Run unit tests +yarn test + +# Run tests in watch mode +yarn test:watch + +# Run tests with coverage +yarn test:cov + +# Run end-to-end tests +yarn test:e2e +``` + +### Hot Reload Development + +The development server supports hot reload. Start it with: + +```bash +yarn start:dev +``` + +The server will automatically restart when you make changes to the source code. + +### Debugging + +To debug the application: + +```bash +yarn start:debug +``` + +This starts the server with Node.js debugging enabled. You can attach a debugger on the default port (9229). + +## Architecture Overview + +### NestJS Module Structure + +The application follows a modular architecture with the following core modules: + +#### Core Modules + +- **AppModule**: Main application module that imports all other modules +- **AuthModule**: Handles authentication, JWT tokens, and password management +- **UserModule**: User management, profiles, and configuration +- **BillModule**: Bank account management (called "bills" in the codebase) +- **TransactionModule**: Money transfers and transaction processing +- **CurrencyModule**: Multi-currency support and exchange rate management +- **MessageModule**: User messaging and notification templates +- **LanguageModule**: Internationalization support + +#### Shared Components + +- **Common**: Shared DTOs, entities, and base classes +- **Guards**: Authentication and authorization guards +- **Interceptors**: Request/response processing +- **Filters**: Exception handling +- **Middlewares**: Express middleware integration + +### Key Architectural Patterns + +#### Double-Entry Bookkeeping + +The application implements double-entry bookkeeping principles: + +- Each transaction affects two accounts (sender and recipient) +- Account balances are calculated dynamically from transaction history +- Ensures data integrity and accurate financial reporting + +#### Domain-Driven Design + +- Each module represents a business domain +- Clear separation of concerns +- Service-oriented architecture within modules + +#### Event-Driven Architecture + +- Uses TypeORM subscribers for automated actions +- Welcome bonuses triggered on account creation +- Automated messaging and notifications + +## API Development + +### Swagger Documentation + +The application includes automatic API documentation using Swagger. Access it at: + +``` +http://localhost:4000/documentation +``` + +### Adding New Endpoints + +1. **Create DTOs** in the appropriate module's `dtos/` directory +2. **Add controller methods** with proper decorators +3. **Implement business logic** in services +4. **Add Swagger documentation** using decorators + +Example controller method: + +```typescript +@Post() +@ApiOperation({ summary: 'Create a new resource' }) +@ApiResponse({ status: 201, description: 'Resource created successfully' }) +@ApiResponse({ status: 400, description: 'Bad request' }) +async create(@Body() createDto: CreateResourceDto): Promise { + return this.resourceService.create(createDto); +} +``` + +### Authentication + +The application uses JWT-based authentication: + +- **Login**: POST `/bank/auth/login` +- **Register**: POST `/bank/auth/register` +- **Protected routes**: Include `Authorization: Bearer ` header + +### API Versioning + +All API endpoints are prefixed with `/bank`. This is configured in `main.ts`: + +```typescript +app.setGlobalPrefix('bank'); +``` + +## Testing + +### Unit Tests + +Unit tests are located alongside source files with `.spec.ts` extension: + +```bash +# Run all unit tests +yarn test + +# Run tests in watch mode +yarn test:watch + +# Run tests with coverage report +yarn test:cov +``` + +### End-to-End Tests + +E2E tests are in the `test/` directory: + +```bash +# Run E2E tests +yarn test:e2e +``` + +### Test Configuration + +Jest configuration is in `package.json`: + +```json +{ + "jest": { + "moduleFileExtensions": ["js", "json", "ts"], + "rootDir": "src", + "testRegex": ".spec.ts$", + "transform": { + "^.+\\.(t|j)s$": "ts-jest" + }, + "collectCoverageFrom": ["**/*.(t|j)s"], + "coverageDirectory": "../coverage", + "testEnvironment": "node" + } +} +``` + +## Database Migrations + +### Creating Migrations + +When you modify entities, generate a migration: + +```bash +yarn migration:generate MigrationName +``` + +This creates a new migration file in `src/migrations/`. + +### Migration Best Practices + +1. **Review generated migrations** before running them +2. **Test migrations** on a copy of production data +3. **Keep migrations small** and focused +4. **Add rollback logic** when possible +5. **Document complex migrations** + +### Entity Development + +When creating or modifying entities: + +1. **Use TypeORM decorators** properly +2. **Follow naming conventions** (snake_case for database columns) +3. **Add proper relationships** between entities +4. **Include validation decorators** from class-validator + +Example entity: + +```typescript +@Entity('users') +export class UserEntity extends AbstractEntity { + @Column({ type: 'varchar', length: 255 }) + @IsString() + @IsNotEmpty() + firstName: string; + + @Column({ type: 'varchar', length: 255 }) + @IsString() + @IsNotEmpty() + lastName: string; + + @OneToMany(() => BillEntity, bill => bill.user) + bills: BillEntity[]; +} +``` + +## Performance Considerations + +### Database Optimization + +- Use proper indexes on frequently queried columns +- Implement pagination for large datasets +- Use database transactions for data consistency +- Monitor query performance with TypeORM logging + +### Caching + +Consider implementing caching for: + +- Currency exchange rates +- User session data +- Frequently accessed configuration + +### Security + +- All endpoints use rate limiting (configured in `main.ts`) +- Passwords are hashed using bcrypt +- JWT tokens have configurable expiration +- Input validation using class-validator +- SQL injection protection via TypeORM + +## Monitoring and Logging + +### Request Logging + +The application uses Morgan for HTTP request logging: + +```typescript +app.use(morgan('combined')); +``` + +### Error Handling + +Global exception filters handle errors consistently: + +- `HttpExceptionFilter`: Handles HTTP exceptions +- `QueryFailedFilter`: Handles database query errors + +### Health Checks + +Consider implementing health check endpoints for: + +- Database connectivity +- External API availability +- Application status + +## Deployment Considerations + +### Environment Variables + +Ensure all required environment variables are set in production: + +- Database credentials +- JWT secrets +- Email configuration +- External API keys + +### Database + +- Run migrations before deploying new versions +- Backup database before major updates +- Monitor database performance and connections + +### Security + +- Use HTTPS in production +- Set secure JWT secrets +- Configure proper CORS settings +- Enable security headers (Helmet is already configured) + +## Next Steps + +- Set up continuous integration +- Implement comprehensive logging +- Add monitoring and alerting +- Consider containerization with Docker +- Implement automated testing in CI/CD pipeline diff --git a/README.md b/README.md index 2f90f58..ddc7e75 100644 --- a/README.md +++ b/README.md @@ -1,3 +1,5 @@ +# Bank Server + +## Features + - The current account balance is calculated based on the SQL operation (**Double-entry bookkeeping**) - Internalization of the application for three languages: **English**, **German** and **Polish** - Support for **multiple currencies** with the current rate supplied from an external server via **API** @@ -28,31 +32,94 @@ Full Stack Web Application similar to financial software that is used in profess
-
-

Backend technologies stack

-
TypeScript, Node.js, Nest.js, REST API, PostgreSQL and Swagger Documentation
-
+## Technology Stack -
+**Backend technologies:** [TypeScript](https://github.com/microsoft/TypeScript), [Node.js](https://github.com/nodejs/node), [Nest.js](https://github.com/nestjs/nest), REST API, PostgreSQL and Swagger Documentation -

System requirements

+## Quick Start + +### System Requirements - [**Node.js** v12.18+](https://nodejs.org/en/) - [**yarn** v1.22+](https://classic.yarnpkg.com/en/) - [**PostgreSQL** v10.12+](https://www.postgresql.org/) -

Installation

+### Installation ```bash -# 1. Install the required dependencies -yarn +# 1. Clone the repository +git clone +cd bank-server + +# 2. Install dependencies +yarn install + +# 3. Set up environment variables +cp .env.example .env +# Edit .env file with your database credentials and other settings -# 2. Rename the .env.example filename to .env and set your local variables -mv .env.example .env +# 4. Set up PostgreSQL database +# Create a database named 'bank' (or as specified in your .env) +createdb bank -# 3. Start the server with the backend application -yarn start +# 5. Run database migrations +yarn migration:run + +# 6. Start the development server +yarn start:dev ``` -

License

+The server will start on `http://localhost:4000` (or the port specified in your `.env` file). + +### API Documentation + +Once the server is running, you can access the Swagger API documentation at: +`http://localhost:4000/documentation` + +## Project Structure + +``` +src/ +├── common/ # Shared DTOs, entities, and utilities +├── decorators/ # Custom decorators +├── exceptions/ # Custom exception classes +├── filters/ # Exception filters +├── guards/ # Authentication and authorization guards +├── interceptors/ # Request/response interceptors +├── interfaces/ # TypeScript interfaces +├── middlewares/ # Express middlewares +├── migrations/ # Database migration files +├── modules/ # Feature modules +│ ├── app/ # Main application module +│ ├── auth/ # Authentication and JWT management +│ ├── bill/ # Account management (banking accounts) +│ ├── currency/ # Multi-currency support and exchange rates +│ ├── language/ # Internationalization +│ ├── message/ # User messaging system +│ ├── notification/# System notifications +│ ├── transaction/ # Money transfer operations +│ └── user/ # User management +├── providers/ # Custom providers +├── utils/ # Utility functions and configurations +└── main.ts # Application entry point +``` + +## Development + +For detailed development instructions, see [DEVELOPMENT.md](./DEVELOPMENT.md). + +## Contributing + +Please read [CONTRIBUTING.md](./CONTRIBUTING.md) for details on our code of conduct and the process for submitting pull requests. + +## Troubleshooting + +For common issues and solutions, see [TROUBLESHOOTING.md](./TROUBLESHOOTING.md). + +## Coding Standards + +For coding guidelines and standards, see [CODING_STANDARDS.md](./CODING_STANDARDS.md). + +## License + This project is licensed under the MIT license. Copyright (c) 2020 Adrian Pietrzak. diff --git a/TROUBLESHOOTING.md b/TROUBLESHOOTING.md new file mode 100644 index 0000000..493ccac --- /dev/null +++ b/TROUBLESHOOTING.md @@ -0,0 +1,731 @@ +# Troubleshooting Guide + +This guide helps you diagnose and resolve common issues when developing with the Bank Server application. + +## Table of Contents + +- [Installation Issues](#installation-issues) +- [Database Issues](#database-issues) +- [Environment Configuration](#environment-configuration) +- [Development Server Issues](#development-server-issues) +- [Authentication Problems](#authentication-problems) +- [Migration Issues](#migration-issues) +- [Testing Issues](#testing-issues) +- [Performance Issues](#performance-issues) +- [API Issues](#api-issues) +- [Debugging Techniques](#debugging-techniques) + +## Installation Issues + +### Node.js Version Compatibility + +**Problem**: Application fails to start with Node.js version errors. + +**Solution**: +```bash +# Check your Node.js version +node --version + +# Should be v12.18 or higher +# If not, install the correct version using nvm +nvm install 12.18 +nvm use 12.18 +``` + +### Yarn Installation Problems + +**Problem**: `yarn install` fails with permission errors or package conflicts. + +**Solutions**: +```bash +# Clear yarn cache +yarn cache clean + +# Remove node_modules and yarn.lock, then reinstall +rm -rf node_modules yarn.lock +yarn install + +# If permission issues on macOS/Linux +sudo chown -R $(whoami) ~/.yarn +``` + +### Native Dependencies Issues + +**Problem**: Native dependencies fail to compile (bcrypt, etc.). + +**Solutions**: +```bash +# Install build tools (Ubuntu/Debian) +sudo apt-get install build-essential python3 + +# Install build tools (macOS) +xcode-select --install + +# Install build tools (Windows) +npm install --global windows-build-tools + +# Rebuild native dependencies +yarn install --force +``` + +## Database Issues + +### Connection Refused + +**Problem**: `ECONNREFUSED` error when connecting to PostgreSQL. + +**Diagnosis**: +```bash +# Check if PostgreSQL is running +sudo systemctl status postgresql + +# Check if PostgreSQL is listening on the correct port +sudo netstat -tlnp | grep 5432 +``` + +**Solutions**: +```bash +# Start PostgreSQL service +sudo systemctl start postgresql + +# Enable PostgreSQL to start on boot +sudo systemctl enable postgresql + +# Check PostgreSQL configuration +sudo -u postgres psql -c "SHOW port;" +``` + +### Authentication Failed + +**Problem**: `password authentication failed for user` error. + +**Solutions**: +```bash +# Reset PostgreSQL user password +sudo -u postgres psql +ALTER USER your_username PASSWORD 'new_password'; +\q + +# Check pg_hba.conf authentication method +sudo nano /etc/postgresql/*/main/pg_hba.conf +# Change 'peer' to 'md5' for local connections if needed + +# Restart PostgreSQL after config changes +sudo systemctl restart postgresql +``` + +### Database Does Not Exist + +**Problem**: `database "bank" does not exist` error. + +**Solutions**: +```bash +# Create the database +sudo -u postgres createdb bank + +# Or using psql +sudo -u postgres psql +CREATE DATABASE bank; +\q + +# Grant permissions to your user +sudo -u postgres psql +GRANT ALL PRIVILEGES ON DATABASE bank TO your_username; +\q +``` + +### Migration Errors + +**Problem**: Migrations fail to run or create conflicts. + +**Solutions**: +```bash +# Check migration status +yarn migration:show + +# Revert the last migration +yarn migration:revert + +# Drop schema and recreate (CAUTION: destroys data) +yarn schema:drop +yarn migration:run + +# Generate a new migration after entity changes +yarn migration:generate FixMigrationName +``` + +## Environment Configuration + +### Missing Environment Variables + +**Problem**: Application crashes with "Cannot read property of undefined" for config values. + +**Diagnosis**: +```bash +# Check if .env file exists +ls -la .env + +# Verify environment variables are loaded +node -e "require('dotenv').config(); console.log(process.env.DB_HOST);" +``` + +**Solutions**: +```bash +# Copy example environment file +cp .env.example .env + +# Edit with your values +nano .env + +# Verify all required variables are set +grep -v '^#' .env | grep -v '^$' +``` + +### Invalid Environment Values + +**Problem**: Application starts but behaves unexpectedly due to wrong config values. + +**Common Issues**: +- Wrong database port (should be number, not string) +- Invalid JWT secret (too short or contains special characters) +- Wrong email configuration + +**Solutions**: +```bash +# Validate database connection +node -e " +const config = require('dotenv').config().parsed; +console.log('DB Config:', { + host: config.DB_HOST, + port: parseInt(config.DB_PORT), + database: config.DB_DATABASE +}); +" + +# Test email configuration +# Check if EMAIL_HOST is valid (gmail, outlook, etc.) +# Verify EMAIL_PORT matches your provider +``` + +## Development Server Issues + +### Port Already in Use + +**Problem**: `EADDRINUSE: address already in use :::4000` + +**Solutions**: +```bash +# Find process using the port +lsof -i :4000 +# or +netstat -tlnp | grep 4000 + +# Kill the process +kill -9 + +# Or use a different port in .env +echo "PORT=4001" >> .env +``` + +### Hot Reload Not Working + +**Problem**: Changes to code don't trigger server restart. + +**Solutions**: +```bash +# Ensure you're using the dev script +yarn start:dev + +# Check if file watching is working +# On Linux, you might need to increase inotify limits +echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf +sudo sysctl -p + +# Clear NestJS build cache +rm -rf dist/ +yarn start:dev +``` + +### Memory Issues + +**Problem**: Development server crashes with out-of-memory errors. + +**Solutions**: +```bash +# Increase Node.js memory limit +export NODE_OPTIONS="--max-old-space-size=4096" +yarn start:dev + +# Or add to package.json scripts +"start:dev": "NODE_OPTIONS='--max-old-space-size=4096' nest start --watch" +``` + +## Authentication Problems + +### JWT Token Issues + +**Problem**: Authentication fails with "Invalid token" or "Token expired". + +**Diagnosis**: +```bash +# Check JWT configuration in .env +grep JWT .env + +# Verify token format (should be: Bearer ) +# Check token expiration time +``` + +**Solutions**: +```bash +# Ensure JWT_SECRET_KEY is set and consistent +# Check JWT_EXPIRATION_TIME is reasonable (3600 = 1 hour) +# Verify client sends token in correct format: +# Authorization: Bearer + +# Debug token in development +node -e " +const jwt = require('jsonwebtoken'); +const token = 'your-token-here'; +const secret = 'your-secret-here'; +try { + console.log(jwt.verify(token, secret)); +} catch (e) { + console.error('Token error:', e.message); +} +" +``` + +### Password Hashing Issues + +**Problem**: Login fails even with correct credentials. + +**Solutions**: +```bash +# Check if bcrypt is working +node -e " +const bcrypt = require('bcrypt'); +const password = 'test123'; +const hash = bcrypt.hashSync(password, 10); +console.log('Hash:', hash); +console.log('Valid:', bcrypt.compareSync(password, hash)); +" + +# Verify password hashing in user creation +# Check if UtilsService.generateHash is being called +``` + +## Migration Issues + +### Schema Sync Problems + +**Problem**: Entity changes don't reflect in database. + +**Solutions**: +```bash +# Generate migration for entity changes +yarn migration:generate UpdateEntityName + +# Check generated migration file +ls -la src/migrations/ + +# Run the migration +yarn migration:run + +# If synchronize is enabled (development only) +# Check ormconfig.ts: synchronize should be false in production +``` + +### Foreign Key Constraints + +**Problem**: Migration fails due to foreign key constraint violations. + +**Solutions**: +```bash +# Check existing data conflicts +# Manually fix data inconsistencies +# Or create a data migration to clean up + +# Example: Remove orphaned records +sudo -u postgres psql bank +DELETE FROM child_table WHERE parent_id NOT IN (SELECT id FROM parent_table); +``` + +### Column Type Conflicts + +**Problem**: Migration fails when changing column types. + +**Solutions**: +```bash +# Create a custom migration for complex type changes +yarn migration:create CustomColumnChange + +# Edit the migration file to handle data transformation +# Example: string to number conversion with data preservation +``` + +## Testing Issues + +### Test Database Setup + +**Problem**: Tests fail due to database connection issues. + +**Solutions**: +```bash +# Create a separate test database +sudo -u postgres createdb bank_test + +# Set TEST_DATABASE_URL environment variable +export TEST_DATABASE_URL="postgresql://user:pass@localhost:5432/bank_test" + +# Or configure test-specific environment +cp .env .env.test +# Edit .env.test with test database settings +``` + +### Mock Issues + +**Problem**: Tests fail due to unmocked dependencies. + +**Solutions**: +```typescript +// Ensure all external dependencies are mocked +jest.mock('external-library'); + +// Mock TypeORM repositories properly +const mockRepository = { + findOne: jest.fn(), + save: jest.fn(), + create: jest.fn(), +}; + +// Use proper TypeORM testing utilities +import { getRepositoryToken } from '@nestjs/typeorm'; +``` + +### Test Isolation + +**Problem**: Tests affect each other or fail when run together. + +**Solutions**: +```bash +# Run tests in isolation +yarn test --runInBand + +# Clear database between tests +# Use transactions that rollback after each test +# Or use a fresh database for each test suite +``` + +## Performance Issues + +### Slow Database Queries + +**Problem**: API responses are slow due to database performance. + +**Diagnosis**: +```bash +# Enable TypeORM query logging +# In ormconfig.ts: logging: true + +# Check slow query log in PostgreSQL +sudo -u postgres psql bank +SHOW log_min_duration_statement; +SET log_min_duration_statement = 1000; -- Log queries > 1 second +``` + +**Solutions**: +```sql +-- Add indexes for frequently queried columns +CREATE INDEX idx_users_email ON users(email); +CREATE INDEX idx_transactions_sender_bill ON transactions(sender_bill_id); + +-- Analyze query performance +EXPLAIN ANALYZE SELECT * FROM users WHERE email = 'test@example.com'; +``` + +### Memory Leaks + +**Problem**: Application memory usage grows over time. + +**Diagnosis**: +```bash +# Monitor memory usage +node --inspect=0.0.0.0:9229 dist/main.js +# Use Chrome DevTools to profile memory + +# Check for event listener leaks +# Monitor database connection pool +``` + +**Solutions**: +```typescript +// Properly close database connections +// Remove event listeners when done +// Use weak references where appropriate +// Implement proper cleanup in services +``` + +## API Issues + +### CORS Problems + +**Problem**: Frontend cannot access API due to CORS errors. + +**Solutions**: +```typescript +// In main.ts, CORS is enabled globally +const app = await NestFactory.create(AppModule, { cors: true }); + +// For specific origins: +app.enableCors({ + origin: ['http://localhost:3000', 'https://yourdomain.com'], + credentials: true, +}); +``` + +### Request Size Limits + +**Problem**: Large requests fail with payload too large errors. + +**Solutions**: +```typescript +// In main.ts, increase body parser limits +app.use(express.json({ limit: '50mb' })); +app.use(express.urlencoded({ limit: '50mb', extended: true })); +``` + +### Rate Limiting Issues + +**Problem**: Requests are blocked by rate limiter. + +**Solutions**: +```typescript +// Adjust rate limiting in main.ts +app.use(RateLimit({ + windowMs: 15 * 60 * 1000, // 15 minutes + max: 1000 // Increase limit for development +})); + +// Disable rate limiting in development +if (process.env.NODE_ENV !== 'production') { + // Skip rate limiting +} +``` + +## Debugging Techniques + +### Enable Debug Logging + +```bash +# Start with debug mode +yarn start:debug + +# Enable TypeORM logging +# In ormconfig.ts: logging: ['query', 'error', 'schema'] + +# Use debug module +DEBUG=* yarn start:dev +``` + +### Using Debugger + +```bash +# Start with Node.js debugger +yarn start:debug + +# Attach debugger (VS Code) +# Create .vscode/launch.json: +{ + "type": "node", + "request": "attach", + "name": "Attach to NestJS", + "port": 9229, + "restart": true +} +``` + +### Common Error Messages + +#### "Cannot resolve dependency" + +**Problem**: NestJS dependency injection fails. + +**Solutions**: +```typescript +// Ensure proper imports in module +@Module({ + imports: [TypeOrmModule.forFeature([UserEntity])], + providers: [UserService], + controllers: [UserController], +}) + +// Check circular dependencies +// Use forwardRef() if needed +@Inject(forwardRef(() => UserService)) +``` + +#### "Entity metadata not found" + +**Problem**: TypeORM cannot find entity definitions. + +**Solutions**: +```typescript +// Ensure entity is imported in module +TypeOrmModule.forFeature([UserEntity]) + +// Check entity decorator +@Entity('users') +export class UserEntity {} + +// Verify entity path in ormconfig +entities: ['src/modules/**/*.entity{.ts,.js}'] +``` + +#### "Cannot read property of undefined" + +**Problem**: Service or repository injection fails. + +**Solutions**: +```typescript +// Check constructor injection +constructor( + @InjectRepository(UserEntity) + private readonly userRepository: Repository, +) {} + +// Ensure module imports +@Module({ + imports: [TypeOrmModule.forFeature([UserEntity])], +}) +``` + +### Performance Debugging + +#### Slow API Responses + +**Diagnosis**: +```bash +# Enable request logging +# Check main.ts: app.use(morgan('combined')); + +# Profile database queries +# Enable TypeORM logging: logging: ['query'] + +# Use Node.js profiler +node --prof dist/main.js +``` + +**Solutions**: +- Add database indexes +- Implement query optimization +- Use pagination for large datasets +- Cache frequently accessed data + +#### Memory Usage Issues + +**Diagnosis**: +```bash +# Monitor memory usage +node --inspect dist/main.js +# Open chrome://inspect in Chrome + +# Check for memory leaks +# Use heap snapshots in Chrome DevTools +``` + +**Solutions**: +- Implement proper cleanup in services +- Remove event listeners when done +- Use weak references for caches +- Monitor database connection pools + +### Development Environment Issues + +#### TypeScript Compilation Errors + +**Problem**: TypeScript fails to compile with type errors. + +**Solutions**: +```bash +# Check TypeScript configuration +cat tsconfig.json + +# Verify all dependencies are installed +yarn install + +# Clear TypeScript cache +rm -rf dist/ node_modules/.cache/ +yarn build +``` + +#### Hot Reload Issues + +**Problem**: Changes don't trigger automatic restart. + +**Solutions**: +```bash +# Check file watching limits (Linux) +echo fs.inotify.max_user_watches=524288 | sudo tee -a /etc/sysctl.conf +sudo sysctl -p + +# Restart development server +yarn start:dev + +# Check for syntax errors preventing compilation +yarn build +``` + +### Production Deployment Issues + +#### Environment Variables + +**Problem**: Application fails in production due to missing environment variables. + +**Solutions**: +```bash +# Verify all required variables are set +env | grep -E "(DB_|JWT_|EMAIL_)" + +# Check .env file is not committed to git +git status --ignored + +# Use proper environment variable management +# Consider using Docker secrets or cloud provider secrets +``` + +#### Database Connection Pool + +**Problem**: Database connection errors in production. + +**Solutions**: +```typescript +// Configure connection pool in ormconfig +{ + type: 'postgres', + // ... other config + extra: { + max: 20, // Maximum connections + min: 5, // Minimum connections + acquire: 30000, // Connection timeout + idle: 10000, // Idle timeout + } +} +``` + +#### SSL/TLS Issues + +**Problem**: Database connection fails with SSL errors. + +**Solutions**: +```typescript +// Configure SSL in production +{ + type: 'postgres', + // ... other config + ssl: process.env.NODE_ENV === 'production' ? { + rejectUnauthorized: false + } : false +} +``` + +This troubleshooting guide covers the most common issues developers encounter. For additional help, check the [DEVELOPMENT.md](./DEVELOPMENT.md) guide or reach out to the development team.