@nine-lab/nine-mu 0.1.344 โ†’ 0.1.346

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.344",
3
+ "version": "0.1.346",
4
4
  "description": "AI-Driven Full-Stack Code Fabrication Engine",
5
5
  "type": "module",
6
6
  "main": "./dist/nine-mu.umd.js",
@@ -1,238 +1,77 @@
1
1
  // src/components/exception/ExceptionHook.js
2
2
  import { nine } from '@nine-lab/nine-util';
3
3
  import { trace } from '@nopeer';
4
-
5
- export class ExceptionHook extends HTMLElement {
6
- #lastPath = window.location.pathname;
7
- #hasError = false;
8
- #cssPath = "/css/nine-exception-hook.css";
9
- #oldOnError = null;
10
-
11
- constructor() {
12
- super();
13
- this.attachShadow({ mode: 'open' });
14
- trace.log("๐Ÿ” [nine-exception-hook] ์ธ์Šคํ„ด์Šค ์ƒ์„ฑ๋จ");
4
+ // npm ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์šฉ ํŒจํ‚ค์ง€์˜ ํ•ต์‹ฌ ์†Œ์Šค (์˜ˆ: src/components/ContentErrorBoundary.jsx)
5
+ import React from 'react';
6
+
7
+ export class NineExceptionHook extends React.Component {
8
+ constructor(props) {
9
+ super(props);
10
+ this.state = { hasError: false, error: null };
11
+ this.lastPath = window.location.pathname;
12
+ this.handleLocationChange = this.handleLocationChange.bind(this);
15
13
  }
16
14
 
17
- connectedCallback() {
18
- trace.log("๐Ÿ” [nine-exception-hook] DOM์— ๋งˆ์šดํŠธ๋จ. ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ๋ฐ”์ธ๋”ฉ ์‹œ์ž‘");
19
- this.#renderer();
20
- this.#injectShadowStylesheet();
21
-
22
- this.#setupGlobalSniffer();
23
-
24
- window.addEventListener('unhandledrejection', this.#handlePromiseError, true);
25
- window.addEventListener('popstate', this.#handleLocationChange);
26
- document.addEventListener('click', this.#handleLocationChange, true);
15
+ static getDerivedStateFromError(error) {
16
+ return { hasError: true, error };
27
17
  }
28
18
 
29
- disconnectedCallback() {
30
- trace.log("๐Ÿ” [nine-exception-hook] DOM์—์„œ ์–ธ๋งˆ์šดํŠธ๋จ. ๋ฆฌ์Šค๋„ˆ ํ•ด์ œ");
31
- window.removeEventListener('error', this.#handleRuntimeError, true);
32
- window.removeEventListener('unhandledrejection', this.#handlePromiseError, true);
33
- window.removeEventListener('popstate', this.#handleLocationChange);
34
- document.removeEventListener('click', this.#handleLocationChange, true);
19
+ componentDidCatch(error, errorInfo) {
20
+ console.error("๐Ÿšจ [Nine-Library] ๋ณธ๋ฌธ ๋ Œ๋”๋ง ์—๋Ÿฌ ํฌ์ฐฉ:", error);
35
21
 
36
- if (window.onerror === this.#handleRuntimeError || this.#oldOnError) {
37
- window.onerror = this.#oldOnError;
38
- trace.log("๐Ÿ” [nine-exception-hook] window.onerror ๋ณต๊ตฌ ์™„๋ฃŒ");
22
+ // 1. ์™ธ๋ถ€ ์ „์—ญ ๋ณต๊ตฌ ์—”์ง„(triggerAutoRecovery)์ด ์žˆ์œผ๋ฉด ํ˜ธ์ถœ
23
+ if (window.triggerAutoRecovery) {
24
+ window.triggerAutoRecovery(error.message || String(error));
39
25
  }
40
26
 
41
- // ํ™”๋ฉด ๋ฆฌ์…‹ ์‹œ ๋ฐ•ํ˜€์žˆ๋˜ ๋ฐ”๊นฅ์ชฝ ์—๋Ÿฌ ์ปจํ…Œ์ด๋„ˆ ์ œ๊ฑฐ
42
- this.#removeExternalOverlay();
43
- }
44
-
45
- #setupGlobalSniffer() {
46
- window.addEventListener('error', this.#handleRuntimeError, true);
47
- trace.log("๐Ÿ” [nine-exception-hook] window.addEventListener('error') ๋“ฑ๋ก ์™„๋ฃŒ");
48
-
49
- this.#oldOnError = window.onerror;
50
- window.onerror = (message, source, lineno, colno, error) => {
51
- trace.log("๐Ÿšจ [nine-exception-hook] ์›์‹œ window.onerror ํฌ์ฐฉ!!", { message, source, lineno, error });
52
-
53
- if (!this.#hasError) {
54
- trace.log("๐ŸŽฏ [nine-exception-hook] ํ˜„์žฌ ์—๋Ÿฌ ์ƒํƒœ ์—†์Œ -> ์—๋Ÿฌ ๋ณด๋“œ ์ถœ๋ ฅ ์‹œ๋„");
55
- const errorMessage = error?.message || message || "์•Œ ์ˆ˜ ์—†๋Š” ๋Ÿฐํƒ€์ž„ ์˜ˆ์™ธ";
56
- const errorStack = error?.stack || `${source}:${lineno}:${colno}`;
57
- this.#renderError(errorMessage, errorStack);
58
- } else {
59
- trace.log("โš ๏ธ [nine-exception-hook] ์ด๋ฏธ ์—๋Ÿฌ ํ™”๋ฉด์ด ํ™œ์„ฑํ™”๋˜์–ด ์žˆ์–ด ์›์‹œ onerror ํŒจ์Šค");
60
- }
61
-
62
- if (this.#oldOnError) {
63
- trace.log("๐Ÿ”„ [nine-exception-hook] ๊ธฐ์กด์— ๋“ฑ๋ก๋˜์–ด ์žˆ๋˜ ๋‹ค๋ฅธ onerror ์—”์ง„์œผ๋กœ ์œ„์ž„");
64
- return this.#oldOnError(message, source, lineno, colno, error);
65
- }
66
- return false;
67
- };
68
- trace.log("๐Ÿ” [nine-exception-hook] ์›์‹œ window.onerror ๊ฐ€๋กœ์ฑ„๊ธฐ(Chaining) ์™„๋ฃŒ");
69
- }
70
-
71
- #renderer = () => {
72
- const customImport = nine.cssPath ? `@import "${nine.cssPath}/nine-mu.css";` : "";
73
-
74
- this.shadowRoot.innerHTML = `
75
- <style>
76
- @import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-mu@${__APP_VERSION__}/dist/css/nine-mu.css";
77
- ${customImport}
78
- :host {
79
- display: block;
80
- width: 100%;
81
- height: 100%;
82
- }
83
- </style>
84
- <div class="nine-hook-core" style="width: 100%; height: 100%;">
85
- <slot></slot>
86
- </div>
87
- <div class="nine-exception-board"></div>
88
- `;
89
- }
90
-
91
- #injectShadowStylesheet() {
92
- if (this.shadowRoot.querySelector(`link[href="${this.#cssPath}"]`)) return;
93
-
94
- const link = document.createElement('link');
95
- link.rel = 'stylesheet';
96
- link.href = this.#cssPath;
97
- this.shadowRoot.appendChild(link);
98
- }
99
-
100
- #handleRuntimeError = (event) => {
101
- trace.log("๐Ÿšจ [nine-exception-hook] window.addEventListener('error') ๋ฆฌ์Šค๋„ˆ ํฌ์ฐฉ!!", event);
102
-
103
- if (this.#hasError) return;
104
-
105
- const errorMessage = event.error?.message || event.message || String(event);
106
- const errorStack = event.error?.stack || "No stack trace available";
107
-
108
- if (errorMessage && errorMessage !== "Script error.") {
109
- this.#renderError(errorMessage, errorStack);
27
+ // 2. ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ํ™•์žฅ์„ฑ: ์ปดํฌ๋„ŒํŠธ ์ž์ฒด Props๋กœ ์ฝœ๋ฐฑ์„ ๋„˜๊ฒจ๋ฐ›์•˜๋‹ค๋ฉด ์‹คํ–‰
28
+ if (this.props.onCatch) {
29
+ this.props.onCatch(error, errorInfo);
110
30
  }
111
31
  }
112
32
 
113
- #handlePromiseError = (event) => {
114
- trace.log("๐Ÿšจ [nine-exception-hook] unhandledrejection (Promise ์—๋Ÿฌ) ํฌ์ฐฉ!!", event);
115
-
116
- if (this.#hasError) return;
117
-
118
- const reason = event.reason;
119
- const errorMessage = reason?.message || String(reason || "Unhandled Promise Rejection");
120
- const errorStack = reason?.stack || "No stack trace available";
33
+ componentDidMount() {
34
+ window.addEventListener('popstate', this.handleLocationChange);
35
+ document.addEventListener('click', this.handleLocationChange, true);
36
+ }
121
37
 
122
- this.#renderError(errorMessage, errorStack);
38
+ componentWillUnmount() {
39
+ window.removeEventListener('popstate', this.handleLocationChange);
40
+ document.removeEventListener('click', this.handleLocationChange, true);
123
41
  }
124
42
 
125
- #handleLocationChange = () => {
43
+ handleLocationChange() {
126
44
  setTimeout(() => {
127
- if (this.#hasError && this.#lastPath !== window.location.pathname) {
128
- trace.log("โœจ [nine-exception-hook] Shadow DOM ๋ฐ ๊ธ€๋กœ๋ฒŒ ์˜ค๋ฒ„๋ ˆ์ด ๋‚ด๋ถ€ ์˜ˆ์™ธ ์ฒญ์†Œ ๋ฐ ์ •์ƒ ๋ณต๊ตฌ");
129
- this.#lastPath = window.location.pathname;
130
- this.#hasError = false;
131
-
132
- this.#removeExternalOverlay();
133
-
134
- const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
135
- if (coreContainer) coreContainer.style.display = '';
45
+ if (this.state.hasError && this.lastPath !== window.location.pathname) {
46
+ console.log("โœจ [Nine-Library] ํŽ˜์ด์ง€ ์ฃผ์†Œ ๋ณ€๊ฒฝ ๊ฐ์ง€ -> ๋ฆฌ์•กํŠธ ์—๋Ÿฌ ์ƒํƒœ ์ดˆ๊ธฐํ™”");
47
+ this.lastPath = window.location.pathname;
48
+ this.setState({ hasError: false, error: null });
136
49
  }
137
- }, 50);
138
- }
139
-
140
- #removeExternalOverlay() {
141
- const target = document.getElementById('nine-global-exception-container');
142
- if (target) target.remove();
50
+ }, 10);
143
51
  }
144
52
 
145
- #sendToAiAction = async (errorMessage, errorStack) => {
146
- // ๊ธ€๋กœ๋ฒŒ ์—˜๋ฆฌ๋จผํŠธ ๋‚ด์—์„œ ํƒ์ƒ‰ํ•˜๋„๋ก ๋ณ€๊ฒฝ
147
- const root = document.getElementById('nine-global-exception-container') || this.shadowRoot;
148
- const btn = root.querySelector('.nine-ai-btn');
149
- const footer = root.querySelector('.nine-error-footer');
150
- if (!btn) return;
151
-
152
- btn.disabled = true;
153
- btn.innerText = "โšก AI ๊ด€์ œํƒ‘์— ์†Œ์Šค ๋ถ„์„ ์š”์ฒญ ์ค‘...";
154
- btn.classList.add('loading');
155
-
156
- try {
157
- if (window.triggerAutoRecovery) {
158
- await window.triggerAutoRecovery({
159
- message: errorMessage,
160
- stack: errorStack || "No stack trace available",
161
- path: window.location.pathname
162
- });
163
-
164
- footer.innerHTML = `โœ… <b>AI ๊ด€์ œํƒ‘ ์ ‘์ˆ˜ ์™„๋ฃŒ:</b> ๋ถ„์„์„ ๋ฐ”ํƒ•์œผ๋กœ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ๊ต์ •ํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ž ์‹œ๋งŒ ๊ธฐ๋‹ค๋ ค์ฃผ์„ธ์š”.`;
165
- btn.innerText = "๐Ÿš€ ์ „์†ก ์™„๋ฃŒ";
166
- } else {
167
- throw new Error("window.triggerAutoRecovery ๊ด€์ œํƒ‘ ์—”์ง„์ด ๋กœ๋“œ๋˜์ง€ ์•Š์•˜์Šต๋‹ˆ๋‹ค.");
53
+ render() {
54
+ if (this.state.hasError) {
55
+ // ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ ์ปค์Šคํ…€ UI ์ œ๊ณต (์™ธ๋ถ€์—์„œ ์ปค์Šคํ…€ fallback UI๋ฅผ ์ฃผ์ž…ํ•˜์ง€ ์•Š์•˜๋‹ค๋ฉด ๊ธฐ๋ณธ ํ…œํ”Œ๋ฆฟ ์‚ฌ์šฉ)
56
+ if (this.props.fallback) {
57
+ return this.props.fallback(this.state.error);
168
58
  }
169
- } catch (err) {
170
- trace.error("โŒ AI ์ „์†ก ์‹คํŒจ:", err);
171
- btn.disabled = false;
172
- btn.innerText = "โŒ ์žฌ์ „์†ก ์‹œ๋„";
173
- footer.innerHTML = `<span style="color: #E53E3E;">โš ๏ธ ์ „์†ก ์‹คํŒจ: ${err.message}</span>`;
174
- }
175
- }
176
59
 
177
- #renderError(errorMessage, errorStack) {
178
- if (this.#hasError) return;
179
- this.#hasError = true;
180
-
181
- setTimeout(() => {
182
- trace.log("๐ŸŽจ [nine-exception-hook] ๋ฆฌ์•กํŠธ ์‚ฌ์ดํด ์ข…๋ฃŒ ํ›„ ์ตœ์ƒ๋‹จ ๊ธ€๋กœ๋ฒŒ ์—๋Ÿฌ ๋ ˆ์ด์–ด ์ƒ์„ฑ");
183
-
184
- const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
185
- if (coreContainer) coreContainer.style.display = 'none';
186
-
187
- // ๐ŸŽฏ [ํ•ต์‹ฌ ๋ณ€๊ฒฝ] Shadow DOM ๋‚ด๋ถ€๊ฐ€ ์•„๋‹ˆ๋ผ document.body์— ์ง์ ‘ fixed ์ปจํ…Œ์ด๋„ˆ๋ฅผ ๊ฝ‚์•„๋ฒ„๋ ค
188
- // global-loading-overlay๋ฅผ ์™„๋ฒฝํžˆ ๋ฎ์–ด๋ฒ„๋ฆฝ๋‹ˆ๋‹ค.
189
- this.#removeExternalOverlay();
190
-
191
- const externalContainer = document.createElement('div');
192
- externalContainer.id = 'nine-global-exception-container';
193
-
194
- // ์ธ๋ผ์ธ ์Šคํƒ€์ผ๋กœ ์™ธ๋ถ€ ์š”์†Œ๋ฅผ ์™„์ „ํžˆ ์ฐจ๋‹จํ•˜๊ณ  ๋งจ ์•ž์œผ๋กœ ๋ฐฐ์น˜
195
- Object.assign(externalContainer.style, {
196
- position: 'fixed',
197
- top: '0',
198
- left: '0',
199
- width: '100vw',
200
- height: '100vh',
201
- backgroundColor: '#FFF5F5',
202
- zIndex: '2147483647', // ๋ธŒ๋ผ์šฐ์ € ํ‘œํ˜„ ์ตœ๋Œ€ z-index ๊ฐ’ ๋ถ€์—ฌ
203
- overflow: 'auto',
204
- boxSizing: 'border-box',
205
- display: 'block'
206
- });
207
-
208
- const errorHTML = `
209
- <div class="nine-error-container" style="padding: 40px; max-width: 1200px; margin: 40px auto; font-family: sans-serif; background: white; border-radius: 8px; box-shadow: 0 10px 25px rgba(0,0,0,0.08); text-align: left;">
210
- <h3 class="nine-error-title" style="color: #C53030; margin-top: 0; font-size: 22px; font-weight: 700; border-bottom: 2px solid #FED2D2; padding-bottom: 12px; font-family: sans-serif;">โš ๏ธ ์‹œ์Šคํ…œ ์˜ˆ์™ธ ๊ฐ์ง€ (nine-exception-hook)</h3>
211
- <p class="nine-error-label" style="font-weight: bold; margin: 20px 0 8px 0; color: #4A5568; font-size: 15px; font-family: sans-serif;">[์—๋Ÿฌ ์›์ธ ๋กœ๊ทธ]:</p>
212
- <pre class="nine-error-log" style="background: #1A202C; color: #EDF2F7; padding: 20px; border-radius: 6px; overflow-x: auto; white-space: pre-wrap; font-family: monospace; font-size: 14px; line-height: 1.6; margin-bottom: 25px;">${errorMessage}\n\n[Stack Trace]\n${errorStack}</pre>
213
-
214
- <div class="nine-action-area" style="display: flex; align-items: center; gap: 20px; border-top: 1px solid #E2E8F0; padding-top: 20px;">
215
- <button class="nine-ai-btn" style="background: #3182CE; color: white; border: none; padding: 14px 28px; border-radius: 6px; font-weight: bold; cursor: pointer; font-size: 16px;">๐Ÿค– AI์—๊ฒŒ ์†Œ์Šค์ฝ”๋“œ ์ˆ˜์ • ์š”์ฒญ</button>
216
- <div class="nine-error-footer" style="font-size: 14px; color: #718096; line-height: 1.4; font-family: sans-serif;">
217
- ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด AI๊ฐ€ ๋กœ๊ทธ ๋ฐ ์ปดํฌ๋„ŒํŠธ ๋งต์„ ์—ญ์ถ”์ ํ•˜์—ฌ ์ˆ˜์ •์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
218
- </div>
60
+ return (
61
+ <div style={{ padding: '30px', margin: '20px', background: '#FFF5F5', border: '1px solid #FEB2B2', borderRadius: '8px', fontFamily: 'sans-serif', textAlign: 'left', ...this.props.containerStyle }}>
62
+ <h3 style={{ color: '#C53030', marginTop: 0, fontSize: '18px' }}>โš ๏ธ ์ปดํฌ๋„ŒํŠธ ๋นŒ๋“œ/๋ Œ๋”๋ง ์—๋Ÿฌ ๊ฐ์ง€</h3>
63
+ <p style={{ margin: '10px 0 5px 0', fontWeight: 'bold', color: '#4A5568' }}>[์—๋Ÿฌ ์›์ธ ๋กœ๊ทธ]:</p>
64
+ <pre style={{ background: '#1A202C', color: '#EDF2F7', padding: '15px', borderRadius: '6px', overflowX: 'auto', whiteSpace: 'pre-wrap', fontFamily: 'monospace' }}>
65
+ {this.state.error?.message || String(this.state.error)}
66
+ </pre>
67
+ <div style={{ marginTop: '15px', fontSize: '14px', color: '#718096' }}>
68
+ ๐Ÿ”„ ์—๋Ÿฌ ๋กœ๊ทธ๊ฐ€ ๊ด€์ œํƒ‘์œผ๋กœ ์ž๋™ ํ”ผ๋“œ๋ฐฑ๋˜์—ˆ์Šต๋‹ˆ๋‹ค. AI๊ฐ€ ์†Œ์Šค ์ฝ”๋“œ๋ฅผ ์žฌ์ˆ˜์ •ํ•˜๋Š” ๋™์•ˆ ์ž ์‹œ๋งŒ ๊ธฐ๋‹ค๋ ค์ฃผ์„ธ์š”...
219
69
  </div>
220
70
  </div>
221
- `;
222
-
223
- externalContainer.innerHTML = errorHTML;
224
- document.body.appendChild(externalContainer);
225
- trace.log("๐ŸŽจ [nine-exception-hook] ๋ธŒ๋ผ์šฐ์ € Body ์ตœ์ƒ๋‹จ ๋ ˆ์ด์–ด ๋ฐฐ์ • ์„ฑ๊ณต");
226
-
227
- const aiBtn = externalContainer.querySelector('.nine-ai-btn');
228
- if (aiBtn) {
229
- aiBtn.addEventListener('click', () => this.#sendToAiAction(errorMessage, errorStack));
230
- trace.log("๐ŸŽจ [nine-exception-hook] AI ์š”์ฒญ ๋ฒ„ํŠผ ์ด๋ฒคํŠธ ๋ฆฌ์Šค๋„ˆ ์ตœ์ข… ๋ฐ”์ธ๋”ฉ ์„ฑ๊ณต");
231
- }
232
- }, 0);
71
+ );
72
+ }
73
+ return this.props.children;
233
74
  }
234
75
  }
235
76
 
236
- if (!customElements.get('nine-exception-hook')) {
237
- customElements.define('nine-exception-hook', ExceptionHook);
238
- }
77
+ export default NineExceptionHook;
package/src/index.js CHANGED
@@ -4,7 +4,7 @@ import { NineDiff } from './components/NineDiff.js';
4
4
  import { NineDiffPopup } from './components/NineDiffPopup.js';
5
5
  import { NineMenuDiffPopup } from './components/NineMenuDiffPopup.js';
6
6
  import './components/ChatMessage.js';
7
- import './components/exception/ExceptionHook.js';
7
+ //import { NineExceptionHook } from './components/exception/ExceptionHook.js';
8
8
 
9
9
  /**
10
10
  * Nine-Mu ์—”์ง„ ๋ฉ”์ธ ํด๋ž˜์Šค