create-backlist 2.0.1 → 4.0.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/bin/index.js CHANGED
@@ -34,15 +34,32 @@ async function main() {
34
34
  ],
35
35
  },
36
36
  {
37
- type: 'input',
38
- name: 'srcPath',
39
- message: 'Enter the path to your frontend `src` directory:',
40
- default: 'src',
37
+ type: 'input',
38
+ name: 'srcPath',
39
+ message: 'Enter the path to your frontend `src` directory:',
40
+ default: 'src',
41
+ },
42
+ {
43
+ type: 'confirm',
44
+ name: 'addAuth',
45
+ message: 'Do you want to add basic JWT authentication? (generates a User model, login/register routes)',
46
+ default: true,
47
+ when: (answers) => answers.stack === 'node-ts-express'
48
+ },
49
+ // --- NEW QUESTION FOR V4.0 ---
50
+ {
51
+ type: 'confirm',
52
+ name: 'addSeeder',
53
+ message: 'Do you want to add a database seeder with sample user data?',
54
+ default: true,
55
+ // Only ask this if Node.js is selected AND authentication is being added
56
+ when: (answers) => answers.stack === 'node-ts-express' && answers.addAuth
41
57
  }
42
58
  ]);
43
59
 
60
+ // Pass all answers to the options object
44
61
  const options = {
45
- ...answers,
62
+ ...answers,
46
63
  projectDir: path.resolve(process.cwd(), answers.projectName),
47
64
  frontendSrcDir: path.resolve(process.cwd(), answers.srcPath),
48
65
  };
