@stacksjs/error-handling 0.70.45 → 0.70.54
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/LICENSE.md +21 -0
- package/dist/src/error-page-styles.d.ts +624 -0
- package/dist/src/error-page.d.ts +12 -145
- package/dist/src/http.d.ts +10 -10
- package/package.json +9 -7
- package/dist/index.js +0 -417
package/LICENSE.md
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
# MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2023 Open Web Foundation
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
|
@@ -0,0 +1,624 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Laravel-style error page styles (v12.29+ local debug page).
|
|
3
|
+
* Inline CSS — no external dependencies.
|
|
4
|
+
*/
|
|
5
|
+
export declare const ERROR_PAGE_CSS: `
|
|
6
|
+
:root {
|
|
7
|
+
--font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
|
|
8
|
+
--font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
|
|
9
|
+
--neutral-50: #fafafa;
|
|
10
|
+
--neutral-100: #f5f5f5;
|
|
11
|
+
--neutral-200: #e5e5e5;
|
|
12
|
+
--neutral-300: #d4d4d4;
|
|
13
|
+
--neutral-400: #a3a3a3;
|
|
14
|
+
--neutral-500: #737373;
|
|
15
|
+
--neutral-600: #525252;
|
|
16
|
+
--neutral-700: #404040;
|
|
17
|
+
--neutral-800: #262626;
|
|
18
|
+
--neutral-900: #171717;
|
|
19
|
+
--neutral-950: #0a0a0a;
|
|
20
|
+
--rose-100: #ffe4e6;
|
|
21
|
+
--rose-200: #fecdd3;
|
|
22
|
+
--rose-500: #f43f5e;
|
|
23
|
+
--rose-600: #e11d48;
|
|
24
|
+
--rose-900: #881337;
|
|
25
|
+
--rose-950: #4c0519;
|
|
26
|
+
--blue-100: #dbeafe;
|
|
27
|
+
--blue-500: #3b82f6;
|
|
28
|
+
--blue-600: #2563eb;
|
|
29
|
+
--blue-700: #1d4ed8;
|
|
30
|
+
--blue-900: #1e3a8a;
|
|
31
|
+
--emerald-500: #10b981;
|
|
32
|
+
--amber-200: #fde68a;
|
|
33
|
+
--amber-600: #d97706;
|
|
34
|
+
--amber-900: #78350f;
|
|
35
|
+
--white: #fff;
|
|
36
|
+
--radius-md: 0.375rem;
|
|
37
|
+
--radius-lg: 0.5rem;
|
|
38
|
+
--radius-xl: 0.75rem;
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
42
|
+
|
|
43
|
+
html {
|
|
44
|
+
-webkit-text-size-adjust: 100%;
|
|
45
|
+
color-scheme: light dark;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
body {
|
|
49
|
+
font-family: var(--font-sans);
|
|
50
|
+
-webkit-font-smoothing: antialiased;
|
|
51
|
+
-moz-osx-font-smoothing: grayscale;
|
|
52
|
+
background: var(--neutral-50);
|
|
53
|
+
color: var(--neutral-950);
|
|
54
|
+
line-height: 1.5;
|
|
55
|
+
min-height: 100dvh;
|
|
56
|
+
}
|
|
57
|
+
|
|
58
|
+
@media (prefers-color-scheme: dark) {
|
|
59
|
+
body {
|
|
60
|
+
background: var(--neutral-900);
|
|
61
|
+
color: var(--white);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
.page {
|
|
66
|
+
max-width: 80rem;
|
|
67
|
+
margin: 0 auto;
|
|
68
|
+
padding: 3.5rem 1.5rem 2rem;
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
@media (min-width: 640px) {
|
|
72
|
+
.page { padding: 4rem 3.5rem 2rem; }
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
/* ── Header ── */
|
|
76
|
+
.header {
|
|
77
|
+
display: flex;
|
|
78
|
+
align-items: center;
|
|
79
|
+
justify-content: space-between;
|
|
80
|
+
gap: 1rem;
|
|
81
|
+
margin-bottom: 2rem;
|
|
82
|
+
flex-wrap: wrap;
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
.header-title {
|
|
86
|
+
display: flex;
|
|
87
|
+
align-items: center;
|
|
88
|
+
gap: 0.625rem;
|
|
89
|
+
font-size: 0.875rem;
|
|
90
|
+
font-weight: 500;
|
|
91
|
+
color: var(--neutral-600);
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@media (prefers-color-scheme: dark) {
|
|
95
|
+
.header-title { color: var(--neutral-400); }
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
.header-dot {
|
|
99
|
+
width: 0.625rem;
|
|
100
|
+
height: 0.625rem;
|
|
101
|
+
border-radius: 9999px;
|
|
102
|
+
background: var(--rose-500);
|
|
103
|
+
flex-shrink: 0;
|
|
104
|
+
}
|
|
105
|
+
|
|
106
|
+
.btn-copy {
|
|
107
|
+
display: inline-flex;
|
|
108
|
+
align-items: center;
|
|
109
|
+
gap: 0.375rem;
|
|
110
|
+
padding: 0.375rem 0.75rem;
|
|
111
|
+
font-size: 0.75rem;
|
|
112
|
+
font-weight: 500;
|
|
113
|
+
border: 1px solid var(--neutral-200);
|
|
114
|
+
border-radius: var(--radius-md);
|
|
115
|
+
background: var(--white);
|
|
116
|
+
color: var(--neutral-700);
|
|
117
|
+
cursor: pointer;
|
|
118
|
+
transition: background 0.15s, border-color 0.15s;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.btn-copy:hover { background: var(--neutral-100); }
|
|
122
|
+
.btn-copy.copied { border-color: var(--emerald-500); color: var(--emerald-500); }
|
|
123
|
+
|
|
124
|
+
@media (prefers-color-scheme: dark) {
|
|
125
|
+
.btn-copy {
|
|
126
|
+
background: var(--neutral-800);
|
|
127
|
+
border-color: rgba(255,255,255,0.1);
|
|
128
|
+
color: var(--neutral-200);
|
|
129
|
+
}
|
|
130
|
+
.btn-copy:hover { background: rgba(255,255,255,0.05); }
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
/* ── Error summary card ── */
|
|
134
|
+
.summary {
|
|
135
|
+
margin-bottom: 2rem;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
.summary h1 {
|
|
139
|
+
font-size: 1.875rem;
|
|
140
|
+
font-weight: 600;
|
|
141
|
+
line-height: 1.2;
|
|
142
|
+
margin-bottom: 0.75rem;
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
.summary-file {
|
|
146
|
+
font-family: var(--font-mono);
|
|
147
|
+
font-size: 0.875rem;
|
|
148
|
+
color: var(--rose-600);
|
|
149
|
+
margin-bottom: 0.75rem;
|
|
150
|
+
word-break: break-all;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
@media (prefers-color-scheme: dark) {
|
|
154
|
+
.summary-file { color: var(--rose-500); }
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.summary-message {
|
|
158
|
+
font-size: 1.125rem;
|
|
159
|
+
color: var(--neutral-800);
|
|
160
|
+
margin-bottom: 1.25rem;
|
|
161
|
+
word-break: break-word;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
@media (prefers-color-scheme: dark) {
|
|
165
|
+
.summary-message { color: var(--neutral-200); }
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
.badges {
|
|
169
|
+
display: flex;
|
|
170
|
+
flex-wrap: wrap;
|
|
171
|
+
gap: 0.5rem;
|
|
172
|
+
margin-bottom: 1.25rem;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
.badge {
|
|
176
|
+
display: inline-flex;
|
|
177
|
+
align-items: center;
|
|
178
|
+
padding: 0.25rem 0.5rem;
|
|
179
|
+
font-size: 0.6875rem;
|
|
180
|
+
font-weight: 600;
|
|
181
|
+
letter-spacing: 0.04em;
|
|
182
|
+
text-transform: uppercase;
|
|
183
|
+
border-radius: var(--radius-md);
|
|
184
|
+
border: 1px solid var(--neutral-200);
|
|
185
|
+
background: var(--neutral-100);
|
|
186
|
+
color: var(--neutral-600);
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
@media (prefers-color-scheme: dark) {
|
|
190
|
+
.badge {
|
|
191
|
+
border-color: rgba(255,255,255,0.1);
|
|
192
|
+
background: rgba(255,255,255,0.05);
|
|
193
|
+
color: var(--neutral-400);
|
|
194
|
+
}
|
|
195
|
+
}
|
|
196
|
+
|
|
197
|
+
.badge-status {
|
|
198
|
+
background: var(--rose-100);
|
|
199
|
+
border-color: var(--rose-200);
|
|
200
|
+
color: var(--rose-900);
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
@media (prefers-color-scheme: dark) {
|
|
204
|
+
.badge-status {
|
|
205
|
+
background: var(--rose-950);
|
|
206
|
+
border-color: var(--rose-900);
|
|
207
|
+
color: var(--rose-100);
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
.request-row {
|
|
212
|
+
display: flex;
|
|
213
|
+
align-items: center;
|
|
214
|
+
gap: 0.75rem;
|
|
215
|
+
flex-wrap: wrap;
|
|
216
|
+
font-size: 0.875rem;
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
.badge-method {
|
|
220
|
+
background: var(--blue-100);
|
|
221
|
+
border-color: transparent;
|
|
222
|
+
color: var(--blue-900);
|
|
223
|
+
font-family: var(--font-mono);
|
|
224
|
+
font-size: 0.6875rem;
|
|
225
|
+
}
|
|
226
|
+
|
|
227
|
+
@media (prefers-color-scheme: dark) {
|
|
228
|
+
.badge-method {
|
|
229
|
+
background: var(--blue-700);
|
|
230
|
+
color: var(--white);
|
|
231
|
+
}
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
.request-url {
|
|
235
|
+
font-family: var(--font-mono);
|
|
236
|
+
font-size: 0.8125rem;
|
|
237
|
+
color: var(--neutral-500);
|
|
238
|
+
word-break: break-all;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
@media (prefers-color-scheme: dark) {
|
|
242
|
+
.request-url { color: var(--neutral-400); }
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
/* ── Hints ── */
|
|
246
|
+
.hints {
|
|
247
|
+
border: 1px solid var(--amber-200);
|
|
248
|
+
border-radius: var(--radius-lg);
|
|
249
|
+
background: #fffbeb;
|
|
250
|
+
margin-bottom: 2rem;
|
|
251
|
+
overflow: hidden;
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
@media (prefers-color-scheme: dark) {
|
|
255
|
+
.hints {
|
|
256
|
+
border-color: var(--amber-600);
|
|
257
|
+
background: rgba(120, 53, 15, 0.3);
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
.hints-header {
|
|
262
|
+
padding: 0.75rem 1rem;
|
|
263
|
+
font-size: 0.8125rem;
|
|
264
|
+
font-weight: 600;
|
|
265
|
+
color: var(--amber-900);
|
|
266
|
+
border-bottom: 1px solid var(--amber-200);
|
|
267
|
+
}
|
|
268
|
+
|
|
269
|
+
@media (prefers-color-scheme: dark) {
|
|
270
|
+
.hints-header { color: var(--amber-200); border-bottom-color: rgba(217,119,6,0.3); }
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
.hints-body {
|
|
274
|
+
padding: 1rem;
|
|
275
|
+
font-size: 0.875rem;
|
|
276
|
+
color: var(--neutral-700);
|
|
277
|
+
}
|
|
278
|
+
|
|
279
|
+
@media (prefers-color-scheme: dark) {
|
|
280
|
+
.hints-body { color: var(--neutral-300); }
|
|
281
|
+
}
|
|
282
|
+
|
|
283
|
+
.hints-body ul { margin: 0 0 0.75rem 1.25rem; }
|
|
284
|
+
.hints-body li { margin: 0.2rem 0; }
|
|
285
|
+
.hints-suggestion { font-weight: 500; margin-bottom: 0.5rem; }
|
|
286
|
+
.hints-doc { color: var(--blue-600); text-decoration: none; font-size: 0.8125rem; }
|
|
287
|
+
.hints-doc:hover { text-decoration: underline; }
|
|
288
|
+
|
|
289
|
+
/* ── Exception trace ── */
|
|
290
|
+
.trace {
|
|
291
|
+
margin-bottom: 2rem;
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
.trace-title {
|
|
295
|
+
font-size: 0.875rem;
|
|
296
|
+
font-weight: 600;
|
|
297
|
+
color: var(--neutral-500);
|
|
298
|
+
text-transform: uppercase;
|
|
299
|
+
letter-spacing: 0.05em;
|
|
300
|
+
margin-bottom: 1rem;
|
|
301
|
+
}
|
|
302
|
+
|
|
303
|
+
@media (prefers-color-scheme: dark) {
|
|
304
|
+
.trace-title { color: var(--neutral-400); }
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
.trace-frame {
|
|
308
|
+
border: 1px solid var(--neutral-200);
|
|
309
|
+
border-radius: var(--radius-lg);
|
|
310
|
+
margin-bottom: 0.5rem;
|
|
311
|
+
overflow: hidden;
|
|
312
|
+
background: var(--white);
|
|
313
|
+
}
|
|
314
|
+
|
|
315
|
+
@media (prefers-color-scheme: dark) {
|
|
316
|
+
.trace-frame {
|
|
317
|
+
border-color: rgba(255,255,255,0.1);
|
|
318
|
+
background: rgba(255,255,255,0.02);
|
|
319
|
+
}
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
.trace-frame-header {
|
|
323
|
+
display: flex;
|
|
324
|
+
align-items: baseline;
|
|
325
|
+
gap: 0.5rem;
|
|
326
|
+
padding: 0.75rem 1rem;
|
|
327
|
+
cursor: pointer;
|
|
328
|
+
font-size: 0.8125rem;
|
|
329
|
+
transition: background 0.15s;
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
.trace-frame-header:hover { background: var(--neutral-50); }
|
|
333
|
+
|
|
334
|
+
@media (prefers-color-scheme: dark) {
|
|
335
|
+
.trace-frame-header:hover { background: rgba(255,255,255,0.03); }
|
|
336
|
+
}
|
|
337
|
+
|
|
338
|
+
.trace-frame-fn {
|
|
339
|
+
font-family: var(--font-mono);
|
|
340
|
+
color: var(--neutral-800);
|
|
341
|
+
flex: 1;
|
|
342
|
+
min-width: 0;
|
|
343
|
+
overflow: hidden;
|
|
344
|
+
text-overflow: ellipsis;
|
|
345
|
+
white-space: nowrap;
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
@media (prefers-color-scheme: dark) {
|
|
349
|
+
.trace-frame-fn { color: var(--neutral-200); }
|
|
350
|
+
}
|
|
351
|
+
|
|
352
|
+
.trace-frame-file {
|
|
353
|
+
font-family: var(--font-mono);
|
|
354
|
+
font-size: 0.75rem;
|
|
355
|
+
color: var(--neutral-400);
|
|
356
|
+
flex-shrink: 0;
|
|
357
|
+
}
|
|
358
|
+
|
|
359
|
+
.trace-frame-body {
|
|
360
|
+
display: none;
|
|
361
|
+
border-top: 1px solid var(--neutral-200);
|
|
362
|
+
}
|
|
363
|
+
|
|
364
|
+
.trace-frame.expanded .trace-frame-body { display: block; }
|
|
365
|
+
|
|
366
|
+
@media (prefers-color-scheme: dark) {
|
|
367
|
+
.trace-frame-body { border-top-color: rgba(255,255,255,0.08); }
|
|
368
|
+
}
|
|
369
|
+
|
|
370
|
+
.trace-vendor {
|
|
371
|
+
border: 1px dashed var(--neutral-300);
|
|
372
|
+
border-radius: var(--radius-lg);
|
|
373
|
+
margin-bottom: 0.5rem;
|
|
374
|
+
overflow: hidden;
|
|
375
|
+
}
|
|
376
|
+
|
|
377
|
+
@media (prefers-color-scheme: dark) {
|
|
378
|
+
.trace-vendor { border-color: rgba(255,255,255,0.15); }
|
|
379
|
+
}
|
|
380
|
+
|
|
381
|
+
.trace-vendor-toggle {
|
|
382
|
+
display: flex;
|
|
383
|
+
align-items: center;
|
|
384
|
+
gap: 0.5rem;
|
|
385
|
+
padding: 0.75rem 1rem;
|
|
386
|
+
font-size: 0.8125rem;
|
|
387
|
+
font-weight: 500;
|
|
388
|
+
color: var(--neutral-500);
|
|
389
|
+
cursor: pointer;
|
|
390
|
+
background: var(--neutral-50);
|
|
391
|
+
transition: background 0.15s;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
.trace-vendor-toggle:hover { background: var(--neutral-100); }
|
|
395
|
+
|
|
396
|
+
@media (prefers-color-scheme: dark) {
|
|
397
|
+
.trace-vendor-toggle {
|
|
398
|
+
background: rgba(255,255,255,0.03);
|
|
399
|
+
color: var(--neutral-400);
|
|
400
|
+
}
|
|
401
|
+
.trace-vendor-toggle:hover { background: rgba(255,255,255,0.05); }
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
.trace-vendor-frames { display: none; padding: 0.25rem 0; }
|
|
405
|
+
.trace-vendor.expanded .trace-vendor-frames { display: block; }
|
|
406
|
+
|
|
407
|
+
/* ── Code snippet ── */
|
|
408
|
+
.code-block {
|
|
409
|
+
overflow-x: auto;
|
|
410
|
+
font-family: var(--font-mono);
|
|
411
|
+
font-size: 0.8125rem;
|
|
412
|
+
line-height: 1.6;
|
|
413
|
+
background: var(--neutral-950);
|
|
414
|
+
color: #abb2bf;
|
|
415
|
+
}
|
|
416
|
+
|
|
417
|
+
.code-line {
|
|
418
|
+
display: flex;
|
|
419
|
+
min-height: 1.5rem;
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
.code-line:nth-child(odd) { background: rgba(255,255,255,0.02); }
|
|
423
|
+
.code-line:nth-child(even) { background: rgba(255,255,255,0.04); }
|
|
424
|
+
|
|
425
|
+
.code-line.highlight {
|
|
426
|
+
background: rgba(244, 63, 94, 0.25) !important;
|
|
427
|
+
}
|
|
428
|
+
|
|
429
|
+
.code-ln {
|
|
430
|
+
width: 3.5rem;
|
|
431
|
+
text-align: right;
|
|
432
|
+
padding: 0 1rem 0 0.5rem;
|
|
433
|
+
color: var(--neutral-500);
|
|
434
|
+
user-select: none;
|
|
435
|
+
flex-shrink: 0;
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
.code-line.highlight .code-ln { color: var(--rose-500); }
|
|
439
|
+
|
|
440
|
+
.code-txt {
|
|
441
|
+
flex: 1;
|
|
442
|
+
padding-right: 1rem;
|
|
443
|
+
white-space: pre;
|
|
444
|
+
}
|
|
445
|
+
|
|
446
|
+
/* ── Context panels ── */
|
|
447
|
+
.context {
|
|
448
|
+
margin-bottom: 2rem;
|
|
449
|
+
}
|
|
450
|
+
|
|
451
|
+
.context-tabs {
|
|
452
|
+
display: flex;
|
|
453
|
+
gap: 0;
|
|
454
|
+
border-bottom: 2px solid var(--neutral-200);
|
|
455
|
+
overflow-x: auto;
|
|
456
|
+
}
|
|
457
|
+
|
|
458
|
+
@media (prefers-color-scheme: dark) {
|
|
459
|
+
.context-tabs { border-bottom-color: rgba(255,255,255,0.1); }
|
|
460
|
+
}
|
|
461
|
+
|
|
462
|
+
.context-tab {
|
|
463
|
+
padding: 0.625rem 1rem;
|
|
464
|
+
font-size: 0.8125rem;
|
|
465
|
+
font-weight: 500;
|
|
466
|
+
color: var(--neutral-500);
|
|
467
|
+
background: none;
|
|
468
|
+
border: none;
|
|
469
|
+
border-bottom: 2px solid transparent;
|
|
470
|
+
margin-bottom: -2px;
|
|
471
|
+
cursor: pointer;
|
|
472
|
+
white-space: nowrap;
|
|
473
|
+
transition: color 0.15s;
|
|
474
|
+
}
|
|
475
|
+
|
|
476
|
+
.context-tab:hover { color: var(--neutral-800); }
|
|
477
|
+
.context-tab.active {
|
|
478
|
+
color: var(--rose-600);
|
|
479
|
+
border-bottom-color: var(--rose-500);
|
|
480
|
+
}
|
|
481
|
+
|
|
482
|
+
@media (prefers-color-scheme: dark) {
|
|
483
|
+
.context-tab:hover { color: var(--neutral-200); }
|
|
484
|
+
.context-tab.active { color: var(--rose-500); }
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
.context-panel {
|
|
488
|
+
display: none;
|
|
489
|
+
padding: 1.25rem 0;
|
|
490
|
+
}
|
|
491
|
+
|
|
492
|
+
.context-panel.active { display: block; }
|
|
493
|
+
|
|
494
|
+
.kv-table {
|
|
495
|
+
width: 100%;
|
|
496
|
+
border-collapse: collapse;
|
|
497
|
+
font-size: 0.8125rem;
|
|
498
|
+
}
|
|
499
|
+
|
|
500
|
+
.kv-table tr {
|
|
501
|
+
border-bottom: 1px solid var(--neutral-100);
|
|
502
|
+
}
|
|
503
|
+
|
|
504
|
+
@media (prefers-color-scheme: dark) {
|
|
505
|
+
.kv-table tr { border-bottom-color: rgba(255,255,255,0.05); }
|
|
506
|
+
}
|
|
507
|
+
|
|
508
|
+
.kv-table td {
|
|
509
|
+
padding: 0.5rem 0.75rem;
|
|
510
|
+
vertical-align: top;
|
|
511
|
+
}
|
|
512
|
+
|
|
513
|
+
.kv-table td:first-child {
|
|
514
|
+
font-weight: 500;
|
|
515
|
+
color: var(--neutral-500);
|
|
516
|
+
width: 30%;
|
|
517
|
+
font-family: var(--font-mono);
|
|
518
|
+
font-size: 0.75rem;
|
|
519
|
+
word-break: break-all;
|
|
520
|
+
}
|
|
521
|
+
|
|
522
|
+
@media (prefers-color-scheme: dark) {
|
|
523
|
+
.kv-table td:first-child { color: var(--neutral-400); }
|
|
524
|
+
}
|
|
525
|
+
|
|
526
|
+
.kv-table td:last-child {
|
|
527
|
+
font-family: var(--font-mono);
|
|
528
|
+
font-size: 0.75rem;
|
|
529
|
+
word-break: break-all;
|
|
530
|
+
color: var(--neutral-800);
|
|
531
|
+
}
|
|
532
|
+
|
|
533
|
+
@media (prefers-color-scheme: dark) {
|
|
534
|
+
.kv-table td:last-child { color: var(--neutral-200); }
|
|
535
|
+
}
|
|
536
|
+
|
|
537
|
+
.query-item {
|
|
538
|
+
padding: 0.75rem 1rem;
|
|
539
|
+
margin-bottom: 0.5rem;
|
|
540
|
+
border: 1px solid var(--neutral-200);
|
|
541
|
+
border-radius: var(--radius-md);
|
|
542
|
+
font-family: var(--font-mono);
|
|
543
|
+
font-size: 0.75rem;
|
|
544
|
+
background: var(--neutral-50);
|
|
545
|
+
}
|
|
546
|
+
|
|
547
|
+
@media (prefers-color-scheme: dark) {
|
|
548
|
+
.query-item {
|
|
549
|
+
border-color: rgba(255,255,255,0.08);
|
|
550
|
+
background: rgba(255,255,255,0.03);
|
|
551
|
+
}
|
|
552
|
+
}
|
|
553
|
+
|
|
554
|
+
.query-time {
|
|
555
|
+
margin-top: 0.375rem;
|
|
556
|
+
font-size: 0.6875rem;
|
|
557
|
+
color: var(--neutral-400);
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
.json-block {
|
|
561
|
+
font-family: var(--font-mono);
|
|
562
|
+
font-size: 0.75rem;
|
|
563
|
+
background: var(--neutral-100);
|
|
564
|
+
border-radius: var(--radius-md);
|
|
565
|
+
padding: 1rem;
|
|
566
|
+
overflow-x: auto;
|
|
567
|
+
white-space: pre-wrap;
|
|
568
|
+
word-break: break-all;
|
|
569
|
+
}
|
|
570
|
+
|
|
571
|
+
@media (prefers-color-scheme: dark) {
|
|
572
|
+
.json-block {
|
|
573
|
+
background: rgba(255,255,255,0.05);
|
|
574
|
+
color: var(--neutral-200);
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
|
|
578
|
+
/* ── Production page ── */
|
|
579
|
+
.production-page {
|
|
580
|
+
display: flex;
|
|
581
|
+
flex-direction: column;
|
|
582
|
+
align-items: center;
|
|
583
|
+
justify-content: center;
|
|
584
|
+
min-height: 100dvh;
|
|
585
|
+
text-align: center;
|
|
586
|
+
padding: 2rem;
|
|
587
|
+
}
|
|
588
|
+
|
|
589
|
+
.production-status {
|
|
590
|
+
font-size: 6rem;
|
|
591
|
+
font-weight: 700;
|
|
592
|
+
color: var(--neutral-200);
|
|
593
|
+
margin-bottom: 1rem;
|
|
594
|
+
line-height: 1;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
@media (prefers-color-scheme: dark) {
|
|
598
|
+
.production-status { color: var(--neutral-700); }
|
|
599
|
+
}
|
|
600
|
+
|
|
601
|
+
.production-title {
|
|
602
|
+
font-size: 1.5rem;
|
|
603
|
+
font-weight: 600;
|
|
604
|
+
margin-bottom: 0.5rem;
|
|
605
|
+
}
|
|
606
|
+
|
|
607
|
+
.production-message {
|
|
608
|
+
color: var(--neutral-500);
|
|
609
|
+
margin-bottom: 2rem;
|
|
610
|
+
max-width: 28rem;
|
|
611
|
+
}
|
|
612
|
+
|
|
613
|
+
.production-link {
|
|
614
|
+
color: var(--blue-600);
|
|
615
|
+
text-decoration: none;
|
|
616
|
+
font-size: 0.875rem;
|
|
617
|
+
}
|
|
618
|
+
|
|
619
|
+
.production-link:hover { text-decoration: underline; }
|
|
620
|
+
|
|
621
|
+
@media (prefers-color-scheme: dark) {
|
|
622
|
+
.production-link { color: var(--blue-500); }
|
|
623
|
+
}
|
|
624
|
+
`;
|
package/dist/src/error-page.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
|
+
import { ERROR_PAGE_CSS } from './error-page-styles';
|
|
1
2
|
export declare function isFrameworkFrame(file: string): boolean;
|
|
2
3
|
/**
|
|
3
|
-
* Render a simple production error page
|
|
4
|
+
* Render a simple production error page.
|
|
5
|
+
*
|
|
6
|
+
* Checks for a userland override at `resources/views/errors/<status>.html`
|
|
7
|
+
* (or `error.html` as a generic fallback) first; renders the built-in
|
|
8
|
+
* template only when no custom page is provided. stacksjs/stacks#863.
|
|
4
9
|
*/
|
|
5
10
|
export declare function renderProductionErrorPage(status: number): string;
|
|
6
11
|
/**
|
|
@@ -16,15 +21,15 @@ export declare function createErrorHandler(config?: ErrorPageConfig): ErrorPageH
|
|
|
16
21
|
/**
|
|
17
22
|
* Render an error page (alias)
|
|
18
23
|
*/
|
|
19
|
-
export declare function renderErrorPage(error: Error, status?: number, config?: ErrorPageConfig): string
|
|
24
|
+
export declare function renderErrorPage(error: Error, status?: number, config?: ErrorPageConfig): Promise<string>;
|
|
20
25
|
/**
|
|
21
26
|
* Render error (alias)
|
|
22
27
|
*/
|
|
23
|
-
export declare function renderError(error: Error, status?: number): string
|
|
28
|
+
export declare function renderError(error: Error, status?: number): Promise<string>;
|
|
24
29
|
/**
|
|
25
30
|
* Create an error response
|
|
26
31
|
*/
|
|
27
|
-
export declare function errorResponse(error: Error, status?: number, config?: ErrorPageConfig): Response
|
|
32
|
+
export declare function errorResponse(error: Error, status?: number, config?: ErrorPageConfig): Promise<Response>;
|
|
28
33
|
// HTTP error definitions. Each entry includes a doc link, likely causes,
|
|
29
34
|
// and a concrete suggestion so the dev-mode error page reads like a hint
|
|
30
35
|
// instead of just "something went wrong".
|
|
@@ -142,145 +147,6 @@ export declare const HTTP_ERRORS: {
|
|
|
142
147
|
suggestion: 'Move the work to a queued job or raise the upstream timeout if the latency is expected.'
|
|
143
148
|
}
|
|
144
149
|
};
|
|
145
|
-
// CSS for error pages
|
|
146
|
-
export declare const ERROR_PAGE_CSS: `
|
|
147
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
148
|
-
body {
|
|
149
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
150
|
-
line-height: 1.6;
|
|
151
|
-
color: #1a1a2e;
|
|
152
|
-
background: #f8f9fa;
|
|
153
|
-
}
|
|
154
|
-
.dark body { background: #1a1a2e; color: #e8e8e8; }
|
|
155
|
-
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
|
|
156
|
-
.error-header {
|
|
157
|
-
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
|
158
|
-
color: white;
|
|
159
|
-
padding: 2rem;
|
|
160
|
-
border-radius: 12px;
|
|
161
|
-
margin-bottom: 1.5rem;
|
|
162
|
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
163
|
-
}
|
|
164
|
-
.error-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
165
|
-
.error-message { font-size: 1.1rem; opacity: 0.9; word-break: break-word; }
|
|
166
|
-
.error-status { font-size: 0.875rem; opacity: 0.75; margin-top: 0.5rem; }
|
|
167
|
-
.card {
|
|
168
|
-
background: white;
|
|
169
|
-
border-radius: 12px;
|
|
170
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
171
|
-
margin-bottom: 1.5rem;
|
|
172
|
-
overflow: hidden;
|
|
173
|
-
}
|
|
174
|
-
.dark .card { background: #252540; }
|
|
175
|
-
.card-header {
|
|
176
|
-
padding: 1rem 1.5rem;
|
|
177
|
-
border-bottom: 1px solid #e9ecef;
|
|
178
|
-
font-weight: 600;
|
|
179
|
-
display: flex;
|
|
180
|
-
align-items: center;
|
|
181
|
-
gap: 0.5rem;
|
|
182
|
-
}
|
|
183
|
-
.dark .card-header { border-bottom-color: #3a3a5a; }
|
|
184
|
-
.card-body { padding: 1.5rem; }
|
|
185
|
-
.stack-frame {
|
|
186
|
-
padding: 1rem 1.5rem;
|
|
187
|
-
border-bottom: 1px solid #e9ecef;
|
|
188
|
-
cursor: pointer;
|
|
189
|
-
transition: background 0.2s;
|
|
190
|
-
}
|
|
191
|
-
.stack-frame:hover { background: #f8f9fa; }
|
|
192
|
-
.dark .stack-frame:hover { background: #1a1a2e; }
|
|
193
|
-
.stack-frame:last-child { border-bottom: none; }
|
|
194
|
-
.stack-frame.expanded { background: #f8f9fa; }
|
|
195
|
-
.dark .stack-frame.expanded { background: #1a1a2e; }
|
|
196
|
-
.frame-file { font-family: 'Monaco', 'Menlo', monospace; font-size: 0.875rem; color: #6c757d; }
|
|
197
|
-
.frame-function { font-weight: 500; color: #495057; }
|
|
198
|
-
.dark .frame-function { color: #e8e8e8; }
|
|
199
|
-
.frame-line { color: #dc3545; font-weight: 600; }
|
|
200
|
-
.code-snippet {
|
|
201
|
-
background: #282c34;
|
|
202
|
-
color: #abb2bf;
|
|
203
|
-
padding: 1rem;
|
|
204
|
-
margin-top: 0.5rem;
|
|
205
|
-
border-radius: 8px;
|
|
206
|
-
overflow-x: auto;
|
|
207
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
208
|
-
font-size: 0.8125rem;
|
|
209
|
-
line-height: 1.8;
|
|
210
|
-
}
|
|
211
|
-
.code-line { display: flex; }
|
|
212
|
-
.code-line-number {
|
|
213
|
-
width: 3rem;
|
|
214
|
-
text-align: right;
|
|
215
|
-
padding-right: 1rem;
|
|
216
|
-
color: #636d83;
|
|
217
|
-
user-select: none;
|
|
218
|
-
}
|
|
219
|
-
.code-line-content { flex: 1; }
|
|
220
|
-
.code-line.highlight { background: rgba(220, 53, 69, 0.2); }
|
|
221
|
-
.code-line.highlight .code-line-number { color: #dc3545; }
|
|
222
|
-
.info-table { width: 100%; border-collapse: collapse; }
|
|
223
|
-
.info-table td { padding: 0.75rem 0; border-bottom: 1px solid #e9ecef; }
|
|
224
|
-
.dark .info-table td { border-bottom-color: #3a3a5a; }
|
|
225
|
-
.info-table td:first-child { font-weight: 500; width: 30%; color: #6c757d; }
|
|
226
|
-
.info-table tr:last-child td { border-bottom: none; }
|
|
227
|
-
.query-item {
|
|
228
|
-
padding: 1rem;
|
|
229
|
-
background: #f8f9fa;
|
|
230
|
-
border-radius: 8px;
|
|
231
|
-
margin-bottom: 0.75rem;
|
|
232
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
233
|
-
font-size: 0.8125rem;
|
|
234
|
-
}
|
|
235
|
-
.dark .query-item { background: #1a1a2e; }
|
|
236
|
-
.query-time { color: #6c757d; font-size: 0.75rem; margin-top: 0.5rem; }
|
|
237
|
-
.badge {
|
|
238
|
-
display: inline-block;
|
|
239
|
-
padding: 0.25rem 0.5rem;
|
|
240
|
-
border-radius: 4px;
|
|
241
|
-
font-size: 0.75rem;
|
|
242
|
-
font-weight: 500;
|
|
243
|
-
}
|
|
244
|
-
.badge-method { background: #e7f5ff; color: #1971c2; }
|
|
245
|
-
.dark .badge-method { background: #1971c2; color: white; }
|
|
246
|
-
.production-page {
|
|
247
|
-
display: flex;
|
|
248
|
-
flex-direction: column;
|
|
249
|
-
align-items: center;
|
|
250
|
-
justify-content: center;
|
|
251
|
-
min-height: 100vh;
|
|
252
|
-
text-align: center;
|
|
253
|
-
padding: 2rem;
|
|
254
|
-
}
|
|
255
|
-
.production-status { font-size: 6rem; font-weight: 700; color: #dee2e6; margin-bottom: 1rem; }
|
|
256
|
-
.production-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
257
|
-
.production-message { color: #6c757d; margin-bottom: 2rem; }
|
|
258
|
-
.production-link { color: #0d6efd; text-decoration: none; }
|
|
259
|
-
.production-link:hover { text-decoration: underline; }
|
|
260
|
-
.error-hint {
|
|
261
|
-
border-left: 4px solid #f59f00;
|
|
262
|
-
background: #fff9db;
|
|
263
|
-
}
|
|
264
|
-
.dark .error-hint, .auto .error-hint { background: #2b2410; border-left-color: #f59f00; }
|
|
265
|
-
.error-hint .card-header { color: #845200; }
|
|
266
|
-
.dark .error-hint .card-header, .auto .error-hint .card-header { color: #ffd43b; }
|
|
267
|
-
.error-hint-causes { margin: 0 0 0.75rem 1.25rem; padding: 0; }
|
|
268
|
-
.error-hint-causes li { margin: 0.2rem 0; }
|
|
269
|
-
.error-hint-suggestion { font-weight: 500; margin-bottom: 0.75rem; }
|
|
270
|
-
.error-hint-doc { color: #0d6efd; text-decoration: none; }
|
|
271
|
-
.error-hint-doc:hover { text-decoration: underline; }
|
|
272
|
-
@media (prefers-color-scheme: dark) {
|
|
273
|
-
.auto body { background: #1a1a2e; color: #e8e8e8; }
|
|
274
|
-
.auto .card { background: #252540; }
|
|
275
|
-
.auto .card-header { border-bottom-color: #3a3a5a; }
|
|
276
|
-
.auto .stack-frame:hover { background: #1a1a2e; }
|
|
277
|
-
.auto .stack-frame.expanded { background: #1a1a2e; }
|
|
278
|
-
.auto .frame-function { color: #e8e8e8; }
|
|
279
|
-
.auto .info-table td { border-bottom-color: #3a3a5a; }
|
|
280
|
-
.auto .query-item { background: #1a1a2e; }
|
|
281
|
-
.auto .badge-method { background: #1971c2; color: white; }
|
|
282
|
-
}
|
|
283
|
-
`;
|
|
284
150
|
/**
|
|
285
151
|
* Error Page Rendering - Ignition-style error pages
|
|
286
152
|
*
|
|
@@ -376,6 +242,7 @@ export declare class ErrorPageHandler {
|
|
|
376
242
|
setRouting(routing: RoutingContext): this;
|
|
377
243
|
setUser(user: UserContext): this;
|
|
378
244
|
addQuery(query: string, time?: number, connection?: string): this;
|
|
379
|
-
render(error: Error, status?: number): string
|
|
380
|
-
handleError(error: Error, status?: number): Response
|
|
245
|
+
render(error: Error, status?: number): Promise<string>;
|
|
246
|
+
handleError(error: Error, status?: number): Promise<Response>;
|
|
381
247
|
}
|
|
248
|
+
export { ERROR_PAGE_CSS };
|
package/dist/src/http.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ export declare function renderHttpError(error: Error, request?: Request, options
|
|
|
13
13
|
status?: number
|
|
14
14
|
isDevelopment?: boolean
|
|
15
15
|
config?: ErrorPageConfig
|
|
16
|
-
}): Response
|
|
16
|
+
}): Promise<Response>;
|
|
17
17
|
/**
|
|
18
18
|
* Express/Hono style error middleware
|
|
19
19
|
*/
|
|
@@ -37,13 +37,13 @@ export declare class HttpErrorHandler {
|
|
|
37
37
|
setRequest(request: Request | RequestContext): this;
|
|
38
38
|
setRouting(routing: RoutingContext): this;
|
|
39
39
|
addQuery(query: string, time?: number, connection?: string): this;
|
|
40
|
-
handle(error: Error, status?: number): Response
|
|
41
|
-
notFound(message?: string): Response
|
|
42
|
-
serverError(error: Error): Response
|
|
43
|
-
forbidden(message?: string): Response
|
|
44
|
-
unauthorized(message?: string): Response
|
|
45
|
-
badRequest(message?: string): Response
|
|
46
|
-
validationError(message?: string): Response
|
|
47
|
-
tooManyRequests(message?: string): Response
|
|
48
|
-
serviceUnavailable(message?: string): Response
|
|
40
|
+
handle(error: Error, status?: number): Promise<Response>;
|
|
41
|
+
notFound(message?: string): Promise<Response>;
|
|
42
|
+
serverError(error: Error): Promise<Response>;
|
|
43
|
+
forbidden(message?: string): Promise<Response>;
|
|
44
|
+
unauthorized(message?: string): Promise<Response>;
|
|
45
|
+
badRequest(message?: string): Promise<Response>;
|
|
46
|
+
validationError(message?: string): Promise<Response>;
|
|
47
|
+
tooManyRequests(message?: string): Promise<Response>;
|
|
48
|
+
serviceUnavailable(message?: string): Promise<Response>;
|
|
49
49
|
}
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@stacksjs/error-handling",
|
|
3
3
|
"type": "module",
|
|
4
|
-
"version": "0.70.
|
|
4
|
+
"version": "0.70.54",
|
|
5
5
|
"description": "Type safe error handling.",
|
|
6
6
|
"author": "Chris Breuer",
|
|
7
7
|
"contributors": [
|
|
@@ -47,15 +47,17 @@
|
|
|
47
47
|
"prepublishOnly": "bun run build"
|
|
48
48
|
},
|
|
49
49
|
"dependencies": {
|
|
50
|
-
"
|
|
50
|
+
"@stacksjs/stx": "^0.2.82",
|
|
51
|
+
"ts-error-handling": "^0.1.1",
|
|
52
|
+
"ts-syntax-highlighter": "^0.2.1"
|
|
51
53
|
},
|
|
52
54
|
"devDependencies": {
|
|
53
|
-
"@stacksjs/cli": "
|
|
54
|
-
"@stacksjs/config": "
|
|
55
|
+
"@stacksjs/cli": "0.70.54",
|
|
56
|
+
"@stacksjs/config": "0.70.54",
|
|
55
57
|
"better-dx": "^0.2.12",
|
|
56
|
-
"@stacksjs/path": "
|
|
57
|
-
"@stacksjs/types": "
|
|
58
|
-
"@stacksjs/validation": "
|
|
58
|
+
"@stacksjs/path": "0.70.54",
|
|
59
|
+
"@stacksjs/types": "0.70.54",
|
|
60
|
+
"@stacksjs/validation": "0.70.54"
|
|
59
61
|
},
|
|
60
62
|
"sideEffects": false
|
|
61
63
|
}
|
package/dist/index.js
DELETED
|
@@ -1,417 +0,0 @@
|
|
|
1
|
-
var{default:k}=(()=>({}));function y(f){if(typeof f!=="string")throw TypeError("Path must be a string. Received "+JSON.stringify(f))}function Y(f,n){var l="",i=0,v=-1,u=0,A;for(var d=0;d<=f.length;++d){if(d<f.length)A=f.charCodeAt(d);else if(A===47)break;else A=47;if(A===47){if(v===d-1||u===1);else if(v!==d-1&&u===2){if(l.length<2||i!==2||l.charCodeAt(l.length-1)!==46||l.charCodeAt(l.length-2)!==46){if(l.length>2){var C=l.lastIndexOf("/");if(C!==l.length-1){if(C===-1)l="",i=0;else l=l.slice(0,C),i=l.length-1-l.lastIndexOf("/");v=d,u=0;continue}}else if(l.length===2||l.length===1){l="",i=0,v=d,u=0;continue}}if(n){if(l.length>0)l+="/..";else l="..";i=2}}else{if(l.length>0)l+="/"+f.slice(v+1,d);else l=f.slice(v+1,d);i=d-v-1}v=d,u=0}else if(A===46&&u!==-1)++u;else u=-1}return l}function I(f,n){var l=n.dir||n.root,i=n.base||(n.name||"")+(n.ext||"");if(!l)return i;if(l===n.root)return l+i;return l+f+i}function J(){var f="",n=!1,l;for(var i=arguments.length-1;i>=-1&&!n;i--){var v;if(i>=0)v=arguments[i];else{if(l===void 0)l=process.cwd();v=l}if(y(v),v.length===0)continue;f=v+"/"+f,n=v.charCodeAt(0)===47}if(f=Y(f,!n),n)if(f.length>0)return"/"+f;else return"/";else if(f.length>0)return f;else return"."}function Z(f){if(y(f),f.length===0)return".";var n=f.charCodeAt(0)===47,l=f.charCodeAt(f.length-1)===47;if(f=Y(f,!n),f.length===0&&!n)f=".";if(f.length>0&&l)f+="/";if(n)return"/"+f;return f}function F(f){return y(f),f.length>0&&f.charCodeAt(0)===47}function j(){if(arguments.length===0)return".";var f;for(var n=0;n<arguments.length;++n){var l=arguments[n];if(y(l),l.length>0)if(f===void 0)f=l;else f+="/"+l}if(f===void 0)return".";return Z(f)}function O(f,n){if(y(f),y(n),f===n)return"";if(f=J(f),n=J(n),f===n)return"";var l=1;for(;l<f.length;++l)if(f.charCodeAt(l)!==47)break;var i=f.length,v=i-l,u=1;for(;u<n.length;++u)if(n.charCodeAt(u)!==47)break;var A=n.length,d=A-u,C=v<d?v:d,w=-1,b=0;for(;b<=C;++b){if(b===C){if(d>C){if(n.charCodeAt(u+b)===47)return n.slice(u+b+1);else if(b===0)return n.slice(u+b)}else if(v>C){if(f.charCodeAt(l+b)===47)w=b;else if(b===0)w=0}break}var X=f.charCodeAt(l+b),h=n.charCodeAt(u+b);if(X!==h)break;else if(X===47)w=b}var L="";for(b=l+w+1;b<=i;++b)if(b===i||f.charCodeAt(b)===47)if(L.length===0)L+="..";else L+="/..";if(L.length>0)return L+n.slice(u+w);else{if(u+=w,n.charCodeAt(u)===47)++u;return n.slice(u)}}function R(f){return f}function U(f){if(y(f),f.length===0)return".";var n=f.charCodeAt(0),l=n===47,i=-1,v=!0;for(var u=f.length-1;u>=1;--u)if(n=f.charCodeAt(u),n===47){if(!v){i=u;break}}else v=!1;if(i===-1)return l?"/":".";if(l&&i===1)return"//";return f.slice(0,i)}function S(f,n){if(n!==void 0&&typeof n!=="string")throw TypeError('"ext" argument must be a string');y(f);var l=0,i=-1,v=!0,u;if(n!==void 0&&n.length>0&&n.length<=f.length){if(n.length===f.length&&n===f)return"";var A=n.length-1,d=-1;for(u=f.length-1;u>=0;--u){var C=f.charCodeAt(u);if(C===47){if(!v){l=u+1;break}}else{if(d===-1)v=!1,d=u+1;if(A>=0)if(C===n.charCodeAt(A)){if(--A===-1)i=u}else A=-1,i=d}}if(l===i)i=d;else if(i===-1)i=f.length;return f.slice(l,i)}else{for(u=f.length-1;u>=0;--u)if(f.charCodeAt(u)===47){if(!v){l=u+1;break}}else if(i===-1)v=!1,i=u+1;if(i===-1)return"";return f.slice(l,i)}}function x(f){y(f);var n=-1,l=0,i=-1,v=!0,u=0;for(var A=f.length-1;A>=0;--A){var d=f.charCodeAt(A);if(d===47){if(!v){l=A+1;break}continue}if(i===-1)v=!1,i=A+1;if(d===46){if(n===-1)n=A;else if(u!==1)u=1}else if(n!==-1)u=-1}if(n===-1||i===-1||u===0||u===1&&n===i-1&&n===l+1)return"";return f.slice(n,i)}function P(f){if(f===null||typeof f!=="object")throw TypeError('The "pathObject" argument must be of type Object. Received type '+typeof f);return I("/",f)}function M(f){y(f);var n={root:"",dir:"",base:"",ext:"",name:""};if(f.length===0)return n;var l=f.charCodeAt(0),i=l===47,v;if(i)n.root="/",v=1;else v=0;var u=-1,A=0,d=-1,C=!0,w=f.length-1,b=0;for(;w>=v;--w){if(l=f.charCodeAt(w),l===47){if(!C){A=w+1;break}continue}if(d===-1)C=!1,d=w+1;if(l===46){if(u===-1)u=w;else if(b!==1)b=1}else if(u!==-1)b=-1}if(u===-1||d===-1||b===0||b===1&&u===d-1&&u===A+1){if(d!==-1)if(A===0&&i)n.base=n.name=f.slice(1,d);else n.base=n.name=f.slice(A,d)}else{if(A===0&&i)n.name=f.slice(1,u),n.base=f.slice(1,d);else n.name=f.slice(A,u),n.base=f.slice(A,d);n.ext=f.slice(u,d)}if(A>0)n.dir=f.slice(0,A-1);else if(i)n.dir="/";return n}var q="/",m=":",r=((f)=>(f.posix=f,f))({resolve:J,normalize:Z,isAbsolute:F,join:j,relative:O,_makeLong:R,dirname:U,basename:S,extname:x,format:P,parse:M,sep:q,delimiter:m,win32:null,posix:null});import*as z from"@stacksjs/path";import{ExitCode as e}from"@stacksjs/types";function $(f){return`\x1B[3m${f}\x1B[23m`}function E(f){return f.replace(/\x1B\[[0-9;]*m/g,"")}class Q{static isTestEnvironment=!1;static shouldExitProcess=!1;static handle(f,n){if(!this.isTestEnvironment)this.shouldExitProcess=n?.shouldExit===!0;if(n?.silent!==!0)this.writeErrorToConsole(f);let l;if(n?.message)l=n.message;else if(f instanceof Error)l=f.message;else if(typeof f==="string")l=f;else l=JSON.stringify(f);let i=Error(l);if(f instanceof Error)Object.assign(i,f);return this.writeErrorToFile(i).catch((v)=>console.error(v)),i}static handleError(f,n){return this.handle(f,n),f}static async writeErrorToFile(f,n){if(!(f instanceof Error)){console.error("Error is not an instance of Error:",f);return}let l=n?` | url=${n.url||"N/A"} method=${n.method||"N/A"} user=${n.userId||"anonymous"}`:"",i=f.stack?`
|
|
2
|
-
${f.stack.split(`
|
|
3
|
-
`).slice(1,4).join(`
|
|
4
|
-
`)}`:"",v=`[${new Date().toISOString()}] ${f.name}: ${f.message}${l}${i}
|
|
5
|
-
`,u=z.logsPath("stacks.log")??z.logsPath("errors.log");try{await k.promises.mkdir(z.dirname(u),{recursive:!0}),await k.promises.appendFile(u,v)}catch(A){console.error("Failed to write to error file:",A)}}static writeErrorToConsole(f){let n;if(f instanceof Error)n=f.message;else if(typeof f==="string")n=f;else n=JSON.stringify(f);if(console.error(n),n.includes("bunx --bun cdk destroy")||n===`Failed to execute command: ${$("bunx --bun eslint . --fix")}`||n===`Failed to execute command: ${$("bun storage/framework/core/actions/src/lint/fix.ts")}`){if(!this.isTestEnvironment)console.log("No need to worry. The edge function is currently being destroyed. Please run `buddy undeploy` shortly again, and continue doing so until it succeeds running."),console.log("Hoping to see you back soon!")}if(this.shouldExitProcess)(void 0)(e.FatalError)}}var g="storage/logs/stacks.log";function v1(f){g=f}async function H(f,n){let i=`[${new Date().toISOString()}] ${f}
|
|
6
|
-
`,v=n?.logFile??g,u=U(v);await k.promises.mkdir(u,{recursive:!0}),await k.promises.appendFile(v,i)}function u1(f,n){let l,i;if(n&&typeof n==="object"&&!("shouldExit"in n)&&!("silent"in n)&&!("message"in n))i=n,n=void 0;let v=f instanceof Error?f.message:typeof f==="string"?f:JSON.stringify(f);if(n&&"message"in n)l=`${v}: ${n.message}`;else l=v;let u=`ERROR: ${E(l)}`;if(i)u+=`
|
|
7
|
-
Context: ${JSON.stringify(i,null,2)}`;H(u).catch((d)=>{console.error("Failed to write error log:",d)});let A=Error(l);if(f instanceof Error)Object.assign(A,f);return Q.handle(A,{...n,message:l})}var G={400:{status:400,title:"Bad Request",message:"The request was malformed or invalid.",docLink:"https://stacksjs.org/docs/errors/400",commonCauses:["JSON body is missing or has a syntax error","A required field is absent from the payload","Content-Type header does not match the body format"],suggestion:"Inspect the request body and Content-Type — most 400s come from malformed JSON or a missing required field."},401:{status:401,title:"Unauthorized",message:"Authentication is required to access this resource.",docLink:"https://stacksjs.org/docs/errors/401",commonCauses:["No Authorization header was sent","The bearer token expired","The session cookie was cleared"],suggestion:"Confirm a valid `Authorization: Bearer <token>` header is sent and the token has not expired."},403:{status:403,title:"Forbidden",message:"You do not have permission to access this resource.",docLink:"https://stacksjs.org/docs/errors/403",commonCauses:["The authenticated user lacks the required ability or role","A Gate or policy denied access (see app/Gates.ts)","The token was issued without the needed ability"],suggestion:"Check Gates / policies and the abilities encoded in the access token."},404:{status:404,title:"Not Found",message:"The requested resource could not be found.",docLink:"https://stacksjs.org/docs/errors/404",commonCauses:["The route is not registered in app/Routes.ts","A typo in the URL path","A model lookup returned no row (ModelNotFoundError)"],suggestion:"Run `buddy route:list` to see registered routes, or verify the model exists with the given id."},405:{status:405,title:"Method Not Allowed",message:"The request method is not supported for this resource.",docLink:"https://stacksjs.org/docs/errors/405",commonCauses:["The route is registered for a different HTTP method","A form posted GET when the route expects POST"],suggestion:"Confirm the HTTP method in `app/Routes.ts` matches what the client sent."},408:{status:408,title:"Request Timeout",message:"The request took too long to complete.",docLink:"https://stacksjs.org/docs/errors/408",commonCauses:["A long-running query or external API call exceeded the timeout","The client uploaded a slow body that stalled"],suggestion:"Move slow work into a queued job, or raise the route timeout if the work is genuinely long."},409:{status:409,title:"Conflict",message:"The request conflicts with the current state of the resource.",docLink:"https://stacksjs.org/docs/errors/409",commonCauses:["A unique-constraint violation (duplicate email, slug, etc.)","Optimistic locking detected a stale write"],suggestion:"Re-fetch the resource and retry, or surface the conflict to the user."},410:{status:410,title:"Gone",message:"The requested resource is no longer available.",docLink:"https://stacksjs.org/docs/errors/410",commonCauses:["The resource was permanently deleted","A signed URL expired"],suggestion:"Issue a fresh signed URL or fall back to the canonical resource."},422:{status:422,title:"Unprocessable Entity",message:"The request was well-formed but could not be processed.",docLink:"https://stacksjs.org/docs/errors/422",commonCauses:["Validation rules from the action / model rejected the payload","A field value is outside the allowed range or shape"],suggestion:"Inspect `errors` in the response body — each key maps to a failing field."},429:{status:429,title:"Too Many Requests",message:"You have exceeded the rate limit.",docLink:"https://stacksjs.org/docs/errors/429",commonCauses:["Rate-limit middleware tripped on this IP / token","A retry loop is hammering the endpoint"],suggestion:"Honor the `Retry-After` response header and back off before retrying."},500:{status:500,title:"Internal Server Error",message:"An unexpected error occurred on the server.",docLink:"https://stacksjs.org/docs/errors/500",commonCauses:["An unhandled exception in an action or middleware","A failing database connection or migration","A misconfigured environment variable"],suggestion:"Check server logs for the original stack trace — the error page above shows the throw site in dev."},502:{status:502,title:"Bad Gateway",message:"The server received an invalid response from an upstream server.",docLink:"https://stacksjs.org/docs/errors/502",commonCauses:["An upstream HTTP API returned a malformed response","A reverse proxy could not reach the origin"],suggestion:"Verify the upstream service is healthy and returning the expected content type."},503:{status:503,title:"Service Unavailable",message:"The service is temporarily unavailable.",docLink:"https://stacksjs.org/docs/errors/503",commonCauses:["Maintenance mode is enabled","A health check is failing","A dependency (db, redis, queue) is down"],suggestion:"Run `buddy doctor` and check dependent services."},504:{status:504,title:"Gateway Timeout",message:"The upstream server did not respond in time.",docLink:"https://stacksjs.org/docs/errors/504",commonCauses:["An upstream HTTP call exceeded its deadline","A long-running database query timed out"],suggestion:"Move the work to a queued job or raise the upstream timeout if the latency is expected."}};var a=["/storage/framework/core/","/node_modules/@stacksjs/","node:internal/","bun:wrap"];function p(f){if(!f)return!1;return a.some((n)=>f.includes(n))}function K(f,n,l={}){if(!f)return[];let i=f.split(`
|
|
8
|
-
`).slice(1),v=[],u=l.includeFrameworkFrames===!0;for(let A of i){let d=A.match(/^\s*at\s+(?:(.+?)\s+\()?(.+?):(\d+):(\d+)\)?$/);if(d){let C=d[2];if(C===void 0)continue;let w=C;if(n){for(let b of n)if(C.startsWith(b)){C=C.slice(b.length+1);break}}if(!u&&p(w))continue;v.push({function:d[1]||"<anonymous>",file:C,line:parseInt(d[3]??"0",10),column:parseInt(d[4]??"0",10)})}}if(!u&&v.length===0)return K(f,n,{includeFrameworkFrames:!0});return v}function c(f){return f.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">").replace(/"/g,""").replace(/'/g,"'")}function N(f){let n=G[f]||{status:f,title:"Error",message:"An unexpected error occurred."};return`<!DOCTYPE html>
|
|
9
|
-
<html lang="en">
|
|
10
|
-
<head>
|
|
11
|
-
<meta charset="UTF-8">
|
|
12
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
13
|
-
<title>${n.status} - ${n.title}</title>
|
|
14
|
-
<style>
|
|
15
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
16
|
-
body {
|
|
17
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
18
|
-
line-height: 1.6;
|
|
19
|
-
color: #1a1a2e;
|
|
20
|
-
background: #f8f9fa;
|
|
21
|
-
}
|
|
22
|
-
.dark body { background: #1a1a2e; color: #e8e8e8; }
|
|
23
|
-
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
|
|
24
|
-
.error-header {
|
|
25
|
-
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
|
26
|
-
color: white;
|
|
27
|
-
padding: 2rem;
|
|
28
|
-
border-radius: 12px;
|
|
29
|
-
margin-bottom: 1.5rem;
|
|
30
|
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
31
|
-
}
|
|
32
|
-
.error-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
33
|
-
.error-message { font-size: 1.1rem; opacity: 0.9; word-break: break-word; }
|
|
34
|
-
.error-status { font-size: 0.875rem; opacity: 0.75; margin-top: 0.5rem; }
|
|
35
|
-
.card {
|
|
36
|
-
background: white;
|
|
37
|
-
border-radius: 12px;
|
|
38
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
39
|
-
margin-bottom: 1.5rem;
|
|
40
|
-
overflow: hidden;
|
|
41
|
-
}
|
|
42
|
-
.dark .card { background: #252540; }
|
|
43
|
-
.card-header {
|
|
44
|
-
padding: 1rem 1.5rem;
|
|
45
|
-
border-bottom: 1px solid #e9ecef;
|
|
46
|
-
font-weight: 600;
|
|
47
|
-
display: flex;
|
|
48
|
-
align-items: center;
|
|
49
|
-
gap: 0.5rem;
|
|
50
|
-
}
|
|
51
|
-
.dark .card-header { border-bottom-color: #3a3a5a; }
|
|
52
|
-
.card-body { padding: 1.5rem; }
|
|
53
|
-
.stack-frame {
|
|
54
|
-
padding: 1rem 1.5rem;
|
|
55
|
-
border-bottom: 1px solid #e9ecef;
|
|
56
|
-
cursor: pointer;
|
|
57
|
-
transition: background 0.2s;
|
|
58
|
-
}
|
|
59
|
-
.stack-frame:hover { background: #f8f9fa; }
|
|
60
|
-
.dark .stack-frame:hover { background: #1a1a2e; }
|
|
61
|
-
.stack-frame:last-child { border-bottom: none; }
|
|
62
|
-
.stack-frame.expanded { background: #f8f9fa; }
|
|
63
|
-
.dark .stack-frame.expanded { background: #1a1a2e; }
|
|
64
|
-
.frame-file { font-family: 'Monaco', 'Menlo', monospace; font-size: 0.875rem; color: #6c757d; }
|
|
65
|
-
.frame-function { font-weight: 500; color: #495057; }
|
|
66
|
-
.dark .frame-function { color: #e8e8e8; }
|
|
67
|
-
.frame-line { color: #dc3545; font-weight: 600; }
|
|
68
|
-
.code-snippet {
|
|
69
|
-
background: #282c34;
|
|
70
|
-
color: #abb2bf;
|
|
71
|
-
padding: 1rem;
|
|
72
|
-
margin-top: 0.5rem;
|
|
73
|
-
border-radius: 8px;
|
|
74
|
-
overflow-x: auto;
|
|
75
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
76
|
-
font-size: 0.8125rem;
|
|
77
|
-
line-height: 1.8;
|
|
78
|
-
}
|
|
79
|
-
.code-line { display: flex; }
|
|
80
|
-
.code-line-number {
|
|
81
|
-
width: 3rem;
|
|
82
|
-
text-align: right;
|
|
83
|
-
padding-right: 1rem;
|
|
84
|
-
color: #636d83;
|
|
85
|
-
user-select: none;
|
|
86
|
-
}
|
|
87
|
-
.code-line-content { flex: 1; }
|
|
88
|
-
.code-line.highlight { background: rgba(220, 53, 69, 0.2); }
|
|
89
|
-
.code-line.highlight .code-line-number { color: #dc3545; }
|
|
90
|
-
.info-table { width: 100%; border-collapse: collapse; }
|
|
91
|
-
.info-table td { padding: 0.75rem 0; border-bottom: 1px solid #e9ecef; }
|
|
92
|
-
.dark .info-table td { border-bottom-color: #3a3a5a; }
|
|
93
|
-
.info-table td:first-child { font-weight: 500; width: 30%; color: #6c757d; }
|
|
94
|
-
.info-table tr:last-child td { border-bottom: none; }
|
|
95
|
-
.query-item {
|
|
96
|
-
padding: 1rem;
|
|
97
|
-
background: #f8f9fa;
|
|
98
|
-
border-radius: 8px;
|
|
99
|
-
margin-bottom: 0.75rem;
|
|
100
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
101
|
-
font-size: 0.8125rem;
|
|
102
|
-
}
|
|
103
|
-
.dark .query-item { background: #1a1a2e; }
|
|
104
|
-
.query-time { color: #6c757d; font-size: 0.75rem; margin-top: 0.5rem; }
|
|
105
|
-
.badge {
|
|
106
|
-
display: inline-block;
|
|
107
|
-
padding: 0.25rem 0.5rem;
|
|
108
|
-
border-radius: 4px;
|
|
109
|
-
font-size: 0.75rem;
|
|
110
|
-
font-weight: 500;
|
|
111
|
-
}
|
|
112
|
-
.badge-method { background: #e7f5ff; color: #1971c2; }
|
|
113
|
-
.dark .badge-method { background: #1971c2; color: white; }
|
|
114
|
-
.production-page {
|
|
115
|
-
display: flex;
|
|
116
|
-
flex-direction: column;
|
|
117
|
-
align-items: center;
|
|
118
|
-
justify-content: center;
|
|
119
|
-
min-height: 100vh;
|
|
120
|
-
text-align: center;
|
|
121
|
-
padding: 2rem;
|
|
122
|
-
}
|
|
123
|
-
.production-status { font-size: 6rem; font-weight: 700; color: #dee2e6; margin-bottom: 1rem; }
|
|
124
|
-
.production-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
125
|
-
.production-message { color: #6c757d; margin-bottom: 2rem; }
|
|
126
|
-
.production-link { color: #0d6efd; text-decoration: none; }
|
|
127
|
-
.production-link:hover { text-decoration: underline; }
|
|
128
|
-
.error-hint {
|
|
129
|
-
border-left: 4px solid #f59f00;
|
|
130
|
-
background: #fff9db;
|
|
131
|
-
}
|
|
132
|
-
.dark .error-hint, .auto .error-hint { background: #2b2410; border-left-color: #f59f00; }
|
|
133
|
-
.error-hint .card-header { color: #845200; }
|
|
134
|
-
.dark .error-hint .card-header, .auto .error-hint .card-header { color: #ffd43b; }
|
|
135
|
-
.error-hint-causes { margin: 0 0 0.75rem 1.25rem; padding: 0; }
|
|
136
|
-
.error-hint-causes li { margin: 0.2rem 0; }
|
|
137
|
-
.error-hint-suggestion { font-weight: 500; margin-bottom: 0.75rem; }
|
|
138
|
-
.error-hint-doc { color: #0d6efd; text-decoration: none; }
|
|
139
|
-
.error-hint-doc:hover { text-decoration: underline; }
|
|
140
|
-
@media (prefers-color-scheme: dark) {
|
|
141
|
-
.auto body { background: #1a1a2e; color: #e8e8e8; }
|
|
142
|
-
.auto .card { background: #252540; }
|
|
143
|
-
.auto .card-header { border-bottom-color: #3a3a5a; }
|
|
144
|
-
.auto .stack-frame:hover { background: #1a1a2e; }
|
|
145
|
-
.auto .stack-frame.expanded { background: #1a1a2e; }
|
|
146
|
-
.auto .frame-function { color: #e8e8e8; }
|
|
147
|
-
.auto .info-table td { border-bottom-color: #3a3a5a; }
|
|
148
|
-
.auto .query-item { background: #1a1a2e; }
|
|
149
|
-
.auto .badge-method { background: #1971c2; color: white; }
|
|
150
|
-
}
|
|
151
|
-
</style>
|
|
152
|
-
</head>
|
|
153
|
-
<body>
|
|
154
|
-
<div class="production-page">
|
|
155
|
-
<div class="production-status">${n.status}</div>
|
|
156
|
-
<h1 class="production-title">${c(n.title)}</h1>
|
|
157
|
-
<p class="production-message">${c(n.message)}</p>
|
|
158
|
-
<a href="/" class="production-link">← Back to Home</a>
|
|
159
|
-
</div>
|
|
160
|
-
</body>
|
|
161
|
-
</html>`}function o(f){let n=G[f];if(!n)return"";let l=Array.isArray(n.commonCauses)&&n.commonCauses.length>0,i=typeof n.suggestion==="string"&&n.suggestion.length>0,v=typeof n.docLink==="string"&&n.docLink.length>0;if(!l&&!i&&!v)return"";let u=l?`<ul class="error-hint-causes">${n.commonCauses.map((C)=>`<li>${c(C)}</li>`).join("")}</ul>`:"",A=i?`<p class="error-hint-suggestion">${c(n.suggestion)}</p>`:"",d=v?`<a class="error-hint-doc" href="${c(n.docLink)}" target="_blank" rel="noreferrer noopener">Read the docs →</a>`:"";return`<section class="card error-hint">
|
|
162
|
-
<div class="card-header">Likely causes & next steps</div>
|
|
163
|
-
<div class="card-body">${u}${A}${d}</div>
|
|
164
|
-
</section>`}class W{config;framework;request;routing;user;queries=[];constructor(f){this.config={appName:"App",theme:"auto",showEnvironment:!0,showQueries:!0,showRequest:!0,enableCopyMarkdown:!0,snippetLines:8,...f}}setFramework(f,n){return this.framework={name:f,version:n},this}setRequest(f){if(f instanceof Request){let n=new URL(f.url);this.request={method:f.method,url:f.url,headers:Object.fromEntries(f.headers.entries()),queryParams:Object.fromEntries(n.searchParams.entries())}}else this.request=f;return this}setRouting(f){return this.routing=f,this}setUser(f){return this.user=f,this}addQuery(f,n,l){return this.queries.push({query:f,time:n,connection:l}),this}render(f,n=500){let l=K(f.stack,this.config.basePaths,{includeFrameworkFrames:this.config.showFrameworkFrames===!0});return`<!DOCTYPE html>
|
|
165
|
-
<html lang="en" class="${this.config.theme||"auto"}">
|
|
166
|
-
<head>
|
|
167
|
-
<meta charset="UTF-8">
|
|
168
|
-
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
169
|
-
<title>${n} - ${c(f.name||"Error")}</title>
|
|
170
|
-
<style>
|
|
171
|
-
* { box-sizing: border-box; margin: 0; padding: 0; }
|
|
172
|
-
body {
|
|
173
|
-
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Oxygen, Ubuntu, sans-serif;
|
|
174
|
-
line-height: 1.6;
|
|
175
|
-
color: #1a1a2e;
|
|
176
|
-
background: #f8f9fa;
|
|
177
|
-
}
|
|
178
|
-
.dark body { background: #1a1a2e; color: #e8e8e8; }
|
|
179
|
-
.container { max-width: 1200px; margin: 0 auto; padding: 2rem; }
|
|
180
|
-
.error-header {
|
|
181
|
-
background: linear-gradient(135deg, #dc3545 0%, #c82333 100%);
|
|
182
|
-
color: white;
|
|
183
|
-
padding: 2rem;
|
|
184
|
-
border-radius: 12px;
|
|
185
|
-
margin-bottom: 1.5rem;
|
|
186
|
-
box-shadow: 0 4px 6px rgba(0, 0, 0, 0.1);
|
|
187
|
-
}
|
|
188
|
-
.error-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
189
|
-
.error-message { font-size: 1.1rem; opacity: 0.9; word-break: break-word; }
|
|
190
|
-
.error-status { font-size: 0.875rem; opacity: 0.75; margin-top: 0.5rem; }
|
|
191
|
-
.card {
|
|
192
|
-
background: white;
|
|
193
|
-
border-radius: 12px;
|
|
194
|
-
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.05);
|
|
195
|
-
margin-bottom: 1.5rem;
|
|
196
|
-
overflow: hidden;
|
|
197
|
-
}
|
|
198
|
-
.dark .card { background: #252540; }
|
|
199
|
-
.card-header {
|
|
200
|
-
padding: 1rem 1.5rem;
|
|
201
|
-
border-bottom: 1px solid #e9ecef;
|
|
202
|
-
font-weight: 600;
|
|
203
|
-
display: flex;
|
|
204
|
-
align-items: center;
|
|
205
|
-
gap: 0.5rem;
|
|
206
|
-
}
|
|
207
|
-
.dark .card-header { border-bottom-color: #3a3a5a; }
|
|
208
|
-
.card-body { padding: 1.5rem; }
|
|
209
|
-
.stack-frame {
|
|
210
|
-
padding: 1rem 1.5rem;
|
|
211
|
-
border-bottom: 1px solid #e9ecef;
|
|
212
|
-
cursor: pointer;
|
|
213
|
-
transition: background 0.2s;
|
|
214
|
-
}
|
|
215
|
-
.stack-frame:hover { background: #f8f9fa; }
|
|
216
|
-
.dark .stack-frame:hover { background: #1a1a2e; }
|
|
217
|
-
.stack-frame:last-child { border-bottom: none; }
|
|
218
|
-
.stack-frame.expanded { background: #f8f9fa; }
|
|
219
|
-
.dark .stack-frame.expanded { background: #1a1a2e; }
|
|
220
|
-
.frame-file { font-family: 'Monaco', 'Menlo', monospace; font-size: 0.875rem; color: #6c757d; }
|
|
221
|
-
.frame-function { font-weight: 500; color: #495057; }
|
|
222
|
-
.dark .frame-function { color: #e8e8e8; }
|
|
223
|
-
.frame-line { color: #dc3545; font-weight: 600; }
|
|
224
|
-
.code-snippet {
|
|
225
|
-
background: #282c34;
|
|
226
|
-
color: #abb2bf;
|
|
227
|
-
padding: 1rem;
|
|
228
|
-
margin-top: 0.5rem;
|
|
229
|
-
border-radius: 8px;
|
|
230
|
-
overflow-x: auto;
|
|
231
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
232
|
-
font-size: 0.8125rem;
|
|
233
|
-
line-height: 1.8;
|
|
234
|
-
}
|
|
235
|
-
.code-line { display: flex; }
|
|
236
|
-
.code-line-number {
|
|
237
|
-
width: 3rem;
|
|
238
|
-
text-align: right;
|
|
239
|
-
padding-right: 1rem;
|
|
240
|
-
color: #636d83;
|
|
241
|
-
user-select: none;
|
|
242
|
-
}
|
|
243
|
-
.code-line-content { flex: 1; }
|
|
244
|
-
.code-line.highlight { background: rgba(220, 53, 69, 0.2); }
|
|
245
|
-
.code-line.highlight .code-line-number { color: #dc3545; }
|
|
246
|
-
.info-table { width: 100%; border-collapse: collapse; }
|
|
247
|
-
.info-table td { padding: 0.75rem 0; border-bottom: 1px solid #e9ecef; }
|
|
248
|
-
.dark .info-table td { border-bottom-color: #3a3a5a; }
|
|
249
|
-
.info-table td:first-child { font-weight: 500; width: 30%; color: #6c757d; }
|
|
250
|
-
.info-table tr:last-child td { border-bottom: none; }
|
|
251
|
-
.query-item {
|
|
252
|
-
padding: 1rem;
|
|
253
|
-
background: #f8f9fa;
|
|
254
|
-
border-radius: 8px;
|
|
255
|
-
margin-bottom: 0.75rem;
|
|
256
|
-
font-family: 'Monaco', 'Menlo', monospace;
|
|
257
|
-
font-size: 0.8125rem;
|
|
258
|
-
}
|
|
259
|
-
.dark .query-item { background: #1a1a2e; }
|
|
260
|
-
.query-time { color: #6c757d; font-size: 0.75rem; margin-top: 0.5rem; }
|
|
261
|
-
.badge {
|
|
262
|
-
display: inline-block;
|
|
263
|
-
padding: 0.25rem 0.5rem;
|
|
264
|
-
border-radius: 4px;
|
|
265
|
-
font-size: 0.75rem;
|
|
266
|
-
font-weight: 500;
|
|
267
|
-
}
|
|
268
|
-
.badge-method { background: #e7f5ff; color: #1971c2; }
|
|
269
|
-
.dark .badge-method { background: #1971c2; color: white; }
|
|
270
|
-
.production-page {
|
|
271
|
-
display: flex;
|
|
272
|
-
flex-direction: column;
|
|
273
|
-
align-items: center;
|
|
274
|
-
justify-content: center;
|
|
275
|
-
min-height: 100vh;
|
|
276
|
-
text-align: center;
|
|
277
|
-
padding: 2rem;
|
|
278
|
-
}
|
|
279
|
-
.production-status { font-size: 6rem; font-weight: 700; color: #dee2e6; margin-bottom: 1rem; }
|
|
280
|
-
.production-title { font-size: 1.5rem; font-weight: 600; margin-bottom: 0.5rem; }
|
|
281
|
-
.production-message { color: #6c757d; margin-bottom: 2rem; }
|
|
282
|
-
.production-link { color: #0d6efd; text-decoration: none; }
|
|
283
|
-
.production-link:hover { text-decoration: underline; }
|
|
284
|
-
.error-hint {
|
|
285
|
-
border-left: 4px solid #f59f00;
|
|
286
|
-
background: #fff9db;
|
|
287
|
-
}
|
|
288
|
-
.dark .error-hint, .auto .error-hint { background: #2b2410; border-left-color: #f59f00; }
|
|
289
|
-
.error-hint .card-header { color: #845200; }
|
|
290
|
-
.dark .error-hint .card-header, .auto .error-hint .card-header { color: #ffd43b; }
|
|
291
|
-
.error-hint-causes { margin: 0 0 0.75rem 1.25rem; padding: 0; }
|
|
292
|
-
.error-hint-causes li { margin: 0.2rem 0; }
|
|
293
|
-
.error-hint-suggestion { font-weight: 500; margin-bottom: 0.75rem; }
|
|
294
|
-
.error-hint-doc { color: #0d6efd; text-decoration: none; }
|
|
295
|
-
.error-hint-doc:hover { text-decoration: underline; }
|
|
296
|
-
@media (prefers-color-scheme: dark) {
|
|
297
|
-
.auto body { background: #1a1a2e; color: #e8e8e8; }
|
|
298
|
-
.auto .card { background: #252540; }
|
|
299
|
-
.auto .card-header { border-bottom-color: #3a3a5a; }
|
|
300
|
-
.auto .stack-frame:hover { background: #1a1a2e; }
|
|
301
|
-
.auto .stack-frame.expanded { background: #1a1a2e; }
|
|
302
|
-
.auto .frame-function { color: #e8e8e8; }
|
|
303
|
-
.auto .info-table td { border-bottom-color: #3a3a5a; }
|
|
304
|
-
.auto .query-item { background: #1a1a2e; }
|
|
305
|
-
.auto .badge-method { background: #1971c2; color: white; }
|
|
306
|
-
}
|
|
307
|
-
</style>
|
|
308
|
-
</head>
|
|
309
|
-
<body>
|
|
310
|
-
<div class="container">
|
|
311
|
-
<div class="error-header">
|
|
312
|
-
<div class="error-title">${c(f.name||"Error")}</div>
|
|
313
|
-
<div class="error-message">${c(f.message)}</div>
|
|
314
|
-
<div class="error-status">${n} • ${this.framework?`${this.framework.name}${this.framework.version?` v${this.framework.version}`:""}`:"Application"}</div>
|
|
315
|
-
</div>
|
|
316
|
-
|
|
317
|
-
${o(n)}
|
|
318
|
-
|
|
319
|
-
${l.length>0?`
|
|
320
|
-
<div class="card">
|
|
321
|
-
<div class="card-header">\uD83D\uDCDA Stack Trace</div>
|
|
322
|
-
${l.map((v)=>`
|
|
323
|
-
<div class="stack-frame" onclick="this.classList.toggle('expanded')">
|
|
324
|
-
<div class="frame-function">${c(v.function||"<anonymous>")}</div>
|
|
325
|
-
<div class="frame-file">
|
|
326
|
-
${c(v.file)}:<span class="frame-line">${v.line}</span>${v.column?`:${v.column}`:""}
|
|
327
|
-
</div>
|
|
328
|
-
</div>
|
|
329
|
-
`).join("")}
|
|
330
|
-
</div>
|
|
331
|
-
`:""}
|
|
332
|
-
|
|
333
|
-
${this.config.showRequest&&this.request?`
|
|
334
|
-
<div class="card">
|
|
335
|
-
<div class="card-header">\uD83C\uDF10 Request</div>
|
|
336
|
-
<div class="card-body">
|
|
337
|
-
<table class="info-table">
|
|
338
|
-
<tr>
|
|
339
|
-
<td>Method</td>
|
|
340
|
-
<td><span class="badge badge-method">${c(this.request.method)}</span></td>
|
|
341
|
-
</tr>
|
|
342
|
-
<tr>
|
|
343
|
-
<td>URL</td>
|
|
344
|
-
<td>${c(this.request.url)}</td>
|
|
345
|
-
</tr>
|
|
346
|
-
${this.request.queryParams&&Object.keys(this.request.queryParams).length>0?`
|
|
347
|
-
<tr>
|
|
348
|
-
<td>Query Params</td>
|
|
349
|
-
<td><code>${c(JSON.stringify(this.request.queryParams,null,2))}</code></td>
|
|
350
|
-
</tr>
|
|
351
|
-
`:""}
|
|
352
|
-
${this.request.body?`
|
|
353
|
-
<tr>
|
|
354
|
-
<td>Body</td>
|
|
355
|
-
<td><code>${c(JSON.stringify(this.request.body,null,2))}</code></td>
|
|
356
|
-
</tr>
|
|
357
|
-
`:""}
|
|
358
|
-
</table>
|
|
359
|
-
</div>
|
|
360
|
-
</div>
|
|
361
|
-
`:""}
|
|
362
|
-
|
|
363
|
-
${this.routing?`
|
|
364
|
-
<div class="card">
|
|
365
|
-
<div class="card-header">\uD83D\uDEE4️ Routing</div>
|
|
366
|
-
<div class="card-body">
|
|
367
|
-
<table class="info-table">
|
|
368
|
-
${this.routing.controller?`<tr><td>Controller</td><td>${c(this.routing.controller)}</td></tr>`:""}
|
|
369
|
-
${this.routing.routeName?`<tr><td>Route Name</td><td>${c(this.routing.routeName)}</td></tr>`:""}
|
|
370
|
-
${this.routing.middleware?.length?`<tr><td>Middleware</td><td>${this.routing.middleware.map((v)=>c(v)).join(", ")}</td></tr>`:""}
|
|
371
|
-
</table>
|
|
372
|
-
</div>
|
|
373
|
-
</div>
|
|
374
|
-
`:""}
|
|
375
|
-
|
|
376
|
-
${this.user?`
|
|
377
|
-
<div class="card">
|
|
378
|
-
<div class="card-header">\uD83D\uDC64 User</div>
|
|
379
|
-
<div class="card-body">
|
|
380
|
-
<table class="info-table">
|
|
381
|
-
${this.user.id?`<tr><td>ID</td><td>${c(String(this.user.id))}</td></tr>`:""}
|
|
382
|
-
${this.user.email?`<tr><td>Email</td><td>${c(this.user.email)}</td></tr>`:""}
|
|
383
|
-
${this.user.name?`<tr><td>Name</td><td>${c(this.user.name)}</td></tr>`:""}
|
|
384
|
-
</table>
|
|
385
|
-
</div>
|
|
386
|
-
</div>
|
|
387
|
-
`:""}
|
|
388
|
-
|
|
389
|
-
${this.config.showQueries&&this.queries.length>0?`
|
|
390
|
-
<div class="card">
|
|
391
|
-
<div class="card-header">\uD83D\uDDC4️ Queries (${this.queries.length})</div>
|
|
392
|
-
<div class="card-body">
|
|
393
|
-
${this.queries.map((v)=>`
|
|
394
|
-
<div class="query-item">
|
|
395
|
-
${c(v.query)}
|
|
396
|
-
${v.time!==void 0?`<div class="query-time">${v.time.toFixed(2)}ms${v.connection?` • ${c(v.connection)}`:""}</div>`:""}
|
|
397
|
-
</div>
|
|
398
|
-
`).join("")}
|
|
399
|
-
</div>
|
|
400
|
-
</div>
|
|
401
|
-
`:""}
|
|
402
|
-
|
|
403
|
-
${this.config.showEnvironment?`
|
|
404
|
-
<div class="card">
|
|
405
|
-
<div class="card-header">⚙️ Environment</div>
|
|
406
|
-
<div class="card-body">
|
|
407
|
-
<table class="info-table">
|
|
408
|
-
<tr><td>Node Version</td><td>${typeof process<"u"?process.version:"N/A"}</td></tr>
|
|
409
|
-
<tr><td>Platform</td><td>${typeof process<"u"?process.platform:"N/A"}</td></tr>
|
|
410
|
-
<tr><td>Architecture</td><td>${typeof process<"u"?process.arch:"N/A"}</td></tr>
|
|
411
|
-
</table>
|
|
412
|
-
</div>
|
|
413
|
-
</div>
|
|
414
|
-
`:""}
|
|
415
|
-
</div>
|
|
416
|
-
</body>
|
|
417
|
-
</html>`}handleError(f,n=500){let l=this.render(f,n);return new Response(l,{status:n,headers:{"Content-Type":"text/html; charset=utf-8"}})}}function V(f){return new W(f)}class T extends Error{status;details;constructor(f,n,l){super(n);this.status=f;if(this.name=t(f),l!==void 0)this.details=l}}function t(f){switch(f){case 400:return"Bad Request";case 401:return"Unauthorized";case 402:return"Payment Required";case 403:return"Forbidden";case 404:return"Not Found";case 405:return"Method Not Allowed";case 408:return"Request Timeout";case 409:return"Conflict";case 410:return"Gone";case 413:return"Payload Too Large";case 415:return"Unsupported Media Type";case 422:return"Unprocessable Entity";case 423:return"Locked";case 425:return"Too Early";case 426:return"Upgrade Required";case 428:return"Precondition Required";case 429:return"Too Many Requests";case 431:return"Request Header Fields Too Large";case 451:return"Unavailable For Legal Reasons";case 500:return"Internal Server Error";case 501:return"Not Implemented";case 502:return"Bad Gateway";case 503:return"Service Unavailable";case 504:return"Gateway Timeout";case 507:return"Insufficient Storage";case 508:return"Loop Detected";case 511:return"Network Authentication Required";default:return f>=400&&f<500?"Client Error":"Server Error"}}class _{handler=V();isDevelopment;constructor(f){if(this.isDevelopment=f?.isDevelopment??!0,f?.config)this.handler=V(f.config);this.handler.setFramework("Stacks")}setRequest(f){return this.handler.setRequest(f),this}setRouting(f){return this.handler.setRouting(f),this}addQuery(f,n,l){return this.handler.addQuery(f,n,l),this}handle(f,n=500){if(this.isDevelopment)return this.handler.handleError(f,n);return new Response(N(n),{status:n,headers:{"Content-Type":"text/html; charset=utf-8"}})}notFound(f){let n=new T(404,f||"The requested resource could not be found.");return this.handle(n,404)}serverError(f){return this.handle(f,500)}forbidden(f){let n=new T(403,f||"You do not have permission to access this resource.");return this.handle(n,403)}unauthorized(f){let n=new T(401,f||"Authentication is required to access this resource.");return this.handle(n,401)}badRequest(f){let n=new T(400,f||"The request was malformed or invalid.");return this.handle(n,400)}validationError(f){let n=new T(422,f||"The request was well-formed but could not be processed.");return this.handle(n,422)}tooManyRequests(f){let n=new T(429,f||"You have exceeded the rate limit.");return this.handle(n,429)}serviceUnavailable(f){let n=new T(503,f||"The service is temporarily unavailable.");return this.handle(n,503)}}function D(f){return new _(f)}function c1(f,n,l){let i=D({isDevelopment:l?.isDevelopment,config:l?.config});if(n)i.setRequest(n);return i.handle(f,l?.status)}function w1(f){let n=D(f);return async(l,i)=>{n.setRequest(i);let v=500;if(l instanceof T)v=l.status;else if("status"in l&&typeof l.status==="number")v=l.status;else if("statusCode"in l&&typeof l.statusCode==="number")v=l.statusCode;return n.handle(l,v)}}class s extends Error{status;constructor(f,n){super(n);this.status=f;this.name="ModelNotFoundException"}}function z1(f,n,l){try{let i=f();if(i instanceof Promise)return i.catch((v)=>{if(l)l(Q.handle(v));return n});return i}catch(i){if(l)l(Q.handle(i));return n}}export{H as writeToLogFile,v1 as setLogPath,z1 as rescue,F1 as renderProductionErrorPage,I1 as renderHttpErrorHints,c1 as renderHttpError,h1 as renderErrorPage,D1 as renderError,$1 as ok,u1 as handleError,Z1 as fromPromise,W1 as errorResponse,w1 as errorMiddleware,Y1 as err,D as createHttpErrorHandler,G1 as createErrorHandler,s as ModelNotFoundException,_ as HttpErrorHandler,T as HttpError,_1 as HTTP_ERRORS,N1 as ErrorPageHandler,Q as ErrorHandler,K1 as ERROR_PAGE_CSS};
|