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
Markdown
# 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.