@asad_dev/leo-generator 1.6.0 → 1.6.2
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/index.js
CHANGED
|
@@ -530,17 +530,17 @@ function main() {
|
|
|
530
530
|
postmanCollectionId: config.postmanCollectionId
|
|
531
531
|
}, hasFile);
|
|
532
532
|
});
|
|
533
|
-
// Documentation update command
|
|
534
533
|
program
|
|
535
534
|
.command("update-docs")
|
|
536
535
|
.alias("docs")
|
|
537
536
|
.description("Update Postman and Swagger documentation for existing modules")
|
|
537
|
+
.argument("[modules...]", "Specific modules to update (optional)")
|
|
538
538
|
.option("--modules-dir <path>", "Path to modules directory", "src/app/modules")
|
|
539
539
|
.option("--no-postman", "Skip Postman collection generation")
|
|
540
540
|
.option("--no-swagger", "Skip Swagger documentation generation")
|
|
541
541
|
.option("--postman-dir <path>", "Custom Postman output directory", "postman")
|
|
542
542
|
.option("--swagger-file <path>", "Custom Swagger file path", "swagger.json")
|
|
543
|
-
.action((options) => __awaiter(this, void 0, void 0, function* () {
|
|
543
|
+
.action((modules, options) => __awaiter(this, void 0, void 0, function* () {
|
|
544
544
|
yield (0, documentationUpdater_1.updateExistingModulesDocumentation)(options.modulesDir, {
|
|
545
545
|
updatePostman: options.postman !== false,
|
|
546
546
|
updateSwagger: options.swagger !== false,
|
|
@@ -548,7 +548,7 @@ function main() {
|
|
|
548
548
|
swaggerFile: options.swaggerFile,
|
|
549
549
|
postmanApiKey: config.postmanApiKey,
|
|
550
550
|
postmanCollectionId: config.postmanCollectionId
|
|
551
|
-
});
|
|
551
|
+
}, modules);
|
|
552
552
|
}));
|
|
553
553
|
// Legacy support - direct module generation (backward compatibility)
|
|
554
554
|
program
|
|
@@ -84,16 +84,25 @@ function updateAllDocumentation(moduleName_1, fields_1) {
|
|
|
84
84
|
});
|
|
85
85
|
}
|
|
86
86
|
function updateExistingModulesDocumentation() {
|
|
87
|
-
return __awaiter(this, arguments, void 0, function* (modulesDir = "src/app/modules", options = {}) {
|
|
87
|
+
return __awaiter(this, arguments, void 0, function* (modulesDir = "src/app/modules", options = {}, targetModules = []) {
|
|
88
88
|
const fullModulesPath = path.join(process.cwd(), modulesDir);
|
|
89
89
|
if (!fs.existsSync(fullModulesPath)) {
|
|
90
90
|
console.error(`❌ Modules directory not found: ${fullModulesPath}`);
|
|
91
91
|
return;
|
|
92
92
|
}
|
|
93
93
|
console.log("🔄 Scanning existing modules for documentation updates...");
|
|
94
|
-
|
|
94
|
+
let moduleDirectories = fs.readdirSync(fullModulesPath, { withFileTypes: true })
|
|
95
95
|
.filter(dirent => dirent.isDirectory())
|
|
96
96
|
.map(dirent => dirent.name);
|
|
97
|
+
// Filter if target modules are specified
|
|
98
|
+
if (targetModules && targetModules.length > 0) {
|
|
99
|
+
const targets = targetModules.map(m => m.toLowerCase());
|
|
100
|
+
moduleDirectories = moduleDirectories.filter(dir => targets.includes(dir.toLowerCase()));
|
|
101
|
+
if (moduleDirectories.length === 0) {
|
|
102
|
+
console.warn(`⚠️ None of the specified modules were found: ${targetModules.join(', ')}`);
|
|
103
|
+
return;
|
|
104
|
+
}
|
|
105
|
+
}
|
|
97
106
|
let updatedCount = 0;
|
|
98
107
|
// Process modules sequentially to avoid race conditions with Postman API
|
|
99
108
|
for (const moduleDir of moduleDirectories) {
|
|
@@ -149,7 +158,9 @@ function extractFieldsFromInterface(interfaceFilePath) {
|
|
|
149
158
|
}
|
|
150
159
|
const fields = [];
|
|
151
160
|
// Extract nested interface definitions first
|
|
152
|
-
const
|
|
161
|
+
const camelCaseName = toCamelCase(moduleName);
|
|
162
|
+
const mainInterfaceName = `I${camelCaseName}`;
|
|
163
|
+
const nestedInterfaces = extractNestedInterfaces(interfaceContent, mainInterfaceName);
|
|
153
164
|
// Extract enum definitions from the interface file
|
|
154
165
|
const enumDefinitions = extractEnumDefinitions(interfaceContent);
|
|
155
166
|
// Find the main interface definition (starts with 'I' and is the main entity interface)
|
|
@@ -225,15 +236,15 @@ function extractEnumDefinitions(content) {
|
|
|
225
236
|
return enumMap;
|
|
226
237
|
}
|
|
227
238
|
// Extract nested interface definitions
|
|
228
|
-
function extractNestedInterfaces(content) {
|
|
239
|
+
function extractNestedInterfaces(content, mainInterfaceName) {
|
|
229
240
|
const nestedInterfaces = new Map();
|
|
230
241
|
// Find all interface definitions using a more robust approach
|
|
231
242
|
const interfaceRegex = /export interface (\w+)\s*\{([\s\S]*?)\}/g;
|
|
232
243
|
let match;
|
|
233
244
|
while ((match = interfaceRegex.exec(content)) !== null) {
|
|
234
245
|
const [, interfaceName, interfaceBody] = match;
|
|
235
|
-
// Skip the main interface
|
|
236
|
-
if (
|
|
246
|
+
// Skip the main interface
|
|
247
|
+
if (mainInterfaceName && interfaceName === mainInterfaceName) {
|
|
237
248
|
continue;
|
|
238
249
|
}
|
|
239
250
|
// Skip type definitions
|
|
@@ -126,7 +126,40 @@ function parseFieldDefinitions(args) {
|
|
|
126
126
|
isOptional,
|
|
127
127
|
objectProperties,
|
|
128
128
|
});
|
|
129
|
-
console.log(`Added field with ${objectProperties.length} properties`);
|
|
129
|
+
console.log(`Added array:object field with ${objectProperties.length} properties`);
|
|
130
|
+
}
|
|
131
|
+
else if (type === "object" && parts.length > 2) {
|
|
132
|
+
console.log(`Processing object field: ${name}`);
|
|
133
|
+
const objectProperties = [];
|
|
134
|
+
for (let j = 2; j < parts.length; j += 2) {
|
|
135
|
+
if (j + 1 < parts.length) {
|
|
136
|
+
let propName = parts[j];
|
|
137
|
+
const propType = parts[j + 1];
|
|
138
|
+
console.log(` Property: ${propName}:${propType}`);
|
|
139
|
+
const propIsOptional = propName.endsWith("?");
|
|
140
|
+
const propIsRequired = propName.endsWith("!");
|
|
141
|
+
if (propIsOptional) {
|
|
142
|
+
propName = propName.slice(0, -1);
|
|
143
|
+
}
|
|
144
|
+
if (propIsRequired) {
|
|
145
|
+
propName = propName.slice(0, -1);
|
|
146
|
+
}
|
|
147
|
+
objectProperties.push({
|
|
148
|
+
name: propName,
|
|
149
|
+
type: propType,
|
|
150
|
+
isOptional: propIsOptional,
|
|
151
|
+
isRequired: propIsRequired,
|
|
152
|
+
});
|
|
153
|
+
}
|
|
154
|
+
}
|
|
155
|
+
fields.push({
|
|
156
|
+
name,
|
|
157
|
+
type,
|
|
158
|
+
isRequired,
|
|
159
|
+
isOptional,
|
|
160
|
+
objectProperties,
|
|
161
|
+
});
|
|
162
|
+
console.log(`Added object field with ${objectProperties.length} properties`);
|
|
130
163
|
}
|
|
131
164
|
else if (type === "array" && parts.length > 2) {
|
|
132
165
|
// Handle array of references (e.g., products:array:objectid:Product)
|
|
@@ -3,13 +3,14 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.generateInterfaceContent = generateInterfaceContent;
|
|
4
4
|
function generateInterfaceContent(camelCaseName, fields) {
|
|
5
5
|
let interfaceContent = `import { Model, Types } from 'mongoose';\n\n`;
|
|
6
|
-
// Generate nested interfaces for array of objects
|
|
7
6
|
fields.forEach((field) => {
|
|
8
|
-
var _a, _b;
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
const nestedInterfaceName =
|
|
7
|
+
var _a, _b, _c;
|
|
8
|
+
const isArrayObject = field.type.toLowerCase() === "array" && ((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object";
|
|
9
|
+
const isObjectWithProps = field.type.toLowerCase() === "object" && ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length);
|
|
10
|
+
if ((isArrayObject || isObjectWithProps) && ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length)) {
|
|
11
|
+
const nestedInterfaceName = isObjectWithProps
|
|
12
|
+
? `I${toCamelCase(field.name)}`
|
|
13
|
+
: `${toCamelCase(field.name)}Item`;
|
|
13
14
|
interfaceContent += `export interface ${nestedInterfaceName} {\n`;
|
|
14
15
|
field.objectProperties.forEach((prop) => {
|
|
15
16
|
// Skip _id field
|
|
@@ -139,12 +140,8 @@ function mapToTypeScriptType(field) {
|
|
|
139
140
|
case "object":
|
|
140
141
|
if ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length) {
|
|
141
142
|
// Object with defined properties
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
const optionalMarker = prop.isOptional ? "?" : "";
|
|
145
|
-
return `${prop.name}${optionalMarker}: ${mapToTypeScriptType(prop)}`;
|
|
146
|
-
})
|
|
147
|
-
.join("; ")} }`;
|
|
143
|
+
const nestedInterfaceName = `I${toCamelCase(field.name)}`;
|
|
144
|
+
return nestedInterfaceName;
|
|
148
145
|
}
|
|
149
146
|
else {
|
|
150
147
|
return "Record<string, any>";
|
|
@@ -41,11 +41,12 @@ function generateModelContent(camelCaseName, folderName, fields) {
|
|
|
41
41
|
function generateNestedSchemas(fields) {
|
|
42
42
|
let nestedSchemas = "";
|
|
43
43
|
fields.forEach((field) => {
|
|
44
|
-
var _a, _b;
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
const
|
|
44
|
+
var _a, _b, _c;
|
|
45
|
+
const isArrayObject = field.type.toLowerCase() === "array" && ((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object";
|
|
46
|
+
const isObjectWithProps = field.type.toLowerCase() === "object" && ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length);
|
|
47
|
+
if ((isArrayObject || isObjectWithProps) && ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length)) {
|
|
48
|
+
const isArray = field.type.toLowerCase() === "array";
|
|
49
|
+
const nestedSchemaName = isArray ? `${field.name}ItemSchema` : `${field.name}Schema`;
|
|
49
50
|
nestedSchemas += `const ${nestedSchemaName} = new Schema({\n`;
|
|
50
51
|
field.objectProperties.forEach((prop) => {
|
|
51
52
|
// Skip _id field
|
|
@@ -120,11 +121,8 @@ function mapToMongooseType(field) {
|
|
|
120
121
|
case "object":
|
|
121
122
|
if ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length) {
|
|
122
123
|
// Object with defined properties
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
return `${prop.name}: ${mapToMongooseType(prop)}`;
|
|
126
|
-
})
|
|
127
|
-
.join(", ")} }`;
|
|
124
|
+
const nestedSchemaName = `${field.name}Schema`;
|
|
125
|
+
return nestedSchemaName;
|
|
128
126
|
}
|
|
129
127
|
else {
|
|
130
128
|
return "{ type: Schema.Types.Mixed }";
|
package/package.json
CHANGED