nodejs-quickstart-structure 1.19.0 → 1.19.1

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.
Files changed (134) hide show
  1. package/CHANGELOG.md +309 -301
  2. package/LICENSE +15 -15
  3. package/lib/generator.js +139 -139
  4. package/lib/modules/app-setup.js +401 -401
  5. package/lib/modules/config-files.js +151 -151
  6. package/lib/modules/database-setup.js +116 -116
  7. package/lib/modules/project-setup.js +32 -32
  8. package/lib/prompts.js +100 -100
  9. package/package.json +78 -78
  10. package/templates/clean-architecture/js/src/domain/models/User.js +9 -9
  11. package/templates/clean-architecture/js/src/errors/ApiError.js +14 -14
  12. package/templates/clean-architecture/js/src/index.js.ejs +55 -55
  13. package/templates/clean-architecture/js/src/infrastructure/config/env.js.ejs +47 -47
  14. package/templates/clean-architecture/js/src/infrastructure/log/logger.js +36 -36
  15. package/templates/clean-architecture/js/src/infrastructure/log/logger.spec.js.ejs +63 -63
  16. package/templates/clean-architecture/js/src/infrastructure/webserver/middleware/errorMiddleware.js +30 -30
  17. package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +89 -89
  18. package/templates/clean-architecture/js/src/infrastructure/webserver/swagger.js.ejs +6 -6
  19. package/templates/clean-architecture/js/src/interfaces/graphql/context.js.ejs +13 -13
  20. package/templates/clean-architecture/js/src/interfaces/graphql/context.spec.js.ejs +31 -31
  21. package/templates/clean-architecture/js/src/interfaces/graphql/index.js.ejs +5 -5
  22. package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/index.js.ejs +6 -6
  23. package/templates/clean-architecture/js/src/interfaces/graphql/typeDefs/index.js.ejs +6 -6
  24. package/templates/clean-architecture/js/src/interfaces/routes/api.spec.js.ejs +38 -38
  25. package/templates/clean-architecture/js/src/usecases/CreateUser.js +14 -14
  26. package/templates/clean-architecture/js/src/usecases/CreateUser.spec.js.ejs +51 -51
  27. package/templates/clean-architecture/js/src/usecases/GetAllUsers.js +12 -12
  28. package/templates/clean-architecture/js/src/usecases/GetAllUsers.spec.js.ejs +61 -61
  29. package/templates/clean-architecture/js/src/utils/httpCodes.js +9 -9
  30. package/templates/clean-architecture/ts/src/config/env.ts.ejs +46 -46
  31. package/templates/clean-architecture/ts/src/config/swagger.ts.ejs +6 -6
  32. package/templates/clean-architecture/ts/src/domain/user.ts +7 -7
  33. package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -15
  34. package/templates/clean-architecture/ts/src/index.ts.ejs +139 -139
  35. package/templates/clean-architecture/ts/src/infrastructure/log/logger.spec.ts.ejs +63 -63
  36. package/templates/clean-architecture/ts/src/infrastructure/log/logger.ts +36 -36
  37. package/templates/clean-architecture/ts/src/interfaces/graphql/context.spec.ts.ejs +32 -32
  38. package/templates/clean-architecture/ts/src/interfaces/graphql/context.ts.ejs +17 -17
  39. package/templates/clean-architecture/ts/src/interfaces/graphql/index.ts.ejs +3 -3
  40. package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/index.ts.ejs +4 -4
  41. package/templates/clean-architecture/ts/src/interfaces/graphql/typeDefs/index.ts.ejs +4 -4
  42. package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.spec.ts.ejs +40 -40
  43. package/templates/clean-architecture/ts/src/usecases/createUser.spec.ts.ejs +51 -51
  44. package/templates/clean-architecture/ts/src/usecases/createUser.ts +13 -13
  45. package/templates/clean-architecture/ts/src/usecases/getAllUsers.spec.ts.ejs +63 -63
  46. package/templates/clean-architecture/ts/src/usecases/getAllUsers.ts +10 -10
  47. package/templates/clean-architecture/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  48. package/templates/clean-architecture/ts/src/utils/httpCodes.ts +7 -7
  49. package/templates/common/.cursorrules.ejs +60 -60
  50. package/templates/common/.dockerignore +12 -12
  51. package/templates/common/.env.example.ejs +41 -41
  52. package/templates/common/.gitlab-ci.yml.ejs +86 -86
  53. package/templates/common/.lintstagedrc +6 -6
  54. package/templates/common/.prettierrc +7 -7
  55. package/templates/common/Dockerfile +73 -73
  56. package/templates/common/Jenkinsfile.ejs +87 -87
  57. package/templates/common/SECURITY.md +20 -20
  58. package/templates/common/_github/workflows/ci.yml.ejs +46 -46
  59. package/templates/common/_github/workflows/security.yml.ejs +36 -36
  60. package/templates/common/_gitignore +5 -5
  61. package/templates/common/_husky/pre-commit +4 -4
  62. package/templates/common/caching/clean/js/CreateUser.js.ejs +29 -29
  63. package/templates/common/caching/clean/js/GetAllUsers.js.ejs +37 -37
  64. package/templates/common/caching/clean/ts/createUser.ts.ejs +27 -27
  65. package/templates/common/caching/clean/ts/getAllUsers.ts.ejs +34 -34
  66. package/templates/common/caching/js/memoryCache.js.ejs +60 -60
  67. package/templates/common/caching/js/memoryCache.spec.js.ejs +101 -101
  68. package/templates/common/caching/js/redisClient.js.ejs +75 -75
  69. package/templates/common/caching/js/redisClient.spec.js.ejs +147 -147
  70. package/templates/common/caching/ts/memoryCache.spec.ts.ejs +102 -102
  71. package/templates/common/caching/ts/redisClient.spec.ts.ejs +157 -157
  72. package/templates/common/database/js/database.js.ejs +19 -19
  73. package/templates/common/database/js/database.spec.js.ejs +56 -56
  74. package/templates/common/database/js/mongoose.js.ejs +33 -33
  75. package/templates/common/database/js/mongoose.spec.js.ejs +43 -43
  76. package/templates/common/database/ts/database.spec.ts.ejs +56 -56
  77. package/templates/common/database/ts/database.ts.ejs +21 -21
  78. package/templates/common/database/ts/mongoose.spec.ts.ejs +42 -42
  79. package/templates/common/database/ts/mongoose.ts.ejs +28 -28
  80. package/templates/common/docker-compose.yml.ejs +159 -159
  81. package/templates/common/ecosystem.config.js.ejs +40 -40
  82. package/templates/common/eslint.config.mjs.ejs +77 -77
  83. package/templates/common/health/js/healthRoute.spec.js.ejs +70 -70
  84. package/templates/common/health/ts/healthRoute.spec.ts.ejs +76 -76
  85. package/templates/common/jest.config.js.ejs +32 -32
  86. package/templates/common/kafka/js/config/kafka.js +9 -9
  87. package/templates/common/kafka/js/config/kafka.spec.js.ejs +27 -27
  88. package/templates/common/kafka/js/messaging/baseConsumer.spec.js.ejs +58 -58
  89. package/templates/common/kafka/js/messaging/userEventSchema.spec.js.ejs +27 -27
  90. package/templates/common/kafka/js/services/kafkaService.spec.js.ejs +106 -106
  91. package/templates/common/kafka/ts/config/kafka.spec.ts.ejs +27 -27
  92. package/templates/common/kafka/ts/config/kafka.ts +7 -7
  93. package/templates/common/kafka/ts/messaging/baseConsumer.spec.ts.ejs +50 -50
  94. package/templates/common/kafka/ts/messaging/baseConsumer.ts.ejs +27 -27
  95. package/templates/common/kafka/ts/services/kafkaService.spec.ts.ejs +81 -81
  96. package/templates/common/migrate-mongo-config.js.ejs +31 -31
  97. package/templates/common/migrations/init.js.ejs +23 -23
  98. package/templates/common/package.json.ejs +119 -118
  99. package/templates/common/prompts/add-feature.md.ejs +26 -26
  100. package/templates/common/prompts/project-context.md.ejs +43 -43
  101. package/templates/common/prompts/troubleshoot.md.ejs +28 -28
  102. package/templates/common/public/css/style.css +147 -147
  103. package/templates/common/scripts/run-e2e.js.ejs +63 -63
  104. package/templates/common/sonar-project.properties.ejs +27 -27
  105. package/templates/common/src/utils/errorMiddleware.spec.js.ejs +79 -79
  106. package/templates/common/src/utils/errorMiddleware.spec.ts.ejs +94 -94
  107. package/templates/common/tsconfig.json +22 -22
  108. package/templates/common/views/ejs/index.ejs +55 -55
  109. package/templates/common/views/pug/index.pug +40 -40
  110. package/templates/mvc/js/src/config/env.js.ejs +46 -46
  111. package/templates/mvc/js/src/config/swagger.js.ejs +6 -6
  112. package/templates/mvc/js/src/errors/ApiError.js +14 -14
  113. package/templates/mvc/js/src/graphql/context.js.ejs +7 -7
  114. package/templates/mvc/js/src/graphql/context.spec.js.ejs +29 -29
  115. package/templates/mvc/js/src/graphql/index.js.ejs +5 -5
  116. package/templates/mvc/js/src/graphql/resolvers/index.js.ejs +6 -6
  117. package/templates/mvc/js/src/graphql/typeDefs/index.js.ejs +6 -6
  118. package/templates/mvc/js/src/index.js.ejs +136 -136
  119. package/templates/mvc/js/src/utils/errorMiddleware.js +29 -29
  120. package/templates/mvc/js/src/utils/httpCodes.js +9 -9
  121. package/templates/mvc/js/src/utils/logger.js +40 -40
  122. package/templates/mvc/js/src/utils/logger.spec.js.ejs +63 -63
  123. package/templates/mvc/ts/src/config/env.ts.ejs +45 -45
  124. package/templates/mvc/ts/src/config/swagger.ts.ejs +6 -6
  125. package/templates/mvc/ts/src/errors/ApiError.ts +15 -15
  126. package/templates/mvc/ts/src/graphql/context.spec.ts.ejs +30 -30
  127. package/templates/mvc/ts/src/graphql/context.ts.ejs +12 -12
  128. package/templates/mvc/ts/src/graphql/index.ts.ejs +3 -3
  129. package/templates/mvc/ts/src/graphql/resolvers/index.ts.ejs +4 -4
  130. package/templates/mvc/ts/src/graphql/typeDefs/index.ts.ejs +4 -4
  131. package/templates/mvc/ts/src/utils/errorMiddleware.ts.ejs +27 -27
  132. package/templates/mvc/ts/src/utils/httpCodes.ts +7 -7
  133. package/templates/mvc/ts/src/utils/logger.spec.ts.ejs +63 -63
  134. package/templates/mvc/ts/src/utils/logger.ts +36 -36
