Skip to content

Commit 40d531a

Browse files
committed
modify: 린팅
1 parent f29e3cd commit 40d531a

File tree

12 files changed

+78
-63
lines changed

12 files changed

+78
-63
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -41,8 +41,8 @@ pnpm dev
4141
```bash
4242
pnpm dev # 개발 서버 실행
4343
pnpm test # 테스트 실행
44-
pnpm lint # 린트 검사
45-
pnpm lint:fix # 린트 자동 수정
44+
pnpm lint # 린트 검사 (eslint + prettier)
45+
pnpm lint-staged # 린트 자동 수정
4646

4747
pnpm build # 프로젝트 빌드
4848
pnpm start # 빌드된 프로젝트 시작

package.json

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,27 +1,38 @@
11
{
22
"name": "velog-dashboard",
33
"version": "1.0.0",
4-
"description": "",
4+
"description": "Velog Dashboard Project, velog의 모든 게시글, 통계 데이터를 한 눈에 편하게 확인할 수 있는 대시보드입니다.",
55
"main": "index.js",
66
"scripts": {
77
"dev": "tsx watch src/index.ts",
88
"build": "tsc && tsc-alias -p tsconfig.json",
9-
"lint": "eslint src/**/*.ts",
10-
"lint:fix": "eslint src/ --fix",
11-
"format": "prettier --write src/**/*.ts",
9+
"lint": "eslint src/**/*.ts && prettier --check src/**/*.ts",
1210
"test": "jest",
1311
"test:watch": "jest --watch",
1412
"test:coverage": "jest --coverage",
1513
"start": "node dist/index.js"
1614
},
1715
"lint-staged": {
18-
"*.{ts,tsx}": [
16+
".{ts,tsx}": [
1917
"eslint --fix",
2018
"prettier --write"
2119
]
2220
},
23-
"keywords": [],
24-
"author": "",
21+
"keywords": [
22+
"velog",
23+
"dashboard",
24+
"analytics",
25+
"blog",
26+
"monitoring",
27+
"typescript",
28+
"express",
29+
"node.js",
30+
"redis",
31+
"postgresql",
32+
"api",
33+
"swagger"
34+
],
35+
"author": "Nuung",
2536
"license": "ISC",
2637
"dependencies": {
2738
"@sentry/node": "^9.36.0",
@@ -67,4 +78,4 @@
6778
"typescript-eslint": "^8.15.0",
6879
"typescript-transform-paths": "^3.5.3"
6980
}
70-
}
81+
}

src/configs/cache.config.ts

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@ import logger from '@/configs/logger.config';
33
import { ICache, CacheConfig } from '@/modules/cache/cache.type';
44
import { RedisCache } from '@/modules/cache/redis.cache';
55

6-
76
const cacheConfig: CacheConfig = {
87
host: process.env.REDIS_HOST || '152.67.198.7',
98
port: parseInt(process.env.REDIS_PORT || '6379'),
@@ -60,4 +59,4 @@ export const getCacheStatus = async (): Promise<boolean> => {
6059
logger.warn('Cache health check failed:', error);
6160
return false;
6261
}
63-
};
62+
};

src/configs/sentry.config.ts

Lines changed: 2 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,7 @@ export const initSentry = () => {
2525
enabled: true,
2626

2727
// Capture 100% of the transactions for performance monitoring
28-
integrations: [
29-
Sentry.httpIntegration(),
30-
Sentry.expressIntegration(),
31-
],
28+
integrations: [Sentry.httpIntegration(), Sentry.expressIntegration()],
3229
});
3330

3431
sentryInitialized = true;
@@ -41,4 +38,4 @@ export const initSentry = () => {
4138
// Sentry 상태 확인 함수
4239
export const getSentryStatus = (): boolean => {
4340
return sentryInitialized;
44-
};
41+
};

src/controllers/user.controller.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ type Token10 = string & { __lengthBrand: 10 };
1212
const THREE_WEEKS_IN_MS = 21 * 24 * 60 * 60 * 1000;
1313

1414
export class UserController {
15-
constructor(private userService: UserService) { }
15+
constructor(private userService: UserService) {}
1616

1717
/**
1818
* 환경 및 쿠키 삭제 여부에 따라 쿠키 옵션을 생성합니다.

src/controllers/webhook.controller.ts

Lines changed: 11 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,14 @@ import { BadRequestError } from '@/exception';
66

77
export class WebhookController {
88
private readonly STATUS_EMOJI = {
9-
'unresolved': '🔴',
10-
'resolved': '✅',
11-
'ignored': '🔇',
9+
unresolved: '🔴',
10+
resolved: '✅',
11+
ignored: '🔇',
1212
} as const;
1313

14-
handleSentryWebhook: RequestHandler = async (
15-
req: Request,
16-
res: Response,
17-
next: NextFunction,
18-
): Promise<void> => {
14+
handleSentryWebhook: RequestHandler = async (req: Request, res: Response, next: NextFunction): Promise<void> => {
1915
try {
20-
if (req.body?.action !== "created") {
16+
if (req.body?.action !== 'created') {
2117
const response = new BadRequestError('Sentry 웹훅 처리에 실패했습니다');
2218
res.status(400).json(response);
2319
return;
@@ -37,9 +33,12 @@ export class WebhookController {
3733
};
3834

3935
private formatSentryMessage(sentryData: SentryWebhookData): string {
40-
const { data: { issue } } = sentryData;
36+
const {
37+
data: { issue },
38+
} = sentryData;
4139

42-
if(!issue.status || !issue.title || !issue.culprit || !issue.id) throw new BadRequestError('Sentry 웹훅 처리에 실패했습니다');
40+
if (!issue.status || !issue.title || !issue.culprit || !issue.id)
41+
throw new BadRequestError('Sentry 웹훅 처리에 실패했습니다');
4342

4443
const { status, title: issueTitle, culprit, permalink, id } = issue;
4544
const statusEmoji = this.STATUS_EMOJI[status as keyof typeof this.STATUS_EMOJI];
@@ -54,4 +53,4 @@ export class WebhookController {
5453

5554
return message;
5655
}
57-
}
56+
}

src/middlewares/auth.middleware.ts

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import logger from '@/configs/logger.config';
44
import pool from '@/configs/db.config';
55
import { CustomError, DBError, InvalidTokenError } from '@/exception';
66
import { VelogJWTPayload, User } from '@/types';
7-
import crypto from "crypto";
7+
import crypto from 'crypto';
88

99
/**
1010
* 요청에서 토큰을 추출하는 함수
@@ -69,36 +69,37 @@ const verifyBearerTokens = () => {
6969

7070
/**
7171
* Sentry 웹훅 요청의 시그니처 헤더를 검증합니다.
72-
* HMAC SHA256과 Sentry의 Client Secret를 사용하여 요청 본문을 해시화하고,
72+
* HMAC SHA256과 Sentry의 Client Secret를 사용하여 요청 본문을 해시화하고,
7373
* Sentry에서 제공하는 시그니처 헤더와 비교하여 요청의 무결성을 확인합니다.
7474
*/
7575
function verifySentrySignature() {
7676
return (req: Request, res: Response, next: NextFunction) => {
7777
try {
78-
if (!process.env.SENTRY_CLIENT_SECRET) throw new Error("SENTRY_CLIENT_SECRET가 env에 없습니다");
79-
80-
const hmac = crypto.createHmac("sha256", process.env.SENTRY_CLIENT_SECRET);
81-
78+
if (!process.env.SENTRY_CLIENT_SECRET) throw new Error('SENTRY_CLIENT_SECRET가 env에 없습니다');
79+
80+
const hmac = crypto.createHmac('sha256', process.env.SENTRY_CLIENT_SECRET);
81+
8282
// Raw body 사용 - Express에서 파싱되기 전의 원본 데이터 필요
8383
// req.rawBody가 없다면 fallback으로 JSON.stringify 사용 (완벽하지 않음)
8484
// @ts-expect-error - rawBody는 커스텀 미들웨어에서 추가되는 속성
8585
const bodyToVerify = req.rawBody || JSON.stringify(req.body);
86-
const sentrySignature = req.headers["sentry-hook-signature"];
87-
88-
if (!bodyToVerify) throw new Error("요청 본문이 없습니다.");
89-
if (!sentrySignature) throw new Error("시그니처 헤더가 없습니다.");
90-
91-
hmac.update(bodyToVerify, "utf8");
92-
const digest = hmac.digest("hex");
93-
94-
if (digest !== sentrySignature) throw new CustomError("유효하지 않은 시그니처 헤더입니다.", "INVALID_SIGNATURE", 400);
95-
86+
const sentrySignature = req.headers['sentry-hook-signature'];
87+
88+
if (!bodyToVerify) throw new Error('요청 본문이 없습니다.');
89+
if (!sentrySignature) throw new Error('시그니처 헤더가 없습니다.');
90+
91+
hmac.update(bodyToVerify, 'utf8');
92+
const digest = hmac.digest('hex');
93+
94+
if (digest !== sentrySignature)
95+
throw new CustomError('유효하지 않은 시그니처 헤더입니다.', 'INVALID_SIGNATURE', 400);
96+
9697
next();
9798
} catch (error) {
9899
logger.error('시그니처 검증 중 오류가 발생하였습니다. : ', error);
99100
next(error);
100101
}
101-
}
102+
};
102103
}
103104

104105
/**

src/middlewares/errorHandling.middleware.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,10 +16,10 @@ export const errorHandlingMiddleware: ErrorRequestHandler = (
1616
.json({ success: false, message: err.message, error: { code: err.code, statusCode: err.statusCode } });
1717
return;
1818
}
19-
19+
2020
Sentry.captureException(err);
2121
logger.error('Internal Server Error');
22-
22+
2323
res.status(500).json({
2424
success: false,
2525
message: '서버 내부 에러가 발생하였습니다.',

src/repositories/user.repository.ts

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { QRLoginToken } from '@/types/models/QRLoginToken.type';
55
import { DBError } from '@/exception';
66

77
export class UserRepository {
8-
constructor(private readonly pool: Pool) { }
8+
constructor(private readonly pool: Pool) {}
99

1010
async findByUserId(id: number): Promise<User> {
1111
try {
@@ -42,7 +42,14 @@ export class UserRepository {
4242
}
4343
}
4444

45-
async updateTokens(uuid: string, email: string | null, username: string | null, thumbnail: string | null, encryptedAccessToken: string, encryptedRefreshToken: string): Promise<User> {
45+
async updateTokens(
46+
uuid: string,
47+
email: string | null,
48+
username: string | null,
49+
thumbnail: string | null,
50+
encryptedAccessToken: string,
51+
encryptedRefreshToken: string,
52+
): Promise<User> {
4653
try {
4754
const query = `
4855
UPDATE "users_user"

src/routes/webhook.router.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,4 @@ const webhookController = new WebhookController();
5050
*/
5151
router.post('/webhook/sentry', authMiddleware.verifySignature, webhookController.handleSentryWebhook);
5252

53-
export default router;
53+
export default router;

0 commit comments

Comments
 (0)