@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.cjs CHANGED
@@ -11538,22 +11538,36 @@ function copyStaticAssets(projectRoot, outDir) {
11538
11538
  const assetsSrc = import_path13.default.join(projectRoot, "assets");
11539
11539
  const assetsDest = import_path13.default.join(outDir, "assets");
11540
11540
  copyDirRecursive(assetsSrc, assetsDest);
11541
- const appDir = import_path13.default.join(projectRoot, "app");
11541
+ const publicDir = import_path13.default.join(projectRoot, "public");
11542
11542
  const candidates = ["favicon.ico", "favicon.png"];
11543
11543
  for (const name of candidates) {
11544
- const fromApp = import_path13.default.join(appDir, name);
11545
- const fromRoot = import_path13.default.join(projectRoot, name);
11546
- let src = null;
11547
- if (import_fs11.default.existsSync(fromApp)) src = fromApp;
11548
- else if (import_fs11.default.existsSync(fromRoot)) src = fromRoot;
11549
- if (src) {
11544
+ const fromPublic = import_path13.default.join(publicDir, name);
11545
+ if (import_fs11.default.existsSync(fromPublic)) {
11550
11546
  const dest = import_path13.default.join(outDir, name);
11551
11547
  ensureDir(import_path13.default.dirname(dest));
11552
- import_fs11.default.copyFileSync(src, dest);
11548
+ import_fs11.default.copyFileSync(fromPublic, dest);
11553
11549
  break;
11554
11550
  }
11555
11551
  }
11556
11552
  }
11553
+ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
11554
+ const candidates = [
11555
+ { name: "favicon.ico", type: "image/x-icon" },
11556
+ { name: "favicon.png", type: "image/png" }
11557
+ ];
11558
+ const publicDir = import_path13.default.join(projectRoot, staticDir);
11559
+ for (const candidate of candidates) {
11560
+ const publicPath = import_path13.default.join(publicDir, candidate.name);
11561
+ if (import_fs11.default.existsSync(publicPath)) {
11562
+ return {
11563
+ path: `/${candidate.name}`,
11564
+ // Served at root from public/
11565
+ type: candidate.type
11566
+ };
11567
+ }
11568
+ }
11569
+ return null;
11570
+ }
11557
11571
  function generateAssetManifest(outDir, stats) {
11558
11572
  const manifest = {
11559
11573
  client: {
@@ -14652,8 +14666,12 @@ function createDocumentTree(options) {
14652
14666
  clientJsPath = "/static/client.js",
14653
14667
  clientCssPath = "/static/client.css",
14654
14668
  nonce,
14655
- includeInlineScripts = true
14669
+ includeInlineScripts = true,
14656
14670
  // Default true - scripts inline in body for both SSR and SSG
14671
+ faviconPath = FAVICON_PATH,
14672
+ // Default to /static/favicon.png for backward compatibility
14673
+ faviconType = "image/png"
14674
+ // Default to PNG for backward compatibility
14657
14675
  } = options;
14658
14676
  const metaObj = meta ?? null;
14659
14677
  const title = metaObj?.title ?? titleFallback ?? "My Framework Dev";
@@ -14960,10 +14978,11 @@ function createDocumentTree(options) {
14960
14978
  href: chunkHref,
14961
14979
  as: "script"
14962
14980
  }),
14963
- import_react.default.createElement("link", {
14981
+ faviconPath && import_react.default.createElement("link", {
14982
+ key: "favicon",
14964
14983
  rel: "icon",
14965
- href: FAVICON_PATH,
14966
- type: "image/png"
14984
+ href: faviconPath,
14985
+ type: faviconType || (faviconPath.endsWith(".ico") ? "image/x-icon" : "image/png")
14967
14986
  }),
14968
14987
  import_react.default.createElement("link", {
14969
14988
  rel: "stylesheet",
@@ -15245,7 +15264,7 @@ async function handlePageRequest(options) {
15245
15264
  const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
15246
15265
  const reqLogger = getRequestLogger(req);
15247
15266
  if (errorPage) {
15248
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
15267
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env, options.config);
15249
15268
  } else {
15250
15269
  reqLogger.error("Unhandled error in page request", error, {
15251
15270
  urlPath: options.urlPath,
@@ -15271,11 +15290,13 @@ async function handlePageRequestInternal(options) {
15271
15290
  env = "dev",
15272
15291
  ssgOutDir,
15273
15292
  theme,
15274
- projectRoot
15293
+ projectRoot,
15294
+ config
15275
15295
  } = options;
15276
15296
  const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
15277
15297
  const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
15278
15298
  const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
15299
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
15279
15300
  const isDataReq = isDataRequest(req);
15280
15301
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
15281
15302
  if (env === "prod" && ssgOutDir) {
@@ -15390,7 +15411,9 @@ async function handlePageRequestInternal(options) {
15390
15411
  theme,
15391
15412
  clientJsPath,
15392
15413
  clientCssPath,
15393
- nonce: nonce2
15414
+ nonce: nonce2,
15415
+ faviconPath: faviconInfo?.path || null,
15416
+ faviconType: faviconInfo?.type || null
15394
15417
  });
15395
15418
  let didError2 = false;
15396
15419
  const { pipe: pipe2, abort: abort2 } = (0, import_server.renderToPipeableStream)(documentTree2, {
@@ -15405,7 +15428,7 @@ async function handlePageRequestInternal(options) {
15405
15428
  const reqLogger2 = getRequestLogger(req);
15406
15429
  reqLogger2.error("SSR shell error", err, { route: "not-found" });
15407
15430
  if (!res.headersSent && errorPage) {
15408
- renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
15431
+ renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env, config);
15409
15432
  } else if (!res.headersSent) {
15410
15433
  res.statusCode = 500;
15411
15434
  res.setHeader("Content-Type", "text/html; charset=utf-8");
@@ -15520,7 +15543,7 @@ async function handlePageRequestInternal(options) {
15520
15543
  return;
15521
15544
  } else {
15522
15545
  if (errorPage) {
15523
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
15546
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env, config);
15524
15547
  return;
15525
15548
  } else {
15526
15549
  throw error;
@@ -15598,7 +15621,9 @@ async function handlePageRequestInternal(options) {
15598
15621
  theme,
15599
15622
  clientJsPath,
15600
15623
  clientCssPath,
15601
- nonce
15624
+ nonce,
15625
+ faviconPath: faviconInfo?.path || null,
15626
+ faviconType: faviconInfo?.type || null
15602
15627
  });
15603
15628
  let didError = false;
15604
15629
  const { pipe, abort } = (0, import_server.renderToPipeableStream)(documentTree, {
@@ -15646,7 +15671,7 @@ async function handlePageRequestInternal(options) {
15646
15671
  abort();
15647
15672
  });
15648
15673
  }
15649
- async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
15674
+ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev", config) {
15650
15675
  try {
15651
15676
  const isDataReq = isDataRequest(req);
15652
15677
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
@@ -15657,6 +15682,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
15657
15682
  pathname: req.path,
15658
15683
  locals: { error }
15659
15684
  };
15685
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
15660
15686
  const layoutProps = {};
15661
15687
  const reqLogger = getRequestLogger(req);
15662
15688
  if (!skipLayoutHooks && errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
@@ -15762,7 +15788,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
15762
15788
  theme,
15763
15789
  clientJsPath,
15764
15790
  clientCssPath,
15765
- nonce
15791
+ nonce,
15792
+ faviconPath: faviconInfo?.path || null,
15793
+ faviconType: faviconInfo?.type || null
15766
15794
  });
15767
15795
  let didError = false;
15768
15796
  const { pipe, abort } = (0, import_server.renderToPipeableStream)(documentTree, {
@@ -16019,7 +16047,8 @@ function setupRoutes(options) {
16019
16047
  env: isDev ? "dev" : "prod",
16020
16048
  ssgOutDir,
16021
16049
  theme: req.cookies?.theme || "light",
16022
- projectRoot
16050
+ projectRoot,
16051
+ config
16023
16052
  });
16024
16053
  });
16025
16054
  }
@@ -17342,11 +17371,12 @@ var import_fs20 = __toESM(require("fs"));
17342
17371
  var import_path27 = __toESM(require("path"));
17343
17372
  var import_server3 = require("react-dom/server");
17344
17373
  init_globals();
17345
- async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params) {
17374
+ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
17346
17375
  const routeChunks = loadChunksFromManifest(projectRoot);
17347
17376
  const assetManifest = loadAssetManifest(projectRoot);
17348
17377
  const clientJsPath = getClientJsPath(projectRoot);
17349
17378
  const clientCssPath = getClientCssPath(projectRoot);
17379
+ const faviconInfo = config ? getFaviconInfo(projectRoot, config.directories.static, false) : null;
17350
17380
  const chunkName = routeChunks[route.pattern];
17351
17381
  let chunkHref = null;
17352
17382
  if (chunkName != null) {
@@ -17454,8 +17484,10 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
17454
17484
  entrypointFiles,
17455
17485
  clientJsPath,
17456
17486
  clientCssPath,
17457
- includeInlineScripts: true
17487
+ includeInlineScripts: true,
17458
17488
  // SSG needs inline scripts (renderToString doesn't support bootstrapScripts)
17489
+ faviconPath: faviconInfo?.path || null,
17490
+ faviconType: faviconInfo?.type || null
17459
17491
  });
17460
17492
  const html = "<!DOCTYPE html>" + (0, import_server3.renderToString)(documentTree);
17461
17493
  const dir = pathToOutDir(ssgOutDir, urlPath);
@@ -17468,7 +17500,7 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
17468
17500
 
17469
17501
  // modules/build/ssg/builder.ts
17470
17502
  init_globals();
17471
- async function buildStaticPages(projectRoot, routes) {
17503
+ async function buildStaticPages(projectRoot, routes, config) {
17472
17504
  const ssgOutDir = import_path29.default.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
17473
17505
  ensureDir(ssgOutDir);
17474
17506
  for (const route of routes) {
@@ -17517,7 +17549,7 @@ async function buildStaticPages(projectRoot, routes) {
17517
17549
  }
17518
17550
  for (const params of allParams) {
17519
17551
  const urlPath = buildPathFromPattern(route.pattern, params);
17520
- await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);
17552
+ await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config);
17521
17553
  }
17522
17554
  }
17523
17555
  console.log(`\u2705 [framework][ssg] Finished building all static pages`);
@@ -17738,7 +17770,7 @@ async function buildApp(options = {}) {
17738
17770
  writeClientBoostrapManifest(projectRoot);
17739
17771
  writeClientRoutesManifest(routes, projectRoot);
17740
17772
  await buildClientBundle(projectRoot);
17741
- await buildStaticPages(projectRoot, routes);
17773
+ await buildStaticPages(projectRoot, routes, config);
17742
17774
  delete process.env.LOLY_BUILD;
17743
17775
  console.log(`[framework][build] Build completed successfully`);
17744
17776
  }