UNPKG

coddyger

Version:

Coddyger est une bibliothèque JavaScript/TypeScript qui fournit des fonctions communes et des plugins pour la gestion des données, la communication entre services, et des utilitaires avancés pour le développement d'applications.

682 lines (542 loc) 21.9 kB
# Coddyger Coddyger est une bibliothèque JavaScript/TypeScript qui fournit des fonctions communes et des plugins pour la gestion des données, la communication entre services, et des utilitaires avancés pour le développement d'applications. ## Description Coddyger est un module conteneur qui offre : - Gestion des opérations CRUD avec support MongoDB et SQL - Communication via Kafka avec gestion avancée des événements - Utilitaires complets pour la manipulation de données - Système de logging configurable - Validation et formatage de données - Gestion des fichiers et des téléchargements - Support multilingue et internationalisation - Gestion des dates et des fuseaux horaires - **Gestion de cache configurable (Redis, mémoire, etc.)** ## Installation ```bash npm install coddyger ``` ## Prérequis - Node.js >= 20.15.1 - npm >= 10.7.0 ## Configuration ### Configuration de l'Environnement Créez un fichier `.env` à la racine de votre projet : ```env # Configuration Kafka TRANSPORTER_CLIENT=your-client-id TRANSPORTER_BROKER=host1:port1,host2:port2 TRANSPORTER_GROUP=your-group-id TRANSPORTER_TOPIC=your-topic TRANSPORTER_FOREIGNERS=topic1,topic2,topic3 # Configuration Base de données DATABASE_URL=your-database-url DATABASE_NAME=your-database-name DATABASE_DIALECT=mongodb|mysql|postgres|sqlite DATABASE_STORAGE=path/to/sqlite.db # Pour SQLite uniquement # Configuration des chemins DOWNLOAD_PATH=/path/to/downloads # Configuration du cache (exemple pour Redis) CACHE_TYPE=redis CACHE_HOST=localhost CACHE_PORT=6379 CACHE_PASSWORD=yourpassword CACHE_DB=0 CACHE_TTL=3600 CACHE_URL=redis://:yourpassword@localhost:6379/0 ``` ### Configuration de la Base de Données Coddyger supporte deux types d'accès aux données : #### MongoDB (via Mongoose) ```typescript import { MongooseDataAccess } from 'coddyger'; const db = new MongooseDataAccess(); db.connect(); // Utilise les variables d'environnement // ou db.connect('mongodb://custom-uri/database'); ``` ##### Transactions MongoDB Coddyger propose aussi un helper pour les transactions MongoDB (sessions) : ```typescript import { MongooseDataAccess } from 'coddyger'; const db = new MongooseDataAccess(); await db.connect(); await db.transaction(async (session) => { await User.create([{ name: 'Alice' }], { session }); await Post.create([{ title: 'Hello' }], { session }); // Toutes les opérations sont atomiques }); ``` #### SQL (via Sequelize) ```typescript import { SequelizeDataAccess } from 'coddyger'; // Utilisation de la chaîne de connexion de l'environnement const db = new SequelizeDataAccess(); await db.connect(); // ← Obligatoire AVANT toute autre méthode await db.sync(); // Synchronise les modèles const isConnected = await db.isConnected(); // OU : passer une chaîne de connexion personnalisée (comme pour Mongoose) const dbCustom = new SequelizeDataAccess('postgresql://user:password@localhost:5432/ma_base'); await dbCustom.connect(); ``` > Vous pouvez passer la chaîne de connexion SQL directement au constructeur, ou laisser Coddyger utiliser celle de l'environnement (.env). ##### Transactions SQL Coddyger propose des helpers pour gérer facilement les transactions avec Sequelize : ```typescript import { SequelizeDataAccess } from 'coddyger'; const db = new SequelizeDataAccess(); await db.connect(); // Transaction automatique (commit/rollback auto) await db.transaction(async (t) => { await User.create({ ... }, { transaction: t }); await Post.create({ ... }, { transaction: t }); }); // Transaction manuelle const t = await db.getTransaction(); try { await User.create({ ... }, { transaction: t }); await t.commit(); } catch (err) { await t.rollback(); } ``` ### Configuration du Cache Coddyger supporte la configuration d’un système de cache (Redis, mémoire, etc.) via l’environnement : ```env # Exemple pour Redis CACHE_TYPE=redis CACHE_HOST=localhost CACHE_PORT=6379 CACHE_PASSWORD=yourpassword CACHE_DB=0 CACHE_TTL=3600 CACHE_URL=redis://:yourpassword@localhost:6379/0 ``` La configuration est accessible via `env.cache`. #### Exemple d'utilisation de la config cache ```typescript import { env } from 'coddyger'; console.log(env.cache.type); // 'redis' console.log(env.cache.host); // 'localhost' ``` > Tu peux brancher un client Redis ou autre système de cache selon cette configuration. ## Fonctionnalités ### 1. Utilitaires (Namespaces) #### String ```typescript import { string } from 'coddyger'; // Génération de mots de passe et tokens const password = string.generateSecurePassword(12); // "aX9#mK2$pL5&" const pin = string.generatePIN(6); // "123456" const token = string.generateToken(32); // Formatage et nettoyage const clean = string.cleanText(" Mon Texte! "); // "mon texte" const truncated = string.truncate("Long texte...", 10); // "Long te..." const slug = string.slugify("Mon Titre"); // "mon-titre" ``` #### Array ```typescript import { array } from 'coddyger'; // Manipulation de tableaux const unique = array.unique([1, 2, 2, 3]); // [1, 2, 3] const chunks = array.chunk([1, 2, 3, 4], 2); // [[1,2], [3,4]] const intersection = array.intersection([1, 2], [2, 3]); // [2] const difference = array.difference([1, 2, 3], [2]); // [1, 3] ``` #### Object ```typescript import { object } from 'coddyger'; // Manipulation d'objets const cloned = object.deepClone(originalObj); const merged = object.deepMerge(obj1, obj2); const value = object.get(obj, "user.profile.name", "default"); const cleaned = object.removeNullish(obj); ``` #### Number ```typescript import { number } from 'coddyger'; // Formatage et calculs const formatted = number.formatCurrency(1234.56, 'EUR'); // "1 234,56 €" const random = number.random(1, 100); const bytes = number.formatBytes(1234567); // "1.18 MB" const percent = number.percentage(50, 200); // 25 ``` #### URL ```typescript import { url } from 'coddyger'; // Manipulation d'URLs const isValid = url.isValid("https://example.com"); const domain = url.getDomain("https://sub.example.com"); const withParams = url.buildWithParams("https://api.com", { id: 123 }); const params = url.parseParams("https://api.com?key=value"); ``` #### Validation ```typescript import { validation } from 'coddyger'; // Validation de données const isValidJson = validation.isValidJSON('{"key": "value"}'); const pwdStrength = validation.passwordStrength("MonMotDePasse123!"); const isValidSiret = validation.isSIRET("12345678901234"); const isValidIban = validation.isIBAN("FR7630006000011234567890189"); ``` ### 2. Gestion des Dates ```typescript import { date } from 'coddyger'; // Manipulation de dates const isInRange = date.isWithinInterval( new Date(), startDate, endDate ); const daysInMonth = date.getDaysInMonthCount(3, 2024); // 31 ``` ### 3. Gestion des Fichiers ```typescript import { file } from 'coddyger'; // Opérations sur les fichiers const exists = file.exists("/path/to/file"); const ext = file.extension("document.pdf"); // ".pdf" const base64 = file.toBase64("/path/to/image.jpg"); await file.download("https://example.com/file.pdf", "local.pdf"); ``` ### 4. Gestion des Erreurs Coddyger fournit des codes d'erreur et messages standardisés : ```typescript import { defines } from 'coddyger'; // Codes d'état HTTP const { status } = defines; response.status(status.badRequest); // 400 // Messages d'erreur const { message } = defines; console.log(message.notFound); // "Route introuvable ou inexistante" ``` ### 5. Système de Logging Avancé Coddyger utilise Pino pour un logging performant et structuré : ```typescript import { LoggerService, LogLevel } from 'coddyger'; // Méthodes de logging simples LoggerService.info('Opération réussie'); LoggerService.debug('Données de débogage', { userId: 123 }); LoggerService.warn('Attention', { resource: 'users' }); LoggerService.error(new Error('Erreur critique')); LoggerService.fatal('Erreur système', { service: 'auth' }); // Logging avec contexte personnalisé LoggerService.log({ type: LogLevel.Info, content: 'Message personnalisé', location: 'UserService', method: 'create', context: { userId: 123, action: 'create' } }); ``` Caractéristiques du système de logging : - Logs structurés au format JSON - Niveaux de log multiples (trace, debug, info, warn, error, fatal) - Rotation automatique des fichiers de log par date - Fichiers séparés pour les erreurs - Formatage coloré en développement avec pino-pretty - Redaction automatique des données sensibles (mots de passe, tokens) - Support du mode production/développement - Contexte enrichi pour chaque log Configuration des logs selon l'environnement : ```env # Configuration des logs NODE_ENV=development # ou production ``` ### 6. Service HTTP (Axios) Coddyger fournit un service HTTP robuste basé sur Axios avec des fonctionnalités avancées : ```typescript import { AxiosService } from 'coddyger'; // Configuration initiale const axiosInstance = AxiosService.connect({ baseURL: 'https://api.example.com', timeout: 30000, retryConfig: { maxRetries: 3, delayMs: 1000, retryCondition: (error) => error.response?.status >= 500 }, cacheConfig: { enabled: true, ttlMs: 5 * 60 * 1000 // 5 minutes } }); // Requêtes avec cache et retry const response = await AxiosService.get('/users', { cache: true, // Active le cache cacheTTL: 60000, // Cache pendant 1 minute retry: true // Active les retries en cas d'erreur }); // Requête POST avec retry const newUser = await AxiosService.post('/users', { name: 'John Doe', email: 'john@example.com' }, { retry: true }); // Gestion des headers par type de requête AxiosService.setHeader('Authorization', 'Bearer token123', 'common'); AxiosService.setHeader('Custom-Header', 'value', 'post'); // Gestion du cache AxiosService.clearCache(); const cacheSize = AxiosService.getCacheSize(); ``` #### Caractéristiques 1. **Système de Cache Intelligent** - Cache configurable pour les requêtes GET - TTL (Time To Live) personnalisable - Invalidation automatique - API pour gérer le cache manuellement 2. **Gestion Avancée des Retries** - Nombre de tentatives configurable - Délai exponentiel entre les tentatives - Conditions de retry personnalisables - Logging des tentatives 3. **Gestion des Erreurs** ```typescript try { const response = await AxiosService.get('/users'); } catch (error) { console.log(error.message); // Message d'erreur en français console.log(error.code); // Code d'erreur standardisé console.log(error.status); // Status HTTP console.log(error.timestamp); // Horodatage de l'erreur console.log(error.path); // Chemin de la requête } ``` #### Codes d'État HTTP REST Complets ```typescript import { defines } from 'coddyger'; const { status } = defines; // Codes de Succès (2xx) status.requestOK; // 200 - Requête traitée avec succès status.created; // 201 - Ressource créée avec succès status.accepted; // 202 - Requête acceptée, traitement en cours status.noContent; // 204 - Requête traitée mais pas d'information à renvoyer // Codes de Redirection (3xx) status.movedPerm; // 301 - Redirection permanente status.found; // 302 - Redirection temporaire status.seeOther; // 303 - Voir autre (redirection vers une autre URI) status.notModified; // 304 - Contenu non modifié depuis la dernière requête status.tempRedirect; // 307 - Redirection temporaire (méthode HTTP préservée) status.permRedirect; // 308 - Redirection permanente (méthode HTTP préservée) // Codes d'Erreur Client (4xx) status.badRequest; // 400 - Syntaxe de la requête erronée status.authError; // 401 - Authentification nécessaire status.forbidden; // 403 - Accès refusé status.notFound; // 404 - Ressource non trouvée status.notAllowed; // 405 - Méthode HTTP non autorisée status.notAcceptable; // 406 - Format demandé non disponible status.conflict; // 409 - La requête conflicte avec l'état actuel status.gone; // 410 - La ressource n'est plus disponible status.lengthReq; // 411 - La longueur de contenu est requise status.precondFailed; // 412 - Précondition échouée status.payloadLarge; // 413 - Contenu trop volumineux status.uriTooLong; // 414 - URI trop longue status.unsupported; // 415 - Format de contenu non supporté status.rangeInvalid; // 416 - Plage demandée non satisfiable status.clientError; // 422 - Entité non traitable status.locked; // 423 - Ressource verrouillée status.tooEarly; // 425 - Trop tôt (anti-replay) status.tooMany; // 429 - Trop de requêtes status.headerLarge; // 431 - En-têtes trop grands status.legalReasons; // 451 - Indisponible pour raisons légales // Codes d'Erreur Serveur (5xx) status.serverError; // 500 - Erreur interne du serveur status.notImpl; // 501 - Fonctionnalité non implémentée status.badGateway; // 502 - Mauvaise réponse du serveur en amont status.unavailable; // 503 - Service temporairement indisponible status.gatewayTimeout;// 504 - Délai d'attente de la passerelle dépassé status.httpVersion; // 505 - Version HTTP non supportée status.variantAlso; // 506 - La négociation de contenu a échoué status.insuffStorage; // 507 - Espace insuffisant status.loopDetected; // 508 - Boucle détectée status.bandwidthLimit;// 509 - Limite de bande passante dépassée ``` #### Messages d'Erreur Standardisés par Code HTTP ```typescript const { message } = defines; // Messages pour les erreurs 4xx console.log(message.badRequest); // "La requête contient des erreurs de syntaxe" console.log(message.unauthorized); // "Authentification requise pour accéder à cette ressource" console.log(message.forbidden); // "Vous n'avez pas les droits nécessaires" console.log(message.notFound); // "La ressource demandée n'existe pas" console.log(message.methodNotAllowed); // "Cette méthode HTTP n'est pas autorisée" console.log(message.conflict); // "La ressource existe déjà ou conflit de version" console.log(message.tooMany); // "Vous avez dépassé la limite de requêtes autorisées" // Messages pour les erreurs 5xx console.log(message.serverError); // "Une erreur interne s'est produite" console.log(message.notImplemented);// "Cette fonctionnalité n'est pas encore disponible" console.log(message.unavailable); // "Le service est temporairement indisponible" // Messages génériques console.log(message.tryCatch); // "Une erreur imprévue s'est produite" console.log(message.validation); // "Les données fournies sont invalides" console.log(message.timeout); // "Le délai d'attente a été dépassé" ``` #### Exemple d'Utilisation avec Gestion d'Erreur Complète ```typescript import { AxiosService, defines, LoggerService } from 'coddyger'; class APIService { async handleRequest(method: string, url: string, data?: any) { try { const response = await AxiosService[method](url, data, { retry: true, cache: method === 'get' }); return response.data; } catch (error) { switch (error.status) { case defines.status.authError: throw new Error("Votre session a expiré. Veuillez vous reconnecter."); case defines.status.forbidden: throw new Error("Vous n'avez pas les permissions nécessaires."); case defines.status.notFound: throw new Error(`La ressource ${url} n'existe pas.`); case defines.status.conflict: throw new Error("Cette opération crée un conflit avec les données existantes."); case defines.status.tooMany: const retryAfter = error.response?.headers['retry-after'] || 60; throw new Error(`Trop de requêtes. Réessayez dans ${retryAfter} secondes.`); case defines.status.clientError: throw new Error("Les données fournies sont invalides."); case defines.status.serverError: LoggerService.error("Erreur serveur", { method, url, error: error.message, stack: error.stack }); throw new Error("Une erreur serveur s'est produite. L'équipe technique a été notifiée."); default: throw error; } } } } ``` 4. **Headers et Authentification** ```typescript // Headers globaux AxiosService.setHeader('Accept-Language', 'fr-FR', 'common'); // Headers spécifiques par méthode AxiosService.setHeader('Content-Type', 'application/json', 'post'); AxiosService.setHeader('Authorization', 'Bearer token123', 'get'); // Suppression de headers AxiosService.removeHeader('Custom-Header', 'post'); ``` 5. **Logging et Traçabilité** - ID unique pour chaque requête - Logging automatique des requêtes et réponses - Masquage des données sensibles - Intégration avec le système de logging 6. **Configuration Flexible** ```typescript const config = { baseURL: 'https://api.example.com', timeout: 30000, withCredentials: true, retryConfig: { maxRetries: 3, delayMs: 1000, retryCondition: (error) => error.response?.status >= 500 }, cacheConfig: { enabled: true, ttlMs: 300000 // 5 minutes } }; AxiosService.connect(config); ``` 7. **Méthodes HTTP Supportées** ```typescript // GET avec cache const users = await AxiosService.get('/users', { cache: true }); // POST avec retry const newUser = await AxiosService.post('/users', data, { retry: true }); // PUT avec configuration personnalisée const updatedUser = await AxiosService.put('/users/123', data, { retry: true, timeout: 5000 }); // DELETE avec retry await AxiosService.delete('/users/123', { retry: true }); // PATCH avec configuration const patchedUser = await AxiosService.patch('/users/123', data, { retry: true, headers: { 'Custom-Header': 'value' } }); ``` 8. **Gestion des Timeouts** ```typescript // Timeout global AxiosService.connect({ baseURL: 'https://api.example.com', timeout: 30000 // 30 secondes }); // Timeout par requête const response = await AxiosService.get('/users', { timeout: 5000 // 5 secondes pour cette requête }); ``` ### 7. Méthodes Génériques DAO Les DAO SQL (`SequelizeDao`) proposent des méthodes supplémentaires : - `findByPk(id)` - `findAll(options)` - `increment(params, field, by)` - `decrement(params, field, by)` - `upsert(data, options)` - `restore(params)` > Ces méthodes sont facultatives côté Mongo (non implémentées par défaut). ## Structure du Projet ``` src/ ├── config/ # Configuration (Swagger, etc.) ├── controllers/ # Contrôleurs REST ├── data/ # Données statiques ├── database/ # Configuration et accès DB │ ├── mongoose/ # Support MongoDB │ └── sequelize/ # Support SQL ├── services/ # Services (Transporter, Logger) ├── types/ # Types TypeScript ├── coddyger.ts # Fonctionnalités principales ├── globals.ts # Variables globales └── interface.ts # Interfaces TypeScript ``` ## Exports Toutes les classes et utilitaires principaux sont exportés par le module principal : ```typescript import { LoggerService, TransporterService, AxiosService, env, defines, LogLevel, getDatabaseAccess, MongoDbDao, MongooseDataAccess, SequelizeDataAccess, MigrationManager, // <--- Ajouté // etc. } from 'coddyger'; ``` ## Scripts ```bash npm start # Compile et exécute npm run dev # Compile et exécute avec nodemon npm run build # Compile TypeScript ``` ## Dépendances Principales - axios: ^1.x.x - Client HTTP - bcrypt: ^5.x.x - Hachage de mots de passe - date-fns: ^2.x.x - Manipulation de dates - dotenv: ^16.x.x - Variables d'environnement - kafkajs: ^2.x.x - Client Kafka - mongoose: ^7.x.x - ODM MongoDB - pino: ^8.x.x - Logger performant et structuré - pino-pretty: ^10.x.x - Formatage des logs en développement - sequelize: ^6.x.x - ORM SQL - libphonenumber-js: ^1.x.x - Validation de numéros de téléphone ## Licence MIT ## Auteur Jordan Gnazalé ## Support For support, email <grebejordan@gmail.com> or create an issue in the GitHub repository.