@diagramers/cli 4.0.19 → 4.0.21
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/dist/commands/api.d.ts.map +1 -1
- package/dist/commands/api.js +368 -9
- package/dist/commands/api.js.map +1 -1
- package/dist/commands/extend.d.ts.map +1 -1
- package/dist/commands/extend.js +125 -4
- package/dist/commands/extend.js.map +1 -1
- package/dist/commands/update.d.ts.map +1 -1
- package/dist/commands/update.js +84 -5
- package/dist/commands/update.js.map +1 -1
- package/dist/index.js +0 -0
- package/dist/services/api-generator.d.ts +1 -1
- package/dist/services/api-generator.d.ts.map +1 -1
- package/dist/services/api-generator.js +525 -223
- package/dist/services/api-generator.js.map +1 -1
- package/dist/services/project-extender.d.ts.map +1 -1
- package/dist/services/project-extender.js +422 -247
- package/dist/services/project-extender.js.map +1 -1
- package/dist/services/relation-generator.d.ts +1 -1
- package/dist/services/relation-generator.d.ts.map +1 -1
- package/dist/services/relation-generator.js +15 -1
- package/dist/services/relation-generator.js.map +1 -1
- package/dist/services/table-generator.d.ts.map +1 -1
- package/dist/services/table-generator.js +27 -18
- package/dist/services/table-generator.js.map +1 -1
- package/dist/services/template-updater.d.ts +2 -0
- package/dist/services/template-updater.d.ts.map +1 -1
- package/dist/services/template-updater.js +109 -3
- package/dist/services/template-updater.js.map +1 -1
- package/package.json +1 -1
|
@@ -37,12 +37,17 @@ exports.generateModule = generateModule;
|
|
|
37
37
|
exports.generateEndpoint = generateEndpoint;
|
|
38
38
|
const fs = __importStar(require("fs"));
|
|
39
39
|
const path = __importStar(require("path"));
|
|
40
|
-
async function generateModule(moduleName) {
|
|
40
|
+
async function generateModule(moduleName, options = {}) {
|
|
41
41
|
// Validate module name
|
|
42
42
|
if (!moduleName || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(moduleName)) {
|
|
43
43
|
throw new Error('Invalid module name. Use only letters, numbers, hyphens, and underscores. Must start with a letter.');
|
|
44
44
|
}
|
|
45
|
-
|
|
45
|
+
// Convert module name to valid TypeScript identifiers
|
|
46
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
47
|
+
const moduleNameCapitalized = moduleNameCamelCase.charAt(0).toUpperCase() + moduleNameCamelCase.slice(1);
|
|
48
|
+
console.log(`🔍 Debug: moduleName = "${moduleName}"`);
|
|
49
|
+
console.log(`🔍 Debug: moduleNameCamelCase = "${moduleNameCamelCase}"`);
|
|
50
|
+
console.log(`🔍 Debug: moduleNameCapitalized = "${moduleNameCapitalized}"`);
|
|
46
51
|
const currentDir = process.cwd();
|
|
47
52
|
// Check for required API project structure
|
|
48
53
|
const requiredDirs = ['src/modules'];
|
|
@@ -60,34 +65,49 @@ async function generateModule(moduleName) {
|
|
|
60
65
|
fs.mkdirSync(path.join(modulePath, 'controllers'), { recursive: true });
|
|
61
66
|
fs.mkdirSync(path.join(modulePath, 'routes'), { recursive: true });
|
|
62
67
|
}
|
|
68
|
+
// Parse options
|
|
69
|
+
const fields = options.fields || ['name', 'description', 'status'];
|
|
70
|
+
const generateRoutes = options.generateRoutes !== false;
|
|
71
|
+
const generateDatabase = options.generateDatabase !== false;
|
|
72
|
+
const crud = options.crud || false;
|
|
63
73
|
console.log('📝 Creating entity...');
|
|
64
|
-
const entityContent = generateEntityContent(
|
|
65
|
-
fs.writeFileSync(path.join(modulePath, 'entities', `${
|
|
74
|
+
const entityContent = generateEntityContent(moduleNameCamelCase, moduleNameCapitalized, fields);
|
|
75
|
+
fs.writeFileSync(path.join(modulePath, 'entities', `${moduleNameCamelCase}.entity.ts`), entityContent);
|
|
66
76
|
console.log('📋 Creating schema...');
|
|
67
|
-
const schemaContent = generateSchemaContent(
|
|
68
|
-
fs.writeFileSync(path.join(modulePath, 'schemas', `${
|
|
77
|
+
const schemaContent = generateSchemaContent(moduleNameCamelCase, moduleNameCapitalized, fields);
|
|
78
|
+
fs.writeFileSync(path.join(modulePath, 'schemas', `${moduleNameCamelCase}.schema.ts`), schemaContent);
|
|
69
79
|
console.log('🔧 Creating service...');
|
|
70
|
-
const serviceContent = generateServiceContent(
|
|
71
|
-
fs.writeFileSync(path.join(modulePath, 'services', `${
|
|
80
|
+
const serviceContent = generateServiceContent(moduleNameCamelCase, moduleNameCapitalized, fields, crud);
|
|
81
|
+
fs.writeFileSync(path.join(modulePath, 'services', `${moduleNameCamelCase}.service.ts`), serviceContent);
|
|
72
82
|
console.log('🎮 Creating controller...');
|
|
73
|
-
const controllerContent = generateControllerContent(
|
|
74
|
-
fs.writeFileSync(path.join(modulePath, 'controllers', `${
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
83
|
+
const controllerContent = generateControllerContent(moduleNameCamelCase, moduleNameCapitalized, fields, crud);
|
|
84
|
+
fs.writeFileSync(path.join(modulePath, 'controllers', `${moduleNameCamelCase}.controller.ts`), controllerContent);
|
|
85
|
+
if (generateRoutes) {
|
|
86
|
+
console.log('🛣️ Creating routes...');
|
|
87
|
+
const routesContent = generateRoutesContent(moduleNameCamelCase, moduleNameCapitalized, crud, fields);
|
|
88
|
+
fs.writeFileSync(path.join(modulePath, 'routes', `${moduleNameCamelCase}.routes.ts`), routesContent);
|
|
89
|
+
// Register routes in server manager
|
|
90
|
+
console.log('🔗 Registering routes...');
|
|
91
|
+
await registerModuleRoutes(currentDir, moduleName, moduleNameCapitalized);
|
|
92
|
+
}
|
|
93
|
+
if (generateDatabase) {
|
|
94
|
+
// Create database table/collection
|
|
95
|
+
console.log('🗄️ Creating database table...');
|
|
96
|
+
await createDatabaseTable(currentDir, moduleName, moduleNameCapitalized);
|
|
97
|
+
}
|
|
84
98
|
console.log('✅ Module generation completed!');
|
|
85
99
|
console.log(`📁 Module: src/modules/${moduleName}/`);
|
|
86
|
-
|
|
87
|
-
|
|
100
|
+
if (generateRoutes) {
|
|
101
|
+
console.log(`🔗 Routes: /api/${moduleName}s`);
|
|
102
|
+
}
|
|
103
|
+
if (generateDatabase) {
|
|
104
|
+
console.log(`🗄️ Database: ${moduleName} collection`);
|
|
105
|
+
}
|
|
88
106
|
}
|
|
89
|
-
function generateEntityContent(moduleName, moduleNameCapitalized) {
|
|
90
|
-
|
|
107
|
+
function generateEntityContent(moduleName, moduleNameCapitalized, fields) {
|
|
108
|
+
// Convert moduleName to camelCase for internal identifiers
|
|
109
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
110
|
+
let entityContent = `import * as mongoose from 'mongoose';
|
|
91
111
|
import { ObjectId } from "bson";
|
|
92
112
|
|
|
93
113
|
export interface I${moduleNameCapitalized} extends mongoose.Document {
|
|
@@ -98,12 +118,33 @@ export interface I${moduleNameCapitalized} extends mongoose.Document {
|
|
|
98
118
|
createdAt: Date,
|
|
99
119
|
updatedAt: Date
|
|
100
120
|
}`;
|
|
121
|
+
if (fields.length > 0) {
|
|
122
|
+
entityContent += `
|
|
123
|
+
export interface I${moduleNameCapitalized} extends mongoose.Document {
|
|
124
|
+
_id: ObjectId,
|
|
125
|
+
name: string,
|
|
126
|
+
description?: string,
|
|
127
|
+
status: number,
|
|
128
|
+
createdAt: Date,
|
|
129
|
+
updatedAt: Date
|
|
130
|
+
`;
|
|
131
|
+
fields.forEach(field => {
|
|
132
|
+
entityContent += `
|
|
133
|
+
${field}: string;
|
|
134
|
+
`;
|
|
135
|
+
});
|
|
136
|
+
entityContent += `
|
|
137
|
+
}`;
|
|
138
|
+
}
|
|
139
|
+
return entityContent;
|
|
101
140
|
}
|
|
102
|
-
function generateSchemaContent(moduleName, moduleNameCapitalized) {
|
|
103
|
-
|
|
104
|
-
|
|
141
|
+
function generateSchemaContent(moduleName, moduleNameCapitalized, fields) {
|
|
142
|
+
// Convert moduleName to camelCase for file paths
|
|
143
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
144
|
+
let schemaContent = `import * as mongoose from 'mongoose';
|
|
145
|
+
import { I${moduleNameCapitalized} } from '../entities/${moduleNameCamelCase}.entity';
|
|
105
146
|
|
|
106
|
-
export const ${
|
|
147
|
+
export const ${moduleNameCamelCase}Schema = new mongoose.Schema(
|
|
107
148
|
{
|
|
108
149
|
name: {
|
|
109
150
|
type: mongoose.SchemaTypes.String,
|
|
@@ -121,12 +162,90 @@ export const ${moduleName}Schema = new mongoose.Schema(
|
|
|
121
162
|
{ timestamps: true, suppressReservedKeysWarning: true },
|
|
122
163
|
);
|
|
123
164
|
|
|
124
|
-
export const ${moduleNameCapitalized}Model = mongoose.model<I${moduleNameCapitalized}>('${
|
|
165
|
+
export const ${moduleNameCapitalized}Model = mongoose.model<I${moduleNameCapitalized}>('${moduleNameCamelCase}', ${moduleNameCamelCase}Schema);`;
|
|
166
|
+
if (fields.length > 0) {
|
|
167
|
+
schemaContent += `
|
|
168
|
+
export const ${moduleNameCamelCase}Schema = new mongoose.Schema(
|
|
169
|
+
{
|
|
170
|
+
name: {
|
|
171
|
+
type: mongoose.SchemaTypes.String,
|
|
172
|
+
required: true,
|
|
173
|
+
},
|
|
174
|
+
description: {
|
|
175
|
+
type: mongoose.SchemaTypes.String,
|
|
176
|
+
required: false,
|
|
177
|
+
},
|
|
178
|
+
status: {
|
|
179
|
+
type: mongoose.SchemaTypes.Number,
|
|
180
|
+
default: 1,
|
|
181
|
+
}
|
|
182
|
+
`;
|
|
183
|
+
fields.forEach(field => {
|
|
184
|
+
schemaContent += `
|
|
185
|
+
${field}: {
|
|
186
|
+
type: mongoose.SchemaTypes.String,
|
|
187
|
+
required: true,
|
|
188
|
+
},
|
|
189
|
+
`;
|
|
190
|
+
});
|
|
191
|
+
schemaContent += `
|
|
192
|
+
},
|
|
193
|
+
{ timestamps: true, suppressReservedKeysWarning: true },
|
|
194
|
+
);
|
|
195
|
+
`;
|
|
196
|
+
}
|
|
197
|
+
return schemaContent;
|
|
125
198
|
}
|
|
126
|
-
function generateServiceContent(moduleName, moduleNameCapitalized) {
|
|
127
|
-
|
|
128
|
-
|
|
199
|
+
function generateServiceContent(moduleName, moduleNameCapitalized, fields, crud) {
|
|
200
|
+
// Convert moduleName to camelCase for file paths
|
|
201
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
202
|
+
let serviceContent = `import { ObjectId } from "bson";
|
|
203
|
+
import { ${moduleNameCapitalized}Model } from '../schemas/${moduleNameCamelCase}.schema';
|
|
129
204
|
|
|
205
|
+
export class ${moduleNameCapitalized}Service {
|
|
206
|
+
async getAll() {
|
|
207
|
+
try {
|
|
208
|
+
return await ${moduleNameCapitalized}Model.find({ status: 1 });
|
|
209
|
+
} catch (error) {
|
|
210
|
+
throw new Error(\`Failed to fetch ${moduleNameCamelCase}s: \${error.message}\`);
|
|
211
|
+
}
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
async getById(id: string) {
|
|
215
|
+
try {
|
|
216
|
+
return await ${moduleNameCapitalized}Model.findById(id);
|
|
217
|
+
} catch (error) {
|
|
218
|
+
throw new Error(\`Failed to fetch ${moduleNameCamelCase}: \${error.message}\`);
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
|
|
222
|
+
async create(data: any) {
|
|
223
|
+
try {
|
|
224
|
+
const entity = new ${moduleNameCapitalized}Model({ _id: new ObjectId(), ...data, status: 1 });
|
|
225
|
+
return await ${moduleNameCapitalized}Model.create(entity);
|
|
226
|
+
} catch (error) {
|
|
227
|
+
throw new Error(\`Failed to create ${moduleNameCamelCase}: \${error.message}\`);
|
|
228
|
+
}
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
async update(id: string, data: any) {
|
|
232
|
+
try {
|
|
233
|
+
return await ${moduleNameCapitalized}Model.findByIdAndUpdate(id, { ...data }, { new: true });
|
|
234
|
+
} catch (error) {
|
|
235
|
+
throw new Error(\`Failed to update ${moduleNameCamelCase}: \${error.message}\`);
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
async delete(id: string) {
|
|
240
|
+
try {
|
|
241
|
+
return await ${moduleNameCapitalized}Model.findByIdAndUpdate(id, { status: 0 }, { new: true });
|
|
242
|
+
} catch (error) {
|
|
243
|
+
throw new Error(\`Failed to delete ${moduleNameCamelCase}: \${error.message}\`);
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
}`;
|
|
247
|
+
if (crud) {
|
|
248
|
+
serviceContent += `
|
|
130
249
|
export class ${moduleNameCapitalized}Service {
|
|
131
250
|
async getAll() {
|
|
132
251
|
return await ${moduleNameCapitalized}Model.find({ status: 1 });
|
|
@@ -144,10 +263,21 @@ export class ${moduleNameCapitalized}Service {
|
|
|
144
263
|
async delete(id: string) {
|
|
145
264
|
return await ${moduleNameCapitalized}Model.findByIdAndUpdate(id, { status: 0 }, { new: true });
|
|
146
265
|
}
|
|
147
|
-
|
|
266
|
+
`;
|
|
267
|
+
fields.forEach(field => {
|
|
268
|
+
serviceContent += `
|
|
269
|
+
async ${field}(id: string, data: any) {
|
|
270
|
+
return await ${moduleNameCapitalized}Model.findByIdAndUpdate(id, { ${field}: data }, { new: true });
|
|
271
|
+
}
|
|
272
|
+
`;
|
|
273
|
+
});
|
|
274
|
+
}
|
|
275
|
+
return serviceContent;
|
|
148
276
|
}
|
|
149
|
-
function generateControllerContent(moduleName, moduleNameCapitalized) {
|
|
150
|
-
|
|
277
|
+
function generateControllerContent(moduleName, moduleNameCapitalized, fields, crud) {
|
|
278
|
+
// Convert moduleName to camelCase for file paths
|
|
279
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
280
|
+
let controllerContent = `import { ${moduleNameCapitalized}Service } from '../services/${moduleNameCamelCase}.service';
|
|
151
281
|
|
|
152
282
|
/**
|
|
153
283
|
* @openapi
|
|
@@ -189,14 +319,14 @@ export class ${moduleNameCapitalized}Controller {
|
|
|
189
319
|
|
|
190
320
|
/**
|
|
191
321
|
* @openapi
|
|
192
|
-
* /api/${
|
|
322
|
+
* /api/${moduleNameCamelCase}:
|
|
193
323
|
* get:
|
|
194
|
-
* summary: Get all ${
|
|
195
|
-
* description: Retrieve a list of all active ${
|
|
324
|
+
* summary: Get all ${moduleNameCamelCase}s
|
|
325
|
+
* description: Retrieve a list of all active ${moduleNameCamelCase}s
|
|
196
326
|
* tags: [${moduleNameCapitalized}s]
|
|
197
327
|
* responses:
|
|
198
328
|
* 200:
|
|
199
|
-
* description: List of ${
|
|
329
|
+
* description: List of ${moduleNameCamelCase}s retrieved successfully
|
|
200
330
|
* content:
|
|
201
331
|
* application/json:
|
|
202
332
|
* schema:
|
|
@@ -213,16 +343,28 @@ export class ${moduleNameCapitalized}Controller {
|
|
|
213
343
|
* description: Bad request
|
|
214
344
|
*/
|
|
215
345
|
async getAll(req, res) {
|
|
216
|
-
|
|
217
|
-
|
|
346
|
+
try {
|
|
347
|
+
const data = await this.service.getAll();
|
|
348
|
+
res.json({
|
|
349
|
+
Data: data,
|
|
350
|
+
StatusCode: 1000,
|
|
351
|
+
Message: '${moduleNameCapitalized}s retrieved successfully'
|
|
352
|
+
});
|
|
353
|
+
} catch (error: any) {
|
|
354
|
+
res.status(400).json({
|
|
355
|
+
Data: null,
|
|
356
|
+
StatusCode: 4000,
|
|
357
|
+
Message: error.message
|
|
358
|
+
});
|
|
359
|
+
}
|
|
218
360
|
}
|
|
219
361
|
|
|
220
362
|
/**
|
|
221
363
|
* @openapi
|
|
222
|
-
* /api/${
|
|
364
|
+
* /api/${moduleNameCamelCase}/{id}:
|
|
223
365
|
* get:
|
|
224
|
-
* summary: Get ${
|
|
225
|
-
* description: Retrieve a specific ${
|
|
366
|
+
* summary: Get ${moduleNameCamelCase} by ID
|
|
367
|
+
* description: Retrieve a specific ${moduleNameCamelCase} by its ID
|
|
226
368
|
* tags: [${moduleNameCapitalized}s]
|
|
227
369
|
* parameters:
|
|
228
370
|
* - in: path
|
|
@@ -248,8 +390,27 @@ export class ${moduleNameCapitalized}Controller {
|
|
|
248
390
|
* description: ${moduleNameCapitalized} not found
|
|
249
391
|
*/
|
|
250
392
|
async getById(req, res) {
|
|
251
|
-
|
|
252
|
-
|
|
393
|
+
try {
|
|
394
|
+
const data = await this.service.getById(req.params.id);
|
|
395
|
+
if (!data) {
|
|
396
|
+
return res.status(404).json({
|
|
397
|
+
Data: null,
|
|
398
|
+
StatusCode: 4004,
|
|
399
|
+
Message: '${moduleNameCapitalized} not found'
|
|
400
|
+
});
|
|
401
|
+
}
|
|
402
|
+
res.json({
|
|
403
|
+
Data: data,
|
|
404
|
+
StatusCode: 1000,
|
|
405
|
+
Message: '${moduleNameCapitalized} retrieved successfully'
|
|
406
|
+
});
|
|
407
|
+
} catch (error: any) {
|
|
408
|
+
res.status(400).json({
|
|
409
|
+
Data: null,
|
|
410
|
+
StatusCode: 4000,
|
|
411
|
+
Message: error.message
|
|
412
|
+
});
|
|
413
|
+
}
|
|
253
414
|
}
|
|
254
415
|
|
|
255
416
|
/**
|
|
@@ -295,8 +456,20 @@ export class ${moduleNameCapitalized}Controller {
|
|
|
295
456
|
* description: Bad request or missing required fields
|
|
296
457
|
*/
|
|
297
458
|
async create(req, res) {
|
|
298
|
-
|
|
299
|
-
|
|
459
|
+
try {
|
|
460
|
+
const data = await this.service.create(req.body);
|
|
461
|
+
res.status(201).json({
|
|
462
|
+
Data: data,
|
|
463
|
+
StatusCode: 1000,
|
|
464
|
+
Message: '${moduleNameCapitalized} created successfully'
|
|
465
|
+
});
|
|
466
|
+
} catch (error: any) {
|
|
467
|
+
res.status(400).json({
|
|
468
|
+
Data: null,
|
|
469
|
+
StatusCode: 4000,
|
|
470
|
+
Message: error.message
|
|
471
|
+
});
|
|
472
|
+
}
|
|
300
473
|
}
|
|
301
474
|
|
|
302
475
|
/**
|
|
@@ -382,19 +555,115 @@ export class ${moduleNameCapitalized}Controller {
|
|
|
382
555
|
* description: ${moduleNameCapitalized} not found
|
|
383
556
|
*/
|
|
384
557
|
async delete(req, res) {
|
|
385
|
-
|
|
386
|
-
|
|
558
|
+
try {
|
|
559
|
+
const data = await this.service.delete(req.params.id);
|
|
560
|
+
if (!data) {
|
|
561
|
+
return res.status(404).json({
|
|
562
|
+
Data: null,
|
|
563
|
+
StatusCode: 4004,
|
|
564
|
+
Message: '${moduleNameCapitalized} not found'
|
|
565
|
+
});
|
|
566
|
+
}
|
|
567
|
+
res.json({
|
|
568
|
+
Data: data,
|
|
569
|
+
StatusCode: 1000,
|
|
570
|
+
Message: '${moduleNameCapitalized} deleted successfully'
|
|
571
|
+
});
|
|
572
|
+
} catch (error: any) {
|
|
573
|
+
res.status(400).json({
|
|
574
|
+
Data: null,
|
|
575
|
+
StatusCode: 4000,
|
|
576
|
+
Message: error.message
|
|
577
|
+
});
|
|
578
|
+
}
|
|
387
579
|
}
|
|
388
|
-
|
|
580
|
+
`;
|
|
581
|
+
if (crud) {
|
|
582
|
+
controllerContent += `
|
|
583
|
+
`;
|
|
584
|
+
fields.forEach(field => {
|
|
585
|
+
controllerContent += `
|
|
586
|
+
/**
|
|
587
|
+
* @openapi
|
|
588
|
+
* /api/${moduleName}/{id}:
|
|
589
|
+
* put:
|
|
590
|
+
* summary: Update ${moduleName}
|
|
591
|
+
* description: Update an existing ${moduleName} record
|
|
592
|
+
* tags: [${moduleNameCapitalized}s]
|
|
593
|
+
* parameters:
|
|
594
|
+
* - in: path
|
|
595
|
+
* name: id
|
|
596
|
+
* required: true
|
|
597
|
+
* schema:
|
|
598
|
+
* type: string
|
|
599
|
+
* description: ${moduleNameCapitalized} ID
|
|
600
|
+
* requestBody:
|
|
601
|
+
* required: true
|
|
602
|
+
* content:
|
|
603
|
+
* application/json:
|
|
604
|
+
* schema:
|
|
605
|
+
* type: object
|
|
606
|
+
* properties:
|
|
607
|
+
* ${field}:
|
|
608
|
+
* type: string
|
|
609
|
+
* description: ${field} of the ${moduleNameCapitalized}
|
|
610
|
+
* responses:
|
|
611
|
+
* 200:
|
|
612
|
+
* description: ${moduleNameCapitalized} updated successfully
|
|
613
|
+
* content:
|
|
614
|
+
* application/json:
|
|
615
|
+
* schema:
|
|
616
|
+
* type: object
|
|
617
|
+
* properties:
|
|
618
|
+
* Data:
|
|
619
|
+
* $ref: '#/components/schemas/${moduleNameCapitalized}'
|
|
620
|
+
* StatusCode:
|
|
621
|
+
* type: integer
|
|
622
|
+
* example: 1000
|
|
623
|
+
* 404:
|
|
624
|
+
* description: ${moduleNameCapitalized} not found
|
|
625
|
+
*/
|
|
626
|
+
async update(req, res) {
|
|
627
|
+
try {
|
|
628
|
+
const data = await this.service.update(req.params.id, req.body);
|
|
629
|
+
if (!data) {
|
|
630
|
+
return res.status(404).json({
|
|
631
|
+
Data: null,
|
|
632
|
+
StatusCode: 4004,
|
|
633
|
+
Message: '${moduleNameCapitalized} not found'
|
|
634
|
+
});
|
|
635
|
+
}
|
|
636
|
+
res.json({
|
|
637
|
+
Data: data,
|
|
638
|
+
StatusCode: 1000,
|
|
639
|
+
Message: '${moduleNameCapitalized} updated successfully'
|
|
640
|
+
});
|
|
641
|
+
} catch (error: any) {
|
|
642
|
+
res.status(400).json({
|
|
643
|
+
Data: null,
|
|
644
|
+
StatusCode: 4000,
|
|
645
|
+
Message: error.message
|
|
646
|
+
});
|
|
647
|
+
}
|
|
648
|
+
}
|
|
649
|
+
`;
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
return controllerContent;
|
|
389
653
|
}
|
|
390
|
-
function generateRoutesContent(moduleName, moduleNameCapitalized) {
|
|
391
|
-
|
|
392
|
-
|
|
654
|
+
function generateRoutesContent(moduleName, moduleNameCapitalized, crud, fields = []) {
|
|
655
|
+
// Convert moduleName to camelCase for file paths
|
|
656
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
657
|
+
let routesContent = `import { Router } from 'express';
|
|
658
|
+
import { ${moduleNameCapitalized}Controller } from '../controllers/${moduleNameCamelCase}.controller';
|
|
393
659
|
|
|
394
660
|
const router = Router();
|
|
395
661
|
const controller = new ${moduleNameCapitalized}Controller();
|
|
396
662
|
|
|
397
|
-
|
|
663
|
+
// Health check endpoint
|
|
664
|
+
router.get('/health', (req, res) => res.send('${moduleNameCapitalized} API is up.'));
|
|
665
|
+
|
|
666
|
+
// CRUD endpoints
|
|
398
667
|
router.get('/all', (req, res) => controller.getAll(req, res));
|
|
399
668
|
router.get('/:id', (req, res) => controller.getById(req, res));
|
|
400
669
|
router.post('/', (req, res) => controller.create(req, res));
|
|
@@ -402,6 +671,16 @@ router.put('/:id', (req, res) => controller.update(req, res));
|
|
|
402
671
|
router.delete('/:id', (req, res) => controller.delete(req, res));
|
|
403
672
|
|
|
404
673
|
export default router;`;
|
|
674
|
+
if (crud && fields.length > 0) {
|
|
675
|
+
routesContent += `
|
|
676
|
+
`;
|
|
677
|
+
fields.forEach((field) => {
|
|
678
|
+
routesContent += `
|
|
679
|
+
router.put('/${field}/:id', (req, res) => controller.update(req, res));
|
|
680
|
+
`;
|
|
681
|
+
});
|
|
682
|
+
}
|
|
683
|
+
return routesContent;
|
|
405
684
|
}
|
|
406
685
|
function updateRoutesIndex(currentDir, moduleName) {
|
|
407
686
|
const routesIndexPath = path.join(currentDir, 'src/routes/index.ts');
|
|
@@ -409,15 +688,17 @@ function updateRoutesIndex(currentDir, moduleName) {
|
|
|
409
688
|
console.log('⚠️ routes/index.ts not found, skipping routes index update');
|
|
410
689
|
return;
|
|
411
690
|
}
|
|
691
|
+
// Convert moduleName to camelCase for file paths
|
|
692
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
412
693
|
let routesContent = fs.readFileSync(routesIndexPath, 'utf8');
|
|
413
|
-
// Add import
|
|
414
|
-
const importStatement = `import ${
|
|
694
|
+
// Add import - use camelCase for file path
|
|
695
|
+
const importStatement = `import ${moduleNameCamelCase}Routes from '../modules/${moduleName}/routes/${moduleNameCamelCase}.routes';`;
|
|
415
696
|
if (!routesContent.includes(importStatement)) {
|
|
416
697
|
// Add import after the userRoutes import
|
|
417
|
-
routesContent = routesContent.replace(/import userRoutes from '\.\.\/modules\/
|
|
698
|
+
routesContent = routesContent.replace(/import userRoutes from '\.\.\/modules\/user\/routes\/user\.routes';/, `import userRoutes from '../modules/user/routes/user.routes';\n${importStatement}`);
|
|
418
699
|
}
|
|
419
|
-
// Add route registration
|
|
420
|
-
const routeRegistration = `router.use('/${moduleName}', ${
|
|
700
|
+
// Add route registration - use original moduleName for route path
|
|
701
|
+
const routeRegistration = `router.use('/${moduleName}', ${moduleNameCamelCase}Routes);`;
|
|
421
702
|
if (!routesContent.includes(routeRegistration)) {
|
|
422
703
|
// Add route after the users route
|
|
423
704
|
routesContent = routesContent.replace(/router\.use\('\/users', userRoutes\);/, `router.use('/users', userRoutes);\n${routeRegistration}`);
|
|
@@ -435,9 +716,10 @@ async function createDatabaseTable(currentDir, moduleName, moduleNameCapitalized
|
|
|
435
716
|
if (fs.existsSync(mainSeederPath)) {
|
|
436
717
|
let seederContent = fs.readFileSync(mainSeederPath, 'utf8');
|
|
437
718
|
// Add import for the model
|
|
438
|
-
const
|
|
719
|
+
const moduleNameCamelCase = moduleName.replace(/[-_]([a-z0-9])/g, (_, char) => char.toUpperCase());
|
|
720
|
+
const importStatement = `import { ${moduleNameCapitalized}Model } from '../../modules/${moduleName}/schemas/${moduleNameCamelCase}.schema';`;
|
|
439
721
|
if (!seederContent.includes(importStatement)) {
|
|
440
|
-
seederContent = seederContent.replace(/import { UserModel } from '\.\.\/\.\.\/modules\/
|
|
722
|
+
seederContent = seederContent.replace(/import { UserModel } from '\.\.\/\.\.\/modules\/user\/schemas\/user\.schema';/, `import { UserModel } from '../../modules/user/schemas/user.schema';\n${importStatement}`);
|
|
441
723
|
}
|
|
442
724
|
// Add seeder function - use exact module name provided by developer
|
|
443
725
|
const seederFunction = ` private async seed${moduleNameCapitalized}(data: any[]): Promise<void> {
|
|
@@ -491,27 +773,46 @@ async function generateEndpoint(moduleName, endpointName, options = {}) {
|
|
|
491
773
|
if (!fs.existsSync(modulePath)) {
|
|
492
774
|
throw new Error(`Module '${moduleName}' does not exist. Please create the module first using 'generate:module ${moduleName}'`);
|
|
493
775
|
}
|
|
494
|
-
//
|
|
776
|
+
// Parse options
|
|
495
777
|
const method = (options.method || 'GET').toUpperCase();
|
|
496
778
|
const customPath = options.path || endpointName;
|
|
497
779
|
const description = options.description || `${endpointNameCapitalized} endpoint for ${moduleName}`;
|
|
780
|
+
const generateService = options.generateService !== false;
|
|
781
|
+
const generateController = options.generateController !== false;
|
|
782
|
+
const generateRoute = options.generateRoute !== false;
|
|
783
|
+
const force = options.force || false;
|
|
498
784
|
console.log(`🔧 Adding endpoint '${endpointName}' to module '${moduleName}'...`);
|
|
499
785
|
// Convert endpoint name to camelCase for method names
|
|
500
786
|
const camelCaseEndpoint = endpointName.replace(/-/g, '_').replace(/_([a-z])/g, (g) => g[1].toUpperCase());
|
|
501
787
|
const camelCaseEndpointCapitalized = camelCaseEndpoint.charAt(0).toUpperCase() + camelCaseEndpoint.slice(1);
|
|
502
|
-
// Add service method
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
788
|
+
// Add service method if requested
|
|
789
|
+
if (generateService) {
|
|
790
|
+
console.log('📝 Adding service method...');
|
|
791
|
+
await addServiceMethod(modulePath, moduleName, moduleNameCapitalized, camelCaseEndpoint, camelCaseEndpointCapitalized, method, description, force);
|
|
792
|
+
}
|
|
793
|
+
// Add controller method if requested
|
|
794
|
+
if (generateController) {
|
|
795
|
+
console.log('🎮 Adding controller method...');
|
|
796
|
+
await addControllerMethod(modulePath, moduleName, moduleNameCapitalized, camelCaseEndpoint, camelCaseEndpointCapitalized, method, customPath, description, force);
|
|
797
|
+
}
|
|
798
|
+
// Add route if requested
|
|
799
|
+
if (generateRoute) {
|
|
800
|
+
console.log('🛣️ Adding route...');
|
|
801
|
+
await addRoute(modulePath, moduleName, moduleNameCapitalized, camelCaseEndpoint, camelCaseEndpointCapitalized, method, customPath);
|
|
802
|
+
}
|
|
511
803
|
console.log(`✅ Endpoint '${endpointName}' added to module '${moduleName}' successfully!`);
|
|
512
804
|
console.log(`🔗 New endpoint available at: ${method} /api/${moduleName}/${customPath}`);
|
|
805
|
+
if (generateService) {
|
|
806
|
+
console.log(`📝 Service: Method '${camelCaseEndpoint}' added to service`);
|
|
807
|
+
}
|
|
808
|
+
if (generateController) {
|
|
809
|
+
console.log(`🎮 Controller: Method '${camelCaseEndpoint}' added to controller`);
|
|
810
|
+
}
|
|
811
|
+
if (generateRoute) {
|
|
812
|
+
console.log(`🛣️ Route: ${method} /${customPath} added to routes`);
|
|
813
|
+
}
|
|
513
814
|
}
|
|
514
|
-
async function addServiceMethod(modulePath, moduleName, moduleNameCapitalized, endpointName, endpointNameCapitalized, method, description) {
|
|
815
|
+
async function addServiceMethod(modulePath, moduleName, moduleNameCapitalized, endpointName, endpointNameCapitalized, method, description, force) {
|
|
515
816
|
// Use singular form for file names (convert plural to singular if needed)
|
|
516
817
|
const singularName = moduleName.endsWith('s') && moduleName.length > 1 ? moduleName.slice(0, -1) : moduleName;
|
|
517
818
|
const servicePath = path.join(modulePath, 'services', `${singularName}.service.ts`);
|
|
@@ -519,6 +820,10 @@ async function addServiceMethod(modulePath, moduleName, moduleNameCapitalized, e
|
|
|
519
820
|
throw new Error(`Service file not found: ${servicePath}`);
|
|
520
821
|
}
|
|
521
822
|
let serviceContent = fs.readFileSync(servicePath, 'utf8');
|
|
823
|
+
// Check if method already exists
|
|
824
|
+
if (serviceContent.includes(`async ${endpointName}(`) && !force) {
|
|
825
|
+
throw new Error(`Service method '${endpointName}' already exists. Use --force to override.`);
|
|
826
|
+
}
|
|
522
827
|
// Generate service method based on HTTP method
|
|
523
828
|
let serviceMethod = '';
|
|
524
829
|
switch (method) {
|
|
@@ -556,12 +861,19 @@ async function addServiceMethod(modulePath, moduleName, moduleNameCapitalized, e
|
|
|
556
861
|
return { message: '${endpointNameCapitalized} endpoint - implement your logic here', params };
|
|
557
862
|
}`;
|
|
558
863
|
}
|
|
559
|
-
//
|
|
560
|
-
|
|
561
|
-
|
|
864
|
+
// If method exists and force is enabled, replace it
|
|
865
|
+
if (serviceContent.includes(`async ${endpointName}(`) && force) {
|
|
866
|
+
const methodRegex = new RegExp(`\\s*async ${endpointName}\\([^)]*\\)\\s*\\{[^}]*\\}`, 's');
|
|
867
|
+
serviceContent = serviceContent.replace(methodRegex, serviceMethod);
|
|
868
|
+
}
|
|
869
|
+
else {
|
|
870
|
+
// Add method before the closing brace
|
|
871
|
+
const lastBraceIndex = serviceContent.lastIndexOf('}');
|
|
872
|
+
serviceContent = serviceContent.slice(0, lastBraceIndex) + serviceMethod + '\n' + serviceContent.slice(lastBraceIndex);
|
|
873
|
+
}
|
|
562
874
|
fs.writeFileSync(servicePath, serviceContent);
|
|
563
875
|
}
|
|
564
|
-
async function addControllerMethod(modulePath, moduleName, moduleNameCapitalized, endpointName, endpointNameCapitalized, method, customPath, description) {
|
|
876
|
+
async function addControllerMethod(modulePath, moduleName, moduleNameCapitalized, endpointName, endpointNameCapitalized, method, customPath, description, force) {
|
|
565
877
|
// Use singular form for file names (convert plural to singular if needed)
|
|
566
878
|
const singularName = moduleName.endsWith('s') && moduleName.length > 1 ? moduleName.slice(0, -1) : moduleName;
|
|
567
879
|
const controllerPath = path.join(modulePath, 'controllers', `${singularName}.controller.ts`);
|
|
@@ -569,132 +881,117 @@ async function addControllerMethod(modulePath, moduleName, moduleNameCapitalized
|
|
|
569
881
|
throw new Error(`Controller file not found: ${controllerPath}`);
|
|
570
882
|
}
|
|
571
883
|
let controllerContent = fs.readFileSync(controllerPath, 'utf8');
|
|
572
|
-
//
|
|
573
|
-
if (
|
|
574
|
-
|
|
575
|
-
}
|
|
576
|
-
if (!controllerContent.includes('import { handleResponse }')) {
|
|
577
|
-
controllerContent = `import { handleResponse } from '../../../shared/utils/handle-response';\n` + controllerContent;
|
|
884
|
+
// Check if method already exists
|
|
885
|
+
if (controllerContent.includes(`async ${endpointName}(`) && !force) {
|
|
886
|
+
throw new Error(`Controller method '${endpointName}' already exists. Use --force to override.`);
|
|
578
887
|
}
|
|
579
|
-
|
|
580
|
-
controllerContent = `import { Result } from '../../../shared/types/result';\n` + controllerContent;
|
|
581
|
-
}
|
|
582
|
-
if (!controllerContent.includes('import { v4 as uuidv4 }')) {
|
|
583
|
-
controllerContent = `import { v4 as uuidv4 } from 'uuid';\n` + controllerContent;
|
|
584
|
-
}
|
|
585
|
-
if (!controllerContent.includes('import { ResponseCode }')) {
|
|
586
|
-
controllerContent = `import { ResponseCode } from '../../../shared/constants/enums';\n` + controllerContent;
|
|
587
|
-
}
|
|
588
|
-
// Generate Swagger documentation and controller method
|
|
589
|
-
let swaggerDoc = '';
|
|
888
|
+
// Generate controller method based on HTTP method
|
|
590
889
|
let controllerMethod = '';
|
|
591
890
|
switch (method) {
|
|
592
891
|
case 'GET':
|
|
593
|
-
|
|
594
|
-
* @
|
|
892
|
+
controllerMethod = ` /**
|
|
893
|
+
* @openapi
|
|
595
894
|
* /api/${moduleName}/${customPath}:
|
|
596
895
|
* get:
|
|
597
|
-
* summary: ${endpointNameCapitalized}
|
|
896
|
+
* summary: ${endpointNameCapitalized}
|
|
598
897
|
* description: ${description}
|
|
599
|
-
* tags: [${moduleNameCapitalized}]
|
|
898
|
+
* tags: [${moduleNameCapitalized}s]
|
|
600
899
|
* parameters:
|
|
601
900
|
* - in: query
|
|
602
|
-
* name:
|
|
901
|
+
* name: params
|
|
603
902
|
* schema:
|
|
604
|
-
* type:
|
|
605
|
-
* description:
|
|
903
|
+
* type: object
|
|
904
|
+
* description: Query parameters
|
|
606
905
|
* responses:
|
|
607
906
|
* 200:
|
|
608
|
-
* description: ${endpointNameCapitalized}
|
|
907
|
+
* description: ${endpointNameCapitalized} executed successfully
|
|
609
908
|
* content:
|
|
610
909
|
* application/json:
|
|
611
910
|
* schema:
|
|
612
911
|
* type: object
|
|
613
912
|
* properties:
|
|
614
|
-
*
|
|
913
|
+
* Data:
|
|
615
914
|
* type: object
|
|
616
|
-
*
|
|
915
|
+
* StatusCode:
|
|
617
916
|
* type: integer
|
|
618
917
|
* example: 1000
|
|
619
|
-
* errors:
|
|
620
|
-
* type: array
|
|
621
|
-
* items:
|
|
622
|
-
* type: object
|
|
623
|
-
* requestIdentifier:
|
|
624
|
-
* type: string
|
|
625
918
|
* 400:
|
|
626
919
|
* description: Bad request
|
|
627
|
-
|
|
628
|
-
|
|
629
|
-
const requestIdentifier = req.headers['x-request-id'] || uuidv4();
|
|
920
|
+
*/
|
|
921
|
+
async ${endpointName}(req, res) {
|
|
630
922
|
try {
|
|
631
|
-
|
|
632
|
-
|
|
633
|
-
|
|
634
|
-
|
|
635
|
-
|
|
636
|
-
|
|
923
|
+
const params = req.query;
|
|
924
|
+
const result = await this.service.${endpointName}(params);
|
|
925
|
+
res.json({
|
|
926
|
+
Data: result,
|
|
927
|
+
StatusCode: 1000,
|
|
928
|
+
Message: '${endpointNameCapitalized} executed successfully'
|
|
929
|
+
});
|
|
930
|
+
} catch (error) {
|
|
931
|
+
res.status(400).json({
|
|
932
|
+
Data: null,
|
|
933
|
+
StatusCode: 4000,
|
|
934
|
+
Message: error.message
|
|
935
|
+
});
|
|
637
936
|
}
|
|
638
|
-
|
|
937
|
+
}`;
|
|
639
938
|
break;
|
|
640
939
|
case 'POST':
|
|
641
|
-
|
|
642
|
-
* @
|
|
940
|
+
controllerMethod = ` /**
|
|
941
|
+
* @openapi
|
|
643
942
|
* /api/${moduleName}/${customPath}:
|
|
644
943
|
* post:
|
|
645
|
-
* summary: ${endpointNameCapitalized}
|
|
944
|
+
* summary: ${endpointNameCapitalized}
|
|
646
945
|
* description: ${description}
|
|
647
|
-
* tags: [${moduleNameCapitalized}]
|
|
946
|
+
* tags: [${moduleNameCapitalized}s]
|
|
648
947
|
* requestBody:
|
|
649
948
|
* required: true
|
|
650
949
|
* content:
|
|
651
950
|
* application/json:
|
|
652
951
|
* schema:
|
|
653
952
|
* type: object
|
|
654
|
-
* properties:
|
|
655
|
-
* # Add your request body properties here
|
|
656
953
|
* responses:
|
|
657
954
|
* 200:
|
|
658
|
-
* description: ${endpointNameCapitalized}
|
|
955
|
+
* description: ${endpointNameCapitalized} executed successfully
|
|
659
956
|
* content:
|
|
660
957
|
* application/json:
|
|
661
958
|
* schema:
|
|
662
959
|
* type: object
|
|
663
960
|
* properties:
|
|
664
|
-
*
|
|
961
|
+
* Data:
|
|
665
962
|
* type: object
|
|
666
|
-
*
|
|
963
|
+
* StatusCode:
|
|
667
964
|
* type: integer
|
|
668
965
|
* example: 1000
|
|
669
|
-
* errors:
|
|
670
|
-
* type: array
|
|
671
|
-
* items:
|
|
672
|
-
* type: object
|
|
673
|
-
* requestIdentifier:
|
|
674
|
-
* type: string
|
|
675
966
|
* 400:
|
|
676
967
|
* description: Bad request
|
|
677
|
-
|
|
678
|
-
|
|
679
|
-
const requestIdentifier = req.headers['x-request-id'] || uuidv4();
|
|
968
|
+
*/
|
|
969
|
+
async ${endpointName}(req, res) {
|
|
680
970
|
try {
|
|
681
|
-
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
686
|
-
|
|
971
|
+
const data = req.body;
|
|
972
|
+
const result = await this.service.${endpointName}(data);
|
|
973
|
+
res.json({
|
|
974
|
+
Data: result,
|
|
975
|
+
StatusCode: 1000,
|
|
976
|
+
Message: '${endpointNameCapitalized} executed successfully'
|
|
977
|
+
});
|
|
978
|
+
} catch (error) {
|
|
979
|
+
res.status(400).json({
|
|
980
|
+
Data: null,
|
|
981
|
+
StatusCode: 4000,
|
|
982
|
+
Message: error.message
|
|
983
|
+
});
|
|
687
984
|
}
|
|
688
|
-
|
|
985
|
+
}`;
|
|
689
986
|
break;
|
|
690
987
|
case 'PUT':
|
|
691
|
-
|
|
692
|
-
* @
|
|
988
|
+
controllerMethod = ` /**
|
|
989
|
+
* @openapi
|
|
693
990
|
* /api/${moduleName}/${customPath}/{id}:
|
|
694
991
|
* put:
|
|
695
|
-
* summary: ${endpointNameCapitalized}
|
|
992
|
+
* summary: ${endpointNameCapitalized}
|
|
696
993
|
* description: ${description}
|
|
697
|
-
* tags: [${moduleNameCapitalized}]
|
|
994
|
+
* tags: [${moduleNameCapitalized}s]
|
|
698
995
|
* parameters:
|
|
699
996
|
* - in: path
|
|
700
997
|
* name: id
|
|
@@ -708,50 +1005,49 @@ async function addControllerMethod(modulePath, moduleName, moduleNameCapitalized
|
|
|
708
1005
|
* application/json:
|
|
709
1006
|
* schema:
|
|
710
1007
|
* type: object
|
|
711
|
-
* properties:
|
|
712
|
-
* # Add your request body properties here
|
|
713
1008
|
* responses:
|
|
714
1009
|
* 200:
|
|
715
|
-
* description: ${endpointNameCapitalized}
|
|
1010
|
+
* description: ${endpointNameCapitalized} executed successfully
|
|
716
1011
|
* content:
|
|
717
1012
|
* application/json:
|
|
718
1013
|
* schema:
|
|
719
1014
|
* type: object
|
|
720
1015
|
* properties:
|
|
721
|
-
*
|
|
1016
|
+
* Data:
|
|
722
1017
|
* type: object
|
|
723
|
-
*
|
|
1018
|
+
* StatusCode:
|
|
724
1019
|
* type: integer
|
|
725
1020
|
* example: 1000
|
|
726
|
-
*
|
|
727
|
-
*
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
* requestIdentifier:
|
|
731
|
-
* type: string
|
|
732
|
-
* 404:
|
|
733
|
-
* description: ${moduleNameCapitalized} not found
|
|
734
|
-
*/`;
|
|
735
|
-
controllerMethod = ` async ${endpointName}(req: Request, res: Response): Promise<void> {
|
|
736
|
-
const requestIdentifier = req.headers['x-request-id'] || uuidv4();
|
|
1021
|
+
* 400:
|
|
1022
|
+
* description: Bad request
|
|
1023
|
+
*/
|
|
1024
|
+
async ${endpointName}(req, res) {
|
|
737
1025
|
try {
|
|
738
|
-
|
|
739
|
-
|
|
740
|
-
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
1026
|
+
const { id } = req.params;
|
|
1027
|
+
const data = req.body;
|
|
1028
|
+
const result = await this.service.${endpointName}(id, data);
|
|
1029
|
+
res.json({
|
|
1030
|
+
Data: result,
|
|
1031
|
+
StatusCode: 1000,
|
|
1032
|
+
Message: '${endpointNameCapitalized} executed successfully'
|
|
1033
|
+
});
|
|
1034
|
+
} catch (error) {
|
|
1035
|
+
res.status(400).json({
|
|
1036
|
+
Data: null,
|
|
1037
|
+
StatusCode: 4000,
|
|
1038
|
+
Message: error.message
|
|
1039
|
+
});
|
|
744
1040
|
}
|
|
745
|
-
|
|
1041
|
+
}`;
|
|
746
1042
|
break;
|
|
747
1043
|
case 'DELETE':
|
|
748
|
-
|
|
749
|
-
* @
|
|
1044
|
+
controllerMethod = ` /**
|
|
1045
|
+
* @openapi
|
|
750
1046
|
* /api/${moduleName}/${customPath}/{id}:
|
|
751
1047
|
* delete:
|
|
752
|
-
* summary: ${endpointNameCapitalized}
|
|
1048
|
+
* summary: ${endpointNameCapitalized}
|
|
753
1049
|
* description: ${description}
|
|
754
|
-
* tags: [${moduleNameCapitalized}]
|
|
1050
|
+
* tags: [${moduleNameCapitalized}s]
|
|
755
1051
|
* parameters:
|
|
756
1052
|
* - in: path
|
|
757
1053
|
* name: id
|
|
@@ -761,84 +1057,90 @@ async function addControllerMethod(modulePath, moduleName, moduleNameCapitalized
|
|
|
761
1057
|
* description: ${moduleNameCapitalized} ID
|
|
762
1058
|
* responses:
|
|
763
1059
|
* 200:
|
|
764
|
-
* description: ${endpointNameCapitalized}
|
|
1060
|
+
* description: ${endpointNameCapitalized} executed successfully
|
|
765
1061
|
* content:
|
|
766
1062
|
* application/json:
|
|
767
1063
|
* schema:
|
|
768
1064
|
* type: object
|
|
769
1065
|
* properties:
|
|
770
|
-
*
|
|
1066
|
+
* Data:
|
|
771
1067
|
* type: object
|
|
772
|
-
*
|
|
1068
|
+
* StatusCode:
|
|
773
1069
|
* type: integer
|
|
774
1070
|
* example: 1000
|
|
775
|
-
*
|
|
776
|
-
*
|
|
777
|
-
|
|
778
|
-
|
|
779
|
-
* requestIdentifier:
|
|
780
|
-
* type: string
|
|
781
|
-
* 404:
|
|
782
|
-
* description: ${moduleNameCapitalized} not found
|
|
783
|
-
*/`;
|
|
784
|
-
controllerMethod = ` async ${endpointName}(req: Request, res: Response): Promise<void> {
|
|
785
|
-
const requestIdentifier = req.headers['x-request-id'] || uuidv4();
|
|
1071
|
+
* 400:
|
|
1072
|
+
* description: Bad request
|
|
1073
|
+
*/
|
|
1074
|
+
async ${endpointName}(req, res) {
|
|
786
1075
|
try {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
|
|
790
|
-
|
|
791
|
-
|
|
792
|
-
|
|
1076
|
+
const { id } = req.params;
|
|
1077
|
+
const result = await this.service.${endpointName}(id);
|
|
1078
|
+
res.json({
|
|
1079
|
+
Data: result,
|
|
1080
|
+
StatusCode: 1000,
|
|
1081
|
+
Message: '${endpointNameCapitalized} executed successfully'
|
|
1082
|
+
});
|
|
1083
|
+
} catch (error) {
|
|
1084
|
+
res.status(400).json({
|
|
1085
|
+
Data: null,
|
|
1086
|
+
StatusCode: 4000,
|
|
1087
|
+
Message: error.message
|
|
1088
|
+
});
|
|
793
1089
|
}
|
|
794
|
-
|
|
1090
|
+
}`;
|
|
795
1091
|
break;
|
|
796
1092
|
default:
|
|
797
|
-
|
|
798
|
-
* @
|
|
1093
|
+
controllerMethod = ` /**
|
|
1094
|
+
* @openapi
|
|
799
1095
|
* /api/${moduleName}/${customPath}:
|
|
800
1096
|
* ${method.toLowerCase()}:
|
|
801
|
-
* summary: ${endpointNameCapitalized}
|
|
1097
|
+
* summary: ${endpointNameCapitalized}
|
|
802
1098
|
* description: ${description}
|
|
803
|
-
* tags: [${moduleNameCapitalized}]
|
|
1099
|
+
* tags: [${moduleNameCapitalized}s]
|
|
804
1100
|
* responses:
|
|
805
1101
|
* 200:
|
|
806
|
-
* description: ${endpointNameCapitalized}
|
|
1102
|
+
* description: ${endpointNameCapitalized} executed successfully
|
|
807
1103
|
* content:
|
|
808
1104
|
* application/json:
|
|
809
1105
|
* schema:
|
|
810
1106
|
* type: object
|
|
811
1107
|
* properties:
|
|
812
|
-
*
|
|
1108
|
+
* Data:
|
|
813
1109
|
* type: object
|
|
814
|
-
*
|
|
1110
|
+
* StatusCode:
|
|
815
1111
|
* type: integer
|
|
816
1112
|
* example: 1000
|
|
817
|
-
* errors:
|
|
818
|
-
* type: array
|
|
819
|
-
* items:
|
|
820
|
-
* type: object
|
|
821
|
-
* requestIdentifier:
|
|
822
|
-
* type: string
|
|
823
1113
|
* 400:
|
|
824
1114
|
* description: Bad request
|
|
825
|
-
|
|
826
|
-
|
|
827
|
-
const requestIdentifier = req.headers['x-request-id'] || uuidv4();
|
|
1115
|
+
*/
|
|
1116
|
+
async ${endpointName}(req, res) {
|
|
828
1117
|
try {
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
1118
|
+
const params = req.query || req.body || req.params;
|
|
1119
|
+
const result = await this.service.${endpointName}(params);
|
|
1120
|
+
res.json({
|
|
1121
|
+
Data: result,
|
|
1122
|
+
StatusCode: 1000,
|
|
1123
|
+
Message: '${endpointNameCapitalized} executed successfully'
|
|
1124
|
+
});
|
|
1125
|
+
} catch (error) {
|
|
1126
|
+
res.status(400).json({
|
|
1127
|
+
Data: null,
|
|
1128
|
+
StatusCode: 4000,
|
|
1129
|
+
Message: error.message
|
|
1130
|
+
});
|
|
835
1131
|
}
|
|
836
|
-
|
|
1132
|
+
}`;
|
|
1133
|
+
}
|
|
1134
|
+
// If method exists and force is enabled, replace it
|
|
1135
|
+
if (controllerContent.includes(`async ${endpointName}(`) && force) {
|
|
1136
|
+
const methodRegex = new RegExp(`\\s*async ${endpointName}\\([^)]*\\)\\s*\\{[^}]*\\}`, 's');
|
|
1137
|
+
controllerContent = controllerContent.replace(methodRegex, controllerMethod);
|
|
1138
|
+
}
|
|
1139
|
+
else {
|
|
1140
|
+
// Add method before the closing brace
|
|
1141
|
+
const lastBraceIndex = controllerContent.lastIndexOf('}');
|
|
1142
|
+
controllerContent = controllerContent.slice(0, lastBraceIndex) + controllerMethod + '\n' + controllerContent.slice(lastBraceIndex);
|
|
837
1143
|
}
|
|
838
|
-
// Add method before the closing brace
|
|
839
|
-
const lastBraceIndex = controllerContent.lastIndexOf('}');
|
|
840
|
-
const methodWithDoc = swaggerDoc + '\n' + controllerMethod;
|
|
841
|
-
controllerContent = controllerContent.slice(0, lastBraceIndex) + methodWithDoc + '\n' + controllerContent.slice(lastBraceIndex);
|
|
842
1144
|
fs.writeFileSync(controllerPath, controllerContent);
|
|
843
1145
|
}
|
|
844
1146
|
async function addRoute(modulePath, moduleName, moduleNameCapitalized, endpointName, endpointNameCapitalized, method, customPath) {
|