outlet-orm 5.5.2 โ†’ 5.5.3

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 +217 -243
  2. package/package.json +1 -1
package/README.md CHANGED
@@ -3,9 +3,9 @@
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 inspired de Laravel Eloquent pour Node.js avec support pour MySQL, PostgreSQL et SQLite.
6
+ A JavaScript ORM inspired by Laravel Eloquent for Node.js with support for MySQL, PostgreSQL and SQLite.
7
7
 
8
- ๐Ÿ“š **[Documentation complete available dans `/docs`](./docs/INDEX.md)**
8
+ ๐Ÿ“š **[Complete documentation available in `/docs`](./docs/INDEX.md)**
9
9
 
10
10
  ## โœ… Prerequisites and compatibility
11
11
 
@@ -20,7 +20,7 @@ npm install outlet-orm
20
20
 
21
21
  ### Install the database driver
22
22
 
23
- Outlet ORM utilise des peerDependencies optionnelles pour les drivers de database. Installez uniquement le driver dont vous avez besoin:
23
+ Outlet ORM uses optional peer dependencies for database drivers. Install only the driver you need:
24
24
 
25
25
  - MySQL/MariaDB: `npm install mysql2`
26
26
  - PostgreSQL: `npm install pg`
@@ -28,45 +28,34 @@ Outlet ORM utilise des peerDependencies optionnelles pour les drivers de databas
28
28
 
29
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 recommended
31
+ ## ๐Ÿ“ Recommended Project Structure
32
32
 
33
- Organisez votre projet utilisant Outlet ORM avec une **architecture en couches** (recommended pour la production) :
33
+ Organise your project using Outlet ORM with a **2-layer architecture** โ€” Controllers call Models directly, keeping the codebase lean and productive:
34
34
 
35
- > ๐Ÿ” **Sรฉcuritรฉ** : See the [Security Guide](./docs/SECURITY.md) pour les bonnes pratiques.
35
+ > ๐Ÿ” **Security**: See the [Security Guide](./docs/SECURITY.md) for best practices.
36
36
 
37
37
  ```
38
- mon-projet/
39
- โ”œโ”€โ”€ .env # โš ๏ธ JAMAIS committed (dans .gitignore)
38
+ my-project/
39
+ โ”œโ”€โ”€ .env # โš ๏ธ NEVER committed (in .gitignore)
40
40
  โ”œโ”€โ”€ .env.example # Template without secrets
41
41
  โ”œโ”€โ”€ .gitignore
42
42
  โ”œโ”€โ”€ package.json
43
43
  โ”‚
44
- โ”œโ”€โ”€ src/ # ๐Ÿ“ฆ Code source centralisรฉ
45
- โ”‚ โ”œโ”€โ”€ index.js # Entry point de l'application
44
+ โ”œโ”€โ”€ src/ # ๐Ÿ“ฆ Centralised source code
45
+ โ”‚ โ”œโ”€โ”€ index.js # Application entry point
46
46
  โ”‚ โ”‚
47
47
  โ”‚ โ”œโ”€โ”€ config/ # โš™๏ธ Configuration
48
48
  โ”‚ โ”‚ โ”œโ”€โ”€ app.js # General config (port, env)
49
- โ”‚ โ”‚ โ”œโ”€โ”€ database.js # Config DB (lit .env)
49
+ โ”‚ โ”‚ โ”œโ”€โ”€ database.js # DB config (reads .env)
50
50
  โ”‚ โ”‚ โ””โ”€โ”€ security.js # CORS, helmet, rate limit
51
51
  โ”‚ โ”‚
52
- โ”‚ โ”œโ”€โ”€ models/ # ๐Ÿ“Š Data Layer (Entities)
53
- โ”‚ โ”‚ โ”œโ”€โ”€ index.js # Export centralisรฉ des models
52
+ โ”‚ โ”œโ”€โ”€ models/ # ๐Ÿ“Š outlet-orm Models (entities)
53
+ โ”‚ โ”‚ โ”œโ”€โ”€ index.js # Centralised model exports
54
54
  โ”‚ โ”‚ โ”œโ”€โ”€ User.js
55
55
  โ”‚ โ”‚ โ”œโ”€โ”€ Post.js
56
56
  โ”‚ โ”‚ โ””โ”€โ”€ Comment.js
57
57
  โ”‚ โ”‚
58
- โ”‚ โ”œโ”€โ”€ repositories/ # ๐Ÿ—„๏ธ Data Access Layer
59
- โ”‚ โ”‚ โ”œโ”€โ”€ BaseRepository.js # Generic CRUD methods
60
- โ”‚ โ”‚ โ”œโ”€โ”€ UserRepository.js # Specific queries User
61
- โ”‚ โ”‚ โ””โ”€โ”€ PostRepository.js
62
- โ”‚ โ”‚
63
- โ”‚ โ”œโ”€โ”€ services/ # ๐Ÿ’ผ Business Layer (Business Logic)
64
- โ”‚ โ”‚ โ”œโ”€โ”€ AuthService.js # Logique d'authentification
65
- โ”‚ โ”‚ โ”œโ”€โ”€ UserService.js # User business logic
66
- โ”‚ โ”‚ โ”œโ”€โ”€ PostService.js
67
- โ”‚ โ”‚ โ””โ”€โ”€ EmailService.js # Service externe (emails)
68
- โ”‚ โ”‚
69
- โ”‚ โ”œโ”€โ”€ controllers/ # ๐ŸŽฎ Presentation Layer (HTTP)
58
+ โ”‚ โ”œโ”€โ”€ controllers/ # ๐ŸŽฎ HTTP handling + business logic (direct ORM calls)
70
59
  โ”‚ โ”‚ โ”œโ”€โ”€ AuthController.js
71
60
  โ”‚ โ”‚ โ”œโ”€โ”€ UserController.js
72
61
  โ”‚ โ”‚ โ””โ”€โ”€ PostController.js
@@ -82,13 +71,13 @@ mon-projet/
82
71
  โ”‚ โ”‚ โ”œโ”€โ”€ authorize.js # RBAC / permissions
83
72
  โ”‚ โ”‚ โ”œโ”€โ”€ rateLimiter.js # Protection DDoS
84
73
  โ”‚ โ”‚ โ”œโ”€โ”€ validator.js # Validation request body
85
- โ”‚ โ”‚ โ””โ”€โ”€ errorHandler.js # Gestion centralisede erreurs
74
+ โ”‚ โ”‚ โ””โ”€โ”€ errorHandler.js # Centralised error handling
86
75
  โ”‚ โ”‚
87
76
  โ”‚ โ”œโ”€โ”€ validators/ # โœ… Validation schemas
88
77
  โ”‚ โ”‚ โ”œโ”€โ”€ authValidator.js
89
78
  โ”‚ โ”‚ โ””โ”€โ”€ userValidator.js
90
79
  โ”‚ โ”‚
91
- โ”‚ โ””โ”€โ”€ utils/ # ๐Ÿ”ง Utilitaires
80
+ โ”‚ โ””โ”€โ”€ utils/ # ๐Ÿ”ง Utilities
92
81
  โ”‚ โ”œโ”€โ”€ hash.js # bcrypt wrapper
93
82
  โ”‚ โ”œโ”€โ”€ token.js # JWT helpers
94
83
  โ”‚ โ”œโ”€โ”€ logger.js # Winston/Pino config
@@ -107,19 +96,17 @@ mon-projet/
107
96
  โ”‚
108
97
  โ”œโ”€โ”€ uploads/ # โš ๏ธ Uploaded files
109
98
  โ”‚
110
- โ”œโ”€โ”€ logs/ # ๐Ÿ“‹ Journaux (not versioned)
99
+ โ”œโ”€โ”€ logs/ # ๐Ÿ“‹ Logs (not versioned)
111
100
  โ”‚
112
101
  โ””โ”€โ”€ tests/ # ๐Ÿงช Tests
113
- โ”œโ”€โ”€ unit/ # Tests unitaires
114
- โ”‚ โ”œโ”€โ”€ services/
115
- โ”‚ โ””โ”€โ”€ models/
116
- โ”œโ”€โ”€ integration/ # Integration tests
102
+ โ”œโ”€โ”€ unit/ # Unit tests (models)
103
+ โ”œโ”€โ”€ integration/ # Integration tests (API)
117
104
  โ”‚ โ””โ”€โ”€ api/
118
105
  โ””โ”€โ”€ fixtures/ # Test data
119
106
  โ””โ”€โ”€ users.json
120
107
  ```
