Skip to content

Commit 438b949

Browse files
committed
add eslint
1 parent 6b6d7f5 commit 438b949

25 files changed

+884
-98
lines changed

.eslintignore

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
node_modules/
2+
dist/

.prettierignore

-2
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,6 @@ docker-compose.yml
2929
Dockerfile
3030

3131
# Ignore configuration files for other tools or IDE-specific files
32-
*.config.js
33-
*.config.ts
3432
.idea/
3533
.vscode/
3634

.prettierrc

-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
{
2-
"singleQuote": true,
32
"trailingComma": "all",
43
"printWidth": 100,
54
"singleAttributePerLine": true

eslint.config.mjs

+22
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
import globals from "globals";
2+
import pluginJs from "@eslint/js";
3+
import tseslint from "typescript-eslint";
4+
5+
export default [
6+
{ files: ["**/*.{ts}"] },
7+
{ languageOptions: { globals: globals.browser } },
8+
{
9+
rules: {
10+
"@typescript-eslint/no-unused-vars": [
11+
"warn",
12+
{
13+
argsIgnorePattern: "^_", // Ignore unused arguments starting with an underscore
14+
varsIgnorePattern: "^_", // Ignore unused variables starting with an underscore
15+
},
16+
],
17+
"@typescript-eslint/explicit-function-return-type": "off", // Disable explicit return type enforcement
18+
},
19+
},
20+
pluginJs.configs.recommended,
21+
...tseslint.configs.recommended,
22+
];

package.json

+13-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,8 @@
88
"start": "node dist/server.js",
99
"dev": "tsup src/server.ts --watch --onSuccess \"node dist/server.js\"",
1010
"build": "tsup",
11-
"prettier:fix": "npx prettier --write ."
11+
"prettier:fix": "npx prettier --write .",
12+
"lint": "eslint 'src/**/*.ts' --fix"
1213
},
1314
"keywords": [],
1415
"author": "",
@@ -24,13 +25,23 @@
2425
"zod": "^3.23.8"
2526
},
2627
"devDependencies": {
28+
"@eslint/js": "^9.13.0",
2729
"@types/bcrypt": "^5.0.2",
2830
"@types/cookie-parser": "^1.4.7",
2931
"@types/express": "^5.0.0",
3032
"@types/jsonwebtoken": "^9.0.7",
3133
"@types/node": "^22.7.7",
3234
"@types/pg": "^8.11.10",
35+
"@typescript-eslint/eslint-plugin": "^8.10.0",
36+
"@typescript-eslint/parser": "^8.10.0",
37+
"eslint": "^9.13.0",
38+
"eslint-config-prettier": "^9.1.0",
39+
"eslint-plugin-node": "^11.1.0",
40+
"eslint-plugin-prettier": "^5.2.1",
41+
"globals": "^15.11.0",
42+
"prettier": "^3.3.3",
3343
"tsup": "^8.3.0",
34-
"typescript": "^5.6.3"
44+
"typescript": "^5.6.3",
45+
"typescript-eslint": "^8.10.0"
3546
}
3647
}

src/app.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import express from 'express';
2-
import { env } from 'config/env';
3-
import errorMiddleware from 'middleware/error.middleware';
4-
import { type Controller } from 'interfaces/controller.interface';
5-
import cookieParser from 'cookie-parser';
1+
import express from "express";
2+
import { env } from "config/env";
3+
import errorMiddleware from "middleware/error.middleware";
4+
import { type Controller } from "interfaces/controller.interface";
5+
import cookieParser from "cookie-parser";
66

