@absolutejs/absolute 0.19.0-beta.171 → 0.19.0-beta.172

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/index.js CHANGED
@@ -526,6 +526,105 @@ var init_devCert = __esm(() => {
526
526
  KEY_PATH = join3(CERT_DIR, "key.pem");
527
527
  });
528
528
 
529
+ // src/core/prerender.ts
530
+ var exports_prerender = {};
531
+ __export(exports_prerender, {
532
+ prerenderWithServer: () => prerenderWithServer,
533
+ prerender: () => prerender
534
+ });
535
+ import { mkdirSync as mkdirSync3 } from "fs";
536
+ import { join as join5 } from "path";
537
+ var routeToFilename = (route) => route === "/" ? "index.html" : `${route.slice(1).replace(/\//g, "-")}.html`, crawlRoutes = async (baseUrl, log) => {
538
+ const visited = new Set;
539
+ const queue = ["/"];
540
+ const routes = [];
541
+ while (queue.length > 0) {
542
+ const path = queue.shift();
543
+ if (visited.has(path))
544
+ continue;
545
+ visited.add(path);
546
+ try {
547
+ const res = await fetch(`${baseUrl}${path}`);
548
+ if (!res.ok)
549
+ continue;
550
+ const contentType = res.headers.get("content-type") ?? "";
551
+ if (!contentType.includes("text/html"))
552
+ continue;
553
+ const html = await res.text();
554
+ routes.push(path);
555
+ const linkRegex = /href=["'](\/[^"']*?)["']/g;
556
+ let match;
557
+ while ((match = linkRegex.exec(html)) !== null) {
558
+ const href = match[1] ?? "";
559
+ if (!href || href.includes(".") || href.includes("#") || visited.has(href))
560
+ continue;
561
+ queue.push(href);
562
+ }
563
+ } catch {}
564
+ }
565
+ return routes;
566
+ }, prerender = async (port, outDir, staticConfig, log) => {
567
+ const prerenderDir = join5(outDir, "_prerendered");
568
+ mkdirSync3(prerenderDir, { recursive: true });
569
+ const baseUrl = `http://localhost:${port}`;
570
+ let routes;
571
+ if (staticConfig.routes === "all") {
572
+ log?.("Crawling routes...");
573
+ routes = await crawlRoutes(baseUrl, log);
574
+ } else {
575
+ routes = staticConfig.routes;
576
+ }
577
+ const result = {
578
+ routes: new Map,
579
+ dir: prerenderDir
580
+ };
581
+ for (const route of routes) {
582
+ try {
583
+ const res = await fetch(`${baseUrl}${route}`);
584
+ if (!res.ok) {
585
+ log?.(` Skipped ${route} (HTTP ${res.status})`);
586
+ continue;
587
+ }
588
+ const html = await res.text();
589
+ const fileName = routeToFilename(route);
590
+ const filePath = join5(prerenderDir, fileName);
591
+ await Bun.write(filePath, html);
592
+ result.routes.set(route, filePath);
593
+ log?.(` Pre-rendered ${route} \u2192 ${fileName} (${html.length} bytes)`);
594
+ } catch {
595
+ log?.(` Failed to pre-render ${route}`);
596
+ }
597
+ }
598
+ return result;
599
+ }, prerenderWithServer = async (serverBundlePath, port, outDir, staticConfig, env2, log) => {
600
+ const serverProcess = Bun.spawn(["bun", "run", serverBundlePath], {
601
+ cwd: process.cwd(),
602
+ env: { ...process.env, ...env2, PORT: String(port) },
603
+ stdout: "pipe",
604
+ stderr: "pipe"
605
+ });
606
+ let ready = false;
607
+ for (let i = 0;i < 50; i++) {
608
+ try {
609
+ const res = await fetch(`http://localhost:${port}/`);
610
+ if (res.ok) {
611
+ ready = true;
612
+ break;
613
+ }
614
+ } catch {}
615
+ await Bun.sleep(100);
616
+ }
617
+ if (!ready) {
618
+ serverProcess.kill();
619
+ throw new Error("Server failed to start for pre-rendering");
620
+ }
621
+ const result = await prerender(port, outDir, staticConfig, log);
622
+ serverProcess.kill();
623
+ await serverProcess.exited;
624
+ return result;
625
+ };
626
+ var init_prerender = () => {};
627
+
529
628
  // src/cli/scripts/compile.ts
