@nine-lab/nine-mu 0.1.14
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/dist/css/nine-mu.css +796 -0
- package/dist/nine-mu.js +170 -0
- package/dist/nine-mu.js.map +1 -0
- package/dist/nine-mu.umd.js +2 -0
- package/dist/nine-mu.umd.js.map +1 -0
- package/package.json +45 -0
- package/public/css/nine-mu.css +796 -0
- package/src/components/NineChat.js +124 -0
- package/src/index.js +17 -0
- package/src/services/NineMuService.js +55 -0
- package/vite.config.js +30 -0
package/dist/nine-mu.js
ADDED
|
@@ -0,0 +1,170 @@
|
|
|
1
|
+
var __typeError = (msg) => {
|
|
2
|
+
throw TypeError(msg);
|
|
3
|
+
};
|
|
4
|
+
var __accessCheck = (obj, member, msg) => member.has(obj) || __typeError("Cannot " + msg);
|
|
5
|
+
var __privateGet = (obj, member, getter) => (__accessCheck(obj, member, "read from private field"), getter ? getter.call(obj) : member.get(obj));
|
|
6
|
+
var __privateAdd = (obj, member, value) => member.has(obj) ? __typeError("Cannot add the same private member more than once") : member instanceof WeakSet ? member.add(obj) : member.set(obj, value);
|
|
7
|
+
var __privateSet = (obj, member, value, setter) => (__accessCheck(obj, member, "write to private field"), setter ? setter.call(obj, value) : member.set(obj, value), value);
|
|
8
|
+
var __privateMethod = (obj, member, method) => (__accessCheck(obj, member, "access private method"), method);
|
|
9
|
+
var _service, _routes, _NineChat_instances, initInteractions_fn, initActions_fn, render_fn;
|
|
10
|
+
import { trace, nine } from "@nine-lab/nine-util";
|
|
11
|
+
class NineMuService {
|
|
12
|
+
constructor(connectorUrl) {
|
|
13
|
+
this.connectorUrl = connectorUrl;
|
|
14
|
+
}
|
|
15
|
+
/**
|
|
16
|
+
* AI 소스 생성 실행
|
|
17
|
+
* @param {string} command - 사용자 입력 명령
|
|
18
|
+
* @param {Array} targets - 체크된 생성 대상 (MyBatis, Service 등)
|
|
19
|
+
* @param {Array} currentRoutes - 현재 프로젝트 경로 정보
|
|
20
|
+
*/
|
|
21
|
+
async generate(command, targets, currentRoutes) {
|
|
22
|
+
try {
|
|
23
|
+
trace.log(`🚀 Fab 공정 시작: "${command}" [대상: ${targets.join(", ")}]`);
|
|
24
|
+
const response = await fetch(`${this.connectorUrl}/api/fab/generate`, {
|
|
25
|
+
method: "POST",
|
|
26
|
+
headers: { "Content-Type": "application/json" },
|
|
27
|
+
body: JSON.stringify({
|
|
28
|
+
command,
|
|
29
|
+
targets,
|
|
30
|
+
projectType: "spring-react",
|
|
31
|
+
currentRoutes
|
|
32
|
+
})
|
|
33
|
+
});
|
|
34
|
+
const result = await response.json();
|
|
35
|
+
if (!result.success) {
|
|
36
|
+
throw new Error(result.error || "소스 생성 중 서버 오류가 발생했습니다.");
|
|
37
|
+
}
|
|
38
|
+
return result;
|
|
39
|
+
} catch (error) {
|
|
40
|
+
trace.error("❌ Fab Service Error:", error);
|
|
41
|
+
throw error;
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* 초기 경로 정보 로드
|
|
46
|
+
*/
|
|
47
|
+
async fetchRoutes(routeUrl) {
|
|
48
|
+
if (!routeUrl) return [];
|
|
49
|
+
try {
|
|
50
|
+
const res = await fetch(routeUrl);
|
|
51
|
+
return await res.json();
|
|
52
|
+
} catch (err) {
|
|
53
|
+
trace.error("Route load fail", err);
|
|
54
|
+
return [];
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
}
|
|
58
|
+
class NineChat extends HTMLElement {
|
|
59
|
+
constructor() {
|
|
60
|
+
super();
|
|
61
|
+
__privateAdd(this, _NineChat_instances);
|
|
62
|
+
__privateAdd(this, _service, null);
|
|
63
|
+
__privateAdd(this, _routes, []);
|
|
64
|
+
this.attachShadow({ mode: "open" });
|
|
65
|
+
}
|
|
66
|
+
async connectedCallback() {
|
|
67
|
+
const connectorUrl = this.getAttribute("connector-url") || "http://localhost:3002";
|
|
68
|
+
__privateSet(this, _service, new NineMuService(connectorUrl));
|
|
69
|
+
__privateMethod(this, _NineChat_instances, render_fn).call(this);
|
|
70
|
+
__privateMethod(this, _NineChat_instances, initInteractions_fn).call(this);
|
|
71
|
+
__privateMethod(this, _NineChat_instances, initActions_fn).call(this);
|
|
72
|
+
__privateSet(this, _routes, await __privateGet(this, _service).fetchRoutes(this.getAttribute("route-url")));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
_service = new WeakMap();
|
|
76
|
+
_routes = new WeakMap();
|
|
77
|
+
_NineChat_instances = new WeakSet();
|
|
78
|
+
// --- [그룹 1: Interaction] 화면 토글 및 메뉴 클릭 ---
|
|
79
|
+
initInteractions_fn = function() {
|
|
80
|
+
const $settings = this.shadowRoot.querySelector("nine-ai-settings");
|
|
81
|
+
const $menuIcons = this.shadowRoot.querySelectorAll(".menu-icon");
|
|
82
|
+
const toggleUI = () => this.classList.toggle("collapse");
|
|
83
|
+
this.shadowRoot.querySelector(".expand-icon").addEventListener("click", toggleUI);
|
|
84
|
+
this.shadowRoot.querySelector(".collapse-icon").addEventListener("click", toggleUI);
|
|
85
|
+
$menuIcons.forEach((el) => {
|
|
86
|
+
el.addEventListener("click", (e) => {
|
|
87
|
+
$menuIcons.forEach((icon) => icon.classList.remove("active"));
|
|
88
|
+
const clicked = e.target.closest(".menu-icon");
|
|
89
|
+
clicked.classList.add("active");
|
|
90
|
+
$settings.classList.toggle("expand", clicked.classList.contains("menu-setting"));
|
|
91
|
+
});
|
|
92
|
+
});
|
|
93
|
+
};
|
|
94
|
+
// --- [그룹 2: Action] 엔터키 입력 시 서비스 호출 ---
|
|
95
|
+
initActions_fn = function() {
|
|
96
|
+
const $textarea = this.shadowRoot.querySelector("#q");
|
|
97
|
+
const $status = this.shadowRoot.querySelector("#status-tag");
|
|
98
|
+
$textarea.addEventListener("keypress", async (e) => {
|
|
99
|
+
if (e.key === "Enter" && !e.shiftKey) {
|
|
100
|
+
e.preventDefault();
|
|
101
|
+
const command = e.target.value.trim();
|
|
102
|
+
if (!command) return;
|
|
103
|
+
$status.textContent = "⚙️ 공정 분석 중...";
|
|
104
|
+
e.target.value = "";
|
|
105
|
+
const targets = Array.from(this.shadowRoot.querySelectorAll('input[name="gen_target"]:checked')).map((el) => el.value);
|
|
106
|
+
try {
|
|
107
|
+
const result = await __privateGet(this, _service).generate(command, targets, __privateGet(this, _routes));
|
|
108
|
+
$status.textContent = "✅ 완료";
|
|
109
|
+
nine.alert("소스 생성 성공").rgb();
|
|
110
|
+
this.dispatchEvent(new CustomEvent("nine-fab-completed", { detail: result, bubbles: true }));
|
|
111
|
+
} catch (err) {
|
|
112
|
+
$status.textContent = "❌ 실패";
|
|
113
|
+
nine.alert(err.message).rgb().shake();
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
});
|
|
117
|
+
};
|
|
118
|
+
render_fn = function() {
|
|
119
|
+
const placeholder = this.getAttribute("placeholder") || "나에게 무엇이든 물어봐...";
|
|
120
|
+
const customImport = this.getAttribute("css-path") ? `@import "${this.getAttribute("css-path")}";` : "";
|
|
121
|
+
this.shadowRoot.innerHTML = `
|
|
122
|
+
<style>
|
|
123
|
+
@import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-fab@${"0.1.13"}/dist/css/nine-fab.css";
|
|
124
|
+
${customImport}
|
|
125
|
+
</style>
|
|
126
|
+
<div class="wrapper">
|
|
127
|
+
<nine-ai-settings></nine-ai-settings>
|
|
128
|
+
<div class="container">
|
|
129
|
+
<div class="head">
|
|
130
|
+
<div class="logo"><span></span></div>
|
|
131
|
+
<div id="status-tag" style="font-size:10px; color:#ff5722; padding:5px;">Fab Engine Ready</div>
|
|
132
|
+
</div>
|
|
133
|
+
<nx-ai-chat></nx-ai-chat>
|
|
134
|
+
<div class="foot">
|
|
135
|
+
<div class="apply-src">
|
|
136
|
+
${["MyBatis", "Service", "Controller", "JavaScript"].map((t) => `
|
|
137
|
+
<div>
|
|
138
|
+
<input type="checkbox" id="${t.toLowerCase()}" name="gen_target" value="${t}" checked />
|
|
139
|
+
<label for="${t.toLowerCase()}">${t}</label>
|
|
140
|
+
</div>
|
|
141
|
+
`).join("")}
|
|
142
|
+
</div>
|
|
143
|
+
<textarea id="q" rows="4" placeholder="${placeholder}"></textarea>
|
|
144
|
+
</div>
|
|
145
|
+
</div>
|
|
146
|
+
<div class="menu">
|
|
147
|
+
<div class="collapse-icon"></div>
|
|
148
|
+
<div class="menu-icon menu-filter active"></div>
|
|
149
|
+
<div class="menu-icon menu-general"></div>
|
|
150
|
+
<div class="menu-icon menu-setting"></div>
|
|
151
|
+
</div>
|
|
152
|
+
</div>
|
|
153
|
+
<div class="expand-icon"></div>
|
|
154
|
+
`;
|
|
155
|
+
};
|
|
156
|
+
if (!customElements.get("nine-chat")) {
|
|
157
|
+
customElements.define("nine-chat", NineChat);
|
|
158
|
+
}
|
|
159
|
+
const NineFab = {
|
|
160
|
+
version: "0.1.13",
|
|
161
|
+
init: (config) => {
|
|
162
|
+
trace.log("🛠️ Nine-Fab Engine initialized", config);
|
|
163
|
+
}
|
|
164
|
+
};
|
|
165
|
+
export {
|
|
166
|
+
NineChat,
|
|
167
|
+
NineFab,
|
|
168
|
+
NineFab as default
|
|
169
|
+
};
|
|
170
|
+
//# sourceMappingURL=nine-mu.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nine-mu.js","sources":["../src/services/NineMuService.js","../src/components/NineChat.js","../src/index.js"],"sourcesContent":["import { nine, trace } from '@nine-lab/nine-util';\n\nexport class NineMuService {\n constructor(connectorUrl) {\n this.connectorUrl = connectorUrl;\n }\n\n /**\n * AI 소스 생성 실행\n * @param {string} command - 사용자 입력 명령\n * @param {Array} targets - 체크된 생성 대상 (MyBatis, Service 등)\n * @param {Array} currentRoutes - 현재 프로젝트 경로 정보\n */\n async generate(command, targets, currentRoutes) {\n try {\n trace.log(`🚀 Fab 공정 시작: \"${command}\" [대상: ${targets.join(', ')}]`);\n\n const response = await fetch(`${this.connectorUrl}/api/fab/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n command,\n targets,\n projectType: 'spring-react',\n currentRoutes\n })\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || \"소스 생성 중 서버 오류가 발생했습니다.\");\n }\n\n return result;\n } catch (error) {\n trace.error(\"❌ Fab Service Error:\", error);\n throw error;\n }\n }\n\n /**\n * 초기 경로 정보 로드\n */\n async fetchRoutes(routeUrl) {\n if (!routeUrl) return [];\n try {\n const res = await fetch(routeUrl);\n return await res.json();\n } catch (err) {\n trace.error(\"Route load fail\", err);\n return [];\n }\n }\n}","import { nine, trace } from '@nine-lab/nine-util';\nimport { NineMuService } from '../services/NineMuService.js';\n\nexport class NineChat extends HTMLElement {\n #service = null;\n #routes = [];\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n\n async connectedCallback() {\n // 서비스 초기화\n const connectorUrl = this.getAttribute('connector-url') || 'http://localhost:3002';\n this.#service = new NineMuService(connectorUrl);\n\n this.#render();\n this.#initInteractions(); // UI 토글 로직\n this.#initActions(); // 엔터 시 실행 로직\n\n // 경로 데이터 로드\n this.#routes = await this.#service.fetchRoutes(this.getAttribute('route-url'));\n }\n\n // --- [그룹 1: Interaction] 화면 토글 및 메뉴 클릭 ---\n #initInteractions() {\n const $settings = this.shadowRoot.querySelector('nine-ai-settings');\n const $menuIcons = this.shadowRoot.querySelectorAll(\".menu-icon\");\n\n const toggleUI = () => this.classList.toggle(\"collapse\");\n this.shadowRoot.querySelector(\".expand-icon\").addEventListener(\"click\", toggleUI);\n this.shadowRoot.querySelector(\".collapse-icon\").addEventListener(\"click\", toggleUI);\n\n $menuIcons.forEach(el => {\n el.addEventListener(\"click\", (e) => {\n $menuIcons.forEach(icon => icon.classList.remove(\"active\"));\n const clicked = e.target.closest(\".menu-icon\");\n clicked.classList.add(\"active\");\n $settings.classList.toggle(\"expand\", clicked.classList.contains('menu-setting'));\n });\n });\n }\n\n // --- [그룹 2: Action] 엔터키 입력 시 서비스 호출 ---\n #initActions() {\n const $textarea = this.shadowRoot.querySelector('#q');\n const $status = this.shadowRoot.querySelector('#status-tag');\n\n $textarea.addEventListener('keypress', async (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n const command = e.target.value.trim();\n if (!command) return;\n\n // 1. UI 피드백\n $status.textContent = \"⚙️ 공정 분석 중...\";\n e.target.value = '';\n\n // 2. 체크된 타겟 수집\n const targets = Array.from(this.shadowRoot.querySelectorAll('input[name=\"gen_target\"]:checked'))\n .map(el => el.value);\n\n // 3. 분리된 서비스 호출\n try {\n const result = await this.#service.generate(command, targets, this.#routes);\n\n // 4. 성공 처리\n $status.textContent = \"✅ 완료\";\n nine.alert(\"소스 생성 성공\").rgb();\n this.dispatchEvent(new CustomEvent('nine-fab-completed', { detail: result, bubbles: true }));\n } catch (err) {\n // 5. 실패 처리\n $status.textContent = \"❌ 실패\";\n nine.alert(err.message).rgb().shake();\n }\n }\n });\n }\n\n #render() {\n const placeholder = this.getAttribute(\"placeholder\") || \"나에게 무엇이든 물어봐...\";\n const customImport = this.getAttribute(\"css-path\") ? `@import \"${this.getAttribute(\"css-path\")}\";` : \"\";\n\n this.shadowRoot.innerHTML = `\n <style>\n @import \"https://cdn.jsdelivr.net/npm/@nine-lab/nine-fab@${__APP_VERSION__}/dist/css/nine-fab.css\";\n ${customImport}\n </style>\n <div class=\"wrapper\">\n <nine-ai-settings></nine-ai-settings>\n <div class=\"container\">\n <div class=\"head\">\n <div class=\"logo\"><span></span></div>\n <div id=\"status-tag\" style=\"font-size:10px; color:#ff5722; padding:5px;\">Fab Engine Ready</div>\n </div>\n <nx-ai-chat></nx-ai-chat>\n <div class=\"foot\">\n <div class=\"apply-src\">\n ${['MyBatis', 'Service', 'Controller', 'JavaScript'].map(t => `\n <div>\n <input type=\"checkbox\" id=\"${t.toLowerCase()}\" name=\"gen_target\" value=\"${t}\" checked />\n <label for=\"${t.toLowerCase()}\">${t}</label>\n </div>\n `).join('')}\n </div>\n <textarea id=\"q\" rows=\"4\" placeholder=\"${placeholder}\"></textarea>\n </div>\n </div>\n <div class=\"menu\">\n <div class=\"collapse-icon\"></div>\n <div class=\"menu-icon menu-filter active\"></div>\n <div class=\"menu-icon menu-general\"></div>\n <div class=\"menu-icon menu-setting\"></div>\n </div>\n </div>\n <div class=\"expand-icon\"></div>\n `;\n }\n}\n\nif (!customElements.get('nine-chat')) {\n customElements.define('nine-chat', NineChat);\n}","import { trace } from '@nine-lab/nine-util';\nimport { NineChat } from './components/NineChat.js';\n\n/**\n * Nine-Fab 엔진 메인 클래스\n */\nexport const NineFab = {\n version: typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0',\n init: (config) => {\n trace.log(\"🛠️ Nine-Fab Engine initialized\", config);\n // 향후 커넥터 URL 전역 설정이나 인증 토큰 처리 로직 추가 가능\n }\n};\n\n// 기본 export 및 컴포넌트 export\nexport default NineFab;\nexport { NineChat };"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,2 @@
|
|
|
1
|
+
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports,require("@nine-lab/nine-util")):"function"==typeof define&&define.amd?define(["exports","@nine-lab/nine-util"],t):t((e="undefined"!=typeof globalThis?globalThis:e||self).NineFab={},e.NineUtil)}(this,function(e,t){"use strict";var n,i,s,a,o,r,c=e=>{throw TypeError(e)},l=(e,t,n)=>t.has(e)||c("Cannot "+n),d=(e,t,n)=>(l(e,t,"read from private field"),n?n.call(e):t.get(e)),h=(e,t,n)=>t.has(e)?c("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,n),u=(e,t,n,i)=>(l(e,t,"write to private field"),i?i.call(e,n):t.set(e,n),n),p=(e,t,n)=>(l(e,t,"access private method"),n);class v{constructor(e){this.connectorUrl=e}async generate(e,n,i){try{t.trace.log(`🚀 Fab 공정 시작: "${e}" [대상: ${n.join(", ")}]`);const s=await fetch(`${this.connectorUrl}/api/fab/generate`,{method:"POST",headers:{"Content-Type":"application/json"},body:JSON.stringify({command:e,targets:n,projectType:"spring-react",currentRoutes:i})}),a=await s.json();if(!a.success)throw new Error(a.error||"소스 생성 중 서버 오류가 발생했습니다.");return a}catch(s){throw t.trace.error("❌ Fab Service Error:",s),s}}async fetchRoutes(e){if(!e)return[];try{const t=await fetch(e);return await t.json()}catch(n){return t.trace.error("Route load fail",n),[]}}}class f extends HTMLElement{constructor(){super(),h(this,s),h(this,n,null),h(this,i,[]),this.attachShadow({mode:"open"})}async connectedCallback(){const e=this.getAttribute("connector-url")||"http://localhost:3002";u(this,n,new v(e)),p(this,s,r).call(this),p(this,s,a).call(this),p(this,s,o).call(this),u(this,i,await d(this,n).fetchRoutes(this.getAttribute("route-url")))}}n=new WeakMap,i=new WeakMap,s=new WeakSet,a=function(){const e=this.shadowRoot.querySelector("nine-ai-settings"),t=this.shadowRoot.querySelectorAll(".menu-icon"),n=()=>this.classList.toggle("collapse");this.shadowRoot.querySelector(".expand-icon").addEventListener("click",n),this.shadowRoot.querySelector(".collapse-icon").addEventListener("click",n),t.forEach(n=>{n.addEventListener("click",n=>{t.forEach(e=>e.classList.remove("active"));const i=n.target.closest(".menu-icon");i.classList.add("active"),e.classList.toggle("expand",i.classList.contains("menu-setting"))})})},o=function(){const e=this.shadowRoot.querySelector("#q"),s=this.shadowRoot.querySelector("#status-tag");e.addEventListener("keypress",async e=>{if("Enter"===e.key&&!e.shiftKey){e.preventDefault();const o=e.target.value.trim();if(!o)return;s.textContent="⚙️ 공정 분석 중...",e.target.value="";const r=Array.from(this.shadowRoot.querySelectorAll('input[name="gen_target"]:checked')).map(e=>e.value);try{const e=await d(this,n).generate(o,r,d(this,i));s.textContent="✅ 완료",t.nine.alert("소스 생성 성공").rgb(),this.dispatchEvent(new CustomEvent("nine-fab-completed",{detail:e,bubbles:!0}))}catch(a){s.textContent="❌ 실패",t.nine.alert(a.message).rgb().shake()}}})},r=function(){const e=this.getAttribute("placeholder")||"나에게 무엇이든 물어봐...",t=this.getAttribute("css-path")?`@import "${this.getAttribute("css-path")}";`:"";this.shadowRoot.innerHTML=`\n <style>\n @import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-fab@0.1.13/dist/css/nine-fab.css";\n ${t}\n </style>\n <div class="wrapper">\n <nine-ai-settings></nine-ai-settings>\n <div class="container">\n <div class="head">\n <div class="logo"><span></span></div>\n <div id="status-tag" style="font-size:10px; color:#ff5722; padding:5px;">Fab Engine Ready</div>\n </div>\n <nx-ai-chat></nx-ai-chat>\n <div class="foot">\n <div class="apply-src">\n ${["MyBatis","Service","Controller","JavaScript"].map(e=>`\n <div>\n <input type="checkbox" id="${e.toLowerCase()}" name="gen_target" value="${e}" checked />\n <label for="${e.toLowerCase()}">${e}</label>\n </div>\n `).join("")}\n </div>\n <textarea id="q" rows="4" placeholder="${e}"></textarea>\n </div>\n </div>\n <div class="menu">\n <div class="collapse-icon"></div>\n <div class="menu-icon menu-filter active"></div>\n <div class="menu-icon menu-general"></div>\n <div class="menu-icon menu-setting"></div>\n </div>\n </div>\n <div class="expand-icon"></div>\n `},customElements.get("nine-chat")||customElements.define("nine-chat",f);const g={version:"0.1.13",init:e=>{t.trace.log("🛠️ Nine-Fab Engine initialized",e)}};e.NineChat=f,e.NineFab=g,e.default=g,Object.defineProperties(e,{__esModule:{value:!0},[Symbol.toStringTag]:{value:"Module"}})});
|
|
2
|
+
//# sourceMappingURL=nine-mu.umd.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"nine-mu.umd.js","sources":["../src/services/NineMuService.js","../src/components/NineChat.js","../src/index.js"],"sourcesContent":["import { nine, trace } from '@nine-lab/nine-util';\n\nexport class NineMuService {\n constructor(connectorUrl) {\n this.connectorUrl = connectorUrl;\n }\n\n /**\n * AI 소스 생성 실행\n * @param {string} command - 사용자 입력 명령\n * @param {Array} targets - 체크된 생성 대상 (MyBatis, Service 등)\n * @param {Array} currentRoutes - 현재 프로젝트 경로 정보\n */\n async generate(command, targets, currentRoutes) {\n try {\n trace.log(`🚀 Fab 공정 시작: \"${command}\" [대상: ${targets.join(', ')}]`);\n\n const response = await fetch(`${this.connectorUrl}/api/fab/generate`, {\n method: 'POST',\n headers: { 'Content-Type': 'application/json' },\n body: JSON.stringify({\n command,\n targets,\n projectType: 'spring-react',\n currentRoutes\n })\n });\n\n const result = await response.json();\n\n if (!result.success) {\n throw new Error(result.error || \"소스 생성 중 서버 오류가 발생했습니다.\");\n }\n\n return result;\n } catch (error) {\n trace.error(\"❌ Fab Service Error:\", error);\n throw error;\n }\n }\n\n /**\n * 초기 경로 정보 로드\n */\n async fetchRoutes(routeUrl) {\n if (!routeUrl) return [];\n try {\n const res = await fetch(routeUrl);\n return await res.json();\n } catch (err) {\n trace.error(\"Route load fail\", err);\n return [];\n }\n }\n}","import { nine, trace } from '@nine-lab/nine-util';\nimport { NineMuService } from '../services/NineMuService.js';\n\nexport class NineChat extends HTMLElement {\n #service = null;\n #routes = [];\n\n constructor() {\n super();\n this.attachShadow({ mode: 'open' });\n }\n\n async connectedCallback() {\n // 서비스 초기화\n const connectorUrl = this.getAttribute('connector-url') || 'http://localhost:3002';\n this.#service = new NineMuService(connectorUrl);\n\n this.#render();\n this.#initInteractions(); // UI 토글 로직\n this.#initActions(); // 엔터 시 실행 로직\n\n // 경로 데이터 로드\n this.#routes = await this.#service.fetchRoutes(this.getAttribute('route-url'));\n }\n\n // --- [그룹 1: Interaction] 화면 토글 및 메뉴 클릭 ---\n #initInteractions() {\n const $settings = this.shadowRoot.querySelector('nine-ai-settings');\n const $menuIcons = this.shadowRoot.querySelectorAll(\".menu-icon\");\n\n const toggleUI = () => this.classList.toggle(\"collapse\");\n this.shadowRoot.querySelector(\".expand-icon\").addEventListener(\"click\", toggleUI);\n this.shadowRoot.querySelector(\".collapse-icon\").addEventListener(\"click\", toggleUI);\n\n $menuIcons.forEach(el => {\n el.addEventListener(\"click\", (e) => {\n $menuIcons.forEach(icon => icon.classList.remove(\"active\"));\n const clicked = e.target.closest(\".menu-icon\");\n clicked.classList.add(\"active\");\n $settings.classList.toggle(\"expand\", clicked.classList.contains('menu-setting'));\n });\n });\n }\n\n // --- [그룹 2: Action] 엔터키 입력 시 서비스 호출 ---\n #initActions() {\n const $textarea = this.shadowRoot.querySelector('#q');\n const $status = this.shadowRoot.querySelector('#status-tag');\n\n $textarea.addEventListener('keypress', async (e) => {\n if (e.key === 'Enter' && !e.shiftKey) {\n e.preventDefault();\n const command = e.target.value.trim();\n if (!command) return;\n\n // 1. UI 피드백\n $status.textContent = \"⚙️ 공정 분석 중...\";\n e.target.value = '';\n\n // 2. 체크된 타겟 수집\n const targets = Array.from(this.shadowRoot.querySelectorAll('input[name=\"gen_target\"]:checked'))\n .map(el => el.value);\n\n // 3. 분리된 서비스 호출\n try {\n const result = await this.#service.generate(command, targets, this.#routes);\n\n // 4. 성공 처리\n $status.textContent = \"✅ 완료\";\n nine.alert(\"소스 생성 성공\").rgb();\n this.dispatchEvent(new CustomEvent('nine-fab-completed', { detail: result, bubbles: true }));\n } catch (err) {\n // 5. 실패 처리\n $status.textContent = \"❌ 실패\";\n nine.alert(err.message).rgb().shake();\n }\n }\n });\n }\n\n #render() {\n const placeholder = this.getAttribute(\"placeholder\") || \"나에게 무엇이든 물어봐...\";\n const customImport = this.getAttribute(\"css-path\") ? `@import \"${this.getAttribute(\"css-path\")}\";` : \"\";\n\n this.shadowRoot.innerHTML = `\n <style>\n @import \"https://cdn.jsdelivr.net/npm/@nine-lab/nine-fab@${__APP_VERSION__}/dist/css/nine-fab.css\";\n ${customImport}\n </style>\n <div class=\"wrapper\">\n <nine-ai-settings></nine-ai-settings>\n <div class=\"container\">\n <div class=\"head\">\n <div class=\"logo\"><span></span></div>\n <div id=\"status-tag\" style=\"font-size:10px; color:#ff5722; padding:5px;\">Fab Engine Ready</div>\n </div>\n <nx-ai-chat></nx-ai-chat>\n <div class=\"foot\">\n <div class=\"apply-src\">\n ${['MyBatis', 'Service', 'Controller', 'JavaScript'].map(t => `\n <div>\n <input type=\"checkbox\" id=\"${t.toLowerCase()}\" name=\"gen_target\" value=\"${t}\" checked />\n <label for=\"${t.toLowerCase()}\">${t}</label>\n </div>\n `).join('')}\n </div>\n <textarea id=\"q\" rows=\"4\" placeholder=\"${placeholder}\"></textarea>\n </div>\n </div>\n <div class=\"menu\">\n <div class=\"collapse-icon\"></div>\n <div class=\"menu-icon menu-filter active\"></div>\n <div class=\"menu-icon menu-general\"></div>\n <div class=\"menu-icon menu-setting\"></div>\n </div>\n </div>\n <div class=\"expand-icon\"></div>\n `;\n }\n}\n\nif (!customElements.get('nine-chat')) {\n customElements.define('nine-chat', NineChat);\n}","import { trace } from '@nine-lab/nine-util';\nimport { NineChat } from './components/NineChat.js';\n\n/**\n * Nine-Fab 엔진 메인 클래스\n */\nexport const NineFab = {\n version: typeof __APP_VERSION__ !== 'undefined' ? __APP_VERSION__ : '0.1.0',\n init: (config) => {\n trace.log(\"🛠️ Nine-Fab Engine initialized\", config);\n // 향후 커넥터 URL 전역 설정이나 인증 토큰 처리 로직 추가 가능\n }\n};\n\n// 기본 export 및 컴포넌트 export\nexport default NineFab;\nexport { NineChat };"],"names":["NineMuService","constructor","connectorUrl","this","generate","command","targets","currentRoutes","trace","log","join","response","fetch","method","headers","body","JSON","stringify","projectType","result","json","success","Error","error","fetchRoutes","routeUrl","res","err","NineChat","HTMLElement","super","__privateAdd","_NineChat_instances","_service","_routes","attachShadow","mode","connectedCallback","getAttribute","__privateSet","__privateMethod","render_fn","call","initInteractions_fn","initActions_fn","__privateGet","WeakMap","WeakSet","$settings","shadowRoot","querySelector","$menuIcons","querySelectorAll","toggleUI","classList","toggle","addEventListener","forEach","el","e","icon","remove","clicked","target","closest","add","contains","$textarea","$status","async","key","shiftKey","preventDefault","value","trim","textContent","Array","from","map","nine","alert","rgb","dispatchEvent","CustomEvent","detail","bubbles","message","shake","placeholder","customImport","innerHTML","t","toLowerCase","customElements","get","define","NineFab","version","init","config"],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@nine-lab/nine-mu",
|
|
3
|
+
"version": "0.1.14",
|
|
4
|
+
"description": "AI-Driven Full-Stack Code Fabrication Engine",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "./dist/nine-mu.umd.js",
|
|
7
|
+
"module": "",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/nine-mu.js",
|
|
11
|
+
"require": "./dist/nine-mu.umd.js"
|
|
12
|
+
},
|
|
13
|
+
"./chat": {
|
|
14
|
+
"import": "./dist/nine-chat.js"
|
|
15
|
+
},
|
|
16
|
+
"./css": "./dist/css/nine-mu.css"
|
|
17
|
+
},
|
|
18
|
+
"scripts": {
|
|
19
|
+
"dev": "vite",
|
|
20
|
+
"build": "vite build && mkdir -p dist/css && cp -r public/css/. dist/css/",
|
|
21
|
+
"release": "npm run build && npm version patch && npm publish"
|
|
22
|
+
},
|
|
23
|
+
"devDependencies": {
|
|
24
|
+
"terser": "^5.31.0",
|
|
25
|
+
"vite": "^6.0.0"
|
|
26
|
+
},
|
|
27
|
+
"dependencies": {
|
|
28
|
+
"@nine-lab/nine-ai": "^0.1.75",
|
|
29
|
+
"@nine-lab/nine-util": "^0.9.40",
|
|
30
|
+
"@nine-lab/nine-ux": "^0.1.103"
|
|
31
|
+
},
|
|
32
|
+
"publishConfig": {
|
|
33
|
+
"access": "public"
|
|
34
|
+
},
|
|
35
|
+
"keywords": [
|
|
36
|
+
"fab",
|
|
37
|
+
"codegen",
|
|
38
|
+
"ai",
|
|
39
|
+
"gemini",
|
|
40
|
+
"web-components",
|
|
41
|
+
"spring-react"
|
|
42
|
+
],
|
|
43
|
+
"author": "nine-mu",
|
|
44
|
+
"license": "MIT"
|
|
45
|
+
}
|