Skip to Content
Wagoo SaaS 1.0.25 is released 🎉
08 DevelopmentCode StandardsCode Standards

Code Standards

Guide des conventions de code pour Wagoo.

TypeScript

Types obligatoires

Toujours typer vos variables :

// ✅ Bon const user: User = { id: '1', name: 'John' } const count: number = 0 const isActive: boolean = true // ❌ Mauvais const user = { id: '1', name: 'John' } const count = 0

Return types

Toujours typer les retours de fonction :

// ✅ Bon function getUser(id: string): Promise<User> { return db.user.findUnique({ where: { id } }) } function formatName(name: string): string { return name.toUpperCase() } // ❌ Mauvais function getUser(id: string) { return db.user.findUnique({ where: { id } }) }

Interfaces vs Types

Préférer les interfaces pour les objets :

// ✅ Bon interface User { id: string name: string email: string } // Types pour les unions type Status = 'active' | 'inactive' | 'archived' // ❌ Moins bon type User = { id: string name: string email: string }

React Components

Nommage

// ✅ PascalCase pour les composants const UserProfile = () => { ... } const SettingsForm = () => { ... } // ❌ camelCase const userProfile = () => { ... } const settingsForm = () => { ... }

Props typing

// ✅ Bon interface ButtonProps { label: string onClick?: () => void disabled?: boolean variant?: 'primary' | 'secondary' } const Button: React.FC<ButtonProps> = ({ label, onClick, disabled = false, variant = 'primary', }) => { return ( <button onClick={onClick} disabled={disabled} className={variant}> {label} </button> ) } // ❌ Mauvais - props pas typées const Button = ({ label, onClick, ...props }) => { return <button {...props}>{label}</button> }

Hooks rules

// ✅ Bon - Hooks à la racine const Profile = () => { const [name, setName] = useState('') const router = useRouter() return <div>{name}</div> } // ❌ Mauvais - Hooks dans une condition const Profile = ({ show }: { show: boolean }) => { if (show) { const [name, setName] = useState('') // ❌ Hook conditionnel! } return null }

Nommage de fichiers

Conventions

# Composants components/ ├── Button.tsx ├── UserCard.tsx └── forms/ └── LoginForm.tsx # Pages app/ ├── (dashboard)/ │ ├── page.tsx │ └── settings/ │ └── page.tsx # Utilities lib/ ├── api.ts ├── utils.ts └── validators.ts # Types types/ ├── user.ts ├── project.ts

Jamais camelCase pour les fichiers :

// ✅ Bon import Button from '@/components/Button' // ❌ Mauvais import Button from '@/components/button'

Imports

Ordre des imports

// ✅ Bon - Groupes séparés par ligne vide import React from 'react' import { useState } from 'react' import { Button } from '@/components/Button' import { useUser } from '@/hooks/useUser' import type { User } from '@/types/user' // ❌ Mélangé import React from 'react' import { Button } from '@/components/Button' import type { User } from '@/types/user' import { useUser } from '@/hooks/useUser'

Imports relatifs vs absolus

// ✅ Bon - Absolus pour clarté import { Button } from '@/components/Button' import { User } from '@/types/user' // ❌ Relatifs à éviter import { Button } from '../../../components/Button'

Conventions de formatage

Prettier config

{ "semi": false, "singleQuote": true, "trailingComma": "es5", "tabWidth": 2, "printWidth": 100, "arrowParens": "always" }

Quotes

// ✅ Single quotes const name = 'John' // ❌ Double quotes const name = "John"

Semicolons

// ✅ Pas de semicolon const name = 'John' // ❌ Avec semicolon const name = 'John';

ESLint rules

Règles importantes

// .eslintrc.js module.exports = { rules: { 'no-console': ['warn', { allow: ['warn', 'error'] }], 'no-unused-vars': 'error', 'prefer-const': 'error', 'eqeqeq': ['error', 'always'], '@typescript-eslint/explicit-function-return-types': 'warn', '@typescript-eslint/no-explicit-any': 'error', }, }

Linter

# Vérifier pnpm lint # Corriger pnpm lint:fix

Comments

Commentaires utiles

// ✅ Bon - explique le "pourquoi" // Cache le résultat pendant 1h pour éviter les requêtes API const cacheKey = `user-${userId}-${Date.now()}` // ❌ Mauvais - évident // Set the name const name = 'John'

JSDoc

// ✅ Bon pour les exports publics /** * Formate une date selon la locale de l'utilisateur * @param date - La date à formater * @param locale - La locale (défaut: 'fr-FR') * @returns La date formatée en string */ export function formatDate(date: Date, locale = 'fr-FR'): string { return date.toLocaleDateString(locale) } // ❌ Pas besoin partout // Calcule la somme function sum(a: number, b: number) { return a + b }

Gestion des erreurs

Toujours catcher

// ✅ Bon try { const user = await db.user.findUnique(...) } catch (error) { console.error('Failed to fetch user:', error) throw new Error('Unable to fetch user') } // ❌ Mauvais const user = await db.user.findUnique(...) // Si erreur, crash

Validation

import { z } from 'zod' // ✅ Bon avec Zod const userSchema = z.object({ email: z.string().email(), name: z.string().min(1), }) const validateUser = (data: unknown) => { return userSchema.safeParse(data) } // ❌ Mauvais - validation manuelle function validateUser(data: any) { if (!data.email || !data.email.includes('@')) { throw new Error('Invalid email') } // ... plus de validation }

Constantes

// ✅ Bon - constants en haut const MAX_RETRY_ATTEMPTS = 3 const DEFAULT_PAGE_SIZE = 20 const getUserById = async (id: string) => { // ... } // ❌ Hardcoded const getUserById = async (id: string) => { for (let i = 0; i < 3; i++) { // Pourquoi 3? try { return await db.user.findUnique(...) } catch {} } }

Async/Await

// ✅ Bon async function fetchUserData(id: string) { try { const user = await db.user.findUnique({ where: { id } }) return user } catch (error) { console.error('Failed:', error) } } // ❌ Mélanger promises et async function fetchUserData(id: string) { return db.user.findUnique({ where: { id } }).then(user => user) }

Environment variables

// ✅ Bon - valider les vars au startup if (!process.env.DATABASE_URL) { throw new Error('DATABASE_URL is required') } // ❌ Mauvais - utiliser sans vérifier const dbUrl = process.env.DATABASE_URL // Undefined?

Prochaines étapes

→ Contributing

Last updated on