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.
- package/.idea/libalexis.iml +8 -0
- package/.idea/modules.xml +8 -0
- package/.idea/php.xml +19 -0
- package/bin/alexis.js +56 -0
- package/commands/make-auth.js +308 -0
- package/commands/make-crud.js +276 -0
- package/commands/make-entity.js +97 -0
- package/commands/make-migration.js +13 -0
- package/commands/make-module.js +174 -0
- package/commands/make-swagger.js +439 -0
- package/commands/migrate.js +15 -0
- package/package.json +15 -0
|
@@ -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
|
+
};
|