@nine-lab/nine-mu 0.1.342 โ 0.1.344
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/nine-mu.js +58 -51
- package/dist/nine-mu.js.map +1 -1
- package/dist/nine-mu.umd.js +3 -3
- package/dist/nine-mu.umd.js.map +1 -1
- package/package.json +1 -1
- package/src/components/exception/ExceptionHook.js +56 -47
package/package.json
CHANGED
|
@@ -37,6 +37,9 @@ export class ExceptionHook extends HTMLElement {
|
|
|
37
37
|
window.onerror = this.#oldOnError;
|
|
38
38
|
trace.log("๐ [nine-exception-hook] window.onerror ๋ณต๊ตฌ ์๋ฃ");
|
|
39
39
|
}
|
|
40
|
+
|
|
41
|
+
// ํ๋ฉด ๋ฆฌ์
์ ๋ฐํ์๋ ๋ฐ๊นฅ์ชฝ ์๋ฌ ์ปจํ
์ด๋ ์ ๊ฑฐ
|
|
42
|
+
this.#removeExternalOverlay();
|
|
40
43
|
}
|
|
41
44
|
|
|
42
45
|
#setupGlobalSniffer() {
|
|
@@ -72,9 +75,13 @@ export class ExceptionHook extends HTMLElement {
|
|
|
72
75
|
<style>
|
|
73
76
|
@import "https://cdn.jsdelivr.net/npm/@nine-lab/nine-mu@${__APP_VERSION__}/dist/css/nine-mu.css";
|
|
74
77
|
${customImport}
|
|
78
|
+
:host {
|
|
79
|
+
display: block;
|
|
80
|
+
width: 100%;
|
|
81
|
+
height: 100%;
|
|
82
|
+
}
|
|
75
83
|
</style>
|
|
76
|
-
|
|
77
|
-
<div class="nine-hook-core">
|
|
84
|
+
<div class="nine-hook-core" style="width: 100%; height: 100%;">
|
|
78
85
|
<slot></slot>
|
|
79
86
|
</div>
|
|
80
87
|
<div class="nine-exception-board"></div>
|
|
@@ -93,19 +100,13 @@ export class ExceptionHook extends HTMLElement {
|
|
|
93
100
|
#handleRuntimeError = (event) => {
|
|
94
101
|
trace.log("๐จ [nine-exception-hook] window.addEventListener('error') ๋ฆฌ์ค๋ ํฌ์ฐฉ!!", event);
|
|
95
102
|
|
|
96
|
-
if (this.#hasError)
|
|
97
|
-
trace.log("โ ๏ธ [nine-exception-hook] ์ด๋ฏธ ์๋ฌ ํ๋ฉด์ด ํ์ฑํ๋์ด ์์ด ์ด๋ฒคํธ ๋ฆฌ์ค๋ ํจ์ค");
|
|
98
|
-
return;
|
|
99
|
-
}
|
|
103
|
+
if (this.#hasError) return;
|
|
100
104
|
|
|
101
105
|
const errorMessage = event.error?.message || event.message || String(event);
|
|
102
106
|
const errorStack = event.error?.stack || "No stack trace available";
|
|
103
107
|
|
|
104
108
|
if (errorMessage && errorMessage !== "Script error.") {
|
|
105
|
-
trace.log("๐ฏ [nine-exception-hook] ์ ์์ ์ธ ์๋ฌ ๋ฉ์์ง ํ์ธ -> ์๋ฌ ๋ณด๋ ์ถ๋ ฅ ์๋", { errorMessage });
|
|
106
109
|
this.#renderError(errorMessage, errorStack);
|
|
107
|
-
} else {
|
|
108
|
-
trace.log("โ ๏ธ [nine-exception-hook] 'Script error.' ์ด๊ฑฐ๋ ๋น ๋ฉ์์ง๋ผ ๋ฌด์๋จ");
|
|
109
110
|
}
|
|
110
111
|
}
|
|
111
112
|
|
|
@@ -118,36 +119,34 @@ export class ExceptionHook extends HTMLElement {
|
|
|
118
119
|
const errorMessage = reason?.message || String(reason || "Unhandled Promise Rejection");
|
|
119
120
|
const errorStack = reason?.stack || "No stack trace available";
|
|
120
121
|
|
|
121
|
-
trace.log("๐ฏ [nine-exception-hook] Promise ๊ฑฐ๋ถ ํ์ธ -> ์๋ฌ ๋ณด๋ ์ถ๋ ฅ ์๋");
|
|
122
122
|
this.#renderError(errorMessage, errorStack);
|
|
123
123
|
}
|
|
124
124
|
|
|
125
125
|
#handleLocationChange = () => {
|
|
126
126
|
setTimeout(() => {
|
|
127
|
-
trace.log("๐ [nine-exception-hook] ์ฃผ์ ์ด๋ ๊ฐ์ง ์ฒดํฌ", {
|
|
128
|
-
hasError: this.#hasError,
|
|
129
|
-
lastPath: this.#lastPath,
|
|
130
|
-
currentPath: window.location.pathname
|
|
131
|
-
});
|
|
132
|
-
|
|
133
127
|
if (this.#hasError && this.#lastPath !== window.location.pathname) {
|
|
134
|
-
trace.log("โจ [nine-exception-hook] Shadow DOM ๋ด๋ถ ์์ธ ์ฒญ์ ๋ฐ ์ ์ ๋ณต๊ตฌ");
|
|
128
|
+
trace.log("โจ [nine-exception-hook] Shadow DOM ๋ฐ ๊ธ๋ก๋ฒ ์ค๋ฒ๋ ์ด ๋ด๋ถ ์์ธ ์ฒญ์ ๋ฐ ์ ์ ๋ณต๊ตฌ");
|
|
135
129
|
this.#lastPath = window.location.pathname;
|
|
136
130
|
this.#hasError = false;
|
|
137
131
|
|
|
138
|
-
|
|
139
|
-
if (exceptionBoard) exceptionBoard.innerHTML = '';
|
|
132
|
+
this.#removeExternalOverlay();
|
|
140
133
|
|
|
141
134
|
const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
|
|
142
135
|
if (coreContainer) coreContainer.style.display = '';
|
|
143
136
|
}
|
|
144
|
-
},
|
|
137
|
+
}, 50);
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
#removeExternalOverlay() {
|
|
141
|
+
const target = document.getElementById('nine-global-exception-container');
|
|
142
|
+
if (target) target.remove();
|
|
145
143
|
}
|
|
146
144
|
|
|
147
145
|
#sendToAiAction = async (errorMessage, errorStack) => {
|
|
148
|
-
|
|
149
|
-
const
|
|
150
|
-
const
|
|
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');
|
|
151
150
|
if (!btn) return;
|
|
152
151
|
|
|
153
152
|
btn.disabled = true;
|
|
@@ -156,7 +155,6 @@ export class ExceptionHook extends HTMLElement {
|
|
|
156
155
|
|
|
157
156
|
try {
|
|
158
157
|
if (window.triggerAutoRecovery) {
|
|
159
|
-
trace.log("๐ก [nine-exception-hook] window.triggerAutoRecovery ํธ์ถ ์คํ");
|
|
160
158
|
await window.triggerAutoRecovery({
|
|
161
159
|
message: errorMessage,
|
|
162
160
|
stack: errorStack || "No stack trace available",
|
|
@@ -180,42 +178,53 @@ export class ExceptionHook extends HTMLElement {
|
|
|
180
178
|
if (this.#hasError) return;
|
|
181
179
|
this.#hasError = true;
|
|
182
180
|
|
|
183
|
-
// ๐ฏ [ํต์ฌ] ๋ฆฌ์กํธ๊ฐ ์๋ฌ ๋ฐ์ ํ ํ์ DOM์ Unmount/์กฐ์ํ๋ ๋๊ธฐ์ ์ธ ํ์ด๋ฐ์
|
|
184
|
-
// ์์ ํ ํ๋ ค๋ณด๋ธ ๋ค(setTimeout 0)์ ์์ ํ๊ฒ Web Component UI๋ฅผ ๊ฝ์ ๋ฃ์ต๋๋ค.
|
|
185
181
|
setTimeout(() => {
|
|
186
|
-
trace.log("๐จ [nine-exception-hook] ๋ฆฌ์กํธ ์ฌ์ดํด ์ข
๋ฃ ํ ์๋ฌ
|
|
182
|
+
trace.log("๐จ [nine-exception-hook] ๋ฆฌ์กํธ ์ฌ์ดํด ์ข
๋ฃ ํ ์ต์๋จ ๊ธ๋ก๋ฒ ์๋ฌ ๋ ์ด์ด ์์ฑ");
|
|
187
183
|
|
|
188
184
|
const coreContainer = this.shadowRoot.querySelector('.nine-hook-core');
|
|
189
|
-
if (coreContainer)
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
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
|
+
});
|
|
199
207
|
|
|
200
208
|
const errorHTML = `
|
|
201
|
-
<div class="nine-error-container">
|
|
202
|
-
<h3 class="nine-error-title">โ ๏ธ ์์คํ
์์ธ ๊ฐ์ง (
|
|
203
|
-
<p class="nine-error-label">[์๋ฌ ์์ธ ๋ก๊ทธ]:</p>
|
|
204
|
-
<pre class="nine-error-log">${errorMessage}</pre>
|
|
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>
|
|
205
213
|
|
|
206
|
-
<div class="nine-action-area" style="
|
|
207
|
-
<button class="nine-ai-btn">๐ค AI์๊ฒ ์์ค์ฝ๋ ์์ ์์ฒญ</button>
|
|
208
|
-
<div class="nine-error-footer">
|
|
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;">
|
|
209
217
|
๋ฒํผ์ ๋๋ฅด๋ฉด AI๊ฐ ๋ก๊ทธ ๋ฐ ์ปดํฌ๋ํธ ๋งต์ ์ญ์ถ์ ํ์ฌ ์์ ์ ์์ํฉ๋๋ค.
|
|
210
218
|
</div>
|
|
211
219
|
</div>
|
|
212
220
|
</div>
|
|
213
221
|
`;
|
|
214
222
|
|
|
215
|
-
|
|
216
|
-
|
|
223
|
+
externalContainer.innerHTML = errorHTML;
|
|
224
|
+
document.body.appendChild(externalContainer);
|
|
225
|
+
trace.log("๐จ [nine-exception-hook] ๋ธ๋ผ์ฐ์ Body ์ต์๋จ ๋ ์ด์ด ๋ฐฐ์ ์ฑ๊ณต");
|
|
217
226
|
|
|
218
|
-
const aiBtn =
|
|
227
|
+
const aiBtn = externalContainer.querySelector('.nine-ai-btn');
|
|
219
228
|
if (aiBtn) {
|
|
220
229
|
aiBtn.addEventListener('click', () => this.#sendToAiAction(errorMessage, errorStack));
|
|
221
230
|
trace.log("๐จ [nine-exception-hook] AI ์์ฒญ ๋ฒํผ ์ด๋ฒคํธ ๋ฆฌ์ค๋ ์ต์ข
๋ฐ์ธ๋ฉ ์ฑ๊ณต");
|