start-it-cli 1.0.0 → 1.0.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.
@@ -0,0 +1,519 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SmartAIProvider = void 0;
4
+ class SmartAIProvider {
5
+ constructor(apiKey) {
6
+ this.apiKey = apiKey || process.env.OPENAI_API_KEY || "";
7
+ this.baseUrl = process.env.AI_BASE_URL || "https://api.openai.com/v1";
8
+ }
9
+ async generateProject(request) {
10
+ // Fallback to rule-based recommendations if no API key
11
+ if (!this.apiKey) {
12
+ return this.generateRuleBasedRecommendation(request);
13
+ }
14
+ const prompt = this.buildProjectPrompt(request);
15
+ try {
16
+ const response = await fetch(`${this.baseUrl}/chat/completions`, {
17
+ method: "POST",
18
+ headers: {
19
+ Authorization: `Bearer ${this.apiKey}`,
20
+ "Content-Type": "application/json",
21
+ },
22
+ body: JSON.stringify({
23
+ model: "gpt-3.5-turbo",
24
+ messages: [{ role: "user", content: prompt }],
25
+ temperature: 0.7,
26
+ }),
27
+ });
28
+ if (!response.ok) {
29
+ throw new Error(`AI API error: ${response.statusText}`);
30
+ }
31
+ const data = await response.json();
32
+ return this.parseAIResponse(data.choices[0].message.content);
33
+ }
34
+ catch (error) {
35
+ console.warn("AI service unavailable, falling back to rule-based recommendations");
36
+ return this.generateRuleBasedRecommendation(request);
37
+ }
38
+ }
39
+ async analyzeRequirements(description) {
40
+ const features = [
41
+ "authentication",
42
+ "database",
43
+ "api",
44
+ "frontend",
45
+ "backend",
46
+ "testing",
47
+ "logging",
48
+ "monitoring",
49
+ "cache",
50
+ "queue",
51
+ "websocket",
52
+ "file-upload",
53
+ "email",
54
+ "payment",
55
+ "search",
56
+ ];
57
+ const found = [];
58
+ const lowerDesc = description.toLowerCase();
59
+ features.forEach((feature) => {
60
+ if (this.containsFeature(lowerDesc, feature)) {
61
+ found.push(feature);
62
+ }
63
+ });
64
+ return found;
65
+ }
66
+ async suggestDependencies(framework, features) {
67
+ const dependencyMap = {
68
+ "Node.js": {
69
+ authentication: {
70
+ name: "passport",
71
+ purpose: "Authentication middleware",
72
+ optional: false,
73
+ },
74
+ database: { name: "mongoose", purpose: "MongoDB ODM", optional: false },
75
+ api: { name: "express", purpose: "Web framework", optional: false },
76
+ testing: {
77
+ name: "jest",
78
+ purpose: "Testing framework",
79
+ optional: false,
80
+ },
81
+ logging: {
82
+ name: "winston",
83
+ purpose: "Logging library",
84
+ optional: true,
85
+ },
86
+ monitoring: {
87
+ name: "prometheus-client",
88
+ purpose: "Metrics collection",
89
+ optional: true,
90
+ },
91
+ cache: { name: "redis", purpose: "Caching layer", optional: true },
92
+ queue: { name: "bull", purpose: "Job queue", optional: true },
93
+ },
94
+ Go: {
95
+ authentication: {
96
+ name: "github.com/golang-jwt/jwt",
97
+ purpose: "JWT tokens",
98
+ optional: false,
99
+ },
100
+ database: {
101
+ name: "gorm.io/gorm",
102
+ purpose: "ORM library",
103
+ optional: false,
104
+ },
105
+ api: {
106
+ name: "github.com/gin-gonic/gin",
107
+ purpose: "Web framework",
108
+ optional: false,
109
+ },
110
+ testing: {
111
+ name: "github.com/stretchr/testify",
112
+ purpose: "Testing utilities",
113
+ optional: false,
114
+ },
115
+ logging: {
116
+ name: "github.com/sirupsen/logrus",
117
+ purpose: "Structured logging",
118
+ optional: true,
119
+ },
120
+ monitoring: {
121
+ name: "github.com/prometheus/client_golang",
122
+ purpose: "Metrics",
123
+ optional: true,
124
+ },
125
+ },
126
+ Python: {
127
+ authentication: {
128
+ name: "django-auth",
129
+ purpose: "Django auth system",
130
+ optional: false,
131
+ },
132
+ database: { name: "sqlalchemy", purpose: "SQL ORM", optional: false },
133
+ api: {
134
+ name: "fastapi",
135
+ purpose: "Modern web framework",
136
+ optional: false,
137
+ },
138
+ testing: {
139
+ name: "pytest",
140
+ purpose: "Testing framework",
141
+ optional: false,
142
+ },
143
+ logging: {
144
+ name: "structlog",
145
+ purpose: "Structured logging",
146
+ optional: true,
147
+ },
148
+ monitoring: {
149
+ name: "prometheus-client",
150
+ purpose: "Metrics",
151
+ optional: true,
152
+ },
153
+ },
154
+ };
155
+ const frameworkDeps = dependencyMap[framework] || {};
156
+ return features.map((feature) => frameworkDeps[feature]).filter(Boolean);
157
+ }
158
+ containsFeature(description, feature) {
159
+ const keywords = this.getFeatureKeywords(feature);
160
+ return keywords.some((keyword) => description.includes(keyword));
161
+ }
162
+ getFeatureKeywords(feature) {
163
+ const keywordMap = {
164
+ authentication: ["auth", "login", "user", "session", "token", "jwt"],
165
+ database: ["database", "db", "storage", "persist", "model", "orm"],
166
+ api: ["api", "rest", "endpoint", "service", "backend"],
167
+ frontend: ["ui", "frontend", "interface", "gui", "web"],
168
+ backend: ["backend", "server", "service", "logic"],
169
+ testing: ["test", "spec", "unit", "integration"],
170
+ logging: ["log", "audit", "track", "monitor"],
171
+ monitoring: ["monitor", "metrics", "analytics", "performance"],
172
+ cache: ["cache", "redis", "memory", "fast"],
173
+ queue: ["queue", "job", "task", "worker", "background"],
174
+ websocket: ["websocket", "real-time", "socket", "live"],
175
+ "file-upload": ["upload", "file", "image", "document"],
176
+ email: ["email", "mail", "notification", "send"],
177
+ payment: ["payment", "stripe", "billing", "subscription"],
178
+ search: ["search", "elasticsearch", "query", "filter"],
179
+ };
180
+ return keywordMap[feature] || [feature];
181
+ }
182
+ generateRuleBasedRecommendation(request) {
183
+ const framework = request.framework || this.suggestFramework(request);
184
+ const template = this.suggestTemplate(framework, request);
185
+ // Generate basic file structure based on framework and description
186
+ const structure = this.generateBasicFileStructure(framework, template, request);
187
+ return {
188
+ framework,
189
+ template,
190
+ dependencies: this.generateBasicDependencies(framework, request.features),
191
+ structure,
192
+ reasoning: `Based on your requirements: ${request.description}, I recommend ${framework} with ${template} template.`,
193
+ };
194
+ }
195
+ generateBasicFileStructure(framework, template, request) {
196
+ const files = [];
197
+ // Basic package.json
198
+ files.push({
199
+ path: "package.json",
200
+ content: this.generatePackageJson(framework, request),
201
+ description: "Package configuration",
202
+ isExecutable: false,
203
+ });
204
+ // Main application file
205
+ files.push({
206
+ path: this.getMainFilePath(framework),
207
+ content: this.generateMainFile(framework, template, request),
208
+ description: "Main application entry point",
209
+ isExecutable: true,
210
+ });
211
+ // Add framework-specific files
212
+ if (framework === "Node.js" && request.features.includes("api")) {
213
+ files.push({
214
+ path: "src/routes/index.ts",
215
+ content: this.generateBasicRoutes(request),
216
+ description: "API routes",
217
+ isExecutable: false,
218
+ });
219
+ }
220
+ if (request.features.includes("database")) {
221
+ files.push({
222
+ path: "src/models/index.ts",
223
+ content: this.generateBasicModels(request),
224
+ description: "Database models",
225
+ isExecutable: false,
226
+ });
227
+ }
228
+ return files;
229
+ }
230
+ generatePackageJson(framework, request) {
231
+ const basePackage = {
232
+ name: "generated-project",
233
+ version: "1.0.0",
234
+ description: request.description,
235
+ main: this.getMainFilePath(framework),
236
+ scripts: {
237
+ start: framework === "Node.js" ? "node dist/index.js" : "start",
238
+ dev: framework === "Node.js" ? "ts-node src/index.ts" : "dev",
239
+ build: framework === "Node.js" ? "tsc" : "build",
240
+ },
241
+ dependencies: {},
242
+ devDependencies: framework === "Node.js"
243
+ ? {
244
+ "@types/node": "^20.0.0",
245
+ typescript: "^5.0.0",
246
+ "ts-node": "^10.0.0",
247
+ }
248
+ : {},
249
+ };
250
+ return JSON.stringify(basePackage, null, 2);
251
+ }
252
+ generateMainFile(framework, template, request) {
253
+ if (framework === "Node.js") {
254
+ return `// Auto-generated ${template} for ${request.description}
255
+ import express from 'express';
256
+ import cors from 'cors';
257
+
258
+ const app = express();
259
+ const PORT = process.env.PORT || 3000;
260
+
261
+ // Middleware
262
+ app.use(cors());
263
+ app.use(express.json());
264
+
265
+ // Basic routes
266
+ app.get('/', (req, res) => {
267
+ res.json({ message: '${request.description} API' });
268
+ });
269
+
270
+ app.get('/health', (req, res) => {
271
+ res.json({ status: 'OK', timestamp: new Date().toISOString() });
272
+ });
273
+
274
+ app.listen(PORT, () => {
275
+ console.log(\`Server running on port \${PORT}\`);
276
+ });
277
+
278
+ export default app;`;
279
+ }
280
+ return `// Generated ${framework} application
281
+ console.log('${request.description}');`;
282
+ }
283
+ generateBasicRoutes(request) {
284
+ return `// API routes for ${request.description}
285
+ import { Router } from 'express';
286
+
287
+ const router = Router();
288
+
289
+ // Example routes based on project description
290
+ router.get('/', (req, res) => {
291
+ res.json({ message: '${request.description} API endpoints' });
292
+ });
293
+
294
+ ${request.features.includes("authentication")
295
+ ? `
296
+ router.post('/auth/login', (req, res) => {
297
+ // Login logic here
298
+ res.json({ token: 'sample-token' });
299
+ });
300
+
301
+ router.post('/auth/register', (req, res) => {
302
+ // Registration logic here
303
+ res.json({ message: 'User registered' });
304
+ });
305
+ `
306
+ : ""}
307
+
308
+ ${request.features.includes("database")
309
+ ? `
310
+ router.get('/data', (req, res) => {
311
+ // Data retrieval logic here
312
+ res.json({ data: [] });
313
+ });
314
+
315
+ router.post('/data', (req, res) => {
316
+ // Data creation logic here
317
+ res.json({ message: 'Data created' });
318
+ });
319
+ `
320
+ : ""}
321
+
322
+ export default router;`;
323
+ }
324
+ generateBasicModels(request) {
325
+ return `// Database models for ${request.description}
326
+ export interface BaseModel {
327
+ id: string;
328
+ createdAt: Date;
329
+ updatedAt: Date;
330
+ }
331
+
332
+ ${request.features.includes("authentication")
333
+ ? `
334
+ export interface User extends BaseModel {
335
+ email: string;
336
+ password: string;
337
+ name: string;
338
+ }
339
+ `
340
+ : ""}
341
+
342
+ ${request.description.toLowerCase().includes("hospital")
343
+ ? `
344
+ export interface Patient extends BaseModel {
345
+ name: string;
346
+ dateOfBirth: Date;
347
+ medicalRecord: string;
348
+ }
349
+
350
+ export interface Doctor extends BaseModel {
351
+ name: string;
352
+ specialization: string;
353
+ licenseNumber: string;
354
+ }
355
+ `
356
+ : ""}`;
357
+ }
358
+ getMainFilePath(framework) {
359
+ switch (framework) {
360
+ case "Node.js":
361
+ return "src/index.ts";
362
+ case "Python":
363
+ return "main.py";
364
+ case "Go":
365
+ return "main.go";
366
+ default:
367
+ return "index.js";
368
+ }
369
+ }
370
+ generateBasicDependencies(framework, features) {
371
+ const deps = [];
372
+ if (framework === "Node.js") {
373
+ deps.push({
374
+ name: "express",
375
+ version: "^4.18.0",
376
+ purpose: "Web framework",
377
+ optional: false,
378
+ });
379
+ deps.push({
380
+ name: "cors",
381
+ version: "^2.8.5",
382
+ purpose: "CORS support",
383
+ optional: false,
384
+ });
385
+ if (features.includes("database")) {
386
+ deps.push({
387
+ name: "mongoose",
388
+ version: "^7.0.0",
389
+ purpose: "MongoDB ODM",
390
+ optional: false,
391
+ });
392
+ }
393
+ if (features.includes("authentication")) {
394
+ deps.push({
395
+ name: "jsonwebtoken",
396
+ version: "^9.0.0",
397
+ purpose: "JWT tokens",
398
+ optional: false,
399
+ });
400
+ deps.push({
401
+ name: "bcryptjs",
402
+ version: "^2.4.3",
403
+ purpose: "Password hashing",
404
+ optional: false,
405
+ });
406
+ }
407
+ }
408
+ return deps;
409
+ }
410
+ suggestFramework(request) {
411
+ const desc = request.description.toLowerCase();
412
+ if (desc.includes("mobile") || desc.includes("app")) {
413
+ return desc.includes("cross-platform") ? "Flutter" : "React Native";
414
+ }
415
+ if (desc.includes("enterprise") || desc.includes("java")) {
416
+ return "Spring Boot";
417
+ }
418
+ if (desc.includes("python") ||
419
+ desc.includes("ml") ||
420
+ desc.includes("data")) {
421
+ return "Python";
422
+ }
423
+ if (desc.includes("performance") || desc.includes("concurrent")) {
424
+ return "Go";
425
+ }
426
+ return "Node.js"; // Default
427
+ }
428
+ suggestTemplate(framework, request) {
429
+ const desc = request.description.toLowerCase();
430
+ const scale = request.scale;
431
+ switch (framework) {
432
+ case "Node.js":
433
+ if (desc.includes("api") || desc.includes("backend"))
434
+ return "Express API";
435
+ if (desc.includes("fullstack") || desc.includes("ssr"))
436
+ return "Next.js";
437
+ return "TypeScript Project";
438
+ case "Go":
439
+ if (desc.includes("api") || desc.includes("web"))
440
+ return "Web API";
441
+ if (scale === "large")
442
+ return "Microservice";
443
+ return "Basic CLI";
444
+ case "Flutter":
445
+ if (desc.includes("web"))
446
+ return "Web App";
447
+ if (desc.includes("desktop"))
448
+ return "Desktop App";
449
+ return "Mobile App";
450
+ case "Python":
451
+ if (desc.includes("api") || desc.includes("fast"))
452
+ return "FastAPI";
453
+ if (desc.includes("full") || desc.includes("admin"))
454
+ return "Django";
455
+ return "Flask";
456
+ default:
457
+ return "Basic";
458
+ }
459
+ }
460
+ buildProjectPrompt(request) {
461
+ return `
462
+ As an expert software architect and full-stack developer, analyze this project request and generate a complete, production-ready project:
463
+
464
+ Project Description: ${request.description}
465
+ Preferred Framework: ${request.framework || "Auto-detect"}
466
+ Key Features: ${request.features.join(", ")}
467
+ Project Scale: ${request.scale}
468
+ Deployment Target: ${request.deployment || "Not specified"}
469
+
470
+ Generate a JSON response with:
471
+ 1. Recommended framework and template
472
+ 2. Essential dependencies with purposes and versions
473
+ 3. Complete file structure with ACTUAL CODE CONTENT
474
+ 4. Clear reasoning for choices
475
+
476
+ For each file, provide real, working code that implements the described functionality. Include:
477
+ - Package.json with proper dependencies
478
+ - Main application files with actual implementation
479
+ - Configuration files
480
+ - Example routes/models/controllers based on the description
481
+ - Basic error handling and validation
482
+ - Proper TypeScript types if applicable
483
+
484
+ Format as:
485
+ {
486
+ "framework": "...",
487
+ "template": "...",
488
+ "dependencies": [{"name": "...", "version": "...", "purpose": "...", "optional": false}],
489
+ "structure": [
490
+ {
491
+ "path": "package.json",
492
+ "content": "...",
493
+ "description": "Package configuration",
494
+ "isExecutable": false
495
+ },
496
+ {
497
+ "path": "src/index.ts",
498
+ "content": "...",
499
+ "description": "Main application entry point",
500
+ "isExecutable": true
501
+ }
502
+ ],
503
+ "reasoning": "..."
504
+ }
505
+
506
+ IMPORTANT: Provide complete, working code files that would actually run and implement the described functionality.
507
+ `;
508
+ }
509
+ parseAIResponse(response) {
510
+ try {
511
+ return JSON.parse(response);
512
+ }
513
+ catch (error) {
514
+ throw new Error("Invalid AI response format");
515
+ }
516
+ }
517
+ }
518
+ exports.SmartAIProvider = SmartAIProvider;
519
+ //# sourceMappingURL=provider.js.map
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=types.js.map
package/dist/cli.js CHANGED
@@ -7,6 +7,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
7
7
  const chalk_1 = __importDefault(require("chalk"));
