create-prod-backend 1.0.2 → 1.1.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.
- package/bin/index.js +5 -0
- package/package.json +4 -3
- package/src/core/createProject.js +19 -0
- package/src/index.js +20 -0
- package/src/prompts/questions.js +47 -0
- package/src/services/dependency.service.js +35 -0
- package/src/services/file.service.js +56 -0
- package/src/services/folder.service.js +24 -0
- package/src/services/package.service.js +21 -0
- package/src/templates/base/app.template.js +24 -0
- package/src/templates/base/index.template.js +25 -0
- package/src/templates/config/env.template.js +12 -0
- package/src/templates/db/mongo.template.js +15 -0
- package/src/templates/utils/utils.template.js +58 -0
package/bin/index.js
ADDED
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "create-prod-backend",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.1.2",
|
|
4
4
|
"description": "A cli tool to generate a production-ready backend boilerplate with Express.js, MongoDB, and essential features.",
|
|
5
5
|
"main": "index.js",
|
|
6
6
|
"bin": {
|
|
7
|
-
"create-prod-backend": "./index.js"
|
|
7
|
+
"create-prod-backend": "./bin/index.js"
|
|
8
8
|
},
|
|
9
9
|
"scripts": {
|
|
10
10
|
"test": "echo \"Error: no test specified\" && exit 1",
|
|
@@ -20,6 +20,7 @@
|
|
|
20
20
|
"license": "ISC",
|
|
21
21
|
"type": "module",
|
|
22
22
|
"dependencies": {
|
|
23
|
+
"chalk": "^5.6.2",
|
|
23
24
|
"inquirer": "^13.3.2"
|
|
24
25
|
}
|
|
25
|
-
}
|
|
26
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import path from "path";
|
|
2
|
+
import { createFolders } from "../services/folder.service.js";
|
|
3
|
+
import { initPackage } from "../services/package.service.js";
|
|
4
|
+
import { createFiles } from "../services/file.service.js";
|
|
5
|
+
import { installDeps } from "../services/dependency.service.js";
|
|
6
|
+
import chalk from "chalk";
|
|
7
|
+
|
|
8
|
+
export async function createProject(answer) {
|
|
9
|
+
const projectPath = path.join(process.cwd(), answer.projectName);
|
|
10
|
+
|
|
11
|
+
createFolders(projectPath);
|
|
12
|
+
initPackage(projectPath);
|
|
13
|
+
createFiles(projectPath, answer);
|
|
14
|
+
|
|
15
|
+
if (answer.npmi) {
|
|
16
|
+
console.log(chalk.blue("Installing dependencies..."));
|
|
17
|
+
installDeps(projectPath, answer);
|
|
18
|
+
}
|
|
19
|
+
}
|
package/src/index.js
ADDED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import inquirer from "inquirer";
|
|
2
|
+
import questions from "./prompts/questions.js";
|
|
3
|
+
import { createProject } from "./core/createProject.js";
|
|
4
|
+
import chalk from "chalk";
|
|
5
|
+
|
|
6
|
+
export default async function runCLI() {
|
|
7
|
+
console.log(chalk.bold.cyan("\n------------------Welcome to the CREATE-PROD-BACKEND CLI------------------\n"));
|
|
8
|
+
|
|
9
|
+
try {
|
|
10
|
+
const answer = await inquirer.prompt(questions);
|
|
11
|
+
|
|
12
|
+
await createProject(answer);
|
|
13
|
+
|
|
14
|
+
console.log(chalk.green(`\n${chalk.bold(answer.projectName)} project created successfully!\n`));
|
|
15
|
+
console.log(chalk.yellow("Happy coding! :)"));
|
|
16
|
+
} catch (error) {
|
|
17
|
+
console.error(chalk.red(("Error:", error.message)));
|
|
18
|
+
process.exit(1);
|
|
19
|
+
}
|
|
20
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
import chalk from "chalk";
|
|
4
|
+
|
|
5
|
+
export default [
|
|
6
|
+
{
|
|
7
|
+
name: "projectName",
|
|
8
|
+
message: chalk.bold.yellow("Enter the Project (Folder) Name:"),
|
|
9
|
+
validate: (input) => {
|
|
10
|
+
if (!input) return chalk.red("Please enter a valid project name");
|
|
11
|
+
if (fs.existsSync(path.join(process.cwd(), input)))
|
|
12
|
+
return chalk.red("Folder already exists");
|
|
13
|
+
return true;
|
|
14
|
+
},
|
|
15
|
+
},
|
|
16
|
+
{
|
|
17
|
+
type: "confirm",
|
|
18
|
+
name: "useMongo",
|
|
19
|
+
message: chalk.bold.yellow("Do you want MongoDB?"),
|
|
20
|
+
},
|
|
21
|
+
{
|
|
22
|
+
type: "confirm",
|
|
23
|
+
name: "ENV",
|
|
24
|
+
message: chalk.bold.yellow("Do you want .env?"),
|
|
25
|
+
},
|
|
26
|
+
{
|
|
27
|
+
type: "checkbox",
|
|
28
|
+
name: "dependencies",
|
|
29
|
+
message: chalk.bold.yellow("Select dependencies to install:"),
|
|
30
|
+
choices: [
|
|
31
|
+
"express",
|
|
32
|
+
"nodemon",
|
|
33
|
+
"cors",
|
|
34
|
+
"bcryptjs",
|
|
35
|
+
"dotenv",
|
|
36
|
+
"jsonwebtoken",
|
|
37
|
+
"cookie-parser",
|
|
38
|
+
"cloudinary",
|
|
39
|
+
"multer",
|
|
40
|
+
],
|
|
41
|
+
},
|
|
42
|
+
{
|
|
43
|
+
type: "confirm",
|
|
44
|
+
name: "npmi",
|
|
45
|
+
message: chalk.bold.yellow("Do you want to install dependencies?"),
|
|
46
|
+
},
|
|
47
|
+
];
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
|
|
3
|
+
export function installDeps(projectPath, answer) {
|
|
4
|
+
let deps = [...answer.dependencies];
|
|
5
|
+
|
|
6
|
+
if (answer.useMongo) {
|
|
7
|
+
deps.push("mongoose");
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
deps = deps.map(dep => dep.replace(/['"]/g, "").trim());
|
|
11
|
+
|
|
12
|
+
const dev = [];
|
|
13
|
+
const normal = [];
|
|
14
|
+
|
|
15
|
+
deps.forEach((dep) => {
|
|
16
|
+
if (dep === "nodemon") dev.push(dep);
|
|
17
|
+
else normal.push(dep);
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
console.log("Installing:", normal, dev); // debug
|
|
21
|
+
|
|
22
|
+
if (normal.length) {
|
|
23
|
+
execSync(`npm i ${normal.join(" ")}`, {
|
|
24
|
+
cwd: projectPath,
|
|
25
|
+
stdio: "inherit",
|
|
26
|
+
});
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
if (dev.length) {
|
|
30
|
+
execSync(`npm i -D ${dev.join(" ")}`, {
|
|
31
|
+
cwd: projectPath,
|
|
32
|
+
stdio: "inherit",
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
}
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
import { indexTemplate } from "../templates/base/index.template.js";
|
|
5
|
+
import { appTemplate } from "../templates/base/app.template.js";
|
|
6
|
+
import { mongoTemplate } from "../templates/db/mongo.template.js";
|
|
7
|
+
import { envTemplate } from "../templates/config/env.template.js";
|
|
8
|
+
import { utilsTemplates } from "../templates/utils/utils.template.js";
|
|
9
|
+
|
|
10
|
+
export function createFiles(projectPath, answer) {
|
|
11
|
+
// index.js
|
|
12
|
+
fs.writeFileSync(
|
|
13
|
+
path.join(projectPath,"src", "index.js"),
|
|
14
|
+
indexTemplate(answer)
|
|
15
|
+
);
|
|
16
|
+
|
|
17
|
+
// app.js
|
|
18
|
+
fs.writeFileSync(
|
|
19
|
+
path.join(projectPath,"src", "app.js"),
|
|
20
|
+
appTemplate(answer)
|
|
21
|
+
);
|
|
22
|
+
|
|
23
|
+
// utils
|
|
24
|
+
Object.entries(utilsTemplates).forEach(([file, content]) => {
|
|
25
|
+
fs.writeFileSync(path.join(projectPath, "src", "utils", file), content);
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
// constants
|
|
29
|
+
fs.writeFileSync(
|
|
30
|
+
path.join(projectPath, "src", "constants.js"),
|
|
31
|
+
`export const DB_NAME = "your_db_name";`
|
|
32
|
+
);
|
|
33
|
+
|
|
34
|
+
// mongo
|
|
35
|
+
if (answer.useMongo) {
|
|
36
|
+
fs.writeFileSync(
|
|
37
|
+
path.join(projectPath, "src", "db", "connect.js"),
|
|
38
|
+
mongoTemplate()
|
|
39
|
+
);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// .env
|
|
43
|
+
if (answer.ENV) {
|
|
44
|
+
fs.writeFileSync(path.join(projectPath, ".env"), envTemplate());
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
// gitignore
|
|
48
|
+
fs.writeFileSync(
|
|
49
|
+
path.join(projectPath, ".gitignore"),
|
|
50
|
+
`node_modules/
|
|
51
|
+
.env
|
|
52
|
+
dist/
|
|
53
|
+
coverage/
|
|
54
|
+
.DS_Store`
|
|
55
|
+
);
|
|
56
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
import path from "path";
|
|
3
|
+
|
|
4
|
+
export function createFolders(projectPath) {
|
|
5
|
+
fs.mkdirSync(projectPath, {
|
|
6
|
+
recursive: true
|
|
7
|
+
});
|
|
8
|
+
|
|
9
|
+
const folders = [
|
|
10
|
+
"controllers",
|
|
11
|
+
"routes",
|
|
12
|
+
"db",
|
|
13
|
+
"middlewares",
|
|
14
|
+
"models",
|
|
15
|
+
"utils",
|
|
16
|
+
"public",
|
|
17
|
+
];
|
|
18
|
+
|
|
19
|
+
folders.forEach((folder) => {
|
|
20
|
+
fs.mkdirSync(path.join(projectPath, "src", folder), {
|
|
21
|
+
recursive: true
|
|
22
|
+
});
|
|
23
|
+
});
|
|
24
|
+
}
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
import { execSync } from "child_process";
|
|
2
|
+
import fs from "fs";
|
|
3
|
+
import path from "path";
|
|
4
|
+
|
|
5
|
+
export function initPackage(projectPath) {
|
|
6
|
+
execSync("npm init -y", {
|
|
7
|
+
cwd: projectPath,
|
|
8
|
+
stdio: "inherit"
|
|
9
|
+
});
|
|
10
|
+
|
|
11
|
+
const pkgPath = path.join(projectPath, "package.json");
|
|
12
|
+
const pkg = JSON.parse(fs.readFileSync(pkgPath, "utf-8"));
|
|
13
|
+
|
|
14
|
+
pkg.type = "module";
|
|
15
|
+
pkg.scripts = {
|
|
16
|
+
start: "node index.js",
|
|
17
|
+
dev: "nodemon index.js",
|
|
18
|
+
};
|
|
19
|
+
|
|
20
|
+
fs.writeFileSync(pkgPath, JSON.stringify(pkg, null, 2));
|
|
21
|
+
}
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
export const appTemplate = (answer) => `
|
|
2
|
+
import express from "express";
|
|
3
|
+
${answer.dependencies.includes("cors") ? `import cors from "cors";` : ""}
|
|
4
|
+
${answer.dependencies.includes("cookie-parser") ? `import cookieParser from "cookie-parser";` : ""}
|
|
5
|
+
|
|
6
|
+
const app = express();
|
|
7
|
+
|
|
8
|
+
app.use(express.json());
|
|
9
|
+
app.use(express.urlencoded({ extended: true }));
|
|
10
|
+
app.use(express.static("public"));
|
|
11
|
+
|
|
12
|
+
${answer.dependencies.includes("cors") ? `
|
|
13
|
+
app.use(cors({
|
|
14
|
+
origin: process.env.CORS_ORIGIN || "*",
|
|
15
|
+
credentials: true
|
|
16
|
+
}));
|
|
17
|
+
` : ""}
|
|
18
|
+
|
|
19
|
+
${answer.dependencies.includes("cookie-parser") ? `app.use(cookieParser());` : ""}
|
|
20
|
+
|
|
21
|
+
// routes here
|
|
22
|
+
|
|
23
|
+
export { app };
|
|
24
|
+
`;
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
export const indexTemplate = (answer) => `
|
|
2
|
+
import { app } from "./app.js";
|
|
3
|
+
${answer.useMongo ? `import connectDB from "./db/connect.js";` : ""}
|
|
4
|
+
${answer.ENV ? `import dotenv from "dotenv";\ndotenv.config();` : ""}
|
|
5
|
+
|
|
6
|
+
const startServer = async () => {
|
|
7
|
+
try {
|
|
8
|
+
${answer.useMongo ? `await connectDB();` : ""}
|
|
9
|
+
|
|
10
|
+
app.on("error", (error) => {
|
|
11
|
+
console.error("App error:", error);
|
|
12
|
+
throw error;
|
|
13
|
+
});
|
|
14
|
+
|
|
15
|
+
app.listen(process.env.PORT || 3000, () => {
|
|
16
|
+
console.log("Server running on port", process.env.PORT || 3000);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
} catch (error) {
|
|
20
|
+
console.error("Server failed to start", error);
|
|
21
|
+
}
|
|
22
|
+
};
|
|
23
|
+
|
|
24
|
+
startServer();
|
|
25
|
+
`;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export const mongoTemplate = () => `
|
|
2
|
+
import mongoose from "mongoose";
|
|
3
|
+
|
|
4
|
+
const connectDB = async () => {
|
|
5
|
+
try {
|
|
6
|
+
const conn = await mongoose.connect(process.env.MONGO_URI);
|
|
7
|
+
console.log("MongoDB connected:", conn.connection.host);
|
|
8
|
+
} catch (error) {
|
|
9
|
+
console.error("MongoDB connection FAILED", error);
|
|
10
|
+
process.exit(1);
|
|
11
|
+
}
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export default connectDB;
|
|
15
|
+
`;
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
export const utilsTemplates = {
|
|
2
|
+
"ApiError.js": `
|
|
3
|
+
class ApiError extends Error {
|
|
4
|
+
constructor(
|
|
5
|
+
statusCode,
|
|
6
|
+
message = "Something went wrong",
|
|
7
|
+
errors = [],
|
|
8
|
+
stack = ""
|
|
9
|
+
) {
|
|
10
|
+
super(message);
|
|
11
|
+
this.statusCode = statusCode;
|
|
12
|
+
this.data = null;
|
|
13
|
+
this.message = message;
|
|
14
|
+
this.success = false;
|
|
15
|
+
this.errors = errors;
|
|
16
|
+
|
|
17
|
+
if (stack) {
|
|
18
|
+
this.stack = stack;
|
|
19
|
+
} else {
|
|
20
|
+
Error.captureStackTrace(this, this.constructor);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
export default ApiError;
|
|
25
|
+
`,
|
|
26
|
+
|
|
27
|
+
"ApiResponse.js": `
|
|
28
|
+
class ApiResponse {
|
|
29
|
+
constructor(statusCode, data, message = "Success") {
|
|
30
|
+
this.statusCode = statusCode;
|
|
31
|
+
this.data = data;
|
|
32
|
+
this.message = message;
|
|
33
|
+
this.success = statusCode < 400; // basically hamra apiResponse hai to hum statusCode -> 400 se kaam he bheja ga
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
// basically statusCode ka knowledge hona chiya aap ke pass
|
|
37
|
+
// Informational responses (100 – 199)
|
|
38
|
+
// Successful responses (200 – 299)
|
|
39
|
+
// Redirection messages (300 – 399)
|
|
40
|
+
// Client error responses (400 – 499)
|
|
41
|
+
// Server error responses (500 – 599)
|
|
42
|
+
|
|
43
|
+
export { ApiResponse };
|
|
44
|
+
`,
|
|
45
|
+
|
|
46
|
+
"asyncHandler.js": `
|
|
47
|
+
const asyncHandler = (requestHandler) => {
|
|
48
|
+
return (req, res, next) => {
|
|
49
|
+
Promise.resolve(requestHandler(req, res, next)).catch((error) =>
|
|
50
|
+
next(error)
|
|
51
|
+
);
|
|
52
|
+
};
|
|
53
|
+
};
|
|
54
|
+
|
|
55
|
+
|
|
56
|
+
export default asyncHandler;
|
|
57
|
+
`,
|
|
58
|
+
};
|