outlet-orm 5.5.1 → 5.5.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +259 -259
  2. package/package.json +3 -1
package/README.md CHANGED
@@ -3,14 +3,14 @@
3
3
  [![npm version](https://badge.fury.io/js/outlet-orm.svg)](https://www.npmjs.com/package/outlet-orm)
4
4
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
5
 
6
- Un ORM JavaScript inspiré de Laravel Eloquent pour Node.js avec support pour MySQL, PostgreSQL et SQLite.
6
+ Un ORM JavaScript inspired de Laravel Eloquent pour Node.js avec support pour MySQL, PostgreSQL et SQLite.
7
7
 
8
- 📚 **[Documentation complète disponible dans `/docs`](./docs/INDEX.md)**
8
+ 📚 **[Documentation complete available dans `/docs`](./docs/INDEX.md)**
9
9
 
10
- ## ✅ Prérequis et compatibilité
10
+ ## ✅ Prerequisites and compatibility
11
11
 
12
- - Node.js >= 18 (recommandé/exigé)
13
- - Installez le driver de base de données correspondant à votre SGBD (voir ci-dessous)
12
+ - Node.js >= 18 (recommended/required)
13
+ - Install the database driver corresponding to your DBMS (see below)
14
14
 
15
15
  ## 🚀 Installation
16
16
 
@@ -18,61 +18,61 @@ Un ORM JavaScript inspiré de Laravel Eloquent pour Node.js avec support pour My
18
18
  npm install outlet-orm
19
19
  ```
20
20
 
21
- ### Installer le driver de base de données
21
+ ### Install the database driver
22
22
 
23
- Outlet ORM utilise des peerDependencies optionnelles pour les drivers de base de données. Installez uniquement le driver dont vous avez besoin:
23
+ Outlet ORM utilise des peerDependencies optionnelles pour les drivers de database. Installez uniquement le driver dont vous avez besoin:
24
24
 
25
25
  - MySQL/MariaDB: `npm install mysql2`
26
26
  - PostgreSQL: `npm install pg`
27
27
  - SQLite: `npm install sqlite3`
28
28
 
29
- Si aucun driver n'est installé, un message d'erreur explicite vous indiquera lequel installer lors de la connexion.
29
+ If no driver is installed, an explicit error message will tell you which one to install when connecting.
30
30
 
31
- ## 📁 Structure de Projet Recommandée
31
+ ## 📁 Structure de Projet recommended
32
32
 
33
- Organisez votre projet utilisant Outlet ORM avec une **architecture en couches** (recommandée pour la production) :
33
+ Organisez votre projet utilisant Outlet ORM avec une **architecture en couches** (recommended pour la production) :
34
34
 
35
- > 🔐 **Sécurité** : Voir le [Guide de Sécurité](./docs/SECURITY.md) pour les bonnes pratiques.
35
+ > 🔐 **Sécurité** : See the [Security Guide](./docs/SECURITY.md) pour les bonnes pratiques.
36
36
 
37
37
  ```
38
38
  mon-projet/
39
- ├── .env # ⚠️ JAMAIS commité (dans .gitignore)
40
- ├── .env.example # Template sans secrets
39
+ ├── .env # ⚠️ JAMAIS committed (dans .gitignore)
40
+ ├── .env.example # Template without secrets
41
41
  ├── .gitignore
42
42
  ├── package.json
43
43
 
44
44
  ├── src/ # 📦 Code source centralisé
45
- │ ├── index.js # Point d'entrée de l'application
45
+ │ ├── index.js # Entry point de l'application
46
46
  │ │
47
47
  │ ├── config/ # ⚙️ Configuration
48
- │ │ ├── app.js # Config générale (port, env)
48
+ │ │ ├── app.js # General config (port, env)
49
49
  │ │ ├── database.js # Config DB (lit .env)
50
50
  │ │ └── security.js # CORS, helmet, rate limit
51
51
  │ │
52
- │ ├── models/ # 📊 Couche Data (Entities)
52
+ │ ├── models/ # 📊 Data Layer (Entities)
53
53
  │ │ ├── index.js # Export centralisé des models
54
54
  │ │ ├── User.js
55
55
  │ │ ├── Post.js
56
56
  │ │ └── Comment.js
57
57
  │ │
58
- │ ├── repositories/ # 🗄️ Couche Accès Données
59
- │ │ ├── BaseRepository.js # Méthodes CRUD génériques
60
- │ │ ├── UserRepository.js # Requêtes spécifiques User
58
+ │ ├── repositories/ # 🗄️ Data Access Layer
59
+ │ │ ├── BaseRepository.js # Generic CRUD methods
60
+ │ │ ├── UserRepository.js # Specific queries User
61
61
  │ │ └── PostRepository.js
62
62
  │ │
63
- │ ├── services/ # 💼 Couche Métier (Business Logic)
63
+ │ ├── services/ # 💼 Business Layer (Business Logic)
64
64
  │ │ ├── AuthService.js # Logique d'authentification
65
- │ │ ├── UserService.js # Logique métier utilisateur
65
+ │ │ ├── UserService.js # User business logic
66
66
  │ │ ├── PostService.js
67
67
  │ │ └── EmailService.js # Service externe (emails)
68
68
  │ │
69
- │ ├── controllers/ # 🎮 Couche Présentation (HTTP)
69
+ │ ├── controllers/ # 🎮 Presentation Layer (HTTP)
70
70
  │ │ ├── AuthController.js
71
71
  │ │ ├── UserController.js
72
72
  │ │ └── PostController.js
73
73
  │ │
74
- │ ├── routes/ # 🛤️ Définition des routes
75
- │ │ ├── index.js # Agrégateur de routes
74
+ │ ├── routes/ # 🛤️ Route definitions
75
+ │ │ ├── index.js # Route aggregator
76
76
  │ │ ├── auth.routes.js
77
77
  │ │ ├── user.routes.js
78
78
  │ │ └── post.routes.js
@@ -82,9 +82,9 @@ mon-projet/
82
82
  │ │ ├── authorize.js # RBAC / permissions
83
83
  │ │ ├── rateLimiter.js # Protection DDoS
84
84
  │ │ ├── validator.js # Validation request body
85
- │ │ └── errorHandler.js # Gestion centralisée erreurs
85
+ │ │ └── errorHandler.js # Gestion centralisede erreurs
86
86
  │ │
87
- │ ├── validators/ # ✅ Schémas de validation
87
+ │ ├── validators/ # ✅ Validation schemas
88
88
  │ │ ├── authValidator.js
89
89
  │ │ └── userValidator.js
90
90
  │ │
@@ -92,34 +92,34 @@ mon-projet/
92
92
  │ ├── hash.js # bcrypt wrapper
93
93
  │ ├── token.js # JWT helpers
94
94
  │ ├── logger.js # Winston/Pino config
95
- │ └── response.js # Formatage réponses API
95
+ │ └── response.js # API response formatting
96
96
 
97
97
  ├── database/
98
98
  │ ├── config.js # Config migrations (outlet-init)
99
- │ ├── migrations/ # Fichiers de migration
100
- │ └── seeds/ # Données de test/démo
99
+ │ ├── migrations/ # Migration files
100
+ │ └── seeds/ # Test/demo data
101
101
  │ └── UserSeeder.js
102
102
 
103
- ├── public/ # ✅ Fichiers statiques publics
103
+ ├── public/ # ✅ Public static files
104
104
  │ ├── images/
105
105
  │ ├── css/
106
106
  │ └── js/
107
107
 
108
- ├── uploads/ # ⚠️ Fichiers uploadés
108
+ ├── uploads/ # ⚠️ Uploaded files
109
109
 
110
- ├── logs/ # 📋 Journaux (non versionnés)
110
+ ├── logs/ # 📋 Journaux (not versioned)
111
111
 
112
112
  └── tests/ # 🧪 Tests
113
113
  ├── unit/ # Tests unitaires
114
114
  │ ├── services/
115
115
  │ └── models/
116
- ├── integration/ # Tests d'intégration
116
+ ├── integration/ # Integration tests
117
117
  │ └── api/
118
- └── fixtures/ # Données de test
118
+ └── fixtures/ # Test data
119
119
  └── users.json
120
120
  ```
121
121
 
122
- ### 🏗️ Architecture en Couches
122
+ ### 🏗️ Layered Architecture
123
123
 
124
124
  ```
125
125
  ┌─────────────────────────────────────────────────────────────┐
@@ -133,20 +133,20 @@ mon-projet/
133
133
 
134
134
 
135
135
  ┌─────────────────────────────────────────────────────────────┐
136
- │ ROUTES → CONTROLLERS (Couche Présentation) │
137
- Reçoit la requête, appelle le service, retourne réponse
136
+ │ ROUTES → CONTROLLERS (Presentation Layer) │
137
+ Receives the request, calls the service, returns a response
138
138
  └─────────────────────────────────────────────────────────────┘
139
139
 
140
140
 
141
141
  ┌─────────────────────────────────────────────────────────────┐
142
- │ SERVICES (Couche Métier / Business Logic) │
143
- │ Logique métier, orchestration, règles business │
142
+ │ SERVICES (Business Layer / Business Logic) │
143
+ │ Logique métier, orchestration, rules business │
144
144
  └─────────────────────────────────────────────────────────────┘
145
145
 
146
146
 
147
147
  ┌─────────────────────────────────────────────────────────────┐
148
- │ REPOSITORIES (Couche Accès Données) │
149
- │ Abstraction des requêtes DB, utilise les Models │
148
+ │ REPOSITORIES (Data Access Layer) │
149
+ │ Abstraction des queries DB, utilise les Models │
150
150
  └─────────────────────────────────────────────────────────────┘
151
151
 
152
152
 
@@ -155,23 +155,23 @@ mon-projet/
155
155
  └─────────────────────────────────────────────────────────────┘
156
156
  ```
157
157
 
158
- ### 📋 Rôle de chaque couche
158
+ ### 📋 Role of each layer
159
159
 
160
- | Couche | Dossier | Responsabilité | Dépend de |
160
+ | Layer | Folder | Responsibility | Depends on |
161
161
  |--------|---------|----------------|-----------|
162
- | **Présentation** | `controllers/` | Traiter HTTP, valider entrées, formater réponses | Services |
163
- | **Métier** | `services/` | Logique business, orchestration, règles | Repositories |
164
- | **Données** | `repositories/` | Requêtes DB complexes, abstraction | Models |
165
- | **Entités** | `models/` | Définition des entités, relations, validations | Outlet ORM |
162
+ | **Présentation** | `controllers/` | Handle HTTP, validate entrées, format responses | Services |
163
+ | **Métier** | `services/` | Logique business, orchestration, rules | Repositories |
164
+ | **Data** | `repositories/` | Complex DB queries, abstraction | Models |
165
+ | **Entities** | `models/` | Entity definitions, relationships, validations | Outlet ORM |
166
166
 
167
- ### ✅ Avantages de cette architecture
167
+ ### ✅ Benefits of this architecture
168
168
 
169
- - **Testabilité** : Chaque couche peut être testée indépendamment
170
- - **Maintenabilité** : Séparation claire des responsabilités
171
- - **Scalabilité** : Facile d'ajouter de nouvelles fonctionnalités
172
- - **Réutilisabilité** : Services utilisables depuis CLI, workers, etc.
169
+ - **Testability** : Each layer can be tested independently
170
+ - **Maintainability** : Clear separation of responsibilities
171
+ - **Scalability** : Easy to add new features
172
+ - **Reusability** : Services reusable from CLI, workers, etc.
173
173
 
174
- ### 📝 Exemple de flux
174
+ ### 📝 Example workflow
175
175
 
176
176
  ```javascript
177
177
  // routes/user.routes.js
@@ -196,71 +196,71 @@ async findWithPosts(id) {
196
196
  }
197
197
  ```
198
198
 
199
- ## ✨ Fonctionnalités clés
199
+ ## ✨ Key features
200
200
 
201
- - **API inspirée d'Eloquent** (Active Record) pour un usage fluide
201
+ - **API inspirede d'Eloquent** (Active Record) pour un usage fluide
202
202
  - **Query Builder expressif**: where/joins/order/limit/offset/paginate
203
- - **Filtres relationnels façon Laravel**: `whereHas()`, `has()`, `whereDoesntHave()`, `withCount()`
204
- - **Eager Loading** des relations via `.with(...)` avec contraintes et dot-notation
205
- - **Relations complètes**:
203
+ - **Relationship filters Laravel-style**: `whereHas()`, `has()`, `whereDoesntHave()`, `withCount()`
204
+ - **Eager Loading** des relationships via `.with(...)` avec constraints et dot-notation
205
+ - **Relations completes**:
206
206
  - `hasOne`, `hasMany`, `belongsTo`, `belongsToMany` (avec attach/detach/sync)
207
- - `hasManyThrough`, `hasOneThrough` (relations transitives)
208
- - `morphOne`, `morphMany`, `morphTo` (relations polymorphiques)
209
- - **Transactions** complètes: `beginTransaction()`, `commit()`, `rollback()`, `transaction()`
210
- - **Soft Deletes**: suppression logique avec `deleted_at`, `withTrashed()`, `onlyTrashed()`, `restore()`
211
- - **Scopes**: globaux et locaux pour réutiliser vos filtres
207
+ - `hasManyThrough`, `hasOneThrough` (relationships transitives)
208
+ - `morphOne`, `morphMany`, `morphTo` (relationships polymorphiques)
209
+ - **Transactions** completes: `beginTransaction()`, `commit()`, `rollback()`, `transaction()`
210
+ - **Soft Deletes**: soft deletion avec `deleted_at`, `withTrashed()`, `onlyTrashed()`, `restore()`
211
+ - **Scopes**: global and local to reuse your filters
212
212
  - **Events/Hooks**: `creating`, `created`, `updating`, `updated`, `deleting`, `deleted`, etc.
213
- - **Validation**: règles basiques intégrées (`required`, `email`, `min`, `max`, etc.)
213
+ - **Validation**: rules built-in basic (`required`, `email`, `min`, `max`, etc.)
214
214
  - **Query Logging**: mode debug avec `enableQueryLog()` et `getQueryLog()`
215
- - **Pool PostgreSQL**: connexions poolées pour de meilleures performances
215
+ - **Pool PostgreSQL**: pooled connections pour better performance
216
216
  - **Protection SQL**: sanitization automatique des identifiants
217
217
  - **Casts automatiques** (int, float, boolean, json, date...)
218
- - **Attributs masqués** (`hidden`) et timestamps automatiques
219
- - **Contrôle de visibilité** des attributs cachés: `withHidden()` et `withoutHidden()`
220
- - **Incrément/Décrément atomiques**: `increment()` et `decrement()`
218
+ - **Hidden attributes** (`hidden`) et timestamps automatiques
219
+ - **Visibility control** des attributs cachés: `withHidden()` et `withoutHidden()`
220
+ - **Atomic increment/decrement**: `increment()` et `decrement()`
221
221
  - **Aliases ergonomiques**: `columns([...])`, `ordrer()` (alias typo de `orderBy`)
222
- - **Requêtes brutes**: `executeRawQuery()` et `execute()` (résultats natifs du driver)
223
- - **Migrations complètes** (create/alter/drop, index, foreign keys, batch tracking)
222
+ - **Raw queries**: `executeRawQuery()` et `execute()` (native driver results)
223
+ - **Migrations completes** (create/alter/drop, index, foreign keys, batch tracking)
224
224
  - **CLI pratiques**: `outlet-init`, `outlet-migrate`, `outlet-convert`
225
- - **Configuration via `.env`** (chargée automatiquement)
226
- - **Multi-base de données**: MySQL, PostgreSQL et SQLite
227
- - **Types TypeScript complets** avec Generic Model et Schema Builder typé (v4.0.0+)
225
+ - **Configuration via `.env`** (loaded automatically)
226
+ - **Multi-database**: MySQL, PostgreSQL et SQLite
227
+ - **Complete TypeScript types** avec Generic Model et Schema Builder typed (v4.0.0+)
228
228
 
229
- ## ⚡ Démarrage Rapide
229
+ ## ⚡ Quick Start
230
230
 
231
231
  ### Initialisation du projet
232
232
 
233
233
  ```bash
234
- # Créer la configuration initiale
234
+ # Create la configuration initiale
235
235
  outlet-init
236
236
 
237
- # Créer une migration
237
+ # Create une migration
238
238
  outlet-migrate make create_users_table
239
239
 
240
- # Exécuter les migrations
240
+ # Run les migrations
241
241
  outlet-migrate migrate
242
242
  ```
243
243
 
244
244
  ### 🌱 Seeding rapide
245
245
 
246
246
  ```bash
247
- # Créer un seeder
247
+ # Create un seeder
248
248
  outlet-migrate make:seed UserSeeder
249
249
 
250
- # Exécuter les seeds (DatabaseSeeder prioritaire)
250
+ # Run les seeds (DatabaseSeeder prioritaire)
251
251
  outlet-migrate seed
252
252
 
253
- # Exécuter un seeder spécifique
253
+ # Run un specific seeder
254
254
  outlet-migrate seed --class UserSeeder
255
255
  ```
256
256
 
257
- ## 📖 Utilisation
257
+ ## 📖 Usage
258
258
 
259
- ### Configuration de la connexion
259
+ ### Connection configuration
260
260
 
261
- Outlet ORM charge automatiquement la connexion depuis le fichier `.env`. **Plus besoin d'importer DatabaseConnection !**
261
+ Outlet ORM charge automatiquement la connection depuis le file `.env`. **Plus besoin d'importer DatabaseConnection !**
262
262
 
263
- #### Fichier `.env`
263
+ #### `.env` file
264
264
 
265
265
  ```env
266
266
  DB_DRIVER=mysql
@@ -271,7 +271,7 @@ DB_PASSWORD=secret
271
271
  DB_PORT=3306
272
272
  ```
273
273
 
274
- #### Utilisation simplifiée
274
+ #### Simplified usage
275
275
 
276
276
  ```javascript
277
277
  const { Model } = require('outlet-orm');
@@ -280,18 +280,18 @@ class User extends Model {
280
280
  static table = 'users';
281
281
  }
282
282
 
283
- // C'est tout ! La connexion est automatique
283
+ // C'est tout ! La connection est automatique
284
284
  const users = await User.all();
285
285
  ```
286
286
 
287
- #### Configuration manuelle (optionnel)
287
+ #### Manual configuration (optional)
288
288
 
289
- Si vous avez besoin de contrôler la connexion :
289
+ If you need to control the connection :
290
290
 
291
291
  ```javascript
292
292
  const { DatabaseConnection, Model } = require('outlet-orm');
293
293
 
294
- // Option 1 – via .env (aucun paramètre nécessaire)
294
+ // Option 1 – via .env (no parameters required)
295
295
  const db = new DatabaseConnection();
296
296
 
297
297
  // Option 2 – via objet de configuration
@@ -304,48 +304,48 @@ const db = new DatabaseConnection({
304
304
  port: 3306
305
305
  });
306
306
 
307
- // Définir la connexion manuellement (optionnel)
307
+ // Définir la connection manuellement (optionnel)
308
308
  Model.setConnection(db);
309
309
  ```
310
310
 
311
- #### Variables d'environnement (.env)
311
+ #### Environment variables (.env)
312
312
 
313
- | Variable | Description | Par défaut |
313
+ | Variable | Description | Default |
314
314
  |----------|-------------|------------|
315
315
  | `DB_DRIVER` | `mysql`, `postgres`, `sqlite` | `mysql` |
316
316
  | `DB_HOST` | Hôte de la base | `localhost` |
317
- | `DB_PORT` | Port de connexion | Selon driver |
317
+ | `DB_PORT` | Port de connection | Selon driver |
318
318
  | `DB_USER` / `DB_USERNAME` | Identifiant | - |
319
319
  | `DB_PASSWORD` | Mot de passe | - |
320
320
  | `DB_DATABASE` / `DB_NAME` | Nom de la base | - |
321
- | `DB_FILE` / `SQLITE_DB` | Fichier SQLite | `:memory:` |
321
+ | `DB_FILE` / `SQLITE_DB` | SQLite file | `:memory:` |
322
322
 
323
323
  ### Importation
324
324
 
325
325
  ```javascript
326
- // CommonJS - Import simple (connexion automatique via .env)
326
+ // CommonJS - Import simple (connection automatique via .env)
327
327
  const { Model } = require('outlet-orm');
328
328
 
329
329
  // ES Modules
330
330
  import { Model } from 'outlet-orm';
331
331
 
332
- // Si besoin de contrôle manuel sur la connexion
332
+ // Si besoin de Manual control sur la connection
333
333
  const { DatabaseConnection, Model } = require('outlet-orm');
334
334
  ```
335
335
 
336
- ### Définir un modèle
336
+ ### Define a model
337
337
 
338
338
  ```javascript
339
339
  const { Model } = require('outlet-orm');
340
340
 
341
- // Définition des modèles liés (voir Relations)
341
+ // Define related models (see Relationships)
342
342
  class Post extends Model { static table = 'posts'; }
343
343
  class Profile extends Model { static table = 'profiles'; }
344
344
 
345
345
  class User extends Model {
346
346
  static table = 'users';
347
- static primaryKey = 'id'; // Par défaut: 'id'
348
- static timestamps = true; // Par défaut: true
347
+ static primaryKey = 'id'; // Default: 'id'
348
+ static timestamps = true; // Default: true
349
349
  static fillable = ['name', 'email', 'password'];
350
350
  static hidden = ['password'];
351
351
  static casts = {
@@ -366,19 +366,19 @@ class User extends Model {
366
366
  }
367
367
  ```
368
368
 
369
- ### Opérations CRUD
369
+ ### CRUD operations
370
370
 
371
- #### Créer
371
+ #### Create
372
372
 
373
373
  ```javascript
374
- // Méthode 1: create()
374
+ // Method 1: create()
375
375
  const user = await User.create({
376
376
  name: 'John Doe',
377
377
  email: 'john@example.com',
378
378
  password: 'secret123'
379
379
  });
380
380
 
381
- // Méthode 2: new + save()
381
+ // Method 2: new + save()
382
382
  const user = new User({
383
383
  name: 'Jane Doe',
384
384
  email: 'jane@example.com'
@@ -386,7 +386,7 @@ const user = new User({
386
386
  user.setAttribute('password', 'secret456');
387
387
  await user.save();
388
388
 
389
- // Insert brut (sans créer d'instance)
389
+ // Insert brut (sans create d'instance)
390
390
  await User.insert({ name: 'Bob', email: 'bob@example.com' });
391
391
  ```
392
392
 
@@ -398,9 +398,9 @@ const users = await User.all();
398
398
 
399
399
  // Par ID
400
400
  const user = await User.find(1);
401
- const user = await User.findOrFail(1); // Lance une erreur si non trouvé
401
+ const user = await User.findOrFail(1); // Throws an error if not found
402
402
 
403
- // Premier résultat
403
+ // First result
404
404
  const firstUser = await User.first();
405
405
 
406
406
  // Avec conditions
@@ -409,7 +409,7 @@ const activeUsers = await User
409
409
  .where('age', '>', 18)
410
410
  .get();
411
411
 
412
- // Avec relations (Eager Loading)
412
+ // Avec relationships (Eager Loading)
413
413
  const usersWithPosts = await User
414
414
  .with('posts', 'profile')
415
415
  .get();
@@ -421,7 +421,7 @@ const recentUsers = await User
421
421
  .get();
422
422
  ```
423
423
 
424
- #### Mettre à jour
424
+ #### Update
425
425
 
426
426
  ```javascript
427
427
  // Instance
@@ -444,7 +444,7 @@ const user = await User.updateAndFetchById(1, { name: 'Trinity' }, ['profile']);
444
444
  await User.updateById(2, { status: 'active' });
445
445
  ```
446
446
 
447
- #### Supprimer
447
+ #### Delete
448
448
 
449
449
  ```javascript
450
450
  // Instance
@@ -494,7 +494,7 @@ const result = await User
494
494
  .select('users.*', 'profiles.bio', 'countries.name as country')
495
495
  .get();
496
496
 
497
- // Agrégations
497
+ // Aggregations
498
498
  const stats = await User
499
499
  .distinct()
500
500
  .groupBy('status')
@@ -506,7 +506,7 @@ await User.where('id', 1).increment('login_count');
506
506
  await User.where('id', 1).decrement('credits', 10);
507
507
  ```
508
508
 
509
- ### Filtres relationnels
509
+ ### Relationship filters
510
510
 
511
511
  ```javascript
512
512
  // whereHas: Utilisateurs ayant au moins un post publié
@@ -519,7 +519,7 @@ const authors = await User
519
519
  // has: Au moins N enfants
520
520
  const prolific = await User.has('posts', '>=', 10).get();
521
521
 
522
- // whereDoesntHave: Aucun enfant
522
+ // whereDoesntHave: No children
523
523
  const noPostUsers = await User.whereDoesntHave('posts').get();
524
524
 
525
525
  // withCount: Ajouter une colonne {relation}_count
@@ -610,14 +610,14 @@ const user = await User.find(1);
610
610
  const roles = await user.roles().get();
611
611
 
612
612
  // Méthodes pivot
613
- await user.roles().attach([1, 2]); // Attacher des rôles
614
- await user.roles().detach(2); // Détacher un rôle
613
+ await user.roles().attach([1, 2]); // Attach roles
614
+ await user.roles().detach(2); // Detach a role
615
615
  await user.roles().sync([1, 3]); // Synchroniser (remplace tout)
616
616
  ```
617
617
 
618
618
  ### Has Many Through (hasManyThrough)
619
619
 
620
- Accéder à une relation distante via un modèle intermédiaire.
620
+ Access a distant relationship via an intermediate model.
621
621
 
622
622
  ```javascript
623
623
  const { Model } = require('outlet-orm');
@@ -649,9 +649,9 @@ const user = await User.find(1);
649
649
  const country = await user.country().get();
650
650
  ```
651
651
 
652
- ### Relations Polymorphiques
652
+ ### Polymorphic relationships
653
653
 
654
- Les relations polymorphiques permettent à un modèle d'appartenir à plusieurs autres modèles.
654
+ Polymorphic relationships allow a model to belong to multiple other models.
655
655
 
656
656
  ```javascript
657
657
  const { Model } = require('outlet-orm');
@@ -662,7 +662,7 @@ Model.setMorphMap({
662
662
  'videos': Video
663
663
  });
664
664
 
665
- // Modèles
665
+ // Models
666
666
  class Post extends Model {
667
667
  comments() {
668
668
  return this.morphMany(Comment, 'commentable');
@@ -689,7 +689,7 @@ const comment = await Comment.find(1);
689
689
  const parent = await comment.commentable().get(); // Post ou Video
690
690
  ```
691
691
 
692
- **Relations polymorphiques disponibles:**
692
+ **Relations polymorphiques availables:**
693
693
  - `morphOne(Related, 'morphName')` - One-to-One polymorphique
694
694
  - `morphMany(Related, 'morphName')` - One-to-Many polymorphique
695
695
  - `morphTo('morphName')` - Inverse polymorphique
@@ -697,15 +697,15 @@ const parent = await comment.commentable().get(); // Post ou Video
697
697
  ### Eager Loading
698
698
 
699
699
  ```javascript
700
- // Charger plusieurs relations
700
+ // Charger plusieurs relationships
701
701
  const users = await User.with('posts', 'profile', 'roles').get();
702
702
 
703
- // Charger avec contraintes
703
+ // Charger avec constraints
704
704
  const users = await User.with({
705
705
  posts: (q) => q.where('status', 'published').orderBy('created_at', 'desc')
706
706
  }).get();
707
707
 
708
- // Charger des relations imbriquées (dot notation)
708
+ // Load nested relationships (dot notation)
709
709
  const users = await User.with('posts.comments.author').get();
710
710
 
711
711
  // Charger sur une instance existante
@@ -713,10 +713,10 @@ const user = await User.find(1);
713
713
  await user.load('posts', 'profile');
714
714
  await user.load(['roles', 'posts.comments']);
715
715
 
716
- // Accéder aux relations chargées
716
+ // Access loaded relationships
717
717
  users.forEach(user => {
718
- console.log(user.relations.posts);
719
- console.log(user.relations.profile);
718
+ console.log(user.relationships.posts);
719
+ console.log(user.relationships.profile);
720
720
  });
721
721
  ```
722
722
 
@@ -742,7 +742,7 @@ class User extends Model {
742
742
  }
743
743
  ```
744
744
 
745
- ### Attributs cachés
745
+ ### Hidden attributes
746
746
 
747
747
  ```javascript
748
748
  const { Model } = require('outlet-orm');
@@ -755,21 +755,21 @@ const user = await User.find(1);
755
755
  console.log(user.toJSON()); // password et secret_token exclus
756
756
  ```
757
757
 
758
- #### Afficher les attributs cachés
758
+ #### Show hidden attributes
759
759
 
760
760
  ```javascript
761
- // Inclure les attributs cachés
761
+ // Include hidden attributes
762
762
  const user = await User.withHidden().where('email', 'john@example.com').first();
763
763
  console.log(user.toJSON()); // password inclus
764
764
 
765
- // Contrôler avec un booléen
765
+ // Control with a boolean
766
766
  const user = await User.withoutHidden(true).first(); // true = afficher
767
- const user = await User.withoutHidden(false).first(); // false = masquer (défaut)
767
+ const user = await User.withoutHidden(false).first(); // false = hide (default)
768
768
 
769
769
  // Cas d'usage: authentification
770
770
  const user = await User.withHidden().where('email', email).first();
771
771
  if (user && await bcrypt.compare(password, user.getAttribute('password'))) {
772
- // Authentification réussie
772
+ // Authentication successful
773
773
  }
774
774
  ```
775
775
 
@@ -778,12 +778,12 @@ if (user && await bcrypt.compare(password, user.getAttribute('password'))) {
778
778
  ```javascript
779
779
  const { Model } = require('outlet-orm');
780
780
 
781
- // Activés par défaut (created_at, updated_at)
781
+ // Activés Default (created_at, updated_at)
782
782
  class User extends Model {
783
783
  static timestamps = true;
784
784
  }
785
785
 
786
- // Désactiver
786
+ // Disable
787
787
  class Log extends Model {
788
788
  static timestamps = false;
789
789
  }
@@ -791,21 +791,21 @@ class Log extends Model {
791
791
 
792
792
  ## 🔄 Transactions
793
793
 
794
- Outlet ORM supporte les transactions pour garantir l'intégrité des données:
794
+ Outlet ORM supports transactions to guarantee data integrity:
795
795
 
796
796
  ```javascript
797
797
  const { DatabaseConnection, Model } = require('outlet-orm');
798
798
 
799
- // Méthode 1: Callback automatique (recommandé)
799
+ // Method 1: Automatic callback (recommended)
800
800
  const db = Model.connection;
801
801
  const result = await db.transaction(async (connection) => {
802
802
  const user = await User.create({ name: 'John', email: 'john@example.com' });
803
803
  await Account.create({ user_id: user.getAttribute('id'), balance: 0 });
804
804
  return user;
805
805
  });
806
- // Commit automatique, rollback si erreur
806
+ // Automatic commit, rollback on error
807
807
 
808
- // Méthode 2: Contrôle manuel
808
+ // Method 2: Manual control
809
809
  await db.beginTransaction();
810
810
  try {
811
811
  await User.create({ name: 'Jane' });
@@ -829,28 +829,28 @@ class Post extends Model {
829
829
  // static DELETED_AT = 'deleted_at'; // Personnalisable
830
830
  }
831
831
 
832
- // Les requêtes excluent automatiquement les supprimés
833
- const posts = await Post.all(); // Seulement les non-supprimés
832
+ // Les queries excluent automatiquement les deleteds
833
+ const posts = await Post.all(); // Seulement les non-deleteds
834
834
 
835
- // Inclure les supprimés
835
+ // Inclure les deleteds
836
836
  const allPosts = await Post.withTrashed().get();
837
837
 
838
- // Seulement les supprimés
838
+ // Seulement les deleteds
839
839
  const trashedPosts = await Post.onlyTrashed().get();
840
840
 
841
- // Supprimer (soft delete)
841
+ // Delete (soft delete)
842
842
  const post = await Post.find(1);
843
- await post.destroy(); // Met deleted_at à la date actuelle
843
+ await post.destroy(); // Sets deleted_at to the current date
844
844
 
845
- // Vérifier si supprimé
845
+ // Check if deleted
846
846
  if (post.trashed()) {
847
- console.log('Ce post est supprimé');
847
+ console.log('This post is deleted');
848
848
  }
849
849
 
850
850
  // Restaurer
851
851
  await post.restore();
852
852
 
853
- // Supprimer définitivement
853
+ // Delete permanently
854
854
  await post.forceDelete();
855
855
  ```
856
856
 
@@ -858,7 +858,7 @@ await post.forceDelete();
858
858
 
859
859
  ### Scopes Globaux
860
860
 
861
- Appliqués automatiquement à toutes les requêtes:
861
+ Applied automatically to all queries:
862
862
 
863
863
  ```javascript
864
864
  const { Model } = require('outlet-orm');
@@ -872,19 +872,19 @@ Post.addGlobalScope('published', (query) => {
872
872
  query.where('status', 'published');
873
873
  });
874
874
 
875
- // Toutes les requêtes filtrent automatiquement
876
- const posts = await Post.all(); // Seulement les publiés
875
+ // Toutes les queries filtrent automatiquement
876
+ const posts = await Post.all(); // Published only
877
877
 
878
- // Désactiver temporairement un scope
878
+ // Disable temporairement un scope
879
879
  const allPosts = await Post.withoutGlobalScope('published').get();
880
880
 
881
- // Désactiver tous les scopes
881
+ // Disable tous les scopes
882
882
  const rawPosts = await Post.withoutGlobalScopes().get();
883
883
  ```
884
884
 
885
885
  ## 📣 Events / Hooks
886
886
 
887
- Interceptez les opérations sur vos modèles:
887
+ Intercept operations on your models:
888
888
 
889
889
  ```javascript
890
890
  const { Model } = require('outlet-orm');
@@ -893,30 +893,30 @@ class User extends Model {
893
893
  static table = 'users';
894
894
  }
895
895
 
896
- // Avant création
896
+ // Before creation
897
897
  User.creating((user) => {
898
898
  user.setAttribute('uuid', generateUUID());
899
- // Retourner false pour annuler
899
+ // Retourner false pour rollback
900
900
  });
901
901
 
902
- // Après création
902
+ // After creation
903
903
  User.created((user) => {
904
904
  console.log(`Utilisateur ${user.getAttribute('id')} créé`);
905
905
  });
906
906
 
907
- // Avant mise à jour
907
+ // Before update
908
908
  User.updating((user) => {
909
909
  user.setAttribute('updated_at', new Date());
910
910
  });
911
911
 
912
- // Après mise à jour
912
+ // After update
913
913
  User.updated((user) => {
914
914
  // Notifier les systèmes externes
915
915
  });
916
916
 
917
- // Événements saving/saved (création ET mise à jour)
917
+ // saving/saved events (creation AND update)
918
918
  User.saving((user) => {
919
- // Nettoyage des données
919
+ // Nettoyage des data
920
920
  });
921
921
 
922
922
  User.saved((user) => {
@@ -925,11 +925,11 @@ User.saved((user) => {
925
925
 
926
926
  // Avant/après suppression
927
927
  User.deleting((user) => {
928
- // Vérifications avant suppression
928
+ // Checks before deletion
929
929
  });
930
930
 
931
931
  User.deleted((user) => {
932
- // Nettoyage des relations
932
+ // Nettoyage des relationships
933
933
  });
934
934
 
935
935
  // Pour les soft deletes
@@ -939,7 +939,7 @@ User.restored((user) => {});
939
939
 
940
940
  ## ✅ Validation
941
941
 
942
- Validation basique intégrée:
942
+ Built-in basic validation:
943
943
 
944
944
  ```javascript
945
945
  const { Model } = require('outlet-orm');
@@ -979,24 +979,24 @@ try {
979
979
  }
980
980
  ```
981
981
 
982
- ### Règles disponibles
982
+ ### Available rules
983
983
 
984
984
  | Règle | Description |
985
985
  |-------|-------------|
986
986
  | `required` | Champ obligatoire |
987
- | `string` | Doit être une chaîne |
988
- | `number` / `numeric` | Doit être un nombre |
987
+ | `string` | Must be a string |
988
+ | `number` / `numeric` | Must be a number |
989
989
  | `email` | Format email valide |
990
- | `boolean` | Doit être un booléen |
990
+ | `boolean` | Must be a boolean |
991
991
  | `date` | Date valide |
992
- | `min:N` | Minimum N (longueur ou valeur) |
993
- | `max:N` | Maximum N (longueur ou valeur) |
992
+ | `min:N` | Minimum N (longueur ou value) |
993
+ | `max:N` | Maximum N (longueur ou value) |
994
994
  | `in:a,b,c` | Valeur parmi la liste |
995
995
  | `regex:pattern` | Match le pattern regex |
996
996
 
997
997
  ## 📊 Query Logging
998
998
 
999
- Mode debug pour analyser vos requêtes:
999
+ Debug mode to analyse your queries:
1000
1000
 
1001
1001
  ```javascript
1002
1002
  const { Model } = require('outlet-orm');
@@ -1005,11 +1005,11 @@ const { Model } = require('outlet-orm');
1005
1005
  const db = Model.getConnection();
1006
1006
  db.enableQueryLog();
1007
1007
 
1008
- // Exécuter des requêtes
1008
+ // Run des queries
1009
1009
  await User.where('status', 'active').get();
1010
1010
  await Post.with('author').get();
1011
1011
 
1012
- // Récupérer le log
1012
+ // Retrieve the log
1013
1013
  const queries = db.getQueryLog();
1014
1014
  console.log(queries);
1015
1015
  // [
@@ -1020,10 +1020,10 @@ console.log(queries);
1020
1020
  // Vider le log
1021
1021
  db.flushQueryLog();
1022
1022
 
1023
- // Désactiver le logging
1023
+ // Disable le logging
1024
1024
  db.disableQueryLog();
1025
1025
 
1026
- // Vérifier si actif
1026
+ // Check if active
1027
1027
  if (db.isLogging()) {
1028
1028
  console.log('Logging actif');
1029
1029
  }
@@ -1033,39 +1033,39 @@ if (db.isLogging()) {
1033
1033
 
1034
1034
  ### DatabaseConnection
1035
1035
 
1036
- | Méthode | Description |
1036
+ | Method | Description |
1037
1037
  |---------|-------------|
1038
- | `new DatabaseConnection(config?)` | Crée une connexion (lit `.env` si config omis) |
1039
- | `connect()` | Établit la connexion (appelé automatiquement) |
1040
- | `beginTransaction()` | Démarre une transaction |
1038
+ | `new DatabaseConnection(config?)` | Creates a connection (lit `.env` si config omis) |
1039
+ | `connect()` | Establishes the connection (appelé automatiquement) |
1040
+ | `beginTransaction()` | Starts a transaction |
1041
1041
  | `commit()` | Valide la transaction |
1042
1042
  | `rollback()` | Annule la transaction |
1043
- | `transaction(callback)` | Exécute dans une transaction (auto commit/rollback) |
1044
- | `select(table, query)` | Exécute un SELECT |
1045
- | `insert(table, data)` | Insère un enregistrement |
1046
- | `insertMany(table, data[])` | Insère plusieurs enregistrements |
1047
- | `update(table, data, query)` | Met à jour des enregistrements |
1043
+ | `transaction(callback)` | Runs in a transaction (auto commit/rollback) |
1044
+ | `select(table, query)` | Runs a SELECT |
1045
+ | `insert(table, data)` | Inserts a record |
1046
+ | `insertMany(table, data[])` | Inserts multiple records |
1047
+ | `update(table, data, query)` | Updates records |
1048
1048
  | `delete(table, query)` | Supprime des enregistrements |
1049
1049
  | `count(table, query)` | Compte les enregistrements |
1050
1050
  | `executeRawQuery(sql, params?)` | Requête brute (résultats normalisés) |
1051
1051
  | `execute(sql, params?)` | Requête brute (résultats natifs driver) |
1052
1052
  | `increment(table, column, query, amount?)` | Incrément atomique |
1053
1053
  | `decrement(table, column, query, amount?)` | Décrément atomique |
1054
- | `close()` / `disconnect()` | Ferme la connexion |
1054
+ | `close()` / `disconnect()` | Ferme la connection |
1055
1055
  | **Query Logging (static)** | |
1056
- | `enableQueryLog()` | Active le logging des requêtes |
1056
+ | `enableQueryLog()` | Active le logging des queries |
1057
1057
  | `disableQueryLog()` | Désactive le logging |
1058
- | `getQueryLog()` | Retourne le log des requêtes |
1058
+ | `getQueryLog()` | Returns the query log |
1059
1059
  | `flushQueryLog()` | Vide le log |
1060
- | `isLogging()` | Vérifie si le logging est actif |
1060
+ | `isLogging()` | Checks whether logging is active |
1061
1061
 
1062
- ### Model (méthodes statiques)
1062
+ ### Model (methods statiques)
1063
1063
 
1064
- | Méthode | Description |
1064
+ | Method | Description |
1065
1065
  |---------|-------------|
1066
- | `setConnection(db)` | Définit la connexion par défaut |
1067
- | `getConnection()` | Récupère la connexion (v3.0.0+) |
1068
- | `setMorphMap(map)` | Définit le mapping polymorphique |
1066
+ | `setConnection(db)` | Définit la connection Default |
1067
+ | `getConnection()` | Gets the connection (v3.0.0+) |
1068
+ | `setMorphMap(map)` | Defines polymorphic mapping |
1069
1069
  | `query()` | Retourne un QueryBuilder |
1070
1070
  | `all()` | Tous les enregistrements |
1071
1071
  | `find(id)` | Trouve par ID |
@@ -1075,61 +1075,61 @@ if (db.isLogging()) {
1075
1075
  | `whereIn(col, vals)` | Clause WHERE IN |
1076
1076
  | `whereNull(col)` | Clause WHERE NULL |
1077
1077
  | `whereNotNull(col)` | Clause WHERE NOT NULL |
1078
- | `create(attrs)` | Crée et sauvegarde |
1078
+ | `create(attrs)` | Creates and saves |
1079
1079
  | `insert(data)` | Insert brut |
1080
1080
  | `update(attrs)` | Update bulk |
1081
1081
  | `updateById(id, attrs)` | Update par ID |
1082
- | `updateAndFetchById(id, attrs, rels?)` | Update + fetch avec relations |
1082
+ | `updateAndFetchById(id, attrs, rels?)` | Update + fetch avec relationships |
1083
1083
  | `delete()` | Delete bulk |
1084
1084
  | `with(...rels)` | Eager loading |
1085
- | `withHidden()` | Inclut les attributs cachés |
1085
+ | `withHidden()` | Includes hidden attributes |
1086
1086
  | `withoutHidden(show?)` | Contrôle visibilité |
1087
1087
  | `orderBy(col, dir?)` | Tri |
1088
1088
  | `limit(n)` / `offset(n)` | Limite/Offset |
1089
1089
  | `paginate(page, perPage)` | Pagination |
1090
1090
  | `count()` | Compte |
1091
1091
  | **Soft Deletes** | |
1092
- | `withTrashed()` | Inclut les supprimés |
1093
- | `onlyTrashed()` | Seulement les supprimés |
1092
+ | `withTrashed()` | Inclut les deleteds |
1093
+ | `onlyTrashed()` | Seulement les deleteds |
1094
1094
  | **Scopes** | |
1095
- | `addGlobalScope(name, cb)` | Ajoute un scope global |
1096
- | `removeGlobalScope(name)` | Supprime un scope |
1097
- | `withoutGlobalScope(name)` | Requête sans un scope |
1098
- | `withoutGlobalScopes()` | Requête sans tous les scopes |
1095
+ | `addGlobalScope(name, cb)` | Adds a global scope |
1096
+ | `removeGlobalScope(name)` | Removes a scope |
1097
+ | `withoutGlobalScope(name)` | Query without one scope |
1098
+ | `withoutGlobalScopes()` | Query without all scopes |
1099
1099
  | **Events** | |
1100
1100
  | `on(event, callback)` | Enregistre un listener |
1101
- | `creating(cb)` / `created(cb)` | Events création |
1102
- | `updating(cb)` / `updated(cb)` | Events mise à jour |
1101
+ | `creating(cb)` / `created(cb)` | Creation events |
1102
+ | `updating(cb)` / `updated(cb)` | Update events |
1103
1103
  | `saving(cb)` / `saved(cb)` | Events sauvegarde |
1104
1104
  | `deleting(cb)` / `deleted(cb)` | Events suppression |
1105
1105
  | `restoring(cb)` / `restored(cb)` | Events restauration |
1106
1106
 
1107
- ### Model (méthodes d'instance)
1107
+ ### Model (methods d'instance)
1108
1108
 
1109
- | Méthode | Description |
1109
+ | Method | Description |
1110
1110
  |---------|-------------|
1111
- | `fill(attrs)` | Remplit les attributs |
1112
- | `setAttribute(key, val)` | Définit un attribut |
1113
- | `getAttribute(key)` | Récupère un attribut |
1111
+ | `fill(attrs)` | Fills attributes |
1112
+ | `setAttribute(key, val)` | Sets an attribute |
1113
+ | `getAttribute(key)` | Gets an attribute |
1114
1114
  | `save()` | Sauvegarde (insert ou update) |
1115
1115
  | `destroy()` | Supprime l'instance (soft si activé) |
1116
- | `load(...rels)` | Charge des relations |
1116
+ | `load(...rels)` | Charge des relationships |
1117
1117
  | `getDirty()` | Attributs modifiés |
1118
- | `isDirty()` | A été modifié? |
1118
+ | `isDirty()` | Has been modified? |
1119
1119
  | `toJSON()` | Convertit en objet |
1120
1120
  | **Soft Deletes** | |
1121
- | `trashed()` | Est supprimé? |
1122
- | `restore()` | Restaure le modèle |
1123
- | `forceDelete()` | Suppression définitive |
1121
+ | `trashed()` | Is deleted? |
1122
+ | `restore()` | Restore le model |
1123
+ | `forceDelete()` | Permanent deletion |
1124
1124
  | **Validation** | |
1125
- | `validate()` | Valide selon les règles |
1125
+ | `validate()` | Valide selon les rules |
1126
1126
  | `validateOrFail()` | Valide ou lance erreur |
1127
1127
 
1128
1128
  ### QueryBuilder
1129
1129
 
1130
- | Méthode | Description |
1130
+ | Method | Description |
1131
1131
  |---------|-------------|
1132
- | `select(...cols)` / `columns([...])` | Sélection de colonnes |
1132
+ | `select(...cols)` / `columns([...])` | Column selection |
1133
1133
  | `distinct()` | SELECT DISTINCT |
1134
1134
  | `where(col, op?, val)` | Clause WHERE |
1135
1135
  | `whereIn(col, vals)` | WHERE IN |
@@ -1151,16 +1151,16 @@ if (db.isLogging()) {
1151
1151
  | `leftJoin(table, first, op?, second)` | LEFT JOIN |
1152
1152
  | `with(...rels)` | Eager loading |
1153
1153
  | `withCount(rels)` | Ajoute {rel}_count |
1154
- | `withTrashed()` | Inclut les supprimés |
1155
- | `onlyTrashed()` | Seulement les supprimés |
1154
+ | `withTrashed()` | Inclut les deleteds |
1155
+ | `onlyTrashed()` | Seulement les deleteds |
1156
1156
  | `withoutGlobalScope(name)` | Sans un scope global |
1157
1157
  | `withoutGlobalScopes()` | Sans tous les scopes |
1158
- | `get()` | Exécute et retourne tous |
1159
- | `first()` | Premier résultat |
1158
+ | `get()` | Runs and returns all |
1159
+ | `first()` | First result |
1160
1160
  | `firstOrFail()` | Premier ou erreur |
1161
1161
  | `paginate(page, perPage)` | Pagination |
1162
1162
  | `count()` | Compte |
1163
- | `exists()` | Vérifie l'existence |
1163
+ | `exists()` | Checks existence |
1164
1164
  | `insert(data)` | Insert |
1165
1165
  | `update(attrs)` | Update |
1166
1166
  | `updateAndFetch(attrs, rels?)` | Update + fetch |
@@ -1169,37 +1169,37 @@ if (db.isLogging()) {
1169
1169
  | `decrement(col, amount?)` | Décrément atomique |
1170
1170
  | `clone()` | Clone le query builder |
1171
1171
 
1172
- ## 🛠️ Outils CLI
1172
+ ## 🛠️ CLI tools
1173
1173
 
1174
1174
  ### outlet-init
1175
1175
 
1176
- Initialise un nouveau projet avec configuration de base de données.
1176
+ Initialise un nouveau projet avec configuration de database.
1177
1177
 
1178
1178
  ```bash
1179
1179
  outlet-init
1180
1180
  ```
1181
1181
 
1182
- Génère:
1183
- - Fichier de configuration `database/config.js`
1184
- - Fichier `.env` avec les paramètres
1185
- - Modèle exemple
1186
- - Fichier d'utilisation
1182
+ Generates:
1183
+ - Configuration file `database/config.js`
1184
+ - `.env` file with settings
1185
+ - Example model
1186
+ - Usage file
1187
1187
 
1188
1188
  ### outlet-migrate
1189
1189
 
1190
- Système complet de migrations.
1190
+ complete migration system.
1191
1191
 
1192
1192
  ```bash
1193
- # Créer une migration
1193
+ # Create une migration
1194
1194
  outlet-migrate make create_users_table
1195
1195
 
1196
- # Exécuter les migrations
1196
+ # Run les migrations
1197
1197
  outlet-migrate migrate
1198
1198
 
1199
- # Voir le statut
1199
+ # See le statut
1200
1200
  outlet-migrate status
1201
1201
 
1202
- # Annuler la dernière migration
1202
+ # Roll back the latest migration
1203
1203
  outlet-migrate rollback --steps 1
1204
1204
 
1205
1205
  # Reset toutes les migrations
@@ -1212,35 +1212,35 @@ outlet-migrate refresh --yes
1212
1212
  outlet-migrate fresh --yes
1213
1213
  ```
1214
1214
 
1215
- **Fonctionnalités des Migrations:**
1215
+ **Features des Migrations:**
1216
1216
 
1217
- - ✅ Création et gestion des migrations (create, alter, drop tables)
1217
+ - ✅ Creation and management of migrations (create, alter, drop tables)
1218
1218
  - ✅ Types de colonnes: id, string, text, integer, boolean, date, datetime, timestamp, decimal, float, json, enum, uuid, foreignId
1219
1219
  - ✅ Modificateurs: nullable, default, unique, index, unsigned, autoIncrement, comment, after, first
1220
- - ✅ Clés étrangères: foreign(), constrained(), onDelete(), onUpdate(), CASCADE
1220
+ - ✅ Foreign keys: foreign(), constrained(), onDelete(), onUpdate(), CASCADE
1221
1221
  - ✅ Index: index(), unique(), fullText()
1222
1222
  - ✅ Manipulation: renameColumn(), dropColumn(), dropTimestamps()
1223
- - ✅ Migrations réversibles: Méthodes up() et down()
1224
- - ✅ Batch tracking: Rollback précis par batch
1225
- - ✅ SQL personnalisé: execute() pour commandes avancées
1223
+ - ✅ Reversible migrations: Méthodes up() et down()
1224
+ - ✅ Batch tracking: Precise rollback by batch
1225
+ - ✅ Custom SQL: execute() pour advanced commands
1226
1226
 
1227
1227
  ### outlet-convert
1228
1228
 
1229
- Convertit des schémas SQL en modèles ORM.
1229
+ Converts SQL schemas into ORM models.
1230
1230
 
1231
1231
  ```bash
1232
1232
  outlet-convert
1233
1233
  ```
1234
1234
 
1235
1235
  **Options:**
1236
- 1. Depuis un fichier SQL local
1237
- 2. Depuis une base de données connectée
1238
-
1239
- **Fonctionnalités:**
1240
- - ✅ Détection automatique des types et casts
1241
- - ✅ Génération automatique de TOUTES les relations (belongsTo, hasMany, hasOne, belongsToMany)
1242
- - ✅ Relations récursives (auto-relations)
1243
- - ✅ Détection des champs sensibles (password, token, etc.)
1236
+ 1. Depuis un file SQL local
1237
+ 2. From a connected database
1238
+
1239
+ **Features:**
1240
+ - ✅ Detection automatique des types et casts
1241
+ - ✅ Automatic generation of ALL relationships (belongsTo, hasMany, hasOne, belongsToMany)
1242
+ - ✅ Recursive relationships (auto-relationships)
1243
+ - ✅ Detection des champs sensibles (password, token, etc.)
1244
1244
  - ✅ Support des timestamps automatiques
1245
1245
  - ✅ Conversion des noms en PascalCase
1246
1246
 
@@ -1248,16 +1248,16 @@ outlet-convert
1248
1248
 
1249
1249
  - [Guide des Migrations](docs/MIGRATIONS.md)
1250
1250
  - [Conversion SQL](docs/SQL_CONVERSION.md)
1251
- - [Détection des Relations](docs/RELATIONS_DETECTION.md)
1252
- - [Guide de démarrage rapide](docs/QUICKSTART.md)
1251
+ - [Detection des Relations](docs/RELATIONS_DETECTION.md)
1252
+ - [Quick Start Guide](docs/QUICKSTART.md)
1253
1253
  - [Architecture](docs/ARCHITECTURE.md)
1254
1254
  - [**TypeScript (complet)**](docs/TYPESCRIPT.md)
1255
1255
 
1256
1256
  ## 📘 TypeScript Support
1257
1257
 
1258
- Outlet ORM v4.0.0 inclut des définitions TypeScript complètes avec support des **generics pour les attributs typés**.
1258
+ Outlet ORM v4.0.0 inclut des définitions TypeScript completes avec support des **generics pour les attributs typeds**.
1259
1259
 
1260
- ### Modèles typés
1260
+ ### Typed models
1261
1261
 
1262
1262
  ```typescript
1263
1263
  import { Model, HasManyRelation } from 'outlet-orm';
@@ -1281,11 +1281,11 @@ class User extends Model<UserAttributes> {
1281
1281
 
1282
1282
  // Type-safe getAttribute/setAttribute
1283
1283
  const user = await User.find(1);
1284
- const name: string = user.getAttribute('name'); // ✅ Type inféré
1284
+ const name: string = user.getAttribute('name'); // ✅ Inferred type
1285
1285
  const role: 'admin' | 'user' = user.getAttribute('role');
1286
1286
  ```
1287
1287
 
1288
- ### Migrations typées
1288
+ ### Migrations typedes
1289
1289
 
1290
1290
  ```typescript
1291
1291
  import { MigrationInterface, Schema, TableBuilder } from 'outlet-orm';
@@ -1310,16 +1310,16 @@ export const migration: MigrationInterface = {
1310
1310
 
1311
1311
  📖 [Guide TypeScript complet](docs/TYPESCRIPT.md)
1312
1312
 
1313
- ## 🤝 Contribution
1313
+ ## 🤝 Contributions
1314
1314
 
1315
- Les contributions sont les bienvenues! N'hésitez pas à ouvrir une issue ou un pull request.
1315
+ Contributions are welcome! Feel free to open an issue or pull request.
1316
1316
 
1317
- Voir [CONTRIBUTING.md](CONTRIBUTING.md) pour les guidelines.
1317
+ See [CONTRIBUTING.md](CONTRIBUTING.md) for contribution guidelines.
1318
1318
 
1319
1319
  ## 📄 Licence
1320
1320
 
1321
- MIT - Voir [LICENSE](LICENSE) pour plus de détails.
1321
+ MIT - See [LICENSE](LICENSE) for details.
1322
1322
 
1323
1323
  ---
1324
1324
 
1325
- Créé par [omgbwa-yasse](https://github.com/omgbwa-yasse)
1325
+ Created by [omgbwa-yasse](https://github.com/omgbwa-yasse)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "outlet-orm",
3
- "version": "5.5.1",
3
+ "version": "5.5.2",
4
4
  "description": "A Laravel Eloquent-inspired ORM for Node.js with support for MySQL, PostgreSQL, and SQLite",
5
5
  "main": "src/index.js",
6
6
  "types": "types/index.d.ts",
@@ -21,6 +21,8 @@
21
21
  "test": "jest",
22
22
  "test:watch": "jest --watch",
23
23
  "test:coverage": "jest --coverage",
24
+ "check:version": "node scripts/check-changelog-version.js",
25
+ "prepublishOnly": "npm run check:version",
24
26
  "lint": "eslint \"{src,bin}/**/*.js\"",
25
27
  "lint:fix": "eslint \"{src,bin}/**/*.js\" --fix",
26
28
  "migrate": "node bin/migrate.js migrate",