# ๐Ÿค Contributing to Ospabhost 8.1 Thank you for considering contributing to **Ospabhost 8.1**! This document provides guidelines and instructions for contributing to the project. --- ## ๐Ÿ“‹ Table of Contents - [Code of Conduct](#code-of-conduct) - [Getting Started](#getting-started) - [Development Workflow](#development-workflow) - [Coding Standards](#coding-standards) - [Commit Guidelines](#commit-guidelines) - [Pull Request Process](#pull-request-process) - [Testing Requirements](#testing-requirements) - [Documentation](#documentation) - [Contact](#contact) --- ## ๐Ÿ“œ Code of Conduct ### Our Pledge We pledge to make participation in our project a harassment-free experience for everyone, regardless of: - Age, body size, disability, ethnicity - Gender identity and expression - Level of experience - Nationality, personal appearance, race, religion - Sexual identity and orientation ### Our Standards **Positive behavior includes:** - Using welcoming and inclusive language - Being respectful of differing viewpoints - Gracefully accepting constructive criticism - Focusing on what is best for the project - Showing empathy towards other community members **Unacceptable behavior includes:** - Trolling, insulting comments, personal attacks - Public or private harassment - Publishing others' private information without permission - Other conduct which could reasonably be considered inappropriate ### Enforcement Violations of the Code of Conduct can be reported to: - **Email:** support@ospab.host - **Telegram:** @ospab_support All complaints will be reviewed and investigated promptly and fairly. --- ## ๐Ÿš€ Getting Started ### Prerequisites Before you begin, ensure you have the following installed: ```bash # Node.js (v24.x or higher) node --version # npm (v10.x or higher) npm --version # MySQL (8.0 or higher) mysql --version # Git git --version ``` ### Fork and Clone 1. **Fork the repository** on GitHub: - Click "Fork" button at https://github.com/Ospab/ospabhost8.1 2. **Clone your fork locally:** ```bash git clone https://github.com/YOUR_USERNAME/ospabhost8.1.git cd ospabhost8.1/ospabhost ``` 3. **Add upstream remote:** ```bash git remote add upstream https://github.com/Ospab/ospabhost8.1.git git remote -v ``` ### Setup Development Environment #### Backend Setup ```bash cd backend # Install dependencies npm install # Copy environment template cp .env.example .env # Edit .env with your local configuration nano .env # Generate Prisma client npx prisma generate # Run migrations npx prisma migrate dev # Seed database (optional) npx prisma db seed # Start development server npm run dev ``` #### Frontend Setup ```bash cd frontend # Install dependencies npm install # Copy environment template cp .env.example .env # Edit .env nano .env # Start development server npm run dev ``` #### Database Setup ```sql -- Create database CREATE DATABASE ospab CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci; -- Create user (optional) CREATE USER 'ospab_user'@'localhost' IDENTIFIED BY 'secure_password'; GRANT ALL PRIVILEGES ON ospab.* TO 'ospab_user'@'localhost'; FLUSH PRIVILEGES; ``` --- ## ๐Ÿ”„ Development Workflow ### Branch Strategy We follow **Git Flow** workflow: ``` main # Production-ready code โ”œโ”€โ”€ develop # Development branch โ”‚ โ”œโ”€โ”€ feature/ # New features โ”‚ โ”œโ”€โ”€ fix/ # Bug fixes โ”‚ โ”œโ”€โ”€ refactor/ # Code refactoring โ”‚ โ””โ”€โ”€ docs/ # Documentation updates โ””โ”€โ”€ hotfix/ # Critical production fixes ``` ### Creating a Feature Branch ```bash # Ensure you're on latest develop git checkout develop git pull upstream develop # Create feature branch git checkout -b feature/your-feature-name # Example: git checkout -b feature/add-payment-gateway git checkout -b fix/proxmox-connection git checkout -b docs/api-examples ``` ### Branch Naming Convention | Type | Pattern | Example | |------|---------|---------| | Feature | `feature/` | `feature/panel-websocket` | | Bug Fix | `fix/` | `fix/sso-timestamp-validation` | | Hotfix | `hotfix/` | `hotfix/critical-security-patch` | | Refactor | `refactor/` | `refactor/prisma-queries` | | Docs | `docs/` | `docs/sso-integration` | | Test | `test/` | `test/panel-api-integration` | ### Staying Updated ```bash # Fetch latest changes from upstream git fetch upstream # Merge upstream changes into your branch git checkout feature/your-feature git merge upstream/develop # Or rebase (preferred for cleaner history) git rebase upstream/develop ``` --- ## ๐Ÿ“ Coding Standards ### TypeScript Style Guide #### File Structure ```typescript // 1. Imports (external first, then internal) import express from 'express'; import { PrismaClient } from '@prisma/client'; import { authenticateJWT } from '../middleware/auth'; import { validateRequest } from '../utils/validation'; // 2. Types/Interfaces interface CreateServerRequest { tariffId: number; osId: number; } // 3. Constants const PROXMOX_TIMEOUT = 30000; const MAX_SERVERS_PER_USER = 10; // 4. Main code export class ServerService { // Implementation } // 5. Helper functions function generateServerName(userId: number): string { return `server-${userId}-${Date.now()}`; } // 6. Exports export default ServerService; ``` #### Naming Conventions ```typescript // Classes: PascalCase class ServerService {} class ProxmoxApi {} // Interfaces: PascalCase with "I" prefix (optional) interface IUser {} interface ServerConfig {} // Functions: camelCase function createServer() {} function validateEmail(email: string): boolean {} // Variables: camelCase const userCount = 42; let isActive = true; // Constants: SCREAMING_SNAKE_CASE const API_BASE_URL = 'https://api.ospab.host'; const MAX_RETRY_ATTEMPTS = 3; // Private properties: prefix with underscore (optional) class Example { private _privateField: string; public publicField: string; } // Files: kebab-case // server-service.ts // proxmox-api.ts // auth-middleware.ts ``` #### Code Style ```typescript // โœ… GOOD: Explicit types function calculateTotal(price: number, quantity: number): number { return price * quantity; } // โŒ BAD: Implicit any function calculateTotal(price, quantity) { return price * quantity; } // โœ… GOOD: Async/await async function getUser(id: number): Promise { const user = await prisma.user.findUnique({ where: { id } }); return user; } // โŒ BAD: Promise chaining function getUser(id: number) { return prisma.user.findUnique({ where: { id } }) .then(user => user); } // โœ… GOOD: Error handling async function createServer(userId: number): Promise { try { const server = await prisma.server.create({ data: { userId, name: generateServerName(userId) } }); return server; } catch (error) { console.error('Failed to create server:', error); throw new Error('Server creation failed'); } } // โœ… GOOD: Destructuring const { id, username, email } = user; // โŒ BAD: Multiple property access const id = user.id; const username = user.username; const email = user.email; // โœ… GOOD: Optional chaining const serverName = user?.servers?.[0]?.name ?? 'N/A'; // โŒ BAD: Nested checks const serverName = user && user.servers && user.servers[0] ? user.servers[0].name : 'N/A'; ``` ### React/Frontend Standards ```tsx // โœ… GOOD: Functional components with TypeScript interface UserCardProps { user: User; onEdit: (id: number) => void; } export const UserCard: React.FC = ({ user, onEdit }) => { const handleEdit = () => { onEdit(user.id); }; return (

{user.username}

); }; // โœ… GOOD: Custom hooks function useServerData(userId: number) { const [servers, setServers] = useState([]); const [loading, setLoading] = useState(true); useEffect(() => { async function fetchServers() { try { const response = await api.get(`/users/${userId}/servers`); setServers(response.data); } catch (error) { console.error('Failed to fetch servers:', error); } finally { setLoading(false); } } fetchServers(); }, [userId]); return { servers, loading }; } // โœ… GOOD: Tailwind CSS classes organized
Content
``` ### Prisma Schema Conventions ```prisma // โœ… GOOD: Explicit relations model User { id Int @id @default(autoincrement()) username String @unique email String @unique createdAt DateTime @default(now()) updatedAt DateTime @updatedAt servers Server[] @relation("UserServers") tickets Ticket[] @relation("UserTickets") @@map("users") } model Server { id Int @id @default(autoincrement()) name String userId Int user User @relation("UserServers", fields: [userId], references: [id], onDelete: Cascade) @@index([userId]) @@map("servers") } ``` --- ## ๐Ÿ’ฌ Commit Guidelines ### Commit Message Format We follow **Conventional Commits** specification: ``` ():