8
8
  const inquirer_1 = __importDefault(require("inquirer"));
9
9
  const generator_1 = require("./generator");
10
+ const generator_2 = require("./ai/generator");
10
11
  const FRAMEWORKS = [
11
12
  "Go",
12
13
  "Flutter",
@@ -15,16 +16,27 @@ const FRAMEWORKS = [
15
16
  "Node.js",
16
17
  "Python",
17
18
  ];
19
+ const GENERATION_TYPES = [
20
+ { name: "Traditional (Template-based)", value: "traditional" },
21
+ { name: "AI-Powered (Smart recommendations)", value: "ai" },
22
+ ];
18
23
  async function main() {
19
24
  console.log(chalk_1.default.bold.cyan("\nšŸš€ Welcome to start-it!\n"));
20
25
  console.log(chalk_1.default.gray("Create a new project with ease.\n"));
21
26
  try {
22
27
  const answers = await inquirer_1.default.prompt([
28
+ {
29
+ type: "list",
30
+ name: "generationType",
31
+ message: "Choose project generation method:",
32
+ choices: GENERATION_TYPES,
33
+ },
23
34
  {
24
35
  type: "list",
25
36
  name: "framework",
26
37
  message: "What type of project would you like to create?",
27
38
  choices: FRAMEWORKS,
39
+ when: (answers) => answers.generationType === "traditional",
28
40
  },
29
41
  {
30
42
  type: "input",
@@ -47,11 +59,72 @@ async function main() {
47
59
  projectName: answers.projectName,
48
60
  projectPath: process.cwd(),
49
61
  };
50
- // Get framework-specific options
51
- const frameworkOptions = await getFrameworkOptions(config.framework);
52
- config.options = frameworkOptions;
53
- const generator = new generator_1.ProjectGenerator(config);
54
- await generator.generate();
62
+ if (answers.generationType === "traditional") {
63
+ // Get framework-specific options
64
+ const frameworkOptions = await getFrameworkOptions(config.framework);
65
+ config.options = frameworkOptions;
66
+ const generator = new generator_1.ProjectGenerator(config);
67
+ await generator.generate();
68
+ }
69
+ else {
70
+ // AI-powered generation
71
+ const aiAnswers = await inquirer_1.default.prompt([
72
+ {
73
+ type: "input",
74
+ name: "description",
75
+ message: "Describe your project:",
76
+ validate: (input) => {
77
+ if (!input.trim()) {
78
+ return "Project description cannot be empty";
79
+ }
80
+ return true;
81
+ },
82
+ },
83
+ {
84
+ type: "list",
85
+ name: "scale",
86
+ message: "Project scale:",
87
+ choices: ["small", "medium", "large"],
88
+ },
89
+ {
90
+ type: "input",
91
+ name: "deployment",
92
+ message: "Deployment target (optional):",
93
+ },
94
+ {
95
+ type: "checkbox",
96
+ name: "features",
97
+ message: "Select features you need:",
98
+ choices: [
99
+ "authentication",
100
+ "database",
101
+ "api",
102
+ "frontend",
103
+ "backend",
104
+ "testing",
105
+ "logging",
106
+ "monitoring",
107
+ "cache",
108
+ "queue",
109
+ "websocket",
110
+ "file-upload",
111
+ "email",
112
+ "payment",
113
+ "search",
114
+ ],
115
+ },
116
+ ]);
117
+ const aiGenerator = new generator_2.AIProjectGenerator();
118
+ await aiGenerator.generate({
119
+ projectName: answers.projectName,
120
+ projectPath: process.cwd(),
121
+ description: aiAnswers.description,
122
+ framework: undefined,
123
+ scale: aiAnswers.scale,
124
+ deployment: aiAnswers.deployment,
125
+ features: aiAnswers.features,
126
+ });
127
+ }
55
128
  console.log(chalk_1.default.bold.green(`\nāœ“ Project "${config.projectName}" created successfully!\n`));
56
129
  console.log(chalk_1.default.cyan(`Next steps:`));
57
130
  console.log(chalk_1.default.gray(` cd ${config.projectName}`));
package/package.json CHANGED
@@ -1,10 +1,10 @@
1
1
  {
2
2
  "name": "start-it-cli",
3
- "version": "1.0.0",
3
+ "version": "1.0.2",
4
4
  "description": "A prompt-based CLI tool to scaffold projects for Go, Flutter, React Native, Spring Boot, and more",
5
5
  "main": "dist/index.js",
6
6
  "bin": {
7
- "start-it": "dist/cli.js"
7
+ "start-it-cli": "dist/cli.js"
8
8
  },
9
9
  "scripts": {
10
10
  "build": "tsc",