@diagramers/cli 1.0.16 → 1.0.17

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/README.md CHANGED
@@ -1,6 +1,6 @@
1
1
  # @diagramers/cli
2
2
 
3
- Command-line tools for managing Diagramers projects.
3
+ Command-line tools for managing Diagramers projects with comprehensive API development features.
4
4
 
5
5
  ## 🚀 Installation
6
6
 
@@ -55,6 +55,78 @@ diagramers extend --feature cron
55
55
  diagramers extend --feature audit
56
56
  ```
57
57
 
58
+ ### API-Specific Commands
59
+
60
+ The CLI provides powerful commands specifically for API development:
61
+
62
+ #### Generate Full Module
63
+ Creates a complete CRUD module with entity, schema, service, controller, and routes:
64
+
65
+ ```bash
66
+ # Generate a complete product module
67
+ diagramers api generate:module product
68
+
69
+ # Generate a user profile module
70
+ diagramers api generate:module user_profile
71
+ ```
72
+
73
+ **What it creates:**
74
+ - 📝 Entity interface (`src/entities/product.ts`)
75
+ - 📋 Mongoose schema (`src/schemas/product.ts`)
76
+ - 🔧 Service layer (`src/services/product-service.ts`)
77
+ - 🎮 Controller (`src/controllers/product-controller.ts`)
78
+ - 🛣️ Routes (`src/routes/product-routes.ts`)
79
+ - 🔄 Updates `dbcontext.ts` and `routes/index.ts`
80
+
81
+ #### Generate Database Table
82
+ Creates only the database layer (entity and schema) without API endpoints:
83
+
84
+ ```bash
85
+ # Generate a category table
86
+ diagramers api generate:table category
87
+
88
+ # Generate a settings table
89
+ diagramers api generate:table app_settings
90
+ ```
91
+
92
+ **What it creates:**
93
+ - 📝 Entity interface (`src/entities/category.ts`)
94
+ - 📋 Mongoose schema (`src/schemas/category.ts`)
95
+ - 🔄 Updates `dbcontext.ts`
96
+
97
+ #### Process Template
98
+ Customize your API project template with a new name:
99
+
100
+ ```bash
101
+ # Process template for a new project
102
+ diagramers api process:template my-custom-api
103
+ ```
104
+
105
+ **What it updates:**
106
+ - 📦 Package.json name and description
107
+ - 📄 README.md title and description
108
+ - ⚙️ Configuration files (development, staging, production)
109
+ - 🗄️ Database names in config files
110
+ - 📄 Creates `.env.example` template
111
+
112
+ ## 🎯 Use Cases
113
+
114
+ ### When to use `generate:module`:
115
+ - Building full CRUD APIs
116
+ - Creating complete feature modules
117
+ - When you need both database and API endpoints
118
+
119
+ ### When to use `generate:table`:
120
+ - Adding database tables without API endpoints
121
+ - Creating lookup/reference tables
122
+ - Building data models for internal use
123
+ - When you only need the database layer
124
+
125
+ ### When to use `process:template`:
126
+ - Customizing a new API project
127
+ - Setting up project-specific configurations
128
+ - Preparing for deployment with custom names
129
+
58
130
  ## 🔧 Development
59
131
 
60
132
  ```bash
@@ -68,6 +140,9 @@ npm install
68
140
  # Build the CLI
69
141
  npm run build
70
142
 
143
+ # Run in development mode
144
+ npm run dev
145
+
71
146
  # Link locally
72
147
  npm link
73
148
 
@@ -75,16 +150,45 @@ npm link
75
150
  diagramers --help
76
151
  ```
77
152
 
78
- ## 📚 Documentation
153
+ ## 📚 Examples
79
154
 
80
- For detailed documentation, visit our [docs](https://github.com/diagramers/diagramers-cli/wiki).
155
+ ### Complete API Development Workflow
156
+
157
+ ```bash
158
+ # 1. Initialize a new API project
159
+ diagramers init api my-ecommerce-api
81
160
 
82
- ## 🤝 Contributing
161
+ # 2. Navigate to the project
162
+ cd my-ecommerce-api
83
163
 
