@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/cli.js CHANGED
@@ -11464,22 +11464,36 @@ function copyStaticAssets(projectRoot, outDir) {
11464
11464
  const assetsSrc = path10.join(projectRoot, "assets");
11465
11465
  const assetsDest = path10.join(outDir, "assets");
11466
11466
  copyDirRecursive(assetsSrc, assetsDest);
11467
- const appDir = path10.join(projectRoot, "app");
11467
+ const publicDir = path10.join(projectRoot, "public");
11468
11468
  const candidates = ["favicon.ico", "favicon.png"];
11469
11469
  for (const name of candidates) {
11470
- const fromApp = path10.join(appDir, name);
11471
- const fromRoot = path10.join(projectRoot, name);
11472
- let src = null;
11473
- if (fs10.existsSync(fromApp)) src = fromApp;
11474
- else if (fs10.existsSync(fromRoot)) src = fromRoot;
11475
- if (src) {
11470
+ const fromPublic = path10.join(publicDir, name);
11471
+ if (fs10.existsSync(fromPublic)) {
11476
11472
  const dest = path10.join(outDir, name);
11477
11473
  ensureDir(path10.dirname(dest));
11478
- fs10.copyFileSync(src, dest);
11474
+ fs10.copyFileSync(fromPublic, dest);
11479
11475
  break;
11480
11476
  }
11481
11477
  }
11482
11478
  }
11479
+ function getFaviconInfo(projectRoot, staticDir = "public", isDev = false) {
11480
+ const candidates = [
11481
+ { name: "favicon.ico", type: "image/x-icon" },
11482
+ { name: "favicon.png", type: "image/png" }
11483
+ ];
11484
+ const publicDir = path10.join(projectRoot, staticDir);
11485
+ for (const candidate of candidates) {
11486
+ const publicPath = path10.join(publicDir, candidate.name);
11487
+ if (fs10.existsSync(publicPath)) {
11488
+ return {
11489
+ path: `/${candidate.name}`,
11490
+ // Served at root from public/
11491
+ type: candidate.type
11492
+ };
11493
+ }
11494
+ }
11495
+ return null;
11496
+ }
11483
11497
  function generateAssetManifest(outDir, stats) {
11484
11498
  const manifest = {
11485
11499
  client: {
@@ -11964,8 +11978,12 @@ function createDocumentTree(options) {
11964
11978
  clientJsPath = "/static/client.js",
11965
11979
  clientCssPath = "/static/client.css",
11966
11980
  nonce,
11967
- includeInlineScripts = true
11981
+ includeInlineScripts = true,
11968
11982
  // Default true - scripts inline in body for both SSR and SSG
11983
+ faviconPath = FAVICON_PATH,
11984
+ // Default to /static/favicon.png for backward compatibility
11985
+ faviconType = "image/png"
11986
+ // Default to PNG for backward compatibility
11969
11987
  } = options;
11970
11988
  const metaObj = meta ?? null;
11971
11989
  const title = metaObj?.title ?? titleFallback ?? "My Framework Dev";
@@ -12272,10 +12290,11 @@ function createDocumentTree(options) {
12272
12290
  href: chunkHref,
12273
12291
  as: "script"
12274
12292
  }),
12275
- React.createElement("link", {
12293
+ faviconPath && React.createElement("link", {
12294
+ key: "favicon",
12276
12295
  rel: "icon",
12277
- href: FAVICON_PATH,
12278
- type: "image/png"
12296
+ href: faviconPath,
12297
+ type: faviconType || (faviconPath.endsWith(".ico") ? "image/x-icon" : "image/png")
12279
12298
  }),
12280
12299
  React.createElement("link", {
12281
12300
  rel: "stylesheet",
@@ -12805,7 +12824,7 @@ async function handlePageRequest(options) {
12805
12824
  const { errorPage, req, res, routeChunks, theme, projectRoot } = options;
12806
12825
  const reqLogger = getRequestLogger(req);
12807
12826
  if (errorPage) {
12808
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env);
12827
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks || {}, theme, projectRoot, options.env, options.config);
12809
12828
  } else {
12810
12829
  reqLogger.error("Unhandled error in page request", error, {
12811
12830
  urlPath: options.urlPath,
@@ -12831,11 +12850,13 @@ async function handlePageRequestInternal(options) {
12831
12850
  env = "dev",
12832
12851
  ssgOutDir,
12833
12852
  theme,
12834
- projectRoot
12853
+ projectRoot,
12854
+ config
12835
12855
  } = options;
12836
12856
  const clientJsPath = env === "dev" ? "/static/client.js" : projectRoot ? getClientJsPath(projectRoot) : "/static/client.js";
12837
12857
  const clientCssPath = env === "dev" ? "/static/client.css" : projectRoot ? getClientCssPath(projectRoot) : "/static/client.css";
12838
12858
  const assetManifest = env === "prod" && projectRoot ? loadAssetManifest(projectRoot) : null;
12859
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
12839
12860
  const isDataReq = isDataRequest(req);
12840
12861
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
12841
12862
  if (env === "prod" && ssgOutDir) {
@@ -12950,7 +12971,9 @@ async function handlePageRequestInternal(options) {
12950
12971
  theme,
12951
12972
  clientJsPath,
12952
12973
  clientCssPath,
12953
- nonce: nonce2
12974
+ nonce: nonce2,
12975
+ faviconPath: faviconInfo?.path || null,
12976
+ faviconType: faviconInfo?.type || null
12954
12977
  });
12955
12978
  let didError2 = false;
12956
12979
  const { pipe: pipe2, abort: abort2 } = renderToPipeableStream(documentTree2, {
@@ -12965,7 +12988,7 @@ async function handlePageRequestInternal(options) {
12965
12988
  const reqLogger2 = getRequestLogger(req);
12966
12989
  reqLogger2.error("SSR shell error", err, { route: "not-found" });
12967
12990
  if (!res.headersSent && errorPage) {
12968
- renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env);
12991
+ renderErrorPageWithStream(errorPage, req, res, err, routeChunks, theme, projectRoot, env, config);
12969
12992
  } else if (!res.headersSent) {
12970
12993
  res.statusCode = 500;
12971
12994
  res.setHeader("Content-Type", "text/html; charset=utf-8");
@@ -13080,7 +13103,7 @@ async function handlePageRequestInternal(options) {
13080
13103
  return;
13081
13104
  } else {
13082
13105
  if (errorPage) {
13083
- await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env);
13106
+ await renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env, config);
13084
13107
  return;
13085
13108
  } else {
13086
13109
  throw error;
@@ -13158,7 +13181,9 @@ async function handlePageRequestInternal(options) {
13158
13181
  theme,
13159
13182
  clientJsPath,
13160
13183
  clientCssPath,
13161
- nonce
13184
+ nonce,
13185
+ faviconPath: faviconInfo?.path || null,
13186
+ faviconType: faviconInfo?.type || null
13162
13187
  });
13163
13188
  let didError = false;
13164
13189
  const { pipe, abort } = renderToPipeableStream(documentTree, {
@@ -13206,7 +13231,7 @@ async function handlePageRequestInternal(options) {
13206
13231
  abort();
13207
13232
  });
13208
13233
  }
13209
- async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev") {
13234
+ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks, theme, projectRoot, env = "dev", config) {
13210
13235
  try {
13211
13236
  const isDataReq = isDataRequest(req);
13212
13237
  const skipLayoutHooks = isDataReq && req.headers["x-skip-layout-hooks"] === "true";
@@ -13217,6 +13242,7 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
13217
13242
  pathname: req.path,
13218
13243
  locals: { error }
13219
13244
  };
13245
+ const faviconInfo = projectRoot && config ? getFaviconInfo(projectRoot, config.directories.static, env === "dev") : null;
13220
13246
  const layoutProps = {};
13221
13247
  const reqLogger = getRequestLogger(req);
13222
13248
  if (!skipLayoutHooks && errorPage.layoutServerHooks && errorPage.layoutServerHooks.length > 0) {
@@ -13322,7 +13348,9 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
13322
13348
  theme,
13323
13349
  clientJsPath,
13324
13350
  clientCssPath,
13325
- nonce
13351
+ nonce,
13352
+ faviconPath: faviconInfo?.path || null,
13353
+ faviconType: faviconInfo?.type || null
13326
13354
  });
13327
13355
  let didError = false;
13328
13356
  const { pipe, abort } = renderToPipeableStream(documentTree, {
@@ -13366,11 +13394,12 @@ async function renderErrorPageWithStream(errorPage, req, res, error, routeChunks
13366
13394
  }
13367
13395
 
13368
13396
  // modules/build/ssg/renderer.ts
13369
- async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params) {
13397
+ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config) {
13370
13398
  const routeChunks = loadChunksFromManifest(projectRoot);
13371
13399
  const assetManifest = loadAssetManifest(projectRoot);
13372
13400
  const clientJsPath = getClientJsPath(projectRoot);
13373
13401
  const clientCssPath = getClientCssPath(projectRoot);
13402
+ const faviconInfo = config ? getFaviconInfo(projectRoot, config.directories.static, false) : null;
13374
13403
  const chunkName = routeChunks[route.pattern];
13375
13404
  let chunkHref = null;
13376
13405
  if (chunkName != null) {
@@ -13478,8 +13507,10 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
13478
13507
  entrypointFiles,
13479
13508
  clientJsPath,
13480
13509
  clientCssPath,
13481
- includeInlineScripts: true
13510
+ includeInlineScripts: true,
13482
13511
  // SSG needs inline scripts (renderToString doesn't support bootstrapScripts)
13512
+ faviconPath: faviconInfo?.path || null,
13513
+ faviconType: faviconInfo?.type || null
13483
13514
  });
13484
13515
  const html = "<!DOCTYPE html>" + renderToString(documentTree);
13485
13516
  const dir = pathToOutDir(ssgOutDir, urlPath);
@@ -13492,7 +13523,7 @@ async function renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params)
13492
13523
 
13493
13524
  // modules/build/ssg/builder.ts
13494
13525
  init_globals();
13495
- async function buildStaticPages(projectRoot, routes) {
13526
+ async function buildStaticPages(projectRoot, routes, config) {
13496
13527
  const ssgOutDir = path19.join(projectRoot, BUILD_FOLDER_NAME, "ssg");
13497
13528
  ensureDir(ssgOutDir);
13498
13529
  for (const route of routes) {
@@ -13541,7 +13572,7 @@ async function buildStaticPages(projectRoot, routes) {
13541
13572
  }
13542
13573
  for (const params of allParams) {
13543
13574
  const urlPath = buildPathFromPattern(route.pattern, params);
13544
- await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params);
13575
+ await renderStaticRoute(projectRoot, ssgOutDir, route, urlPath, params, config);
13545
13576
  }
13546
13577
  }
13547
13578
  console.log(`\u2705 [framework][ssg] Finished building all static pages`);
@@ -14190,7 +14221,7 @@ async function buildApp(options = {}) {
14190
14221
  writeClientBoostrapManifest(projectRoot);
14191
14222
  writeClientRoutesManifest(routes, projectRoot);
14192
14223
  await buildClientBundle(projectRoot);
14193
- await buildStaticPages(projectRoot, routes);
14224
+ await buildStaticPages(projectRoot, routes, config);
14194
14225
  delete process.env.LOLY_BUILD;
14195
14226
  console.log(`[framework][build] Build completed successfully`);
14196
14227
  }
@@ -16432,7 +16463,8 @@ function setupRoutes(options) {
16432
16463
  env: isDev ? "dev" : "prod",
16433
16464
  ssgOutDir,
16434
16465
  theme: req.cookies?.theme || "light",
16435
- projectRoot
16466
+ projectRoot,
16467
+ config
16436
16468
  });
16437
16469
  });
16438
16470
  }