@@ -1,6 +1,6 @@
1
- const { mergeResolvers } = require('@graphql-tools/merge');
2
- const { userResolvers } = require('./user.resolvers');
3
-
4
- const resolvers = mergeResolvers([userResolvers]);
5
-
6
- module.exports = { resolvers };
1
+ const { mergeResolvers } = require('@graphql-tools/merge');
2
+ const { userResolvers } = require('./user.resolvers');
3
+
4
+ const resolvers = mergeResolvers([userResolvers]);
5
+
6
+ module.exports = { resolvers };
@@ -1,6 +1,6 @@
1
- const { mergeTypeDefs } = require('@graphql-tools/merge');
2
- const { userTypes } = require('./user.types');
3
-
4
- const typeDefs = mergeTypeDefs([userTypes]);
5
-
6
- module.exports = { typeDefs };
1
+ const { mergeTypeDefs } = require('@graphql-tools/merge');
2
+ const { userTypes } = require('./user.types');
3
+
4
+ const typeDefs = mergeTypeDefs([userTypes]);
5
+
6
+ module.exports = { typeDefs };
@@ -1,137 +1,137 @@
1
- const { env } = require('./config/env');
2
- const express = require('express');
3
- const cors = require('cors');
4
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>const apiRoutes = require('./routes/api');<%_ } %>
5
- const healthRoutes = require('./routes/healthRoute');
6
- <%_ if (communication === 'Kafka') { -%>const { connectKafka, sendMessage } = require('./services/kafkaService');<%_ } -%>
7
- <%_ if (communication === 'GraphQL') { -%>
8
- const { ApolloServer } = require('@apollo/server');
9
- const { expressMiddleware } = require('@as-integrations/express4');
10
- const { ApolloServerPluginLandingPageLocalDefault } = require('@apollo/server/plugin/landingPage/default');
11
- const { unwrapResolverError } = require('@apollo/server/errors');
12
- const { ApiError } = require('./errors/ApiError');
13
- const { typeDefs, resolvers } = require('./graphql');
14
- const { gqlContext } = require('./graphql/context');
15
- <% } %>
16
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
17
- const swaggerUi = require('swagger-ui-express');
18
- const swaggerSpecs = require('./config/swagger');
19
- <%_ } -%>
20
- const setupGracefulShutdown = require('./utils/gracefulShutdown');
21
-
22
- const app = express();
23
- const PORT = env.PORT;
24
- const logger = require('./utils/logger');
25
- const morgan = require('morgan');
26
- const { errorMiddleware } = require('./utils/errorMiddleware');
27
-
28
- app.use(cors());
29
- app.use(express.json());
30
- app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));
31
-
32
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
33
- app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
34
- <%_ } -%>
35
- <%_ if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
36
- // View Engine Setup
37
- const path = require('path');
38
- app.set('views', path.join(__dirname, 'views'));
39
- app.set('view engine', '<%= viewEngine.toLowerCase() %>');
40
- app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
41
- <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
42
- app.use('/api', apiRoutes);
43
- <%_ } -%><% if (viewEngine && viewEngine !== 'None') { -%>
44
- app.get('/', (req, res) => {
45
- res.render('index', {
46
- projectName: 'NodeJS Service',
47
- architecture: 'MVC',
48
- database: '<%= database %>',
49
- communication: '<%= communication %>'
50
- });
51
- });
52
- <% } -%>
53
- app.use('/health', healthRoutes);
54
-
55
- // Start Server Logic
56
- const startServer = async () => {
57
- <%_ if (communication === 'GraphQL') { -%>
58
- // GraphQL Setup
59
- const apolloServer = new ApolloServer({
60
- typeDefs,
61
- resolvers,
62
- plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
63
- formatError: (formattedError, error) => {
64
- const originalError = unwrapResolverError(error);
65
- if (originalError instanceof ApiError) {
66
- return {
67
- ...formattedError,
68
- message: originalError.message,
69
- extensions: {
70
- ...formattedError.extensions,
71
- code: originalError.statusCode.toString(),
72
- }
73
- };
74
- }
75
-
76
- logger.error(`GraphQL Error: ${formattedError.message}`);
77
- if (originalError && originalError.stack && process.env.NODE_ENV === 'development') {
78
- logger.error(originalError.stack);
79
- }
80
- return formattedError;
81
- },
82
- });
83
- await apolloServer.start();
84
- app.use('/graphql', expressMiddleware(apolloServer, { context: gqlContext }));
85
- <%_ } -%>
86
- app.use(errorMiddleware);
87
- const server = app.listen(PORT, () => {
88
- logger.info(`Server running on port ${PORT}`);
89
- <%_ if (communication === 'Kafka') { -%>
90
- connectKafka()
91
- .then(async () => {
92
- logger.info('Kafka connected');
93
- })
94
- .catch(err => {
95
- logger.error('Failed to connect to Kafka after retries:', err.message);
96
- });
97
- <%_ } -%>
98
- });
99
-
100
- setupGracefulShutdown(server);
101
- };
102
-
103
- <%_ if (database !== 'None') { -%>
104
- // Database Sync
105
- <%_ if (database !== 'None') { -%>
106
- <%_ if (database === 'MongoDB') { -%>
107
- const connectDB = require('./config/database');
108
- <%_ } else { -%>
109
- const sequelize = require('./config/database');
110
- <%_ } -%>
111
- <%_ } -%>
112
- const syncDatabase = async () => {
113
- let retries = 30;
114
- while (retries) {
115
- try {
116
- <%_ if (database === 'MongoDB') { -%>
117
- await connectDB();
118
- <%_ } else { -%>
119
- await sequelize.sync();
120
- <%_ } -%>
121
- logger.info('Database synced');
122
- // Start Server after DB is ready
123
- await startServer();
124
- break;
125
- } catch (err) {
126
- logger.error('Database sync failed:', err);
127
- retries -= 1;
128
- logger.info(`Retries left: ${retries}. Waiting 5s...`);
129
- await new Promise(res => setTimeout(res, 5000));
130
- }
131
- }
132
- };
133
-
134
- syncDatabase();
135
- <%_ } else { -%>
136
- startServer();
1
+ const { env } = require('./config/env');
2
+ const express = require('express');
3
+ const cors = require('cors');
4
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>const apiRoutes = require('./routes/api');<%_ } %>
5
+ const healthRoutes = require('./routes/healthRoute');
6
+ <%_ if (communication === 'Kafka') { -%>const { connectKafka, sendMessage } = require('./services/kafkaService');<%_ } -%>
7
+ <%_ if (communication === 'GraphQL') { -%>
8
+ const { ApolloServer } = require('@apollo/server');
9
+ const { expressMiddleware } = require('@as-integrations/express4');
10
+ const { ApolloServerPluginLandingPageLocalDefault } = require('@apollo/server/plugin/landingPage/default');
11
+ const { unwrapResolverError } = require('@apollo/server/errors');
12
+ const { ApiError } = require('./errors/ApiError');
13
+ const { typeDefs, resolvers } = require('./graphql');
14
+ const { gqlContext } = require('./graphql/context');
15
+ <% } %>
16
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
17
+ const swaggerUi = require('swagger-ui-express');
18
+ const swaggerSpecs = require('./config/swagger');
19
+ <%_ } -%>
20
+ const setupGracefulShutdown = require('./utils/gracefulShutdown');
21
+
22
+ const app = express();
23
+ const PORT = env.PORT;
24
+ const logger = require('./utils/logger');
25
+ const morgan = require('morgan');
26
+ const { errorMiddleware } = require('./utils/errorMiddleware');
27
+
28
+ app.use(cors());
29
+ app.use(express.json());
30
+ app.use(morgan('combined', { stream: { write: message => logger.info(message.trim()) } }));
31
+
32
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
33
+ app.use('/api-docs', swaggerUi.serve, swaggerUi.setup(swaggerSpecs));
34
+ <%_ } -%>
35
+ <%_ if (viewEngine === 'EJS' || viewEngine === 'Pug') { -%>
36
+ // View Engine Setup
37
+ const path = require('path');
38
+ app.set('views', path.join(__dirname, 'views'));
39
+ app.set('view engine', '<%= viewEngine.toLowerCase() %>');
40
+ app.use(express.static(path.join(__dirname, '../public')));<%_ } %>
41
+ <%_ if (communication === 'REST APIs' || communication === 'Kafka') { -%>
42
+ app.use('/api', apiRoutes);
43
+ <%_ } -%><% if (viewEngine && viewEngine !== 'None') { -%>
44
+ app.get('/', (req, res) => {
45
+ res.render('index', {
46
+ projectName: 'NodeJS Service',
47
+ architecture: 'MVC',
48
+ database: '<%= database %>',
49
+ communication: '<%= communication %>'
50
+ });
51
+ });
52
+ <% } -%>
53
+ app.use('/health', healthRoutes);
54
+
55
+ // Start Server Logic
56
+ const startServer = async () => {
57
+ <%_ if (communication === 'GraphQL') { -%>
58
+ // GraphQL Setup
59
+ const apolloServer = new ApolloServer({
60
+ typeDefs,
61
+ resolvers,
62
+ plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
63
+ formatError: (formattedError, error) => {
64
+ const originalError = unwrapResolverError(error);
65
+ if (originalError instanceof ApiError) {
66
+ return {
67
+ ...formattedError,
68
+ message: originalError.message,
69
+ extensions: {
70
+ ...formattedError.extensions,
71
+ code: originalError.statusCode.toString(),
72
+ }
73
+ };
74
+ }
75
+
76
+ logger.error(`GraphQL Error: ${formattedError.message}`);
77
+ if (originalError && originalError.stack && process.env.NODE_ENV === 'development') {
78
+ logger.error(originalError.stack);
79
+ }
80
+ return formattedError;
81
+ },
82
+ });
83
+ await apolloServer.start();
84
+ app.use('/graphql', expressMiddleware(apolloServer, { context: gqlContext }));
85
+ <%_ } -%>
86
+ app.use(errorMiddleware);
87
+ const server = app.listen(PORT, () => {
88
+ logger.info(`Server running on port ${PORT}`);
89
+ <%_ if (communication === 'Kafka') { -%>
90
+ connectKafka()
91
+ .then(async () => {
92
+ logger.info('Kafka connected');
93
+ })
94
+ .catch(err => {
95
+ logger.error('Failed to connect to Kafka after retries:', err.message);
96
+ });
97
+ <%_ } -%>
98
+ });
99
+
100
+ setupGracefulShutdown(server);
101
+ };
102
+
103
+ <%_ if (database !== 'None') { -%>
104
+ // Database Sync
105
+ <%_ if (database !== 'None') { -%>
106
+ <%_ if (database === 'MongoDB') { -%>
107
+ const connectDB = require('./config/database');
108
+ <%_ } else { -%>
109
+ const sequelize = require('./config/database');
110
+ <%_ } -%>
111
+ <%_ } -%>
112
+ const syncDatabase = async () => {
113
+ let retries = 30;
114
+ while (retries) {
115
+ try {
116
+ <%_ if (database === 'MongoDB') { -%>
117
+ await connectDB();
118
+ <%_ } else { -%>
119
+ await sequelize.sync();
120
+ <%_ } -%>
121
+ logger.info('Database synced');
122
+ // Start Server after DB is ready
123
+ await startServer();
124
+ break;
125
+ } catch (err) {
126
+ logger.error('Database sync failed:', err);
127
+ retries -= 1;
128
+ logger.info(`Retries left: ${retries}. Waiting 5s...`);
129
+ await new Promise(res => setTimeout(res, 5000));
130
+ }
131
+ }
132
+ };
133
+
134
+ syncDatabase();
135
+ <%_ } else { -%>
136
+ startServer();
137
137
  <%_ } -%>
