@float.js/core 2.0.7 → 2.1.0

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
@@ -729,7 +729,7 @@ function generateAPIResponse(state) {
729
729
  function createDevDashboard(options = {}) {
730
730
  const {
731
731
  enabled = process.env.NODE_ENV !== "production",
732
- path: path7 = "/__float",
732
+ path: path9 = "/__float",
733
733
  auth
734
734
  } = options;
735
735
  if (!enabled) {
@@ -737,7 +737,7 @@ function createDevDashboard(options = {}) {
737
737
  }
738
738
  return (req, res, next) => {
739
739
  const url = req.url || "";
740
- if (!url.startsWith(path7)) {
740
+ if (!url.startsWith(path9)) {
741
741
  return next();
742
742
  }
743
743
  if (auth) {
@@ -756,7 +756,7 @@ function createDevDashboard(options = {}) {
756
756
  return;
757
757
  }
758
758
  }
759
- const subPath = url.slice(path7.length);
759
+ const subPath = url.slice(path9.length);
760
760
  if (subPath === "" || subPath === "/") {
761
761
  res.setHeader("Content-Type", "text/html");
762
762
  res.end(generateDashboardHTML(dashboardState));
@@ -1017,9 +1017,9 @@ init_esm_shims();
1017
1017
  // src/server/dev-server.ts
1018
1018
  init_esm_shims();
1019
1019
  import http from "http";
1020
- import fs2 from "fs";
1021
- import path4 from "path";
1022
- import pc from "picocolors";
1020
+ import fs4 from "fs";
1021
+ import path6 from "path";
1022
+ import pc2 from "picocolors";
1023
1023
  import chokidar from "chokidar";
1024
1024
  import { WebSocketServer, WebSocket } from "ws";
1025
1025
  import mime from "mime-types";
@@ -2520,11 +2520,214 @@ function generateExamplesPage() {
2520
2520
  ` + footer;
2521
2521
  }
2522
2522
 
2523
+ // src/build/css-processor.ts
2524
+ init_esm_shims();
2525
+ import fs3 from "fs";
2526
+ import path5 from "path";
2527
+
2528
+ // src/build/tailwind-setup.ts
2529
+ init_esm_shims();
2530
+ import fs2 from "fs";
2531
+ import path4 from "path";
2532
+ import pc from "picocolors";
2533
+ function checkTailwindSetup(rootDir) {
2534
+ const possibleConfigs = [
2535
+ "tailwind.config.js",
2536
+ "tailwind.config.ts",
2537
+ "tailwind.config.mjs",
2538
+ "tailwind.config.cjs"
2539
+ ];
2540
+ let configPath = null;
2541
+ for (const config of possibleConfigs) {
2542
+ const fullPath = path4.join(rootDir, config);
2543
+ if (fs2.existsSync(fullPath)) {
2544
+ configPath = fullPath;
2545
+ break;
2546
+ }
2547
+ }
2548
+ const globalsPath = path4.join(rootDir, "app", "globals.css");
2549
+ const hasGlobals = fs2.existsSync(globalsPath);
2550
+ return {
2551
+ hasTailwind: !!configPath,
2552
+ configPath,
2553
+ globalsPath: hasGlobals ? globalsPath : null,
2554
+ needsSetup: !configPath || !hasGlobals
2555
+ };
2556
+ }
2557
+ async function setupTailwind(rootDir, options = {}) {
2558
+ const { force = false, silent = false } = options;
2559
+ const config = checkTailwindSetup(rootDir);
2560
+ if (!force && !config.needsSetup) {
2561
+ return;
2562
+ }
2563
+ if (!silent) {
2564
+ console.log(pc.cyan("\n\u{1F3A8} Setting up Tailwind CSS..."));
2565
+ }
2566
+ if (!config.configPath || force) {
2567
+ const tailwindConfig = `/** @type {import('tailwindcss').Config} */
2568
+ export default {
2569
+ content: [
2570
+ './app/**/*.{js,ts,jsx,tsx}',
2571
+ './components/**/*.{js,ts,jsx,tsx}',
2572
+ ],
2573
+ theme: {
2574
+ extend: {},
2575
+ },
2576
+ plugins: [],
2577
+ }
2578
+ `;
2579
+ const configPath = path4.join(rootDir, "tailwind.config.js");
2580
+ fs2.writeFileSync(configPath, tailwindConfig);
2581
+ if (!silent) {
2582
+ console.log(pc.green(" \u2713 Created tailwind.config.js"));
2583
+ }
2584
+ }
2585
+ const postcssPath = path4.join(rootDir, "postcss.config.js");
2586
+ if (!fs2.existsSync(postcssPath) || force) {
2587
+ const postcssConfig = `export default {
2588
+ plugins: {
2589
+ tailwindcss: {},
2590
+ autoprefixer: {},
2591
+ },
2592
+ }
2593
+ `;
2594
+ fs2.writeFileSync(postcssPath, postcssConfig);
2595
+ if (!silent) {
2596
+ console.log(pc.green(" \u2713 Created postcss.config.js"));
2597
+ }
2598
+ }
2599
+ const appDir = path4.join(rootDir, "app");
2600
+ if (!fs2.existsSync(appDir)) {
2601
+ fs2.mkdirSync(appDir, { recursive: true });
2602
+ }
2603
+ const globalsPath = path4.join(appDir, "globals.css");
2604
+ if (!fs2.existsSync(globalsPath) || force) {
2605
+ const globalsCss = `@tailwind base;
2606
+ @tailwind components;
2607
+ @tailwind utilities;
2608
+ `;
2609
+ fs2.writeFileSync(globalsPath, globalsCss);
2610
+ if (!silent) {
2611
+ console.log(pc.green(" \u2713 Created app/globals.css"));
2612
+ }
2613
+ }
2614
+ const layoutPath = path4.join(appDir, "layout.tsx");
2615
+ if (!fs2.existsSync(layoutPath)) {
2616
+ const layoutContent = `import './globals.css'
2617
+
2618
+ export default function RootLayout({
2619
+ children,
2620
+ }: {
2621
+ children: React.ReactNode
2622
+ }) {
2623
+ return (
2624
+ <html lang="en">
2625
+ <body>{children}</body>
2626
+ </html>
2627
+ )
2628
+ }
2629
+ `;
2630
+ fs2.writeFileSync(layoutPath, layoutContent);
2631
+ if (!silent) {
2632
+ console.log(pc.green(" \u2713 Created app/layout.tsx"));
2633
+ }
2634
+ }
2635
+ if (!silent) {
2636
+ console.log(pc.green("\n\u2728 Tailwind CSS ready!\n"));
2637
+ }
2638
+ }
2639
+ function checkTailwindDeps(rootDir) {
2640
+ const packageJsonPath = path4.join(rootDir, "package.json");
2641
+ if (!fs2.existsSync(packageJsonPath)) {
2642
+ return {
2643
+ hasPackageJson: false,
2644
+ hasTailwind: false,
2645
+ hasPostCSS: false,
2646
+ hasAutoprefixer: false
2647
+ };
2648
+ }
2649
+ const packageJson = JSON.parse(fs2.readFileSync(packageJsonPath, "utf-8"));
2650
+ const allDeps = {
2651
+ ...packageJson.dependencies,
2652
+ ...packageJson.devDependencies
2653
+ };
2654
+ return {
2655
+ hasPackageJson: true,
2656
+ hasTailwind: !!allDeps["tailwindcss"],
2657
+ hasPostCSS: !!allDeps["postcss"],
2658
+ hasAutoprefixer: !!allDeps["autoprefixer"]
2659
+ };
2660
+ }
2661
+ function getTailwindInstallCommand(rootDir) {
2662
+ const deps = checkTailwindDeps(rootDir);
2663
+ if (!deps.hasPackageJson) {
2664
+ return null;
2665
+ }
2666
+ const missing = [];
2667
+ if (!deps.hasTailwind) missing.push("tailwindcss");
2668
+ if (!deps.hasPostCSS) missing.push("postcss");
2669
+ if (!deps.hasAutoprefixer) missing.push("autoprefixer");
2670
+ if (missing.length === 0) {
2671
+ return null;
2672
+ }
2673
+ const hasYarnLock = fs2.existsSync(path4.join(rootDir, "yarn.lock"));
2674
+ const hasPnpmLock = fs2.existsSync(path4.join(rootDir, "pnpm-lock.yaml"));
2675
+ const hasBunLock = fs2.existsSync(path4.join(rootDir, "bun.lockb"));
2676
+ let pm = "npm install -D";
2677
+ if (hasBunLock) pm = "bun add -d";
2678
+ else if (hasPnpmLock) pm = "pnpm add -D";
2679
+ else if (hasYarnLock) pm = "yarn add -D";
2680
+ return `${pm} ${missing.join(" ")}`;
2681
+ }
2682
+
2683
+ // src/build/css-processor.ts
2684
+ async function processCSS(filePath, rootDir = process.cwd()) {
2685
+ const content = fs3.readFileSync(filePath, "utf-8");
2686
+ const tailwindConfig = checkTailwindSetup(rootDir);
2687
+ if (!tailwindConfig.hasTailwind) {
2688
+ return { code: content };
2689
+ }
2690
+ try {
2691
+ const postcss = await import("postcss").then((m) => m.default);
2692
+ const tailwindcss = await import("tailwindcss").then((m) => m.default);
2693
+ const autoprefixer = await import("autoprefixer").then((m) => m.default);
2694
+ const configPath = tailwindConfig.configPath || path5.join(rootDir, "tailwind.config.js");
2695
+ let tailwindConfigModule = {};
2696
+ if (fs3.existsSync(configPath)) {
2697
+ const configUrl = new URL(`file://${configPath}`);
2698
+ tailwindConfigModule = await import(configUrl.href).then((m) => m.default || m);
2699
+ }
2700
+ const result = await postcss([
2701
+ tailwindcss(tailwindConfigModule),
2702
+ autoprefixer()
2703
+ ]).process(content, {
2704
+ from: filePath,
2705
+ to: filePath,
2706
+ map: { inline: false }
2707
+ });
2708
+ return {
2709
+ code: result.css,
2710
+ map: result.map?.toString()
2711
+ };
2712
+ } catch (error2) {
2713
+ console.warn("CSS processing failed, serving raw CSS:", error2);
2714
+ return { code: content };
2715
+ }
2716
+ }
2717
+ function needsCSSProcessing(filePath, rootDir) {
2718
+ const config = checkTailwindSetup(rootDir);
2719
+ if (!config.hasTailwind) {
2720
+ return false;
2721
+ }
2722
+ const content = fs3.readFileSync(filePath, "utf-8");
2723
+ return content.includes("@tailwind") || content.includes("@apply");
2724
+ }
2725
+
2523
2726
  // src/server/dev-server.ts
2524
2727
  async function createDevServer(options) {
2525
2728
  const { port, host, open } = options;
2526
2729
  const rootDir = process.cwd();
2527
- const publicDir = path4.join(rootDir, "public");
2730
+ const publicDir = path6.join(rootDir, "public");
2528
2731
  let routes = [];
2529
2732
  let server = null;
2530
2733
  let wss = null;
@@ -2532,9 +2735,20 @@ async function createDevServer(options) {
2532
2735
  async function refreshRoutes() {
2533
2736
  try {
2534
2737
  routes = await scanRoutes(rootDir);
2535
- console.log(pc.dim(` \u{1F4C1} Found ${routes.length} routes`));
2738
+ console.log(pc2.dim(` \u{1F4C1} Found ${routes.length} routes`));
2739
+ const tailwindConfig = checkTailwindSetup(rootDir);
2740
+ if (tailwindConfig.needsSetup) {
2741
+ console.log(pc2.yellow(" \u26A0\uFE0F Tailwind not configured"));
2742
+ const installCmd = getTailwindInstallCommand(rootDir);
2743
+ if (installCmd) {
2744
+ console.log(pc2.dim(` \u{1F4A1} Run: ${installCmd}`));
2745
+ console.log(pc2.dim(` \u{1F4A1} Then: npx float dev`));
2746
+ } else {
2747
+ await setupTailwind(rootDir);
2748
+ }
2749
+ }
2536
2750
  } catch (error2) {
2537
- console.error(pc.red("Failed to scan routes:"), error2);
2751
+ console.error(pc2.red("Failed to scan routes:"), error2);
2538
2752
  }
2539
2753
  }
2540
2754
  function notifyClients(type, data) {
@@ -2595,16 +2809,46 @@ ${FLOAT_ERROR_OVERLAY}
2595
2809
  async function handleRequest(req, res) {
2596
2810
  const url = new URL(req.url || "/", `http://${host}:${port}`);
2597
2811
  const pathname = url.pathname;
2598
- console.log(pc.dim(` ${req.method} ${pathname}`));
2812
+ console.log(pc2.dim(` ${req.method} ${pathname}`));
2599
2813
  try {
2600
- const publicFilePath = path4.join(publicDir, pathname);
2601
- if (fs2.existsSync(publicFilePath) && fs2.statSync(publicFilePath).isFile()) {
2602
- const content = fs2.readFileSync(publicFilePath);
2814
+ const publicFilePath = path6.join(publicDir, pathname);
2815
+ if (fs4.existsSync(publicFilePath) && fs4.statSync(publicFilePath).isFile()) {
2816
+ const content = fs4.readFileSync(publicFilePath);
2603
2817
  const contentType = mime.lookup(publicFilePath) || "application/octet-stream";
2604
2818
  res.writeHead(200, { "Content-Type": contentType });
2605
2819
  res.end(content);
2606
2820
  return;
2607
2821
  }
2822
+ if (pathname.endsWith(".css")) {
2823
+ const cssPath = path6.join(rootDir, "app", pathname.replace(/^\//, ""));
2824
+ if (fs4.existsSync(cssPath)) {
2825
+ try {
2826
+ const needsProcessing = needsCSSProcessing(cssPath, rootDir);
2827
+ if (needsProcessing) {
2828
+ const result = await processCSS(cssPath, rootDir);
2829
+ res.writeHead(200, {
2830
+ "Content-Type": "text/css",
2831
+ "Cache-Control": "no-cache"
2832
+ });
2833
+ res.end(result.code);
2834
+ } else {
2835
+ const content = fs4.readFileSync(cssPath, "utf-8");
2836
+ res.writeHead(200, {
2837
+ "Content-Type": "text/css",
2838
+ "Cache-Control": "no-cache"
2839
+ });
2840
+ res.end(content);
2841
+ }
2842
+ return;
2843
+ } catch (error2) {
2844
+ console.error(pc2.red("CSS processing error:"), error2);
2845
+ const content = fs4.readFileSync(cssPath, "utf-8");
2846
+ res.writeHead(200, { "Content-Type": "text/css" });
2847
+ res.end(content);
2848
+ return;
2849
+ }
2850
+ }
2851
+ }
2608
2852
  if (pathname.startsWith("/_float/")) {
2609
2853
  res.writeHead(200, { "Content-Type": "application/javascript" });
2610
2854
  res.end("// Float.js internal asset");
@@ -2669,7 +2913,7 @@ ${FLOAT_ERROR_OVERLAY}
2669
2913
  });
2670
2914
  res.end(html);
2671
2915
  } catch (error2) {
2672
- console.error(pc.red("Request error:"), error2);
2916
+ console.error(pc2.red("Request error:"), error2);
2673
2917
  res.writeHead(500, { "Content-Type": "text/html" });
2674
2918
  res.end(createErrorPage(error2));
2675
2919
  }
@@ -2698,7 +2942,7 @@ ${FLOAT_ERROR_OVERLAY}
2698
2942
  const responseBody = await response.text();
2699
2943
  res.end(responseBody);
2700
2944
  } catch (error2) {
2701
- console.error(pc.red("API route error:"), error2);
2945
+ console.error(pc2.red("API route error:"), error2);
2702
2946
  res.writeHead(500, { "Content-Type": "application/json" });
2703
2947
  res.end(JSON.stringify({ error: "Internal server error" }));
2704
2948
  }
@@ -2713,9 +2957,9 @@ ${FLOAT_ERROR_OVERLAY}
2713
2957
  });
2714
2958
  const watcher = chokidar.watch(
2715
2959
  [
2716
- path4.join(rootDir, "app/**/*.{ts,tsx,js,jsx}"),
2717
- path4.join(rootDir, "components/**/*.{ts,tsx,js,jsx}"),
2718
- path4.join(rootDir, "lib/**/*.{ts,tsx,js,jsx}")
2960
+ path6.join(rootDir, "app/**/*.{ts,tsx,js,jsx}"),
2961
+ path6.join(rootDir, "components/**/*.{ts,tsx,js,jsx}"),
2962
+ path6.join(rootDir, "lib/**/*.{ts,tsx,js,jsx}")
2719
2963
  ],
2720
2964
  {
2721
2965
  ignored: /node_modules/,
@@ -2723,8 +2967,8 @@ ${FLOAT_ERROR_OVERLAY}
2723
2967
  }
2724
2968
  );
2725
2969
  watcher.on("change", async (filePath) => {
2726
- console.log(pc.yellow(`
2727
- \u26A1 File changed: ${path4.relative(rootDir, filePath)}`));
2970
+ console.log(pc2.yellow(`
2971
+ \u26A1 File changed: ${path6.relative(rootDir, filePath)}`));
2728
2972
  if (filePath.includes("/app/")) {
2729
2973
  await refreshRoutes();
2730
2974
  }
@@ -2732,31 +2976,31 @@ ${FLOAT_ERROR_OVERLAY}
2732
2976
  });
2733
2977
  watcher.on("add", async (filePath) => {
2734
2978
  if (filePath.includes("/app/")) {
2735
- console.log(pc.green(`
2736
- \u2795 File added: ${path4.relative(rootDir, filePath)}`));
2979
+ console.log(pc2.green(`
2980
+ \u2795 File added: ${path6.relative(rootDir, filePath)}`));
2737
2981
  await refreshRoutes();
2738
2982
  notifyClients("reload");
2739
2983
  }
2740
2984
  });
2741
2985
  watcher.on("unlink", async (filePath) => {
2742
2986
  if (filePath.includes("/app/")) {
2743
- console.log(pc.red(`
2744
- \u2796 File removed: ${path4.relative(rootDir, filePath)}`));
2987
+ console.log(pc2.red(`
2988
+ \u2796 File removed: ${path6.relative(rootDir, filePath)}`));
2745
2989
  await refreshRoutes();
2746
2990
  notifyClients("reload");
2747
2991
  }
2748
2992
  });
2749
2993
  return new Promise((resolve, reject) => {
2750
2994
  server.listen(port, host, () => {
2751
- console.log(pc.green(` \u2705 Server running at ${pc.cyan(`http://${host}:${port}`)}`));
2752
- console.log(pc.dim(` \u26A1 HMR enabled on ws://${host}:${port + 1}
2995
+ console.log(pc2.green(` \u2705 Server running at ${pc2.cyan(`http://${host}:${port}`)}`));
2996
+ console.log(pc2.dim(` \u26A1 HMR enabled on ws://${host}:${port + 1}
2753
2997
  `));
2754
- console.log(pc.bold(" Routes:"));
2998
+ console.log(pc2.bold(" Routes:"));
2755
2999
  routes.forEach((route) => {
2756
3000
  if (route.type === "page") {
2757
- console.log(pc.dim(` ${pc.green("\u25CF")} ${route.path}`));
3001
+ console.log(pc2.dim(` ${pc2.green("\u25CF")} ${route.path}`));
2758
3002
  } else if (route.type === "api") {
2759
- console.log(pc.dim(` ${pc.blue("\u25C6")} ${route.path} (API)`));
3003
+ console.log(pc2.dim(` ${pc2.blue("\u25C6")} ${route.path} (API)`));
2760
3004
  }
2761
3005
  });
2762
3006
  console.log("");
@@ -2876,45 +3120,45 @@ function escapeHtml2(text) {
2876
3120
  // src/server/prod-server.ts
2877
3121
  init_esm_shims();
2878
3122
  import http2 from "http";
2879
- import fs3 from "fs";
2880
- import path5 from "path";
2881
- import pc2 from "picocolors";
3123
+ import fs5 from "fs";
3124
+ import path7 from "path";
3125
+ import pc3 from "picocolors";
2882
3126
  import mime2 from "mime-types";
2883
3127
  var cachedRoutes = [];
2884
3128
  var pageCache = /* @__PURE__ */ new Map();
2885
3129
  async function startProductionServer(options) {
2886
3130
  const { port, host } = options;
2887
3131
  const rootDir = process.cwd();
2888
- const distDir = path5.join(rootDir, ".float");
2889
- const publicDir = path5.join(rootDir, "public");
2890
- const manifestPath = path5.join(distDir, "routes-manifest.json");
2891
- if (fs3.existsSync(manifestPath)) {
2892
- const manifest = JSON.parse(fs3.readFileSync(manifestPath, "utf-8"));
3132
+ const distDir = path7.join(rootDir, ".float");
3133
+ const publicDir = path7.join(rootDir, "public");
3134
+ const manifestPath = path7.join(distDir, "routes-manifest.json");
3135
+ if (fs5.existsSync(manifestPath)) {
3136
+ const manifest = JSON.parse(fs5.readFileSync(manifestPath, "utf-8"));
2893
3137
  cachedRoutes = manifest.routes;
2894
- console.log(pc2.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
3138
+ console.log(pc3.dim(` \u{1F4E6} Loaded ${cachedRoutes.length} routes from manifest`));
2895
3139
  } else {
2896
- console.error(pc2.red(" \u274C No build manifest found. Run `float build` first."));
3140
+ console.error(pc3.red(" \u274C No build manifest found. Run `float build` first."));
2897
3141
  process.exit(1);
2898
3142
  }
2899
- const pagesDir = path5.join(distDir, "pages");
2900
- if (fs3.existsSync(pagesDir)) {
2901
- const prerenderedFiles = fs3.readdirSync(pagesDir, { recursive: true });
3143
+ const pagesDir = path7.join(distDir, "pages");
3144
+ if (fs5.existsSync(pagesDir)) {
3145
+ const prerenderedFiles = fs5.readdirSync(pagesDir, { recursive: true });
2902
3146
  for (const file of prerenderedFiles) {
2903
3147
  if (file.endsWith(".html")) {
2904
3148
  const routePath = "/" + file.replace(/\.html$/, "").replace(/index$/, "");
2905
- const content = fs3.readFileSync(path5.join(pagesDir, file), "utf-8");
3149
+ const content = fs5.readFileSync(path7.join(pagesDir, file), "utf-8");
2906
3150
  pageCache.set(routePath, content);
2907
3151
  }
2908
3152
  }
2909
- console.log(pc2.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
3153
+ console.log(pc3.dim(` \u{1F4C4} Loaded ${pageCache.size} pre-rendered pages`));
2910
3154
  }
2911
3155
  const server = http2.createServer(async (req, res) => {
2912
3156
  const url = new URL(req.url || "/", `http://${host}:${port}`);
2913
3157
  const pathname = url.pathname;
2914
3158
  try {
2915
- const staticPath = path5.join(distDir, "static", pathname);
2916
- if (fs3.existsSync(staticPath) && fs3.statSync(staticPath).isFile()) {
2917
- const content = fs3.readFileSync(staticPath);
3159
+ const staticPath = path7.join(distDir, "static", pathname);
3160
+ if (fs5.existsSync(staticPath) && fs5.statSync(staticPath).isFile()) {
3161
+ const content = fs5.readFileSync(staticPath);
2918
3162
  const contentType = mime2.lookup(staticPath) || "application/octet-stream";
2919
3163
  res.writeHead(200, {
2920
3164
  "Content-Type": contentType,
@@ -2923,9 +3167,9 @@ async function startProductionServer(options) {
2923
3167
  res.end(content);
2924
3168
  return;
2925
3169
  }
2926
- const publicFilePath = path5.join(publicDir, pathname);
2927
- if (fs3.existsSync(publicFilePath) && fs3.statSync(publicFilePath).isFile()) {
2928
- const content = fs3.readFileSync(publicFilePath);
3170
+ const publicFilePath = path7.join(publicDir, pathname);
3171
+ if (fs5.existsSync(publicFilePath) && fs5.statSync(publicFilePath).isFile()) {
3172
+ const content = fs5.readFileSync(publicFilePath);
2929
3173
  const contentType = mime2.lookup(publicFilePath) || "application/octet-stream";
2930
3174
  res.writeHead(200, { "Content-Type": contentType });
2931
3175
  res.end(content);
@@ -2958,13 +3202,13 @@ async function startProductionServer(options) {
2958
3202
  });
2959
3203
  res.end(html);
2960
3204
  } catch (error2) {
2961
- console.error(pc2.red("Request error:"), error2);
3205
+ console.error(pc3.red("Request error:"), error2);
2962
3206
  res.writeHead(500, { "Content-Type": "text/html" });
2963
3207
  res.end("<h1>500 - Internal Server Error</h1>");
2964
3208
  }
2965
3209
  });
2966
3210
  server.listen(port, host, () => {
2967
- console.log(pc2.green(` \u2705 Production server running at ${pc2.cyan(`http://${host}:${port}`)}
3211
+ console.log(pc3.green(` \u2705 Production server running at ${pc3.cyan(`http://${host}:${port}`)}
2968
3212
  `));
2969
3213
  });
2970
3214
  }
@@ -2972,9 +3216,9 @@ async function startProductionServer(options) {
2972
3216
  // src/build/index.ts
2973
3217
  init_esm_shims();
2974
3218
  import * as esbuild2 from "esbuild";
2975
- import fs4 from "fs";
2976
- import path6 from "path";
2977
- import pc3 from "picocolors";
3219
+ import fs6 from "fs";
3220
+ import path8 from "path";
3221
+ import pc4 from "picocolors";
2978
3222
  var DEFAULT_BUILD_OPTIONS = {
2979
3223
  analyze: false,
2980
3224
  minify: true,
@@ -2984,27 +3228,27 @@ async function build2(options = {}) {
2984
3228
  const opts = { ...DEFAULT_BUILD_OPTIONS, ...options };
2985
3229
  const startTime = Date.now();
2986
3230
  const rootDir = process.cwd();
2987
- const outputDir = path6.join(rootDir, ".float");
2988
- if (fs4.existsSync(outputDir)) {
2989
- fs4.rmSync(outputDir, { recursive: true });
2990
- }
2991
- fs4.mkdirSync(outputDir, { recursive: true });
2992
- fs4.mkdirSync(path6.join(outputDir, "pages"), { recursive: true });
2993
- fs4.mkdirSync(path6.join(outputDir, "static"), { recursive: true });
2994
- fs4.mkdirSync(path6.join(outputDir, "server"), { recursive: true });
2995
- console.log(pc3.dim(" Scanning routes..."));
3231
+ const outputDir = path8.join(rootDir, ".float");
3232
+ if (fs6.existsSync(outputDir)) {
3233
+ fs6.rmSync(outputDir, { recursive: true });
3234
+ }
3235
+ fs6.mkdirSync(outputDir, { recursive: true });
3236
+ fs6.mkdirSync(path8.join(outputDir, "pages"), { recursive: true });
3237
+ fs6.mkdirSync(path8.join(outputDir, "static"), { recursive: true });
3238
+ fs6.mkdirSync(path8.join(outputDir, "server"), { recursive: true });
3239
+ console.log(pc4.dim(" Scanning routes..."));
2996
3240
  const routes = await scanRoutes(rootDir);
2997
3241
  const pageRoutes = routes.filter((r) => r.type === "page" && !r.params.length);
2998
3242
  const dynamicRoutes = routes.filter((r) => r.type === "page" && r.params.length > 0);
2999
3243
  const apiRoutes = routes.filter((r) => r.type === "api");
3000
- console.log(pc3.dim(` Found ${pageRoutes.length} static pages, ${dynamicRoutes.length} dynamic routes, ${apiRoutes.length} API routes`));
3001
- console.log(pc3.dim(" Building client bundle..."));
3244
+ console.log(pc4.dim(` Found ${pageRoutes.length} static pages, ${dynamicRoutes.length} dynamic routes, ${apiRoutes.length} API routes`));
3245
+ console.log(pc4.dim(" Building client bundle..."));
3002
3246
  const clientEntryPoints = routes.filter((r) => r.type === "page").map((r) => r.absolutePath);
3003
3247
  if (clientEntryPoints.length > 0) {
3004
3248
  await esbuild2.build({
3005
3249
  entryPoints: clientEntryPoints,
3006
3250
  bundle: true,
3007
- outdir: path6.join(outputDir, "static", "_float"),
3251
+ outdir: path8.join(outputDir, "static", "_float"),
3008
3252
  format: "esm",
3009
3253
  splitting: true,
3010
3254
  minify: opts.minify,
@@ -3026,13 +3270,13 @@ async function build2(options = {}) {
3026
3270
  metafile: opts.analyze
3027
3271
  });
3028
3272
  }
3029
- console.log(pc3.dim(" Building server bundle..."));
3273
+ console.log(pc4.dim(" Building server bundle..."));
3030
3274
  const serverEntryPoints = routes.map((r) => r.absolutePath);
3031
3275
  if (serverEntryPoints.length > 0) {
3032
3276
  await esbuild2.build({
3033
3277
  entryPoints: serverEntryPoints,
3034
3278
  bundle: true,
3035
- outdir: path6.join(outputDir, "server"),
3279
+ outdir: path8.join(outputDir, "server"),
3036
3280
  format: "esm",
3037
3281
  platform: "node",
3038
3282
  target: ["node18"],
@@ -3049,26 +3293,26 @@ async function build2(options = {}) {
3049
3293
  external: ["react", "react-dom", "@float/core"]
3050
3294
  });
3051
3295
  }
3052
- console.log(pc3.dim(" Pre-rendering static pages..."));
3296
+ console.log(pc4.dim(" Pre-rendering static pages..."));
3053
3297
  const prerenderedPages = [];
3054
3298
  for (const route of pageRoutes) {
3055
3299
  try {
3056
3300
  const html = await renderPage(route, {}, { isDev: false });
3057
- const outputPath = route.path === "/" ? path6.join(outputDir, "pages", "index.html") : path6.join(outputDir, "pages", route.path, "index.html");
3058
- fs4.mkdirSync(path6.dirname(outputPath), { recursive: true });
3059
- fs4.writeFileSync(outputPath, html);
3301
+ const outputPath = route.path === "/" ? path8.join(outputDir, "pages", "index.html") : path8.join(outputDir, "pages", route.path, "index.html");
3302
+ fs6.mkdirSync(path8.dirname(outputPath), { recursive: true });
3303
+ fs6.writeFileSync(outputPath, html);
3060
3304
  prerenderedPages.push(route.path);
3061
- console.log(pc3.dim(` \u2713 ${route.path}`));
3305
+ console.log(pc4.dim(` \u2713 ${route.path}`));
3062
3306
  } catch (error2) {
3063
- console.log(pc3.yellow(` \u26A0 ${route.path} (will render at runtime)`));
3307
+ console.log(pc4.yellow(` \u26A0 ${route.path} (will render at runtime)`));
3064
3308
  }
3065
3309
  }
3066
- console.log(pc3.dim(" Building API routes..."));
3310
+ console.log(pc4.dim(" Building API routes..."));
3067
3311
  for (const route of apiRoutes) {
3068
3312
  await esbuild2.build({
3069
3313
  entryPoints: [route.absolutePath],
3070
3314
  bundle: true,
3071
- outfile: path6.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
3315
+ outfile: path8.join(outputDir, "server", "api", `${route.path.replace(/\//g, "_")}.js`),
3072
3316
  format: "esm",
3073
3317
  platform: "neutral",
3074
3318
  // Edge compatible
@@ -3076,10 +3320,10 @@ async function build2(options = {}) {
3076
3320
  minify: true
3077
3321
  });
3078
3322
  }
3079
- const publicDir = path6.join(rootDir, "public");
3080
- if (fs4.existsSync(publicDir)) {
3081
- console.log(pc3.dim(" Copying public assets..."));
3082
- copyDir(publicDir, path6.join(outputDir, "static"));
3323
+ const publicDir = path8.join(rootDir, "public");
3324
+ if (fs6.existsSync(publicDir)) {
3325
+ console.log(pc4.dim(" Copying public assets..."));
3326
+ copyDir(publicDir, path8.join(outputDir, "static"));
3083
3327
  }
3084
3328
  const manifest = {
3085
3329
  version: 1,
@@ -3088,19 +3332,19 @@ async function build2(options = {}) {
3088
3332
  path: r.path,
3089
3333
  type: r.type,
3090
3334
  filePath: r.filePath,
3091
- absolutePath: path6.relative(rootDir, r.absolutePath),
3335
+ absolutePath: path8.relative(rootDir, r.absolutePath),
3092
3336
  params: r.params,
3093
3337
  isCatchAll: r.isCatchAll,
3094
3338
  isOptionalCatchAll: r.isOptionalCatchAll,
3095
- layouts: r.layouts.map((l) => path6.relative(rootDir, l)),
3339
+ layouts: r.layouts.map((l) => path8.relative(rootDir, l)),
3096
3340
  prerendered: prerenderedPages.includes(r.path)
3097
3341
  })),
3098
3342
  staticPages: prerenderedPages,
3099
3343
  dynamicRoutes: dynamicRoutes.map((r) => r.path),
3100
3344
  apiRoutes: apiRoutes.map((r) => r.path)
3101
3345
  };
3102
- fs4.writeFileSync(
3103
- path6.join(outputDir, "routes-manifest.json"),
3346
+ fs6.writeFileSync(
3347
+ path8.join(outputDir, "routes-manifest.json"),
3104
3348
  JSON.stringify(manifest, null, 2)
3105
3349
  );
3106
3350
  const duration = Date.now() - startTime;
@@ -3110,16 +3354,16 @@ async function build2(options = {}) {
3110
3354
  routes: routes.length,
3111
3355
  pages: prerenderedPages.length
3112
3356
  };
3113
- fs4.writeFileSync(
3114
- path6.join(outputDir, "build-info.json"),
3357
+ fs6.writeFileSync(
3358
+ path8.join(outputDir, "build-info.json"),
3115
3359
  JSON.stringify(buildInfo, null, 2)
3116
3360
  );
3117
3361
  console.log("");
3118
- console.log(pc3.bold(" Build Summary:"));
3119
- console.log(pc3.dim(` Static Pages: ${prerenderedPages.length}`));
3120
- console.log(pc3.dim(` Dynamic Routes: ${dynamicRoutes.length}`));
3121
- console.log(pc3.dim(` API Routes: ${apiRoutes.length}`));
3122
- console.log(pc3.dim(` Output: .float/`));
3362
+ console.log(pc4.bold(" Build Summary:"));
3363
+ console.log(pc4.dim(` Static Pages: ${prerenderedPages.length}`));
3364
+ console.log(pc4.dim(` Dynamic Routes: ${dynamicRoutes.length}`));
3365
+ console.log(pc4.dim(` API Routes: ${apiRoutes.length}`));
3366
+ console.log(pc4.dim(` Output: .float/`));
3123
3367
  return {
3124
3368
  routes,
3125
3369
  duration,
@@ -3129,15 +3373,15 @@ async function build2(options = {}) {
3129
3373
  };
3130
3374
  }
3131
3375
  function copyDir(src, dest) {
3132
- fs4.mkdirSync(dest, { recursive: true });
3133
- const entries = fs4.readdirSync(src, { withFileTypes: true });
3376
+ fs6.mkdirSync(dest, { recursive: true });
3377
+ const entries = fs6.readdirSync(src, { withFileTypes: true });
3134
3378
  for (const entry of entries) {
3135
- const srcPath = path6.join(src, entry.name);
3136
- const destPath = path6.join(dest, entry.name);
3379
+ const srcPath = path8.join(src, entry.name);
3380
+ const destPath = path8.join(dest, entry.name);
3137
3381
  if (entry.isDirectory()) {
3138
3382
  copyDir(srcPath, destPath);
3139
3383
  } else {
3140
- fs4.copyFileSync(srcPath, destPath);
3384
+ fs6.copyFileSync(srcPath, destPath);
3141
3385
  }
3142
3386
  }
3143
3387
  }
@@ -5590,10 +5834,10 @@ function matcherToRegex(pattern) {
5590
5834
  let regex = pattern.replace(/[.+?^${}()|[\]\\]/g, "\\$&").replace(/:([a-zA-Z_][a-zA-Z0-9_]*)/g, "(?<$1>[^/]+)").replace(/\\\*/g, ".*").replace(/\\\(([^)]+)\\\)/g, "($1)?");
5591
5835
  return new RegExp(`^${regex}$`);
5592
5836
  }
5593
- function matchesPath(path7, matcher) {
5837
+ function matchesPath(path9, matcher) {
5594
5838
  if (!matcher) return true;
5595
5839
  const patterns = Array.isArray(matcher) ? matcher : [matcher];
5596
- return patterns.some((pattern) => matcherToRegex(pattern).test(path7));
5840
+ return patterns.some((pattern) => matcherToRegex(pattern).test(path9));
5597
5841
  }
5598
5842
  function parseCookies(cookieHeader) {
5599
5843
  const cookies = /* @__PURE__ */ new Map();
@@ -5839,14 +6083,14 @@ var middlewareHelpers = {
5839
6083
  */
5840
6084
  trailingSlash(add = false) {
5841
6085
  return (req) => {
5842
- const path7 = req.nextUrl.pathname;
5843
- if (path7 === "/") return NextResponse.next();
5844
- const hasSlash = path7.endsWith("/");
6086
+ const path9 = req.nextUrl.pathname;
6087
+ if (path9 === "/") return NextResponse.next();
6088
+ const hasSlash = path9.endsWith("/");
5845
6089
  if (add && !hasSlash) {
5846
- return NextResponse.redirect(new URL(path7 + "/", req.request.url));
6090
+ return NextResponse.redirect(new URL(path9 + "/", req.request.url));
5847
6091
  }
5848
6092
  if (!add && hasSlash) {
5849
- return NextResponse.redirect(new URL(path7.slice(0, -1), req.request.url));
6093
+ return NextResponse.redirect(new URL(path9.slice(0, -1), req.request.url));
5850
6094
  }
5851
6095
  return NextResponse.next();
5852
6096
  };
@@ -5884,8 +6128,8 @@ var SSGEngine = class {
5884
6128
  mkdirSync2(this.diskCachePath, { recursive: true });
5885
6129
  }
5886
6130
  }
5887
- getCacheKey(path7, locale) {
5888
- const normalized = path7.replace(/^\/+|\/+$/g, "") || "index";
6131
+ getCacheKey(path9, locale) {
6132
+ const normalized = path9.replace(/^\/+|\/+$/g, "") || "index";
5889
6133
  const key = locale ? `${locale}/${normalized}` : normalized;
5890
6134
  return key.replace(/\//g, "__");
5891
6135
  }
@@ -5898,9 +6142,9 @@ var SSGEngine = class {
5898
6142
  /**
5899
6143
  * Generate static page and cache it
5900
6144
  */
5901
- async generatePage(path7, getStaticProps, render, params = {}, locale) {
6145
+ async generatePage(path9, getStaticProps, render, params = {}, locale) {
5902
6146
  const startTime = Date.now();
5903
- const cacheKey = this.getCacheKey(path7, locale);
6147
+ const cacheKey = this.getCacheKey(path9, locale);
5904
6148
  try {
5905
6149
  const propsResult = await getStaticProps({
5906
6150
  params,
@@ -5909,7 +6153,7 @@ var SSGEngine = class {
5909
6153
  });
5910
6154
  if (propsResult.redirect) {
5911
6155
  return {
5912
- path: path7,
6156
+ path: path9,
5913
6157
  success: true,
5914
6158
  duration: Date.now() - startTime,
5915
6159
  size: 0
@@ -5917,7 +6161,7 @@ var SSGEngine = class {
5917
6161
  }
5918
6162
  if (propsResult.notFound) {
5919
6163
  return {
5920
- path: path7,
6164
+ path: path9,
5921
6165
  success: false,
5922
6166
  duration: Date.now() - startTime,
5923
6167
  size: 0,
@@ -5941,7 +6185,7 @@ var SSGEngine = class {
5941
6185
  this.setMemoryCache(cacheKey, cachedPage);
5942
6186
  this.writeToDisk(cacheKey, cachedPage);
5943
6187
  return {
5944
- path: path7,
6188
+ path: path9,
5945
6189
  success: true,
5946
6190
  duration: Date.now() - startTime,
5947
6191
  size: html.length,
@@ -5949,7 +6193,7 @@ var SSGEngine = class {
5949
6193
  };
5950
6194
  } catch (error2) {
5951
6195
  return {
5952
- path: path7,
6196
+ path: path9,
5953
6197
  success: false,
5954
6198
  duration: Date.now() - startTime,
5955
6199
  size: 0,
@@ -5960,8 +6204,8 @@ var SSGEngine = class {
5960
6204
  /**
5961
6205
  * Get cached page or generate on-demand
5962
6206
  */
5963
- async getPage(path7, getStaticProps, render, params = {}, locale, fallback = false) {
5964
- const cacheKey = this.getCacheKey(path7, locale);
6207
+ async getPage(path9, getStaticProps, render, params = {}, locale, fallback = false) {
6208
+ const cacheKey = this.getCacheKey(path9, locale);
5965
6209
  let cached = this.memoryCache.get(cacheKey);
5966
6210
  if (!cached) {
5967
6211
  cached = this.readFromDisk(cacheKey) || void 0;
@@ -5972,7 +6216,7 @@ var SSGEngine = class {
5972
6216
  if (cached) {
5973
6217
  const isStale = cached.revalidateAfter !== null && Date.now() > cached.revalidateAfter;
5974
6218
  if (isStale && this.config.staleWhileRevalidate) {
5975
- this.triggerRevalidation(path7, getStaticProps, render, params, locale);
6219
+ this.triggerRevalidation(path9, getStaticProps, render, params, locale);
5976
6220
  }
5977
6221
  return { cached, stale: isStale };
5978
6222
  }
@@ -5980,7 +6224,7 @@ var SSGEngine = class {
5980
6224
  return null;
5981
6225
  }
5982
6226
  if (fallback === "blocking") {
5983
- const result = await this.generatePage(path7, getStaticProps, render, params, locale);
6227
+ const result = await this.generatePage(path9, getStaticProps, render, params, locale);
5984
6228
  if (result.success) {
5985
6229
  const newCached = this.memoryCache.get(cacheKey);
5986
6230
  return newCached ? { cached: newCached, stale: false } : null;
@@ -5991,14 +6235,14 @@ var SSGEngine = class {
5991
6235
  /**
5992
6236
  * Trigger ISR revalidation in background
5993
6237
  */
5994
- async triggerRevalidation(path7, getStaticProps, render, params = {}, locale) {
5995
- const cacheKey = this.getCacheKey(path7, locale);
6238
+ async triggerRevalidation(path9, getStaticProps, render, params = {}, locale) {
6239
+ const cacheKey = this.getCacheKey(path9, locale);
5996
6240
  if (this.isrState.revalidating.has(cacheKey)) {
5997
6241
  return;
5998
6242
  }
5999
6243
  this.isrState.revalidating.add(cacheKey);
6000
6244
  try {
6001
- await this.generatePage(path7, getStaticProps, render, params, locale);
6245
+ await this.generatePage(path9, getStaticProps, render, params, locale);
6002
6246
  this.isrState.lastRevalidation.set(cacheKey, Date.now());
6003
6247
  } finally {
6004
6248
  this.isrState.revalidating.delete(cacheKey);
@@ -6007,9 +6251,9 @@ var SSGEngine = class {
6007
6251
  /**
6008
6252
  * Force revalidation of a path (On-Demand ISR)
6009
6253
  */
6010
- async revalidate(path7, getStaticProps, render, params = {}, locale) {
6254
+ async revalidate(path9, getStaticProps, render, params = {}, locale) {
6011
6255
  try {
6012
- const result = await this.generatePage(path7, getStaticProps, render, params, locale);
6256
+ const result = await this.generatePage(path9, getStaticProps, render, params, locale);
6013
6257
  return { revalidated: result.success, error: result.error?.message };
6014
6258
  } catch (error2) {
6015
6259
  return {
@@ -6172,10 +6416,10 @@ function createSSGHandler(options) {
6172
6416
  const engine = getSSGEngine();
6173
6417
  return async (req) => {
6174
6418
  const url = new URL(req.url);
6175
- const path7 = url.pathname;
6419
+ const path9 = url.pathname;
6176
6420
  const params = {};
6177
6421
  const result = await engine.getPage(
6178
- path7,
6422
+ path9,
6179
6423
  options.getStaticProps,
6180
6424
  options.render,
6181
6425
  params,
@@ -6542,7 +6786,7 @@ var AnalyticsEngine = class {
6542
6786
  for (const pv of recentPageviews) {
6543
6787
  pathCounts[pv.pathname] = (pathCounts[pv.pathname] || 0) + 1;
6544
6788
  }
6545
- const topPages = Object.entries(pathCounts).map(([path7, count]) => ({ path: path7, count })).sort((a, b) => b.count - a.count).slice(0, 10);
6789
+ const topPages = Object.entries(pathCounts).map(([path9, count]) => ({ path: path9, count })).sort((a, b) => b.count - a.count).slice(0, 10);
6546
6790
  return {
6547
6791
  activeUsers: activeSessions.size,
6548
6792
  pageviews: recentPageviews.length,