@lolyjs/core 0.1.0-alpha.9 → 0.2.0-alpha.1
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/README.md +467 -325
- package/dist/bootstrap-BiCQmSkx.d.mts +50 -0
- package/dist/bootstrap-BiCQmSkx.d.ts +50 -0
- package/dist/cli.cjs +98 -20
- package/dist/cli.cjs.map +1 -1
- package/dist/cli.js +98 -20
- package/dist/cli.js.map +1 -1
- package/dist/index.cjs +169 -158
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.mts +2 -35
- package/dist/index.d.ts +2 -35
- package/dist/index.js +169 -158
- package/dist/index.js.map +1 -1
- package/dist/react/hooks.cjs +5 -5
- package/dist/react/hooks.cjs.map +1 -1
- package/dist/react/hooks.d.mts +13 -3
- package/dist/react/hooks.d.ts +13 -3
- package/dist/react/hooks.js +5 -5
- package/dist/react/hooks.js.map +1 -1
- package/dist/react/sockets.cjs +5 -1
- package/dist/react/sockets.cjs.map +1 -1
- package/dist/react/sockets.js +5 -1
- package/dist/react/sockets.js.map +1 -1
- package/dist/runtime.cjs +91 -160
- package/dist/runtime.cjs.map +1 -1
- package/dist/runtime.d.mts +3 -45
- package/dist/runtime.d.ts +3 -45
- package/dist/runtime.js +87 -160
- package/dist/runtime.js.map +1 -1
- package/package.json +2 -4
package/dist/index.cjs
CHANGED
|
@@ -1407,24 +1407,69 @@ function createClientConfig(projectRoot, mode) {
|
|
|
1407
1407
|
var import_path15 = __toESM(require("path"));
|
|
1408
1408
|
var import_fs12 = __toESM(require("fs"));
|
|
1409
1409
|
init_globals();
|
|
1410
|
-
function startClientBundler(projectRoot) {
|
|
1411
|
-
const { config, outDir } = createClientConfig(projectRoot,
|
|
1410
|
+
function startClientBundler(projectRoot, mode = "development") {
|
|
1411
|
+
const { config, outDir } = createClientConfig(projectRoot, mode);
|
|
1412
1412
|
copyStaticAssets(projectRoot, outDir);
|
|
1413
1413
|
const compiler = (0, import_core2.rspack)(config);
|
|
1414
|
+
let isBuilding = false;
|
|
1415
|
+
let buildResolve = null;
|
|
1416
|
+
let buildPromise = null;
|
|
1417
|
+
let lastBuildTime = Date.now();
|
|
1418
|
+
compiler.hooks.compile.tap("HotReload", () => {
|
|
1419
|
+
isBuilding = true;
|
|
1420
|
+
buildPromise = new Promise((resolve3) => {
|
|
1421
|
+
buildResolve = resolve3;
|
|
1422
|
+
});
|
|
1423
|
+
});
|
|
1414
1424
|
compiler.watch({}, (err, stats) => {
|
|
1415
1425
|
if (err) {
|
|
1416
1426
|
console.error("[framework][client] Rspack error:", err);
|
|
1427
|
+
isBuilding = false;
|
|
1428
|
+
lastBuildTime = Date.now();
|
|
1429
|
+
if (buildResolve) {
|
|
1430
|
+
buildResolve();
|
|
1431
|
+
buildResolve = null;
|
|
1432
|
+
buildPromise = null;
|
|
1433
|
+
}
|
|
1434
|
+
return;
|
|
1435
|
+
}
|
|
1436
|
+
if (!stats) {
|
|
1437
|
+
isBuilding = false;
|
|
1438
|
+
lastBuildTime = Date.now();
|
|
1417
1439
|
return;
|
|
1418
1440
|
}
|
|
1419
|
-
if (!stats) return;
|
|
1420
1441
|
if (stats.hasErrors()) {
|
|
1421
1442
|
console.error(
|
|
1422
1443
|
"[framework][client] Build with errors:\n",
|
|
1423
1444
|
stats.toString("errors-only")
|
|
1424
1445
|
);
|
|
1446
|
+
} else {
|
|
1447
|
+
console.log("[framework][client] \u2713 Client bundle rebuilt successfully");
|
|
1448
|
+
}
|
|
1449
|
+
isBuilding = false;
|
|
1450
|
+
lastBuildTime = Date.now();
|
|
1451
|
+
if (buildResolve) {
|
|
1452
|
+
buildResolve();
|
|
1453
|
+
buildResolve = null;
|
|
1454
|
+
buildPromise = null;
|
|
1425
1455
|
}
|
|
1426
1456
|
});
|
|
1427
|
-
return {
|
|
1457
|
+
return {
|
|
1458
|
+
outDir,
|
|
1459
|
+
waitForBuild: async () => {
|
|
1460
|
+
if (isBuilding && buildPromise) {
|
|
1461
|
+
await buildPromise;
|
|
1462
|
+
await new Promise((resolve3) => setTimeout(resolve3, 100));
|
|
1463
|
+
return;
|
|
1464
|
+
}
|
|
1465
|
+
const timeSinceLastBuild = Date.now() - lastBuildTime;
|
|
1466
|
+
if (timeSinceLastBuild < 500) {
|
|
1467
|
+
await new Promise((resolve3) => setTimeout(resolve3, 200));
|
|
1468
|
+
return;
|
|
1469
|
+
}
|
|
1470
|
+
return Promise.resolve();
|
|
1471
|
+
}
|
|
1472
|
+
};
|
|
1428
1473
|
}
|
|
1429
1474
|
function buildClientBundle(projectRoot) {
|
|
1430
1475
|
const { config, outDir } = createClientConfig(projectRoot, "production");
|
|
@@ -3155,7 +3200,9 @@ init_globals();
|
|
|
3155
3200
|
function setupHotReload({
|
|
3156
3201
|
app,
|
|
3157
3202
|
appDir,
|
|
3158
|
-
route = "/__fw/hot"
|
|
3203
|
+
route = "/__fw/hot",
|
|
3204
|
+
waitForBuild,
|
|
3205
|
+
onFileChange
|
|
3159
3206
|
}) {
|
|
3160
3207
|
const clients = /* @__PURE__ */ new Set();
|
|
3161
3208
|
app.get(route, (req, res) => {
|
|
@@ -3176,9 +3223,25 @@ data: connected
|
|
|
3176
3223
|
ignoreInitial: true,
|
|
3177
3224
|
ignored: ["**/node_modules/**", `**/${BUILD_FOLDER_NAME}/**`, "**/.git/**"]
|
|
3178
3225
|
});
|
|
3179
|
-
function broadcastReload(reason, filePath) {
|
|
3226
|
+
async function broadcastReload(reason, filePath) {
|
|
3180
3227
|
const rel = import_path16.default.relative(appDir, filePath);
|
|
3181
3228
|
console.log(`[hot-reload] ${reason}: ${rel}`);
|
|
3229
|
+
if (onFileChange) {
|
|
3230
|
+
try {
|
|
3231
|
+
await onFileChange(filePath);
|
|
3232
|
+
} catch (error) {
|
|
3233
|
+
console.warn("[hot-reload] Error in onFileChange callback:", error);
|
|
3234
|
+
}
|
|
3235
|
+
}
|
|
3236
|
+
if (waitForBuild) {
|
|
3237
|
+
try {
|
|
3238
|
+
console.log("[hot-reload] Waiting for client bundle to finish...");
|
|
3239
|
+
await waitForBuild();
|
|
3240
|
+
console.log("[hot-reload] Client bundle ready, sending reload event");
|
|
3241
|
+
} catch (error) {
|
|
3242
|
+
console.warn("[hot-reload] Error waiting for build:", error);
|
|
3243
|
+
}
|
|
3244
|
+
}
|
|
3182
3245
|
for (const res of clients) {
|
|
3183
3246
|
res.write(`event: message
|
|
3184
3247
|
data: reload:${rel}
|
|
@@ -3317,14 +3380,29 @@ function setupServer(app, options) {
|
|
|
3317
3380
|
};
|
|
3318
3381
|
};
|
|
3319
3382
|
var getRoutes = getRoutes2;
|
|
3320
|
-
|
|
3383
|
+
const { outDir, waitForBuild } = startClientBundler(projectRoot, "development");
|
|
3384
|
+
const onFileChange = async (filePath) => {
|
|
3385
|
+
const rel = import_path19.default.relative(appDir, filePath);
|
|
3386
|
+
const isPageFile = filePath.includes("page.tsx") || filePath.includes("page.ts") || filePath.includes("layout.tsx") || filePath.includes("layout.ts") || filePath.includes("_not-found") || filePath.includes("_error");
|
|
3387
|
+
const isTsFile = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
|
|
3388
|
+
if (isTsFile) {
|
|
3389
|
+
clearAppRequireCache(appDir);
|
|
3390
|
+
console.log(`[hot-reload] Cleared require cache for: ${rel}`);
|
|
3391
|
+
}
|
|
3392
|
+
if (isPageFile) {
|
|
3393
|
+
const loader = new FilesystemRouteLoader(appDir);
|
|
3394
|
+
const newRoutes = loader.loadRoutes();
|
|
3395
|
+
writeClientRoutesManifest(newRoutes, projectRoot);
|
|
3396
|
+
console.log("[hot-reload] Client routes manifest reloaded");
|
|
3397
|
+
}
|
|
3398
|
+
};
|
|
3399
|
+
setupHotReload({ app, appDir, waitForBuild, onFileChange });
|
|
3400
|
+
app.use("/static", import_express.default.static(outDir));
|
|
3321
3401
|
const routes = routeLoader.loadRoutes();
|
|
3322
3402
|
const wssRoutes = routeLoader.loadWssRoutes();
|
|
3323
3403
|
const notFoundPage = routeLoader.loadNotFoundRoute();
|
|
3324
3404
|
const errorPage = routeLoader.loadErrorRoute();
|
|
3325
3405
|
writeClientRoutesManifest(routes, projectRoot);
|
|
3326
|
-
const { outDir } = startClientBundler(projectRoot);
|
|
3327
|
-
app.use("/static", import_express.default.static(outDir));
|
|
3328
3406
|
return {
|
|
3329
3407
|
routes,
|
|
3330
3408
|
wssRoutes,
|
|
@@ -4022,7 +4100,7 @@ async function handlePageRequest(options) {
|
|
|
4022
4100
|
const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
|
|
4023
4101
|
const reqLogger = getRequestLogger(req);
|
|
4024
4102
|
if (errorPage) {
|
|
4025
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot);
|
|
4103
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
|
|
4026
4104
|
} else {
|
|
4027
4105
|
reqLogger.error("Unhandled error in page request", error, {
|
|
4028
4106
|
urlPath: options.urlPath,
|
|
@@ -4050,9 +4128,9 @@ async function handlePageRequestInternal(options) {
|
|
|
4050
4128
|
theme,
|
|
4051
4129
|
projectRoot
|
|
4052
4130
|
} = options;
|
|
4053
|
-
const clientJsPath = projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4054
|
-
const clientCssPath = projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4055
|
-
const assetManifest = projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4131
|
+
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4132
|
+
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4133
|
+
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4056
4134
|
const isDataReq = isDataRequest(req);
|
|
4057
4135
|
if (env === "prod" && ssgOutDir) {
|
|
4058
4136
|
if (isDataReq) {
|
|
@@ -4108,7 +4186,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4108
4186
|
const reqLogger = getRequestLogger(req);
|
|
4109
4187
|
reqLogger.error("SSR shell error", err, { route: "not-found" });
|
|
4110
4188
|
if (!res.headersSent && errorPage) {
|
|
4111
|
-
renderErrorPageWithStream(errorPage, req, res, err, routeChunks);
|
|
4189
|
+
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4112
4190
|
} else if (!res.headersSent) {
|
|
4113
4191
|
res.statusCode = 500;
|
|
4114
4192
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4155,7 +4233,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4155
4233
|
return;
|
|
4156
4234
|
} else {
|
|
4157
4235
|
if (errorPage) {
|
|
4158
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot);
|
|
4236
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
|
|
4159
4237
|
return;
|
|
4160
4238
|
} else {
|
|
4161
4239
|
throw error;
|
|
@@ -4217,7 +4295,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4217
4295
|
const reqLogger = getRequestLogger(req);
|
|
4218
4296
|
reqLogger.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4219
4297
|
if (!res.headersSent && errorPage) {
|
|
4220
|
-
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot);
|
|
4298
|
+
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4221
4299
|
} else if (!res.headersSent) {
|
|
4222
4300
|
res.statusCode = 500;
|
|
4223
4301
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4235,7 +4313,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4235
4313
|
abort();
|
|
4236
4314
|
});
|
|
4237
4315
|
}
|
|
4238
|
-
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot) {
|
|
4316
|
+
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
|
|
4239
4317
|
try {
|
|
4240
4318
|
const isDataReq = isDataRequest(req);
|
|
4241
4319
|
const ctx = {
|
|
@@ -4264,9 +4342,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4264
4342
|
return;
|
|
4265
4343
|
}
|
|
4266
4344
|
const appTree = buildAppTree(errorPage, { error: String(error) }, initialData.props);
|
|
4267
|
-
const clientJsPath = projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4268
|
-
const clientCssPath = projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4269
|
-
const assetManifest = projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4345
|
+
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4346
|
+
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4347
|
+
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4270
4348
|
const chunkName = routeChunks[ERROR_CHUNK_KEY];
|
|
4271
4349
|
let chunkHref = null;
|
|
4272
4350
|
if (chunkName != null) {
|
|
@@ -5141,11 +5219,6 @@ var import_react2 = require("react");
|
|
|
5141
5219
|
// modules/runtime/client/RouterView.tsx
|
|
5142
5220
|
var import_jsx_runtime = require("react/jsx-runtime");
|
|
5143
5221
|
function RouterView({ state }) {
|
|
5144
|
-
console.log("[loly:RouterView] Rendering", {
|
|
5145
|
-
url: state.url,
|
|
5146
|
-
hasRoute: !!state.route,
|
|
5147
|
-
hasComponents: !!state.components
|
|
5148
|
-
});
|
|
5149
5222
|
if (!state.route) {
|
|
5150
5223
|
if (state.components === null) {
|
|
5151
5224
|
return null;
|
|
@@ -5157,11 +5230,6 @@ function RouterView({ state }) {
|
|
|
5157
5230
|
}
|
|
5158
5231
|
const { Page, layouts } = state.components;
|
|
5159
5232
|
const { params, props } = state;
|
|
5160
|
-
console.log("[loly:RouterView] Creating page element", {
|
|
5161
|
-
hasPage: !!Page,
|
|
5162
|
-
layoutsCount: layouts.length,
|
|
5163
|
-
paramsKeys: Object.keys(params)
|
|
5164
|
-
});
|
|
5165
5233
|
let element = /* @__PURE__ */ (0, import_jsx_runtime.jsx)(Page, { params, ...props });
|
|
5166
5234
|
const layoutChain = layouts.slice().reverse();
|
|
5167
5235
|
for (const Layout of layoutChain) {
|
|
@@ -5467,7 +5535,6 @@ async function navigate(nextUrl, handlers, options) {
|
|
|
5467
5535
|
revalidate: options?.revalidate
|
|
5468
5536
|
});
|
|
5469
5537
|
if (json && json.error) {
|
|
5470
|
-
console.log("[client] Error detected in response:", json);
|
|
5471
5538
|
if (errorRoute) {
|
|
5472
5539
|
const handled = await handleErrorRoute(
|
|
5473
5540
|
nextUrl,
|
|
@@ -5509,50 +5576,23 @@ async function navigate(nextUrl, handlers, options) {
|
|
|
5509
5576
|
}
|
|
5510
5577
|
function createClickHandler(navigate2) {
|
|
5511
5578
|
return function handleClick(ev) {
|
|
5512
|
-
const target = ev.target;
|
|
5513
|
-
const tagName = target?.tagName.toLowerCase() || "unknown";
|
|
5514
|
-
console.log("[loly:click] Click event received", {
|
|
5515
|
-
type: ev.type,
|
|
5516
|
-
tagName,
|
|
5517
|
-
target: target?.tagName,
|
|
5518
|
-
defaultPrevented: ev.defaultPrevented,
|
|
5519
|
-
button: ev.button,
|
|
5520
|
-
clientX: ev.clientX,
|
|
5521
|
-
clientY: ev.clientY
|
|
5522
|
-
});
|
|
5523
5579
|
try {
|
|
5524
|
-
if (ev.defaultPrevented)
|
|
5525
|
-
|
|
5526
|
-
|
|
5527
|
-
|
|
5528
|
-
|
|
5529
|
-
console.log("[loly:click] Not a click event, skipping", { type: ev.type });
|
|
5530
|
-
return;
|
|
5531
|
-
}
|
|
5532
|
-
if (ev.button !== 0) {
|
|
5533
|
-
console.log("[loly:click] Not left button, skipping", { button: ev.button });
|
|
5534
|
-
return;
|
|
5535
|
-
}
|
|
5536
|
-
if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) {
|
|
5537
|
-
console.log("[loly:click] Modifier keys pressed, skipping");
|
|
5538
|
-
return;
|
|
5539
|
-
}
|
|
5580
|
+
if (ev.defaultPrevented) return;
|
|
5581
|
+
if (ev.type !== "click") return;
|
|
5582
|
+
if (ev.button !== 0) return;
|
|
5583
|
+
if (ev.metaKey || ev.ctrlKey || ev.shiftKey || ev.altKey) return;
|
|
5584
|
+
const target = ev.target;
|
|
5540
5585
|
if (ev.clientX === 0 && ev.clientY === 0 && ev.detail === 0) {
|
|
5541
5586
|
if (target) {
|
|
5542
|
-
const
|
|
5543
|
-
if (
|
|
5544
|
-
console.log("[loly:click] Synthetic event on interactive element, skipping", { tagName: tagName3 });
|
|
5587
|
+
const tagName2 = target.tagName.toLowerCase();
|
|
5588
|
+
if (tagName2 === "input" || tagName2 === "textarea" || tagName2 === "button" || tagName2 === "select") {
|
|
5545
5589
|
return;
|
|
5546
5590
|
}
|
|
5547
5591
|
}
|
|
5548
5592
|
}
|
|
5549
|
-
if (!target)
|
|
5550
|
-
|
|
5551
|
-
|
|
5552
|
-
}
|
|
5553
|
-
const tagName2 = target.tagName.toLowerCase();
|
|
5554
|
-
if (tagName2 === "input" || tagName2 === "textarea" || tagName2 === "button" || tagName2 === "select" || target.isContentEditable || target.getAttribute("contenteditable") === "true") {
|
|
5555
|
-
console.log("[loly:click] Target is interactive element, skipping", { tagName: tagName2 });
|
|
5593
|
+
if (!target) return;
|
|
5594
|
+
const tagName = target.tagName.toLowerCase();
|
|
5595
|
+
if (tagName === "input" || tagName === "textarea" || tagName === "button" || tagName === "select" || target.isContentEditable || target.getAttribute("contenteditable") === "true") {
|
|
5556
5596
|
return;
|
|
5557
5597
|
}
|
|
5558
5598
|
const interactiveParent = target.closest("input, textarea, button, select, [contenteditable], label");
|
|
@@ -5560,60 +5600,29 @@ function createClickHandler(navigate2) {
|
|
|
5560
5600
|
if (interactiveParent.tagName.toLowerCase() === "label") {
|
|
5561
5601
|
const label = interactiveParent;
|
|
5562
5602
|
if (label.control) {
|
|
5563
|
-
console.log("[loly:click] Inside label with control, skipping");
|
|
5564
5603
|
return;
|
|
5565
5604
|
}
|
|
5566
5605
|
} else {
|
|
5567
|
-
console.log("[loly:click] Inside interactive parent, skipping", {
|
|
5568
|
-
parentTag: interactiveParent.tagName.toLowerCase()
|
|
5569
|
-
});
|
|
5570
5606
|
return;
|
|
5571
5607
|
}
|
|
5572
5608
|
}
|
|
5573
5609
|
const anchor = target.closest("a[href]");
|
|
5574
|
-
if (!anchor)
|
|
5575
|
-
console.log("[loly:click] No anchor found, skipping");
|
|
5576
|
-
return;
|
|
5577
|
-
}
|
|
5578
|
-
console.log("[loly:click] Anchor found, processing navigation", {
|
|
5579
|
-
href: anchor.getAttribute("href")
|
|
5580
|
-
});
|
|
5610
|
+
if (!anchor) return;
|
|
5581
5611
|
const href = anchor.getAttribute("href");
|
|
5582
|
-
if (!href)
|
|
5583
|
-
|
|
5584
|
-
return;
|
|
5585
|
-
}
|
|
5586
|
-
if (href.startsWith("#")) {
|
|
5587
|
-
console.log("[loly:click] Hash link, skipping");
|
|
5588
|
-
return;
|
|
5589
|
-
}
|
|
5612
|
+
if (!href) return;
|
|
5613
|
+
if (href.startsWith("#")) return;
|
|
5590
5614
|
const url = new URL(href, window.location.href);
|
|
5591
|
-
if (url.origin !== window.location.origin)
|
|
5592
|
-
|
|
5593
|
-
return;
|
|
5594
|
-
}
|
|
5595
|
-
if (anchor.target && anchor.target !== "_self") {
|
|
5596
|
-
console.log("[loly:click] Link has target, skipping", { target: anchor.target });
|
|
5597
|
-
return;
|
|
5598
|
-
}
|
|
5615
|
+
if (url.origin !== window.location.origin) return;
|
|
5616
|
+
if (anchor.target && anchor.target !== "_self") return;
|
|
5599
5617
|
ev.preventDefault();
|
|
5600
|
-
console.log("[loly:click] Prevented default, navigating");
|
|
5601
5618
|
const nextUrl = url.pathname + url.search;
|
|
5602
5619
|
const currentUrl = window.location.pathname + window.location.search;
|
|
5603
|
-
if (nextUrl === currentUrl)
|
|
5604
|
-
console.log("[loly:click] Same URL, skipping", { nextUrl });
|
|
5605
|
-
return;
|
|
5606
|
-
}
|
|
5620
|
+
if (nextUrl === currentUrl) return;
|
|
5607
5621
|
const shouldRevalidate = anchor.hasAttribute("data-revalidate") && anchor.getAttribute("data-revalidate") !== "false";
|
|
5608
|
-
console.log("[loly:click] Pushing state and navigating", {
|
|
5609
|
-
nextUrl,
|
|
5610
|
-
currentUrl,
|
|
5611
|
-
shouldRevalidate
|
|
5612
|
-
});
|
|
5613
5622
|
window.history.pushState({}, "", nextUrl);
|
|
5614
5623
|
navigate2(nextUrl, shouldRevalidate ? { revalidate: true } : void 0);
|
|
5615
5624
|
} catch (error) {
|
|
5616
|
-
console.error("[
|
|
5625
|
+
console.error("[navigation] Error in click handler:", error);
|
|
5617
5626
|
}
|
|
5618
5627
|
};
|
|
5619
5628
|
}
|
|
@@ -5632,10 +5641,6 @@ function AppShell({
|
|
|
5632
5641
|
notFoundRoute,
|
|
5633
5642
|
errorRoute
|
|
5634
5643
|
}) {
|
|
5635
|
-
console.log("[loly:AppShell] Component rendering", {
|
|
5636
|
-
url: initialState.url,
|
|
5637
|
-
hasRoute: !!initialState.route
|
|
5638
|
-
});
|
|
5639
5644
|
const [state, setState] = (0, import_react2.useState)(initialState);
|
|
5640
5645
|
const handlersRef = (0, import_react2.useRef)({
|
|
5641
5646
|
setState,
|
|
@@ -5644,11 +5649,6 @@ function AppShell({
|
|
|
5644
5649
|
errorRoute
|
|
5645
5650
|
});
|
|
5646
5651
|
(0, import_react2.useEffect)(() => {
|
|
5647
|
-
console.log("[loly:AppShell] Updating handlersRef", {
|
|
5648
|
-
routesCount: routes.length,
|
|
5649
|
-
hasNotFound: !!notFoundRoute,
|
|
5650
|
-
hasError: !!errorRoute
|
|
5651
|
-
});
|
|
5652
5652
|
handlersRef.current = {
|
|
5653
5653
|
setState,
|
|
5654
5654
|
routes,
|
|
@@ -5657,34 +5657,16 @@ function AppShell({
|
|
|
5657
5657
|
};
|
|
5658
5658
|
}, [routes, notFoundRoute, errorRoute]);
|
|
5659
5659
|
(0, import_react2.useEffect)(() => {
|
|
5660
|
-
const effectId = Math.random().toString(36).substring(7);
|
|
5661
|
-
console.log("[loly:AppShell] Setting up event listeners", { effectId });
|
|
5662
5660
|
let isMounted = true;
|
|
5663
|
-
let listenerCount = 0;
|
|
5664
5661
|
async function handleNavigate(nextUrl, options) {
|
|
5665
|
-
if (!isMounted)
|
|
5666
|
-
console.warn("[loly:AppShell] navigate called but component is unmounted");
|
|
5667
|
-
return;
|
|
5668
|
-
}
|
|
5669
|
-
console.log("[loly:AppShell] Navigating to", nextUrl, options);
|
|
5662
|
+
if (!isMounted) return;
|
|
5670
5663
|
await navigate(nextUrl, handlersRef.current, options);
|
|
5671
5664
|
}
|
|
5672
5665
|
const handleClick = createClickHandler(handleNavigate);
|
|
5673
5666
|
const handlePopState = createPopStateHandler(handleNavigate);
|
|
5674
5667
|
window.addEventListener("click", handleClick, false);
|
|
5675
5668
|
window.addEventListener("popstate", handlePopState, false);
|
|
5676
|
-
listenerCount = 2;
|
|
5677
|
-
console.log("[loly:AppShell] Event listeners added", {
|
|
5678
|
-
clickListener: true,
|
|
5679
|
-
popStateListener: true,
|
|
5680
|
-
totalListeners: listenerCount
|
|
5681
|
-
});
|
|
5682
5669
|
return () => {
|
|
5683
|
-
console.log("[loly:AppShell] Cleaning up event listeners", {
|
|
5684
|
-
effectId,
|
|
5685
|
-
wasMounted: isMounted,
|
|
5686
|
-
listenersToRemove: listenerCount
|
|
5687
|
-
});
|
|
5688
5670
|
isMounted = false;
|
|
5689
5671
|
window.removeEventListener("click", handleClick, false);
|
|
5690
5672
|
window.removeEventListener("popstate", handlePopState, false);
|
|
@@ -5699,7 +5681,6 @@ function AppShell({
|
|
|
5699
5681
|
|
|
5700
5682
|
// modules/runtime/client/bootstrap.tsx
|
|
5701
5683
|
var import_jsx_runtime3 = require("react/jsx-runtime");
|
|
5702
|
-
var __loly_hydrated = false;
|
|
5703
5684
|
async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute, errorRoute) {
|
|
5704
5685
|
const isInitialNotFound = initialData?.notFound === true;
|
|
5705
5686
|
const isInitialError = initialData?.error === true;
|
|
@@ -5726,7 +5707,7 @@ async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute,
|
|
|
5726
5707
|
initialComponents = await notFoundRoute.load();
|
|
5727
5708
|
} else {
|
|
5728
5709
|
console.warn(
|
|
5729
|
-
`[client] No route match found for ${initialUrl}.
|
|
5710
|
+
`[client] No route match found for ${initialUrl}. Available routes:`,
|
|
5730
5711
|
routes.map((r) => r.pattern)
|
|
5731
5712
|
);
|
|
5732
5713
|
}
|
|
@@ -5739,29 +5720,62 @@ async function loadInitialRoute(initialUrl, initialData, routes, notFoundRoute,
|
|
|
5739
5720
|
props: initialData?.props ?? {}
|
|
5740
5721
|
};
|
|
5741
5722
|
}
|
|
5742
|
-
function
|
|
5743
|
-
|
|
5744
|
-
|
|
5723
|
+
function setupHotReload2() {
|
|
5724
|
+
const nodeEnv = typeof process !== "undefined" && process?.env?.NODE_ENV || "production";
|
|
5725
|
+
const isDev = nodeEnv !== "production";
|
|
5726
|
+
if (!isDev) {
|
|
5745
5727
|
return;
|
|
5746
5728
|
}
|
|
5747
|
-
|
|
5748
|
-
|
|
5729
|
+
try {
|
|
5730
|
+
console.log("[hot-reload] Attempting to connect to /__fw/hot...");
|
|
5731
|
+
const eventSource = new EventSource("/__fw/hot");
|
|
5732
|
+
let reloadTimeout = null;
|
|
5733
|
+
eventSource.addEventListener("message", (event) => {
|
|
5734
|
+
const data = event.data;
|
|
5735
|
+
if (data && data.startsWith("reload:")) {
|
|
5736
|
+
const filePath = data.slice(7);
|
|
5737
|
+
console.log(`[hot-reload] File changed: ${filePath}`);
|
|
5738
|
+
if (reloadTimeout) {
|
|
5739
|
+
clearTimeout(reloadTimeout);
|
|
5740
|
+
}
|
|
5741
|
+
reloadTimeout = setTimeout(() => {
|
|
5742
|
+
console.log("[hot-reload] Reloading page...");
|
|
5743
|
+
window.location.reload();
|
|
5744
|
+
}, 500);
|
|
5745
|
+
}
|
|
5746
|
+
});
|
|
5747
|
+
eventSource.addEventListener("ping", () => {
|
|
5748
|
+
console.log("[hot-reload] \u2713 Connected to hot reload server");
|
|
5749
|
+
});
|
|
5750
|
+
eventSource.onopen = () => {
|
|
5751
|
+
console.log("[hot-reload] \u2713 SSE connection opened");
|
|
5752
|
+
};
|
|
5753
|
+
eventSource.onerror = (error) => {
|
|
5754
|
+
const states = ["CONNECTING", "OPEN", "CLOSED"];
|
|
5755
|
+
const state = states[eventSource.readyState] || "UNKNOWN";
|
|
5756
|
+
if (eventSource.readyState === EventSource.CONNECTING) {
|
|
5757
|
+
console.log("[hot-reload] Connecting...");
|
|
5758
|
+
} else if (eventSource.readyState === EventSource.OPEN) {
|
|
5759
|
+
console.warn("[hot-reload] Connection error (but connection is open):", error);
|
|
5760
|
+
} else {
|
|
5761
|
+
console.log("[hot-reload] Connection closed (readyState:", state, ")");
|
|
5762
|
+
}
|
|
5763
|
+
};
|
|
5764
|
+
} catch (error) {
|
|
5765
|
+
console.log("[hot-reload] EventSource not supported or error:", error);
|
|
5766
|
+
}
|
|
5767
|
+
}
|
|
5768
|
+
function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
|
|
5769
|
+
console.log("[client] Bootstrap starting, setting up hot reload...");
|
|
5770
|
+
setupHotReload2();
|
|
5749
5771
|
(async function bootstrap() {
|
|
5750
5772
|
const container = document.getElementById(APP_CONTAINER_ID2);
|
|
5751
5773
|
const initialData = getWindowData();
|
|
5752
|
-
console.log("[loly:runtime] bootstrap starting", {
|
|
5753
|
-
hasContainer: !!container,
|
|
5754
|
-
hasInitialData: !!initialData,
|
|
5755
|
-
containerId: APP_CONTAINER_ID2
|
|
5756
|
-
});
|
|
5757
5774
|
if (!container) {
|
|
5758
|
-
console.error(
|
|
5759
|
-
`[loly:runtime] Container #${APP_CONTAINER_ID2} not found.`
|
|
5760
|
-
);
|
|
5775
|
+
console.error(`Container #${APP_CONTAINER_ID2} not found for hydration`);
|
|
5761
5776
|
return;
|
|
5762
5777
|
}
|
|
5763
5778
|
const initialUrl = window.location.pathname + window.location.search;
|
|
5764
|
-
console.log("[loly:runtime] Loading initial route", { initialUrl });
|
|
5765
5779
|
try {
|
|
5766
5780
|
const initialState = await loadInitialRoute(
|
|
5767
5781
|
initialUrl,
|
|
@@ -5770,15 +5784,9 @@ function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
|
|
|
5770
5784
|
notFoundRoute,
|
|
5771
5785
|
errorRoute
|
|
5772
5786
|
);
|
|
5773
|
-
console.log("[loly:runtime] Initial route loaded", {
|
|
5774
|
-
url: initialState.url,
|
|
5775
|
-
hasRoute: !!initialState.route,
|
|
5776
|
-
hasComponents: !!initialState.components
|
|
5777
|
-
});
|
|
5778
5787
|
if (initialData?.metadata) {
|
|
5779
5788
|
applyMetadata(initialData.metadata);
|
|
5780
5789
|
}
|
|
5781
|
-
console.log("[loly:runtime] Hydrating React app");
|
|
5782
5790
|
(0, import_client5.hydrateRoot)(
|
|
5783
5791
|
container,
|
|
5784
5792
|
/* @__PURE__ */ (0, import_jsx_runtime3.jsx)(
|
|
@@ -5791,9 +5799,12 @@ function bootstrapClient(routes, notFoundRoute, errorRoute = null) {
|
|
|
5791
5799
|
}
|
|
5792
5800
|
)
|
|
5793
5801
|
);
|
|
5794
|
-
console.log("[loly:runtime] Hydrated successfully");
|
|
5795
5802
|
} catch (error) {
|
|
5796
|
-
console.error(
|
|
5803
|
+
console.error(
|
|
5804
|
+
"[client] Error loading initial route components for",
|
|
5805
|
+
initialUrl,
|
|
5806
|
+
error
|
|
5807
|
+
);
|
|
5797
5808
|
window.location.reload();
|
|
5798
5809
|
}
|
|
5799
5810
|
})();
|