@nine-lab/nine-mu 0.1.283 → 0.1.285

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": "@nine-lab/nine-mu",
3
- "version": "0.1.283",
3
+ "version": "0.1.285",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -5,7 +5,7 @@ import '@nine-lab/nine-util';
5
5
  export class NineDiffPopup extends HTMLElement {
6
6
  #dialog = null;
7
7
  #tabContainer = null;
8
- #filesMap = new Map(); // 탭(파일)별 메타데이터 에디터 인스턴스를 관리할 고유 저장소
8
+ #fileList = []; // 최종 [모두 저장]을 위한 차분 명세 데이터 버퍼
9
9
  #host;
10
10
 
11
11
  constructor() {
@@ -19,7 +19,7 @@ export class NineDiffPopup extends HTMLElement {
19
19
  }
20
20
 
21
21
  /**
22
- * 💡 기본 다이얼로그 프레임 스타일 스케폴딩 렌더링
22
+ * 💡 기본 다이얼로그 외곽 프레임만 정적으로 선언 (탭 레이아웃은 비워둠)
23
23
  */
24
24
  #renderScaffolding() {
25
25
  const customImport = this.getAttribute("css-path") ? `@import "${this.getAttribute("css-path")}";` : "";
@@ -43,14 +43,13 @@ export class NineDiffPopup extends HTMLElement {
43
43
  display: flex;
44
44
  flex-direction: column;
45
45
  }
46
- /* 💡 nx-tab / nine-tab 프레임워크가 100% 자라나도록 높이 강제 배치 */
47
46
  nine-tab {
48
47
  flex: 1;
49
48
  display: flex;
50
49
  flex-direction: column;
51
50
  height: 100%;
52
51
  }
53
- /* 💡 내부 에디터 가시성이 유실되어 숨겨지는 현상을 확실하게 방어 */
52
+ /* 💡 하얗게 보이는 현상을 방지하기 위해 동적 삽입될 에디터 영역의 높이를 확실히 보장 */
54
53
  .diff-wrapper {
55
54
  height: calc(80vh - 120px);
56
55
  width: 100%;
@@ -96,18 +95,18 @@ export class NineDiffPopup extends HTMLElement {
96
95
  }
97
96
 
98
97
  /**
99
- * 💡 [완벽 동적 빌딩 시스템]
100
- * 백엔드 완료 시그널로부터 모아진 collectedFiles 들어오면, 런타임에 해당하는 탭만 정확하게 파싱하여 주입합니다.
98
+ * 💡 [100% 동적 빌딩 시스템]
99
+ * 들어온 데이터 개수에 정확히 맞추어 런타임에 페이지와 에디터를 일대일 매핑으로 직접 조립합니다.
101
100
  * @param {Array} fileList - [{ layer: "MyBatis", full_path: "...", asis_source: "...", source: "..." }]
102
101
  */
103
102
  async data(fileList) {
104
103
  if (!Array.isArray(fileList) || fileList.length === 0) return this;
104
+ this.#fileList = fileList;
105
105
 
106
- // 1. 기존에 잔존하던 동적 컨텐츠 구성원 완전 청소
106
+ // 1. 🧼 이전 실행 흔적이 있다면 동적 컨텐츠 내부를 완전히 청소 (인덱스 리셋)
107
107
  this.#tabContainer.innerHTML = "";
108
- this.#filesMap.clear();
109
108
 
110
- // 확장자 기반 언어셋 하이라이팅 추론 헬퍼
109
+ // 확장자 기반 주석/언어 유추 헬퍼
111
110
  const detectLanguage = (path) => {
112
111
  const lower = (path || "").toLowerCase();
113
112
  if (lower.endsWith('.xml')) return 'xml';
@@ -116,84 +115,79 @@ export class NineDiffPopup extends HTMLElement {
116
115
  return 'javascript';
117
116
  };
118
117
 
119
- // 2. 수신된 파일 명세 묶음 크기만큼 루프를 돌며 컴포넌트 런타임 인스턴싱
120
- fileList.forEach((file, index) => {
121
- const { layer, full_path, asis_source, source } = file;
118
+ // 2. 수신된 파일 갯수만큼 루프를 돌며 필요한 요소만 정확히 DOM 생성(Injection)
119
+ fileList.forEach((file) => {
120
+ const { layer, full_path } = file;
122
121
  const lang = detectLanguage(full_path);
123
-
124
- // 파일명만 추출하여 보기 좋게 캡션 가공
125
122
  const fileName = full_path.split('/').pop() || "Unknown";
126
- const caption = `${layer.toUpperCase()} (${fileName})`;
123
+ const captionName = `${layer.toUpperCase()} (${fileName})`; // 예: MYBATIS (MemberUsersMapper.xml)
127
124
 
128
- // A. <nine-tab-page> 엘리먼트 동적 생성 및 헤더 캡션 설정
125
+ // A. <nine-tab-page> 런타임 인스턴싱
129
126
  const tabPage = document.createElement('nine-tab-page');
130
- tabPage.setAttribute('caption', caption);
127
+ tabPage.setAttribute('caption', captionName);
131
128
 
132
- // B. 차분 레이아웃 정밀 래퍼 생성
129
+ // B. 높이 유실 방어용 래퍼 생성
133
130
  const diffWrapper = document.createElement('div');
134
131
  diffWrapper.className = 'diff-wrapper';
135
132
 
136
- // C. <nine-diff> 소스 비교 전용 에디터 장치 인스턴싱
133
+ // C. <nine-diff> 에디터 장치 동적 생성 매칭용 레이어 클래스 주입
137
134
  const diffView = document.createElement('nine-diff');
135
+ diffView.className = layer; // 예: class="MyBatis" 또는 class="JavaScript"
138
136
 
139
- // D. 계층 하위 조립 완성된 컴포넌트 트리를 실제 탭 컨테이너에 피딩
137
+ // D. 하위 트리 계층 결합 실제 탭 컨테이너 레이아웃에 안착
140
138
  diffWrapper.appendChild(diffView);
141
139
  tabPage.appendChild(diffWrapper);
142
140
  this.#tabContainer.appendChild(tabPage);
143
-
144
- // E. 추후 [모두 저장] 작동시 순회 타겟 명세 확보를 위한 고유 맵 바인딩
145
- const fileKey = `file_tab_${index}`;
146
- this.#filesMap.set(fileKey, {
147
- layer,
148
- fullPath: full_path,
149
- asisSource: asis_source,
150
- diffView: diffView
151
- });
152
-
153
- // F. 동적으로 추가된 에디터 가상 장치가 준비 완료(ready) 상태를 발행하면 소스 코드 로드 기동
154
- diffView.addEventListener('ready', () => {
155
- diffView.initialize(asis_source || "", source || "", lang);
156
- }, { once: true });
157
141
  });
158
142
 
159
- // 3. 렌더링 트리 결합 nine-tab 컴포넌트 자체 라이프사이클 엔진 강제 구동
143
+ // 3. 브라우저가 동적으로 추가된 태그들을 완벽하게 렌더트리에 마운트할 있도록 비동기 여유 마진 확보
160
144
  setTimeout(() => {
161
- if (typeof this.#tabContainer.initialize === 'function') {
145
+ fileList.forEach((file) => {
146
+ const { layer, asis_source, source } = file;
147
+ const diff = this.shadowRoot.querySelector(`nine-diff.${layer}`);
148
+
149
+ if (diff) {
150
+ const lang = detectLanguage(file.full_path);
151
+ // 확보된 실제 에디터 버퍼 장치에 소스코드 강제 바인딩 초기화
152
+ diff.initialize(asis_source || "", source || "", lang);
153
+ }
154
+ });
155
+
156
+ // E. 데이터 주입이 모두 완벽히 끝난 시점에 nine-tab 컴포넌트의 가상 빌더 엔진 트리거!
157
+ if (this.#tabContainer && typeof this.#tabContainer.initialize === 'function') {
162
158
  this.#tabContainer.initialize();
163
159
  }
164
- }, 50);
160
+ }, 150); // 150ms의 마진 타임 적용
165
161
 
166
162
  return this;
167
163
  }
168
164
 
169
165
  /**
170
- * 💡 [일괄 물리 파일 라이팅]
171
- * 활성화된 모든 탭 영역의 우측 창(TO-BE) 최종 소스들을 취합하여 단 한 번의 일괄 요청으로 커밋
166
+ * 💡 [일괄 물리 저장]
172
167
  */
173
168
  async #handleConfirmAll() {
174
169
  const payloadList = [];
175
170
 
176
- // 관리용 저장소를 순회하며 최종 수정본 코드 스냅샷 추출
177
- for (const [key, fileObj] of this.#filesMap.entries()) {
178
- const { diffView, fullPath, asisSource, layer } = fileObj;
171
+ for (const file of this.#fileList) {
172
+ const { layer, full_path, asis_source } = file;
173
+ // 레이어 클래스로 지정해 동적 에디터를 순회하며 텍스트 캡처
174
+ const diff = this.shadowRoot.querySelector(`nine-diff.${layer}`);
179
175
 
180
- // 사용자가 수정한 최종 우측 창 텍스트를 추출 (에디터 로드 전 예외 발생 시 원본 보호용 fallback)
181
- const currentContent = diffView ? diffView.getContents() : asisSource;
176
+ const currentContent = diff ? diff.getContents() : asis_source;
182
177
 
183
178
  payloadList.push({
184
179
  layer,
185
- fullPath: fullPath,
180
+ fullPath: full_path,
186
181
  packageName: this.#host?.getAttribute('package-name') || "com.ninelab.ai",
187
182
  contents: currentContent
188
183
  });
189
184
  }
190
185
 
191
186
  try {
192
- // 변경된 멀티 레이어 파일 묶음을 전송하는 일괄 일치 컨트롤러 API 최종 동기화
193
187
  await api.post(`/nine-mu/source/generateJsonFileBatch`, { fileList: payloadList });
194
188
 
195
189
  await nine.alert("요청하신 모든 파일의 소스 변경 사항이 성공적으로 반영되었습니다.");
196
- this.#dialog.close(); // 팝업 모달 소멸
190
+ this.#dialog.close();
197
191
  } catch (error) {
198
192
  trace.error("일괄 파일 저장 처리 중 실패:", error);
199
193
  nine.alert("소스 일괄 저장 연동 중 치명적인 오류가 발생했습니다.");
@@ -205,7 +199,6 @@ export class NineDiffPopup extends HTMLElement {
205
199
  }
206
200
  }
207
201
 
208
- // 중복 등록 충돌 방지 처리 포함 등록
209
202
  if (!customElements.get("nine-diff-popup")) {
210
203
  customElements.define("nine-diff-popup", NineDiffPopup);
211
204
  }