@mandujs/core 0.18.12 → 0.18.13

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@mandujs/core",
3
- "version": "0.18.12",
3
+ "version": "0.18.13",
4
4
  "description": "Mandu Framework Core - Spec, Generator, Guard, Runtime",
5
5
  "type": "module",
6
6
  "main": "./src/index.ts",
@@ -1010,30 +1010,80 @@ function toCamelCase(str: string): string {
1010
1010
  .replace(/^(.)/, (_, c) => c.toLowerCase());
1011
1011
  }
1012
1012
 
1013
+ // 한국어 도메인 키워드 → 영문 slug 매핑
1014
+ const KOREAN_DOMAIN_MAP: Record<string, string> = {
1015
+ "채팅": "chat", "메시지": "message", "사용자": "user", "유저": "user",
1016
+ "인증": "auth", "로그인": "login", "로그아웃": "logout", "회원가입": "signup",
1017
+ "결제": "payment", "주문": "order", "상품": "product", "장바구니": "cart",
1018
+ "알림": "notification", "푸시": "push",
1019
+ "게시글": "post", "게시판": "board", "댓글": "comment", "좋아요": "like",
1020
+ "검색": "search", "필터": "filter", "정렬": "sort",
1021
+ "파일": "file", "업로드": "upload", "다운로드": "download", "이미지": "image",
1022
+ "대시보드": "dashboard", "통계": "stats", "분석": "analytics",
1023
+ "설정": "settings", "프로필": "profile", "계정": "account",
1024
+ "팀": "team", "프로젝트": "project", "태스크": "task", "일정": "schedule",
1025
+ "컴포넌트": "component", "레이아웃": "layout", "네비게이션": "navigation",
1026
+ "실시간": "realtime", "스트리밍": "streaming", "웹소켓": "websocket",
1027
+ };
1028
+
1013
1029
  function extractFeatureName(intent: string): string {
1014
- // 한글/영문에서 핵심 명사 추출 시도
1015
- const patterns = [
1016
- /(?:추가|구현|만들)(?:어|해)[줘요]?\s*[:\-]?\s*(.+)/,
1017
- /(.+?)\s*(?:기능|시스템|모듈)/,
1018
- /(?:add|implement|create)\s+(.+)/i,
1030
+ // 1. 영문 패턴 우선 시도 (가장 신뢰도 높음)
1031
+ const englishPatterns = [
1032
+ /(?:add|implement|create|build)\s+(.+)/i,
1033
+ /(.+?)\s+(?:feature|system|module|service)/i,
1019
1034
  ];
1020
1035
 
1021
- for (const pattern of patterns) {
1036
+ for (const pattern of englishPatterns) {
1022
1037
  const match = intent.match(pattern);
1023
1038
  if (match) {
1024
- return match[1]
1039
+ const slug = match[1]
1025
1040
  .trim()
1026
1041
  .toLowerCase()
1027
1042
  .replace(/\s+/g, "-")
1028
- .replace(/[^a-z0-9-]/g, "");
1043
+ .replace(/[^a-z0-9-]/g, "")
1044
+ .replace(/^-+|-+$/g, "");
1045
+ if (slug) return slug;
1029
1046
  }
1030
1047
  }
1031
1048
 
1032
- // 기본값: 단어
1033
- return intent
1034
- .split(/\s+/)[0]
1035
- .toLowerCase()
1036
- .replace(/[^a-z0-9]/g, "") || "feature";
1049
+ // 2. 한글 패턴 시도 → 매칭된 텍스트에서 도메인 키워드 추출
1050
+ const koreanPatterns = [
1051
+ /(?:추가|구현|만들|개발|작성|생성)(?:어|해|하)[줘요]?\s*[:\-]?\s*(.+)/,
1052
+ /(.+?)\s*(?:기능|시스템|모듈|서비스|페이지|컴포넌트)\s*(?:추가|구현|만들|개발)?/,
1053
+ /(.+?)\s*(?:을|를|의|에)\s/,
1054
+ ];
1055
+
1056
+ for (const pattern of koreanPatterns) {
1057
+ const match = intent.match(pattern);
1058
+ if (match) {
1059
+ const captured = match[1].trim();
1060
+ // 캡처된 텍스트에서 도메인 키워드 매칭
1061
+ const slug = koreanToSlug(captured);
1062
+ if (slug) return slug;
1063
+ }
1064
+ }
1065
+
1066
+ // 3. intent 전체에서 도메인 키워드 직접 탐색
1067
+ const slug = koreanToSlug(intent);
1068
+ if (slug) return slug;
1069
+
1070
+ // 4. intent에서 영문 단어 추출 시도
1071
+ const englishWord = intent.match(/[a-z][a-z0-9-]{2,}/i)?.[0]?.toLowerCase();
1072
+ if (englishWord) return englishWord;
1073
+
1074
+ return "feature";
1075
+ }
1076
+
1077
+ function koreanToSlug(text: string): string {
1078
+ const matches: string[] = [];
1079
+ for (const [korean, english] of Object.entries(KOREAN_DOMAIN_MAP)) {
1080
+ if (text.includes(korean)) {
1081
+ matches.push(english);
1082
+ }
1083
+ }
1084
+ if (matches.length === 0) return "";
1085
+ // 여러 키워드 매칭 시 하이폰으로 연결 (최대 2개)
1086
+ return matches.slice(0, 2).join("-");
1037
1087
  }
1038
1088
 
1039
1089
  /**