@lolyjs/core 0.2.0-alpha.22 → 0.2.0-alpha.24

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/index.js CHANGED
@@ -11505,22 +11505,36 @@ function copyStaticAssets(projectRoot, outDir) {
11505
11505
  const assetsSrc = path11.join(projectRoot, "assets");
11506
11506
  const assetsDest = path11.join(outDir, "assets");
11507
11507
  copyDirRecursive(assetsSrc, assetsDest);
11508
- const appDir = path11.join(projectRoot, "app");
11508
+ const publicDir = path11.join(projectRoot, "public");
11509
11509
  const candidates = ["favicon.ico", "favicon.png"];
11510
11510
  for (const name of candidates) {
11511
- const fromApp = path11.join(appDir, name);
11512
- const fromRoot = path11.join(projectRoot, name);
11513
- let src = null;
11514
- if (fs11.existsSync(fromApp)) src = fromApp;
11515
- else if (fs11.existsSync(fromRoot)) src = fromRoot;
11516
- if (src) {
11511
+ const fromPublic = path11.join(publicDir, name);
11512
+ if (fs11.existsSync(fromPublic)) {
11517
11513
  const dest = path11.join(outDir, name);
11518
11514
  ensureDir(path11.dirname(dest));
11519
- fs11.copyFileSync(src, dest);
11515
+ fs11.copyFileSync(fromPublic, dest);
11520
11516
  break;
11521
11517
  }
11522
11518
  }
11523
11519
  }
11520
+ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
11521
+ const candidates = [
11522
+ { name: "favicon.ico", type: "image/x-icon" },
11523
+ { name: "favicon.png", type: "image/png" }
11524
+ ];
11525
+ const publicDir = path11.join(projectRoot, staticDir);
11526
+ for (const candidate of candidates) {
11527
+ const publicPath = path11.join(publicDir, candidate.name);
11528
+ if (fs11.existsSync(publicPath)) {
11529
+ return {
11530
+ path: `/${candidate.name}`,
11531
+ // Served at root from public/
11532
+ type: candidate.type
11533
+ };
11534
+ }
11535
+ }
11536
+ return null;
11537
+ }
11524
11538
  function generateAssetManifest(outDir, stats) {
11525
11539
  const manifest = {
11526
11540
  client: {
@@ -14619,8 +14633,12 @@ function createDocumentTree(options) {
14619
14633
  clientJsPath = "/static/client.js",
14620
14634
  clientCssPath = "/static/client.css",
14621
14635
  nonce,
14622
- includeInlineScripts = true
14636
+ includeInlineScripts = true,
14623
14637
  // Default true - scripts inline in body for both SSR and SSG
14638
+ faviconPath = FAVICON_PATH,
14639
+ // Default to /static/favicon.png for backward compatibility
14640
+ faviconType = "image/png"
14641
+ // Default to PNG for backward compatibility
14624
14642
  } = options;
14625
14643
  const metaObj = meta ?? null;
14626
14644
  const title = metaObj?.title ?? titleFallback ?? "My Framework Dev";
@@ -14927,10 +14945,11 @@ function createDocumentTree(options) {
14927
14945
  href: chunkHref,
14928
14946
  as: "script"
14929
14947
  }),
14930
- React.createElement("link", {
14948
+ faviconPath && React.createElement("link", {
14949
+ key: "favicon",
14931
14950
  rel: "icon",
14932
- href: FAVICON_PATH,
14933
- type: "image/png"
14951
+ href: faviconPath,
14952
+ type: faviconType || (faviconPath.endsWith(".ico") ? "image/x-icon" : "image/png")
14934
14953
  }),
14935
14954
  React.createElement("link", {
14936
14955
  rel: "stylesheet",
@@ -15212,7 +15231,7 @@ async function handlePageRequest(options) {
15212
15231
  const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
15213
15232
  const reqLogger = getRequestLogger(req);
15214
15233
  if (errorPage) {
15215
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
15234
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env, options.config);
15216
15235
  } else {
15217
15236
  reqLogger.error("Unhandled error in page request", error, {
15218
15237
  urlPath: options.urlPath,
@@ -15238,11 +15257,13 @@ async function handlePageRequestInternal(options) {
15238
15257
  env = "dev",
15239
15258
  ssgOutDir,
15240
15259
  theme,
15241
- projectRoot
15260
+ projectRoot,
15261
+ config
15242
15262
  } = options;
15243
15263
  const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
15244
15264
  const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
15245
15265
  const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
15266
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
15246
15267
  const isDataReq = isDataRequest(req);
15247
15268
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
15248
15269
  if (env === "prod" && ssgOutDir) {
@@ -15357,7 +15378,9 @@ async function handlePageRequestInternal(options) {
15357
15378
  theme,
15358
15379
  clientJsPath,
15359
15380
  clientCssPath,
15360
- nonce: nonce2
15381
+ nonce: nonce2,
15382
+ faviconPath: faviconInfo?.path || null,
15383
+ faviconType: faviconInfo?.type || null
15361
15384
  });
15362
15385
  let didError2 = false;
15363
15386
  const { pipe: pipe2, abort: abort2 } = renderToPipeableStream(documentTree2, {
@@ -15372,7 +15395,7 @@ async function handlePageRequestInternal(options) {
15372
15395
  const reqLogger2 = getRequestLogger(req);
15373
15396
  reqLogger2.error("SSR shell error", err, { route: "not-found" });
15374
15397
  if (!res.headersSent && errorPage) {
15375
- renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
15398
+ renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env, config);
15376
15399
  } else if (!res.headersSent) {
15377
15400
  res.statusCode = 500;
15378
15401
  res.setHeader("Content-Type", "text/html; charset=utf-8");
@@ -15487,7 +15510,7 @@ async function handlePageRequestInternal(options) {
15487
15510
  return;
15488
15511
  } else {
15489
15512
  if (errorPage) {
15490
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
15513
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env, config);
15491
15514
  return;
15492
15515
  } else {
15493
15516
  throw error;
@@ -15565,7 +15588,9 @@ async function handlePageRequestInternal(options) {
15565
15588
  theme,
15566
15589
  clientJsPath,
15567
15590
  clientCssPath,
15568
- nonce
15591
+ nonce,
15592
+ faviconPath: faviconInfo?.path || null,
15593
+ faviconType: faviconInfo?.type || null
15569
15594
  });
15570
15595
  let didError = false;
15571
15596
  const { pipe, abort } = renderToPipeableStream(documentTree, {
@@ -15613,7 +15638,7 @@ async function handlePageRequestInternal(options) {
15613
15638
  abort();
15614
15639
  });
15615
15640
  }
15616
- async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
15641
+ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev", config) {
15617
15642
  try {
15618
15643
  const isDataReq = isDataRequest(req);
15619
15644
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
@@ -15624,6 +15649,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
15624
15649
  pathname: req.path,
15625
15650
  locals: { error }
15626
15651
  };
15652
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
15627
15653
  const layoutProps = {};
15628
15654
  const reqLogger = getRequestLogger(req);
15629
15655
  if (!skipLayoutHooks && errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
@@ -15729,7 +15755,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
15729
15755
  theme,
15730
15756
  clientJsPath,
15731
15757
  clientCssPath,
15732
- nonce
15758
+ nonce,
15759
+ faviconPath: faviconInfo?.path || null,
15760
+ faviconType: faviconInfo?.type || null
15733
15761
  });
15734
15762
  let didError = false;
15735
15763
  const { pipe, abort } = renderToPipeableStream(documentTree, {
@@ -15986,7 +16014,8 @@ function setupRoutes(options) {
15986
16014
  env: isDev ? "dev" : "prod",
15987
16015
  ssgOutDir,
15988
16016
  theme: req.cookies?.theme || "light",
15989
- projectRoot
16017
+ projectRoot,
16018
+ config
15990
16019
  });
15991
16020
  });
15992
16021
  }
@@ -17309,11 +17338,12 @@ import fs18 from "fs";
17309
17338
  import path25 from "path";
17310
17339
  import { renderToString } from "react-dom/server";
17311
17340
  init_globals();
17312
- async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params) {
17341
+ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
17313
17342
  const routeChunks = loadChunksFromManifest(projectRoot);
17314
17343
  const assetManifest = loadAssetManifest(projectRoot);
17315
17344
  const clientJsPath = getClientJsPath(projectRoot);
17316
17345
  const clientCssPath = getClientCssPath(projectRoot);
17346
+ const faviconInfo = config ? getFaviconInfo(projectRoot, config.directories.static, false) : null;
17317
17347
  const chunkName = routeChunks[route.pattern];
17318
17348
  let chunkHref = null;
17319
17349
  if (chunkName != null) {
@@ -17421,8 +17451,10 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
17421
17451
  entrypointFiles,
17422
17452
  clientJsPath,
17423
17453
  clientCssPath,
17424
- includeInlineScripts: true
17454
+ includeInlineScripts: true,
17425
17455
  // SSG needs inline scripts (renderToString doesn't support bootstrapScripts)
17456
+ faviconPath: faviconInfo?.path || null,
17457
+ faviconType: faviconInfo?.type || null
17426
17458
  });
17427
17459
  const html = "<!DOCTYPE html>" + renderToString(documentTree);
17428
17460
  const dir = pathToOutDir(ssgOutDir, urlPath);
@@ -17435,7 +17467,7 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
17435
17467
 
17436
17468
  // modules/build/ssg/builder.ts
17437
17469
  init_globals();
17438
- async function buildStaticPages(projectRoot, routes) {
17470
+ async function buildStaticPages(projectRoot, routes, config) {
17439
17471
  const ssgOutDir = path26.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
17440
17472
  ensureDir(ssgOutDir);
17441
17473
  for (const route of routes) {
@@ -17484,7 +17516,7 @@ async function buildStaticPages(projectRoot, routes) {
17484
17516
  }
17485
17517
  for (const params of allParams) {
17486
17518
  const urlPath = buildPathFromPattern(route.pattern, params);
17487
- await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);
17519
+ await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config);
17488
17520
  }
17489
17521
  }
17490
17522
  console.log(`\u2705 [framework][ssg] Finished building all static pages`);
@@ -17705,7 +17737,7 @@ async function buildApp(options = {}) {
17705
17737
  writeClientBoostrapManifest(projectRoot);
17706
17738
  writeClientRoutesManifest(routes, projectRoot);
17707
17739
  await buildClientBundle(projectRoot);
17708
- await buildStaticPages(projectRoot, routes);
17740
+ await buildStaticPages(projectRoot, routes, config);
17709
17741
  delete process.env.LOLY_BUILD;
17710
17742
  console.log(`[framework][build] Build completed successfully`);
17711
17743
  }