@nine-lab/nine-mu 0.1.337 โ†’ 0.1.339

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.337",
3
+ "version": "0.1.339",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -1,9 +1,12 @@
1
1
  // src/components/exception/ExceptionHook.js
2
+ import { nine } from '@nine-lab/nine-util';
3
+
2
4
  export class ExceptionHook extends HTMLElement {
3
- // ๐Ÿ’ก [ํ•ต์‹ฌ] ๋น„๊ณต๊ฐœ ์ธ์Šคํ„ด์Šค ํ•„๋“œ๋Š” ํด๋ž˜์Šค ์ตœ์ƒ๋‹จ์— ๋จผ์ € ์„ ์–ธํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
5
+ // ๐Ÿ’ก ๋น„๊ณต๊ฐœ ์ธ์Šคํ„ด์Šค ํ•„๋“œ ์ •์˜
4
6
  #lastPath = window.location.pathname;
5
7
  #hasError = false;
6
8
  #cssPath = "/css/nine-exception-hook.css";
9
+ #oldOnError = null;
7
10
 
8
11
  constructor() {
9
12
  super();
@@ -11,13 +14,13 @@ export class ExceptionHook extends HTMLElement {
11
14
  this.attachShadow({ mode: 'open' });
12
15
  }
13
16
 
14
- // src/components/exception/ExceptionHook.js ๋‚ด๋ถ€ ์ˆ˜์ •
15
-
16
17
  connectedCallback() {
17
18
  this.#renderer();
18
19
  this.#injectShadowStylesheet();
19
20
 
20
- window.addEventListener('error', this.#handleRuntimeError, true);
21
+ // ๐ŸŽฏ ๋ฆฌ์•กํŠธ ๋ฐ ๊ฐœ๋ฐœ ์˜ค๋ฒ„๋ ˆ์ด์˜ stopPropagation์„ ์šฐํšŒํ•˜๊ธฐ ์œ„ํ•œ ์ด์ค‘ ์Šค๋‹ˆํผ ๊ฐ€๋™
22
+ this.#setupGlobalSniffer();
23
+
21
24
  window.addEventListener('unhandledrejection', this.#handlePromiseError, true);
22
25
  window.addEventListener('popstate', this.#handleLocationChange);
23
26
  document.addEventListener('click', this.#handleLocationChange, true);
@@ -28,18 +31,43 @@ export class ExceptionHook extends HTMLElement {
28
31
  window.removeEventListener('unhandledrejection', this.#handlePromiseError, true);
29
32
  window.removeEventListener('popstate', this.#handleLocationChange);
30
33
  document.removeEventListener('click', this.#handleLocationChange, true);
34
+
35
+ // ๐ŸŽฏ ์›์‹œ onerror ํ•ธ๋“ค๋Ÿฌ ๋ณต๊ตฌ
36
+ if (window.onerror === this.#handleRuntimeError || this.#oldOnError) {
37
+ window.onerror = this.#oldOnError;
38
+ }
31
39
  }
32
40
 
41
+ #setupGlobalSniffer() {
42
+ // ํ‘œ์ค€ ์บก์ฒ˜๋ง ๋ฆฌ์Šค๋„ˆ ๋“ฑ๋ก
43
+ window.addEventListener('error', this.#handleRuntimeError, true);
44
+
45
+ // ๐ŸŽฏ [์น˜ํŠธํ‚ค] ํƒ€ ํ”„๋ ˆ์ž„์›Œํฌ๊ฐ€ ์ด๋ฒคํŠธ๋ฅผ ์‚ผ์ผœ๋„ ๋ฌด์กฐ๊ฑด ์‹คํ–‰๋˜๋Š” ์›์‹œ hook ๊ฐ€๋กœ์ฑ„๊ธฐ
46
+ this.#oldOnError = window.onerror;
47
+ window.onerror = (message, source, lineno, colno, error) => {
48
+ if (!this.#hasError) {
49
+ const errorMessage = error?.message || message || "์•Œ ์ˆ˜ ์—†๋Š” ๋Ÿฐํƒ€์ž„ ์˜ˆ์™ธ";
50
+ const errorStack = error?.stack || `${source}:${lineno}:${colno}`;
51
+ this.#renderError(errorMessage, errorStack);
52
+ }
53
+
54
+ // ๊ธฐ์กด์— ๋“ฑ๋ก๋˜์–ด ์žˆ๋˜ ๋‹ค๋ฅธ onerror ์—”์ง„(Vite, ๋ธŒ๋ผ์šฐ์ € ๋“ฑ)์ด ์žˆ์œผ๋ฉด ๊ทธ๋Œ€๋กœ ์‹คํ–‰๋˜๋„๋ก ์œ„์ž„
55
+ if (this.#oldOnError) {
56
+ return this.#oldOnError(message, source, lineno, colno, error);
57
+ }
58
+ return false;
59
+ };
60
+ }
33
61
 
34
62
  #renderer = () => {
35
63
  const customImport = nine.cssPath ? `@import "${nine.cssPath}/nine-mu.css";` : "";
36
64
 
37
65
  this.shadowRoot.innerHTML = `
38
- <style>
39
- @import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-mu@${__APP_VERSION__}/dist/css/nine-mu.css";
40
- ${customImport}
41
- </style>
42
-
66
+ <style>
67
+ @import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-mu@${__APP_VERSION__}/dist/css/nine-mu.css";
68
+ ${customImport}
69
+ </style>
70
+
43
71
  <div class="nine-hook-core">
44
72
  <slot></slot>
45
73
  </div>
@@ -48,7 +76,6 @@ export class ExceptionHook extends HTMLElement {
48
76
  }
49
77
 
50
78
  #injectShadowStylesheet() {
51
- // ๐Ÿ’ก ๋‚ด๋ถ€ ํ•„๋“œ ํ˜ธ์ถœ ์‹œ์—๋„ ๋ชจ๋‘ this.#ํ˜•์‹์œผ๋กœ ๋งคํ•‘ํ•ฉ๋‹ˆ๋‹ค.
52
79
  if (this.shadowRoot.querySelector(`link[href="${this.#cssPath}"]`)) return;
53
80
 
54
81
  const link = document.createElement('link');
@@ -60,27 +87,20 @@ export class ExceptionHook extends HTMLElement {
60
87
  #handleRuntimeError = (event) => {
61
88
  if (this.#hasError) return;
62
89
 
63
- // 1. ์—๋Ÿฌ ๋ฉ”์‹œ์ง€ ์ถ”์ถœ (event ๊ฐ์ฒด ์ž์ฒด ๋˜๋Š” event.error์—์„œ ํƒ€๊ฒŸํŒ…)
90
+ // ๐ŸŽฏ event.error๊ฐ€ null์ด๊ฑฐ๋‚˜ ์œ ์‹ค๋˜๋”๋ผ๋„ message๋ฅผ ํ†ตํ•ด ์—๋Ÿฌ๋ฅผ ๋ฌด์กฐ๊ฑด ํฌ์ฐฉํ•ฉ๋‹ˆ๋‹ค.
64
91
  const errorMessage = event.error?.message || event.message || String(event);
65
92
  const errorStack = event.error?.stack || "No stack trace available";
66
93
 
67
- // 2. ๊ฐœ๋ฐœ ํ™˜๊ฒฝ(Vite, Webpack) ๋ฐ ๋ฆฌ์•กํŠธ ํŠน์œ ์˜ ๋ฌด์กฐ๊ฑด์ ์ธ ์ „์—ญ ์—๋Ÿฌ ์ „ํŒŒ ์บ์น˜
68
- // ๋ฆฌ์•กํŠธ ์—๋Ÿฌ๋Š” ๋ณดํ†ต ์ „์—ญ window๋กœ ๋˜์ ธ์ง€๋ฏ€๋กœ, ์ด ํ›…์ด ๋–  ์žˆ๋Š” ์ƒํƒœ๋ผ๋ฉด ๊ทธ๋ƒฅ ๊ฐ€์ฐจ์—†์ด ์žก์•„์•ผ ํ•ฉ๋‹ˆ๋‹ค.
69
- if (errorMessage) {
70
-
71
- // 3. ๋ฆฌ์•กํŠธ๊ฐ€ ์—๋Ÿฌ ๋•Œ๋ฌธ์— <slot> ๋‚ด๋ถ€ DOM์„ ํ†ต์งธ๋กœ Unmount(ํŒŒ๊ดด)ํ•ด๋ฒ„๋ฆฌ๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด
72
- // ๋ธŒ๋ผ์šฐ์ € ๋ฒ„๋ธ”๋ง์„ ์ฆ‰์‹œ ์ฐจ๋‹จํ•˜๊ณ , ์—๋Ÿฌ ๋ณด๋“œ๋ฅผ ์ฆ‰๊ฐ ๊ทธ๋ฆฌ๋„๋ก ์ˆœ์„œ๋ฅผ ๊ฐ€๋กœ์ฑ•๋‹ˆ๋‹ค.
94
+ // ๋ธŒ๋ผ์šฐ์ € ๋‚ด๋ถ€ ์Šคํฌ๋ฆฝํŠธ ๋กœ๋”ฉ ์—๋Ÿฌ ์˜ˆ์™ธ ์ฒ˜๋ฆฌ ํ›„ ๊ฐ€์ฐจ์—†์ด ๋ฐ”์ธ๋”ฉ
95
+ if (errorMessage && errorMessage !== "Script error.") {
73
96
  this.#renderError(errorMessage, errorStack);
74
-
75
- // ํ•„์š”์‹œ ๋ธŒ๋ผ์šฐ์ € ๊ธฐ๋ณธ ๋นจ๊ฐ„ ์—๋Ÿฌ์ฐฝ(Vite Overlay ๋“ฑ) ์–ต์ œ ์›ํ•  ๋•Œ ํ™œ์„ฑํ™”
76
- // event.preventDefault();
77
97
  }
78
98
  }
79
99
 
80
100
  #handlePromiseError = (event) => {
81
101
  if (this.#hasError) return;
82
102
 
83
- // ๋น„๋™๊ธฐ ํ›…(useEffect ์•ˆ์˜ null.data ๊ฐ™์€ Promise ๊ฑฐ๋ถ€) ์—๋Ÿฌ ์บ์น˜
103
+ // ๋น„๋™๊ธฐ ๋น„์ •์ƒ ๋Ÿฐํƒ€์ž„ ๊ฑฐ๋ถ€(ex. null.data ์ฝ๊ธฐ ์—๋Ÿฌ) ์บ์น˜
84
104
  const reason = event.reason;
85
105
  const errorMessage = reason?.message || String(reason || "Unhandled Promise Rejection");
86
106
  const errorStack = reason?.stack || "No stack trace available";
@@ -145,19 +165,19 @@ export class ExceptionHook extends HTMLElement {
145
165
  if (!exceptionBoard) return;
146
166
 
147
167
  const errorHTML = `
148
- <div class="nine-error-container">
149
- <h3 class="nine-error-title">โš ๏ธ ์‹œ์Šคํ…œ ์˜ˆ์™ธ ๊ฐ์ง€ (${this.tagName.toLowerCase()})</h3>
150
- <p class="nine-error-label">[์—๋Ÿฌ ์›์ธ ๋กœ๊ทธ]:</p>
151
- <pre class="nine-error-log">${errorMessage}</pre>
152
-
153
- <div class="nine-action-area" style="margin-top: 20px; display: flex; align-items: center; gap: 15px;">
154
- <button class="nine-ai-btn">๐Ÿค– AI์—๊ฒŒ ์†Œ์Šค์ฝ”๋“œ ์ˆ˜์ • ์š”์ฒญ</button>
155
- <div class="nine-error-footer">
156
- ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด AI๊ฐ€ ๋กœ๊ทธ ๋ฐ ์ปดํฌ๋„ŒํŠธ ๋งต์„ ์—ญ์ถ”์ ํ•˜์—ฌ ์ˆ˜์ •์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
157
- </div>
158
- </div>
159
- </div>
160
- `;
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๊ฐ€ ๋กœ๊ทธ ๋ฐ ์ปดํฌ๋„ŒํŠธ ๋งต์„ ์—ญ์ถ”์ ํ•˜์—ฌ ์ˆ˜์ •์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
177
+ </div>
178
+ </div>
179
+ </div>
180
+ `;
161
181
 
162
182
  exceptionBoard.innerHTML = errorHTML;
163
183