@asad_dev/leo-generator 1.6.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.
Files changed (38) hide show
  1. package/CHANGELOG.md +194 -0
  2. package/COMMAND_REFERENCE.md +412 -0
  3. package/README.md +486 -0
  4. package/dist/app/modules/imagemodule/imagemodule.constants.js +18 -0
  5. package/dist/app/modules/imagemodule/imagemodule.controller.js +98 -0
  6. package/dist/app/modules/imagemodule/imagemodule.interface.js +2 -0
  7. package/dist/app/modules/imagemodule/imagemodule.model.js +10 -0
  8. package/dist/app/modules/imagemodule/imagemodule.route.js +20 -0
  9. package/dist/app/modules/imagemodule/imagemodule.service.js +137 -0
  10. package/dist/app/modules/imagemodule/imagemodule.validation.js +12 -0
  11. package/dist/app/modules/skiptest/skiptest.controller.js +81 -0
  12. package/dist/app/modules/skiptest/skiptest.route.js +19 -0
  13. package/dist/app/modules/skiptest/skiptest.service.js +129 -0
  14. package/dist/app/modules/skiptest/skiptest.validation.js +12 -0
  15. package/dist/app/modules/testmodule/testmodule.constants.js +18 -0
  16. package/dist/app/modules/testmodule/testmodule.controller.js +81 -0
  17. package/dist/app/modules/testmodule/testmodule.interface.js +2 -0
  18. package/dist/app/modules/testmodule/testmodule.model.js +11 -0
  19. package/dist/app/modules/testmodule/testmodule.route.js +19 -0
  20. package/dist/app/modules/testmodule/testmodule.service.js +129 -0
  21. package/dist/app/modules/testmodule/testmodule.validation.js +14 -0
  22. package/dist/helpers/fileHelper.js +44 -0
  23. package/dist/index.js +586 -0
  24. package/dist/templates/constants.template.js +24 -0
  25. package/dist/templates/controller.template.js +108 -0
  26. package/dist/templates/route.template.js +68 -0
  27. package/dist/templates/service.template.js +184 -0
  28. package/dist/types.js +2 -0
  29. package/dist/utils/documentationUpdater.js +430 -0
  30. package/dist/utils/fieldParser.js +163 -0
  31. package/dist/utils/helperGenerator.js +87 -0
  32. package/dist/utils/interfaceGenerator.js +158 -0
  33. package/dist/utils/modelGenerator.js +140 -0
  34. package/dist/utils/postmanApi.js +113 -0
  35. package/dist/utils/postmanGenerator.js +283 -0
  36. package/dist/utils/swaggerGenerator.js +444 -0
  37. package/dist/utils/validationGenerator.js +170 -0
  38. package/package.json +58 -0
