@hamjimin/xplat-back 0.1.0 → 0.2.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 +40 -0
- package/dist/core/XplatSystem.js +51 -0
- package/dist/index.d.ts +16 -3
- package/dist/index.js +29 -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/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/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
package/README.md
CHANGED
package/dist/cli/init.js
CHANGED
|
@@ -73,6 +73,8 @@ async function initializeProject(config = {}) {
|
|
|
73
73
|
await createEnvFile(projectRoot, port, corsOrigins);
|
|
74
74
|
// 예시 라우트 파일 생성
|
|
75
75
|
await createExampleRouteFile(restapiDir);
|
|
76
|
+
// 상수 파일 생성 (src/const 디렉토리)
|
|
77
|
+
await createConstantsFiles(srcDir);
|
|
76
78
|
console.log('\n✅ 프로젝트 초기화가 완료되었습니다!');
|
|
77
79
|
console.log(`\n생성된 파일:`);
|
|
78
80
|
console.log(` - src/app.ts`);
|
|
@@ -81,6 +83,8 @@ async function initializeProject(config = {}) {
|
|
|
81
83
|
console.log(` - package.json (없던 경우만)`);
|
|
82
84
|
console.log(` - .env`);
|
|
83
85
|
console.log(` - ${routerDirectory}/health.ts`);
|
|
86
|
+
console.log(` - src/const/api_code.ts`);
|
|
87
|
+
console.log(` - src/const/constants.ts`);
|
|
84
88
|
console.log(`\n다음 단계:`);
|
|
85
89
|
console.log(` 1. npm install (또는 yarn install)`);
|
|
86
90
|
console.log(` 2. npm run dev (또는 yarn dev)로 서버 실행`);
|
|
@@ -262,3 +266,35 @@ async function createExampleRouteFile(restapiDir) {
|
|
|
262
266
|
fs.writeFileSync(healthPath, templateContent, 'utf-8');
|
|
263
267
|
console.log(`✅ health.ts 파일이 생성되었습니다.`);
|
|
264
268
|
}
|
|
269
|
+
/**
|
|
270
|
+
* 상수 파일 생성 (api_code.ts, constants.ts)
|
|
271
|
+
*/
|
|
272
|
+
async function createConstantsFiles(srcDir) {
|
|
273
|
+
const constDir = path.join(srcDir, 'const');
|
|
274
|
+
// const 디렉토리 생성
|
|
275
|
+
if (!fs.existsSync(constDir)) {
|
|
276
|
+
fs.mkdirSync(constDir, { recursive: true });
|
|
277
|
+
}
|
|
278
|
+
// api_code.ts 파일 생성
|
|
279
|
+
const apiCodePath = path.join(constDir, 'api_code.ts');
|
|
280
|
+
if (!fs.existsSync(apiCodePath)) {
|
|
281
|
+
const templatePath = path.join(__dirname, 'templates', 'api_code.ts.example');
|
|
282
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
283
|
+
fs.writeFileSync(apiCodePath, templateContent, 'utf-8');
|
|
284
|
+
console.log(`✅ src/const/api_code.ts 파일이 생성되었습니다.`);
|
|
285
|
+
}
|
|
286
|
+
else {
|
|
287
|
+
console.log(`⚠️ src/const/api_code.ts 파일이 이미 존재합니다. 건너뜁니다.`);
|
|
288
|
+
}
|
|
289
|
+
// constants.ts 파일 생성
|
|
290
|
+
const constantsPath = path.join(constDir, 'constants.ts');
|
|
291
|
+
if (!fs.existsSync(constantsPath)) {
|
|
292
|
+
const templatePath = path.join(__dirname, 'templates', 'constants.ts.example');
|
|
293
|
+
const templateContent = fs.readFileSync(templatePath, 'utf-8');
|
|
294
|
+
fs.writeFileSync(constantsPath, templateContent, 'utf-8');
|
|
295
|
+
console.log(`✅ src/const/constants.ts 파일이 생성되었습니다.`);
|
|
296
|
+
}
|
|
297
|
+
else {
|
|
298
|
+
console.log(`⚠️ src/const/constants.ts 파일이 이미 존재합니다. 건너뜁니다.`);
|
|
299
|
+
}
|
|
300
|
+
}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* API 응답 코드 정의
|
|
3
|
+
*
|
|
4
|
+
* 프로젝트에서 사용할 API 응답 코드를 정의합니다.
|
|
5
|
+
* xplat-back의 기본 코드를 포함하며, 프로젝트에 맞게 확장 가능합니다.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
export interface ApiCode {
|
|
9
|
+
code: number;
|
|
10
|
+
msg: string;
|
|
11
|
+
message?: string;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
export const API_CODE: Record<number, ApiCode> = {
|
|
15
|
+
// 성공
|
|
16
|
+
200: { code: 200, msg: "성공" },
|
|
17
|
+
|
|
18
|
+
// Not Found
|
|
19
|
+
404: { code: 404, msg: "요청 사항을 찾을 수 없습니다" },
|
|
20
|
+
|
|
21
|
+
// 권한 (1000~1999)
|
|
22
|
+
1000: { code: 1000, msg: "권한이 없습니다" },
|
|
23
|
+
|
|
24
|
+
// 사용자 (2000~2999)
|
|
25
|
+
2000: { code: 2000, msg: "아이디 또는 비밀번호를 확인해주세요" },
|
|
26
|
+
2001: { code: 2001, msg: "중복된 아이디 입니다" },
|
|
27
|
+
2002: { code: 2002, msg: "유효한 EMAIL이 아닙니다" },
|
|
28
|
+
2003: { code: 2003, msg: "유효한 회원이 아닙니다" },
|
|
29
|
+
2004: { code: 2004, msg: "비밀번호를 재설정 해주세요" },
|
|
30
|
+
2005: { code: 2005, msg: "비밀번호가 초기화 되었습니다 EMAIL 확인해주세요" },
|
|
31
|
+
2006: { code: 2006, msg: "탈퇴한 회원입니다" },
|
|
32
|
+
2007: { code: 2007, msg: "유효한 이메일이 아닙니다" },
|
|
33
|
+
2008: { code: 2008, msg: "유효한 비밀번호가 아닙니다" },
|
|
34
|
+
2009: { code: 2009, msg: "유효한 휴대폰 번호가 아닙니다" },
|
|
35
|
+
2010: { code: 2010, msg: "카카오 로그인 오류" },
|
|
36
|
+
2011: { code: 2011, msg: "비밀번호가 틀렸습니다" },
|
|
37
|
+
2012: { code: 2012, msg: "회원가입 시 문제가 발생했습니다. 관리자에게 문의 해주세요" },
|
|
38
|
+
2013: { code: 2013, msg: "사용되지 않는 회원(고객)입니다. - 전화번호 중복 -" },
|
|
39
|
+
|
|
40
|
+
// 관리자 (3000 ~ 3999)
|
|
41
|
+
3000: { code: 3000, msg: "기존 회원입니다." },
|
|
42
|
+
3001: { code: 3001, msg: "비 회원입니다." },
|
|
43
|
+
3002: { code: 3002, msg: "중복된데이터 입니다." },
|
|
44
|
+
3003: { code: 3003, msg: "등록된 상품이 아닙니다." },
|
|
45
|
+
|
|
46
|
+
// 결제 실패 (4000~4999)
|
|
47
|
+
4000: { code: 4000, msg: "결제 실패" },
|
|
48
|
+
|
|
49
|
+
// 공용사항 (9000~9999)
|
|
50
|
+
9000: { code: 9000, msg: "오류가 발생했습니다. 관리자에게 문의 해주세요" },
|
|
51
|
+
9001: { code: 9001, msg: "유효하지 않은 데이터입니다." },
|
|
52
|
+
9002: { code: 9002, msg: "유효하지 않은 컬럼입니다." },
|
|
53
|
+
9003: { code: 9003, msg: "잘못된 요청입니다." },
|
|
54
|
+
|
|
55
|
+
// 프로젝트별 추가 코드는 아래에 추가하세요
|
|
56
|
+
// 예:
|
|
57
|
+
// 5000: { code: 5000, msg: "프로젝트별 에러 메시지" },
|
|
58
|
+
};
|
|
59
|
+
|
|
60
|
+
/**
|
|
61
|
+
* API 코드 가져오기
|
|
62
|
+
*/
|
|
63
|
+
export function getApiCode(code: number): ApiCode {
|
|
64
|
+
return API_CODE[code] || API_CODE[9000];
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
/**
|
|
68
|
+
* API 코드 타입
|
|
69
|
+
*/
|
|
70
|
+
export type ApiCodeType = keyof typeof API_CODE;
|
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* 프로젝트 공통 상수 및 설정
|
|
3
|
+
*
|
|
4
|
+
* 이 파일은 프로젝트에 필요한 공통 변수들을 정의하는 곳입니다.
|
|
5
|
+
* 프로젝트에 맞게 수정하여 사용하세요.
|
|
6
|
+
*/
|
|
7
|
+
|
|
8
|
+
// 기본 불리언 문자열 상수
|
|
9
|
+
export const strTrue = "T";
|
|
10
|
+
export const strFalse = "F";
|
|
11
|
+
|
|
12
|
+
// 날짜 상수
|
|
13
|
+
export const toDay = new Date();
|
|
14
|
+
export const yesterDay = new Date(toDay.getTime() - 24 * 60 * 60 * 1000);
|
|
15
|
+
export const tomorrow = new Date(toDay.getTime() + 24 * 60 * 60 * 1000);
|
|
16
|
+
|
|
17
|
+
// S3 설정
|
|
18
|
+
export const bucketName = process.env.S3_BUCKET || "your-bucket-name";
|
|
19
|
+
export const region = process.env.AWS_REGION || "ap-northeast-2"; // 서울 리전
|
|
20
|
+
|
|
21
|
+
// 예외 메시지
|
|
22
|
+
export const exceptionMessage = {
|
|
23
|
+
requiredData: "선행 데이터가 입력(선택)되지 않았습니다.",
|
|
24
|
+
notFoundData: "조회된 데이터가 없습니다. - 잘못된 정보 -",
|
|
25
|
+
failedInsert: "데이터 저장에 실패했습니다.",
|
|
26
|
+
invalidType: "유효하지 않은 타입입니다.",
|
|
27
|
+
duplicateData: "중복된 데이터입니다.",
|
|
28
|
+
alreadyExists: "이미 존재하는 데이터입니다.",
|
|
29
|
+
haveAPayment: "결제중인 결제건이 있습니다.",
|
|
30
|
+
paymentAmount: "결제 금액이 0원 이하입니다.",
|
|
31
|
+
paymentAmountOver: "결제 금액이 총 결제 금액보다 높습니다.",
|
|
32
|
+
retryData: "데이터 저장에 실패했습니다. 다시 시도해주세요.",
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
// 시스템 메시지
|
|
36
|
+
export const systemMessage = {
|
|
37
|
+
updateData: "데이터 수정과 같이 진행되었습니다.",
|
|
38
|
+
};
|
|
39
|
+
|
|
40
|
+
// 빈 문자열
|
|
41
|
+
export const emptyString = "";
|
|
42
|
+
|
|
43
|
+
// 메시지 타입
|
|
44
|
+
export const messageType = {
|
|
45
|
+
SMS: "단문",
|
|
46
|
+
LMS: "장문",
|
|
47
|
+
MMS: "사진문자",
|
|
48
|
+
CTA: "카카오 친구톡",
|
|
49
|
+
ATA: "카카오 알림톡",
|
|
50
|
+
CTI: "친구 이미지 톡",
|
|
51
|
+
} as const;
|
|
52
|
+
|
|
53
|
+
// 사용자 역할
|
|
54
|
+
export const memberRole = {
|
|
55
|
+
none: "none", // 비회원
|
|
56
|
+
customer: "customer", // 회원
|
|
57
|
+
employee: "employee", // 직원
|
|
58
|
+
admin: "admin", // 관리자
|
|
59
|
+
manager: "manager", // 지점장
|
|
60
|
+
};
|
|
61
|
+
|
|
62
|
+
// 기본 정렬
|
|
63
|
+
export const DEFAULT_ORDER = "ORDER BY (SELECT NULL)";
|
|
64
|
+
|
|
65
|
+
// 상태 값 (프로젝트에 맞게 수정)
|
|
66
|
+
export const status: Record<string, string> = {
|
|
67
|
+
Pending: "pending", // 대기
|
|
68
|
+
Confirm: "confirm", // 확정
|
|
69
|
+
serviceComplete: "serviceComplete", // 서비스 완료
|
|
70
|
+
duplication: "duplication", // 중복
|
|
71
|
+
cancleRetry: "cancleRetry", // 취소 후 결제 재시도
|
|
72
|
+
nonProcess: "nonProcess", // 미진행
|
|
73
|
+
reservation: "reservation", // 예약
|
|
74
|
+
delteStatus: "delete", // 삭제
|
|
75
|
+
updateStatus: "update", // 수정
|
|
76
|
+
inProcess: "inProcess", // 진행 중
|
|
77
|
+
callConsult: "callConsult", // 상담 완료
|
|
78
|
+
Emergency: "emergency", // 긴급
|
|
79
|
+
Discussion: "discussion", // 협의
|
|
80
|
+
Completed: "complete", // 완료
|
|
81
|
+
Cancelled: "cancel", // 취소
|
|
82
|
+
temporarySave: "temporarySave", // 임시저장
|
|
83
|
+
issued: "issued", // 발행
|
|
84
|
+
used: "used", // 사용
|
|
85
|
+
expired: "expired", // 만료
|
|
86
|
+
paymenting: "paymenting", // 결제 중
|
|
87
|
+
paymentComplete: "paymentComplete", // 결제 완료
|
|
88
|
+
paymentPending: "paymentPending", // 결제 대기
|
|
89
|
+
refund: "refund", // 환불
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
// 결제 방법
|
|
93
|
+
export const paymebtMethod = {
|
|
94
|
+
Card: "card",
|
|
95
|
+
Bank: "bank",
|
|
96
|
+
Cash: "cash",
|
|
97
|
+
ETC: "etc",
|
|
98
|
+
};
|
|
99
|
+
|
|
100
|
+
// 메시지 타입 (상세)
|
|
101
|
+
export const messageTypes = {
|
|
102
|
+
alarm: "alarm",
|
|
103
|
+
ba: "BA",
|
|
104
|
+
ex: "EX",
|
|
105
|
+
lms: "LMS",
|
|
106
|
+
sms: "SMS",
|
|
107
|
+
mms: "MMS",
|
|
108
|
+
cta: "CTA",
|
|
109
|
+
cti: "CTI",
|
|
110
|
+
ati: "ATI",
|
|
111
|
+
ata: "ATA",
|
|
112
|
+
friend: "friend",
|
|
113
|
+
};
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { AppModule } from '../modules/app';
|
|
2
|
+
import { RouterModule } from '../modules/router';
|
|
3
|
+
import { AuthModule } from '../modules/auth';
|
|
4
|
+
import { UtilsModule } from '../modules/utils';
|
|
5
|
+
import { MiddlewareModule } from '../modules/middleware';
|
|
6
|
+
import { ConstantsModule } from '../modules/constants';
|
|
7
|
+
import { StorageModule } from '../modules/storage';
|
|
8
|
+
import { ORMModule } from '../modules/orm';
|
|
9
|
+
/**
|
|
10
|
+
* XplatSystem - Singleton 패턴 기반 Framework 인스턴스
|
|
11
|
+
*
|
|
12
|
+
* 모든 framework 기능을 하나의 인스턴스를 통해 접근할 수 있도록 합니다.
|
|
13
|
+
*/
|
|
14
|
+
export declare class XplatSystem {
|
|
15
|
+
private static instance;
|
|
16
|
+
readonly app: AppModule;
|
|
17
|
+
readonly router: RouterModule;
|
|
18
|
+
readonly auth: AuthModule;
|
|
19
|
+
readonly utils: UtilsModule;
|
|
20
|
+
readonly middleware: MiddlewareModule;
|
|
21
|
+
readonly constants: ConstantsModule;
|
|
22
|
+
readonly storage: StorageModule;
|
|
23
|
+
readonly orm: ORMModule;
|
|
24
|
+
/**
|
|
25
|
+
* Private constructor (Singleton 패턴)
|
|
26
|
+
*/
|
|
27
|
+
private constructor();
|
|
28
|
+
/**
|
|
29
|
+
* Singleton 인스턴스 반환
|
|
30
|
+
*/
|
|
31
|
+
static getInstance(): XplatSystem;
|
|
32
|
+
/**
|
|
33
|
+
* 인스턴스 리셋 (테스트용)
|
|
34
|
+
*/
|
|
35
|
+
static resetInstance(): void;
|
|
36
|
+
}
|
|
37
|
+
/**
|
|
38
|
+
* Singleton 인스턴스 export
|
|
39
|
+
*/
|
|
40
|
+
export declare const xplatSystem: XplatSystem;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.xplatSystem = exports.XplatSystem = void 0;
|
|
4
|
+
const app_1 = require("../modules/app");
|
|
5
|
+
const router_1 = require("../modules/router");
|
|
6
|
+
const auth_1 = require("../modules/auth");
|
|
7
|
+
const utils_1 = require("../modules/utils");
|
|
8
|
+
const middleware_1 = require("../modules/middleware");
|
|
9
|
+
const constants_1 = require("../modules/constants");
|
|
10
|
+
const storage_1 = require("../modules/storage");
|
|
11
|
+
const orm_1 = require("../modules/orm");
|
|
12
|
+
/**
|
|
13
|
+
* XplatSystem - Singleton 패턴 기반 Framework 인스턴스
|
|
14
|
+
*
|
|
15
|
+
* 모든 framework 기능을 하나의 인스턴스를 통해 접근할 수 있도록 합니다.
|
|
16
|
+
*/
|
|
17
|
+
class XplatSystem {
|
|
18
|
+
/**
|
|
19
|
+
* Private constructor (Singleton 패턴)
|
|
20
|
+
*/
|
|
21
|
+
constructor() {
|
|
22
|
+
this.app = new app_1.AppModule();
|
|
23
|
+
this.router = new router_1.RouterModule();
|
|
24
|
+
this.auth = new auth_1.AuthModule();
|
|
25
|
+
this.utils = new utils_1.UtilsModule();
|
|
26
|
+
this.middleware = new middleware_1.MiddlewareModule();
|
|
27
|
+
this.constants = new constants_1.ConstantsModule();
|
|
28
|
+
this.storage = new storage_1.StorageModule();
|
|
29
|
+
this.orm = new orm_1.ORMModule();
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Singleton 인스턴스 반환
|
|
33
|
+
*/
|
|
34
|
+
static getInstance() {
|
|
35
|
+
if (!XplatSystem.instance) {
|
|
36
|
+
XplatSystem.instance = new XplatSystem();
|
|
37
|
+
}
|
|
38
|
+
return XplatSystem.instance;
|
|
39
|
+
}
|
|
40
|
+
/**
|
|
41
|
+
* 인스턴스 리셋 (테스트용)
|
|
42
|
+
*/
|
|
43
|
+
static resetInstance() {
|
|
44
|
+
XplatSystem.instance = null;
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
exports.XplatSystem = XplatSystem;
|
|
48
|
+
/**
|
|
49
|
+
* Singleton 인스턴스 export
|
|
50
|
+
*/
|
|
51
|
+
exports.xplatSystem = XplatSystem.getInstance();
|
package/dist/index.d.ts
CHANGED
|
@@ -4,9 +4,22 @@
|
|
|
4
4
|
* Express + TypeScript 백엔드 스캐폴딩 도구 (zium-backend 기반)
|
|
5
5
|
*
|
|
6
6
|
* 파일명과 API endpoint가 자동으로 일치하는 라우팅 시스템을 제공합니다.
|
|
7
|
+
* Singleton 패턴 기반 framework로 모든 기능을 xplatSystem 인스턴스를 통해 접근할 수 있습니다.
|
|
7
8
|
*
|
|
8
9
|
* @packageDocumentation
|
|
9
10
|
*/
|
|
10
|
-
export {
|
|
11
|
-
export {
|
|
12
|
-
export
|
|
11
|
+
export { xplatSystem, XplatSystem } from './core/XplatSystem';
|
|
12
|
+
export { createRouter } from './modules/router/route-factory';
|
|
13
|
+
export { createApp } from './modules/app/app-factory';
|
|
14
|
+
export type { AppConfig, ExtendedRequest, ExtendedResponse, AuthenticatedRequest, XplatSystemInstance, } from './types';
|
|
15
|
+
export type { TokenPayload, TokenOptions, TokenPair, } from './modules/auth/jwt';
|
|
16
|
+
export { AppModule } from './modules/app';
|
|
17
|
+
export { RouterModule } from './modules/router';
|
|
18
|
+
export { AuthModule } from './modules/auth';
|
|
19
|
+
export { UtilsModule } from './modules/utils';
|
|
20
|
+
export { MiddlewareModule } from './modules/middleware';
|
|
21
|
+
export { ConstantsModule } from './modules/constants';
|
|
22
|
+
export { StorageModule } from './modules/storage';
|
|
23
|
+
export { ORMModule } from './modules/orm';
|
|
24
|
+
export type { DetailSearch, SortQueryData, SearchDataItem, SortDataItem, ColumnMapper, } from './modules/orm/query-builder';
|
|
25
|
+
export type { S3Config } from './modules/storage/s3';
|
package/dist/index.js
CHANGED
|
@@ -5,14 +5,36 @@
|
|
|
5
5
|
* Express + TypeScript 백엔드 스캐폴딩 도구 (zium-backend 기반)
|
|
6
6
|
*
|
|
7
7
|
* 파일명과 API endpoint가 자동으로 일치하는 라우팅 시스템을 제공합니다.
|
|
8
|
+
* Singleton 패턴 기반 framework로 모든 기능을 xplatSystem 인스턴스를 통해 접근할 수 있습니다.
|
|
8
9
|
*
|
|
9
10
|
* @packageDocumentation
|
|
10
11
|
*/
|
|
11
12
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
12
|
-
exports.createApp = exports.createRouter = void 0;
|
|
13
|
-
//
|
|
14
|
-
var
|
|
15
|
-
Object.defineProperty(exports, "
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
13
|
+
exports.ORMModule = exports.StorageModule = exports.ConstantsModule = exports.MiddlewareModule = exports.UtilsModule = exports.AuthModule = exports.RouterModule = exports.AppModule = exports.createApp = exports.createRouter = exports.XplatSystem = exports.xplatSystem = void 0;
|
|
14
|
+
// Singleton 인스턴스 및 클래스
|
|
15
|
+
var XplatSystem_1 = require("./core/XplatSystem");
|
|
16
|
+
Object.defineProperty(exports, "xplatSystem", { enumerable: true, get: function () { return XplatSystem_1.xplatSystem; } });
|
|
17
|
+
Object.defineProperty(exports, "XplatSystem", { enumerable: true, get: function () { return XplatSystem_1.XplatSystem; } });
|
|
18
|
+
// 라우팅 유틸리티 (하위 호환성)
|
|
19
|
+
var route_factory_1 = require("./modules/router/route-factory");
|
|
20
|
+
Object.defineProperty(exports, "createRouter", { enumerable: true, get: function () { return route_factory_1.createRouter; } });
|
|
21
|
+
// Express 앱 생성 함수 (하위 호환성)
|
|
22
|
+
var app_factory_1 = require("./modules/app/app-factory");
|
|
23
|
+
Object.defineProperty(exports, "createApp", { enumerable: true, get: function () { return app_factory_1.createApp; } });
|
|
24
|
+
// 모듈들 (선택적 export)
|
|
25
|
+
var app_1 = require("./modules/app");
|
|
26
|
+
Object.defineProperty(exports, "AppModule", { enumerable: true, get: function () { return app_1.AppModule; } });
|
|
27
|
+
var router_1 = require("./modules/router");
|
|
28
|
+
Object.defineProperty(exports, "RouterModule", { enumerable: true, get: function () { return router_1.RouterModule; } });
|
|
29
|
+
var auth_1 = require("./modules/auth");
|
|
30
|
+
Object.defineProperty(exports, "AuthModule", { enumerable: true, get: function () { return auth_1.AuthModule; } });
|
|
31
|
+
var utils_1 = require("./modules/utils");
|
|
32
|
+
Object.defineProperty(exports, "UtilsModule", { enumerable: true, get: function () { return utils_1.UtilsModule; } });
|
|
33
|
+
var middleware_1 = require("./modules/middleware");
|
|
34
|
+
Object.defineProperty(exports, "MiddlewareModule", { enumerable: true, get: function () { return middleware_1.MiddlewareModule; } });
|
|
35
|
+
var constants_1 = require("./modules/constants");
|
|
36
|
+
Object.defineProperty(exports, "ConstantsModule", { enumerable: true, get: function () { return constants_1.ConstantsModule; } });
|
|
37
|
+
var storage_1 = require("./modules/storage");
|
|
38
|
+
Object.defineProperty(exports, "StorageModule", { enumerable: true, get: function () { return storage_1.StorageModule; } });
|
|
39
|
+
var orm_1 = require("./modules/orm");
|
|
40
|
+
Object.defineProperty(exports, "ORMModule", { enumerable: true, get: function () { return orm_1.ORMModule; } });
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
import { Application } from 'express';
|
|
2
|
+
import { AppConfig } from '../../types';
|
|
3
|
+
/**
|
|
4
|
+
* Express 앱 생성 함수
|
|
5
|
+
*
|
|
6
|
+
* zium-backend의 app.ts 구조를 기반으로 한 Express 애플리케이션을 생성합니다.
|
|
7
|
+
* 파일명과 API endpoint가 자동으로 일치하도록 라우팅 시스템을 포함합니다.
|
|
8
|
+
*
|
|
9
|
+
* @param config - 앱 설정 옵션
|
|
10
|
+
* @returns Express Application 인스턴스
|
|
11
|
+
*/
|
|
12
|
+
export declare function createApp(config?: AppConfig): Application;
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
|
|
14
|
+
Object.defineProperty(o, "default", { enumerable: true, value: v });
|
|
15
|
+
}) : function(o, v) {
|
|
16
|
+
o["default"] = v;
|
|
17
|
+
});
|
|
18
|
+
var __importStar = (this && this.__importStar) || (function () {
|
|
19
|
+
var ownKeys = function(o) {
|
|
20
|
+
ownKeys = Object.getOwnPropertyNames || function (o) {
|
|
21
|
+
var ar = [];
|
|
22
|
+
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
|
|
23
|
+
return ar;
|
|
24
|
+
};
|
|
25
|
+
return ownKeys(o);
|
|
26
|
+
};
|
|
27
|
+
return function (mod) {
|
|
28
|
+
if (mod && mod.__esModule) return mod;
|
|
29
|
+
var result = {};
|
|
30
|
+
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
|
|
31
|
+
__setModuleDefault(result, mod);
|
|
32
|
+
return result;
|
|
33
|
+
};
|
|
34
|
+
})();
|
|
35
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
36
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
37
|
+
};
|
|
38
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
39
|
+
exports.createApp = createApp;
|
|
40
|
+
const express_1 = __importDefault(require("express"));
|
|
41
|
+
const cookie_parser_1 = __importDefault(require("cookie-parser"));
|
|
42
|
+
const cors_1 = __importDefault(require("cors"));
|
|
43
|
+
const path = __importStar(require("path"));
|
|
44
|
+
const route_1 = require("../../util/route");
|
|
45
|
+
/**
|
|
46
|
+
* Express 앱 생성 함수
|
|
47
|
+
*
|
|
48
|
+
* zium-backend의 app.ts 구조를 기반으로 한 Express 애플리케이션을 생성합니다.
|
|
49
|
+
* 파일명과 API endpoint가 자동으로 일치하도록 라우팅 시스템을 포함합니다.
|
|
50
|
+
*
|
|
51
|
+
* @param config - 앱 설정 옵션
|
|
52
|
+
* @returns Express Application 인스턴스
|
|
53
|
+
*/
|
|
54
|
+
function createApp(config = {}) {
|
|
55
|
+
const app = (0, express_1.default)();
|
|
56
|
+
// Trust proxy 설정 (실제 IP를 얻기 위해)
|
|
57
|
+
if (config.trustProxy !== false) {
|
|
58
|
+
app.set('trust proxy', true);
|
|
59
|
+
}
|
|
60
|
+
// CORS 설정
|
|
61
|
+
app.use((req, res, next) => {
|
|
62
|
+
res.vary('Origin');
|
|
63
|
+
next();
|
|
64
|
+
});
|
|
65
|
+
const corsOrigin = config.cors?.origin ||
|
|
66
|
+
(process.env.CORS_ALLOW_ORIGINS
|
|
67
|
+
? process.env.CORS_ALLOW_ORIGINS.split(',').map(s => s.trim())
|
|
68
|
+
: ['*']);
|
|
69
|
+
app.use((0, cors_1.default)({
|
|
70
|
+
origin: typeof corsOrigin === 'function'
|
|
71
|
+
? corsOrigin
|
|
72
|
+
: corsOrigin,
|
|
73
|
+
credentials: config.cors?.credentials !== false,
|
|
74
|
+
}));
|
|
75
|
+
// Body parser 설정
|
|
76
|
+
app.use(express_1.default.json({ limit: config.json?.limit || '1mb' }));
|
|
77
|
+
app.use(express_1.default.urlencoded({
|
|
78
|
+
extended: config.urlencoded?.extended !== false
|
|
79
|
+
}));
|
|
80
|
+
// Cookie parser 설정
|
|
81
|
+
app.use((0, cookie_parser_1.default)());
|
|
82
|
+
// 커스텀 미들웨어 적용
|
|
83
|
+
if (config.middleware && config.middleware.length > 0) {
|
|
84
|
+
config.middleware.forEach(middleware => {
|
|
85
|
+
app.use(middleware);
|
|
86
|
+
});
|
|
87
|
+
}
|
|
88
|
+
// 라우터 등록
|
|
89
|
+
if (config.router?.directory) {
|
|
90
|
+
const routerDirectory = config.router.directory;
|
|
91
|
+
const basePath = config.router.basePath || '/restapi';
|
|
92
|
+
// 절대 경로가 아니면 현재 작업 디렉토리를 기준으로 해석
|
|
93
|
+
const absoluteRouterDirectory = path.isAbsolute(routerDirectory)
|
|
94
|
+
? routerDirectory
|
|
95
|
+
: path.join(process.cwd(), routerDirectory);
|
|
96
|
+
try {
|
|
97
|
+
const router = (0, route_1.createRouter)(absoluteRouterDirectory);
|
|
98
|
+
app.use(basePath, router);
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
console.warn(`Warning: Failed to load router from directory "${absoluteRouterDirectory}". ` +
|
|
102
|
+
`Make sure the directory exists and contains route files.`);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
// 404 핸들러
|
|
106
|
+
app.use((req, res) => {
|
|
107
|
+
res.status(404).json({
|
|
108
|
+
success: false,
|
|
109
|
+
message: 'Not Found',
|
|
110
|
+
path: req.path,
|
|
111
|
+
});
|
|
112
|
+
});
|
|
113
|
+
// 에러 핸들러
|
|
114
|
+
app.use((err, req, res, next) => {
|
|
115
|
+
console.error('Error:', err);
|
|
116
|
+
res.status(500).json({
|
|
117
|
+
success: false,
|
|
118
|
+
message: process.env.NODE_ENV === 'production'
|
|
119
|
+
? 'Internal Server Error'
|
|
120
|
+
: err.message,
|
|
121
|
+
...(process.env.NODE_ENV !== 'production' && { stack: err.stack }),
|
|
122
|
+
});
|
|
123
|
+
});
|
|
124
|
+
return app;
|
|
125
|
+
}
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.AppModule = void 0;
|
|
4
|
+
const app_factory_1 = require("./app-factory");
|
|
5
|
+
/**
|
|
6
|
+
* AppModule - Express 앱 생성 모듈
|
|
7
|
+
*/
|
|
8
|
+
class AppModule {
|
|
9
|
+
/**
|
|
10
|
+
* Express 앱 생성
|
|
11
|
+
*/
|
|
12
|
+
create(config = {}) {
|
|
13
|
+
return (0, app_factory_1.createApp)(config);
|
|
14
|
+
}
|
|
15
|
+
}
|
|
16
|
+
exports.AppModule = AppModule;
|
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import { TokenPayload, TokenOptions, TokenPair } from './jwt';
|
|
2
|
+
import { AuthMiddlewareOptions } from './middleware';
|
|
3
|
+
import { Request, Response, NextFunction } from 'express';
|
|
4
|
+
/**
|
|
5
|
+
* AuthModule - 인증/인가 모듈
|
|
6
|
+
*/
|
|
7
|
+
export declare class AuthModule {
|
|
8
|
+
/**
|
|
9
|
+
* JWT 토큰 생성
|
|
10
|
+
*/
|
|
11
|
+
generateToken(payload: TokenPayload, options: TokenOptions): string;
|
|
12
|
+
/**
|
|
13
|
+
* JWT 토큰 검증
|
|
14
|
+
*/
|
|
15
|
+
verifyToken(token: string, secret: string): TokenPayload | null;
|
|
16
|
+
/**
|
|
17
|
+
* Access Token과 Refresh Token 쌍 생성
|
|
18
|
+
*/
|
|
19
|
+
createTokenPair(payload: TokenPayload, accessTokenOptions: TokenOptions, refreshTokenOptions: TokenOptions): TokenPair;
|
|
20
|
+
/**
|
|
21
|
+
* 인증 미들웨어 생성
|
|
22
|
+
*/
|
|
23
|
+
createMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
24
|
+
/**
|
|
25
|
+
* 선택적 인증 미들웨어 생성 (토큰이 있으면 검증, 없으면 통과)
|
|
26
|
+
*/
|
|
27
|
+
createOptionalMiddleware(options: AuthMiddlewareOptions): (req: Request, res: Response, next: NextFunction) => void;
|
|
28
|
+
/**
|
|
29
|
+
* 환경변수 기반 토큰 생성 (편의 메서드)
|
|
30
|
+
*/
|
|
31
|
+
createTokenFromEnv(payload: TokenPayload): TokenPair;
|
|
32
|
+
/**
|
|
33
|
+
* 환경변수 기반 인증 미들웨어 생성 (편의 메서드)
|
|
34
|
+
*/
|
|
35
|
+
createMiddlewareFromEnv(onSuccess?: (req: Request, payload: TokenPayload) => void, onError?: (req: Request, res: Response, error: Error) => void): (req: Request, res: Response, next: NextFunction) => void | Response<any, Record<string, any>>;
|
|
36
|
+
}
|