84
- 1. Fork the repository
85
- 2. Create a feature branch
86
- 3. Make your changes
87
- 4. Submit a pull request
164
+ # 3. Generate full modules for main entities
165
+ diagramers api generate:module product
166
+ diagramers api generate:module user
167
+ diagramers api generate:module order
168
+
169
+ # 4. Generate tables for supporting data
170
+ diagramers api generate:table category
171
+ diagramers api generate:table brand
172
+ diagramers api generate:table shipping_method
173
+
174
+ # 5. Process template for production
175
+ diagramers api process:template ecommerce-production
176
+ ```
177
+
178
+ ## 🛠️ Project Structure
179
+
180
+ After using the CLI, your API project will have:
181
+
182
+ ```
183
+ src/
184
+ ├── entities/ # TypeScript interfaces
185
+ ├── schemas/ # Mongoose schemas
186
+ ├── services/ # Business logic
187
+ ├── controllers/ # Request handlers
188
+ ├── routes/ # API endpoints
189
+ ├── helpers/ # Utilities
190
+ └── config/ # Environment configs
191
+ ```
88
192
 
89
193
  ## 📄 License
90
194
 
@@ -1 +1 @@
1
- {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAKpC,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,WAoC1C"}
1
+ {"version":3,"file":"api.d.ts","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AAMpC,wBAAgB,UAAU,CAAC,OAAO,EAAE,OAAO,WAmD1C"}
@@ -5,6 +5,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
6
  exports.apiCommand = apiCommand;
7
7
  const api_generator_1 = require("../services/api-generator");
8
+ const table_generator_1 = require("../services/table-generator");
8
9
  const template_processor_1 = require("../services/template-processor");
9
10
  const chalk_1 = __importDefault(require("chalk"));
10
11
  function apiCommand(program) {
@@ -41,6 +42,21 @@ function apiCommand(program) {
41
42
  process.exit(1);
42
43
  }
43
44
  });
45
+ // Generate table command
46
+ api
47
+ .command('generate:table <name>')
48
+ .description('Generate a new database table with entity and schema only')
49
+ .action(async (name) => {
50
+ try {
51
+ console.log(chalk_1.default.blue(`🚀 Generating table: ${name}`));
52
+ await (0, table_generator_1.generateTable)(name);
53
+ console.log(chalk_1.default.green(`✅ Table '${name}' generated successfully!`));
54
+ }
55
+ catch (error) {
56
+ console.error(chalk_1.default.red(`❌ Error generating table: ${error.message}`));
57
+ process.exit(1);
58
+ }
59
+ });
44
60
  return api;
45
61
  }
46
62
  //# sourceMappingURL=api.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":";;;;;AAKA,gCAoCC;AAxCD,6DAA2D;AAC3D,uEAAiE;AACjE,kDAA0B;AAE1B,SAAgB,UAAU,CAAC,OAAgB;IACzC,MAAM,GAAG,GAAG,OAAO;SAChB,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,+CAA+C,CAAC,CAAC;IAEhE,0BAA0B;IAC1B,GAAG;SACA,OAAO,CAAC,wBAAwB,CAAC;SACjC,WAAW,CAAC,4EAA4E,CAAC;SACzF,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;YACzD,MAAM,IAAA,8BAAc,EAAC,IAAI,CAAC,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,aAAa,IAAI,2BAA2B,CAAC,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,8BAA8B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,2BAA2B;IAC3B,GAAG;SACA,OAAO,CAAC,yBAAyB,CAAC;SAClC,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAC,CAAC;YACvE,MAAM,IAAA,oCAAe,EAAC,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,wCAAwC,IAAI,IAAI,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,gCAAgC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC"}
1
+ {"version":3,"file":"api.js","sourceRoot":"","sources":["../../src/commands/api.ts"],"names":[],"mappings":";;;;;AAMA,gCAmDC;AAxDD,6DAA2D;AAC3D,iEAA4D;AAC5D,uEAAiE;AACjE,kDAA0B;AAE1B,SAAgB,UAAU,CAAC,OAAgB;IACzC,MAAM,GAAG,GAAG,OAAO;SAChB,OAAO,CAAC,KAAK,CAAC;SACd,WAAW,CAAC,+CAA+C,CAAC,CAAC;IAEhE,0BAA0B;IAC1B,GAAG;SACA,OAAO,CAAC,wBAAwB,CAAC;SACjC,WAAW,CAAC,4EAA4E,CAAC;SACzF,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,yBAAyB,IAAI,EAAE,CAAC,CAAC,CAAC;YACzD,MAAM,IAAA,8BAAc,EAAC,IAAI,CAAC,CAAC;YAC3B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,aAAa,IAAI,2BAA2B,CAAC,CAAC,CAAC;QACzE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,8BAA8B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACxE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,2BAA2B;IAC3B,GAAG;SACA,OAAO,CAAC,yBAAyB,CAAC;SAClC,WAAW,CAAC,0CAA0C,CAAC;SACvD,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,uCAAuC,IAAI,EAAE,CAAC,CAAC,CAAC;YACvE,MAAM,IAAA,oCAAe,EAAC,IAAI,CAAC,CAAC;YAC5B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,wCAAwC,IAAI,IAAI,CAAC,CAAC,CAAC;QAC7E,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,gCAAgC,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YAC1E,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,yBAAyB;IACzB,GAAG;SACA,OAAO,CAAC,uBAAuB,CAAC;SAChC,WAAW,CAAC,2DAA2D,CAAC;SACxE,MAAM,CAAC,KAAK,EAAE,IAAY,EAAE,EAAE;QAC7B,IAAI,CAAC;YACH,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,IAAI,CAAC,wBAAwB,IAAI,EAAE,CAAC,CAAC,CAAC;YACxD,MAAM,IAAA,+BAAa,EAAC,IAAI,CAAC,CAAC;YAC1B,OAAO,CAAC,GAAG,CAAC,eAAK,CAAC,KAAK,CAAC,YAAY,IAAI,2BAA2B,CAAC,CAAC,CAAC;QACxE,CAAC;QAAC,OAAO,KAAU,EAAE,CAAC;YACpB,OAAO,CAAC,KAAK,CAAC,eAAK,CAAC,GAAG,CAAC,6BAA6B,KAAK,CAAC,OAAO,EAAE,CAAC,CAAC,CAAC;YACvE,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC;QAClB,CAAC;IACH,CAAC,CAAC,CAAC;IAEL,OAAO,GAAG,CAAC;AACb,CAAC"}
package/dist/index.js CHANGED
@@ -24,6 +24,7 @@ Examples:
24
24
  $ diagramers update
25
25
  $ diagramers extend --feature auth
26
26
  $ diagramers api generate:module product
27
+ $ diagramers api generate:table category
27
28
  $ diagramers api process:template my-api-project
28
29
  `);
