@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.
- package/dist/build/index.js +3 -3
- package/dist/chunk-BQ4HFLRL.js +16 -0
- package/dist/chunk-BQ4HFLRL.js.map +1 -0
- package/dist/{chunk-HGP4TUJS.js → chunk-MAAAP4QR.js} +358 -549
- package/dist/chunk-MAAAP4QR.js.map +1 -0
- package/dist/{chunk-MLLSS7Y5.js → chunk-SNWXKPXR.js} +143 -8
- package/dist/chunk-SNWXKPXR.js.map +1 -0
- package/dist/{chunk-3LWUS6AC.js → chunk-VK4EZACN.js} +7 -3
- package/dist/chunk-VK4EZACN.js.map +1 -0
- package/dist/client/index.js +1 -1
- package/dist/config.d.ts +2 -2
- package/dist/config.js +1 -1
- package/dist/{image-optimizer-KPRXE5VI.js → image-optimizer-QDXS3LHQ.js} +3 -3
- package/dist/{image-optimizer-KPRXE5VI.js.map → image-optimizer-QDXS3LHQ.js.map} +1 -1
- package/dist/index.js +4 -4
- package/dist/islands/index.js +1 -1
- package/dist/runtime/start-build.js +164 -21
- package/dist/runtime/start-build.js.map +1 -1
- package/dist/runtime/start-dev.js +311 -360
- package/dist/runtime/start-dev.js.map +1 -1
- package/dist/runtime/start-prod.js +311 -360
- package/dist/runtime/start-prod.js.map +1 -1
- package/dist/server/index.js +3 -3
- package/package.json +3 -3
- package/dist/chunk-3LWUS6AC.js.map +0 -1
- package/dist/chunk-4S5YQJHB.js +0 -11
- package/dist/chunk-4S5YQJHB.js.map +0 -1
- package/dist/chunk-HGP4TUJS.js.map +0 -1
- package/dist/chunk-MLLSS7Y5.js.map +0 -1
|
@@ -1,10 +1,10 @@
|
|
|
1
|
-
import { logger_default, buildRouteTree, matchRoute, VERSION } from './chunk-
|
|
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-
|
|
4
|
+
import { __dirname as __dirname$1, __require } from './chunk-BQ4HFLRL.js';
|
|
5
5
|
import http from 'http';
|
|
6
|
-
import
|
|
7
|
-
import
|
|
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 =
|
|
77
|
-
if (!
|
|
76
|
+
const filePath = path3.join(projectRoot, file);
|
|
77
|
+
if (!fs3.existsSync(filePath)) continue;
|
|
78
78
|
try {
|
|
79
|
-
const { pathToFileURL:
|
|
80
|
-
const url =
|
|
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 (!
|
|
231
|
+
if (!fs3.existsSync(input)) {
|
|
366
232
|
logger_default.warn(`Tailwind input file not found: ${input}`);
|
|
367
233
|
return;
|
|
368
234
|
}
|
|
369
|
-
const outputDir =
|
|
370
|
-
if (!
|
|
371
|
-
|
|
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, "&").replace(/</g, "<").replace(/>/g, ">").replace(/"/g, """);
|
|
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
|
|
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:
|
|
1197
|
+
background: #161616;
|
|
1329
1198
|
color: white;
|
|
1330
|
-
font-family:
|
|
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
|
-
|
|
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:
|
|
1214
|
+
font-size: 160px;
|
|
1353
1215
|
font-weight: 900;
|
|
1354
1216
|
margin: 0;
|
|
1355
|
-
background: linear-gradient(135deg, #
|
|
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:
|
|
1222
|
+
animation: fadeIn 0.5s ease-out;
|
|
1361
1223
|
}
|
|
1362
1224
|
h2 {
|
|
1363
|
-
font-size:
|
|
1364
|
-
font-weight:
|
|
1365
|
-
margin:
|
|
1366
|
-
color: #
|
|
1367
|
-
animation:
|
|
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: #
|
|
1371
|
-
font-size:
|
|
1232
|
+
color: #888;
|
|
1233
|
+
font-size: 16px;
|
|
1372
1234
|
line-height: 1.7;
|
|
1373
|
-
margin-bottom:
|
|
1374
|
-
animation:
|
|
1235
|
+
margin-bottom: 36px;
|
|
1236
|
+
animation: fadeIn 0.5s ease-out 0.2s backwards;
|
|
1375
1237
|
}
|
|
1376
1238
|
code {
|
|
1377
|
-
background:
|
|
1378
|
-
padding:
|
|
1239
|
+
background: #222;
|
|
1240
|
+
padding: 3px 8px;
|
|
1379
1241
|
border-radius: 6px;
|
|
1380
|
-
font-family: '
|
|
1381
|
-
color: #
|
|
1382
|
-
font-size:
|
|
1383
|
-
border: 1px solid
|
|
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:
|
|
1249
|
+
gap: 12px;
|
|
1388
1250
|
justify-content: center;
|
|
1389
|
-
|
|
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:
|
|
1255
|
+
background: #222;
|
|
1395
1256
|
color: white;
|
|
1396
1257
|
text-decoration: none;
|
|
1397
|
-
padding:
|
|
1398
|
-
border-radius:
|
|
1258
|
+
padding: 12px 28px;
|
|
1259
|
+
border-radius: 10px;
|
|
1399
1260
|
font-weight: 600;
|
|
1400
|
-
font-size:
|
|
1401
|
-
transition: all 0.
|
|
1402
|
-
|
|
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
|
-
|
|
1408
|
-
|
|
1409
|
-
|
|
1410
|
-
|
|
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-
|
|
1417
|
-
|
|
1418
|
-
|
|
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
|
|
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 {
|
|
1448
|
-
let
|
|
1449
|
-
let
|
|
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("
|
|
1452
|
-
|
|
1453
|
-
|
|
1454
|
-
|
|
1455
|
-
|
|
1456
|
-
|
|
1457
|
-
|
|
1458
|
-
|
|
1459
|
-
|
|
1460
|
-
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
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
|
-
|
|
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
|
|
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
|
-
|
|
1483
|
-
|
|
1484
|
-
|
|
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
|
-
|
|
1488
|
-
|
|
1489
|
-
|
|
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
|
-
.
|
|
1526
|
-
|
|
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:
|
|
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
|
-
|
|
1551
|
-
|
|
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
|
-
.
|
|
1384
|
+
.source-header {
|
|
1554
1385
|
display: flex;
|
|
1555
1386
|
align-items: center;
|
|
1556
1387
|
justify-content: space-between;
|
|
1557
|
-
|
|
1388
|
+
padding: 10px 16px;
|
|
1389
|
+
background: #1e1e1e;
|
|
1390
|
+
border-bottom: 1px solid #2a2a2a;
|
|
1391
|
+
font-size: 13px;
|
|
1392
|
+
color: #aaa;
|
|
1558
1393
|
}
|
|
1559
|
-
.
|
|
1560
|
-
|
|
1561
|
-
|
|
1562
|
-
|
|
1563
|
-
|
|
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
|
-
.
|
|
1568
|
-
|
|
1569
|
-
|
|
1570
|
-
|
|
1571
|
-
|
|
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
|
-
|
|
1574
|
-
border: 1px solid rgba(34, 211, 238, 0.2);
|
|
1406
|
+
line-height: 1.7;
|
|
1575
1407
|
}
|
|
1576
|
-
.
|
|
1577
|
-
|
|
1578
|
-
|
|
1579
|
-
|
|
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
|
-
.
|
|
1587
|
-
|
|
1588
|
-
|
|
1413
|
+
.src-err {
|
|
1414
|
+
background: rgba(255,50,50,0.1);
|
|
1415
|
+
color: #ff8a8a;
|
|
1416
|
+
font-weight: 500;
|
|
1589
1417
|
}
|
|
1590
|
-
|
|
1591
|
-
|
|
1592
|
-
|
|
1593
|
-
|
|
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
|
-
.
|
|
1602
|
-
color: #22D3EE;
|
|
1427
|
+
.stack-label {
|
|
1603
1428
|
font-size: 15px;
|
|
1604
1429
|
font-weight: 700;
|
|
1605
|
-
|
|
1430
|
+
color: #ededed;
|
|
1431
|
+
display: flex;
|
|
1432
|
+
align-items: center;
|
|
1433
|
+
gap: 8px;
|
|
1606
1434
|
}
|
|
1607
|
-
.
|
|
1608
|
-
background:
|
|
1609
|
-
color: #
|
|
1610
|
-
padding:
|
|
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:
|
|
1441
|
+
font-weight: 600;
|
|
1614
1442
|
}
|
|
1615
|
-
.
|
|
1616
|
-
color: #94A3B8;
|
|
1443
|
+
.stack-toggle {
|
|
1617
1444
|
font-size: 13px;
|
|
1618
|
-
|
|
1619
|
-
|
|
1620
|
-
|
|
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:
|
|
1627
|
-
|
|
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
|
-
.
|
|
1647
|
-
|
|
1648
|
-
|
|
1454
|
+
.stack-toggle:hover { color: #fff; }
|
|
1455
|
+
|
|
1456
|
+
.frame {
|
|
1457
|
+
padding: 12px 0;
|
|
1458
|
+
border-bottom: 1px solid #1e1e1e;
|
|
1649
1459
|
}
|
|
1650
|
-
.
|
|
1651
|
-
|
|
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
|
-
|
|
1663
|
-
|
|
1467
|
+
gap: 6px;
|
|
1468
|
+
margin-bottom: 4px;
|
|
1664
1469
|
}
|
|
1665
|
-
.
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
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
|
-
.
|
|
1674
|
-
|
|
1675
|
-
|
|
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
|
-
|
|
1481
|
+
|
|
1482
|
+
/* Footer */
|
|
1483
|
+
.footer-row {
|
|
1678
1484
|
display: flex;
|
|
1679
|
-
|
|
1680
|
-
|
|
1485
|
+
justify-content: flex-end;
|
|
1486
|
+
padding: 16px 0;
|
|
1487
|
+
border-top: 1px solid #1e1e1e;
|
|
1488
|
+
margin-top: 8px;
|
|
1681
1489
|
}
|
|
1682
|
-
.footer-
|
|
1683
|
-
color: #
|
|
1490
|
+
.footer-row a {
|
|
1491
|
+
color: #ff6b6b;
|
|
1684
1492
|
text-decoration: none;
|
|
1685
|
-
font-
|
|
1686
|
-
|
|
1687
|
-
|
|
1688
|
-
|
|
1689
|
-
|
|
1690
|
-
|
|
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
|
-
.
|
|
1694
|
-
|
|
1695
|
-
|
|
1696
|
-
|
|
1697
|
-
|
|
1698
|
-
|
|
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
|
-
|
|
1509
|
+
margin-top: 32px;
|
|
1701
1510
|
}
|
|
1702
|
-
|
|
1703
|
-
|
|
1704
|
-
|
|
1705
|
-
|
|
1706
|
-
|
|
1707
|
-
|
|
1708
|
-
|
|
1709
|
-
|
|
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="
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
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
|
-
|
|
1724
|
-
|
|
1725
|
-
|
|
1726
|
-
|
|
1727
|
-
|
|
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
|
-
|
|
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-
|
|
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
|
-
|
|
1569
|
+
${ignoredCount > 0 ? `<button class="stack-toggle" onclick="toggleIgnored()">Show ${ignoredCount} ignore-listed frames \u21D5</button>` : ""}
|
|
1740
1570
|
</div>
|
|
1741
|
-
<div id="
|
|
1742
|
-
${
|
|
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
|
-
|
|
1745
|
-
|
|
1746
|
-
<
|
|
1747
|
-
<
|
|
1748
|
-
|
|
1749
|
-
</
|
|
1750
|
-
|
|
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
|
-
|
|
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
|
-
` :
|
|
1765
|
-
|
|
1766
|
-
|
|
1767
|
-
<
|
|
1768
|
-
|
|
1769
|
-
|
|
1770
|
-
|
|
1771
|
-
|
|
1772
|
-
|
|
1773
|
-
|
|
1774
|
-
|
|
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 =
|
|
1784
|
-
|
|
1785
|
-
|
|
1786
|
-
|
|
1787
|
-
|
|
1788
|
-
|
|
1789
|
-
|
|
1790
|
-
|
|
1791
|
-
|
|
1792
|
-
|
|
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
|
-
|
|
1812
|
-
|
|
1813
|
-
|
|
1814
|
-
|
|
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(
|
|
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 ||
|
|
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-
|
|
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 ||
|
|
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 =
|
|
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 =
|
|
1799
|
+
const ext = path3.extname(filePath);
|
|
1990
1800
|
const tmpPath = filePath.replace(ext, `.__velix_ssr${ext}`);
|
|
1991
|
-
|
|
1801
|
+
fs3.writeFileSync(tmpPath, stripped);
|
|
1992
1802
|
try {
|
|
1993
1803
|
const mod = await import(`${pathToFileURL(tmpPath).href}?t=${Date.now()}`);
|
|
1994
1804
|
try {
|
|
1995
|
-
|
|
1805
|
+
fs3.unlinkSync(tmpPath);
|
|
1996
1806
|
} catch {
|
|
1997
1807
|
}
|
|
1998
1808
|
return mod;
|
|
1999
1809
|
} catch (e2) {
|
|
2000
1810
|
try {
|
|
2001
|
-
|
|
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 =
|
|
2013
|
-
let current =
|
|
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 =
|
|
2017
|
-
if (
|
|
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 (
|
|
2023
|
-
const parent =
|
|
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 =
|
|
1853
|
+
const filePath = path3.join(publicDir, pathname);
|
|
2044
1854
|
if (!filePath.startsWith(publicDir)) return false;
|
|
2045
|
-
if (!
|
|
2046
|
-
const ext =
|
|
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 =
|
|
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 ||
|
|
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 =
|
|
2110
|
+
const __dirname2 = path3.dirname(__filename2);
|
|
2302
2111
|
const candidates = [
|
|
2303
|
-
|
|
2304
|
-
|
|
2305
|
-
|
|
2306
|
-
|
|
2307
|
-
|
|
2308
|
-
|
|
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) =>
|
|
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(
|
|
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
|
-
|
|
2324
|
-
|
|
2325
|
-
|
|
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) =>
|
|
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
|
-
|
|
2357
|
-
|
|
2358
|
-
|
|
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 (!
|
|
2363
|
-
const files =
|
|
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 =
|
|
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 {
|
|
2454
|
-
//# sourceMappingURL=chunk-
|
|
2455
|
-
//# sourceMappingURL=chunk-
|
|
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
|