@teamvelix/velix 5.2.9 → 5.3.0
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/build/index.js +2 -2
- package/dist/{chunk-YZDIHMDS.js → chunk-H27Z2PL5.js} +3 -3
- package/dist/{chunk-YZDIHMDS.js.map → chunk-H27Z2PL5.js.map} +1 -1
- package/dist/{chunk-RU23OKU5.js → chunk-IH5DV2WC.js} +3 -3
- package/dist/{chunk-RU23OKU5.js.map → chunk-IH5DV2WC.js.map} +1 -1
- package/dist/{chunk-HMCBOHTD.js → chunk-OKEPYKAP.js} +576 -303
- package/dist/chunk-OKEPYKAP.js.map +1 -0
- package/dist/config.d.ts +2 -2
- package/dist/index.js +3 -3
- package/dist/runtime/start-build.js +1 -1
- package/dist/runtime/start-build.js.map +1 -1
- package/dist/runtime/start-dev.js +574 -303
- package/dist/runtime/start-dev.js.map +1 -1
- package/dist/runtime/start-prod.js +574 -303
- package/dist/runtime/start-prod.js.map +1 -1
- package/dist/server/index.js +2 -2
- package/package.json +3 -3
- package/dist/chunk-HMCBOHTD.js.map +0 -1
|
@@ -707,7 +707,7 @@ init_esm_shims();
|
|
|
707
707
|
|
|
708
708
|
// version.ts
|
|
709
709
|
init_esm_shims();
|
|
710
|
-
var VERSION = "5.
|
|
710
|
+
var VERSION = "5.3.0";
|
|
711
711
|
|
|
712
712
|
// logger.ts
|
|
713
713
|
var colors = {
|
|
@@ -1307,73 +1307,76 @@ function generateDevToolsHtml(isDev, ctx = {}) {
|
|
|
1307
1307
|
return `
|
|
1308
1308
|
<style>
|
|
1309
1309
|
/* \u2500\u2500 Velix DevTools v5.1 \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */
|
|
1310
|
-
#__vdt-btn{position:fixed;bottom:16px;left:16px;z-index:9999;width:40px;height:40px;border-radius:
|
|
1311
|
-
#__vdt-btn:hover{transform:scale(1.
|
|
1312
|
-
#__vdt-
|
|
1313
|
-
#__vdt
|
|
1310
|
+
#__vdt-btn{position:fixed;bottom:16px;left:16px;z-index:9999;min-width:40px;height:40px;border-radius:20px;background:#0B1120;border:1px solid rgba(255,255,255,0.1);display:flex;align-items:center;justify-content:center;cursor:pointer;box-shadow:0 4px 16px rgba(0,0,0,.5);transition:all .3s cubic-bezier(0.4, 0, 0.2, 1);outline:none;padding:0 12px;gap:8px;color:#fff;overflow:hidden;}
|
|
1311
|
+
#__vdt-btn:hover{transform:scale(1.05);background:#0F172A;border-color:rgba(255,255,255,0.2);}
|
|
1312
|
+
#__vdt-status-text{font-size:12px;font-weight:600;white-space:nowrap;opacity:0;max-width:0;transition:all .3s cubic-bezier(0.4, 0, 0.2, 1);font-family:ui-sans-serif,system-ui,sans-serif;letter-spacing:0.3px;}
|
|
1313
|
+
#__vdt-btn.vdt-compiling #__vdt-status-text, #__vdt-btn.vdt-navigating #__vdt-status-text{opacity:1;max-width:120px;}
|
|
1314
|
+
|
|
1315
|
+
#__vdt-dot{display:none;}
|
|
1316
|
+
#__vdt{display:none;position:fixed;bottom:68px;left:16px;width:340px;background:#0B1120;color:#f3f4f6;border-radius:14px;font-family:ui-sans-serif,system-ui,-apple-system,BlinkMacSystemFont,'Segoe UI',sans-serif;font-size:13px;box-shadow:0 24px 60px rgba(0,0,0,.6);z-index:10000;border:1px solid #0F172A;overflow:hidden;}
|
|
1314
1317
|
/* header */
|
|
1315
|
-
.__vdt-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #
|
|
1318
|
+
.__vdt-header{display:flex;align-items:center;justify-content:space-between;padding:12px 16px;border-bottom:1px solid #0F172A;}
|
|
1316
1319
|
.__vdt-brand{display:flex;align-items:center;gap:8px;font-weight:700;font-size:14px;color:#f9fafb;}
|
|
1317
|
-
.__vdt-badge{font-size:11px;font-weight:600;background:#
|
|
1320
|
+
.__vdt-badge{font-size:11px;font-weight:600;background:#0F172A;color:#9ca3af;border-radius:5px;padding:2px 7px;letter-spacing:.3px;}
|
|
1318
1321
|
.__vdt-close{background:none;border:none;color:#6b7280;cursor:pointer;font-size:20px;line-height:1;padding:0;transition:color .15s;}
|
|
1319
1322
|
.__vdt-close:hover{color:#f9fafb;}
|
|
1320
1323
|
/* tabs */
|
|
1321
|
-
.__vdt-tabs{display:flex;border-bottom:1px solid #
|
|
1324
|
+
.__vdt-tabs{display:flex;border-bottom:1px solid #0F172A;}
|
|
1322
1325
|
.__vdt-tab{flex:1;padding:10px 0;background:none;border:none;color:#6b7280;font-size:12px;font-weight:500;cursor:pointer;display:flex;align-items:center;justify-content:center;gap:5px;border-bottom:2px solid transparent;transition:color .15s,border-color .15s;font-family:inherit;letter-spacing:.1px;}
|
|
1323
1326
|
.__vdt-tab:hover{color:#d1d5db;}
|
|
1324
|
-
.__vdt-tab.active{color:#
|
|
1327
|
+
.__vdt-tab.active{color:#2563EB;border-bottom-color:#2563EB;}
|
|
1325
1328
|
/* body */
|
|
1326
1329
|
.__vdt-body{padding:14px 16px;min-height:200px;}
|
|
1327
1330
|
.__vdt-section{margin-bottom:14px;}
|
|
1328
1331
|
.__vdt-label{font-size:11px;color:#6b7280;text-transform:uppercase;letter-spacing:.6px;margin-bottom:8px;}
|
|
1329
|
-
.__vdt-box{background:#
|
|
1330
|
-
.__vdt-row{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#
|
|
1332
|
+
.__vdt-box{background:#0F172A;border-radius:8px;padding:10px 13px;font-size:13px;color:#e5e7eb;font-family:ui-monospace,'Cascadia Code','Fira Code',monospace;border:1px solid #162032;}
|
|
1333
|
+
.__vdt-row{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#0F172A;border-radius:8px;margin-bottom:6px;border:1px solid #162032;}
|
|
1331
1334
|
.__vdt-row-left{display:flex;align-items:center;gap:8px;color:#d1d5db;}
|
|
1332
|
-
.__vdt-row-right{font-family:ui-monospace,'Cascadia Code',monospace;color:#
|
|
1335
|
+
.__vdt-row-right{font-family:ui-monospace,'Cascadia Code',monospace;color:#2563EB;font-size:12px;font-weight:500;}
|
|
1333
1336
|
.__vdt-pill{font-size:10px;font-weight:600;padding:2px 7px;border-radius:4px;letter-spacing:.2px;}
|
|
1334
|
-
.__vdt-pill-green{background:#
|
|
1337
|
+
.__vdt-pill-green{background:#162032;color:#38BDF8;border:1px solid #2563EB;}
|
|
1335
1338
|
.__vdt-pill-blue{background:#0c1a3a;color:#60a5fa;border:1px solid #1e3a8a;}
|
|
1336
|
-
.__vdt-render{display:flex;align-items:center;gap:6px;padding:8px 13px;background:#
|
|
1339
|
+
.__vdt-render{display:flex;align-items:center;gap:6px;padding:8px 13px;background:#0F172A;border-radius:8px;border:1px solid #162032;color:#9ca3af;font-size:12px;}
|
|
1337
1340
|
.__vdt-render svg{color:#6b7280;}
|
|
1338
1341
|
/* vitals */
|
|
1339
|
-
.__vdt-vital{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#
|
|
1342
|
+
.__vdt-vital{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#0F172A;border-radius:8px;margin-bottom:6px;border:1px solid #162032;}
|
|
1340
1343
|
.__vdt-vital-left{display:flex;align-items:center;gap:8px;}
|
|
1341
|
-
.__vdt-dot-good{width:8px;height:8px;border-radius:50%;background:#
|
|
1344
|
+
.__vdt-dot-good{width:8px;height:8px;border-radius:50%;background:#2563EB;flex-shrink:0;}
|
|
1342
1345
|
.__vdt-dot-warn{width:8px;height:8px;border-radius:50%;background:#f59e0b;flex-shrink:0;}
|
|
1343
1346
|
.__vdt-dot-bad{width:8px;height:8px;border-radius:50%;background:#ef4444;flex-shrink:0;}
|
|
1344
1347
|
.__vdt-vital-name{color:#d1d5db;font-weight:500;}
|
|
1345
|
-
.__vdt-vital-val{font-family:ui-monospace,'Cascadia Code',monospace;color:#
|
|
1346
|
-
.__vdt-build{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;color:#9ca3af;font-size:12px;border-top:1px solid #
|
|
1348
|
+
.__vdt-vital-val{font-family:ui-monospace,'Cascadia Code',monospace;color:#2563EB;font-size:12px;font-weight:600;}
|
|
1349
|
+
.__vdt-build{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;color:#9ca3af;font-size:12px;border-top:1px solid #162032;margin-top:8px;padding-top:12px;}
|
|
1347
1350
|
/* info rows */
|
|
1348
|
-
.__vdt-info-row{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#
|
|
1351
|
+
.__vdt-info-row{display:flex;align-items:center;justify-content:space-between;padding:9px 13px;background:#0F172A;border-radius:8px;margin-bottom:6px;border:1px solid #162032;}
|
|
1349
1352
|
.__vdt-info-left{display:flex;align-items:center;gap:8px;color:#d1d5db;}
|
|
1350
1353
|
.__vdt-info-val{font-family:ui-monospace,'Cascadia Code',monospace;color:#9ca3af;font-size:12px;}
|
|
1351
|
-
.__vdt-dev-badge{display:flex;align-items:center;gap:8px;padding:10px 13px;background:#
|
|
1354
|
+
.__vdt-dev-badge{display:flex;align-items:center;gap:8px;padding:10px 13px;background:#162032;border:1px solid #2563EB;border-radius:8px;color:#38BDF8;font-size:12px;font-weight:500;margin-top:10px;}
|
|
1352
1355
|
/* footer */
|
|
1353
|
-
.__vdt-footer{padding:10px 16px;border-top:1px solid #
|
|
1356
|
+
.__vdt-footer{padding:10px 16px;border-top:1px solid #0F172A;display:flex;align-items:center;justify-content:space-between;}
|
|
1354
1357
|
.__vdt-host{color:#6b7280;font-size:11px;font-family:ui-monospace,'Cascadia Code',monospace;}
|
|
1355
|
-
.__vdt-conn{display:flex;align-items:center;gap:5px;font-size:11px;color:#
|
|
1356
|
-
.__vdt-conn-dot{width:6px;height:6px;border-radius:50%;background:#
|
|
1358
|
+
.__vdt-conn{display:flex;align-items:center;gap:5px;font-size:11px;color:#2563EB;}
|
|
1359
|
+
.__vdt-conn-dot{width:6px;height:6px;border-radius:50%;background:#2563EB;}
|
|
1357
1360
|
|
|
1358
1361
|
/* \u2500\u2500 Widget state colors \u2500\u2500 */
|
|
1359
1362
|
.vdt-idle{border-color:#22D3EE !important;}
|
|
1360
|
-
.vdt-compiling{border-color:#
|
|
1363
|
+
.vdt-compiling{border-color:#38BDF8 !important;}
|
|
1361
1364
|
.vdt-rendering{border-color:#fb923c !important;}
|
|
1362
1365
|
.vdt-navigating{border-color:#60a5fa !important;}
|
|
1363
1366
|
.vdt-error{border-color:#f87171 !important;}
|
|
1364
1367
|
#__vdt-dot.idle{background:#22D3EE;}
|
|
1365
|
-
#__vdt-dot.compiling{background:#
|
|
1368
|
+
#__vdt-dot.compiling{background:#38BDF8;}
|
|
1366
1369
|
#__vdt-dot.rendering{background:#fb923c;}
|
|
1367
1370
|
#__vdt-dot.navigating{background:#60a5fa;}
|
|
1368
1371
|
#__vdt-dot.error{background:#f87171;}
|
|
1369
1372
|
@keyframes __vdt-pulse{0%,100%{opacity:1;}50%{opacity:.4;}}
|
|
1370
|
-
.vdt-compiling
|
|
1373
|
+
.vdt-compiling svg, .vdt-navigating svg{animation:__vdt-pulse .8s alternate infinite;}
|
|
1371
1374
|
</style>
|
|
1372
1375
|
|
|
1373
1376
|
<!-- \u2500\u2500 Floating button \u2500\u2500 -->
|
|
1374
1377
|
<button id="__vdt-btn" class="vdt-idle" onclick="__vdtOpen()" title="Velix DevTools (${version})">
|
|
1375
1378
|
${ICON_LOGO}
|
|
1376
|
-
<
|
|
1379
|
+
<span id="__vdt-status-text"></span>
|
|
1377
1380
|
</button>
|
|
1378
1381
|
|
|
1379
1382
|
<!-- \u2500\u2500 Panel \u2500\u2500 -->
|
|
@@ -1524,7 +1527,7 @@ function generateDevToolsHtml(isDev, ctx = {}) {
|
|
|
1524
1527
|
dot.className = v <= threshGood ? '__vdt-dot-good' : v <= threshOk ? '__vdt-dot-warn' : '__vdt-dot-bad';
|
|
1525
1528
|
}
|
|
1526
1529
|
if(el && typeof v === 'number'){
|
|
1527
|
-
el.style.color = v <= threshGood ? '#
|
|
1530
|
+
el.style.color = v <= threshGood ? '#2563EB' : v <= threshOk ? '#f59e0b' : '#ef4444';
|
|
1528
1531
|
}
|
|
1529
1532
|
}
|
|
1530
1533
|
|
|
@@ -1574,13 +1577,18 @@ function generateDevToolsHtml(isDev, ctx = {}) {
|
|
|
1574
1577
|
|
|
1575
1578
|
function setStatus(s){
|
|
1576
1579
|
if(btn){ btn.className = 'vdt-' + s; }
|
|
1577
|
-
|
|
1580
|
+
var text = document.getElementById('__vdt-status-text');
|
|
1581
|
+
if(text) {
|
|
1582
|
+
if(s === 'compiling') text.textContent = 'Compiling...';
|
|
1583
|
+
else if(s === 'navigating') text.textContent = 'Loading...';
|
|
1584
|
+
else text.textContent = '';
|
|
1585
|
+
}
|
|
1578
1586
|
}
|
|
1579
1587
|
|
|
1580
1588
|
function setConn(ok){
|
|
1581
|
-
if(connDot) connDot.style.background = ok ? '#
|
|
1589
|
+
if(connDot) connDot.style.background = ok ? '#2563EB' : '#ef4444';
|
|
1582
1590
|
if(connText) connText.textContent = ok ? 'connected' : 'disconnected';
|
|
1583
|
-
if(connText) connText.style.color = ok ? '#
|
|
1591
|
+
if(connText) connText.style.color = ok ? '#2563EB' : '#ef4444';
|
|
1584
1592
|
}
|
|
1585
1593
|
|
|
1586
1594
|
var ws = new WebSocket('ws://' + window.location.host + '/__velix_hmr');
|
|
@@ -1635,88 +1643,203 @@ function generate404Page(pathname = "/") {
|
|
|
1635
1643
|
<head>
|
|
1636
1644
|
<meta charset="UTF-8">
|
|
1637
1645
|
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
|
1638
|
-
<title>404
|
|
1646
|
+
<title>404 \u2014 Page Not Found | Velix v${VERSION}</title>
|
|
1639
1647
|
<link rel="icon" href="/favicon.webp">
|
|
1648
|
+
<link rel="preconnect" href="https://fonts.googleapis.com">
|
|
1649
|
+
<link href="https://fonts.googleapis.com/css2?family=DM+Mono:wght@400;500&display=swap" rel="stylesheet">
|
|
1640
1650
|
<style>
|
|
1641
1651
|
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1652
|
+
|
|
1653
|
+
@keyframes fadeUp {
|
|
1654
|
+
from { opacity: 0; transform: translateY(16px); }
|
|
1655
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1656
|
+
}
|
|
1657
|
+
@keyframes pulse {
|
|
1658
|
+
0%, 100% { opacity: 1; }
|
|
1659
|
+
50% { opacity: 0.4; }
|
|
1660
|
+
}
|
|
1661
|
+
|
|
1642
1662
|
body {
|
|
1643
|
-
background: #
|
|
1644
|
-
|
|
1645
|
-
|
|
1663
|
+
background-color: #0B1120;
|
|
1664
|
+
background-image:
|
|
1665
|
+
linear-gradient(to right, rgba(255, 255, 255, 0.05) 1px, transparent 1px),
|
|
1666
|
+
linear-gradient(to bottom, rgba(255, 255, 255, 0.05) 1px, transparent 1px);
|
|
1667
|
+
background-size: 60px 60px;
|
|
1668
|
+
color: #F8FAFC;
|
|
1669
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
|
|
1646
1670
|
display: flex;
|
|
1671
|
+
flex-direction: column;
|
|
1647
1672
|
align-items: center;
|
|
1648
1673
|
justify-content: center;
|
|
1649
1674
|
min-height: 100vh;
|
|
1675
|
+
padding: 2rem;
|
|
1650
1676
|
-webkit-font-smoothing: antialiased;
|
|
1651
1677
|
}
|
|
1652
|
-
|
|
1678
|
+
|
|
1679
|
+
/* radial vignette over the grid */
|
|
1680
|
+
body::before {
|
|
1681
|
+
content: '';
|
|
1682
|
+
position: fixed;
|
|
1683
|
+
inset: 0;
|
|
1684
|
+
background: radial-gradient(ellipse 80% 60% at 50% 50%, transparent 0%, #0B1120 80%);
|
|
1685
|
+
pointer-events: none;
|
|
1686
|
+
z-index: 0;
|
|
1687
|
+
}
|
|
1688
|
+
|
|
1689
|
+
.card {
|
|
1690
|
+
position: relative;
|
|
1691
|
+
z-index: 1;
|
|
1653
1692
|
display: flex;
|
|
1693
|
+
flex-direction: column;
|
|
1654
1694
|
align-items: center;
|
|
1655
|
-
|
|
1656
|
-
|
|
1695
|
+
text-align: center;
|
|
1696
|
+
max-width: 480px;
|
|
1697
|
+
animation: fadeUp 0.25s ease forwards;
|
|
1657
1698
|
}
|
|
1658
|
-
|
|
1659
|
-
|
|
1660
|
-
|
|
1699
|
+
|
|
1700
|
+
/* \u2500\u2500 glowing 404 number \u2500\u2500 */
|
|
1701
|
+
.status-number {
|
|
1702
|
+
font-family: 'DM Mono', monospace;
|
|
1703
|
+
font-size: clamp(80px, 18vw, 140px);
|
|
1704
|
+
font-weight: 500;
|
|
1661
1705
|
line-height: 1;
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
}
|
|
1666
|
-
.body h1 {
|
|
1667
|
-
font-size: 18px;
|
|
1668
|
-
font-weight: 600;
|
|
1669
|
-
color: #ededed;
|
|
1706
|
+
letter-spacing: -0.04em;
|
|
1707
|
+
color: #F8FAFC;
|
|
1708
|
+
position: relative;
|
|
1670
1709
|
margin-bottom: 8px;
|
|
1671
1710
|
}
|
|
1672
|
-
.
|
|
1673
|
-
|
|
1674
|
-
|
|
1675
|
-
|
|
1711
|
+
.status-number::after {
|
|
1712
|
+
content: attr(data-value);
|
|
1713
|
+
position: absolute;
|
|
1714
|
+
inset: 0;
|
|
1715
|
+
color: #2563EB;
|
|
1716
|
+
opacity: 0.12;
|
|
1717
|
+
filter: blur(24px);
|
|
1718
|
+
pointer-events: none;
|
|
1719
|
+
}
|
|
1720
|
+
|
|
1721
|
+
/* \u2500\u2500 accent line \u2500\u2500 */
|
|
1722
|
+
.accent-line {
|
|
1723
|
+
width: 40px;
|
|
1724
|
+
height: 3px;
|
|
1725
|
+
background: #2563EB;
|
|
1726
|
+
border-radius: 9999px;
|
|
1727
|
+
margin-bottom: 24px;
|
|
1676
1728
|
}
|
|
1677
|
-
|
|
1678
|
-
|
|
1729
|
+
|
|
1730
|
+
/* \u2500\u2500 heading \u2500\u2500 */
|
|
1731
|
+
h1 {
|
|
1732
|
+
font-size: 22px;
|
|
1733
|
+
font-weight: 700;
|
|
1734
|
+
color: #fff;
|
|
1735
|
+
margin-bottom: 10px;
|
|
1736
|
+
letter-spacing: -0.01em;
|
|
1737
|
+
}
|
|
1738
|
+
|
|
1739
|
+
/* \u2500\u2500 route badge \u2500\u2500 */
|
|
1740
|
+
.route-badge {
|
|
1741
|
+
display: inline-flex;
|
|
1742
|
+
align-items: center;
|
|
1743
|
+
gap: 8px;
|
|
1744
|
+
font-family: 'DM Mono', monospace;
|
|
1679
1745
|
font-size: 13px;
|
|
1680
|
-
|
|
1681
|
-
|
|
1682
|
-
border
|
|
1683
|
-
|
|
1746
|
+
color: #94A3B8;
|
|
1747
|
+
background: #0F172A;
|
|
1748
|
+
border: 1px solid #1E293B;
|
|
1749
|
+
padding: 5px 14px;
|
|
1750
|
+
border-radius: 9999px;
|
|
1751
|
+
margin-bottom: 32px;
|
|
1752
|
+
}
|
|
1753
|
+
.route-badge .dot {
|
|
1754
|
+
width: 6px;
|
|
1755
|
+
height: 6px;
|
|
1756
|
+
border-radius: 50%;
|
|
1757
|
+
background: #ff6b6b;
|
|
1758
|
+
animation: pulse 1.8s ease-in-out infinite;
|
|
1759
|
+
flex-shrink: 0;
|
|
1760
|
+
}
|
|
1761
|
+
|
|
1762
|
+
/* \u2500\u2500 actions \u2500\u2500 */
|
|
1763
|
+
.actions {
|
|
1764
|
+
display: flex;
|
|
1765
|
+
gap: 12px;
|
|
1684
1766
|
}
|
|
1685
|
-
.actions { display: flex; gap: 10px; }
|
|
1686
1767
|
.btn {
|
|
1687
|
-
display: inline-
|
|
1688
|
-
|
|
1689
|
-
|
|
1768
|
+
display: inline-flex;
|
|
1769
|
+
align-items: center;
|
|
1770
|
+
gap: 6px;
|
|
1771
|
+
padding: 10px 22px;
|
|
1772
|
+
border-radius: 10px;
|
|
1690
1773
|
font-size: 14px;
|
|
1691
|
-
font-weight:
|
|
1774
|
+
font-weight: 600;
|
|
1692
1775
|
text-decoration: none;
|
|
1693
|
-
transition: all .15s;
|
|
1694
|
-
border: 1px solid transparent;
|
|
1776
|
+
transition: all 0.15s ease;
|
|
1695
1777
|
}
|
|
1696
1778
|
.btn-primary {
|
|
1697
|
-
background: #
|
|
1698
|
-
color: #
|
|
1779
|
+
background: #2563EB;
|
|
1780
|
+
color: #0B1120;
|
|
1781
|
+
border: 1px solid #2563EB;
|
|
1782
|
+
}
|
|
1783
|
+
.btn-primary:hover {
|
|
1784
|
+
background: #3B82F6;
|
|
1785
|
+
transform: translateY(-1px);
|
|
1786
|
+
box-shadow: 0 0 20px rgba(37, 99, 235, 0.35);
|
|
1699
1787
|
}
|
|
1700
|
-
.btn-primary:hover { background: #e5e5e5; }
|
|
1701
1788
|
.btn-secondary {
|
|
1702
|
-
background:
|
|
1703
|
-
color: #
|
|
1704
|
-
border
|
|
1789
|
+
background: transparent;
|
|
1790
|
+
color: #F8FAFC;
|
|
1791
|
+
border: 1px solid #1E293B;
|
|
1792
|
+
}
|
|
1793
|
+
.btn-secondary:hover {
|
|
1794
|
+
background: #0F172A;
|
|
1795
|
+
border-color: #334155;
|
|
1796
|
+
}
|
|
1797
|
+
|
|
1798
|
+
/* \u2500\u2500 footer branding \u2500\u2500 */
|
|
1799
|
+
.brand {
|
|
1800
|
+
position: fixed;
|
|
1801
|
+
bottom: 28px;
|
|
1802
|
+
left: 50%;
|
|
1803
|
+
transform: translateX(-50%);
|
|
1804
|
+
display: flex;
|
|
1805
|
+
align-items: center;
|
|
1806
|
+
gap: 8px;
|
|
1807
|
+
font-size: 12px;
|
|
1808
|
+
color: #475569;
|
|
1809
|
+
font-family: 'DM Mono', monospace;
|
|
1810
|
+
}
|
|
1811
|
+
.brand-dot {
|
|
1812
|
+
width: 6px;
|
|
1813
|
+
height: 6px;
|
|
1814
|
+
border-radius: 50%;
|
|
1815
|
+
background: #2563EB;
|
|
1705
1816
|
}
|
|
1706
|
-
.btn-secondary:hover { background: rgba(255,255,255,0.1); }
|
|
1707
1817
|
</style>
|
|
1708
1818
|
</head>
|
|
1709
1819
|
<body>
|
|
1710
|
-
<div class="
|
|
1711
|
-
|
|
1712
|
-
|
|
1713
|
-
|
|
1714
|
-
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1820
|
+
<div class="card">
|
|
1821
|
+
<div class="status-number" data-value="404">404</div>
|
|
1822
|
+
<div class="accent-line"></div>
|
|
1823
|
+
<h1>Page not found</h1>
|
|
1824
|
+
<div class="route-badge">
|
|
1825
|
+
<span class="dot"></span>
|
|
1826
|
+
<span>${escapeHtml2(pathname)}</span>
|
|
1827
|
+
</div>
|
|
1828
|
+
<div class="actions">
|
|
1829
|
+
<a href="/" class="btn btn-primary">
|
|
1830
|
+
<svg width="14" height="14" fill="none" viewBox="0 0 24 24"><path d="M3 12L12 3l9 9M5 10v9a1 1 0 001 1h4v-5h4v5h4a1 1 0 001-1v-9" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
1831
|
+
Home
|
|
1832
|
+
</a>
|
|
1833
|
+
<a href="javascript:history.back()" class="btn btn-secondary">
|
|
1834
|
+
<svg width="14" height="14" fill="none" viewBox="0 0 24 24"><path d="M19 12H5M5 12l7-7M5 12l7 7" stroke="currentColor" stroke-width="2.5" stroke-linecap="round" stroke-linejoin="round"/></svg>
|
|
1835
|
+
Go back
|
|
1836
|
+
</a>
|
|
1837
|
+
</div>
|
|
1838
|
+
</div>
|
|
1839
|
+
|
|
1840
|
+
<div class="brand">
|
|
1841
|
+
<span class="brand-dot"></span>
|
|
1842
|
+
Velix v${VERSION}
|
|
1720
1843
|
</div>
|
|
1721
1844
|
</body>
|
|
1722
1845
|
</html>`;
|
|
@@ -1747,14 +1870,23 @@ function generate500Page(options) {
|
|
|
1747
1870
|
const src = fs8.readFileSync(errorFile, "utf-8").split("\n");
|
|
1748
1871
|
const start = Math.max(0, errorLine - 4);
|
|
1749
1872
|
const end = Math.min(src.length, errorLine + 3);
|
|
1873
|
+
const syntaxHighlight = (code) => {
|
|
1874
|
+
let hl = code;
|
|
1875
|
+
hl = hl.replace(/\\b(let|const|function|return|import|export|if|else|for|while|await|async|class|var)\\b/g, '<span style="color:#c084fc">$1</span>');
|
|
1876
|
+
hl = hl.replace(/(".*?"|'.*?'|`.*?`)/g, '<span style="color:#86efac">$1</span>');
|
|
1877
|
+
hl = hl.replace(/(\\/\\/.*)$/g, '<span style="color:#94A3B8">$1</span>');
|
|
1878
|
+
hl = hl.replace(/\\b(\\d+)\\b/g, '<span style="color:#f59e0b">$1</span>');
|
|
1879
|
+
return hl;
|
|
1880
|
+
};
|
|
1750
1881
|
sourceSnippet = src.slice(start, end).map((l, i) => {
|
|
1751
1882
|
const num = start + i + 1;
|
|
1752
1883
|
const isErr = num === errorLine;
|
|
1753
1884
|
const numStr = String(num).padStart(3, " ");
|
|
1885
|
+
const highlightedLine = syntaxHighlight(escapeHtml2(l));
|
|
1754
1886
|
if (isErr) {
|
|
1755
|
-
return `<div class="src-line src-err"><span class="ln">${numStr}</span>${
|
|
1887
|
+
return `<div class="src-line src-err"><span class="ln">${numStr}</span><span class="active-arrow">\u25B6</span><span class="code-content">${highlightedLine}</span></div>`;
|
|
1756
1888
|
}
|
|
1757
|
-
return `<div class="src-line"><span class="ln">${numStr}</span>${
|
|
1889
|
+
return `<div class="src-line"><span class="ln">${numStr}</span><span class="active-arrow"> </span><span class="code-content">${highlightedLine}</span></div>`;
|
|
1758
1890
|
}).join("");
|
|
1759
1891
|
}
|
|
1760
1892
|
} catch (_) {
|
|
@@ -1762,6 +1894,13 @@ function generate500Page(options) {
|
|
|
1762
1894
|
}
|
|
1763
1895
|
}
|
|
1764
1896
|
}
|
|
1897
|
+
const formatErrorMessage = (msg) => {
|
|
1898
|
+
let formatted = escapeHtml2(msg);
|
|
1899
|
+
const pathSpan = `<span style="color:#2563EB;cursor:pointer;" onclick="console.log('open in editor')">`;
|
|
1900
|
+
formatted = formatted.replace(/([A-Z]:\\[^\s<]+|\/(?:Users|home|var|srv)\/[^\s<]+)/g, pathSpan + "$1</span>");
|
|
1901
|
+
formatted = formatted.replace(/(ERROR:)/g, '<strong style="color:#ff6b6b">$1</strong>');
|
|
1902
|
+
return formatted;
|
|
1903
|
+
};
|
|
1765
1904
|
const userFrames = frames.filter((f) => f.file && !f.file.includes("node_modules"));
|
|
1766
1905
|
const ignoredFrames = frames.filter((f) => !f.file || f.file.includes("node_modules"));
|
|
1767
1906
|
const shortFile = errorFile.replace(/\\/g, "/").replace(/.*\/(?=app\/|server\/|src\/|pages\/)/, "");
|
|
@@ -1776,7 +1915,7 @@ function generate500Page(options) {
|
|
|
1776
1915
|
<style>
|
|
1777
1916
|
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1778
1917
|
body {
|
|
1779
|
-
background: #
|
|
1918
|
+
background: #0B1120;
|
|
1780
1919
|
color: #ededed;
|
|
1781
1920
|
font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
1782
1921
|
display: flex; align-items: center; justify-content: center;
|
|
@@ -1811,327 +1950,459 @@ function generate500Page(options) {
|
|
|
1811
1950
|
<title>Error | Velix v${VERSION}</title>
|
|
1812
1951
|
<link rel="icon" href="/favicon.webp">
|
|
1813
1952
|
<style>
|
|
1953
|
+
@import url('https://fonts.googleapis.com/css2?family=DM+Mono:ital,wght@0,300;0,400;0,500;1,300;1,400;1,500&display=swap');
|
|
1954
|
+
|
|
1814
1955
|
*, *::before, *::after { margin: 0; padding: 0; box-sizing: border-box; }
|
|
1815
1956
|
|
|
1957
|
+
@keyframes fadeIn {
|
|
1958
|
+
from { opacity: 0; transform: translateY(10px); }
|
|
1959
|
+
to { opacity: 1; transform: translateY(0); }
|
|
1960
|
+
}
|
|
1961
|
+
|
|
1816
1962
|
body {
|
|
1817
|
-
background:
|
|
1818
|
-
|
|
1819
|
-
|
|
1963
|
+
background-color: #0B1120;
|
|
1964
|
+
background-image:
|
|
1965
|
+
linear-gradient(to right, rgba(255, 255, 255, 0.03) 1px, transparent 1px),
|
|
1966
|
+
linear-gradient(to bottom, rgba(255, 255, 255, 0.03) 1px, transparent 1px);
|
|
1967
|
+
background-size: 60px 60px;
|
|
1968
|
+
color: #F8FAFC;
|
|
1969
|
+
font-family: system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
|
|
1820
1970
|
min-height: 100vh;
|
|
1821
1971
|
display: flex;
|
|
1822
|
-
align-items:
|
|
1972
|
+
align-items: flex-start;
|
|
1823
1973
|
justify-content: center;
|
|
1824
|
-
padding:
|
|
1974
|
+
padding: 2rem;
|
|
1825
1975
|
-webkit-font-smoothing: antialiased;
|
|
1826
1976
|
}
|
|
1827
1977
|
|
|
1828
|
-
/*
|
|
1829
|
-
.
|
|
1978
|
+
/* Radial mask for the grid background */
|
|
1979
|
+
.bg-mask {
|
|
1980
|
+
position: fixed;
|
|
1981
|
+
top: 0; left: 0; right: 0; bottom: 0;
|
|
1982
|
+
background: radial-gradient(circle at center, transparent 0%, #0B1120 80%);
|
|
1983
|
+
z-index: -1;
|
|
1984
|
+
pointer-events: none;
|
|
1985
|
+
}
|
|
1986
|
+
|
|
1987
|
+
/* \u2500\u2500 Main Container \u2500\u2500 */
|
|
1988
|
+
.container {
|
|
1830
1989
|
width: 100%;
|
|
1831
|
-
max-width:
|
|
1832
|
-
|
|
1833
|
-
|
|
1834
|
-
border-radius: 12px;
|
|
1835
|
-
box-shadow: 0 24px 64px rgba(0,0,0,0.6);
|
|
1836
|
-
overflow: hidden;
|
|
1990
|
+
max-width: 780px;
|
|
1991
|
+
margin-top: 4vh;
|
|
1992
|
+
animation: fadeIn 0.2s ease forwards;
|
|
1837
1993
|
display: flex;
|
|
1838
1994
|
flex-direction: column;
|
|
1839
|
-
|
|
1995
|
+
gap: 24px;
|
|
1840
1996
|
}
|
|
1841
1997
|
|
|
1842
1998
|
/* \u2500\u2500 Header Bar \u2500\u2500 */
|
|
1843
1999
|
.header {
|
|
2000
|
+
position: relative;
|
|
2001
|
+
background: transparent;
|
|
1844
2002
|
display: flex;
|
|
1845
2003
|
align-items: center;
|
|
1846
2004
|
justify-content: space-between;
|
|
1847
|
-
padding: 12px
|
|
1848
|
-
|
|
1849
|
-
|
|
1850
|
-
|
|
1851
|
-
|
|
2005
|
+
padding-top: 12px;
|
|
2006
|
+
}
|
|
2007
|
+
.header::before {
|
|
2008
|
+
content: '';
|
|
2009
|
+
position: absolute;
|
|
2010
|
+
top: -12px; left: 0; right: 0;
|
|
2011
|
+
height: 4px;
|
|
2012
|
+
background: #ff6b6b;
|
|
2013
|
+
border-radius: 4px;
|
|
1852
2014
|
}
|
|
1853
2015
|
.header-left {
|
|
1854
2016
|
display: flex;
|
|
1855
2017
|
align-items: center;
|
|
1856
|
-
gap:
|
|
1857
|
-
font-size: 13px;
|
|
1858
|
-
color: #888;
|
|
2018
|
+
gap: 12px;
|
|
1859
2019
|
}
|
|
1860
|
-
.
|
|
1861
|
-
|
|
1862
|
-
|
|
1863
|
-
|
|
1864
|
-
|
|
2020
|
+
.header-icon {
|
|
2021
|
+
width: 20px;
|
|
2022
|
+
height: 20px;
|
|
2023
|
+
fill: #ff6b6b;
|
|
2024
|
+
}
|
|
2025
|
+
.header-title {
|
|
2026
|
+
font-size: 18px;
|
|
2027
|
+
font-weight: 700;
|
|
2028
|
+
color: #fff;
|
|
2029
|
+
}
|
|
2030
|
+
.dev-badge {
|
|
2031
|
+
background: rgba(255, 107, 107, 0.1);
|
|
2032
|
+
border: 1px solid rgba(255, 107, 107, 0.2);
|
|
2033
|
+
color: #ff6b6b;
|
|
2034
|
+
padding: 2px 10px;
|
|
2035
|
+
border-radius: 9999px;
|
|
1865
2036
|
font-size: 12px;
|
|
1866
|
-
|
|
1867
|
-
|
|
2037
|
+
font-weight: 600;
|
|
2038
|
+
letter-spacing: 0.05em;
|
|
1868
2039
|
}
|
|
1869
|
-
|
|
1870
|
-
|
|
1871
|
-
|
|
1872
|
-
border-radius: 6px;
|
|
1873
|
-
color: #888;
|
|
1874
|
-
cursor: pointer;
|
|
1875
|
-
width: 24px;
|
|
1876
|
-
height: 24px;
|
|
2040
|
+
|
|
2041
|
+
/* \u2500\u2500 Status & Route \u2500\u2500 */
|
|
2042
|
+
.status-bar {
|
|
1877
2043
|
display: flex;
|
|
1878
2044
|
align-items: center;
|
|
1879
|
-
|
|
2045
|
+
gap: 12px;
|
|
2046
|
+
margin-top: 8px;
|
|
2047
|
+
font-family: 'DM Mono', monospace;
|
|
1880
2048
|
font-size: 13px;
|
|
1881
|
-
transition: all .15s;
|
|
1882
2049
|
}
|
|
1883
|
-
.
|
|
1884
|
-
|
|
1885
|
-
|
|
1886
|
-
|
|
1887
|
-
|
|
1888
|
-
|
|
1889
|
-
font-size: 12px;
|
|
1890
|
-
color: #666;
|
|
2050
|
+
.status-badge {
|
|
2051
|
+
background: #0F172A;
|
|
2052
|
+
border: 1px solid #1E293B;
|
|
2053
|
+
color: #ff6b6b;
|
|
2054
|
+
padding: 4px 10px;
|
|
2055
|
+
border-radius: 6px;
|
|
1891
2056
|
}
|
|
1892
|
-
.
|
|
1893
|
-
|
|
1894
|
-
|
|
1895
|
-
|
|
1896
|
-
|
|
1897
|
-
|
|
2057
|
+
.route-badge {
|
|
2058
|
+
background: #0F172A;
|
|
2059
|
+
border: 1px solid #1E293B;
|
|
2060
|
+
color: #2563EB;
|
|
2061
|
+
padding: 4px 10px;
|
|
2062
|
+
border-radius: 6px;
|
|
1898
2063
|
}
|
|
1899
|
-
|
|
1900
|
-
|
|
1901
|
-
|
|
1902
|
-
|
|
1903
|
-
|
|
2064
|
+
.separator { color: #94A3B8; }
|
|
2065
|
+
.timestamp { color: #94A3B8; font-family: system-ui; font-size: 13px; }
|
|
2066
|
+
|
|
2067
|
+
/* \u2500\u2500 Error Message \u2500\u2500 */
|
|
2068
|
+
.error-message-box {
|
|
2069
|
+
background: #0F172A;
|
|
2070
|
+
border: 1px solid #1E293B;
|
|
2071
|
+
border-left: 3px solid #ff6b6b;
|
|
2072
|
+
border-radius: 10px;
|
|
2073
|
+
padding: 1rem 1.25rem;
|
|
2074
|
+
font-family: 'DM Mono', monospace;
|
|
2075
|
+
font-size: 14px;
|
|
2076
|
+
color: #F8FAFC;
|
|
2077
|
+
line-height: 1.6;
|
|
2078
|
+
white-space: pre-wrap;
|
|
2079
|
+
word-break: break-word;
|
|
1904
2080
|
}
|
|
1905
2081
|
|
|
1906
|
-
/* \u2500\u2500
|
|
1907
|
-
.
|
|
1908
|
-
|
|
1909
|
-
|
|
2082
|
+
/* \u2500\u2500 Source Code Viewer \u2500\u2500 */
|
|
2083
|
+
.source-viewer {
|
|
2084
|
+
display: flex;
|
|
2085
|
+
flex-direction: column;
|
|
2086
|
+
gap: 12px;
|
|
1910
2087
|
}
|
|
1911
|
-
.
|
|
1912
|
-
display:
|
|
2088
|
+
.source-header {
|
|
2089
|
+
display: flex;
|
|
1913
2090
|
align-items: center;
|
|
1914
|
-
|
|
1915
|
-
font-size: 11px;
|
|
1916
|
-
font-weight: 700;
|
|
1917
|
-
letter-spacing: 0.08em;
|
|
1918
|
-
text-transform: uppercase;
|
|
1919
|
-
color: #f87171;
|
|
1920
|
-
background: rgba(248, 113, 113, 0.1);
|
|
1921
|
-
border: 1px solid rgba(248, 113, 113, 0.25);
|
|
1922
|
-
padding: 3px 8px;
|
|
1923
|
-
border-radius: 4px;
|
|
1924
|
-
margin-bottom: 14px;
|
|
1925
|
-
}
|
|
1926
|
-
.error-label svg { width: 10px; height: 10px; fill: currentColor; }
|
|
1927
|
-
.error-message {
|
|
1928
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
1929
|
-
font-size: 18px;
|
|
1930
|
-
font-weight: 600;
|
|
1931
|
-
line-height: 1.5;
|
|
1932
|
-
color: #fff;
|
|
1933
|
-
word-break: break-word;
|
|
2091
|
+
justify-content: space-between;
|
|
1934
2092
|
}
|
|
1935
|
-
.
|
|
1936
|
-
|
|
2093
|
+
.source-filepath {
|
|
2094
|
+
font-family: 'DM Mono', monospace;
|
|
1937
2095
|
font-size: 13px;
|
|
1938
|
-
color: #
|
|
1939
|
-
}
|
|
1940
|
-
.error-location strong { color: #ccc; }
|
|
1941
|
-
|
|
1942
|
-
/* \u2500\u2500 Source Block \u2500\u2500 */
|
|
1943
|
-
.source-block {
|
|
1944
|
-
border-bottom: 1px solid #1e1e1e;
|
|
2096
|
+
color: #2563EB;
|
|
1945
2097
|
}
|
|
1946
|
-
.
|
|
2098
|
+
.open-in-editor {
|
|
2099
|
+
color: #94A3B8;
|
|
2100
|
+
cursor: pointer;
|
|
2101
|
+
transition: color 0.15s;
|
|
1947
2102
|
display: flex;
|
|
1948
2103
|
align-items: center;
|
|
1949
|
-
|
|
1950
|
-
|
|
1951
|
-
|
|
1952
|
-
gap: 8px;
|
|
1953
|
-
font-size: 12px;
|
|
1954
|
-
color: #666;
|
|
2104
|
+
gap: 6px;
|
|
2105
|
+
font-size: 13px;
|
|
2106
|
+
text-decoration: none;
|
|
1955
2107
|
}
|
|
1956
|
-
.
|
|
1957
|
-
.
|
|
1958
|
-
|
|
2108
|
+
.open-in-editor:hover { color: #F8FAFC; }
|
|
2109
|
+
.open-in-editor svg { width: 14px; height: 14px; stroke: currentColor; fill: none; }
|
|
2110
|
+
|
|
2111
|
+
.source-body {
|
|
2112
|
+
background: #020617;
|
|
2113
|
+
border: 1px solid #1E293B;
|
|
2114
|
+
border-radius: 8px;
|
|
2115
|
+
padding: 16px 0;
|
|
1959
2116
|
overflow-x: auto;
|
|
1960
|
-
|
|
1961
|
-
font-family: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, monospace;
|
|
2117
|
+
font-family: 'DM Mono', monospace;
|
|
1962
2118
|
font-size: 13px;
|
|
1963
|
-
line-height: 1.
|
|
2119
|
+
line-height: 1.6;
|
|
1964
2120
|
}
|
|
1965
2121
|
.src-line {
|
|
1966
2122
|
display: flex;
|
|
1967
|
-
|
|
1968
|
-
padding: 0 20px;
|
|
1969
|
-
white-space: pre;
|
|
1970
|
-
color: #555;
|
|
2123
|
+
padding: 0 16px;
|
|
1971
2124
|
}
|
|
1972
|
-
.
|
|
1973
|
-
color: #
|
|
2125
|
+
.ln {
|
|
2126
|
+
color: #475569;
|
|
2127
|
+
width: 32px;
|
|
1974
2128
|
text-align: right;
|
|
1975
|
-
width: 36px;
|
|
1976
2129
|
margin-right: 16px;
|
|
1977
|
-
flex-shrink: 0;
|
|
1978
2130
|
user-select: none;
|
|
2131
|
+
flex-shrink: 0;
|
|
1979
2132
|
}
|
|
1980
|
-
.
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
2133
|
+
.active-arrow {
|
|
2134
|
+
color: transparent;
|
|
2135
|
+
margin-right: 12px;
|
|
2136
|
+
width: 14px;
|
|
2137
|
+
text-align: center;
|
|
2138
|
+
flex-shrink: 0;
|
|
1984
2139
|
}
|
|
1985
|
-
.
|
|
1986
|
-
|
|
1987
|
-
|
|
1988
|
-
|
|
1989
|
-
left: 0;
|
|
1990
|
-
top: 0; bottom: 0;
|
|
1991
|
-
width: 3px;
|
|
1992
|
-
background: #ef4444;
|
|
2140
|
+
.code-content { white-space: pre; }
|
|
2141
|
+
|
|
2142
|
+
.src-err {
|
|
2143
|
+
background: rgba(37, 99, 235, 0.04);
|
|
1993
2144
|
}
|
|
2145
|
+
.src-err .ln { color: #2563EB; }
|
|
2146
|
+
.src-err .active-arrow { color: #2563EB; }
|
|
2147
|
+
.src-err .code-content { color: #F8FAFC; }
|
|
1994
2148
|
|
|
1995
2149
|
/* \u2500\u2500 Call Stack \u2500\u2500 */
|
|
1996
|
-
.callstack {
|
|
1997
|
-
|
|
2150
|
+
.callstack-section {
|
|
2151
|
+
margin-top: 16px;
|
|
2152
|
+
display: flex;
|
|
2153
|
+
flex-direction: column;
|
|
2154
|
+
gap: 12px;
|
|
1998
2155
|
}
|
|
1999
2156
|
.callstack-header {
|
|
2000
2157
|
display: flex;
|
|
2001
2158
|
align-items: center;
|
|
2002
2159
|
justify-content: space-between;
|
|
2003
|
-
margin-bottom: 14px;
|
|
2004
2160
|
}
|
|
2005
2161
|
.callstack-title {
|
|
2006
|
-
font-size:
|
|
2162
|
+
font-size: 16px;
|
|
2007
2163
|
font-weight: 600;
|
|
2008
|
-
|
|
2009
|
-
|
|
2010
|
-
|
|
2164
|
+
display: flex;
|
|
2165
|
+
align-items: center;
|
|
2166
|
+
gap: 12px;
|
|
2011
2167
|
}
|
|
2012
|
-
.
|
|
2168
|
+
.callstack-count {
|
|
2169
|
+
background: #1E293B;
|
|
2170
|
+
color: #F8FAFC;
|
|
2171
|
+
padding: 2px 10px;
|
|
2172
|
+
border-radius: 9999px;
|
|
2013
2173
|
font-size: 12px;
|
|
2014
|
-
|
|
2174
|
+
font-weight: 500;
|
|
2175
|
+
}
|
|
2176
|
+
|
|
2177
|
+
.toggle-node-modules {
|
|
2178
|
+
color: #94A3B8;
|
|
2179
|
+
font-size: 13px;
|
|
2015
2180
|
background: none;
|
|
2016
2181
|
border: none;
|
|
2017
2182
|
cursor: pointer;
|
|
2183
|
+
transition: color 0.15s;
|
|
2184
|
+
}
|
|
2185
|
+
.toggle-node-modules:hover { color: #F8FAFC; }
|
|
2186
|
+
|
|
2187
|
+
.frame {
|
|
2188
|
+
background: #0F172A;
|
|
2189
|
+
border: 1px solid #1E293B;
|
|
2190
|
+
border-radius: 8px;
|
|
2191
|
+
padding: 0.875rem 1rem;
|
|
2018
2192
|
display: flex;
|
|
2193
|
+
justify-content: space-between;
|
|
2019
2194
|
align-items: center;
|
|
2195
|
+
transition: background-color 0.15s, transform 0.15s;
|
|
2196
|
+
}
|
|
2197
|
+
.frame:hover { background: #1E293B; }
|
|
2198
|
+
|
|
2199
|
+
.frame-info {
|
|
2200
|
+
display: flex;
|
|
2201
|
+
flex-direction: column;
|
|
2020
2202
|
gap: 4px;
|
|
2021
|
-
transition: color .15s;
|
|
2022
2203
|
}
|
|
2023
|
-
.
|
|
2024
|
-
|
|
2025
|
-
|
|
2204
|
+
.frame-call {
|
|
2205
|
+
font-family: 'DM Mono', monospace;
|
|
2206
|
+
font-size: 14px;
|
|
2207
|
+
font-weight: 700;
|
|
2208
|
+
color: #2563EB;
|
|
2209
|
+
}
|
|
2210
|
+
.frame-file {
|
|
2211
|
+
font-family: 'DM Mono', monospace;
|
|
2212
|
+
font-size: 13px;
|
|
2213
|
+
color: #94A3B8;
|
|
2214
|
+
}
|
|
2215
|
+
|
|
2216
|
+
.frame.node-modules .frame-call { color: #94A3B8; font-weight: 400; }
|
|
2217
|
+
.frame.node-modules .frame-file { color: #475569; }
|
|
2218
|
+
|
|
2219
|
+
.frame-number {
|
|
2220
|
+
background: #1E293B;
|
|
2221
|
+
color: #94A3B8;
|
|
2222
|
+
padding: 2px 8px;
|
|
2223
|
+
border-radius: 6px;
|
|
2224
|
+
font-size: 12px;
|
|
2225
|
+
font-variant-numeric: tabular-nums;
|
|
2226
|
+
}
|
|
2026
2227
|
|
|
2027
|
-
.
|
|
2028
|
-
|
|
2228
|
+
.pagination {
|
|
2229
|
+
display: flex;
|
|
2230
|
+
justify-content: flex-end;
|
|
2231
|
+
gap: 8px;
|
|
2232
|
+
margin-top: 8px;
|
|
2233
|
+
}
|
|
2234
|
+
.page-btn {
|
|
2235
|
+
background: transparent;
|
|
2236
|
+
border: 1px solid #1E293B;
|
|
2237
|
+
color: #F8FAFC;
|
|
2238
|
+
padding: 6px 14px;
|
|
2029
2239
|
border-radius: 6px;
|
|
2030
|
-
margin-bottom: 4px;
|
|
2031
2240
|
font-size: 13px;
|
|
2032
|
-
cursor:
|
|
2241
|
+
cursor: pointer;
|
|
2242
|
+
transition: all 0.15s;
|
|
2033
2243
|
}
|
|
2034
|
-
.
|
|
2035
|
-
.
|
|
2036
|
-
|
|
2244
|
+
.page-btn:hover:not(:disabled) { background: #1E293B; }
|
|
2245
|
+
.page-btn:disabled { opacity: 0.3; cursor: default; }
|
|
2246
|
+
|
|
2247
|
+
.node-modules-list { display: none; flex-direction: column; gap: 12px; margin-top: 12px; }
|
|
2248
|
+
.node-modules-list.visible { display: flex; }
|
|
2249
|
+
|
|
2250
|
+
/* \u2500\u2500 Footer \u2500\u2500 */
|
|
2251
|
+
.footer {
|
|
2252
|
+
margin-top: 32px;
|
|
2253
|
+
padding-top: 24px;
|
|
2254
|
+
border-top: 1px solid #1E293B;
|
|
2255
|
+
display: flex;
|
|
2256
|
+
justify-content: space-between;
|
|
2257
|
+
align-items: center;
|
|
2258
|
+
}
|
|
2259
|
+
.footer-left {
|
|
2260
|
+
display: flex;
|
|
2261
|
+
align-items: center;
|
|
2262
|
+
gap: 8px;
|
|
2263
|
+
font-size: 13px;
|
|
2037
2264
|
font-weight: 600;
|
|
2038
|
-
color: #
|
|
2039
|
-
|
|
2265
|
+
color: #F8FAFC;
|
|
2266
|
+
}
|
|
2267
|
+
.velix-dot { width: 8px; height: 8px; border-radius: 50%; background: #2563EB; }
|
|
2268
|
+
.footer-right {
|
|
2269
|
+
display: flex;
|
|
2270
|
+
align-items: center;
|
|
2271
|
+
gap: 16px;
|
|
2040
2272
|
}
|
|
2041
|
-
.
|
|
2042
|
-
|
|
2273
|
+
.footer-link {
|
|
2274
|
+
color: #94A3B8;
|
|
2275
|
+
text-decoration: none;
|
|
2276
|
+
font-size: 13px;
|
|
2277
|
+
transition: color 0.15s;
|
|
2278
|
+
}
|
|
2279
|
+
.footer-link:hover { color: #F8FAFC; }
|
|
2280
|
+
.dev-pill {
|
|
2281
|
+
background: #1E293B;
|
|
2282
|
+
color: #F8FAFC;
|
|
2283
|
+
padding: 4px 12px;
|
|
2284
|
+
border-radius: 9999px;
|
|
2043
2285
|
font-size: 12px;
|
|
2044
|
-
color: #555;
|
|
2045
2286
|
}
|
|
2046
|
-
.frame.ignored .frame-call { color: #444; }
|
|
2047
|
-
|
|
2048
|
-
.ignored-section { margin-top: 8px; display: none; }
|
|
2049
|
-
.ignored-section.open { display: block; }
|
|
2050
2287
|
</style>
|
|
2051
2288
|
</head>
|
|
2052
2289
|
<body>
|
|
2053
|
-
<div class="
|
|
2054
|
-
|
|
2055
|
-
|
|
2290
|
+
<div class="bg-mask"></div>
|
|
2291
|
+
<div class="container">
|
|
2292
|
+
|
|
2293
|
+
<!-- Header -->
|
|
2056
2294
|
<div class="header">
|
|
2057
2295
|
<div class="header-left">
|
|
2058
|
-
<
|
|
2059
|
-
<
|
|
2060
|
-
<button class="nav-btn" disabled>\u203A</button>
|
|
2061
|
-
<span style="margin-left: 4px;">Unhandled Runtime Error</span>
|
|
2296
|
+
<svg class="header-icon" viewBox="0 0 24 24"><path d="M12 2L1 21h22L12 2zm0 3.83L19.17 19H4.83L12 5.83zM11 10h2v5h-2v-5zm0 6h2v2h-2v-2z"/></svg>
|
|
2297
|
+
<div class="header-title">Unhandled Runtime Error</div>
|
|
2062
2298
|
</div>
|
|
2063
|
-
<div class="
|
|
2299
|
+
<div class="dev-badge">DEV</div>
|
|
2064
2300
|
</div>
|
|
2065
2301
|
|
|
2066
|
-
<!--
|
|
2067
|
-
<div class="
|
|
2302
|
+
<!-- Status & Route -->
|
|
2303
|
+
<div class="status-bar">
|
|
2304
|
+
<div class="status-badge">${options.statusCode || 500}</div>
|
|
2305
|
+
<div class="separator">\xB7</div>
|
|
2306
|
+
<div class="route-badge">Route: ${pathname || "/"}</div>
|
|
2307
|
+
<div class="separator">\xB7</div>
|
|
2308
|
+
<div class="timestamp">just now</div>
|
|
2309
|
+
</div>
|
|
2068
2310
|
|
|
2069
|
-
|
|
2070
|
-
|
|
2071
|
-
|
|
2072
|
-
|
|
2073
|
-
Runtime Error
|
|
2074
|
-
</div>
|
|
2075
|
-
<div class="error-message">${escapeHtml2(message)}</div>
|
|
2076
|
-
${pathname ? `<div class="error-location">in <strong>${escapeHtml2(pathname)}</strong></div>` : ""}
|
|
2077
|
-
</div>
|
|
2311
|
+
<!-- Error Message -->
|
|
2312
|
+
<div class="error-message-box">
|
|
2313
|
+
${formatErrorMessage(message)}
|
|
2314
|
+
</div>
|
|
2078
2315
|
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2082
|
-
|
|
2083
|
-
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2316
|
+
${sourceSnippet ? `
|
|
2317
|
+
<!-- Source Viewer -->
|
|
2318
|
+
<div class="source-viewer">
|
|
2319
|
+
<div class="source-header">
|
|
2320
|
+
<div class="source-filepath">${escapeHtml2(shortFile)}${errorLine ? ` (${errorLine})` : ""} @ runtime</div>
|
|
2321
|
+
<a href="#" class="open-in-editor" onclick="console.log('Open in editor clicked')">
|
|
2322
|
+
Open in editor
|
|
2323
|
+
<svg viewBox="0 0 24 24"><path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M10 6H6a2 2 0 00-2 2v10a2 2 0 002 2h10a2 2 0 002-2v-4M14 4h6m0 0v6m0-6L10 14"></path></svg>
|
|
2324
|
+
</a>
|
|
2087
2325
|
</div>
|
|
2088
|
-
|
|
2089
|
-
|
|
2090
|
-
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
|
|
2096
|
-
|
|
2097
|
-
|
|
2098
|
-
|
|
2099
|
-
|
|
2100
|
-
</button>
|
|
2101
|
-
` : ""}
|
|
2326
|
+
<div class="source-body">
|
|
2327
|
+
${sourceSnippet}
|
|
2328
|
+
</div>
|
|
2329
|
+
</div>
|
|
2330
|
+
` : ""}
|
|
2331
|
+
|
|
2332
|
+
<!-- Call Stack -->
|
|
2333
|
+
<div class="callstack-section">
|
|
2334
|
+
<div class="callstack-header">
|
|
2335
|
+
<div class="callstack-title">
|
|
2336
|
+
Call Stack
|
|
2337
|
+
<div class="callstack-count">${frames.length}</div>
|
|
2102
2338
|
</div>
|
|
2339
|
+
${ignoredFrames.length > 0 ? `
|
|
2340
|
+
<button class="toggle-node-modules" id="toggleNodeModules" onclick="toggleNodeModules()">
|
|
2341
|
+
Show ${ignoredFrames.length} node_modules frames
|
|
2342
|
+
</button>
|
|
2343
|
+
` : ""}
|
|
2344
|
+
</div>
|
|
2103
2345
|
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
<div class="frame">
|
|
2346
|
+
${userFrames.map((f, i) => `
|
|
2347
|
+
<div class="frame">
|
|
2348
|
+
<div class="frame-info">
|
|
2107
2349
|
<div class="frame-call">${escapeHtml2(f.call)}</div>
|
|
2108
|
-
<div class="frame-
|
|
2350
|
+
<div class="frame-file">${escapeHtml2(f.file.replace(/\\\\/g, "/"))}${f.line ? `:${f.line}` : ""}</div>
|
|
2109
2351
|
</div>
|
|
2110
|
-
|
|
2352
|
+
<div class="frame-number">${i + 1}</div>
|
|
2353
|
+
</div>
|
|
2354
|
+
`).join("")}
|
|
2111
2355
|
|
|
2112
|
-
|
|
2113
|
-
|
|
2114
|
-
|
|
2115
|
-
|
|
2116
|
-
<div class="frame
|
|
2356
|
+
${ignoredFrames.length > 0 ? `
|
|
2357
|
+
<div class="node-modules-list" id="nodeModulesList">
|
|
2358
|
+
${ignoredFrames.map((f, i) => `
|
|
2359
|
+
<div class="frame node-modules">
|
|
2360
|
+
<div class="frame-info">
|
|
2117
2361
|
<div class="frame-call">${escapeHtml2(f.call)}</div>
|
|
2118
|
-
<div class="frame-
|
|
2362
|
+
<div class="frame-file">${escapeHtml2(f.file)}${f.line ? `:${f.line}` : ""}</div>
|
|
2119
2363
|
</div>
|
|
2120
|
-
|
|
2364
|
+
<div class="frame-number">${userFrames.length + i + 1}</div>
|
|
2121
2365
|
</div>
|
|
2122
|
-
`
|
|
2366
|
+
`).join("")}
|
|
2367
|
+
</div>
|
|
2368
|
+
` : ""}
|
|
2369
|
+
|
|
2370
|
+
<div class="pagination">
|
|
2371
|
+
<button class="page-btn" disabled>Previous</button>
|
|
2372
|
+
<button class="page-btn" disabled>Next</button>
|
|
2373
|
+
</div>
|
|
2374
|
+
</div>
|
|
2375
|
+
|
|
2376
|
+
<!-- Footer -->
|
|
2377
|
+
<div class="footer">
|
|
2378
|
+
<div class="footer-left">
|
|
2379
|
+
<div class="velix-dot"></div>
|
|
2380
|
+
Velix v${VERSION}
|
|
2123
2381
|
</div>
|
|
2382
|
+
<div class="footer-right">
|
|
2383
|
+
<a href="/" class="footer-link">Home</a>
|
|
2384
|
+
<a href="#" class="footer-link" onclick="window.location.reload()">Reload</a>
|
|
2385
|
+
<a href="https://velixcloud.io/docs" class="footer-link" target="_blank">Documentation</a>
|
|
2386
|
+
<div class="dev-pill">Development Mode</div>
|
|
2387
|
+
</div>
|
|
2388
|
+
</div>
|
|
2124
2389
|
|
|
2125
|
-
|
|
2126
|
-
</div><!-- /overlay -->
|
|
2390
|
+
</div>
|
|
2127
2391
|
|
|
2128
2392
|
<script>
|
|
2129
|
-
function
|
|
2130
|
-
const
|
|
2131
|
-
const
|
|
2132
|
-
if (!
|
|
2133
|
-
|
|
2134
|
-
|
|
2393
|
+
function toggleNodeModules() {
|
|
2394
|
+
const list = document.getElementById('nodeModulesList');
|
|
2395
|
+
const btn = document.getElementById('toggleNodeModules');
|
|
2396
|
+
if (!list || !btn) return;
|
|
2397
|
+
|
|
2398
|
+
const isVisible = list.classList.contains('visible');
|
|
2399
|
+
if (isVisible) {
|
|
2400
|
+
list.classList.remove('visible');
|
|
2401
|
+
btn.textContent = 'Show ' + list.children.length + ' node_modules frames';
|
|
2402
|
+
} else {
|
|
2403
|
+
list.classList.add('visible');
|
|
2404
|
+
btn.textContent = 'Hide node_modules frames';
|
|
2405
|
+
}
|
|
2135
2406
|
}
|
|
2136
2407
|
</script>
|
|
2137
2408
|
</body>
|