This document outlines the coding standards and conventions used in both Server and Client repositories to maintain consistency across the entire project.
All properties, variables, functions, and interfaces follow PascalCase naming convention:
// Interfaces
export interface IApiResponse<T> {
Success: boolean;
Message: string;
Data?: T;
Error?: string;
Code: number;
}
export interface IUser {
Id: number;
Username: string;
Email: string;
Password: string;
Role: EUserRole;
IsActive: boolean;
TwoFactorEnabled: boolean;
LastLogin: Date | null;
CreatedAt: Date;
UpdatedAt: Date;
}
// Variables and Properties
const UserId = 123;
const AccessToken = "token_value";
const IsActive = true;
// Function Parameters
function CreateUser(Username: string, Email: string, Password: string) {
// ...
}
// React Component Props
interface IButtonProps {
Label: string;
OnClick: () => void;
IsDisabled: boolean;
}// DO NOT USE camelCase
interface IApiResponse<T> {
success: boolean; // ❌ Wrong
message: string; // ❌ Wrong
data?: T; // ❌ Wrong
}
// DO NOT USE snake_case
const user_id = 123; // ❌ Wrong
const access_token = "token"; // ❌ Wrong- Enum names: PascalCase with
Eprefix - Enum values: PascalCase
export enum EUserRole {
Admin = 'admin',
Developer = 'developer',
Viewer = 'viewer',
}
export enum EDeploymentStatus {
Queued = 'queued',
Pending = 'pending',
InProgress = 'inProgress',
Success = 'success',
Failed = 'failed',
}- All interfaces must start with
Iprefix - Use PascalCase for interface names
interface IProject {
Id: number;
Name: string;
RepoUrl: string;
Branch: string;
}
interface IDeployment {
Id: number;
ProjectId: number;
Status: EDeploymentStatus;
CreatedAt: Date;
}import React, { useState, useEffect } from 'react';
interface IMyComponentProps {
Title: string;
OnSave: (Data: any) => void;
IsLoading: boolean;
}
export const MyComponent: React.FC<IMyComponentProps> = ({ Title, OnSave, IsLoading }) => {
const [Data, setData] = useState<any>(null);
const HandleSubmit = () => {
OnSave(Data);
};
return (
<div>
<h1>{Title}</h1>
</div>
);
};export class ProjectsService {
private readonly ApiInstance: AxiosInstance;
constructor() {
this.ApiInstance = ApiInstance;
}
public async GetAll(): Promise<IProject[]> {
const Response = await this.ApiInstance.get('/projects');
return Response.data.Data?.Projects || [];
}
public async GetById(Id: number): Promise<IProject> {
const Response = await this.ApiInstance.get(`/projects/${Id}`);
return Response.data.Data?.Project;
}
public async Create(Data: ICreateProjectData): Promise<IProject> {
const Response = await this.ApiInstance.post('/projects', Data);
return Response.data.Data?.Project;
}
}export class AuthController {
private readonly AuthService: AuthService;
constructor() {
this.AuthService = new AuthService();
}
public Login = async (req: Request, res: Response): Promise<void> => {
try {
const { Username, Password } = req.body;
if (!Username || !Password) {
ResponseHelper.ValidationError(res, 'Missing required fields');
return;
}
const Result = await this.AuthService.Login({ Username, Password });
ResponseHelper.Success(res, 'Login successful', { User: Result.User });
} catch (error) {
Logger.Error('Login failed', error as Error);
ResponseHelper.Unauthorized(res, (error as Error).message);
}
};
}Order imports logically:
// 1. External libraries
import React, { useState } from 'react';
import { Box, Button, Typography } from '@mui/material';
import { useNavigate } from 'react-router-dom';
// 2. Internal contexts and hooks
import { useAuth } from '@/contexts/AuthContext';
import { useLanguage } from '@/contexts/LanguageContext';
// 3. Services and utilities
import { ProjectsService } from '@/services/projectsService';
// 4. Types
import type { IProject } from '@/types';All API responses must follow this structure:
{
Success: boolean;
Message: string;
Data?: {
// Response data here
};
Error?: string;
Code: number;
}// Success Response
{
Success: true,
Message: "User logged in successfully",
Data: {
User: {
Id: 1,
Username: "admin",
Email: "admin@example.com"
}
},
Code: 200
}
// Error Response
{
Success: false,
Message: "Authentication failed",
Error: "Invalid credentials",
Code: 401
}// ✅ Good
interface IFormData {
Username: string;
Email: string;
Password: string;
}
const [FormData, setFormData] = useState<IFormData>({
Username: "",
Email: "",
Password: "",
});
// ❌ Bad
const [formData, setFormData] = useState<any>({});interface ICardProps {
Title: string;
Description?: string;
Children?: React.ReactNode;
OnClick?: () => void;
IsLoading?: boolean;
}
export const Card: React.FC<ICardProps> = ({
Title,
Description,
Children,
OnClick,
IsLoading = false,
}) => {
// Component implementation
};/**
* Create a new project
* @param Data - Project creation data
* @returns Created project
*/
public async CreateProject(Data: ICreateProjectData): Promise<IProject> {
// Implementation
}/**
* Authentication Service
* Handles user authentication and token management
* Following SOLID principles and PascalCase naming convention
*/// ❌ Bad - Mixed conventions
interface IUser {
id: number; // ❌ camelCase
Username: string; // ✅ PascalCase
email_address: string; // ❌ snake_case
}
// ✅ Good - Consistent PascalCase
interface IUser {
Id: number;
Username: string;
Email: string;
}// ❌ Bad
const Data = getUserData();
const Temp = processData();
// ✅ Good
const UserProfile = getUserData();
const ProcessedProjects = processData();Always use async/await for asynchronous operations:
// ✅ Good
const FetchProjects = async () => {
try {
const Projects = await ProjectsService.GetAll();
setProjects(Projects);
} catch (Error) {
console.error('Failed to fetch projects', Error);
} finally {
setLoading(false);
}
};
// ❌ Bad
ProjectsService.GetAll().then(projects => {
setProjects(projects);
}).catch(error => {
console.error(error);
});// State hooks - use descriptive names
const [Projects, setProjects] = useState<IProject[]>([]);
const [IsLoading, setIsLoading] = useState<boolean>(false);
const [ErrorMessage, setErrorMessage] = useState<string | null>(null);
// Event handlers - use Handle prefix
const HandleSubmit = async (Event: React.FormEvent) => {
Event.preventDefault();
// Handle form submission
};
const HandleDelete = async (Id: number) => {
// Handle deletion
};- Always use PascalCase for all properties, variables, and functions
- Prefix interfaces with
I(e.g.,IUser,IProject) - Prefix enums with
E(e.g.,EUserRole,EDeploymentStatus) - Use strong typing - avoid
anywhen possible - Follow the standard API response format
- Use async/await for asynchronous operations
- Write clear, descriptive variable names
- Add JSDoc comments for public functions
- Keep code consistent across Server and Client
Important: This document applies to both Server and Client repositories. All code must follow these standards to maintain consistency across the project.