530
629
  var exports_compile = {};
531
630
  __export(exports_compile, {
@@ -534,16 +633,15 @@ __export(exports_compile, {
534
633
  var {env: env3 } = globalThis.Bun;
535
634
  import {
536
635
  existsSync as existsSync8,
537
- mkdirSync as mkdirSync3,
538
636
  readdirSync,
539
637
  readFileSync as readFileSync7,
540
638
  unlinkSync
541
639
  } from "fs";
542
- import { basename as basename2, join as join5, relative, resolve as resolve6 } from "path";
640
+ import { basename as basename3, join as join6, relative, resolve as resolve6 } from "path";
543
641
  var cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`, collectFiles2 = (dir) => {
544
642
  const results = [];
545
643
  for (const entry of readdirSync(dir, { withFileTypes: true })) {
546
- const fullPath = join5(dir, entry.name);
644
+ const fullPath = join6(dir, entry.name);
547
645
  if (entry.isDirectory()) {
548
646
  results.push(...collectFiles2(fullPath));
549
647
  } else {
@@ -568,45 +666,9 @@ var cliTag3 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[c
568
666
  } catch {}
569
667
  }
570
668
  return;
571
- }, prerender = async (port, outDir) => {
572
- const prerenderDir = join5(outDir, "_prerendered");
573
- mkdirSync3(prerenderDir, { recursive: true });
574
- const baseUrl = `http://localhost:${port}`;
575
- const visited = new Set;
576
- const queue = ["/"];
577
- const savedFiles = [];
578
- while (queue.length > 0) {
579
- const path = queue.shift();
580
- if (visited.has(path))
581
- continue;
582
- visited.add(path);
583
- try {
584
- const res = await fetch(`${baseUrl}${path}`);
585
- if (!res.ok)
586
- continue;
587
- const contentType = res.headers.get("content-type") ?? "";
588
- if (!contentType.includes("text/html"))
589
- continue;
590
- const html = await res.text();
591
- const fileName = path === "/" ? "index.html" : `${path.slice(1).replace(/\//g, "-")}.html`;
592
- const filePath = join5(prerenderDir, fileName);
593
- await Bun.write(filePath, html);
594
- savedFiles.push(filePath);
595
- console.log(cliTag3("\x1B[36m", ` Pre-rendered ${path} \u2192 ${fileName} (${html.length} bytes)`));
596
- const linkRegex = /href=["'](\/[^"']*?)["']/g;
597
- let match;
598
- while ((match = linkRegex.exec(html)) !== null) {
599
- const href = match[1] ?? "";
600
- if (!href || href.includes(".") || href.includes("#") || visited.has(href))
601
- continue;
602
- queue.push(href);
603
- }
604
- } catch {}
605
- }
606
- return savedFiles;
607
669
  }, generateEntrypoint = (distDir, serverEntry, prerenderMap, version2) => {
608
670
  const allFiles = collectFiles2(distDir);
609
- const serverBundleName = basename2(serverEntry).replace(/\.[^.]+$/, "") + ".js";
671
+ const serverBundleName = basename3(serverEntry).replace(/\.[^.]+$/, "") + ".js";
610
672
  const skip = new Set([
611
673
  serverBundleName,
612
674
  "manifest.json",
@@ -775,7 +837,7 @@ console.log(\`
775
837
  }), FRAMEWORK_EXTERNALS, compile = async (serverEntry, outdir, outfile, configPath2) => {
776
838
  const prerenderPort = Number(env3.COMPILE_PORT) || Number(env3.PORT) || DEFAULT_PORT + 1;
777
839
  killStaleProcesses(prerenderPort);
778
- const entryName = basename2(serverEntry).replace(/\.[^.]+$/, "");
840
+ const entryName = basename3(serverEntry).replace(/\.[^.]+$/, "");
779
841
  const resolvedOutdir = resolve6(outdir ?? "dist");
780
842
  const resolvedOutfile = resolve6(outfile ?? "compiled-server");
781
843
  const absoluteVersion = resolvePackageVersion2([
@@ -825,50 +887,20 @@ console.log(\`
825
887
  console.log(` \x1B[2m(${getDurationString(performance.now() - bundleStart)})\x1B[0m`);
826
888
  const prerenderStart = performance.now();
827
889
  console.log(cliTag3("\x1B[36m", "Pre-rendering pages..."));
828
- const serverProcess = Bun.spawn(["bun", "run", outputPath], {
829
- cwd: process.cwd(),
830
- env: {
831
- ...process.env,
832
- ABSOLUTE_BUILD_DIR: resolvedOutdir,
833
- ABSOLUTE_VERSION: absoluteVersion,
834
- FORCE_COLOR: "0",
835
- NODE_ENV: "production",
836
- PORT: String(prerenderPort),
837
- ...configPath2 ? { ABSOLUTE_CONFIG: configPath2 } : {}
838
- },
839
- stdout: "pipe",
840
- stderr: "pipe"
841
- });
842
- let ready = false;
843
- for (let i = 0;i < 50; i++) {
844
- try {
845
- const res = await fetch(`http://localhost:${prerenderPort}/`);
846
- if (res.ok) {
847
- ready = true;
848
- break;
849
- }
850
- } catch {}
851
- await Bun.sleep(100);
852
- }
853
- if (!ready) {
854
- serverProcess.kill();
855
- console.error(cliTag3("\x1B[31m", "Server failed to start for pre-rendering."));
856
- process.exit(1);
857
- }
858
- const prerenderFiles = await prerender(prerenderPort, resolvedOutdir);
859
- serverProcess.kill();
860
- await serverProcess.exited;
861
- const prerenderMap = new Map;
862
- for (const filePath of prerenderFiles) {
863
- const fileName = basename2(filePath, ".html");
864
- const route = fileName === "index" ? "/" : `/${fileName}`;
865
- prerenderMap.set(route, filePath);
866
- }
890
+ const staticConfig = buildConfig.static ?? { routes: "all" };
891
+ const prerenderResult = await prerenderWithServer(outputPath, prerenderPort, resolvedOutdir, staticConfig, {
892
+ ABSOLUTE_BUILD_DIR: resolvedOutdir,
893
+ ABSOLUTE_VERSION: absoluteVersion,
894
+ FORCE_COLOR: "0",
895
+ NODE_ENV: "production",
896
+ ...configPath2 ? { ABSOLUTE_CONFIG: configPath2 } : {}
897
+ }, (msg) => console.log(cliTag3("\x1B[36m", msg)));
898
+ const prerenderMap = prerenderResult.routes;
867
899
  console.log(cliTag3("\x1B[36m", `Pre-rendered ${prerenderMap.size} pages (${getDurationString(performance.now() - prerenderStart)})`));
868
900
  const compileStart = performance.now();
869
901
  process.stdout.write(cliTag3("\x1B[36m", "Compiling standalone executable"));
870
902
  const entrypointCode = generateEntrypoint(resolvedOutdir, serverEntry, prerenderMap, absoluteVersion);
871
- const entrypointPath = join5(resolvedOutdir, "_compile_entrypoint.ts");
903
+ const entrypointPath = join6(resolvedOutdir, "_compile_entrypoint.ts");
872
904
  await Bun.write(entrypointPath, entrypointCode);
873
905
  const result = await Bun.build({
874
906
  entrypoints: [entrypointPath],
@@ -888,7 +920,7 @@ console.log(\`
888
920
  const size = (Bun.file(resolvedOutfile).size / 1048576).toFixed(0);
889
921
  const totalDuration = getDurationString(performance.now() - totalStart);
890
922
  console.log(cliTag3("\x1B[32m", `Compiled to ${resolvedOutfile} (${size}MB) in ${totalDuration}`));
891
- console.log(cliTag3("\x1B[2m", `Run with: ./${basename2(resolvedOutfile)}`));
923
+ console.log(cliTag3("\x1B[2m", `Run with: ./${basename3(resolvedOutfile)}`));
892
924
  sendTelemetryEvent("compile:complete", {
893
925
  durationMs: Math.round(performance.now() - totalStart),
894
926
  entry: serverEntry,
@@ -897,6 +929,7 @@ console.log(\`
897
929
  };
898
930
  var init_compile = __esm(() => {
899
931
  init_constants();
932
+ init_prerender();
900
933
  init_getDurationString();
901
934
  init_loadConfig();
902
935
  init_startupBanner();
@@ -1770,7 +1803,7 @@ init_telemetryEvent();
1770
1803
  init_utils();
1771
1804
  var {env: env2 } = globalThis.Bun;
1772
1805
  import { existsSync as existsSync7, readFileSync as readFileSync6 } from "fs";
1773
- import { basename, resolve as resolve5 } from "path";
1806
+ import { basename as basename2, resolve as resolve5 } from "path";
1774
1807
  var cliTag2 = (color, message) => `\x1B[2m${formatTimestamp()}\x1B[0m ${color}[cli]\x1B[0m ${color}${message}\x1B[0m`;
1775
1808
  var resolvePackageVersion = (candidates) => {
1776
1809
  for (const candidate of candidates) {
@@ -1824,7 +1857,7 @@ var handleBundleFailure = (serverBundle, bundleStart, serverEntry) => {
1824
1857
  var start = async (serverEntry, outdir, configPath2) => {
1825
1858
  const port = Number(env2.PORT) || DEFAULT_PORT;
1826
1859
  killStaleProcesses(port);
1827
- const entryName = basename(serverEntry).replace(/\.[^.]+$/, "");
1860
+ const entryName = basename2(serverEntry).replace(/\.[^.]+$/, "");
1828
1861
  const resolvedOutdir = resolve5(outdir ?? "dist");
1829
1862
  const absoluteVersion = resolvePackageVersion([
1830
1863
  resolve5(import.meta.dir, "..", "..", "..", "package.json"),
@@ -1954,6 +1987,27 @@ var start = async (serverEntry, outdir, configPath2) => {
1954
1987
  durationMs: bundleDurationMs,
1955
1988
  entry: serverEntry
1956
1989
  });
1990
+ if (buildConfig.static) {
1991
+ const prerenderStart = performance.now();
1992
+ console.log(cliTag2("\x1B[36m", "Pre-rendering static pages..."));
1993
+ const { prerenderWithServer: prerenderWithServer2 } = await Promise.resolve().then(() => (init_prerender(), exports_prerender));
1994
+ const prerenderPort = port + 1;
1995
+ try {
1996
+ killStaleProcesses(prerenderPort);
1997
+ const result = await prerenderWithServer2(outputPath, prerenderPort, resolvedOutdir, buildConfig.static, {
1998
+ ABSOLUTE_BUILD_DIR: resolvedOutdir,
1999
+ ABSOLUTE_VERSION: absoluteVersion,
2000
+ FORCE_COLOR: "0",
2001
+ NODE_ENV: "production",
2002
+ ...configPath2 ? { ABSOLUTE_CONFIG: configPath2 } : {}
2003
+ }, (msg) => console.log(cliTag2("\x1B[36m", msg)));
2004
+ const prerenderDuration = getDurationString(performance.now() - prerenderStart);
2005
+ console.log(cliTag2("\x1B[36m", `Pre-rendered ${result.routes.size} pages (${prerenderDuration})`));
2006
+ } catch (err) {
2007
+ console.error(cliTag2("\x1B[33m", "Pre-rendering failed, pages will use SSR."));
2008
+ console.error(err);
2009
+ }
2010
+ }
1957
2011
  const usesDocker = existsSync7(resolve5(COMPOSE_PATH));
1958
2012
  const scripts = usesDocker ? await readDbScripts() : null;
1959
2013
  if (scripts)
package/dist/index.js CHANGED
@@ -205641,7 +205641,7 @@ __export(exports_devCert, {
205641
205641
  });
205642
205642
  import { existsSync as existsSync17, mkdirSync as mkdirSync10, readFileSync as readFileSync11, rmSync as rmSync2 } from "fs";
205643
205643
  import { platform as platform3 } from "os";
205644
- import { join as join17 } from "path";
205644
+ import { join as join18 } from "path";
205645
205645
  var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[36m[dev]\x1B[0m ${msg}`), devWarn = (msg) => console.log(`\x1B[2m${new Date().toLocaleTimeString()}\x1B[0m \x1B[33m[dev]\x1B[0m \x1B[33m${msg}\x1B[0m`), certFilesExist = () => existsSync17(CERT_PATH) && existsSync17(KEY_PATH), isCertExpired = () => {
205646
205646
  try {
205647
205647
  const certPem = readFileSync11(CERT_PATH, "utf-8");
@@ -205847,9 +205847,9 @@ var CERT_DIR, CERT_PATH, KEY_PATH, CERT_VALIDITY_DAYS = 365, devLog = (msg) => c
205847
205847
  return true;
205848
205848
  };
205849
205849
  var init_devCert = __esm(() => {
205850
- CERT_DIR = join17(process.cwd(), ".absolutejs");
205851
- CERT_PATH = join17(CERT_DIR, "cert.pem");
205852
- KEY_PATH = join17(CERT_DIR, "key.pem");
205850
+ CERT_DIR = join18(process.cwd(), ".absolutejs");
205851
+ CERT_PATH = join18(CERT_DIR, "cert.pem");
205852
+ KEY_PATH = join18(CERT_DIR, "key.pem");
205853
205853
  });
205854
205854
  // types/client.ts
205855
205855
  var hmrState = {
@@ -205876,8 +205876,8 @@ var {file } = globalThis.Bun;
205876
205876
  var handleHTMLPageRequest = (pagePath) => file(pagePath);
205877
205877
  var handleHTMXPageRequest = (pagePath) => file(pagePath);
205878
205878
  // src/core/prepare.ts
205879
- import { existsSync as existsSync16, readFileSync as readFileSync10 } from "fs";
205880
- import { relative as relative10, resolve as resolve23 } from "path";
205879
+ import { existsSync as existsSync16, readdirSync as readdirSync2, readFileSync as readFileSync10 } from "fs";
205880
+ import { basename as basename9, join as join17, relative as relative10, resolve as resolve23 } from "path";
205881
205881
 
205882
205882
  // src/utils/loadConfig.ts
205883
205883
  import { resolve } from "path";
@@ -206005,6 +206005,21 @@ var prepareDev = async (config, buildDir) => {
206005
206005
  absolutejs: (app) => hmrPlugin(app.use(staticPlugin({ assets: buildDir, prefix: "" })))
206006
206006
  };
206007
206007
  };
206008
+ var loadPrerenderMap = (prerenderDir) => {
206009
+ const map = new Map;
206010
+ if (!existsSync16(prerenderDir))
206011
+ return map;
206012
+ try {
206013
+ for (const entry of readdirSync2(prerenderDir)) {
206014
+ if (!entry.endsWith(".html"))
206015
+ continue;
206016
+ const name = basename9(entry, ".html");
206017
+ const route = name === "index" ? "/" : `/${name}`;
206018
+ map.set(route, join17(prerenderDir, entry));
206019
+ }
206020
+ } catch {}
206021
+ return map;
206022
+ };
206008
206023
  var prepare = async (configOrPath) => {
206009
206024
  const config = await loadConfig(configOrPath);
206010
206025
  const nodeEnv = process.env["NODE_ENV"];
@@ -206014,8 +206029,24 @@ var prepare = async (configOrPath) => {
206014
206029
  return prepareDev(config, buildDir);
206015
206030
  const manifest = JSON.parse(readFileSync10(`${buildDir}/manifest.json`, "utf-8"));
206016
206031
  const { staticPlugin } = await import("@elysiajs/static");
206017
- const absolutejs = staticPlugin({ assets: buildDir, prefix: "" });
206018
- return { absolutejs, manifest };
206032
+ const staticFiles = staticPlugin({ assets: buildDir, prefix: "" });
206033
+ const prerenderDir = join17(buildDir, "_prerendered");
206034
+ const prerenderMap = loadPrerenderMap(prerenderDir);
206035
+ if (prerenderMap.size > 0) {
206036
+ const { Elysia } = await import("elysia");
206037
+ const prerenderPlugin = new Elysia({ name: "prerendered-pages" }).onRequest(({ request }) => {
206038
+ const url = new URL(request.url);
206039
+ const filePath = prerenderMap.get(url.pathname);
206040
+ if (!filePath)
206041
+ return;
206042
+ return new Response(Bun.file(filePath), {
206043
+ headers: { "content-type": "text/html; charset=utf-8" }
206044
+ });
206045
+ });
206046
+ const absolutejs = (app) => app.use(prerenderPlugin).use(staticFiles);
206047
+ return { absolutejs, manifest };
206048
+ }
206049
+ return { absolutejs: staticFiles, manifest };
206019
206050
  };
206020
206051
  // src/plugins/pageRouter.ts
206021
206052
  var pageRouterPlugin = () => {
@@ -206198,5 +206229,5 @@ export {
206198
206229
  ANGULAR_INIT_TIMEOUT_MS
206199
206230
  };
206200
206231
 
206201
- //# debugId=8D9238CCCF55663464756E2164756E21
206232
+ //# debugId=B51D68800393AB0664756E2164756E21
206202
206233
  //# sourceMappingURL=index.js.map