nodejs-quickstart-structure 1.4.3 → 1.7.5
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/CHANGELOG.md +78 -0
- package/README.md +18 -20
- package/bin/index.js +1 -0
- package/docs/generateCase.md +127 -61
- package/docs/generatorFlow.md +15 -3
- package/docs/releaseNoteRule.md +42 -0
- package/lib/generator.js +46 -314
- package/lib/modules/app-setup.js +96 -0
- package/lib/modules/caching-setup.js +56 -0
- package/lib/modules/config-files.js +109 -0
- package/lib/modules/database-setup.js +111 -0
- package/lib/modules/kafka-setup.js +112 -0
- package/lib/modules/project-setup.js +31 -0
- package/lib/prompts.js +12 -4
- package/package.json +4 -3
- package/templates/clean-architecture/js/src/index.js.ejs +19 -6
- package/templates/clean-architecture/js/src/infrastructure/log/logger.js +16 -2
- package/templates/clean-architecture/js/src/infrastructure/repositories/UserRepository.js.ejs +18 -6
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +2 -0
- package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +1 -2
- package/templates/clean-architecture/ts/src/index.ts.ejs +27 -19
- package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +16 -2
- package/templates/clean-architecture/ts/src/infrastructure/repositories/userRepository.ts.ejs +17 -6
- package/templates/common/.env.example.ejs +39 -0
- package/templates/common/Dockerfile +3 -0
- package/templates/common/Jenkinsfile.ejs +41 -0
- package/templates/common/README.md.ejs +113 -106
- package/templates/common/caching/clean/js/CreateUser.js.ejs +25 -0
- package/templates/common/caching/clean/js/GetAllUsers.js.ejs +33 -0
- package/templates/common/caching/clean/ts/createUser.ts.ejs +23 -0
- package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +30 -0
- package/templates/common/caching/js/redisClient.js.ejs +71 -0
- package/templates/common/caching/ts/redisClient.ts.ejs +76 -0
- package/templates/common/docker-compose.yml.ejs +156 -116
- package/templates/common/package.json.ejs +13 -2
- package/templates/mvc/js/src/controllers/userController.js.ejs +35 -3
- package/templates/mvc/js/src/index.js.ejs +26 -17
- package/templates/mvc/js/src/utils/logger.js +16 -6
- package/templates/mvc/ts/src/config/swagger.ts.ejs +1 -2
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +35 -3
- package/templates/mvc/ts/src/index.ts.ejs +27 -18
- package/templates/mvc/ts/src/utils/logger.ts +16 -2
- package/templates/mvc/js/src/config/database.js +0 -12
- /package/templates/db/mysql/{V1__Initial_Setup.sql → V1__Initial_Setup.sql.ejs} +0 -0
- /package/templates/db/postgres/{V1__Initial_Setup.sql → V1__Initial_Setup.sql.ejs} +0 -0
|
@@ -1,116 +1,156 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
- db
|
|
10
|
-
<%
|
|
11
|
-
<%
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
-
|
|
19
|
-
-
|
|
20
|
-
<%
|
|
21
|
-
-
|
|
22
|
-
-
|
|
23
|
-
|
|
24
|
-
<% }
|
|
25
|
-
|
|
26
|
-
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
- DB_PASSWORD=root
|
|
30
|
-
- DB_NAME=<%= dbName %>
|
|
31
|
-
<% }
|
|
32
|
-
-
|
|
33
|
-
-
|
|
34
|
-
|
|
35
|
-
<% }
|
|
36
|
-
|
|
37
|
-
<%
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
<% }
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
volumes:
|
|
69
|
-
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
1
|
+
services:
|
|
2
|
+
app:
|
|
3
|
+
build: .
|
|
4
|
+
ports:
|
|
5
|
+
- "${PORT:-3000}:3000"
|
|
6
|
+
<%_ if (database !== 'None' || communication === 'Kafka') { -%>
|
|
7
|
+
depends_on:
|
|
8
|
+
<%_ if (database !== 'None') { -%>
|
|
9
|
+
- db
|
|
10
|
+
<%_ } -%>
|
|
11
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
12
|
+
- kafka
|
|
13
|
+
<%_ } -%>
|
|
14
|
+
<%_ } -%>
|
|
15
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
16
|
+
environment:
|
|
17
|
+
- KAFKA_BROKER=kafka:29092
|
|
18
|
+
- KAFKAJS_NO_PARTITIONER_WARNING=1
|
|
19
|
+
- PORT=3000
|
|
20
|
+
<%_ if (caching === 'Redis') { -%>
|
|
21
|
+
- REDIS_HOST=redis
|
|
22
|
+
- REDIS_PORT=6379
|
|
23
|
+
- REDIS_PASSWORD=
|
|
24
|
+
<%_ } -%>
|
|
25
|
+
<%_ if (database !== 'None') { -%>
|
|
26
|
+
- DB_HOST=db
|
|
27
|
+
<%_ if (database === 'MySQL') { -%>
|
|
28
|
+
- DB_USER=root
|
|
29
|
+
- DB_PASSWORD=root
|
|
30
|
+
- DB_NAME=<%= dbName %>
|
|
31
|
+
<%_ } -%><%_ if (database === 'PostgreSQL') { -%>
|
|
32
|
+
- DB_USER=postgres
|
|
33
|
+
- DB_PASSWORD=root
|
|
34
|
+
- DB_NAME=<%= dbName %>
|
|
35
|
+
<%_ } -%>
|
|
36
|
+
<%_ } -%>
|
|
37
|
+
<%_ } else { -%>
|
|
38
|
+
environment:
|
|
39
|
+
- PORT=3000
|
|
40
|
+
<%_ if (caching === 'Redis') { -%>
|
|
41
|
+
- REDIS_HOST=redis
|
|
42
|
+
- REDIS_PORT=6379
|
|
43
|
+
- REDIS_PASSWORD=
|
|
44
|
+
<%_ } -%>
|
|
45
|
+
<%_ if (database !== 'None') { -%>
|
|
46
|
+
- DB_HOST=db
|
|
47
|
+
<%_ if (database === 'MySQL') { -%>
|
|
48
|
+
- DB_USER=root
|
|
49
|
+
- DB_PASSWORD=root
|
|
50
|
+
- DB_NAME=<%= dbName %>
|
|
51
|
+
<%_ } -%><%_ if (database === 'PostgreSQL') { -%>
|
|
52
|
+
- DB_USER=postgres
|
|
53
|
+
- DB_PASSWORD=root
|
|
54
|
+
- DB_NAME=<%= dbName %>
|
|
55
|
+
<%_ } -%>
|
|
56
|
+
<%_ } -%>
|
|
57
|
+
<%_ } -%>
|
|
58
|
+
<%_ if (database !== 'None') { -%>
|
|
59
|
+
db:
|
|
60
|
+
<%_ if (database === 'MySQL') { -%>
|
|
61
|
+
image: mysql:8.0
|
|
62
|
+
restart: always
|
|
63
|
+
environment:
|
|
64
|
+
MYSQL_ROOT_PASSWORD: root
|
|
65
|
+
MYSQL_DATABASE: <%= dbName %>
|
|
66
|
+
ports:
|
|
67
|
+
- "${DB_PORT:-3306}:3306"
|
|
68
|
+
volumes:
|
|
69
|
+
- ./flyway/sql:/docker-entrypoint-initdb.d
|
|
70
|
+
<%_ } else if (database === 'PostgreSQL') { -%>
|
|
71
|
+
image: postgres:15
|
|
72
|
+
restart: always
|
|
73
|
+
environment:
|
|
74
|
+
POSTGRES_USER: postgres
|
|
75
|
+
POSTGRES_PASSWORD: root
|
|
76
|
+
POSTGRES_DB: <%= dbName %>
|
|
77
|
+
ports:
|
|
78
|
+
- "${DB_PORT:-5432}:5432"
|
|
79
|
+
volumes:
|
|
80
|
+
- ./flyway/sql:/docker-entrypoint-initdb.d
|
|
81
|
+
<%_ } else if (database === 'MongoDB') { -%>
|
|
82
|
+
image: mongo:latest
|
|
83
|
+
restart: always
|
|
84
|
+
environment:
|
|
85
|
+
MONGO_INITDB_DATABASE: <%= dbName %>
|
|
86
|
+
ports:
|
|
87
|
+
- "${DB_PORT:-27017}:27017"
|
|
88
|
+
volumes:
|
|
89
|
+
- mongodb_data:/data/db
|
|
90
|
+
|
|
91
|
+
mongo-migrate:
|
|
92
|
+
image: node:18-alpine
|
|
93
|
+
working_dir: /app
|
|
94
|
+
volumes:
|
|
95
|
+
- .:/app
|
|
96
|
+
command: sh -c "npm install migrate-mongo && npm run migrate"
|
|
97
|
+
environment:
|
|
98
|
+
- DB_HOST=db
|
|
99
|
+
- DB_NAME=<%= dbName %>
|
|
100
|
+
depends_on:
|
|
101
|
+
- db
|
|
102
|
+
<%_ } -%>
|
|
103
|
+
<%_ } -%>
|
|
104
|
+
<%_ if (database !== 'MongoDB' && database !== 'None') { -%>
|
|
105
|
+
flyway:
|
|
106
|
+
image: flyway/flyway
|
|
107
|
+
command: -connectRetries=60 migrate
|
|
108
|
+
volumes:
|
|
109
|
+
- ./flyway/sql:/flyway/sql
|
|
110
|
+
environment:
|
|
111
|
+
<%_ if (database === 'MySQL') { -%>
|
|
112
|
+
FLYWAY_URL: jdbc:mysql://db:3306/<%= dbName %>
|
|
113
|
+
FLYWAY_USER: root
|
|
114
|
+
FLYWAY_PASSWORD: root
|
|
115
|
+
<%_ } -%><%_ if (database === 'PostgreSQL') { -%>
|
|
116
|
+
FLYWAY_URL: jdbc:postgresql://db:5432/<%= dbName %>
|
|
117
|
+
FLYWAY_USER: postgres
|
|
118
|
+
FLYWAY_PASSWORD: root
|
|
119
|
+
<%_ } -%>
|
|
120
|
+
depends_on:
|
|
121
|
+
- db
|
|
122
|
+
<%_ } -%>
|
|
123
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
124
|
+
zookeeper:
|
|
125
|
+
image: confluentinc/cp-zookeeper:7.4.0
|
|
126
|
+
environment:
|
|
127
|
+
ZOOKEEPER_CLIENT_PORT: 2181
|
|
128
|
+
ZOOKEEPER_TICK_TIME: 2000
|
|
129
|
+
ports:
|
|
130
|
+
- "${ZOOKEEPER_PORT:-2181}:2181"
|
|
131
|
+
|
|
132
|
+
kafka:
|
|
133
|
+
image: confluentinc/cp-kafka:7.4.0
|
|
134
|
+
depends_on:
|
|
135
|
+
- zookeeper
|
|
136
|
+
ports:
|
|
137
|
+
- "${KAFKA_PORT:-9092}:9092"
|
|
138
|
+
environment:
|
|
139
|
+
KAFKA_BROKER_ID: 1
|
|
140
|
+
KAFKA_ZOOKEEPER_CONNECT: zookeeper:2181
|
|
141
|
+
KAFKA_ADVERTISED_LISTENERS: PLAINTEXT://kafka:29092,PLAINTEXT_HOST://localhost:9092
|
|
142
|
+
KAFKA_LISTENER_SECURITY_PROTOCOL_MAP: PLAINTEXT:PLAINTEXT,PLAINTEXT_HOST:PLAINTEXT
|
|
143
|
+
KAFKA_INTER_BROKER_LISTENER_NAME: PLAINTEXT
|
|
144
|
+
KAFKA_OFFSETS_TOPIC_REPLICATION_FACTOR: 1
|
|
145
|
+
<%_ } -%>
|
|
146
|
+
<%_ if (caching === 'Redis') { -%>
|
|
147
|
+
redis:
|
|
148
|
+
image: redis:alpine
|
|
149
|
+
restart: always
|
|
150
|
+
ports:
|
|
151
|
+
- "${REDIS_PORT:-6379}:6379"
|
|
152
|
+
<%_ } -%>
|
|
153
|
+
<%_ if (database !== 'None') { -%>
|
|
154
|
+
volumes:
|
|
155
|
+
<%= database.toLowerCase() %>_data:
|
|
156
|
+
<%_ } -%>
|
|
@@ -13,8 +13,10 @@
|
|
|
13
13
|
"prepare": "husky install",
|
|
14
14
|
"test": "jest",
|
|
15
15
|
"test:watch": "jest --watch",
|
|
16
|
-
"test:coverage": "jest --coverage"
|
|
16
|
+
"test:coverage": "jest --coverage"
|
|
17
|
+
<%_ if (database === 'MongoDB') { -%>,
|
|
17
18
|
"migrate": "migrate-mongo up"
|
|
19
|
+
<%_ } -%>
|
|
18
20
|
},
|
|
19
21
|
"dependencies": {
|
|
20
22
|
"express": "^4.18.2",
|
|
@@ -30,6 +32,8 @@
|
|
|
30
32
|
<% } -%>
|
|
31
33
|
<% if (communication === 'Kafka') { %> "kafkajs": "^2.2.4",
|
|
32
34
|
<% } -%>
|
|
35
|
+
<% if (caching === 'Redis') { %> "ioredis": "^5.3.2",
|
|
36
|
+
<% } -%>
|
|
33
37
|
<% if (viewEngine === 'EJS') { %> "ejs": "^3.1.9",
|
|
34
38
|
<% } -%>
|
|
35
39
|
<% if (viewEngine === 'Pug') { %> "pug": "^3.0.2",
|
|
@@ -38,7 +42,9 @@
|
|
|
38
42
|
"helmet": "^7.1.0",
|
|
39
43
|
"hpp": "^0.2.3",
|
|
40
44
|
"express-rate-limit": "^7.1.5",
|
|
41
|
-
"winston": "^3.11.0"
|
|
45
|
+
"winston": "^3.11.0",
|
|
46
|
+
"winston-daily-rotate-file": "^5.0.0",
|
|
47
|
+
"morgan": "^1.10.0"<% if (communication === 'REST APIs') { %>,
|
|
42
48
|
"swagger-ui-express": "^5.0.0",
|
|
43
49
|
"swagger-jsdoc": "^6.2.8"<% } %>
|
|
44
50
|
},
|
|
@@ -51,9 +57,14 @@
|
|
|
51
57
|
"@types/cors": "^2.8.17",
|
|
52
58
|
"@types/dotenv": "^8.2.0",
|
|
53
59
|
"@types/hpp": "^0.2.3",
|
|
60
|
+
<% if (caching === 'Redis') { %> "@types/ioredis": "^5.0.0",
|
|
61
|
+
<% } -%>
|
|
54
62
|
<% if (database === 'PostgreSQL') { %> "@types/pg": "^8.10.9",
|
|
55
63
|
<% } -%>
|
|
64
|
+
<%_ if (database === 'MySQL' || database === 'PostgreSQL') { -%>
|
|
56
65
|
"@types/sequelize": "^4.28.19",
|
|
66
|
+
<%_ } -%>
|
|
67
|
+
"@types/morgan": "^1.9.9",
|
|
57
68
|
"rimraf": "^5.0.5"<% if (viewEngine && viewEngine !== 'None') { %>,
|
|
58
69
|
"copyfiles": "^2.4.1"<% } %><% } %>,
|
|
59
70
|
"eslint": "^8.56.0",
|
|
@@ -1,12 +1,31 @@
|
|
|
1
1
|
const User = require('../models/User');
|
|
2
2
|
const HTTP_STATUS = require('../utils/httpCodes');
|
|
3
3
|
const logger = require('../utils/logger');
|
|
4
|
+
<%_ if (caching === 'Redis') { -%>
|
|
5
|
+
const redisService = require('../config/redisClient');
|
|
6
|
+
<%_ } -%>
|
|
4
7
|
|
|
5
8
|
const getUsers = async (req, res) => {
|
|
6
9
|
try {
|
|
7
|
-
<% if (
|
|
8
|
-
|
|
9
|
-
<%
|
|
10
|
+
<%_ if (caching === 'Redis') { -%>
|
|
11
|
+
const users = await redisService.getOrSet('users:all', async () => {
|
|
12
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
13
|
+
return await User.find();
|
|
14
|
+
<%_ } else if (database === 'None') { -%>
|
|
15
|
+
return User.mockData;
|
|
16
|
+
<%_ } else { -%>
|
|
17
|
+
return await User.findAll();
|
|
18
|
+
<%_ } -%>
|
|
19
|
+
}, 60);
|
|
20
|
+
<%_ } else { -%>
|
|
21
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
22
|
+
const users = await User.find();
|
|
23
|
+
<%_ } else if (database === 'None') { -%>
|
|
24
|
+
const users = User.mockData;
|
|
25
|
+
<%_ } else { -%>
|
|
26
|
+
const users = await User.findAll();
|
|
27
|
+
<%_ } -%>
|
|
28
|
+
<%_ } -%>
|
|
10
29
|
res.json(users);
|
|
11
30
|
} catch (error) {
|
|
12
31
|
logger.error('Error fetching users:', error);
|
|
@@ -17,11 +36,24 @@ const getUsers = async (req, res) => {
|
|
|
17
36
|
const createUser = async (req, res) => {
|
|
18
37
|
try {
|
|
19
38
|
const { name, email } = req.body;
|
|
39
|
+
<%_ if (database === 'None') { -%>
|
|
40
|
+
const newUser = { id: String(User.mockData.length + 1), name, email };
|
|
41
|
+
User.mockData.push(newUser);
|
|
42
|
+
<%_ if (caching === 'Redis') { -%>
|
|
43
|
+
await redisService.del('users:all');
|
|
44
|
+
<%_ } -%>
|
|
45
|
+
res.status(HTTP_STATUS.CREATED).json(newUser);
|
|
46
|
+
<%_ } else { -%>
|
|
20
47
|
const user = await User.create({ name, email });
|
|
48
|
+
<%_ if (caching === 'Redis') { -%>
|
|
49
|
+
await redisService.del('users:all');
|
|
50
|
+
<%_ } -%>
|
|
21
51
|
res.status(HTTP_STATUS.CREATED).json(user);
|
|
52
|
+
<%_ } -%>
|
|
22
53
|
} catch (error) {
|
|
23
54
|
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
|
|
24
55
|
}
|
|
25
56
|
};
|
|
26
57
|
|
|
27
58
|
module.exports = { getUsers, createUser };
|
|
59
|
+
|
|
@@ -11,9 +11,11 @@ const swaggerSpecs = require('./config/swagger');
|
|
|
11
11
|
const app = express();
|
|
12
12
|
const PORT = process.env.PORT || 3000;
|
|
13
13
|
const logger = require('./utils/logger');
|
|
14
|
+
const morgan = require('morgan');
|
|
14
15
|
|
|
15
16
|
app.use(cors());
|
|
16
17
|
app.use(express.json());
|
|
18
|
+
app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));
|
|
17
19
|
|
|
18
20
|
<% if (communication === 'REST APIs') { -%>
|
|
19
21
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
|
|
@@ -45,34 +47,38 @@ app.get('/health', (req, res) => {
|
|
|
45
47
|
res.json({ status: 'UP' });
|
|
46
48
|
});
|
|
47
49
|
|
|
50
|
+
// Start Server Logic
|
|
51
|
+
const startServer = async () => {
|
|
52
|
+
logger.info(`Server running on port ${PORT}`);
|
|
53
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
54
|
+
try {
|
|
55
|
+
await connectKafka();
|
|
56
|
+
logger.info('Kafka connected');
|
|
57
|
+
// Demo: Send a test message
|
|
58
|
+
await sendMessage('test-topic', 'Hello Kafka from MVC JS!');
|
|
59
|
+
} catch (err) {
|
|
60
|
+
logger.error('Failed to connect to Kafka:', err);
|
|
61
|
+
}
|
|
62
|
+
<%_ } -%>
|
|
63
|
+
};
|
|
64
|
+
|
|
65
|
+
<%_ if (database !== 'None') { -%>
|
|
48
66
|
// Database Sync
|
|
49
67
|
const syncDatabase = async () => {
|
|
50
68
|
let retries = 30;
|
|
51
69
|
while (retries) {
|
|
52
70
|
try {
|
|
53
|
-
<% if (database === 'MongoDB') {
|
|
71
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
54
72
|
const connectDB = require('./config/database');
|
|
55
73
|
await connectDB();
|
|
56
|
-
<% } else {
|
|
74
|
+
<%_ } else { -%>
|
|
57
75
|
const sequelize = require('./config/database');
|
|
58
76
|
await sequelize.sync();
|
|
59
|
-
<% }
|
|
77
|
+
<%_ } -%>
|
|
60
78
|
logger.info('Database synced');
|
|
61
79
|
|
|
62
80
|
// Start Server after DB is ready
|
|
63
|
-
app.listen(PORT,
|
|
64
|
-
logger.info(`Server running on port ${PORT}`);
|
|
65
|
-
<%_ if (communication === 'Kafka') { -%>
|
|
66
|
-
try {
|
|
67
|
-
await connectKafka();
|
|
68
|
-
logger.info('Kafka connected');
|
|
69
|
-
// Demo: Send a test message
|
|
70
|
-
await sendMessage('test-topic', 'Hello Kafka from MVC JS!');
|
|
71
|
-
} catch (err) {
|
|
72
|
-
logger.error('Failed to connect to Kafka:', err);
|
|
73
|
-
}
|
|
74
|
-
<%_ } -%>
|
|
75
|
-
});
|
|
81
|
+
app.listen(PORT, startServer);
|
|
76
82
|
break;
|
|
77
83
|
} catch (err) {
|
|
78
84
|
logger.error('Database sync failed:', err);
|
|
@@ -83,4 +89,7 @@ const syncDatabase = async () => {
|
|
|
83
89
|
}
|
|
84
90
|
};
|
|
85
91
|
|
|
86
|
-
syncDatabase();
|
|
92
|
+
syncDatabase();
|
|
93
|
+
<%_ } else { -%>
|
|
94
|
+
app.listen(PORT, startServer);
|
|
95
|
+
<%_ } -%>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
const winston = require('winston');
|
|
2
|
+
require('winston-daily-rotate-file');
|
|
2
3
|
|
|
3
4
|
const logger = winston.createLogger({
|
|
4
5
|
level: 'info',
|
|
@@ -8,12 +9,21 @@ const logger = winston.createLogger({
|
|
|
8
9
|
),
|
|
9
10
|
defaultMeta: { service: 'user-service' },
|
|
10
11
|
transports: [
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
new winston.transports.DailyRotateFile({
|
|
13
|
+
filename: 'logs/error-%DATE%.log',
|
|
14
|
+
datePattern: 'YYYY-MM-DD',
|
|
15
|
+
zippedArchive: true,
|
|
16
|
+
maxSize: '20m',
|
|
17
|
+
maxFiles: '14d',
|
|
18
|
+
level: 'error',
|
|
19
|
+
}),
|
|
20
|
+
new winston.transports.DailyRotateFile({
|
|
21
|
+
filename: 'logs/combined-%DATE%.log',
|
|
22
|
+
datePattern: 'YYYY-MM-DD',
|
|
23
|
+
zippedArchive: true,
|
|
24
|
+
maxSize: '20m',
|
|
25
|
+
maxFiles: '14d',
|
|
26
|
+
}),
|
|
17
27
|
],
|
|
18
28
|
});
|
|
19
29
|
|
|
@@ -2,13 +2,32 @@ import { Request, Response } from 'express';
|
|
|
2
2
|
import User from '@/models/User';
|
|
3
3
|
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
4
4
|
import logger from '@/utils/logger';
|
|
5
|
+
<%_ if (caching === 'Redis') { -%>
|
|
6
|
+
import redisService from '@/config/redisClient';
|
|
7
|
+
<%_ } -%>
|
|
5
8
|
|
|
6
9
|
export class UserController {
|
|
7
10
|
async getUsers(req: Request, res: Response) {
|
|
8
11
|
try {
|
|
9
|
-
<% if (
|
|
10
|
-
|
|
11
|
-
<%
|
|
12
|
+
<%_ if (caching === 'Redis') { -%>
|
|
13
|
+
const users = await redisService.getOrSet('users:all', async () => {
|
|
14
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
15
|
+
return await User.find();
|
|
16
|
+
<%_ } else if (database === 'None') { -%>
|
|
17
|
+
return User.mockData;
|
|
18
|
+
<%_ } else { -%>
|
|
19
|
+
return await User.findAll();
|
|
20
|
+
<%_ } -%>
|
|
21
|
+
}, 60);
|
|
22
|
+
<%_ } else { -%>
|
|
23
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
24
|
+
const users = await User.find();
|
|
25
|
+
<%_ } else if (database === 'None') { -%>
|
|
26
|
+
const users = User.mockData;
|
|
27
|
+
<%_ } else { -%>
|
|
28
|
+
const users = await User.findAll();
|
|
29
|
+
<%_ } -%>
|
|
30
|
+
<%_ } -%>
|
|
12
31
|
res.json(users);
|
|
13
32
|
} catch (error) {
|
|
14
33
|
logger.error('Error fetching users:', error);
|
|
@@ -23,8 +42,20 @@ export class UserController {
|
|
|
23
42
|
async createUser(req: Request, res: Response) {
|
|
24
43
|
try {
|
|
25
44
|
const { name, email } = req.body;
|
|
45
|
+
<%_ if (database === 'None') { -%>
|
|
46
|
+
const newUser = { id: String(User.mockData.length + 1), name, email };
|
|
47
|
+
User.mockData.push(newUser);
|
|
48
|
+
<%_ if (caching === 'Redis') { -%>
|
|
49
|
+
await redisService.del('users:all');
|
|
50
|
+
<%_ } -%>
|
|
51
|
+
res.status(HTTP_STATUS.CREATED).json(newUser);
|
|
52
|
+
<%_ } else { -%>
|
|
26
53
|
const user = await User.create({ name, email });
|
|
54
|
+
<%_ if (caching === 'Redis') { -%>
|
|
55
|
+
await redisService.del('users:all');
|
|
56
|
+
<%_ } -%>
|
|
27
57
|
res.status(HTTP_STATUS.CREATED).json(user);
|
|
58
|
+
<%_ } -%>
|
|
28
59
|
} catch (error) {
|
|
29
60
|
logger.error('Error creating user:', error);
|
|
30
61
|
if (error instanceof Error) {
|
|
@@ -35,3 +66,4 @@ export class UserController {
|
|
|
35
66
|
}
|
|
36
67
|
}
|
|
37
68
|
}
|
|
69
|
+
|
|
@@ -5,6 +5,7 @@ import hpp from 'hpp';
|
|
|
5
5
|
import rateLimit from 'express-rate-limit';
|
|
6
6
|
import dotenv from 'dotenv';
|
|
7
7
|
import logger from '@/utils/logger';
|
|
8
|
+
import morgan from 'morgan';
|
|
8
9
|
<% if (communication === 'REST APIs' || (viewEngine && viewEngine !== 'None')) { %>import apiRoutes from '@/routes/api';<% } -%>
|
|
9
10
|
<% if (communication === 'REST APIs') { %>
|
|
10
11
|
import swaggerUi from 'swagger-ui-express';
|
|
@@ -24,6 +25,7 @@ const limiter = rateLimit({ windowMs: 10 * 60 * 1000, max: 100 });
|
|
|
24
25
|
app.use(limiter);
|
|
25
26
|
|
|
26
27
|
app.use(express.json());
|
|
28
|
+
app.use(morgan('combined', { stream: { write: (message) => logger.info(message.trim()) } }));
|
|
27
29
|
|
|
28
30
|
<% if (communication === 'REST APIs') { -%>
|
|
29
31
|
app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
|
|
@@ -55,34 +57,38 @@ app.get('/health', (req: Request, res: Response) => {
|
|
|
55
57
|
res.json({ status: 'UP' });
|
|
56
58
|
});
|
|
57
59
|
|
|
60
|
+
// Start Server Logic
|
|
61
|
+
const startServer = async () => {
|
|
62
|
+
logger.info(`Server running on port ${port}`);
|
|
63
|
+
<%_ if (communication === 'Kafka') { -%>
|
|
64
|
+
try {
|
|
65
|
+
const kafkaService = new KafkaService();
|
|
66
|
+
await kafkaService.connect();
|
|
67
|
+
logger.info('Kafka connected');
|
|
68
|
+
// Demo: Send a test message
|
|
69
|
+
await kafkaService.sendMessage('test-topic', 'Hello Kafka from MVC TS!');
|
|
70
|
+
} catch (err) {
|
|
71
|
+
logger.error('Failed to connect to Kafka:', err);
|
|
72
|
+
}
|
|
73
|
+
<%_ } -%>
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
<%_ if (database !== 'None') { -%>
|
|
58
77
|
// Database Sync
|
|
59
78
|
const syncDatabase = async () => {
|
|
60
79
|
let retries = 30;
|
|
61
80
|
while (retries) {
|
|
62
81
|
try {
|
|
63
|
-
<% if (database === 'MongoDB') {
|
|
82
|
+
<%_ if (database === 'MongoDB') { -%>
|
|
64
83
|
const connectDB = (await import('@/config/database')).default;
|
|
65
84
|
await connectDB();
|
|
66
|
-
<% } else {
|
|
85
|
+
<%_ } else { -%>
|
|
67
86
|
const sequelize = (await import('@/config/database')).default;
|
|
68
87
|
await sequelize.sync();
|
|
69
|
-
<% }
|
|
88
|
+
<%_ } -%>
|
|
70
89
|
logger.info('Database synced');
|
|
71
90
|
// Start Server after DB is ready
|
|
72
|
-
app.listen(port,
|
|
73
|
-
logger.info(`Server running on port ${port}`);
|
|
74
|
-
<%_ if (communication === 'Kafka') { -%>
|
|
75
|
-
try {
|
|
76
|
-
const kafkaService = new KafkaService();
|
|
77
|
-
await kafkaService.connect();
|
|
78
|
-
logger.info('Kafka connected');
|
|
79
|
-
// Demo: Send a test message
|
|
80
|
-
await kafkaService.sendMessage('test-topic', 'Hello Kafka from MVC TS!');
|
|
81
|
-
} catch (err) {
|
|
82
|
-
logger.error('Failed to connect to Kafka:', err);
|
|
83
|
-
}
|
|
84
|
-
<%_ } -%>
|
|
85
|
-
});
|
|
91
|
+
app.listen(port, startServer);
|
|
86
92
|
break;
|
|
87
93
|
} catch (error) {
|
|
88
94
|
logger.error('Error syncing database:', error);
|
|
@@ -93,4 +99,7 @@ const syncDatabase = async () => {
|
|
|
93
99
|
}
|
|
94
100
|
};
|
|
95
101
|
|
|
96
|
-
syncDatabase();
|
|
102
|
+
syncDatabase();
|
|
103
|
+
<%_ } else { -%>
|
|
104
|
+
app.listen(port, startServer);
|
|
105
|
+
<%_ } -%>
|
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
import winston from 'winston';
|
|
2
|
+
import 'winston-daily-rotate-file';
|
|
2
3
|
|
|
3
4
|
const logger = winston.createLogger({
|
|
4
5
|
level: 'info',
|
|
@@ -8,8 +9,21 @@ const logger = winston.createLogger({
|
|
|
8
9
|
),
|
|
9
10
|
defaultMeta: { service: 'user-service' },
|
|
10
11
|
transports: [
|
|
11
|
-
new winston.transports.
|
|
12
|
-
|
|
12
|
+
new winston.transports.DailyRotateFile({
|
|
13
|
+
filename: 'logs/error-%DATE%.log',
|
|
14
|
+
datePattern: 'YYYY-MM-DD',
|
|
15
|
+
zippedArchive: true,
|
|
16
|
+
maxSize: '20m',
|
|
17
|
+
maxFiles: '14d',
|
|
18
|
+
level: 'error',
|
|
19
|
+
}),
|
|
20
|
+
new winston.transports.DailyRotateFile({
|
|
21
|
+
filename: 'logs/combined-%DATE%.log',
|
|
22
|
+
datePattern: 'YYYY-MM-DD',
|
|
23
|
+
zippedArchive: true,
|
|
24
|
+
maxSize: '20m',
|
|
25
|
+
maxFiles: '14d',
|
|
26
|
+
}),
|
|
13
27
|
],
|
|
14
28
|
});
|
|
15
29
|
|