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 +193 -0
- package/my-test/.env.example +21 -0
- package/my-test/README.md +137 -0
- package/my-test/package.json +38 -0
- package/my-test/src/app.ts +77 -0
- package/my-test/src/config/database.ts +54 -0
- package/my-test/src/config/env.ts +42 -0
- package/my-test/src/config/winston-logger.ts +75 -0
- package/my-test/src/index.ts +3 -0
- package/my-test/src/middleware/error.middleware.ts +88 -0
- package/my-test/src/middleware/request-id.middleware.ts +20 -0
- package/my-test/src/modules/example/example.controller.ts +45 -0
- package/my-test/src/modules/example/example.model.ts +31 -0
- package/my-test/src/modules/example/example.route.ts +20 -0
- package/my-test/src/modules/example/example.service.ts +92 -0
- package/my-test/src/modules/example/example.validation.ts +16 -0
- package/my-test/src/server.ts +57 -0
- package/my-test/src/utils/apiError.ts +63 -0
- package/my-test/src/utils/asyncHandler.ts +7 -0
- package/my-test/src/utils/response.ts +102 -0
- package/my-test/src/utils/validationMiddleware.ts +32 -0
- package/my-test/tsconfig.json +26 -0
- package/my-test/yarn.lock +1149 -0
- package/package.json +35 -0
- package/src/cli.js +126 -0
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;
|