@@ -0,0 +1,158 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateInterfaceContent = generateInterfaceContent;
4
+ function generateInterfaceContent(camelCaseName, fields) {
5
+ let interfaceContent = `import { Model, Types } from 'mongoose';\n\n`;
6
+ // Generate nested interfaces for array of objects
7
+ 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`;
13
+ interfaceContent += `export interface ${nestedInterfaceName} {\n`;
14
+ field.objectProperties.forEach((prop) => {
15
+ // Skip _id field
16
+ if (prop.name.toLowerCase() === "_id") {
17
+ return;
18
+ }
19
+ const optionalMarker = prop.isOptional ? "?" : "";
20
+ const tsType = mapToTypeScriptType(prop);
21
+ interfaceContent += ` ${prop.name}${optionalMarker}: ${tsType};\n`;
22
+ });
23
+ interfaceContent += `}\n\n`;
24
+ }
25
+ });
26
+ // Generate enum types
27
+ fields.forEach((field) => {
28
+ if (field.type.toLowerCase() === "enum" &&
29
+ field.enumValues &&
30
+ field.enumValues.length > 0) {
31
+ const enumName = `${toCamelCase(field.name)}Enum`;
32
+ interfaceContent += `export enum ${enumName} {\n`;
33
+ field.enumValues.forEach(value => {
34
+ // Handle special characters in enum keys if necessary, simplified for now
35
+ const key = value.toUpperCase().replace(/[^A-Z0-9]/g, '_');
36
+ interfaceContent += ` ${key} = '${value}',\n`;
37
+ });
38
+ interfaceContent += `}\n\n`;
39
+ }
40
+ });
41
+ // Generate filterable interface
42
+ const filterableFields = fields.filter(f => f.type.toLowerCase() === "string" || f.type.toLowerCase() === "enum");
43
+ if (filterableFields.length > 0) {
44
+ interfaceContent += `export interface I${camelCaseName}Filterables {\n`;
45
+ interfaceContent += ` searchTerm?: string;\n`;
46
+ filterableFields.forEach((field) => {
47
+ let tsType = mapToTypeScriptType(field);
48
+ // Use enum type if applicable
49
+ if (field.type.toLowerCase() === "enum" &&
50
+ field.enumValues &&
51
+ field.enumValues.length > 0) {
52
+ tsType = `${toCamelCase(field.name)}Enum`;
53
+ }
54
+ interfaceContent += ` ${field.name}?: ${tsType};\n`;
55
+ });
56
+ interfaceContent += `}\n\n`;
57
+ }
58
+ // Generate main interface
59
+ interfaceContent += `export interface I${camelCaseName} {\n`;
60
+ interfaceContent += ` _id: Types.ObjectId;\n`;
61
+ if (fields.length > 0) {
62
+ fields.forEach((field) => {
63
+ // Skip _id field as it's already included
64
+ if (field.name.toLowerCase() === "_id") {
65
+ return;
66
+ }
67
+ const optionalMarker = field.isOptional ? "?" : "";
68
+ let tsType = mapToTypeScriptType(field);
69
+ // Use enum type if applicable
70
+ if (field.type.toLowerCase() === "enum" &&
71
+ field.enumValues &&
72
+ field.enumValues.length > 0) {
73
+ tsType = `${toCamelCase(field.name)}Enum`;
74
+ }
75
+ interfaceContent += ` ${field.name}${optionalMarker}: ${tsType};\n`;
76
+ });
77
+ }
78
+ else {
79
+ interfaceContent += ` // Define interface properties here\n`;
80
+ }
81
+ interfaceContent += `}\n\n`;
82
+ // Generate model interface
83
+ interfaceContent += `export type ${camelCaseName}Model = Model<I${camelCaseName}, {}, {}>;\n`;
84
+ return interfaceContent;
85
+ }
86
+ // Helper function to convert to camelCase
87
+ function toCamelCase(str) {
88
+ return str.charAt(0).toUpperCase() + str.slice(1);
89
+ }
90
+ // Helper function to map field definitions to TypeScript types
91
+ function mapToTypeScriptType(field) {
92
+ var _a, _b, _c;
93
+ switch (field.type.toLowerCase()) {
94
+ case "string":
95
+ return "string";
96
+ case "number":
97
+ return "number";
98
+ case "boolean":
99
+ return "boolean";
100
+ case "date":
101
+ return "Date";
102
+ case "enum":
103
+ if (field.enumValues && field.enumValues.length > 0) {
104
+ return `${toCamelCase(field.name)}Enum`;
105
+ }
106
+ return "string";
107
+ case "array":
108
+ if (((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object" &&
109
+ ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length)) {
110
+ // Array of objects with defined structure
111
+ const nestedInterfaceName = `${toCamelCase(field.name)}Item`;
112
+ return `${nestedInterfaceName}[]`;
113
+ }
114
+ else if (field.arrayItemType) {
115
+ // Array with specified item type
116
+ switch (field.arrayItemType.toLowerCase()) {
117
+ case "string":
118
+ return "string[]";
119
+ case "number":
120
+ return "number[]";
121
+ case "boolean":
122
+ return "boolean[]";
123
+ case "date":
124
+ return "Date[]";
125
+ case "objectid":
126
+ case "id":
127
+ return "Types.ObjectId[]";
128
+ default:
129
+ return "string[]"; // Default to string[] instead of any[]
130
+ }
131
+ }
132
+ else if (field.ref && field.type.toLowerCase() === "array") {
133
+ // Handle array of references (e.g., products:array:objectid:Product)
134
+ return "Types.ObjectId[]";
135
+ }
136
+ else {
137
+ return "string[]"; // Default to string[] instead of any[]
138
+ }
139
+ case "object":
140
+ if ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length) {
141
+ // 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("; ")} }`;
148
+ }
149
+ else {
150
+ return "Record<string, any>";
151
+ }
152
+ case "objectid":
153
+ case "id":
154
+ return "Types.ObjectId";
155
+ default:
156
+ return "string"; // Default to string instead of any
157
+ }
158
+ }
@@ -0,0 +1,140 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.generateModelContent = generateModelContent;
4
+ function generateModelContent(camelCaseName, folderName, fields) {
5
+ let modelContent = `import { Schema, model } from 'mongoose';\nimport { I${camelCaseName}, ${camelCaseName}Model } from './${folderName}.interface';\n\n`;
6
+ // Generate nested schemas
7
+ const nestedSchemas = generateNestedSchemas(fields);
8
+ modelContent += nestedSchemas;
9
+ modelContent += `const ${folderName}Schema = new Schema<I${camelCaseName}, ${camelCaseName}Model>({\n`;
10
+ // Add fields to schema
11
+ if (fields.length > 0) {
12
+ fields.forEach((field) => {
13
+ // Skip _id field as it's automatically handled by MongoDB
14
+ if (field.name.toLowerCase() === "_id") {
15
+ return;
16
+ }
17
+ let schemaType = mapToMongooseType(field);
18
+ if (!schemaType)
19
+ return; // Skip if empty (like for _id)
20
+ let additionalProps = "";
21
+ // Add required property if marked as required
22
+ if (field.isRequired) {
23
+ additionalProps += ", required: true";
24
+ }
25
+ // Add default value for enum if it has values
26
+ if (field.type.toLowerCase() === "enum" &&
27
+ field.enumValues &&
28
+ field.enumValues.length > 0) {
29
+ additionalProps += `, default: '${field.enumValues[0]}'`;
30
+ }
31
+ modelContent += ` ${field.name}: ${schemaType}${additionalProps},\n`;
32
+ });
33
+ }
34
+ else {
35
+ modelContent += " // Define schema fields here\n";
36
+ }
37
+ modelContent += `}, {\n timestamps: true\n});\n\nexport const ${camelCaseName} = model<I${camelCaseName}, ${camelCaseName}Model>('${camelCaseName}', ${folderName}Schema);\n`;
38
+ return modelContent;
39
+ }
40
+ // Helper function to generate nested schemas for complex types
41
+ function generateNestedSchemas(fields) {
42
+ let nestedSchemas = "";
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`;
49
+ nestedSchemas += `const ${nestedSchemaName} = new Schema({\n`;
50
+ field.objectProperties.forEach((prop) => {
51
+ // Skip _id field
52
+ if (prop.name.toLowerCase() === "_id") {
53
+ return;
54
+ }
55
+ let schemaType = mapToMongooseType(prop);
56
+ let additionalProps = "";
57
+ if (prop.isRequired) {
58
+ additionalProps += ", required: true";
59
+ }
60
+ nestedSchemas += ` ${prop.name}: ${schemaType}${additionalProps},\n`;
61
+ });
62
+ nestedSchemas += `}, { _id: false });\n\n`;
63
+ }
64
+ });
65
+ return nestedSchemas;
66
+ }
67
+ // Helper function to map field definitions to Mongoose schema types
68
+ function mapToMongooseType(field) {
69
+ var _a, _b, _c;
70
+ // Skip _id field as it's automatically handled by MongoDB
71
+ if (field.name.toLowerCase() === "_id") {
72
+ return ""; // Skip this field
73
+ }
74
+ switch (field.type.toLowerCase()) {
75
+ case "string":
76
+ return "{ type: String }";
77
+ case "number":
78
+ return "{ type: Number }";
79
+ case "boolean":
80
+ return "{ type: Boolean }";
81
+ case "date":
82
+ return "{ type: Date }";
83
+ case "enum":
84
+ if (field.enumValues && field.enumValues.length > 0) {
85
+ return `{ type: String, enum: ['${field.enumValues.join("', '")}'] }`;
86
+ }
87
+ return "{ type: String }";
88
+ case "array":
89
+ if (((_a = field.ref) === null || _a === void 0 ? void 0 : _a.toLowerCase()) === "object" &&
90
+ ((_b = field.objectProperties) === null || _b === void 0 ? void 0 : _b.length)) {
91
+ // Array of objects with defined structure
92
+ const nestedSchemaName = `${field.name}ItemSchema`;
93
+ return `[${nestedSchemaName}]`;
94
+ }
95
+ else if (field.arrayItemType) {
96
+ // Array with specified item type
97
+ switch (field.arrayItemType.toLowerCase()) {
98
+ case "string":
99
+ return "{ type: [String] }";
100
+ case "number":
101
+ return "{ type: [Number] }";
102
+ case "boolean":
103
+ return "{ type: [Boolean] }";
104
+ case "date":
105
+ return "{ type: [Date] }";
106
+ case "objectid":
107
+ case "id":
108
+ return `{ type: [Schema.Types.ObjectId], ref: '${field.ref || "Document"}' }`;
109
+ default:
110
+ return "{ type: [String] }"; // Default to String instead of Mixed
111
+ }
112
+ }
113
+ else if (field.ref) {
114
+ // Handle array of references (e.g., products:array:objectid:Product)
115
+ return `{ type: [Schema.Types.ObjectId], ref: '${field.ref}' }`;
116
+ }
117
+ else {
118
+ return "{ type: [String] }"; // Default to String instead of Mixed
119
+ }
120
+ case "object":
121
+ if ((_c = field.objectProperties) === null || _c === void 0 ? void 0 : _c.length) {
122
+ // Object with defined properties
123
+ return `{ ${field.objectProperties
124
+ .map((prop) => {
125
+ return `${prop.name}: ${mapToMongooseType(prop)}`;
126
+ })
127
+ .join(", ")} }`;
128
+ }
129
+ else {
130
+ return "{ type: Schema.Types.Mixed }";
131
+ }
132
+ case "objectid":
133
+ case "id":
134
+ return field.ref
135
+ ? `{ type: Schema.Types.ObjectId, ref: '${field.ref}' }`
136
+ : "{ type: Schema.Types.ObjectId }";
137
+ default:
138
+ return "{ type: String }"; // Default to String instead of Mixed
139
+ }
140
+ }
@@ -0,0 +1,113 @@
1
+ "use strict";
2
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
3
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
4
+ return new (P || (P = Promise))(function (resolve, reject) {
5
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
6
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
7
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
8
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
9
+ });
10
+ };
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.updatePostmanCollectionViaApi = updatePostmanCollectionViaApi;
13
+ /**
14
+ * Updates an existing Postman collection via the Postman API.
15
+ * It fetches the existing collection, finds the folder for the current module,
16
+ * and replaces it or adds it to the collection.
17
+ */
18
+ function updatePostmanCollectionViaApi(moduleName, newCollectionData, config) {
19
+ return __awaiter(this, void 0, void 0, function* () {
20
+ const { apiKey, collectionId } = config;
21
+ const url = `https://api.getpostman.com/collections/${collectionId}`;
22
+ try {
23
+ console.log(`🚀 Connecting to Postman API for collection: ${collectionId}...`);
24
+ // 1. Fetch current collection
25
+ const getResponse = yield fetch(url, {
26
+ headers: {
27
+ "X-Api-Key": apiKey
28
+ }
29
+ });
30
+ if (!getResponse.ok) {
31
+ const errorData = yield getResponse.json();
32
+ throw new Error(`Failed to fetch collection: ${JSON.stringify(errorData)}`);
33
+ }
34
+ const currentData = yield getResponse.json();
35
+ const collection = currentData.collection;
36
+ console.log(`đŸ“Ļ Collection Keys: ${Object.keys(collection).join(", ")}`);
37
+ // Handle variables - Postman API is very strict about variable structure
38
+ if (collection.variable) {
39
+ console.log(`🔍 Found ${collection.variable.length} variables in collection.`);
40
+ if (collection.variable.length > 0) {
41
+ console.log(`📄 Sample Variable [0]: ${JSON.stringify(collection.variable[0])}`);
42
+ }
43
+ const allowedTypes = ["string", "secret", "boolean", "number", "any"];
44
+ // Filter and sanitize variables
45
+ const validVariables = collection.variable
46
+ .map((v) => {
47
+ var _a;
48
+ const currentType = (_a = v.type) === null || _a === void 0 ? void 0 : _a.toLowerCase();
49
+ if (!currentType || !allowedTypes.includes(currentType)) {
50
+ // Force to 'string' if invalid or missing
51
+ const newType = "string";
52
+ console.log(` 🔧 Variable '${v.key}' has invalid/missing type: '${v.type || "N/A"}'. Setting to '${newType}'.`);
53
+ return Object.assign(Object.assign({}, v), { type: newType });
54
+ }
55
+ return v;
56
+ })
57
+ .filter((v) => v.key && v.type); // Remove any variables without key or type
58
+ // Only keep variable array if it has valid entries
59
+ if (validVariables.length > 0) {
60
+ collection.variable = validVariables;
61
+ }
62
+ else {
63
+ console.log(" đŸ—‘ī¸ Removing empty/invalid variable array");
64
+ delete collection.variable;
65
+ }
66
+ }
67
+ else {
68
+ console.log("â„šī¸ No variables found in retrieved collection.");
69
+ }
70
+ // 2. Prepare the new folder for this module
71
+ // The generator creates a collection where 'item' is the list of requests
72
+ const moduleFolderName = `${moduleName} API`;
73
+ const newModuleFolder = {
74
+ name: moduleFolderName,
75
+ item: newCollectionData.item
76
+ };
77
+ // 3. Update or Add the folder in the existing collection
78
+ if (!collection.item) {
79
+ collection.item = [];
80
+ }
81
+ const existingFolderIndex = collection.item.findIndex((item) => item.name === moduleFolderName);
82
+ if (existingFolderIndex !== -1) {
83
+ console.log(`📝 Updating existing folder: ${moduleFolderName} in Postman collection`);
84
+ collection.item[existingFolderIndex] = newModuleFolder;
85
+ }
86
+ else {
87
+ console.log(`➕ Adding new folder: ${moduleFolderName} to Postman collection`);
88
+ collection.item.push(newModuleFolder);
89
+ }
90
+ // Debug: Log a snippet of what we are sending
91
+ console.log(`📤 Sending PUT request to Postman API...`);
92
+ // console.log(`📤 Variable snippet: ${JSON.stringify(collection.variable?.slice(0, 1))}`);
93
+ // 4. Send the updated collection back to Postman
94
+ const putResponse = yield fetch(url, {
95
+ method: "PUT",
96
+ headers: {
97
+ "X-Api-Key": apiKey,
98
+ "Content-Type": "application/json"
99
+ },
100
+ body: JSON.stringify({ collection })
101
+ });
102
+ if (!putResponse.ok) {
103
+ const errorData = yield putResponse.json();
104
+ throw new Error(`Failed to update collection: ${JSON.stringify(errorData)}`);
105
+ }
106
+ console.log(`✅ Postman collection updated successfully via API!`);
107
+ }
108
+ catch (error) {
109
+ console.error("❌ Error updating Postman collection via API:", error instanceof Error ? error.message : String(error));
110
+ throw error;
111
+ }
112
+ });
113
+ }