veza/apps/web/src/config/constants.ts
senke 5dedc2ce4e fix: Corriger URL Swagger et finaliser implémentation DeveloperPage
- Ajouter fallback pour Swagger UI si doc.json ne fonctionne pas
- Améliorer message d'erreur avec bouton pour ouvrir Swagger UI directement
- Les fonctionnalités API Keys et Usage Stats sont maintenant complètes et fonctionnelles
- Tous les onglets de DeveloperPage sont maintenant implémentés
2026-01-18 13:55:28 +01:00

324 lines
8.3 KiB
TypeScript

/**
* 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;