@nine-lab/nine-mu 0.1.339 β†’ 0.1.341

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.339",
3
+ "version": "0.1.341",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -1,8 +1,8 @@
1
1
  // src/components/exception/ExceptionHook.js
2
2
  import { nine } from '@nine-lab/nine-util';
3
+ import { trace } from '@nopeer';
3
4
 
4
5
  export class ExceptionHook extends HTMLElement {
5
- // πŸ’‘ λΉ„κ³΅κ°œ μΈμŠ€ν„΄μŠ€ ν•„λ“œ μ •μ˜
6
6
  #lastPath = window.location.pathname;
7
7
  #hasError = false;
8
8
  #cssPath = "/css/nine-exception-hook.css";
@@ -10,15 +10,15 @@ export class ExceptionHook extends HTMLElement {
10
10
 
11
11
  constructor() {
12
12
  super();
13
- // Shadow DOM(open λͺ¨λ“œ) ν™œμ„±ν™”
14
13
  this.attachShadow({ mode: 'open' });
14
+ trace.log("πŸ” [nine-exception-hook] μΈμŠ€ν„΄μŠ€ 생성됨");
15
15
  }
16
16
 
17
17
  connectedCallback() {
18
+ trace.log("πŸ” [nine-exception-hook] DOM에 마운트됨. 이벀트 λ¦¬μŠ€λ„ˆ 바인딩 μ‹œμž‘");
18
19
  this.#renderer();
19
20
  this.#injectShadowStylesheet();
20
21
 
21
- // 🎯 λ¦¬μ•‘νŠΈ 및 개발 μ˜€λ²„λ ˆμ΄μ˜ stopPropagation을 μš°νšŒν•˜κΈ° μœ„ν•œ 이쀑 μŠ€λ‹ˆνΌ 가동
22
22
  this.#setupGlobalSniffer();
23
23
 
24
24
  window.addEventListener('unhandledrejection', this.#handlePromiseError, true);
@@ -27,36 +27,42 @@ export class ExceptionHook extends HTMLElement {
27
27
  }
28
28
 
29
29
  disconnectedCallback() {
30
+ trace.log("πŸ” [nine-exception-hook] DOMμ—μ„œ μ–Έλ§ˆμš΄νŠΈλ¨. λ¦¬μŠ€λ„ˆ ν•΄μ œ");
30
31
  window.removeEventListener('error', this.#handleRuntimeError, true);
31
32
  window.removeEventListener('unhandledrejection', this.#handlePromiseError, true);
32
33
  window.removeEventListener('popstate', this.#handleLocationChange);
33
34
  document.removeEventListener('click', this.#handleLocationChange, true);
34
35
 
35
- // 🎯 μ›μ‹œ onerror ν•Έλ“€λŸ¬ 볡ꡬ
36
36
  if (window.onerror === this.#handleRuntimeError || this.#oldOnError) {
37
37
  window.onerror = this.#oldOnError;
38
+ trace.log("πŸ” [nine-exception-hook] window.onerror 볡ꡬ μ™„λ£Œ");
38
39
  }
39
40
  }
40
41
 
41
42
  #setupGlobalSniffer() {
42
- // ν‘œμ€€ 캑처링 λ¦¬μŠ€λ„ˆ 등둝
43
43
  window.addEventListener('error', this.#handleRuntimeError, true);
44
+ trace.log("πŸ” [nine-exception-hook] window.addEventListener('error') 등둝 μ™„λ£Œ");
44
45
 
45
- // 🎯 [μΉ˜νŠΈν‚€] 타 ν”„λ ˆμž„μ›Œν¬κ°€ 이벀트λ₯Ό μ‚ΌμΌœλ„ 무쑰건 μ‹€ν–‰λ˜λŠ” μ›μ‹œ hook κ°€λ‘œμ±„κΈ°
46
46
  this.#oldOnError = window.onerror;
47
47
  window.onerror = (message, source, lineno, colno, error) => {
48
+ trace.log("🚨 [nine-exception-hook] μ›μ‹œ window.onerror 포착!!", { message, source, lineno, error });
49
+
48
50
  if (!this.#hasError) {
51
+ trace.log("🎯 [nine-exception-hook] ν˜„μž¬ μ—λŸ¬ μƒνƒœ μ—†μŒ -> μ—λŸ¬ λ³΄λ“œ 좜λ ₯ μ‹œλ„");
49
52
  const errorMessage = error?.message || message || "μ•Œ 수 μ—†λŠ” λŸ°νƒ€μž„ μ˜ˆμ™Έ";
50
53
  const errorStack = error?.stack || `${source}:${lineno}:${colno}`;
51
54
  this.#renderError(errorMessage, errorStack);
55
+ } else {
56
+ trace.log("⚠️ [nine-exception-hook] 이미 μ—λŸ¬ 화면이 ν™œμ„±ν™”λ˜μ–΄ μžˆμ–΄ μ›μ‹œ onerror 패슀");
52
57
  }
53
58
 
54
- // 기쑴에 λ“±λ‘λ˜μ–΄ 있던 λ‹€λ₯Έ onerror μ—”μ§„(Vite, λΈŒλΌμš°μ € λ“±)이 있으면 κ·ΈλŒ€λ‘œ μ‹€ν–‰λ˜λ„λ‘ μœ„μž„
55
59
  if (this.#oldOnError) {
60
+ trace.log("πŸ”„ [nine-exception-hook] 기쑴에 λ“±λ‘λ˜μ–΄ 있던 λ‹€λ₯Έ onerror μ—”μ§„μœΌλ‘œ μœ„μž„");
56
61
  return this.#oldOnError(message, source, lineno, colno, error);
57
62
  }
58
63
  return false;
59
64
  };
65
+ trace.log("πŸ” [nine-exception-hook] μ›μ‹œ window.onerror κ°€λ‘œμ±„κΈ°(Chaining) μ™„λ£Œ");
60
66
  }
61
67
 
62
68
  #renderer = () => {
@@ -85,33 +91,47 @@ export class ExceptionHook extends HTMLElement {
85
91
  }
86
92
 
87
93
  #handleRuntimeError = (event) => {
88
- if (this.#hasError) return;
94
+ trace.log("🚨 [nine-exception-hook] window.addEventListener('error') λ¦¬μŠ€λ„ˆ 포착!!", event);
95
+
96
+ if (this.#hasError) {
97
+ trace.log("⚠️ [nine-exception-hook] 이미 μ—λŸ¬ 화면이 ν™œμ„±ν™”λ˜μ–΄ μžˆμ–΄ 이벀트 λ¦¬μŠ€λ„ˆ 패슀");
98
+ return;
99
+ }
89
100
 
90
- // 🎯 event.errorκ°€ nullμ΄κ±°λ‚˜ μœ μ‹€λ˜λ”λΌλ„ messageλ₯Ό 톡해 μ—λŸ¬λ₯Ό 무쑰건 ν¬μ°©ν•©λ‹ˆλ‹€.
91
101
  const errorMessage = event.error?.message || event.message || String(event);
92
102
  const errorStack = event.error?.stack || "No stack trace available";
93
103
 
94
- // λΈŒλΌμš°μ € λ‚΄λΆ€ 슀크립트 λ‘œλ”© μ—λŸ¬ μ˜ˆμ™Έ 처리 ν›„ 가차없이 바인딩
95
104
  if (errorMessage && errorMessage !== "Script error.") {
105
+ trace.log("🎯 [nine-exception-hook] 정상적인 μ—λŸ¬ λ©”μ‹œμ§€ 확인 -> μ—λŸ¬ λ³΄λ“œ 좜λ ₯ μ‹œλ„", { errorMessage });
96
106
  this.#renderError(errorMessage, errorStack);
107
+ } else {
108
+ trace.log("⚠️ [nine-exception-hook] 'Script error.' μ΄κ±°λ‚˜ 빈 λ©”μ‹œμ§€λΌ λ¬΄μ‹œλ¨");
97
109
  }
98
110
  }
99
111
 
100
112
  #handlePromiseError = (event) => {
113
+ trace.log("🚨 [nine-exception-hook] unhandledrejection (Promise μ—λŸ¬) 포착!!", event);
114
+
101
115
  if (this.#hasError) return;
102
116
 
103
- // 비동기 비정상 λŸ°νƒ€μž„ κ±°λΆ€(ex. null.data 읽기 μ—λŸ¬) 캐치
104
117
  const reason = event.reason;
105
118
  const errorMessage = reason?.message || String(reason || "Unhandled Promise Rejection");
106
119
  const errorStack = reason?.stack || "No stack trace available";
107
120
 
121
+ trace.log("🎯 [nine-exception-hook] Promise κ±°λΆ€ 확인 -> μ—λŸ¬ λ³΄λ“œ 좜λ ₯ μ‹œλ„");
108
122
  this.#renderError(errorMessage, errorStack);
109
123
  }
110
124
 
111
125
  #handleLocationChange = () => {
112
126
  setTimeout(() => {
127
+ trace.log("πŸ“ [nine-exception-hook] μ£Όμ†Œ 이동 감지 체크", {
128
+ hasError: this.#hasError,
129
+ lastPath: this.#lastPath,
130
+ currentPath: window.location.pathname
131
+ });
132
+
113
133
  if (this.#hasError && this.#lastPath !== window.location.pathname) {
114
- console.log("✨ [nine-exception-hook] Shadow DOM λ‚΄λΆ€ μ˜ˆμ™Έ μ²­μ†Œ 및 정상 볡ꡬ");
134
+ trace.log("✨ [nine-exception-hook] Shadow DOM λ‚΄λΆ€ μ˜ˆμ™Έ μ²­μ†Œ 및 정상 볡ꡬ");
115
135
  this.#lastPath = window.location.pathname;
116
136
  this.#hasError = false;
117
137
 
@@ -125,6 +145,7 @@ export class ExceptionHook extends HTMLElement {
125
145
  }
126
146
 
127
147
  #sendToAiAction = async (errorMessage, errorStack) => {
148
+ trace.log("πŸš€ [nine-exception-hook] AI μˆ˜μ • μš”μ²­ λ²„νŠΌ 클릭됨");
128
149
  const btn = this.shadowRoot.querySelector('.nine-ai-btn');
129
150
  const footer = this.shadowRoot.querySelector('.nine-error-footer');
130
151
  if (!btn) return;
@@ -135,6 +156,7 @@ export class ExceptionHook extends HTMLElement {
135
156
 
136
157
  try {
137
158
  if (window.triggerAutoRecovery) {
159
+ trace.log("πŸ“‘ [nine-exception-hook] window.triggerAutoRecovery 호좜 μ‹€ν–‰");
138
160
  await window.triggerAutoRecovery({
139
161
  message: errorMessage,
140
162
  stack: errorStack || "No stack trace available",
@@ -147,7 +169,7 @@ export class ExceptionHook extends HTMLElement {
147
169
  throw new Error("window.triggerAutoRecovery κ΄€μ œνƒ‘ 엔진이 λ‘œλ“œλ˜μ§€ μ•Šμ•˜μŠ΅λ‹ˆλ‹€.");
148
170
  }
149
171
  } catch (err) {
150
- console.error("❌ AI 전솑 μ‹€νŒ¨:", err);
172
+ trace.error("❌ AI 전솑 μ‹€νŒ¨:", err);
151
173
  btn.disabled = false;
152
174
  btn.innerText = "❌ μž¬μ „μ†‘ μ‹œλ„";
153
175
  footer.innerHTML = `<span style="color: #E53E3E;">⚠️ 전솑 μ‹€νŒ¨: ${err.message}</span>`;
@@ -158,33 +180,47 @@ export class ExceptionHook extends HTMLElement {
158
180
  if (this.#hasError) return;
159
181
  this.#hasError = true;
160
182
 
161
- const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
162
- if (coreContainer) coreContainer.style.display = 'none';
163
-
164
- const exceptionBoard = this.shadowRoot.querySelector('.nine-exception-board');
165
- if (!exceptionBoard) return;
166
-
167
- const errorHTML = `
168
- <div class="nine-error-container">
169
- <h3 class="nine-error-title">⚠️ μ‹œμŠ€ν…œ μ˜ˆμ™Έ 감지 (${this.tagName.toLowerCase()})</h3>
170
- <p class="nine-error-label">[μ—λŸ¬ 원인 둜그]:</p>
171
- <pre class="nine-error-log">${errorMessage}</pre>
172
-
173
- <div class="nine-action-area" style="margin-top: 20px; display: flex; align-items: center; gap: 15px;">
174
- <button class="nine-ai-btn">πŸ€– AIμ—κ²Œ μ†ŒμŠ€μ½”λ“œ μˆ˜μ • μš”μ²­</button>
175
- <div class="nine-error-footer">
176
- λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ AIκ°€ 둜그 및 μ»΄ν¬λ„ŒνŠΈ 맡을 μ—­μΆ”μ ν•˜μ—¬ μˆ˜μ •μ„ μ‹œμž‘ν•©λ‹ˆλ‹€.
183
+ // 🎯 [핡심] λ¦¬μ•‘νŠΈκ°€ μ—λŸ¬ λ°œμƒ ν›„ ν•˜μœ„ DOM을 Unmount/μ‘°μž‘ν•˜λŠ” 동기적인 타이밍을
184
+ // μ™„μ „νžˆ ν˜λ €λ³΄λ‚Έ λ’€(setTimeout 0)에 μ•ˆμ „ν•˜κ²Œ Web Component UIλ₯Ό 꽂아 λ„£μŠ΅λ‹ˆλ‹€.
185
+ setTimeout(() => {
186
+ console.log("🎨 [nine-exception-hook] λ¦¬μ•‘νŠΈ 사이클 μ’…λ£Œ ν›„ μ—λŸ¬ UI μ΅œμ’… λ Œλ”λ§");
187
+
188
+ const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
189
+ if (coreContainer) {
190
+ coreContainer.style.display = 'none';
191
+ console.log("🎨 [nine-exception-hook] <slot> λ³Έλ¬Έ μ˜μ—­ μ»¨ν…Œμ΄λ„ˆ μˆ¨κΉ€");
192
+ }
193
+
194
+ const exceptionBoard = this.shadowRoot.querySelector('.nine-exception-board');
195
+ if (!exceptionBoard) {
196
+ console.error("❌ [nine-exception-hook] .nine-exception-board μ—˜λ¦¬λ¨ΌνŠΈλ₯Ό 찾을 수 μ—†μŠ΅λ‹ˆλ‹€.");
197
+ return;
198
+ }
199
+
200
+ const errorHTML = `
201
+ <div class="nine-error-container">
202
+ <h3 class="nine-error-title">⚠️ μ‹œμŠ€ν…œ μ˜ˆμ™Έ 감지 (${this.tagName.toLowerCase()})</h3>
203
+ <p class="nine-error-label">[μ—λŸ¬ 원인 둜그]:</p>
204
+ <pre class="nine-error-log">${errorMessage}</pre>
205
+
206
+ <div class="nine-action-area" style="margin-top: 20px; display: flex; align-items: center; gap: 15px;">
207
+ <button class="nine-ai-btn">πŸ€– AIμ—κ²Œ μ†ŒμŠ€μ½”λ“œ μˆ˜μ • μš”μ²­</button>
208
+ <div class="nine-error-footer">
209
+ λ²„νŠΌμ„ λˆ„λ₯΄λ©΄ AIκ°€ 둜그 및 μ»΄ν¬λ„ŒνŠΈ 맡을 μ—­μΆ”μ ν•˜μ—¬ μˆ˜μ •μ„ μ‹œμž‘ν•©λ‹ˆλ‹€.
210
+ </div>
177
211
  </div>
178
212
  </div>
179
- </div>
180
- `;
213
+ `;
181
214
 
182
- exceptionBoard.innerHTML = errorHTML;
215
+ exceptionBoard.innerHTML = errorHTML;
216
+ console.log("🎨 [nine-exception-hook] Shadow DOM에 μ—λŸ¬ UI μ΅œμ’… μ‚½μž… 성곡");
183
217
 
184
- const aiBtn = this.shadowRoot.querySelector('.nine-ai-btn');
185
- if (aiBtn) {
186
- aiBtn.addEventListener('click', () => this.#sendToAiAction(errorMessage, errorStack));
187
- }
218
+ const aiBtn = this.shadowRoot.querySelector('.nine-ai-btn');
219
+ if (aiBtn) {
220
+ aiBtn.addEventListener('click', () => this.#sendToAiAction(errorMessage, errorStack));
221
+ console.log("🎨 [nine-exception-hook] AI μš”μ²­ λ²„νŠΌ 이벀트 λ¦¬μŠ€λ„ˆ μ΅œμ’… 바인딩 성곡");
222
+ }
223
+ }, 0);
188
224
  }
189
225
  }
190
226