29
30
  program.parse();
package/dist/index.js.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,8CAAkD;AAClD,8CAAkD;AAClD,wCAA4C;AAG5C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,eAAe;AACf,IAAA,kBAAW,EAAC,OAAO,CAAC,CAAC;AACrB,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC;AACvB,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC;AACvB,IAAA,gBAAU,EAAC,OAAO,CAAC,CAAC;AAEpB,gBAAgB;AAChB,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE;;;;;;;;CAQ5B,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,uCAAuC;AACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,OAAO,CAAC,UAAU,EAAE,CAAC;AACvB,CAAC"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;AAEA,yCAAoC;AACpC,0CAA8C;AAC9C,8CAAkD;AAClD,8CAAkD;AAClD,wCAA4C;AAG5C,MAAM,OAAO,GAAG,IAAI,mBAAO,EAAE,CAAC;AAE9B,OAAO;KACJ,IAAI,CAAC,YAAY,CAAC;KAClB,WAAW,CAAC,2CAA2C,CAAC;KACxD,OAAO,CAAC,OAAO,CAAC,CAAC;AAEpB,eAAe;AACf,IAAA,kBAAW,EAAC,OAAO,CAAC,CAAC;AACrB,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC;AACvB,IAAA,sBAAa,EAAC,OAAO,CAAC,CAAC;AACvB,IAAA,gBAAU,EAAC,OAAO,CAAC,CAAC;AAEpB,gBAAgB;AAChB,OAAO,CAAC,WAAW,CAAC,OAAO,EAAE;;;;;;;;;CAS5B,CAAC,CAAC;AAEH,OAAO,CAAC,KAAK,EAAE,CAAC;AAEhB,uCAAuC;AACvC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,MAAM,EAAE,CAAC;IAClC,OAAO,CAAC,UAAU,EAAE,CAAC;AACvB,CAAC"}
@@ -0,0 +1,2 @@
1
+ export declare function generateTable(tableName: string): Promise<void>;
2
+ //# sourceMappingURL=table-generator.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-generator.d.ts","sourceRoot":"","sources":["../../src/services/table-generator.ts"],"names":[],"mappings":"AAGA,wBAAsB,aAAa,CAAC,SAAS,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAkCpE"}
@@ -0,0 +1,137 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || (function () {
19
+ var ownKeys = function(o) {
20
+ ownKeys = Object.getOwnPropertyNames || function (o) {
21
+ var ar = [];
22
+ for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
23
+ return ar;
24
+ };
25
+ return ownKeys(o);
26
+ };
27
+ return function (mod) {
28
+ if (mod && mod.__esModule) return mod;
29
+ var result = {};
30
+ if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
31
+ __setModuleDefault(result, mod);
32
+ return result;
33
+ };
34
+ })();
35
+ Object.defineProperty(exports, "__esModule", { value: true });
36
+ exports.generateTable = generateTable;
37
+ const fs = __importStar(require("fs"));
38
+ const path = __importStar(require("path"));
39
+ async function generateTable(tableName) {
40
+ // Validate table name
41
+ if (!tableName || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(tableName)) {
42
+ throw new Error('Invalid table name. Use only letters, numbers, hyphens, and underscores. Must start with a letter.');
43
+ }
44
+ const tableNameCapitalized = tableName.charAt(0).toUpperCase() + tableName.slice(1);
45
+ const currentDir = process.cwd();
46
+ // Check for required API project structure
47
+ const requiredDirs = [
48
+ 'src/entities',
49
+ 'src/schemas'
50
+ ];
51
+ const missingDirs = requiredDirs.filter(dir => !fs.existsSync(path.join(currentDir, dir)));
52
+ if (missingDirs.length > 0) {
53
+ throw new Error(`This command should be run from a diagramers API project. Missing directories: ${missingDirs.join(', ')}`);
54
+ }
55
+ console.log('📝 Creating entity...');
56
+ const entityContent = generateEntityContent(tableName, tableNameCapitalized);
57
+ fs.writeFileSync(path.join(currentDir, 'src/entities', `${tableName}.ts`), entityContent);
58
+ console.log('📋 Creating schema...');
59
+ const schemaContent = generateSchemaContent(tableName, tableNameCapitalized);
60
+ fs.writeFileSync(path.join(currentDir, 'src/schemas', `${tableName}.ts`), schemaContent);
61
+ // Update dbcontext to include the new entity
62
+ updateDbContext(currentDir, tableName, tableNameCapitalized);
63
+ console.log('✅ Table generation completed!');
64
+ console.log(`📊 Entity: src/entities/${tableName}.ts`);
65
+ console.log(`📋 Schema: src/schemas/${tableName}.ts`);
66
+ console.log('🔄 dbcontext.ts updated');
67
+ }
68
+ function generateEntityContent(tableName, tableNameCapitalized) {
69
+ return `import * as mongoose from 'mongoose';
70
+ import { ObjectId } from "bson";
71
+
72
+ export interface I${tableNameCapitalized} extends mongoose.Document {
73
+ _id: ObjectId,
74
+ name: string,
75
+ description?: string,
76
+ status: number,
77
+ createdAt: Date,
78
+ updatedAt: Date
79
+ }`;
80
+ }
81
+ function generateSchemaContent(tableName, tableNameCapitalized) {
82
+ return `import * as mongoose from 'mongoose';
83
+ import { I${tableNameCapitalized} } from '../entities/${tableName}';
84
+
85
+ export const ${tableName}Schema = new mongoose.Schema(
86
+ {
87
+ name: {
88
+ type: mongoose.SchemaTypes.String,
89
+ required: true,
90
+ },
91
+ description: {
92
+ type: mongoose.SchemaTypes.String,
93
+ required: false,
94
+ },
95
+ status: {
96
+ type: mongoose.SchemaTypes.Number,
97
+ default: 1,
98
+ }
99
+ },
100
+ { timestamps: true, suppressReservedKeysWarning: true },
101
+ );
102
+
103
+ export const ${tableNameCapitalized}Entity = mongoose.model<I${tableNameCapitalized}>('${tableName}', ${tableName}Schema);`;
104
+ }
105
+ function updateDbContext(currentDir, tableName, tableNameCapitalized) {
106
+ const dbcontextPath = path.join(currentDir, 'src/helpers/dbcontext.ts');
107
+ if (!fs.existsSync(dbcontextPath)) {
108
+ console.log('⚠️ dbcontext.ts not found, skipping dbcontext update');
109
+ return;
110
+ }
111
+ let dbcontextContent = fs.readFileSync(dbcontextPath, 'utf8');
112
+ // Add import
113
+ const importStatement = `import { ${tableNameCapitalized}Entity } from '../schemas/${tableName}';`;
114
+ if (!dbcontextContent.includes(importStatement)) {
115
+ // Find the last import statement and add after it
116
+ const importRegex = /import.*from.*['"];?\s*$/gm;
117
+ const matches = [...dbcontextContent.matchAll(importRegex)];
118
+ if (matches.length > 0) {
119
+ const lastImport = matches[matches.length - 1];
120
+ const insertIndex = lastImport.index + lastImport[0].length;
121
+ dbcontextContent = dbcontextContent.slice(0, insertIndex) + '\n' + importStatement + dbcontextContent.slice(insertIndex);
122
+ }
123
+ }
124
+ // Add to dbcontext object
125
+ const dbcontextObjectRegex = /export\s+default\s*\{([^}]*)\}/s;
126
+ const match = dbcontextContent.match(dbcontextObjectRegex);
127
+ if (match) {
128
+ const objectContent = match[1];
129
+ if (!objectContent.includes(`${tableNameCapitalized}Entity`)) {
130
+ const newObjectContent = objectContent.trim() + `,\n ${tableNameCapitalized}Entity`;
131
+ dbcontextContent = dbcontextContent.replace(dbcontextObjectRegex, `export default {$1${newObjectContent}\n}`);
132
+ }
133
+ }
134
+ fs.writeFileSync(dbcontextPath, dbcontextContent);
135
+ console.log('📊 Updated dbcontext.ts');
136
+ }
137
+ //# sourceMappingURL=table-generator.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"table-generator.js","sourceRoot":"","sources":["../../src/services/table-generator.ts"],"names":[],"mappings":"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"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@diagramers/cli",
3
- "version": "1.0.16",
3
+ "version": "1.0.17",
4
4
  "description": "Diagramers CLI - Command-line tools for managing Diagramers projects",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