121
108
 
122
- ### ๐Ÿ—๏ธ Layered Architecture
109
+ ### ๐Ÿ—๏ธ Architecture Flow
123
110
 
124
111
  ```
125
112
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
@@ -133,43 +120,30 @@ mon-projet/
133
120
  โ”‚
134
121
  โ–ผ
135
122
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
136
- โ”‚ ROUTES โ†’ CONTROLLERS (Presentation Layer) โ”‚
137
- โ”‚ Receives the request, calls the service, returns a response โ”‚
138
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
139
- โ”‚
140
- โ–ผ
141
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
142
- โ”‚ SERVICES (Business Layer / Business Logic) โ”‚
143
- โ”‚ Logique mรฉtier, orchestration, rules business โ”‚
144
- โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
145
- โ”‚
146
- โ–ผ
147
- โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
148
- โ”‚ REPOSITORIES (Data Access Layer) โ”‚
149
- โ”‚ Abstraction des queries DB, utilise les Models โ”‚
123
+ โ”‚ ROUTES โ†’ CONTROLLERS HTTP handling + business logic โ”‚
124
+ โ”‚ Direct outlet-orm Model calls โ”‚
150
125
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
151
126
  โ”‚
152
127
  โ–ผ
153
128
  โ”Œโ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”
154
- โ”‚ MODELS (Outlet ORM) โ†’ DATABASE โ”‚
129
+ โ”‚ MODELS (outlet-orm) โ†’ DATABASE โ”‚
155
130
  โ””โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”˜
156
131
  ```
157
132
 
158
133
  ### ๐Ÿ“‹ Role of each layer
159
134
 
160
- | Layer | Folder | Responsibility | Depends on |
161
- |--------|---------|----------------|-----------|
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 |
135
+ | Layer | Folder | Responsibility | Security |
136
+ |--------|---------|----------------|----------|
137
+ | **Controllers** | `controllers/` | Handle HTTP, call ORM models, return responses | Input validation, ownership checks |
138
+ | **Models** | `models/` | Entity definition, relationships, validations | `fillable`, `hidden`, rules |
139
+ | **Middlewares** | `middlewares/` | Auth, rate limiting, error handling | ๐Ÿ”’ Critical |
166
140
 
167
141
  ### โœ… Benefits of this architecture
168
142
 
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.
143
+ - **Simplicity**: Less files, less abstraction, faster to navigate
144
+ - **Productivity**: Outlet ORM's expressive API handles data access directly
145
+ - **Testability**: Integration tests with SQLite in-memory cover full request flows
146
+ - **Flexibility**: Add a `services/` or `repositories/` layer later if complexity grows
173
147
 
174
148
  ### ๐Ÿ“ Example workflow
175
149
 
@@ -179,78 +153,78 @@ router.get('/users/:id', auth, UserController.show);
179
153
 
180
154
  // controllers/UserController.js
181
155
  async show(req, res) {
182
- const user = await userService.findById(req.params.id);
156
+ const user = await User.with('posts').find(req.params.id);
157
+ if (!user) return res.status(404).json({ message: 'User not found' });
183
158
  res.json({ data: user });
184
159
  }
185
160
 
