create-prod-backend 1.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/LICENSE +7 -0
- package/README.md +12 -0
- package/index.js +295 -0
- package/package.json +22 -0
package/LICENSE
ADDED
package/README.md
ADDED
package/index.js
ADDED
|
@@ -0,0 +1,295 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
import inquirer from "inquirer";
|
|
4
|
+
import { execSync } from "child_process";
|
|
5
|
+
import fs from "fs";
|
|
6
|
+
import path from "path";
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
// answer object will have projectName, useMongo, ENV, dependencies, npmi
|
|
10
|
+
// to access these values we can use answer.projectName, answer.useMongo, answer.ENV, answer.dependencies, answer.npmi
|
|
11
|
+
|
|
12
|
+
// through message we are taking input from terminal and name is for variable name and type is for type of input like confirm, checkbox etc and validate is for validation of input
|
|
13
|
+
try {
|
|
14
|
+
const answer = await inquirer.prompt([
|
|
15
|
+
{
|
|
16
|
+
name: "projectName",
|
|
17
|
+
message: "Enter the Project (Folder) Name:",
|
|
18
|
+
validate: (input) => {
|
|
19
|
+
if (!input) return "Please enter a valid project name";
|
|
20
|
+
if (fs.existsSync(path.join(process.cwd(), input)))
|
|
21
|
+
return "Folder already exists";
|
|
22
|
+
return true;
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
{
|
|
26
|
+
type: "confirm",
|
|
27
|
+
name: "useMongo",
|
|
28
|
+
message: "Do you want MongoDB?",
|
|
29
|
+
},
|
|
30
|
+
{
|
|
31
|
+
type: "confirm",
|
|
32
|
+
name: "ENV",
|
|
33
|
+
message: "Do you want .env?",
|
|
34
|
+
},
|
|
35
|
+
{
|
|
36
|
+
type: "checkbox",
|
|
37
|
+
name: "dependencies",
|
|
38
|
+
message: "Select dependencies to install:",
|
|
39
|
+
choices: [
|
|
40
|
+
"express",
|
|
41
|
+
"nodemon",
|
|
42
|
+
"cors",
|
|
43
|
+
"bcryptjs",
|
|
44
|
+
"dotenv",
|
|
45
|
+
"jsonwebtoken",
|
|
46
|
+
"cookie-parser",
|
|
47
|
+
"cloudinary",
|
|
48
|
+
"multer",
|
|
49
|
+
],
|
|
50
|
+
},
|
|
51
|
+
{
|
|
52
|
+
type: "confirm",
|
|
53
|
+
name: "npmi",
|
|
54
|
+
message: "Do you want to install dependencies?",
|
|
55
|
+
},
|
|
56
|
+
]);
|
|
57
|
+
|
|
58
|
+
const projectPath = path.join(process.cwd(), answer.projectName);
|
|
59
|
+
|
|
60
|
+
// Create root folder
|
|
61
|
+
fs.mkdirSync(projectPath, { recursive: true });
|
|
62
|
+
|
|
63
|
+
// Folder structure
|
|
64
|
+
const folders = [
|
|
65
|
+
"controllers",
|
|
66
|
+
"routes",
|
|
67
|
+
"db",
|
|
68
|
+
"middlewares",
|
|
69
|
+
"models",
|
|
70
|
+
"utils",
|
|
71
|
+
"public",
|
|
72
|
+
];
|
|
73
|
+
|
|
74
|
+
folders.forEach((folder) => {
|
|
75
|
+
fs.mkdirSync(path.join(projectPath, folder), { recursive: true });
|
|
76
|
+
});
|
|
77
|
+
|
|
78
|
+
// Initialize npm
|
|
79
|
+
execSync("npm init -y", { cwd: projectPath, stdio: "inherit" });
|
|
80
|
+
|
|
81
|
+
// Fix package.json
|
|
82
|
+
const pkgPath = path.join(projectPath, "package.json");
|
|
83
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
84
|
+
|
|
85
|
+
pkg.type = "module";
|
|
86
|
+
pkg.scripts = {
|
|
87
|
+
start: "node index.js",
|
|
88
|
+
dev: "nodemon index.js",
|
|
89
|
+
};
|
|
90
|
+
|
|
91
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
92
|
+
|
|
93
|
+
// ---------------- UTILS ----------------
|
|
94
|
+
fs.writeFileSync(
|
|
95
|
+
path.join(projectPath, "utils", "ApiError.js"),
|
|
96
|
+
`
|
|
97
|
+
class ApiError extends Error {
|
|
98
|
+
constructor(
|
|
99
|
+
statusCode,
|
|
100
|
+
message = "Something went wrong",
|
|
101
|
+
errors = [],
|
|
102
|
+
stack = ""
|
|
103
|
+
) {
|
|
104
|
+
super(message);
|
|
105
|
+
this.statusCode = statusCode;
|
|
106
|
+
this.data = null;
|
|
107
|
+
this.message = message;
|
|
108
|
+
this.success = false;
|
|
109
|
+
this.errors = errors;
|
|
110
|
+
|
|
111
|
+
if (stack) {
|
|
112
|
+
this.stack = stack;
|
|
113
|
+
} else {
|
|
114
|
+
Error.captureStackTrace(this, this.constructor);
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
export default ApiError;
|
|
120
|
+
`
|
|
121
|
+
);
|
|
122
|
+
|
|
123
|
+
fs.writeFileSync(
|
|
124
|
+
path.join(projectPath, "utils", "ApiResponse.js"),
|
|
125
|
+
`class ApiResponse {
|
|
126
|
+
constructor(statusCode, data, message = "Success") {
|
|
127
|
+
this.statusCode = statusCode;
|
|
128
|
+
this.data = data;
|
|
129
|
+
this.message = message;
|
|
130
|
+
this.success = statusCode < 400;
|
|
131
|
+
}
|
|
132
|
+
}
|
|
133
|
+
// basically statusCode ka knowledge hona chiya aap ke pass
|
|
134
|
+
// Informational responses (100 – 199)
|
|
135
|
+
// Successful responses (200 – 299)
|
|
136
|
+
// Redirection messages (300 – 399)
|
|
137
|
+
// Client error responses (400 – 499)
|
|
138
|
+
// Server error responses (500 – 599)
|
|
139
|
+
|
|
140
|
+
export { ApiResponse };
|
|
141
|
+
`
|
|
142
|
+
);
|
|
143
|
+
|
|
144
|
+
fs.writeFileSync(
|
|
145
|
+
path.join(projectPath, "utils", "asyncHandler.js"),
|
|
146
|
+
`const asyncHandler = (requestHandler) => {
|
|
147
|
+
return (req, res, next) => {
|
|
148
|
+
Promise.resolve(requestHandler(req, res, next)).catch((error) =>
|
|
149
|
+
next(error)
|
|
150
|
+
);
|
|
151
|
+
};
|
|
152
|
+
};
|
|
153
|
+
|
|
154
|
+
export default asyncHandler;`
|
|
155
|
+
);
|
|
156
|
+
|
|
157
|
+
// ---------------- CORE FILES ----------------
|
|
158
|
+
const indexContent = `
|
|
159
|
+
import { app } from "./app.js";
|
|
160
|
+
${answer.useMongo ? `import connectDB from "./db/connect.js";` : ""}
|
|
161
|
+
${answer.ENV ? `import dotenv from "dotenv"; \n dotenv.config();` : ""}
|
|
162
|
+
|
|
163
|
+
const startServer = async () => {
|
|
164
|
+
try {
|
|
165
|
+
${answer.useMongo ? `await connectDB();` : ""}
|
|
166
|
+
app.on('error', (error) => {
|
|
167
|
+
console.log('app is facing error while connecting with db')
|
|
168
|
+
throw error
|
|
169
|
+
})
|
|
170
|
+
app.listen(process.env.PORT || 3000, () => {
|
|
171
|
+
console.log("Server running on port", process.env.PORT || 3000);
|
|
172
|
+
});
|
|
173
|
+
|
|
174
|
+
} catch (error) {
|
|
175
|
+
console.error("Server failed to start", error);
|
|
176
|
+
}
|
|
177
|
+
};
|
|
178
|
+
|
|
179
|
+
startServer();
|
|
180
|
+
`;
|
|
181
|
+
|
|
182
|
+
fs.writeFileSync(path.join(projectPath, "index.js"), indexContent);
|
|
183
|
+
|
|
184
|
+
fs.writeFileSync(
|
|
185
|
+
path.join(projectPath, "app.js"),
|
|
186
|
+
`import express from "express";
|
|
187
|
+
${answer.dependencies.includes("cors") ? `import cors from "cors";` : ""}
|
|
188
|
+
${answer.dependencies.includes("cookie-parser") ? `import cookieParser from "cookie-parser";` : ""}
|
|
189
|
+
|
|
190
|
+
const app = express();
|
|
191
|
+
|
|
192
|
+
app.use(express.json());
|
|
193
|
+
app.use(express.urlencoded({ extended: true }));
|
|
194
|
+
app.use(express.static("public"));
|
|
195
|
+
|
|
196
|
+
${answer.dependencies.includes("cors") ? `
|
|
197
|
+
app.use(cors({
|
|
198
|
+
origin: process.env.CORS_ORIGIN || "*",
|
|
199
|
+
credentials: true
|
|
200
|
+
}));
|
|
201
|
+
` : ""}
|
|
202
|
+
|
|
203
|
+
${answer.dependencies.includes("cookie-parser") ? `app.use(cookieParser());` : ""}
|
|
204
|
+
|
|
205
|
+
// routes here
|
|
206
|
+
|
|
207
|
+
export { app };`
|
|
208
|
+
);
|
|
209
|
+
|
|
210
|
+
fs.writeFileSync(
|
|
211
|
+
path.join(projectPath, "constants.js"),
|
|
212
|
+
`export const DB_NAME = "your_db_name";`
|
|
213
|
+
);
|
|
214
|
+
|
|
215
|
+
// ---------------- MONGODB ----------------
|
|
216
|
+
let deps = [...answer.dependencies];
|
|
217
|
+
|
|
218
|
+
if (answer.useMongo) {
|
|
219
|
+
deps.push("mongoose");
|
|
220
|
+
|
|
221
|
+
fs.writeFileSync(
|
|
222
|
+
path.join(projectPath, "db", "connect.js"),
|
|
223
|
+
`import mongoose from "mongoose";
|
|
224
|
+
|
|
225
|
+
const connectDB = async () => {
|
|
226
|
+
try {
|
|
227
|
+
const conn = await mongoose.connect(process.env.MONGO_URI);
|
|
228
|
+
console.log("MongoDB connected:", conn.connection.host);
|
|
229
|
+
} catch (error) {
|
|
230
|
+
console.error("MongoDB connection FAILED", error);
|
|
231
|
+
process.exit(1);
|
|
232
|
+
}
|
|
233
|
+
};
|
|
234
|
+
|
|
235
|
+
export default connectDB;`
|
|
236
|
+
);
|
|
237
|
+
}
|
|
238
|
+
|
|
239
|
+
// ---------------- ENV ----------------
|
|
240
|
+
if (answer.ENV) {
|
|
241
|
+
fs.writeFileSync(
|
|
242
|
+
path.join(projectPath, ".env"),
|
|
243
|
+
`PORT=3000
|
|
244
|
+
MONGO_URI=your_mongodb_uri
|
|
245
|
+
|
|
246
|
+
ACCESS_TOKEN_SECRET=your_access_token
|
|
247
|
+
ACCESS_TOKEN_EXPIRY=2d
|
|
248
|
+
|
|
249
|
+
REFRESH_TOKEN_SECRET=your_refresh_token
|
|
250
|
+
REFRESH_TOKEN_EXPIRY=20d
|
|
251
|
+
|
|
252
|
+
CORS_ORIGIN=*`
|
|
253
|
+
);
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
// ---------------- GITIGNORE ----------------
|
|
257
|
+
fs.writeFileSync(
|
|
258
|
+
path.join(projectPath, ".gitignore"),
|
|
259
|
+
`node_modules/
|
|
260
|
+
.env
|
|
261
|
+
dist/
|
|
262
|
+
coverage/
|
|
263
|
+
.DS_Store`
|
|
264
|
+
);
|
|
265
|
+
|
|
266
|
+
// ---------------- INSTALL DEPENDENCIES ----------------
|
|
267
|
+
const devDeps = [];
|
|
268
|
+
const normalDeps = [];
|
|
269
|
+
|
|
270
|
+
deps.forEach((dep) => {
|
|
271
|
+
if (dep === "nodemon") devDeps.push(dep);
|
|
272
|
+
else normalDeps.push(dep);
|
|
273
|
+
});
|
|
274
|
+
|
|
275
|
+
if (answer.npmi) {
|
|
276
|
+
if (normalDeps.length) {
|
|
277
|
+
execSync(`npm i ${normalDeps.join(" ")}`, {
|
|
278
|
+
cwd: projectPath,
|
|
279
|
+
stdio: "inherit",
|
|
280
|
+
});
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
if (devDeps.length) {
|
|
284
|
+
execSync(`npm i -D ${devDeps.join(" ")}`, {
|
|
285
|
+
cwd: projectPath,
|
|
286
|
+
stdio: "inherit",
|
|
287
|
+
});
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
console.log(`\n${answer.projectName} project created successfully!\n`);
|
|
292
|
+
} catch (error) {
|
|
293
|
+
console.error("Error:", error.message);
|
|
294
|
+
process.exit(1);
|
|
295
|
+
}
|
package/package.json
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "create-prod-backend",
|
|
3
|
+
"version": "1.0.0",
|
|
4
|
+
"description": "A cli tool to generate a production-ready backend boilerplate with Express.js, MongoDB, and essential features.",
|
|
5
|
+
"main": "index.js",
|
|
6
|
+
"scripts": {
|
|
7
|
+
"test": "echo \"Error: no test specified\" && exit 1",
|
|
8
|
+
"build": "tsc"
|
|
9
|
+
},
|
|
10
|
+
"keywords": [
|
|
11
|
+
"cli",
|
|
12
|
+
"backend",
|
|
13
|
+
"production",
|
|
14
|
+
"generator"
|
|
15
|
+
],
|
|
16
|
+
"author": "codeurge123",
|
|
17
|
+
"license": "ISC",
|
|
18
|
+
"type": "module",
|
|
19
|
+
"dependencies": {
|
|
20
|
+
"inquirer": "^13.3.2"
|
|
21
|
+
}
|
|
22
|
+
}
|