@@ -1,29 +1,29 @@
1
- const logger = require('./logger');
2
- const { ApiError } = require('../errors/ApiError');
3
- const HTTP_STATUS = require('./httpCodes');
4
-
5
- // eslint-disable-next-line no-unused-vars
6
- const errorMiddleware = (err, req, res, next) => {
7
- let error = err;
8
-
9
- if (!(error instanceof ApiError)) {
10
- const statusCode = err.statusCode || HTTP_STATUS.INTERNAL_SERVER_ERROR;
11
- const message = error.message || 'Internal Server Error';
12
- error = new ApiError(statusCode, message, false, err.stack);
13
- }
14
-
15
- const { statusCode, message } = error;
16
-
17
- if (statusCode === HTTP_STATUS.INTERNAL_SERVER_ERROR) {
18
- logger.error(`${statusCode} - ${message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
19
- logger.error(error.stack || 'No stack trace');
20
- }
21
-
22
- res.status(statusCode).json({
23
- statusCode,
24
- message,
25
- ...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
26
- });
27
- };
28
-
29
- module.exports = { errorMiddleware };
1
+ const logger = require('./logger');
2
+ const { ApiError } = require('../errors/ApiError');
3
+ const HTTP_STATUS = require('./httpCodes');
4
+
5
+ // eslint-disable-next-line no-unused-vars
6
+ const errorMiddleware = (err, req, res, next) => {
7
+ let error = err;
8
+
9
+ if (!(error instanceof ApiError)) {
10
+ const statusCode = err.statusCode || HTTP_STATUS.INTERNAL_SERVER_ERROR;
11
+ const message = error.message || 'Internal Server Error';
12
+ error = new ApiError(statusCode, message, false, err.stack);
13
+ }
14
+
15
+ const { statusCode, message } = error;
16
+
17
+ if (statusCode === HTTP_STATUS.INTERNAL_SERVER_ERROR) {
18
+ logger.error(`${statusCode} - ${message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
19
+ logger.error(error.stack || 'No stack trace');
20
+ }
21
+
22
+ res.status(statusCode).json({
23
+ statusCode,
24
+ message,
25
+ ...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
26
+ });
27
+ };
28
+
29
+ module.exports = { errorMiddleware };
@@ -1,9 +1,9 @@
1
- const HTTP_STATUS = {
2
- OK: 200,
3
- CREATED: 201,
4
- BAD_REQUEST: 400,
5
- NOT_FOUND: 404,
6
- INTERNAL_SERVER_ERROR: 500
7
- };
8
-
9
- module.exports = HTTP_STATUS;
1
+ const HTTP_STATUS = {
2
+ OK: 200,
3
+ CREATED: 201,
4
+ BAD_REQUEST: 400,
5
+ NOT_FOUND: 404,
6
+ INTERNAL_SERVER_ERROR: 500
7
+ };
8
+
9
+ module.exports = HTTP_STATUS;
@@ -1,40 +1,40 @@
1
- const winston = require('winston');
2
- require('winston-daily-rotate-file');
3
-
4
- const logger = winston.createLogger({
5
- level: 'info',
6
- format: winston.format.combine(
7
- winston.format.timestamp(),
8
- winston.format.json()
9
- ),
10
- defaultMeta: { service: 'user-service' },
11
- transports: [
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
- }),
27
- ],
28
- });
29
-
30
- //
31
- // If we're not in production then log to the `console` with the format:
32
- // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
33
- //
34
- logger.add(new winston.transports.Console({
35
- format: process.env.NODE_ENV !== 'production'
36
- ? winston.format.simple()
37
- : winston.format.json(),
38
- }));
39
-
40
- module.exports = logger;
1
+ const winston = require('winston');
2
+ require('winston-daily-rotate-file');
3
+
4
+ const logger = winston.createLogger({
5
+ level: 'info',
6
+ format: winston.format.combine(
7
+ winston.format.timestamp(),
8
+ winston.format.json()
9
+ ),
10
+ defaultMeta: { service: 'user-service' },
11
+ transports: [
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
+ }),
27
+ ],
28
+ });
29
+
30
+ //
31
+ // If we're not in production then log to the `console` with the format:
32
+ // `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
33
+ //
34
+ logger.add(new winston.transports.Console({
35
+ format: process.env.NODE_ENV !== 'production'
36
+ ? winston.format.simple()
37
+ : winston.format.json(),
38
+ }));
39
+
40
+ module.exports = logger;
@@ -1,63 +1,63 @@
1
- jest.mock('winston-daily-rotate-file');
2
- jest.mock('winston', () => {
3
- const mockLogger = {
4
- add: jest.fn(),
5
- info: jest.fn(),
6
- error: jest.fn(),
7
- warn: jest.fn()
8
- };
9
- const format = {
10
- combine: jest.fn(),
11
- timestamp: jest.fn(),
12
- json: jest.fn(),
13
- simple: jest.fn()
14
- };
15
- const transports = {
16
- Console: jest.fn(),
17
- DailyRotateFile: jest.fn()
18
- };
19
- return {
20
- format,
21
- transports,
22
- createLogger: jest.fn().mockReturnValue(mockLogger)
23
- };
24
- });
25
-
26
- <% if (architecture === 'MVC') { -%>
27
- const logger = require('@/utils/logger');
28
- <% } else { -%>
29
- const logger = require('@/infrastructure/log/logger');
30
- <% } -%>
31
-
32
- describe('Logger', () => {
33
- it('should export a logger instance', () => {
34
- expect(logger).toBeDefined();
35
- });
36
-
37
- it('should have info method', () => {
38
- expect(typeof logger.info).toBe('function');
39
- });
40
-
41
- it('should have error method', () => {
42
- expect(typeof logger.error).toBe('function');
43
- });
44
-
45
- it('should call info', () => {
46
- logger.info('test message');
47
- expect(logger.info).toHaveBeenCalledWith('test message');
48
- });
49
-
50
- it('should call error', () => {
51
- logger.error('test error');
52
- expect(logger.error).toHaveBeenCalledWith('test error');
53
- });
54
-
55
- it('should use JSON format in production environment', () => {
56
- const winston = require('winston');
57
- jest.resetModules();
58
- process.env.NODE_ENV = 'production';
59
- require('@/utils/logger');
60
- expect(winston.format.json).toHaveBeenCalled();
61
- process.env.NODE_ENV = 'test';
62
- });
63
- });
1
+ jest.mock('winston-daily-rotate-file');
2
+ jest.mock('winston', () => {
3
+ const mockLogger = {
4
+ add: jest.fn(),
5
+ info: jest.fn(),
6
+ error: jest.fn(),
7
+ warn: jest.fn()
8
+ };
9
+ const format = {
10
+ combine: jest.fn(),
11
+ timestamp: jest.fn(),
12
+ json: jest.fn(),
13
+ simple: jest.fn()
14
+ };
15
+ const transports = {
16
+ Console: jest.fn(),
17
+ DailyRotateFile: jest.fn()
18
+ };
19
+ return {
20
+ format,
21
+ transports,
22
+ createLogger: jest.fn().mockReturnValue(mockLogger)
23
+ };
24
+ });
25
+
26
+ <% if (architecture === 'MVC') { -%>
27
+ const logger = require('@/utils/logger');
28
+ <% } else { -%>
29
+ const logger = require('@/infrastructure/log/logger');
30
+ <% } -%>
31
+
32
+ describe('Logger', () => {
33
+ it('should export a logger instance', () => {
34
+ expect(logger).toBeDefined();
35
+ });
36
+
37
+ it('should have info method', () => {
38
+ expect(typeof logger.info).toBe('function');
39
+ });
40
+
41
+ it('should have error method', () => {
42
+ expect(typeof logger.error).toBe('function');
43
+ });
44
+
45
+ it('should call info', () => {
46
+ logger.info('test message');
47
+ expect(logger.info).toHaveBeenCalledWith('test message');
48
+ });
49
+
50
+ it('should call error', () => {
51
+ logger.error('test error');
52
+ expect(logger.error).toHaveBeenCalledWith('test error');
53
+ });
54
+
55
+ it('should use JSON format in production environment', () => {
56
+ const winston = require('winston');
57
+ jest.resetModules();
58
+ process.env.NODE_ENV = 'production';
59
+ require('@/utils/logger');
60
+ expect(winston.format.json).toHaveBeenCalled();
61
+ process.env.NODE_ENV = 'test';
62
+ });
63
+ });