@@ -1,5 +1,6 @@
1
1
  import { Command } from 'commander';
2
2
  import { generateModule } from '../services/api-generator';
3
+ import { generateTable } from '../services/table-generator';
3
4
  import { processTemplate } from '../services/template-processor';
4
5
  import chalk from 'chalk';
5
6
 
@@ -38,5 +39,20 @@ export function apiCommand(program: Command) {
38
39
  }
39
40
  });
40
41
 
42
+ // Generate table command
43
+ api
44
+ .command('generate:table <name>')
45
+ .description('Generate a new database table with entity and schema only')
46
+ .action(async (name: string) => {
47
+ try {
48
+ console.log(chalk.blue(`🚀 Generating table: ${name}`));
49
+ await generateTable(name);
50
+ console.log(chalk.green(`✅ Table '${name}' generated successfully!`));
51
+ } catch (error: any) {
52
+ console.error(chalk.red(`❌ Error generating table: ${error.message}`));
53
+ process.exit(1);
54
+ }
55
+ });
56
+
41
57
  return api;
42
58
  }
package/src/index.ts CHANGED
@@ -28,6 +28,7 @@ Examples:
28
28
  $ diagramers update
29
29
  $ diagramers extend --feature auth
30
30
  $ diagramers api generate:module product
31
+ $ diagramers api generate:table category
31
32
  $ diagramers api process:template my-api-project