@@ -53,7 +70,7 @@ async function main() {
53
70
  // --- Dispatcher Logic ---
54
71
  switch (options.stack) {
55
72
  case 'node-ts-express':
56
- await generateNodeProject(options);
73
+ await generateNodeProject(options); // Pass the entire options object
57
74
  break;
58
75
 
59
76
  case 'dotnet-webapi':
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "create-backlist",
3
- "version": "2.0.1",
3
+ "version": "4.0.0",
4
4
  "description": "An advanced, multi-language backend generator based on frontend analysis.",
5
5
  "type": "commonjs",
6
6
  "bin": {
@@ -6,7 +6,8 @@ const { analyzeFrontend } = require('../analyzer');
6
6
  const { renderAndWrite, getTemplatePath } = require('./template');
7
7
 
8
8
  async function generateNodeProject(options) {
9
- const { projectDir, projectName, frontendSrcDir } = options;
9
+ // v4.0: Destructure the new 'addSeeder' option
10
+ const { projectDir, projectName, frontendSrcDir, addAuth, addSeeder } = options;
10
11
 
11
12
  try {
12
13
  // --- Step 1: Analyze Frontend to get Endpoints and Schema Info ---
@@ -21,107 +22,122 @@ async function generateNodeProject(options) {
21
22
  // --- Step 2: Identify which Database Models to Generate ---
22
23
  const modelsToGenerate = new Map();
23
24
  endpoints.forEach(ep => {
24
- // If an endpoint has schemaFields and a valid controllerName, add it to our map.
25
25
  if (ep.schemaFields && ep.controllerName !== 'Default' && !modelsToGenerate.has(ep.controllerName)) {
26
26
  modelsToGenerate.set(ep.controllerName, ep.schemaFields);
27
27
  }
28
28
  });
29
29
 
30
+ if (addAuth && !modelsToGenerate.has('User')) {
31
+ console.log(chalk.yellow(' -> Authentication requires a "User" model. Creating a default one.'));
32
+ modelsToGenerate.set('User', { name: 'String', email: 'String', password: 'String' });
33
+ }
34
+
30
35
  // --- Step 3: Scaffold Base Project Structure & Files ---
31
36
  console.log(chalk.blue(' -> Scaffolding Node.js (Express + TS) project...'));
32
-
33
- // Create the main source directory
34
37
  const destSrcDir = path.join(projectDir, 'src');
35
38
  await fs.ensureDir(destSrcDir);
36
-
37
- // Copy static base files
38
39
  await fs.copy(getTemplatePath('node-ts-express/base/server.ts'), path.join(destSrcDir, 'server.ts'));
39
40
  await fs.copy(getTemplatePath('node-ts-express/base/tsconfig.json'), path.join(projectDir, 'tsconfig.json'));
40
41
 
41
- // --- Step 4: Generate Dynamic Files (package.json, Models, Controllers) ---
42
-
43
- // Prepare package.json content (in memory)
42
+ // --- Step 4: Prepare and Write package.json with all conditional dependencies ---
44
43
  const packageJsonContent = JSON.parse(
45
44
  await ejs.renderFile(getTemplatePath('node-ts-express/partials/package.json.ejs'), { projectName })
46
45
  );
47
46
 
48
- // Conditionally add Mongoose if we are generating models
49
- if (modelsToGenerate.size > 0) {
50
- console.log(chalk.gray(' -> Preparing to add Mongoose to dependencies...'));
51
- packageJsonContent.dependencies['mongoose'] = '^7.5.0'; // Use a recent, stable version
47
+ if (modelsToGenerate.size > 0 || addAuth) {
48
+ packageJsonContent.dependencies['mongoose'] = '^7.5.0';
49
+ }
50
+ if (addAuth) {
51
+ packageJsonContent.dependencies['jsonwebtoken'] = '^9.0.2';
52
+ packageJsonContent.dependencies['bcryptjs'] = '^2.4.3';
53
+ packageJsonContent.devDependencies['@types/jsonwebtoken'] = '^9.0.2';
54
+ packageJsonContent.devDependencies['@types/bcryptjs'] = '^2.4.2';
55
+ }
56
+ // v4.0: Add seeder dependencies and scripts
57
+ if (addSeeder) {
58
+ packageJsonContent.devDependencies['@faker-js/faker'] = '^8.2.0';
59
+ // We also need chalk for the seeder script's console logs
60
+ packageJsonContent.dependencies['chalk'] = '^4.1.2';
61
+ packageJsonContent.scripts['seed'] = 'ts-node scripts/seeder.ts';
62
+ packageJsonContent.scripts['destroy'] = 'ts-node scripts/seeder.ts -d';
52
63
  }
53
-
54
- // Write the final package.json to the disk
55
64
  await fs.writeJson(path.join(projectDir, 'package.json'), packageJsonContent, { spaces: 2 });
56
65
 
57
- // Generate Model and Controller files if any were found
66
+ // --- Step 5 & 6: Generate Models, Controllers, and Auth boilerplate ---
58
67
  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'));
68
+ console.log(chalk.blue(' -> Generating database models and controllers...'));
69
+ await fs.ensureDir(path.join(destSrcDir, 'models'));
70
+ await fs.ensureDir(path.join(destSrcDir, 'controllers'));
71
+ for (let [modelName, schema] of modelsToGenerate.entries()) {
72
+ if (addAuth && modelName === 'User') {
73
+ schema = { name: 'String', email: 'String', password: 'String', ...schema };
74
+ }
75
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/Model.ts.ejs'), path.join(destSrcDir, 'models', `${modelName}.model.ts`), { modelName, schema });
76
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/Controller.ts.ejs'), path.join(destSrcDir, 'controllers', `${modelName}.controller.ts`), { modelName });
77
+ }
78
+ }
79
+ if (addAuth) {
80
+ console.log(chalk.blue(' -> Generating authentication boilerplate...'));
81
+ await fs.ensureDir(path.join(destSrcDir, 'routes'));
82
+ await fs.ensureDir(path.join(destSrcDir, 'middleware'));
83
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/Auth.controller.ts.ejs'), path.join(destSrcDir, 'controllers', 'Auth.controller.ts'), {});
84
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/Auth.routes.ts.ejs'), path.join(destSrcDir, 'routes', 'Auth.routes.ts'), {});
85
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/Auth.middleware.ts.ejs'), path.join(destSrcDir, 'middleware', 'Auth.middleware.ts'), {});
62
86
 
63
- for (const [modelName, schema] of modelsToGenerate.entries()) {
64
- // Generate Model File (e.g., models/User.model.ts)
65
- await renderAndWrite(
66
- getTemplatePath('node-ts-express/partials/Model.ts.ejs'),
67
- path.join(destSrcDir, 'models', `${modelName}.model.ts`),
68
- { modelName, schema }
69
- );
70
- // Generate Controller File (e.g., controllers/User.controller.ts)
71
- await renderAndWrite(
72
- getTemplatePath('node-ts-express/partials/Controller.ts.ejs'),
73
- path.join(destSrcDir, 'controllers', `${modelName}.controller.ts`),
74
- { modelName }
75
- );
76
- }
87
+ const userModelPath = path.join(destSrcDir, 'models', 'User.model.ts');
88
+ if (await fs.pathExists(userModelPath)) {
89
+ let userModelContent = await fs.readFile(userModelPath, 'utf-8');
90
+ if (!userModelContent.includes('bcryptjs')) {
91
+ userModelContent = userModelContent.replace(`import mongoose, { Schema, Document } from 'mongoose';`, `import mongoose, { Schema, Document } from 'mongoose';\nimport bcrypt from 'bcryptjs';`);
92
+ const preSaveHook = `\n// Hash password before saving\nUserSchema.pre('save', async function(next) {\n if (!this.isModified('password')) {\n return next();\n }\n const salt = await bcrypt.genSalt(10);\n this.password = await bcrypt.hash(this.password, salt);\n next();\n});\n`;
93
+ userModelContent = userModelContent.replace(`// Create and export the Model`, `${preSaveHook}\n// Create and export the Model`);
94
+ await fs.writeFile(userModelPath, userModelContent);
95
+ }
96
+ }
77
97
  }
78
98
 
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');
99
+ // --- Step 7 (v4.0): Generate Seeder Script ---
100
+ if (addSeeder) {
101
+ console.log(chalk.blue(' -> Generating database seeder script...'));
102
+ await fs.ensureDir(path.join(projectDir, 'scripts'));
103
+ await renderAndWrite(
104
+ getTemplatePath('node-ts-express/partials/Seeder.ts.ejs'),
105
+ path.join(projectDir, 'scripts', 'seeder.ts'),
106
+ { projectName }
107
+ );
108
+ }
109
+
110
+ // --- Step 8: Generate the Main Route File ---
111
+ console.log(chalk.gray(' -> Generating dynamic API routes...'));
112
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/routes.ts.ejs'), path.join(destSrcDir, 'routes.ts'), { endpoints, addAuth });
90
113
 
114
+ // --- Step 9: Inject Logic into Main Server File ---
115
+ let serverFileContent = await fs.readFile(path.join(destSrcDir, 'server.ts'), 'utf-8');
91
116
  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
- `;
117
+ if (modelsToGenerate.size > 0 || addAuth) {
118
+ dbConnectionCode = `\n// --- Database Connection ---\nimport mongoose from 'mongoose';\nconst MONGO_URI = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/${projectName}';\nmongoose.connect(MONGO_URI)\n .then(() => console.log('MongoDB Connected...'))\n .catch(err => console.error('MongoDB Connection Error:', err));\n// -------------------------\n`;
119
+ }
120
+ let authRoutesInjector = '';
121
+ if (addAuth) {
122
+ authRoutesInjector = `import authRoutes from './routes/Auth.routes';\napp.use('/api/auth', authRoutes);\n\n`;
102
123
  }
103
-
104
- // Inject DB connection code after dotenv.config() and route loader
105
124
  serverFileContent = serverFileContent
106
- .replace("dotenv.config();", `dotenv.config();\n${dbConnectionCode}`)
107
- .replace('// INJECT:ROUTES', `import apiRoutes from './routes';\napp.use(apiRoutes);`);
108
-
109
- await fs.writeFile(serverDestPath, serverFileContent);
125
+ .replace("dotenv.config();", `dotenv.config();${dbConnectionCode}`)
126
+ .replace('// INJECT:ROUTES', `${authRoutesInjector}import apiRoutes from './routes';\napp.use('/api', apiRoutes);`);
127
+ await fs.writeFile(path.join(destSrcDir, 'server.ts'), serverFileContent);
110
128
 
111
- // --- Step 7: Install All Dependencies at Once ---
112
- console.log(chalk.magenta(' -> Installing dependencies (npm install)... This might take a moment.'));
129
+ // --- Step 10: Install All Dependencies ---
130
+ console.log(chalk.magenta(' -> Installing all dependencies... This might take a moment.'));
113
131
  await execa('npm', ['install'], { cwd: projectDir });
114
132
 
115
- // --- Step 8: Generate README ---
116
- await renderAndWrite(
117
- getTemplatePath('node-ts-express/partials/README.md.ejs'),
118
- path.join(projectDir, 'README.md'),
119
- { projectName }
120
- );
133
+ // --- Step 11: Generate Final Files (README, .env.example) ---
134
+ await renderAndWrite(getTemplatePath('node-ts-express/partials/README.md.ejs'), path.join(projectDir, 'README.md'), { projectName });
135
+ if (addAuth) {
136
+ const envExampleContent = `PORT=8000\nMONGO_URI=mongodb://127.0.0.1:27017/${projectName}\nJWT_SECRET=your_super_secret_jwt_key_123`;
137
+ await fs.writeFile(path.join(projectDir, '.env.example'), envExampleContent);
138
+ }
121
139
 
122
140
  } catch (error) {
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
141
  throw error;
126
142
  }
127
143
  }
@@ -0,0 +1,89 @@
1
+ // Auto-generated by create-backlist v3.0 on <%= new Date().toISOString() %>
2
+ import { Request, Response } from 'express';
3
+ import bcrypt from 'bcryptjs';
4
+ import jwt from 'jsonwebtoken';
5
+ import User, { IUser } from '../models/User.model'; // We assume the model is named 'User'
6
+
7
+ // @desc Register a new user
8
+ export const registerUser = async (req: Request, res: Response) => {
9
+ const { name, email, password } = req.body;
10
+
11
+ try {
12
+ // Check if user already exists
13
+ let user = await User.findOne({ email });
14
+ if (user) {
15
+ return res.status(400).json({ message: 'User already exists' });
16
+ }
17
+
18
+ // Create a new user instance
19
+ user = new User({
20
+ name,
21
+ email,
22
+ password, // Password will be hashed by the pre-save hook in the model
23
+ });
24
+
25
+ // Save the user to the database
26
+ await user.save();
27
+
28
+ // Create JWT Payload
29
+ const payload = {
30
+ user: {
31
+ id: user.id,
32
+ },
33
+ };
34
+
35
+ // Sign the token
36
+ jwt.sign(
37
+ payload,
38
+ process.env.JWT_SECRET as string,
39
+ { expiresIn: '5h' }, // Token expires in 5 hours
40
+ (err, token) => {
41
+ if (err) throw err;
42
+ res.status(201).json({ token });
43
+ }
44
+ );
45
+ } catch (error) {
46
+ console.error(error);
47
+ res.status(500).send('Server Error');
48
+ }
49
+ };
50
+
51
+ // @desc Authenticate user & get token (Login)
52
+ export const loginUser = async (req: Request, res: Response) => {
53
+ const { email, password } = req.body;
54
+
55
+ try {
56
+ // Check if user exists
57
+ const user = await User.findOne({ email });
58
+ if (!user) {
59
+ return res.status(400).json({ message: 'Invalid Credentials' });
60
+ }
61
+
62
+ // Compare entered password with stored hashed password
63
+ const isMatch = await bcrypt.compare(password, user.password);
64
+ if (!isMatch) {
65
+ return res.status(400).json({ message: 'Invalid Credentials' });
66
+ }
67
+
68
+ // Create JWT Payload
69
+ const payload = {
70
+ user: {
71
+ id: user.id,
72
+ },
73
+ };
74
+
75
+ // Sign the token
76
+ jwt.sign(
77
+ payload,
78
+ process.env.JWT_SECRET as string,
79
+ { expiresIn: '5h' },
80
+ (err, token) => {
81
+ if (err) throw err;
82
+ res.json({ token });
83
+ }
84
+ );
85
+ } catch (error) {
86
+ console.error(error);
87
+ res.status(500).send('Server Error');
88
+ }
89
+ };
@@ -0,0 +1,27 @@
1
+ // Auto-generated by create-backlist v3.0 on <%= new Date().toISOString() %>
2
+ import { Request, Response, NextFunction } from 'express';
3
+ import jwt from 'jsonwebtoken';
4
+
5
+ // Extend the default Request interface to include our 'user' property
6
+ interface AuthRequest extends Request {
7
+ user?: any;
8
+ }
9
+
10
+ export const protect = (req: AuthRequest, res: Response, next: NextFunction) => {
11
+ // Get token from header
12
+ const token = req.header('x-auth-token');
13
+
14
+ // Check if not token
15
+ if (!token) {
16
+ return res.status(401).json({ message: 'No token, authorization denied' });
17
+ }
18
+
19
+ // Verify token
20
+ try {
21
+ const decoded = jwt.verify(token, process.env.JWT_SECRET as string);
22
+ req.user = decoded.user;
23
+ next();
24
+ } catch (err) {
25
+ res.status(401).json({ message: 'Token is not valid' });
26
+ }
27
+ };
@@ -0,0 +1,15 @@
1
+ // Auto-generated by create-backlist v3.0 on <%= new Date().toISOString() %>
2
+ import { Router } from 'express';
3
+ import { registerUser, loginUser } from '../controllers/Auth.controller';
4
+
5
+ const router = Router();
6
+
7
+ // @route POST /api/auth/register
8
+ // @desc Register a new user
9
+ router.post('/register', registerUser);
10
+
11
+ // @route POST /api/auth/login
12
+ // @desc Authenticate user and get token
13
+ router.post('/login', loginUser);
14
+
15
+ export default router;
@@ -9,6 +9,9 @@ export const create<%= modelName %> = async (req: Request, res: Response) => {
9
9
  await newDoc.save();
10
10
  res.status(201).json(newDoc);
11
11
  } catch (error) {
12
+ if (error.name === 'ValidationError') {
13
+ return res.status(400).json({ message: 'Validation Error', errors: error.errors });
14
+ }
12
15
  res.status(500).json({ message: 'Error creating document', error });
13
16
  }
14
17
  };
@@ -41,6 +44,9 @@ export const update<%= modelName %>ById = async (req: Request, res: Response) =>
41
44
  if (!doc) return res.status(404).json({ message: 'Document not found' });
42
45
  res.status(200).json(doc);
43
46
  } catch (error) {
47
+ if (error.name === 'ValidationError') {
48
+ return res.status(400).json({ message: 'Validation Error', errors: error.errors });
49
+ }
44
50
  res.status(500).json({ message: 'Error updating document', error });
45
51
  }
46
52
  };
