Skip to content

Commit

Permalink
refactor(Auth,-Redis,-SocketIO,-reconfigure-ioc-container): refactori…
Browse files Browse the repository at this point in the history
…ng middleware ad services
  • Loading branch information
AllStackDev1 committed Oct 29, 2024
1 parent 0d6bb05 commit 3546f88
Show file tree
Hide file tree
Showing 29 changed files with 427 additions and 142 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ An express server boilerplate built using the latest version of Node.js and inte
```bash
pnpm run db:create
pnpm run db:migrate:up
pnpm run db:seed:all
```

6. **Start the development server**
Expand Down
11 changes: 7 additions & 4 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -5,15 +5,17 @@
"main": "src/server.ts",
"scripts": {
"build": "rimraf build && tsc -p ./tsconfig.build.json",
"docker-up-dev": "NODE_ENV=development ./run-docker.sh",
"dev": "NODE_ENV=development nodemon -r tsconfig-paths/register ./src/server.ts",
"start": "NODE_ENV=development TS_NODE_BASEURL=./build nodemon -r tsconfig-paths/register ./build/server.js",
"docker-up-dev": "rimraf .env && NODE_ENV=development ./run-docker.sh",
"docker-up-prod": "rimraf .env && NODE_ENV=production ./run-docker.sh",
"dev": "NODE_ENV=development nodemon -r tsconfig-paths/register ./src/index.ts",
"start": "NODE_ENV=development TS_NODE_BASEURL=./build nodemon -r tsconfig-paths/register ./build/index.js",
"db:create": "pnpm run build && NODE_ENV=development npx sequelize-cli db:create",
"db:seed:all": "pnpm run build && NODE_ENV=development npx sequelize-cli db:seed:all",
"db:migrate:up": "pnpm run build && NODE_ENV=development npx sequelize-cli db:migrate",
"db:migrate:undo": "pnpm run build && NODE_ENV=development npx sequelize-cli db:migrate:undo",
"test": "NODE_ENV=test TEST_MODEL=mock jest src --runInBand --detectOpenHandles",
"test:watch": "NODE_ENV=test TEST_MODEL=real jest --runInBand --watch",
"test-single": "NODE_ENV=test TEST_MODEL=mock jest ./src/tests/server.test.ts --detectOpenHandles",
"test-single": "NODE_ENV=test TEST_MODEL=mock jest ./src/tests/app.test.ts --detectOpenHandles",
"lint": "eslint ./src/**/*"
},
"author": "Chinedu",
Expand All @@ -40,6 +42,7 @@
"reflect-metadata": "^0.2.2",
"safe-regex": "^2.1.1",
"sequelize": "^6.37.3",
"socket.io": "^4.8.1",
"zod": "^3.23.8"
},
"devDependencies": {
Expand Down
103 changes: 103 additions & 0 deletions pnpm-lock.yaml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

57 changes: 33 additions & 24 deletions src/app.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import helmet from 'helmet';
import http from 'node:http';
import express from 'express';
import { Server } from 'node:http';
import cookieParser from 'cookie-parser';
import express, { Express } from 'express';
import { NOT_FOUND, OK } from 'http-status';
import { inject, injectable } from 'inversify';

Expand All @@ -23,16 +23,20 @@ import {

import { TYPES } from 'di/types';

import { SocketService, RedisService } from 'services';
import { AuthController, UserController } from 'controllers';
import { RedisClient } from 'configs/redis.config';

@injectable()
export class App {
public _express = express();
private httpServer: ReturnType<typeof http.createServer> | undefined;
private isInitialized: boolean = false;

constructor(
@inject(TYPES.Server)
private server: Server,
@inject(TYPES.Express)
private express: Express,
@inject(TYPES.SocketService)
private socketService: SocketService,
@inject(TYPES.AuthController)
private authController: AuthController,
@inject(TYPES.UserController)
Expand All @@ -41,8 +45,8 @@ export class App {
private rateLimitHandler: RateLimitHandler,
@inject(TYPES.SessionHandler)
private sessionHandler: SessionHandler,
@inject(TYPES.RedisClient)
private redisClient: RedisClient,
@inject(TYPES.RedisService)
private redisService: RedisService,
) {}

public async initialize() {
Expand All @@ -61,50 +65,55 @@ export class App {
logger.log('----------------------------------------');
logger.log('Starting Server');
logger.log('----------------------------------------');
this.httpServer = http.createServer(this._express);
this.httpServer.listen(serverConfig.port, () => {
this.server.listen(serverConfig.port, () => {
logger.log('----------------------------------------');
logger.log(`Server started on ${serverConfig.host}:${serverConfig.port}`);
logger.log('----------------------------------------');

// Initialize Socket.IO listeners
logger.log('----------------------------------------');
logger.log('Initialize Socket.IO listeners');
logger.log('----------------------------------------');
this.socketService.setupListeners();
});
}

public async shutdown(callback: (err?: Error) => void) {
await this.redisClient.close();
await this.redisService.close();
await sequelize.close();
this.httpServer?.close(callback);
this.server?.close(callback);
}

private setExpressSettings() {
logger.log('----------------------------------------');
logger.log('Initializing API');
logger.log('----------------------------------------');
this._express.use(helmet());
this._express.use(cookieParser(cookiesConfig.secretKey));
this._express.use(express.urlencoded({ extended: true }));
this._express.use(express.json());
this._express.disable('x-powered-by');
this.express.use(helmet());
this.express.use(cookieParser(cookiesConfig.secretKey));
this.express.use(express.urlencoded({ extended: true }));
this.express.use(express.json());
this.express.disable('x-powered-by');
}

private initializePreMiddlewares() {
logger.log('----------------------------------------');
logger.log('Configuration Pre Middlewares');
logger.log('----------------------------------------');
this._express.use(corsHandler);
this._express.use(this.sessionHandler.handler);
this._express.use(this.rateLimitHandler.handler);
this._express.use(loggerHandler);
this.express.use(corsHandler);
this.express.use(this.sessionHandler.handler);
this.express.use(this.rateLimitHandler.handler);
this.express.use(loggerHandler);
}

private initializeControllers() {
logger.log('----------------------------------------');
logger.log('Define Routes & Controllers');
logger.log('----------------------------------------');
this._express.get('/health-check', (_, res) => {
this.express.get('/health-check', (_, res) => {
res.status(OK).json({ status: 'success', health: '100%' });
});
defineRoutes([this.authController, this.userController], this._express);
this._express.use(
defineRoutes([this.authController, this.userController], this.express);
this.express.use(
'*',
catchAsync(async (req) => {
throw new AppError(
Expand All @@ -130,6 +139,6 @@ export class App {
logger.log('----------------------------------------');
logger.log('Configuration Post Middlewares');
logger.log('----------------------------------------');
this._express.use(globalErrorHandler);
this.express.use(globalErrorHandler);
}
}
2 changes: 1 addition & 1 deletion src/controllers/auth.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,7 @@ export class AuthController {
secure: isProd,
})
.status(OK)
.json({ ...result.user, accessToken: result.accessToken });
.json({ user: result.user, accessToken: result.accessToken });
}

@Route('post', '/login')
Expand Down
18 changes: 12 additions & 6 deletions src/controllers/user.controller.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,9 @@ import { injectable, inject } from 'inversify';
import { ACCEPTED, NO_CONTENT, OK } from 'http-status';

import {
QuerySchema,
UserQuerySchema,
ParamsWithId,
UpdateSchema,
UserUpdateSchema,
DeleteTypeSchema,
} from 'validators';
import { TYPES } from 'di/types';
Expand All @@ -28,8 +28,8 @@ export class UserController {

@Route('get', '/search')
@AuthGuard()
@Validator({ query: QuerySchema })
async query(req: Request<[], [], [], QuerySchema>, res: Response) {
@Validator({ query: UserQuerySchema })
async query(req: Request<[], [], [], UserQuerySchema>, res: Response) {
return res.status(OK).json(await this.service.getUsersByQuery(req.query));
}

Expand All @@ -42,8 +42,14 @@ export class UserController {

@Route('patch', '/:id')
@AuthGuard()
@Validator({ body: UpdateSchema, params: ParamsWithId })
async update(req: Request<ParamsWithId, [], UpdateSchema>, res: Response) {
@Validator({
body: UserUpdateSchema,
params: ParamsWithId,
})
async update(
req: Request<ParamsWithId, [], UserUpdateSchema>,
res: Response,
) {
return res.status(OK).json({
message: 'User details updated successfully',
data: await this.service.update(req.params.id, req.body),
Expand Down
Loading

0 comments on commit 3546f88

Please sign in to comment.