@teamvelix/velix 5.2.5 → 5.2.7

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,10 +1,10 @@
1
- import { logger_default, buildRouteTree, matchRoute, VERSION } from './chunk-MLLSS7Y5.js';
1
+ import { definePlugin, PluginHooks, logger_default, loadPlugins, pluginManager, buildRouteTree, matchRoute, VERSION } from './chunk-SNWXKPXR.js';
2
2
  import { loadConfig, resolvePaths } from './chunk-F24Q2MX3.js';
3
3
  import { getRegisteredIslands, generateAdvancedHydrationScript } from './chunk-JI2HJFUT.js';
4
- import { __dirname as __dirname$1 } from './chunk-4S5YQJHB.js';
4
+ import { __dirname as __dirname$1, __require } from './chunk-BQ4HFLRL.js';
5
5
  import http from 'http';
6
- import fs4 from 'fs';
7
- import path4 from 'path';
6
+ import fs3 from 'fs';
7
+ import path3 from 'path';
8
8
  import { pathToFileURL, fileURLToPath } from 'url';
9
9
  import { createRequire } from 'module';
10
10
  import React, { useActionState } from 'react';
@@ -73,11 +73,11 @@ async function loadMiddleware(projectRoot) {
73
73
  const fns = [];
74
74
  const possibleFiles = ["proxy.ts", "proxy.js"];
75
75
  for (const file of possibleFiles) {
76
- const filePath = path4.join(projectRoot, file);
77
- if (!fs4.existsSync(filePath)) continue;
76
+ const filePath = path3.join(projectRoot, file);
77
+ if (!fs3.existsSync(filePath)) continue;
78
78
  try {
79
- const { pathToFileURL: pathToFileURL3 } = await import('url');
80
- const url = pathToFileURL3(filePath).href;
79
+ const { pathToFileURL: pathToFileURL2 } = await import('url');
80
+ const url = pathToFileURL2(filePath).href;
81
81
  const mod = await import(`${url}?t=${Date.now()}`);
82
82
  const fn = mod.default || mod.proxy || mod.middleware;
83
83
  if (typeof fn === "function") {
@@ -179,140 +179,6 @@ function composeMiddleware(...fns) {
179
179
  await run();
180
180
  };
181
181
  }
182
- var PluginHooks = {
183
- CONFIG: "config",
184
- SERVER_START: "server:start",
185
- REQUEST: "request",
186
- RESPONSE: "response",
187
- ROUTES_LOADED: "routes:loaded",
188
- BEFORE_RENDER: "render:before",
189
- AFTER_RENDER: "render:after",
190
- BUILD_START: "build:start",
191
- BUILD_END: "build:end"
192
- };
193
- var PluginManager = class {
194
- plugins = [];
195
- hooks = /* @__PURE__ */ new Map();
196
- /**
197
- * Register a plugin
198
- */
199
- register(plugin) {
200
- this.plugins.push(plugin);
201
- if (plugin.hooks) {
202
- for (const [hookName, handler] of Object.entries(plugin.hooks)) {
203
- if (handler) {
204
- const existing = this.hooks.get(hookName) || [];
205
- existing.push(handler);
206
- this.hooks.set(hookName, existing);
207
- }
208
- }
209
- }
210
- }
211
- /**
212
- * Run a hook with arguments
213
- */
214
- async runHook(hookName, ...args) {
215
- const handlers = this.hooks.get(hookName) || [];
216
- for (const handler of handlers) {
217
- await handler(...args);
218
- }
219
- }
220
- /**
221
- * Run a waterfall hook — each handler transforms the first argument
222
- */
223
- async runWaterfallHook(hookName, value, ...args) {
224
- const handlers = this.hooks.get(hookName) || [];
225
- let result = value;
226
- for (const handler of handlers) {
227
- const transformed = await handler(result, ...args);
228
- if (transformed !== void 0) result = transformed;
229
- }
230
- return result;
231
- }
232
- /**
233
- * Get all registered plugins
234
- */
235
- getPlugins() {
236
- return [...this.plugins];
237
- }
238
- /**
239
- * Check if a plugin is registered
240
- */
241
- hasPlugin(name) {
242
- return this.plugins.some((p) => p.name === name);
243
- }
244
- };
245
- var pluginManager = new PluginManager();
246
- async function loadPlugins(projectRoot, config) {
247
- const pluginEntries = config.plugins || [];
248
- for (const entry of pluginEntries) {
249
- try {
250
- if (typeof entry === "string") {
251
- const localPath = path4.join(projectRoot, "plugins", entry + ".ts");
252
- const localPathJs = path4.join(projectRoot, "plugins", entry + ".js");
253
- const localPathDir = path4.join(projectRoot, "plugins", entry, "index.ts");
254
- let pluginPath = null;
255
- if (fs4.existsSync(localPath)) pluginPath = localPath;
256
- else if (fs4.existsSync(localPathJs)) pluginPath = localPathJs;
257
- else if (fs4.existsSync(localPathDir)) pluginPath = localPathDir;
258
- if (pluginPath) {
259
- const url = pathToFileURL(pluginPath).href;
260
- const mod = await import(`${url}?t=${Date.now()}`);
261
- const plugin = mod.default || mod;
262
- if (plugin.name) {
263
- pluginManager.register(plugin);
264
- }
265
- } else {
266
- try {
267
- const mod = await import(entry);
268
- const plugin = mod.default || mod;
269
- if (plugin.name) pluginManager.register(plugin);
270
- } catch {
271
- console.warn(`\u26A0 Plugin not found: ${entry}`);
272
- }
273
- }
274
- } else if (typeof entry === "object" && entry !== null && "name" in entry) {
275
- pluginManager.register(entry);
276
- }
277
- } catch (err) {
278
- const error = err;
279
- console.warn(`\u26A0 Failed to load plugin: ${error?.message || String(error)}`);
280
- }
281
- }
282
- }
283
- function definePlugin(definition) {
284
- return definition;
285
- }
286
- ({
287
- /**
288
- * Security headers plugin
289
- */
290
- security: definePlugin({
291
- name: "velix:security",
292
- hooks: {
293
- [PluginHooks.RESPONSE]: (_req, res) => {
294
- const response = res;
295
- if (!response.headersSent) {
296
- response.setHeader("X-Content-Type-Options", "nosniff");
297
- response.setHeader("X-Frame-Options", "DENY");
298
- response.setHeader("X-XSS-Protection", "1; mode=block");
299
- }
300
- }
301
- }
302
- }),
303
- /**
304
- * Request logging plugin
305
- */
306
- logger: definePlugin({
307
- name: "velix:logger",
308
- hooks: {
309
- [PluginHooks.RESPONSE]: (req, _res, duration) => {
310
- const request = req;
311
- console.log(` ${request.method} ${request.url} ${duration}ms`);
312
- }
313
- }
314
- })
315
- });
316
182
  function detectTailwindCli() {
317
183
  const v4 = spawnSync("npx @tailwindcss/cli --help", {
318
184
  stdio: "pipe",
@@ -362,13 +228,13 @@ function tailwindPlugin(options = {}) {
362
228
  [PluginHooks.SERVER_START]: async (server, isDevArg) => {
363
229
  const isDev = isDevArg;
364
230
  if (!isDev) return;
365
- if (!fs4.existsSync(input)) {
231
+ if (!fs3.existsSync(input)) {
366
232
  logger_default.warn(`Tailwind input file not found: ${input}`);
367
233
  return;
368
234
  }
369
- const outputDir = path4.dirname(output);
370
- if (!fs4.existsSync(outputDir)) {
371
- fs4.mkdirSync(outputDir, { recursive: true });
235
+ const outputDir = path3.dirname(output);
236
+ if (!fs3.existsSync(outputDir)) {
237
+ fs3.mkdirSync(outputDir, { recursive: true });
372
238
  }
373
239
  logger_default.info("Building initial Tailwind CSS...");
374
240
  try {
@@ -1313,27 +1179,30 @@ function generateDevToolsHtml(isDev, ctx = {}) {
1313
1179
  }
1314
1180
 
1315
1181
  // server/error-pages.ts
1182
+ function escapeHtml2(str) {
1183
+ return str.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
1184
+ }
1316
1185
  function generate404Page(pathname = "/") {
1317
1186
  return `<!DOCTYPE html>
1318
1187
  <html lang="en">
1319
1188
  <head>
1320
1189
  <meta charset="UTF-8">
1321
1190
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1322
- <title>404 - Page Not Found | Velix v5</title>
1191
+ <title>404 - Page Not Found | Velix v${VERSION}</title>
1323
1192
  <link rel="icon" href="/favicon.webp">
1324
1193
  <style>
1325
1194
  * { margin: 0; padding: 0; box-sizing: border-box; }
1326
1195
  body {
1327
1196
  margin: 0;
1328
- background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);
1197
+ background: #161616;
1329
1198
  color: white;
1330
- font-family: ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, sans-serif;
1199
+ font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1331
1200
  display: flex;
1332
1201
  align-items: center;
1333
1202
  justify-content: center;
1334
1203
  min-height: 100vh;
1335
1204
  text-align: center;
1336
- overflow: hidden;
1205
+ -webkit-font-smoothing: antialiased;
1337
1206
  }
1338
1207
  .container {
1339
1208
  max-width: 700px;
@@ -1341,489 +1210,431 @@ function generate404Page(pathname = "/") {
1341
1210
  position: relative;
1342
1211
  z-index: 10;
1343
1212
  }
1344
- .bg-pattern {
1345
- position: absolute;
1346
- inset: 0;
1347
- background-image: radial-gradient(circle at 20% 50%, rgba(34, 211, 238, 0.1) 0%, transparent 50%),
1348
- radial-gradient(circle at 80% 80%, rgba(37, 99, 235, 0.1) 0%, transparent 50%);
1349
- z-index: 1;
1350
- }
1351
1213
  h1 {
1352
- font-size: 180px;
1214
+ font-size: 160px;
1353
1215
  font-weight: 900;
1354
1216
  margin: 0;
1355
- background: linear-gradient(135deg, #22D3EE 0%, #2563EB 100%);
1217
+ background: linear-gradient(135deg, #00e87a 0%, #22d3ee 100%);
1356
1218
  -webkit-background-clip: text;
1357
1219
  -webkit-text-fill-color: transparent;
1358
1220
  line-height: 1;
1359
1221
  letter-spacing: -0.05em;
1360
- animation: fadeInUp 0.6s ease-out;
1222
+ animation: fadeIn 0.5s ease-out;
1361
1223
  }
1362
1224
  h2 {
1363
- font-size: 36px;
1364
- font-weight: 800;
1365
- margin: 30px 0 15px;
1366
- color: #F8FAFC;
1367
- animation: fadeInUp 0.6s ease-out 0.1s backwards;
1225
+ font-size: 32px;
1226
+ font-weight: 700;
1227
+ margin: 24px 0 12px;
1228
+ color: #ededed;
1229
+ animation: fadeIn 0.5s ease-out 0.1s backwards;
1368
1230
  }
1369
1231
  p {
1370
- color: #94A3B8;
1371
- font-size: 18px;
1232
+ color: #888;
1233
+ font-size: 16px;
1372
1234
  line-height: 1.7;
1373
- margin-bottom: 40px;
1374
- animation: fadeInUp 0.6s ease-out 0.2s backwards;
1235
+ margin-bottom: 36px;
1236
+ animation: fadeIn 0.5s ease-out 0.2s backwards;
1375
1237
  }
1376
1238
  code {
1377
- background: rgba(255,255,255,0.1);
1378
- padding: 4px 10px;
1239
+ background: #222;
1240
+ padding: 3px 8px;
1379
1241
  border-radius: 6px;
1380
- font-family: 'Fira Code', 'Courier New', monospace;
1381
- color: #22D3EE;
1382
- font-size: 16px;
1383
- border: 1px solid rgba(34, 211, 238, 0.2);
1242
+ font-family: 'JetBrains Mono', monospace;
1243
+ color: #00e87a;
1244
+ font-size: 14px;
1245
+ border: 1px solid #333;
1384
1246
  }
1385
1247
  .btn-group {
1386
1248
  display: flex;
1387
- gap: 16px;
1249
+ gap: 12px;
1388
1250
  justify-content: center;
1389
- flex-wrap: wrap;
1390
- animation: fadeInUp 0.6s ease-out 0.3s backwards;
1251
+ animation: fadeIn 0.5s ease-out 0.3s backwards;
1391
1252
  }
1392
1253
  .btn {
1393
1254
  display: inline-block;
1394
- background: linear-gradient(135deg, #2563EB 0%, #1D4ED8 100%);
1255
+ background: #222;
1395
1256
  color: white;
1396
1257
  text-decoration: none;
1397
- padding: 14px 36px;
1398
- border-radius: 12px;
1258
+ padding: 12px 28px;
1259
+ border-radius: 10px;
1399
1260
  font-weight: 600;
1400
- font-size: 16px;
1401
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1402
- box-shadow: 0 10px 30px rgba(37, 99, 235, 0.3);
1403
- border: none;
1261
+ font-size: 14px;
1262
+ transition: all 0.2s;
1263
+ border: 1px solid #333;
1404
1264
  cursor: pointer;
1405
1265
  }
1406
- .btn:hover {
1407
- transform: translateY(-2px);
1408
- box-shadow: 0 15px 40px rgba(37, 99, 235, 0.4);
1409
- }
1410
- .btn-outline {
1411
- background: transparent;
1412
- color: #22D3EE;
1413
- border: 2px solid #22D3EE;
1414
- box-shadow: none;
1266
+ .btn:hover { background: #333; }
1267
+ .btn-accent {
1268
+ background: #00e87a;
1269
+ color: #000;
1270
+ border-color: #00e87a;
1415
1271
  }
1416
- .btn-outline:hover {
1417
- background: rgba(34, 211, 238, 0.1);
1418
- box-shadow: 0 10px 30px rgba(34, 211, 238, 0.2);
1419
- }
1420
- @keyframes fadeInUp {
1421
- from {
1422
- opacity: 0;
1423
- transform: translateY(30px);
1424
- }
1425
- to {
1426
- opacity: 1;
1427
- transform: translateY(0);
1428
- }
1272
+ .btn-accent:hover { background: #00d46e; }
1273
+ @keyframes fadeIn {
1274
+ from { opacity: 0; transform: translateY(16px); }
1275
+ to { opacity: 1; transform: translateY(0); }
1429
1276
  }
1430
1277
  </style>
1431
1278
  </head>
1432
1279
  <body>
1433
- <div class="bg-pattern"></div>
1434
1280
  <div class="container">
1435
1281
  <h1>404</h1>
1436
1282
  <h2>Page Not Found</h2>
1437
1283
  <p>The page <code>${pathname}</code> could not be found.<br>It may have been moved or deleted.</p>
1438
1284
  <div class="btn-group">
1439
- <a href="/" class="btn">Return Home</a>
1440
- <a href="javascript:history.back()" class="btn btn-outline">Go Back</a>
1285
+ <a href="/" class="btn btn-accent">Return Home</a>
1286
+ <a href="javascript:history.back()" class="btn">Go Back</a>
1441
1287
  </div>
1442
1288
  </div>
1443
1289
  </body>
1444
1290
  </html>`;
1445
1291
  }
1446
1292
  function generate500Page(options) {
1447
- const { title, message, stack, isDev, pathname } = options;
1448
- let callStackCards = "";
1449
- let frameCount = 0;
1293
+ const { message, stack, isDev, pathname } = options;
1294
+ let frames = [];
1295
+ let sourceSnippet = "";
1296
+ let errorLine = 0;
1297
+ let errorFile = "";
1450
1298
  if (isDev && stack) {
1451
- const stackLines = stack.split("\n").filter((line) => line.trim());
1452
- const frames = stackLines.slice(1).filter((line) => line.includes("at "));
1453
- frameCount = frames.length;
1454
- callStackCards = frames.map((frame, index) => {
1455
- const match = frame.match(/at\s+(.+?)\s+\((.+?)\)/) || frame.match(/at\s+(.+)/);
1456
- if (match) {
1457
- const funcName = match[1] || "anonymous";
1458
- const location = match[2] || match[1];
1459
- return `
1460
- <div class="error-card" data-frame="${index}">
1461
- <div class="card-header">
1462
- <div class="card-title">${funcName.trim()}</div>
1463
- <div class="card-number">${index + 1}</div>
1464
- </div>
1465
- <div class="card-location">${location.trim()}</div>
1466
- </div>
1467
- `;
1299
+ const stackLines = stack.split("\\n").filter((line) => line.trim());
1300
+ frames = stackLines.slice(1).filter((line) => line.includes("at ")).map((frame) => {
1301
+ const match = frame.match(/at\s+(.+?)\s+\((.+?):(\d+):(\d+)\)/) || frame.match(/at\s+(.+?):(\d+):(\d+)/);
1302
+ if (match && match.length === 5) {
1303
+ return { funcName: match[1].trim(), file: match[2], line: match[3], col: match[4] };
1304
+ }
1305
+ if (match && match.length === 4) {
1306
+ return { funcName: "(anonymous)", file: match[1].trim(), line: match[2], col: match[3] };
1307
+ }
1308
+ const simpleMatch = frame.match(/at\s+(.+)/);
1309
+ return { funcName: simpleMatch?.[1]?.trim() || "unknown", file: "", line: "", col: "" };
1310
+ });
1311
+ if (frames.length > 0) {
1312
+ const firstFrame = frames.find((f) => f.file && !f.file.includes("node_modules")) || frames[0];
1313
+ errorFile = firstFrame.file;
1314
+ errorLine = parseInt(firstFrame.line, 10) || 0;
1315
+ if (errorFile && errorLine > 0) {
1316
+ try {
1317
+ const fs4 = __require("fs");
1318
+ if (fs4.existsSync(errorFile)) {
1319
+ const src = fs4.readFileSync(errorFile, "utf-8").split("\\n");
1320
+ const start = Math.max(0, errorLine - 3);
1321
+ const end = Math.min(src.length, errorLine + 3);
1322
+ sourceSnippet = src.slice(start, end).map((l, i) => {
1323
+ const num = start + i + 1;
1324
+ const isErr = num === errorLine;
1325
+ const prefix = isErr ? "> " : " ";
1326
+ const numStr = String(num).padStart(4, " ");
1327
+ return `<div class="src-line${isErr ? " src-err" : ""}">${prefix}${numStr} | ${escapeHtml2(l)}</div>`;
1328
+ }).join("");
1329
+ }
1330
+ } catch (_) {
1331
+ }
1468
1332
  }
1469
- return "";
1470
- }).join("");
1333
+ }
1471
1334
  }
1335
+ const userFrames = frames.filter((f) => f.file && !f.file.includes("node_modules"));
1336
+ const ignoredCount = frames.length - userFrames.length;
1337
+ const shortFile = errorFile.replace(/\\/g, "/").replace(/.*\/(?=app\/|server\/|src\/|pages\/)/, "");
1472
1338
  return `<!DOCTYPE html>
1473
1339
  <html lang="en">
1474
1340
  <head>
1475
1341
  <meta charset="UTF-8">
1476
1342
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
1477
- <title>Error | Velix v5</title>
1343
+ <title>Error | Velix v${VERSION}</title>
1478
1344
  <link rel="icon" href="/favicon.webp">
1479
1345
  <style>
1346
+ :root {
1347
+ --bg-body: #000;
1348
+ --bg-card: #111;
1349
+ --border: #333;
1350
+ --text-main: #ededed;
1351
+ --text-muted: #888;
1352
+ --red-tag: #e5484d;
1353
+ --red-bg: rgba(229, 72, 77, 0.15);
1354
+ --code-bg: #000;
1355
+ --code-hl: rgba(255,255,255,0.1);
1356
+ --font-sans: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif;
1357
+ --font-mono: ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, "Liberation Mono", "Courier New", monospace;
1358
+ }
1359
+
1480
1360
  * { margin: 0; padding: 0; box-sizing: border-box; }
1481
- body {
1482
- margin: 0;
1483
- background: linear-gradient(135deg, #0F172A 0%, #1E293B 100%);
1484
- color: #F8FAFC;
1485
- font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif;
1361
+ body {
1362
+ background: var(--bg-body);
1363
+ color: var(--text-main);
1364
+ font-family: var(--font-sans);
1486
1365
  min-height: 100vh;
1487
- overflow-x: hidden;
1488
- }
1489
- .container {
1490
- max-width: 900px;
1491
- margin: 0 auto;
1492
- padding: 40px 20px;
1493
- }
1494
- .error-header {
1495
- background: linear-gradient(135deg, #EF4444 0%, #DC2626 100%);
1496
- color: white;
1497
- padding: 20px 28px;
1498
- border-radius: 16px;
1499
- display: flex;
1500
- align-items: center;
1501
- gap: 14px;
1502
- margin-bottom: 28px;
1503
- font-size: 18px;
1504
- font-weight: 700;
1505
- box-shadow: 0 10px 40px rgba(239, 68, 68, 0.3);
1506
- }
1507
- .error-header svg {
1508
- width: 24px;
1509
- height: 24px;
1510
- flex-shrink: 0;
1511
- }
1512
- .error-badge {
1513
- display: inline-block;
1514
- background: linear-gradient(135deg, #1E40AF 0%, #1E3A8A 100%);
1515
- color: #60A5FA;
1516
- padding: 6px 16px;
1517
- border-radius: 8px;
1518
- font-size: 13px;
1519
- font-weight: 700;
1520
- margin-bottom: 18px;
1521
- text-transform: uppercase;
1522
- letter-spacing: 0.8px;
1523
- box-shadow: 0 4px 12px rgba(30, 64, 175, 0.3);
1366
+ line-height: 1.7;
1367
+ margin-bottom: 12px;
1368
+ word-break: break-word;
1524
1369
  }
1525
- .route-badge {
1526
- background: linear-gradient(135deg, #0C4A6E 0%, #075985 100%);
1527
- color: #22D3EE;
1528
- padding: 10px 18px;
1529
- border-radius: 10px;
1370
+ .error-hint {
1371
+ color: #22c55e;
1530
1372
  font-size: 14px;
1531
- margin-bottom: 24px;
1532
- font-family: 'Courier New', monospace;
1533
- box-shadow: 0 4px 12px rgba(12, 74, 110, 0.3);
1534
- border: 1px solid rgba(34, 211, 238, 0.2);
1535
- }
1536
- .error-message {
1537
- background: rgba(239, 68, 68, 0.1);
1538
- border-left: 4px solid #EF4444;
1539
- padding: 18px 20px;
1540
- border-radius: 10px;
1541
- margin-bottom: 32px;
1542
- }
1543
- .error-message-text {
1544
- color: #FCA5A5;
1545
- font-size: 16px;
1546
- font-weight: 600;
1547
- line-height: 1.6;
1548
- font-family: 'Courier New', monospace;
1373
+ margin-bottom: 20px;
1549
1374
  }
1550
- .stack-section {
1551
- margin-top: 32px;
1375
+
1376
+ /* Source block */
1377
+ .source-block {
1378
+ background: #1a1a1a;
1379
+ border: 1px solid #2a2a2a;
1380
+ border-radius: 12px;
1381
+ overflow: hidden;
1382
+ margin-bottom: 24px;
1552
1383
  }
1553
- .stack-header {
1384
+ .source-header {
1554
1385
  display: flex;
1555
1386
  align-items: center;
1556
1387
  justify-content: space-between;
1557
- margin-bottom: 20px;
1388
+ padding: 10px 16px;
1389
+ background: #1e1e1e;
1390
+ border-bottom: 1px solid #2a2a2a;
1391
+ font-size: 13px;
1392
+ color: #aaa;
1558
1393
  }
1559
- .stack-title {
1560
- font-size: 18px;
1561
- font-weight: 700;
1562
- color: #F1F5F9;
1563
- display: flex;
1564
- align-items: center;
1565
- gap: 10px;
1394
+ .source-header .file-icon { color: #666; margin-right: 8px; }
1395
+ .source-header a {
1396
+ color: #666;
1397
+ text-decoration: none;
1398
+ transition: color .15s;
1566
1399
  }
1567
- .frame-counter {
1568
- background: linear-gradient(135deg, #1F2937 0%, #111827 100%);
1569
- color: #22D3EE;
1570
- padding: 6px 14px;
1571
- border-radius: 8px;
1400
+ .source-header a:hover { color: #fff; }
1401
+ .source-code {
1402
+ padding: 12px 0;
1403
+ overflow-x: auto;
1404
+ font-family: 'JetBrains Mono', 'Fira Code', 'SF Mono', Menlo, monospace;
1572
1405
  font-size: 13px;
1573
- font-weight: 700;
1574
- border: 1px solid rgba(34, 211, 238, 0.2);
1406
+ line-height: 1.7;
1575
1407
  }
1576
- .error-card {
1577
- background: linear-gradient(135deg, #1E293B 0%, #0F172A 100%);
1578
- border: 1px solid rgba(34, 211, 238, 0.2);
1579
- border-radius: 14px;
1580
- padding: 20px;
1581
- margin-bottom: 12px;
1582
- transition: all 0.3s cubic-bezier(0.4, 0, 0.2, 1);
1583
- box-shadow: 0 4px 12px rgba(0, 0, 0, 0.3);
1584
- display: none;
1408
+ .src-line {
1409
+ padding: 0 16px;
1410
+ white-space: pre;
1411
+ color: #888;
1585
1412
  }
1586
- .error-card.active {
1587
- display: block;
1588
- animation: slideIn 0.3s ease-out;
1413
+ .src-err {
1414
+ background: rgba(255,50,50,0.1);
1415
+ color: #ff8a8a;
1416
+ font-weight: 500;
1589
1417
  }
1590
- .error-card:hover {
1591
- border-color: rgba(34, 211, 238, 0.5);
1592
- box-shadow: 0 8px 24px rgba(34, 211, 238, 0.2);
1593
- transform: translateY(-2px);
1594
- }
1595
- .card-header {
1418
+
1419
+ /* Call stack */
1420
+ .stack-section { margin-bottom: 24px; }
1421
+ .stack-header {
1596
1422
  display: flex;
1597
- justify-content: space-between;
1598
1423
  align-items: center;
1424
+ justify-content: space-between;
1599
1425
  margin-bottom: 12px;
1600
1426
  }
1601
- .card-title {
1602
- color: #22D3EE;
1427
+ .stack-label {
1603
1428
  font-size: 15px;
1604
1429
  font-weight: 700;
1605
- font-family: 'Courier New', monospace;
1430
+ color: #ededed;
1431
+ display: flex;
1432
+ align-items: center;
1433
+ gap: 8px;
1606
1434
  }
1607
- .card-number {
1608
- background: rgba(34, 211, 238, 0.2);
1609
- color: #22D3EE;
1610
- padding: 4px 10px;
1435
+ .stack-count {
1436
+ background: #2a2a2a;
1437
+ color: #aaa;
1438
+ padding: 2px 8px;
1611
1439
  border-radius: 6px;
1612
1440
  font-size: 12px;
1613
- font-weight: 700;
1441
+ font-weight: 600;
1614
1442
  }
1615
- .card-location {
1616
- color: #94A3B8;
1443
+ .stack-toggle {
1617
1444
  font-size: 13px;
1618
- font-family: 'Courier New', monospace;
1619
- word-break: break-all;
1620
- line-height: 1.6;
1621
- }
1622
- .pagination {
1445
+ color: #888;
1446
+ cursor: pointer;
1447
+ background: none;
1448
+ border: none;
1623
1449
  display: flex;
1624
- justify-content: center;
1625
1450
  align-items: center;
1626
- gap: 12px;
1627
- margin-top: 24px;
1628
- }
1629
- .pagination-btn {
1630
- background: linear-gradient(135deg, #1E293B 0%, #0F172A 100%);
1631
- border: 1px solid rgba(34, 211, 238, 0.3);
1632
- color: #22D3EE;
1633
- padding: 10px 20px;
1634
- border-radius: 10px;
1635
- font-size: 14px;
1636
- font-weight: 600;
1637
- cursor: pointer;
1638
- transition: all 0.2s;
1639
- }
1640
- .pagination-btn:hover:not(:disabled) {
1641
- background: linear-gradient(135deg, #22D3EE 0%, #06B6D4 100%);
1642
- color: #0F172A;
1643
- transform: translateY(-2px);
1644
- box-shadow: 0 6px 20px rgba(34, 211, 238, 0.4);
1451
+ gap: 4px;
1452
+ transition: color .15s;
1645
1453
  }
1646
- .pagination-btn:disabled {
1647
- opacity: 0.3;
1648
- cursor: not-allowed;
1454
+ .stack-toggle:hover { color: #fff; }
1455
+
1456
+ .frame {
1457
+ padding: 12px 0;
1458
+ border-bottom: 1px solid #1e1e1e;
1649
1459
  }
1650
- .pagination-info {
1651
- color: #94A3B8;
1460
+ .frame:last-child { border-bottom: none; }
1461
+ .frame-name {
1652
1462
  font-size: 14px;
1653
1463
  font-weight: 600;
1654
- }
1655
- .footer {
1656
- margin-top: 48px;
1657
- padding-top: 28px;
1658
- border-top: 1px solid rgba(34, 211, 238, 0.2);
1464
+ color: #ededed;
1659
1465
  display: flex;
1660
- justify-content: space-between;
1661
1466
  align-items: center;
1662
- flex-wrap: wrap;
1663
- gap: 20px;
1467
+ gap: 6px;
1468
+ margin-bottom: 4px;
1664
1469
  }
1665
- .brand {
1666
- display: flex;
1667
- align-items: center;
1668
- gap: 10px;
1669
- font-weight: 700;
1670
- color: #22D3EE;
1671
- font-size: 15px;
1470
+ .frame-name a {
1471
+ color: #666;
1472
+ text-decoration: none;
1473
+ transition: color .15s;
1672
1474
  }
1673
- .brand img {
1674
- width: 20px;
1675
- height: 20px;
1475
+ .frame-name a:hover { color: #fff; }
1476
+ .frame-loc {
1477
+ font-size: 13px;
1478
+ color: #666;
1479
+ font-family: 'JetBrains Mono', 'Fira Code', monospace;
1676
1480
  }
1677
- .footer-links {
1481
+
1482
+ /* Footer */
1483
+ .footer-row {
1678
1484
  display: flex;
1679
- gap: 24px;
1680
- flex-wrap: wrap;
1485
+ justify-content: flex-end;
1486
+ padding: 16px 0;
1487
+ border-top: 1px solid #1e1e1e;
1488
+ margin-top: 8px;
1681
1489
  }
1682
- .footer-links a {
1683
- color: #60A5FA;
1490
+ .footer-row a {
1491
+ color: #ff6b6b;
1684
1492
  text-decoration: none;
1685
- font-weight: 600;
1686
- transition: all 0.2s;
1687
- font-size: 14px;
1688
- }
1689
- .footer-links a:hover {
1690
- color: #22D3EE;
1691
- transform: translateY(-1px);
1493
+ font-size: 13px;
1494
+ font-weight: 500;
1495
+ display: flex;
1496
+ align-items: center;
1497
+ gap: 6px;
1498
+ transition: opacity .15s;
1692
1499
  }
1693
- .no-stack {
1694
- background: rgba(239, 68, 68, 0.1);
1695
- border: 1px solid rgba(239, 68, 68, 0.3);
1696
- border-radius: 12px;
1697
- padding: 32px;
1698
- color: #FCA5A5;
1500
+ .footer-row a:hover { opacity: 0.8; }
1501
+
1502
+ /* Prod mode */
1503
+ .prod-card {
1504
+ background: #1a1a1a;
1505
+ border: 1px solid #2a2a2a;
1506
+ border-radius: 16px;
1507
+ padding: 48px 32px;
1699
1508
  text-align: center;
1700
- font-size: 15px;
1509
+ margin-top: 32px;
1701
1510
  }
1702
- @keyframes slideIn {
1703
- from {
1704
- opacity: 0;
1705
- transform: translateY(10px);
1706
- }
1707
- to {
1708
- opacity: 1;
1709
- transform: translateY(0);
1710
- }
1511
+ .prod-card h2 { font-size: 20px; margin-bottom: 8px; color: #fff; }
1512
+ .prod-card p { font-size: 15px; color: #888; margin-bottom: 24px; }
1513
+ .prod-card a {
1514
+ display: inline-block;
1515
+ padding: 10px 24px;
1516
+ border-radius: 10px;
1517
+ background: #222;
1518
+ border: 1px solid #333;
1519
+ color: #fff;
1520
+ text-decoration: none;
1521
+ font-weight: 500;
1522
+ font-size: 14px;
1523
+ transition: all .15s;
1711
1524
  }
1525
+ .prod-card a:hover { background: #333; }
1712
1526
  </style>
1713
1527
  </head>
1714
1528
  <body>
1715
- <div class="container">
1716
- <div class="error-header">
1717
- <svg fill="none" stroke="currentColor" viewBox="0 0 24 24">
1718
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M12 9v2m0 4h.01m-6.938 4h13.856c1.54 0 2.502-1.667 1.732-3L13.732 4c-.77-1.333-2.694-1.333-3.464 0L3.34 16c-.77 1.333.192 3 1.732 3z"></path>
1719
- </svg>
1720
- <span>Unhandled Runtime Error</span>
1529
+ <div class="overlay">
1530
+ <!-- Top Bar -->
1531
+ <div class="top-bar">
1532
+ <div class="page-nav">
1533
+ <button id="prev-btn" onclick="changePage(-1)" disabled>\u2039</button>
1534
+ <span><span id="current-page">1</span>/<span id="total-pages">1</span></span>
1535
+ <button id="next-btn" onclick="changePage(1)" disabled>\u203A</button>
1536
+ </div>
1537
+ <div class="version-badge">
1538
+ <span class="version-dot"></span>
1539
+ Velix v${VERSION} esbuild
1540
+ </div>
1721
1541
  </div>
1722
-
1723
- <div class="error-badge">SERVER ERROR 500</div>
1724
- ${pathname ? `<div class="route-badge">Route: ${pathname}</div>` : ""}
1725
-
1726
- <div class="error-message">
1727
- <div class="error-message-text">${message}</div>
1542
+
1543
+ <!-- Error Tag -->
1544
+ <div class="error-tag">Unhandled Runtime Error</div>
1545
+
1546
+ <!-- Error Message -->
1547
+ <div class="error-msg">${escapeHtml2(message)}</div>
1548
+ ${pathname ? `<div class="error-hint">Check the render method of '<strong>${escapeHtml2(pathname)}</strong>'.</div>` : ""}
1549
+
1550
+ ${isDev && sourceSnippet ? `
1551
+ <!-- Source Code Block -->
1552
+ <div class="source-block">
1553
+ <div class="source-header">
1554
+ <span><span class="file-icon">\u2699</span> ${escapeHtml2(shortFile)}${errorLine ? ` (${errorLine})` : ""}${userFrames[0]?.funcName ? ` @ ${escapeHtml2(userFrames[0].funcName)}` : ""}</span>
1555
+ <a href="#" title="Open in editor">\u2197</a>
1556
+ </div>
1557
+ <div class="source-code">${sourceSnippet}</div>
1728
1558
  </div>
1729
-
1730
- ${isDev && callStackCards ? `
1559
+ ` : ""}
1560
+
1561
+ ${isDev && frames.length > 0 ? `
1562
+ <!-- Call Stack -->
1731
1563
  <div class="stack-section">
1732
1564
  <div class="stack-header">
1733
- <div class="stack-title">
1734
- <svg width="20" height="20" fill="none" stroke="currentColor" viewBox="0 0 24 24">
1735
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 12h6m-6 4h6m2 5H7a2 2 0 01-2-2V5a2 2 0 012-2h5.586a1 1 0 01.707.293l5.414 5.414a1 1 0 01.293.707V19a2 2 0 01-2 2z"></path>
1736
- </svg>
1565
+ <div class="stack-label">
1737
1566
  Call Stack
1567
+ <span class="stack-count">${frames.length}</span>
1738
1568
  </div>
1739
- <div class="frame-counter">${frameCount}</div>
1569
+ ${ignoredCount > 0 ? `<button class="stack-toggle" onclick="toggleIgnored()">Show ${ignoredCount} ignore-listed frames \u21D5</button>` : ""}
1740
1570
  </div>
1741
- <div id="error-cards">
1742
- ${callStackCards}
1571
+ <div id="frames-list">
1572
+ ${userFrames.map((f, i) => `
1573
+ <div class="frame" data-frame="${i}">
1574
+ <div class="frame-name">
1575
+ <strong>${escapeHtml2(f.funcName)}</strong>
1576
+ <a href="#" title="Open in editor">\u2197</a>
1577
+ </div>
1578
+ <div class="frame-loc">${escapeHtml2(f.file.replace(/.*[\\\/](?=app[\\\/]|server[\\\/]|src[\\\/]|pages[\\\/])/, ""))}${f.line ? ` (${f.line}:${f.col})` : ""}</div>
1579
+ </div>
1580
+ `).join("")}
1743
1581
  </div>
1744
- ${frameCount > 1 ? `
1745
- <div class="pagination">
1746
- <button class="pagination-btn" id="prev-btn" onclick="changePage(-1)">
1747
- <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="display:inline;vertical-align:middle;margin-right:4px;">
1748
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M15 19l-7-7 7-7"></path>
1749
- </svg>
1750
- Previous
1751
- </button>
1752
- <div class="pagination-info">
1753
- <span id="current-page">1</span> / <span id="total-pages">${frameCount}</span>
1582
+ <div id="ignored-frames" style="display:none;">
1583
+ ${frames.filter((f) => !f.file || f.file.includes("node_modules")).map((f, i) => `
1584
+ <div class="frame" data-frame="ignored-${i}">
1585
+ <div class="frame-name" style="color:#666;">
1586
+ <strong>${escapeHtml2(f.funcName)}</strong>
1587
+ </div>
1588
+ <div class="frame-loc">${escapeHtml2(f.file)}${f.line ? ` (${f.line}:${f.col})` : ""}</div>
1754
1589
  </div>
1755
- <button class="pagination-btn" id="next-btn" onclick="changePage(1)">
1756
- Next
1757
- <svg width="16" height="16" fill="none" stroke="currentColor" viewBox="0 0 24 24" style="display:inline;vertical-align:middle;margin-left:4px;">
1758
- <path stroke-linecap="round" stroke-linejoin="round" stroke-width="2" d="M9 5l7 7-7 7"></path>
1759
- </svg>
1760
- </button>
1590
+ `).join("")}
1761
1591
  </div>
1762
- ` : ""}
1763
1592
  </div>
1764
- ` : '<div class="no-stack">An error occurred while processing your request. Please check the server logs for more details.</div>'}
1765
-
1766
- <div class="footer">
1767
- <div class="brand">
1768
- <img src="/__velix/logo.webp" alt="Velix" onerror="this.style.display='none'"/>
1769
- <span>Velix v${VERSION}</span>
1770
- </div>
1771
- <div class="footer-links">
1772
- <a href="/">Home</a>
1773
- <a href="javascript:location.reload()">Reload</a>
1774
- <a href="https://github.com/velix/velix/tree/main/docs" target="_blank">Documentation</a>
1775
- ${isDev ? '<span style="color:#94A3B8;">Development Mode</span>' : ""}
1776
- </div>
1593
+ ` : `
1594
+ <div class="prod-card">
1595
+ <h2>Application Error</h2>
1596
+ <p>A server-side error occurred. Check your server logs for more details.</p>
1597
+ <a href="/">Return Home</a>
1598
+ </div>
1599
+ `}
1600
+
1601
+ <!-- Footer -->
1602
+ <div class="footer-row">
1603
+ <a href="javascript:location.reload()">Was this helpful? \u21BB</a>
1777
1604
  </div>
1778
1605
  </div>
1779
-
1780
- ${isDev && frameCount > 0 ? `
1606
+
1781
1607
  <script>
1782
1608
  let currentPage = 1;
1783
- const totalPages = ${frameCount};
1784
- const cards = document.querySelectorAll('.error-card');
1785
- const prevBtn = document.getElementById('prev-btn');
1786
- const nextBtn = document.getElementById('next-btn');
1787
- const currentPageSpan = document.getElementById('current-page');
1788
-
1789
- function showPage(page) {
1790
- cards.forEach((card, index) => {
1791
- card.classList.remove('active');
1792
- if (index === page - 1) {
1793
- card.classList.add('active');
1794
- }
1795
- });
1796
-
1797
- currentPage = page;
1798
- currentPageSpan.textContent = page;
1799
-
1800
- if (prevBtn) prevBtn.disabled = page === 1;
1801
- if (nextBtn) nextBtn.disabled = page === totalPages;
1802
- }
1803
-
1804
- function changePage(direction) {
1805
- const newPage = currentPage + direction;
1806
- if (newPage >= 1 && newPage <= totalPages) {
1807
- showPage(newPage);
1609
+ const totalPages = 1;
1610
+ document.getElementById('total-pages').textContent = totalPages;
1611
+
1612
+ function changePage(d) {
1613
+ const next = currentPage + d;
1614
+ if (next >= 1 && next <= totalPages) {
1615
+ currentPage = next;
1616
+ document.getElementById('current-page').textContent = currentPage;
1617
+ document.getElementById('prev-btn').disabled = currentPage === 1;
1618
+ document.getElementById('next-btn').disabled = currentPage === totalPages;
1808
1619
  }
1809
1620
  }
1810
-
1811
- // Show first page on load
1812
- showPage(1);
1813
-
1814
- // Keyboard navigation
1621
+
1622
+ function toggleIgnored() {
1623
+ const el = document.getElementById('ignored-frames');
1624
+ if (el) el.style.display = el.style.display === 'none' ? 'block' : 'none';
1625
+ }
1626
+
1815
1627
  document.addEventListener('keydown', (e) => {
1816
1628
  if (e.key === 'ArrowLeft') changePage(-1);
1817
1629
  if (e.key === 'ArrowRight') changePage(1);
1818
1630
  });
1819
1631
  </script>
1820
- ` : ""}
1821
1632
  </body>
1822
1633
  </html>`;
1823
1634
  }
1824
1635
  function getProjectVersion(dep, projectRoot) {
1825
1636
  try {
1826
- const projectRequire = createRequire(pathToFileURL(path4.join(projectRoot, "package.json")).href);
1637
+ const projectRequire = createRequire(pathToFileURL(path3.join(projectRoot, "package.json")).href);
1827
1638
  return projectRequire(`${dep}/package.json`).version;
1828
1639
  } catch (e) {
1829
1640
  try {
@@ -1868,7 +1679,7 @@ async function createServer(options = {}) {
1868
1679
  await loadPlugins(projectRoot, config);
1869
1680
  await pluginManager.runHook(PluginHooks.CONFIG, config);
1870
1681
  const middlewareFns = await loadMiddleware(projectRoot);
1871
- const appDir = config.resolvedAppDir || path4.join(projectRoot, "app");
1682
+ const appDir = config.resolvedAppDir || path3.join(projectRoot, "app");
1872
1683
  const routes = buildRouteTree(appDir);
1873
1684
  await pluginManager.runHook(PluginHooks.ROUTES_LOADED, routes);
1874
1685
  const startTime = Date.now();
@@ -1902,7 +1713,7 @@ async function createServer(options = {}) {
1902
1713
  return;
1903
1714
  }
1904
1715
  if (pathname === "/__velix/image") {
1905
- const { handleImageOptimization } = await import('./image-optimizer-KPRXE5VI.js');
1716
+ const { handleImageOptimization } = await import('./image-optimizer-QDXS3LHQ.js');
1906
1717
  await handleImageOptimization(req, res, projectRoot);
1907
1718
  return;
1908
1719
  }
@@ -1910,7 +1721,7 @@ async function createServer(options = {}) {
1910
1721
  await serveVelixInternal(pathname, req, res, projectRoot);
1911
1722
  return;
1912
1723
  }
1913
- const publicDir = config.resolvedPublicDir || path4.join(projectRoot, "public");
1724
+ const publicDir = config.resolvedPublicDir || path3.join(projectRoot, "public");
1914
1725
  if (await serveStaticFile(pathname, publicDir, res, isDev)) {
1915
1726
  if (isDev) logger_default.request(req.method || "GET", pathname, 200, Date.now() - requestStart, { type: "static" });
1916
1727
  return;
@@ -1936,7 +1747,6 @@ async function createServer(options = {}) {
1936
1747
  if (!res.headersSent) {
1937
1748
  res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
1938
1749
  res.end(generate500Page({
1939
- title: "Server Error",
1940
1750
  message: err.message || "An unexpected error occurred",
1941
1751
  stack: isDev ? err.stack : void 0,
1942
1752
  isDev,
@@ -1983,22 +1793,22 @@ async function importModuleSSR(filePath) {
1983
1793
  try {
1984
1794
  return await import(`${fileUrl}?t=${Date.now()}`);
1985
1795
  } catch (err) {
1986
- const source = fs4.readFileSync(filePath, "utf-8");
1796
+ const source = fs3.readFileSync(filePath, "utf-8");
1987
1797
  if (source.match(/^import\s+['"][^'"]+\.(css|scss|less|sass)['"];?\s*$/m)) {
1988
1798
  const stripped = source.replace(/^import\s+['"][^'"]+\.(css|scss|less|sass)['"];?\s*$/gm, "// [velix:ssr] css import stripped");
1989
- const ext = path4.extname(filePath);
1799
+ const ext = path3.extname(filePath);
1990
1800
  const tmpPath = filePath.replace(ext, `.__velix_ssr${ext}`);
1991
- fs4.writeFileSync(tmpPath, stripped);
1801
+ fs3.writeFileSync(tmpPath, stripped);
1992
1802
  try {
1993
1803
  const mod = await import(`${pathToFileURL(tmpPath).href}?t=${Date.now()}`);
1994
1804
  try {
1995
- fs4.unlinkSync(tmpPath);
1805
+ fs3.unlinkSync(tmpPath);
1996
1806
  } catch {
1997
1807
  }
1998
1808
  return mod;
1999
1809
  } catch (e2) {
2000
1810
  try {
2001
- fs4.unlinkSync(tmpPath);
1811
+ fs3.unlinkSync(tmpPath);
2002
1812
  } catch {
2003
1813
  }
2004
1814
  throw e2;
@@ -2009,18 +1819,18 @@ async function importModuleSSR(filePath) {
2009
1819
  }
2010
1820
  function collectLayouts(pageFilePath, appDir) {
2011
1821
  const layouts = [];
2012
- const normalizedAppDir = path4.resolve(appDir);
2013
- let current = path4.dirname(path4.resolve(pageFilePath));
1822
+ const normalizedAppDir = path3.resolve(appDir);
1823
+ let current = path3.dirname(path3.resolve(pageFilePath));
2014
1824
  while (true) {
2015
1825
  for (const ext of [".tsx", ".jsx", ".ts", ".js"]) {
2016
- const layoutPath = path4.join(current, `layout${ext}`);
2017
- if (fs4.existsSync(layoutPath)) {
1826
+ const layoutPath = path3.join(current, `layout${ext}`);
1827
+ if (fs3.existsSync(layoutPath)) {
2018
1828
  layouts.unshift(layoutPath);
2019
1829
  break;
2020
1830
  }
2021
1831
  }
2022
- if (path4.resolve(current) === normalizedAppDir) break;
2023
- const parent = path4.dirname(current);
1832
+ if (path3.resolve(current) === normalizedAppDir) break;
1833
+ const parent = path3.dirname(current);
2024
1834
  if (parent === current) break;
2025
1835
  current = parent;
2026
1836
  }
@@ -2040,12 +1850,12 @@ async function renderComponentAsync(Component, props) {
2040
1850
  return element;
2041
1851
  }
2042
1852
  async function serveStaticFile(pathname, publicDir, res, isDev = false) {
2043
- const filePath = path4.join(publicDir, pathname);
1853
+ const filePath = path3.join(publicDir, pathname);
2044
1854
  if (!filePath.startsWith(publicDir)) return false;
2045
- if (!fs4.existsSync(filePath) || fs4.statSync(filePath).isDirectory()) return false;
2046
- const ext = path4.extname(filePath);
1855
+ if (!fs3.existsSync(filePath) || fs3.statSync(filePath).isDirectory()) return false;
1856
+ const ext = path3.extname(filePath);
2047
1857
  const contentType = MIME_TYPES[ext] || "application/octet-stream";
2048
- const content = fs4.readFileSync(filePath);
1858
+ const content = fs3.readFileSync(filePath);
2049
1859
  res.writeHead(200, {
2050
1860
  "Content-Type": contentType,
2051
1861
  "Content-Length": content.length,
@@ -2124,7 +1934,7 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
2124
1934
  const mod = await import(`${fileUrl}?t=${Date.now()}`);
2125
1935
  const PageComponent = mod.default;
2126
1936
  let metadata = mod.metadata || mod.generateMetadata?.(route.params) || {};
2127
- const appDir = config.resolvedAppDir || path4.join(projectRoot, "app");
1937
+ const appDir = config.resolvedAppDir || path3.join(projectRoot, "app");
2128
1938
  const layoutPaths = collectLayouts(route.filePath, appDir);
2129
1939
  const layoutModules = [];
2130
1940
  for (const lp of layoutPaths) {
@@ -2272,7 +2082,6 @@ async function handlePageRoute(route, routes, req, res, url, config, isDev, proj
2272
2082
  logger_default.error(`Render error: ${route.path}`, error);
2273
2083
  res.writeHead(500, { "Content-Type": "text/html; charset=utf-8" });
2274
2084
  res.end(generate500Page({
2275
- title: "Render Error",
2276
2085
  message: error.message || "Failed to render page",
2277
2086
  stack: isDev ? error.stack : void 0,
2278
2087
  isDev,
@@ -2298,19 +2107,19 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2298
2107
  }
2299
2108
  if (pathname === "/__velix/logo.webp") {
2300
2109
  const __filename2 = fileURLToPath(import.meta.url);
2301
- const __dirname2 = path4.dirname(__filename2);
2110
+ const __dirname2 = path3.dirname(__filename2);
2302
2111
  const candidates = [
2303
- path4.join(__dirname2, "..", "assets", "logo.webp"),
2304
- path4.join(__dirname2, "..", "..", "assets", "logo.webp"),
2305
- path4.join(process.cwd(), "node_modules", "@teamvelix", "velix", "assets", "logo.webp"),
2306
- path4.join(process.cwd(), "packages", "velix", "assets", "logo.webp"),
2307
- path4.join(process.cwd(), "node_modules", "velix", "assets", "logo.webp"),
2308
- path4.join(process.cwd(), "public", "favicon.webp")
2112
+ path3.join(__dirname2, "..", "assets", "logo.webp"),
2113
+ path3.join(__dirname2, "..", "..", "assets", "logo.webp"),
2114
+ path3.join(process.cwd(), "node_modules", "@teamvelix", "velix", "assets", "logo.webp"),
2115
+ path3.join(process.cwd(), "packages", "velix", "assets", "logo.webp"),
2116
+ path3.join(process.cwd(), "node_modules", "velix", "assets", "logo.webp"),
2117
+ path3.join(process.cwd(), "public", "favicon.webp")
2309
2118
  ];
2310
- const logoPath = candidates.find((p) => fs4.existsSync(p));
2119
+ const logoPath = candidates.find((p) => fs3.existsSync(p));
2311
2120
  if (logoPath) {
2312
2121
  res.writeHead(200, { "Content-Type": "image/webp", "Cache-Control": "public, max-age=31536000, immutable" });
2313
- res.end(fs4.readFileSync(logoPath));
2122
+ res.end(fs3.readFileSync(logoPath));
2314
2123
  } else {
2315
2124
  res.writeHead(404);
2316
2125
  res.end();
@@ -2320,11 +2129,11 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2320
2129
  if (pathname === "/__velix/hmr-client.js") {
2321
2130
  try {
2322
2131
  const candidates = [
2323
- path4.join(process.cwd(), "packages", "velix-react", "src", "hmr", "hmr-client.ts"),
2324
- path4.join(process.cwd(), "node_modules", "@teamvelix", "velix-react", "src", "hmr", "hmr-client.ts"),
2325
- path4.join(__dirname$1, "..", "..", "velix-react", "src", "hmr", "hmr-client.ts")
2132
+ path3.join(process.cwd(), "packages", "velix-react", "src", "hmr", "hmr-client.ts"),
2133
+ path3.join(process.cwd(), "node_modules", "@teamvelix", "velix-react", "src", "hmr", "hmr-client.ts"),
2134
+ path3.join(__dirname$1, "..", "..", "velix-react", "src", "hmr", "hmr-client.ts")
2326
2135
  ];
2327
- const hmrClientSrc = candidates.find((p) => fs4.existsSync(p));
2136
+ const hmrClientSrc = candidates.find((p) => fs3.existsSync(p));
2328
2137
  if (!hmrClientSrc) {
2329
2138
  res.writeHead(404);
2330
2139
  res.end();
@@ -2353,17 +2162,17 @@ async function serveVelixInternal(pathname, req, res, projectRoot) {
2353
2162
  const componentName = pathname.replace("/__velix/islands/", "").replace(".js", "");
2354
2163
  try {
2355
2164
  const searchDirs = [
2356
- path4.join(projectRoot, "components"),
2357
- path4.join(projectRoot, "app"),
2358
- path4.join(projectRoot, "islands")
2165
+ path3.join(projectRoot, "components"),
2166
+ path3.join(projectRoot, "app"),
2167
+ path3.join(projectRoot, "islands")
2359
2168
  ];
2360
2169
  let componentPath = "";
2361
2170
  for (const dir of searchDirs) {
2362
- if (!fs4.existsSync(dir)) continue;
2363
- const files = fs4.readdirSync(dir, { recursive: true });
2171
+ if (!fs3.existsSync(dir)) continue;
2172
+ const files = fs3.readdirSync(dir, { recursive: true });
2364
2173
  const found = files.find((f) => f.replace(/\\/g, "/").endsWith(`${componentName}.tsx`) || f.replace(/\\/g, "/").endsWith(`${componentName}.jsx`));
2365
2174
  if (found) {
2366
- componentPath = path4.join(dir, found);
2175
+ componentPath = path3.join(dir, found);
2367
2176
  break;
2368
2177
  }
2369
2178
  }
@@ -2450,6 +2259,6 @@ function parseRawBody(req) {
2450
2259
  }
2451
2260
  var server_default = { createServer, tailwindPlugin };
2452
2261
 
2453
- export { PluginHooks, PluginManager, RedirectError, bindArgs, callServerAction, composeMiddleware, cookies, createServer, definePlugin, deserializeArgs, executeAction, formAction, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getAction, getMethod, getPathname, headers, html, isMethod, json, jsonLd, loadMiddleware, loadPlugins, mergeMetadata, middlewares, notFound, parseFormData, parseJson, parseSearchParams, pluginManager, redirect, registerAction, runMiddleware, serverAction, server_default, tailwindPlugin, text, useActionContext, useVelixAction };
2454
- //# sourceMappingURL=chunk-HGP4TUJS.js.map
2455
- //# sourceMappingURL=chunk-HGP4TUJS.js.map
2262
+ export { RedirectError, bindArgs, callServerAction, composeMiddleware, cookies, createServer, deserializeArgs, executeAction, formAction, generateJsonLd, generateMetadataTags, generateRobotsTxt, generateSitemap, getAction, getMethod, getPathname, headers, html, isMethod, json, jsonLd, loadMiddleware, mergeMetadata, middlewares, notFound, parseFormData, parseJson, parseSearchParams, redirect, registerAction, runMiddleware, serverAction, server_default, tailwindPlugin, text, useActionContext, useVelixAction };
2263
+ //# sourceMappingURL=chunk-MAAAP4QR.js.map
2264
+ //# sourceMappingURL=chunk-MAAAP4QR.js.map