@stacksjs/error-handling 0.70.87 → 0.70.88

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.
@@ -1,620 +0,0 @@
1
- export const ERROR_PAGE_CSS = `
2
- :root {
3
- --font-sans: ui-sans-serif, system-ui, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
4
- --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
5
- --neutral-50: #fafafa;
6
- --neutral-100: #f5f5f5;
7
- --neutral-200: #e5e5e5;
8
- --neutral-300: #d4d4d4;
9
- --neutral-400: #a3a3a3;
10
- --neutral-500: #737373;
11
- --neutral-600: #525252;
12
- --neutral-700: #404040;
13
- --neutral-800: #262626;
14
- --neutral-900: #171717;
15
- --neutral-950: #0a0a0a;
16
- --rose-100: #ffe4e6;
17
- --rose-200: #fecdd3;
18
- --rose-500: #f43f5e;
19
- --rose-600: #e11d48;
20
- --rose-900: #881337;
21
- --rose-950: #4c0519;
22
- --blue-100: #dbeafe;
23
- --blue-500: #3b82f6;
24
- --blue-600: #2563eb;
25
- --blue-700: #1d4ed8;
26
- --blue-900: #1e3a8a;
27
- --emerald-500: #10b981;
28
- --amber-200: #fde68a;
29
- --amber-600: #d97706;
30
- --amber-900: #78350f;
31
- --white: #fff;
32
- --radius-md: 0.375rem;
33
- --radius-lg: 0.5rem;
34
- --radius-xl: 0.75rem;
35
- }
36
-
37
- * { box-sizing: border-box; margin: 0; padding: 0; }
38
-
39
- html {
40
- -webkit-text-size-adjust: 100%;
41
- color-scheme: light dark;
42
- }
43
-
44
- body {
45
- font-family: var(--font-sans);
46
- -webkit-font-smoothing: antialiased;
47
- -moz-osx-font-smoothing: grayscale;
48
- background: var(--neutral-50);
49
- color: var(--neutral-950);
50
- line-height: 1.5;
51
- min-height: 100dvh;
52
- }
53
-
54
- @media (prefers-color-scheme: dark) {
55
- body {
56
- background: var(--neutral-900);
57
- color: var(--white);
58
- }
59
- }
60
-
61
- .page {
62
- max-width: 80rem;
63
- margin: 0 auto;
64
- padding: 3.5rem 1.5rem 2rem;
65
- }
66
-
67
- @media (min-width: 640px) {
68
- .page { padding: 4rem 3.5rem 2rem; }
69
- }
70
-
71
- /* \u2500\u2500 Header \u2500\u2500 */
72
- .header {
73
- display: flex;
74
- align-items: center;
75
- justify-content: space-between;
76
- gap: 1rem;
77
- margin-bottom: 2rem;
78
- flex-wrap: wrap;
79
- }
80
-
81
- .header-title {
82
- display: flex;
83
- align-items: center;
84
- gap: 0.625rem;
85
- font-size: 0.875rem;
86
- font-weight: 500;
87
- color: var(--neutral-600);
88
- }
89
-
90
- @media (prefers-color-scheme: dark) {
91
- .header-title { color: var(--neutral-400); }
92
- }
93
-
94
- .header-dot {
95
- width: 0.625rem;
96
- height: 0.625rem;
97
- border-radius: 9999px;
98
- background: var(--rose-500);
99
- flex-shrink: 0;
100
- }
101
-
102
- .btn-copy {
103
- display: inline-flex;
104
- align-items: center;
105
- gap: 0.375rem;
106
- padding: 0.375rem 0.75rem;
107
- font-size: 0.75rem;
108
- font-weight: 500;
109
- border: 1px solid var(--neutral-200);
110
- border-radius: var(--radius-md);
111
- background: var(--white);
112
- color: var(--neutral-700);
113
- cursor: pointer;
114
- transition: background 0.15s, border-color 0.15s;
115
- }
116
-
117
- .btn-copy:hover { background: var(--neutral-100); }
118
- .btn-copy.copied { border-color: var(--emerald-500); color: var(--emerald-500); }
119
-
120
- @media (prefers-color-scheme: dark) {
121
- .btn-copy {
122
- background: var(--neutral-800);
123
- border-color: rgba(255,255,255,0.1);
124
- color: var(--neutral-200);
125
- }
126
- .btn-copy:hover { background: rgba(255,255,255,0.05); }
127
- }
128
-
129
- /* \u2500\u2500 Error summary card \u2500\u2500 */
130
- .summary {
131
- margin-bottom: 2rem;
132
- }
133
-
134
- .summary h1 {
135
- font-size: 1.875rem;
136
- font-weight: 600;
137
- line-height: 1.2;
138
- margin-bottom: 0.75rem;
139
- }
140
-
141
- .summary-file {
142
- font-family: var(--font-mono);
143
- font-size: 0.875rem;
144
- color: var(--rose-600);
145
- margin-bottom: 0.75rem;
146
- word-break: break-all;
147
- }
148
-
149
- @media (prefers-color-scheme: dark) {
150
- .summary-file { color: var(--rose-500); }
151
- }
152
-
153
- .summary-message {
154
- font-size: 1.125rem;
155
- color: var(--neutral-800);
156
- margin-bottom: 1.25rem;
157
- word-break: break-word;
158
- }
159
-
160
- @media (prefers-color-scheme: dark) {
161
- .summary-message { color: var(--neutral-200); }
162
- }
163
-
164
- .badges {
165
- display: flex;
166
- flex-wrap: wrap;
167
- gap: 0.5rem;
168
- margin-bottom: 1.25rem;
169
- }
170
-
171
- .badge {
172
- display: inline-flex;
173
- align-items: center;
174
- padding: 0.25rem 0.5rem;
175
- font-size: 0.6875rem;
176
- font-weight: 600;
177
- letter-spacing: 0.04em;
178
- text-transform: uppercase;
179
- border-radius: var(--radius-md);
180
- border: 1px solid var(--neutral-200);
181
- background: var(--neutral-100);
182
- color: var(--neutral-600);
183
- }
184
-
185
- @media (prefers-color-scheme: dark) {
186
- .badge {
187
- border-color: rgba(255,255,255,0.1);
188
- background: rgba(255,255,255,0.05);
189
- color: var(--neutral-400);
190
- }
191
- }
192
-
193
- .badge-status {
194
- background: var(--rose-100);
195
- border-color: var(--rose-200);
196
- color: var(--rose-900);
197
- }
198
-
199
- @media (prefers-color-scheme: dark) {
200
- .badge-status {
201
- background: var(--rose-950);
202
- border-color: var(--rose-900);
203
- color: var(--rose-100);
204
- }
205
- }
206
-
207
- .request-row {
208
- display: flex;
209
- align-items: center;
210
- gap: 0.75rem;
211
- flex-wrap: wrap;
212
- font-size: 0.875rem;
213
- }
214
-
215
- .badge-method {
216
- background: var(--blue-100);
217
- border-color: transparent;
218
- color: var(--blue-900);
219
- font-family: var(--font-mono);
220
- font-size: 0.6875rem;
221
- }
222
-
223
- @media (prefers-color-scheme: dark) {
224
- .badge-method {
225
- background: var(--blue-700);
226
- color: var(--white);
227
- }
228
- }
229
-
230
- .request-url {
231
- font-family: var(--font-mono);
232
- font-size: 0.8125rem;
233
- color: var(--neutral-500);
234
- word-break: break-all;
235
- }
236
-
237
- @media (prefers-color-scheme: dark) {
238
- .request-url { color: var(--neutral-400); }
239
- }
240
-
241
- /* \u2500\u2500 Hints \u2500\u2500 */
242
- .hints {
243
- border: 1px solid var(--amber-200);
244
- border-radius: var(--radius-lg);
245
- background: #fffbeb;
246
- margin-bottom: 2rem;
247
- overflow: hidden;
248
- }
249
-
250
- @media (prefers-color-scheme: dark) {
251
- .hints {
252
- border-color: var(--amber-600);
253
- background: rgba(120, 53, 15, 0.3);
254
- }
255
- }
256
-
257
- .hints-header {
258
- padding: 0.75rem 1rem;
259
- font-size: 0.8125rem;
260
- font-weight: 600;
261
- color: var(--amber-900);
262
- border-bottom: 1px solid var(--amber-200);
263
- }
264
-
265
- @media (prefers-color-scheme: dark) {
266
- .hints-header { color: var(--amber-200); border-bottom-color: rgba(217,119,6,0.3); }
267
- }
268
-
269
- .hints-body {
270
- padding: 1rem;
271
- font-size: 0.875rem;
272
- color: var(--neutral-700);
273
- }
274
-
275
- @media (prefers-color-scheme: dark) {
276
- .hints-body { color: var(--neutral-300); }
277
- }
278
-
279
- .hints-body ul { margin: 0 0 0.75rem 1.25rem; }
280
- .hints-body li { margin: 0.2rem 0; }
281
- .hints-suggestion { font-weight: 500; margin-bottom: 0.5rem; }
282
- .hints-doc { color: var(--blue-600); text-decoration: none; font-size: 0.8125rem; }
283
- .hints-doc:hover { text-decoration: underline; }
284
-
285
- /* \u2500\u2500 Exception trace \u2500\u2500 */
286
- .trace {
287
- margin-bottom: 2rem;
288
- }
289
-
290
- .trace-title {
291
- font-size: 0.875rem;
292
- font-weight: 600;
293
- color: var(--neutral-500);
294
- text-transform: uppercase;
295
- letter-spacing: 0.05em;
296
- margin-bottom: 1rem;
297
- }
298
-
299
- @media (prefers-color-scheme: dark) {
300
- .trace-title { color: var(--neutral-400); }
301
- }
302
-
303
- .trace-frame {
304
- border: 1px solid var(--neutral-200);
305
- border-radius: var(--radius-lg);
306
- margin-bottom: 0.5rem;
307
- overflow: hidden;
308
- background: var(--white);
309
- }
310
-
311
- @media (prefers-color-scheme: dark) {
312
- .trace-frame {
313
- border-color: rgba(255,255,255,0.1);
314
- background: rgba(255,255,255,0.02);
315
- }
316
- }
317
-
318
- .trace-frame-header {
319
- display: flex;
320
- align-items: baseline;
321
- gap: 0.5rem;
322
- padding: 0.75rem 1rem;
323
- cursor: pointer;
324
- font-size: 0.8125rem;
325
- transition: background 0.15s;
326
- }
327
-
328
- .trace-frame-header:hover { background: var(--neutral-50); }
329
-
330
- @media (prefers-color-scheme: dark) {
331
- .trace-frame-header:hover { background: rgba(255,255,255,0.03); }
332
- }
333
-
334
- .trace-frame-fn {
335
- font-family: var(--font-mono);
336
- color: var(--neutral-800);
337
- flex: 1;
338
- min-width: 0;
339
- overflow: hidden;
340
- text-overflow: ellipsis;
341
- white-space: nowrap;
342
- }
343
-
344
- @media (prefers-color-scheme: dark) {
345
- .trace-frame-fn { color: var(--neutral-200); }
346
- }
347
-
348
- .trace-frame-file {
349
- font-family: var(--font-mono);
350
- font-size: 0.75rem;
351
- color: var(--neutral-400);
352
- flex-shrink: 0;
353
- }
354
-
355
- .trace-frame-body {
356
- display: none;
357
- border-top: 1px solid var(--neutral-200);
358
- }
359
-
360
- .trace-frame.expanded .trace-frame-body { display: block; }
361
-
362
- @media (prefers-color-scheme: dark) {
363
- .trace-frame-body { border-top-color: rgba(255,255,255,0.08); }
364
- }
365
-
366
- .trace-vendor {
367
- border: 1px dashed var(--neutral-300);
368
- border-radius: var(--radius-lg);
369
- margin-bottom: 0.5rem;
370
- overflow: hidden;
371
- }
372
-
373
- @media (prefers-color-scheme: dark) {
374
- .trace-vendor { border-color: rgba(255,255,255,0.15); }
375
- }
376
-
377
- .trace-vendor-toggle {
378
- display: flex;
379
- align-items: center;
380
- gap: 0.5rem;
381
- padding: 0.75rem 1rem;
382
- font-size: 0.8125rem;
383
- font-weight: 500;
384
- color: var(--neutral-500);
385
- cursor: pointer;
386
- background: var(--neutral-50);
387
- transition: background 0.15s;
388
- }
389
-
390
- .trace-vendor-toggle:hover { background: var(--neutral-100); }
391
-
392
- @media (prefers-color-scheme: dark) {
393
- .trace-vendor-toggle {
394
- background: rgba(255,255,255,0.03);
395
- color: var(--neutral-400);
396
- }
397
- .trace-vendor-toggle:hover { background: rgba(255,255,255,0.05); }
398
- }
399
-
400
- .trace-vendor-frames { display: none; padding: 0.25rem 0; }
401
- .trace-vendor.expanded .trace-vendor-frames { display: block; }
402
-
403
- /* \u2500\u2500 Code snippet \u2500\u2500 */
404
- .code-block {
405
- overflow-x: auto;
406
- font-family: var(--font-mono);
407
- font-size: 0.8125rem;
408
- line-height: 1.6;
409
- background: var(--neutral-950);
410
- color: #abb2bf;
411
- }
412
-
413
- .code-line {
414
- display: flex;
415
- min-height: 1.5rem;
416
- }
417
-
418
- .code-line:nth-child(odd) { background: rgba(255,255,255,0.02); }
419
- .code-line:nth-child(even) { background: rgba(255,255,255,0.04); }
420
-
421
- .code-line.highlight {
422
- background: rgba(244, 63, 94, 0.25) !important;
423
- }
424
-
425
- .code-ln {
426
- width: 3.5rem;
427
- text-align: right;
428
- padding: 0 1rem 0 0.5rem;
429
- color: var(--neutral-500);
430
- user-select: none;
431
- flex-shrink: 0;
432
- }
433
-
434
- .code-line.highlight .code-ln { color: var(--rose-500); }
435
-
436
- .code-txt {
437
- flex: 1;
438
- padding-right: 1rem;
439
- white-space: pre;
440
- }
441
-
442
- /* \u2500\u2500 Context panels \u2500\u2500 */
443
- .context {
444
- margin-bottom: 2rem;
445
- }
446
-
447
- .context-tabs {
448
- display: flex;
449
- gap: 0;
450
- border-bottom: 2px solid var(--neutral-200);
451
- overflow-x: auto;
452
- }
453
-
454
- @media (prefers-color-scheme: dark) {
455
- .context-tabs { border-bottom-color: rgba(255,255,255,0.1); }
456
- }
457
-
458
- .context-tab {
459
- padding: 0.625rem 1rem;
460
- font-size: 0.8125rem;
461
- font-weight: 500;
462
- color: var(--neutral-500);
463
- background: none;
464
- border: none;
465
- border-bottom: 2px solid transparent;
466
- margin-bottom: -2px;
467
- cursor: pointer;
468
- white-space: nowrap;
469
- transition: color 0.15s;
470
- }
471
-
472
- .context-tab:hover { color: var(--neutral-800); }
473
- .context-tab.active {
474
- color: var(--rose-600);
475
- border-bottom-color: var(--rose-500);
476
- }
477
-
478
- @media (prefers-color-scheme: dark) {
479
- .context-tab:hover { color: var(--neutral-200); }
480
- .context-tab.active { color: var(--rose-500); }
481
- }
482
-
483
- .context-panel {
484
- display: none;
485
- padding: 1.25rem 0;
486
- }
487
-
488
- .context-panel.active { display: block; }
489
-
490
- .kv-table {
491
- width: 100%;
492
- border-collapse: collapse;
493
- font-size: 0.8125rem;
494
- }
495
-
496
- .kv-table tr {
497
- border-bottom: 1px solid var(--neutral-100);
498
- }
499
-
500
- @media (prefers-color-scheme: dark) {
501
- .kv-table tr { border-bottom-color: rgba(255,255,255,0.05); }
502
- }
503
-
504
- .kv-table td {
505
- padding: 0.5rem 0.75rem;
506
- vertical-align: top;
507
- }
508
-
509
- .kv-table td:first-child {
510
- font-weight: 500;
511
- color: var(--neutral-500);
512
- width: 30%;
513
- font-family: var(--font-mono);
514
- font-size: 0.75rem;
515
- word-break: break-all;
516
- }
517
-
518
- @media (prefers-color-scheme: dark) {
519
- .kv-table td:first-child { color: var(--neutral-400); }
520
- }
521
-
522
- .kv-table td:last-child {
523
- font-family: var(--font-mono);
524
- font-size: 0.75rem;
525
- word-break: break-all;
526
- color: var(--neutral-800);
527
- }
528
-
529
- @media (prefers-color-scheme: dark) {
530
- .kv-table td:last-child { color: var(--neutral-200); }
531
- }
532
-
533
- .query-item {
534
- padding: 0.75rem 1rem;
535
- margin-bottom: 0.5rem;
536
- border: 1px solid var(--neutral-200);
537
- border-radius: var(--radius-md);
538
- font-family: var(--font-mono);
539
- font-size: 0.75rem;
540
- background: var(--neutral-50);
541
- }
542
-
543
- @media (prefers-color-scheme: dark) {
544
- .query-item {
545
- border-color: rgba(255,255,255,0.08);
546
- background: rgba(255,255,255,0.03);
547
- }
548
- }
549
-
550
- .query-time {
551
- margin-top: 0.375rem;
552
- font-size: 0.6875rem;
553
- color: var(--neutral-400);
554
- }
555
-
556
- .json-block {
557
- font-family: var(--font-mono);
558
- font-size: 0.75rem;
559
- background: var(--neutral-100);
560
- border-radius: var(--radius-md);
561
- padding: 1rem;
562
- overflow-x: auto;
563
- white-space: pre-wrap;
564
- word-break: break-all;
565
- }
566
-
567
- @media (prefers-color-scheme: dark) {
568
- .json-block {
569
- background: rgba(255,255,255,0.05);
570
- color: var(--neutral-200);
571
- }
572
- }
573
-
574
- /* \u2500\u2500 Production page \u2500\u2500 */
575
- .production-page {
576
- display: flex;
577
- flex-direction: column;
578
- align-items: center;
579
- justify-content: center;
580
- min-height: 100dvh;
581
- text-align: center;
582
- padding: 2rem;
583
- }
584
-
585
- .production-status {
586
- font-size: 6rem;
587
- font-weight: 700;
588
- color: var(--neutral-200);
589
- margin-bottom: 1rem;
590
- line-height: 1;
591
- }
592
-
593
- @media (prefers-color-scheme: dark) {
594
- .production-status { color: var(--neutral-700); }
595
- }
596
-
597
- .production-title {
598
- font-size: 1.5rem;
599
- font-weight: 600;
600
- margin-bottom: 0.5rem;
601
- }
602
-
603
- .production-message {
604
- color: var(--neutral-500);
605
- margin-bottom: 2rem;
606
- max-width: 28rem;
607
- }
608
-
609
- .production-link {
610
- color: var(--blue-600);
611
- text-decoration: none;
612
- font-size: 0.875rem;
613
- }
614
-
615
- .production-link:hover { text-decoration: underline; }
616
-
617
- @media (prefers-color-scheme: dark) {
618
- .production-link { color: var(--blue-500); }
619
- }
620
- `;
@@ -1,66 +0,0 @@
1
- /**
2
- * Escape HTML special characters
3
- */
4
- export declare function escapeHtml(str: string): string;
5
- /**
6
- * Read source lines around a stack frame for the code snippet panel.
7
- */
8
- export declare function readCodeSnippet(filePath: string, line: number, radius?: number): CodeSnippetResult | null;
9
- export declare function renderCodeSnippet(snippet: CodeSnippetResult): string;
10
- export declare function renderTraceFrame(frame: ParsedFrame, index: number, snippetLines: number): string;
11
- export declare function renderVendorGroup(frames: ParsedFrame[], snippetLines: number): string;
12
- export declare function groupTraceFrames(frames: ParsedFrame[]): Array<ParsedFrame | ParsedFrame[]>;
13
- export declare function renderExceptionTrace(frames: ParsedFrame[], snippetLines: number): string;
14
- export declare function renderContextTabs(opts: {
15
- request?: RequestContext
16
- routing?: RoutingContext
17
- user?: UserContext
18
- queries?: QueryInfo[]
19
- showEnvironment?: boolean
20
- }): string;
21
- export declare function buildErrorMarkdown(opts: {
22
- statusTitle: string
23
- errorName: string
24
- errorMessage: string
25
- status: number
26
- file?: string
27
- line?: number
28
- request?: RequestContext
29
- framework?: { name: string, version?: string }
30
- frames: ParsedFrame[]
31
- }): string;
32
- export declare function wrapErrorPage(body: string, markdown: string): string;
33
- export declare const ERROR_PAGE_SCRIPT: string;
34
- export declare interface ParsedFrame {
35
- file: string
36
- line: number
37
- column?: number
38
- function?: string
39
- absoluteFile: string
40
- isFramework: boolean
41
- }
42
- declare interface QueryInfo {
43
- query: string
44
- time?: number
45
- connection?: string
46
- }
47
- declare interface RequestContext {
48
- method: string
49
- url: string
50
- headers: Record<string, string>
51
- queryParams?: Record<string, string>
52
- body?: unknown
53
- }
54
- declare interface RoutingContext {
55
- controller?: string
56
- routeName?: string
57
- middleware?: string[]
58
- }
59
- declare interface UserContext {
60
- id?: string | number
61
- email?: string
62
- name?: string
63
- }
64
- export declare interface CodeSnippetResult {
65
- lines: Array<{ number: number, content: string, highlight: boolean }>
66
- }