nodejs-quickstart-structure 1.10.1 → 1.11.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.
- package/CHANGELOG.md +22 -0
- package/README.md +4 -0
- package/docs/generateCase.md +245 -165
- package/docs/generatorFlow.md +65 -23
- package/lib/generator.js +4 -1
- package/lib/modules/app-setup.js +56 -5
- package/package.json +1 -1
- package/templates/clean-architecture/js/src/errors/ApiError.js +14 -0
- package/templates/clean-architecture/js/src/errors/BadRequestError.js +10 -0
- package/templates/clean-architecture/js/src/errors/NotFoundError.js +10 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/middlewares/error.middleware.js +29 -0
- package/templates/clean-architecture/js/src/infrastructure/webserver/server.js.ejs +24 -0
- package/templates/clean-architecture/js/src/interfaces/controllers/userController.js.ejs +4 -7
- package/templates/clean-architecture/js/src/interfaces/graphql/resolvers/user.resolvers.js.ejs +2 -11
- package/templates/clean-architecture/js/src/interfaces/routes/api.js +2 -2
- package/templates/clean-architecture/ts/src/errors/ApiError.ts +15 -0
- package/templates/clean-architecture/ts/src/errors/BadRequestError.ts +8 -0
- package/templates/clean-architecture/ts/src/errors/NotFoundError.ts +8 -0
- package/templates/clean-architecture/ts/src/index.ts.ejs +23 -0
- package/templates/clean-architecture/ts/src/interfaces/controllers/userController.ts.ejs +13 -19
- package/templates/clean-architecture/ts/src/interfaces/graphql/resolvers/user.resolvers.ts.ejs +4 -13
- package/templates/clean-architecture/ts/src/interfaces/routes/userRoutes.ts +4 -3
- package/templates/clean-architecture/ts/src/utils/error.middleware.ts.ejs +27 -0
- package/templates/common/package.json.ejs +5 -6
- package/templates/mvc/js/src/controllers/userController.js.ejs +5 -4
- package/templates/mvc/js/src/errors/ApiError.js +14 -0
- package/templates/mvc/js/src/errors/BadRequestError.js +10 -0
- package/templates/mvc/js/src/errors/NotFoundError.js +10 -0
- package/templates/mvc/js/src/graphql/resolvers/user.resolvers.js.ejs +2 -11
- package/templates/mvc/js/src/index.js.ejs +23 -0
- package/templates/mvc/js/src/utils/error.middleware.js +28 -0
- package/templates/mvc/ts/src/controllers/userController.ts.ejs +6 -14
- package/templates/mvc/ts/src/errors/ApiError.ts +15 -0
- package/templates/mvc/ts/src/errors/BadRequestError.ts +8 -0
- package/templates/mvc/ts/src/errors/NotFoundError.ts +8 -0
- package/templates/mvc/ts/src/graphql/resolvers/user.resolvers.ts.ejs +4 -13
- package/templates/mvc/ts/src/index.ts.ejs +23 -0
- package/templates/mvc/ts/src/routes/api.ts +3 -3
- package/templates/mvc/ts/src/utils/error.middleware.ts.ejs +27 -0
- /package/templates/clean-architecture/js/src/infrastructure/webserver/{swagger.js → swagger.js.ejs} +0 -0
- /package/templates/clean-architecture/ts/src/infrastructure/repositories/{userRepository.ts.ejs → UserRepository.ts.ejs} +0 -0
- /package/templates/mvc/js/src/config/{swagger.js → swagger.js.ejs} +0 -0
|
@@ -1,10 +1,11 @@
|
|
|
1
|
-
import { Router, Request, Response } from 'express';
|
|
1
|
+
import { Router, Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { UserController } from '@/interfaces/controllers/userController';
|
|
3
3
|
|
|
4
4
|
const router = Router();
|
|
5
5
|
const userController = new UserController();
|
|
6
6
|
|
|
7
|
-
router.post('/', (req: Request, res: Response) => userController.createUser(req, res));
|
|
8
|
-
router.get('/', (req: Request, res: Response) => userController.getUsers(req, res));
|
|
7
|
+
router.post('/', (req: Request, res: Response, next: NextFunction) => userController.createUser(req, res, next));
|
|
8
|
+
router.get('/', (req: Request, res: Response, next: NextFunction) => userController.getUsers(req, res, next));
|
|
9
9
|
|
|
10
10
|
export default router;
|
|
11
|
+
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import logger from '@/infrastructure/log/logger';
|
|
3
|
+
import { ApiError } from '@/errors/ApiError';
|
|
4
|
+
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
5
|
+
|
|
6
|
+
export const errorMiddleware = (err: Error, req: Request, res: Response, _: unknown) => {
|
|
7
|
+
let error = err;
|
|
8
|
+
|
|
9
|
+
if (!(error instanceof ApiError)) {
|
|
10
|
+
const 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 as ApiError;
|
|
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
|
+
};
|
|
@@ -11,12 +11,11 @@
|
|
|
11
11
|
"lint:fix": "eslint . --fix",
|
|
12
12
|
"format": "prettier --write .",
|
|
13
13
|
"prepare": "node -e \"try { require('child_process').execSync('husky install'); } catch (e) { console.log('Not a git repository, skipping husky install'); }\"",
|
|
14
|
+
<% if (database === 'MongoDB') { %> "migrate": "migrate-mongo up",
|
|
15
|
+
<% } -%>
|
|
14
16
|
"test": "jest",
|
|
15
17
|
"test:watch": "jest --watch",
|
|
16
18
|
"test:coverage": "jest --coverage"
|
|
17
|
-
<%_ if (database === 'MongoDB') { -%>,
|
|
18
|
-
"migrate": "migrate-mongo up"
|
|
19
|
-
<%_ } -%>
|
|
20
19
|
},
|
|
21
20
|
"dependencies": {
|
|
22
21
|
"express": "^4.18.2",
|
|
@@ -80,9 +79,9 @@
|
|
|
80
79
|
"eslint-config-prettier": "^10.0.1",
|
|
81
80
|
"husky": "^8.0.3",
|
|
82
81
|
"lint-staged": "^15.4.3"<% if (language === 'TypeScript') { %>,
|
|
83
|
-
"typescript-eslint": "^8.24.1"
|
|
84
|
-
|
|
85
|
-
"@types/yamljs": "^0.2.34",<% }
|
|
82
|
+
"typescript-eslint": "^8.24.1",<%_ if (communication === 'REST APIs') { %>
|
|
83
|
+
"@types/swagger-ui-express": "^4.1.6",
|
|
84
|
+
"@types/yamljs": "^0.2.34",<%_ } -%>
|
|
86
85
|
"jest": "^29.7.0",
|
|
87
86
|
"ts-jest": "^29.2.5",
|
|
88
87
|
"@types/jest": "^29.5.14",
|
|
@@ -61,7 +61,7 @@ const createUser = async (data) => {
|
|
|
61
61
|
}
|
|
62
62
|
};
|
|
63
63
|
<% } else { -%>
|
|
64
|
-
const getUsers = async (req, res) => {
|
|
64
|
+
const getUsers = async (req, res, next) => {
|
|
65
65
|
try {
|
|
66
66
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
67
67
|
const users = await cacheService.getOrSet('users:all', async () => {
|
|
@@ -85,11 +85,11 @@ const getUsers = async (req, res) => {
|
|
|
85
85
|
res.json(users);
|
|
86
86
|
} catch (error) {
|
|
87
87
|
logger.error('Error fetching users:', error);
|
|
88
|
-
|
|
88
|
+
next(error);
|
|
89
89
|
}
|
|
90
90
|
};
|
|
91
91
|
|
|
92
|
-
const createUser = async (req, res) => {
|
|
92
|
+
const createUser = async (req, res, next) => {
|
|
93
93
|
try {
|
|
94
94
|
const { name, email } = req.body;
|
|
95
95
|
<%_ if (database === 'None') { -%>
|
|
@@ -107,7 +107,8 @@ const createUser = async (req, res) => {
|
|
|
107
107
|
res.status(HTTP_STATUS.CREATED).json(user);
|
|
108
108
|
<%_ } -%>
|
|
109
109
|
} catch (error) {
|
|
110
|
-
|
|
110
|
+
logger.error('Error creating user:', error);
|
|
111
|
+
next(error);
|
|
111
112
|
}
|
|
112
113
|
};
|
|
113
114
|
<% } -%>
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
class ApiError extends Error {
|
|
2
|
+
constructor(statusCode, message, isOperational = true, stack = '') {
|
|
3
|
+
super(message);
|
|
4
|
+
this.statusCode = statusCode;
|
|
5
|
+
this.isOperational = isOperational;
|
|
6
|
+
if (stack) {
|
|
7
|
+
this.stack = stack;
|
|
8
|
+
} else {
|
|
9
|
+
Error.captureStackTrace(this, this.constructor);
|
|
10
|
+
}
|
|
11
|
+
}
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
module.exports = { ApiError };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { ApiError } = require('./ApiError');
|
|
2
|
+
const { HTTP_STATUS } = require('../utils/httpCodes');
|
|
3
|
+
|
|
4
|
+
class BadRequestError extends ApiError {
|
|
5
|
+
constructor(message = 'Bad request') {
|
|
6
|
+
super(HTTP_STATUS.BAD_REQUEST, message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = { BadRequestError };
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
const { ApiError } = require('./ApiError');
|
|
2
|
+
const { HTTP_STATUS } = require('../utils/httpCodes');
|
|
3
|
+
|
|
4
|
+
class NotFoundError extends ApiError {
|
|
5
|
+
constructor(message = 'Resource not found') {
|
|
6
|
+
super(HTTP_STATUS.NOT_FOUND, message);
|
|
7
|
+
}
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
module.exports = { NotFoundError };
|
|
@@ -1,23 +1,14 @@
|
|
|
1
|
-
const { GraphQLError } = require('graphql');
|
|
2
1
|
const userController = require('../../controllers/userController');
|
|
3
2
|
|
|
4
3
|
const userResolvers = {
|
|
5
4
|
Query: {
|
|
6
5
|
getAllUsers: async () => {
|
|
7
|
-
|
|
8
|
-
return await userController.getUsers();
|
|
9
|
-
} catch (error) {
|
|
10
|
-
throw new GraphQLError(error.message || 'Internal server error', { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
11
|
-
}
|
|
6
|
+
return await userController.getUsers();
|
|
12
7
|
}
|
|
13
8
|
},
|
|
14
9
|
Mutation: {
|
|
15
10
|
createUser: async (_, { name, email }) => {
|
|
16
|
-
|
|
17
|
-
return await userController.createUser({ name, email });
|
|
18
|
-
} catch (error) {
|
|
19
|
-
throw new GraphQLError(error.message || 'Internal server error', { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
20
|
-
}
|
|
11
|
+
return await userController.createUser({ name, email });
|
|
21
12
|
}
|
|
22
13
|
}
|
|
23
14
|
};
|
|
@@ -7,6 +7,8 @@ require('dotenv').config();
|
|
|
7
7
|
const { ApolloServer } = require('@apollo/server');
|
|
8
8
|
const { expressMiddleware } = require('@apollo/server/express4');
|
|
9
9
|
const { ApolloServerPluginLandingPageLocalDefault } = require('@apollo/server/plugin/landingPage/default');
|
|
10
|
+
const { unwrapResolverError } = require('@apollo/server/errors');
|
|
11
|
+
const { ApiError } = require('./errors/ApiError');
|
|
10
12
|
const { typeDefs, resolvers } = require('./graphql');
|
|
11
13
|
const { gqlContext } = require('./graphql/context');
|
|
12
14
|
<% } -%>
|
|
@@ -19,6 +21,7 @@ const app = express();
|
|
|
19
21
|
const PORT = process.env.PORT || 3000;
|
|
20
22
|
const logger = require('./utils/logger');
|
|
21
23
|
const morgan = require('morgan');
|
|
24
|
+
const { errorMiddleware } = require('./utils/error.middleware');
|
|
22
25
|
|
|
23
26
|
app.use(cors());
|
|
24
27
|
app.use(express.json());
|
|
@@ -57,10 +60,30 @@ const startServer = async () => {
|
|
|
57
60
|
typeDefs,
|
|
58
61
|
resolvers,
|
|
59
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
|
+
},
|
|
60
82
|
});
|
|
61
83
|
await server.start();
|
|
62
84
|
app.use('/graphql', expressMiddleware(server, { context: gqlContext }));
|
|
63
85
|
<%_ } -%>
|
|
86
|
+
app.use(errorMiddleware);
|
|
64
87
|
app.listen(PORT, () => {
|
|
65
88
|
logger.info(`Server running on port ${PORT}`);
|
|
66
89
|
<%_ if (communication === 'Kafka') { -%>
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
const logger = require('./logger');
|
|
2
|
+
const { ApiError } = require('../errors/ApiError');
|
|
3
|
+
const HTTP_STATUS = require('./httpCodes');
|
|
4
|
+
|
|
5
|
+
const errorMiddleware = (err, req, res, _) => {
|
|
6
|
+
let error = err;
|
|
7
|
+
|
|
8
|
+
if (!(error instanceof ApiError)) {
|
|
9
|
+
const statusCode = err.statusCode || HTTP_STATUS.INTERNAL_SERVER_ERROR;
|
|
10
|
+
const message = error.message || 'Internal Server Error';
|
|
11
|
+
error = new ApiError(statusCode, message, false, err.stack);
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
const { statusCode, message } = error;
|
|
15
|
+
|
|
16
|
+
if (statusCode === HTTP_STATUS.INTERNAL_SERVER_ERROR) {
|
|
17
|
+
logger.error(`${statusCode} - ${message} - ${req.originalUrl} - ${req.method} - ${req.ip}`);
|
|
18
|
+
logger.error(error.stack || 'No stack trace');
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
res.status(statusCode).json({
|
|
22
|
+
statusCode,
|
|
23
|
+
message,
|
|
24
|
+
...(process.env.NODE_ENV === 'development' && { stack: error.stack }),
|
|
25
|
+
});
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
module.exports = { errorMiddleware };
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
<% if (communication !== 'GraphQL') { -%>
|
|
2
|
-
import { Request, Response } from 'express';
|
|
2
|
+
import { Request, Response, NextFunction } from 'express';
|
|
3
3
|
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
4
4
|
<% } -%>
|
|
5
5
|
import User from '@/models/User';
|
|
@@ -63,7 +63,7 @@ export class UserController {
|
|
|
63
63
|
}
|
|
64
64
|
}
|
|
65
65
|
<% } else { -%>
|
|
66
|
-
async getUsers(req: Request, res: Response) {
|
|
66
|
+
async getUsers(req: Request, res: Response, next: NextFunction) {
|
|
67
67
|
try {
|
|
68
68
|
<%_ if (caching === 'Redis' || caching === 'Memory Cache') { -%>
|
|
69
69
|
const users = await cacheService.getOrSet('users:all', async () => {
|
|
@@ -86,16 +86,12 @@ export class UserController {
|
|
|
86
86
|
<%_ } -%>
|
|
87
87
|
res.json(users);
|
|
88
88
|
} catch (error) {
|
|
89
|
-
logger.error('Error fetching
|
|
90
|
-
|
|
91
|
-
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
|
|
92
|
-
} else {
|
|
93
|
-
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: 'Unknown error occurred' });
|
|
94
|
-
}
|
|
89
|
+
logger.error('Error fetching user:', error);
|
|
90
|
+
next(error);
|
|
95
91
|
}
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
async createUser(req: Request, res: Response) {
|
|
94
|
+
async createUser(req: Request, res: Response, next: NextFunction) {
|
|
99
95
|
try {
|
|
100
96
|
const { name, email } = req.body;
|
|
101
97
|
<%_ if (database === 'None') { -%>
|
|
@@ -114,11 +110,7 @@ export class UserController {
|
|
|
114
110
|
<%_ } -%>
|
|
115
111
|
} catch (error) {
|
|
116
112
|
logger.error('Error creating user:', error);
|
|
117
|
-
|
|
118
|
-
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: error.message });
|
|
119
|
-
} else {
|
|
120
|
-
res.status(HTTP_STATUS.INTERNAL_SERVER_ERROR).json({ error: 'Unknown error occurred' });
|
|
121
|
-
}
|
|
113
|
+
next(error);
|
|
122
114
|
}
|
|
123
115
|
}
|
|
124
116
|
<% } -%>
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
export class ApiError extends Error {
|
|
2
|
+
statusCode: number;
|
|
3
|
+
isOperational: boolean;
|
|
4
|
+
|
|
5
|
+
constructor(statusCode: number, message: string, isOperational = true, stack = '') {
|
|
6
|
+
super(message);
|
|
7
|
+
this.statusCode = statusCode;
|
|
8
|
+
this.isOperational = isOperational;
|
|
9
|
+
if (stack) {
|
|
10
|
+
this.stack = stack;
|
|
11
|
+
} else {
|
|
12
|
+
Error.captureStackTrace(this, this.constructor);
|
|
13
|
+
}
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { GraphQLError } from 'graphql';
|
|
2
1
|
import { UserController } from '@/controllers/userController';
|
|
3
2
|
|
|
4
3
|
const userController = new UserController();
|
|
@@ -6,22 +5,14 @@ const userController = new UserController();
|
|
|
6
5
|
export const userResolvers = {
|
|
7
6
|
Query: {
|
|
8
7
|
getAllUsers: async () => {
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
} catch (error: unknown) {
|
|
12
|
-
const message = error instanceof Error ? error.message : 'Internal server error';
|
|
13
|
-
throw new GraphQLError(message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
14
|
-
}
|
|
8
|
+
const users = await userController.getUsers();
|
|
9
|
+
return users;
|
|
15
10
|
}
|
|
16
11
|
},
|
|
17
12
|
Mutation: {
|
|
18
13
|
createUser: async (_: unknown, { name, email }: { name: string, email: string }) => {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
} catch (error: unknown) {
|
|
22
|
-
const message = error instanceof Error ? error.message : 'Internal server error';
|
|
23
|
-
throw new GraphQLError(message, { extensions: { code: 'INTERNAL_SERVER_ERROR' } });
|
|
24
|
-
}
|
|
14
|
+
const user = await userController.createUser({ name, email });
|
|
15
|
+
return user;
|
|
25
16
|
}
|
|
26
17
|
}
|
|
27
18
|
};
|
|
@@ -6,6 +6,7 @@ import rateLimit from 'express-rate-limit';
|
|
|
6
6
|
import dotenv from 'dotenv';
|
|
7
7
|
import logger from '@/utils/logger';
|
|
8
8
|
import morgan from 'morgan';
|
|
9
|
+
import { errorMiddleware } from '@/utils/error.middleware';
|
|
9
10
|
<%_ if (communication === 'REST APIs') { -%>
|
|
10
11
|
import apiRoutes from '@/routes/api';<%_ } -%>
|
|
11
12
|
<% if (communication === 'REST APIs') { %>
|
|
@@ -16,6 +17,8 @@ import swaggerSpecs from '@/config/swagger';<% } -%>
|
|
|
16
17
|
import { ApolloServer } from '@apollo/server';
|
|
17
18
|
import { expressMiddleware } from '@apollo/server/express4';
|
|
18
19
|
import { ApolloServerPluginLandingPageLocalDefault } from '@apollo/server/plugin/landingPage/default';
|
|
20
|
+
import { unwrapResolverError } from '@apollo/server/errors';
|
|
21
|
+
import { ApiError } from '@/errors/ApiError';
|
|
19
22
|
import { typeDefs, resolvers } from '@/graphql';
|
|
20
23
|
import { gqlContext, MyContext } from '@/graphql/context';
|
|
21
24
|
<% } -%>
|
|
@@ -81,10 +84,30 @@ const startServer = async () => {
|
|
|
81
84
|
typeDefs,
|
|
82
85
|
resolvers,
|
|
83
86
|
plugins: [ApolloServerPluginLandingPageLocalDefault({ embed: true })],
|
|
87
|
+
formatError: (formattedError, error) => {
|
|
88
|
+
const originalError = unwrapResolverError(error);
|
|
89
|
+
if (originalError instanceof ApiError) {
|
|
90
|
+
return {
|
|
91
|
+
...formattedError,
|
|
92
|
+
message: originalError.message,
|
|
93
|
+
extensions: {
|
|
94
|
+
...formattedError.extensions,
|
|
95
|
+
code: originalError.statusCode.toString(),
|
|
96
|
+
}
|
|
97
|
+
};
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
logger.error(`GraphQL Error: ${formattedError.message}`);
|
|
101
|
+
if (originalError instanceof Error && originalError.stack && process.env.NODE_ENV === 'development') {
|
|
102
|
+
logger.error(originalError.stack);
|
|
103
|
+
}
|
|
104
|
+
return formattedError;
|
|
105
|
+
},
|
|
84
106
|
});
|
|
85
107
|
await server.start();
|
|
86
108
|
app.use('/graphql', expressMiddleware(server, { context: gqlContext }));
|
|
87
109
|
<%_ } -%>
|
|
110
|
+
app.use(errorMiddleware);
|
|
88
111
|
app.listen(port, () => {
|
|
89
112
|
logger.info(`Server running on port ${port}`);
|
|
90
113
|
<%_ if (communication === 'Kafka') { -%>
|
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { Router, Request, Response } from 'express';
|
|
1
|
+
import { Router, Request, Response, NextFunction } from 'express';
|
|
2
2
|
import { UserController } from '@/controllers/userController';
|
|
3
3
|
|
|
4
4
|
const router = Router();
|
|
5
5
|
const userController = new UserController();
|
|
6
6
|
|
|
7
|
-
router.get('/users', (req: Request, res: Response) => userController.getUsers(req, res));
|
|
8
|
-
router.post('/users', (req: Request, res: Response) => userController.createUser(req, res));
|
|
7
|
+
router.get('/users', (req: Request, res: Response, next: NextFunction) => userController.getUsers(req, res, next));
|
|
8
|
+
router.post('/users', (req: Request, res: Response, next: NextFunction) => userController.createUser(req, res, next));
|
|
9
9
|
|
|
10
10
|
export default router;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import { Request, Response } from 'express';
|
|
2
|
+
import logger from '@/utils/logger';
|
|
3
|
+
import { ApiError } from '@/errors/ApiError';
|
|
4
|
+
import { HTTP_STATUS } from '@/utils/httpCodes';
|
|
5
|
+
|
|
6
|
+
export const errorMiddleware = (err: Error, req: Request, res: Response, _: unknown) => {
|
|
7
|
+
let error = err;
|
|
8
|
+
|
|
9
|
+
if (!(error instanceof ApiError)) {
|
|
10
|
+
const 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 as ApiError;
|
|
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
|
+
};
|
/package/templates/clean-architecture/js/src/infrastructure/webserver/{swagger.js → swagger.js.ejs}
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|