express-genix 3.0.0 → 4.1.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.
package/README.md CHANGED
@@ -3,6 +3,7 @@
3
3
  A production-grade CLI tool that generates Express.js applications with best-in-class defaults. Scaffold a complete REST API in seconds — with TypeScript, authentication, Prisma/Mongoose/Sequelize, Docker, CI/CD, and more.
4
4
 
5
5
  [![npm version](https://img.shields.io/npm/v/express-genix.svg)](https://www.npmjs.com/package/express-genix)
6
+ [![npm downloads](https://img.shields.io/npm/dm/express-genix.svg)](https://www.npmjs.com/package/express-genix)
6
7
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
7
8
  [![Node.js](https://img.shields.io/badge/node-%3E%3D18-brightgreen.svg)](https://nodejs.org)
8
9
 
@@ -41,6 +42,13 @@ A production-grade CLI tool that generates Express.js applications with best-in-
41
42
  - Prometheus metrics (`/metrics` endpoint with prom-client)
42
43
  - Audit logging middleware with request tracking and sensitive field redaction
43
44
 
45
+ **AI & Agent Integration**
46
+ - MCP Server — exposes your API as tools for AI agents (Claude Desktop, Cursor, Copilot)
47
+ - LangChain / LangGraph AI service with chat, streaming (SSE), prompt chains, and ReAct agent
48
+ - Provider-agnostic: OpenAI, Anthropic, Google Gemini, Ollama (local)
49
+ - AI-powered CLI: `express-genix ai "describe your app"` generates a project from natural language
50
+ - **Coda VS Code extension** — in-editor AI chat for Express Genix projects (auto-prompted on AI/MCP projects)
51
+
44
52
  **Developer Experience**
45
53
  - Interactive prompts — pick language, database, features via checkbox
46
54
  - Winston or Pino logger (you choose)
@@ -83,7 +91,7 @@ You'll be prompted for:
83
91
  1. **Project name**
84
92
  2. **Language** — JavaScript or TypeScript
85
93
  3. **Database** — MongoDB, PostgreSQL (Sequelize), PostgreSQL (Prisma), or None
86
- 4. **Features** — Auth, Rate Limiting, Swagger, Redis, Docker, CI/CD, WebSocket, Request ID, Email, File Uploads, Soft Deletes, Audit Logging, Prometheus Metrics, API Versioning, Background Jobs, GraphQL
94
+ 4. **Features** — Auth, Rate Limiting, Swagger, Redis, Docker, CI/CD, WebSocket, Request ID, Email, File Uploads, Soft Deletes, Audit Logging, Prometheus Metrics, API Versioning, Background Jobs, GraphQL, MCP Server, AI/LLM Service
87
95
  5. **Logger** — Winston or Pino
88
96
 
89
97
  The CLI generates your project, installs dependencies, formats code, and creates an initial git commit.
@@ -110,24 +118,40 @@ express-genix add websocket # Adds Socket.io setup
110
118
  express-genix add prisma # Adds Prisma schema, client config, migrations
111
119
  ```
112
120
 
121
+ ### Generate from natural language (AI)
122
+
123
+ Requires `OPENAI_API_KEY` or `ANTHROPIC_API_KEY` in your environment.
124
+
125
+ ```bash
126
+ express-genix ai "a task manager API with auth, real-time updates, and email notifications"
127
+ ```
128
+
129
+ The CLI interprets your description, maps it to features, shows the config for confirmation, then generates the project.
130
+
113
131
  ## Generated Project Structure
114
132
 
115
133
  ```
116
134
  my-express-app/
117
135
  ├── src/
118
- │ ├── config/ # Database, Swagger, WebSocket configuration
119
- │ ├── controllers/ # Route handlers
120
- │ ├── middleware/ # Auth, validation, error handling, request ID
121
- │ ├── models/ # Database models (Mongoose/Sequelize)
136
+ │ ├── config/ # Database, Swagger, WebSocket, queue configuration
137
+ │ ├── controllers/ # Route handlers (auth, user, admin, example)
138
+ │ ├── graphql/ # GraphQL type definitions & resolvers (if selected)
139
+ │ ├── jobs/ # BullMQ background workers (if selected)
140
+ │ ├── mcp/ # MCP server for AI agent tools (if selected)
141
+ │ ├── agents/ # LangGraph ReAct agent (if selected)
142
+ │ ├── middleware/ # Auth, RBAC, validation, error handling, uploads, metrics, audit log
143
+ │ ├── models/ # Database models (Mongoose/Sequelize/Prisma)
122
144
  │ ├── routes/ # API route definitions with Swagger annotations
123
- │ ├── services/ # Business logic layer
145
+ │ ├── services/ # Business logic layer (auth, user, email)
124
146
  │ ├── utils/ # Logger, errors, response helpers, validators
125
147
  │ ├── app.js|ts # Express app setup
126
- │ └── server.js|ts # Server + clustering + WebSocket
148
+ │ └── server.js|ts # Server + clustering + WebSocket + workers
127
149
  ├── tests/ # Jest + Supertest suites
128
150
  ├── prisma/ # Prisma schema (if selected)
129
151
  ├── migrations/ # Sequelize migrations (if PostgreSQL + Sequelize)
130
152
  ├── seeders/ # Sequelize seeders (if PostgreSQL + Sequelize)
153
+ ├── uploads/ # File upload directory (if selected)
154
+ ├── mcp.json # MCP client config for Claude Desktop (if selected)
131
155
  ├── .github/workflows/ # CI/CD pipeline (if selected)
132
156
  ├── .env # Auto-generated environment config
133
157
  ├── .env.example # Template for team sharing
@@ -138,6 +162,8 @@ my-express-app/
138
162
 
139
163
  ## API Endpoints (with database + auth)
140
164
 
165
+ > When API versioning is enabled, all `/api/*` routes become `/api/v1/*`.
166
+
141
167
  ### Authentication
142
168
  | Method | Endpoint | Description |
143
169
  |--------|----------|-------------|
@@ -153,12 +179,43 @@ my-express-app/
153
179
  |--------|----------|-------------|
154
180
  | GET | `/api/users/profile` | Get current user |
155
181
  | PUT | `/api/users/profile` | Update profile |
156
- | DELETE | `/api/users/profile` | Delete account |
182
+ | DELETE | `/api/users/profile` | Delete account (soft delete if enabled) |
183
+
184
+ ### Admin (RBAC — admin role required)
185
+ | Method | Endpoint | Description |
186
+ |--------|----------|-------------|
187
+ | GET | `/api/admin/users` | List all users (paginated) |
188
+ | GET | `/api/admin/users/:id` | Get user by ID |
189
+ | PUT | `/api/admin/users/:id/role` | Update user role |
190
+ | DELETE | `/api/admin/users/:id` | Delete user |
191
+ | POST | `/api/admin/users/:id/restore` | Restore soft-deleted user |
192
+
193
+ ### File Uploads
194
+ | Method | Endpoint | Description |
195
+ |--------|----------|-------------|
196
+ | POST | `/api/uploads/single` | Upload a single file |
197
+ | POST | `/api/uploads/multiple` | Upload multiple files (max 10) |
198
+
199
+ ### Background Jobs (BullMQ)
200
+ | Method | Endpoint | Description |
201
+ |--------|----------|-------------|
202
+ | POST | `/api/jobs` | Dispatch a background job |
203
+ | GET | `/api/jobs/:id` | Get job status |
157
204
 
158
- ### Health
205
+ ### Observability & Health
159
206
  | Method | Endpoint | Description |
160
207
  |--------|----------|-------------|
161
- | GET | `/health` | Health check with uptime, DB status, Redis status, memory usage |
208
+ | GET | `/health` | Health check (uptime, DB, Redis, memory) |
209
+ | GET | `/metrics` | Prometheus metrics (prom-client) |
210
+ | GET | `/graphql` | GraphQL Playground (Apollo Server) |
211
+
212
+ ### AI / LLM (LangChain)
213
+ | Method | Endpoint | Description |
214
+ |--------|----------|-------------|
215
+ | POST | `/api/ai/chat` | Chat with AI (complete response) |
216
+ | POST | `/api/ai/stream` | Stream AI response (SSE) |
217
+ | POST | `/api/ai/chain` | Run a prompt template chain |
218
+ | POST | `/api/ai/agent` | Run LangGraph ReAct agent with tools |
162
219
 
163
220
  ## Available Scripts
164
221
 
@@ -183,6 +240,7 @@ npm run prisma:studio # Open Prisma Studio
183
240
  express-genix init --skip-install # Skip npm install (useful for CI)
184
241
  express-genix init --skip-cleanup # Skip auto-formatting (for debugging)
185
242
  express-genix add <feature> # Add feature to existing project
243
+ express-genix ai "<description>" # Generate project from natural language
186
244
  ```
187
245
 
188
246
  ## Environment Variables
@@ -197,10 +255,25 @@ Generated `.env` includes auto-generated JWT secrets:
197
255
  | `JWT_SECRET` | Access token secret (auto-generated) | — |
198
256
  | `JWT_REFRESH_SECRET` | Refresh token secret (auto-generated) | — |
199
257
  | `MONGO_URI` / `DATABASE_URL` | Database connection string | — |
200
- | `REDIS_URL` | Redis URL (when Redis blacklist enabled) | `redis://localhost:6379` |
258
+ | `REDIS_URL` | Redis URL (token blacklist, caching, BullMQ) | `redis://localhost:6379` |
201
259
  | `RATE_LIMIT_WINDOW_MS` | Rate limit window (ms) | `900000` |
202
260
  | `RATE_LIMIT_MAX` | Max requests per window | `100` |
203
261
  | `LOG_LEVEL` | Logging level | `info` |
262
+ | `SMTP_HOST` | SMTP server host (email service) | — |
263
+ | `SMTP_PORT` | SMTP server port | `587` |
264
+ | `SMTP_USER` | SMTP username | — |
265
+ | `SMTP_PASS` | SMTP password | — |
266
+ | `EMAIL_FROM` | Default sender address | — |
267
+ | `UPLOAD_MAX_SIZE` | Max file upload size in bytes | `5242880` (5 MB) |
268
+ | `UPLOAD_DIR` | Upload destination directory | `uploads` |
269
+ | `MCP_SERVER_NAME` | MCP server display name | project name |
270
+ | `AI_PROVIDER` | LLM provider (`openai`, `anthropic`, `ollama`) | `openai` |
271
+ | `AI_MODEL` | Model name | `gpt-4o-mini` |
272
+ | `AI_TEMPERATURE` | Sampling temperature | `0.7` |
273
+ | `AI_MAX_TOKENS` | Max response tokens | `2048` |
274
+ | `OPENAI_API_KEY` | OpenAI API key (if using OpenAI) | — |
275
+ | `ANTHROPIC_API_KEY` | Anthropic API key (if using Anthropic) | — |
276
+ | `OLLAMA_BASE_URL` | Ollama server URL (if using Ollama) | `http://localhost:11434` |
204
277
 
205
278
  ## Docker
206
279
 
@@ -208,6 +281,44 @@ Generated `.env` includes auto-generated JWT secrets:
208
281
  docker-compose up --build
209
282
  ```
210
283
 
284
+ The generated `docker-compose.yml` includes services for your app and its dependencies (MongoDB/PostgreSQL, Redis) with health checks, volumes, and a shared network. The `Dockerfile` uses multi-stage builds, runs as a non-root user, and only copies production dependencies.
285
+
286
+ ## Coda VS Code Extension
287
+
288
+ When you select **AI** or **MCP** features, the CLI prompts you to install the **Coda** VS Code extension — an in-editor AI assistant that talks to your running project's AI endpoints.
289
+
290
+ ### What it does
291
+
292
+ - **Sidebar chat** — a chat panel in the VS Code activity bar that streams responses from your project's `/ai/chat` and `/ai/stream` endpoints
293
+ - **`@coda` in Copilot Chat** — type `@coda` in the native Copilot Chat to interact with your project's AI agent
294
+ - **Agent mode** — toggle between Chat (streaming) and Agent (LangGraph tool-calling) modes
295
+ - **Auto-detection** — activates automatically when it detects an Express Genix project
296
+ - **Code actions** — copy or insert code blocks from AI responses directly into your editor
297
+
298
+ ### Install manually
299
+
300
+ ```bash
301
+ # Download from GitHub Releases
302
+ curl -sLO https://github.com/LambdaAI001/coda/releases/latest/download/coda-ai-0.1.0.vsix
303
+
304
+ # Install
305
+ code --install-extension coda-ai-0.1.0.vsix
306
+ ```
307
+
308
+ Or grab it from [github.com/LambdaAI001/coda/releases](https://github.com/LambdaAI001/coda/releases).
309
+
310
+ ### Configuration
311
+
312
+ In VS Code Settings (search "Coda"):
313
+
314
+ | Setting | Default | Description |
315
+ |---------|---------|-------------|
316
+ | `coda.serverUrl` | `http://localhost:3000` | Your Express server URL |
317
+ | `coda.apiPrefix` | `/api/v1` | API prefix path |
318
+ | `coda.aiProvider` | `openai` | AI provider (openai, anthropic, gemini, ollama) |
319
+ | `coda.model` | *(server default)* | Model override |
320
+ | `coda.systemPrompt` | *Coding assistant prompt* | Default system prompt |
321
+
211
322
  ## Contributing
212
323
 
213
324
  Contributions are welcome! Please read our [Contributing Guide](CONTRIBUTING.md) for details.
package/index.js CHANGED
@@ -14,6 +14,50 @@ const prompt = inquirer.createPromptModule();
14
14
 
15
15
  const generateSecret = (length = 64) => crypto.randomBytes(length).toString('hex');
16
16
 
17
+ const CODA_EXTENSION_ID = 'express-genix.coda-ai';
18
+ const CODA_VSIX_URL = 'https://github.com/LambdaAI001/coda/releases/latest/download/coda-ai-0.1.0.vsix';
19
+
20
+ async function promptCodaExtension() {
21
+ const inquirerPrompt = inquirer.createPromptModule();
22
+ console.log('');
23
+ console.log('🤖 Your project includes AI/MCP features.');
24
+ console.log(' The Coda VS Code extension lets you chat with your AI agent');
25
+ console.log(' directly from VS Code — no extra setup needed.');
26
+ console.log('');
27
+
28
+ const { installCoda } = await inquirerPrompt([
29
+ {
30
+ type: 'confirm',
31
+ name: 'installCoda',
32
+ message: 'Install the Coda AI VS Code extension?',
33
+ default: true,
34
+ },
35
+ ]);
36
+
37
+ if (!installCoda) return;
38
+
39
+ try {
40
+ // Check if VS Code CLI is available
41
+ execSync('code --version', { stdio: 'pipe' });
42
+
43
+ // Download .vsix from GitHub Releases and install
44
+ const os = require('os');
45
+ const tmpFile = path.join(os.tmpdir(), 'coda-ai.vsix');
46
+ console.log('\n📦 Downloading Coda AI extension...');
47
+ execSync(`curl -sL -o "${tmpFile}" "${CODA_VSIX_URL}"`, { stdio: 'pipe' });
48
+ console.log('📦 Installing...');
49
+ execSync(`code --install-extension "${tmpFile}"`, { stdio: 'pipe' });
50
+ // Clean up temp file
51
+ try { fs.unlinkSync(tmpFile); } catch {}
52
+ console.log('✅ Coda extension installed! Open your project in VS Code to use it.');
53
+ console.log(' Look for the Coda AI icon in the sidebar, or type @coda in Copilot Chat.');
54
+ } catch {
55
+ console.log('\n⚠️ Could not install automatically. Install it manually:');
56
+ console.log(' 1. Download from: https://github.com/LambdaAI001/coda/releases');
57
+ console.log(' 2. Then run: code --install-extension coda-ai-0.1.0.vsix');
58
+ }
59
+ }
60
+
17
61
  async function main() {
18
62
  program
19
63
  .name('express-genix')
@@ -83,6 +127,8 @@ async function main() {
83
127
  { name: 'API Versioning (/api/v1)', value: 'apiVersioning' },
84
128
  { name: 'Background Jobs (BullMQ)', value: 'backgroundJobs' },
85
129
  { name: 'GraphQL (Apollo Server)', value: 'graphql' },
130
+ { name: 'MCP Server (AI Agent Tools)', value: 'mcp' },
131
+ { name: 'AI / LLM Service (LangChain)', value: 'ai' },
86
132
  ],
87
133
  when: (ans) => ans.db !== 'none',
88
134
  },
@@ -102,6 +148,8 @@ async function main() {
102
148
  { name: 'Prometheus Metrics', value: 'metrics' },
103
149
  { name: 'API Versioning (/api/v1)', value: 'apiVersioning' },
104
150
  { name: 'GraphQL (Apollo Server)', value: 'graphql' },
151
+ { name: 'MCP Server (AI Agent Tools)', value: 'mcp' },
152
+ { name: 'AI / LLM Service (LangChain)', value: 'ai' },
105
153
  ],
106
154
  when: (ans) => ans.db === 'none',
107
155
  },
@@ -142,6 +190,8 @@ async function main() {
142
190
  hasApiVersioning: features.includes('apiVersioning'),
143
191
  hasBackgroundJobs: features.includes('backgroundJobs'),
144
192
  hasGraphQL: features.includes('graphql'),
193
+ hasMCP: features.includes('mcp'),
194
+ hasAI: features.includes('ai'),
145
195
  jwtSecret: generateSecret(),
146
196
  jwtRefreshSecret: generateSecret(),
147
197
  };
@@ -184,7 +234,7 @@ async function main() {
184
234
  To get started:
185
235
  cd ${config.projectName}
186
236
  npm run dev
187
- ${config.hasSwagger ? `\nAPI Documentation: http://localhost:3000/api-docs` : ''}${config.hasGraphQL ? `\nGraphQL Playground: http://localhost:3000/graphql` : ''}${config.hasMetrics ? `\nPrometheus Metrics: http://localhost:3000/metrics` : ''}
237
+ ${config.hasSwagger ? `\nAPI Documentation: http://localhost:3000/api-docs` : ''}${config.hasGraphQL ? `\nGraphQL Playground: http://localhost:3000/graphql` : ''}${config.hasMetrics ? `\nPrometheus Metrics: http://localhost:3000/metrics` : ''}${config.hasMCP ? `\nMCP Server: npm run mcp:start` : ''}${config.hasAI ? `\nAI Endpoints: http://localhost:3000/api${config.hasApiVersioning ? '/v1' : ''}/ai/chat` : ''}
188
238
  Health Check: http://localhost:3000/health
189
239
 
190
240
  Available scripts:
@@ -203,6 +253,11 @@ Configuration:
203
253
  Features: ${features.join(', ') || 'base'}
204
254
  `);
205
255
 
256
+ // Prompt to install Coda VS Code extension for AI/MCP projects
257
+ if (config.hasAI || config.hasMCP) {
258
+ await promptCodaExtension();
259
+ }
260
+
206
261
  } catch (error) {
207
262
  // Rollback: remove partial project directory on failure
208
263
  if (fs.existsSync(projectDir)) {
@@ -245,6 +300,110 @@ Configuration:
245
300
  }
246
301
  });
247
302
 
303
+ program
304
+ .command('ai <description>')
305
+ .description('Generate a project from a natural language description (requires OPENAI_API_KEY or ANTHROPIC_API_KEY)')
306
+ .option('--skip-install', 'Skip npm install')
307
+ .option('--skip-cleanup', 'Skip post-generation cleanup')
308
+ .action(async (description, options) => {
309
+ const { runAiCommand } = require('./lib/ai-cli');
310
+ const aiConfig = await runAiCommand(description);
311
+
312
+ const inquirerPrompt = inquirer.createPromptModule();
313
+ const { confirmed } = await inquirerPrompt([
314
+ {
315
+ type: 'confirm',
316
+ name: 'confirmed',
317
+ message: 'Generate project with this configuration?',
318
+ default: true,
319
+ },
320
+ ]);
321
+
322
+ if (!confirmed) {
323
+ console.log('Cancelled.');
324
+ process.exit(0);
325
+ }
326
+
327
+ const features = aiConfig.features || [];
328
+ const config = {
329
+ projectName: aiConfig.projectName,
330
+ language: aiConfig.language || 'javascript',
331
+ db: aiConfig.db || 'none',
332
+ logger: aiConfig.logger || 'winston',
333
+ hasDatabase: aiConfig.db !== 'none',
334
+ isNoDatabase: aiConfig.db === 'none',
335
+ isPrisma: aiConfig.db === 'prisma',
336
+ isTypescript: aiConfig.language === 'typescript',
337
+ hasAuth: features.includes('auth') && aiConfig.db !== 'none',
338
+ hasRateLimit: features.includes('rateLimit'),
339
+ hasSwagger: features.includes('swagger'),
340
+ hasDocker: features.includes('docker'),
341
+ hasCicd: features.includes('cicd'),
342
+ hasWebsocket: features.includes('websocket'),
343
+ hasRequestId: features.includes('requestId'),
344
+ hasRedis: features.includes('redis') && features.includes('auth') && aiConfig.db !== 'none',
345
+ hasEmail: features.includes('email') && aiConfig.db !== 'none',
346
+ hasFileUpload: features.includes('fileUpload'),
347
+ hasSoftDelete: features.includes('softDelete') && aiConfig.db !== 'none',
348
+ hasAuditLog: features.includes('auditLog'),
349
+ hasMetrics: features.includes('metrics'),
350
+ hasApiVersioning: features.includes('apiVersioning'),
351
+ hasBackgroundJobs: features.includes('backgroundJobs'),
352
+ hasGraphQL: features.includes('graphql'),
353
+ hasMCP: features.includes('mcp'),
354
+ hasAI: features.includes('ai'),
355
+ jwtSecret: generateSecret(),
356
+ jwtRefreshSecret: generateSecret(),
357
+ };
358
+
359
+ const projectDir = path.join(process.cwd(), config.projectName);
360
+
361
+ if (fs.existsSync(projectDir)) {
362
+ console.error(`\n❌ Directory "${config.projectName}" already exists!`);
363
+ process.exit(1);
364
+ }
365
+
366
+ const dbLabel = config.isNoDatabase ? 'no database' : config.db;
367
+ console.log(`\n🚀 Creating ${config.projectName} (${config.language}, ${dbLabel})...\n`);
368
+
369
+ try {
370
+ await generateProject(config, projectDir, options);
371
+
372
+ if (!options.skipCleanup) {
373
+ await runPostGenerationCleanup(projectDir, config);
374
+ }
375
+
376
+ try {
377
+ execSync('git init', { cwd: projectDir, stdio: 'pipe' });
378
+ execSync('git add -A', { cwd: projectDir, stdio: 'pipe' });
379
+ execSync('git commit -m "Initial commit from express-genix ai"', {
380
+ cwd: projectDir,
381
+ stdio: 'pipe',
382
+ env: { ...process.env, GIT_COMMITTER_NAME: 'express-genix', GIT_COMMITTER_EMAIL: 'cli@express-genix.dev', GIT_AUTHOR_NAME: 'express-genix', GIT_AUTHOR_EMAIL: 'cli@express-genix.dev' },
383
+ });
384
+ } catch {
385
+ // Git not available
386
+ }
387
+
388
+ console.log(`\n✅ Project ${config.projectName} created from AI description!\n`);
389
+ console.log(` cd ${config.projectName}`);
390
+ console.log(' npm run dev\n');
391
+
392
+ // Prompt to install Coda VS Code extension for AI/MCP projects
393
+ if (config.hasAI || config.hasMCP) {
394
+ await promptCodaExtension();
395
+ }
396
+
397
+ } catch (error) {
398
+ if (fs.existsSync(projectDir)) {
399
+ fs.rmSync(projectDir, { recursive: true, force: true });
400
+ console.error('\n🧹 Rolled back partial project directory.');
401
+ }
402
+ console.error(`\n❌ Failed to create project: ${error.message}`);
403
+ process.exit(1);
404
+ }
405
+ });
406
+
248
407
  await program.parseAsync(process.argv);
249
408
  }
250
409
 
package/lib/ai-cli.js ADDED
@@ -0,0 +1,133 @@
1
+ /**
2
+ * AI CLI handler — interprets natural language project descriptions
3
+ * and maps them to express-genix configuration flags.
4
+ *
5
+ * Requires @langchain/openai or @langchain/anthropic to be installed.
6
+ * These are NOT bundled with express-genix to keep the CLI lightweight.
7
+ *
8
+ * Install with: npm install -g @langchain/core @langchain/openai
9
+ */
10
+
11
+ const SYSTEM_PROMPT = `You are an expert Express.js project configurator for the express-genix CLI tool.
12
+ Given a natural language description of a web application, output a JSON configuration object.
13
+
14
+ Available options:
15
+ - projectName: string (lowercase, hyphens only, no spaces)
16
+ - language: "javascript" | "typescript"
17
+ - db: "mongodb" | "postgresql" | "prisma" | "none"
18
+ - logger: "winston" | "pino"
19
+ - features: array of feature strings from this list:
20
+ - "auth" (JWT authentication — requires a database)
21
+ - "rateLimit" (rate limiting)
22
+ - "swagger" (Swagger/OpenAPI docs)
23
+ - "redis" (Redis token blacklist — requires auth)
24
+ - "docker" (Docker & Docker Compose)
25
+ - "cicd" (GitHub Actions CI/CD)
26
+ - "websocket" (WebSocket via Socket.io)
27
+ - "requestId" (request ID / correlation tracking)
28
+ - "email" (Nodemailer email service — requires database)
29
+ - "fileUpload" (Multer file uploads)
30
+ - "softDelete" (soft deletes — requires database + auth)
31
+ - "auditLog" (audit logging middleware)
32
+ - "metrics" (Prometheus metrics)
33
+ - "apiVersioning" (API versioning /api/v1)
34
+ - "backgroundJobs" (BullMQ background jobs)
35
+ - "graphql" (GraphQL via Apollo Server)
36
+ - "mcp" (MCP Server — exposes API as AI-agent tools)
37
+ - "ai" (LangChain/LangGraph AI service)
38
+
39
+ Rules:
40
+ - Always include "auth", "rateLimit", "swagger", "requestId" unless explicitly unwanted
41
+ - Include "docker" for production-ready apps
42
+ - Include "ai" if the description mentions AI, chatbot, LLM, or intelligence
43
+ - Include "mcp" if the description mentions AI agents, tools, or MCP
44
+ - Choose "prisma" for modern stacks, "mongodb" for documents, "postgresql" for relational
45
+ - Infer a short kebab-case project name from the description
46
+ - Output ONLY valid JSON. No explanation, no markdown fences.`;
47
+
48
+ const runAiCommand = async (description) => {
49
+ // Check for API key
50
+ const hasOpenAI = !!process.env.OPENAI_API_KEY;
51
+ const hasAnthropic = !!process.env.ANTHROPIC_API_KEY;
52
+ const hasGemini = !!process.env.GOOGLE_API_KEY;
53
+
54
+ if (!hasOpenAI && !hasAnthropic && !hasGemini) {
55
+ console.error('❌ The AI command requires an API key.');
56
+ console.error(' Set one of these environment variables:');
57
+ console.error(' export OPENAI_API_KEY=sk-...');
58
+ console.error(' export ANTHROPIC_API_KEY=sk-ant-...');
59
+ console.error(' export GOOGLE_API_KEY=AI...');
60
+ process.exit(1);
61
+ }
62
+
63
+ // Try to load LangChain (not bundled — must be installed separately)
64
+ let ChatModel;
65
+ try {
66
+ if (hasGemini) {
67
+ const { ChatGoogleGenerativeAI } = require('@langchain/google-genai');
68
+ ChatModel = new ChatGoogleGenerativeAI({
69
+ model: 'gemini-2.0-flash',
70
+ maxOutputTokens: 1024,
71
+ apiKey: process.env.GOOGLE_API_KEY,
72
+ });
73
+ } else if (hasAnthropic) {
74
+ const { ChatAnthropic } = require('@langchain/anthropic');
75
+ ChatModel = new ChatAnthropic({
76
+ modelName: 'claude-sonnet-4-20250514',
77
+ maxTokens: 1024,
78
+ anthropicApiKey: process.env.ANTHROPIC_API_KEY,
79
+ });
80
+ } else {
81
+ const { ChatOpenAI } = require('@langchain/openai');
82
+ ChatModel = new ChatOpenAI({
83
+ modelName: 'gpt-4o-mini',
84
+ maxTokens: 1024,
85
+ openAIApiKey: process.env.OPENAI_API_KEY,
86
+ });
87
+ }
88
+ } catch {
89
+ console.error('❌ LangChain packages not found.');
90
+ console.error(' Install them globally to use the AI command:');
91
+ console.error(' npm install -g @langchain/core @langchain/openai @langchain/anthropic @langchain/google-genai');
92
+ process.exit(1);
93
+ }
94
+
95
+ const { HumanMessage, SystemMessage } = require('@langchain/core/messages');
96
+
97
+ console.log('🤖 Analyzing your description...\n');
98
+
99
+ const response = await ChatModel.invoke([
100
+ new SystemMessage(SYSTEM_PROMPT),
101
+ new HumanMessage(description),
102
+ ]);
103
+
104
+ let config;
105
+ try {
106
+ const jsonMatch = response.content.match(/\{[\s\S]*\}/);
107
+ if (!jsonMatch) throw new Error('No JSON found in response');
108
+ config = JSON.parse(jsonMatch[0]);
109
+ } catch {
110
+ console.error('❌ Could not parse AI response. Try a clearer description.');
111
+ console.error(' Raw output:', response.content);
112
+ process.exit(1);
113
+ }
114
+
115
+ // Validate required fields
116
+ if (!config.projectName || !config.language || !config.db) {
117
+ console.error('❌ AI response missing required fields. Try again.');
118
+ process.exit(1);
119
+ }
120
+
121
+ // Display interpreted config
122
+ console.log('📋 Interpreted configuration:\n');
123
+ console.log(` Project: ${config.projectName}`);
124
+ console.log(` Language: ${config.language}`);
125
+ console.log(` Database: ${config.db}`);
126
+ console.log(` Logger: ${config.logger || 'winston'}`);
127
+ console.log(` Features: ${(config.features || []).join(', ') || 'base'}`);
128
+ console.log('');
129
+
130
+ return config;
131
+ };
132
+
133
+ module.exports = { runAiCommand };
package/lib/features.js CHANGED
@@ -240,6 +240,8 @@ const inferConfig = (projectDir, pkg) => {
240
240
  hasApiVersioning: false,
241
241
  hasBackgroundJobs: !!(pkg.dependencies && pkg.dependencies.bullmq),
242
242
  hasGraphQL: !!(pkg.dependencies && pkg.dependencies['@apollo/server']),
243
+ hasMCP: !!(pkg.dependencies && pkg.dependencies['@modelcontextprotocol/sdk']),
244
+ hasAI: !!(pkg.dependencies && pkg.dependencies['@langchain/core']),
243
245
  logger: pkg.dependencies && pkg.dependencies.pino ? 'pino' : 'winston',
244
246
  };
245
247
  };
package/lib/generator.js CHANGED
@@ -61,6 +61,14 @@ const createDirectoryStructure = (projectDir, config) => {
61
61
  dirs.push('src/graphql');
62
62
  }
63
63
 
64
+ if (config.hasMCP) {
65
+ dirs.push('src/mcp');
66
+ }
67
+
68
+ if (config.hasAI) {
69
+ dirs.push('src/agents');
70
+ }
71
+
64
72
  fs.mkdirSync(projectDir);
65
73
  dirs.forEach((dir) => {
66
74
  fs.mkdirSync(path.join(projectDir, dir), { recursive: true });
@@ -144,6 +152,10 @@ const generateFiles = async (config, projectDir) => {
144
152
  configFiles.push({ template: 'config/queue.js.ejs', output: `src/config/queue.${ext}` });
145
153
  }
146
154
 
155
+ if (config.hasAI) {
156
+ configFiles.push({ template: 'config/ai.js.ejs', output: `src/config/ai.${ext}` });
157
+ }
158
+
147
159
  // Route files
148
160
  const routeFiles = [
149
161
  { template: 'routes/index.js.ejs', output: `src/routes/index.${ext}` },
@@ -202,6 +214,18 @@ const generateFiles = async (config, projectDir) => {
202
214
  );
203
215
  }
204
216
 
217
+ if (config.hasAI) {
218
+ serviceFiles.push(
219
+ { template: 'services/aiService.js.ejs', output: `src/services/aiService.${ext}` }
220
+ );
221
+ controllerFiles.push(
222
+ { template: 'controllers/aiController.js.ejs', output: `src/controllers/aiController.${ext}` }
223
+ );
224
+ routeFiles.push(
225
+ { template: 'routes/aiRoutes.js.ejs', output: `src/routes/aiRoutes.${ext}` }
226
+ );
227
+ }
228
+
205
229
  if (config.hasFileUpload) {
206
230
  routeFiles.push(
207
231
  { template: 'routes/uploadRoutes.js.ejs', output: `src/routes/uploadRoutes.${ext}` }
@@ -214,6 +238,35 @@ const generateFiles = async (config, projectDir) => {
214
238
  );
215
239
  }
216
240
 
241
+ // GraphQL files
242
+ const graphqlFiles = [];
243
+
244
+ if (config.hasGraphQL) {
245
+ graphqlFiles.push(
246
+ { template: 'graphql/typeDefs.js.ejs', output: `src/graphql/typeDefs.${ext}` },
247
+ { template: 'graphql/resolvers.js.ejs', output: `src/graphql/resolvers.${ext}` }
248
+ );
249
+ }
250
+
251
+ // MCP files
252
+ const mcpFiles = [];
253
+
254
+ if (config.hasMCP) {
255
+ mcpFiles.push(
256
+ { template: 'mcp/server.js.ejs', output: `src/mcp/server.${ext}` },
257
+ { template: 'mcp/mcp-config.json.ejs', output: 'mcp.json' }
258
+ );
259
+ }
260
+
261
+ // Agent files
262
+ const agentFiles = [];
263
+
264
+ if (config.hasAI) {
265
+ agentFiles.push(
266
+ { template: 'agents/graph.js.ejs', output: `src/agents/graph.${ext}` }
267
+ );
268
+ }
269
+
217
270
  // Middleware files
218
271
  const middlewareFiles = [
219
272
  { template: 'middleware/errorHandler.js.ejs', output: `src/middleware/errorHandler.${ext}` },
@@ -303,15 +356,12 @@ const generateFiles = async (config, projectDir) => {
303
356
  ...serviceFiles,
304
357
  ...utilFiles,
305
358
  ...testFiles,
359
+ ...graphqlFiles,
360
+ ...mcpFiles,
361
+ ...agentFiles,
306
362
  ];
307
363
 
308
- // GraphQL files
309
- if (config.hasGraphQL) {
310
- allFiles.push(
311
- { template: 'graphql/typeDefs.js.ejs', output: `src/graphql/typeDefs.${ext}` },
312
- { template: 'graphql/resolvers.js.ejs', output: `src/graphql/resolvers.${ext}` }
313
- );
314
- }
364
+ // GraphQL files (legacy — now handled above)
315
365
 
316
366
  // Background job worker
317
367
  if (config.hasBackgroundJobs) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "express-genix",
3
- "version": "3.0.0",
3
+ "version": "4.1.0",
4
4
  "description": "Production-grade CLI to generate Express apps with JWT, RBAC, GraphQL, TypeScript, Prisma, MongoDB, PostgreSQL, file uploads, email, background jobs, and more",
5
5
  "main": "index.js",
6
6
  "bin": {