outlet-orm 4.2.1 → 5.0.0

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.
package/bin/init.js CHANGED
@@ -1,379 +1,379 @@
1
- #!/usr/bin/env node
2
-
3
- /**
4
- * Script d'initialisation pour le package ORM
5
- * Ce script aide à configurer rapidement un projet avec l'ORM
6
- */
7
-
8
- const fs = require('fs');
9
- const path = require('path');
10
- const readline = require('readline');
11
-
12
- const rl = readline.createInterface({
13
- input: process.stdin,
14
- output: process.stdout
15
- });
16
-
17
- const question = (query) => new Promise((resolve) => rl.question(query, resolve));
18
-
19
- async function init() {
20
- console.log('\n🚀 Bienvenue dans l\'assistant de configuration Outlet ORM!\n');
21
-
22
- try {
23
- // Database driver
24
- console.log('Quel driver de base de données souhaitez-vous utiliser?');
25
- console.log('1. MySQL');
26
- console.log('2. PostgreSQL');
27
- console.log('3. SQLite');
28
- const driverChoice = await question('\nVotre choix (1-3): ');
29
-
30
- const drivers = {
31
- '1': { name: 'mysql', package: 'mysql2', defaultPort: 3306 },
32
- '2': { name: 'postgres', package: 'pg', defaultPort: 5432 },
33
- '3': { name: 'sqlite', package: 'sqlite3', defaultPort: null }
34
- };
35
-
36
- const selectedDriver = drivers[driverChoice];
37
- if (!selectedDriver) {
38
- console.error('❌ Choix invalide!');
39
- process.exit(1);
40
- }
41
-
42
- // Database configuration
43
- let config = {
44
- driver: selectedDriver.name
45
- };
46
-
47
- if (selectedDriver.name !== 'sqlite') {
48
- config.host = await question('Host (localhost): ') || 'localhost';
49
- config.port = await question(`Port (${selectedDriver.defaultPort}): `) || selectedDriver.defaultPort;
50
- config.database = await question('Nom de la base de données: ');
51
- config.user = await question('Utilisateur: ');
52
- config.password = await question('Mot de passe: ');
53
- } else {
54
- config.database = await question('Chemin du fichier SQLite (./database.sqlite): ') || './database.sqlite';
55
- }
56
-
57
- // Ask to generate a .env file
58
- const generateEnv = (await question('\nSouhaitez-vous générer un fichier .env avec ces paramètres ? (oui/non) [oui]: ')).trim().toLowerCase();
59
- const wantEnv = generateEnv === '' || generateEnv === 'oui' || generateEnv === 'o' || generateEnv === 'yes' || generateEnv === 'y';
60
-
61
- if (wantEnv) {
62
- const envLines = [];
63
- envLines.push(`DB_DRIVER=${config.driver}`);
64
- if (config.driver !== 'sqlite') {
65
- envLines.push(`DB_HOST=${config.host || 'localhost'}`);
66
- envLines.push(`DB_PORT=${config.port || selectedDriver.defaultPort || ''}`);
67
- envLines.push(`DB_USER=${config.user || ''}`);
68
- envLines.push(`DB_PASSWORD=${config.password || ''}`);
69
- envLines.push(`DB_DATABASE=${config.database || ''}`);
70
- } else {
71
- envLines.push(`DB_FILE=${config.database}`);
72
- }
73
-
74
- const envPath = path.join(process.cwd(), '.env');
75
- if (fs.existsSync(envPath)) {
76
- console.log('ℹ️ .env existe déjà, génération ignorée.');
77
- } else {
78
- fs.writeFileSync(envPath, envLines.join('\n') + '\n');
79
- console.log(`✅ Fichier .env créé: ${envPath}`);
80
- }
81
- }
82
-
83
- // Generate config file
84
- const configContent = `const { DatabaseConnection } = require('outlet-orm');
85
-
86
- // Configuration de la base de données
87
- const db = new DatabaseConnection(${JSON.stringify(config, null, 2)});
88
-
89
- module.exports = db;
90
- `;
91
-
92
- const configPath = path.join(process.cwd(), 'database.js');
93
- fs.writeFileSync(configPath, configContent);
94
- console.log(`\n✅ Fichier de configuration créé: ${configPath}`);
95
-
96
- // Create project structure directories
97
- const directories = [
98
- 'config',
99
- 'database',
100
- 'database/migrations',
101
- 'models',
102
- 'controllers',
103
- 'routes',
104
- 'middlewares',
105
- 'services',
106
- 'utils',
107
- 'validators',
108
- 'public',
109
- 'public/images',
110
- 'public/css',
111
- 'public/js',
112
- 'uploads',
113
- 'logs',
114
- 'src',
115
- 'tests'
116
- ];
117
-
118
- console.log('\n📁 Création de la structure de projet...');
119
- for (const dir of directories) {
120
- const dirPath = path.join(process.cwd(), dir);
121
- if (!fs.existsSync(dirPath)) {
122
- fs.mkdirSync(dirPath, { recursive: true });
123
- console.log(` ✅ ${dir}/`);
124
- } else {
125
- console.log(` ⏭️ ${dir}/ (existe déjà)`);
126
- }
127
- }
128
-
129
- // Generate .gitignore
130
- const gitignoreContent = `# Secrets
131
- .env
132
- .env.local
133
- .env.production
134
-
135
- # Logs
136
- logs/
137
- *.log
138
-
139
- # Uploads
140
- uploads/
141
-
142
- # Dependencies
143
- node_modules/
144
-
145
- # Build
146
- dist/
147
- build/
148
-
149
- # IDE
150
- .vscode/
151
- .idea/
152
- `;
153
-
154
- const gitignorePath = path.join(process.cwd(), '.gitignore');
155
- if (!fs.existsSync(gitignorePath)) {
156
- fs.writeFileSync(gitignorePath, gitignoreContent);
157
- console.log(`\n✅ .gitignore créé`);
158
- }
159
-
160
- // Generate .env.example
161
- const envExampleContent = `# Base de données
162
- DB_DRIVER=mysql
163
- DB_HOST=localhost
164
- DB_PORT=3306
165
- DB_DATABASE=myapp
166
- DB_USER=your_user
167
- DB_PASSWORD=your_password
168
-
169
- # Sécurité
170
- JWT_SECRET=your_jwt_secret_here
171
- JWT_EXPIRES_IN=15m
172
-
173
- # Application
174
- NODE_ENV=development
175
- PORT=3000
176
-
177
- # CORS
178
- CORS_ORIGIN=http://localhost:3000
179
- `;
180
-
181
- const envExamplePath = path.join(process.cwd(), '.env.example');
182
- if (!fs.existsSync(envExamplePath)) {
183
- fs.writeFileSync(envExamplePath, envExampleContent);
184
- console.log(`✅ .env.example créé`);
185
- }
186
-
187
- // Generate config/security.js
188
- const securityConfigContent = `/**
189
- * Configuration de sécurité
190
- * npm install helmet express-rate-limit xss-clean hpp
191
- */
192
-
193
- module.exports = {
194
- // Rate limiting (100 requêtes/15min par IP)
195
- rateLimit: {
196
- windowMs: 15 * 60 * 1000,
197
- max: 100,
198
- message: { error: 'Trop de requêtes, réessayez plus tard' }
199
- },
200
-
201
- // Rate limiting strict pour auth (5 tentatives/15min)
202
- authRateLimit: {
203
- windowMs: 15 * 60 * 1000,
204
- max: 5,
205
- message: { error: 'Trop de tentatives de connexion' }
206
- },
207
-
208
- // CORS
209
- cors: {
210
- origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
211
- credentials: true,
212
- methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
213
- allowedHeaders: ['Content-Type', 'Authorization']
214
- },
215
-
216
- // JWT
217
- jwt: {
218
- secret: process.env.JWT_SECRET,
219
- expiresIn: process.env.JWT_EXPIRES_IN || '15m'
220
- }
221
- };
222
- `;
223
-
224
- const securityConfigPath = path.join(process.cwd(), 'config', 'security.js');
225
- if (!fs.existsSync(securityConfigPath)) {
226
- fs.writeFileSync(securityConfigPath, securityConfigContent);
227
- console.log(`✅ config/security.js créé`);
228
- }
229
-
230
- // Generate middlewares/errorHandler.js
231
- const errorHandlerContent = `/**
232
- * Gestionnaire d'erreurs centralisé
233
- */
234
- const errorHandler = (err, req, res, next) => {
235
- console.error(\`[\${new Date().toISOString()}] Error:\`, err);
236
-
237
- const isDev = process.env.NODE_ENV === 'development';
238
-
239
- res.status(err.status || 500).json({
240
- error: isDev ? err.message : 'Erreur serveur',
241
- stack: isDev ? err.stack : undefined
242
- });
243
- };
244
-
245
- module.exports = errorHandler;
246
- `;
247
-
248
- const errorHandlerPath = path.join(process.cwd(), 'middlewares', 'errorHandler.js');
249
- if (!fs.existsSync(errorHandlerPath)) {
250
- fs.writeFileSync(errorHandlerPath, errorHandlerContent);
251
- console.log(`✅ middlewares/errorHandler.js créé`);
252
- }
253
-
254
- // Generate utils/hash.js
255
- const hashUtilContent = `/**
256
- * Utilitaires de hachage
257
- * npm install bcrypt
258
- */
259
- const bcrypt = require('bcrypt');
260
-
261
- const SALT_ROUNDS = 12;
262
-
263
- const hashPassword = async (password) => {
264
- return bcrypt.hash(password, SALT_ROUNDS);
265
- };
266
-
267
- const verifyPassword = async (password, hash) => {
268
- return bcrypt.compare(password, hash);
269
- };
270
-
271
- module.exports = { hashPassword, verifyPassword };
272
- `;
273
-
274
- const hashUtilPath = path.join(process.cwd(), 'utils', 'hash.js');
275
- if (!fs.existsSync(hashUtilPath)) {
276
- fs.writeFileSync(hashUtilPath, hashUtilContent);
277
- console.log(`✅ utils/hash.js créé`);
278
- }
279
-
280
- // Generate example model
281
- const modelContent = `const { Model } = require('outlet-orm');
282
- const db = require('./database');
283
-
284
- class User extends Model {
285
- static table = 'users';
286
- static fillable = ['name', 'email', 'password'];
287
- static hidden = ['password', 'refresh_token']; // 🔒 Ne jamais exposer
288
- static casts = {
289
- id: 'int',
290
- email_verified: 'boolean'
291
- };
292
- static rules = {
293
- name: 'required|string|min:2|max:100',
294
- email: 'required|email',
295
- password: 'required|min:8'
296
- };
297
- static connection = db;
298
-
299
- // Définissez vos relations ici
300
- // posts() {
301
- // return this.hasMany(Post, 'user_id');
302
- // }
303
- }
304
-
305
- module.exports = User;
306
- `;
307
-
308
- const modelPath = path.join(process.cwd(), 'User.js');
309
- fs.writeFileSync(modelPath, modelContent);
310
- console.log(`✅ Modèle exemple créé: ${modelPath}`);
311
-
312
- // Generate usage example
313
- const usageContent = `const User = require('./User');
314
-
315
- async function main() {
316
- try {
317
- // Exemple: Créer un utilisateur
318
- const user = await User.create({
319
- name: 'John Doe',
320
- email: 'john@example.com',
321
- password: 'secret123'
322
- });
323
- console.log('Utilisateur créé:', user.toJSON());
324
-
325
- // Exemple: Rechercher des utilisateurs
326
- const users = await User.all();
327
- console.log('Tous les utilisateurs:', users.length);
328
-
329
- // Exemple: Requête avec conditions
330
- const activeUsers = await User
331
- .where('status', 'active')
332
- .orderBy('name')
333
- .get();
334
- console.log('Utilisateurs actifs:', activeUsers.length);
335
-
336
- } catch (error) {
337
- console.error('Erreur:', error.message);
338
- }
339
- }
340
-
341
- main();
342
- `;
343
-
344
- const usagePath = path.join(process.cwd(), 'example.js');
345
- fs.writeFileSync(usagePath, usageContent);
346
- console.log(`✅ Exemple d'utilisation créé: ${usagePath}`);
347
-
348
- // Optionally skip package init/install in non-interactive or test context
349
- const skipInstall = process.env.OUTLET_INIT_NO_INSTALL === '1';
350
- if (!skipInstall) {
351
- // Check if package needs to be installed
352
- const packageJsonPath = path.join(process.cwd(), 'package.json');
353
- if (!fs.existsSync(packageJsonPath)) {
354
- console.log('\n⚠️ Aucun package.json trouvé. Initialisation...');
355
- require('child_process').execSync('npm init -y', { stdio: 'inherit' });
356
- }
357
-
358
- console.log(`\n📦 Installation du driver ${selectedDriver.package}...`);
359
- require('child_process').execSync(`npm install ${selectedDriver.package}`, { stdio: 'inherit' });
360
- } else {
361
- console.log('\n⏭️ Installation du driver ignorée (OUTLET_INIT_NO_INSTALL=1).');
362
- }
363
-
364
- console.log('\n✨ Configuration terminée!\n');
365
- console.log('Prochaines étapes:');
366
- console.log('1. Créez votre schéma de base de données');
367
- console.log('2. Modifiez User.js selon vos besoins');
368
- console.log('3. Exécutez example.js: node example.js');
369
- console.log('\n📚 Documentation: https://github.com/yourusername/outlet-orm');
370
-
371
- } catch (error) {
372
- console.error('\n❌ Erreur:', error.message);
373
- process.exit(1);
374
- } finally {
375
- rl.close();
376
- }
377
- }
378
-
379
- init();
1
+ #!/usr/bin/env node
2
+
3
+ /**
4
+ * Script d'initialisation pour le package ORM
5
+ * Ce script aide à configurer rapidement un projet avec l'ORM
6
+ */
7
+
8
+ const fs = require('fs');
9
+ const path = require('path');
10
+ const readline = require('readline');
11
+
12
+ const rl = readline.createInterface({
13
+ input: process.stdin,
14
+ output: process.stdout
15
+ });
16
+
17
+ const question = (query) => new Promise((resolve) => rl.question(query, resolve));
18
+
19
+ async function init() {
20
+ console.log('\n🚀 Bienvenue dans l\'assistant de configuration Outlet ORM!\n');
21
+
22
+ try {
23
+ // Database driver
24
+ console.log('Quel driver de base de données souhaitez-vous utiliser?');
25
+ console.log('1. MySQL');
26
+ console.log('2. PostgreSQL');
27
+ console.log('3. SQLite');
28
+ const driverChoice = await question('\nVotre choix (1-3): ');
29
+
30
+ const drivers = {
31
+ '1': { name: 'mysql', package: 'mysql2', defaultPort: 3306 },
32
+ '2': { name: 'postgres', package: 'pg', defaultPort: 5432 },
33
+ '3': { name: 'sqlite', package: 'sqlite3', defaultPort: null }
34
+ };
35
+
36
+ const selectedDriver = drivers[driverChoice];
37
+ if (!selectedDriver) {
38
+ console.error('❌ Choix invalide!');
39
+ process.exit(1);
40
+ }
41
+
42
+ // Database configuration
43
+ let config = {
44
+ driver: selectedDriver.name
45
+ };
46
+
47
+ if (selectedDriver.name !== 'sqlite') {
48
+ config.host = await question('Host (localhost): ') || 'localhost';
49
+ config.port = await question(`Port (${selectedDriver.defaultPort}): `) || selectedDriver.defaultPort;
50
+ config.database = await question('Nom de la base de données: ');
51
+ config.user = await question('Utilisateur: ');
52
+ config.password = await question('Mot de passe: ');
53
+ } else {
54
+ config.database = await question('Chemin du fichier SQLite (./database.sqlite): ') || './database.sqlite';
55
+ }
56
+
57
+ // Ask to generate a .env file
58
+ const generateEnv = (await question('\nSouhaitez-vous générer un fichier .env avec ces paramètres ? (oui/non) [oui]: ')).trim().toLowerCase();
59
+ const wantEnv = generateEnv === '' || generateEnv === 'oui' || generateEnv === 'o' || generateEnv === 'yes' || generateEnv === 'y';
60
+
61
+ if (wantEnv) {
62
+ const envLines = [];
63
+ envLines.push(`DB_DRIVER=${config.driver}`);
64
+ if (config.driver !== 'sqlite') {
65
+ envLines.push(`DB_HOST=${config.host || 'localhost'}`);
66
+ envLines.push(`DB_PORT=${config.port || selectedDriver.defaultPort || ''}`);
67
+ envLines.push(`DB_USER=${config.user || ''}`);
68
+ envLines.push(`DB_PASSWORD=${config.password || ''}`);
69
+ envLines.push(`DB_DATABASE=${config.database || ''}`);
70
+ } else {
71
+ envLines.push(`DB_FILE=${config.database}`);
72
+ }
73
+
74
+ const envPath = path.join(process.cwd(), '.env');
75
+ if (fs.existsSync(envPath)) {
76
+ console.log('ℹ️ .env existe déjà, génération ignorée.');
77
+ } else {
78
+ fs.writeFileSync(envPath, envLines.join('\n') + '\n');
79
+ console.log(`✅ Fichier .env créé: ${envPath}`);
80
+ }
81
+ }
82
+
83
+ // Generate config file
84
+ const configContent = `const { DatabaseConnection } = require('outlet-orm');
85
+
86
+ // Configuration de la base de données
87
+ const db = new DatabaseConnection(${JSON.stringify(config, null, 2)});
88
+
89
+ module.exports = db;
90
+ `;
91
+
92
+ const configPath = path.join(process.cwd(), 'database.js');
93
+ fs.writeFileSync(configPath, configContent);
94
+ console.log(`\n✅ Fichier de configuration créé: ${configPath}`);
95
+
96
+ // Create project structure directories
97
+ const directories = [
98
+ 'config',
99
+ 'database',
100
+ 'database/migrations',
101
+ 'models',
102
+ 'controllers',
103
+ 'routes',
104
+ 'middlewares',
105
+ 'services',
106
+ 'utils',
107
+ 'validators',
108
+ 'public',
109
+ 'public/images',
110
+ 'public/css',
111
+ 'public/js',
112
+ 'uploads',
113
+ 'logs',
114
+ 'src',
115
+ 'tests'
116
+ ];
117
+
118
+ console.log('\n📁 Création de la structure de projet...');
119
+ for (const dir of directories) {
120
+ const dirPath = path.join(process.cwd(), dir);
121
+ if (!fs.existsSync(dirPath)) {
122
+ fs.mkdirSync(dirPath, { recursive: true });
123
+ console.log(` ✅ ${dir}/`);
124
+ } else {
125
+ console.log(` ⏭️ ${dir}/ (existe déjà)`);
126
+ }
127
+ }
128
+
129
+ // Generate .gitignore
130
+ const gitignoreContent = `# Secrets
131
+ .env
132
+ .env.local
133
+ .env.production
134
+
135
+ # Logs
136
+ logs/
137
+ *.log
138
+
139
+ # Uploads
140
+ uploads/
141
+
142
+ # Dependencies
143
+ node_modules/
144
+
145
+ # Build
146
+ dist/
147
+ build/
148
+
149
+ # IDE
150
+ .vscode/
151
+ .idea/
152
+ `;
153
+
154
+ const gitignorePath = path.join(process.cwd(), '.gitignore');
155
+ if (!fs.existsSync(gitignorePath)) {
156
+ fs.writeFileSync(gitignorePath, gitignoreContent);
157
+ console.log(`\n✅ .gitignore créé`);
158
+ }
159
+
160
+ // Generate .env.example
161
+ const envExampleContent = `# Base de données
162
+ DB_DRIVER=mysql
163
+ DB_HOST=localhost
164
+ DB_PORT=3306
165
+ DB_DATABASE=myapp
166
+ DB_USER=your_user
167
+ DB_PASSWORD=your_password
168
+
169
+ # Sécurité
170
+ JWT_SECRET=your_jwt_secret_here
171
+ JWT_EXPIRES_IN=15m
172
+
173
+ # Application
174
+ NODE_ENV=development
175
+ PORT=3000
176
+
177
+ # CORS
178
+ CORS_ORIGIN=http://localhost:3000
179
+ `;
180
+
181
+ const envExamplePath = path.join(process.cwd(), '.env.example');
182
+ if (!fs.existsSync(envExamplePath)) {
183
+ fs.writeFileSync(envExamplePath, envExampleContent);
184
+ console.log(`✅ .env.example créé`);
185
+ }
186
+
187
+ // Generate config/security.js
188
+ const securityConfigContent = `/**
189
+ * Configuration de sécurité
190
+ * npm install helmet express-rate-limit xss-clean hpp
191
+ */
192
+
193
+ module.exports = {
194
+ // Rate limiting (100 requêtes/15min par IP)
195
+ rateLimit: {
196
+ windowMs: 15 * 60 * 1000,
197
+ max: 100,
198
+ message: { error: 'Trop de requêtes, réessayez plus tard' }
199
+ },
200
+
201
+ // Rate limiting strict pour auth (5 tentatives/15min)
202
+ authRateLimit: {
203
+ windowMs: 15 * 60 * 1000,
204
+ max: 5,
205
+ message: { error: 'Trop de tentatives de connexion' }
206
+ },
207
+
208
+ // CORS
209
+ cors: {
210
+ origin: process.env.CORS_ORIGIN || 'http://localhost:3000',
211
+ credentials: true,
212
+ methods: ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'],
213
+ allowedHeaders: ['Content-Type', 'Authorization']
214
+ },
215
+
216
+ // JWT
217
+ jwt: {
218
+ secret: process.env.JWT_SECRET,
219
+ expiresIn: process.env.JWT_EXPIRES_IN || '15m'
220
+ }
221
+ };
222
+ `;
223
+
224
+ const securityConfigPath = path.join(process.cwd(), 'config', 'security.js');
225
+ if (!fs.existsSync(securityConfigPath)) {
226
+ fs.writeFileSync(securityConfigPath, securityConfigContent);
227
+ console.log(`✅ config/security.js créé`);
228
+ }
229
+
230
+ // Generate middlewares/errorHandler.js
231
+ const errorHandlerContent = `/**
232
+ * Gestionnaire d'erreurs centralisé
233
+ */
234
+ const errorHandler = (err, req, res, next) => {
235
+ console.error(\`[\${new Date().toISOString()}] Error:\`, err);
236
+
237
+ const isDev = process.env.NODE_ENV === 'development';
238
+
239
+ res.status(err.status || 500).json({
240
+ error: isDev ? err.message : 'Erreur serveur',
241
+ stack: isDev ? err.stack : undefined
242
+ });
243
+ };
244
+
245
+ module.exports = errorHandler;
246
+ `;
247
+
248
+ const errorHandlerPath = path.join(process.cwd(), 'middlewares', 'errorHandler.js');
249
+ if (!fs.existsSync(errorHandlerPath)) {
250
+ fs.writeFileSync(errorHandlerPath, errorHandlerContent);
251
+ console.log(`✅ middlewares/errorHandler.js créé`);
252
+ }
253
+
254
+ // Generate utils/hash.js
255
+ const hashUtilContent = `/**
256
+ * Utilitaires de hachage
257
+ * npm install bcrypt
258
+ */
259
+ const bcrypt = require('bcrypt');
260
+
261
+ const SALT_ROUNDS = 12;
262
+
263
+ const hashPassword = async (password) => {
264
+ return bcrypt.hash(password, SALT_ROUNDS);
265
+ };
266
+
267
+ const verifyPassword = async (password, hash) => {
268
+ return bcrypt.compare(password, hash);
269
+ };
270
+
271
+ module.exports = { hashPassword, verifyPassword };
272
+ `;
273
+
274
+ const hashUtilPath = path.join(process.cwd(), 'utils', 'hash.js');
275
+ if (!fs.existsSync(hashUtilPath)) {
276
+ fs.writeFileSync(hashUtilPath, hashUtilContent);
277
+ console.log(`✅ utils/hash.js créé`);
278
+ }
279
+
280
+ // Generate example model
281
+ const modelContent = `const { Model } = require('outlet-orm');
282
+ const db = require('./database');
283
+
284
+ class User extends Model {
285
+ static table = 'users';
286
+ static fillable = ['name', 'email', 'password'];
287
+ static hidden = ['password', 'refresh_token']; // 🔒 Ne jamais exposer
288
+ static casts = {
289
+ id: 'int',
290
+ email_verified: 'boolean'
291
+ };
292
+ static rules = {
293
+ name: 'required|string|min:2|max:100',
294
+ email: 'required|email',
295
+ password: 'required|min:8'
296
+ };
297
+ static connection = db;
298
+
299
+ // Définissez vos relations ici
300
+ // posts() {
301
+ // return this.hasMany(Post, 'user_id');
302
+ // }
303
+ }
304
+
305
+ module.exports = User;
306
+ `;
307
+
308
+ const modelPath = path.join(process.cwd(), 'User.js');
309
+ fs.writeFileSync(modelPath, modelContent);
310
+ console.log(`✅ Modèle exemple créé: ${modelPath}`);
311
+
312
+ // Generate usage example
313
+ const usageContent = `const User = require('./User');
314
+
315
+ async function main() {
316
+ try {
317
+ // Exemple: Créer un utilisateur
318
+ const user = await User.create({
319
+ name: 'John Doe',
320
+ email: 'john@example.com',
321
+ password: 'secret123'
322
+ });
323
+ console.log('Utilisateur créé:', user.toJSON());
324
+
325
+ // Exemple: Rechercher des utilisateurs
326
+ const users = await User.all();
327
+ console.log('Tous les utilisateurs:', users.length);
328
+
329
+ // Exemple: Requête avec conditions
330
+ const activeUsers = await User
331
+ .where('status', 'active')
332
+ .orderBy('name')
333
+ .get();
334
+ console.log('Utilisateurs actifs:', activeUsers.length);
335
+
336
+ } catch (error) {
337
+ console.error('Erreur:', error.message);
338
+ }
339
+ }
340
+
341
+ main();
342
+ `;
343
+
344
+ const usagePath = path.join(process.cwd(), 'example.js');
345
+ fs.writeFileSync(usagePath, usageContent);
346
+ console.log(`✅ Exemple d'utilisation créé: ${usagePath}`);
347
+
348
+ // Optionally skip package init/install in non-interactive or test context
349
+ const skipInstall = process.env.OUTLET_INIT_NO_INSTALL === '1';
350
+ if (!skipInstall) {
351
+ // Check if package needs to be installed
352
+ const packageJsonPath = path.join(process.cwd(), 'package.json');
353
+ if (!fs.existsSync(packageJsonPath)) {
354
+ console.log('\n⚠️ Aucun package.json trouvé. Initialisation...');
355
+ require('child_process').execSync('npm init -y', { stdio: 'inherit' });
356
+ }
357
+
358
+ console.log(`\n📦 Installation du driver ${selectedDriver.package}...`);
359
+ require('child_process').execSync(`npm install ${selectedDriver.package}`, { stdio: 'inherit' });
360
+ } else {
361
+ console.log('\n⏭️ Installation du driver ignorée (OUTLET_INIT_NO_INSTALL=1).');
362
+ }
363
+
364
+ console.log('\n✨ Configuration terminée!\n');
365
+ console.log('Prochaines étapes:');
366
+ console.log('1. Créez votre schéma de base de données');
367
+ console.log('2. Modifiez User.js selon vos besoins');
368
+ console.log('3. Exécutez example.js: node example.js');
369
+ console.log('\n📚 Documentation: https://github.com/yourusername/outlet-orm');
370
+
371
+ } catch (error) {
372
+ console.error('\n❌ Erreur:', error.message);
373
+ process.exit(1);
374
+ } finally {
375
+ rl.close();
376
+ }
377
+ }
378
+
379
+ init();