186
- // services/UserService.js
187
- async findById(id) {
188
- const user = await userRepository.findWithPosts(id);
189
- if (!user) throw new NotFoundError('User not found');
190
- return user;
191
- }
161
+ async store(req, res) {
162
+ const existing = await User.where('email', req.body.email).first();
163
+ if (existing) return res.status(409).json({ message: 'Email already in use' });
164
+
165
+ const data = { ...req.body };
166
+ data.password = await bcrypt.hash(data.password, 10);
192
167
 
193
- // repositories/UserRepository.js
194
- async findWithPosts(id) {
195
- return User.with('posts').find(id);
168
+ const user = await User.create(data);
169
+ res.status(201).json({ success: true, data: user });
196
170
  }
197
171
  ```
198
172
 
199
173
  ## โœจ Key features
200
174
 
201
- - **API inspirede d'Eloquent** (Active Record) pour un usage fluide
202
- - **Query Builder expressif**: where/joins/order/limit/offset/paginate
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
- - `hasOne`, `hasMany`, `belongsTo`, `belongsToMany` (avec attach/detach/sync)
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
175
+ - **Eloquent-inspired API** (Active Record) for a fluent developer experience
176
+ - **Expressive Query Builder**: where/joins/order/limit/offset/paginate
177
+ - **Laravel-style relationship filters**: `whereHas()`, `has()`, `whereDoesntHave()`, `withCount()`
178
+ - **Eager Loading** of relationships via `.with(...)` with constraints and dot-notation
179
+ - **Complete relations**:
180
+ - `hasOne`, `hasMany`, `belongsTo`, `belongsToMany` (with attach/detach/sync)
181
+ - `hasManyThrough`, `hasOneThrough` (transitive relationships)
182
+ - `morphOne`, `morphMany`, `morphTo` (polymorphic relationships)
183
+ - **Complete Transactions**: `beginTransaction()`, `commit()`, `rollback()`, `transaction()`
184
+ - **Soft Deletes**: soft deletion with `deleted_at`, `withTrashed()`, `onlyTrashed()`, `restore()`
185
+ - **Scopes**: global and local, to reuse your query filters
212
186
  - **Events/Hooks**: `creating`, `created`, `updating`, `updated`, `deleting`, `deleted`, etc.
213
- - **Validation**: rules built-in basic (`required`, `email`, `min`, `max`, etc.)
214
- - **Query Logging**: mode debug avec `enableQueryLog()` et `getQueryLog()`
215
- - **Pool PostgreSQL**: pooled connections pour better performance
216
- - **Protection SQL**: sanitization automatique des identifiants
217
- - **Casts automatiques** (int, float, boolean, json, date...)
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
- - **Aliases ergonomiques**: `columns([...])`, `ordrer()` (alias typo de `orderBy`)
222
- - **Raw queries**: `executeRawQuery()` et `execute()` (native driver results)
223
- - **Migrations completes** (create/alter/drop, index, foreign keys, batch tracking)
224
- - **CLI pratiques**: `outlet-init`, `outlet-migrate`, `outlet-convert`
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+)
187
+ - **Validation**: built-in basic rules (`required`, `email`, `min`, `max`, etc.)
188
+ - **Query Logging**: debug mode with `enableQueryLog()` and `getQueryLog()`
189
+ - **PostgreSQL Pool**: pooled connections for better performance
190
+ - **SQL Protection**: automatic sanitisation of identifiers
191
+ - **Automatic Casts** (int, float, boolean, json, date...)
192
+ - **Hidden attributes** (`hidden`) and automatic timestamps
193
+ - **Visibility control** of hidden attributes: `withHidden()` and `withoutHidden()`
194
+ - **Atomic increment/decrement**: `increment()` and `decrement()`
195
+ - **Ergonomic aliases**: `columns([...])`, `ordrer()` (typo alias for `orderBy`)
196
+ - **Raw queries**: `executeRawQuery()` and `execute()` (native driver results)
197
+ - **Complete Migrations** (create/alter/drop, index, foreign keys, batch tracking)
198
+ - **Handy CLI tools**: `outlet-init`, `outlet-migrate`, `outlet-convert`
199
+ - **`.env` configuration** (loaded automatically)
200
+ - **Multi-database**: MySQL, PostgreSQL, and SQLite
201
+ - **Complete TypeScript types** with Generic Model and typed Schema Builder (v4.0.0+)
228
202
 
229
203
  ## โšก Quick Start
230
204
 
231
- ### Initialisation du projet
205
+ ### Project Initialisation
232
206
 
233
207
  ```bash
234
- # Create la configuration initiale
208
+ # Create initial configuration
235
209
  outlet-init
236
210
 
237
- # Create une migration
211
+ # Create a migration
238
212
  outlet-migrate make create_users_table
239
213
 
240
- # Run les migrations
214
+ # Run migrations
241
215
  outlet-migrate migrate
242
216
  ```
243
217
 
244
- ### ๐ŸŒฑ Seeding rapide
218
+ ### ๐ŸŒฑ Quick Seeding
245
219
 
246
220
  ```bash
247
- # Create un seeder
221
+ # Create a seeder
248
222
  outlet-migrate make:seed UserSeeder
249
223
 
250
- # Run les seeds (DatabaseSeeder prioritaire)
224
+ # Run seeders (DatabaseSeeder runs first)
251
225
  outlet-migrate seed
252
226
 
253
- # Run un specific seeder
227
+ # Run a specific seeder
254
228
  outlet-migrate seed --class UserSeeder
255
229
  ```
256
230
 
@@ -258,7 +232,7 @@ outlet-migrate seed --class UserSeeder
258
232
 
259
233
  ### Connection configuration
260
234
 
261
- Outlet ORM charge automatiquement la connection depuis le file `.env`. **Plus besoin d'importer DatabaseConnection !**
235
+ Outlet ORM automatically loads the connection from the `.env` file. **No need to import DatabaseConnection!**
262
236
 
263
237
  #### `.env` file
264
238
 
@@ -280,7 +254,7 @@ class User extends Model {
280
254
  static table = 'users';
281
255
  }
282
256
 
283
- // C'est tout ! La connection est automatique
257
+ // That's it! The connection is automatic
284
258
  const users = await User.all();
285
259
  ```
286
260
 
@@ -294,7 +268,7 @@ const { DatabaseConnection, Model } = require('outlet-orm');
294
268
  // Option 1 โ€“ via .env (no parameters required)
295
269
  const db = new DatabaseConnection();
296
270
 
297
- // Option 2 โ€“ via objet de configuration
271
+ // Option 2 โ€“ via configuration object
298
272
  const db = new DatabaseConnection({
299
273
  driver: 'mysql',
300
274
  host: 'localhost',
@@ -304,7 +278,7 @@ const db = new DatabaseConnection({
304
278
  port: 3306
305
279
  });
306
280
 
307
- // Dรฉfinir la connection manuellement (optionnel)
281
+ // Set the connection manually (optional)
308
282
  Model.setConnection(db);
309
283
  ```
310
284
 
@@ -313,23 +287,23 @@ Model.setConnection(db);
313
287
  | Variable | Description | Default |
314
288
  |----------|-------------|------------|
315
289
  | `DB_DRIVER` | `mysql`, `postgres`, `sqlite` | `mysql` |
316
- | `DB_HOST` | Hรดte de la base | `localhost` |
317
- | `DB_PORT` | Port de connection | Selon driver |
318
- | `DB_USER` / `DB_USERNAME` | Identifiant | - |
319
- | `DB_PASSWORD` | Mot de passe | - |
320
- | `DB_DATABASE` / `DB_NAME` | Nom de la base | - |
290
+ | `DB_HOST` | Database host | `localhost` |
291
+ | `DB_PORT` | Connection port | Driver default |
292
+ | `DB_USER` / `DB_USERNAME` | Username | - |
293
+ | `DB_PASSWORD` | Password | - |
294
+ | `DB_DATABASE` / `DB_NAME` | Database name | - |
321
295
  | `DB_FILE` / `SQLITE_DB` | SQLite file | `:memory:` |
322
296
 
323
297
  ### Importation
324
298
 
325
299
  ```javascript
326
- // CommonJS - Import simple (connection automatique via .env)
300
+ // CommonJS - Simple import (automatic connection via .env)
327
301
  const { Model } = require('outlet-orm');
328
302
 
329
303
  // ES Modules
330
304
  import { Model } from 'outlet-orm';
331
305
 
332
- // Si besoin de Manual control sur la connection
306
+ // If you need manual control over the connection
333
307
  const { DatabaseConnection, Model } = require('outlet-orm');
334
308
  ```
335
309
 
@@ -386,30 +360,30 @@ const user = new User({
386
360
  user.setAttribute('password', 'secret456');
387
361
  await user.save();
388
362
 
389
- // Insert brut (sans create d'instance)
363
+ // Raw insert (without creating an instance)
390
364
  await User.insert({ name: 'Bob', email: 'bob@example.com' });
391
365
  ```
392
366
 
393
- #### Lire
367
+ #### Read
394
368
 
395
369
  ```javascript
396
- // Tous les enregistrements
370
+ // All records
397
371
  const users = await User.all();
398
372
 
399
- // Par ID
373
+ // By ID
400
374
  const user = await User.find(1);
401
375
  const user = await User.findOrFail(1); // Throws an error if not found
402
376
 
403
377
  // First result
404
378
  const firstUser = await User.first();
405
379
 
406
- // Avec conditions
380
+ // With conditions
407
381
  const activeUsers = await User
408
382
  .where('status', 'active')
409
383
  .where('age', '>', 18)
410
384
  .get();
411
385
 
412
- // Avec relationships (Eager Loading)
386
+ // With relationships (Eager Loading)
413
387
  const usersWithPosts = await User
414
388
  .with('posts', 'profile')
415
389
  .get();
@@ -439,7 +413,7 @@ const updated = await User
439
413
  .where('id', 1)
440
414
  .updateAndFetch({ name: 'Neo' }, ['profile', 'posts']);
441
415
 
442
- // Helpers par ID
416
+ // Helpers by ID
443
417
  const user = await User.updateAndFetchById(1, { name: 'Trinity' }, ['profile']);
444
418
  await User.updateById(2, { status: 'active' });
445
419
  ```
@@ -501,7 +475,7 @@ const stats = await User
501
475
  .having('COUNT(*)', '>', 5)
502
476
  .get();
503
477
 
504
- // Incrรฉment / Dรฉcrรฉment atomique
478
+ // Atomic increment / decrement
505
479
  await User.where('id', 1).increment('login_count');
506
480
  await User.where('id', 1).decrement('credits', 10);
507
481
  ```
@@ -509,22 +483,22 @@ await User.where('id', 1).decrement('credits', 10);
509
483
  ### Relationship filters
510
484
 
511
485
  ```javascript
512
- // whereHas: Utilisateurs ayant au moins un post publiรฉ
486
+ // whereHas: Users who have at least one published post
513
487
  const authors = await User
514
488
  .whereHas('posts', (q) => {
515
489
  q.where('status', 'published');
516
490
  })
517
491
  .get();
518
492
 
519
- // has: Au moins N enfants
493
+ // has: At least N children
520
494
  const prolific = await User.has('posts', '>=', 10).get();
521
495
 
522
496
  // whereDoesntHave: No children
523
497
  const noPostUsers = await User.whereDoesntHave('posts').get();
524
498
 
525
- // withCount: Ajouter une colonne {relation}_count
499
+ // withCount: Add a {relation}_count column
526
500
  const withCounts = await User.withCount('posts').get();
527
- // Chaque user aura: user.getAttribute('posts_count')
501
+ // Each user will have: user.getAttribute('posts_count')
528
502
  ```
529
503
 
530
504
  ## ๐Ÿ”— Relations
@@ -609,10 +583,10 @@ class User extends Model {
609
583
  const user = await User.find(1);
610
584
  const roles = await user.roles().get();
611
585
 
612
- // Mรฉthodes pivot
586
+ // Pivot methods
613
587
  await user.roles().attach([1, 2]); // Attach roles
614
588
  await user.roles().detach(2); // Detach a role
615
- await user.roles().sync([1, 3]); // Synchroniser (remplace tout)
589
+ await user.roles().sync([1, 3]); // Synchronise (replaces all)
616
590
  ```
617
591
 
618
592
  ### Has Many Through (hasManyThrough)
@@ -656,7 +630,7 @@ Polymorphic relationships allow a model to belong to multiple other models.
656
630
  ```javascript
657
631
  const { Model } = require('outlet-orm');
658
632
 
659
- // Configuration du morph map
633
+ // Set up the morph map
660
634
  Model.setMorphMap({
661
635
  'posts': Post,
662
636
  'videos': Video
@@ -686,21 +660,21 @@ const post = await Post.find(1);
686
660
  const comments = await post.comments().get();
687
661
 
688
662
  const comment = await Comment.find(1);
689
- const parent = await comment.commentable().get(); // Post ou Video
663
+ const parent = await comment.commentable().get(); // Post or Video
690
664
  ```
691
665
 
692
- **Relations polymorphiques availables:**
693
- - `morphOne(Related, 'morphName')` - One-to-One polymorphique
694
- - `morphMany(Related, 'morphName')` - One-to-Many polymorphique
695
- - `morphTo('morphName')` - Inverse polymorphique
666
+ **Available polymorphic relationships:**
667
+ - `morphOne(Related, 'morphName')` - One-to-One polymorphic
668
+ - `morphMany(Related, 'morphName')` - One-to-Many polymorphic
669
+ - `morphTo('morphName')` - Inverse polymorphic
696
670
 
697
671
  ### Eager Loading
698
672
 
699
673
  ```javascript
700
- // Charger plusieurs relationships
674
+ // Load multiple relationships
701
675
  const users = await User.with('posts', 'profile', 'roles').get();
702
676
 
703
- // Charger avec constraints
677
+ // Load with constraints
704
678
  const users = await User.with({
705
679
  posts: (q) => q.where('status', 'published').orderBy('created_at', 'desc')
706
680
  }).get();
@@ -708,7 +682,7 @@ const users = await User.with({
708
682
  // Load nested relationships (dot notation)
709
683
  const users = await User.with('posts.comments.author').get();
710
684
 
711
- // Charger sur une instance existante
685
+ // Load on an existing instance
712
686
  const user = await User.find(1);
713
687
  await user.load('posts', 'profile');
714
688
  await user.load(['roles', 'posts.comments']);
@@ -724,7 +698,7 @@ users.forEach(user => {
724
698
 
725
699
  ### Casts
726
700
 
727
- Les casts convertissent automatiquement les attributs:
701
+ Casts automatically convert attributes:
728
702
 
729
703
  ```javascript
730
704
  const { Model } = require('outlet-orm');
@@ -736,8 +710,8 @@ class User extends Model {
736
710
  balance: 'float', // ou 'double'
737
711
  email_verified: 'boolean', // ou 'bool'
738
712
  metadata: 'json', // Parse JSON
739
- settings: 'array', // Parse JSON en array
740
- birthday: 'date' // Convertit en Date
713
+ settings: 'array', // Parse JSON as array
714
+ birthday: 'date' // Converts to Date
741
715
  };
742
716
  }
743
717
  ```
@@ -752,7 +726,7 @@ class User extends Model {
752
726
  }
753
727
 
754
728
  const user = await User.find(1);
755
- console.log(user.toJSON()); // password et secret_token exclus
729
+ console.log(user.toJSON()); // password and secret_token excluded
756
730
  ```
757
731
 
758
732
  #### Show hidden attributes
@@ -760,13 +734,13 @@ console.log(user.toJSON()); // password et secret_token exclus
760
734
  ```javascript
761
735
  // Include hidden attributes
762
736
  const user = await User.withHidden().where('email', 'john@example.com').first();
763
- console.log(user.toJSON()); // password inclus
737
+ console.log(user.toJSON()); // password included
764
738
 
765
739
  // Control with a boolean
766
- const user = await User.withoutHidden(true).first(); // true = afficher
740
+ const user = await User.withoutHidden(true).first(); // true = show
767
741
  const user = await User.withoutHidden(false).first(); // false = hide (default)
768
742
 
769
- // Cas d'usage: authentification
743
+ // Use case: authentication
770
744
  const user = await User.withHidden().where('email', email).first();
771
745
  if (user && await bcrypt.compare(password, user.getAttribute('password'))) {
772
746
  // Authentication successful
@@ -778,7 +752,7 @@ if (user && await bcrypt.compare(password, user.getAttribute('password'))) {
778
752
  ```javascript
779
753
  const { Model } = require('outlet-orm');
780
754
 
781
- // Activรฉs Default (created_at, updated_at)
755
+ // Enabled by default (created_at, updated_at)
782
756
  class User extends Model {
783
757
  static timestamps = true;
784
758
  }
@@ -818,7 +792,7 @@ try {
818
792
 
819
793
  ## ๐Ÿ—‘๏ธ Soft Deletes
820
794
 
821
- Suppression logique avec colonne `deleted_at`:
795
+ Soft deletion using a `deleted_at` column:
822
796
 
823
797
  ```javascript
824
798
  const { Model } = require('outlet-orm');
@@ -826,16 +800,16 @@ const { Model } = require('outlet-orm');
826
800
  class Post extends Model {
827
801
  static table = 'posts';
828
802
  static softDeletes = true;
829
- // static DELETED_AT = 'deleted_at'; // Personnalisable
803
+ // static DELETED_AT = 'deleted_at'; // Customisable
830
804
  }
831
805
 
832
- // Les queries excluent automatiquement les deleteds
833
- const posts = await Post.all(); // Seulement les non-deleteds
806
+ // Queries automatically exclude soft-deleted records
807
+ const posts = await Post.all(); // Only non-deleted records
834
808
 
835
- // Inclure les deleteds
809
+ // Include deleted records
836
810
  const allPosts = await Post.withTrashed().get();
837
811
 
838
- // Seulement les deleteds
812
+ // Only deleted records
839
813
  const trashedPosts = await Post.onlyTrashed().get();
840
814
 
841
815
  // Delete (soft delete)
@@ -867,18 +841,18 @@ class Post extends Model {
867
841
  static table = 'posts';
868
842
  }
869
843
 
870
- // Ajouter un scope global
844
+ // Add a global scope
871
845
  Post.addGlobalScope('published', (query) => {
872
846
  query.where('status', 'published');
873
847
  });
874
848
 
875
- // Toutes les queries filtrent automatiquement
849
+ // All queries filter automatically
876
850
  const posts = await Post.all(); // Published only
877
851
 
878
- // Disable temporairement un scope
852
+ // Temporarily disable a scope
879
853
  const allPosts = await Post.withoutGlobalScope('published').get();
880
854
 
881
- // Disable tous les scopes
855
+ // Disable all scopes
882
856
  const rawPosts = await Post.withoutGlobalScopes().get();
883
857
  ```
884
858
 
@@ -896,12 +870,12 @@ class User extends Model {
896
870
  // Before creation
897
871
  User.creating((user) => {
898
872
  user.setAttribute('uuid', generateUUID());
899
- // Retourner false pour rollback
873
+ // Return false to roll back
900
874
  });
901
875
 
902
876
  // After creation
903
877
  User.created((user) => {
904
- console.log(`Utilisateur ${user.getAttribute('id')} crรฉรฉ`);
878
+ console.log(`User ${user.getAttribute('id')} created`);
905
879
  });
906
880
 
907
881
  // Before update
@@ -911,28 +885,28 @@ User.updating((user) => {
911
885
 
912
886
  // After update
913
887
  User.updated((user) => {
914
- // Notifier les systรจmes externes
888
+ // Notify external systems
915
889
  });
916
890
 
917
891
  // saving/saved events (creation AND update)
918
892
  User.saving((user) => {
919
- // Nettoyage des data
893
+ // Data cleanup
920
894
  });
921
895
 
922
896
  User.saved((user) => {
923
897
  // Cache invalidation
924
898
  });
925
899
 
926
- // Avant/aprรจs suppression
900
+ // Before/after deletion
927
901
  User.deleting((user) => {
928
902
  // Checks before deletion
929
903
  });
930
904
 
931
905
  User.deleted((user) => {
932
- // Nettoyage des relationships
906
+ // Clean up relationships
933
907
  });
934
908
 
935
- // Pour les soft deletes
909
+ // For soft deletes
936
910
  User.restoring((user) => {});
937
911
  User.restored((user) => {});
938
912
  ```
@@ -971,7 +945,7 @@ console.log(errors);
971
945
  // age: ['age must not exceed 150']
972
946
  // }
973
947
 
974
- // Valider ou lancer une erreur
948
+ // Validate or throw an error
975
949
  try {
976
950
  user.validateOrFail();
977
951
  } catch (error) {
@@ -981,14 +955,14 @@ try {
981
955
 
982
956
  ### Available rules
983
957
 
984
- | Rรจgle | Description |
958
+ | Rule | Description |
985
959
  |-------|-------------|
986
- | `required` | Champ obligatoire |
960
+ | `required` | Required field |
987
961
  | `string` | Must be a string |
988
962
  | `number` / `numeric` | Must be a number |
989
- | `email` | Format email valide |
963
+ | `email` | Valid email format |
990
964
  | `boolean` | Must be a boolean |
991
- | `date` | Date valide |
965
+ | `date` | Valid date |
992
966
  | `min:N` | Minimum N (longueur ou value) |
993
967
  | `max:N` | Maximum N (longueur ou value) |
994
968
  | `in:a,b,c` | Valeur parmi la liste |
@@ -1005,7 +979,7 @@ const { Model } = require('outlet-orm');
1005
979
  const db = Model.getConnection();
1006
980
  db.enableQueryLog();
1007
981
 
1008
- // Run des queries
982
+ // Run queries
1009
983
  await User.where('status', 'active').get();
1010
984
  await Post.with('author').get();
1011
985
 
@@ -1025,7 +999,7 @@ db.disableQueryLog();
1025
999
 
1026
1000
  // Check if active
1027
1001
  if (db.isLogging()) {
1028
- console.log('Logging actif');
1002
+ console.log('Logging active');
1029
1003
  }
1030
1004
  ```
1031
1005
 
@@ -1035,95 +1009,95 @@ if (db.isLogging()) {
1035
1009
 
1036
1010
  | Method | Description |
1037
1011
  |---------|-------------|
1038
- | `new DatabaseConnection(config?)` | Creates a connection (lit `.env` si config omis) |
1039
- | `connect()` | Establishes the connection (appelรฉ automatiquement) |
1012
+ | `new DatabaseConnection(config?)` | Creates a connection (reads `.env` if config is omitted) |
1013
+ | `connect()` | Establishes the connection (called automatically) |
1040
1014
  | `beginTransaction()` | Starts a transaction |
1041
- | `commit()` | Valide la transaction |
1042
- | `rollback()` | Annule la transaction |
1015
+ | `commit()` | Commits the transaction |
1016
+ | `rollback()` | Rolls back the transaction |
1043
1017
  | `transaction(callback)` | Runs in a transaction (auto commit/rollback) |
1044
1018
  | `select(table, query)` | Runs a SELECT |
1045
1019
  | `insert(table, data)` | Inserts a record |
1046
1020
  | `insertMany(table, data[])` | Inserts multiple records |
1047
1021
  | `update(table, data, query)` | Updates records |
1048
- | `delete(table, query)` | Supprime des enregistrements |
1049
- | `count(table, query)` | Compte les enregistrements |
1050
- | `executeRawQuery(sql, params?)` | Requรชte brute (rรฉsultats normalisรฉs) |
1051
- | `execute(sql, params?)` | Requรชte brute (rรฉsultats natifs driver) |
1052
- | `increment(table, column, query, amount?)` | Incrรฉment atomique |
1053
- | `decrement(table, column, query, amount?)` | Dรฉcrรฉment atomique |
1054
- | `close()` / `disconnect()` | Ferme la connection |
1022
+ | `delete(table, query)` | Deletes records |
1023
+ | `count(table, query)` | Counts records |
1024
+ | `executeRawQuery(sql, params?)` | Raw query (normalised results) |
1025
+ | `execute(sql, params?)` | Raw query (native driver results) |
1026
+ | `increment(table, column, query, amount?)` | Atomic increment |
1027
+ | `decrement(table, column, query, amount?)` | Atomic decrement |
1028
+ | `close()` / `disconnect()` | Closes the connection |
1055
1029
  | **Query Logging (static)** | |
1056
- | `enableQueryLog()` | Active le logging des queries |
1057
- | `disableQueryLog()` | Dรฉsactive le logging |
1030
+ | `enableQueryLog()` | Enables query logging |
1031
+ | `disableQueryLog()` | Disables logging |
1058
1032
  | `getQueryLog()` | Returns the query log |
1059
- | `flushQueryLog()` | Vide le log |
1033
+ | `flushQueryLog()` | Clears the log |
1060
1034
  | `isLogging()` | Checks whether logging is active |
1061
1035
 
1062
- ### Model (methods statiques)
1036
+ ### Model (static methods)
1063
1037
 
1064
1038
  | Method | Description |
1065
1039
  |---------|-------------|
1066
- | `setConnection(db)` | Dรฉfinit la connection Default |
1040
+ | `setConnection(db)` | Sets the default connection |
1067
1041
  | `getConnection()` | Gets the connection (v3.0.0+) |
1068
1042
  | `setMorphMap(map)` | Defines polymorphic mapping |
1069
- | `query()` | Retourne un QueryBuilder |
1070
- | `all()` | Tous les enregistrements |
1071
- | `find(id)` | Trouve par ID |
1072
- | `findOrFail(id)` | Trouve ou lance une erreur |
1073
- | `first()` | Premier enregistrement |
1043
+ | `query()` | Returns a QueryBuilder |
1044
+ | `all()` | All records |
1045
+ | `find(id)` | Finds by ID |
1046
+ | `findOrFail(id)` | Finds or throws an error |
1047
+ | `first()` | First record |
1074
1048
  | `where(col, op?, val)` | Clause WHERE |
1075
1049
  | `whereIn(col, vals)` | Clause WHERE IN |
1076
1050
  | `whereNull(col)` | Clause WHERE NULL |
1077
1051
  | `whereNotNull(col)` | Clause WHERE NOT NULL |
1078
1052
  | `create(attrs)` | Creates and saves |
1079
- | `insert(data)` | Insert brut |
1053
+ | `insert(data)` | Raw insert |
1080
1054
  | `update(attrs)` | Update bulk |
1081
- | `updateById(id, attrs)` | Update par ID |
1082
- | `updateAndFetchById(id, attrs, rels?)` | Update + fetch avec relationships |
1055
+ | `updateById(id, attrs)` | Update by ID |
1056
+ | `updateAndFetchById(id, attrs, rels?)` | Update + fetch with relationships |
1083
1057
  | `delete()` | Delete bulk |
1084
1058
  | `with(...rels)` | Eager loading |
1085
1059
  | `withHidden()` | Includes hidden attributes |
1086
- | `withoutHidden(show?)` | Contrรดle visibilitรฉ |
1087
- | `orderBy(col, dir?)` | Tri |
1088
- | `limit(n)` / `offset(n)` | Limite/Offset |
1060
+ | `withoutHidden(show?)` | Control attribute visibility |
1061
+ | `orderBy(col, dir?)` | Sort |
1062
+ | `limit(n)` / `offset(n)` | Limit/Offset |
1089
1063
  | `paginate(page, perPage)` | Pagination |
1090
- | `count()` | Compte |
1064
+ | `count()` | Count |
1091
1065
  | **Soft Deletes** | |
1092
- | `withTrashed()` | Inclut les deleteds |
1093
- | `onlyTrashed()` | Seulement les deleteds |
1066
+ | `withTrashed()` | Includes soft-deleted records |
1067
+ | `onlyTrashed()` | Only soft-deleted records |
1094
1068
  | **Scopes** | |
1095
1069
  | `addGlobalScope(name, cb)` | Adds a global scope |
1096
1070
  | `removeGlobalScope(name)` | Removes a scope |
1097
1071
  | `withoutGlobalScope(name)` | Query without one scope |
1098
1072
  | `withoutGlobalScopes()` | Query without all scopes |
1099
1073
  | **Events** | |
1100
- | `on(event, callback)` | Enregistre un listener |
1074
+ | `on(event, callback)` | Registers a listener |
1101
1075
  | `creating(cb)` / `created(cb)` | Creation events |
1102
1076
  | `updating(cb)` / `updated(cb)` | Update events |
1103
- | `saving(cb)` / `saved(cb)` | Events sauvegarde |
1104
- | `deleting(cb)` / `deleted(cb)` | Events suppression |
1105
- | `restoring(cb)` / `restored(cb)` | Events restauration |
1077
+ | `saving(cb)` / `saved(cb)` | Save events |
1078
+ | `deleting(cb)` / `deleted(cb)` | Delete events |
1079
+ | `restoring(cb)` / `restored(cb)` | Restore events |
1106
1080
 
1107
- ### Model (methods d'instance)
1081
+ ### Model (instance methods)
1108
1082
 
1109
1083
  | Method | Description |
1110
1084
  |---------|-------------|
1111
1085
  | `fill(attrs)` | Fills attributes |
1112
1086
  | `setAttribute(key, val)` | Sets an attribute |
1113
1087
  | `getAttribute(key)` | Gets an attribute |
1114
- | `save()` | Sauvegarde (insert ou update) |
1115
- | `destroy()` | Supprime l'instance (soft si activรฉ) |
1116
- | `load(...rels)` | Charge des relationships |
1117
- | `getDirty()` | Attributs modifiรฉs |
1088
+ | `save()` | Save (insert or update) |
1089
+ | `destroy()` | Delete the instance (soft if enabled) |
1090
+ | `load(...rels)` | Load relationships |
1091
+ | `getDirty()` | Modified attributes |
1118
1092
  | `isDirty()` | Has been modified? |
1119
- | `toJSON()` | Convertit en objet |
1093
+ | `toJSON()` | Convert to plain object |
1120
1094
  | **Soft Deletes** | |
1121
1095
  | `trashed()` | Is deleted? |
1122
- | `restore()` | Restore le model |
1096
+ | `restore()` | Restore the model |
1123
1097
  | `forceDelete()` | Permanent deletion |
1124
1098
  | **Validation** | |
1125
- | `validate()` | Valide selon les rules |
1126
- | `validateOrFail()` | Valide ou lance erreur |
1099
+ | `validate()` | Validate against rules |
1100
+ | `validateOrFail()` | Validate or throw error |
1127
1101
 
1128
1102
  ### QueryBuilder
1129
1103
 
@@ -1139,22 +1113,22 @@ if (db.isLogging()) {
1139
1113
  | `orWhere(col, op?, val)` | OR WHERE |
1140
1114
  | `whereBetween(col, [min, max])` | WHERE BETWEEN |
1141
1115
  | `whereLike(col, pattern)` | WHERE LIKE |
1142
- | `whereHas(rel, cb?)` | Filtre par relation |
1143
- | `has(rel, op?, count)` | Existence relationnelle |
1144
- | `whereDoesntHave(rel)` | Absence de relation |
1145
- | `orderBy(col, dir?)` / `ordrer(...)` | Tri |
1146
- | `limit(n)` / `take(n)` | Limite |
1116
+ | `whereHas(rel, cb?)` | Filter by existence of relation |
1117
+ | `has(rel, op?, count)` | Relational existence |
1118
+ | `whereDoesntHave(rel)` | Absence of relation |
1119
+ | `orderBy(col, dir?)` / `ordrer(...)` | Sort |
1120
+ | `limit(n)` / `take(n)` | Limit |
1147
1121
  | `offset(n)` / `skip(n)` | Offset |
1148
1122
  | `groupBy(...cols)` | GROUP BY |
1149
1123
  | `having(col, op, val)` | HAVING |
1150
1124
  | `join(table, first, op?, second)` | INNER JOIN |
1151
1125
  | `leftJoin(table, first, op?, second)` | LEFT JOIN |
1152
1126
  | `with(...rels)` | Eager loading |
1153
- | `withCount(rels)` | Ajoute {rel}_count |
1154
- | `withTrashed()` | Inclut les deleteds |
1155
- | `onlyTrashed()` | Seulement les deleteds |
1156
- | `withoutGlobalScope(name)` | Sans un scope global |
1157
- | `withoutGlobalScopes()` | Sans tous les scopes |
1127
+ | `withCount(rels)` | Adds `{rel}_count` |
1128
+ | `withTrashed()` | Includes soft-deleted records |
1129
+ | `onlyTrashed()` | Only soft-deleted records |
1130
+ | `withoutGlobalScope(name)` | Without one global scope |
1131
+ | `withoutGlobalScopes()` | Without all global scopes |
1158
1132
  | `get()` | Runs and returns all |
1159
1133
  | `first()` | First result |
1160
1134
  | `firstOrFail()` | Premier ou erreur |
@@ -1165,15 +1139,15 @@ if (db.isLogging()) {
1165
1139
  | `update(attrs)` | Update |
1166
1140
  | `updateAndFetch(attrs, rels?)` | Update + fetch |
1167
1141
  | `delete()` | Delete |
1168
- | `increment(col, amount?)` | Incrรฉment atomique |
1169
- | `decrement(col, amount?)` | Dรฉcrรฉment atomique |
1170
- | `clone()` | Clone le query builder |
1142
+ | `increment(col, amount?)` | Atomic increment |
1143
+ | `decrement(col, amount?)` | Atomic decrement |
1144
+ | `clone()` | Clones the query builder |
1171
1145
 
1172
1146
  ## ๐Ÿ› ๏ธ CLI tools
1173
1147
 
1174
1148
  ### outlet-init
1175
1149
 
1176
- Initialise un nouveau projet avec configuration de database.
1150
+ Initialises a new project with database configuration.
1177
1151
 
1178
1152
  ```bash
1179
1153
  outlet-init
@@ -1190,19 +1164,19 @@ Generates:
1190
1164
  complete migration system.
1191
1165
 
1192
1166
  ```bash
1193
- # Create une migration
1167
+ # Create a migration
1194
1168
  outlet-migrate make create_users_table
1195
1169
 
1196
- # Run les migrations
1170
+ # Run migrations
1197
1171
  outlet-migrate migrate
1198
1172
 
1199
- # See le statut
1173
+ # See migration status
1200
1174
  outlet-migrate status
1201
1175
 
1202
1176
  # Roll back the latest migration
1203
1177
  outlet-migrate rollback --steps 1
1204
1178
 
1205
- # Reset toutes les migrations
1179
+ # Reset all migrations
1206
1180
  outlet-migrate reset --yes
1207
1181
 
1208
1182
  # Refresh (reset + migrate)
@@ -1212,17 +1186,17 @@ outlet-migrate refresh --yes
1212
1186
  outlet-migrate fresh --yes
1213
1187
  ```
1214
1188
 
1215
- **Features des Migrations:**
1189
+ **Migration Features:**
1216
1190
 
1217
1191
  - โœ… Creation and management of migrations (create, alter, drop tables)
1218
- - โœ… Types de colonnes: id, string, text, integer, boolean, date, datetime, timestamp, decimal, float, json, enum, uuid, foreignId
1219
- - โœ… Modificateurs: nullable, default, unique, index, unsigned, autoIncrement, comment, after, first
1192
+ - โœ… Column types: id, string, text, integer, boolean, date, datetime, timestamp, decimal, float, json, enum, uuid, foreignId
1193
+ - โœ… Modifiers: nullable, default, unique, index, unsigned, autoIncrement, comment, after, first
1220
1194
  - โœ… Foreign keys: foreign(), constrained(), onDelete(), onUpdate(), CASCADE
1221
1195
  - โœ… Index: index(), unique(), fullText()
1222
1196
  - โœ… Manipulation: renameColumn(), dropColumn(), dropTimestamps()
1223
- - โœ… Reversible migrations: Mรฉthodes up() et down()
1197
+ - โœ… Reversible migrations: up() and down() methods
1224
1198
  - โœ… Batch tracking: Precise rollback by batch
1225
- - โœ… Custom SQL: execute() pour advanced commands
1199
+ - โœ… Custom SQL: execute() for advanced commands
1226
1200
 
1227
1201
  ### outlet-convert
1228
1202
 
@@ -1233,29 +1207,29 @@ outlet-convert
1233
1207
  ```
1234
1208
 
1235
1209
  **Options:**
1236
- 1. Depuis un file SQL local
1210
+ 1. From a local SQL file
1237
1211
  2. From a connected database
1238
1212
 
1239
1213
  **Features:**
1240
- - โœ… Detection automatique des types et casts
1214
+ - โœ… Automatic type and cast detection
1241
1215
  - โœ… Automatic generation of ALL relationships (belongsTo, hasMany, hasOne, belongsToMany)
1242
1216
  - โœ… Recursive relationships (auto-relationships)
1243
- - โœ… Detection des champs sensibles (password, token, etc.)
1244
- - โœ… Support des timestamps automatiques
1245
- - โœ… Conversion des noms en PascalCase
1217
+ - โœ… Detection of sensitive fields (password, token, etc.)
1218
+ - โœ… Automatic timestamps support
1219
+ - โœ… Class names converted to PascalCase
1246
1220
 
1247
1221
  ## ๐Ÿ“š Documentation
1248
1222
 
1249
- - [Guide des Migrations](docs/MIGRATIONS.md)
1250
- - [Conversion SQL](docs/SQL_CONVERSION.md)
1251
- - [Detection des Relations](docs/RELATIONS_DETECTION.md)
1223
+ - [Migrations Guide](docs/MIGRATIONS.md)
1224
+ - [SQL Conversion](docs/SQL_CONVERSION.md)
1225
+ - [Relation Detection](docs/RELATIONS_DETECTION.md)
1252
1226
  - [Quick Start Guide](docs/QUICKSTART.md)
1253
1227
  - [Architecture](docs/ARCHITECTURE.md)
1254
1228
  - [**TypeScript (complet)**](docs/TYPESCRIPT.md)
1255
1229
 
1256
1230
  ## ๐Ÿ“˜ TypeScript Support
1257
1231
 
1258
- Outlet ORM v4.0.0 inclut des dรฉfinitions TypeScript completes avec support des **generics pour les attributs typeds**.
1232
+ Outlet ORM v4.0.0 includes complete TypeScript definitions with support for **generics for typed model attributes**.
1259
1233
 
1260
1234
  ### Typed models
1261
1235
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "outlet-orm",
3
- "version": "5.5.2",
3
+ "version": "5.5.3",
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",