@@ -50,6 +56,7 @@ export const delete<%= modelName %>ById = async (req: Request, res: Response) =>
50
56
  try {
51
57
  const doc = await <%= modelName %>.findByIdAndDelete(req.params.id);
52
58
  if (!doc) return res.status(404).json({ message: 'Document not found' });
59
+ // For DELETE, it's common to return a success message or just a 204 No Content status.
53
60
  res.status(200).json({ message: 'Document deleted successfully' });
54
61
  } catch (error) {
55
62
  res.status(500).json({ message: 'Error deleting document', error });
@@ -0,0 +1,83 @@
1
+ // Auto-generated by create-backlist v4.0 on <%= new Date().toISOString() %>
2
+ import mongoose from 'mongoose';
3
+ import dotenv from 'dotenv';
4
+ import { faker } from '@faker-js/faker';
5
+ import chalk from 'chalk'; // For colorful console logs
6
+
7
+ // Load env vars
8
+ dotenv.config();
9
+
10
+ // We assume a User model exists for seeding.
11
+ // The path is relative to the generated 'backend' project root.
12
+ import User from '../src/models/User.model';
13
+
14
+ // --- Connect to DB ---
15
+ const connectDB = async () => {
16
+ try {
17
+ const MONGO_URI = process.env.MONGO_URI || 'mongodb://127.0.0.1:27017/<%= projectName %>';
18
+ if (!MONGO_URI) {
19
+ throw new Error('MONGO_URI is not defined in your .env file');
20
+ }
21
+ await mongoose.connect(MONGO_URI);
22
+ console.log(chalk.green('MongoDB Connected for Seeder...'));
23
+ } catch (err) {
24
+ console.error(chalk.red(`Seeder DB Connection Error: ${err.message}`));
25
+ process.exit(1);
26
+ }
27
+ };
28
+
29
+ // --- Import Data ---
30
+ const importData = async () => {
31
+ try {
32
+ // Clear existing data
33
+ await User.deleteMany();
34
+
35
+ const sampleUsers = [];
36
+ const userCount = 10; // Number of sample users to create
37
+
38
+ for (let i = 0; i < userCount; i++) {
39
+ sampleUsers.push({
40
+ name: faker.person.fullName(),
41
+ email: faker.internet.email().toLowerCase(),
42
+ password: 'password123', // All sample users will have the same password for easy testing
43
+ });
44
+ }
45
+
46
+ await User.insertMany(sampleUsers);
47
+
48
+ console.log(chalk.green.bold('✅ Data Imported Successfully!'));
49
+ process.exit();
50
+ } catch (error) {
51
+ console.error(chalk.red(`Error with data import: ${error.message}`));
52
+ process.exit(1);
53
+ }
54
+ };
55
+
56
+ // --- Destroy Data ---
57
+ const destroyData = async () => {
58
+ try {
59
+ await User.deleteMany();
60
+ // If you have other models, you can add them here for destruction
61
+ // e.g., await Product.deleteMany();
62
+
63
+ console.log(chalk.red.bold('🔥 Data Destroyed Successfully!'));
64
+ process.exit();
65
+ } catch (error) {
66
+ console.error(chalk.red(`Error with data destruction: ${error.message}`));
67
+ process.exit(1);
68
+ }
69
+ };
70
+
71
+ // --- CLI Logic to run the seeder ---
72
+ const runSeeder = async () => {
73
+ await connectDB();
74
+
75
+ // process.argv[2] will be '-d' if the script is run with `npm run destroy`
76
+ if (process.argv[2] === '-d') {
77
+ await destroyData();
78
+ } else {
79
+ await importData();
80
+ }
81
+ };
82
+
83
+ runSeeder();
@@ -1,4 +1,4 @@
1
- // Auto-generated by create-backlist on <%= new Date().toISOString() %>
1
+ // Auto-generated by create-backlist v3.0 on <%= new Date().toISOString() %>
2
2
  import { Router, Request, Response } from 'express';
3
3
  <%# Create a unique set of controller names from the endpoints array %>
4
4
  <% const controllersToImport = new Set(endpoints.map(ep => ep.controllerName).filter(name => name !== 'Default')); %>
@@ -8,6 +8,11 @@ import { Router, Request, Response } from 'express';
8
8
  import * as <%= controller %>Controller from '../controllers/<%= controller %>.controller';
9
9
  <% } %>
