@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
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
declare const WINDOW_DATA_KEY = "__FW_DATA__";
|
|
2
|
+
|
|
3
|
+
type InitialData = {
|
|
4
|
+
pathname: string;
|
|
5
|
+
params: Record<string, string>;
|
|
6
|
+
props: Record<string, any>;
|
|
7
|
+
metadata?: {
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
} | null;
|
|
11
|
+
notFound?: boolean;
|
|
12
|
+
error?: boolean;
|
|
13
|
+
theme?: string;
|
|
14
|
+
};
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
[WINDOW_DATA_KEY]?: InitialData;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
type ClientLoadedComponents = {
|
|
21
|
+
Page: React.ComponentType<any>;
|
|
22
|
+
layouts: React.ComponentType<any>[];
|
|
23
|
+
};
|
|
24
|
+
type ClientRouteLoaded = {
|
|
25
|
+
pattern: string;
|
|
26
|
+
paramNames: string[];
|
|
27
|
+
load: () => Promise<ClientLoadedComponents>;
|
|
28
|
+
};
|
|
29
|
+
type ClientRouteMatch = {
|
|
30
|
+
route: ClientRouteLoaded;
|
|
31
|
+
params: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
type RouteViewState = {
|
|
34
|
+
url: string;
|
|
35
|
+
route: ClientRouteLoaded | null;
|
|
36
|
+
params: Record<string, string>;
|
|
37
|
+
components: ClientLoadedComponents | null;
|
|
38
|
+
props: Record<string, any>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Bootstraps the client-side application.
|
|
43
|
+
*
|
|
44
|
+
* @param routes - Array of client routes
|
|
45
|
+
* @param notFoundRoute - Not-found route definition
|
|
46
|
+
* @param errorRoute - Error route definition
|
|
47
|
+
*/
|
|
48
|
+
declare function bootstrapClient(routes: ClientRouteLoaded[], notFoundRoute: ClientRouteLoaded | null, errorRoute?: ClientRouteLoaded | null): void;
|
|
49
|
+
|
|
50
|
+
export { type ClientRouteLoaded as C, type InitialData as I, type RouteViewState as R, type ClientLoadedComponents as a, type ClientRouteMatch as b, bootstrapClient as c };
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
declare const WINDOW_DATA_KEY = "__FW_DATA__";
|
|
2
|
+
|
|
3
|
+
type InitialData = {
|
|
4
|
+
pathname: string;
|
|
5
|
+
params: Record<string, string>;
|
|
6
|
+
props: Record<string, any>;
|
|
7
|
+
metadata?: {
|
|
8
|
+
title?: string;
|
|
9
|
+
description?: string;
|
|
10
|
+
} | null;
|
|
11
|
+
notFound?: boolean;
|
|
12
|
+
error?: boolean;
|
|
13
|
+
theme?: string;
|
|
14
|
+
};
|
|
15
|
+
declare global {
|
|
16
|
+
interface Window {
|
|
17
|
+
[WINDOW_DATA_KEY]?: InitialData;
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
type ClientLoadedComponents = {
|
|
21
|
+
Page: React.ComponentType<any>;
|
|
22
|
+
layouts: React.ComponentType<any>[];
|
|
23
|
+
};
|
|
24
|
+
type ClientRouteLoaded = {
|
|
25
|
+
pattern: string;
|
|
26
|
+
paramNames: string[];
|
|
27
|
+
load: () => Promise<ClientLoadedComponents>;
|
|
28
|
+
};
|
|
29
|
+
type ClientRouteMatch = {
|
|
30
|
+
route: ClientRouteLoaded;
|
|
31
|
+
params: Record<string, string>;
|
|
32
|
+
};
|
|
33
|
+
type RouteViewState = {
|
|
34
|
+
url: string;
|
|
35
|
+
route: ClientRouteLoaded | null;
|
|
36
|
+
params: Record<string, string>;
|
|
37
|
+
components: ClientLoadedComponents | null;
|
|
38
|
+
props: Record<string, any>;
|
|
39
|
+
};
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* Bootstraps the client-side application.
|
|
43
|
+
*
|
|
44
|
+
* @param routes - Array of client routes
|
|
45
|
+
* @param notFoundRoute - Not-found route definition
|
|
46
|
+
* @param errorRoute - Error route definition
|
|
47
|
+
*/
|
|
48
|
+
declare function bootstrapClient(routes: ClientRouteLoaded[], notFoundRoute: ClientRouteLoaded | null, errorRoute?: ClientRouteLoaded | null): void;
|
|
49
|
+
|
|
50
|
+
export { type ClientRouteLoaded as C, type InitialData as I, type RouteViewState as R, type ClientLoadedComponents as a, type ClientRouteMatch as b, bootstrapClient as c };
|
package/dist/cli.cjs
CHANGED
|
@@ -1330,24 +1330,69 @@ function createClientConfig(projectRoot, mode) {
|
|
|
1330
1330
|
var import_path14 = __toESM(require("path"));
|
|
1331
1331
|
var import_fs11 = __toESM(require("fs"));
|
|
1332
1332
|
init_globals();
|
|
1333
|
-
function startClientBundler(projectRoot) {
|
|
1334
|
-
const { config, outDir } = createClientConfig(projectRoot,
|
|
1333
|
+
function startClientBundler(projectRoot, mode = "development") {
|
|
1334
|
+
const { config, outDir } = createClientConfig(projectRoot, mode);
|
|
1335
1335
|
copyStaticAssets(projectRoot, outDir);
|
|
1336
1336
|
const compiler = (0, import_core2.rspack)(config);
|
|
1337
|
+
let isBuilding = false;
|
|
1338
|
+
let buildResolve = null;
|
|
1339
|
+
let buildPromise = null;
|
|
1340
|
+
let lastBuildTime = Date.now();
|
|
1341
|
+
compiler.hooks.compile.tap("HotReload", () => {
|
|
1342
|
+
isBuilding = true;
|
|
1343
|
+
buildPromise = new Promise((resolve3) => {
|
|
1344
|
+
buildResolve = resolve3;
|
|
1345
|
+
});
|
|
1346
|
+
});
|
|
1337
1347
|
compiler.watch({}, (err, stats) => {
|
|
1338
1348
|
if (err) {
|
|
1339
1349
|
console.error("[framework][client] Rspack error:", err);
|
|
1350
|
+
isBuilding = false;
|
|
1351
|
+
lastBuildTime = Date.now();
|
|
1352
|
+
if (buildResolve) {
|
|
1353
|
+
buildResolve();
|
|
1354
|
+
buildResolve = null;
|
|
1355
|
+
buildPromise = null;
|
|
1356
|
+
}
|
|
1357
|
+
return;
|
|
1358
|
+
}
|
|
1359
|
+
if (!stats) {
|
|
1360
|
+
isBuilding = false;
|
|
1361
|
+
lastBuildTime = Date.now();
|
|
1340
1362
|
return;
|
|
1341
1363
|
}
|
|
1342
|
-
if (!stats) return;
|
|
1343
1364
|
if (stats.hasErrors()) {
|
|
1344
1365
|
console.error(
|
|
1345
1366
|
"[framework][client] Build with errors:\n",
|
|
1346
1367
|
stats.toString("errors-only")
|
|
1347
1368
|
);
|
|
1369
|
+
} else {
|
|
1370
|
+
console.log("[framework][client] \u2713 Client bundle rebuilt successfully");
|
|
1371
|
+
}
|
|
1372
|
+
isBuilding = false;
|
|
1373
|
+
lastBuildTime = Date.now();
|
|
1374
|
+
if (buildResolve) {
|
|
1375
|
+
buildResolve();
|
|
1376
|
+
buildResolve = null;
|
|
1377
|
+
buildPromise = null;
|
|
1348
1378
|
}
|
|
1349
1379
|
});
|
|
1350
|
-
return {
|
|
1380
|
+
return {
|
|
1381
|
+
outDir,
|
|
1382
|
+
waitForBuild: async () => {
|
|
1383
|
+
if (isBuilding && buildPromise) {
|
|
1384
|
+
await buildPromise;
|
|
1385
|
+
await new Promise((resolve3) => setTimeout(resolve3, 100));
|
|
1386
|
+
return;
|
|
1387
|
+
}
|
|
1388
|
+
const timeSinceLastBuild = Date.now() - lastBuildTime;
|
|
1389
|
+
if (timeSinceLastBuild < 500) {
|
|
1390
|
+
await new Promise((resolve3) => setTimeout(resolve3, 200));
|
|
1391
|
+
return;
|
|
1392
|
+
}
|
|
1393
|
+
return Promise.resolve();
|
|
1394
|
+
}
|
|
1395
|
+
};
|
|
1351
1396
|
}
|
|
1352
1397
|
function buildClientBundle(projectRoot) {
|
|
1353
1398
|
const { config, outDir } = createClientConfig(projectRoot, "production");
|
|
@@ -3702,7 +3747,9 @@ init_globals();
|
|
|
3702
3747
|
function setupHotReload({
|
|
3703
3748
|
app,
|
|
3704
3749
|
appDir,
|
|
3705
|
-
route = "/__fw/hot"
|
|
3750
|
+
route = "/__fw/hot",
|
|
3751
|
+
waitForBuild,
|
|
3752
|
+
onFileChange
|
|
3706
3753
|
}) {
|
|
3707
3754
|
const clients = /* @__PURE__ */ new Set();
|
|
3708
3755
|
app.get(route, (req, res) => {
|
|
@@ -3723,9 +3770,25 @@ data: connected
|
|
|
3723
3770
|
ignoreInitial: true,
|
|
3724
3771
|
ignored: ["**/node_modules/**", `**/${BUILD_FOLDER_NAME}/**`, "**/.git/**"]
|
|
3725
3772
|
});
|
|
3726
|
-
function broadcastReload(reason, filePath) {
|
|
3773
|
+
async function broadcastReload(reason, filePath) {
|
|
3727
3774
|
const rel = import_path23.default.relative(appDir, filePath);
|
|
3728
3775
|
console.log(`[hot-reload] ${reason}: ${rel}`);
|
|
3776
|
+
if (onFileChange) {
|
|
3777
|
+
try {
|
|
3778
|
+
await onFileChange(filePath);
|
|
3779
|
+
} catch (error) {
|
|
3780
|
+
console.warn("[hot-reload] Error in onFileChange callback:", error);
|
|
3781
|
+
}
|
|
3782
|
+
}
|
|
3783
|
+
if (waitForBuild) {
|
|
3784
|
+
try {
|
|
3785
|
+
console.log("[hot-reload] Waiting for client bundle to finish...");
|
|
3786
|
+
await waitForBuild();
|
|
3787
|
+
console.log("[hot-reload] Client bundle ready, sending reload event");
|
|
3788
|
+
} catch (error) {
|
|
3789
|
+
console.warn("[hot-reload] Error waiting for build:", error);
|
|
3790
|
+
}
|
|
3791
|
+
}
|
|
3729
3792
|
for (const res of clients) {
|
|
3730
3793
|
res.write(`event: message
|
|
3731
3794
|
data: reload:${rel}
|
|
@@ -3762,14 +3825,29 @@ function setupServer(app, options) {
|
|
|
3762
3825
|
};
|
|
3763
3826
|
};
|
|
3764
3827
|
var getRoutes = getRoutes2;
|
|
3765
|
-
|
|
3828
|
+
const { outDir, waitForBuild } = startClientBundler(projectRoot, "development");
|
|
3829
|
+
const onFileChange = async (filePath) => {
|
|
3830
|
+
const rel = import_path25.default.relative(appDir, filePath);
|
|
3831
|
+
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");
|
|
3832
|
+
const isTsFile = filePath.endsWith(".ts") || filePath.endsWith(".tsx");
|
|
3833
|
+
if (isTsFile) {
|
|
3834
|
+
clearAppRequireCache(appDir);
|
|
3835
|
+
console.log(`[hot-reload] Cleared require cache for: ${rel}`);
|
|
3836
|
+
}
|
|
3837
|
+
if (isPageFile) {
|
|
3838
|
+
const loader = new FilesystemRouteLoader(appDir);
|
|
3839
|
+
const newRoutes = loader.loadRoutes();
|
|
3840
|
+
writeClientRoutesManifest(newRoutes, projectRoot);
|
|
3841
|
+
console.log("[hot-reload] Client routes manifest reloaded");
|
|
3842
|
+
}
|
|
3843
|
+
};
|
|
3844
|
+
setupHotReload({ app, appDir, waitForBuild, onFileChange });
|
|
3845
|
+
app.use("/static", import_express.default.static(outDir));
|
|
3766
3846
|
const routes = routeLoader.loadRoutes();
|
|
3767
3847
|
const wssRoutes = routeLoader.loadWssRoutes();
|
|
3768
3848
|
const notFoundPage = routeLoader.loadNotFoundRoute();
|
|
3769
3849
|
const errorPage = routeLoader.loadErrorRoute();
|
|
3770
3850
|
writeClientRoutesManifest(routes, projectRoot);
|
|
3771
|
-
const { outDir } = startClientBundler(projectRoot);
|
|
3772
|
-
app.use("/static", import_express.default.static(outDir));
|
|
3773
3851
|
return {
|
|
3774
3852
|
routes,
|
|
3775
3853
|
wssRoutes,
|
|
@@ -4332,7 +4410,7 @@ async function handlePageRequest(options) {
|
|
|
4332
4410
|
const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
|
|
4333
4411
|
const reqLogger = getRequestLogger(req);
|
|
4334
4412
|
if (errorPage) {
|
|
4335
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot);
|
|
4413
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
|
|
4336
4414
|
} else {
|
|
4337
4415
|
reqLogger.error("Unhandled error in page request", error, {
|
|
4338
4416
|
urlPath: options.urlPath,
|
|
@@ -4360,9 +4438,9 @@ async function handlePageRequestInternal(options) {
|
|
|
4360
4438
|
theme,
|
|
4361
4439
|
projectRoot
|
|
4362
4440
|
} = options;
|
|
4363
|
-
const clientJsPath = projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4364
|
-
const clientCssPath = projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4365
|
-
const assetManifest = projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4441
|
+
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4442
|
+
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4443
|
+
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4366
4444
|
const isDataReq = isDataRequest(req);
|
|
4367
4445
|
if (env === "prod" && ssgOutDir) {
|
|
4368
4446
|
if (isDataReq) {
|
|
@@ -4418,7 +4496,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4418
4496
|
const reqLogger = getRequestLogger(req);
|
|
4419
4497
|
reqLogger.error("SSR shell error", err, { route: "not-found" });
|
|
4420
4498
|
if (!res.headersSent && errorPage) {
|
|
4421
|
-
renderErrorPageWithStream(errorPage, req, res, err, routeChunks);
|
|
4499
|
+
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4422
4500
|
} else if (!res.headersSent) {
|
|
4423
4501
|
res.statusCode = 500;
|
|
4424
4502
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4465,7 +4543,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4465
4543
|
return;
|
|
4466
4544
|
} else {
|
|
4467
4545
|
if (errorPage) {
|
|
4468
|
-
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot);
|
|
4546
|
+
await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
|
|
4469
4547
|
return;
|
|
4470
4548
|
} else {
|
|
4471
4549
|
throw error;
|
|
@@ -4527,7 +4605,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4527
4605
|
const reqLogger = getRequestLogger(req);
|
|
4528
4606
|
reqLogger.error("SSR shell error", err, { route: matched?.route?.pattern || "unknown" });
|
|
4529
4607
|
if (!res.headersSent && errorPage) {
|
|
4530
|
-
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot);
|
|
4608
|
+
renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
|
|
4531
4609
|
} else if (!res.headersSent) {
|
|
4532
4610
|
res.statusCode = 500;
|
|
4533
4611
|
res.setHeader("Content-Type", "text/html; charset=utf-8");
|
|
@@ -4545,7 +4623,7 @@ async function handlePageRequestInternal(options) {
|
|
|
4545
4623
|
abort();
|
|
4546
4624
|
});
|
|
4547
4625
|
}
|
|
4548
|
-
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot) {
|
|
4626
|
+
async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
|
|
4549
4627
|
try {
|
|
4550
4628
|
const isDataReq = isDataRequest(req);
|
|
4551
4629
|
const ctx = {
|
|
@@ -4574,9 +4652,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
|
|
|
4574
4652
|
return;
|
|
4575
4653
|
}
|
|
4576
4654
|
const appTree = buildAppTree(errorPage, { error: String(error) }, initialData.props);
|
|
4577
|
-
const clientJsPath = projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4578
|
-
const clientCssPath = projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4579
|
-
const assetManifest = projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4655
|
+
const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
|
|
4656
|
+
const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
|
|
4657
|
+
const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
|
|
4580
4658
|
const chunkName = routeChunks[ERROR_CHUNK_KEY];
|
|
4581
4659
|
let chunkHref = null;
|
|
4582
4660
|
if (chunkName != null) {
|