32
33
  `);
33
34
 
@@ -0,0 +1,114 @@
1
+ import * as fs from 'fs';
2
+ import * as path from 'path';
3
+
4
+ export async function generateTable(tableName: string): Promise<void> {
5
+ // Validate table name
6
+ if (!tableName || !/^[a-zA-Z][a-zA-Z0-9_-]*$/.test(tableName)) {
7
+ throw new Error('Invalid table name. Use only letters, numbers, hyphens, and underscores. Must start with a letter.');
8
+ }
9
+
10
+ const tableNameCapitalized = tableName.charAt(0).toUpperCase() + tableName.slice(1);
11
+ const currentDir = process.cwd();
12
+
13
+ // Check for required API project structure
14
+ const requiredDirs = [
15
+ 'src/entities',
16
+ 'src/schemas'
17
+ ];
18
+ const missingDirs = requiredDirs.filter(dir => !fs.existsSync(path.join(currentDir, dir)));
19
+ if (missingDirs.length > 0) {
20
+ throw new Error(`This command should be run from a diagramers API project. Missing directories: ${missingDirs.join(', ')}`);
21
+ }
22
+
23
+ console.log('📝 Creating entity...');
24
+ const entityContent = generateEntityContent(tableName, tableNameCapitalized);
25
+ fs.writeFileSync(path.join(currentDir, 'src/entities', `${tableName}.ts`), entityContent);
26
+
27
+ console.log('📋 Creating schema...');
28
+ const schemaContent = generateSchemaContent(tableName, tableNameCapitalized);
29
+ fs.writeFileSync(path.join(currentDir, 'src/schemas', `${tableName}.ts`), schemaContent);
30
+
31
+ // Update dbcontext to include the new entity
32
+ updateDbContext(currentDir, tableName, tableNameCapitalized);
33
+
34
+ console.log('✅ Table generation completed!');
35
+ console.log(`📊 Entity: src/entities/${tableName}.ts`);
36
+ console.log(`📋 Schema: src/schemas/${tableName}.ts`);
37
+ console.log('🔄 dbcontext.ts updated');
38
+ }
39
+
40
+ function generateEntityContent(tableName: string, tableNameCapitalized: string): string {
41
+ return `import * as mongoose from 'mongoose';
42
+ import { ObjectId } from "bson";
43
+
44
+ export interface I${tableNameCapitalized} extends mongoose.Document {
45
+ _id: ObjectId,
46
+ name: string,
47
+ description?: string,
48
+ status: number,
49
+ createdAt: Date,
50
+ updatedAt: Date
51
+ }`;
52
+ }
53
+
54
+ function generateSchemaContent(tableName: string, tableNameCapitalized: string): string {
55
+ return `import * as mongoose from 'mongoose';
56
+ import { I${tableNameCapitalized} } from '../entities/${tableName}';
57
+
58
+ export const ${tableName}Schema = new mongoose.Schema(
59
+ {
60
+ name: {
61
+ type: mongoose.SchemaTypes.String,
62
+ required: true,
63
+ },
64
+ description: {
65
+ type: mongoose.SchemaTypes.String,
66
+ required: false,
67
+ },
68
+ status: {
69
+ type: mongoose.SchemaTypes.Number,
70
+ default: 1,
71
+ }
72
+ },
73
+ { timestamps: true, suppressReservedKeysWarning: true },
74
+ );
75
+
76
+ export const ${tableNameCapitalized}Entity = mongoose.model<I${tableNameCapitalized}>('${tableName}', ${tableName}Schema);`;
77
+ }
78
+
79
+ function updateDbContext(currentDir: string, tableName: string, tableNameCapitalized: string): void {
80
+ const dbcontextPath = path.join(currentDir, 'src/helpers/dbcontext.ts');
81
+ if (!fs.existsSync(dbcontextPath)) {
82
+ console.log('⚠️ dbcontext.ts not found, skipping dbcontext update');
83
+ return;
84
+ }
85
+
86
+ let dbcontextContent = fs.readFileSync(dbcontextPath, 'utf8');
87
+
88
+ // Add import
89
+ const importStatement = `import { ${tableNameCapitalized}Entity } from '../schemas/${tableName}';`;
90
+ if (!dbcontextContent.includes(importStatement)) {
91
+ // Find the last import statement and add after it
92
+ const importRegex = /import.*from.*['"];?\s*$/gm;
93
+ const matches = [...dbcontextContent.matchAll(importRegex)];
94
+ if (matches.length > 0) {
95
+ const lastImport = matches[matches.length - 1];
96
+ const insertIndex = lastImport.index! + lastImport[0].length;
97
+ dbcontextContent = dbcontextContent.slice(0, insertIndex) + '\n' + importStatement + dbcontextContent.slice(insertIndex);
98
+ }
99
+ }
100
+
101
+ // Add to dbcontext object
102
+ const dbcontextObjectRegex = /export\s+default\s*\{([^}]*)\}/s;
103
+ const match = dbcontextContent.match(dbcontextObjectRegex);
104
+ if (match) {
105
+ const objectContent = match[1];
106
+ if (!objectContent.includes(`${tableNameCapitalized}Entity`)) {
107
+ const newObjectContent = objectContent.trim() + `,\n ${tableNameCapitalized}Entity`;
108
+ dbcontextContent = dbcontextContent.replace(dbcontextObjectRegex, `export default {$1${newObjectContent}\n}`);
109
+ }
110
+ }
111
+
112
+ fs.writeFileSync(dbcontextPath, dbcontextContent);
113
+ console.log('📊 Updated dbcontext.ts');
114
+ }