/** * Constantes de l'application */ // URLs de l'API // SECURITY: Ne jamais utiliser localhost hardcodé en production // Utiliser des chemins relatifs par défaut qui seront résolus par le navigateur export const API_URLS = (() => { // En production, les variables d'environnement doivent être définies if (import.meta.env.PROD) { const apiUrl = import.meta.env.VITE_API_URL; const wsUrl = import.meta.env.VITE_WS_URL; const uploadUrl = import.meta.env.VITE_UPLOAD_URL; const streamUrl = import.meta.env.VITE_STREAM_URL; if (!apiUrl || !wsUrl) { throw new Error('VITE_API_URL and VITE_WS_URL must be defined in production'); } return { BASE: apiUrl, WS: wsUrl, UPLOAD: uploadUrl || '/upload', STREAM: streamUrl || '/stream', } as const; } // En développement, utiliser les variables d'environnement ou des chemins relatifs par défaut return { BASE: import.meta.env.VITE_API_URL || '/api/v1', WS: import.meta.env.VITE_WS_URL || '/ws', UPLOAD: import.meta.env.VITE_UPLOAD_URL || '/upload', STREAM: import.meta.env.VITE_STREAM_URL || '/stream', } as const; })(); // Endpoints de l'API export const API_ENDPOINTS = { AUTH: { LOGIN: '/auth/login', REGISTER: '/auth/register', REFRESH: '/auth/refresh', LOGOUT: '/auth/logout', PROFILE: '/auth/profile', VERIFY_2FA: '/auth/2fa/verify', SETUP_2FA: '/auth/2fa/setup', DISABLE_2FA: '/auth/2fa/disable', }, USERS: { LIST: '/users', CREATE: '/users', GET: '/users/:id', UPDATE: '/users/:id', DELETE: '/users/:id', SEARCH: '/users/search', }, MESSAGES: { LIST: '/messages', CREATE: '/messages', GET: '/messages/:id', UPDATE: '/messages/:id', DELETE: '/messages/:id', }, CONVERSATIONS: { LIST: '/conversations', CREATE: '/conversations', GET: '/conversations/:id', UPDATE: '/conversations/:id', DELETE: '/conversations/:id', PARTICIPANTS: '/conversations/:id/participants', ADD_PARTICIPANT: '/conversations/:id/participants', REMOVE_PARTICIPANT: '/conversations/:id/participants/:userId', }, TRACKS: { LIST: '/tracks', CREATE: '/tracks', GET: '/tracks/:id', UPDATE: '/tracks/:id', DELETE: '/tracks/:id', SEARCH: '/tracks/search', UPLOAD: '/tracks/upload', STREAM: '/tracks/:id/stream', }, UPLOADS: { FILE: '/uploads/file', IMAGE: '/uploads/image', AUDIO: '/uploads/audio', }, HEALTH: { LIVE: '/health/live', READY: '/health/ready', }, } as const; // Limites de l'application export const LIMITS = { FILE_SIZE: { IMAGE: 10 * 1024 * 1024, // 10MB AUDIO: 100 * 1024 * 1024, // 100MB DOCUMENT: 50 * 1024 * 1024, // 50MB }, MESSAGE_LENGTH: 1000, USERNAME_LENGTH: { MIN: 3, MAX: 20, }, PASSWORD_LENGTH: { MIN: 8, MAX: 128, }, CONVERSATION_NAME_LENGTH: { MIN: 3, MAX: 100, }, TRACK_TITLE_LENGTH: { MIN: 1, MAX: 200, }, PAGINATION: { DEFAULT_LIMIT: 20, MAX_LIMIT: 100, }, RATE_LIMITS: { MESSAGES_PER_MINUTE: 60, UPLOADS_PER_HOUR: 10, LOGIN_ATTEMPTS_PER_15MIN: 5, }, } as const; // Formats de fichiers supportés export const SUPPORTED_FORMATS = { IMAGE: ['image/jpeg', 'image/png', 'image/gif', 'image/webp'], AUDIO: ['audio/mpeg', 'audio/wav', 'audio/flac', 'audio/ogg', 'audio/mp4'], DOCUMENT: ['application/pdf', 'text/plain', 'application/msword'], ALL: [ 'image/jpeg', 'image/png', 'image/gif', 'image/webp', 'audio/mpeg', 'audio/wav', 'audio/flac', 'audio/ogg', 'audio/mp4', 'application/pdf', 'text/plain', 'application/msword', ], } as const; // Durées en millisecondes export const DURATIONS = { DEBOUNCE: 300, TOAST_DURATION: 5000, SESSION_TIMEOUT: 30 * 60 * 1000, // 30 minutes REFRESH_TOKEN_DURATION: 7 * 24 * 60 * 60 * 1000, // 7 jours CACHE_DURATION: 5 * 60 * 1000, // 5 minutes RETRY_DELAY: 1000, MAX_RETRY_ATTEMPTS: 3, WEBSOCKET_RECONNECT_DELAY: 3000, TYPING_INDICATOR_DURATION: 3000, } as const; // Regex patterns export const REGEX_PATTERNS = { EMAIL: /^[^\s@]+@[^\s@]+\.[^\s@]+$/, USERNAME: /^[a-zA-Z0-9_-]+$/, PASSWORD: /^(?=.*[a-z])(?=.*[A-Z])(?=.*\d)(?=.*[!@#$%^&*(),.?":{}|<>]).{8,}$/, PHONE: /^(?:\+33|0)[1-9](?:[0-9]{8})$/, URL: /^https?:\/\/.+/, UUID: /^[0-9a-f]{8}-[0-9a-f]{4}-[1-5][0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i, HEX_COLOR: /^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/, } as const; // Messages d'erreur export const ERROR_MESSAGES = { REQUIRED: 'Ce champ est requis', INVALID_EMAIL: "Format d'email invalide", INVALID_USERNAME: "Nom d'utilisateur invalide", INVALID_PASSWORD: 'Mot de passe invalide', PASSWORD_TOO_SHORT: 'Le mot de passe doit contenir au moins 8 caractères', PASSWORD_TOO_LONG: 'Le mot de passe ne peut pas dépasser 128 caractères', USERNAME_TOO_SHORT: "Le nom d'utilisateur doit contenir au moins 3 caractères", USERNAME_TOO_LONG: "Le nom d'utilisateur ne peut pas dépasser 20 caractères", FILE_TOO_LARGE: 'Le fichier est trop volumineux', INVALID_FILE_TYPE: 'Type de fichier non supporté', NETWORK_ERROR: 'Erreur de connexion', UNAUTHORIZED: 'Non autorisé', FORBIDDEN: 'Accès interdit', NOT_FOUND: 'Ressource non trouvée', SERVER_ERROR: 'Erreur serveur', VALIDATION_ERROR: 'Erreur de validation', RATE_LIMIT_EXCEEDED: 'Limite de taux dépassée', } as const; // Messages de succès export const SUCCESS_MESSAGES = { LOGIN: 'Connexion réussie', REGISTER: 'Inscription réussie', LOGOUT: 'Déconnexion réussie', PROFILE_UPDATED: 'Profil mis à jour', PASSWORD_CHANGED: 'Mot de passe modifié', MESSAGE_SENT: 'Message envoyé', CONVERSATION_CREATED: 'Conversation créée', TRACK_UPLOADED: 'Piste téléchargée', FILE_UPLOADED: 'Fichier téléchargé', SETTINGS_SAVED: 'Paramètres sauvegardés', } as const; // Types de messages WebSocket export const WS_MESSAGE_TYPES = { MESSAGE: 'message', TYPING: 'typing', READ_RECEIPT: 'read_receipt', USER_JOINED: 'user_joined', USER_LEFT: 'user_left', CONVERSATION_UPDATED: 'conversation_updated', ERROR: 'error', PING: 'ping', PONG: 'pong', } as const; // Types de notifications export const NOTIFICATION_TYPES = { NEW_MESSAGE: 'new_message', TRACK_UPLOADED: 'track_uploaded', USER_MENTIONED: 'user_mentioned', SYSTEM: 'system', FRIEND_REQUEST: 'friend_request', CONVERSATION_INVITE: 'conversation_invite', } as const; // Thèmes disponibles export const THEMES = { LIGHT: 'light', DARK: 'dark', AUTO: 'auto', } as const; // Langues supportées export const LANGUAGES = { FR: 'fr', EN: 'en', ES: 'es', DE: 'de', } as const; // Raccourcis clavier export const KEYBOARD_SHORTCUTS = { SEARCH: 'Ctrl+K', NEW_MESSAGE: 'Ctrl+N', PLAY_PAUSE: 'Space', NEXT_TRACK: 'Ctrl+Right', PREVIOUS_TRACK: 'Ctrl+Left', VOLUME_UP: 'Ctrl+Up', VOLUME_DOWN: 'Ctrl+Down', MUTE: 'Ctrl+M', HELP: '?', ESCAPE: 'Escape', } as const; // Codes de statut HTTP export const HTTP_STATUS = { OK: 200, CREATED: 201, NO_CONTENT: 204, BAD_REQUEST: 400, UNAUTHORIZED: 401, FORBIDDEN: 403, NOT_FOUND: 404, CONFLICT: 409, UNPROCESSABLE_ENTITY: 422, TOO_MANY_REQUESTS: 429, INTERNAL_SERVER_ERROR: 500, SERVICE_UNAVAILABLE: 503, } as const; // Configuration par défaut export const DEFAULT_CONFIG = { THEME: THEMES.AUTO, LANGUAGE: LANGUAGES.FR, NOTIFICATIONS: true, SOUNDS: true, AUTO_PLAY: false, VOLUME: 0.7, QUALITY: 'high', OFFLINE_MODE: false, } as const; // Configuration des fonctionnalités export const FEATURES = { CHAT: true, LIBRARY: true, STREAMING: true, UPLOADS: true, NOTIFICATIONS: true, TWO_FACTOR_AUTH: true, DARK_MODE: true, OFFLINE_MODE: false, PUSH_NOTIFICATIONS: false, VOICE_MESSAGES: false, VIDEO_CALLS: false, } as const; // Configuration de l'interface export const UI_CONFIG = { SIDEBAR_WIDTH: 280, HEADER_HEIGHT: 64, FOOTER_HEIGHT: 48, MODAL_MAX_WIDTH: 'lg', TOAST_POSITION: 'top-right', ANIMATION_DURATION: 200, DEBOUNCE_DELAY: 300, } as const; // Configuration des caches export const CACHE_CONFIG = { USER_PROFILE: 5 * 60 * 1000, // 5 minutes CONVERSATIONS: 1 * 60 * 1000, // 1 minute TRACKS: 30 * 60 * 1000, // 30 minutes MESSAGES: 30 * 1000, // 30 secondes SEARCH_RESULTS: 2 * 60 * 1000, // 2 minutes } as const;