10
10
 
11
+ <%# Import the protect middleware only if authentication is enabled %>
12
+ <% if (addAuth) { %>
13
+ import { protect } from '../middleware/Auth.middleware';
14
+ <% } %>
15
+
11
16
  const router = Router();
12
17
 
13
18
  <%# Loop through each endpoint found by the analyzer %>
@@ -19,41 +24,40 @@ const router = Router();
19
24
  let handlerFunction;
20
25
 
21
26
  // --- LOGIC TO MAP ENDPOINT TO A CRUD CONTROLLER FUNCTION ---
22
- // This logic assumes a standard RESTful API structure.
23
-
24
27
  if (controllerName !== 'Default') {
25
28
  if (endpoint.method === 'POST' && !expressPath.includes(':')) {
26
- // e.g., POST /users -> create a new user
27
29
  handlerFunction = `${controllerName}Controller.create${controllerName}`;
28
30
  } else if (endpoint.method === 'GET' && !expressPath.includes(':')) {
29
- // e.g., GET /users -> get all users
30
31
  handlerFunction = `${controllerName}Controller.getAll${controllerName}s`;
31
32
  } else if (endpoint.method === 'GET' && expressPath.includes(':')) {
32
- // e.g., GET /users/:id -> get a single user by ID
33
33
  handlerFunction = `${controllerName}Controller.get${controllerName}ById`;
34
34
  } else if (endpoint.method === 'PUT' && expressPath.includes(':')) {
35
- // e.g., PUT /users/:id -> update a user by ID
36
35
  handlerFunction = `${controllerName}Controller.update${controllerName}ById`;
37
36
  } else if (endpoint.method === 'DELETE' && expressPath.includes(':')) {
38
- // e.g., DELETE /users/:id -> delete a user by ID
39
37
  handlerFunction = `${controllerName}Controller.delete${controllerName}ById`;
40
38
  }
41
39
  }