77
class App {
88
private app: express.Application;
@@ -23,7 +23,7 @@ class App {
2323

2424
private initializeControllers(controllers: Controller[]) {
2525
controllers.forEach((controller) => {
26-
this.app.use('/api/v1', controller.router);
26+
this.app.use("/api/v1", controller.router);
2727
});
2828
}
2929

src/auth/auth.controller.ts

+12-12
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
import { Request, Response, NextFunction } from 'express';
2-
import validationMiddleware from 'middleware/validation.middleware';
3-
import { loginSchema, registerSchema } from './auth.validation';
4-
import { AuthService } from './auth.service';
5-
import { Controller } from 'interfaces/controller.interface';
6-
import authMiddleware from 'middleware/auth.middleware';
1+
import { Request, Response, NextFunction } from "express";
2+
import validationMiddleware from "middleware/validation.middleware";
3+
import { loginSchema, registerSchema } from "./auth.validation";
4+
import { AuthService } from "./auth.service";
5+
import { Controller } from "interfaces/controller.interface";
6+
import authMiddleware from "middleware/auth.middleware";
77

88
export class AuthController extends Controller {
99
private authService = new AuthService();
1010

1111
constructor() {
12-
super('/auth');
12+
super("/auth");
1313
this.initializeRoutes();
1414
}
1515

@@ -23,10 +23,10 @@ export class AuthController extends Controller {
2323
private register = async (request: Request, response: Response, next: NextFunction) => {
2424
try {
2525
const createdUser = await this.authService.registerUser(request.body);
26-
if (!createdUser) return next('No user created');
26+
if (!createdUser) return next("No user created");
2727

2828
response.cookie(
29-
'Authentication',
29+
"Authentication",
3030
this.authService.createToken(createdUser.id),
3131
this.authService.createCookieOptions(),
3232
);
@@ -40,10 +40,10 @@ export class AuthController extends Controller {
4040
private login = async (request: Request, response: Response, next: NextFunction) => {
4141
try {
4242
const user = await this.authService.login(request.body);
43-
if (!user) return next('No user found');
43+
if (!user) return next("No user found");
4444

4545
response.cookie(
46-
'Authentication',
46+
"Authentication",
4747
this.authService.createToken(user.id),
4848
this.authService.createCookieOptions(),
4949
);
@@ -67,7 +67,7 @@ export class AuthController extends Controller {
6767

6868
private logout = (_: Request, response: Response) => {
6969
response
70-
.setHeader('Set-Cookie', ['Authentication=; Max-Age=0; Path=/; HttpOnly'])
70+
.setHeader("Set-Cookie", ["Authentication=; Max-Age=0; Path=/; HttpOnly"])
7171
.status(204)
7272
.end();
7373
};

src/auth/auth.repository.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,23 @@
1-
import pool from 'config/database';
2-
import { RegisterPayload } from './auth.validation';
3-
import { User } from 'users/users.model';
1+
import pool from "config/database";
2+
import { RegisterPayload } from "./auth.validation";
3+
import { User } from "users/users.model";
44

55
export class AuthRepository {
66
public async createUser(payload: RegisterPayload) {
77
const result = await pool.query<User>(
8-
'INSERT INTO users (username, email, password) VALUES ($1, $2, $3) RETURNING *',
8+
"INSERT INTO users (username, email, password) VALUES ($1, $2, $3) RETURNING *",
99
[payload.username, payload.email, payload.password],
1010
);
1111
return result.rows[0];
1212
}
1313

1414
public async findUserById(id: number) {
15-
const result = await pool.query<User>('SELECT * FROM users WHERE id = $1', [id]);
15+
const result = await pool.query<User>("SELECT * FROM users WHERE id = $1", [id]);
1616
return result.rows[0];
1717
}
1818

1919
public async findUserByEmail(email: string) {
20-
const result = await pool.query<User>('SELECT * FROM users WHERE email = $1', [email]);
20+
const result = await pool.query<User>("SELECT * FROM users WHERE email = $1", [email]);
2121
return result.rows[0];
2222
}
2323
}

src/auth/auth.service.ts

+15-15
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,11 @@
1-
import jwt from 'jsonwebtoken';
2-
import bcrypt from 'bcrypt';
3-
import { LoginPayload, RegisterPayload } from './auth.validation';
4-
import { AuthRepository } from './auth.repository';
5-
import { env } from 'config/env';
6-
import { BadRequestError } from 'errors/bad-request.error';
7-
import { CookieOptions } from 'express';
8-
import { User } from 'users/users.model';
1+
import jwt from "jsonwebtoken";
2+
import bcrypt from "bcrypt";
3+
import { LoginPayload, RegisterPayload } from "./auth.validation";
4+
import { AuthRepository } from "./auth.repository";
5+
import { env } from "config/env";
6+
import { BadRequestError } from "errors/bad-request.error";
7+
import { CookieOptions } from "express";
8+
import { User } from "users/users.model";
99

1010
export class AuthService {
1111
private authRepository = new AuthRepository();
@@ -14,15 +14,15 @@ export class AuthService {
1414
// Check if email already exists
1515
const foundUser = await this.authRepository.findUserByEmail(payload.email);
1616
if (foundUser) {
17-
throw new BadRequestError('User with that email already exists');
17+
throw new BadRequestError("User with that email already exists");
1818
}
1919

2020
const user = await this.authRepository.createUser({
2121
...payload,
2222
password: await bcrypt.hash(payload.password, 10), // Hash password
2323
});
2424
if (!user) {
25-
throw new BadRequestError('Failed to create user');
25+
throw new BadRequestError("Failed to create user");
2626
}
2727

2828
return this.removePassword(user);
@@ -31,12 +31,12 @@ export class AuthService {
3131
public async login(payload: LoginPayload) {
3232
const user = await this.authRepository.findUserByEmail(payload.email);
3333
if (!user) {
34-
throw new BadRequestError('Invalid email or password');
34+
throw new BadRequestError("Invalid email or password");
3535
}
3636

3737
const isPasswordCorrect = await bcrypt.compare(payload.password, user.password);
3838
if (!isPasswordCorrect) {
39-
throw new BadRequestError('Invalid email or password');
39+
throw new BadRequestError("Invalid email or password");
4040
}
4141

4242
return this.removePassword(user);
@@ -55,13 +55,13 @@ export class AuthService {
5555
return {
5656
maxAge: 5 * 60 * 60 * 1000, // 5 hours
5757
httpOnly: true,
58-
sameSite: 'lax',
59-
secure: process.env.NODE_ENV === 'production',
58+
sameSite: "lax",
59+
secure: process.env.NODE_ENV === "production",
6060
};
6161
}
6262

6363
private removePassword(user: User) {
64-
const { password, ...userWithoutPassword } = user;
64+
const { password: _password, ...userWithoutPassword } = user;
6565
return userWithoutPassword;
6666
}
6767
}

src/auth/auth.validation.ts

+3-3
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { z } from 'zod';
1+
import { z } from "zod";
22

33
export const registerSchema = z.object({
44
body: z.object({
@@ -8,7 +8,7 @@ export const registerSchema = z.object({
88
}),
99
});
1010

11-
export type RegisterPayload = z.infer<typeof registerSchema>['body'];
11+
export type RegisterPayload = z.infer<typeof registerSchema>["body"];
1212

1313
export const loginSchema = z.object({
1414
body: z.object({
@@ -17,4 +17,4 @@ export const loginSchema = z.object({
1717
}),
1818
});
1919

20-
export type LoginPayload = z.infer<typeof loginSchema>['body'];
20+
export type LoginPayload = z.infer<typeof loginSchema>["body"];

src/config/database.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { Pool } from 'pg';
2-
import { env } from './env';
1+
import { Pool } from "pg";
2+
import { env } from "./env";
33

44
const pool = new Pool({
55
host: env.POSTGRES_HOST,

src/config/env.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
1-
import { config } from 'dotenv';
2-
import { cleanEnv, port, str } from 'envalid';
1+
import { config } from "dotenv";
2+
import { cleanEnv, port, str } from "envalid";
33

44
config();
55

src/errors/bad-request.error.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { HttpError } from './http.error';
1+
import { HttpError } from "./http.error";
22

33
export class BadRequestError extends HttpError {
44
constructor(message?: string) {
5-
super(400, 'Bad Request');
5+
super(400, message || "Bad Request");
66
}
77
}

src/errors/forbidden.error.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { HttpError } from './http.error';
1+
import { HttpError } from "./http.error";
22

33
export class ForbiddenError extends HttpError {
44
constructor(message?: string) {
5-
super(403, message || 'Forbidden');
5+
super(403, message || "Forbidden");
66
}
77
}

src/errors/unauthorized.error.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
import { HttpError } from './http.error';
1+
import { HttpError } from "./http.error";
22

33
export class UnauthorizedError extends HttpError {
44
constructor(message?: string) {
5-
super(401, message || 'Unauthorized');
5+
super(401, message || "Unauthorized");
66
}
77
}

src/interfaces/api.interface.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ export interface PaginatedResponse<T> {
66
}
77

88
// Extend the Express session interface to include user ID
9-
declare module 'express' {
9+
declare module "express" {
1010
interface Request {
1111
userId?: number;
1212
}

src/interfaces/controller.interface.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
import { Router } from 'express';
1+
import { Router } from "express";
22

33
export abstract class Controller {
44
public router: Router;

src/middleware/auth.middleware.ts

+6-6
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
import { NextFunction, Response, Request } from 'express';
2-
import pool from 'config/database';
3-
import jwt from 'jsonwebtoken';
4-
import { UnauthorizedError } from 'errors/unauthorized.error';
5-
import { env } from 'config/env';
1+
import { NextFunction, Response, Request } from "express";
2+
import pool from "config/database";
3+
import jwt from "jsonwebtoken";
4+
import { UnauthorizedError } from "errors/unauthorized.error";
5+
import { env } from "config/env";
66

77
async function authMiddleware(request: Request, _: Response, next: NextFunction) {
88
const token = request.cookies.Authentication;
@@ -11,7 +11,7 @@ async function authMiddleware(request: Request, _: Response, next: NextFunction)
1111
const decoded = jwt.verify(token, env.JWT_SECRET) as { _id: number };
1212
if (!decoded._id) return next(new UnauthorizedError());
1313

14-
const result = await pool.query('SELECT id FROM users WHERE id = $1', [decoded._id]);
14+
const result = await pool.query("SELECT id FROM users WHERE id = $1", [decoded._id]);
1515
if (result.rows.length === 0) return next(new UnauthorizedError());
1616

1717
request.userId = decoded._id;

src/middleware/error.middleware.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,14 @@
1-
import { HttpError } from 'errors/http.error';
2-
import { NextFunction, Request, Response } from 'express';
1+
import { HttpError } from "errors/http.error";
2+
import { NextFunction, Request, Response } from "express";
33

44
function errorMiddleware(
55
error: HttpError,
6-
request: Request,
6+
_request: Request,
77
response: Response,
8-
next: NextFunction,
8+
_next: NextFunction,
99
) {
1010
const status = error.status || 500;
11-
const message = error.message || 'Something went wrong';
11+
const message = error.message || "Something went wrong";
1212
response.status(status).json({
1313
status,
1414
message,

0 commit comments

Comments
 (0)