diff --git a/package.json b/package.json index dc395ff..61055cd 100644 --- a/package.json +++ b/package.json @@ -5,7 +5,7 @@ "main": "index.js", "scripts": { "dev": "tsx watch src/index.ts", - "build": "tsc", + "build": "tsc && tsc-alias -p tsconfig.json", "lint": "eslint src/**/*.ts", "lint:fix": "eslint src/ --fix", "format": "prettier --write src/**/*.ts", @@ -54,6 +54,7 @@ "lint-staged": "^15.2.10", "prettier": "^3.3.3", "ts-jest": "^29.2.5", + "tsc-alias": "^1.8.10", "tsx": "^4.19.2", "typescript": "^5.7.2", "typescript-eslint": "^8.15.0", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index be68ee3..f33289f 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -93,6 +93,9 @@ importers: ts-jest: specifier: ^29.2.5 version: 29.2.5(@babel/core@7.26.0)(@jest/transform@29.7.0)(@jest/types@29.6.3)(babel-jest@29.7.0(@babel/core@7.26.0))(jest@29.7.0(@types/node@22.9.0)(ts-node@10.9.2(@types/node@22.9.0)(typescript@5.7.2)))(typescript@5.7.2) + tsc-alias: + specifier: ^1.8.10 + version: 1.8.10 tsx: specifier: ^4.19.2 version: 4.19.2 @@ -836,6 +839,10 @@ packages: array-flatten@1.1.1: resolution: {integrity: sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==} + array-union@2.1.0: + resolution: {integrity: sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==} + engines: {node: '>=8'} + async@3.2.6: resolution: {integrity: sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==} @@ -873,6 +880,10 @@ packages: balanced-match@1.0.2: resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==} + binary-extensions@2.3.0: + resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==} + engines: {node: '>=8'} + body-parser@1.20.3: resolution: {integrity: sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==} engines: {node: '>= 0.8', npm: 1.2.8000 || >= 1.4.16} @@ -937,6 +948,10 @@ packages: resolution: {integrity: sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==} engines: {node: '>=10'} + chokidar@3.6.0: + resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==} + engines: {node: '>= 8.10.0'} + ci-info@3.9.0: resolution: {integrity: sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==} engines: {node: '>=8'} @@ -1002,6 +1017,10 @@ packages: resolution: {integrity: sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==} engines: {node: '>=18'} + commander@9.5.0: + resolution: {integrity: sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==} + engines: {node: ^12.20.0 || >=14} + concat-map@0.0.1: resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==} @@ -1107,6 +1126,10 @@ packages: resolution: {integrity: sha512-58lmxKSA4BNyLz+HHMUzlOEpg09FV+ev6ZMe3vJihgdxzgcwZ8VoEEPmALCZG9LmqfVoNMMKpttIYTVG6uDY7A==} engines: {node: '>=0.3.1'} + dir-glob@3.0.1: + resolution: {integrity: sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==} + engines: {node: '>=8'} + dotenv@16.4.5: resolution: {integrity: sha512-ZmdL2rui+eB2YwhsWzjInR8LldtZHGDoQ1ugH85ppHKwpUHL7j7rN0Ti9NCnGiQbhaZ11FpR+7ao1dNsmduNUg==} engines: {node: '>=12'} @@ -1429,6 +1452,10 @@ packages: resolution: {integrity: sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==} engines: {node: '>=18'} + globby@11.1.0: + resolution: {integrity: sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==} + engines: {node: '>=10'} + gopd@1.0.1: resolution: {integrity: sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==} @@ -1510,6 +1537,10 @@ packages: is-arrayish@0.3.2: resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==} + is-binary-path@2.1.0: + resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==} + engines: {node: '>=8'} + is-core-module@2.15.1: resolution: {integrity: sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==} engines: {node: '>= 0.4'} @@ -1883,6 +1914,10 @@ packages: ms@2.1.3: resolution: {integrity: sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==} + mylas@2.1.13: + resolution: {integrity: sha512-+MrqnJRtxdF+xngFfUUkIMQrUUL0KsxbADUkn23Z/4ibGg192Q+z+CQyiYwvWTsYjJygmMR8+w3ZDa98Zh6ESg==} + engines: {node: '>=12.0.0'} + natural-compare@1.4.0: resolution: {integrity: sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==} @@ -2003,6 +2038,10 @@ packages: path-to-regexp@0.1.10: resolution: {integrity: sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==} + path-type@4.0.0: + resolution: {integrity: sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==} + engines: {node: '>=8'} + pg-cloudflare@1.1.1: resolution: {integrity: sha512-xWPagP/4B6BgFO+EKz3JONXv3YDgvkbVrGw2mTo3D6tVDQRh1e7cqVGvyR3BE+eQgAvx1XhW/iEASj4/jCWl3Q==} @@ -2065,6 +2104,10 @@ packages: resolution: {integrity: sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==} engines: {node: '>=8'} + plimit-lit@1.6.1: + resolution: {integrity: sha512-B7+VDyb8Tl6oMJT9oSO2CW8XC/T4UcJGrwOVoNGwOQsQYhlpfajmrMj5xeejqaASq3V/EqThyOeATEOMuSEXiA==} + engines: {node: '>=12'} + postgres-array@2.0.0: resolution: {integrity: sha512-VpZrUqU5A69eQyW2c5CA1jtLecCsN2U/bD6VilrFDWq5+5UIEVO7nazS3TEcHf1zuPYO/sqGvUvW62g86RXZuA==} engines: {node: '>=4'} @@ -2139,6 +2182,10 @@ packages: resolution: {integrity: sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==} engines: {node: '>=0.6'} + queue-lit@1.5.2: + resolution: {integrity: sha512-tLc36IOPeMAubu8BkW8YDBV+WyIgKlYU7zUNs0J5Vk9skSZ4JfGlPOqplP0aHdfv7HL0B2Pg6nwiq60Qc6M2Hw==} + engines: {node: '>=12'} + queue-microtask@1.2.3: resolution: {integrity: sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==} @@ -2157,6 +2204,10 @@ packages: resolution: {integrity: sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==} engines: {node: '>= 6'} + readdirp@3.6.0: + resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==} + engines: {node: '>=8.10.0'} + reflect-metadata@0.2.2: resolution: {integrity: sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==} @@ -2422,6 +2473,10 @@ packages: '@swc/wasm': optional: true + tsc-alias@1.8.10: + resolution: {integrity: sha512-Ibv4KAWfFkFdKJxnWfVtdOmB0Zi1RJVxcbPGiCDsFpCQSsmpWyuzHG3rQyI5YkobWwxFPEyQfu1hdo4qLG2zPw==} + hasBin: true + tslib@2.8.1: resolution: {integrity: sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==} @@ -3401,6 +3456,8 @@ snapshots: array-flatten@1.1.1: {} + array-union@2.1.0: {} + async@3.2.6: {} asynckit@0.4.0: {} @@ -3470,6 +3527,8 @@ snapshots: balanced-match@1.0.2: {} + binary-extensions@2.3.0: {} + body-parser@1.20.3: dependencies: bytes: 3.1.2 @@ -3544,6 +3603,18 @@ snapshots: char-regex@1.0.2: {} + chokidar@3.6.0: + dependencies: + anymatch: 3.1.3 + braces: 3.0.3 + glob-parent: 5.1.2 + is-binary-path: 2.1.0 + is-glob: 4.0.3 + normalize-path: 3.0.0 + readdirp: 3.6.0 + optionalDependencies: + fsevents: 2.3.3 + ci-info@3.9.0: {} cjs-module-lexer@1.4.1: {} @@ -3610,6 +3681,8 @@ snapshots: commander@12.1.0: {} + commander@9.5.0: {} + concat-map@0.0.1: {} content-disposition@0.5.4: @@ -3693,6 +3766,10 @@ snapshots: diff@4.0.2: optional: true + dir-glob@3.0.1: + dependencies: + path-type: 4.0.0 + dotenv@16.4.5: {} ee-first@1.1.1: {} @@ -4065,6 +4142,15 @@ snapshots: globals@14.0.0: {} + globby@11.1.0: + dependencies: + array-union: 2.1.0 + dir-glob: 3.0.1 + fast-glob: 3.3.2 + ignore: 5.3.2 + merge2: 1.4.1 + slash: 3.0.0 + gopd@1.0.1: dependencies: get-intrinsic: 1.2.4 @@ -4132,6 +4218,10 @@ snapshots: is-arrayish@0.3.2: {} + is-binary-path@2.1.0: + dependencies: + binary-extensions: 2.3.0 + is-core-module@2.15.1: dependencies: hasown: 2.0.2 @@ -4675,6 +4765,8 @@ snapshots: ms@2.1.3: {} + mylas@2.1.13: {} + natural-compare@1.4.0: {} negotiator@0.6.3: {} @@ -4777,6 +4869,8 @@ snapshots: path-to-regexp@0.1.10: {} + path-type@4.0.0: {} + pg-cloudflare@1.1.1: optional: true @@ -4836,6 +4930,10 @@ snapshots: dependencies: find-up: 4.1.0 + plimit-lit@1.6.1: + dependencies: + queue-lit: 1.5.2 + postgres-array@2.0.0: {} postgres-array@3.0.2: {} @@ -4892,6 +4990,8 @@ snapshots: dependencies: side-channel: 1.0.6 + queue-lit@1.5.2: {} + queue-microtask@1.2.3: {} range-parser@1.2.1: {} @@ -4911,6 +5011,10 @@ snapshots: string_decoder: 1.3.0 util-deprecate: 1.0.2 + readdirp@3.6.0: + dependencies: + picomatch: 2.3.1 + reflect-metadata@0.2.2: {} require-directory@2.1.1: {} @@ -5162,6 +5266,15 @@ snapshots: yn: 3.1.1 optional: true + tsc-alias@1.8.10: + dependencies: + chokidar: 3.6.0 + commander: 9.5.0 + globby: 11.1.0 + mylas: 2.1.13 + normalize-path: 3.0.0 + plimit-lit: 1.6.1 + tslib@2.8.1: {} tsx@4.19.2: diff --git a/src/middlewares/errorHandling.middleware.ts b/src/middlewares/errorHandling.middleware.ts index 67513ee..36b408e 100644 --- a/src/middlewares/errorHandling.middleware.ts +++ b/src/middlewares/errorHandling.middleware.ts @@ -3,11 +3,17 @@ import { Request, Response, NextFunction, ErrorRequestHandler } from 'express'; import { CustomError } from '@/exception'; import logger from '@/configs/logger.config'; -export const errorHandlingMiddleware = ((err: CustomError, req: Request, res: Response, next: NextFunction) => { +export const errorHandlingMiddleware: ErrorRequestHandler = ( + err: CustomError, + req: Request, + res: Response, + next: NextFunction, +) => { if (err instanceof CustomError) { - return res + res .status(err.statusCode) .json({ success: false, message: err.message, error: { code: err.code, statusCode: err.statusCode } }); + return; } logger.error('Internal Server Error'); res.status(500).json({ @@ -18,4 +24,5 @@ export const errorHandlingMiddleware = ((err: CustomError, req: Request, res: Re statusCode: 500, }, }); -}) as ErrorRequestHandler; + return; +}; diff --git a/src/middlewares/validation.middleware.ts b/src/middlewares/validation.middleware.ts index e635011..ac78d21 100644 --- a/src/middlewares/validation.middleware.ts +++ b/src/middlewares/validation.middleware.ts @@ -1,19 +1,22 @@ -import { NextFunction, Request, Response, RequestHandler } from 'express'; +import { NextFunction, Request, Response } from 'express'; import { plainToInstance } from 'class-transformer'; import { validate } from 'class-validator'; import logger from '@/configs/logger.config'; type RequestKey = 'body' | 'user' | 'query'; -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export const validateRequestDto = (dtoClass: new (...args: any) => T, key: RequestKey) => { - return (async (req: Request, res: Response, next: NextFunction) => { +export const validateRequestDto = ( + // eslint-disable-next-line @typescript-eslint/no-explicit-any + dtoClass: new (...args: any[]) => T, + key: RequestKey, +) => { + return async (req: Request, res: Response, next: NextFunction): Promise => { try { const value = plainToInstance(dtoClass, req[key]); const errors = await validate(value); if (errors.length > 0) { - return res.status(400).json({ + res.status(400).json({ success: false, message: '검증에 실패하였습니다. 입력값을 다시 확인해주세요.', errors: errors.map((error) => ({ @@ -21,6 +24,7 @@ export const validateRequestDto = (dtoClass: new (...args: any constraints: error.constraints, })), }); + return; } req[key] = value as T; @@ -29,5 +33,5 @@ export const validateRequestDto = (dtoClass: new (...args: any logger.error(`${key} Dto 검증 중 오류 발생 : `, error); next(error); } - }) as RequestHandler; + }; }; diff --git a/src/types/dto/velogUser.dto.ts b/src/types/dto/velogUser.dto.ts deleted file mode 100644 index 4e54e49..0000000 --- a/src/types/dto/velogUser.dto.ts +++ /dev/null @@ -1,33 +0,0 @@ -import { IsEmail, IsString, IsUUID, ValidateNested } from 'class-validator'; -import { Type } from 'class-transformer'; - -class ProfileDTO { - @IsString() - thumbnail: string; - - constructor(thumbnail: string) { - this.thumbnail = thumbnail; - } -} - -export class VelogUserLoginDto { - @IsUUID() - id: string; - - @IsString() - username: string; - - @IsEmail() - email: string; - - @ValidateNested() - @Type(() => ProfileDTO) - profile: ProfileDTO; - - constructor(id: string, username: string, email: string, profile: ProfileDTO) { - this.id = id; - this.username = username; - this.email = email; - this.profile = profile; - } -} diff --git a/src/types/dto/velogUser.type.ts b/src/types/dto/velogUser.type.ts index 11859df..4e54e49 100644 --- a/src/types/dto/velogUser.type.ts +++ b/src/types/dto/velogUser.type.ts @@ -1,6 +1,15 @@ import { IsEmail, IsString, IsUUID, ValidateNested } from 'class-validator'; import { Type } from 'class-transformer'; +class ProfileDTO { + @IsString() + thumbnail: string; + + constructor(thumbnail: string) { + this.thumbnail = thumbnail; + } +} + export class VelogUserLoginDto { @IsUUID() id: string; @@ -22,11 +31,3 @@ export class VelogUserLoginDto { this.profile = profile; } } -class ProfileDTO { - @IsString() - thumbnail: string; - - constructor(thumbnail: string) { - this.thumbnail = thumbnail; - } -}