Skip to content

Commit 2ad571e

Browse files
authored
Express server optimization (#16)
* optimization wip * express-server done
1 parent 6a78353 commit 2ad571e

File tree

20 files changed

+138
-101
lines changed

20 files changed

+138
-101
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ You can clone the full repo and keep only the packages you need in your monorepo
1010
- [React](https://reactjs.org/), [NestJs](https://nestjs.com/), [ExpressJS](https://expressjs.com/), [NestJS](https://nestjs.com/)
1111
- 100% [Typescript](https://www.typescriptlang.org/)
1212
- [Prettier](https://prettier.io/) and [Eslint](https://eslint.org/) setup alongside `pre-commit` hook.
13-
- [Mui v6](https://mui.com/) alongside theme change preconfigured.
13+
- [Mui v7](https://mui.com/) alongside theme change preconfigured.
1414
- [Dockerize](https://docs.docker.com/) images
1515
- Github Actions to build apps and publish their docker images
1616

apps/express-server/src/app-constants/index.ts

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/express-server/src/app.ts

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -4,9 +4,10 @@ import express, {
44
type Response
55
} from 'express';
66
import cors from 'cors';
7-
import { ENV_VARS } from '@/app-constants';
7+
import { ENV_CONFIG } from '@/constants';
88
import { requestLogger } from '@/middleware';
9-
import * as Routes from '@/routes';
9+
import { routesList } from '@/routes';
10+
import { sendErrorResponse } from '@/utils';
1011

1112
const app: Express = express();
1213

@@ -17,15 +18,22 @@ app.use(cors());
1718
app.use(requestLogger);
1819

1920
app.get('/', (_: Request, response: Response) => {
20-
response.status(200).send(`ENV: ${ENV_VARS.env} - Api is up & running!!!`);
21+
response.status(200).json({
22+
env: ENV_CONFIG.env,
23+
message: 'Api is up & running!!!'
24+
});
2125
});
2226

23-
app.use('/api/auth', Routes.authRouter);
27+
routesList.forEach(route => app.use(route.path, route.router));
2428

2529
/* 404 Handler - To be written at last */
2630
app.get('*', (req: Request, response: Response) => {
27-
const notFoundMsg = `Not Found - "${req.originalUrl}"`;
28-
response.status(404).send(notFoundMsg);
31+
const notFoundError = `No route exists for this endpoint: "${req.originalUrl}"`;
32+
return sendErrorResponse(response, {
33+
statusCode: 404,
34+
message: '404 - Not Found',
35+
error: notFoundError
36+
});
2937
});
3038

3139
export default app;

apps/express-server/src/app-constants/env_vars.ts renamed to apps/express-server/src/constants/environment.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66
const env = process.env;
77

8-
export const ENV_VARS = Object.freeze({
8+
export const ENV_CONFIG = Object.freeze({
99
env: env.NODE_ENV ?? 'development',
1010
port: env.PORT ?? 8000
1111
});
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './environment';

apps/express-server/src/index.ts

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -17,29 +17,27 @@
1717
import 'dotenv/config';
1818
import os from 'os';
1919
import { createServer } from 'node:http';
20-
import { ENV_VARS } from '@/app-constants';
20+
import { ENV_CONFIG } from '@/constants';
2121
import { winstonLogger } from '@/middleware';
2222
import app from './app';
2323

2424
const hostName = os.hostname();
25-
const port = ENV_VARS.port;
25+
const { port, env } = ENV_CONFIG;
2626

2727
function bootstrap() {
28-
/* DB Connection Logic */
29-
// try {
30-
// await mongoose.connect(db_connection_string, { autoIndex: true });
31-
// console_log('Connected to DATABASE', `${db_name}@${db_url}`);
32-
// } catch (err) {
33-
// console.log(chalk.red('⚠ Error connecting to the Database ⚠'));
34-
// console.log(err);
35-
// process.exit(1);
36-
// }
3728

38-
const server = createServer(app);
29+
/**
30+
* You can write any custom logic here, like connecting to the
31+
* database. Refer this snippet to connect to MongoDB, Postgres
32+
* or MySQL database.
33+
*
34+
* https://github.com/nishkohli96/client-server-libs/blob/main/apps/express-server/src/index.ts#L171
35+
*/
3936

37+
const server = createServer(app);
4038
server.listen(port, () => {
4139
winstonLogger.info(
42-
`[ ⚡️ ${hostName} ⚡️ ] - Server running on port ${port}`
40+
`[⚡️ ${hostName}@${env} ⚡️] - Server running on port ${port}`
4341
);
4442
});
4543
}

apps/express-server/src/middleware/guard.ts

Lines changed: 0 additions & 49 deletions
This file was deleted.
Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,2 @@
1-
export * from './guard';
21
export * from './request-logger';
32
export * from './winston-logger';

apps/express-server/src/middleware/request-logger.ts

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -16,19 +16,3 @@ export function requestLogger(
1616
});
1717
next();
1818
}
19-
20-
export function printSuccessMsg(msg: string): void {
21-
winstonLogger.info(`✅ SUCCESS - ${msg}`);
22-
}
23-
24-
export function printError(error: unknown): void {
25-
winstonLogger.error(
26-
`⚠ ERROR - ${error instanceof Error ? error.message : JSON.stringify(error)}`
27-
);
28-
}
29-
30-
export function errorLogger(res: Response, error: unknown) {
31-
const err = JSON.stringify(error);
32-
printError(error);
33-
res.status(500).send(err);
34-
}

apps/express-server/src/middleware/winston-logger.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* eslint-disable @typescript-eslint/restrict-template-expressions */
22

33
import { createLogger, addColors, format, transports } from 'winston';
4-
import { ENV_VARS } from '@/app-constants';
4+
import { ENV_CONFIG } from '@/constants';
55

66
const { combine, timestamp, printf } = format;
77

@@ -72,7 +72,7 @@ addColors(customLevels.colors);
7272
* `${info.level}: ${info.message} JSON.stringify({ ...rest }) `
7373
*/
7474

75-
if (ENV_VARS.env !== 'production') {
75+
if (ENV_CONFIG.env !== 'production') {
7676
winstonLogger.add(
7777
new transports.Console({ format: format.colorize({ all: true }) })
7878
);

apps/express-server/src/routes/auth/controller.ts

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,18 @@
1-
import { Router, type Request, type Response } from 'express';
1+
import { Router, type Response } from 'express';
22
import authService from './service';
33
import type * as AuthTypes from './types';
44

55
const authRouter = Router();
66

77
authRouter.get('/test', function printHello(_, res: Response) {
8-
return res.status(200).send('Hello World !!')
9-
.end();
8+
return res.status(200).send('Hello World !!').end();
109
});
1110

1211
/* Login user */
1312
authRouter.post(
1413
'/login',
1514
function loginUser(
16-
req: Request<object, object, AuthTypes.UserLoginBody>,
15+
req: AuthTypes.UserLoginRequest,
1716
res: Response
1817
) {
1918
const { email, password } = req.body;
Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,21 @@
11
import type { Response } from 'express';
2+
import { sendErrorResponse } from '@/utils';
23

34
class AuthService {
45
loginUser(res: Response, email: string, password: string) {
56
try {
6-
res
7+
return res
78
.status(200)
89
.send({
910
email,
1011
password
1112
})
1213
.end();
1314
} catch (error) {
14-
res.status(500).send(`Internal Server Error: ${JSON.stringify(error)}`);
15+
return sendErrorResponse(res, { error });
1516
}
16-
res.end();
1717
}
1818
}
1919

20-
export default new AuthService();
20+
const authService = new AuthService();
21+
export default authService;
Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,7 @@
1+
import { type Request } from 'express';
12
export interface UserLoginBody {
23
email: string;
34
password: string;
45
}
6+
7+
export type UserLoginRequest = Request<object, object, UserLoginBody>;
Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,20 @@
1+
import { type Router } from 'express';
12
import { authRouter } from './auth/controller';
23

3-
export { authRouter };
4+
type RouteInfo = {
5+
path: string;
6+
router: Router;
7+
};
8+
9+
function generatePrefix(routeName: string) {
10+
return `/api${routeName}`;
11+
}
12+
13+
const routesList: RouteInfo[] = [
14+
{
15+
path: generatePrefix('/auth'),
16+
router: authRouter
17+
}
18+
];
19+
20+
export { routesList };
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
export * from './printObject';
2+
export * from './response';
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
/**
2+
* Winston logger expects string message by default.
3+
* If you pass an object directly (like your response),
4+
* Winston doesn't automatically serialize it.
5+
*
6+
* JSON.stringify's 2nd and 3rd args:
7+
* - replacer (Optional): A function or array to control
8+
* which properties are included in the output. Usually
9+
* null if you want to include everything. Specify only
10+
* those keys in an array which you want to log.
11+
* - space (Optional): A number or string to control spacing
12+
* or indentation. 2 means 2 spaces of indentation per level
13+
* (for pretty-printing).
14+
*/
15+
export function printObject(obj: unknown): string {
16+
return JSON.stringify(obj, null, 2);
17+
}
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/**
2+
* Move this in types/request folder if you want to
3+
* use this code snippet.
4+
*/
5+
type PaginationConfig = {
6+
records_per_page: number;
7+
page: number;
8+
};
9+
10+
export const DefaultPaginationOptions: PaginationConfig = {
11+
records_per_page: 10,
12+
page: 1
13+
};
14+
15+
export function getPaginationParams(
16+
page?: string,
17+
records_per_page?: string
18+
): PaginationConfig {
19+
return {
20+
records_per_page: records_per_page
21+
? Number(records_per_page)
22+
: DefaultPaginationOptions.records_per_page,
23+
page: page ? Number(page) : DefaultPaginationOptions.page
24+
};
25+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
import { winstonLogger } from '@/middleware';
2+
import type { Response } from 'express';
3+
4+
type ErrorResponseOptions = {
5+
error: unknown;
6+
message?: string;
7+
statusCode?: number;
8+
};
9+
10+
export function sendErrorResponse(
11+
res: Response,
12+
{
13+
error,
14+
message = 'Internal Server Error',
15+
statusCode = 500,
16+
}: ErrorResponseOptions
17+
) {
18+
const errorMessage = error instanceof Error
19+
? error.message
20+
: JSON.stringify(error);
21+
22+
winstonLogger.error(`⚠ ERROR - ${errorMessage}`);
23+
return res.status(statusCode).json({
24+
success: false,
25+
status: statusCode,
26+
message,
27+
error: errorMessage,
28+
});
29+
}

apps/next-client/src/theme/palette.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
*
44
* https://zenoo.github.io/mui-theme-creator/
55
* https://m2.material.io/inline-tools/color/
6+
* https://bareynol.github.io/mui-theme-creator/
67
*/
78

89
export const LightThemePalette = {

apps/react-client/src/assets/styles/palette.ts

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,9 @@
11
/**
2-
* Dark mode with MUI.
3-
* https://mui.com/material-ui/customization/dark-mode/
2+
* Check out these resources for building theme -
3+
*
4+
* https://zenoo.github.io/mui-theme-creator/
5+
* https://m2.material.io/inline-tools/color/
6+
* https://bareynol.github.io/mui-theme-creator/
47
*/
58

69
export const LightThemePalette = {

0 commit comments

Comments
 (0)