@hamjimin/xplat-back 0.1.0 → 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +0 -1
- package/dist/cli/init.js +36 -0
- package/dist/cli/templates/api_code.ts.example +70 -0
- package/dist/cli/templates/constants.ts.example +113 -0
- package/dist/core/XplatSystem.d.ts +44 -0
- package/dist/core/XplatSystem.js +55 -0
- package/dist/index.d.ts +22 -3
- package/dist/index.js +40 -7
- package/dist/modules/app/app-factory.d.ts +12 -0
- package/dist/modules/app/app-factory.js +125 -0
- package/dist/modules/app/index.d.ts +11 -0
- package/dist/modules/app/index.js +16 -0
- package/dist/modules/auth/index.d.ts +36 -0
- package/dist/modules/auth/index.js +61 -0
- package/dist/modules/auth/jwt.d.ts +40 -0
- package/dist/modules/auth/jwt.js +49 -0
- package/dist/modules/auth/middleware.d.ts +20 -0
- package/dist/modules/auth/middleware.js +88 -0
- package/dist/modules/constants/api-code.d.ts +15 -0
- package/dist/modules/constants/api-code.js +50 -0
- package/dist/modules/constants/index.d.ts +30 -0
- package/dist/modules/constants/index.js +46 -0
- package/dist/modules/middleware/error-handler.d.ts +9 -0
- package/dist/modules/middleware/error-handler.js +31 -0
- package/dist/modules/middleware/index.d.ts +30 -0
- package/dist/modules/middleware/index.js +48 -0
- package/dist/modules/middleware/logger.d.ts +11 -0
- package/dist/modules/middleware/logger.js +43 -0
- package/dist/modules/middleware/validator.d.ts +13 -0
- package/dist/modules/middleware/validator.js +81 -0
- package/dist/modules/orm/index.d.ts +30 -0
- package/dist/modules/orm/index.js +46 -0
- package/dist/modules/orm/query-builder.d.ts +68 -0
- package/dist/modules/orm/query-builder.js +238 -0
- package/dist/modules/payment/index.d.ts +43 -0
- package/dist/modules/payment/index.js +92 -0
- package/dist/modules/payment/providers/kakaopay.d.ts +17 -0
- package/dist/modules/payment/providers/kakaopay.js +51 -0
- package/dist/modules/payment/providers/toss.d.ts +15 -0
- package/dist/modules/payment/providers/toss.js +54 -0
- package/dist/modules/payment/types.d.ts +46 -0
- package/dist/modules/payment/types.js +2 -0
- package/dist/modules/router/index.d.ts +10 -0
- package/dist/modules/router/index.js +16 -0
- package/dist/modules/router/route-factory.d.ts +10 -0
- package/dist/modules/router/route-factory.js +72 -0
- package/dist/modules/shipping/index.d.ts +19 -0
- package/dist/modules/shipping/index.js +66 -0
- package/dist/modules/shipping/providers/cj.d.ts +14 -0
- package/dist/modules/shipping/providers/cj.js +35 -0
- package/dist/modules/shipping/providers/cvs.d.ts +14 -0
- package/dist/modules/shipping/providers/cvs.js +35 -0
- package/dist/modules/shipping/providers/logen.d.ts +13 -0
- package/dist/modules/shipping/providers/logen.js +35 -0
- package/dist/modules/shipping/types.d.ts +54 -0
- package/dist/modules/shipping/types.js +2 -0
- package/dist/modules/storage/index.d.ts +81 -0
- package/dist/modules/storage/index.js +86 -0
- package/dist/modules/storage/s3.d.ts +80 -0
- package/dist/modules/storage/s3.js +133 -0
- package/dist/modules/utils/date.d.ts +37 -0
- package/dist/modules/utils/date.js +72 -0
- package/dist/modules/utils/index.d.ts +44 -0
- package/dist/modules/utils/index.js +139 -0
- package/dist/modules/utils/lodash.d.ts +107 -0
- package/dist/modules/utils/lodash.js +154 -0
- package/dist/modules/utils/password.d.ts +31 -0
- package/dist/modules/utils/password.js +102 -0
- package/dist/modules/utils/pk.d.ts +18 -0
- package/dist/modules/utils/pk.js +41 -0
- package/dist/modules/utils/response.d.ts +20 -0
- package/dist/modules/utils/response.js +87 -0
- package/dist/modules/utils/validation.d.ts +50 -0
- package/dist/modules/utils/validation.js +90 -0
- package/dist/types/index.d.ts +26 -0
- package/package.json +14 -2
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AuthModule = void 0;
|
|
4
|
+
const jwt_1 = require("./jwt");
|
|
5
|
+
const middleware_1 = require("./middleware");
|
|
6
|
+
/**
|
|
7
|
+
* AuthModule - 인증/인가 모듈
|
|
8
|
+
*/
|
|
9
|
+
class AuthModule {
|
|
10
|
+
/**
|
|
11
|
+
* JWT 토큰 생성
|
|
12
|
+
*/
|
|
13
|
+
generateToken(payload, options) {
|
|
14
|
+
return (0, jwt_1.generateJWT)(payload, options);
|
|
15
|
+
}
|
|
16
|
+
/**
|
|
17
|
+
* JWT 토큰 검증
|
|
18
|
+
*/
|
|
19
|
+
verifyToken(token, secret) {
|
|
20
|
+
return (0, jwt_1.verifyJWT)(token, secret);
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Access Token과 Refresh Token 쌍 생성
|
|
24
|
+
*/
|
|
25
|
+
createTokenPair(payload, accessTokenOptions, refreshTokenOptions) {
|
|
26
|
+
return (0, jwt_1.createTokenPair)(payload, accessTokenOptions, refreshTokenOptions);
|
|
27
|
+
}
|
|
28
|
+
/**
|
|
29
|
+
* 인증 미들웨어 생성
|
|
30
|
+
*/
|
|
31
|
+
createMiddleware(options) {
|
|
32
|
+
return (0, middleware_1.createAuthMiddleware)(options);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* 선택적 인증 미들웨어 생성 (토큰이 있으면 검증, 없으면 통과)
|
|
36
|
+
*/
|
|
37
|
+
createOptionalMiddleware(options) {
|
|
38
|
+
return (0, middleware_1.createOptionalAuthMiddleware)(options);
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 환경변수 기반 토큰 생성 (편의 메서드)
|
|
42
|
+
*/
|
|
43
|
+
createTokenFromEnv(payload) {
|
|
44
|
+
const secret = process.env.JWT_SECRET || 'default-secret';
|
|
45
|
+
const accessTokenExpire = process.env.ACCESS_TOKEN_EXPIRE || '1h';
|
|
46
|
+
const refreshTokenExpire = process.env.REFRESH_TOKEN_EXPIRE || '7d';
|
|
47
|
+
return this.createTokenPair(payload, { secret, expiresIn: accessTokenExpire }, { secret, expiresIn: refreshTokenExpire });
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* 환경변수 기반 인증 미들웨어 생성 (편의 메서드)
|
|
51
|
+
*/
|
|
52
|
+
createMiddlewareFromEnv(onSuccess, onError) {
|
|
53
|
+
const secret = process.env.JWT_SECRET || 'default-secret';
|
|
54
|
+
return this.createMiddleware({
|
|
55
|
+
secret,
|
|
56
|
+
onSuccess,
|
|
57
|
+
onError,
|
|
58
|
+
});
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
exports.AuthModule = AuthModule;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* JWT 토큰 생성/검증 유틸리티
|
|
3
|
+
*
|
|
4
|
+
* zium-backend의 util/jwt.ts를 기반으로 작성되었습니다.
|
|
5
|
+
*/
|
|
6
|
+
export interface TokenPayload {
|
|
7
|
+
id: string;
|
|
8
|
+
role?: string;
|
|
9
|
+
[key: string]: any;
|
|
10
|
+
}
|
|
11
|
+
export interface TokenOptions {
|
|
12
|
+
secret: string;
|
|
13
|
+
expiresIn: string | number;
|
|
14
|
+
}
|
|
15
|
+
export interface TokenPair {
|
|
16
|
+
accessToken: string;
|
|
17
|
+
refreshToken: string;
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* JWT 토큰 생성
|
|
21
|
+
* @param payload 토큰에 포함될 데이터
|
|
22
|
+
* @param options 토큰 옵션
|
|
23
|
+
* @returns JWT 토큰
|
|
24
|
+
*/
|
|
25
|
+
export declare function generateJWT(payload: TokenPayload, options: TokenOptions): string;
|
|
26
|
+
/**
|
|
27
|
+
* JWT 토큰 검증
|
|
28
|
+
* @param token 검증할 토큰
|
|
29
|
+
* @param secret 시크릿 키
|
|
30
|
+
* @returns 디코딩된 페이로드 또는 null
|
|
31
|
+
*/
|
|
32
|
+
export declare function verifyJWT(token: string, secret: string): TokenPayload | null;
|
|
33
|
+
/**
|
|
34
|
+
* Access Token과 Refresh Token 쌍 생성
|
|
35
|
+
* @param payload 토큰에 포함될 데이터
|
|
36
|
+
* @param accessTokenOptions Access Token 옵션
|
|
37
|
+
* @param refreshTokenOptions Refresh Token 옵션
|
|
38
|
+
* @returns 토큰 쌍
|
|
39
|
+
*/
|
|
40
|
+
export declare function createTokenPair(payload: TokenPayload, accessTokenOptions: TokenOptions, refreshTokenOptions: TokenOptions): TokenPair;
|
|
@@ -0,0 +1,49 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.generateJWT = generateJWT;
|
|
7
|
+
exports.verifyJWT = verifyJWT;
|
|
8
|
+
exports.createTokenPair = createTokenPair;
|
|
9
|
+
const jsonwebtoken_1 = __importDefault(require("jsonwebtoken"));
|
|
10
|
+
/**
|
|
11
|
+
* JWT 토큰 생성
|
|
12
|
+
* @param payload 토큰에 포함될 데이터
|
|
13
|
+
* @param options 토큰 옵션
|
|
14
|
+
* @returns JWT 토큰
|
|
15
|
+
*/
|
|
16
|
+
function generateJWT(payload, options) {
|
|
17
|
+
const { secret, expiresIn } = options;
|
|
18
|
+
return jsonwebtoken_1.default.sign(payload, secret, {
|
|
19
|
+
expiresIn: typeof expiresIn === 'number' ? expiresIn : expiresIn,
|
|
20
|
+
});
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* JWT 토큰 검증
|
|
24
|
+
* @param token 검증할 토큰
|
|
25
|
+
* @param secret 시크릿 키
|
|
26
|
+
* @returns 디코딩된 페이로드 또는 null
|
|
27
|
+
*/
|
|
28
|
+
function verifyJWT(token, secret) {
|
|
29
|
+
try {
|
|
30
|
+
const decoded = jsonwebtoken_1.default.verify(token, secret);
|
|
31
|
+
return decoded;
|
|
32
|
+
}
|
|
33
|
+
catch (error) {
|
|
34
|
+
return null;
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Access Token과 Refresh Token 쌍 생성
|
|
39
|
+
* @param payload 토큰에 포함될 데이터
|
|
40
|
+
* @param accessTokenOptions Access Token 옵션
|
|
41
|
+
* @param refreshTokenOptions Refresh Token 옵션
|
|
42
|
+
* @returns 토큰 쌍
|
|
43
|
+
*/
|
|
44
|
+
function createTokenPair(payload, accessTokenOptions, refreshTokenOptions) {
|
|
45
|
+
return {
|
|
46
|
+
accessToken: generateJWT(payload, accessTokenOptions),
|
|
47
|
+
refreshToken: generateJWT(payload, refreshTokenOptions),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
import { TokenPayload } from './jwt';
|
|
3
|
+
export interface AuthMiddlewareOptions {
|
|
4
|
+
secret: string;
|
|
5
|
+
tokenName?: string;
|
|
6
|
+
cookieName?: string;
|
|
7
|
+
onSuccess?: (req: Request, payload: TokenPayload) => void;
|
|
8
|
+
onError?: (req: Request, res: Response, error: Error) => void;
|
|
9
|
+
}
|
|
10
|
+
/**
|
|
11
|
+
* JWT 토큰 검증 미들웨어 생성
|
|
12
|
+
*
|
|
13
|
+
* @param options 인증 옵션
|
|
14
|
+
* @returns Express 미들웨어
|
|
15
|
+
*/
|
|
16
|
+
export declare function createAuthMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
17
|
+
/**
|
|
18
|
+
* 선택적 인증 미들웨어 (토큰이 있으면 검증, 없으면 통과)
|
|
19
|
+
*/
|
|
20
|
+
export declare function createOptionalAuthMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.createAuthMiddleware = createAuthMiddleware;
|
|
4
|
+
exports.createOptionalAuthMiddleware = createOptionalAuthMiddleware;
|
|
5
|
+
const jwt_1 = require("./jwt");
|
|
6
|
+
const api_code_1 = require("../constants/api-code");
|
|
7
|
+
/**
|
|
8
|
+
* JWT 토큰 검증 미들웨어 생성
|
|
9
|
+
*
|
|
10
|
+
* @param options 인증 옵션
|
|
11
|
+
* @returns Express 미들웨어
|
|
12
|
+
*/
|
|
13
|
+
function createAuthMiddleware(options) {
|
|
14
|
+
const { secret, tokenName = 'accessToken', cookieName = 'accessToken', onSuccess, onError, } = options;
|
|
15
|
+
return (req, res, next) => {
|
|
16
|
+
// 쿠키나 헤더에서 토큰 가져오기
|
|
17
|
+
let token = req.cookies[cookieName];
|
|
18
|
+
if (!token && req.headers.authorization) {
|
|
19
|
+
// Bearer 토큰 형식 지원
|
|
20
|
+
const authHeader = req.headers.authorization;
|
|
21
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
22
|
+
token = authHeader.substring(7);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
if (!token) {
|
|
26
|
+
const error = new Error('Token not provided');
|
|
27
|
+
if (onError) {
|
|
28
|
+
return onError(req, res, error);
|
|
29
|
+
}
|
|
30
|
+
return res.status(401).json({
|
|
31
|
+
...(0, api_code_1.getApiCode)(1000),
|
|
32
|
+
message: 'Token not provided',
|
|
33
|
+
});
|
|
34
|
+
}
|
|
35
|
+
// 토큰 검증
|
|
36
|
+
const payload = (0, jwt_1.verifyJWT)(token, secret);
|
|
37
|
+
if (!payload) {
|
|
38
|
+
const error = new Error('Invalid token');
|
|
39
|
+
if (onError) {
|
|
40
|
+
return onError(req, res, error);
|
|
41
|
+
}
|
|
42
|
+
return res.status(401).json({
|
|
43
|
+
...(0, api_code_1.getApiCode)(1000),
|
|
44
|
+
message: 'Invalid token',
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
// 요청 객체에 사용자 정보 추가
|
|
48
|
+
req.user = payload;
|
|
49
|
+
req[tokenName] = payload;
|
|
50
|
+
// 성공 콜백 실행
|
|
51
|
+
if (onSuccess) {
|
|
52
|
+
onSuccess(req, payload);
|
|
53
|
+
}
|
|
54
|
+
next();
|
|
55
|
+
};
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* 선택적 인증 미들웨어 (토큰이 있으면 검증, 없으면 통과)
|
|
59
|
+
*/
|
|
60
|
+
function createOptionalAuthMiddleware(options) {
|
|
61
|
+
const { secret, tokenName = 'accessToken', cookieName = 'accessToken', onSuccess, } = options;
|
|
62
|
+
return (req, res, next) => {
|
|
63
|
+
// 쿠키나 헤더에서 토큰 가져오기
|
|
64
|
+
let token = req.cookies[cookieName];
|
|
65
|
+
if (!token && req.headers.authorization) {
|
|
66
|
+
const authHeader = req.headers.authorization;
|
|
67
|
+
if (authHeader.startsWith('Bearer ')) {
|
|
68
|
+
token = authHeader.substring(7);
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 토큰이 없으면 그냥 통과
|
|
72
|
+
if (!token) {
|
|
73
|
+
return next();
|
|
74
|
+
}
|
|
75
|
+
// 토큰 검증
|
|
76
|
+
const payload = (0, jwt_1.verifyJWT)(token, secret);
|
|
77
|
+
if (payload) {
|
|
78
|
+
// 요청 객체에 사용자 정보 추가
|
|
79
|
+
req.user = payload;
|
|
80
|
+
req[tokenName] = payload;
|
|
81
|
+
// 성공 콜백 실행
|
|
82
|
+
if (onSuccess) {
|
|
83
|
+
onSuccess(req, payload);
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
next();
|
|
87
|
+
};
|
|
88
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API 응답 코드 정의
|
|
3
|
+
*
|
|
4
|
+
* zium-backend의 api_code.ts를 기반으로 작성되었습니다.
|
|
5
|
+
*/
|
|
6
|
+
export interface ApiCode {
|
|
7
|
+
code: number;
|
|
8
|
+
msg: string;
|
|
9
|
+
message?: string;
|
|
10
|
+
}
|
|
11
|
+
export declare const API_CODE: Record<number, ApiCode>;
|
|
12
|
+
/**
|
|
13
|
+
* API 코드 가져오기
|
|
14
|
+
*/
|
|
15
|
+
export declare function getApiCode(code: number): ApiCode;
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
/**
|
|
3
|
+
* API 응답 코드 정의
|
|
4
|
+
*
|
|
5
|
+
* zium-backend의 api_code.ts를 기반으로 작성되었습니다.
|
|
6
|
+
*/
|
|
7
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
8
|
+
exports.API_CODE = void 0;
|
|
9
|
+
exports.getApiCode = getApiCode;
|
|
10
|
+
exports.API_CODE = {
|
|
11
|
+
// 성공
|
|
12
|
+
200: { code: 200, msg: '성공' },
|
|
13
|
+
// Not Found
|
|
14
|
+
404: { code: 404, msg: '요청 사항을 찾을 수 없습니다' },
|
|
15
|
+
// 권한 (1000~1999)
|
|
16
|
+
1000: { code: 1000, msg: '권한이 없습니다' },
|
|
17
|
+
// 사용자 (2000~2999)
|
|
18
|
+
2000: { code: 2000, msg: '아이디 또는 비밀번호를 확인해주세요' },
|
|
19
|
+
2001: { code: 2001, msg: '중복된 아이디 입니다' },
|
|
20
|
+
2002: { code: 2002, msg: '유효한 EMAIL이 아닙니다' },
|
|
21
|
+
2003: { code: 2003, msg: '유효한 회원이 아닙니다' },
|
|
22
|
+
2004: { code: 2004, msg: '비밀번호를 재설정 해주세요' },
|
|
23
|
+
2005: { code: 2005, msg: '비밀번호가 초기화 되었습니다 EMAIL 확인해주세요' },
|
|
24
|
+
2006: { code: 2006, msg: '탈퇴한 회원입니다' },
|
|
25
|
+
2007: { code: 2007, msg: '유효한 이메일이 아닙니다' },
|
|
26
|
+
2008: { code: 2008, msg: '유효한 비밀번호가 아닙니다' },
|
|
27
|
+
2009: { code: 2009, msg: '유효한 휴대폰 번호가 아닙니다' },
|
|
28
|
+
2010: { code: 2010, msg: '카카오 로그인 오류' },
|
|
29
|
+
2011: { code: 2011, msg: '비밀번호가 틀렸습니다' },
|
|
30
|
+
2012: { code: 2012, msg: '회원가입 시 문제가 발생했습니다. 관리자에게 문의 해주세요' },
|
|
31
|
+
2013: { code: 2013, msg: '사용되지 않는 회원(고객)입니다. - 전화번호 중복 -' },
|
|
32
|
+
// 관리자 (3000 ~ 3999)
|
|
33
|
+
3000: { code: 3000, msg: '기존 회원입니다.' },
|
|
34
|
+
3001: { code: 3001, msg: '비 회원입니다.' },
|
|
35
|
+
3002: { code: 3002, msg: '중복된데이터 입니다.' },
|
|
36
|
+
3003: { code: 3003, msg: '등록된 상품이 아닙니다.' },
|
|
37
|
+
// 결제 실패 (4000~4999)
|
|
38
|
+
4000: { code: 4000, msg: '결제 실패' },
|
|
39
|
+
// 공용사항 (9000~9999)
|
|
40
|
+
9000: { code: 9000, msg: '오류가 발생했습니다. 관리자에게 문의 해주세요' },
|
|
41
|
+
9001: { code: 9001, msg: '유효하지 않은 데이터입니다.' },
|
|
42
|
+
9002: { code: 9002, msg: '유효하지 않은 컬럼입니다.' },
|
|
43
|
+
9003: { code: 9003, msg: '잘못된 요청입니다.' },
|
|
44
|
+
};
|
|
45
|
+
/**
|
|
46
|
+
* API 코드 가져오기
|
|
47
|
+
*/
|
|
48
|
+
function getApiCode(code) {
|
|
49
|
+
return exports.API_CODE[code] || exports.API_CODE[9000];
|
|
50
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { ApiCode } from './api-code';
|
|
2
|
+
/**
|
|
3
|
+
* ConstantsModule - 상수 관리 모듈
|
|
4
|
+
*/
|
|
5
|
+
export declare class ConstantsModule {
|
|
6
|
+
/**
|
|
7
|
+
* API 코드 가져오기
|
|
8
|
+
*/
|
|
9
|
+
getApiCode(code: number): ApiCode;
|
|
10
|
+
/**
|
|
11
|
+
* 모든 API 코드 접근
|
|
12
|
+
*/
|
|
13
|
+
get codes(): Record<number, ApiCode>;
|
|
14
|
+
/**
|
|
15
|
+
* 성공 코드
|
|
16
|
+
*/
|
|
17
|
+
get SUCCESS(): ApiCode;
|
|
18
|
+
/**
|
|
19
|
+
* NotFound 코드
|
|
20
|
+
*/
|
|
21
|
+
get NOT_FOUND(): ApiCode;
|
|
22
|
+
/**
|
|
23
|
+
* 권한 없음 코드
|
|
24
|
+
*/
|
|
25
|
+
get UNAUTHORIZED(): ApiCode;
|
|
26
|
+
/**
|
|
27
|
+
* 서버 에러 코드
|
|
28
|
+
*/
|
|
29
|
+
get SERVER_ERROR(): ApiCode;
|
|
30
|
+
}
|
|
@@ -0,0 +1,46 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.ConstantsModule = void 0;
|
|
4
|
+
const api_code_1 = require("./api-code");
|
|
5
|
+
/**
|
|
6
|
+
* ConstantsModule - 상수 관리 모듈
|
|
7
|
+
*/
|
|
8
|
+
class ConstantsModule {
|
|
9
|
+
/**
|
|
10
|
+
* API 코드 가져오기
|
|
11
|
+
*/
|
|
12
|
+
getApiCode(code) {
|
|
13
|
+
return (0, api_code_1.getApiCode)(code);
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* 모든 API 코드 접근
|
|
17
|
+
*/
|
|
18
|
+
get codes() {
|
|
19
|
+
return api_code_1.API_CODE;
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 성공 코드
|
|
23
|
+
*/
|
|
24
|
+
get SUCCESS() {
|
|
25
|
+
return api_code_1.API_CODE[200];
|
|
26
|
+
}
|
|
27
|
+
/**
|
|
28
|
+
* NotFound 코드
|
|
29
|
+
*/
|
|
30
|
+
get NOT_FOUND() {
|
|
31
|
+
return api_code_1.API_CODE[404];
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* 권한 없음 코드
|
|
35
|
+
*/
|
|
36
|
+
get UNAUTHORIZED() {
|
|
37
|
+
return api_code_1.API_CODE[1000];
|
|
38
|
+
}
|
|
39
|
+
/**
|
|
40
|
+
* 서버 에러 코드
|
|
41
|
+
*/
|
|
42
|
+
get SERVER_ERROR() {
|
|
43
|
+
return api_code_1.API_CODE[9000];
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
exports.ConstantsModule = ConstantsModule;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* 에러 핸들러 미들웨어
|
|
4
|
+
*/
|
|
5
|
+
export declare function errorHandler(): (err: Error, req: Request, res: Response, next: NextFunction) => void;
|
|
6
|
+
/**
|
|
7
|
+
* 404 핸들러
|
|
8
|
+
*/
|
|
9
|
+
export declare function notFoundHandler(): (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.errorHandler = errorHandler;
|
|
4
|
+
exports.notFoundHandler = notFoundHandler;
|
|
5
|
+
const api_code_1 = require("../constants/api-code");
|
|
6
|
+
/**
|
|
7
|
+
* 에러 핸들러 미들웨어
|
|
8
|
+
*/
|
|
9
|
+
function errorHandler() {
|
|
10
|
+
return (err, req, res, next) => {
|
|
11
|
+
console.error('Error:', err);
|
|
12
|
+
const isProduction = process.env.NODE_ENV === 'production';
|
|
13
|
+
const errorResponse = {
|
|
14
|
+
...(0, api_code_1.getApiCode)(9000),
|
|
15
|
+
message: isProduction ? 'Internal Server Error' : err.message,
|
|
16
|
+
...(isProduction ? {} : { stack: err.stack }),
|
|
17
|
+
};
|
|
18
|
+
res.status(500).json(errorResponse);
|
|
19
|
+
};
|
|
20
|
+
}
|
|
21
|
+
/**
|
|
22
|
+
* 404 핸들러
|
|
23
|
+
*/
|
|
24
|
+
function notFoundHandler() {
|
|
25
|
+
return (req, res, next) => {
|
|
26
|
+
res.status(404).json({
|
|
27
|
+
...(0, api_code_1.getApiCode)(404),
|
|
28
|
+
path: req.path,
|
|
29
|
+
});
|
|
30
|
+
};
|
|
31
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { dataValidator } from './validator';
|
|
2
|
+
/**
|
|
3
|
+
* MiddlewareModule - 미들웨어 생성 모듈
|
|
4
|
+
*/
|
|
5
|
+
export declare class MiddlewareModule {
|
|
6
|
+
/**
|
|
7
|
+
* 요청 로깅 미들웨어 생성
|
|
8
|
+
*/
|
|
9
|
+
logger(): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => void;
|
|
10
|
+
/**
|
|
11
|
+
* 상세 요청 로깅 미들웨어 생성 (body 포함)
|
|
12
|
+
*/
|
|
13
|
+
detailedLogger(): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => void;
|
|
14
|
+
/**
|
|
15
|
+
* 에러 핸들러 미들웨어 생성
|
|
16
|
+
*/
|
|
17
|
+
errorHandler(): (err: Error, req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => void;
|
|
18
|
+
/**
|
|
19
|
+
* 404 핸들러 미들웨어 생성
|
|
20
|
+
*/
|
|
21
|
+
notFound(): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => void;
|
|
22
|
+
/**
|
|
23
|
+
* 데이터 검증 미들웨어 생성
|
|
24
|
+
*/
|
|
25
|
+
validator(rules: Parameters<typeof dataValidator>[0]): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => import("express").Response<any, Record<string, any>> | undefined;
|
|
26
|
+
/**
|
|
27
|
+
* 필수 필드 검증 미들웨어 생성
|
|
28
|
+
*/
|
|
29
|
+
requireFields(fields: string[]): (req: import("express").Request, res: import("express").Response, next: import("express").NextFunction) => import("express").Response<any, Record<string, any>> | undefined;
|
|
30
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.MiddlewareModule = void 0;
|
|
4
|
+
const logger_1 = require("./logger");
|
|
5
|
+
const error_handler_1 = require("./error-handler");
|
|
6
|
+
const validator_1 = require("./validator");
|
|
7
|
+
/**
|
|
8
|
+
* MiddlewareModule - 미들웨어 생성 모듈
|
|
9
|
+
*/
|
|
10
|
+
class MiddlewareModule {
|
|
11
|
+
/**
|
|
12
|
+
* 요청 로깅 미들웨어 생성
|
|
13
|
+
*/
|
|
14
|
+
logger() {
|
|
15
|
+
return (0, logger_1.requestLogger)();
|
|
16
|
+
}
|
|
17
|
+
/**
|
|
18
|
+
* 상세 요청 로깅 미들웨어 생성 (body 포함)
|
|
19
|
+
*/
|
|
20
|
+
detailedLogger() {
|
|
21
|
+
return (0, logger_1.detailedRequestLogger)();
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 에러 핸들러 미들웨어 생성
|
|
25
|
+
*/
|
|
26
|
+
errorHandler() {
|
|
27
|
+
return (0, error_handler_1.errorHandler)();
|
|
28
|
+
}
|
|
29
|
+
/**
|
|
30
|
+
* 404 핸들러 미들웨어 생성
|
|
31
|
+
*/
|
|
32
|
+
notFound() {
|
|
33
|
+
return (0, error_handler_1.notFoundHandler)();
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* 데이터 검증 미들웨어 생성
|
|
37
|
+
*/
|
|
38
|
+
validator(rules) {
|
|
39
|
+
return (0, validator_1.dataValidator)(rules);
|
|
40
|
+
}
|
|
41
|
+
/**
|
|
42
|
+
* 필수 필드 검증 미들웨어 생성
|
|
43
|
+
*/
|
|
44
|
+
requireFields(fields) {
|
|
45
|
+
return (0, validator_1.requireFields)(fields);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
exports.MiddlewareModule = MiddlewareModule;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* 요청 로깅 미들웨어
|
|
4
|
+
*
|
|
5
|
+
* zium-backend의 messageCheck를 기반으로 작성되었습니다.
|
|
6
|
+
*/
|
|
7
|
+
export declare function requestLogger(): (req: Request, res: Response, next: NextFunction) => void;
|
|
8
|
+
/**
|
|
9
|
+
* 상세 요청 로깅 미들웨어 (body 포함)
|
|
10
|
+
*/
|
|
11
|
+
export declare function detailedRequestLogger(): (req: Request, res: Response, next: NextFunction) => void;
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.requestLogger = requestLogger;
|
|
4
|
+
exports.detailedRequestLogger = detailedRequestLogger;
|
|
5
|
+
/**
|
|
6
|
+
* 요청 로깅 미들웨어
|
|
7
|
+
*
|
|
8
|
+
* zium-backend의 messageCheck를 기반으로 작성되었습니다.
|
|
9
|
+
*/
|
|
10
|
+
function requestLogger() {
|
|
11
|
+
return (req, res, next) => {
|
|
12
|
+
const start = Date.now();
|
|
13
|
+
const { method, path, ip } = req;
|
|
14
|
+
// 응답 완료 후 로깅
|
|
15
|
+
res.on('finish', () => {
|
|
16
|
+
const duration = Date.now() - start;
|
|
17
|
+
const { statusCode } = res;
|
|
18
|
+
console.log(`[${new Date().toISOString()}] ${method} ${path} ${statusCode} - ${duration}ms - ${ip}`);
|
|
19
|
+
});
|
|
20
|
+
next();
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
/**
|
|
24
|
+
* 상세 요청 로깅 미들웨어 (body 포함)
|
|
25
|
+
*/
|
|
26
|
+
function detailedRequestLogger() {
|
|
27
|
+
return (req, res, next) => {
|
|
28
|
+
const start = Date.now();
|
|
29
|
+
const { method, path, ip, body } = req;
|
|
30
|
+
// 요청 시작 시 로깅
|
|
31
|
+
console.log(`[${new Date().toISOString()}] ${method} ${path} - ${ip}`);
|
|
32
|
+
if (Object.keys(body || {}).length > 0) {
|
|
33
|
+
console.log('Request Body:', JSON.stringify(body, null, 2));
|
|
34
|
+
}
|
|
35
|
+
// 응답 완료 후 로깅
|
|
36
|
+
res.on('finish', () => {
|
|
37
|
+
const duration = Date.now() - start;
|
|
38
|
+
const { statusCode } = res;
|
|
39
|
+
console.log(`[${new Date().toISOString()}] ${method} ${path} ${statusCode} - ${duration}ms`);
|
|
40
|
+
});
|
|
41
|
+
next();
|
|
42
|
+
};
|
|
43
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import { Request, Response, NextFunction } from 'express';
|
|
2
|
+
/**
|
|
3
|
+
* 데이터 검증 미들웨어
|
|
4
|
+
*/
|
|
5
|
+
export declare function dataValidator(rules: {
|
|
6
|
+
body?: Record<string, (value: any) => boolean | string>;
|
|
7
|
+
query?: Record<string, (value: any) => boolean | string>;
|
|
8
|
+
params?: Record<string, (value: any) => boolean | string>;
|
|
9
|
+
}): (req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>> | undefined;
|
|
10
|
+
/**
|
|
11
|
+
* 요청 body 필수 필드 검증
|
|
12
|
+
*/
|
|
13
|
+
export declare function requireFields(fields: string[]): (req: Request, res: Response, next: NextFunction) => Response<any, Record<string, any>> | undefined;
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.dataValidator = dataValidator;
|
|
4
|
+
exports.requireFields = requireFields;
|
|
5
|
+
const api_code_1 = require("../constants/api-code");
|
|
6
|
+
/**
|
|
7
|
+
* 데이터 검증 미들웨어
|
|
8
|
+
*/
|
|
9
|
+
function dataValidator(rules) {
|
|
10
|
+
return (req, res, next) => {
|
|
11
|
+
const errors = [];
|
|
12
|
+
// Body 검증
|
|
13
|
+
if (rules.body) {
|
|
14
|
+
for (const [key, validator] of Object.entries(rules.body)) {
|
|
15
|
+
const value = req.body[key];
|
|
16
|
+
const result = validator(value);
|
|
17
|
+
if (typeof result === 'string') {
|
|
18
|
+
errors.push(result);
|
|
19
|
+
}
|
|
20
|
+
else if (!result) {
|
|
21
|
+
errors.push(`${key} is invalid`);
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
// Query 검증
|
|
26
|
+
if (rules.query) {
|
|
27
|
+
for (const [key, validator] of Object.entries(rules.query)) {
|
|
28
|
+
const value = req.query[key];
|
|
29
|
+
const result = validator(value);
|
|
30
|
+
if (typeof result === 'string') {
|
|
31
|
+
errors.push(result);
|
|
32
|
+
}
|
|
33
|
+
else if (!result) {
|
|
34
|
+
errors.push(`Query parameter ${key} is invalid`);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
// Params 검증
|
|
39
|
+
if (rules.params) {
|
|
40
|
+
for (const [key, validator] of Object.entries(rules.params)) {
|
|
41
|
+
const value = req.params[key];
|
|
42
|
+
const result = validator(value);
|
|
43
|
+
if (typeof result === 'string') {
|
|
44
|
+
errors.push(result);
|
|
45
|
+
}
|
|
46
|
+
else if (!result) {
|
|
47
|
+
errors.push(`Parameter ${key} is invalid`);
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
if (errors.length > 0) {
|
|
52
|
+
return res.status(400).json({
|
|
53
|
+
...(0, api_code_1.getApiCode)(9001),
|
|
54
|
+
message: 'Validation failed',
|
|
55
|
+
errors,
|
|
56
|
+
});
|
|
57
|
+
}
|
|
58
|
+
next();
|
|
59
|
+
};
|
|
60
|
+
}
|
|
61
|
+
/**
|
|
62
|
+
* 요청 body 필수 필드 검증
|
|
63
|
+
*/
|
|
64
|
+
function requireFields(fields) {
|
|
65
|
+
return (req, res, next) => {
|
|
66
|
+
const missing = [];
|
|
67
|
+
for (const field of fields) {
|
|
68
|
+
if (!req.body[field]) {
|
|
69
|
+
missing.push(field);
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
if (missing.length > 0) {
|
|
73
|
+
return res.status(400).json({
|
|
74
|
+
...(0, api_code_1.getApiCode)(9001),
|
|
75
|
+
message: `Missing required fields: ${missing.join(', ')}`,
|
|
76
|
+
missing,
|
|
77
|
+
});
|
|
78
|
+
}
|
|
79
|
+
next();
|
|
80
|
+
};
|
|
81
|
+
}
|