create-backlist 2.0.0 β†’ 2.0.1

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/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [W.A.H.ISHAN]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
package/README.md ADDED
@@ -0,0 +1,97 @@
1
+ # πŸš€ Create Backlist
2
+
3
+ [![NPM Version](https://img.shields.io/npm/v/create-backlist.svg)](https://www.npmjs.com/package/create-backlist)
4
+ [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
5
+
6
+ Tired of manually creating backend boilerplate every time you build a frontend? **`create-backlist`** is an intelligent CLI tool that analyzes your frontend project and automatically generates a backend with all the necessary routes and controllers, saving you hours of repetitive work.
7
+
8
+ It's not just another scaffolder; it's a **context-aware, dynamic code generator** that builds a backend tailor-made for your frontend's specific API needs.
9
+
10
+ ![Demo GIF (Optional: Add a GIF of your tool in action here)](link-to-your-demo-gif.gif)
11
+
12
+ ## ✨ Key Features
13
+
14
+ - **πŸ€– Intelligent Code Analysis:** Scans your frontend codebase (React, Vue, etc.) using Abstract Syntax Trees (ASTs) to detect API calls (`fetch` requests).
15
+ - **🌐 Multi-Language Support:** Generate a backend in your preferred stack.
16
+ - βœ… **Currently Supports:**
17
+ - Node.js (with TypeScript & Express)
18
+ - C# (with ASP.NET Core Web API)
19
+ - ⏳ **Coming Soon:**
20
+ - Python (with FastAPI)
21
+ - Java (with Spring Boot)
22
+ - **⚑️ Fully Automated:** A single command handles everything from project scaffolding to dependency installation.
23
+ - **πŸ”§ Zero-Configuration:** No complex config files needed. Just run the command and answer a few simple questions.
24
+ - **🧼 Clean Code Generation:** Creates a well-structured backend, ready for you to implement your business logic.
25
+
26
+ ## πŸ“¦ Installation & Usage
27
+
28
+ No global installation needed! Just run this command inside your existing frontend project's root directory:
29
+
30
+ ```bash
31
+ npm create backlist@latest
32
+ ```
33
+
34
+ The tool will then guide you through an interactive setup process:
35
+
36
+ 1. **Enter a name for your backend directory:** (default: `backend`)
37
+ 2. **Select the backend stack:** (e.g., `Node.js (TypeScript, Express)`)
38
+ 3. **Enter the path to your frontend `src` directory:** (default: `src`)
39
+
40
+ That's it! The tool will analyze your code, generate the backend in a new directory, and install all the necessary dependencies.
41
+
42
+ ### Example
43
+
44
+ Let's say your frontend has this API call:
45
+
46
+ ```javascript
47
+ // in your React component
48
+ fetch('/api/products/123', { method: 'PUT' });
49
+ ```
50
+
51
+ `create-backlist` will automatically generate a backend with a `products` controller and a `PUT` route for `products/:id`.
52
+
53
+ ## πŸ’‘ How It's Different from Other Tools
54
+
55
+ | Tool | Approach | Use Case |
56
+ | --------------------- | -------------------------------------- | ----------------------------------------------------------- |
57
+ | **Express Generator** | Static Scaffolding | Quickly start a *new, empty* Express project. |
58
+ | **NestJS CLI** | Static Scaffolding & Code Generation | Start a *new, structured* NestJS project and add parts manually. |
59
+ | **`create-backlist`** | **Dynamic & Context-Aware Scaffolding** | Generate a backend that is **tailor-made** for an *existing* frontend. |
60
+
61
+ While traditional generators give you a blank canvas, `create-backlist` looks at your finished painting (the frontend) and builds the perfect frame (the backend) for it.
62
+
63
+ ## πŸ—ΊοΈ Roadmap
64
+
65
+ `create-backlist` is actively being developed. Here are some of the features planned for future releases:
66
+
67
+ - [ ] **Python Support:** Generate a backend using FastAPI.
68
+ - [ ] **Java Support:** Generate a backend using Spring Boot.
69
+ - [ ] **Database Model Generation:** Automatically create basic database models (e.g., Mongoose, Prisma) based on `POST`/`PUT` request bodies.
70
+ - [ ] **Authentication Boilerplate:** Add an option to generate basic JWT-based authentication routes (`/login`, `/register`).
71
+
72
+ Have an idea for a new feature? Feel free to [open an issue](https://github.com/WAH-ISHAN/create-backlist/issues) on GitHub!
73
+
74
+ ## πŸ› οΈ Contributing
75
+
76
+ Contributions are what make the open-source community such an amazing place to learn, inspire, and create. Any contributions you make are **greatly appreciated**.
77
+
78
+ 1. Fork the Project
79
+ 2. Create your Feature Branch (`git checkout -b feature/AmazingFeature`)
80
+ 3. Commit your Changes (`git commit -m 'Add some AmazingFeature'`)
81
+ 4. Push to the Branch (`git push origin feature/AmazingFeature`)
82
+ 5. Open a Pull Request
83
+
84
+ ## πŸ“„ License
85
+
86
+ This project is licensed under the MIT License - see the [LICENSE](LICENSE) file for details.
87
+
88
+ ## πŸ™ Acknowledgements
89
+
90
+ - **Babel** for the amazing AST parser.
91
+ - **Inquirer.js** for the interactive CLI prompts.
92
+ - **fs-extra** for making file system operations a breeze.
93
+ - **Google's Gemini** for assistance with brainstorming and debugging.
94
+
95
+ ---
96
+
97
+ _Built with ❀️ by [W.A.H. ISHAN](https://github.com/WAH-ISHAN)._
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-backlist",
3
- "version": "2.0.0",
3
+ "version": "2.0.1",
4
4
  "description": "An advanced, multi-language backend generator based on frontend analysis.",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -5,137 +5,125 @@ const path = require('path');
5
5
  const { analyzeFrontend } = require('../analyzer');
6
6
  const { renderAndWrite, getTemplatePath } = require('./template');
7
7
 
8
- /**
9
- * Generate a Node.js + TypeScript (Express) backend project automatically.
10
- */
11
8
  async function generateNodeProject(options) {
12
9
  const { projectDir, projectName, frontendSrcDir } = options;
13
10
 
14
11
  try {
15
- // --- Step 1: Analyze Frontend ---
16
- console.log(chalk.blue(' -> Analyzing frontend for API endpoints...'));
12
+ // --- Step 1: Analyze Frontend to get Endpoints and Schema Info ---
13
+ console.log(chalk.blue(' -> Analyzing frontend for API endpoints...'));
17
14
  const endpoints = await analyzeFrontend(frontendSrcDir);
18
-
19
15
  if (endpoints.length > 0) {
20
- console.log(chalk.green(` -> Found ${endpoints.length} endpoints.`));
16
+ console.log(chalk.green(` -> Found ${endpoints.length} endpoints.`));
21
17
  } else {
22
- console.log(
23
- chalk.yellow(' -> No API endpoints found. A basic project will be created.')
24
- );
18
+ console.log(chalk.yellow(' -> No API endpoints found. A basic project will be created.'));
25
19
  }
26
20
 
27
- // --- Step 2: Scaffold Base Project ---
28
- console.log(chalk.blue(' -> Scaffolding Node.js (Express + TS) project...'));
29
-
30
- const baseDir = getTemplatePath('node-ts-express/base');
31
- const serverTemplatePath = path.join(baseDir, 'server.ts');
32
- const tsconfigTemplatePath = path.join(baseDir, 'tsconfig.json');
21
+ // --- Step 2: Identify which Database Models to Generate ---
22
+ const modelsToGenerate = new Map();
23
+ endpoints.forEach(ep => {
24
+ // If an endpoint has schemaFields and a valid controllerName, add it to our map.
25
+ if (ep.schemaFields && ep.controllerName !== 'Default' && !modelsToGenerate.has(ep.controllerName)) {
26
+ modelsToGenerate.set(ep.controllerName, ep.schemaFields);
27
+ }
28
+ });
33
29
 
30
+ // --- Step 3: Scaffold Base Project Structure & Files ---
31
+ console.log(chalk.blue(' -> Scaffolding Node.js (Express + TS) project...'));
32
+
33
+ // Create the main source directory
34
34
  const destSrcDir = path.join(projectDir, 'src');
35
- const serverDestPath = path.join(destSrcDir, 'server.ts');
36
- const tsconfigDestPath = path.join(projectDir, 'tsconfig.json');
37
-
38
35
  await fs.ensureDir(destSrcDir);
39
- await fs.copy(serverTemplatePath, serverDestPath);
40
- await fs.copy(tsconfigTemplatePath, tsconfigDestPath);
41
-
42
- console.log(chalk.gray(' -> Base server.ts and tsconfig.json copied.'));
43
36
 
44
- // --- Step 3: Generate package.json and routes.ts ---
45
- await renderAndWrite(
46
- getTemplatePath('node-ts-express/partials/package.json.ejs'),
47
- path.join(projectDir, 'package.json'),
48
- { projectName }
49
- );
37
+ // Copy static base files
38
+ await fs.copy(getTemplatePath('node-ts-express/base/server.ts'), path.join(destSrcDir, 'server.ts'));
39
+ await fs.copy(getTemplatePath('node-ts-express/base/tsconfig.json'), path.join(projectDir, 'tsconfig.json'));
40
+
41
+ // --- Step 4: Generate Dynamic Files (package.json, Models, Controllers) ---
50
42
 
51
- await renderAndWrite(
52
- getTemplatePath('node-ts-express/partials/routes.ts.ejs'),
53
- path.join(destSrcDir, 'routes.ts'),
54
- { endpoints }
43
+ // Prepare package.json content (in memory)
44
+ const packageJsonContent = JSON.parse(
45
+ await ejs.renderFile(getTemplatePath('node-ts-express/partials/package.json.ejs'), { projectName })
55
46
  );
56
47
 
57
- console.log(chalk.gray(' -> package.json and routes.ts generated.'));
58
-
59
- // --- Step 4: Analyze endpoints for models/controllers ---
60
- const modelsToGenerate = new Map();
61
-
62
- endpoints.forEach((ep) => {
63
- if (ep.schemaFields && !modelsToGenerate.has(ep.controllerName)) {
64
- modelsToGenerate.set(ep.controllerName, ep.schemaFields);
65
- }
66
- });
67
-
68
- // --- Step 5: Generate Models and Controllers if applicable ---
48
+ // Conditionally add Mongoose if we are generating models
69
49
  if (modelsToGenerate.size > 0) {
70
- console.log(chalk.blue(' -> Generating database models and controllers...'));
50
+ console.log(chalk.gray(' -> Preparing to add Mongoose to dependencies...'));
51
+ packageJsonContent.dependencies['mongoose'] = '^7.5.0'; // Use a recent, stable version
52
+ }
71
53
 
72
- await fs.ensureDir(path.join(projectDir, 'src', 'models'));
73
- await fs.ensureDir(path.join(projectDir, 'src', 'controllers'));
54
+ // Write the final package.json to the disk
55
+ await fs.writeJson(path.join(projectDir, 'package.json'), packageJsonContent, { spaces: 2 });
56
+
57
+ // Generate Model and Controller files if any were found
58
+ if (modelsToGenerate.size > 0) {
59
+ console.log(chalk.blue(' -> Generating database models and controllers...'));
60
+ await fs.ensureDir(path.join(destSrcDir, 'models'));
61
+ await fs.ensureDir(path.join(destSrcDir, 'controllers'));
74
62
 
75
63
  for (const [modelName, schema] of modelsToGenerate.entries()) {
76
- // Generate Model file
64
+ // Generate Model File (e.g., models/User.model.ts)
77
65
  await renderAndWrite(
78
66
  getTemplatePath('node-ts-express/partials/Model.ts.ejs'),
79
- path.join(projectDir, 'src', 'models', `${modelName}.model.ts`),
67
+ path.join(destSrcDir, 'models', `${modelName}.model.ts`),
80
68
  { modelName, schema }
81
69
  );
82
-
83
- // Generate Controller file
70
+ // Generate Controller File (e.g., controllers/User.controller.ts)
84
71
  await renderAndWrite(
85
72
  getTemplatePath('node-ts-express/partials/Controller.ts.ejs'),
86
- path.join(projectDir, 'src', 'controllers', `${modelName}.controller.ts`),
73
+ path.join(destSrcDir, 'controllers', `${modelName}.controller.ts`),
87
74
  { modelName }
88
75
  );
89
76
  }
90
-
91
- console.log(chalk.gray(' -> Models and controllers generated.'));
92
77
  }
93
78
 
94
- // --- Step 6: Modify server.ts ---
95
- if (!(await fs.pathExists(serverDestPath))) {
96
- throw new Error(`Critical error: server.ts was not found at ${serverDestPath}.`);
79
+ // --- Step 5: Generate the Smart Route File ---
80
+ console.log(chalk.gray(' -> Generating dynamic routes...'));
81
+ await renderAndWrite(
82
+ getTemplatePath('node-ts-express/partials/routes.ts.ejs'),
83
+ path.join(destSrcDir, 'routes.ts'),
84
+ { endpoints } // Pass all endpoints to the template
85
+ );
86
+
87
+ // --- Step 6: Inject Routes into the Main Server File ---
88
+ const serverDestPath = path.join(destSrcDir, 'server.ts');
89
+ let serverFileContent = await fs.readFile(serverDestPath, 'utf-8');
90
+
91
+ let dbConnectionCode = '';
92
+ if (modelsToGenerate.size > 0) {
93
+ dbConnectionCode = `
94
+ // --- Database Connection ---
95
+ import mongoose from 'mongoose';
96
+ const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/${projectName}';
97
+ mongoose.connect(MONGO_URI)
98
+ .then(() => console.log('MongoDB Connected...'))
99
+ .catch(err => console.error('MongoDB Connection Error:', err));
100
+ // -------------------------
101
+ `;
97
102
  }
98
103
 
99
- let serverFileContent = await fs.readFile(serverDestPath, 'utf-8');
100
- serverFileContent = serverFileContent.replace(
101
- '// INJECT:ROUTES',
102
- `import apiRoutes from './routes';\napp.use(apiRoutes);`
103
- );
104
+ // Inject DB connection code after dotenv.config() and route loader
105
+ serverFileContent = serverFileContent
106
+ .replace("dotenv.config();", `dotenv.config();\n${dbConnectionCode}`)
107
+ .replace('// INJECT:ROUTES', `import apiRoutes from './routes';\napp.use(apiRoutes);`);
108
+
104
109
  await fs.writeFile(serverDestPath, serverFileContent);
105
110
 
106
- console.log(chalk.gray(' -> server.ts modified successfully.'));
107
-
108
- // --- Step 7: Install dependencies ---
109
- console.log(chalk.magenta(' -> Installing dependencies (npm install)...'));
111
+ // --- Step 7: Install All Dependencies at Once ---
112
+ console.log(chalk.magenta(' -> Installing dependencies (npm install)... This might take a moment.'));
110
113
  await execa('npm', ['install'], { cwd: projectDir });
111
114
 
112
- // --- Step 8: Add mongoose if models were generated ---
113
- if (modelsToGenerate.size > 0) {
114
- console.log(chalk.gray(' -> Adding Mongoose to dependencies...'));
115
-
116
- const packageJsonPath = path.join(projectDir, 'package.json');
117
- const packageJson = await fs.readJson(packageJsonPath);
118
- packageJson.dependencies = packageJson.dependencies || {};
119
- packageJson.dependencies['mongoose'] = '^7.5.0';
120
-
121
- await fs.writeJson(packageJsonPath, packageJson, { spaces: 2 });
122
-
123
- console.log(chalk.magenta(' -> Installing new dependencies (mongoose)...'));
124
- await execa('npm', ['install'], { cwd: projectDir });
125
- }
126
-
127
- // --- Step 9: Generate README ---
115
+ // --- Step 8: Generate README ---
128
116
  await renderAndWrite(
129
117
  getTemplatePath('node-ts-express/partials/README.md.ejs'),
130
118
  path.join(projectDir, 'README.md'),
131
119
  { projectName }
132
120
  );
133
121
 
134
- console.log(chalk.green('βœ… Project generation completed successfully!'));
135
122
  } catch (error) {
136
- console.error(chalk.red('❌ Error generating Node project:'), error);
137
- throw error; // Pass to main CLI handler
123
+ // Re-throw the error so it can be caught by the main CLI handler in index.js
124
+ // This allows for centralized error message display and cleanup.
125
+ throw error;
138
126
  }
139
127
  }
140
128
 
141
- module.exports = { generateNodeProject };
129
+ module.exports = { generateNodeProject };