42
40
 
43
- // If no specific CRUD function matches, or if it's a default/unhandled route,
44
- // create a simple placeholder function.
41
+ // If no specific CRUD function matches, create a placeholder handler.
45
42
  if (!handlerFunction) {
46
43
  handlerFunction = `(req: Request, res: Response) => {
47
- // TODO: Implement logic for this custom endpoint
48
44
  res.status(501).json({ message: 'Handler not implemented for <%= endpoint.method %> <%= expressPath %>' });
49
45
  }`;
50
46
  }
47
+
48
+ // --- V3.0 AUTH LOGIC: Decide if the route should be protected ---
49
+ // We protect all routes that modify data (POST, PUT, DELETE) if auth is enabled.
50
+ // We leave GET routes public by default. This is a common pattern.
51
+ const middleware = (addAuth && (endpoint.method === 'POST' || endpoint.method === 'PUT' || endpoint.method === 'DELETE'))
52
+ ? 'protect, '
53
+ : '';
51
54
  %>
52
55
  /**
53
56
  * Route for <%= endpoint.method.toUpperCase() %> <%= endpoint.path %>
54
57
  * Mapped to: <%- handlerFunction.includes('=>') ? 'Inline Handler' : handlerFunction %>
58
+ * Protected: <%= middleware ? 'Yes' : 'No' %>
55
59
  */
56
- router.<%= endpoint.method.toLowerCase() %>('<%- expressPath %>', <%- handlerFunction %>);
60
+ router.<%= endpoint.method.toLowerCase() %>('<%- expressPath %>', <%- middleware %><%- handlerFunction %>);
57
61
 
58
62
  <% }); %>
59
63