create-express-mongoose-app 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/README.md ADDED
@@ -0,0 +1,193 @@
1
+ # create-express-mongo-app
2
+
3
+ A CLI tool to quickly bootstrap a production-grade Express.js + MongoDB/Mongoose project with TypeScript.
4
+
5
+ ## Features
6
+
7
+ - 🚀 **Quick Setup** - Create a new project in seconds
8
+ - 📦 **Package Manager Support** - Choose npm, yarn, or pnpm
9
+ - 🔒 **Security First** - Includes Helmet, CORS, rate limiting
10
+ - 📝 **TypeScript** - Strict mode enabled by default
11
+ - 🛡️ **Error Handling** - Centralized error middleware with standardized responses
12
+ - 📊 **Logging** - Winston logger with file rotation
13
+ - ✅ **Validation** - Joi schema validation
14
+ - 🗄️ **Database Ready** - MongoDB/Mongoose with connection retry logic
15
+ - 🏥 **Health Checks** - Built-in /health and /ready endpoints
16
+
17
+ ## Installation
18
+
19
+ ```bash
20
+ npm install -g create-express-mongo-app
21
+ ```
22
+
23
+ Or use npx without installation:
24
+
25
+ ```bash
26
+ npx create-express-mongo-app
27
+ ```
28
+
29
+ ## Usage
30
+
31
+ Run the CLI:
32
+
33
+ ```bash
34
+ create-express-mongo-app
35
+ ```
36
+
37
+ Or with npx:
38
+
39
+ ```bash
40
+ npx create-express-mongo-app
41
+ ```
42
+
43
+ The CLI will ask for:
44
+
45
+ 1. **Project Name** - The name of your project directory
46
+ 2. **Package Manager** - Choose between npm, yarn, or pnpm
47
+
48
+ ## What's Included
49
+
50
+ The generated project includes:
51
+
52
+ ### Core Features
53
+
54
+ - Express.js server with TypeScript
55
+ - MongoDB/Mongoose integration
56
+ - Centralized error handling
57
+ - API response wrapper class
58
+ - Async error handling
59
+ - Winston logging with file rotation
60
+ - Joi validation framework
61
+ - Security middleware stack (helmet, CORS, rate-limit)
62
+ - Request ID tracking
63
+ - Health check endpoints
64
+
65
+ ### Project Structure
66
+
67
+ ```
68
+ src/
69
+ ├── config/ # Configuration
70
+ ├── middleware/ # Express middleware
71
+ ├── modules/ # Feature modules
72
+ ├── utils/ # Utility functions
73
+ ├── app.ts # Express app setup
74
+ ├── index.ts # Entry point
75
+ └── server.ts # Server startup
76
+ ```
77
+
78
+ ### Generated Files
79
+
80
+ - `.env.example` - Environment variables template
81
+ - `package.json` - Dependencies configured
82
+ - `tsconfig.json` - TypeScript configuration
83
+ - `.gitignore` - Git ignore rules
84
+ - `README.md` - Project documentation
85
+
86
+ ## Quick Start After Generation
87
+
88
+ ```bash
89
+ # 1. Navigate to project
90
+ cd my-express-app
91
+
92
+ # 2. Set up environment variables
93
+ cp .env.example .env
94
+
95
+ # 3. Configure MongoDB URI in .env
96
+ # MONGODB_URI=mongodb://localhost:27017/your-db-name
97
+
98
+ # 4. Start development server
99
+ npm run dev
100
+
101
+ # 5. Build for production
102
+ npm run build
103
+ npm start
104
+ ```
105
+
106
+ ## Environment Variables
107
+
108
+ The `.env.example` file includes all available configuration options:
109
+
110
+ - `NODE_ENV` - Application environment
111
+ - `PORT` - Server port
112
+ - `MONGODB_URI` - MongoDB connection string
113
+ - `API_PREFIX` - API route prefix
114
+ - `LOG_LEVEL` - Logging level
115
+ - `CORS_ORIGIN` - CORS origin
116
+ - And more...
117
+
118
+ ## API Examples
119
+
120
+ ### Success Response
121
+
122
+ ```json
123
+ {
124
+ "status": "success",
125
+ "data": {...},
126
+ "message": "Retrieved successfully"
127
+ }
128
+ ```
129
+
130
+ ### Error Response
131
+
132
+ ```json
133
+ {
134
+ "status": "error",
135
+ "message": "Validation failed",
136
+ "errors": {...},
137
+ "statusCode": 422
138
+ }
139
+ ```
140
+
141
+ ## Generating New Modules
142
+
143
+ After project creation, generate new modules:
144
+
145
+ ```bash
146
+ npm run generate-module <module-name>
147
+ ```
148
+
149
+ This creates a complete CRUD module with:
150
+
151
+ - Model
152
+ - Service
153
+ - Controller
154
+ - Routes
155
+ - Validation schema
156
+
157
+ ## Troubleshooting
158
+
159
+ ### Template Clone Failed
160
+
161
+ - Ensure you have internet access
162
+ - Check if the template repository is accessible
163
+ - Verify the repository name is correct
164
+
165
+ ### Dependencies Installation Failed
166
+
167
+ - Ensure you have Node.js >= 16.0.0 installed
168
+ - Try running the package manager command manually
169
+ - Check for permission issues
170
+
171
+ ### MongoDB Connection Failed
172
+
173
+ - Ensure MongoDB is running
174
+ - Verify `MONGODB_URI` in `.env` is correct
175
+ - Check MongoDB connection permissions
176
+
177
+ ## Support
178
+
179
+ For issues, questions, or suggestions, please visit the template repository:
180
+
181
+ https://github.com/YOUR_GITHUB_USERNAME/express-mongo-starter
182
+
183
+ ## License
184
+
185
+ MIT
186
+
187
+ ## Author
188
+
189
+ Your Name
190
+
191
+ ---
192
+
193
+ Built with ❤️ for developers
@@ -0,0 +1,21 @@
1
+ # Server Configuration
2
+ NODE_ENV=development
3
+ PORT=3000
4
+ API_PREFIX=/api
5
+
6
+ # Database Configuration
7
+ MONGODB_URI=mongodb://localhost:27017/express-mongo-starter
8
+ DB_MIN_POOL_SIZE=5
9
+ DB_MAX_POOL_SIZE=10
10
+
11
+ # Logging Configuration
12
+ LOG_LEVEL=info
13
+ ENABLE_FILE_LOGGING=false
14
+
15
+ # Security & Rate Limiting
16
+ CORS_ORIGIN=http://localhost:3000
17
+ RATE_LIMIT_WINDOW_MS=900000
18
+ RATE_LIMIT_MAX_REQUESTS=100
19
+
20
+ # Request Configuration
21
+ REQUEST_BODY_LIMIT=10kb
@@ -0,0 +1,137 @@
1
+ # Express MongoDB Starter Template
2
+
3
+ A production-grade Express.js + MongoDB/Mongoose starter template with TypeScript, comprehensive error handling, Winston logging, Joi validation, and security best practices.
4
+
5
+ ## Features
6
+
7
+ - ✅ **TypeScript** - Strict mode enabled
8
+ - ✅ **Error Handling** - Centralized error middleware with standardized responses
9
+ - ✅ **Response Handler** - Universal ApiResponseHandler with error/success/info methods
10
+ - ✅ **Logging** - Winston logger with file rotation
11
+ - ✅ **Validation** - Joi schema validation
12
+ - ✅ **Security** - Helmet, CORS, Rate Limiting
13
+ - ✅ **Database** - MongoDB with connection retry logic and graceful shutdown
14
+ - ✅ **Async Handler** - Eliminate try-catch boilerplate
15
+ - ✅ **Health Checks** - /health and /ready endpoints
16
+
17
+ ## Quick Start
18
+
19
+ 1. Clone this repository
20
+ 2. Install dependencies:
21
+
22
+ ```bash
23
+ npm install
24
+ # or
25
+ yarn install
26
+ # or
27
+ pnpm install
28
+ ```
29
+
30
+ 3. Copy `.env.example` to `.env` and configure:
31
+
32
+ ```bash
33
+ cp .env.example .env
34
+ ```
35
+
36
+ 4. Start development server:
37
+
38
+ ```bash
39
+ npm run dev
40
+ ```
41
+
42
+ 5. Build for production:
43
+ ```bash
44
+ npm run build
45
+ npm start
46
+ ```
47
+
48
+ ## Project Structure
49
+
50
+ ```
51
+ src/
52
+ ├── config/ # Configuration files
53
+ │ ├── env.ts # Environment variables
54
+ │ ├── database.ts # MongoDB connection
55
+ │ └── winston-logger.ts # Logger setup
56
+ ├── middleware/ # Express middleware
57
+ │ ├── error.middleware.ts
58
+ │ ├── auth.middleware.ts
59
+ │ └── request-id.middleware.ts
60
+ ├── modules/ # Feature modules
61
+ │ └── example/ # Example module
62
+ │ ├── example.controller.ts
63
+ │ ├── example.service.ts
64
+ │ ├── example.model.ts
65
+ │ ├── example.route.ts
66
+ │ └── example.validation.ts
67
+ ├── utils/ # Utility functions
68
+ │ ├── response.ts # Response handler
69
+ │ ├── asyncHandler.ts
70
+ │ ├── apiError.ts
71
+ │ └── validationMiddleware.ts
72
+ ├── app.ts # Express app setup
73
+ ├── index.ts # Entry point
74
+ └── generate-module.ts # Module generator CLI
75
+ ```
76
+
77
+ ## API Response Format
78
+
79
+ All endpoints return standardized responses:
80
+
81
+ ```typescript
82
+ // Success Response
83
+ {
84
+ "status": "success",
85
+ "data": {...},
86
+ "message": "Retrieved successfully"
87
+ }
88
+
89
+ // Error Response
90
+ {
91
+ "status": "error",
92
+ "message": "Error message",
93
+ "errors": {...},
94
+ "statusCode": 400
95
+ }
96
+
97
+ // Info Response
98
+ {
99
+ "status": "info",
100
+ "message": "Info message",
101
+ "data": {...}
102
+ }
103
+ ```
104
+
105
+ ## Generating New Modules
106
+
107
+ Generate a new module with all CRUD operations:
108
+
109
+ ```bash
110
+ npm run generate-module <module-name>
111
+ ```
112
+
113
+ This creates:
114
+
115
+ - Controller
116
+ - Service
117
+ - Model
118
+ - Routes
119
+ - Validation schema
120
+
121
+ ## Environment Variables
122
+
123
+ See `.env.example` for all available configuration options.
124
+
125
+ ## Error Handling
126
+
127
+ Errors are automatically caught by the centralized error middleware and formatted consistently. Supports:
128
+
129
+ - Mongoose validation errors
130
+ - MongoDB duplicate key errors (11000)
131
+ - JWT errors
132
+ - Custom ApiError instances
133
+ - Unhandled exceptions
134
+
135
+ ## License
136
+
137
+ MIT
@@ -0,0 +1,38 @@
1
+ {
2
+ "name": "express-mongo-starter",
3
+ "version": "1.0.0",
4
+ "description": "Production-grade Express.js with MongoDB/Mongoose starter template",
5
+ "main": "dist/index.js",
6
+ "scripts": {
7
+ "dev": "ts-node src/index.ts",
8
+ "build": "tsc",
9
+ "start": "node dist/index.js",
10
+ "generate-module": "ts-node src/generate-module.ts"
11
+ },
12
+ "dependencies": {
13
+ "cors": "^2.8.5",
14
+ "dotenv": "^16.3.1",
15
+ "express": "^4.18.2",
16
+ "express-async-errors": "^3.1.1",
17
+ "express-rate-limit": "^7.1.5",
18
+ "express-validator": "^7.0.0",
19
+ "helmet": "^7.1.0",
20
+ "http-status-codes": "^2.3.0",
21
+ "joi": "^17.11.0",
22
+ "mongoose": "^8.1.0",
23
+ "morgan": "^1.10.0",
24
+ "uuid": "^13.0.0",
25
+ "winston": "^3.11.0"
26
+ },
27
+ "devDependencies": {
28
+ "@types/cors": "^2.8.19",
29
+ "@types/express": "^4.17.21",
30
+ "@types/morgan": "^1.9.10",
31
+ "@types/node": "^20.10.6",
32
+ "ts-node": "^10.9.2",
33
+ "typescript": "^5.3.3"
34
+ },
35
+ "engines": {
36
+ "node": ">=16.0.0"
37
+ }
38
+ }
@@ -0,0 +1,77 @@
1
+ import express, { Express, Request, Response } from "express";
2
+ import helmet from "helmet";
3
+ import cors from "cors";
4
+ import rateLimit from "express-rate-limit";
5
+ import morgan from "morgan";
6
+ import "express-async-errors";
7
+ import { config } from "./config/env";
8
+ import { errorMiddleware } from "./middleware/error.middleware";
9
+ import { requestIdMiddleware } from "./middleware/request-id.middleware";
10
+ import { logger } from "./config/winston-logger";
11
+ import { ApiResponseHandler } from "./utils/response";
12
+
13
+ export const createApp = (): Express => {
14
+ const app = express();
15
+
16
+ // Security middleware
17
+ app.use(helmet());
18
+ app.use(
19
+ cors({
20
+ origin: config.corsOrigin,
21
+ credentials: true,
22
+ }),
23
+ );
24
+
25
+ // Request ID middleware
26
+ app.use(requestIdMiddleware);
27
+
28
+ // Body parser middleware
29
+ app.use(express.json({ limit: config.requestBodyLimit }));
30
+ app.use(
31
+ express.urlencoded({ limit: config.requestBodyLimit, extended: true }),
32
+ );
33
+
34
+ // Rate limiting
35
+ const limiter = rateLimit({
36
+ windowMs: config.rateLimitWindowMs,
37
+ max: config.rateLimitMaxRequests,
38
+ message: "Too many requests from this IP, please try again later.",
39
+ });
40
+ app.use(limiter);
41
+
42
+ // Logging middleware
43
+ app.use(
44
+ morgan("combined", {
45
+ stream: {
46
+ write: (message) => logger.info(message.trim()),
47
+ },
48
+ }),
49
+ );
50
+
51
+ // Health check endpoints
52
+ app.get("/health", (req: Request, res: Response) => {
53
+ ApiResponseHandler.success(res, { status: "healthy" }, "Server is running");
54
+ });
55
+
56
+ app.get("/ready", (req: Request, res: Response) => {
57
+ ApiResponseHandler.success(res, { ready: true }, "Server is ready");
58
+ });
59
+
60
+ // API routes
61
+ app.use(config.apiPrefix, (req: Request, res: Response) => {
62
+ ApiResponseHandler.info(res, "API is running", {
63
+ version: "1.0.0",
64
+ apiPrefix: config.apiPrefix,
65
+ });
66
+ });
67
+
68
+ // 404 handler
69
+ app.use("*", (req: Request, res: Response) => {
70
+ ApiResponseHandler.error(res, "Route not found", 404);
71
+ });
72
+
73
+ // Error middleware (must be last)
74
+ app.use(errorMiddleware);
75
+
76
+ return app;
77
+ };
@@ -0,0 +1,54 @@
1
+ import mongoose from "mongoose";
2
+ import { config } from "./env";
3
+ import { logger } from "./winston-logger";
4
+
5
+ export const connectDatabase = async () => {
6
+ try {
7
+ const mongoOptions = {
8
+ minPoolSize: 5,
9
+ maxPoolSize: 10,
10
+ };
11
+
12
+ await mongoose.connect(config.mongodbUri, mongoOptions);
13
+
14
+ logger.info("Database connected successfully");
15
+
16
+ mongoose.connection.on("disconnected", () => {
17
+ logger.warn("Database disconnected");
18
+ });
19
+
20
+ mongoose.connection.on("error", (error) => {
21
+ logger.error("Database connection error:", error);
22
+ });
23
+
24
+ mongoose.connection.on("reconnected", () => {
25
+ logger.info("Database reconnected");
26
+ });
27
+ } catch (error: any) {
28
+ logger.error("Failed to connect to database:", error.message);
29
+ // Retry logic
30
+ const retryAttempts = 5;
31
+ for (let i = 1; i <= retryAttempts; i++) {
32
+ logger.info(`Retrying database connection (${i}/${retryAttempts})...`);
33
+ await new Promise((resolve) => setTimeout(resolve, 5000));
34
+ try {
35
+ await mongoose.connect(config.mongodbUri);
36
+ logger.info("Database connected successfully on retry");
37
+ return;
38
+ } catch (retryError: any) {
39
+ logger.error(`Retry attempt ${i} failed:`, retryError.message);
40
+ }
41
+ }
42
+ process.exit(1);
43
+ }
44
+ };
45
+
46
+ export const disconnectDatabase = async () => {
47
+ try {
48
+ await mongoose.disconnect();
49
+ logger.info("Database disconnected");
50
+ } catch (error: any) {
51
+ logger.error("Error disconnecting database:", error.message);
52
+ process.exit(1);
53
+ }
54
+ };
@@ -0,0 +1,42 @@
1
+ import dotenv from "dotenv";
2
+
3
+ dotenv.config();
4
+
5
+ export interface IConfig {
6
+ port: number;
7
+ nodeEnv: string;
8
+ mongodbUri: string;
9
+ apiPrefix: string;
10
+ logLevel: string;
11
+ corsOrigin: string;
12
+ rateLimitWindowMs: number;
13
+ rateLimitMaxRequests: number;
14
+ requestBodyLimit: string;
15
+ enableFileLogging: boolean;
16
+ }
17
+
18
+ export const config: IConfig = {
19
+ port: parseInt(process.env.PORT || "3000"),
20
+ nodeEnv: process.env.NODE_ENV || "development",
21
+ mongodbUri:
22
+ process.env.MONGODB_URI ||
23
+ "mongodb://localhost:27017/express-mongo-starter",
24
+ apiPrefix: process.env.API_PREFIX || "/api",
25
+ logLevel: process.env.LOG_LEVEL || "info",
26
+ corsOrigin: process.env.CORS_ORIGIN || "http://localhost:3000",
27
+ rateLimitWindowMs: parseInt(process.env.RATE_LIMIT_WINDOW_MS || "900000"),
28
+ rateLimitMaxRequests: parseInt(process.env.RATE_LIMIT_MAX_REQUESTS || "100"),
29
+ requestBodyLimit: process.env.REQUEST_BODY_LIMIT || "10kb",
30
+ enableFileLogging: process.env.ENABLE_FILE_LOGGING === "true",
31
+ };
32
+
33
+ // Validate required environment variables in production
34
+ if (config.nodeEnv === "production") {
35
+ const requiredVars = ["MONGODB_URI"];
36
+ const missingVars = requiredVars.filter((v) => !process.env[v]);
37
+ if (missingVars.length > 0) {
38
+ throw new Error(
39
+ `Missing required environment variables: ${missingVars.join(", ")}`,
40
+ );
41
+ }
42
+ }
@@ -0,0 +1,75 @@
1
+ import winston from "winston";
2
+ import path from "path";
3
+ import { config } from "./env";
4
+
5
+ const logsDir = path.join(process.cwd(), "logs");
6
+
7
+ const levels = {
8
+ error: 0,
9
+ warn: 1,
10
+ info: 2,
11
+ debug: 3,
12
+ };
13
+
14
+ const colors = {
15
+ error: "red",
16
+ warn: "yellow",
17
+ info: "green",
18
+ debug: "blue",
19
+ };
20
+
21
+ winston.addColors(colors);
22
+
23
+ const format = winston.format.combine(
24
+ winston.format.timestamp({ format: "YYYY-MM-DD HH:mm:ss" }),
25
+ winston.format.printf(
26
+ (info) =>
27
+ `${info.timestamp} [${info.level}]: ${info.message}${info.error ? "\n" + info.error : ""}`,
28
+ ),
29
+ );
30
+
31
+ const transports: winston.transport[] = [
32
+ new winston.transports.Console({
33
+ format: winston.format.combine(
34
+ winston.format.colorize({ all: true }),
35
+ format,
36
+ ),
37
+ }),
38
+ ];
39
+
40
+ if (config.nodeEnv === "production" || config.enableFileLogging) {
41
+ transports.push(
42
+ new winston.transports.File({
43
+ filename: path.join(logsDir, "error.log"),
44
+ level: "error",
45
+ format,
46
+ maxsize: 5242880,
47
+ maxFiles: 5,
48
+ }),
49
+ new winston.transports.File({
50
+ filename: path.join(logsDir, "combined.log"),
51
+ format,
52
+ maxsize: 5242880,
53
+ maxFiles: 5,
54
+ }),
55
+ );
56
+ }
57
+
58
+ export const logger = winston.createLogger({
59
+ level: config.logLevel || "info",
60
+ levels,
61
+ format,
62
+ transports,
63
+ exceptionHandlers: [
64
+ new winston.transports.File({
65
+ filename: path.join(logsDir, "exceptions.log"),
66
+ }),
67
+ ],
68
+ rejectionHandlers: [
69
+ new winston.transports.File({
70
+ filename: path.join(logsDir, "rejections.log"),
71
+ }),
72
+ ],
73
+ });
74
+
75
+ export default logger;
@@ -0,0 +1,3 @@
1
+ import { startServer } from "./server";
2
+
3
+ startServer();