@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
- const moduleDirectories = fs.readdirSync(fullModulesPath, { withFileTypes: true })
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 nestedInterfaces = extractNestedInterfaces(interfaceContent);
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 (starts with 'I' and has more than 1 character after 'I')
236
- if (interfaceName.startsWith('I') && interfaceName.length > 1 && interfaceName !== 'ItemsItem') {
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
- if (field.type.toLowerCase() === "array" &&
10
- ((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object" &&
11
- ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length)) {
12
- const nestedInterfaceName = `${toCamelCase(field.name)}Item`;
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
- return `{ ${field.objectProperties
143
- .map((prop) => {
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
- if (field.type.toLowerCase() === "array" &&
46
- ((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object" &&
47
- ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length)) {
48
- const nestedSchemaName = `${field.name}ItemSchema`;
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
- return `{ ${field.objectProperties
124
- .map((prop) => {
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
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@asad_dev/leo-generator",
3
- "version": "1.6.0",
3
+ "version": "1.6.2",
4
4
  "description": "Enhanced Express module generator with Mongoose models, automated Postman Cloud sync, and Swagger documentation",
5
5
  "main": "dist/index.js",
6
6
  "bin": {