alexis-cli 1.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.
@@ -0,0 +1,97 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+ const readline = require('readline');
4
+ const entityTypes = require('../cli/entity-types');
5
+
6
+ module.exports = async (name) => {
7
+ if (!name) {
8
+ console.error('❌ Usage: alexis make entity <Name>');
9
+ process.exit(1);
10
+ }
11
+
12
+ const entityName = name.charAt(0).toUpperCase() + name.slice(1);
13
+ const tableName = name.toLowerCase() + 's';
14
+
15
+ const entityDir = path.join(__dirname, '../../src/entities');
16
+ const entityPath = path.join(entityDir, `${entityName}.entity.js`);
17
+
18
+ if (!fs.existsSync(entityDir)) {
19
+ fs.mkdirSync(entityDir, { recursive: true });
20
+ }
21
+
22
+ if (fs.existsSync(entityPath)) {
23
+ console.error(`❌ Entity "${entityName}" already exists`);
24
+ process.exit(1);
25
+ }
26
+
27
+ const rl = readline.createInterface({
28
+ input: process.stdin,
29
+ output: process.stdout
30
+ });
31
+
32
+ const ask = (q) =>
33
+ new Promise((resolve) => rl.question(q, resolve));
34
+
35
+ const columns = {
36
+ id: {
37
+ type: Number,
38
+ primary: true,
39
+ generated: true
40
+ }
41
+ };
42
+
43
+ console.log(`\n🧱 Creating entity ${entityName}`);
44
+ console.log(`Available types: ${Object.keys(entityTypes).join(', ')}`);
45
+
46
+ while (true) {
47
+ const field = await ask('\n➤ New field name (leave empty to finish): ');
48
+ if (!field) break;
49
+
50
+ if (columns[field]) {
51
+ console.log('❌ Field already exists');
52
+ continue;
53
+ }
54
+
55
+ const type = await ask(
56
+ `➤ Field type (${Object.keys(entityTypes).join(', ')}): `
57
+ );
58
+
59
+ if (!entityTypes[type]) {
60
+ console.log('❌ Invalid type');
61
+ continue;
62
+ }
63
+
64
+ const nullable =
65
+ (await ask('➤ Is nullable? (y/N): ')).toLowerCase() === 'y';
66
+
67
+ const unique =
68
+ (await ask('➤ Is unique? (y/N): ')).toLowerCase() === 'y';
69
+
70
+ columns[field] = {
71
+ ...entityTypes[type],
72
+ nullable,
73
+ unique
74
+ };
75
+ }
76
+
77
+ rl.close();
78
+
79
+ // timestamps auto (Symfony-like)
80
+ columns.createdAt = { type: 'timestamp', createDate: true };
81
+ columns.updatedAt = { type: 'timestamp', updateDate: true };
82
+
83
+ const entityTemplate = `
84
+ const { EntitySchema } = require('typeorm');
85
+
86
+ module.exports = new EntitySchema({
87
+ name: '${entityName}',
88
+ tableName: '${tableName}',
89
+ columns: ${JSON.stringify(columns, null, 2)}
90
+ });
91
+ `.trim();
92
+
93
+ fs.writeFileSync(entityPath, entityTemplate + '\n');
94
+
95
+ console.log(`\n✅ Entity "${entityName}" created`);
96
+ console.log(`➡️ Next: alexis make migration create-${tableName}`);
97
+ };
@@ -0,0 +1,13 @@
1
+ const { execSync } = require('child_process');
2
+
3
+ module.exports = (name) => {
4
+ if (!name) {
5
+ console.error('❌ Usage: alexis make migration <name>');
6
+ process.exit(1);
7
+ }
8
+
9
+ execSync(
10
+ `npx typeorm migration:generate src/migrations/${name} -d src/config/orm.js --outputJs`,
11
+ { stdio: 'inherit' }
12
+ );
13
+ };
@@ -0,0 +1,174 @@
1
+ const fs = require('fs');
2
+ const path = require('path');
3
+
4
+ module.exports = (moduleName) => {
5
+ if (!moduleName) {
6
+ console.error('❌ Usage: alexis make module <name>');
7
+ process.exit(1);
8
+ }
9
+
10
+ const entityName =
11
+ moduleName.charAt(0).toUpperCase() + moduleName.slice(1);
12
+
13
+ // 🔎 Vérifier que l'Entity existe
14
+ const entityPath = path.join(
15
+ __dirname,
16
+ '../../src/entities',
17
+ `${entityName}.entity.js`
18
+ );
19
+
20
+ if (!fs.existsSync(entityPath)) {
21
+ console.error(
22
+ `❌ Entity "${entityName}" not found.\n➡️ Create it first with: alexis make entity ${entityName}`
23
+ );
24
+ process.exit(1);
25
+ }
26
+
27
+ // 📁 Création du module
28
+ const basePath = path.join(
29
+ __dirname,
30
+ '../../src/modules/v1',
31
+ moduleName
32
+ );
33
+
34
+ if (fs.existsSync(basePath)) {
35
+ console.error(`❌ Module "${moduleName}" already exists`);
36
+ process.exit(1);
37
+ }
38
+
39
+ fs.mkdirSync(basePath, { recursive: true });
40
+
41
+ // 📄 Templates des fichiers
42
+ const files = {
43
+ [`${moduleName}.controller.js`]: `
44
+ const ${moduleName}Service = require('./${moduleName}.service');
45
+
46
+ exports.getAll = async (req, res, next) => {
47
+ try {
48
+ const data = await ${moduleName}Service.findAll();
49
+ res.json(data);
50
+ } catch (err) {
51
+ next(err);
52
+ }
53
+ };
54
+
55
+ exports.create = async (req, res, next) => {
56
+ try {
57
+ const entity = await ${moduleName}Service.create(req.body);
58
+ res.status(201).json(entity);
59
+ } catch (err) {
60
+ next(err);
61
+ }
62
+ };
63
+ `.trim(),
64
+
65
+ [`${moduleName}.service.js`]: `
66
+ const AppDataSource = require('../../../config/orm');
67
+ const ${entityName} = require('../../../entities/${entityName}.entity');
68
+
69
+ exports.findAll = async () => {
70
+ return AppDataSource.getRepository(${entityName}).find();
71
+ };
72
+
73
+ exports.create = async (data) => {
74
+ const repo = AppDataSource.getRepository(${entityName});
75
+ const entity = repo.create(data);
76
+ return repo.save(entity);
77
+ };
78
+ `.trim(),
79
+
80
+ [`${moduleName}.routes.js`]: `
81
+ /**
82
+ * @swagger
83
+ * tags:
84
+ * name: ${entityName}
85
+ * description: ${entityName} endpoints
86
+ */
87
+
88
+ const express = require('express');
89
+ const router = express.Router();
90
+ const controller = require('./${moduleName}.controller');
91
+
92
+ /**
93
+ * @swagger
94
+ * /${moduleName}:
95
+ * get:
96
+ * summary: Get all ${entityName}
97
+ * tags: [${entityName}]
98
+ * security:
99
+ * - bearerAuth: []
100
+ * responses:
101
+ * 200:
102
+ * description: List of ${entityName}
103
+ */
104
+ router.get('/', controller.getAll);
105
+
106
+ /**
107
+ * @swagger
108
+ * /${moduleName}:
109
+ * post:
110
+ * summary: Create a ${entityName}
111
+ * tags: [${entityName}]
112
+ * security:
113
+ * - bearerAuth: []
114
+ * requestBody:
115
+ * required: true
116
+ * content:
117
+ * application/json:
118
+ * schema:
119
+ * type: object
120
+ * example: {}
121
+ * responses:
122
+ * 201:
123
+ * description: ${entityName} created
124
+ */
125
+ router.post('/', controller.create);
126
+
127
+ module.exports = router;
128
+ `.trim()
129
+ };
130
+
131
+ // ✍️ Écriture des fichiers
132
+ for (const [file, content] of Object.entries(files)) {
133
+ fs.writeFileSync(
134
+ path.join(basePath, file),
135
+ content + '\n'
136
+ );
137
+ }
138
+
139
+ console.log(`✅ Module v1 "${moduleName}" created and linked to entity "${entityName}"`);
140
+
141
+ // 🔗 Auto-register route
142
+ const routesIndexPath = path.join(
143
+ __dirname,
144
+ '../../src/routes/v1/index.js'
145
+ );
146
+
147
+ if (!fs.existsSync(routesIndexPath)) {
148
+ console.warn('⚠️ routes/v1/index.js not found, skipping auto-route registration');
149
+ return;
150
+ }
151
+
152
+ let indexContent = fs.readFileSync(routesIndexPath, 'utf8');
153
+
154
+ const importLine = `const ${moduleName}Routes = require('../../../src/modules/v1/${moduleName}/${moduleName}.routes');`;
155
+ const routeLine = `router.use('/${moduleName}', ${moduleName}Routes);`;
156
+
157
+ if (!indexContent.includes(importLine)) {
158
+ indexContent = indexContent.replace(
159
+ '// AUTO-IMPORTS (do not remove)',
160
+ `// AUTO-IMPORTS (do not remove)\n${importLine}`
161
+ );
162
+ }
163
+
164
+ if (!indexContent.includes(routeLine)) {
165
+ indexContent = indexContent.replace(
166
+ '// AUTO-ROUTES (do not remove)',
167
+ `// AUTO-ROUTES (do not remove)\n${routeLine}`
168
+ );
169
+ }
170
+
171
+ fs.writeFileSync(routesIndexPath, indexContent);
172
+
173
+ console.log(`🔗 Route "/${moduleName}" registered in routes/v1/index.js`);
174
+ };